#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 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>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]); ix[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> 3), (long)(ng >> 3), (long)(nb >> 3)) ; myscreen->RastPort.Mask = 1 ; for (i=0; i= 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= 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; ix[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:", 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; iUCopIns=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> 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; jMask ; 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> 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> 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 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 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; ipos >= realh) { bbp++ ; if (bbp == max) bbp = NULL ; } ret = (bbp != NULL) ; for (j=0, rp=copinst; jpos) { *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 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() {}