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 >
C/C++ Source or Header  |  1989-11-06  |  50KB  |  2,069 lines

  1. #include <exec/types.h>
  2. #include <exec/nodes.h>
  3. #include <exec/lists.h>
  4. #include <exec/memory.h>
  5. #include <intuition/intuition.h>
  6. #include <intuition/intuitionbase.h>
  7. #include <libraries/dos.h>
  8. #include <libraries/dosextens.h>
  9. #include <graphics/gfxbase.h>
  10. #include <graphics/gfxmacros.h>
  11. #include <graphics/sprite.h>
  12. #include <hardware/custom.h>
  13. #include <hardware/dmabits.h>
  14. #include <hardware/cia.h>
  15. #include <hardware/intbits.h>
  16. #include <devices/audio.h>
  17. #include <functions.h>
  18. #include "stdio.h"
  19. struct IntuitionBase *IntuitionBase;
  20. struct GfxBase *GfxBase;
  21. struct DiskfontBase *DiskfontBase ;
  22. extern struct DosLibrary *DOSBase;
  23. struct Screen *myscreen ;
  24. struct Window *mywindow ;
  25. struct ViewPort *vp;
  26. struct UCopList *ucop;
  27. struct Task *task, *rtask ;
  28. int origpri ;
  29. static struct TextFont *font ;
  30. static struct TextAttr myfont = { (STRPTR) "topaz.font", 11, 0, 0 };
  31. char tempbuf[100] ;
  32. struct IntuiText itext = { 1, 0, JAM2, 0, 0, &myfont, (UBYTE *)&tempbuf } ;
  33. #define MAXLINES (50)
  34. #define MAXPOINTS (10)
  35. int maxpoints ;
  36. /*
  37.  *   The external variables we access.
  38.  */
  39. struct RastPort *rastport ;
  40. short screenheight, screenwidth, bytewidth ;
  41. short bytewidthm[700] ;
  42. short color1[700], color2[700] ;
  43. /*
  44.  *   Some locals to this file.
  45.  */
  46. static struct BitMap mybitmap ;
  47. static struct NewScreen newscreen = {
  48.    0, 0, 640, 400, 2, 0, 1, HIRES | LACE | SCREENQUIET | SPRITES,
  49.    CUSTOMSCREEN | CUSTOMBITMAP, 0, 0, 0, &mybitmap } ;
  50. static struct NewWindow newwindow = {
  51.    0, 0, 32, 10, 0, 1, CLOSEWINDOW | VANILLAKEY,
  52.    WINDOWCLOSE | SIMPLE_REFRESH | NOCAREREFRESH | ACTIVATE, 0, 0, 0, 0, 0, 0,
  53.    0, 0, 0, CUSTOMSCREEN } ;
  54. #define BSTRtoS(a) ((char *)(((long)(a))<<2))
  55. long globalreplysignum ;
  56. long rassize ;
  57. long nilh ;
  58. cleanup() {
  59.    struct Process *p ;
  60.  
  61.    downsprites() ;
  62.    freechannels() ;
  63.    if (font != NULL)
  64.       CloseFont(font) ;
  65.    if (rtask) {
  66.       Signal(rtask, 1L << SIGBREAKB_CTRL_C) ;
  67.       SetTaskPri(rtask, 11L) ;
  68.       Wait(1L << globalreplysignum) ;
  69.       RemTask(rtask);
  70.       FreeMem(rtask, (long)sizeof(struct Task)) ;
  71.       rtask = NULL ;
  72.    }
  73.    if (globalreplysignum != -1)
  74.       FreeSignal(globalreplysignum) ;
  75.    if (vp) {
  76.       FreeVPortCopLists(vp) ;
  77.       RemakeDisplay() ;
  78.    }
  79.    if (mywindow)
  80.       CloseWindow(mywindow) ;
  81.    if (myscreen)
  82.       CloseScreen(myscreen) ;
  83.    if (mybitmap.Planes[0])
  84.       FreeMem(mybitmap.Planes[0], rassize) ;
  85.    if (mybitmap.Planes[1])
  86.       FreeMem(mybitmap.Planes[1], rassize + 2 * bytewidth) ;
  87.    if (DiskfontBase)
  88.       CloseLibrary(DiskfontBase) ;
  89.    if (IntuitionBase)
  90.       CloseLibrary(IntuitionBase) ;
  91.    if (GfxBase)
  92.       CloseLibrary(GfxBase) ;
  93.    RestoreFilter() ;
  94.    if (task)
  95.       SetTaskPri(task, (long)origpri) ;
  96. /*
  97.  *   We also kill any CLI processes that are running a program that
  98.  *   starts with our play command.
  99.  */
  100.    p = (struct Process *)FindTask("player.task") ;
  101.    if (p)
  102.       Signal(p, 1L << SIGBREAKB_CTRL_C) ;
  103.    if (nilh)
  104.       Close(nilh) ;
  105.    exit(0) ;
  106. }
  107. error(s)
  108. register char *s ;
  109. {
  110.    Write(Output(), s, (long)strlen(s)) ;
  111.    Write(Output(), "\n", 1L) ;
  112.    Delay(10L) ;
  113.    if (*s == '!')
  114.       cleanup() ;
  115. }
  116. /*
  117.  *   Whenever we need a guaranteed clear row, we use this.
  118.  */
  119. short *emptyrow ;
  120. /*
  121.  *   This routine opens a screen and fires off the task if apropriate.
  122.  */
  123. blankscreen() {
  124.    register short *p, *q ;
  125.    register long t, tt ;
  126.  
  127.    IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0L) ;
  128.    GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L) ;
  129.    if (IntuitionBase == NULL || GfxBase == NULL)
  130.       error("! no library") ;
  131.    if ((t = (long)OpenLibrary("mathtrans.library", 0L))==0)
  132.       error("! no mathtrans.library") ;
  133.    CloseLibrary(t) ;
  134.    screenheight = 2 * GfxBase->NormalDisplayRows ;
  135.    screenwidth = GfxBase->NormalDisplayColumns ;
  136.    newscreen.Height = screenheight ;
  137.    newscreen.Width = screenwidth ;
  138.    bytewidth = ((screenwidth + 15) >> 3) & ~1 ;
  139.    rassize = screenheight * (long)bytewidth ;
  140.    for (t=0; t<screenheight; t++)
  141.       bytewidthm[t] = t * bytewidth ;
  142. /*
  143.  *   We want to make sure we can manipulate the bitmap pointer for the second
  144.  *   bitplane simply by changing the lower 16-bits.  So we allocate a ton of
  145.  *   memory, grab the right part, and then free the stuff above and below.
  146.  */
  147.    tt = (rassize + 2 * bytewidth + 7) & ~7 ;
  148.    p = AllocMem(65536L + tt, MEMF_CHIP | MEMF_CLEAR) ;
  149.    if (p==NULL)
  150.       error("! no memory") ;
  151.    q = (short *)((((long)p) + 65535L) & ~65535L) ;
  152.    t = ((long)q) - ((long)p) ;
  153.    if (t)
  154.       FreeMem(p, t) ;
  155.    t = 65536L - t ;
  156.    if (t)
  157.       FreeMem(((long)p) + tt + 65536L - t, t) ;
  158.    p = AllocMem(rassize, MEMF_CHIP | MEMF_CLEAR) ;
  159.    if (p==NULL) {
  160.       FreeMem(q, rassize + 2 * bytewidth) ;
  161.       error("! out of memory") ;
  162.    }
  163.    emptyrow = (short *)(((long)q) + rassize) ;
  164.    mybitmap.BytesPerRow = bytewidth ;
  165.    mybitmap.Rows = screenheight ;
  166.    mybitmap.Depth = 2 ;
  167.    mybitmap.Planes[0] = (PLANEPTR)p ;
  168.    mybitmap.Planes[1] = (PLANEPTR)q ;
  169.    if ((myscreen = OpenScreen(&newscreen)) == NULL)
  170.       error("! no screen\n") ;
  171.    if (screenheight > 700)
  172.       error("! we don't work on screens that large") ;
  173.    vp = &(myscreen->ViewPort) ;
  174.    SetRGB4(vp, 0L, 0L, 0L, 0L) ;
  175.    SetRGB4(vp, 1L, 0L, 0L, 0L) ;
  176.    SetRGB4(vp, 2L, 0L, 0L, 0L) ;
  177.    SetRGB4(vp, 3L, 0L, 0L, 0L) ;
  178.    newwindow.Height = screenheight ; /* to disable dragging */
  179.    newwindow.Width = screenwidth ;
  180.    newwindow.Screen = myscreen ;
  181.    if ((mywindow = OpenWindow(&newwindow)) == NULL)
  182.       error("! no window\n") ;
  183.    if ((globalreplysignum = AllocSignal(-1L)) == -1)
  184.       error("! no signal\n") ;
  185.    rastport = &(myscreen->RastPort) ;
  186.    SetRast(rastport, 0L) ;
  187.    InstallList() ;
  188.    font = (struct TextFont *)OpenFont(&myfont) ;
  189.    if (font == NULL || font->tf_YSize != 11) {
  190.       if (font) {
  191.          CloseFont(font) ;
  192.          font = NULL ;
  193.       }
  194.       DiskfontBase = (struct DiskfontBase *)OpenLibrary("diskfont.library", 0L) ;
  195.       if (DiskfontBase != NULL)
  196.          font = (struct TextFont *)OpenDiskFont(&myfont) ;
  197.    }
  198.    if (font != NULL)
  199.       SetFont(rastport, font) ;
  200.    else
  201.       error("! I need topaz 11 to run") ;
  202.    SetPointer(mywindow, emptyrow+bytewidth/2, 0L, 0L, 0L, 0L) ;
  203. }
  204. /*
  205.  *   This routine returns a random value from 0 to n-1.
  206.  */
  207. static long seed = 304019 ;
  208. int randm(i)
  209. int i ;
  210. {
  211.    register long rseed ;
  212.    register unsigned int rval ;
  213.  
  214.    rseed = seed ;
  215.    rseed = rseed * 23213 + 121 ;
  216.    rval = (rseed >> 5) & 65535 ;
  217.    seed = rseed ;
  218.    return ((i * (long)rval) >> 16) ;
  219. }
  220. /*
  221.  *   This routine sets x and y values to a random number.
  222.  */
  223. static long x, y ;
  224. randomxy() {
  225.    x = randm(screenwidth) ;
  226.    y = randm(screenheight) ;
  227. }
  228. /*
  229.  *   Main routines are always fun.
  230.  */
  231. struct box {
  232.    short x[MAXPOINTS], y[MAXPOINTS] ;
  233. } store[MAXLINES] ;
  234. #define FIX(x) (((long)(x)) << 7)
  235. #define FIXH(x) (((long)((*(x)+(x)[1])>>1)) << 7)
  236. #define UNFIX(x) ((x)>>7)
  237. struct box *ptr ;
  238. struct box *eptr ;
  239. int numlines ;
  240. int mdelta = -1 ;
  241. int maxlines = MAXLINES/2 ;
  242. short dx[MAXPOINTS], dy[MAXPOINTS] ;
  243. short ox[MAXPOINTS], oy[MAXPOINTS] ;
  244. short nx[MAXPOINTS], ny[MAXPOINTS] ;
  245. short dr, dg, db ;
  246. short or, og, ob ;
  247. short nr, ng, nb ;
  248. long oldx, oldy, oldwidth, oldptr ;
  249. int oldcol ;
  250. /*
  251.  *   Draws a spline!  Expects all arguments in registers.
  252.  */
  253. #asm
  254.     public    _Draw
  255.     cseg
  256. rspline
  257.     move.l    a0,d0
  258.     sub.l    d6,d0
  259.     move.l    d0,d3
  260.     bpl    save1
  261.     neg.l    d0
  262. save1
  263.     move.l    a1,d1
  264.     sub.l    d7,d1
  265.     move.l    d1,d4
  266.     bpl    save2
  267.     neg.l    d1
  268. save2
  269.     move.l    d0,d2
  270.     cmp.l    d0,d1
  271.     bmi    save3
  272.     lsr.l    #3,d2
  273.     bra    save9
  274. save3
  275.     lsr.l    #3,d1
  276. save9
  277.     add.l    d1,d2
  278.     asr.l    #3,d2
  279.     beq    check2
  280.     asr.l    #5,d3
  281.     asr.l    #5,d4
  282.     move.l    a2,d0
  283.     sub.l    a0,d0
  284.     move.l    a3,d1
  285.     sub.l    a1,d1
  286.     asr.l    #5,d0
  287.     asr.l    #5,d1
  288.     muls.w    d4,d0
  289.     muls.w    d3,d1
  290.     sub.l    d1,d0
  291.     bpl    save4
  292.     neg.l    d0
  293. save4
  294.     cmp.l    d0,d2
  295.     ble    pushem
  296.     move.l    a5,d0
  297.     sub.l    a0,d0
  298.     move.l    a6,d1
  299.     sub.l    a1,d1
  300.     asr.l    #5,d0
  301.     asr.l    #5,d1
  302.     muls.w    d4,d0
  303.     muls.w    d3,d1
  304.     sub.l    d1,d0
  305.     bpl    save5
  306.     neg.l    d0
  307. save5
  308.     cmp.l    d0,d2
  309.     ble    pushem
  310. makeline
  311.     lsr.l    #7,d7
  312.     move.l    d7,d1
  313.     lsr.l    #7,d6
  314.     move.l    d6,d0
  315.     movem.l    d2-d5/a0-a1,-(sp)
  316.     move.l    _oldx,d2
  317.     move.l    _oldy,d3
  318.     move.l    d0,_oldx
  319.     move.l    d1,_oldy
  320.     move.l    _oldwidth,d4
  321.     move.l    _oldptr,a0
  322.     jsr    mdraw
  323.     movem.l    (sp)+,d2-d5/a0-a1
  324.     rts
  325. check2
  326.     move.l    a0,d0
  327.     sub.l    a2,d0
  328.     bpl    ch1
  329.     neg.l    d0
  330. ch1
  331.     move.l    a1,d1
  332.     sub.l    a3,d1
  333.     bpl    ch2
  334.     neg.l    d1
  335. ch2
  336.     add.l    d0,d1
  337.     asr.l    #3,d1
  338.     bne    pushem
  339.     move.l    a0,d0
  340.     sub.l    a5,d0
  341.     bpl    ch3
  342.     neg.l    d0
  343. ch3
  344.     move.l    a1,d1
  345.     sub.l    a6,d1
  346.     bpl    ch4
  347.     neg.l    d1
  348. ch4
  349.     add.l    d0,d1
  350.     asr.l    #3,d1
  351.     beq    makeline
  352. pushem
  353.     movem.l    d6/d7,-(sp)
  354.     move.l    a5,d0
  355.     add.l    d6,d0
  356.     asr.l    #1,d0
  357.     move.l    a6,d1
  358.     add.l    d7,d1
  359.     asr.l    #1,d1
  360.     movem.l    d0/d1,-(sp)
  361.     move.l    a2,d2
  362.     add.l    a5,d2
  363.     asr.l    #1,d2
  364.     move.l    a3,d3
  365.     add.l    a6,d3
  366.     asr.l    #1,d3
  367.     move.l    d0,d4
  368.     add.l    d2,d4
  369.     asr.l    #1,d4
  370.     move.l    d1,d5
  371.     add.l    d3,d5
  372.     asr.l    #1,d5
  373.     movem.l    d4/d5,-(sp)
  374.     move.l    a0,d6
  375.     add.l    a2,d6
  376.     asr.l    #1,d6
  377.     move.l    a1,d7
  378.     add.l    a3,d7
  379.     asr.l    #1,d7
  380.     move.l    d2,d0
  381.     add.l    d6,d0
  382.     asr.l    #1,d0
  383.     move.l    d3,d1
  384.     add.l    d7,d1
  385.     asr.l    #1,d1
  386.     move.l    d6,a2
  387.     move.l    d7,a3
  388.     move.l    d0,d6
  389.     add.l    d4,d6
  390.     asr.l    #1,d6
  391.     move.l    d1,d7
  392.     add.l    d5,d7
  393.     asr.l    #1,d7
  394.     movem.l    d6/d7,-(sp)
  395.     move.l    d0,a5
  396.     move.l    d1,a6
  397.     jsr    rspline
  398.     movem.l    (sp)+,a0/a1
  399.     movem.l    (sp)+,a2/a3/a5/a6
  400.     movem.l    (sp)+,d6/d7
  401.     bra    rspline
  402. ;
  403.     include 'exec/types.i'
  404.     include 'hardware/custom.i'
  405.     include 'hardware/blit.i'
  406.     include 'hardware/dmabits.i'
  407. ;
  408.     xref    _custom
  409. ;
  410. ;
  411. ;   Our entry point.
  412. ;
  413. mdraw:
  414.     move.l    #$dff000,a1    ; Manx requires this
  415.     sub.w    d0,d2        ; calculate dx
  416.     bmi    xneg        ; if negative, octant is one of [3,4,5,6]
  417.     sub.w    d1,d3        ; calculate dy   ''   is one of [1,2,7,8]
  418.     bmi    yneg        ; if negative, octant is one of [7,8]
  419.     cmp.w    d3,d2        ; cmp |dx|,|dy|  ''   is one of [1,2]
  420.     bmi    ygtx        ; if y>x, octant is 2
  421.     moveq.l    #OCTANT1+LINEMODE,d5    ; otherwise octant is 1
  422.     bra    lineagain    ; go to the common section
  423. ygtx:
  424.     exg    d2,d3        ; X must be greater than Y
  425.     moveq.l    #OCTANT2+LINEMODE,d5    ; we are in octant 2
  426.     bra    lineagain    ; and common again.
  427. yneg:
  428.     neg.w    d3        ; calculate abs(dy)
  429.     cmp.w    d3,d2        ; cmp |dx|,|dy|, octant is [7,8]
  430.     bmi    ynygtx        ; if y>x, octant is 7
  431.     moveq.l    #OCTANT8+LINEMODE,d5    ; otherwise octant is 8
  432.     bra    lineagain
  433. ynygtx:
  434.     exg    d2,d3        ; X must be greater than Y
  435.     moveq.l    #OCTANT7+LINEMODE,d5    ; we are in octant 7
  436.     bra    lineagain
  437. xneg:
  438.     neg.w    d2        ; dx was negative! octant is [3,4,5,6]
  439.     sub.w    d1,d3        ; we calculate dy
  440.     bmi    xyneg        ; if negative, octant is one of [5,6]
  441.     cmp.w    d3,d2        ; otherwise it's one of [3,4]
  442.     bmi    xnygtx        ; if y>x, octant is 3
  443.     moveq.l    #OCTANT4+LINEMODE,d5    ; otherwise it's 4
  444.     bra    lineagain
  445. xnygtx:
  446.     exg    d2,d3        ; X must be greater than Y
  447.     moveq.l    #OCTANT3+LINEMODE,d5    ; we are in octant 3
  448.     bra    lineagain
  449. waitmore:
  450.     nop
  451.     nop
  452.     btst    #DMAB_BLTDONE-8,dmaconr(a1)
  453.     beq    donewait
  454.     bra    waitmore
  455. xyneg:
  456.     neg.w    d3        ; y was negative, in one of [5,6]
  457.     cmp.w    d3,d2        ; is y>x?
  458.     bmi    xynygtx        ; if so, octant is 6
  459.     moveq.l    #OCTANT5+LINEMODE,d5    ; otherwise, octant is 5
  460.     bra    lineagain
  461. xynygtx:
  462.     exg    d2,d3        ; X must be greater than Y
  463.     moveq.l    #OCTANT6+LINEMODE,d5    ; we are in octant 6
  464. lineagain:
  465.     mulu.w    d4,d1        ; Calculate y1 * width
  466.     ror.l    #4,d0        ; move upper four bits into hi word
  467.     add.w    d0,d0        ; multiply by 2
  468.     add.l    d1,a0        ; ptr += (x1 >> 3)
  469.     add.w    d0,a0        ; ptr += y1 * width
  470.     swap    d0        ; get the four bits of x1
  471.     or.w    _oldcol,d0    ; or with USEA, USEC, USED, F=A~C+~AC
  472.     lsl.w    #2,d3        ; Y = 4 * Y
  473.     add.w    d2,d2        ; X = 2 * X
  474.     move.w    d2,d1        ; set up size word
  475.     lsl.w    #5,d1        ; shift five left
  476.     add.w    #$42,d1        ; and add 1 to height, 2 to width
  477.     btst    #DMAB_BLTDONE-8,dmaconr(a1)    ; safety check
  478. waitblit:
  479.     btst    #DMAB_BLTDONE-8,dmaconr(a1)    ; wait for blitter
  480.     bne    waitmore
  481. donewait:
  482.     move.w    d3,bltbmod(a1)    ; B mod = 4 * Y
  483.     sub.w    d2,d3
  484.     ext.l    d3
  485.     move.l    d3,bltapt(a1)    ; A ptr = 4 * Y - 2 * X
  486.     bpl    lineover    ; if negative,
  487.     or.w    #SIGNFLAG,d5    ; set sign bit in con1
  488. lineover:
  489.     move.w    d0,bltcon0(a1)    ; write control registers
  490.     move.w    d5,bltcon1(a1)
  491.     move.w    d4,bltcmod(a1)    ; C mod = bitplane width
  492.     move.w    d4,bltdmod(a1)    ; D mod = bitplane width
  493.     sub.w    d2,d3
  494.     move.w    d3,bltamod(a1)    ; A mod = 4 * Y - 4 * X
  495.     move.w    #$8000,bltadat(a1)    ; A data = 0x8000
  496.     moveq.l    #-1,d5        ; Set masks to all ones
  497.     move.l    d5,bltafwm(a1)    ; we can hit both masks at once
  498.     move.l    a0,bltcpt(a1)    ; Pointer to first pixel to set
  499.     move.l    a0,bltdpt(a1)
  500.     move.w    d1,bltsize(a1)    ; Start blit
  501.     rts            ; and return, blit still in progress.
  502. #endasm
  503. /*
  504.  *   Now our linkage to the spline routine.  Parameters are in 8(a5)...
  505.  */
  506. int drawspline(x1, y1, x2, y2, x3, y3, x4, y4)
  507. long x1, y1, x2, y2, x3, y3, x4, y4 ;
  508. {
  509. #asm
  510.     movem.l    saver,-(sp)
  511.     move.l    8(a5),a0
  512.     move.l    12(a5),a1
  513.     move.l    16(a5),a2
  514.     move.l    20(a5),a3
  515.     move.l    28(a5),a6
  516.     move.l    32(a5),d6
  517.     move.l    36(a5),d7
  518.     move.l    24(a5),a5
  519.     jsr    rspline
  520.     movem.l    (sp)+,saver
  521. saver    reg    d0-d7/a0-a6
  522. #endasm
  523. }
  524. int closed ;
  525. char *nextlegal[] = { "01458", "236", "01458", "236", "01458", "23", "01458",
  526.                       "", "0145" } ;
  527. int advval[] = { 3, 2, 3, 2, 1, 0, 1, 0, 1 } ;
  528. unsigned char realfunc[14] ;
  529. char namefunc[20] ;
  530. makefunc() {
  531.    register int i ;
  532.    register int goallen ;
  533.    register int sofar = 0 ;
  534.    register unsigned char *p ;
  535.    register char *nextpossib ;
  536.  
  537.    closed = randm(3) ;
  538.    switch(closed) {
  539. case 2:
  540.       goallen = 2 + randm(3) ;
  541.       break ;
  542. case 1:
  543.       goallen = 3 + randm(6) ;
  544.       break ;
  545. case 0:
  546.       goallen = 1 + randm(7) ;
  547.       break ;
  548.    }
  549.    while (1) {
  550.       if (closed == 0)
  551.          nextpossib = "0145" ;
  552.       else
  553.          nextpossib = "0123456" ;
  554.       sofar = 0 ;
  555.       p = realfunc ;
  556.       while (sofar < goallen) {
  557.          i = nextpossib[randm(strlen(nextpossib))] - '0' ;
  558.          *p++ = i ;
  559.          nextpossib = nextlegal[i] ;
  560.          sofar += advval[i] ;
  561.       }
  562.       if (sofar == goallen) {
  563.          if (closed == 0) {
  564.             if (nextpossib[0] == '0')
  565.                break ;
  566.          } else {
  567.             if (*nextpossib == '0' || realfunc[0] < 4 || *(p-1) < 4) {
  568.                if ((*nextpossib == '0') ?
  569.                       ((realfunc[0] & 2) != 0) : ((realfunc[0] & 2) == 0)) {
  570.                   if (realfunc[0] != 5) {
  571.                      realfunc[0] ^= 2 ;
  572.                      break ;
  573.                   }
  574.                } else {
  575.                   break ;
  576.                }
  577.             }
  578.          }
  579.       }
  580.    }
  581.    *p = 100 ;
  582.    maxpoints = goallen ;
  583.    switch (closed) {
  584. case 2:
  585.       for (i=0; i<p-realfunc; i++)
  586.          p[i] = realfunc[i] ;
  587.       p[p-realfunc] = 100 ;
  588.       break ;
  589. case 1:
  590.       break ;
  591. case 0:
  592.       maxpoints++ ;
  593.       break ;
  594.    }
  595.    for (i=0, p=realfunc; *p < 100; p++, i++)
  596.       namefunc[i] = *p + '0' ;
  597.    namefunc[i++] = ' ' ;
  598.    namefunc[i++] = '0' + closed ;
  599.    namefunc[i++] = ' ' ;
  600.    namefunc[i++] = '0' + maxpoints ;
  601.    namefunc[i] = 0 ;
  602. }
  603. #define HALF(a) ((*(a)+(a)[1])>>1)
  604. draw_s_f(xptr, yptr)
  605. register short *xptr, *yptr ;
  606. {
  607.    oldx = HALF(xptr) ;
  608.    oldy = HALF(yptr) ;
  609.    OwnBlitter() ;
  610.    drawspline(FIX(oldx), FIX(oldy), FIX(xptr[1]), FIX(yptr[1]),
  611.               FIX(xptr[2]), FIX(yptr[2]), FIXH(xptr+2), FIXH(yptr+2)) ;
  612.    DisownBlitter() ;
  613. }
  614. draw_sf(xptr, yptr)
  615. register short *xptr, *yptr ;
  616. {
  617.    oldx = HALF(xptr) ;
  618.    oldy = HALF(yptr) ;
  619.    OwnBlitter() ;
  620.    drawspline(FIX(oldx), FIX(oldy), FIX(xptr[1]), FIX(yptr[1]),
  621.               FIX(xptr[2]), FIX(yptr[2]), FIX(xptr[3]), FIX(yptr[3])) ;
  622.    DisownBlitter() ;
  623. }
  624. draws_f(xptr, yptr)
  625. register short *xptr, *yptr ;
  626. {
  627.    oldx = *xptr ;
  628.    oldy = *yptr ;
  629.    OwnBlitter() ;
  630.    drawspline(FIX(*xptr), FIX(*yptr), FIX(xptr[1]), FIX(yptr[1]),
  631.               FIX(xptr[2]), FIX(yptr[2]), FIXH(xptr+2), FIXH(yptr+2)) ;
  632.    DisownBlitter() ;
  633. }
  634. drawsf(xptr, yptr)
  635. register short *xptr, *yptr ;
  636. {
  637.    oldx = *xptr ;
  638.    oldy = *yptr ;
  639.    OwnBlitter() ;
  640.    drawspline(FIX(*xptr), FIX(*yptr), FIX(xptr[1]), FIX(yptr[1]),
  641.               FIX(xptr[2]), FIX(yptr[2]), FIX(xptr[3]), FIX(yptr[3])) ;
  642.    DisownBlitter() ;
  643. }
  644. draw_lf(xptr, yptr)
  645. register short *xptr, *yptr ;
  646. {
  647.    Move(rastport, (long)HALF(xptr), (long)HALF(yptr)) ;
  648.    xptr++ ;
  649.    yptr++ ;
  650.    Draw(rastport, (long)*xptr, (long)*yptr) ;
  651. }
  652. drawl_f(xptr, yptr)
  653. register short *xptr, *yptr ;
  654. {
  655.    Move(rastport, (long)*xptr, (long)*yptr) ;
  656.    Draw(rastport, (long)HALF(xptr), (long)HALF(yptr)) ;
  657. }
  658. drawlf(xptr, yptr)
  659. register short *xptr, *yptr ;
  660. {
  661.    Move(rastport, (long)*xptr, (long)*yptr) ;
  662.    xptr++ ;
  663.    yptr++ ;
  664.    Draw(rastport, (long)*xptr, (long)*yptr) ;
  665. }
  666. drawnlf() {}
  667. int (*funcs[])() = { &drawsf, &draws_f, &draw_sf, &draw_s_f,
  668.                      &drawlf, &drawl_f, &draw_lf, NULL, &drawnlf } ;
  669. drawfunc(bptr)
  670. register struct box *bptr ;
  671. {
  672.    register long i ;
  673.    register short *x, *y ;
  674.    register unsigned char *p ;
  675.  
  676.    oldwidth = rastport->BitMap->BytesPerRow ;
  677.    oldptr = (long)rastport->BitMap->Planes[0] ;
  678.    switch(closed) {
  679. case 2:
  680.       for (i=0, x=&(bptr->x[0]), y=&(bptr->y[0]); i<maxpoints; i++, x++, y++) {
  681.          x[maxpoints] = screenwidth - 1 - *x ;
  682.          y[maxpoints] = screenheight - 1 - *y ;
  683.       }
  684. setup:
  685.       x[maxpoints] = bptr->x[0] ;
  686.       y[maxpoints] = bptr->y[0] ;
  687.       x++, y++ ;
  688.       x[maxpoints] = bptr->x[1] ;
  689.       y[maxpoints] = bptr->y[1] ;
  690.       break ;
  691. case 1:
  692.       x = &(bptr->x[0]) ;
  693.       y = &(bptr->y[0]) ;
  694.       goto setup ;
  695.    }
  696.    p = realfunc ;
  697.    x = &(bptr->x[0]) ;
  698.    y = &(bptr->y[0]) ;
  699.    while (*p < 20) {
  700.       (funcs[*p])(x, y) ;
  701.       i = advval[*p] ;
  702.       x += i ;
  703.       y += i ;
  704.       p++ ;
  705.    }
  706. }
  707. /*
  708.  *   Initialize things for the first lines.
  709.  */
  710. startlines() {
  711.    register int i ;
  712.  
  713.    ptr = store ;
  714.    eptr = store ;
  715.    numlines = 0 ;
  716.    if (dx[0] == 0) {
  717.       for (i=0; i<MAXPOINTS; i++) {
  718.          ox[i] = randm(screenwidth) ;
  719.      oy[i] = randm(screenheight) ;
  720.      dx[i] = 2 + randm(3) ;
  721.      dy[i] = 2 + randm(3) ;
  722.       }
  723.    }
  724.    nr = 53 ;
  725.    ng = 33 ;
  726.    nb = 35 ;
  727.    dr = -3 ;
  728.    dg = 5 ;
  729.    db = 7 ;
  730.    SetRGB4(vp, 0L, 0L, 0L, 0L) ;
  731.    SetRGB4(vp, 1L, (long)(nr >> 3), (long)(ng >> 3), (long)(nb >> 3)) ;
  732.    myscreen->RastPort.Mask = 1 ;
  733.    for (i=0; i<maxlines; i++) {
  734.       advancelines() ;
  735.       drawnew() ;
  736.    }
  737. }
  738. /*
  739.  *   Advance the number by the delta, and check the boundaries.
  740.  */
  741. adv(o, d, n, w)
  742. register short *o, *d, *n ;
  743. short w ;
  744. {
  745.    *n = *o + *d ;
  746.    if (*n < 0) {
  747.       *n = 0 ;
  748.       *d = randm(6) + 1 ;
  749.    } else if (*n >= w) {
  750.       *n = w - 1 ;
  751.       *d = - randm(6) - 1 ;
  752.    }
  753. }
  754. /*
  755.  *   Advance the two points which make up the lines.
  756.  */
  757. advancelines() {
  758.    register int i ;
  759.  
  760.    for (i=0; i<maxpoints; i++) {
  761.       adv(ox+i, dx+i, nx+i, screenwidth) ;
  762.       adv(oy+i, dy+i, ny+i, screenheight) ;
  763.    }
  764. }
  765. /*
  766.  *   Draw a new set of lines.
  767.  */
  768. drawnew() {
  769.    register int i ;
  770.    register short oldpen ;
  771.    register struct box *bptr ;
  772.  
  773.    while (numlines >= maxlines) {
  774.       oldpen = rastport->FgPen ;
  775.       oldcol = 0xb0a ;
  776.       SetAPen(rastport, 0L) ;
  777.       bptr = eptr ;
  778.       drawfunc(bptr) ;
  779.       oldcol = 0xbfa ;
  780.       SetAPen(rastport, (long)oldpen) ;
  781.       numlines-- ;
  782.       bptr++ ;
  783.       if (bptr == store + MAXLINES)
  784.          bptr = store ;
  785.       eptr = bptr ;
  786.    }
  787.    bptr = ptr ;
  788.    for (i=0; i<maxpoints; i++) {
  789.       bptr->x[i] = ox[i] = nx[i] ;
  790.       bptr->y[i] = oy[i] = ny[i] ;
  791.    }
  792.    drawfunc(bptr) ;
  793.    numlines++ ;
  794.    bptr++ ;
  795.    if (bptr == store + MAXLINES) {
  796.       bptr = store ;
  797.       if (mdelta == 1) {
  798.          maxlines++ ;
  799.          if (maxlines >= MAXLINES - 1)
  800.             mdelta = -1 ;
  801.       } else {
  802.          maxlines-- ;
  803.          if (maxlines <= 2)
  804.             mdelta = 1 ;
  805.       }
  806.    }
  807.    ptr = bptr ;
  808. }
  809. /*
  810.  *   This routine mucks with the colors.
  811.  */
  812. colors() {
  813.    or = nr ;
  814.    og = ng ;
  815.    ob = nb ;
  816.    adv(&or, &dr, &nr, 128) ;
  817.    adv(&og, &dg, &ng, 128) ;
  818.    adv(&ob, &db, &nb, 128) ;
  819.    SetRGB4(vp, 1L, (long)(nr >> 3), (long)(ng >> 3), (long)(nb >> 3)) ;
  820. }
  821. long time = 0 ;
  822. settime() {
  823.    time = 0 ;
  824. }
  825. long gettime() {
  826.    return time ;
  827. }
  828. /*
  829.  *   Our actual task, in an infinite loop.
  830.  */
  831. void taskrout() {
  832.    register struct Task *mtask ;
  833.  
  834.    geta4() ;
  835.    settime() ;
  836.    makefunc() ;
  837.    mtask = FindTask(0L) ;
  838.    startlines() ;
  839.    colors() ;
  840.    while (SetSignal(0L, 0L)==0) {
  841.       advancelines() ;
  842.       drawnew() ;
  843.       advancelines() ;
  844.       drawnew() ;
  845.       advancelines() ;
  846.       drawnew() ;
  847.       advancelines() ;
  848.       drawnew() ;
  849.       advancelines() ;
  850.       drawnew() ;
  851.       advancelines() ;
  852.       drawnew() ;
  853.       colors() ;
  854.       if (gettime() >= 1000) {
  855.          settime() ;
  856.          makefunc() ;
  857.          SetRast(rastport, 0L) ;
  858.          startlines() ;
  859.       }
  860.    }
  861. done:
  862.    Signal(task, 1L << globalreplysignum) ;
  863.    Wait(0L) ;
  864. }
  865. /*
  866.  *   Our `delay' call that checks for an abort.
  867.  */
  868. MDelay(n)
  869. register long n ;
  870. {
  871.    while (n > 0) {
  872.       checktof() ;
  873.       n-- ;
  874.    }
  875. }
  876. extern int Enable_Abort ;
  877. #define STACKSIZE 1000
  878. long stackmem[STACKSIZE] ;
  879. int (*nextf)(), nextcolor() ;
  880. long flags ;
  881. #define checkflag(c) (flags&(1L<<((c)-'a')))
  882. int onsprites = 32767 ;
  883. main(argc, argv)
  884. int argc ;
  885. char *argv[] ;
  886. {
  887.    register char *p ;
  888.  
  889.    Enable_Abort = 0 ;
  890.    while (argc > 1) {
  891.       argc-- ;
  892.       argv++ ;
  893.       for (p=argv[0]; *p; p++)
  894.          if ('a' <= *p && *p <= 'z')
  895.             flags |= (1L << (*p - 'a')) ;
  896.          else if ('A' <= *p && *p <= 'Z')
  897.             flags |= (1L << (*p - 'A')) ;
  898.    }
  899.    if (checkflag('s'))
  900.       flags |= (1L << ('g'-'a')) | (1L << ('m'-'a')) ;
  901.    blankscreen() ;
  902.    nilh = (long)Open("nil:", MODE_NEWFILE) ;
  903.    loadfont() ;
  904.    readiff("cracked.iff", 0) ;
  905.    task = FindTask(0L) ;
  906.    origpri = task->tc_Node.ln_Pri ;
  907.    if (!checkflag('g'))
  908.       loadsound() ;
  909.    else
  910.       flashscreen() ;
  911.    if (!checkflag('m'))
  912.       Execute("Play * P=Script <nil: >nil:", nilh, nilh) ;
  913.    SetTaskPri(task, (long)(task->tc_Node.ln_Pri+6)) ;
  914.    if (!checkflag('c'))
  915.       rollcredits() ;
  916.    SetTaskPri(task, (long)(task->tc_Node.ln_Pri-5)) ;
  917.    if (!checkflag('b'))
  918.       upsprites() ;
  919.    SetRast(rastport, 0L) ;
  920.    readiff("radboogie.iff", 1) ; /* this needs to go faster */
  921.    onsprites = 420 ;
  922.    rtask = (struct Task *)AllocMem((long)sizeof(struct Task),
  923.              MEMF_CLEAR | MEMF_PUBLIC) ;
  924.    if (rtask != NULL) {
  925.       rtask->tc_Node.ln_Pri = task->tc_Node.ln_Pri - 2 ;
  926.       rtask->tc_Node.ln_Type = NT_TASK ;
  927.       rtask->tc_Node.ln_Name = "ri.Lines" ;
  928.       rtask->tc_SPLower = (APTR)stackmem ;
  929.       rtask->tc_SPUpper = rtask->tc_SPReg =
  930.                    (APTR)(stackmem + STACKSIZE/4 - 8) ;
  931.       AddTask(rtask, taskrout, 0L) ;
  932.    }
  933.    nextf = &nextcolor ;
  934.    MDelay(250L) ;
  935.    while (1) {
  936.       checktof() ;
  937.       nextf() ;
  938.       time++ ;
  939.    }
  940. done: ;
  941.    cleanup() ;
  942. }
  943.  
  944. short *copinst[700] ;
  945. /*
  946.  *   Copper manipulations.
  947.  */
  948. grabcopper(cpr, ptr)
  949. register struct cprlist *cpr ;
  950. int ptr ;
  951. {
  952.    register short *p ;
  953.    register int i ;
  954.  
  955.    for (i=cpr->MaxCount, p=(short *)cpr->start; i; i--, p += 2)
  956.       if (*p == 0xe6)
  957.          break ;
  958.    if (i <= 0)
  959.       error("! couldn't get copper") ;
  960.    i-- ;
  961.    p += 2 ;
  962.    while (ptr < screenheight) {
  963.       for (; i > 0; i--, p += 2)
  964.          if (*p == 0x182)
  965.             break ;
  966.       if (i <= 0) {
  967.          printf("Failed for pointer %d\n", ptr) ;
  968.          error("! couldn't get copper 2") ;
  969.       }
  970.       *p = 0xe6 ;
  971.       copinst[ptr] = p + 1 ;
  972.       i -= 2 ;
  973.       p += 4 ;
  974.       ptr += 2 ;
  975.    }
  976. }
  977. struct View *safeview ;
  978. InstallList() {
  979.    int i ;
  980.  
  981.    ucop=AllocMem((long)sizeof(struct UCopList), MEMF_CHIP|MEMF_CLEAR);
  982.    if (ucop == NULL)
  983.       error("! no copper") ;
  984.    for (i=0; i<screenheight; i += 2) {
  985.       CWAIT(ucop, (long)i, 0L) ;
  986.       CMOVE(ucop, custom.color[1], 0L) ;
  987.       CMOVE(ucop, custom.color[2], 0L) ;
  988.    }
  989.    CEND(ucop);
  990.    Forbid();
  991.    vp->UCopIns=ucop;
  992.    Permit();
  993.    RethinkDisplay();
  994. /*
  995.  *   Now we grab pointers to the instructions for each row.
  996.  *   Note that this is guaranteed to break.  Don't fuck with the
  997.  *   screens while we are grabbing all of these pointers.
  998.  */
  999.    safeview = GfxBase->ActiView ;
  1000.    grabcopper(GfxBase->ActiView->LOFCprList, 0) ;
  1001.    grabcopper(GfxBase->ActiView->SHFCprList, 1) ;
  1002. }
  1003.  
  1004. /*
  1005.  *   This routine checks to make sure we are still the displayed view.  If
  1006.  *   we aren't, we bail out before munging a copper list we may not be
  1007.  *   allowed to touch.  Note that this is *not* how to exit this demo.
  1008.  *   Note also that we should Forbid()/Permit() around our copper
  1009.  *   munging code, but we take our chances instead.
  1010.  */
  1011.  
  1012. checktof() {
  1013.    struct IntuiMessage *msg ;
  1014.    static int msgctr = 4 ;
  1015.  
  1016.    msgctr-- ;
  1017.    if (msgctr <= 0) {
  1018.       if (msg=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
  1019.          if (msg->Class == CLOSEWINDOW ||
  1020.              (msg->Class == VANILLAKEY && (msg->Code == 3 ||
  1021.                                            msg->Code == 27)))
  1022.             cleanup() ;
  1023.          ReplyMsg(msg) ;
  1024.       }
  1025.       msgctr = 4 ;
  1026.    }
  1027.    nextsprite() ;
  1028.    WaitTOF() ;
  1029.    if (GfxBase->ActiView != safeview ||
  1030.        IntuitionBase->FirstScreen != myscreen ||
  1031.        IntuitionBase->ActiveWindow != mywindow)
  1032.       error("!*hey*!  Don't do that!  (I'm no longer in front.)") ;
  1033. }
  1034.  
  1035. long sine = 65536 ;
  1036. long cosine = 0 ;
  1037. long ocos = -10 ;
  1038. static long curcstart = 0 ;
  1039. static int ncrev = 5 ;
  1040.  
  1041. onextcolor()
  1042. {
  1043.    register long acc, delta ;
  1044.    register short **p ;
  1045.    register short *q ;
  1046.    register long t ;
  1047.    register long i ;
  1048.  
  1049.    t = sine + (cosine >> 5) ;
  1050.    ocos = cosine ;
  1051.    cosine -= (sine >> 5)  ;
  1052.    if ((t <= 0 && sine >= 0) ||
  1053.        (t >= 0 && sine <= 0))
  1054.       newcolor(&color1) ;
  1055.    if (cosine <= 0 && ocos >= 0) {
  1056.       ncrev-- ;
  1057.       if (ncrev == 0) {
  1058.          nextf = &nextcolor ;
  1059.          ncrev = 7 ;
  1060.          nextcolor() ;
  1061.       }
  1062.    }
  1063.    sine = t ;
  1064. /*
  1065.  *   Every time around, correct it back into a circle.
  1066.  */
  1067.    if (-500 < sine && sine < 500) {
  1068.       if (cosine < 0)
  1069.           cosine = -65536 ;
  1070.       else
  1071.           cosine = 65536 ;
  1072.       sine = 0 ;
  1073.       delta = 0 ;
  1074.       acc = -203034 ;
  1075.    } else {
  1076.       acc = ((((-(long)screenheight)<<21) + (sine << 4)) / sine
  1077.                                  + (screenheight << 5)) << 5 ;
  1078.       delta = (268435456L + sine) / (sine << 1) ;
  1079.    }
  1080.    pokefast(copinst, screenheight, acc, delta, bytewidthm, color1) ;
  1081. /* for (i=screenheight, p=copinst; i; i--, p++) {
  1082.       q = *p ;
  1083.       acc += delta ;
  1084.       t = (acc >> 11) ;
  1085.       if (((unsigned long)t) >= screenheight) {
  1086.          *q = ((long)emptyrow) ;
  1087.          q[2] = 0 ;
  1088.       } else {
  1089.          *q = bytewidthm[t] ;
  1090.          q[2] = color1[t] ;
  1091.       }
  1092.    } */
  1093. }
  1094. pokefast(cp, sh, acc, del, bw, c1)
  1095. short **cp ;      /* 8 */ /* a3 */
  1096. short sh ;        /* 12 */ /* d0 */ /* d4 */
  1097. long acc, del ;   /* 14, 18 */ /* d1, d2 */
  1098. short *bw, *c1 ;  /* 22, 26 */ /* a0, a5 */
  1099. {
  1100. #asm
  1101.     movem.l    sav37,-(sp)
  1102.     move.l    8(a5),a3
  1103.     move.w    12(a5),d0
  1104.     move.w    d0,d4
  1105.     ext.l    d4
  1106.     lsr.w    #1,d0
  1107.     move.l    14(a5),d1
  1108.     move.l    18(a5),d2
  1109.     move.l    22(a5),a0
  1110.     move.l    26(a5),a5
  1111.     move.l    #11,d5
  1112.     move.w    _emptyrow+2,d6
  1113.     bra    bot37
  1114. top37:
  1115.     move.l    (a3)+,a2
  1116.     add.l    d2,d1
  1117.     move.l    d1,d3
  1118.     lsr.l    d5,d3
  1119.     cmp.l    d3,d4
  1120.     bcc.s    ovr37
  1121.     move.w    d6,(a2)
  1122. ;    clr.w    4(a2)
  1123.     move.l    (a3)+,a2
  1124.     add.l    d2,d1
  1125.     move.l    d1,d3
  1126.     lsr.l    d5,d3
  1127.     cmp.l    d3,d4
  1128.     bcs.s    ovr37c
  1129.     add.w    d3,d3
  1130.     move.w    (a0,d3.w),(a2)
  1131.     move.w    (a5,d3.w),4(a2)
  1132.     dbra    d0,top37
  1133.     bra    don37
  1134. ovr37:
  1135.     add.w    d3,d3
  1136.     move.w    (a0,d3.w),(a2)
  1137.     move.w    (a5,d3.w),4(a2)
  1138. ovr37b:
  1139.     move.l    (a3)+,a2
  1140.     add.l    d2,d1
  1141.     move.l    d1,d3
  1142.     lsr.l    d5,d3
  1143.     cmp.l    d3,d4
  1144.     bcs.s    ovr37c
  1145.     add.w    d3,d3
  1146.     move.w    (a0,d3.w),(a2)
  1147.     move.w    (a5,d3.w),4(a2)
  1148.     dbra    d0,top37
  1149.     bra    don37
  1150. ovr37c:
  1151.     move.w    d6,(a2)
  1152. ;    clr.w    4(a2)
  1153. bot37:
  1154.     dbra    d0,top37
  1155. don37:
  1156.     movem.l    (sp)+,sav37
  1157. sav37    reg    d0-d6/a0-a3/a5
  1158. #endasm
  1159. }
  1160.  
  1161. static int curhpos = -30 ;
  1162.  
  1163. nextcolor()
  1164. {
  1165.    register short **p ;
  1166.    register short *q ;
  1167.    register long acc, div ;
  1168.    register long i, reali ;
  1169.  
  1170.    curhpos -= 4 ;
  1171.    if (curhpos <= 0) {
  1172.       if (curhpos < -10)
  1173.           newcolor(&color2) ;
  1174.       for (i=0; i<screenheight; i++)
  1175.          color1[i] = color2[i] ;
  1176.       newcolor(&color2) ;
  1177.       curhpos = screenheight - 2 ;
  1178.       ncrev-- ;
  1179.       if (ncrev == 0) {
  1180.          nextf = &onextcolor ;
  1181.          ncrev = 5 ;
  1182.          onextcolor() ;
  1183.       }
  1184.    }
  1185.    acc = 0 ;
  1186.    div = screenheight * 65536L / curhpos ;
  1187.    poke2fast(copinst, curhpos, acc, div, bytewidthm, color1) ;
  1188. /* for (i=curhpos, p=copinst; i; i--, p++) {
  1189.       q = *p ;
  1190.       reali = acc >> 16 ;
  1191.       *q = bytewidthm[reali] ;
  1192.       q[2] = color1[reali] ;
  1193.       acc += div ;
  1194.    } */
  1195.    div = screenheight * 65536L / (screenheight - curhpos) ;
  1196.    acc = 0 ;
  1197.    poke2fast(copinst + curhpos, screenheight - curhpos,
  1198.                                          acc, div, bytewidthm, color2) ;
  1199. /* for (i=screenheight-curhpos; i; i--, p++) {
  1200.       q = *p ;
  1201.       reali = acc >> 16 ;
  1202.       *q = bytewidthm[reali] ;
  1203.       q[2] = color2[reali] ;
  1204.       acc += div ;
  1205.    } */
  1206. }
  1207. poke2fast(cp, sh, acc, del, bw, c1)
  1208. short **cp ;      /* 8 */ /* a3 */
  1209. short sh ;        /* 12 */ /* d0 */ /* d4 */
  1210. long acc, del ;   /* 14, 18 */ /* d1, d2 */
  1211. short *bw, *c1 ;  /* 22, 26 */ /* a0, a5 */
  1212. {
  1213. #asm
  1214.     movem.l    sav38,-(sp)
  1215.     move.l    8(a5),a3
  1216.     move.w    12(a5),d0
  1217.     move.w    d0,d4
  1218.     lsr.w    #1,d0
  1219.     ext.l    d4
  1220.     move.l    14(a5),d1
  1221.     move.l    18(a5),d2
  1222.     move.l    22(a5),a0
  1223.     move.l    26(a5),a5
  1224.     bra    bot38
  1225. top38:
  1226.     move.l    (a3)+,a2
  1227.     add.l    d2,d1
  1228.     move.l    d1,d3
  1229.     swap    d3
  1230.     add.w    d3,d3
  1231.     move.w    (a0,d3.w),(a2)
  1232.     move.w    (a5,d3.w),4(a2)
  1233.     move.l    (a3)+,a2
  1234.     add.l    d2,d1
  1235.     move.l    d1,d3
  1236.     swap    d3
  1237.     add.w    d3,d3
  1238.     move.w    (a0,d3.w),(a2)
  1239.     move.w    (a5,d3.w),4(a2)
  1240. bot38:
  1241.     dbra    d0,top38
  1242.     movem.l    (sp)+,sav38
  1243. sav38    reg    d0-d4/a0-a3/a5
  1244. #endasm
  1245. }
  1246.  
  1247. /*
  1248.  *   This routine has to generate a new color.  We grab two random vectors
  1249.  *   in color space and concatenate them and distribute them over the array.
  1250.  *
  1251.  *   This code should be moderately fast; we assume that the random number
  1252.  *   generator generates fairly good numbers.
  1253.  */
  1254. int raininc[6] = { 1, -16, 256, -1, 16, -256 } ;
  1255. newcolor(p)
  1256. short *p ;
  1257. {
  1258.    register int a ;
  1259.    register int i ;
  1260.    int inc ;
  1261.    int s1, s2, s3 ;
  1262.  
  1263.    switch(randm(8)) {
  1264. case 0: /* shaded stripes */
  1265. case 5:
  1266. case 6:
  1267.       inc = randm(2) * 2 - 1 ;
  1268.       a = randm(8192) ;
  1269.       s1 = randm(3) * 4 + 1 ;
  1270.       s2 = randm(2) * 4 + 1 ;
  1271.       if (s1 == s2)
  1272.          s2 = 9 ;
  1273.       s3 = 15 - s1 - s2 ;
  1274.       for (i=screenheight; i; i--, a += inc) {
  1275.          *p++ = ((a >> s1) & 15) +
  1276.                (((a >> s2) & 15) << 4) +
  1277.                (((a >> s3) & 15) << 8) ;
  1278.       }
  1279.       break ;
  1280. case 1: /* solid color */
  1281. case 4:
  1282.       while (1) {
  1283.          a = randm(4096) ;
  1284.          s1 = (a & 15) + ((a >> 4) & 15) + ((a >> 8) & 15) ;
  1285.          if (a > 12)
  1286.             break ;
  1287.       }
  1288.       for (i=screenheight; i; i--)
  1289.          *p++ = a ;
  1290.       break ;
  1291. case 2: /* banded with two colors */
  1292. case 3:
  1293.       while (1) {
  1294.          a = randm(4096) ;
  1295.          s1 = (a & 15) + ((a >> 4) & 15) + ((a >> 8) & 15) ;
  1296.          if (a > 12)
  1297.             break ;
  1298.       }
  1299.       s2 = a ;
  1300.       while (1) {
  1301.          a = randm(4096) ;
  1302.          s1 = (a & 15) + ((a >> 4) & 15) + ((a >> 8) & 15) ;
  1303.          if (a > 12)
  1304.             break ;
  1305.       }
  1306.       s3 = a ;
  1307.       s1 = randm(40) + 10 ;
  1308.       a = s1 ;
  1309.       for (i=screenheight; i; i--) {
  1310.          *p++ = s2 ;
  1311.          a-- ;
  1312.          if (a==0) {
  1313.             a = s2 ;
  1314.             s2 = s3 ;
  1315.             s3 = a ;
  1316.             a = s1 ;
  1317.          }
  1318.       }
  1319.       break ;
  1320. case 7: /* rainbow */
  1321.       a = 240 ;
  1322.       s1 = 0 ;
  1323.       s3 = 1 ;
  1324.       s2 = 15 ;
  1325.       for (i=screenheight; i; i--) {
  1326.          *p++ = a ;
  1327.          a += s3 ;
  1328.          s2-- ;
  1329.          if (s2 == 0) {
  1330.             s2 = 15 ;
  1331.             s1++ ;
  1332.             if (s1 == 6)
  1333.                s1 = 0 ;
  1334.             s3 = raininc[s1] ;
  1335.          }
  1336.       }
  1337.       break ;
  1338.    }
  1339. }
  1340. /*
  1341.  *   Now the code that reads in an IFF file.  We center the file on the
  1342.  *   screen.
  1343.  */
  1344.  
  1345. int compression ;
  1346. long amigaflags ;
  1347. char colormap[2048] ;
  1348. int numcolors, numplanes ;
  1349. int width, height, rowwidth ;
  1350. int masking ;
  1351. FILE *ifffile ;
  1352. struct bmhddata {
  1353.    short w, h, x, y ;
  1354.    unsigned char numplanes, masking, compression, dmy1 ;
  1355.    short transcolor ;
  1356.    unsigned char xas, yas ;
  1357.    short ow, oh ;
  1358. } bmhd ;
  1359.  
  1360. static long getfour()
  1361. {
  1362.    long t ;
  1363.  
  1364.    *((char *)(&t)) = getc(ifffile) ;
  1365.    *((char *)(&t)+1) = getc(ifffile) ;
  1366.    *((char *)(&t)+2) = getc(ifffile) ;
  1367.    *((char *)(&t)+3) = getc(ifffile) ;
  1368.    return(t) ;
  1369. }
  1370.  
  1371. static long getfourup()
  1372. {
  1373.    return((getfour() + 1) & ~1L) ;
  1374. }
  1375. /*
  1376.  *   Starts up an iff file.  Returns `1' on success; 0 on error.
  1377.  */
  1378. static short startiff()
  1379. {
  1380.    register unsigned char *d ;
  1381.    register short i ;
  1382.    register long thislen, ifflen, curform ;
  1383.    short min, max ;
  1384.  
  1385.    if (getfour() != 'FORM')
  1386.       return(-1) ;
  1387.    ifflen = getfour() ;
  1388.    if (getfour() != 'ILBM')
  1389.       return(-1) ;
  1390.    while (1) {
  1391.       curform = getfour() ;
  1392.       switch(curform) {
  1393. case 'CMAP' :
  1394.          thislen = getfourup() ;
  1395.          if (thislen > 2048)
  1396.             return(-1) ;
  1397.          numcolors = thislen / 3 ;
  1398.          d = (unsigned char *)colormap ;
  1399.          while (thislen > 0) {
  1400.             *d++ = getc(ifffile) ;
  1401.             thislen-- ;
  1402.          }
  1403.          break ;
  1404. case 'CAMG' :
  1405.          if (getfour() != 4)
  1406.             return(-1) ;
  1407.          amigaflags = getfour() & (HAM | EXTRA_HALFBRITE) ;
  1408.          break ;
  1409. case 'BMHD' :
  1410.          thislen = getfourup() ;
  1411.          d = (unsigned char *)&bmhd ;
  1412.          i = sizeof(struct bmhddata) ;
  1413.          thislen -= i ;
  1414.          while (i > 0) {
  1415.             *d++ = getc(ifffile) ;
  1416.             i-- ;
  1417.          }
  1418.          while (thislen > 0) {
  1419.             getc(ifffile) ;
  1420.             thislen-- ;
  1421.          }
  1422.          width = bmhd.w ;
  1423.          rowwidth = (bmhd.w + 15) / 16 ;
  1424.          height = bmhd.h ;
  1425.          compression = bmhd.compression ;
  1426.          numplanes = bmhd.numplanes ;
  1427.          if (numplanes < 1 || numplanes > 1)
  1428.             error("! can only handle one-bitplane images") ;
  1429.          masking = bmhd.masking ;
  1430.          break ;
  1431. case 'BODY' :
  1432.          getfour() ;
  1433.          return(0) ;
  1434. case -1:
  1435.          return(-1) ;
  1436. default:
  1437.          thislen = getfourup() ;
  1438.          thislen = (thislen + 1) & ~1 ;
  1439.          while (thislen--)
  1440.             getc(ifffile) ;
  1441.          break ;
  1442.       }
  1443.    }
  1444.    return(-1) ;
  1445. }
  1446. /*
  1447.  *   Here we get one row from the IFF file.
  1448.  */
  1449. static getrow(put)
  1450. register short *put ;
  1451. {
  1452.    register char *rr ;
  1453.    register short lackbits ;
  1454.    register short i ;
  1455.    register short data ;
  1456.  
  1457.    if (compression)
  1458.       lackbits = 0 ;
  1459.    else
  1460.       lackbits = 32767 ;
  1461.    for (i = 2*rowwidth, rr = (char *)put; i; i--) {
  1462.       while (lackbits == 0) {
  1463.          lackbits = (getc(ifffile) & 255) ;
  1464.          if (lackbits > 128) {
  1465.             lackbits = lackbits - 257 ;
  1466.             data = getc(ifffile) ;
  1467.          } else if (lackbits == 128) {
  1468.             lackbits = 0 ;
  1469.          } else
  1470.             lackbits++ ;
  1471.       }
  1472.       if (lackbits > 0) {
  1473.          data = getc(ifffile) ;
  1474.          lackbits-- ;
  1475.       } else {
  1476.          lackbits++ ;
  1477.       }
  1478.       *rr++ = data ;
  1479.    }
  1480. }
  1481. short *bodys[6] ;
  1482.  
  1483. readbody(p)
  1484. register short *p ;
  1485. {
  1486.    register int i, j ;
  1487.    int delta = bytewidth >> 1 ;
  1488.  
  1489.    if (width > screenwidth || height > screenheight) {
  1490.       printf("%d %d %d %d\n", width, screenwidth, height, screenheight) ;
  1491.       error("! IFF file too large for screensize") ;
  1492.    }
  1493.    p += ((screenheight - height) >> 1) * delta + 
  1494.                                 ((screenwidth - width + 16) >> 5) ;
  1495.    for (j=0; j<height; j++) {
  1496.       getrow(p) ;
  1497.       p += delta ;
  1498.    }
  1499. }
  1500.  
  1501. readiff(s, n)
  1502. char *s ;
  1503. int n ;
  1504. {
  1505.    int i ;
  1506.  
  1507.    ifffile = fopen(s, "r") ;
  1508.    if (ifffile==NULL)
  1509.       error("! couldn't open IFF file\n") ;
  1510.    if (startiff())
  1511.       error("! Couldn't start up IFF file\n") ;
  1512.    i = rastport->Mask ;
  1513.    rastport->Mask = 1 << n ;
  1514.    SetRast(rastport, 0L) ;
  1515.    rastport->Mask = i ;
  1516.    readbody(rastport->BitMap->Planes[n]) ;
  1517.    fclose(ifffile) ;
  1518.    ifffile = NULL ;
  1519. }
  1520.  
  1521. /*
  1522.  *   This code loads our font.
  1523.  */
  1524. #define HEIGHT (11)
  1525. long expand[256] ;
  1526. long *final ;
  1527. long fontdat[96*HEIGHT*3] ;
  1528. saytext() {
  1529.    PrintIText(&(myscreen->RastPort), &itext, 0L, 0L) ;
  1530.    WaitBlit() ;
  1531. }
  1532. loadfont() {
  1533.    register int i, b ;
  1534.    register long e ;
  1535.    register unsigned char *p ;
  1536.    int base ;
  1537.    int c ;
  1538.  
  1539.    for (i=0; i<256; i++)
  1540.       for (b=1, e=7; b<256; b <<= 1, e <<= 3)
  1541.          if (i & b)
  1542.             expand[i] |= e ;
  1543.    final = fontdat ;
  1544.    for (base=32; base < 128; base += 16) {
  1545.       p = (unsigned char *)tempbuf ;
  1546.       for (c=base; c < base+16; c++, p++)
  1547.          *p = c ;
  1548.       *p = 0 ;
  1549.       saytext() ;
  1550.       p = (unsigned char *)(rastport->BitMap->Planes[0]) ;
  1551.       for (c=base; c < base+16; c++, p++) {
  1552.          for (i=0; i<HEIGHT; i++) {
  1553.             e = expand[p[i*bytewidth]] ;
  1554.             final[3*i+1] = e ;
  1555.             final[3*i+2] = ~((e ^ (e >> 1)) | (e ^ (e << 1))) ;
  1556.          }
  1557.          final[0] = final[1] ^ (final[1] & ~final[2]) ;
  1558.          for (i=1; i<(HEIGHT-1)*3; i += 3) {
  1559.             e = final[i] ^ final[i+3] ;
  1560.             final[i+2] = final[i+3] ^ (e & final[i+1] & ~final[i+4]) ;
  1561.             final[i+1] = final[i] ^ (e & final[i+4] & ~final[i+1]) ;
  1562.          }
  1563.          final[HEIGHT*3-1] = final[HEIGHT*3-2] ^
  1564.                                   (final[HEIGHT*3-2] & ~final[HEIGHT*3-1]) ;
  1565.          for (i=0; i<HEIGHT*3; i++)
  1566.             final[i] <<= 4 ;
  1567.          final += HEIGHT * 3 ;
  1568.       }
  1569.    }
  1570.    SetAPen(rastport, 0L) ;
  1571.    RectFill(rastport, 0L, 0L, (long)screenwidth-1, 30L) ;
  1572.    SetAPen(rastport, 1L) ;
  1573. }
  1574.  
  1575. /*
  1576.  *   Kludged code to load a sound.
  1577.  */
  1578.  
  1579. short *sounddata ;
  1580. long samrate, len ;
  1581.  
  1582. loadsound() {
  1583.    register long h, *p ;
  1584.  
  1585.    allocchannels() ;
  1586.    ifffile = fopen("crash.snd", "r") ;
  1587.    if (ifffile==0)
  1588.       error("! don't separate me from my sounds (crash.snd).") ;
  1589.    while (1) {
  1590.       h = getfour() ;
  1591.       switch (h) {
  1592. case 'BODY' :
  1593.          getfour() ;
  1594.          break ;
  1595. case 'VHDR' :
  1596.          getfour() ;
  1597.          len = getfour() ;
  1598.          getfour() ;
  1599.          getfour() ;
  1600.          samrate = getfour() >> 16 ;
  1601.          break ;
  1602. case -1:
  1603.          error("! ran off end of sound file before body") ;
  1604. default:
  1605.          break ;
  1606.       }
  1607.       if (h=='BODY')
  1608.          break ;
  1609.    }
  1610.    if (len == 0)
  1611.       error("! no length in sound file") ;
  1612.    sounddata = AllocMem(len, MEMF_CHIP | MEMF_CLEAR) ;
  1613.    if (sounddata == NULL)
  1614.       error("! no memory in sound") ;
  1615.    h = len ;
  1616.    p = (long *)sounddata ;
  1617.    while (h >= 0) {
  1618.       *p++ = getfour() ;
  1619.       h -= 4 ;
  1620.    }
  1621.    fclose(ifffile) ;
  1622.    ifffile = NULL ;
  1623.    playsound() ;
  1624.    freechannels() ;
  1625. }
  1626.  
  1627. UBYTE whichannel[] = { 3, 5, 10, 12 } ;
  1628. struct IOAudio *AudioIOAptr, *AudioIOBptr ;
  1629. struct MsgPort *port ;
  1630. ULONG device = -1 ;
  1631. long clock ;
  1632.  
  1633. allocchannels() {
  1634.    SetFilter() ;
  1635.    clock = ((GfxBase->DisplayFlags & PAL) ? 3546895 : 3579545) ;
  1636.    AudioIOBptr = (struct IOAudio *)AllocMem((long)sizeof(struct IOAudio),
  1637.              MEMF_PUBLIC | MEMF_CLEAR) ;
  1638.    AudioIOAptr = (struct IOAudio *)AllocMem((long)sizeof(struct IOAudio),
  1639.              MEMF_PUBLIC | MEMF_CLEAR) ;
  1640.    port = CreatePort(0L, 0L) ;
  1641.    if (AudioIOBptr == NULL || AudioIOBptr == NULL || port == NULL)
  1642.       error("! no memory") ;
  1643.    AudioIOBptr->ioa_Request.io_Message.mn_ReplyPort = port ;
  1644.    AudioIOBptr->ioa_Request.io_Message.mn_Node.ln_Pri = 0 ;
  1645.    AudioIOBptr->ioa_Request.io_Command = ADCMD_ALLOCATE ;
  1646.    AudioIOBptr->ioa_Request.io_Flags = ADIOF_NOWAIT ;
  1647.    AudioIOBptr->ioa_AllocKey = 0 ;
  1648.    AudioIOBptr->ioa_Data = whichannel ;
  1649.    AudioIOBptr->ioa_Length = 4 ;
  1650.    device = (ULONG)OpenDevice("audio.device", 0L, AudioIOBptr, 0L) ;
  1651.    if (device != 0) {
  1652.       printf("Error returned is %ld\n", device) ;
  1653.       error("! no audio device") ;
  1654.    }
  1655. }
  1656.  
  1657. /*
  1658.  *   We kill the filter; we *need* the high frequencies.
  1659.  */
  1660. freechannels() {
  1661.    if (port) {
  1662.       DeletePort(port) ;
  1663.       port = 0 ;
  1664.    }
  1665.    if (device == 0) {
  1666.       CloseDevice(AudioIOBptr) ;
  1667.       device = -1 ;
  1668.    }
  1669.    if (AudioIOBptr) {
  1670.       FreeMem(AudioIOBptr, (long)sizeof(struct IOAudio)) ;
  1671.       AudioIOBptr = 0 ;
  1672.    }
  1673.    if (AudioIOAptr) {
  1674.       FreeMem(AudioIOAptr, (long)sizeof(struct IOAudio)) ;
  1675.       AudioIOAptr = 0 ;
  1676.    }
  1677.    if (sounddata) {
  1678.       FreeMem(sounddata, len) ;
  1679.       sounddata = 0 ;
  1680.    }
  1681.    RestoreFilter() ;
  1682. }
  1683.  
  1684. int oldbits = -1 ;
  1685.  
  1686. SetFilter() {
  1687.    Disable() ;
  1688.    oldbits = ciaa.ciapra ;
  1689.    ciaa.ciapra |= CIAF_LED ;
  1690.    Enable() ;
  1691. }
  1692.  
  1693. RestoreFilter() {
  1694.    Disable() ;
  1695.    if (!(oldbits & CIAF_LED)) {
  1696.       ciaa.ciapra &= ~CIAF_LED ;
  1697.       oldbits = -1 ;
  1698.    }
  1699.    Enable() ;
  1700. }
  1701.  
  1702. playsound() {
  1703.    AudioIOBptr->ioa_Request.io_Message.mn_ReplyPort = port ;
  1704.    AudioIOBptr->ioa_Request.io_Command = CMD_WRITE ;
  1705.    AudioIOBptr->ioa_Request.io_Flags = ADIOF_PERVOL ;
  1706.    AudioIOBptr->ioa_Data = (UBYTE *)sounddata ;
  1707.    AudioIOBptr->ioa_Length = len ;
  1708.    AudioIOBptr->ioa_Period = clock / samrate ;
  1709.    AudioIOBptr->ioa_Volume = 64 ;
  1710.    AudioIOBptr->ioa_Cycles = 1 ;
  1711.    *AudioIOAptr = *AudioIOBptr ;
  1712.    AudioIOBptr->ioa_Period += 5 ; /* make a slight modification for kicks */
  1713.    AudioIOAptr->ioa_Request.io_Unit = (struct Unit *)
  1714.                          (((long)AudioIOBptr->ioa_Request.io_Unit) & 0x9) ;
  1715.    AudioIOBptr->ioa_Request.io_Unit = (struct Unit *)
  1716.                          (((long)AudioIOBptr->ioa_Request.io_Unit) & 0x6) ;
  1717.    BeginIO(AudioIOBptr) ;
  1718.    BeginIO(AudioIOAptr) ;
  1719.    flashscreen() ;
  1720.    WaitPort(port) ;
  1721.    GetMsg(port) ;
  1722.    WaitPort(port) ;
  1723.    GetMsg(port) ;
  1724.    AudioIOBptr->ioa_Request.io_Unit = (struct Unit *)
  1725.                          (((long)AudioIOBptr->ioa_Request.io_Unit) |
  1726.                           ((long)AudioIOBptr->ioa_Request.io_Unit)) ;
  1727. }
  1728.  
  1729. /*
  1730.  *   This routine flashes our screen bright white for a short time (two
  1731.  *   frames) and then turns the colors on right for normal stuff.
  1732.  */
  1733. flashscreen() {
  1734.    long i ;
  1735.  
  1736.    WaitTOF() ;
  1737.    for (i=0; i<4; i++)
  1738.       SetRGB4(vp, i, 15L, 15L, 15L) ;
  1739.    WaitTOF() ;
  1740.    WaitTOF() ;
  1741.    for (i=0; i<4; i++)
  1742.       SetRGB4(vp, i, 15L, 15L, 0L) ;
  1743.    WaitTOF() ;
  1744.    WaitTOF() ;
  1745.    for (i=0; i<4; i++)
  1746.       SetRGB4(vp, i, 15L, 0L, 0L) ;
  1747.    WaitTOF() ;
  1748.    WaitTOF() ;
  1749.    SetRGB4(vp, 0L, 0L, 0L, 0L) ;
  1750.    SetRGB4(vp, 1L, 4L, 4L, 4L) ;
  1751.    SetRGB4(vp, 2L, 0L, 0L, 0L) ;
  1752.    SetRGB4(vp, 3L, 0L, 0L, 0L) ;
  1753. }
  1754.  
  1755. /*
  1756.  *   Finally we get to use that text.  We roll the credits here, at
  1757.  *   the beginning, while everything is loading.  Too bad we can't make
  1758.  *   the music stop and wait for us!  We try and make things take long
  1759.  *   enough to load all of the music off floppy disks.
  1760.  *
  1761.  *   Of course, we do all of this with copper tricks.
  1762.  *
  1763.  *   We do a lot of `bouncing'---assume everything is perfectly elastic
  1764.  *   and just let them bounce onto the screen.
  1765.  */
  1766. struct billiard {
  1767.    int pos ;
  1768.    int vel ;
  1769.    int ptr ;
  1770.    int color ;
  1771. } balls[12] ;
  1772. #define space 36
  1773. #define realh 33
  1774. #define velocity (randm(3)+2)
  1775. int scrolloff = 0 ;
  1776. rollcredits() {
  1777.    register struct billiard *bbp ;
  1778.    register struct billiard *bp = balls ;
  1779.    register int i, j ;
  1780.    long *p, *q ;
  1781.    short **rp, *rq ;
  1782.    int curiptr = 0 ;
  1783.    FILE *f ;
  1784.    char *pp ;
  1785.    int alive = 0 ;
  1786.    char *done ;
  1787.    extern char *fgets() ;
  1788.  
  1789.    for (i=0, rp=copinst; i<screenheight; i++, rp++)
  1790.      *(*rp) = (long)emptyrow ;
  1791.    f = fopen("TextScript", "r") ;
  1792.    if (f==NULL)
  1793.       error("! don't leave me without a text script (TextScript)") ;
  1794.    while (1) {
  1795.       done = fgets(tempbuf, 100, f) ;
  1796.       if (strlen(tempbuf) > 0)
  1797.          tempbuf[strlen(tempbuf)-1] = 0 ;
  1798.       if (tempbuf[0]) {
  1799.          bp->pos = screenheight ;
  1800.          bp->vel = -velocity ;
  1801.          bp->ptr = curiptr ;
  1802.          bp->color = randm(4096) | 2184 ;
  1803.          bp++ ;
  1804.          alive = 1 ;
  1805.          p = (long *)(((char *)(rastport->BitMap->Planes[1])) +
  1806.             bytewidth * curiptr + 
  1807.             (((screenwidth - 32 * strlen(tempbuf) + 16) >> 4) & ~1)) ;
  1808.          for (pp = tempbuf; *pp; pp++) {
  1809.             q = fontdat + (*pp-32)*HEIGHT*3 ;
  1810.             for (j=0; j<realh; j++)
  1811.                *(long *)(((char *)p) + j * bytewidth) = q[j] ;
  1812.             p++ ;
  1813.          }
  1814.          curiptr += realh ;
  1815.          if (curiptr > screenheight)
  1816.             error("! too many lines") ;
  1817.       } else
  1818.          scrolloff = 1 ;
  1819.       while (1) {
  1820.          for (i=25+randm(25); i; i--) {
  1821.             for (bbp=balls; bbp < bp; bbp++)
  1822.                bbp->pos += bbp->vel ;
  1823.             if (scrolloff < 5 && balls[0].pos < 0) {
  1824.                balls[0].pos = 0 ;
  1825.                balls[0].vel = - balls[0].vel ;
  1826.             }
  1827.             for (bbp=balls; bbp+1 < bp; bbp++) {
  1828.                if (bbp->pos + space > bbp[1].pos) {
  1829.                   j = bbp->vel ;
  1830.                   bbp->vel = bbp[1].vel ;
  1831.                   bbp[1].vel = j ;
  1832.                   bbp[1].pos = bbp->pos + space ;
  1833.                }
  1834.             }
  1835.             if ((bp-1)->pos + space > screenheight && (bp-1)->vel > 0)
  1836.                (bp-1)->vel = -(bp-1)->vel ;
  1837.             checktof() ;
  1838.             alive = fastcop(bp) ;
  1839.          }
  1840.          if (alive == 0)
  1841.             break ;
  1842.          if (scrolloff == 0)
  1843.             break ;
  1844.          scrolloff++ ;
  1845.       }
  1846.       if (!done)
  1847.          break ;
  1848.       if (alive == 0) {
  1849.          bp = balls ;
  1850.          curiptr = 0 ;
  1851.          i = rastport->Mask ;
  1852.          rastport->Mask = 2 ;
  1853.          SetRast(rastport, 0L) ;
  1854.          rastport->Mask = i ;
  1855.          WaitBlit() ;
  1856.       }
  1857.       scrolloff = 0 ;
  1858.    }
  1859.    for (i=0, rp=copinst; i<screenheight; i++, rp++)
  1860.      *(*rp) = (long)emptyrow ;
  1861.    fclose(f) ;
  1862. }
  1863.  
  1864. int fastcop(max)
  1865. struct billiard *max ;
  1866. {
  1867.    register struct billiard *bbp ;
  1868.    register short *rq ;
  1869.    register int j ;
  1870.    register short **rp ;
  1871.    int ret ;
  1872.  
  1873.    bbp = balls ;
  1874.    while (1 - bbp->pos >= realh) {
  1875.       bbp++ ;
  1876.       if (bbp == max)
  1877.          bbp = NULL ;
  1878.    }
  1879.    ret = (bbp != NULL) ;
  1880.    for (j=0, rp=copinst; j<screenheight; j++, rp++) {
  1881.       rq = *rp ;
  1882.       if (bbp == NULL || j < bbp->pos) {
  1883.          *rq = (long)emptyrow ;
  1884. /*       rq[2] = 0L ; */
  1885.       } else {
  1886.          if (bbp->vel < 0)
  1887.             *rq = bytewidthm[bbp->ptr + (j - bbp->pos)] ;
  1888.          else
  1889.             *rq = bytewidthm[bbp->ptr + realh - 1 - (j - bbp->pos)] ;
  1890.          rq[2] = bbp->color ;
  1891.          if (j - bbp->pos >= realh - 1) {
  1892.             bbp++ ;
  1893.             if (bbp == max)
  1894.                bbp = NULL ;
  1895.          }
  1896.       }
  1897.    }
  1898.    return(ret) ;
  1899. }
  1900. /*
  1901.  *   Now we can deal with sprite issues.  (This program just keeps getting
  1902.  *   longer.)  We grab sprites 1 and 2; no real need to grab a matched pair,
  1903.  *   and this (slightly) increases the chances that things will work when
  1904.  *   the pointer is moved all the way to the left.
  1905.  */
  1906. #define NUMPHASES (8)
  1907. #define PI (3.14159265358)
  1908. short *sprts[NUMPHASES][2] ;
  1909. struct SimpleSprite hsprites[2] ;
  1910. int havesprite[2] ;
  1911. double asin(), sqrt() ;
  1912. unsigned char ftab[32][32] ;
  1913. unsigned char fitab[32][32] ;
  1914. initcolor() {
  1915.    int x, y ;
  1916.    float fx, fy ;
  1917.    float rx, ry ;
  1918.    float lat ;
  1919.  
  1920.    for (x=0; x<32; x++) {
  1921.       for (y=0; y<32; y++) {
  1922.          fx = (x - 15.5) / 16.0 ;
  1923.          fy = (y - 15.5) / 16.0 ;
  1924.          rx = 0.9798 * fx + 0.2 * fy ;
  1925.          ry = 0.9798 * fy - 0.2 * fx ;
  1926.          if (rx * rx + ry * ry >= 0.999)
  1927.             ftab[x][y] = 255 ;
  1928.          else {
  1929.             lat = asin(ry) * 4.0 / PI + 8.0 ;
  1930.             fitab[x][y] = ((int)lat) & 1 ;
  1931.             lat = asin(rx / sqrt(1.0 - ry * ry)) * 64.0 / PI + 32.5 ;
  1932.             ftab[x][y] = ((int)lat) ;
  1933.          }
  1934.       }
  1935.    }
  1936. }
  1937. int color(x, y, n)
  1938. int x, y ;
  1939. int n ;
  1940. {
  1941.    int f ;
  1942.    int t ;
  1943.  
  1944.    f = ftab[x][y] ;
  1945.    if (f == 255)
  1946.       return (0) ;
  1947.    else
  1948.       return ((((fitab[x][y]) ^ ((f + n) >> 4)) & 1) ? 1 : 2) ;
  1949. }
  1950.  
  1951. upsprites() {
  1952.    register int i, j, k, m ;
  1953.    register short *p ;
  1954.    register int t ;
  1955.    int n ;
  1956.  
  1957.    initcolor() ;
  1958.    for (i=0; i<2; i++) {
  1959.       if (GetSprite(&(hsprites[i]), i + 1L) == -1)
  1960.          error("! no sprites") ;
  1961.       havesprite[i] = 1 ;
  1962.       hsprites[i].height = 32 ;
  1963.    }
  1964.    for (i=0; i<NUMPHASES; i++) {
  1965.       n = (i << 4) / NUMPHASES ;
  1966.       for (j=0; j<2; j++) {
  1967.          p = (short *)AllocMem(136L, MEMF_CHIP | MEMF_CLEAR) ;
  1968.          if (p)
  1969.             sprts[i][j] = p ;
  1970.          else
  1971.             error("! no sprite memory") ;
  1972.          for (m=0; m<32; m++) {
  1973.             for (k=0; k<16; k++) {
  1974.                t = color(k + (j << 4), m, n) ;
  1975.                if (t)
  1976.                   p[1+t+(m << 1)] |= 1 << (15-k) ;
  1977.             }
  1978.          }
  1979.       }
  1980.    }
  1981. }
  1982.  
  1983. downsprites() {
  1984.    register int i, j ;
  1985.    register short *p ;
  1986.  
  1987.    for (i=0; i<2; i++)
  1988.       if (havesprite[i]) {
  1989.          FreeSprite(i + 1L) ;
  1990.          havesprite[i] = 0 ;
  1991.       }
  1992.    for (i=0; i<NUMPHASES; i++)
  1993.       for (j=0; j<2; j++) {
  1994.          p = sprts[i][j] ;
  1995.          if (p)
  1996.             FreeMem(p, 136L) ;
  1997.       }
  1998.    SetRGB4(vp, 17L, 15L, 0L, 0L) ;
  1999.    SetRGB4(vp, 21L, 15L, 0L, 0L) ;
  2000.    SetRGB4(vp, 18L, 15L, 15L, 15L) ;
  2001.    SetRGB4(vp, 22L, 15L, 15L, 15L) ;
  2002. }
  2003.  
  2004. int hvel = 4 ;
  2005. int xpos = -64 ;
  2006. int ypos = 0 ;
  2007. int vvel = 0 ;
  2008. int vacc = 1 ;
  2009. int phase = 1000 ;
  2010. long parity = 15 ;
  2011. int cc ;
  2012. #define TURNCC (3)
  2013. nextsprite() {
  2014.    register short **ss ;
  2015.  
  2016.    if (onsprites > 0) {
  2017.       onsprites-- ;
  2018.       return ;
  2019.    }
  2020.    if ((xpos += hvel) > screenwidth - 64) {
  2021.       if (onsprites < -200) {
  2022.          if (xpos > screenwidth + 6) {
  2023.             onsprites = 400 ;
  2024.             xpos = -68 ;
  2025.          }
  2026.       } else {
  2027.          xpos = screenwidth - 64 ;
  2028.          hvel = - hvel ;
  2029.          onsprites -= 700 ;
  2030.       }
  2031.    } else if (xpos < 0) {
  2032.       xpos = 0 ;
  2033.       hvel = - hvel ;
  2034.    }
  2035.  
  2036.    if ((ypos += ((vvel += vacc) >> 3)) > screenheight - 64) {
  2037.       ypos = screenheight - 64 ;
  2038.       vvel = - vvel ;
  2039.    } else if (ypos < 0) {
  2040.       ypos = 0 ;
  2041.       vvel = 0 ;
  2042.    }
  2043.    if ((cc--) <= 0) {
  2044.       cc = TURNCC ;
  2045.       phase++ ;
  2046.       if (phase >= NUMPHASES)
  2047.          phase = 0 ;
  2048.       ss = sprts[phase] ;
  2049.       ChangeSprite(vp, &hsprites, ss[0]) ;
  2050.       ChangeSprite(vp, &(hsprites[1]), ss[1]) ;
  2051.       if (phase == 0) {
  2052.          SetRGB4(vp, 17L, 15L, parity, parity) ;
  2053.          SetRGB4(vp, 21L, 15L, parity, parity) ;
  2054.          parity = 15 - parity ;
  2055.          SetRGB4(vp, 18L, 15L, parity, parity) ;
  2056.          SetRGB4(vp, 22L, 15L, parity, parity) ;
  2057.       }
  2058.    }
  2059.    if (hvel > 0) {
  2060.       MoveSprite(vp, &hsprites, (long)xpos, (long)ypos) ;
  2061.       MoveSprite(vp, &(hsprites[1]), 32L + xpos, (long)ypos) ;
  2062.    } else {
  2063.       MoveSprite(vp, &(hsprites[1]), 32L + xpos, (long)ypos) ;
  2064.       MoveSprite(vp, &hsprites, (long)xpos, (long)ypos) ;
  2065.    }
  2066. }
  2067.  
  2068. _wb_parse() {}
  2069.