home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
634.lha
/
ASwarm_III
/
ASwarm3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-03
|
34KB
|
1,344 lines
/*
ASwarm III V1.0
ASwarm III by Jake "Wulf" Rose, February '92
Based upon ASwarm II V1.0 by Markus Illenseer and Matthias Scheler, which
was based upon Jeff Buterworth's XSwarm
*/
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/execbase.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <libraries/commodities.h>
#include <libraries/gadtools.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <clib/alib_protos.h>
#include <clib/commodities_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/macros.h>
#include <string.h>
#include <stdlib.h>
#ifdef LATTICE /* some stuff for SAS-C */
#include <pragmas/commodities_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#define VOID_INTERRUPT void __interrupt __saveds
#define REGARGS __regargs
#define VOID_STDARGS void __stdargs
UBYTE *VersionString = "$VER: ASwarm III 1.0 (compiled with SAS/C)";
void chkabort(void)
{}
#else /* some stuff for Dice especially for -mR */
#define VOID_INTERRUPT __stkargs __geta4 void
#define REGARGS
#define VOID_STDARGS __stkargs void
#undef HotKey
#undef ArgArrayInit
#undef ArgInt
#undef ArgString
__stkargs CxObj *HotKey(UBYTE *,struct MsgPort *,long);
__stkargs UBYTE **ArgArrayInit(long arg1,UBYTE **arg2 );
__stkargs LONG ArgInt(UBYTE **arg1,UBYTE *arg2,long arg3 );
__stkargs UBYTE *ArgString(UBYTE **arg1,UBYTE *arg2,UBYTE *arg3);
UBYTE *VersionString = "$VER: ASwarm III 1.0 (compiled with DICE)";
#endif
/*
Common Definitions
*/
extern struct Custom far custom;
extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
#define FINDPROCPORT (&((struct Process *)SysBase->ThisTask)->pr_MsgPort)
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
#define Move(rp,x,y) {(rp)->cp_x=(x); (rp)->cp_y=(y);}
struct Library *CxBase,*GadToolsBase,*IconBase;
/*
Definitions for our Commodity
*/
struct NewBroker NewBroker =
{NB_VERSION,"ASwarm III","Amiga Swarm III V1.0",
"Screen Blanker based on XSwarm", NBU_NOTIFY|NBU_UNIQUE,COF_SHOW_HIDE,
0,NULL,0};
struct MsgPort *CxPort;
UBYTE *PopKey;
UBYTE *BlankKey;
#define HOTKEY_OPEN_WINDOW 1L
#define HOTKEY_BLANK_SCREEN 2L
#define DEF_CX_PRI 0
#define DEF_POPKEY "control alt s"
#define DEF_BLANKKEY "control alt b"
LONG TimeOut,ClientTimeOut;
#define MAX_TIMEOUT 3600L
#define MAX_CLIENT_TIMEOUT 60L
#define DEF_TIMEOUT 60L
#define DEF_CLIENT_TIMEOUT 5L
#define SERVER_PRI 5L
#define CLIENT_PRI -40L
/*
Definitions for Swarm Movement
*/
#define BEEACC 4
#define BEEVEL 44
#define WASPACC 20
#define WASPVEL 52
#define BORDER 5
#define BEE_COL_NUM 32
UWORD BeeColors[BEE_COL_NUM] =
{0x000F,0x004F,0x008F,0x00BF,0x00FF,0x00FB,0x00F7,0x00F3,0x00F0,0x04F0,0x08F0,
0x09F0,0x0AF0,0x0BF0,0x0CF0,0x0DF0,0x0EF0,0x0FF0,0x0FE0,0x0FD0,0x0FC0,0x0FB0,
0x0F90,0x0F80,0x0F70,0x0F60,0x0F50,0x0F40,0x0F30,0x0F20,0x0F10,0x0F00};
#define RAND(m) (Random(m)-(m)/2)
UWORD SwarmColors[4] = {0x0000,0x0FFF};
LONG NumWasps,NumBees,Tightness,Speed;
struct SwarmStruct /* structure for a swarm, including the wasps */
{
WORD ss_Width;
WORD ss_Height;
WORD ss_NumBees;
WORD ss_NumWasps;
WORD ss_WaspVel;
WORD ss_WaspAcc;
WORD ss_BeeVel;
WORD ss_BeeAcc;
WORD *ss_BX[4]; /* the bees */
WORD *ss_BY[4];
WORD *ss_WX[4]; /* the wasps */
WORD *ss_WY[4];
};
#define ss_BXV ss_BX[3]
#define ss_BYV ss_BY[3]
#define ss_WXV ss_WX[3]
#define ss_WYV ss_WY[3]
#define MAX_WASPS 20L
#define MAX_BEES 100L
#define MAX_SPEED 5L
#define MAX_TIGHTNESS 11L
#define DEF_WASPS 3L
#define DEF_BEES 30L
#define DEF_SPEED 3L
#define DEF_TIGHTNESS 6L
/*
Definitions for our Blanker Screen
*/
struct NewScreen NewBlankerScreen =
{0,0,STDSCREENWIDTH,STDSCREENHEIGHT,2,-1,-1,0L,CUSTOMSCREEN|SCREENQUIET,NULL,NULL,NULL,NULL};
struct ModeNode
{
struct Node mn_Node;
UWORD mn_Index;
ULONG mn_DisplayID;
char mn_Name[DISPLAYNAMELEN];
};
struct List *ModeList;
struct ModeNode *DisplayMode;
#define FindMode(l,n) ((struct ModeNode *)FindName(l,n))
#define DEF_MODE HIRES
/*
Definitions for our configuration window
*/
struct NewWindow NewBlankerWindow =
{80,16,0,0,0,1,IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|IDCMP_GADGETDOWN|
IDCMP_GADGETUP|IDCMP_VANILLAKEY|SLIDERIDCMP|LISTVIEWIDCMP,
WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH|SIMPLE_REFRESH,NULL,NULL,NULL,NULL,NULL,
0,0,0,0,WBENCHSCREEN};
struct Window *BlankerWindow;
#define GID_HIDE 1
#define GID_BLANK 2
#define GID_QUIT 3
#define GID_MODE 4
#define GID_TIMEOUT 5
#define GID_CLIENT 6
#define GID_WASPS 7
#define GID_BEES 8
#define GID_SPEED 9
#define GID_TIGHTNESS 10
#define NUM_GADS 10
struct VisualInfo *BlankerVisualInfo;
struct Gadgets *BlankerGadgets;
struct TextAttr BlankerAttr = {"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT};
struct NewGadget NewBlankerGadgets[NUM_GADS] =
{16,101,48,12,"_Hide",&BlankerAttr,GID_HIDE,PLACETEXT_IN,NULL,NULL,
80,101,48,12,"_Blank",&BlankerAttr,GID_BLANK,PLACETEXT_IN,NULL,NULL,
144,101,48,12,"_Quit",&BlankerAttr,GID_QUIT,PLACETEXT_IN,NULL,NULL,
218,17,248,96,"Display Mode",&BlankerAttr,GID_MODE,PLACETEXT_ABOVE,NULL,NULL,
136,5,66,12,"Timeout",&BlankerAttr,GID_TIMEOUT,PLACETEXT_LEFT,NULL,NULL,
136,21,66,12,"Client Timeout",&BlankerAttr,GID_CLIENT,PLACETEXT_LEFT,NULL,NULL,
136,37,66,12,"Tightness ",&BlankerAttr,GID_TIGHTNESS,PLACETEXT_LEFT,NULL,NULL,
136,53,66,12,"Speed ",&BlankerAttr,GID_SPEED,PLACETEXT_LEFT,NULL,NULL,
136,69,66,12,"Wasps ",&BlankerAttr,GID_WASPS,PLACETEXT_LEFT,NULL,NULL,
136,85,66,12,"Bees ",&BlankerAttr,GID_BEES,PLACETEXT_LEFT,NULL,NULL
};
UBYTE BlankerGadgetKinds[NUM_GADS] =
{BUTTON_KIND,BUTTON_KIND,BUTTON_KIND,LISTVIEW_KIND,
INTEGER_KIND,INTEGER_KIND,SLIDER_KIND,SLIDER_KIND,SLIDER_KIND,SLIDER_KIND};
struct TagItem ButtonGadgetTags[] =
{GT_Underscore,(ULONG)'_',TAG_DONE,0L};
struct TagItem ListGadgetTags[] =
{GTLV_Labels,0L,GTLV_Selected,0L,GTLV_ShowSelected,NULL,TAG_DONE,0L};
struct TagItem TimeGadgetTags[] =
{GTIN_Number,0L,GTIN_MaxChars,4L,TAG_DONE,0L};
struct TagItem ClientGadgetTags[] =
{GTIN_Number,0L,GTIN_MaxChars,2L,TAG_DONE,0L};
struct TagItem TightnessGadgetTags[] =
{GTSL_Level,0L,GTSL_Min,1L,GTSL_Max,MAX_TIGHTNESS,GTSL_LevelFormat,0L,
GTSL_LevelPlace,PLACETEXT_LEFT,GTSL_MaxLevelLen,2L,GA_RELVERIFY,TRUE,
TAG_DONE,0L};
struct TagItem SpeedGadgetTags[] =
{GTSL_Level,0L,GTSL_Min,1L,GTSL_Max,MAX_SPEED,GTSL_LevelFormat,0L,
GTSL_LevelPlace,PLACETEXT_LEFT,GTSL_MaxLevelLen,2L,GA_RELVERIFY,TRUE,
TAG_DONE,0L};
struct TagItem WaspGadgetTags[] =
{GTSL_Level,0L,GTSL_Min,1L,GTSL_Max,MAX_WASPS,GTSL_LevelFormat,0L,
GTSL_LevelPlace,PLACETEXT_LEFT,GTSL_MaxLevelLen,2L,GA_RELVERIFY,TRUE,
TAG_DONE,0L};
struct TagItem BeeGadgetTags[] =
{GTSL_Level,0L,GTSL_Min,1L,GTSL_Max,MAX_BEES,GTSL_LevelFormat,0L,
GTSL_LevelPlace,PLACETEXT_LEFT,GTSL_MaxLevelLen,2L,GA_RELVERIFY,TRUE,
TAG_DONE,0L};
struct TagItem *BlankerGadgetTagLists[NUM_GADS] =
{&ButtonGadgetTags[0],
&ButtonGadgetTags[0],
&ButtonGadgetTags[0],
&ListGadgetTags[0],
&TimeGadgetTags[0],
&ClientGadgetTags[0],
&TightnessGadgetTags[0],
&SpeedGadgetTags[0],
&WaspGadgetTags[0],
&BeeGadgetTags[0]
};
/*
Definitions for Server/Client Communication
*/
BYTE bsp_TimerSig,bsp_InputSig,bsp_ClientSig;
struct Task *BlankerServerProcess;
#define MASK(n) (1L<<(n))
struct BlankerClientMsg
{
struct Message bcm_Message;
struct Screen *bcm_Screen;
LONG bcm_Status;
ULONG bcm_SigMask;
LONG bcm_Wasps,bcm_Bees,bcm_Speed,bcm_Tightness;
};
/*
The following functions are taken from my resource tracker library for SAS/C.
I normally use to link the programs with this library, but to make it possible
for other people to compile ASwarmb I included the required source codes.
*/
struct ToolNode
{
struct ToolNode *Next;
void *Tool;
void (*RemProc)(void *,LONG);
LONG Size;
} *ToolList;
void REGARGS RemTool(void *Tool)
{
struct ToolNode **Ptr,*ToolNode;
Ptr=&ToolList;
while (*Ptr)
if ((*Ptr)->Tool==Tool)
{
ToolNode=*Ptr;
*Ptr=(*Ptr)->Next;
ToolNode->RemProc(ToolNode->Tool,ToolNode->Size);
FreeMem (ToolNode,sizeof(struct ToolNode));
}
else Ptr=&(*Ptr)->Next;
}
void REGARGS Quit(int ReturnCode)
{
while (ToolList) RemTool (ToolList->Tool);
exit (ReturnCode);
}
void REGARGS AddTool(void *NewTool,void *ProcPtr,LONG NewSize)
{
struct ToolNode *Ptr;
void (*NewRemProc)(void *,LONG);
NewRemProc=ProcPtr;
if (NewTool==NULL) Quit (10);
if ((Ptr=AllocMem(sizeof(struct ToolNode),MEMF_CLEAR))==NULL)
{
NewRemProc (NewTool,NewSize);
Quit (20);
}
Ptr->Next=ToolList;
Ptr->Tool=NewTool;
Ptr->RemProc=NewRemProc;
Ptr->Size=NewSize;
ToolList=Ptr;
}
/*
Some useful functions
*/
VOID_STDARGS DeleteMsgPortSafely(struct MsgPort *AnyPort)
{
struct Message *AnyMsg;
while (AnyMsg=GetMsg(AnyPort)) ReplyMsg (AnyMsg);
DeleteMsgPort (AnyPort);
}
int REGARGS ArgIntMax(char **ToolTypes,char *ID,int Default,int Max)
{
int Val;
Val=ArgInt(ToolTypes,ID,Default);
if ((Val<1)||(Val>Max)) return Default;
else return Val;
}
/*
Our "InputHandler"
*/
VOID_INTERRUPT BlankerAction(CxMsg *CxMsg,CxObj *CO)
{
struct InputEvent *IE;
IE=(struct InputEvent *)CxMsgData(CxMsg);
if (IE->ie_Class==IECLASS_TIMER) Signal (BlankerServerProcess,1L<<bsp_TimerSig);
else Signal (BlankerServerProcess,1L<<bsp_InputSig);
}
/*
Functions for Handling the List of the avaible Graphics Modes
*/
VOID_STDARGS DeleteModeList(struct List *ModeList)
{
struct ModeNode *ModeNode;
while (ModeList->lh_Head->ln_Succ)
{
ModeNode=(struct ModeNode *)ModeList->lh_Head;
RemHead (ModeList);
FreeMem (ModeNode,sizeof(struct ModeNode));
}
FreeMem (ModeList,sizeof(struct List));
}
struct List *CreateModeList(void)
{
struct List *ModeList;
UWORD Num;
ULONG DisplayID;
struct DimensionInfo DimInfo;
struct NameInfo NameInfo;
struct ModeNode *ModeNode;
if (ModeList=AllocMem(sizeof(struct List),MEMF_PUBLIC)) NewList (ModeList);
else return NULL;
Num=0;
DisplayID=INVALID_ID;
while ((DisplayID=NextDisplayInfo(DisplayID))!=INVALID_ID)
if ((DisplayID&MONITOR_ID_MASK)&&(ModeNotAvailable(DisplayID)==0L))
if (GetDisplayInfoData(NULL,(UBYTE *)&DimInfo,sizeof(struct DimensionInfo),DTAG_DIMS,DisplayID))
if (DimInfo.MaxDepth>1)
if (GetDisplayInfoData(NULL,(UBYTE *)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,DisplayID))
if (ModeNode=AllocMem(sizeof(struct ModeNode),MEMF_PUBLIC))
{
ModeNode->mn_Node.ln_Name=ModeNode->mn_Name;
ModeNode->mn_Index=Num++;
ModeNode->mn_DisplayID=DisplayID;
strcpy (ModeNode->mn_Name,NameInfo.Name);
AddTail (ModeList,&ModeNode->mn_Node);
}
if (ModeList->lh_Head->ln_Succ) return ModeList;
else
{
FreeMem (ModeList,sizeof(struct List));
return NULL;
}
}
struct ModeNode *GetDefaultMode(struct List *ModeList)
{
struct NameInfo NameInfo;
struct ModeNode *ModeNode;
if (GetDisplayInfoData(NULL,(UBYTE *)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,DEF_MODE))
if (ModeNode=FindMode(ModeList,NameInfo.Name)) return ModeNode;
return (struct ModeNode *)ModeList->lh_Head;
}
struct ModeNode *GetIndexMode(struct List *ModeList,UWORD Index)
{
struct ModeNode *ModeNode;
ModeNode=(struct ModeNode *)ModeList->lh_Head;
while (ModeNode->mn_Node.ln_Succ)
if (ModeNode->mn_Index==Index) return ModeNode;
else ModeNode=(struct ModeNode *)ModeNode->mn_Node.ln_Succ;
return (struct ModeNode *)ModeList->lh_Head;
}
/*
Functions for Handling the Configuration Window
*/
LONG GetNum(struct Gadget *Gadget,LONG *Data,LONG Max)
{
LONG NewData;
NewData=((struct StringInfo *)Gadget->SpecialInfo)->LongInt;
if ((NewData<1L)||(NewData>Max))
{
GT_SetGadgetAttrs(Gadget,BlankerWindow,NULL,GTIN_Number,(ULONG)*Data,TAG_DONE);
return FALSE;
}
else
{
*Data=NewData;
return TRUE;
}
}
void CloseBlankerWindow(void)
{
if (BlankerWindow)
{
NewBlankerWindow.LeftEdge=BlankerWindow->LeftEdge;
NewBlankerWindow.TopEdge=BlankerWindow->TopEdge;
RemTool (BlankerGadgets);
RemTool (BlankerVisualInfo);
RemTool (BlankerWindow);
BlankerWindow=NULL;
}
}
void OpenBlankerWindow(void)
{
struct Gadget *Ptr;
UWORD Index;
static char Title[80];
if (BlankerWindow==NULL)
{
strcpy (Title,"ASwarm III: HotKey=");
strcat (Title,PopKey);
if (BlankerWindow=OpenWindowTags(&NewBlankerWindow,WA_Title,Title,
WA_AutoAdjust,TRUE,WA_InnerWidth,472,WA_InnerHeight,118,TAG_DONE))
{
AddTool (BlankerWindow,CloseWindow,NULL);
if ((BlankerVisualInfo=GetVisualInfo(BlankerWindow->WScreen,TAG_DONE))==
NULL)
{
RemTool (BlankerWindow);
return;
}
AddTool (BlankerVisualInfo,FreeVisualInfo,0L);
BlankerGadgets=NULL;
if ((Ptr=CreateContext(&BlankerGadgets))==NULL)
{
RemTool (BlankerVisualInfo);
RemTool (BlankerWindow);
return;
}
AddTool (Ptr,FreeGadgets,0L);
ListGadgetTags[0].ti_Data=(ULONG)ModeList;
ListGadgetTags[1].ti_Data=(ULONG)DisplayMode->mn_Index;
TimeGadgetTags[0].ti_Data=(ULONG)TimeOut;
ClientGadgetTags[0].ti_Data=(ULONG)ClientTimeOut;
TightnessGadgetTags[0].ti_Data=(ULONG)Tightness;
TightnessGadgetTags[3].ti_Data=(ULONG)"%2ld";
SpeedGadgetTags[0].ti_Data=(ULONG)Speed;
SpeedGadgetTags[3].ti_Data=(ULONG)"%2ld";
WaspGadgetTags[0].ti_Data=(ULONG)NumWasps;
WaspGadgetTags[3].ti_Data=(ULONG)"%2ld";
BeeGadgetTags[0].ti_Data=(ULONG)NumBees;
BeeGadgetTags[3].ti_Data=(ULONG)"%3ld";
for (Index=0L; Index<NUM_GADS; Index++)
{
NewBlankerGadgets[Index].ng_TopEdge += BlankerWindow->BorderTop;
NewBlankerGadgets[Index].ng_VisualInfo=BlankerVisualInfo;
Ptr=CreateGadgetA((ULONG)BlankerGadgetKinds[Index],Ptr,
&NewBlankerGadgets[Index],BlankerGadgetTagLists[Index]);
if (Ptr==NULL)
{
CloseBlankerWindow();
return;
}
NewBlankerGadgets[Index].ng_TopEdge -= BlankerWindow->BorderTop;
}
AddGList (BlankerWindow,BlankerGadgets,0L,-1L,NULL);
RefreshGadgets (BlankerGadgets,BlankerWindow,NULL);
GT_RefreshWindow (BlankerWindow,NULL);
}
}
ScreenToFront (BlankerWindow->WScreen);
WindowToFront (BlankerWindow);
ActivateWindow (BlankerWindow);
}
/*
Function to handle the Commodity Stuff
*/
void REGARGS HandleCxMsg(CxObj *Broker,CxMsg *CxMsg,LONG *TimeUntilBlank,
LONG *ThisTimeOut)
{
ULONG MsgType,MsgID;
MsgType=CxMsgType(CxMsg);
MsgID=CxMsgID(CxMsg);
ReplyMsg ((struct Message *)CxMsg);
switch (MsgType)
{
case CXM_IEVENT: /* a hotkey was pressed */
switch (MsgID)
{
case HOTKEY_OPEN_WINDOW:
OpenBlankerWindow();
break;
case HOTKEY_BLANK_SCREEN:
if (*TimeUntilBlank)
*TimeUntilBlank = *ThisTimeOut = 2L;
}
case CXM_COMMAND:
switch (MsgID)
{
case CXCMD_DISABLE: /* Message from Exchange (except CXCMD_UNIQUE) */
(void)ActivateCxObj(Broker,FALSE);
break;
case CXCMD_ENABLE:
(void)ActivateCxObj(Broker,TRUE);
break;
case CXCMD_UNIQUE:
case CXCMD_APPEAR:
OpenBlankerWindow();
break;
case CXCMD_DISAPPEAR:
CloseBlankerWindow();
break;
case CXCMD_KILL:
Quit (0);
}
}
}
/*
Open a Screen with the supplied DisplayID
*/
void SpritesOff(void)
{
OFF_SPRITE /* switch sprites off */
custom.spr[0].ctl=0;
custom.spr[1].ctl=0;
custom.spr[2].ctl=0;
custom.spr[3].ctl=0;
custom.spr[4].ctl=0;
custom.spr[5].ctl=0;
custom.spr[6].ctl=0;
custom.spr[7].ctl=0;
}
struct Screen *CreateScreen(struct List *ModeList,struct ModeNode *ModeNode)
{
struct Screen *Screen;
if (Screen=OpenScreenTags(&NewBlankerScreen,SA_DisplayID,ModeNode->mn_DisplayID,TAG_DONE))
{
SetRGB4 (&Screen->ViewPort,0,0,0,0);
SetRast (&Screen->RastPort,0);
SpritesOff();
}
return Screen;
}
/*
Functions fore Creating/Deleting the Client Process
*/
VOID_STDARGS DeleteBlankerClient(struct MsgPort *BlankerClientPort)
{
struct BlankerClientMsg BlankerClientMsg;
BlankerClientMsg.bcm_Message.mn_ReplyPort=FINDPROCPORT;
PutMsg (BlankerClientPort,(struct Message *)&BlankerClientMsg);
(void)SetTaskPri(BlankerClientPort->mp_SigTask,SERVER_PRI);
(void)WaitPort(BlankerClientMsg.bcm_Message.mn_ReplyPort);
(void)GetMsg(BlankerClientMsg.bcm_Message.mn_ReplyPort);
}
struct MsgPort *REGARGS CreateBlankerClient(void *CodePtr,struct BlankerClientMsg *BlankerClientMsg)
{
struct Process *BlankerClientProcess;
struct TagItem ProcTags[3];
ProcTags[0].ti_Tag=NP_Entry;
ProcTags[0].ti_Data=(ULONG)CodePtr;
ProcTags[1].ti_Tag=NP_Name;
ProcTags[1].ti_Data=(ULONG)"BlankerClient";
ProcTags[2].ti_Tag=TAG_DONE;
if (BlankerClientProcess=CreateNewProc(ProcTags))
{
BlankerClientMsg->bcm_Message.mn_ReplyPort=FINDPROCPORT;
PutMsg (&BlankerClientProcess->pr_MsgPort,(struct Message *)BlankerClientMsg);
(void)WaitPort(BlankerClientMsg->bcm_Message.mn_ReplyPort);
(void)GetMsg(BlankerClientMsg->bcm_Message.mn_ReplyPort);
(void)SetTaskPri((struct Task *)BlankerClientProcess,CLIENT_PRI);
if (BlankerClientMsg->bcm_Status) return &BlankerClientProcess->pr_MsgPort;
}
return NULL;
}
/*
Functions for Creating/Drawing/Removing the Swarm
*/
/* Ill's strange and genius Random Function :-) */
WORD REGARGS Random(WORD Max)
{
static ULONG Num=0L;
ULONG Sec,Mic;
CurrentTime((LONG *)&Sec,(LONG *)&Mic);
Num*=Sec;
Num+=Mic;
while (Num>32767L) Num=Num>>1;
return (WORD)Num%Max;
}
void REGARGS DeleteSwarm(struct SwarmStruct *Swarm,LONG NumWasps,LONG NumBees)
{
ULONG Size;
Size=sizeof(struct SwarmStruct)+sizeof(WORD)*8L*(NumBees+NumWasps);
FreeMem (Swarm,Size);
}
LONG Insure1(LONG val)
{
return ((val==0)? 1:val); /* return value that is at least 1 */
}
struct SwarmStruct *REGARGS CreateSwarm(struct Screen *SwarmScreen,
LONG NumWasps,LONG NumBees,
LONG Speed,LONG Tightness)
/* allocate memory and initialize the swarm */
{
ULONG Size;
LONG Index;
struct SwarmStruct *Swarm,*SP;
WORD *Ptr;
Size=sizeof(struct SwarmStruct)+sizeof(WORD)*8L*(NumBees+NumWasps);
if ((SP=Swarm=AllocMem(Size,MEMF_CLEAR))==NULL) return NULL;
SP->ss_NumBees=NumBees;
SP->ss_NumWasps=NumWasps;
SP->ss_BeeAcc=Insure1(Tightness*BEEACC/Speed/4)*2+1;
SP->ss_BeeVel=Insure1(BEEVEL/Speed);
SP->ss_WaspAcc=Insure1(WASPACC/Speed/2)*2+1;
SP->ss_WaspVel=Insure1(WASPVEL/Speed);
SP->ss_Width=SwarmScreen->Width;
SP->ss_Height=SwarmScreen->Height;
/* point pointers at the proper locations at the end of the memory block */
/* start at the first location after NumBees, NumWasps, Width, and Height */
Ptr = (WORD *)&(SP[1]);
for (Index=0L; Index<4L; Index++)
{
/* bee pointers */
SP->ss_BX[Index]=Ptr;
Ptr+=SP->ss_NumBees;
SP->ss_BY[Index]=Ptr;
Ptr+=SP->ss_NumBees;
/* wasp pointers */
SP->ss_WX[Index]=Ptr;
Ptr+=SP->ss_NumWasps;
SP->ss_WY[Index]=Ptr;
Ptr+=SP->ss_NumWasps;
}
/* Bee locations */
for (Index=0L; Index<SP->ss_NumBees; Index++)
{
SP->ss_BX[1][Index]=SP->ss_BX[0][Index]=
BORDER+Random(SP->ss_Width-2*BORDER);
SP->ss_BY[1][Index]=SP->ss_BY[0][Index]=
BORDER+Random(SP->ss_Height-2*BORDER);
SP->ss_BXV[Index]=RAND(SP->ss_BeeAcc);
SP->ss_BYV[Index]=RAND(SP->ss_BeeAcc);
}
/* Wasp locations */
for (Index=0L; Index<SP->ss_NumWasps; Index++)
{
SP->ss_WX[1][Index]=SP->ss_WX[0][Index]=
BORDER+Random(SP->ss_Width-2*BORDER);
SP->ss_WY[1][Index]=SP->ss_WY[0][Index]=
BORDER+Random(SP->ss_Height-2*BORDER);
SP->ss_WXV[Index]=RAND(SP->ss_WaspAcc);
SP->ss_WYV[Index]=RAND(SP->ss_WaspAcc);
}
return Swarm;
}
/* move the swarm and redraw it */
void REGARGS DrawSwarm(struct SwarmStruct SP[],struct RastPort *WaspRP,
struct RastPort *BeeRP)
{
LONG WIndex, BIndex;
/* Wasp */
for (WIndex=0; WIndex<SP->ss_NumWasps; WIndex++)
{
SP->ss_WX[2][WIndex]=SP->ss_WX[1][WIndex];
SP->ss_WX[1][WIndex]=SP->ss_WX[0][WIndex];
SP->ss_WY[2][WIndex]=SP->ss_WY[1][WIndex];
SP->ss_WY[1][WIndex]=SP->ss_WY[0][WIndex];
SP->ss_WXV[WIndex]+=RAND(SP->ss_WaspAcc);
SP->ss_WYV[WIndex]+=RAND(SP->ss_WaspAcc);
if (SP->ss_WXV[WIndex]>SP->ss_WaspVel) SP->ss_WXV[WIndex]=SP->ss_WaspVel;
if (SP->ss_WXV[WIndex]<-SP->ss_WaspVel) SP->ss_WXV[WIndex]=-SP->ss_WaspVel;
if (SP->ss_WYV[WIndex]>SP->ss_WaspVel) SP->ss_WYV[WIndex]=SP->ss_WaspVel;
if (SP->ss_WYV[WIndex]<-SP->ss_WaspVel) SP->ss_WYV[WIndex]=-SP->ss_WaspVel;
SP->ss_WX[0][WIndex]=SP->ss_WX[1][WIndex]+SP->ss_WXV[WIndex];
SP->ss_WY[0][WIndex]=SP->ss_WY[1][WIndex]+SP->ss_WYV[WIndex];
/* Bounce check */
if ((SP->ss_WX[0][WIndex]<BORDER)||
(SP->ss_WX[0][WIndex]>SP->ss_Width-BORDER-1))
{
SP->ss_WXV[WIndex]=-SP->ss_WXV[WIndex];
if (SP->ss_WX[0][WIndex]<BORDER) SP->ss_WX[0][WIndex]=BORDER;
else SP->ss_WX[0][WIndex]=SP->ss_Width-BORDER-1;
}
if ((SP->ss_WY[0][WIndex]<BORDER)||
(SP->ss_WY[0][WIndex]>SP->ss_Height-BORDER-1))
{
SP->ss_WYV[WIndex]=-SP->ss_WYV[WIndex];
if (SP->ss_WY[0][WIndex]<BORDER) SP->ss_WY[0][WIndex]=BORDER;
else SP->ss_WY[0][WIndex]=SP->ss_Height-BORDER-1;
}
}
/* Bees */
/* just a little more randomness */
SP->ss_BXV[Random(SP->ss_NumBees)]+=RAND(SP->ss_BeeAcc);
SP->ss_BYV[Random(SP->ss_NumBees)]+=RAND(SP->ss_BeeAcc);
for (BIndex=0; BIndex<SP->ss_NumBees; BIndex++)
{
WORD CDistance=0,CDX,CDY;
SP->ss_BX[2][BIndex]=SP->ss_BX[1][BIndex];
SP->ss_BX[1][BIndex]=SP->ss_BX[0][BIndex];
SP->ss_BY[2][BIndex]=SP->ss_BY[1][BIndex];
SP->ss_BY[1][BIndex]=SP->ss_BY[0][BIndex];
for (WIndex=0; WIndex<SP->ss_NumWasps; WIndex++)
{
WORD Distance,DX,DY;
DX=SP->ss_WX[1][WIndex]-SP->ss_BX[1][BIndex];
DY=SP->ss_WY[1][WIndex]-SP->ss_BY[1][BIndex];
Distance=ABS(DX)+ABS(DY);
if (Distance==0) Distance=1;
if ((CDistance==0) || (Distance<CDistance))
{
CDistance=Distance;
CDX=DX;
CDY=DY;
}
}
SP->ss_BXV[BIndex]+=(CDX*SP->ss_BeeAcc)/CDistance;
SP->ss_BYV[BIndex]+=(CDY*SP->ss_BeeAcc)/CDistance;
if (SP->ss_BXV[BIndex]>SP->ss_BeeVel) SP->ss_BXV[BIndex]=SP->ss_BeeVel;
if (SP->ss_BXV[BIndex]<-SP->ss_BeeVel) SP->ss_BXV[BIndex]=-SP->ss_BeeVel;
if (SP->ss_BYV[BIndex]>SP->ss_BeeVel) SP->ss_BYV[BIndex]=SP->ss_BeeVel;
if (SP->ss_BYV[BIndex]<-SP->ss_BeeVel) SP->ss_BYV[BIndex]=-SP->ss_BeeVel;
SP->ss_BX[0][BIndex]=SP->ss_BX[1][BIndex]+SP->ss_BXV[BIndex];
SP->ss_BY[0][BIndex]=SP->ss_BY[1][BIndex]+SP->ss_BYV[BIndex];
/* Bounce check */
if ((SP->ss_BX[0][BIndex]<BORDER)||
(SP->ss_BX[0][BIndex]>(SP->ss_Width-BORDER-1)))
{
SP->ss_BXV[BIndex]=-SP->ss_BXV[BIndex];
SP->ss_BX[0][BIndex]=SP->ss_BX[1][BIndex]+SP->ss_BXV[BIndex];
}
if ((SP->ss_BY[0][BIndex]<BORDER)||
(SP->ss_BY[0][BIndex]>(SP->ss_Height-BORDER-1)))
{
SP->ss_BYV[BIndex]=-SP->ss_BYV[BIndex];
SP->ss_BY[0][BIndex]=SP->ss_BY[1][BIndex]+SP->ss_BYV[BIndex];
}
}
/* Move the insects */
WaitTOF(); /* synchronize with the display */
for (WIndex=0; WIndex<SP->ss_NumWasps; WIndex++) /* Wasps */
{
SetAPen(WaspRP,0);
Move(WaspRP,SP->ss_WX[2][WIndex],SP->ss_WY[2][WIndex]);
Draw(WaspRP,SP->ss_WX[1][WIndex],SP->ss_WY[1][WIndex]);
SetAPen(WaspRP,1);
Draw(WaspRP,SP->ss_WX[0][WIndex],SP->ss_WY[0][WIndex]);
}
for (BIndex=0; BIndex<SP->ss_NumBees; BIndex++) /* Bees */
{
SetAPen (BeeRP,0);
Move (BeeRP,SP->ss_BX[2][BIndex],SP->ss_BY[2][BIndex]);
Draw (BeeRP,SP->ss_BX[1][BIndex],SP->ss_BY[1][BIndex]);
SetAPen (BeeRP,1);
Draw (BeeRP,SP->ss_BX[0][BIndex],SP->ss_BY[0][BIndex]);
}
}
/*
This is the Client Process's Main Loop
*/
VOID_INTERRUPT ASwarmClientProcess(void)
{
struct BlankerClientMsg *BlankerClientMsg;
struct MsgPort *BlankerClientPort;
struct Task *BlankerServerTask;
ULONG BlankerServerSigMask;
struct Screen *SwarmScreen;
LONG Index,NumWasps,NumBees,Speed,Tightness;
struct SwarmStruct *Swarm;
WORD Color,DColor;
static struct RastPort RastPorts[2];
static struct BitMap BitMaps[2];
/* wait for Server's initial Message */
BlankerClientPort=FINDPROCPORT;
(void)WaitPort(BlankerClientPort);
BlankerClientMsg=(struct BlankerClientMsg *)GetMsg(BlankerClientPort);
BlankerServerTask=BlankerClientMsg->bcm_Message.mn_ReplyPort->mp_SigTask;
BlankerServerSigMask=BlankerClientMsg->bcm_SigMask;
NumWasps=BlankerClientMsg->bcm_Wasps;
NumBees=BlankerClientMsg->bcm_Bees;
Tightness=BlankerClientMsg->bcm_Tightness;
Speed=(MAX_SPEED+1-BlankerClientMsg->bcm_Speed);
SwarmScreen=BlankerClientMsg->bcm_Screen;
/* initialize swarm with requested speed and numbers of wasps and bees */
if ((Swarm=CreateSwarm(SwarmScreen,NumWasps,NumBees,Speed,Tightness))==NULL)
{
BlankerClientMsg->bcm_Status=FALSE;
Forbid();
ReplyMsg ((struct Message *)BlankerClientMsg);
return;
}
BlankerClientMsg->bcm_Status=TRUE;
ReplyMsg ((struct Message *)BlankerClientMsg);
/* Here we do a little trick:
We create two RastPorts - one for the Wasp(s), one for the Bees - with one
BitPlane. So we have only to draw in one BitPlane and are able to do it
faster. */
for (Index=0L; Index<2L; Index++)
{
InitRastPort (&RastPorts[Index]);
RastPorts[Index].BitMap=&BitMaps[Index];
InitBitMap (&BitMaps[Index],1L,SwarmScreen->Width,SwarmScreen->Height);
BitMaps[Index].Planes[0]=SwarmScreen->BitMap.Planes[Index];
SetDrMd(&RastPorts[Index],JAM1);
}
Color=-1;
DColor=1;
while ((BlankerClientMsg=
(struct BlankerClientMsg *)GetMsg(BlankerClientPort))==NULL)
{
/* Color Cycling */
Color+=DColor;
if (Color==BEE_COL_NUM)
{
Color-=2;
DColor=-1;
}
else
if (Color<0)
{
Color+=2;
DColor=1;
}
SwarmColors[2]=BeeColors[Color];
LoadRGB4 (&SwarmScreen->ViewPort,SwarmColors,4);
/* Move the Swarm */
DrawSwarm (Swarm,&RastPorts[0],&RastPorts[1]);
Signal (BlankerServerTask,BlankerServerSigMask);
}
/* We are requested to finish, so we do. */
DeleteSwarm (Swarm,NumWasps,NumBees);
Forbid();
ReplyMsg ((struct Message *)BlankerClientMsg);
}
/*
The Main Loop
*/
void main(LONG argc,UBYTE *argv[])
{
char **ToolTypes;
CxObj *Broker,*ObjectList,*Filter;
struct IntuiMessage *IntMsg;
CxMsg *BlankerCxMsg;
LONG ThisTimeOut,TimeUntilBlank,TimeUntilBlack;
struct Screen *BlankerScreen=NULL;
struct BlankerClientPort *BlankerClientPort=NULL;
/* open our Libraries */
AddTool (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L),
CloseLibrary,0L);
AddTool (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",
37L),CloseLibrary,0L);
AddTool (IconBase=OpenLibrary("icon.library",37L),CloseLibrary,0L);
AddTool (CxBase=OpenLibrary("commodities.library",37L),CloseLibrary,0L);
AddTool (GadToolsBase=OpenLibrary("gadtools.library",37L),CloseLibrary,0L);
/* create List of Graphics Modes */
AddTool (ModeList=CreateModeList(),DeleteModeList,0L);
/* get our Arguments */
if (ToolTypes=ArgArrayInit(argc,argv)) AddTool (ToolTypes,ArgArrayDone,0L);
/* get some Signals */
BlankerServerProcess=SysBase->ThisTask;
if ((bsp_TimerSig=AllocSignal(-1L))==-1) Quit (10);
AddTool ((void *)bsp_TimerSig,FreeSignal,0L);
if ((bsp_InputSig=AllocSignal(-1L))==-1) Quit (10);
AddTool ((void *)bsp_InputSig,FreeSignal,0L);
if ((bsp_ClientSig=AllocSignal(-1L))==-1) Quit (10);
AddTool ((void *)bsp_ClientSig,FreeSignal,0L);
/* initialize our Broker = install us as a Commodity */
AddTool (CxPort=CreateMsgPort(),DeleteMsgPortSafely,0L);
NewBroker.nb_Pri=ArgInt(ToolTypes,"CX_PRIORITY",DEF_CX_PRI);
NewBroker.nb_Port=CxPort;
AddTool (Broker=CxBroker(&NewBroker,NULL),DeleteCxObjAll,0L);
/* get Time Out, Client Time Out and Display mode */
TimeOut=ArgIntMax(ToolTypes,"TIMEOUT",DEF_TIMEOUT,MAX_TIMEOUT);
ClientTimeOut=ArgIntMax(ToolTypes,"CLIENTTIMEOUT",DEF_CLIENT_TIMEOUT,MAX_CLIENT_TIMEOUT);
if ((DisplayMode=FindMode(ModeList,ArgString(ToolTypes,"DISPLAY","")))==NULL)
DisplayMode=GetDefaultMode(ModeList);
/* get Parameters for Swarm Movement */
NumWasps=ArgIntMax(ToolTypes,"WASPS",DEF_WASPS,MAX_WASPS);
NumBees=ArgIntMax(ToolTypes,"BEES",DEF_BEES,MAX_BEES);
Speed=ArgIntMax(ToolTypes,"SPEED",DEF_SPEED,MAX_SPEED);
Tightness=ArgIntMax(ToolTypes,"TIGHTNESS",DEF_TIGHTNESS,MAX_TIGHTNESS);
/* install our hot keys */
PopKey=ArgString(ToolTypes,"CX_POPKEY",DEF_POPKEY);
BlankKey=ArgString(ToolTypes,"BLANKKEY",DEF_BLANKKEY);
if ((Filter=HotKey(PopKey,CxPort,HOTKEY_OPEN_WINDOW))==NULL) Quit (10);
else AttachCxObj(Broker,Filter);
if (CxObjError(Filter)) Quit (10);
if ((Filter=HotKey(BlankKey,CxPort,HOTKEY_BLANK_SCREEN))==NULL) Quit (10);
else AttachCxObj(Broker,Filter);
if (CxObjError(Filter)) Quit (10);
/* install our "InputHandler" */
ObjectList=CxCustom(BlankerAction,0L);
AttachCxObj (Broker,ObjectList);
if (CxObjError(ObjectList)) Quit (10);
(void)ActivateCxObj(Broker,TRUE);
AddTool (Broker,ActivateCxObj,FALSE);
/* open Window on startup if not forbidden */
if (stricmp(ArgString(ToolTypes,"CX_POPUP",""),"NO")) OpenBlankerWindow();
/* increase our Priority */
AddTool(FindTask(NULL),SetTaskPri,(LONG)SetTaskPri(FindTask(NULL),SERVER_PRI));
/* start the Loop */
TimeUntilBlank=ThisTimeOut=10L*TimeOut;
TimeUntilBlack=10L*ClientTimeOut;
FOREVER
{
ULONG Mask;
if (BlankerWindow)
Mask=Wait(MASK(bsp_TimerSig)|MASK(bsp_InputSig)|MASK(bsp_ClientSig)|
MASK(CxPort->mp_SigBit)|MASK(BlankerWindow->UserPort->mp_SigBit)|
SIGBREAKF_CTRL_C);
else
Mask=Wait(MASK(bsp_TimerSig)|MASK(bsp_InputSig)|MASK(bsp_ClientSig)|
MASK(CxPort->mp_SigBit)|SIGBREAKF_CTRL_C);
/* process Window Events */
while ((BlankerWindow!=NULL)&&(IntMsg=GT_GetIMsg(BlankerWindow->UserPort)))
switch (IntMsg->Class)
{
struct Gadget *Clicked;
UWORD Code;
case IDCMP_CLOSEWINDOW:
GT_ReplyIMsg (IntMsg);
CloseBlankerWindow();
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh (BlankerWindow);
GT_EndRefresh (BlankerWindow,TRUE);
break;
case IDCMP_GADGETUP:
Code=IntMsg->Code;
Clicked=(struct Gadget *)IntMsg->IAddress;
GT_ReplyIMsg (IntMsg);
switch (Clicked->GadgetID)
{
case GID_HIDE:
CloseBlankerWindow();
break;
case GID_QUIT:
Quit (0);
case GID_BLANK:
if (TimeUntilBlank) TimeUntilBlank=ThisTimeOut=2L;
break;
case GID_MODE:
DisplayMode=GetIndexMode(ModeList,Code);
break;
case GID_TIMEOUT:
if (GetNum(Clicked,&TimeOut,MAX_TIMEOUT)) TimeUntilBlank=ThisTimeOut=10L*TimeOut;
break;
case GID_CLIENT:
if (GetNum(Clicked,&ClientTimeOut,MAX_CLIENT_TIMEOUT)) TimeUntilBlack=10L*ClientTimeOut;
break;
case GID_WASPS:
NumWasps = Code;
break;
case GID_BEES:
NumBees = Code;
break;
case GID_SPEED:
Speed = Code;
break;
case GID_TIGHTNESS:
Tightness = Code;
}
break;
case IDCMP_VANILLAKEY:
Code=IntMsg->Code;
GT_ReplyIMsg (IntMsg);
switch ((char)Code)
{
case 'H':
case 'h':
CloseBlankerWindow();
break;
case 'Q':
case 'q':
Quit (0);
case 'B':
case 'b':
if (TimeUntilBlank) TimeUntilBlank=ThisTimeOut=2L;
}
break;
default:
GT_ReplyIMsg (IntMsg);
}
/* process Commodity Messages */
while (BlankerCxMsg=(CxMsg *)GetMsg(CxPort))
HandleCxMsg (Broker,BlankerCxMsg,&TimeUntilBlank,&ThisTimeOut);
/* check for <CTRL>-C */
if (Mask&SIGBREAKF_CTRL_C) Quit (0);
/* Input detected, unblank if necessary */
if (Mask&MASK(bsp_InputSig))
{
if (TimeUntilBlank==0L)
{
ON_SPRITE
if (BlankerClientPort) RemTool (BlankerClientPort);
RemTool (BlankerScreen);
ThisTimeOut=10L*TimeOut;
}
TimeUntilBlank=ThisTimeOut;
}
/* client has confirmed that it is still alive */
if (Mask&MASK(bsp_ClientSig))
{
ON_DISPLAY
TimeUntilBlack=10L*ClientTimeOut;
}
/* 1/10 sec is over */
if (Mask&MASK(bsp_TimerSig))
if (TimeUntilBlank)
{
TimeUntilBlank--;
if (TimeUntilBlank==0L) /* Time Out reached, blank the screen */
{
struct BlankerClientMsg BlankerClientMsg;
AddTool (BlankerScreen=CreateScreen(ModeList,DisplayMode),CloseScreen,0L);
BlankerClientMsg.bcm_Screen=BlankerScreen;
BlankerClientMsg.bcm_SigMask=1L<<bsp_ClientSig;
BlankerClientMsg.bcm_Wasps=NumWasps;
BlankerClientMsg.bcm_Bees=NumBees;
BlankerClientMsg.bcm_Speed=Speed;
BlankerClientMsg.bcm_Tightness=Tightness;
if (BlankerClientPort=CreateBlankerClient(ASwarmClientProcess,&BlankerClientMsg))
{
TimeUntilBlack=10L*ClientTimeOut; /* try to start Client */
AddTool (BlankerClientPort,DeleteBlankerClient,0L);
}
}
}
else
{
if (IntuitionBase->FirstScreen!=BlankerScreen)
{
ScreenToFront (BlankerScreen);
SpritesOff();
}
if (TimeUntilBlack)
{
TimeUntilBlack--;
if (TimeUntilBlack==0L) OFF_DISPLAY /* Client Time Out reached, turn entire screen black */
}
}
}
}