home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff256.lzh
/
BlitDemons
/
bdemon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-19
|
14KB
|
425 lines
echo; /* Self-compilation stuff ala John Toebes for Lattice users:
lc -M bdemon.c bdintui.c bdblit.c bdwin.c
blink with bdemon.with
quit
*****************************************************************************
* BlitDemons by Walter Strickler
* This program and all its source code are in the public domain and are
* freely distributable and usable for any purpose, private or commercial.
*
* This program is a port of a program by Loren Blaney which runs under
* Apex, an unknown operating system on the Amiga. It is based on the
* cellular automaton called 'Demons' described in the August, 1989,
* issue of Scientific American.
*
* It is not my fault that it busy-waits. This is usually inexcusable in
* an Amiga program, but it is the call to WaitBlit() that causes it. It is
* really a shame, since this program should require only a small portion of
* the 68000. As it is, it hogs all of it.
****************************************************************************/
#include <math.h>
#include "bdemon.h"
int main()
{
int IntuiReturn,
IPRet,
RetVal;
struct BDMainStruct BDStuff;
IntuiReturn = InitIntui();
if (IntuiReturn == INTUI_OK)
{
IPRet = InitPlanes(&BDStuff, BDWindow);
if (IPRet != PLANES_CHOKE)
{
BDStuff.BDBlitNodes = InitBlits(&BDStuff);
if (BDStuff.BDBlitNodes != NULL)
{
RetVal = MainLoop(&BDStuff);
}
else
{
RetVal = INIT_BLIT_CHOKE;
}
} /* End BDStuff OK */
else
{
RetVal = PLANES_CHOKE;
} /* End BDStuff not OK */
KillPlanes(&BDStuff);
}
else /* Single entry, single exit: so there, Guy! */
{
RetVal = IntuiReturn;
}
CloseIntui();
ErrorMsgs(RetVal);
return RetVal;
} /* End main() */
void ErrorMsgs(ErrorNum)
int ErrorNum;
{
switch (ErrorNum)
{
case 0:
break; /* A-OK */
case NO_INTUI:
printf("Couldn't open Intuition!\n");
break;
case NO_GFX:
printf("Couldn't open Graphics!\n");
break;
case NO_SCREEN:
printf("Couldn't open the Screen.\n");
break;
case NO_WIN:
printf("Couldn't open the Window.\n");
break;
case PLANES_CHOKE:
printf("Couldn't allocate the temp. bit planes.\n");
break;
case ABOUT_CHOKE:
printf("Couldn't open the about window.\n");
break;
case INIT_BLIT_CHOKE:
printf("Couldn't allocate the blitter nodes.\n");
break;
case WBI_CHOKE:
printf("Couldn't start the blitter interrupt.\n");
break;
default:
printf("Unknown error: %d\n", ErrorNum);
break;
}
}
/************************************************************************/
int MainLoop(BDSchtoff)
struct BDMainStruct *BDSchtoff;
{
int RetVal,
LeavingNow,
MsgVal,
MsgControl,
RandReturn,
First;
RetVal = ML_OK;
LeavingNow = FALSE;
MsgControl = NO_WAIT;
First = TRUE;
while (LeavingNow == FALSE)
{
if (First)
{
First = FALSE; /* Do this once only */
MsgVal = NEW; /* Hotwire MsgVal on first time through */
} /* End First */
else
{
if (MsgControl == NO_WAIT) /* If we do WAIT, hurry up and wait! */
{
OneGen(BDSchtoff);
}
MsgVal = CheckMsg(MsgControl);
} /* End not First */
switch (MsgVal)
{
case CLOSE_WIN:
case QUIT:
LeavingNow = TRUE;
break;
case NEW:
RandReturn = Randomize(BDSchtoff, BDWindow);
switch (RandReturn)
{
case RAND_OK:
OffStart(); /* Set menu items */
OnStop();
MsgControl = NO_WAIT;
break;
case RAND_QUIT:
LeavingNow = TRUE;
break;
case RAND_ABOUT_CHOKE:
LeavingNow = TRUE;
RetVal = ABOUT_CHOKE;
break;
}
break;
case STOP:
MsgControl = WAIT;
OffStop();
OnStart();
break;
case START:
MsgControl = NO_WAIT;
OffStart();
OnStop();
break;
case ABOUT:
if (DisplayAbout() == DA_CHOKE)
{
LeavingNow = TRUE;
RetVal = ABOUT_CHOKE;
}
break;
case NO_MSG:
/* One more generation. */
break;
default:
assert (FALSE); /* Shouldn't be here */
break;
} /* End case CheckMsg() */
} /* End while not leaving */
return RetVal;
} /* End MainLoop() */
/*******************************************************************************
InitPlanes() fills in a structure of type BDMainStruct, pointed at by
Strcut, given the pointer to a window, *Win. Returns PLANES_CHOKE if any
allocations weren't successful.
*******************************************************************************/
int InitPlanes(Struct, Win)
struct BDMainStruct *Struct;
struct Window *Win;
{
int i,
DispStartOffset,
RetVal;
RetVal = PLANES_OK;
/* Find the relative start of the blitfield in words */
/* Note that BorderTop and BorderBottom are 1 too large */
DispStartOffset = (((Win -> BorderTop) - 1 ) + Win -> TopEdge)
* ((Win -> WScreen -> Width) / 16) + (Win -> LeftEdge) / 16;
for (i=0; i < NUM_PLANES; i++)
{
(Struct -> Display)[i] = DispStartOffset +
(WORD *) Win -> RPort -> BitMap -> Planes[i]; /* Whew! */
}
Struct -> XSize = Win -> Width;
Struct -> YSize = (Win -> Height) - ((Win -> BorderTop) - 1) -
((Win -> BorderBottom) - 1); /* Sub. borders */
Struct -> Mod = (Win -> WScreen -> Width) - (Win -> Width);/* Blit Modulo */
/* Note that BorderLeft and BorderRight are 2 too large */
Struct -> LRBorder = max (Win -> BorderLeft - 2, Win -> BorderLeft - 2);
/* Now allocate some bitplanes for temporaries... */
Struct -> Temp = (WORD *) AllocRaster(Struct -> XSize, Struct -> YSize);
if (Struct -> Temp == 0)
{
RetVal = PLANES_CHOKE;
} /* End Temp Choke */
else
{
Struct -> Equal = (WORD *)AllocRaster(Struct -> XSize, Struct -> YSize);
if (Struct -> Equal == 0)
{
RetVal = PLANES_CHOKE;
} /* End Equal choke */
else
{
i = 0;
while ((RetVal != PLANES_CHOKE) && (i < NUM_PLANES))
{
Struct -> Incr[i] = (WORD *) AllocRaster(Struct -> XSize,
Struct -> YSize);
if (Struct -> Incr[i] == 0)
{
RetVal = PLANES_CHOKE;
}
i++;
} /* End While allocating Incr */
} /* End Equal OK */
} /* End Temp OK */
return RetVal;
} /* End InitPlanes */
/*******************************************************************************
KillPlanes() deallocates all of the temporary bitplanes allocated
in InitPlanes.
*******************************************************************************/
void KillPlanes(Struct)
struct BDMainStruct *Struct;
{
int i;
if (Struct -> Temp != 0)
{
FreeRaster((PLANEPTR)Struct -> Temp, Struct -> XSize, Struct -> YSize);
Struct -> Temp = 0;
}
if (Struct -> Equal != 0)
{
FreeRaster((PLANEPTR)Struct -> Equal, Struct -> XSize, Struct -> YSize);
Struct -> Equal = 0;
}
for (i = 0; i < NUM_PLANES; i++)
{
if (Struct -> Incr[i] != 0)
{
FreeRaster((PLANEPTR) Struct -> Incr[i], Struct -> XSize,
Struct -> YSize);
Struct -> Incr[i] = NULL;
}
}
} /* End KillPlanes() */
/*******************************************************************************
Randomize() sets every pixel within the borders of the window pointed
at by Win.
*******************************************************************************/
int Randomize(BDStuff, Win)
struct BDMainStruct *BDStuff;
struct Window *Win;
{
int Left,
Right,
Top,
Bottom,
XWords,
YLines,
i,
x,
y,
Redo,
MsgControl,
MsgVal,
LeavingNow,
PlaneNum,
RetVal;
WORD LRBorder,
LMask,
RMask,
*(Disp[NUM_PLANES]),
MyWord,
RandWord;
long Seed;
struct DateStamp *Now;
MsgControl = NO_WAIT;
RetVal = RAND_OK; /* Innocent until proven guilty */
LeavingNow = FALSE;
do /* Loop if Redo gets set to TRUE by the NEW menuitem. */
{
Redo = FALSE; /* Only one more time unless Redo gets set */
/* Seed the random number generator with number of TICK's today: */
Now = (struct DateStamp *) malloc (sizeof (struct DateStamp));
DateStamp(Now); /* This Lattice compiler warning is not my fault */
Seed = (Now -> ds_Tick) + ((Now -> ds_Minute) * TICKS_PER_SECOND * 60);
free(Now);
srand(Seed);
/* Set the border masks */
LRBorder = BDStuff -> LRBorder;
LMask = 0xffff >> LRBorder;
RMask = 0xffff << LRBorder;
/* Set the plane pointers */
for (i=0; i < NUM_PLANES; i++)
{
Disp[i] = BDStuff -> Display[i];
}
/* Clear the screen first */
Left = LRBorder;
Right = ((BDStuff -> XSize) -1) - LRBorder;
Top = (BDWindow -> BorderTop) -1; /* Border off by one */
Bottom = (BDWindow -> Height) - (BDWindow -> BorderBottom);
SetAPen (BDWindow -> RPort, 0);
RectFill (BDWindow -> RPort, Left, Top, Right, Bottom);
/* Now set pixels Randomly */
/* Sweep from top to bottom; bail out if Redo or LeavingNow gets set */
XWords = (BDStuff -> XSize) / 16;
YLines = (BDStuff -> YSize);
y = 0;
while ((y < YLines) && (!Redo) && (!LeavingNow))
{
for (x = 0; x < XWords; x++)
{
for (PlaneNum = 0; PlaneNum < NUM_PLANES; PlaneNum++)
{
RandWord = (rand() >> 8) & 0xffff; /* Use middle 16 bits */
/* Set MyWord given LMask and RMask */
if (x == 0) /* First word */
{
MyWord = *(Disp[PlaneNum]) & ~LMask;
MyWord = MyWord | (RandWord & LMask);
}
else if (x == (XWords -1)) /* Last word */
{
MyWord = *(Disp[PlaneNum]) & ~RMask;
MyWord = MyWord | (RandWord & RMask);
}
else
{
MyWord = RandWord;
}
*(Disp[PlaneNum]) = MyWord;
(Disp[PlaneNum])++;
} /* End for PlaneNum */
} /* End for x */
MsgVal = CheckMsg(MsgControl);
switch(MsgVal)
{
case CLOSE_WIN:
case QUIT:
RetVal = RAND_QUIT;
LeavingNow = TRUE;
break;
case STOP:
MsgControl = WAIT;
OffStop();
OnStart();
break;
case START:
MsgControl = NO_WAIT;
OffStart();
OnStop();
break;
case NEW:
Redo = TRUE;
MsgControl = NO_WAIT;
OffStart();
OnStop();
break;
case ABOUT:
if (DisplayAbout() == DA_CHOKE)
{
LeavingNow = TRUE; /* Let's bomb out now */
RetVal = RAND_ABOUT_CHOKE;
}
break;
case NO_MSG:
break;
default:
assert (FALSE); /* Shouldn't be here */
break;
}
y++; /* Next line */
} /* End for y */
} while (Redo);
return RetVal;
} /* End Randomize() */