Mike Wallace Disk (Disk 98) (Jul 1988) : ExtraHalfBright / EHB.c

/*  :ts=8 bk=0
 *
 * ehb.c:	Program that lets you see if you have EXTRA_HALFBRITE
 *		mode in your system.  Much more obvious than the previously
 *		published program.
 *
 * Leo L. Schwab			8706.16		(415)-456-6565
 */
#include <exec/types.h>
#include <intuition/intuition.h>

#define	DEEP		6	/*  # of bitplanes needed for EHB  */
#define	WIDE		320
#define	HIGH		200
#define	XSIZE		(WIDE - 1)
#define	YSIZE		(HIGH - 1)

extern void	*OpenLibrary(), *OpenScreen(), *OpenWindow(), *GetMsg();
extern long	VBeamPos(), TextLength();
extern short	rnd();


struct NewScreen scrdef = {
	0, 0, WIDE, HIGH, DEEP,
	0, 1,
	EXTRA_HALFBRITE,	/*  This is how you ask for EHB mode  */
	CUSTOMSCREEN,
	NULL, NULL, NULL, NULL
};

struct NewWindow windef = {
	0, 0, WIDE, HIGH,
	-1, -1,
	CLOSEWINDOW,
	WINDOWCLOSE,
	NULL, NULL, NULL,
	NULL,			/*  This pointer filled in later  */
	NULL,
	0, 0, 0, 0,
	CUSTOMSCREEN
};

struct Screen	*scr;
struct Window	*win;
void		*GfxBase, *IntuitionBase;


main ()
{
	register struct RastPort	*rp;
	register int			i;
	long				x1, y1, x2, y2, ox1, oy1, ox2, oy2;
	int				dx1, dy1, dx2, dy2;
	void				*msg;

	openstuff ();
	rp = &scr -> RastPort;
	SetRast (rp, 0L);

	rnd ((short) -VBeamPos());

	hsl_wheel ();

	rp -> Mask = (1 << 5) - 1;	/*  Don't touch 6th plane yet  */
	for (x1=0; x1<100; x1++) {
		SetAPen (rp, x1);
		RectFill (rp, x1, x1, XSIZE-x1, YSIZE-x1);
	}

	SetDrMd (rp, COMPLEMENT);
	rp -> Mask = 1 << 5;		/*  Prepare to show halfbrite  */
	RectFill (rp, 0L, 0L, WIDE-1L, HIGH-1L);	/* Dim everything */
	centertext (rp, 90, "Congratulations!");
	centertext (rp, 110, "You have Extra-Halfbrite mode!");

	/*  Finish off by drawing an EHB line all over the place  */
	x1 = rnd (WIDE);  x2 = rnd (WIDE);
	y1 = rnd (HIGH);  y2 = rnd (HIGH);
	setdxdy (&dx1, &dy1);
	setdxdy (&dx2, &dy2);

	ox1 = -9999;
	FOREVER {
		if (msg = GetMsg (win -> UserPort)) {
			ReplyMsg (msg);
			break;
		}

		if (!rnd (43))
			if (rnd (2))
				setdxdy (&dx1, &dy1);
			else
				setdxdy (&dx2, &dy2);

		x1 += dx1;  y1 += dy1;
		if (x1 > XSIZE || x1 < 0) {
			dx1 = -dx1;
			x1 = x1<0 ? 0 : XSIZE;
		}
		if (y1 > YSIZE || y1 < 0) {
			dy1 = -dy1;
			y1 = y1<0 ? 0 : YSIZE;
		}
		x2 += dx2;  y2 += dy2;
		if (x2 > XSIZE || x2 < 0) {
			dx2 = -dx2;
			x2 = x2<0 ? 0 : XSIZE;
		}
		if (y2 > YSIZE || y2 < 0) {
			dy2 = -dy2;
			y2 = y2<0 ? 0 : YSIZE;
		}

		if (ox1 >= 0)
			box (rp, ox1, oy1, ox2, oy2);
		box (rp, x1, y1, x2, y2);
		WaitTOF ();

		ox1 = x1;  oy1 = y1;
		ox2 = x2;  oy2 = y2;
	}

	closestuff ();
}

