/* dualplayfield.c
** Shows how to turn on dual-playfield mode in a screen.
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y dualplayfield
** blink FROM LIB:c.o dualplayfield.o TO dualplayfield LIB LIB:lc.lib LIB:amiga.lib
*/
#define INTUI_V36_NAMES_ONLY
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/displayinfo.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
VOID doDualPF ( struct Window * );
BOOL installDualPF( struct Screen *, struct RastInfo * );
VOID drawSomething( struct RastPort * );
VOID handleIDCMP ( struct Window * );
VOID removeDualPF( struct Screen *s );
struct Library *IntuitionBase;
struct Library *GfxBase;
VOID main(int argc, char **argv)
{
struct Window *win;
struct Screen *scr;
IntuitionBase = OpenLibrary("intuition.library",37);
if (IntuitionBase != NULL)
{
GfxBase = OpenLibrary("graphics.library", 37);
if (GfxBase != NULL)
{
scr = OpenScreenTags(NULL,
SA_Depth, 2,
SA_DisplayID, HIRES_KEY,
SA_Title, "Dual Playfield Test Screen",
TAG_END);
if ( scr != NULL )
{
win = OpenWindowTags(NULL,
WA_Title, "Dual Playfield Mode",
WA_IDCMP, IDCMP_CLOSEWINDOW,
WA_Width, 200,
WA_Height, 100,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_CustomScreen, scr,
TAG_END);
if ( win != NULL )
{
doDualPF(win);
CloseWindow(win);
}
CloseScreen(scr);
}
CloseLibrary(GfxBase);
}
CloseLibrary(IntuitionBase);
}
}
/*
** Allocate all of the stuff required to add dual playfield to a screen.
*/
VOID doDualPF(struct Window *win)
{
struct Screen *myscreen;
struct RasInfo *rinfo2;
struct BitMap *bmap2;
struct RastPort *rport2;
myscreen = win->WScreen; /* Find the window's screen */
/* Allocate the second playfield's rasinfo, bitmap, and bitplane */
rinfo2 = (struct RasInfo *) AllocMem(sizeof(struct RasInfo), MEMF_PUBLIC | MEMF_CLEAR);
if ( rinfo2 != NULL )
{
/* Get a rastport, and set it up for rendering into bmap2 */
rport2 = (struct RastPort *) AllocMem(sizeof(struct RastPort), MEMF_PUBLIC );
if (rport2 != NULL )
{
bmap2 = (struct BitMap *) AllocMem(sizeof(struct BitMap), MEMF_PUBLIC | MEMF_CLEAR);
if (bmap2 != NULL )
{
InitBitMap(bmap2, 1, myscreen->Width, myscreen->Height);
/* extra playfield will only use one bitplane here. */
bmap2->Planes[0] = (PLANEPTR) AllocRaster(myscreen->Width, myscreen->Height);
if (bmap2->Planes[0] != NULL )
{
InitRastPort(rport2);
rport2->BitMap = rinfo2->BitMap = bmap2;
SetRast(rport2, 0);
if (installDualPF(myscreen,rinfo2))
{
/* Set foreground color; color 9 is color 1 for
** second playfield of hi-res viewport
*/
SetRGB4(&myscreen->ViewPort, 9, 0, 0xF, 0);
drawSomething(rport2);
handleIDCMP(win);
removeDualPF(myscreen);
}
FreeRaster(bmap2->Planes[0], myscreen->Width, myscreen->Height);
}
FreeMem(bmap2, sizeof(struct BitMap));
}
FreeMem(rport2, sizeof(struct RastPort));
}
FreeMem(rinfo2, sizeof(struct RasInfo));
}
}
/*
** Manhandle the viewport:
** install second playfield and change modes
*/
BOOL installDualPF(struct Screen *scrn, struct RastInfo *rinfo2)
{
ULONG screen_modeID;
BOOL return_code = FALSE;
screen_modeID = GetVPModeID(&(scrn->ViewPort));
if( screen_modeID != INVALID_ID )
{
/* you can only play with the bits in the Modes field
** if the upper half of the screen mode ID is zero!!!
*/
if ( (screen_modeID & 0xFFFF0000L) == 0L )
{
return_code = TRUE;
Forbid();
/* Install rinfo for viewport's second playfield */
scrn->ViewPort.RasInfo->Next = rinfo2;
scrn->ViewPort.Modes |= DUALPF;
Permit();
/* Put viewport change into effect */
MakeScreen(scrn);
RethinkDisplay();
}
}
return(return_code);
}
/*
** Draw some lines in a rast port...This is used to get some data into
** the second playfield. The windows on the screen will move underneath
** these graphics without disturbing them.
*/
VOID drawSomething(struct RastPort *rp)
{
int width, height;
int r, c;
width = rp->BitMap->BytesPerRow * 8;
height = rp->BitMap->Rows;
SetAPen(rp, 1);
for (r = 0; r < height; r += 40)
{
for (c = 0; c < width; c += 40)
{
Move(rp, 0L, r);
Draw(rp, c, 0L);
}
}
}
/*
** simple event loop to wait for the user to hit the close gadget
** on the window.
*/
VOID handleIDCMP(struct Window *win)
{
BOOL done = FALSE;
struct IntuiMessage *message = NULL;
ULONG class;
ULONG signals;
while (!done)
{
signals = Wait(1L << win->UserPort->mp_SigBit);
if (signals & (1L << win->UserPort->mp_SigBit))
{
while ((!done) &&
(message = (struct IntuiMessage *)GetMsg(win->UserPort)))
{
class = message->Class;
ReplyMsg((struct Message *)message);
switch (class)
{
case IDCMP_CLOSEWINDOW:
done = TRUE;
break;
}
}
}
}
}
/*
** remove the effects of installDualPF().
** only call if installDualPF() succeeded.
*/
VOID removeDualPF(struct Screen *scrn)
{
Forbid();
scrn->ViewPort.RasInfo->Next = NULL;
scrn->ViewPort.Modes &= ~DUALPF;
Permit();
MakeScreen(scrn);
RethinkDisplay();
}