8

a CHIP-8 emulator
Log | Files | Refs | README

SYZYGY.SRC (21405B)


      1 option binary   ; Let's compile this for a non-HP computer...
      2 align off       ; And let's save some space with even-addresses allowed
      3 
      4 ; From rtrevino@cpocd5.intel.com
      5 ;
      6 ; Several people have requested the source to syzygy, so here it is.
      7 ; Actually it's the listing file.  It would have been posted sooner,
      8 ; but I wanted to add *some* comments at least, etc.  Hopefully whoever
      9 ; sent mail to me will see it.  Anyways, I guess we can all expect to
     10 ; see tons more chip-48 programs posted now, as there is so much interest
     11 ; in source code!   :-)  They are actually quite easy to write.
     12 ; 
     13 ; Roy
     14 ; 
     15 ; PS - has anyone used the shift instructions in chip48?   The documentation
     16 ; does not correlate with the "opcodes".    How do they really work?
     17 
     18      ;
     19      ;   SYZYGY is (c) copyright 1990 by Roy Trevino (RTT)
     20      ;
     21      ;   Noncommercial distribution allowed, provided that this
     22      ;   copyright message is preserved, and any modified versions
     23      ;   are clearly marked as such.
     24      ;
     25      ;   SYZYGY, via CHIP-48, makes use of undocumented low-level features
     26      ;   of the HP48SX calculator, and may or may not cause loss of data,
     27      ;   excessive battery drainage, and/or damage to the calculator
     28      ;   hardware.  The Author takes no responsibility whatsoever for
     29      ;   any damage caused by the use of this program.
     30      ;
     31      ;   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
     32      ;   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     33      ;   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     34      ;   PURPOSE.
     35      ;
     36      ;
     37      ;  Register usage (primary usage, may be others):
     38      ;
     39      ; v0 - scratch
     40      ; v1 - x position of head
     41      ; v2 - y position of head
     42      ; v3 - current direction of head
     43      ; v4 - pointer to segment table entry for head
     44      ; v5 - previous direction of head
     45      ; v6 - x position of tail
     46      ; v7 - y position of tail
     47      ; v8 - direction of tail
     48      ; v9 - pointer to segment table entry for tail
     49      ; va - count of points being added to length
     50      ; vb - x position of target
     51      ; vc - y position of target
     52      ; vd - flags if target is on or off
     53      ; ve - random on time for target
     54      ; vf - carry/borrow/collision detect
     55 
     56 
     57 up        =      #3            ; (9) key for up
     58 down      =      #6            ; (6) key for down
     59 left      =      #7            ; (1) key for left
     60 right     =      #8            ; (2) key for right
     61 
     62      ;
     63      ;  Start of a circular table to track each segment of the syzygy,
     64      ;  which consists of a direction and a length.
     65      ;
     66      ;  The start of the table is at #800 instead of a label at the bottom
     67      ;  of the program (ie.  base:  end) because it seems to run faster
     68      ;  that way.
     69      ;
     70 
     71 base      =      #800          ; base of segment table
     72 
     73 
     74        jp         start
     75 
     76                                  ; copyright notice
     77        dw        #8d8d           ; ->->
     78        dw        #20a9           ; (c)
     79        dw        #3139           ; 19
     80        dw        #3930           ; 90
     81        dw        #2052           ;  R
     82        dw        #5454           ; TT
     83        dw        #208e           ; <-
     84        dw        #8e00           ; <-
     85 start:
     86        call    drawbord
     87        call    drawtitle
     88 waitkp1:
     89        ld      v0,#f           ; wait for (+) (keep border)
     90        sknp    v0
     91        jp        starty
     92        ld      v0,#e           ; wait for (-) (borderless)
     93        sknp    v0
     94        jp        startn
     95        jp        waitkp1
     96 starty:
     97        call    drawtitle        ; erase title (keep border)
     98        jp      initgame
     99 startn:
    100        cls             ; erase everything (borderless)
    101        jp        initgame
    102      ;
    103      ;  initialization routines
    104      ;
    105 initgame:
    106      ;
    107      ;  initial head position near middle of screen
    108      ;
    109        rnd     v1,#1f       ; x-pos = rnd(16,47)
    110        add     v1,#10
    111        rnd     v2,#f        ; y-pos = rnd(8,23)
    112        add     v2,#8
    113        rnd     v3,#3        ; direction = rnd(0,3)
    114        ld      v5,v3           ; last head direction
    115      ;
    116      ;  compute initial tail position
    117      ;
    118        ld      v6,v1           ; start out same as head
    119        ld      v7,v2
    120        ld      v8,v3           ; tail direction
    121 
    122        sne     v8,#0        ; up
    123        add     v7,#1
    124        sne     v8,#1        ; down
    125        add     v7,#ff
    126        sne     v8,#2        ; left
    127        add     v6,#1
    128        sne     v8,#3        ; right
    129        add     v6,#ff
    130      ;
    131      ;  draw initial syzygy, save initial segment to table
    132      ;
    133        ld      i,dot
    134        drw     v1,v2,#1          ; draw head
    135        drw     v6,v7,#1          ; draw tail
    136 
    137        ld      v4,#f0          ; init ptr to head vector
    138        ld      v9,#f1          ; init ptr to tail vector
    139 
    140        ld      i,base         ; save direction
    141        add     i,v4
    142        ld      v0,v3
    143        ld      [i],v0
    144        add     v4,#1        ; increment head ptr
    145        ld      i,base         ; save segment count
    146        add     i,v4
    147        ld      v0,#1
    148        ld      [i],v0
    149 
    150      ;
    151      ;  compute coordinates and value of first target
    152      ; plus set up flag and time until target
    153      ;
    154        call    rndtarg
    155 
    156 
    157        ld      va,#0           ; additional length
    158 
    159      ;
    160      ; initial addition to syzygy for test purposes
    161      ;
    162        add     va,#0
    163      ;
    164      ;  main loop begins here
    165      ;
    166 loop:
    167        ld      v0,dt           ; check if a target is due
    168        se      v0,#0
    169        jp      endtarg
    170        se      vd,#0
    171        jp      targoff
    172 
    173        ld      v0,#0           ; draw target
    174        ld      f,v0
    175        drw     vb,vc,#5
    176 
    177        se      vf,#1           ; if on body, erase immediately
    178        jp      targon
    179        drw     vb,vc,#5
    180        call    rndtarg          ; set up new target
    181        ld      dt,v0           ; no delay though
    182        jp      endtarg        ; process at least one move
    183 
    184 targon:
    185        ld      dt,ve           ; set up on-time
    186        ld      vd,#1           ; set flag to denote on
    187        ld      ve,#0           ; number of points unless hit
    188        jp      endtarg
    189 
    190 targoff:
    191        ld      v0,ve           ; erase old target
    192        ld      f,v0
    193        drw     vb,vc,#5
    194 
    195        call    rndtarg          ; set up new target
    196 
    197 endtarg:
    198        ld      v0,up          ; check for user input
    199        sknp    v0
    200        ld      v3,#0           ; new direction
    201 
    202        ld      v0,down
    203        sknp    v0
    204        ld      v3,#1
    205 
    206        ld      v0,left
    207        sknp    v0
    208        ld      v3,#2
    209 
    210        ld      v0,right
    211        sknp    v0
    212        ld      v3,#3
    213      ;
    214      ;  compute next head position
    215      ;
    216        sne     v3,#0        ; up
    217        add     v2,#ff
    218        sne     v3,#1        ; down
    219        add     v2,#1
    220        sne     v3,#2        ; left
    221        add     v1,#ff
    222        sne     v3,#3        ; right
    223        add     v1,#1
    224      ;
    225      ;  draw next head position
    226      ;
    227        ld      i,dot
    228        drw     v1,v2,#1
    229      ;
    230      ;  check for collision
    231      ;
    232        se      vf,#1
    233        jp      chkhead
    234      ;
    235      ;  if collision is due to target, add points (else die)
    236      ; this also means no doubling back on self
    237      ;
    238        se      vd,#1           ; check if target is even on
    239        jp      endgame
    240 
    241        ld      v0,#3f          ; mask off extra x and y bits
    242        and     v1,v0
    243        ld      v0,#1f
    244        and     v2,v0
    245 
    246        ld      v0,vb           ; check if < target on left
    247        subn    v0,v1
    248        se      vf,#1
    249        jp      endgame
    250 
    251        ld      v0,vb           ; check if > target on right
    252        add     v0,#3
    253        sub     v0,v1
    254        se      vf,#1
    255        jp      endgame
    256 
    257        ld      v0,vc           ; check if < target on top
    258        subn    v0,v2
    259        se      vf,#1
    260        jp      endgame
    261 
    262        ld      v0,vc           ; check if > target on bottom
    263        add     v0,#4
    264        sub     v0,v2
    265        se      vf,#1
    266        jp      endgame
    267      ;
    268      ;  if made it this far, add points, erase target, etc
    269      ;
    270        ld      v0,#4           ; beep (actually, a "bip")
    271        ld      st,v0
    272 
    273        rnd     ve,#7        ; award rnd(2,9) points
    274        add     ve,#2        ;
    275        add     va,ve        ; add points
    276 
    277        ld      i,dot          ; temporarily erase head
    278        drw     v1,v2,#1
    279        ld      v0,#0           ; erase target
    280        ld      f,v0
    281        drw     vb,vc,#5
    282        ld      v0,ve           ; draw points instead
    283        ld      f,v0
    284        drw     vb,vc,#5
    285 
    286        ld      v0,#30          ; delay for a while
    287        ld      dt,v0
    288 targwait:
    289        ld      v0,dt
    290        se      v0,#0
    291        jp      targwait
    292 
    293        ld      i,dot
    294        drw     v1,v2,#1          ; redraw head
    295      ;
    296      ;  if direction changed, create a new segment record
    297      ;
    298 chkhead:
    299        sne     v3,v5
    300        jp      conthead
    301 
    302        add     v4,#1        ; new segment record
    303        ld      i,base
    304        add     i,v4
    305        ld      v0,v3           ; save direction
    306        ld      [i],v0
    307        add     v4,#1        ; point to counter
    308        ld      i,base       ; initialize segment count to
    309        add     i,v4
    310        ld      v0,#0
    311        ld      [i],v0
    312 
    313        ld      v5,v3           ; reset previous direction
    314 
    315 conthead:
    316        ld      i,base       ; simply add to current record
    317        add     i,v4
    318        ld      v0,[i]
    319        add     v0,#1        ; increment head count
    320        ld      [i],v0
    321      ;
    322      ;  don't erase tail if adding points to length
    323      ;
    324        sne     va,#0
    325        jp      contpts        ; if pts = 0, continue normally
    326 
    327        ld      v0,#c           ; delay just a little to compensate
    328 delhead:
    329        add     v0,#ff
    330        se      v0,#0
    331        jp      delhead
    332 
    333        add     va,#ff       ; decrement and loop
    334        jp      loop
    335 
    336 contpts:
    337      ;
    338      ;  erase last tail position
    339      ;
    340        ld      i,dot
    341        drw     v6,v7,#1
    342 
    343      ;
    344      ;  compute next tail position
    345      ;
    346        sne     v8,#0        ; up
    347        add     v7,#ff
    348        sne     v8,#1        ; down
    349        add     v7,#1
    350        sne     v8,#2        ; left
    351        add     v6,#ff
    352        sne     v8,#3        ; right
    353        add     v6,#1
    354 
    355        ld      i,base       ; get tail segment record
    356        add     i,v9
    357        ld      v0,[i]
    358        add     v0,#ff       ; decrement tail count
    359        ld      [i],v0          ; save
    360        se      v0,#0           ; if zero, get new record
    361        jp      loop
    362 
    363        add     v9,#1        ; new segment record
    364        ld      i,base       ; get new direction
    365        add     i,v9
    366        ld      v0,[i]
    367        ld      v8,v0
    368        add     v9,#1        ; point to new count
    369      ;
    370      ;  end of main loop
    371      ;
    372        jp      loop
    373      ;
    374      ;  endgame routines
    375      ;
    376 endgame:
    377        ld      v0,#d           ; beep
    378        ld      st,v0
    379 
    380        ld      v0,#b           ; wait for (space) keypress
    381 endkp:
    382        skp     v0
    383        jp      endkp
    384      ;
    385      ;  finish up tail to count points: digits are in vd:vc:vb format
    386      ;  note that it is theoretically possible to get 64*32=2048 points,
    387      ;  while three digits will only hold 999.  Unlikely but possible.
    388      ;
    389        ld      vb,#1           ; one's digit
    390        ld      vc,#0           ; ten's digit
    391        ld      vd,#0           ; hundred's digit
    392 
    393 endtail:
    394      ;
    395      ;  increment score
    396      ;
    397        add     vb,#1
    398        se      vb,#a
    399        jp      endtailcont
    400        ld      vb,#0
    401        add     vc,#1
    402        se      vc,#a
    403        jp      endtailcont
    404        ld      vc,#0
    405        add     vd,#1
    406      ;
    407      ;  compute next tail position to add up score
    408      ;
    409 endtailcont:
    410        ld      i,dot          ; erase last tail position
    411        drw     v6,v7,#1
    412 
    413        sne     v8,#0        ; up
    414        add     v7,#ff
    415        sne     v8,#1        ; down
    416        add     v7,#1
    417        sne     v8,#2        ; left
    418        add     v6,#ff
    419        sne     v8,#3        ; right
    420        add     v6,#1
    421 
    422        ld      i,base       ; get tail segment record
    423        add     i,v9
    424        ld      v0,[i]
    425        add     v0,#ff       ; decrement tail count
    426        ld      [i],v0          ; save
    427        se      v0,#0           ; if zero, get new record
    428        jp      endtail
    429 
    430        sne     v9,v4        ; done when pointers are equal
    431        jp      drawscore
    432 
    433        add     v9,#1        ; new segment record
    434        ld      i,base       ; get new direction
    435        add     i,v9
    436        ld      v0,[i]
    437        ld      v8,v0
    438        add     v9,#1        ; point to new count
    439        jp      endtail
    440      ;
    441      ;  draw score
    442      ;
    443 drawscore:
    444        cls
    445        ld      v6,#11          ; draw border
    446        ld      v7,#9
    447        ld      v8,#2f
    448        ld      v9,#17
    449        ld      i,vbar
    450        drw     v6,v7,#e
    451        drw     v8,v7,#e
    452        add     v7,#ff
    453        ld      i,hbar
    454        drw     v6,v7,#1
    455        drw     v6,v9,#1
    456        add     v6,#8
    457        drw     v6,v7,#1
    458        drw     v6,v9,#1
    459        add     v6,#8
    460        drw     v6,v7,#1
    461        drw     v6,v9,#1
    462        add     v6,#8
    463        ld      i,hbar2
    464        drw     v6,v7,#1
    465        drw     v6,v9,#1
    466 
    467        ld      i,sc           ; show score (not high score yet)
    468        ld      v6,#13
    469        ld      v7,#11
    470        call    showscore
    471      ;
    472      ;  figure out if it's the high score, save it if it is
    473      ;
    474        ld      i,high_score         ; recover old high score into v3v2v1
    475        ld      v3,[i]
    476 
    477        sne     v3,vd        ; if =, check next digit
    478        jp      conthigh1
    479        ld      v0,v3           ; if borrow, it's a new high score!
    480        sub     v0,vd
    481        se      vf,#1
    482        jp      savehigh
    483        jp      drawhigh
    484 
    485 conthigh1:
    486        sne     v2,vc        ; etc. as above for other digits
    487        jp      conthigh2
    488        ld      v0,v2
    489        sub     v0,vc
    490        se      vf,#1
    491        jp      savehigh
    492        jp      drawhigh
    493 
    494 conthigh2:
    495        ld      v0,v1
    496        sub     v0,vb
    497        se      vf,#0
    498        jp      drawhigh
    499 
    500 savehigh:
    501        ld      i,high_score
    502        ld      v3,vd           ; save new high score
    503        ld      v2,vc
    504        ld      v1,vb
    505        ld      [i],v3
    506      ;
    507      ;  draw the high score
    508      ;
    509 drawhigh:
    510        ld      i,high_score
    511        ld      v3,[i]
    512        ld      v6,#13
    513        add     v7,#f9
    514        ld      vd,v3
    515        ld      vc,v2
    516        ld      vb,v1
    517        ld      i,hi
    518        call    showscore
    519      ;
    520      ;  random memory wasting stuff goes here
    521      ;
    522 waitkp2:
    523 
    524        rnd     v1,#3f       ; get random position
    525        rnd     v2,#1f
    526 
    527        ld      v0,#d           ; check left
    528        sub     v0,v1
    529        se      vf,#0
    530        jp      drawrand
    531 
    532        ld      v0,#30          ; check right
    533        subn    v0,v1
    534        se      vf,#0
    535        jp      drawrand
    536 
    537        ld      v0,#3           ; check top
    538        sub     v0,v2
    539        se      vf,#0
    540        jp      drawrand
    541 
    542        ld      v0,#18          ; check bottom
    543        subn    v0,v2
    544        se      vf,#0
    545        jp      drawrand
    546        jp      chkkp2
    547 
    548 drawrand:
    549        rnd     v3,#0f       ; draw random number
    550        ld      f,v3
    551        drw     v1,v2,#5
    552 
    553 chkkp2:
    554        ld      v0,#f           ; check for keypress
    555        sknp    v0
    556        jp      conty
    557        ld      v0,#e
    558        sknp    v0
    559        jp      contn
    560        jp      waitkp2
    561 
    562 conty:
    563        cls
    564        call    drawbord
    565        jp      initgame
    566 contn:
    567        cls
    568        jp      initgame
    569      ;
    570      ;  function showscore:
    571      ; digits in vd:vc:vb, descriptor in i, initial coords in v6,v7
    572      ;
    573 showscore:
    574        drw     v6,v7,#5
    575        ld      i,col
    576        add     v6,#2
    577        drw     v6,v7,#4
    578        ld      f,vd
    579        add     v6,#a
    580        drw     v6,v7,#5
    581        ld      f,vc
    582        add     v6,#5
    583        drw     v6,v7,#5
    584        ld      f,vb
    585        add     v6,#5
    586        drw     v6,v7,#5
    587 
    588        ret
    589      ;
    590      ;  function drawbord:
    591      ; draw border, try to do it fast
    592      ;
    593 drawbord:
    594        ld      i,hbar
    595        ld      v1,#0           ; left
    596        ld      v2,#0           ; right
    597        ld      v6,#1f          ; lower
    598 horiz1:
    599        drw     v1,v2,#1          ; draw x,0
    600        drw     v1,v6,#1          ; draw x,31
    601        add     v1,#8
    602        se      v1,#40          ; same as 0
    603        jp      horiz1
    604 
    605        ld      i,vbar
    606        ld      v2,#1
    607        ld      v5,#3f
    608        drw     v1,v2,#f
    609        drw     v5,v2,#f
    610        add     v2,#f
    611        drw     v1,v2,#f
    612        drw     v5,v2,#f
    613 
    614        ret
    615      ;
    616      ;  function drawtitle:  draws game title
    617      ;
    618 drawtitle:
    619        ld      v1,#c
    620        ld      v2,#7
    621        ld      i,Title_s
    622        drw     v1,v2,#a
    623        ld      i,Title_y
    624        add     v1,#6
    625        drw     v1,v2,#a
    626        ld      i,Title_z
    627        add     v1,#6
    628        drw     v1,v2,#a
    629        ld      i,Title_y
    630        add     v1,#6
    631        drw     v1,v2,#a
    632        ld      i,Title_g
    633        add     v1,#6
    634        drw     v1,v2,#a
    635        ld      i,Title_y
    636        add     v1,#6
    637        drw     v1,v2,#a
    638 
    639        ld      v1,#e
    640        ld      v2,#18
    641        ld      i,Title_v
    642        drw     v1,v2,#3
    643        ld      i,vers
    644        add     v1,#8
    645        add     v2,#ff
    646        drw     v1,v2,#4
    647        add     v1,#9
    648        add     v2,#fe
    649        ld      i,Title_r
    650        drw     v1,v2,#6
    651        add     v1,#6
    652        add     v2,#1
    653        ld      i,Title_tt
    654        drw     v1,v2,#5
    655 
    656        ret
    657      ;
    658      ;  function rndtarg:
    659      ; returns coords as (vb,vc)
    660      ; 0 in vd
    661      ; time until target in dt
    662      ; on-time value ve
    663      ;
    664 rndtarg:
    665      ;
    666      ; x-pos = rnd(1,59)
    667      ;
    668        ld      vd,#c5          ; -#3b (-59d)
    669 rndx:  rnd     vb,#3f        ; rnd (0,63)
    670        ld      ve,vb
    671        add     ve,vd        ; check if > 58
    672        sne     vf,#1
    673        jp      rndx           ; try again if too big
    674 
    675        add     vb,#1
    676      ;
    677      ; y-pos = rnd(1,26)
    678      ;
    679 
    680        ld      vd,#e6          ; -#1a (-26d)
    681 rndy:  rnd     vc,#1f
    682        ld      ve,vc
    683        add     ve,vd
    684        sne     vf,#1
    685        jp      rndy
    686        add     vc,#1
    687        ld      vd,#0        ; flag marking new target
    688        rnd     ve,#3f       ; random off delay (64 - 127)
    689        add     ve,#40
    690        ld      dt,ve
    691        rnd     ve,#3f       ; random on delay (64 - 127)
    692        add     ve,#40
    693        ret
    694 
    695 dot:   dw        #8000           ; dot for syzygy
    696 hbar:  dw        #ff00           ; horizontal border segment
    697 hbar2: dw        #fe00
    698 vbar:  dw        #8080           ; vertical border segment
    699        dw        #8080
    700        dw        #8080
    701        dw        #8080
    702        dw        #8080
    703        dw        #8080
    704        dw        #8080
    705        dw        #8080
    706      ;
    707      ;  True memory wasting stuff goes here (but why not?)
    708      ;
    709 Title_s:           ; s character
    710        db   $...11111
    711        db   $...1....
    712        db   $...1....
    713        db   $...1....
    714        db   $...11111
    715        db   $.......1
    716        db   $.......1
    717        db   $.......1
    718        db   $.......1
    719        db   $...11111
    720 
    721 Title_y:           ; y character
    722        db   $...1...1
    723        db   $...1...1
    724        db   $...1...1
    725        db   $...1...1
    726        db   $...11111
    727        db   $.....1..
    728        db   $.....1..
    729        db   $.....1..
    730        db   $.....1..
    731        db   $.....1..
    732 
    733 Title_z:           ; z character
    734        db   $...11111
    735        db   $.......1
    736        db   $......1.
    737        db   $......1.
    738        db   $.....1..
    739        db   $.....1..
    740        db   $....1...
    741        db   $....1...
    742        db   $...1....
    743        db   $...11111
    744 
    745 Title_g:           ; g character
    746        db   $...11111
    747        db   $...1...1
    748        db   $...1....
    749        db   $...1....
    750        db   $...1....
    751        db   $...1..11
    752        db   $...1...1
    753        db   $...1...1
    754        db   $...1...1
    755        db   $...11111
    756 
    757 Title_v:           ; v character for version
    758        db   $.....1.1
    759        db   $.....1.1
    760        db   $......1.
    761        db   $........
    762 
    763 vers:           ; version number characters
    764        db   $.111...1
    765        db   $.1.1...1
    766        db   $.1.1...1
    767        db   $.111.1.1
    768 
    769 
    770 Title_r:           ; R character for signature
    771        db   $....11..
    772        db   $...1..1.
    773        db   $...1111.
    774        db   $...1.1..
    775        db   $...1..1.
    776        db   $....1..1
    777 
    778 Title_tt:           ; tt characters for signature
    779        db   $...1.1..
    780        db   $..11111.
    781        db   $...1.1.1
    782        db   $...1.1.1
    783        db   $..1.1.1.
    784        db   $........
    785 
    786 
    787 sc:           ; sc characters for score
    788        db   $.111.111
    789        db   $.1...1..
    790        db   $..1..1..
    791        db   $...1.1..
    792        db   $.111.111
    793        db   $........
    794 
    795 hi:           ; hi character for high score
    796        db   $.1.1.111
    797        db   $.1.1..1.
    798        db   $.111..1.
    799        db   $.1.1..1.
    800        db   $.1.1.111
    801        db   $........
    802 
    803 col:   dw        #0001           ; : character for scores
    804        dw        #0001
    805 
    806 high_score:
    807        dw        #0000           ; high score storage
    808        dw        #0000