
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/sprite.h>

#define REV		0L
#define FRAMES		6
#define SPRHEIGHT	16
#define WORDSPERSPR	(2 * SPRHEIGHT + 4)
#define MAXX		(320-32)
#define MAXY		(200-16)

extern UWORD	ballmask[], ball0[];
extern long	GetSprite();

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

struct NewScreen NewScrn =
{
 0,0,
 320,200,5,
 1,0,
 SPRITES,                 /* ViewModes */
 CUSTOMSCREEN,
 NULL,                    /* Pointer to custom font */
 NULL,                    /* Pointer to title text */
 NULL,                    /* Pointer to screen gadgets */
 NULL                     /* Pointer to custom bitmap */
};


struct NewWindow NewNoBorder =
{
 0,0,
 320,200,
 0,0,
 MOUSEBUTTONS,             /*  IDCMP flags */
 SMART_REFRESH | ACTIVATE | BORDERLESS, /* flags */
 NULL,                    /* Pointer to first gadget */
 NULL,                    /* Pointer to Check Mark image */
 NULL,                    /* Title */
 NULL,                    /* Pointer to Screen structure */
 NULL,                    /* Pointer to custom bitmap */
 0,0,                     /* Min Width, Min Height */
 0,0,                     /* Max Width, Max Height */     
 CUSTOMSCREEN             /* Type of Screen this window resides on */
};

/*	Doing it this way is faster than saying  (i+offset) % 6  */
UBYTE		idx[] = { 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4 };


struct SimpleSprite	spr[FRAMES];
struct Window	*NoBorder;
struct Screen *Scrn;
struct ViewPort	*vp;
struct RastPort *rp;
UWORD		*sprbuf;
UWORD		*sprites[FRAMES];
int		vx[FRAMES], vy[FRAMES];


main (argc,argv)
int argc;
char *argv[];
{
int i, offset = 0, flag = 0, speed;

struct IntuiMessage *msg;

openstuff ();
setupsprites ();

for (i=0; i<FRAMES; i++)
{
 if (GetSprite (&spr[i], (long) i+2) < 0)
  die ("Sprite allocation failed.");
 spr[i].x = 16*i;
 spr[i].y = 16*i;
 spr[i].height = SPRHEIGHT;
 ChangeSprite (vp, &spr[i], sprites[i]);
}

if(argc>1)
  speed = 1 << atoi(argv[1]);
else
  speed = 4;

for (i=0; i<FRAMES; i++)
{
 vx[i]= vy[i]=speed;
}

--speed;

for(;;)
{
WaitTOF ();
if (msg = GetMsg (NoBorder -> UserPort))
{
 ReplyMsg (msg);
 closestuff ();
 return;
}


for (i=0; i<FRAMES; i++)
{

 if((spr[i].x += vx[i]) >= MAXX-speed || spr[i].x <= speed)
 {
  vx[i] = -vx[i];
 }

 if((spr[i].y += vy[i]) >= MAXY-speed || spr[i].y <= speed)
 {
  vy[i] = -vy[i];
 }
}

 /* Hey !!! ChangeSprite also MOVES the sprites !!!! */
for (i=0; i<FRAMES; i++) ChangeSprite (vp, &spr[i], sprites[idx[i+offset]]);

 /*  Rotate balls every other loop  */
if (flag = !flag) offset = (offset + 1) % 6;

}

} /* end of main */

openstuff ()
{
register int i;

if (!(IntuitionBase = OpenLibrary ("intuition.library", REV)))
 die ("");

if (!(GfxBase = OpenLibrary ("graphics.library", REV)))
  die ("");

if((NewNoBorder.Screen = Scrn = OpenScreen(&NewScrn)) == NULL)
 die("");

if((NoBorder = OpenWindow(&NewNoBorder)) == NULL)
 die("");

vp = ViewPortAddress (NoBorder);
rp = &Scrn->RPort;

for (i=20; i<32; i += 4)
 {
  SetRGB4 (vp, i+1L, 15L, 0L, 0L);
  SetRGB4 (vp, i+3L, 0L, 0L, 15L);
 }
}

closestuff ()
{
	register int i;

	for (i=0; i<FRAMES; i++)
		if (spr[i].num)
			FreeSprite ((long) spr[i].num);

	if (sprbuf)
		FreeMem (sprbuf, 2L * WORDSPERSPR * FRAMES);
	if (NoBorder)
		CloseWindow (NoBorder);
        if(Scrn)
                CloseScreen(Scrn);
	if (GfxBase)
		CloseLibrary (GfxBase);
	if (IntuitionBase)
		CloseLibrary (IntuitionBase);
}

die (str)
char *str;
{
	if (NoBorder) {
		SetWindowTitles (NoBorder, str, -1L);
		WaitPort (NoBorder -> UserPort);
	} else
		puts (str);
	closestuff ();
	exit (100);
}

/*
 * The following code segment was lifted (nearly) intact from the Alpha-9
 * 1.2 README disk.  Thanks to Jim Mackraz for the code, and also for
 * drawing all those ball sprites.
 */
