/* doublebuffer.c
** show the use of a double-buffered screen.
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y doublebuffer
** blink FROM LIB:c.o doublebuffer.o TO doublebuffer 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 <intuition/screens.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#ifdef LATTICE
int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); } /* really */
#endif
/* characteristics of the screen */
#define SCR_WIDTH (320)
#define SCR_HEIGHT (200)
#define SCR_DEPTH (2)
/* Prototypes for our functions */
VOID runDBuff(struct Screen *, struct BitMap ** );
struct BitMap **setupBitMaps( LONG, LONG, LONG );
VOID freeBitMaps(struct BitMap **,LONG, LONG, LONG );
LONG setupPlanes(struct BitMap *, LONG, LONG, LONG );
VOID freePlanes(struct BitMap *, LONG, LONG, LONG );
struct Library *IntuitionBase = NULL;
struct Library *GfxBase = NULL;
/*
** Main routine. Setup for using the double buffered screen.
** Clean up all resources when done or on any error.
*/
VOID main(int argc, char **argv)
{
struct BitMap **myBitMaps;
struct Screen *screen;
struct NewScreen myNewScreen;
IntuitionBase = OpenLibrary("intuition.library", 33L);
if ( IntuitionBase != NULL )
{
GfxBase = OpenLibrary("graphics.library", 33L);
if ( GfxBase != NULL )
{
myBitMaps = setupBitMaps(SCR_DEPTH, SCR_WIDTH, SCR_HEIGHT);
if ( myBitMaps != NULL )
{
/* Open a simple quiet screen that is using the first
** of the two bitmaps.
*/
myNewScreen.LeftEdge=0;
myNewScreen.TopEdge=0;
myNewScreen.Width=SCR_WIDTH;
myNewScreen.Height=SCR_HEIGHT;
myNewScreen.Depth=SCR_DEPTH;
myNewScreen.DetailPen=0;
myNewScreen.BlockPen=1;
myNewScreen.ViewModes=HIRES;
myNewScreen.Type=CUSTOMSCREEN | CUSTOMBITMAP | SCREENQUIET;
myNewScreen.Font=NULL;
myNewScreen.DefaultTitle=NULL;
myNewScreen.Gadgets=NULL;
myNewScreen.CustomBitMap=myBitMaps[0];
screen = OpenScreen(&myNewScreen);
if (screen != NULL)
{
/* Indicate that the rastport is double buffered. */
screen->RastPort.Flags = DBUFFER;
runDBuff(screen, myBitMaps);
CloseScreen(screen);
}
freeBitMaps(myBitMaps, SCR_DEPTH, SCR_WIDTH, SCR_HEIGHT);
}
CloseLibrary(GfxBase);
}
CloseLibrary(IntuitionBase);
}
}
/*
** setupBitMaps(): allocate the bit maps for a double buffered screen.
*/
struct BitMap **setupBitMaps(LONG depth, LONG width, LONG height)
{
/* this must be static -- it cannot go away when the routine exits. */
static struct BitMap *myBitMaps[2];
myBitMaps[0] = (struct BitMap *) AllocMem((LONG)sizeof(struct BitMap), MEMF_CLEAR);
if (myBitMaps[0] != NULL)
{
myBitMaps[1] = (struct BitMap *)AllocMem((LONG)sizeof(struct BitMap), MEMF_CLEAR);
if (myBitMaps[1] != NULL)
{
InitBitMap(myBitMaps[0], depth, width, height);
InitBitMap(myBitMaps[1], depth, width, height);
if (NULL != setupPlanes(myBitMaps[0], depth, width, height))
{
if (NULL != setupPlanes(myBitMaps[1], depth, width, height))
return(myBitMaps);
freePlanes(myBitMaps[0], depth, width, height);
}
FreeMem(myBitMaps[1], (LONG)sizeof(struct BitMap));
}
FreeMem(myBitMaps[0], (LONG)sizeof(struct BitMap));
}
return(NULL);
}
/*
** runDBuff(): loop through a number of iterations of drawing into
** alternate frames of the double-buffered screen. Note that the
** object is drawn in color 1.
*/
VOID runDBuff(struct Screen *screen, struct BitMap **myBitMaps)
{
WORD ktr, xpos, ypos;
WORD toggleFrame;
toggleFrame = 0;
SetAPen(&(screen->RastPort), 1);
for (ktr = 1; ktr < 200; ktr++)
{
/* Calculate a position to place the object, these
** calculations insure the object will stay on the screen
** given the range of ktr and the size of the object.
*/
xpos = ktr;
if ((ktr % 100) >= 50)
ypos = 50 - (ktr % 50);
else
ypos = ktr % 50;
/* switch the bitmap so that we are drawing into the correct place */
screen->RastPort.BitMap = myBitMaps[toggleFrame];
screen->ViewPort.RasInfo->BitMap = myBitMaps[toggleFrame];
/* Draw the objects.
** Here we clear the old frame and draw a simple filled rectangle.
*/
SetRast(&(screen->RastPort), 0);
RectFill(&(screen->RastPort), xpos, ypos, xpos+100, ypos+100);
/* update the physical display to match the newly drawn bitmap. */
MakeScreen(screen); /* Tell intuition to do its stuff. */
RethinkDisplay(); /* Intuition compatible MrgCop & LoadView */
/* it also does a WaitTOF(). */
/* switch the frame number for next time through */
toggleFrame ^= 1;
}
}
/*
** freeBitMaps(): free up the memory allocated by setupBitMaps().
*/
VOID freeBitMaps(struct BitMap **myBitMaps, LONG depth, LONG width, LONG height)
{
freePlanes(myBitMaps[0], depth, width, height);
freePlanes(myBitMaps[1], depth, width, height);
FreeMem(myBitMaps[0], (LONG)sizeof(struct BitMap));
FreeMem(myBitMaps[1], (LONG)sizeof(struct BitMap));
}
/*
** setupPlanes(): allocate the bit planes for a screen bit map.
*/
LONG setupPlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height)
{
SHORT plane_num ;
for (plane_num = 0; plane_num < depth; plane_num++)
{
bitMap->Planes[plane_num] = (PLANEPTR)AllocRaster(width, height);
if (bitMap->Planes[plane_num] != NULL )
BltClear(bitMap->Planes[plane_num], (width / 8) * height, 1);
else
{
freePlanes(bitMap, depth, width, height);
return(NULL);
}
}
return(TRUE);
}
/*
** freePlanes(): free up the memory allocated by setupPlanes().
*/
VOID freePlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height)
{
SHORT plane_num ;
for (plane_num = 0; plane_num < depth; plane_num++)
{
if (bitMap->Planes[plane_num] != NULL)
FreeRaster(bitMap->Planes[plane_num], width, height);
}
}
[Back to Amiga Developer Docs]