home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff269.lzh
/
RadBoogie
/
radboogie.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-06
|
50KB
|
2,069 lines
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/sprite.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <hardware/cia.h>
#include <hardware/intbits.h>
#include <devices/audio.h>
#include <functions.h>
#include "stdio.h"
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct DiskfontBase *DiskfontBase ;
extern struct DosLibrary *DOSBase;
struct Screen *myscreen ;
struct Window *mywindow ;
struct ViewPort *vp;
struct UCopList *ucop;
struct Task *task, *rtask ;
int origpri ;
static struct TextFont *font ;
static struct TextAttr myfont = { (STRPTR) "topaz.font", 11, 0, 0 };
char tempbuf[100] ;
struct IntuiText itext = { 1, 0, JAM2, 0, 0, &myfont, (UBYTE *)&tempbuf } ;
#define MAXLINES (50)
#define MAXPOINTS (10)
int maxpoints ;
/*
* The external variables we access.
*/
struct RastPort *rastport ;
short screenheight, screenwidth, bytewidth ;
short bytewidthm[700] ;
short color1[700], color2[700] ;
/*
* Some locals to this file.
*/
static struct BitMap mybitmap ;
static struct NewScreen newscreen = {
0, 0, 640, 400, 2, 0, 1, HIRES | LACE | SCREENQUIET | SPRITES,
CUSTOMSCREEN | CUSTOMBITMAP, 0, 0, 0, &mybitmap } ;
static struct NewWindow newwindow = {
0, 0, 32, 10, 0, 1, CLOSEWINDOW | VANILLAKEY,
WINDOWCLOSE | SIMPLE_REFRESH | NOCAREREFRESH | ACTIVATE, 0, 0, 0, 0, 0, 0,
0, 0, 0, CUSTOMSCREEN } ;
#define BSTRtoS(a) ((char *)(((long)(a))<<2))
long globalreplysignum ;
long rassize ;
long nilh ;
cleanup() {
struct Process *p ;
downsprites() ;
freechannels() ;
if (font != NULL)
CloseFont(font) ;
if (rtask) {
Signal(rtask, 1L << SIGBREAKB_CTRL_C) ;
SetTaskPri(rtask, 11L) ;
Wait(1L << globalreplysignum) ;
RemTask(rtask);
FreeMem(rtask, (long)sizeof(struct Task)) ;
rtask = NULL ;
}
if (globalreplysignum != -1)
FreeSignal(globalreplysignum) ;
if (vp) {
FreeVPortCopLists(vp) ;
RemakeDisplay() ;
}
if (mywindow)
CloseWindow(mywindow) ;
if (myscreen)
CloseScreen(myscreen) ;
if (mybitmap.Planes[0])
FreeMem(mybitmap.Planes[0], rassize) ;
if (mybitmap.Planes[1])
FreeMem(mybitmap.Planes[1], rassize + 2 * bytewidth) ;
if (DiskfontBase)
CloseLibrary(DiskfontBase) ;
if (IntuitionBase)
CloseLibrary(IntuitionBase) ;
if (GfxBase)
CloseLibrary(GfxBase) ;
RestoreFilter() ;
if (task)
SetTaskPri(task, (long)origpri) ;
/*
* We also kill any CLI processes that are running a program that
* starts with our play command.
*/
p = (struct Process *)FindTask("player.task") ;
if (p)
Signal(p, 1L << SIGBREAKB_CTRL_C) ;
if (nilh)
Close(nilh) ;
exit(0) ;
}
error(s)
register char *s ;
{
Write(Output(), s, (long)strlen(s)) ;
Write(Output(), "\n", 1L) ;
Delay(10L) ;
if (*s == '!')
cleanup() ;
}
/*
* Whenever we need a guaranteed clear row, we use this.
*/
short *emptyrow ;
/*
* This routine opens a screen and fires off the task if apropriate.
*/
blankscreen() {
register short *p, *q ;
register long t, tt ;
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0L) ;
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L) ;
if (IntuitionBase == NULL || GfxBase == NULL)
error("! no library") ;
if ((t = (long)OpenLibrary("mathtrans.library", 0L))==0)
error("! no mathtrans.library") ;
CloseLibrary(t) ;
screenheight = 2 * GfxBase->NormalDisplayRows ;
screenwidth = GfxBase->NormalDisplayColumns ;
newscreen.Height = screenheight ;
newscreen.Width = screenwidth ;
bytewidth = ((screenwidth + 15) >> 3) & ~1 ;
rassize = screenheight * (long)bytewidth ;
for (t=0; t<screenheight; t++)
bytewidthm[t] = t * bytewidth ;
/*
* We want to make sure we can manipulate the bitmap pointer for the second
* bitplane simply by changing the lower 16-bits. So we allocate a ton of
* memory, grab the right part, and then free the stuff above and below.
*/
tt = (rassize + 2 * bytewidth + 7) & ~7 ;
p = AllocMem(65536L + tt, MEMF_CHIP | MEMF_CLEAR) ;
if (p==NULL)
error("! no memory") ;
q = (short *)((((long)p) + 65535L) & ~65535L) ;
t = ((long)q) - ((long)p) ;
if (t)
FreeMem(p, t) ;
t = 65536L - t ;
if (t)
FreeMem(((long)p) + tt + 65536L - t, t) ;
p = AllocMem(rassize, MEMF_CHIP | MEMF_CLEAR) ;
if (p==NULL) {
FreeMem(q, rassize + 2 * bytewidth) ;
error("! out of memory") ;
}
emptyrow = (short *)(((long)q) + rassize) ;
mybitmap.BytesPerRow = bytewidth ;
mybitmap.Rows = screenheight ;
mybitmap.Depth = 2 ;
mybitmap.Planes[0] = (PLANEPTR)p ;
mybitmap.Planes[1] = (PLANEPTR)q ;
if ((myscreen = OpenScreen(&newscreen)) == NULL)
error("! no screen\n") ;
if (screenheight > 700)
error("! we don't work on screens that large") ;
vp = &(myscreen->ViewPort) ;
SetRGB4(vp, 0L, 0L, 0L, 0L) ;
SetRGB4(vp, 1L, 0L, 0L, 0L) ;
SetRGB4(vp, 2L, 0L, 0L, 0L) ;
SetRGB4(vp, 3L, 0L, 0L, 0L) ;
newwindow.Height = screenheight ; /* to disable dragging */
newwindow.Width = screenwidth ;
newwindow.Screen = myscreen ;
if ((mywindow = OpenWindow(&newwindow)) == NULL)
error("! no window\n") ;
if ((globalreplysignum = AllocSignal(-1L)) == -1)
error("! no signal\n") ;
rastport = &(myscreen->RastPort) ;
SetRast(rastport, 0L) ;
InstallList() ;
font = (struct TextFont *)OpenFont(&myfont) ;
if (font == NULL || font->tf_YSize != 11) {
if (font) {
CloseFont(font) ;
font = NULL ;
}
DiskfontBase = (struct DiskfontBase *)OpenLibrary("diskfont.library", 0L) ;
if (DiskfontBase != NULL)
font = (struct TextFont *)OpenDiskFont(&myfont) ;
}
if (font != NULL)
SetFont(rastport, font) ;
else
error("! I need topaz 11 to run") ;
SetPointer(mywindow, emptyrow+bytewidth/2, 0L, 0L, 0L, 0L) ;
}
/*
* This routine returns a random value from 0 to n-1.
*/
static long seed = 304019 ;
int randm(i)
int i ;
{
register long rseed ;
register unsigned int rval ;
rseed = seed ;
rseed = rseed * 23213 + 121 ;
rval = (rseed >> 5) & 65535 ;
seed = rseed ;
return ((i * (long)rval) >> 16) ;
}
/*
* This routine sets x and y values to a random number.
*/
static long x, y ;
randomxy() {
x = randm(screenwidth) ;
y = randm(screenheight) ;
}
/*
* Main routines are always fun.
*/
struct box {
short x[MAXPOINTS], y[MAXPOINTS] ;
} store[MAXLINES] ;
#define FIX(x) (((long)(x)) << 7)
#define FIXH(x) (((long)((*(x)+(x)[1])>>1)) << 7)
#define UNFIX(x) ((x)>>7)
struct box *ptr ;
struct box *eptr ;
int numlines ;
int mdelta = -1 ;
int maxlines = MAXLINES/2 ;
short dx[MAXPOINTS], dy[MAXPOINTS] ;
short ox[MAXPOINTS], oy[MAXPOINTS] ;
short nx[MAXPOINTS], ny[MAXPOINTS] ;
short dr, dg, db ;
short or, og, ob ;
short nr, ng, nb ;
long oldx, oldy, oldwidth, oldptr ;
int oldcol ;
/*
* Draws a spline! Expects all arguments in registers.
*/
#asm
public _Draw
cseg
rspline
move.l a0,d0
sub.l d6,d0
move.l d0,d3
bpl save1
neg.l d0
save1
move.l a1,d1
sub.l d7,d1
move.l d1,d4
bpl save2
neg.l d1
save2
move.l d0,d2
cmp.l d0,d1
bmi save3
lsr.l #3,d2
bra save9
save3
lsr.l #3,d1
save9
add.l d1,d2
asr.l #3,d2
beq check2
asr.l #5,d3
asr.l #5,d4
move.l a2,d0
sub.l a0,d0
move.l a3,d1
sub.l a1,d1
asr.l #5,d0
asr.l #5,d1
muls.w d4,d0
muls.w d3,d1
sub.l d1,d0
bpl save4
neg.l d0
save4
cmp.l d0,d2
ble pushem
move.l a5,d0
sub.l a0,d0
move.l a6,d1
sub.l a1,d1
asr.l #5,d0
asr.l #5,d1
muls.w d4,d0
muls.w d3,d1
sub.l d1,d0
bpl save5
neg.l d0
save5
cmp.l d0,d2
ble pushem
makeline
lsr.l #7,d7
move.l d7,d1
lsr.l #7,d6
move.l d6,d0
movem.l d2-d5/a0-a1,-(sp)
move.l _oldx,d2
move.l _oldy,d3
move.l d0,_oldx
move.l d1,_oldy
move.l _oldwidth,d4
move.l _oldptr,a0
jsr mdraw
movem.l (sp)+,d2-d5/a0-a1
rts
check2
move.l a0,d0
sub.l a2,d0
bpl ch1
neg.l d0
ch1
move.l a1,d1
sub.l a3,d1
bpl ch2
neg.l d1
ch2
add.l d0,d1
asr.l #3,d1
bne pushem
move.l a0,d0
sub.l a5,d0
bpl ch3
neg.l d0
ch3
move.l a1,d1
sub.l a6,d1
bpl ch4
neg.l d1
ch4
add.l d0,d1
asr.l #3,d1
beq makeline
pushem
movem.l d6/d7,-(sp)
move.l a5,d0
add.l d6,d0
asr.l #1,d0
move.l a6,d1
add.l d7,d1
asr.l #1,d1
movem.l d0/d1,-(sp)
move.l a2,d2
add.l a5,d2
asr.l #1,d2
move.l a3,d3
add.l a6,d3
asr.l #1,d3
move.l d0,d4
add.l d2,d4
asr.l #1,d4
move.l d1,d5
add.l d3,d5
asr.l #1,d5
movem.l d4/d5,-(sp)
move.l a0,d6
add.l a2,d6
asr.l #1,d6
move.l a1,d7
add.l a3,d7
asr.l #1,d7
move.l d2,d0
add.l d6,d0
asr.l #1,d0
move.l d3,d1
add.l d7,d1
asr.l #1,d1
move.l d6,a2
move.l d7,a3
move.l d0,d6
add.l d4,d6
asr.l #1,d6
move.l d1,d7
add.l d5,d7
asr.l #1,d7
movem.l d6/d7,-(sp)
move.l d0,a5
move.l d1,a6
jsr rspline
movem.l (sp)+,a0/a1
movem.l (sp)+,a2/a3/a5/a6
movem.l (sp)+,d6/d7
bra rspline
;
include 'exec/types.i'
include 'hardware/custom.i'
include 'hardware/blit.i'
include 'hardware/dmabits.i'
;
xref _custom
;
;
; Our entry point.
;
mdraw:
move.l #$dff000,a1 ; Manx requires this
sub.w d0,d2 ; calculate dx
bmi xneg ; if negative, octant is one of [3,4,5,6]
sub.w d1,d3 ; calculate dy '' is one of [1,2,7,8]
bmi yneg ; if negative, octant is one of [7,8]
cmp.w d3,d2 ; cmp |dx|,|dy| '' is one of [1,2]
bmi ygtx ; if y>x, octant is 2
moveq.l #OCTANT1+LINEMODE,d5 ; otherwise octant is 1
bra lineagain ; go to the common section
ygtx:
exg d2,d3 ; X must be greater than Y
moveq.l #OCTANT2+LINEMODE,d5 ; we are in octant 2
bra lineagain ; and common again.
yneg:
neg.w d3 ; calculate abs(dy)
cmp.w d3,d2 ; cmp |dx|,|dy|, octant is [7,8]
bmi ynygtx ; if y>x, octant is 7
moveq.l #OCTANT8+LINEMODE,d5 ; otherwise octant is 8
bra lineagain
ynygtx:
exg d2,d3 ; X must be greater than Y
moveq.l #OCTANT7+LINEMODE,d5 ; we are in octant 7
bra lineagain
xneg:
neg.w d2 ; dx was negative! octant is [3,4,5,6]
sub.w d1,d3 ; we calculate dy
bmi xyneg ; if negative, octant is one of [5,6]
cmp.w d3,d2 ; otherwise it's one of [3,4]
bmi xnygtx ; if y>x, octant is 3
moveq.l #OCTANT4+LINEMODE,d5 ; otherwise it's 4
bra lineagain
xnygtx:
exg d2,d3 ; X must be greater than Y
moveq.l #OCTANT3+LINEMODE,d5 ; we are in octant 3
bra lineagain
waitmore:
nop
nop
btst #DMAB_BLTDONE-8,dmaconr(a1)
beq donewait
bra waitmore
xyneg:
neg.w d3 ; y was negative, in one of [5,6]
cmp.w d3,d2 ; is y>x?
bmi xynygtx ; if so, octant is 6
moveq.l #OCTANT5+LINEMODE,d5 ; otherwise, octant is 5
bra lineagain
xynygtx:
exg d2,d3 ; X must be greater than Y
moveq.l #OCTANT6+LINEMODE,d5 ; we are in octant 6
lineagain:
mulu.w d4,d1 ; Calculate y1 * width
ror.l #4,d0 ; move upper four bits into hi word
add.w d0,d0 ; multiply by 2
add.l d1,a0 ; ptr += (x1 >> 3)
add.w d0,a0 ; ptr += y1 * width
swap d0 ; get the four bits of x1
or.w _oldcol,d0 ; or with USEA, USEC, USED, F=A~C+~AC
lsl.w #2,d3 ; Y = 4 * Y
add.w d2,d2 ; X = 2 * X
move.w d2,d1 ; set up size word
lsl.w #5,d1 ; shift five left
add.w #$42,d1 ; and add 1 to height, 2 to width
btst #DMAB_BLTDONE-8,dmaconr(a1) ; safety check
waitblit:
btst #DMAB_BLTDONE-8,dmaconr(a1) ; wait for blitter
bne waitmore
donewait:
move.w d3,bltbmod(a1) ; B mod = 4 * Y
sub.w d2,d3
ext.l d3
move.l d3,bltapt(a1) ; A ptr = 4 * Y - 2 * X
bpl lineover ; if negative,
or.w #SIGNFLAG,d5 ; set sign bit in con1
lineover:
move.w d0,bltcon0(a1) ; write control registers
move.w d5,bltcon1(a1)
move.w d4,bltcmod(a1) ; C mod = bitplane width
move.w d4,bltdmod(a1) ; D mod = bitplane width
sub.w d2,d3
move.w d3,bltamod(a1) ; A mod = 4 * Y - 4 * X
move.w #$8000,bltadat(a1) ; A data = 0x8000
moveq.l #-1,d5 ; Set masks to all ones
move.l d5,bltafwm(a1) ; we can hit both masks at once
move.l a0,bltcpt(a1) ; Pointer to first pixel to set
move.l a0,bltdpt(a1)
move.w d1,bltsize(a1) ; Start blit
rts ; and return, blit still in progress.
#endasm
/*
* Now our linkage to the spline routine. Parameters are in 8(a5)...
*/
int drawspline(x1, y1, x2, y2, x3, y3, x4, y4)
long x1, y1, x2, y2, x3, y3, x4, y4 ;
{
#asm
movem.l saver,-(sp)
move.l 8(a5),a0
move.l 12(a5),a1
move.l 16(a5),a2
move.l 20(a5),a3
move.l 28(a5),a6
move.l 32(a5),d6
move.l 36(a5),d7
move.l 24(a5),a5
jsr rspline
movem.l (sp)+,saver
saver reg d0-d7/a0-a6
#endasm
}
int closed ;
char *nextlegal[] = { "01458", "236", "01458", "236", "01458", "23", "01458",
"", "0145" } ;
int advval[] = { 3, 2, 3, 2, 1, 0, 1, 0, 1 } ;
unsigned char realfunc[14] ;
char namefunc[20] ;
makefunc() {
register int i ;
register int goallen ;
register int sofar = 0 ;
register unsigned char *p ;
register char *nextpossib ;
closed = randm(3) ;
switch(closed) {
case 2:
goallen = 2 + randm(3) ;
break ;
case 1:
goallen = 3 + randm(6) ;
break ;
case 0:
goallen = 1 + randm(7) ;
break ;
}
while (1) {
if (closed == 0)
nextpossib = "0145" ;
else
nextpossib = "0123456" ;
sofar = 0 ;
p = realfunc ;
while (sofar < goallen) {
i = nextpossib[randm(strlen(nextpossib))] - '0' ;
*p++ = i ;
nextpossib = nextlegal[i] ;
sofar += advval[i] ;
}
if (sofar == goallen) {
if (closed == 0) {
if (nextpossib[0] == '0')
break ;
} else {
if (*nextpossib == '0' || realfunc[0] < 4 || *(p-1) < 4) {
if ((*nextpossib == '0') ?
((realfunc[0] & 2) != 0) : ((realfunc[0] & 2) == 0)) {
if (realfunc[0] != 5) {
realfunc[0] ^= 2 ;
break ;
}
} else {
break ;
}
}
}
}
}
*p = 100 ;
maxpoints = goallen ;
switch (closed) {
case 2:
for (i=0; i<p-realfunc; i++)
p[i] = realfunc[i] ;
p[p-realfunc] = 100 ;
break ;
case 1:
break ;
case 0:
maxpoints++ ;
break ;
}
for (i=0, p=realfunc; *p < 100; p++, i++)
namefunc[i] = *p + '0' ;
namefunc[i++] = ' ' ;
namefunc[i++] = '0' + closed ;
namefunc[i++] = ' ' ;
namefunc[i++] = '0' + maxpoints ;
namefunc[i] = 0 ;
}
#define HALF(a) ((*(a)+(a)[1])>>1)
draw_s_f(xptr, yptr)
register short *xptr, *yptr ;
{
oldx = HALF(xptr) ;
oldy = HALF(yptr) ;
OwnBlitter() ;
drawspline(FIX(oldx), FIX(oldy), FIX(xptr[1]), FIX(yptr[1]),
FIX(xptr[2]), FIX(yptr[2]), FIXH(xptr+2), FIXH(yptr+2)) ;
DisownBlitter() ;
}
draw_sf(xptr, yptr)
register short *xptr, *yptr ;
{
oldx = HALF(xptr) ;
oldy = HALF(yptr) ;
OwnBlitter() ;
drawspline(FIX(oldx), FIX(oldy), FIX(xptr[1]), FIX(yptr[1]),
FIX(xptr[2]), FIX(yptr[2]), FIX(xptr[3]), FIX(yptr[3])) ;
DisownBlitter() ;
}
draws_f(xptr, yptr)
register short *xptr, *yptr ;
{
oldx = *xptr ;
oldy = *yptr ;
OwnBlitter() ;
drawspline(FIX(*xptr), FIX(*yptr), FIX(xptr[1]), FIX(yptr[1]),
FIX(xptr[2]), FIX(yptr[2]), FIXH(xptr+2), FIXH(yptr+2)) ;
DisownBlitter() ;
}
drawsf(xptr, yptr)
register short *xptr, *yptr ;
{
oldx = *xptr ;
oldy = *yptr ;
OwnBlitter() ;
drawspline(FIX(*xptr), FIX(*yptr), FIX(xptr[1]), FIX(yptr[1]),
FIX(xptr[2]), FIX(yptr[2]), FIX(xptr[3]), FIX(yptr[3])) ;
DisownBlitter() ;
}
draw_lf(xptr, yptr)
register short *xptr, *yptr ;
{
Move(rastport, (long)HALF(xptr), (long)HALF(yptr)) ;
xptr++ ;
yptr++ ;
Draw(rastport, (long)*xptr, (long)*yptr) ;
}
drawl_f(xptr, yptr)
register short *xptr, *yptr ;
{
Move(rastport, (long)*xptr, (long)*yptr) ;
Draw(rastport, (long)HALF(xptr), (long)HALF(yptr)) ;
}
drawlf(xptr, yptr)
register short *xptr, *yptr ;
{
Move(rastport, (long)*xptr, (long)*yptr) ;
xptr++ ;
yptr++ ;
Draw(rastport, (long)*xptr, (long)*yptr) ;
}
drawnlf() {}
int (*funcs[])() = { &drawsf, &draws_f, &draw_sf, &draw_s_f,
&drawlf, &drawl_f, &draw_lf, NULL, &drawnlf } ;
drawfunc(bptr)
register struct box *bptr ;
{
register long i ;
register short *x, *y ;
register unsigned char *p ;
oldwidth = rastport->BitMap->BytesPerRow ;
oldptr = (long)rastport->BitMap->Planes[0] ;
switch(closed) {
case 2:
for (i=0, x=&(bptr->x[0]), y=&(bptr->y[0]); i<maxpoints; i++, x++, y++) {
x[maxpoints] = screenwidth - 1 - *x ;
y[maxpoints] = screenheight - 1 - *y ;
}
setup:
x[maxpoints] = bptr->x[0] ;
y[maxpoints] = bptr->y[0] ;
x++, y++ ;
x[maxpoints] = bptr->x[1] ;
y[maxpoints] = bptr->y[1] ;
break ;
case 1:
x = &(bptr->x[0]) ;
y = &(bptr->y[0]) ;
goto setup ;
}
p = realfunc ;
x = &(bptr->x[0]) ;
y = &(bptr->y[0]) ;
while (*p < 20) {
(funcs[*p])(x, y) ;
i = advval[*p] ;
x += i ;
y += i ;
p++ ;
}
}
/*
* Initialize things for the first lines.
*/
startlines() {
register int i ;
ptr = store ;
eptr = store ;
numlines = 0 ;
if (dx[0] == 0) {
for (i=0; i<MAXPOINTS; i++) {
ox[i] = randm(screenwidth) ;
oy[i] = randm(screenheight) ;
dx[i] = 2 + randm(3) ;
dy[i] = 2 + randm(3) ;
}
}
nr = 53 ;
ng = 33 ;
nb = 35 ;
dr = -3 ;
dg = 5 ;
db = 7 ;
SetRGB4(vp, 0L, 0L, 0L, 0L) ;
SetRGB4(vp, 1L, (long)(nr >> 3), (long)(ng >> 3), (long)(nb >> 3)) ;
myscreen->RastPort.Mask = 1 ;
for (i=0; i<maxlines; i++) {
advancelines() ;
drawnew() ;
}
}
/*
* Advance the number by the delta, and check the boundaries.
*/
adv(o, d, n, w)
register short *o, *d, *n ;
short w ;
{
*n = *o + *d ;
if (*n < 0) {
*n = 0 ;
*d = randm(6) + 1 ;
} else if (*n >= w) {
*n = w - 1 ;
*d = - randm(6) - 1 ;
}
}
/*
* Advance the two points which make up the lines.
*/
advancelines() {
register int i ;
for (i=0; i<maxpoints; i++) {
adv(ox+i, dx+i, nx+i, screenwidth) ;
adv(oy+i, dy+i, ny+i, screenheight) ;
}
}
/*
* Draw a new set of lines.
*/
drawnew() {
register int i ;
register short oldpen ;
register struct box *bptr ;
while (numlines >= maxlines) {
oldpen = rastport->FgPen ;
oldcol = 0xb0a ;
SetAPen(rastport, 0L) ;
bptr = eptr ;
drawfunc(bptr) ;
oldcol = 0xbfa ;
SetAPen(rastport, (long)oldpen) ;
numlines-- ;
bptr++ ;
if (bptr == store + MAXLINES)
bptr = store ;
eptr = bptr ;
}
bptr = ptr ;
for (i=0; i<maxpoints; i++) {
bptr->x[i] = ox[i] = nx[i] ;
bptr->y[i] = oy[i] = ny[i] ;
}
drawfunc(bptr) ;
numlines++ ;
bptr++ ;
if (bptr == store + MAXLINES) {
bptr = store ;
if (mdelta == 1) {
maxlines++ ;
if (maxlines >= MAXLINES - 1)
mdelta = -1 ;
} else {
maxlines-- ;
if (maxlines <= 2)
mdelta = 1 ;
}
}
ptr = bptr ;
}
/*
* This routine mucks with the colors.
*/
colors() {
or = nr ;
og = ng ;
ob = nb ;
adv(&or, &dr, &nr, 128) ;
adv(&og, &dg, &ng, 128) ;
adv(&ob, &db, &nb, 128) ;
SetRGB4(vp, 1L, (long)(nr >> 3), (long)(ng >> 3), (long)(nb >> 3)) ;
}
long time = 0 ;
settime() {
time = 0 ;
}
long gettime() {
return time ;
}
/*
* Our actual task, in an infinite loop.
*/
void taskrout() {
register struct Task *mtask ;
geta4() ;
settime() ;
makefunc() ;
mtask = FindTask(0L) ;
startlines() ;
colors() ;
while (SetSignal(0L, 0L)==0) {
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
colors() ;
if (gettime() >= 1000) {
settime() ;
makefunc() ;
SetRast(rastport, 0L) ;
startlines() ;
}
}
done:
Signal(task, 1L << globalreplysignum) ;
Wait(0L) ;
}
/*
* Our `delay' call that checks for an abort.
*/
MDelay(n)
register long n ;
{
while (n > 0) {
checktof() ;
n-- ;
}
}
extern int Enable_Abort ;
#define STACKSIZE 1000
long stackmem[STACKSIZE] ;
int (*nextf)(), nextcolor() ;
long flags ;
#define checkflag(c) (flags&(1L<<((c)-'a')))
int onsprites = 32767 ;
main(argc, argv)
int argc ;
char *argv[] ;
{
register char *p ;
Enable_Abort = 0 ;
while (argc > 1) {
argc-- ;
argv++ ;
for (p=argv[0]; *p; p++)
if ('a' <= *p && *p <= 'z')
flags |= (1L << (*p - 'a')) ;
else if ('A' <= *p && *p <= 'Z')
flags |= (1L << (*p - 'A')) ;
}
if (checkflag('s'))
flags |= (1L << ('g'-'a')) | (1L << ('m'-'a')) ;
blankscreen() ;
nilh = (long)Open("nil:", MODE_NEWFILE) ;
loadfont() ;
readiff("cracked.iff", 0) ;
task = FindTask(0L) ;
origpri = task->tc_Node.ln_Pri ;
if (!checkflag('g'))
loadsound() ;
else
flashscreen() ;
if (!checkflag('m'))
Execute("Play * P=Script <nil: >nil:", nilh, nilh) ;
SetTaskPri(task, (long)(task->tc_Node.ln_Pri+6)) ;
if (!checkflag('c'))
rollcredits() ;
SetTaskPri(task, (long)(task->tc_Node.ln_Pri-5)) ;
if (!checkflag('b'))
upsprites() ;
SetRast(rastport, 0L) ;
readiff("radboogie.iff", 1) ; /* this needs to go faster */
onsprites = 420 ;
rtask = (struct Task *)AllocMem((long)sizeof(struct Task),
MEMF_CLEAR | MEMF_PUBLIC) ;
if (rtask != NULL) {
rtask->tc_Node.ln_Pri = task->tc_Node.ln_Pri - 2 ;
rtask->tc_Node.ln_Type = NT_TASK ;
rtask->tc_Node.ln_Name = "ri.Lines" ;
rtask->tc_SPLower = (APTR)stackmem ;
rtask->tc_SPUpper = rtask->tc_SPReg =
(APTR)(stackmem + STACKSIZE/4 - 8) ;
AddTask(rtask, taskrout, 0L) ;
}
nextf = &nextcolor ;
MDelay(250L) ;
while (1) {
checktof() ;
nextf() ;
time++ ;
}
done: ;
cleanup() ;
}
short *copinst[700] ;
/*
* Copper manipulations.
*/
grabcopper(cpr, ptr)
register struct cprlist *cpr ;
int ptr ;
{
register short *p ;
register int i ;
for (i=cpr->MaxCount, p=(short *)cpr->start; i; i--, p += 2)
if (*p == 0xe6)
break ;
if (i <= 0)
error("! couldn't get copper") ;
i-- ;
p += 2 ;
while (ptr < screenheight) {
for (; i > 0; i--, p += 2)
if (*p == 0x182)
break ;
if (i <= 0) {
printf("Failed for pointer %d\n", ptr) ;
error("! couldn't get copper 2") ;
}
*p = 0xe6 ;
copinst[ptr] = p + 1 ;
i -= 2 ;
p += 4 ;
ptr += 2 ;
}
}
struct View *safeview ;
InstallList() {
int i ;
ucop=AllocMem((long)sizeof(struct UCopList), MEMF_CHIP|MEMF_CLEAR);
if (ucop == NULL)
error("! no copper") ;
for (i=0; i<screenheight; i += 2) {
CWAIT(ucop, (long)i, 0L) ;
CMOVE(ucop, custom.color[1], 0L) ;
CMOVE(ucop, custom.color[2], 0L) ;
}
CEND(ucop);
Forbid();
vp->UCopIns=ucop;
Permit();
RethinkDisplay();
/*
* Now we grab pointers to the instructions for each row.
* Note that this is guaranteed to break. Don't fuck with the
* screens while we are grabbing all of these pointers.
*/
safeview = GfxBase->ActiView ;
grabcopper(GfxBase->ActiView->LOFCprList, 0) ;
grabcopper(GfxBase->ActiView->SHFCprList, 1) ;
}
/*
* This routine checks to make sure we are still the displayed view. If
* we aren't, we bail out before munging a copper list we may not be
* allowed to touch. Note that this is *not* how to exit this demo.
* Note also that we should Forbid()/Permit() around our copper
* munging code, but we take our chances instead.
*/
checktof() {
struct IntuiMessage *msg ;
static int msgctr = 4 ;
msgctr-- ;
if (msgctr <= 0) {
if (msg=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
if (msg->Class == CLOSEWINDOW ||
(msg->Class == VANILLAKEY && (msg->Code == 3 ||
msg->Code == 27)))
cleanup() ;
ReplyMsg(msg) ;
}
msgctr = 4 ;
}
nextsprite() ;
WaitTOF() ;
if (GfxBase->ActiView != safeview ||
IntuitionBase->FirstScreen != myscreen ||
IntuitionBase->ActiveWindow != mywindow)
error("!*hey*! Don't do that! (I'm no longer in front.)") ;
}
long sine = 65536 ;
long cosine = 0 ;
long ocos = -10 ;
static long curcstart = 0 ;
static int ncrev = 5 ;
onextcolor()
{
register long acc, delta ;
register short **p ;
register short *q ;
register long t ;
register long i ;
t = sine + (cosine >> 5) ;
ocos = cosine ;
cosine -= (sine >> 5) ;
if ((t <= 0 && sine >= 0) ||
(t >= 0 && sine <= 0))
newcolor(&color1) ;
if (cosine <= 0 && ocos >= 0) {
ncrev-- ;
if (ncrev == 0) {
nextf = &nextcolor ;
ncrev = 7 ;
nextcolor() ;
}
}
sine = t ;
/*
* Every time around, correct it back into a circle.
*/
if (-500 < sine && sine < 500) {
if (cosine < 0)
cosine = -65536 ;
else
cosine = 65536 ;
sine = 0 ;
delta = 0 ;
acc = -203034 ;
} else {
acc = ((((-(long)screenheight)<<21) + (sine << 4)) / sine
+ (screenheight << 5)) << 5 ;
delta = (268435456L + sine) / (sine << 1) ;
}
pokefast(copinst, screenheight, acc, delta, bytewidthm, color1) ;
/* for (i=screenheight, p=copinst; i; i--, p++) {
q = *p ;
acc += delta ;
t = (acc >> 11) ;
if (((unsigned long)t) >= screenheight) {
*q = ((long)emptyrow) ;
q[2] = 0 ;
} else {
*q = bytewidthm[t] ;
q[2] = color1[t] ;
}
} */
}
pokefast(cp, sh, acc, del, bw, c1)
short **cp ; /* 8 */ /* a3 */
short sh ; /* 12 */ /* d0 */ /* d4 */
long acc, del ; /* 14, 18 */ /* d1, d2 */
short *bw, *c1 ; /* 22, 26 */ /* a0, a5 */
{
#asm
movem.l sav37,-(sp)
move.l 8(a5),a3
move.w 12(a5),d0
move.w d0,d4
ext.l d4
lsr.w #1,d0
move.l 14(a5),d1
move.l 18(a5),d2
move.l 22(a5),a0
move.l 26(a5),a5
move.l #11,d5
move.w _emptyrow+2,d6
bra bot37
top37:
move.l (a3)+,a2
add.l d2,d1
move.l d1,d3
lsr.l d5,d3
cmp.l d3,d4
bcc.s ovr37
move.w d6,(a2)
; clr.w 4(a2)
move.l (a3)+,a2
add.l d2,d1
move.l d1,d3
lsr.l d5,d3
cmp.l d3,d4
bcs.s ovr37c
add.w d3,d3
move.w (a0,d3.w),(a2)
move.w (a5,d3.w),4(a2)
dbra d0,top37
bra don37
ovr37:
add.w d3,d3
move.w (a0,d3.w),(a2)
move.w (a5,d3.w),4(a2)
ovr37b:
move.l (a3)+,a2
add.l d2,d1
move.l d1,d3
lsr.l d5,d3
cmp.l d3,d4
bcs.s ovr37c
add.w d3,d3
move.w (a0,d3.w),(a2)
move.w (a5,d3.w),4(a2)
dbra d0,top37
bra don37
ovr37c:
move.w d6,(a2)
; clr.w 4(a2)
bot37:
dbra d0,top37
don37:
movem.l (sp)+,sav37
sav37 reg d0-d6/a0-a3/a5
#endasm
}
static int curhpos = -30 ;
nextcolor()
{
register short **p ;
register short *q ;
register long acc, div ;
register long i, reali ;
curhpos -= 4 ;
if (curhpos <= 0) {
if (curhpos < -10)
newcolor(&color2) ;
for (i=0; i<screenheight; i++)
color1[i] = color2[i] ;
newcolor(&color2) ;
curhpos = screenheight - 2 ;
ncrev-- ;
if (ncrev == 0) {
nextf = &onextcolor ;
ncrev = 5 ;
onextcolor() ;
}
}
acc = 0 ;
div = screenheight * 65536L / curhpos ;
poke2fast(copinst, curhpos, acc, div, bytewidthm, color1) ;
/* for (i=curhpos, p=copinst; i; i--, p++) {
q = *p ;
reali = acc >> 16 ;
*q = bytewidthm[reali] ;
q[2] = color1[reali] ;
acc += div ;
} */
div = screenheight * 65536L / (screenheight - curhpos) ;
acc = 0 ;
poke2fast(copinst + curhpos, screenheight - curhpos,
acc, div, bytewidthm, color2) ;
/* for (i=screenheight-curhpos; i; i--, p++) {
q = *p ;
reali = acc >> 16 ;
*q = bytewidthm[reali] ;
q[2] = color2[reali] ;
acc += div ;
} */
}
poke2fast(cp, sh, acc, del, bw, c1)
short **cp ; /* 8 */ /* a3 */
short sh ; /* 12 */ /* d0 */ /* d4 */
long acc, del ; /* 14, 18 */ /* d1, d2 */
short *bw, *c1 ; /* 22, 26 */ /* a0, a5 */
{
#asm
movem.l sav38,-(sp)
move.l 8(a5),a3
move.w 12(a5),d0
move.w d0,d4
lsr.w #1,d0
ext.l d4
move.l 14(a5),d1
move.l 18(a5),d2
move.l 22(a5),a0
move.l 26(a5),a5
bra bot38
top38:
move.l (a3)+,a2
add.l d2,d1
move.l d1,d3
swap d3
add.w d3,d3
move.w (a0,d3.w),(a2)
move.w (a5,d3.w),4(a2)
move.l (a3)+,a2
add.l d2,d1
move.l d1,d3
swap d3
add.w d3,d3
move.w (a0,d3.w),(a2)
move.w (a5,d3.w),4(a2)
bot38:
dbra d0,top38
movem.l (sp)+,sav38
sav38 reg d0-d4/a0-a3/a5
#endasm
}
/*
* This routine has to generate a new color. We grab two random vectors
* in color space and concatenate them and distribute them over the array.
*
* This code should be moderately fast; we assume that the random number
* generator generates fairly good numbers.
*/
int raininc[6] = { 1, -16, 256, -1, 16, -256 } ;
newcolor(p)
short *p ;
{
register int a ;
register int i ;
int inc ;
int s1, s2, s3 ;
switch(randm(8)) {
case 0: /* shaded stripes */
case 5:
case 6:
inc = randm(2) * 2 - 1 ;
a = randm(8192) ;
s1 = randm(3) * 4 + 1 ;
s2 = randm(2) * 4 + 1 ;
if (s1 == s2)
s2 = 9 ;
s3 = 15 - s1 - s2 ;
for (i=screenheight; i; i--, a += inc) {
*p++ = ((a >> s1) & 15) +
(((a >> s2) & 15) << 4) +
(((a >> s3) & 15) << 8) ;
}
break ;
case 1: /* solid color */
case 4:
while (1) {
a = randm(4096) ;
s1 = (a & 15) + ((a >> 4) & 15) + ((a >> 8) & 15) ;
if (a > 12)
break ;
}
for (i=screenheight; i; i--)
*p++ = a ;
break ;
case 2: /* banded with two colors */
case 3:
while (1) {
a = randm(4096) ;
s1 = (a & 15) + ((a >> 4) & 15) + ((a >> 8) & 15) ;
if (a > 12)
break ;
}
s2 = a ;
while (1) {
a = randm(4096) ;
s1 = (a & 15) + ((a >> 4) & 15) + ((a >> 8) & 15) ;
if (a > 12)
break ;
}
s3 = a ;
s1 = randm(40) + 10 ;
a = s1 ;
for (i=screenheight; i; i--) {
*p++ = s2 ;
a-- ;
if (a==0) {
a = s2 ;
s2 = s3 ;
s3 = a ;
a = s1 ;
}
}
break ;
case 7: /* rainbow */
a = 240 ;
s1 = 0 ;
s3 = 1 ;
s2 = 15 ;
for (i=screenheight; i; i--) {
*p++ = a ;
a += s3 ;
s2-- ;
if (s2 == 0) {
s2 = 15 ;
s1++ ;
if (s1 == 6)
s1 = 0 ;
s3 = raininc[s1] ;
}
}
break ;
}
}
/*
* Now the code that reads in an IFF file. We center the file on the
* screen.
*/
int compression ;
long amigaflags ;
char colormap[2048] ;
int numcolors, numplanes ;
int width, height, rowwidth ;
int masking ;
FILE *ifffile ;
struct bmhddata {
short w, h, x, y ;
unsigned char numplanes, masking, compression, dmy1 ;
short transcolor ;
unsigned char xas, yas ;
short ow, oh ;
} bmhd ;
static long getfour()
{
long t ;
*((char *)(&t)) = getc(ifffile) ;
*((char *)(&t)+1) = getc(ifffile) ;
*((char *)(&t)+2) = getc(ifffile) ;
*((char *)(&t)+3) = getc(ifffile) ;
return(t) ;
}
static long getfourup()
{
return((getfour() + 1) & ~1L) ;
}
/*
* Starts up an iff file. Returns `1' on success; 0 on error.
*/
static short startiff()
{
register unsigned char *d ;
register short i ;
register long thislen, ifflen, curform ;
short min, max ;
if (getfour() != 'FORM')
return(-1) ;
ifflen = getfour() ;
if (getfour() != 'ILBM')
return(-1) ;
while (1) {
curform = getfour() ;
switch(curform) {
case 'CMAP' :
thislen = getfourup() ;
if (thislen > 2048)
return(-1) ;
numcolors = thislen / 3 ;
d = (unsigned char *)colormap ;
while (thislen > 0) {
*d++ = getc(ifffile) ;
thislen-- ;
}
break ;
case 'CAMG' :
if (getfour() != 4)
return(-1) ;
amigaflags = getfour() & (HAM | EXTRA_HALFBRITE) ;
break ;
case 'BMHD' :
thislen = getfourup() ;
d = (unsigned char *)&bmhd ;
i = sizeof(struct bmhddata) ;
thislen -= i ;
while (i > 0) {
*d++ = getc(ifffile) ;
i-- ;
}
while (thislen > 0) {
getc(ifffile) ;
thislen-- ;
}
width = bmhd.w ;
rowwidth = (bmhd.w + 15) / 16 ;
height = bmhd.h ;
compression = bmhd.compression ;
numplanes = bmhd.numplanes ;
if (numplanes < 1 || numplanes > 1)
error("! can only handle one-bitplane images") ;
masking = bmhd.masking ;
break ;
case 'BODY' :
getfour() ;
return(0) ;
case -1:
return(-1) ;
default:
thislen = getfourup() ;
thislen = (thislen + 1) & ~1 ;
while (thislen--)
getc(ifffile) ;
break ;
}
}
return(-1) ;
}
/*
* Here we get one row from the IFF file.
*/
static getrow(put)
register short *put ;
{
register char *rr ;
register short lackbits ;
register short i ;
register short data ;
if (compression)
lackbits = 0 ;
else
lackbits = 32767 ;
for (i = 2*rowwidth, rr = (char *)put; i; i--) {
while (lackbits == 0) {
lackbits = (getc(ifffile) & 255) ;
if (lackbits > 128) {
lackbits = lackbits - 257 ;
data = getc(ifffile) ;
} else if (lackbits == 128) {
lackbits = 0 ;
} else
lackbits++ ;
}
if (lackbits > 0) {
data = getc(ifffile) ;
lackbits-- ;
} else {
lackbits++ ;
}
*rr++ = data ;
}
}
short *bodys[6] ;
readbody(p)
register short *p ;
{
register int i, j ;
int delta = bytewidth >> 1 ;
if (width > screenwidth || height > screenheight) {
printf("%d %d %d %d\n", width, screenwidth, height, screenheight) ;
error("! IFF file too large for screensize") ;
}
p += ((screenheight - height) >> 1) * delta +
((screenwidth - width + 16) >> 5) ;
for (j=0; j<height; j++) {
getrow(p) ;
p += delta ;
}
}
readiff(s, n)
char *s ;
int n ;
{
int i ;
ifffile = fopen(s, "r") ;
if (ifffile==NULL)
error("! couldn't open IFF file\n") ;
if (startiff())
error("! Couldn't start up IFF file\n") ;
i = rastport->Mask ;
rastport->Mask = 1 << n ;
SetRast(rastport, 0L) ;
rastport->Mask = i ;
readbody(rastport->BitMap->Planes[n]) ;
fclose(ifffile) ;
ifffile = NULL ;
}
/*
* This code loads our font.
*/
#define HEIGHT (11)
long expand[256] ;
long *final ;
long fontdat[96*HEIGHT*3] ;
saytext() {
PrintIText(&(myscreen->RastPort), &itext, 0L, 0L) ;
WaitBlit() ;
}
loadfont() {
register int i, b ;
register long e ;
register unsigned char *p ;
int base ;
int c ;
for (i=0; i<256; i++)
for (b=1, e=7; b<256; b <<= 1, e <<= 3)
if (i & b)
expand[i] |= e ;
final = fontdat ;
for (base=32; base < 128; base += 16) {
p = (unsigned char *)tempbuf ;
for (c=base; c < base+16; c++, p++)
*p = c ;
*p = 0 ;
saytext() ;
p = (unsigned char *)(rastport->BitMap->Planes[0]) ;
for (c=base; c < base+16; c++, p++) {
for (i=0; i<HEIGHT; i++) {
e = expand[p[i*bytewidth]] ;
final[3*i+1] = e ;
final[3*i+2] = ~((e ^ (e >> 1)) | (e ^ (e << 1))) ;
}
final[0] = final[1] ^ (final[1] & ~final[2]) ;
for (i=1; i<(HEIGHT-1)*3; i += 3) {
e = final[i] ^ final[i+3] ;
final[i+2] = final[i+3] ^ (e & final[i+1] & ~final[i+4]) ;
final[i+1] = final[i] ^ (e & final[i+4] & ~final[i+1]) ;
}
final[HEIGHT*3-1] = final[HEIGHT*3-2] ^
(final[HEIGHT*3-2] & ~final[HEIGHT*3-1]) ;
for (i=0; i<HEIGHT*3; i++)
final[i] <<= 4 ;
final += HEIGHT * 3 ;
}
}
SetAPen(rastport, 0L) ;
RectFill(rastport, 0L, 0L, (long)screenwidth-1, 30L) ;
SetAPen(rastport, 1L) ;
}
/*
* Kludged code to load a sound.
*/
short *sounddata ;
long samrate, len ;
loadsound() {
register long h, *p ;
allocchannels() ;
ifffile = fopen("crash.snd", "r") ;
if (ifffile==0)
error("! don't separate me from my sounds (crash.snd).") ;
while (1) {
h = getfour() ;
switch (h) {
case 'BODY' :
getfour() ;
break ;
case 'VHDR' :
getfour() ;
len = getfour() ;
getfour() ;
getfour() ;
samrate = getfour() >> 16 ;
break ;
case -1:
error("! ran off end of sound file before body") ;
default:
break ;
}
if (h=='BODY')
break ;
}
if (len == 0)
error("! no length in sound file") ;
sounddata = AllocMem(len, MEMF_CHIP | MEMF_CLEAR) ;
if (sounddata == NULL)
error("! no memory in sound") ;
h = len ;
p = (long *)sounddata ;
while (h >= 0) {
*p++ = getfour() ;
h -= 4 ;
}
fclose(ifffile) ;
ifffile = NULL ;
playsound() ;
freechannels() ;
}
UBYTE whichannel[] = { 3, 5, 10, 12 } ;
struct IOAudio *AudioIOAptr, *AudioIOBptr ;
struct MsgPort *port ;
ULONG device = -1 ;
long clock ;
allocchannels() {
SetFilter() ;
clock = ((GfxBase->DisplayFlags & PAL) ? 3546895 : 3579545) ;
AudioIOBptr = (struct IOAudio *)AllocMem((long)sizeof(struct IOAudio),
MEMF_PUBLIC | MEMF_CLEAR) ;
AudioIOAptr = (struct IOAudio *)AllocMem((long)sizeof(struct IOAudio),
MEMF_PUBLIC | MEMF_CLEAR) ;
port = CreatePort(0L, 0L) ;
if (AudioIOBptr == NULL || AudioIOBptr == NULL || port == NULL)
error("! no memory") ;
AudioIOBptr->ioa_Request.io_Message.mn_ReplyPort = port ;
AudioIOBptr->ioa_Request.io_Message.mn_Node.ln_Pri = 0 ;
AudioIOBptr->ioa_Request.io_Command = ADCMD_ALLOCATE ;
AudioIOBptr->ioa_Request.io_Flags = ADIOF_NOWAIT ;
AudioIOBptr->ioa_AllocKey = 0 ;
AudioIOBptr->ioa_Data = whichannel ;
AudioIOBptr->ioa_Length = 4 ;
device = (ULONG)OpenDevice("audio.device", 0L, AudioIOBptr, 0L) ;
if (device != 0) {
printf("Error returned is %ld\n", device) ;
error("! no audio device") ;
}
}
/*
* We kill the filter; we *need* the high frequencies.
*/
freechannels() {
if (port) {
DeletePort(port) ;
port = 0 ;
}
if (device == 0) {
CloseDevice(AudioIOBptr) ;
device = -1 ;
}
if (AudioIOBptr) {
FreeMem(AudioIOBptr, (long)sizeof(struct IOAudio)) ;
AudioIOBptr = 0 ;
}
if (AudioIOAptr) {
FreeMem(AudioIOAptr, (long)sizeof(struct IOAudio)) ;
AudioIOAptr = 0 ;
}
if (sounddata) {
FreeMem(sounddata, len) ;
sounddata = 0 ;
}
RestoreFilter() ;
}
int oldbits = -1 ;
SetFilter() {
Disable() ;
oldbits = ciaa.ciapra ;
ciaa.ciapra |= CIAF_LED ;
Enable() ;
}
RestoreFilter() {
Disable() ;
if (!(oldbits & CIAF_LED)) {
ciaa.ciapra &= ~CIAF_LED ;
oldbits = -1 ;
}
Enable() ;
}
playsound() {
AudioIOBptr->ioa_Request.io_Message.mn_ReplyPort = port ;
AudioIOBptr->ioa_Request.io_Command = CMD_WRITE ;
AudioIOBptr->ioa_Request.io_Flags = ADIOF_PERVOL ;
AudioIOBptr->ioa_Data = (UBYTE *)sounddata ;
AudioIOBptr->ioa_Length = len ;
AudioIOBptr->ioa_Period = clock / samrate ;
AudioIOBptr->ioa_Volume = 64 ;
AudioIOBptr->ioa_Cycles = 1 ;
*AudioIOAptr = *AudioIOBptr ;
AudioIOBptr->ioa_Period += 5 ; /* make a slight modification for kicks */
AudioIOAptr->ioa_Request.io_Unit = (struct Unit *)
(((long)AudioIOBptr->ioa_Request.io_Unit) & 0x9) ;
AudioIOBptr->ioa_Request.io_Unit = (struct Unit *)
(((long)AudioIOBptr->ioa_Request.io_Unit) & 0x6) ;
BeginIO(AudioIOBptr) ;
BeginIO(AudioIOAptr) ;
flashscreen() ;
WaitPort(port) ;
GetMsg(port) ;
WaitPort(port) ;
GetMsg(port) ;
AudioIOBptr->ioa_Request.io_Unit = (struct Unit *)
(((long)AudioIOBptr->ioa_Request.io_Unit) |
((long)AudioIOBptr->ioa_Request.io_Unit)) ;
}
/*
* This routine flashes our screen bright white for a short time (two
* frames) and then turns the colors on right for normal stuff.
*/
flashscreen() {
long i ;
WaitTOF() ;
for (i=0; i<4; i++)
SetRGB4(vp, i, 15L, 15L, 15L) ;
WaitTOF() ;
WaitTOF() ;
for (i=0; i<4; i++)
SetRGB4(vp, i, 15L, 15L, 0L) ;
WaitTOF() ;
WaitTOF() ;
for (i=0; i<4; i++)
SetRGB4(vp, i, 15L, 0L, 0L) ;
WaitTOF() ;
WaitTOF() ;
SetRGB4(vp, 0L, 0L, 0L, 0L) ;
SetRGB4(vp, 1L, 4L, 4L, 4L) ;
SetRGB4(vp, 2L, 0L, 0L, 0L) ;
SetRGB4(vp, 3L, 0L, 0L, 0L) ;
}
/*
* Finally we get to use that text. We roll the credits here, at
* the beginning, while everything is loading. Too bad we can't make
* the music stop and wait for us! We try and make things take long
* enough to load all of the music off floppy disks.
*
* Of course, we do all of this with copper tricks.
*
* We do a lot of `bouncing'---assume everything is perfectly elastic
* and just let them bounce onto the screen.
*/
struct billiard {
int pos ;
int vel ;
int ptr ;
int color ;
} balls[12] ;
#define space 36
#define realh 33
#define velocity (randm(3)+2)
int scrolloff = 0 ;
rollcredits() {
register struct billiard *bbp ;
register struct billiard *bp = balls ;
register int i, j ;
long *p, *q ;
short **rp, *rq ;
int curiptr = 0 ;
FILE *f ;
char *pp ;
int alive = 0 ;
char *done ;
extern char *fgets() ;
for (i=0, rp=copinst; i<screenheight; i++, rp++)
*(*rp) = (long)emptyrow ;
f = fopen("TextScript", "r") ;
if (f==NULL)
error("! don't leave me without a text script (TextScript)") ;
while (1) {
done = fgets(tempbuf, 100, f) ;
if (strlen(tempbuf) > 0)
tempbuf[strlen(tempbuf)-1] = 0 ;
if (tempbuf[0]) {
bp->pos = screenheight ;
bp->vel = -velocity ;
bp->ptr = curiptr ;
bp->color = randm(4096) | 2184 ;
bp++ ;
alive = 1 ;
p = (long *)(((char *)(rastport->BitMap->Planes[1])) +
bytewidth * curiptr +
(((screenwidth - 32 * strlen(tempbuf) + 16) >> 4) & ~1)) ;
for (pp = tempbuf; *pp; pp++) {
q = fontdat + (*pp-32)*HEIGHT*3 ;
for (j=0; j<realh; j++)
*(long *)(((char *)p) + j * bytewidth) = q[j] ;
p++ ;
}
curiptr += realh ;
if (curiptr > screenheight)
error("! too many lines") ;
} else
scrolloff = 1 ;
while (1) {
for (i=25+randm(25); i; i--) {
for (bbp=balls; bbp < bp; bbp++)
bbp->pos += bbp->vel ;
if (scrolloff < 5 && balls[0].pos < 0) {
balls[0].pos = 0 ;
balls[0].vel = - balls[0].vel ;
}
for (bbp=balls; bbp+1 < bp; bbp++) {
if (bbp->pos + space > bbp[1].pos) {
j = bbp->vel ;
bbp->vel = bbp[1].vel ;
bbp[1].vel = j ;
bbp[1].pos = bbp->pos + space ;
}
}
if ((bp-1)->pos + space > screenheight && (bp-1)->vel > 0)
(bp-1)->vel = -(bp-1)->vel ;
checktof() ;
alive = fastcop(bp) ;
}
if (alive == 0)
break ;
if (scrolloff == 0)
break ;
scrolloff++ ;
}
if (!done)
break ;
if (alive == 0) {
bp = balls ;
curiptr = 0 ;
i = rastport->Mask ;
rastport->Mask = 2 ;
SetRast(rastport, 0L) ;
rastport->Mask = i ;
WaitBlit() ;
}
scrolloff = 0 ;
}
for (i=0, rp=copinst; i<screenheight; i++, rp++)
*(*rp) = (long)emptyrow ;
fclose(f) ;
}
int fastcop(max)
struct billiard *max ;
{
register struct billiard *bbp ;
register short *rq ;
register int j ;
register short **rp ;
int ret ;
bbp = balls ;
while (1 - bbp->pos >= realh) {
bbp++ ;
if (bbp == max)
bbp = NULL ;
}
ret = (bbp != NULL) ;
for (j=0, rp=copinst; j<screenheight; j++, rp++) {
rq = *rp ;
if (bbp == NULL || j < bbp->pos) {
*rq = (long)emptyrow ;
/* rq[2] = 0L ; */
} else {
if (bbp->vel < 0)
*rq = bytewidthm[bbp->ptr + (j - bbp->pos)] ;
else
*rq = bytewidthm[bbp->ptr + realh - 1 - (j - bbp->pos)] ;
rq[2] = bbp->color ;
if (j - bbp->pos >= realh - 1) {
bbp++ ;
if (bbp == max)
bbp = NULL ;
}
}
}
return(ret) ;
}
/*
* Now we can deal with sprite issues. (This program just keeps getting
* longer.) We grab sprites 1 and 2; no real need to grab a matched pair,
* and this (slightly) increases the chances that things will work when
* the pointer is moved all the way to the left.
*/
#define NUMPHASES (8)
#define PI (3.14159265358)
short *sprts[NUMPHASES][2] ;
struct SimpleSprite hsprites[2] ;
int havesprite[2] ;
double asin(), sqrt() ;
unsigned char ftab[32][32] ;
unsigned char fitab[32][32] ;
initcolor() {
int x, y ;
float fx, fy ;
float rx, ry ;
float lat ;
for (x=0; x<32; x++) {
for (y=0; y<32; y++) {
fx = (x - 15.5) / 16.0 ;
fy = (y - 15.5) / 16.0 ;
rx = 0.9798 * fx + 0.2 * fy ;
ry = 0.9798 * fy - 0.2 * fx ;
if (rx * rx + ry * ry >= 0.999)
ftab[x][y] = 255 ;
else {
lat = asin(ry) * 4.0 / PI + 8.0 ;
fitab[x][y] = ((int)lat) & 1 ;
lat = asin(rx / sqrt(1.0 - ry * ry)) * 64.0 / PI + 32.5 ;
ftab[x][y] = ((int)lat) ;
}
}
}
}
int color(x, y, n)
int x, y ;
int n ;
{
int f ;
int t ;
f = ftab[x][y] ;
if (f == 255)
return (0) ;
else
return ((((fitab[x][y]) ^ ((f + n) >> 4)) & 1) ? 1 : 2) ;
}
upsprites() {
register int i, j, k, m ;
register short *p ;
register int t ;
int n ;
initcolor() ;
for (i=0; i<2; i++) {
if (GetSprite(&(hsprites[i]), i + 1L) == -1)
error("! no sprites") ;
havesprite[i] = 1 ;
hsprites[i].height = 32 ;
}
for (i=0; i<NUMPHASES; i++) {
n = (i << 4) / NUMPHASES ;
for (j=0; j<2; j++) {
p = (short *)AllocMem(136L, MEMF_CHIP | MEMF_CLEAR) ;
if (p)
sprts[i][j] = p ;
else
error("! no sprite memory") ;
for (m=0; m<32; m++) {
for (k=0; k<16; k++) {
t = color(k + (j << 4), m, n) ;
if (t)
p[1+t+(m << 1)] |= 1 << (15-k) ;
}
}
}
}
}
downsprites() {
register int i, j ;
register short *p ;
for (i=0; i<2; i++)
if (havesprite[i]) {
FreeSprite(i + 1L) ;
havesprite[i] = 0 ;
}
for (i=0; i<NUMPHASES; i++)
for (j=0; j<2; j++) {
p = sprts[i][j] ;
if (p)
FreeMem(p, 136L) ;
}
SetRGB4(vp, 17L, 15L, 0L, 0L) ;
SetRGB4(vp, 21L, 15L, 0L, 0L) ;
SetRGB4(vp, 18L, 15L, 15L, 15L) ;
SetRGB4(vp, 22L, 15L, 15L, 15L) ;
}
int hvel = 4 ;
int xpos = -64 ;
int ypos = 0 ;
int vvel = 0 ;
int vacc = 1 ;
int phase = 1000 ;
long parity = 15 ;
int cc ;
#define TURNCC (3)
nextsprite() {
register short **ss ;
if (onsprites > 0) {
onsprites-- ;
return ;
}
if ((xpos += hvel) > screenwidth - 64) {
if (onsprites < -200) {
if (xpos > screenwidth + 6) {
onsprites = 400 ;
xpos = -68 ;
}
} else {
xpos = screenwidth - 64 ;
hvel = - hvel ;
onsprites -= 700 ;
}
} else if (xpos < 0) {
xpos = 0 ;
hvel = - hvel ;
}
if ((ypos += ((vvel += vacc) >> 3)) > screenheight - 64) {
ypos = screenheight - 64 ;
vvel = - vvel ;
} else if (ypos < 0) {
ypos = 0 ;
vvel = 0 ;
}
if ((cc--) <= 0) {
cc = TURNCC ;
phase++ ;
if (phase >= NUMPHASES)
phase = 0 ;
ss = sprts[phase] ;
ChangeSprite(vp, &hsprites, ss[0]) ;
ChangeSprite(vp, &(hsprites[1]), ss[1]) ;
if (phase == 0) {
SetRGB4(vp, 17L, 15L, parity, parity) ;
SetRGB4(vp, 21L, 15L, parity, parity) ;
parity = 15 - parity ;
SetRGB4(vp, 18L, 15L, parity, parity) ;
SetRGB4(vp, 22L, 15L, parity, parity) ;
}
}
if (hvel > 0) {
MoveSprite(vp, &hsprites, (long)xpos, (long)ypos) ;
MoveSprite(vp, &(hsprites[1]), 32L + xpos, (long)ypos) ;
} else {
MoveSprite(vp, &(hsprites[1]), 32L + xpos, (long)ypos) ;
MoveSprite(vp, &hsprites, (long)xpos, (long)ypos) ;
}
}
_wb_parse() {}