setupsprites ()
{
	UWORD *cw;	/* current position in buffer of sprite images */
	UWORD *maskp;	/* current position in ballmask             */
	UWORD *ballp;	/* current position in ball0 data           */
	int frame, scan;

	if (!(sprbuf = AllocMem (2L * WORDSPERSPR * FRAMES, MEMF_CHIP)))
		die ("Can't allocate sprite buffer.");

	cw = sprbuf;	/* current position at top of buffer */
	ballp = ball0;	/* ... top of data to be interleaved */

	for (frame=0; frame<FRAMES; frame++) {
		maskp = ballmask;	/* one mask for all frames */
		sprites[frame] = cw;
		*cw++ = 0;		/* poscntl */
		*cw++ = 0;

		/* one word from ball0, one word from ballmask */
		for (scan=0; scan<SPRHEIGHT; scan++) {
			*cw++ = *maskp++;
			*cw++ = *ballp++;
		}
		*cw++ = 0;	/* termination */
		*cw++ = 0;
	}
}

#asm
*:ts=8 bk=0
_ballmask:
	public	_ballmask

	dc.w	%0000011111100000
	dc.w	%0001111111111000
	dc.w	%0011111111111100
	dc.w	%0111111111111110
	dc.w	%0111111111111110
	dc.w	%1111111111111111
	dc.w	%1111111111111111
	dc.w	%1111111111111111
	dc.w	%1111111111111111
	dc.w	%1111111111111111
	dc.w	%1111111111111111
	dc.w	%0111111111111110
	dc.w	%0111111111111110
	dc.w	%0011111111111100
	dc.w	%0001111111111000
	dc.w	%0000011111100000


_ball0:
	public	_ball0

	dc.w	%0000011001100000
	dc.w	%0001100110011000
	dc.w	%0011001111001100
	dc.w	%0001110000111000
	dc.w	%0011110000111100
	dc.w	%0011100000011100
	dc.w	%1100011111100011
	dc.w	%1000011111100001
	dc.w	%1000011111100001
	dc.w	%1100011111100011
	dc.w	%0011100000011100
	dc.w	%0011110000111100
	dc.w	%0001110000111000
	dc.w	%0011001111001100
	dc.w	%0001100110011000
	dc.w	%0000011001100000


_ball1:
	public	_ball1

	dc.w	%0000010011000000
	dc.w	%0001001100110000
	dc.w	%0010011100011000
	dc.w	%0001100001110010
	dc.w	%0011100001111010
	dc.w	%0111000001111001
	dc.w	%1000111110000111
	dc.w	%1000111110000011
	dc.w	%1000111110000011
	dc.w	%1000111110000111
	dc.w	%0111000001111001
	dc.w	%0011100001111010
	dc.w	%0001100001110010
	dc.w	%0010011100011000
	dc.w	%0001001100110000
	dc.w	%0000010011000000


_ball2:
	public	_ball2

	dc.w	%0000010011000000
	dc.w	%0001001100110000
	dc.w	%0000011000011000
	dc.w	%0011000111100110
	dc.w	%0010000111100010
	dc.w	%0110000111110001
	dc.w	%0001111000001110
	dc.w	%0011111000001110
	dc.w	%0011111000001110
	dc.w	%0001111000001110
	dc.w	%0110000111110001
	dc.w	%0010000111100010
	dc.w	%0011000111100110
	dc.w	%0000011000011000
	dc.w	%0001001100110000
	dc.w	%0000010011000000


_ball3:
	public	_ball3

	dc.w	%0000000110000000
	dc.w	%0000011001100000
	dc.w	%0000110000110000
	dc.w	%0110001111000110
	dc.w	%0110001111000110
	dc.w	%1100011111100011
	dc.w	%0011100000011100
	dc.w	%0111100000011110
	dc.w	%0111100000011110
	dc.w	%0011100000011100
	dc.w	%1100011111100011
	dc.w	%0100001111000010
	dc.w	%0110001111000110
	dc.w	%0000110000110000
	dc.w	%0000011001100000
	dc.w	%0000000110000000


_ball4:		; Batter takes first base
	public	_ball4

	dc.w	%0000001100100000
	dc.w	%0000110011001000
	dc.w	%0001100001100000
	dc.w	%0110011110001100
	dc.w	%0100011110000100
	dc.w	%1000111110000110
	dc.w	%0111000001111000
	dc.w	%0111000001111100
	dc.w	%0111000001111100
	dc.w	%0111000001111000
	dc.w	%1000111110000110
	dc.w	%0100011110000100
	dc.w	%0110011110001100
	dc.w	%0001100001100000
	dc.w	%0000110011001000
	dc.w	%0000001100100000


_ball5:
	public	_ball5

	dc.w	%0000001100100000
	dc.w	%0000110011001000
	dc.w	%0001100011100100
	dc.w	%0100111000011000
	dc.w	%0101111000011100
	dc.w	%1001111000001110
	dc.w	%1110000111110001
	dc.w	%1100000111110001
	dc.w	%1100000111110001
	dc.w	%1110000111110001
	dc.w	%1001111000001110
	dc.w	%0101111000011100
	dc.w	%0101111000011000
	dc.w	%0001100011100100
	dc.w	%0000110011001000
	dc.w	%0000001100100000


#endasm

