Prince-of-Persia-Apple-II

A running-jumping-swordfighting game Jordan Mechner made on the Apple II from 1985-89
Log | Files | Refs | README | LICENSE

CTRLSUBS.S (28089B)


      1 * ctrlsubs
      2 org = $d000
      3  tr on
      4  lst off
      5 *-------------------------------
      6 *
      7 *  PRINCE OF PERSIA
      8 *  Copyright 1989 Jordan Mechner
      9 *
     10 *-------------------------------
     11 *
     12 *   Misc. subroutines relating to character control & movement
     13 *
     14 *-------------------------------
     15  org org
     16 
     17  jmp GETFRAME
     18  jmp GETSEQ
     19  jmp GETBASEX
     20  jmp GETBLOCKX
     21  jmp GETBLOCKXP
     22 
     23  jmp GETBLOCKY
     24  jmp GETBLOCKEJ
     25  jmp ADDCHARX
     26  jmp GETDIST
     27  jmp GETDIST1
     28 
     29  jmp GETABOVEBEH
     30  jmp RDBLOCK
     31  jmp RDBLOCK1
     32  jmp SETUPSWORD
     33  jmp GETSCRNS
     34 
     35  jmp ADDGUARDOBJ
     36  jmp OPJUMPSEQ
     37  jmp GETEDGES
     38  jmp INDEXCHAR
     39  jmp QUICKFG
     40 
     41  jmp CROPCHAR
     42  jmp GETLEFT
     43  jmp GETRIGHT
     44  jmp GETUP
     45  jmp GETDOWN
     46 
     47  jmp CMPSPACE
     48  jmp CMPBARR
     49  jmp ADDKIDOBJ
     50  jmp ADDSHADOBJ
     51  jmp ADDREFLOBJ
     52 
     53  jmp LOADKID
     54  jmp LOADSHAD
     55  jmp SAVEKID
     56  jmp SAVESHAD
     57  jmp SETUPCHAR
     58 
     59  jmp GETFRAMEINFO
     60  jmp INDEXBLOCK
     61  jmp MARKRED
     62  jmp MARKFRED
     63  jmp MARKWIPE
     64 
     65  jmp MARKMOVE
     66  jmp MARKFLOOR
     67  jmp UNINDEX
     68  jmp QUICKFLOOR
     69  jmp UNEVENFLOOR
     70 
     71  jmp MARKHALF
     72  jmp ADDSWORDOBJ
     73  jmp GETBLOCKYP
     74  jmp CHECKLEDGE
     75  jmp GET2INFRONT
     76 
     77  jmp CHECKSPIKES
     78  jmp RECHARGEMETER
     79  jmp ADDFCHARX
     80  jmp FACEDX
     81  jmp JUMPSEQ
     82 
     83  jmp GETBASEBLOCK
     84  jmp LOADKIDWOP
     85  jmp SAVEKIDWOP
     86  jmp GETOPDIST
     87  jmp LOADSHADWOP
     88 
     89  jmp SAVESHADWOP
     90  jmp BOOSTMETER
     91  jmp GETUNDERFT
     92  jmp GETINFRONT
     93  jmp GETBEHIND
     94 
     95  jmp GETABOVE
     96  jmp GETABOVEINF
     97  jmp CMPWALL
     98 
     99 *-------------------------------
    100  lst
    101  put eq
    102  lst
    103  put gameeq
    104  lst
    105  put movedata
    106  lst
    107  put seqdata
    108  lst
    109  put soundnames
    110  lst off
    111 
    112 *-------------------------------
    113  dum locals
    114 
    115 tempright ds 1
    116 ztemp ds 2
    117 tempstate ds 1
    118 ]cutdir ds 1
    119 
    120  dend
    121 
    122 *-------------------------------
    123 *  Misc. data
    124 
    125 plus1 db -1,1
    126 minus1 db 1,-1
    127 
    128 maxmaxstr = 10 ;strength meter maximum
    129 
    130 thinner = 3
    131 
    132 *-------------------------------
    133 *
    134 *  R E A D   B L O C K
    135 *
    136 *  In:  A = screen #
    137 *       X = block x (0-9 onscreen)
    138 *       Y = block y (0-2 onscreen)
    139 *
    140 *  Out: A,X = objid
    141 *       Y = block # (0-29)
    142 *       BlueType, BlueSpec set
    143 *       tempscrn,tempblockx,tempblocky = onscreen block coords
    144 *
    145 *  - Offscreen block values are traced to their home screen
    146 *  - Screen 0 is treated as a solid mass
    147 *
    148 *-------------------------------
    149 RDBLOCK
    150  sta tempscrn
    151  stx tempblockx
    152  sty tempblocky
    153 
    154 RDBLOCK1
    155  jsr handler ;handle offscreen references
    156 
    157  lda tempscrn
    158  beq :nullscrn ;screen 0
    159  jsr calcblue ;returns BlueType/Spec
    160 
    161  ldy tempblocky
    162  lda Mult10,y
    163  clc
    164  adc tempblockx
    165  tay
    166  lda (BlueType),y
    167  and #idmask
    168  tax ;return result in X & A
    169  rts
    170 
    171 :nullscrn lda #block
    172  tax
    173  rts
    174 
    175 *-------------------------------
    176 *  Handle offscreen block references (recursive)
    177 
    178 handler lda tempblockx
    179  bpl :1
    180  jsr offleft
    181  jmp handler
    182 
    183 :1 cmp #10
    184  bcc :2
    185  jsr offrt
    186  jmp handler
    187 
    188 :2 lda tempblocky
    189  bpl :3
    190  jsr offtop
    191  jmp handler
    192 
    193 :3 cmp #3
    194  bcc :rts
    195  jsr offbot
    196  jmp handler
    197 
    198 :rts rts
    199 
    200 offtop clc
    201  adc #3
    202  sta tempblocky
    203 
    204  lda tempscrn
    205  jsr GETUP
    206  sta tempscrn
    207  rts
    208 
    209 offbot sec
    210  sbc #3
    211  sta tempblocky
    212 
    213  lda tempscrn
    214  jsr GETDOWN
    215  sta tempscrn
    216  rts
    217 
    218 offleft clc
    219  adc #10
    220  sta tempblockx
    221 
    222  lda tempscrn
    223  jsr GETLEFT
    224  sta tempscrn
    225  rts
    226 
    227 offrt sec
    228  sbc #10
    229  sta tempblockx
    230 
    231  lda tempscrn
    232  jsr GETRIGHT
    233  sta tempscrn
    234 ]rts rts
    235 
    236 *-------------------------------
    237 *
    238 *  Get adjacent screen numbers
    239 *
    240 *  In:  A = original screen #
    241 *  Out: A = adjacent screen #
    242 *
    243 *-------------------------------
    244 GETLEFT
    245  beq ]rts
    246  asl
    247  asl
    248  tax
    249  lda MAP-4,x
    250 ]rts rts
    251 
    252 GETRIGHT
    253  beq ]rts
    254  asl
    255  asl
    256  tax
    257  lda MAP-3,x
    258  rts
    259 
    260 GETUP
    261  beq ]rts
    262  asl
    263  asl
    264  tax
    265  lda MAP-2,x
    266  rts
    267 
    268 GETDOWN
    269  beq ]rts
    270  asl
    271  asl
    272  tax
    273  lda MAP-1,x
    274  rts
    275 
    276 *-------------------------------
    277 *
    278 *  G E T   S C R E E N S
    279 *
    280 *  Get VisScrn's 8 surrounding screens from map
    281 *  (Store in scrnAbove, scrnBelow, etc.)
    282 *
    283 *-------------------------------
    284 GETSCRNS
    285  lda VisScrn
    286  jsr GETLEFT
    287  sta scrnLeft
    288 
    289  lda VisScrn
    290  jsr GETRIGHT
    291  sta scrnRight
    292 
    293  lda VisScrn
    294  jsr GETUP
    295  sta scrnAbove
    296 
    297  lda VisScrn
    298  jsr GETDOWN
    299  sta scrnBelow
    300 
    301 * and diagonals
    302 
    303  lda scrnBelow
    304  jsr GETLEFT
    305  sta scrnBelowL
    306 
    307  lda scrnBelow
    308  jsr GETRIGHT
    309  sta scrnBelowR
    310 
    311  lda scrnAbove
    312  jsr GETLEFT
    313  sta scrnAboveL
    314 
    315  lda scrnAbove
    316  jsr GETRIGHT
    317  sta scrnAboveR
    318 ]rts rts
    319 
    320 *-------------------------------
    321 *
    322 *  G E T   B A S E   X
    323 *
    324 *  In: Char data; frame data
    325 *
    326 *  Out: A = character's base X-coord
    327 *
    328 *-------------------------------
    329 GETBASEX
    330  lda Fcheck
    331  and #Ffootmark
    332   ;# pixels to count in from left edge of image
    333  eor #$ff
    334  clc
    335  adc #1 ;- Fcheck
    336 
    337  clc
    338  adc Fdx ;Fdx (+ = fwd, - = bkwd)
    339 
    340  jmp ADDCHARX ;Add to CharX in direction char is facing
    341 
    342 *-------------------------------
    343 *
    344 *  Add A to CharX in direction char is facing
    345 *
    346 *  In: A = # pixels to add (+ = fwd, - = bkwd)
    347 *      CharX = original char X-coord
    348 *      CharFace = direction char is facing
    349 *
    350 *  Out: A = new char X-coord
    351 *
    352 *-------------------------------
    353 ADDCHARX
    354  bit CharFace ;-1 = left (normal)
    355  bpl :right ;0 = right (mirrored)
    356 
    357  eor #$ff
    358  clc
    359  adc #1 ;A := -A
    360 
    361 :right clc
    362  adc CharX
    363  rts
    364 
    365 *-------------------------------
    366 *
    367 * Add A to FCharX
    368 * (A range: -127 to 127)
    369 *
    370 * In: A; FChar data
    371 * Out: FCharX
    372 *
    373 *-------------------------------
    374 ADDFCHARX
    375  sta ztemp
    376  bpl :1 ;hibit clr
    377 
    378  lda #0
    379  sec
    380  sbc ztemp
    381  sta ztemp ;make it posititve
    382 
    383  lda #$ff ;hibit set
    384 :1 eor FCharFace
    385  bmi :left
    386 
    387  lda ztemp
    388  clc
    389  adc FCharX
    390  sta FCharX
    391 
    392  lda FCharX+1
    393  adc #0
    394  sta FCharX+1
    395  rts
    396 
    397 :left lda FCharX
    398  sec
    399  sbc ztemp
    400  sta FCharX
    401 
    402  lda FCharX+1
    403  sbc #0
    404  sta FCharX+1
    405  rts
    406 
    407 *-------------------------------
    408 *
    409 * In: CharFace,CharBlockX,CharBlockY,CharScrn
    410 *
    411 * Out: Results of RDBLOCK for block underfoot/in front/etc.
    412 *
    413 *-------------------------------
    414 GETUNDERFT
    415  ldx CharBlockX
    416  ldy CharBlockY
    417  lda CharScrn
    418  jmp RDBLOCK
    419 
    420 GETINFRONT
    421  ldx CharFace
    422  inx
    423  lda CharBlockX
    424  clc
    425  adc plus1,x
    426  sta infrontx
    427  tax
    428 
    429  ldy CharBlockY
    430  lda CharScrn
    431  jmp RDBLOCK
    432 
    433 GET2INFRONT
    434  ldx CharFace
    435  inx
    436  lda CharBlockX
    437  clc
    438  adc plus1,x
    439  clc
    440  adc plus1,x
    441  tax
    442 
    443  ldy CharBlockY
    444  lda CharScrn
    445  jmp RDBLOCK
    446 
    447 GETBEHIND
    448  ldx CharFace
    449  inx
    450  lda CharBlockX
    451  clc
    452  adc minus1,x
    453  sta behindx
    454  tax
    455 
    456  ldy CharBlockY
    457  lda CharScrn
    458  jmp RDBLOCK
    459 
    460 GETABOVE
    461  ldy CharBlockY
    462  dey
    463  sty abovey
    464 
    465  ldx CharBlockX
    466  lda CharScrn
    467  jmp RDBLOCK
    468 
    469 GETABOVEINF
    470  ldx CharFace
    471  inx
    472  lda CharBlockX
    473  clc
    474  adc plus1,x
    475  sta infrontx
    476  tax
    477 
    478  ldy CharBlockY
    479  dey
    480  sty abovey
    481 
    482  lda CharScrn
    483  jmp RDBLOCK
    484 
    485 GETABOVEBEH
    486  ldx CharFace
    487  inx
    488  lda CharBlockX
    489  clc
    490  adc minus1,x
    491  sta behindx
    492  tax
    493 
    494  ldy CharBlockY
    495  dey
    496  sty abovey
    497 
    498  lda CharScrn
    499  jmp RDBLOCK
    500 
    501 *-------------------------------
    502 *
    503 *  G E T   D I S T A N C E
    504 *
    505 *  In: Char data
    506 *
    507 *  Out: A = # of pixels (0-13) to add to CharX to move
    508 *       char base X-coord to end of current block
    509 *
    510 *-------------------------------
    511 GETDIST
    512  jsr GETBASEX ;returns A = base X-coord
    513 
    514 GETDIST1
    515  jsr GETBLOCKXP ;returns A = block #, OFFSET = pixel #
    516 
    517  lda CharFace ;0=right, -1=left
    518  beq :facingright
    519 
    520 :facingleft
    521  lda OFFSET
    522  rts
    523 
    524 :facingright
    525  lda #13
    526  sec
    527  sbc OFFSET
    528  rts
    529 
    530 *-------------------------------
    531 *
    532 *  G E T   B L O C K   E D G E
    533 *
    534 *  In:  A = block # (-5 to 14)
    535 *  Out: A = screen X-coord of left edge
    536 *
    537 *-------------------------------
    538 GETBLOCKEJ
    539  clc
    540  adc #5
    541  tax
    542  lda BlockEdge,x
    543  rts
    544 
    545 *-------------------------------
    546 *
    547 *  G E T   B L O C K   X
    548 *
    549 *  In:  A = X-coord
    550 *
    551 *  Out: A = # of the 14-pixel-wide block within which
    552 *           this pixel falls (0-9 onscreen)
    553 *
    554 *       OFFSET = pixel within this block
    555 *
    556 *  - Use GETBLOCKXP for objects on center plane
    557 *  - Use GETBLOCKX for absolute X-coords & foreground plane
    558 *
    559 *-------------------------------
    560 GETBLOCKXP
    561  sec
    562  sbc #angle
    563 
    564 GETBLOCKX
    565  tay
    566 
    567  lda PixelTable,y
    568  sta OFFSET
    569 
    570  lda BlockTable,y
    571  rts
    572 
    573 *-------------------------------
    574 *
    575 *  G E T   B L O C K   Y
    576 *
    577 *  In: A = screen Y-coord (0-255)
    578 *
    579 *  Out: A = block y (3 = o.s.)
    580 *
    581 *  - Use GETBLOCKYP for objects on center plane
    582 *  - Use GETBLOCKY for absolute Y-coords & foreground plane
    583 *
    584 *-------------------------------
    585 GETBLOCKY
    586  ldx #3
    587 :loop cmp BlockTop+1,x
    588  bcs :gotY
    589  dex
    590  bpl :loop
    591 :gotY txa
    592  rts
    593 
    594 
    595 GETBLOCKYP
    596  ldx #3
    597 :loop cmp FloorY+1,x
    598  bcs :gotY
    599  dex
    600  bpl :loop
    601 :gotY txa
    602 ]rts rts
    603 
    604 *-------------------------------
    605 *
    606 *  I N D E X   B L O C K
    607 *
    608 *  Index (tempblockx,tempblocky)
    609 *
    610 *  Return y = block # (0-29) and cc if block is onscreen
    611 *         y = 0 to 9 and cs if block is on screen above
    612 *         y = 30 and cs if block is o.s.
    613 *
    614 *-------------------------------
    615 INDEXBLOCK
    616  ldy tempblocky
    617  bmi :above
    618  cpy #3
    619  bcs :os
    620 
    621  lda tempblockx
    622  cmp #10
    623  bcs :os ;0 <= tempblockx <= 9
    624 
    625  clc
    626  adc Mult10,y
    627 
    628  tay ;return y = block #
    629  clc ;and carry clr
    630  rts
    631 
    632 :os ldy #30
    633  sec ;and carry set
    634  rts
    635 
    636 :above ldy tempblockx
    637  sec
    638 ]rts rts
    639 
    640 *-------------------------------
    641 *
    642 *  U N I N D E X
    643 *
    644 *  In: A = block index (0-29)
    645 *  Out: A = blockx, X = blocky
    646 *
    647 *-------------------------------
    648 UNINDEX
    649  ldx #0
    650 :loop cmp #10
    651  bcc ]rts
    652  sec
    653  sbc #10
    654  inx
    655  bne :loop
    656 ]rts rts
    657 
    658 *-------------------------------
    659 *
    660 *  G E T   B A S E   B L O C K
    661 *
    662 *  In: Char data
    663 *  Out: CharBlockX
    664 *
    665 *-------------------------------
    666 GETBASEBLOCK
    667  jsr getbasex
    668  jsr getblockxp
    669  sta CharBlockX
    670 ]rts rts
    671 
    672 *-------------------------------
    673 *
    674 *  F A C E   D X
    675 *
    676 *  In: CharFace; A = DX
    677 *
    678 *  Out: DX if char is facing right, -DX if facing left
    679 *
    680 *-------------------------------
    681 FACEDX
    682  bit CharFace
    683  bmi ]rts
    684 
    685  eor #$ff
    686  clc
    687  adc #1 ;negate
    688 
    689 ]rts rts
    690 
    691 *-------------------------------
    692 *
    693 *  J U M P S E Q
    694 *
    695 *  Jump to some other point in sequence table
    696 *
    697 *  In: A = sequence # (1-127)
    698 *
    699 *-------------------------------
    700 JUMPSEQ
    701  sec
    702  sbc #1
    703  asl
    704  tax ;x = 2(a-1)
    705 
    706  lda seqtab,x
    707  sta CharSeq
    708 
    709  lda seqtab+1,x
    710  sta CharSeq+1
    711 ]rts rts
    712 
    713 *-------------------------------
    714 *
    715 *  Similar routine for Opponent
    716 *
    717 *-------------------------------
    718 OPJUMPSEQ
    719  sec
    720  sbc #1
    721  asl
    722  tax ;x = 2(a-1)
    723 
    724  lda seqtab,x
    725  sta OpSeq
    726 
    727  lda seqtab+1,x
    728  sta OpSeq+1
    729 ]rts rts
    730 
    731 *-------------------------------
    732 *
    733 *  I N D E X   C H A R
    734 *
    735 *  In: Char data; GETEDGES results
    736 *
    737 *  Out: FCharIndex = character block index
    738 *
    739 *-------------------------------
    740 INDEXCHAR
    741  lda CharAction
    742  cmp #1
    743  bne :4
    744 ;If CharAction = 1 (on solid ground)
    745 ;use leftblock/bottomblock
    746  lda bottomblock
    747  sta tempblocky
    748 
    749  lda leftblock
    750 :1 sta tempblockx
    751 
    752  lda CharPosn
    753  cmp #135
    754  bcc :2
    755  cmp #149
    756  bcc :climbup
    757 
    758 :2 cmp #2
    759  beq :fall
    760  cmp #3
    761  beq :fall
    762  cmp #4
    763  beq :fall
    764  cmp #6
    765  bne :3
    766 :fall
    767 :climbup dec tempblockx  ;if falling or climbing up
    768 
    769 :3 jsr indexblock
    770  sty FCharIndex
    771  rts
    772 
    773 * else use CharBlockX/Y
    774 
    775 :4 lda CharBlockY
    776  sta tempblocky
    777 
    778  lda CharBlockX
    779  jmp :1
    780 
    781 *-------------------------------
    782 *
    783 *  S E T   U P   C H A R
    784 *
    785 *  Set up character for FRAMEADV
    786 *
    787 *  In: Char data
    788 *  Out: FChar data
    789 *
    790 *  Translate char data into the form "addchar" expects
    791 *  (Decode image #; get actual 280 x 192 screen coords)
    792 *
    793 *-------------------------------
    794 SETUPCHAR
    795  jsr zerocrop ;(can call cropchar later)
    796 
    797  jsr GETFRAMEINFO
    798 
    799  lda CharFace
    800  sta FCharFace
    801 
    802  jsr decodeim ;get FCharImage & Table from
    803  ;encoded Fimage & Fsword data
    804  lda #0
    805  sta FCharX+1
    806 
    807  lda Fdx
    808  jsr addcharx ;A := CharX + Fdx
    809  sec
    810  sbc #ScrnLeft ;different coord system
    811  sta FCharX
    812 
    813  asl FCharX
    814  rol FCharX+1
    815  beq :pos
    816 
    817  lda FCharX
    818  cmp #$f0
    819  bcc :pos
    820  lda #$ff
    821  sta FCharX+1
    822 :pos  ;X := 2X
    823  lda Fdy
    824  clc
    825  adc CharY
    826  sec
    827  sbc #ScrnTop
    828  sta FCharY
    829 
    830  lda Fcheck
    831  eor FCharFace ;Look only at the hibits
    832  bmi :ok ;They don't match-->even X-coord
    833 ;They match-->odd X-coord
    834  lda FCharX
    835  clc
    836  adc #1
    837  sta FCharX
    838  bcc :ok
    839  inc FCharX+1
    840 :ok
    841 ]rts rts
    842 
    843 *-------------------------------
    844 *
    845 *  S E T   U P   S W O R D
    846 *
    847 *  In: Char & FChar data
    848 *
    849 *  If character's sword is visible, add it to obj table
    850 *
    851 *-------------------------------
    852 SETUPSWORD
    853  lda CharID
    854  cmp #2
    855  bne :3
    856  lda CharLife
    857  bmi :2 ;live guard's sword is always visible
    858 
    859 :3 lda CharPosn
    860  cmp #229
    861  bcc :1
    862  cmp #238
    863  bcc :2 ;sheathing
    864 :1 lda CharSword
    865  beq ]rts
    866 :2
    867  lda Fsword
    868  and #$3f ;frame #
    869  beq ]rts ;no sword for this frame
    870 
    871  jsr getswordframe
    872 
    873  ldy #0
    874  lda (framepoint),y
    875  beq ]rts
    876 
    877  jsr decodeswim ;get FCharImage & Table
    878 
    879  iny
    880  lda (framepoint),y
    881  sta Fdx
    882 
    883  iny
    884  lda (framepoint),y
    885  sta Fdy
    886 
    887  lda Fdx
    888  jsr ADDFCHARX ;A := FCharX + Fdx
    889 
    890  lda Fdy
    891  clc
    892  adc FCharY
    893  sta FCharY
    894 
    895  jmp ADDSWORDOBJ
    896 
    897 *-------------------------------
    898 *
    899 *  G E T   F R A M E
    900 *
    901 *  In: A = frame # (1-192)
    902 *  Out: framepoint = 2-byte pointer to frame def table
    903 *
    904 *-------------------------------
    905 GETFRAME ;Kid uses main char set
    906  jsr getfindex
    907  lda framepoint
    908  clc
    909  adc #Fdef
    910  sta framepoint
    911  lda framepoint+1
    912  adc #>Fdef
    913  sta framepoint+1
    914  rts
    915 
    916 *-------------------------------
    917 getaltframe1 ;Enemy uses alt set 1
    918  jsr getfindex
    919  lda framepoint
    920  clc
    921  adc #altset1
    922  sta framepoint
    923  lda framepoint+1
    924  adc #>altset1
    925  sta framepoint+1
    926  rts
    927 
    928 *-------------------------------
    929 getaltframe2 ;Princess & Vizier use alt set 2
    930  jsr getfindex
    931  lda framepoint
    932  clc
    933  adc #altset2
    934  sta framepoint
    935  lda framepoint+1
    936  adc #>altset2
    937  sta framepoint+1
    938  rts
    939 
    940 *-------------------------------
    941 getfindex
    942  sec
    943  sbc #1
    944  sta ztemp
    945  sta framepoint
    946 
    947  lda #0
    948  sta ztemp+1
    949  sta framepoint+1
    950 
    951  asl framepoint
    952  rol framepoint+1
    953  asl framepoint
    954  rol framepoint+1 ;2-byte multiply by 4
    955 
    956  lda framepoint
    957  clc
    958  adc ztemp
    959  sta framepoint
    960 
    961  lda framepoint+1
    962  adc ztemp+1
    963  sta framepoint+1 ;make it x5
    964  rts
    965 
    966 *-------------------------------
    967 *
    968 * getswordframe
    969 *
    970 * In: A = frame #
    971 * Out: framepoint
    972 *
    973 *-------------------------------
    974 getswordframe
    975  sec
    976  sbc #1
    977  sta ztemp
    978  sta framepoint
    979 
    980  lda #0
    981  sta ztemp+1
    982  sta framepoint+1
    983 
    984  asl framepoint
    985  rol framepoint+1 ;x2
    986 
    987  lda framepoint
    988  clc
    989  adc ztemp
    990  sta framepoint
    991 
    992  lda framepoint+1
    993  adc ztemp+1
    994  sta framepoint+1 ;+1 is 3
    995 
    996  lda framepoint
    997  clc
    998  adc #swordtab
    999  sta framepoint
   1000 
   1001  lda framepoint+1
   1002  adc #>swordtab
   1003  sta framepoint+1
   1004 
   1005  rts
   1006 
   1007 *-------------------------------
   1008 *
   1009 * Decode char image
   1010 *
   1011 * In:  Fimage, Fsword (encoded)
   1012 *
   1013 * Out: FCharImage (image #, 0-127)
   1014 *      FCharTable (table #, 0-7)
   1015 *
   1016 *-------------------------------
   1017 decodeim
   1018  lda Fimage
   1019  and #%10000000 ;bit 2 of table #
   1020  sta ztemp
   1021 
   1022  lda Fsword
   1023  and #%11000000 ;bits 0-1 of table #
   1024 
   1025  lsr
   1026  adc ztemp
   1027  lsr
   1028  lsr
   1029  lsr
   1030  lsr
   1031  lsr
   1032  sta FCharTable
   1033 
   1034  lda Fimage
   1035  and #$7f
   1036  ora timebomb ;must be 0!
   1037  sta FCharImage
   1038 
   1039  rts
   1040 
   1041 *-------------------------------
   1042 *
   1043 * Decode sword image
   1044 *
   1045 * In: A = image #
   1046 *
   1047 * Out: FCharImage, FCharTable
   1048 *
   1049 *-------------------------------
   1050 decodeswim
   1051  sta FCharImage ;image #
   1052 
   1053  lda #2 ;chtable3
   1054  sta FCharTable
   1055  rts
   1056 
   1057 *-------------------------------
   1058 *
   1059 *  G E T   E D G E S
   1060 *
   1061 *  Get edges of character image
   1062 *
   1063 *  In: FChar data as set by "setframe"
   1064 *
   1065 *  Out: leftej/rightej/topej = boundaries of image (140-res)
   1066 *       leftblock, rightblock, topblock, bottomblock
   1067 *       CDLeftEj, CDRightEj (for coll detection)
   1068 *       imheight, imwidth
   1069 *
   1070 *-------------------------------
   1071 GETEDGES
   1072  lda FCharImage
   1073  ldx FCharTable
   1074  jsr dimchar ;return A = image width, x = height
   1075  stx imheight
   1076 
   1077  tax ;image width in bytes
   1078  lda Mult7,x ;in 1/2 pixels
   1079  clc
   1080  adc #1 ;add 1/2 pixel
   1081  lsr ;and divide by 2
   1082  sta imwidth ;to get width in pixels
   1083 
   1084  lda FCharX+1
   1085  lsr
   1086  lda FCharX
   1087  ror
   1088  clc
   1089  adc #ScrnLeft ;convert back to 140-res
   1090 
   1091 * (If facing LEFT, X-coord is leftmost pixel of LEFTMOST byte
   1092 * of image; if facing RIGHT, leftmost pixel of RIGHTMOST byte.)
   1093 
   1094  ldx CharFace
   1095  bmi :ok ;facing L
   1096 ;facing R
   1097  sec
   1098  sbc imwidth
   1099 
   1100 :ok sta leftej
   1101  clc
   1102  adc imwidth
   1103  sta rightej
   1104 
   1105  lda FCharY
   1106  sec
   1107  sbc imheight
   1108  clc
   1109  adc #1
   1110 
   1111  cmp #192
   1112  bcc :ok2
   1113  lda #0
   1114 
   1115 :ok2 sta topej
   1116 
   1117  jsr getblocky
   1118 
   1119  cmp #3
   1120  bne :1
   1121  lda #-1 ;if o.s., call it -1
   1122 
   1123 :1 sta topblock
   1124 
   1125  lda FCharY
   1126  jsr getblocky ;if o.s., call it 3
   1127  sta bottomblock
   1128 
   1129  lda leftej
   1130  jsr getblockx ;leftmost affected block
   1131  sta leftblock
   1132 
   1133  lda rightej
   1134  jsr getblockx ;rightmost affected block
   1135  sta rightblock
   1136 
   1137 * get leading edge (for collision detection)
   1138 
   1139  lda #0
   1140  sta ztemp
   1141 
   1142  lda Fcheck
   1143  and #Fthinmark
   1144  beq :nothin
   1145 
   1146  lda #thinner ;make character 3 bits thinner
   1147  sta ztemp ;on both sides
   1148 
   1149 :nothin lda leftej
   1150  clc
   1151  adc ztemp
   1152  sta CDLeftEj
   1153 
   1154  lda rightej
   1155  sec
   1156  sbc ztemp
   1157  sta CDRightEj
   1158 
   1159 ]rts rts
   1160 
   1161 *===============================
   1162 *
   1163 *  Q U I C K   F L O O R
   1164 *
   1165 *  Mark for redraw whatever floorpieces character might be
   1166 *  impinging on
   1167 *
   1168 *  In: CharData; GETEDGES results
   1169 *
   1170 *-------------------------------
   1171 QUICKFLOOR
   1172  lda CharPosn
   1173  cmp #135
   1174  bcc :2
   1175  cmp #149
   1176  bcc :climbup
   1177 
   1178 :2 lda CharAction
   1179  cmp #1
   1180  bne :1
   1181 
   1182  lda CharPosn
   1183  cmp #78
   1184  bcc ]rts
   1185  cmp #80
   1186  bcc :fall
   1187 ]rts rts
   1188 
   1189 :1 cmp #2
   1190  beq :fall
   1191  cmp #3
   1192  beq :fall
   1193  cmp #4
   1194  beq :fall
   1195  cmp #6
   1196  bne ]rts
   1197 
   1198 :fall lda #markfloor
   1199  ldx #>markfloor
   1200  bne :cont1
   1201 
   1202 :climbup
   1203  lda #markhalf
   1204  ldx #>markhalf
   1205 
   1206 * Mark floorbuf/halfbuf for up to 6 affected blocks
   1207 * Start with rightblock, work left to leftblock
   1208 
   1209 :cont1
   1210  sta marksm1+1
   1211  sta marksm2+1
   1212  stx marksm1+2
   1213  stx marksm2+2
   1214 
   1215  lda rightblock
   1216 :loop sta tempblockx
   1217 
   1218  jsr markul
   1219 
   1220  lda tempblockx
   1221  cmp leftblock
   1222  beq ]rts
   1223  sec
   1224  sbc #1
   1225  bpl :loop
   1226 
   1227 ]rts rts
   1228 
   1229 * mark upper & lower blocks for this blockx
   1230 
   1231 markul
   1232  lda bottomblock
   1233  sta tempblocky
   1234 
   1235  jsr indexblock ;lower block
   1236  lda #2
   1237 marksm1 jsr markhalf
   1238 
   1239  lda topblock
   1240  cmp bottomblock
   1241  beq ]rts
   1242  sta tempblocky
   1243 
   1244  jsr indexblock ;upper block
   1245  lda #2
   1246 marksm2 jmp markhalf
   1247 
   1248 *-------------------------------
   1249 *
   1250 *  Q U I C K  F G
   1251 *
   1252 *  Mark for redraw any f.g. elements char (or his sword)
   1253 *  might be impinging on
   1254 *
   1255 *  In: Char data; left/right/top/bottomblock
   1256 *
   1257 *-------------------------------
   1258 QUICKFG
   1259 
   1260 * Quick fix to cover sword
   1261 
   1262  lda CharSword
   1263  cmp #2
   1264  bcc :cont
   1265 
   1266  lda CharFace
   1267  bpl :faceR
   1268  dec leftblock
   1269  jmp :cont
   1270 
   1271 :faceR inc rightblock
   1272 
   1273 * Continue
   1274 
   1275 :cont lda bottomblock
   1276 :outloop
   1277  sta tempblocky
   1278 
   1279  lda rightblock
   1280 :loop sta tempblockx
   1281 
   1282  jsr indexblock
   1283  lda #3
   1284  jsr MARKFRED
   1285 
   1286  lda tempblockx
   1287  cmp leftblock
   1288  beq :end
   1289  sec
   1290  sbc #1
   1291  bpl :loop
   1292 :end
   1293  lda tempblocky
   1294  cmp topblock
   1295  beq ]rts
   1296  sec
   1297  sbc #1
   1298  bpl :outloop
   1299  rts
   1300 
   1301 ]bug jmp showpage
   1302 
   1303 *-------------------------------
   1304 *
   1305 *  C R O P   C H A R A C T E R
   1306 *
   1307 *  In: FChar data as set by "setframe"
   1308 *      leftej,rightej, etc. as set by "getedges"
   1309 *
   1310 *  Out: FCharCL/CR/CU/CD
   1311 *
   1312 *-------------------------------
   1313 CROPCHAR
   1314 
   1315 * If char is climbing stairs, mask door
   1316 
   1317  lda CharPosn
   1318  cmp #224
   1319  bcc :nost
   1320  cmp #229
   1321  bcs :nost
   1322  lda doortop ;set by drawexitb
   1323  clc
   1324  adc #2
   1325  cmp FCharY
   1326  bcs :bug ;temp!
   1327  sta FCharCU
   1328 ]rts rts
   1329 :bug ldy #$F0
   1330  jsr showpage
   1331 :nost
   1332 
   1333 * If char is under solid (a&b) floor, crop top
   1334 
   1335  ldx leftblock
   1336  ldy topblock
   1337  lda CharScrn
   1338  jsr rdblock
   1339  cmp #block
   1340  beq :1
   1341  jsr cmpspace
   1342  beq :not
   1343 
   1344 * Special case (more lenient): if char is jumping
   1345 * up to touch ceiling
   1346 
   1347 :1 lda CharAction
   1348  bne :10
   1349  lda CharPosn
   1350  cmp #79
   1351  beq :2
   1352  cmp #81
   1353  bne :10
   1354  beq :2
   1355 
   1356 * Otherwise, both left & right topblocks must be solid
   1357 
   1358 :10 ldx rightblock
   1359  ldy topblock
   1360  lda CharScrn
   1361  jsr rdblock
   1362  cmp #block
   1363  beq :2
   1364  jsr cmpspace
   1365  beq  :not
   1366 
   1367 :2 ldx CharBlockY
   1368  inx
   1369  cpx #1
   1370  beq :ok
   1371 
   1372  lda BlockTop,x
   1373  cmp FCharY
   1374  bcs :not
   1375 
   1376  sec
   1377  sbc #floorheight
   1378  cmp topej
   1379  bcs :not
   1380 
   1381 :ok lda BlockTop,x
   1382  sta FCharCU
   1383  sta topej
   1384 :not
   1385 
   1386 * If char is standing left of a panel, crop R
   1387 * Char is considered "left" if CDLeftEj falls within
   1388 * panel block
   1389 
   1390  lda CDLeftEj
   1391  jsr getblockx
   1392  sta blockx
   1393 
   1394  tax
   1395  ldy CharBlockY
   1396  lda CharScrn
   1397  jsr rdblock
   1398 
   1399  cmp #panelwof
   1400  beq :r
   1401  cmp #panelwif
   1402  bne :nor
   1403 
   1404 * Char's foot is within panel block
   1405 * Special case: If character is hanging R, we don't
   1406 * need to check his head
   1407 
   1408 :r lda CharFace
   1409  bmi :cont
   1410 
   1411  lda CharAction
   1412  cmp #2
   1413  beq :r2 ;yes--hanging R
   1414 
   1415 * Check block to right of char's head
   1416 
   1417 :cont
   1418  ldx blockx
   1419  ldy topblock
   1420  lda CharScrn
   1421  jsr rdblock
   1422 
   1423  cmp #block
   1424  beq :r2
   1425  cmp #panelwof
   1426  beq :r2
   1427  cmp #panelwif
   1428  bne :nor
   1429 
   1430 * Also a panel -- make a wall
   1431 
   1432 :r2 lda tempblockx
   1433  asl
   1434  asl
   1435  clc
   1436  adc #4
   1437  sta FCharCR
   1438  rts
   1439 
   1440 * Is char standing to L of solid block?
   1441 * (i.e. does CDRightEj fall within block?)
   1442 
   1443 :nor
   1444  lda CDRightEj
   1445  jsr getblockx
   1446  sta blockx
   1447 
   1448  tax
   1449  ldy CharBlockY
   1450  lda CharScrn
   1451  jsr rdblock
   1452 
   1453  cmp #block
   1454  bne :nob
   1455 
   1456 * Foot is under block--what about head?
   1457 
   1458  ldx blockx
   1459  ldy topblock
   1460  lda CharScrn
   1461  jsr rdblock
   1462 
   1463  cmp #block
   1464  bne :nob
   1465 
   1466 * Also a panel -- make a wall
   1467 
   1468 :yescrop
   1469  lda tempscrn
   1470  cmp CharScrn
   1471  bne :nob
   1472 
   1473  lda tempblockx
   1474  asl
   1475  asl
   1476  sta FCharCR
   1477 :nob
   1478  rts
   1479 
   1480 *-------------------------------
   1481 *
   1482 *  Z E R O   C R O P
   1483 *
   1484 *-------------------------------
   1485 zerocrop
   1486  lda #0
   1487  sta FCharCU
   1488  sta FCharCL
   1489  lda #40
   1490  sta FCharCR
   1491  lda #192
   1492  sta FCharCD
   1493  rts
   1494 
   1495 *===============================
   1496 *
   1497 *  C O M P A R E   S P A C E
   1498 *
   1499 *  Is it a space (can you pass thru)?
   1500 *  NOTE: Solid block is considered a space (it has no floor)
   1501 *
   1502 *  In: A = objid
   1503 *  Out: 0 = space, 1 = floor
   1504 *
   1505 *-------------------------------
   1506 CMPSPACE
   1507  cmp #space
   1508  beq :space
   1509  cmp #pillartop
   1510  beq :space
   1511  cmp #panelwof
   1512  beq :space
   1513  cmp #block
   1514  beq :space
   1515  cmp #archtop1
   1516  bcs :space
   1517 
   1518  lda #1
   1519  rts
   1520 
   1521 :space lda #0
   1522  rts
   1523 
   1524 *-------------------------------
   1525 *
   1526 *  C O M P A R E   B A R R I E R
   1527 *
   1528 *  Is it a barrier?
   1529 *
   1530 *  Return A = 0 if clear, else A = barrier code #
   1531 *
   1532 *-------------------------------
   1533 CMPBARR
   1534  cmp #panelwif
   1535  beq :b1
   1536  cmp #panelwof
   1537  beq :b1
   1538  cmp #gate
   1539  bne :2
   1540 
   1541 :b1 lda #1 ;panel/gate
   1542  rts
   1543 
   1544 :2 cmp #mirror
   1545  beq :yes3
   1546 
   1547  cmp #slicer
   1548  bne :3
   1549 
   1550 :yes3 lda #3 ;mirror/slicer
   1551  rts
   1552 
   1553 :3 cmp #block
   1554  bne :4
   1555 
   1556  lda #4 ;block
   1557  rts
   1558 :4
   1559 :clear lda #0
   1560 :rts rts
   1561 
   1562 :barr lda #1
   1563 ]rts rts
   1564 
   1565 *-------------------------------
   1566 *
   1567 * Is it a wall? Return 0 if yes, 1 if no
   1568 * (Solid block, or panel if you're facing L)
   1569 *
   1570 *-------------------------------
   1571 CMPWALL
   1572  cmp #block
   1573  beq :yes
   1574  ldx CharFace
   1575  bpl :no
   1576  cmp #panelwif
   1577  beq :yes
   1578  cmp #panelwof
   1579  beq :yes
   1580 :no lda #1
   1581  rts
   1582 :yes lda #0
   1583  rts
   1584 
   1585 *-------------------------------
   1586 *
   1587 *  Add kid/reflection/shadowman/guard to object table
   1588 *
   1589 *  In: FChar data
   1590 *
   1591 *-------------------------------
   1592 ADDKIDOBJ
   1593  lda #TypeKid
   1594  jmp addcharobj
   1595 
   1596 *-------------------------------
   1597 ADDREFLOBJ
   1598  lda #TypeReflect
   1599  jmp addcharobj
   1600 
   1601 *-------------------------------
   1602 ADDSHADOBJ
   1603  lda #TypeShad
   1604  jmp addcharobj
   1605 
   1606 *-------------------------------
   1607 ADDGUARDOBJ
   1608  lda #TypeGd
   1609  jmp addcharobj
   1610 
   1611 *-------------------------------
   1612 *
   1613 * Add sword to object table
   1614 * In: FChar data for character holding sword
   1615 *
   1616 *-------------------------------
   1617 ADDSWORDOBJ
   1618  lda #TypeSword
   1619  jmp addcharobj
   1620 
   1621 *-------------------------------
   1622 *
   1623 *  G E T   S E Q
   1624 *
   1625 *  Get next byte from seqtable & advance CharSeq
   1626 *  (2-byte pointer to sequence table)
   1627 *
   1628 *-------------------------------
   1629 GETSEQ
   1630  ldy #0
   1631  lda (CharSeq),y
   1632  pha
   1633 
   1634  inc CharSeq
   1635  bne :done
   1636  inc CharSeq+1
   1637 
   1638 :done pla
   1639  rts
   1640 
   1641 *-------------------------------
   1642 *
   1643 *  G E T   F R A M E   I N F O
   1644 *
   1645 *  Get frame info for char (based on CharPosn)
   1646 *
   1647 *-------------------------------
   1648 GETFRAMEINFO
   1649  lda CharPosn
   1650  jsr GETFRAME ;set framepoint
   1651 
   1652  jsr usealtsets ;if appropriate
   1653 
   1654  ldy #0
   1655  lda (framepoint),y
   1656  sta Fimage
   1657 
   1658  iny
   1659  lda (framepoint),y
   1660  sta Fsword
   1661 
   1662  iny
   1663  lda (framepoint),y
   1664  sta Fdx
   1665 
   1666  iny
   1667  lda (framepoint),y
   1668  sta Fdy
   1669 
   1670  iny
   1671  lda (framepoint),y
   1672  sta Fcheck
   1673 
   1674 ]rts rts
   1675 
   1676 *-------------------------------
   1677 *
   1678 * Use alternate character image sets
   1679 * (if appropriate)
   1680 *
   1681 * In: Char data; framepoint
   1682 * Out: framepoint
   1683 *
   1684 *-------------------------------
   1685 usealtsets
   1686  ldx CharID
   1687  beq ]rts ;kid uses main set, enemy uses alt set 1
   1688  cpx #24
   1689  beq ]rts ;mouse uses main set
   1690  cpx #5
   1691  bcs :usealt2 ;princess & vizier use alt set 2
   1692 
   1693  lda CharPosn
   1694  cpx #2
   1695  bcc :1
   1696  cmp #102
   1697  bcc ]rts
   1698  cmp #107
   1699  bcs :1
   1700  ;frames 102-106 (falling): substitute 172-176 altset
   1701  clc
   1702  adc #70
   1703 
   1704 :1 cmp #150
   1705  bcc ]rts
   1706  cmp #190
   1707  bcs ]rts
   1708 ;frames 150-189: use altset
   1709  sec
   1710  sbc #149
   1711  jmp getaltframe1
   1712 
   1713 :usealt2
   1714  lda CharPosn
   1715  jmp getaltframe2
   1716 
   1717 *===============================
   1718 *
   1719 *  M A R K
   1720 *
   1721 *  In: A = mark value (usually 2)
   1722 *      Results of INDEXBLOCK:
   1723 *      Y = block #; carry set or clear
   1724 *
   1725 *  Out: Preserve A, Y, carry
   1726 *
   1727 *-------------------------------
   1728 ]os cpy #10 ;top line from scrn above?
   1729  bcs ]rts ;no
   1730  sta topbuf,y
   1731  sec ;preserve cs
   1732 ]rts rts
   1733 
   1734 MARKRED
   1735  bcs ]os
   1736  sta redbuf,y
   1737  rts
   1738 
   1739 MARKFRED
   1740  bcs ]rts
   1741  sta fredbuf,y
   1742  rts
   1743 
   1744 MARKWIPE
   1745  bcs ]rts
   1746  pha
   1747  lda wipebuf,y
   1748  beq :2
   1749  lda height
   1750  cmp whitebuf,y ;if wipebuf is already marked,
   1751  bcc :1 ;use larger of 2 whitebuf values
   1752 :2 lda height
   1753  sta whitebuf,y
   1754 :1 pla
   1755  sta wipebuf,y
   1756  clc ;return with cc
   1757  rts
   1758 
   1759 MARKMOVE
   1760  bcs ]os
   1761  sta movebuf,y
   1762  rts
   1763 
   1764 MARKFLOOR
   1765  bcs ]os
   1766  sta floorbuf,y
   1767  rts
   1768 
   1769 MARKHALF
   1770  bcs ]os
   1771  sta halfbuf,y
   1772  rts
   1773 
   1774 *-------------------------------
   1775 *
   1776 *  Z E R O   R E D
   1777 *
   1778 *  zero redraw buffers
   1779 *
   1780 *-------------------------------
   1781 ZERORED
   1782  lda #0
   1783 
   1784  ldy #29
   1785 
   1786 :loop sta redbuf,y
   1787  sta fredbuf,y
   1788  sta floorbuf,y
   1789  sta wipebuf,y
   1790  sta movebuf,y
   1791  sta objbuf,y
   1792  sta halfbuf,y
   1793 
   1794  dey
   1795  bpl :loop
   1796 
   1797  ldy #9
   1798 :dloop sta topbuf,y
   1799  dey
   1800  bpl :dloop
   1801 
   1802  rts
   1803 
   1804 *-------------------------------
   1805 *
   1806 *  C H E C K L E D G E
   1807 *
   1808 *  In: blockid = block that must be clear;
   1809 *      A = RDBLOCK results for block that must be ledge
   1810 *
   1811 *  Out: A = 1 if grabbable, 0 if not
   1812 *
   1813 *-------------------------------
   1814 CHECKLEDGE
   1815  sta ztemp
   1816 
   1817  lda (BlueSpec),y
   1818  sta tempstate
   1819 
   1820  lda blockid ;must be clear
   1821 
   1822  cmp #block
   1823  beq :no
   1824 
   1825  cmp #panelwof ;CMPSPACE considers panel w/o floor
   1826   bne :cont ;to be clear--
   1827 
   1828  bit CharFace ;but it isn't if char wants to grab
   1829  bpl :no ;floorpiece to right
   1830 :cont
   1831  jsr cmpspace
   1832  bne :no
   1833 
   1834 * Clear above -- is there a ledge in front?
   1835 
   1836  lda ztemp ;must be a solid floorpiece
   1837 ;with exposed ledge
   1838  cmp #loose
   1839  bne :notloose
   1840 
   1841  bit tempstate
   1842  bne :no ;floor is already loose
   1843 
   1844 :notloose
   1845  cmp #panelwif
   1846  bne :cont2 ;panel w/floor can be grabbed
   1847 ;only if facing right
   1848  bit CharFace
   1849  bmi :no
   1850 
   1851 :cont2 jsr cmpspace
   1852  beq :no
   1853 
   1854 :yes lda #1
   1855  rts
   1856 
   1857 :no lda #0
   1858 ]rts rts
   1859 
   1860 *-------------------------------
   1861 *
   1862 *  C H E C K   S P I K E S
   1863 *
   1864 *  Spikes spring out when char passes over them (at any
   1865 *  height).
   1866 *
   1867 *-------------------------------
   1868 CHECKSPIKES
   1869  lda rightej
   1870  jsr getblockxp
   1871  bmi ]rts
   1872  sta tempright
   1873 
   1874 * for blockx = leftblock to rightblock
   1875 
   1876  lda leftej
   1877  jsr getblockxp
   1878 :loop sta blockx
   1879 
   1880  jsr sub
   1881 
   1882  lda blockx
   1883  cmp tempright
   1884  beq ]rts
   1885  clc
   1886  adc #1
   1887  jmp :loop
   1888 
   1889 sub sta tempblockx
   1890  lda CharBlockY
   1891  sta tempblocky
   1892  lda CharScrn
   1893  sta tempscrn
   1894 :loop jsr rdblock1
   1895 
   1896  cmp #spikes
   1897  bne :again
   1898  jmp trigspikes
   1899 
   1900 :again jsr cmpspace
   1901  bne ]rts
   1902 
   1903  lda tempscrn
   1904  beq ]rts ;null scrn
   1905  cmp CharScrn
   1906  bne ]rts ;wait till he's on same screen
   1907 
   1908  inc tempblocky
   1909  jmp :loop ;check 1 level below
   1910 
   1911 *===============================
   1912 *
   1913 *  Load/save kid/shad vars
   1914 *
   1915 *-------------------------------
   1916 numvars = 16
   1917 
   1918 LOADKID
   1919  ldx #numvars-1
   1920 
   1921 :loop lda Kid,x
   1922  sta Char,x
   1923 
   1924  dex
   1925  bpl :loop
   1926 ]rts rts
   1927 
   1928 SAVEKID
   1929  ldx #numvars-1
   1930 
   1931 :loop lda Char,x
   1932  sta Kid,x
   1933 
   1934  dex
   1935  bpl :loop
   1936 ]rts rts
   1937 
   1938 LOADSHAD
   1939  ldx #numvars-1
   1940 
   1941 :loop lda Shad,x
   1942  sta Char,x
   1943 
   1944  dex
   1945  bpl :loop
   1946 ]rts rts
   1947 
   1948 
   1949 SAVESHAD
   1950  ldx #numvars-1
   1951 
   1952 :loop lda Char,x
   1953  sta Shad,x
   1954 
   1955  dex
   1956  bpl :loop
   1957  rts
   1958 
   1959 *  Load kid w/ opponent
   1960 
   1961 LOADKIDWOP
   1962  ldx #numvars-1
   1963 
   1964 :loop lda Kid,x
   1965  sta Char,x
   1966 
   1967  lda Shad,x
   1968  sta Op,x
   1969 
   1970  dex
   1971  bpl :loop
   1972  rts
   1973 
   1974 SAVEKIDWOP
   1975  ldx #numvars-1
   1976 
   1977 :loop lda Char,x
   1978  sta Kid,x
   1979 
   1980  lda Op,x
   1981  sta Shad,x
   1982 
   1983  dex
   1984  bpl :loop
   1985  rts
   1986 
   1987 * Load shadowman w/ opponent
   1988 
   1989 LOADSHADWOP
   1990  ldx #numvars-1
   1991 
   1992 :loop lda Shad,x
   1993  sta Char,x
   1994 
   1995  lda Kid,x
   1996  sta Op,x
   1997 
   1998  dex
   1999  bpl :loop
   2000  rts
   2001 
   2002 SAVESHADWOP
   2003  ldx #numvars-1
   2004 
   2005 :loop lda Char,x
   2006  sta Shad,x
   2007 
   2008  lda Op,x
   2009  sta Kid,x
   2010 
   2011  dex
   2012  bpl :loop
   2013  rts
   2014 
   2015 *-------------------------------
   2016 *
   2017 * Recharge strength meter to max
   2018 *
   2019 *-------------------------------
   2020 RECHARGEMETER
   2021  lda MaxKidStr
   2022  sec
   2023  sbc KidStrength
   2024  sta ChgKidStr
   2025 ]rts rts
   2026 
   2027 *-------------------------------
   2028 *
   2029 * Boost strength meter max by 1 and recharge
   2030 *
   2031 *-------------------------------
   2032 BOOSTMETER
   2033  lda MaxKidStr
   2034  cmp #maxmaxstr
   2035  bcs :1
   2036 
   2037  clc
   2038  adc #1
   2039  sta MaxKidStr
   2040 
   2041 :1 jmp RECHARGEMETER
   2042 
   2043 *-------------------------------
   2044 *
   2045 * Get distance between char & opponent
   2046 * (# pixels char must move fwd to reach opponent)
   2047 * If dist is greater than 127, return 127 (+ or -)
   2048 *
   2049 *-------------------------------
   2050 estwidth = 13 ;rough est of char width
   2051 
   2052 GETOPDIST
   2053  lda CharScrn
   2054  cmp OpScrn
   2055  bne :safe
   2056 
   2057 * First, get A = OpX-CharX (abs. value <= 127)
   2058 
   2059  lda OpX
   2060  cmp CharX
   2061  bcc :neg
   2062  sec
   2063  sbc CharX
   2064  bpl :got
   2065  lda #127
   2066  bpl :got
   2067 
   2068 :neg lda CharX
   2069  sec
   2070  sbc OpX
   2071  bpl :1
   2072  lda #127
   2073 :1 eor #$ff
   2074  clc
   2075  adc #1 ;negate
   2076 
   2077 * If CharFace = left, negate
   2078 
   2079 :got ldx CharFace
   2080  bpl :cont
   2081  eor #$ff
   2082  clc
   2083  adc #1
   2084 
   2085 * If chars are facing in opposite directions,
   2086 * adjust by estimate of width of figure
   2087 
   2088 :cont tax
   2089  lda CharFace
   2090  eor OpFace
   2091  bpl :done
   2092  txa
   2093  cmp #127-estwidth
   2094  bcs :done2
   2095  clc
   2096  adc #estwidth
   2097 :done2 tax
   2098  rts
   2099 
   2100 :safe ldx #127 ;arbitrary large dist.
   2101 :done txa ;return value in A
   2102 ]rts rts
   2103 
   2104 *-------------------------------
   2105 *
   2106 *  Adjust CharY for uneven floor
   2107 *
   2108 *-------------------------------
   2109 UNEVENFLOOR
   2110  jsr getunderft
   2111  cmp #dpressplate
   2112  bne ]rts
   2113  inc CharY
   2114 ]rts rts
   2115 
   2116 *-------------------------------
   2117  lst
   2118  ds 1
   2119  usr $a9,19,$200,*-org
   2120  lst off