box (rp, x1, y1, x2, y2)
register struct RastPort *rp;
long x1, y1, x2, y2;
{
	register long tmp;

	if (x2 < x1)
		tmp = x2, x2 = x1, x1 = tmp;

	if (y2 < y1)
		tmp = y2, y2 = y1, y1 = tmp;

	RectFill (rp, x1, y1, x2, y2);
}

centertext (rp, y, str)
register struct RastPort *rp;
char *str;
{
	register long len = strlen (str);

	Move (rp, (WIDE - TextLength (rp, str, len)) >> 1, (long) y);
	Text (rp, str, len);
}

setdxdy (x, y)
register int *x, *y;
{
	*x = rnd (9) - 4;
	*y = rnd (9) - 4;
}

/*  This function computes an HSL color wheel (or tries to)  */
hsl_wheel ()
{
	register struct ViewPort	*vp = &scr -> ViewPort;
	register long			r, g, b;
	int				i, sixth;

	for (i=0; i<32; i++) {
		sixth = i * 6 >> 5;	/*  i * 6 / 32  */
		switch (sixth) {
		case 0:		/*  Green on rise, red solid  */
			r = 15;
			g = 3*i;
			b = 0;
			break;
		case 1:		/*  Red falling  */
			r = 32 - 3*i;
			g = 15;
			b = 0;
			break;
		case 2:		/*  Blue rising  */
			r = 0;
			g = 15;
			b = 3*i - 48;
			break;
		case 3:		/*  Green falling */
			r = 0;
			g = 64 - 3*i;
			b = 15;
			break;
		case 4:		/*  Red rising  */
			r = 3*i - 80;
			g = 0;
			b = 15;
			break;
		case 5:		/*  Blue falling  */
			r = 15;
			g = 0;
			b = 96 - 3*i;
		}
		SetRGB4 (vp, (long) i, r, g, b);
	}
}

openstuff ()
{
	if (!(IntuitionBase = OpenLibrary ("intuition.library", 0L)))
		die ("Mackraz isn't around.\n");

	if (!(GfxBase = OpenLibrary ("graphics.library", 0L)))
		die ("Dale is on vacation.\n");

	if (!(scr = OpenScreen (&scrdef)))
		die ("Screen wouldn't open.\n");

	windef.Screen = scr;
	if (!(win = OpenWindow (&windef)))
		die ("Window painted shut.\n");
}

closestuff ()
{
	if (win)		CloseWindow (win);
	if (scr)		CloseScreen (scr);
	if (GfxBase)		CloseLibrary (GfxBase);
	if (IntuitionBase)	CloseLibrary (IntuitionBase);
}

die (str)
char *str;
{
	extern long	Output();

	Write (Output(), str, (long) strlen (str));
	closestuff ();
	exit (20);
}

#asm
*\
*  :ts=8
* Yet Another random number generator.  By Leo Schwab.
* Based on an idea posted on the USENET (Thanks, Sam Dicker!)
* For the Manx assembler.
*
* Calling convention:
*  short rnd (range);
*  short range;
*
* 8606.30
*/

		public    _rnd

_rnd		lea	rndseed,a0	Get address of seed
		move.w	4(sp),d1	Get range argument
		tst.w	d1
		ble.s	setseed		Go reset seed


		move.l	(a0),d0		Get seed
		ADD.L   D0,D0
		BHI.S   over
		EORI.L  #$1D872B41,D0
over
		move.l	d0,(a0)		Save new seed
		andi.l	#$ffff,d0	Coerce into word
		divu	d1,d0		Divide by range
		swap	d0		 and get remainder (modulus)
		rts

setseed		neg.w	d1		Probably don't need this
		move.l	d1,(a0)
		rts

		dseg
rndseed		dc.l	0
		cseg
#endasm