home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
026.lha
/
robotr_off
/
Robotroff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-04-02
|
10KB
|
375 lines
/* :ts=8 bk=0
*
* robotroff.c: Insidious display hack.
*
* Leo L. Schwab 8703.17 (415)-456-6565
*
* Public Domain. Reproduce at will. However, the author would greatly
* appreciate it if:
* 1) All parts of the program are made available free of charge
* (or for cost of media),
* 2) You don't use this in a commercial product unless you at least
* tell me about it,
* 3) This notice and the author's name are preserved, even across
* subsequent revisions (I want to be famous, you see).
*
* Naturally, you don't *have* to abide by these terms. Just remember
* that if you do violate them, it means you are morally bankrupt. You
* wouldn't want people to think that about you, would you?
*
*************************************************************************
A few notes on the code:
Bits of it are extremely messy. Some of it looks unnecessary or
wrong. As it turns out, this program works as written. Hope you can
understand the code; some of it is instructive. Watch out for ternary
operators; I've used quite a few of them.
Since this is supposed to be a background display hack, it was
important to me to make it as small as I could and still do interesting
things. This meant leaving out a couple of features I would have liked.
It would have been nice to have an explosion noise when the grunt or
enforcer ran into the mouse. I was also thinking about arranging things
so that, if you plugged in a joystick at port 2 and tilted it around, you
could shoot the enemy sprites. These are ideas that the more ambitious
among you might want to add in. Some of you may have even more insidious
ideas. Go right ahead.
I encountered some odd behavior in the system I never noticed
before. For example, if you AbortIO() an I/O request, the reply gets posted
to your reply port, and the signal you might Wait() on gets set. WaitIO()
does not clear this signal apparently; I had to do it myself.
Also, when moving the mouse pointer with false InputEvents, I
noticed that the mouse pointer, even in a 200-line screen, assumes it's in
a 400-line screen, and therefore a "movement" of 2 results in an actual
pointer movement of 1. Odd. Does anyone have an explanation for this?
I tried to write the code in a such a way that it *should* work on
an interlaced screen, as well as one that's been 'morerows'ed. However,
since 'morerows' causes overscan, which tromps sprite DMA, this may not
work on an overscan screen. Oddly enough, it also seems to work with any
combination of screens, no matter their arrangement.
I had fun writing this program. I hope you like it at least as
much as you liked Oing.
"If you've enjoyed this program just half as much as I've enjoyed
writing it, then I'll have enjoyed it twice as much as you."
Have fun,
Leo L. Schwab
*************************************************************************/
#include <ctype.h>
#include <exec/types.h>
#include <exec/alerts.h>
#include <intuition/intuition.h>
#include <graphics/sprite.h>
#include <devices/input.h>
#include "robotroff.h"
/* We're just opening this to get a pointer to the WorkBench ViewPort */
struct NewWindow windef = {
0, 0, 3, 10,
-1, -1,
NULL,
NULL,
NULL, NULL,
NULL,
NULL, NULL, 0, 0, 0, 0,
WBENCHSCREEN
};
struct MsgPort *ioport, *timeport, *cmdport;
struct IOStdReq *ioreq;
struct timerequest *timereq;
struct control *ctl;
struct InputEvent mouse;
struct SimpleSprite spr;
struct Preferences prefs;
struct Screen *wbs;
struct Window *win;
long sprnum = -1;
int wide, high;
void *vp;
void *IntuitionBase, *GfxBase;
/* I take so many liberties with void *'s, it's scary. */
main (ac, av)
char **av;
{
void *daemon;
if (daemon = FindPort (PORTNAME))
reconfigure (ac, av, daemon);
else {
dodaemon (ac, av);
postmessage ("Robotroff daemon terminated.");
}
closestuff ();
}
dodaemon (ac, av)
char **av;
{
/*
* cmdport in this context means the port at which commands arrive
* for the daemon to act on.
*/
register struct control *msg;
long csig, tsig, signals;
int hw = DEFAULTHIGHWATER, lw = DEFAULTLOWATER, now = 0;
void *me, *oldms;
openstuff ();
rnd ((short) -VBeamPos()); /* Seed generator */
me = FindTask (NULL);
/* Parse command args */
if (ac)
while (++av, --ac) {
if (!strncmp (*av, "-h", 2)) {
hw = atoi (&(*av)[2]);
if (hw <= 0)
hw = DEFAULTHIGHWATER;
} else if (!strncmp (*av, "-l", 2)) {
lw = atoi (&(*av)[2]);
if (lw <= 0)
lw = DEFAULTLOWATER;
} else if (!strncmp (*av, "-p", 2))
SetTaskPri (me, (long) atoi (&(*av)[2]));
else if (!strcmp (*av, "-i"))
now = 1;
}
if (hw < lw) /* hw time must not be shorter than lw time */
lw = hw;
tsig = TIMESIG;
csig = CMDSIG;
while (1) {
if (now) {
now = 0;
goto dosomething;
}
timereq -> tr_time.tv_secs = rnd (hw-lw+1) + lw;
timereq -> tr_time.tv_micro = 0;
SendIO (timereq);
signals = Wait (tsig | csig);
if (signals & csig) {
/* Command from another task (user) */
msg = GetMsg (cmdport);
AbortIO (timereq);
WaitIO (timereq);
/*
* The I/O reply causes a signal to be
* raised, which screws things up. So
* we clear it.
*/
Wait (tsig);
if (msg -> actions & SUICIDE) {
ReplyMsg (msg);
break;
}
if (msg -> actions & SETHIGH)
hw = msg -> highwater;
if (msg -> actions & SETLOW)
lw = msg -> lowater;
if (hw < lw)
lw = hw;
if (msg -> actions & SETPRI)
SetTaskPri (me, (long) msg -> newpri);
if (msg -> actions & DOSOMETHING)
now = 1;
ReplyMsg (msg);
}
if (signals & tsig) {
/* Timer went off, time to do something weird */
WaitIO (timereq);
dosomething:
switch (rnd (5)) {
case 0: case 1:
dohulk ();
break;
case 2: case 3:
dogrunt ();
break;
case 4:
enforce ();
}
}
}
}
reconfigure (ac, av, daemonport)
char **av;
void *daemonport;
{
/*
* cmdport in this context means the reply port for commands to
* the daemon.
*/
if (ac < 2) /* Nothing to do */
return;
/* In order to use die(), we have to open Intuition. */
if (!(IntuitionBase = OpenLibrary ("intuition.library", 0L))) {
Alert (AG_OpenLib | AO_Intuition, 0L);
closestuff ();
exit (20);
}
GetPrefs (&prefs, (long) sizeof (prefs));
if (!(cmdport = CreatePort (NULL, NULL)))
die ("Can't create command reply port.");
if (!(ctl = CreateExtIO (cmdport, (long) sizeof (*ctl))))
die ("Can't create command block.");
/* Parse command line args */
while (++av, --ac) {
if (!strncmp (*av, "-h", 2)) {
ctl -> highwater = atoi (&(*av)[2]);
if (ctl -> highwater <= 0)
ctl -> highwater = DEFAULTHIGHWATER;
ctl -> actions |= SETHIGH;
} else if (!strncmp (*av, "-l", 2)) {
ctl -> lowater = atoi (&(*av)[2]);
if (ctl -> lowater <= 0)
ctl -> lowater = DEFAULTLOWATER;
ctl -> actions |= SETLOW;
} else if (!strncmp (*av, "-p", 2)) {
ctl -> newpri = atoi (&(*av)[2]);
ctl -> actions |= SETPRI;
} else if (!strcmp (*av, "-i"))
ctl -> actions |= DOSOMETHING;
else if (!strcmp (*av, "-kill"))
ctl -> actions |= SUICIDE;
}
/* Send command to daemon */
PutMsg (daemonport, ctl);
WaitPort (cmdport);
GetMsg (cmdport);
}
openstuff ()
{
if (!(IntuitionBase = OpenLibrary ("intuition.library", 0L))) {
Alert (AG_OpenLib | AO_Intuition, 0L);
closestuff ();
exit (20);
}
GetPrefs (&prefs, (long) sizeof (prefs));
if (!(GfxBase = OpenLibrary ("graphics.library", 0L)))
die ("Art shop closed.");
/* Set up a few environment things based on screen info */
if (!(win = OpenWindow (&windef)))
die ("Window painted shut.");
vp = ViewPortAddress (win);
wbs = win -> WScreen;
CloseWindow (win); win = 0;
high = wbs -> Height;
wide = wbs -> Width;
if (wbs -> ViewPort.Modes & HIRES)
wide /= 2;
if (wbs -> ViewPort.Modes & LACE)
high /= 2;
if ((sprnum = GetSprite (&spr, 2L)) < 0)
die ("Couldn't get sprite.");
if (!(cmdport = CreatePort (PORTNAME)))
die ("Can't create command port.");
if (!(timeport = CreatePort (NULL, NULL)))
die ("Can'r create time port.");
if (!(timereq = CreateExtIO (timeport, (long) sizeof (*timereq))))
die ("Can't make timer I/O.");
if (OpenDevice (TIMERNAME, UNIT_VBLANK, timereq, 0L)) {
timereq -> tr_node.io_Device = 0;
die ("Can't open timer device.");
}
timereq -> tr_node.io_Command = TR_ADDREQUEST;
if (!(ioport = CreatePort (NULL, NULL)))
die ("Can't create I/O port.");
if (!(ioreq = CreateStdIO (ioport)))
die ("Can't make I/O request.");
if (OpenDevice ("input.device", 0L, ioreq, 0L)) {
ioreq -> io_Device = 0;
die ("Can't generate input.");
}
ioreq -> io_Command = IND_WRITEEVENT;
ioreq -> io_Flags = 0;
ioreq -> io_Length = sizeof (struct InputEvent);
ioreq -> io_Data = (APTR) &mouse;
}
closestuff ()
{
if (ioreq) {
if (ioreq -> io_Device)
CloseDevice (ioreq);
DeleteStdIO (ioreq);
}
if (timereq) {
if (timereq -> tr_node.io_Device)
CloseDevice (timereq);
DeleteExtIO (timereq, (long) sizeof (*timereq));
}
if (ctl) DeleteExtIO (ctl, (long) sizeof (*ctl));
if (cmdport) DeletePort (cmdport);
if (ioport) DeletePort (ioport);
if (timeport) DeletePort (timeport);
if (sprnum >= 0) FreeSprite (sprnum);
if (win) CloseWindow (win);
if (GfxBase) CloseLibrary (GfxBase);
if (IntuitionBase) CloseLibrary (IntuitionBase);
}
die (str)
char *str;
{
postmessage (str);
closestuff ();
exit (10);
}
postmessage (str)
char *str;
{
if (win) CloseWindow (win); /* Should never happen */
windef.TopEdge = 0;
windef.Height = 10;
windef.Width = 8 + strlen (str) *
(prefs.FontHeight == TOPAZ_SIXTY ? 10 : 8);
windef.LeftEdge = (640 - windef.Width) / 2;
windef.DetailPen = 1;
windef.BlockPen = 3;
windef.Flags |= ACTIVATE;
windef.Title = (UBYTE *) str;
if (!(win = OpenWindow (&windef)))
/* Crash system and let user worry about it */
Alert (AN_OpenWindow, 0L);
Delay (200L);
CloseWindow (win); win = 0;
}