home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
screen
/
starblnk.lha
/
src
/
StarBlanker.mod
< prev
Wrap
Text File
|
1990-02-21
|
9KB
|
350 lines
IMPLEMENTATION MODULE StarBlanker;
FROM SYSTEM IMPORT ADR, ADDRESS, BYTE, SHIFT, SHORT;
FROM Blitter IMPORT BltClearFlagSet, BltClear,StraightCopy,
BltBitMap;
FROM RunTime IMPORT GfxBase;
FROM Ports IMPORT GetMsg, ReplyMsg, WaitPort;
FROM EasyWindows IMPORT CreateWindow;
FROM EasyScreens IMPORT CreateScreen, SetScreenColor;
FROM RandomNumbers IMPORT Random, seed;
FROM Intuition IMPORT CurrentTime, CloseWindow, CloseScreen,
WindowFlagSet, WindowFlags, IDCMPFlagSet,
IDCMPFlags, WindowPtr, ScreenPtr,
SmartRefresh, ReportMouse, SetPointer,
IntuiMessagePtr;
FROM GfxBase IMPORT GfxBaseRecPtr;
FROM Rasters IMPORT RastPortPtr, AllocRaster, FreeRaster;
FROM Graphics IMPORT BitMapPtr, BitMap, InitBitMap, RASSIZE;
FROM Memory IMPORT AllocMem, FreeMem, MemReqSet, MemReqs;
CONST MaxStars = 128; (* looks good *)
MaxDepth = 3;
MAGIC = 256; (* For Function2() *)
INCR = 4; (* "Speed" of stars in function2() *)
Offset = 1; (* "Speed" of stars in Function() *)
TYPE StarType = RECORD
x, y, z : INTEGER; (* Position of this "star" *)
END;
(* For our blank mouse pointer *)
TYPE PointerPtr = POINTER TO PointerType;
PointerType = ARRAY[0..1] OF CARDINAL;
VAR stars : ARRAY[0..MaxStars-1] OF StarType;
Width, Height : INTEGER; (* Width, height of our display *)
StarScreen : ScreenPtr; (* Pointer to our screen *)
StarWindow : WindowPtr; (* Pointer to our window *)
bm : BitMap; (* Offscreen bitmap for quick blitting *)
ptr: PointerPtr; (* Blank pointer definition *)
method : CARDINAL;
(*
* InitGlobals - Initialize some global variables, namely :
*
* Width, Height - Optimum width/height of lo-res display, considering
* morerows/PAL/what have you
* seed - For slightly more random numbers
* Stars - Pick random locations and "depth"s for the stars
*)
PROCEDURE InitGlobals;
VAR dummy : LONGCARD;
gb : GfxBaseRecPtr;
i : CARDINAL;
BEGIN
gb := GfxBase;
Width := gb^.NormalDisplayColumns DIV 2;
Height:= gb^.NormalDisplayRows;
CurrentTime(dummy,seed);
i := 0;
REPEAT
stars[i].x := Random(Width);
stars[i].y := Random(Height);
stars[i].z := Random(MaxDepth)+1;
INC(i);
UNTIL (i = MaxStars);
END InitGlobals;
(*
* MyWritePixel - Write a pixel into offscreen display memory, so we can
* blit it in really quick
*
* Note - This routine is, I believe, generic enough to use elsewhere.
* I wrote it after finding out how slow WritePixel() is.
* Obviously, this routine does no clipping.
*)
PROCEDURE MyWritePixel(bmap : BitMapPtr; x, y : INTEGER; color : INTEGER);
TYPE Bits = [0..7];
BitSet = SET OF Bits; (* like a short BITSET *)
VAR val : POINTER TO BitSet;
Offset : ADDRESS;
i : CARDINAL;
BEGIN
(* Find correct Y offset *)
Offset := ADDRESS(bmap^.BytesPerRow * CARDINAL(y));
(* Move to beginning of x *)
INC(Offset,x DIV 8);
(* Now Offset is on the right byte. *)
i := 0;
REPEAT
IF i IN BITSET(color) THEN
val := bmap^.Planes[i];
INC(val,Offset);
INCL(val^,7-Bits(x MOD 8)); (* Set the proper bit *)
END;
INC(i);
UNTIL(i = CARDINAL(bmap^.Depth));
END MyWritePixel;
(*
* Function (yeah, I know, it's really a procedure)
*
* Clear the offscreen bitmap, plot the next frame of stars into it,
* and blit it onto the visible display
*)
PROCEDURE Function();
VAR err : LONGCARD;
i : CARDINAL;
BEGIN
(* Clear our display memory *)
i := 0;
REPEAT
BltClear(bm.Planes[i],RASSIZE(Width,Height),BltClearFlagSet{0});
INC(i);
UNTIL(i = 2);
(* Plot the next generation of stars *)
i := 0;
REPEAT
IF stars[i].x+(stars[i].z*Offset) >= Width THEN (* Wrap *)
stars[i].x := 0;
INC(stars[i].y);
IF stars[i].y >= Height THEN
stars[i].y := 0;
END;
ELSE
INC(stars[i].x,stars[i].z*Offset);
END;
MyWritePixel(ADR(bm),stars[i].x,stars[i].y,stars[i].z);
INC(i);
UNTIL i = MaxStars;
(* Now blit in the new bitmap *)
err := BltBitMap(ADR(bm),0,0,
ADR(StarScreen^.BMap),0,0,
Width, Height,
BYTE(0C0H),
BITSET(BYTE(0FFH)),NIL);
END Function;
(*
* See below
*)
PROCEDURE MkPoint(point : INTEGER);
BEGIN
stars[point].x := Random(256);
DEC(stars[point].x,128);
stars[point].y := Random(150);
DEC(stars[point].y,75);
stars[point].z := 255;
END MkPoint;
(*
* Function2 (yeah, I know, it's still a procedure)
*
* This came from Leo Schwab's "Stars" program from a couple of years
* ago. I slightly modified it to work on a 4-color screen and so it
* would use my format for holding the stars. Also, saving the old
* star locations isn't necessary because the screen gets cleared
* every time through.
*)
PROCEDURE Function2();
VAR i : CARDINAL;
err, xs, ys : INTEGER;
BEGIN
(* Clear our display memory *)
i := 0;
REPEAT
BltClear(bm.Planes[i],RASSIZE(Width,Height),BltClearFlagSet{0});
INC(i);
UNTIL(i = 2);
i := 0;
REPEAT
DEC(stars[i].z,INCR);
IF stars[i].z <= 0 THEN
MkPoint(i);
END;
xs := stars[i].x * MAGIC DIV stars[i].z + 160;
ys := stars[i].y * MAGIC DIV stars[i].z + 100;
IF (xs < 0) OR (xs >= Width) OR (ys < 0) OR (ys >= Height) THEN
MkPoint(i);
ELSE
MyWritePixel(ADR(bm),xs,ys,SHIFT(256-stars[i].z,-6));
END;
INC(i);
UNTIL i = MaxStars;
(* Now blit in the new bitmap *)
err := BltBitMap(ADR(bm),0,0,
ADR(StarScreen^.BMap),0,0,
Width, Height,
BYTE(0C0H),
BITSET(BYTE(0FFH)),NIL);
END Function2;
(*
* AllocBitMap - Allocate the temporary bitmap in Chip memory (so
* the blitter can get to it). Also, allocate the image for the
* blank pointer while we're here.
*
* Note - Pointer definition has to be in CHIP memory, which is why
* we're using AllocMem
*)
PROCEDURE AllocBitMap() : BOOLEAN;
BEGIN
InitBitMap(ADR(bm),2,Width,Height);
bm.Planes[0]:=AllocRaster(Width,Height);
IF bm.Planes[0] # NIL THEN
bm.Planes[1]:=AllocRaster(Width,Height);
IF bm.Planes[1] # NIL THEN
(* Alloc the blank pointer while we're here *)
ptr := AllocMem(SIZE(PointerType),MemReqSet{MemClear,MemPublic,MemChip});
IF ptr # NIL THEN
RETURN(TRUE); (* whew, we made it *)
END;
FreeRaster(bm.Planes[1],Width,Height);
END;
FreeRaster(bm.Planes[0],Width,Height);
END;
RETURN(FALSE);
END AllocBitMap;
(*
* FreeBitMap - free stuff created by AllocBitMap()
*)
PROCEDURE FreeBitMap();
BEGIN
FreeMem(ptr,SIZE(PointerType));
FreeRaster(bm.Planes[1],Width,Height);
FreeRaster(bm.Planes[0],Width,Height);
END FreeBitMap;
(*
* OpenDisplay - Does the following :
*
* - Opens the screen
* - Allocates temporary bitmap (using above procedure)
* - Opens the window
* - Starts mouse event report
* - Blanks the pointer
* - Sets the colors
*)
PROCEDURE OpenDisplay() : BOOLEAN;
BEGIN
StarScreen := CreateScreen(Width,Height,2,"");
IF StarScreen # NIL THEN
IF AllocBitMap() THEN
StarWindow := CreateWindow(0,0,Width,Height,"",
IDCMPFlagSet{IntuiTicks,MouseButtons,MouseMove,RawKey,InactiveWindow},
WindowFlagSet{Borderless,Activate,NoCareRefresh}+SmartRefresh,
StarScreen,NIL);
IF StarWindow # NIL THEN
ReportMouse(StarWindow,TRUE);
(* Blank the pointer - note - this is the only way I could think of to do this *)
SetPointer(StarWindow,ptr,1,1,0,0);
SetScreenColor(StarScreen,0,0,0,0);
SetScreenColor(StarScreen,1,5,5,5);
SetScreenColor(StarScreen,2,10,10,10);
SetScreenColor(StarScreen,3,15,15,15);
RETURN(TRUE);
END;
FreeBitMap();
END;
CloseScreen(StarScreen);
END;
RETURN(FALSE);
END OpenDisplay;
(*
* CloseDisplay - Closes everything opened by the above
*)
PROCEDURE CloseDisplay();
BEGIN
FreeBitMap();
CloseWindow(StarWindow);
CloseScreen(StarScreen);
END CloseDisplay;
(*
* DoStarBlank - does the actual blanking.
*
* Note - if any allocations fail, nothing happens, and this
* will return immediately
*)
PROCEDURE DoStarBlank();
VAR i : CARDINAL;
msg : IntuiMessagePtr;
finished : BOOLEAN;
BEGIN
method := Random(2);
IF method = 1 THEN
i := 0;
REPEAT
MkPoint(i);
INC(i);
UNTIL (i = MaxStars);
ELSE
InitGlobals();
END;
IF OpenDisplay() THEN
finished := FALSE;
REPEAT
msg := WaitPort(StarWindow^.UserPort);
LOOP
msg := GetMsg(StarWindow^.UserPort);
IF msg = NIL THEN EXIT; END;
IF msg^.Class = IDCMPFlagSet{IntuiTicks} THEN
IF method = 1 THEN
Function2();
ELSE
Function();
END;
ReplyMsg(msg);
ELSE
finished := TRUE; EXIT;
END;
END; (* loop *)
UNTIL(finished);
CloseDisplay();
END;
END DoStarBlank;
BEGIN
InitGlobals();
END StarBlanker.