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

TOPCTRL.S (25772B)


      1 * topctrl
      2 org = $2000
      3 EditorDisk = 0
      4 FinalDisk = 1
      5 DemoDisk = 0
      6 ThreeFive = 1 ;3.5" disk?
      7  tr on
      8  lst off
      9 *-------------------------------
     10 *
     11 *  PRINCE OF PERSIA
     12 *  Copyright 1989 Jordan Mechner
     13 *
     14 *-------------------------------
     15  org org
     16 
     17  jmp START
     18  jmp RESTART
     19  jmp STARTRESUME
     20  jmp INITSYSTEM
     21  jmp showpage
     22 
     23  jmp showpage
     24  jmp GOATTRACT
     25 
     26 *-------------------------------
     27  lst
     28  put eq
     29  lst
     30  put gameeq
     31  lst
     32  put seqdata
     33  lst
     34  put movedata
     35  lst
     36  put soundnames
     37  lst off
     38 
     39 *-------------------------------
     40 * 18-sector ID bytes
     41 
     42 POPside1 = $a9
     43 POPside2 = $ad
     44 
     45 FirstSideB = 3 ;1st level on Side B
     46 LastSideB = 14 ;& last
     47 
     48 *-------------------------------
     49 * Soft switches
     50 
     51 ALTZPon = $c009
     52 ALTZPoff = $c008
     53 RAMWRTaux = $c005
     54 RAMWRTmain = $c004
     55 RAMRDaux = $c003
     56 RAMRDmain = $c002
     57 TEXTon = $c051
     58 PAGE2off = $c054
     59 
     60 kresurrect = "R"
     61 
     62 *-------------------------------
     63 * Misc. changeable parameters
     64 
     65 initmaxstr = 3
     66 
     67 BTLtimer = 20 ;back to life
     68 wtlflash = 15 ;weightless
     69 
     70 mousetimer = 150
     71 
     72 *-------------------------------
     73 * message #s
     74 
     75 LevelMsg = 1
     76 ContMsg = 2
     77 TimeMsg = 3
     78 
     79 leveltimer = 20 ;level message timer
     80 contflash = 95
     81 contoff = 15
     82 deadenough = 4
     83 
     84 *-------------------------------
     85 * Mirror location
     86 
     87 mirlevel = 4
     88 mirscrn = 4
     89 mirx = 4
     90 miry = 0
     91 
     92 *-------------------------------
     93 *
     94 *  Start a new game
     95 *
     96 *  In: A = level # (0 for demo, 1 for game)
     97 *
     98 *-------------------------------
     99 START
    100  sta ALTZPon
    101  jsr StartGame
    102  jmp RESTART
    103 
    104 *-------------------------------
    105 *
    106 *  Resume saved game
    107 *
    108 *-------------------------------
    109 STARTRESUME
    110  sta ALTZPon
    111  lda #4 ;arbitrary value >1
    112  jsr StartGame
    113  jmp ResumeGame
    114 
    115 *-------------------------------
    116 *
    117 *  Initialize system (Called from MASTER upon bootup)
    118 *
    119 *-------------------------------
    120 INITSYSTEM
    121  sta ALTZPon
    122 
    123  jsr setcenter ;Center joystick
    124 
    125  jsr setfastaux ;bgtable in auxmem
    126 
    127  lda #FinalDisk!1
    128  sta develment
    129 
    130  jsr initgame
    131 
    132  ldx #0
    133  txa
    134 :loop sta $0,x
    135  inx
    136  bne :loop
    137 
    138  sta ALTZPoff
    139  rts
    140 
    141 *-------------------------------
    142 *
    143 *  Start a game
    144 *
    145 *  In: A = level # (0 for demo, 1 for new game, >1 for
    146 *      resumed game)
    147 *
    148 *-------------------------------
    149 StartGame
    150  sta level
    151  sta NextLevel
    152 
    153  cmp #1
    154  bne :notfirst
    155  lda #s_Danger
    156  ldx #25
    157  jsr cuesong ;Cue "Danger" theme if level 1
    158 :notfirst
    159 
    160  lda #initmaxstr
    161  sta origstrength ;set initial strength
    162 
    163  jmp initgame
    164 
    165 *-------------------------------
    166 *
    167 *  Resume saved game
    168 *
    169 *-------------------------------
    170 ResumeGame
    171  do DemoDisk
    172  rts
    173  else
    174 
    175  jsr flipdisk ;Ask player to flip disk
    176  lda #POPside2
    177  sta BBundID ;& expect side 2 from now on
    178 
    179 :cont jsr loadgame ;Load saved-game info from disk
    180 
    181  lda SavLevel ;Has a game been saved?
    182  bpl :ok ;Yes
    183 
    184 * No game saved--start new game instead
    185 
    186  jsr flipdisk
    187  lda #POPside1
    188  sta BBundID
    189 
    190  lda #1
    191  sta level
    192  sta NextLevel
    193  jmp RESTART
    194 
    195 * Restore strength & timer
    196 
    197 :ok lda SavStrength
    198  sta origstrength
    199 
    200  lda SavTimer+1
    201  sta FrameCount+1
    202  lda SavTimer
    203  sta FrameCount
    204 
    205  lda SavNextMsg
    206  sta NextTimeMsg
    207 
    208 * & resume from beginning of level
    209 
    210  lda #1
    211  sta timerequest ;show time remaining
    212  lda #$80
    213  sta yellowflag ;pass copy prot. test
    214  lda SavLevel
    215  sta level
    216  sta NextLevel
    217  jmp RESTART
    218 
    219  fin
    220 
    221 *-------------------------------
    222 *
    223 * Initialize vars before starting game
    224 *
    225 *-------------------------------
    226 initgame
    227  lda #0
    228  sta blackflag
    229  sta redrawflg
    230  sta inmenu
    231  sta inbuilder
    232  sta recheck0
    233  sta SINGSTEP
    234  sta ManCtrl
    235  sta vibes
    236  sta invert
    237  sta milestone
    238  sta timerequest
    239  sta FrameCount
    240  sta FrameCount+1
    241  sta NextTimeMsg
    242 
    243  lda #$ff
    244  sta MinLeft
    245  sta SecLeft
    246 
    247  lda #1 ;no delay
    248  sta SPEED
    249  rts
    250 
    251 *-------------------------------
    252 *
    253 *  Restart current level
    254 *
    255 *-------------------------------
    256 RESTART
    257  sta ALTZPon
    258  sta $c010 ;clr kbd strobe
    259 
    260  do EditorDisk
    261  jsr reloadblue
    262  else
    263 
    264  lda #" "
    265  jsr lrcls
    266  jsr vblank
    267  lda PAGE2off
    268  lda TEXTon
    269 
    270  ldx level
    271  jsr LoadLevelX ;load blueprint & image sets from disk
    272  fin
    273 
    274  jsr setinitials ;Set initial states as specified in blueprint
    275 
    276  jsr initialguards ;& guards
    277 
    278 * Zero a lot of vars & tables
    279 
    280  lda #0
    281  sta SINGSTEP
    282  sta vibes
    283  sta AMtimer
    284  sta VisScrn
    285  sta exitopen
    286  sta lightning
    287  sta mergetimer
    288  sta numtrans
    289  sta nummob
    290  sta EnemyAlert
    291  sta createshad
    292  sta stunned
    293  sta heroic
    294  sta ChgKidStr
    295  sta OppStrength ;no opponent
    296  sta msgtimer
    297  sta PreRecPtr
    298  sta PlayCount
    299 
    300  ldx SongCue
    301  cpx #s_Danger
    302  beq :1st
    303  sta SongCue
    304 :1st
    305 
    306  jsr zerosound
    307 
    308  jsr zeropeels
    309 
    310  jsr initCDbuf ;initialize collision detection buffers
    311 
    312  jsr initinput
    313 
    314  lda #1
    315  sta gotsword
    316 
    317  lda #-1
    318  sta cutorder
    319 
    320  lda #2
    321  sta ShadID ;default opponent is guard
    322  lda #86
    323  sta ShadFace
    324 
    325  jsr startkid
    326 
    327  do EditorDisk
    328  else
    329 
    330  lda level
    331  cmp #1
    332  bne :gotswd
    333  lda #0
    334  sta gotsword ;Start Level 1 w/o sword
    335 :gotswd
    336  fin
    337 
    338  lda level
    339  beq :nomsg
    340  cmp #14
    341  beq :nomsg ;don't announce level 0 or 14
    342  cmp #13
    343  bne :1
    344  lda skipmessage
    345  beq :1
    346  lda #0
    347  sta skipmessage
    348  beq :nomsg ;skip level 13 message 1st time
    349 :1 lda #LevelMsg
    350  sta message
    351  lda #leveltimer
    352  sta msgtimer
    353 :nomsg
    354 
    355  jsr entrance ;entrance slams shut
    356 
    357  jsr FirstFrame ;Generate & display first frame
    358 
    359  jmp MainLoop
    360 
    361 *-------------------------------
    362 *
    363 *  Main loop
    364 *
    365 *-------------------------------
    366 MainLoop
    367  jsr rnd
    368 
    369  lda #0
    370  sta ChgKidStr
    371  sta ChgOppStr
    372 
    373  jsr strobe ;Strobe kbd & jstk
    374 
    375  jsr demokeys
    376  bpl :4
    377  lda #1
    378  jmp START ;During demo, press any key to play
    379 :4
    380  jsr misctimers
    381 
    382  jsr NextFrame ;Determine what next frame should look like
    383 
    384  jsr flashon
    385 
    386  jsr FrameAdv ;Draw next frame & show it
    387 
    388  jsr playback ;Play sounds
    389  jsr zerosound ;& zero sound table
    390 
    391  jsr flashoff
    392 
    393  jsr songcues ;Play music
    394 
    395  lda NextLevel
    396  cmp level
    397  beq MainLoop ;Continue until we change levels
    398 
    399  jsr yellowcheck ;copy protect!
    400 
    401  jmp LoadNextLevel
    402 
    403 *-------------------------------
    404 *
    405 * Load next level
    406 *
    407 * In: NextLevel = # of next level
    408 *     level = # of current level
    409 *
    410 * Out: level = NextLevel
    411 *
    412 *-------------------------------
    413 LoadNextLevel
    414  lda NextLevel
    415  cmp #14
    416  beq LoadNext1
    417  lda #1
    418  sta timerequest ;show time remaining
    419 
    420 LoadNext1
    421  lda MaxKidStr
    422  sta origstrength ;save new strength level
    423  lda #0
    424  sta milestone
    425 
    426  do EditorDisk
    427  lda level
    428  sta NextLevel
    429  jmp RESTART
    430  fin
    431 
    432 * NextLevel must be in range 1 - LastSideB
    433 
    434  lda NextLevel
    435  cmp #LastSideB+1
    436  bcs :illegal
    437  cmp #1
    438  bcs :2
    439 :illegal lda level ;Illegal value--restart current level
    440  sta NextLevel
    441  jmp RESTART
    442 
    443 * Load from correct side of disk
    444 
    445 :2 ldx #POPside2
    446  cmp #FirstSideB
    447  bcs :1
    448  ldx #POPside1
    449 :1 cpx BBundID ;do we need to flip disk?
    450  beq :ok ;no
    451  stx BBundID ;yes
    452  jsr flipdisk
    453 
    454 :ok lda NextLevel
    455  sta level ;set new level
    456  cmp #2
    457  beq :cut1
    458  cmp #4
    459  beq :cut2
    460  cmp #6
    461  beq :cut3
    462  cmp #8
    463  beq :cut8
    464  cmp #9
    465  beq :cut4
    466  cmp #12
    467  beq :cut5 ;Princess cuts before certain levels
    468 
    469 :cont jmp RESTART ;Start new level
    470 
    471 * Princess cuts before certain levels
    472 
    473 :cut1 lda #1
    474 ]pcut pha
    475 :repeat jsr cutprincess ;cut to princess's room...
    476  jsr setrecheck0
    477  jsr recheckyel ;if wrong-disk error, recheck track 0
    478  bne :repeat ;& repeat
    479  pla
    480  jsr playcut ;& play cut #1
    481  jmp :cont
    482 
    483 :cut2 lda #2
    484  bne ]pcut
    485 :cut3 lda #3
    486  bne ]pcut
    487 :cut4 lda #4
    488  bne ]pcut
    489 :cut5 lda #5
    490  bne ]pcut
    491 :cut8 lda #8
    492  bne ]pcut
    493 
    494 *-------------------------------
    495 *
    496 *  N E X T   F R A M E
    497 *
    498 *  Determine what next frame should look like
    499 *
    500 *  In: All data reflects last (currently displayed) frame.
    501 *
    502 *-------------------------------
    503 NextFrame
    504  jsr animmobs ;Update mobile objects (MOBs)
    505 
    506  jsr animtrans ;Update transitional objects (TROBs)
    507 
    508  jsr bonesrise ;Bring skeleton to life?
    509 
    510  jsr checkalert ;Determine EnemyAlert value
    511 
    512  jsr DoKid ;Update kid
    513 
    514  jsr DoShad ;Update shadowman (or other opponent)
    515 
    516  jsr checkstrike
    517  jsr checkstab ;Check for sword strikes
    518 :1
    519  jsr addsfx ;Add additional sound fx
    520 
    521  jsr chgmeters ;Change strength meters
    522 
    523  jsr cutcheck ;Has kid moved offscreen?
    524   jsr PrepCut ;If so, prepare to cut to new screen
    525 
    526  jsr cutguard ;If guard has fallen offscreen, vanish him
    527 
    528  do EditorDisk
    529  rts
    530  fin
    531 
    532 * Level 0 (Demo): When kid exits screen 24, end demo
    533 
    534  lda level
    535  bne :no0
    536  lda KidScrn
    537  cmp #24
    538  bne :cont
    539  jmp GOATTRACT
    540 
    541 * Level 6: When kid falls off screen 1, cut to next level
    542 
    543 :no0 do DemoDisk
    544  else
    545 
    546  lda level
    547  cmp #6
    548  bne :no6
    549  lda KidScrn
    550  cmp #1
    551  bne :cont
    552  lda KidY
    553  cmp #20
    554  bcs :cont
    555  lda #-1
    556  sta KidY
    557  inc NextLevel
    558  jmp :cont
    559 
    560 * Level 12: When kid exits screen 23, cut to next level
    561 
    562 :no6 cmp #12
    563  bne :cont
    564  lda KidScrn
    565  cmp #23
    566  bne :cont
    567  inc NextLevel
    568  lda #1
    569  sta skipmessage ;but don't announce level #
    570  jmp LoadNext1 ;or show time
    571 
    572  fin
    573 
    574 * Continue...
    575 
    576 :cont lda level
    577  cmp #14
    578  bcs :stopped
    579  cmp #13
    580  bcc :ticking
    581  lda exitopen
    582  bne :stopped ;Timer stops when you kill Vizier on level 13
    583 
    584 :ticking jsr keeptime
    585 
    586 :stopped jsr showtime ;if timerequest <> 0
    587 
    588  lda level
    589  cmp #13
    590  bcs :safe ;You have one chance to finish Level 13
    591 ;after time runs out
    592  lda MinLeft
    593  ora SecLeft
    594  bne :safe
    595  jmp YouLose ;time's up--you lose
    596 :safe
    597 ]rts rts
    598 
    599 *-------------------------------
    600 *
    601 *  F R A M E   A D V A N C E
    602 *
    603 *  Draw new frame (on hidden hi-res page) & show it
    604 *
    605 *-------------------------------
    606 FrameAdv
    607  lda cutplan ;set by PrepCut
    608  bne :cut
    609 
    610  jsr DoFast
    611  jmp PageFlip ;Update current screen...
    612 
    613 :cut jmp DoCleanCut ;or draw new screen from scratch
    614 
    615 *-------------------------------
    616 *
    617 *  F I R S T   F R A M E
    618 *
    619 *  Generate & display first frame
    620 *
    621 *-------------------------------
    622 FirstFrame
    623  lda KidScrn
    624  sta cutscrn
    625 
    626  jsr PrepCut
    627 
    628  jmp DoCleanCut
    629 
    630 *-------------------------------
    631 *
    632 *  D O   K I D
    633 *
    634 *  Update kid
    635 *
    636 *-------------------------------
    637 DoKid
    638  jsr LoadKidwOp ;Load kid as character (w/opponent)
    639 
    640  jsr rereadblocks
    641 
    642  jsr unholy ;If shadowman dies, kid dies
    643 
    644  jsr ctrlplayer ;Detect & act on commands from player
    645 
    646  lda invert
    647  beq :3
    648  lda CharLife
    649  bmi :3
    650  lda #2
    651  sta redrawflg
    652  lda #0
    653  sta invert
    654  jmp inverty ;Screen flips back rightside up when you're dead
    655 :3
    656  jsr wtlessflash
    657 
    658  lda CharScrn
    659  beq :skip ;Skip all this if kid is on null screen:
    660 
    661  jsr animchar ;Get next frame from sequence table
    662 
    663  jsr gravity ;Adjust Y-velocity
    664  jsr addfall ;Add falling velocity
    665 
    666  jsr setupchar
    667  jsr rereadblocks
    668  jsr getedges
    669 
    670  jsr firstguard ;Check for collision w/guard
    671 
    672  jsr checkbarr ;Check for collisions w/vertical barriers
    673 
    674  jsr collisions ;React to collisions detected above
    675 
    676  jsr checkgate ;Knocked to side by closing gate?
    677 
    678  jsr  checkfloor ;Is there floor underfoot?  If not, fall
    679 
    680  jsr  checkpress ;Is kid stepping on a pressure plate?
    681 ;If so, add pressplate (& whatever it
    682 ;triggers) to trans list.
    683 
    684  jsr checkspikes  ;Trigger spikes?
    685 
    686  jsr checkimpale ;impaled by spikes?
    687  jsr checkslice ;sliced by slicer?
    688 :1
    689  jsr shakeloose ;shake loose floors
    690 
    691 :skip jsr SaveKid ;Save all changes to char data
    692 ]rts rts
    693 
    694 *-------------------------------
    695 *
    696 *  D O   S H A D
    697 *
    698 *  Update shadowman (or other opponent)
    699 *
    700 *-------------------------------
    701 DoShad
    702  lda ShadFace
    703  cmp #86
    704  beq ]rts ;"no character" code
    705 
    706  jsr LoadShadwOp
    707  jsr rereadblocks
    708 
    709  jsr unholy
    710 
    711  jsr ShadCtrl ;Opponent control module
    712 
    713  lda CharScrn
    714  cmp VisScrn
    715  bne :os
    716 
    717  jsr animchar
    718 
    719  lda CharX
    720  cmp #ScrnLeft-14
    721  bcc :os
    722  cmp #ScrnRight+14
    723  bcs :os ;Skip all this if char is offscreen
    724 
    725  jsr gravity
    726  jsr addfall
    727 
    728  jsr setupchar
    729  jsr rereadblocks
    730  jsr getedges
    731 
    732  jsr enemycoll
    733 
    734  jsr  checkfloor
    735  jsr  checkpress
    736  jsr checkspikes
    737  jsr checkimpale
    738   jsr checkslice2
    739 
    740 :os jmp SaveShad
    741 
    742 *-------------------------------
    743 *
    744 *  Add all visible characters to object table
    745 *
    746 *-------------------------------
    747 addchars
    748  jsr :reflection
    749  jsr :shadowman
    750  jsr :kid
    751 
    752  jsr checkmeters
    753 
    754 ]rts rts
    755 
    756 *-------------------------------
    757 * Draw kid's reflection in mirror
    758 
    759 :reflection
    760  jmp reflection
    761 
    762 *-------------------------------
    763 * Draw shadowman or other opponent
    764 
    765 :shadowman
    766  lda ShadFace
    767  cmp #86 ;Is there a shadowman?
    768  beq ]rts ;no
    769  lda ShadScrn
    770  cmp VisScrn ;Is he visible?
    771  bne ]rts ;no
    772 
    773  jsr setupshad ;Add shadowman to object table
    774 
    775  lda ChgOppStr
    776  bpl :s1
    777  jsr setupcomix ;Add impact star if he's been hurt
    778 :s1 jmp setupsword ;Add sword
    779 
    780 *-------------------------------
    781 * Draw kid
    782 
    783 :kid lda KidScrn
    784  beq ]rts
    785  cmp VisScrn
    786  bne ]rts
    787 
    788  jsr setupkid ;Add kid to obj table
    789 
    790  lda ChgKidStr
    791  bpl :s2
    792  jsr setupcomix ;Add impact star
    793 :s2 jmp setupsword ;Add sword
    794 
    795 *-------------------------------
    796 *
    797 *  S E T   U P   K I D
    798 *
    799 *  Add kid to object table
    800 *  Crop edges, index char, mark fredbuf/floorbuf
    801 *
    802 *-------------------------------
    803 setupkid
    804  jsr LoadKid
    805  jsr rereadblocks
    806 
    807  lda CharPosn
    808  bne :cont ;Delay loop if CharPosn = 0
    809  lda #25
    810  jmp pause
    811 
    812 :cont jsr setupchar
    813  jsr unevenfloor
    814 
    815  jsr getedges
    816  jsr indexchar
    817  jsr quickfg
    818  jsr quickfloor
    819  jsr cropchar
    820 
    821  jmp addkidobj ;add kid to obj table
    822 
    823 *-------------------------------
    824 *
    825 *  S E T   U P   S H A D
    826 *
    827 *  Add shadowman to obj table
    828 *
    829 *-------------------------------
    830 setupshad
    831  jsr LoadShad
    832  jsr rereadblocks
    833 
    834  jsr setupchar
    835  jsr unevenfloor
    836 
    837  jsr getedges
    838  jsr indexchar
    839  jsr quickfg
    840  jsr quickfloor
    841  jsr cropchar
    842 
    843  lda CharID
    844  cmp #1 ;Shadowman?
    845  bne :1 ;no
    846  lda level
    847  cmp #mirlevel
    848  bne :2
    849  lda CharScrn
    850  cmp #mirscrn
    851  bne :2
    852  lda #mirx ;Clip shadman at L as he jumps out of mirror
    853  asl
    854  asl
    855  clc
    856  adc #1
    857  sta FCharCL
    858 :2 jmp addshadobj
    859 
    860 :1 jmp addguardobj
    861 
    862 *-------------------------------
    863 *
    864 *  Cut to new screen
    865 *
    866 *  DoQuickCut: Show bg before adding characters
    867 *  DoCleanCut: Show frame only when complete
    868 *
    869 *-------------------------------
    870 UseQuick = 0
    871 
    872  do UseQuick
    873 
    874 DoQuickCut
    875  jsr fastspeed ;IIGS
    876 
    877  lda #0
    878  sta PAGE
    879  jsr drawbg ;draw bg on p1
    880 
    881  jsr PageFlip
    882 
    883  jsr copyscrn ;copy bg to p2
    884  jsr DoFast ;add chars
    885 
    886  jsr PageFlip ;show complete frame
    887  jmp normspeed
    888 
    889  else
    890 
    891 DoCleanCut
    892  jsr fastspeed ;IIGS
    893 
    894  lda #$20
    895  sta PAGE
    896  jsr drawbg ;draw bg on p2
    897 
    898  lda #0
    899  sta PAGE
    900  jsr copyscrn ;copy bg to p1
    901 
    902  jsr DoFast ;add chars
    903 
    904 ;jsr vblank2
    905  jsr PageFlip
    906  jmp normspeed
    907 
    908  fin
    909 
    910 *-------------------------------
    911 *
    912 *  D R A W   B G
    913 *
    914 *  Clear screen & draw background (on hidden hi-res page)
    915 *  Show black lo-res screen to cover transition
    916 *
    917 *-------------------------------
    918 drawbg
    919  lda #0
    920  sta cutplan
    921 
    922  lda #2
    923  sta CUTTIMER ;min # of frames between cuts
    924 
    925  lda #" "
    926  jsr lrclse
    927  jsr vblank
    928  lda PAGE2off
    929  lda TEXTon
    930 
    931  jsr DoSure ;draw b.g. w/o chars
    932 
    933  jmp markmeters ;mark strength meters
    934 
    935 *-------------------------------
    936 *
    937 *  D O   S U R E
    938 *
    939 *  Clear screen and redraw entire b.g. from scratch
    940 *
    941 *-------------------------------
    942 DoSure
    943  lda VisScrn
    944  sta SCRNUM
    945 
    946  jsr zerolsts ;zero image lists
    947 
    948  jsr sure ;Assemble image lists
    949 
    950  jsr zeropeels ;Zero peel buffers
    951  jsr zerored ;and redraw buffers
    952 ;(for next DoFast call)
    953 
    954  jmp drawall ;Dump contents of image lists to screen
    955 
    956 *-------------------------------
    957 *
    958 *  D O  F A S T
    959 *
    960 *  Do a fast screen update
    961 *  (Redraw objects and as little of b.g. as possible)
    962 *
    963 *-------------------------------
    964 DoFast
    965  jsr zerolsts ;zero image lists
    966 
    967  lda VisScrn
    968  sta SCRNUM
    969 
    970  jsr develpatch
    971 
    972  jsr addmobs ;Add MOBS to object list
    973 
    974  jsr addchars ;Add characters to object list
    975 ;(incl. strength meters)
    976 
    977  jsr fast ;Assemble image lists (including objects
    978 ;from obj list and necessary portions of bg)
    979 
    980  jsr dispmsg ;Superimpose message (if any)
    981 :1
    982  jmp drawall ;Dump contents of image lists to screen
    983 ]rts rts
    984 
    985 *-------------------------------
    986 *
    987 *  Lightning flashes
    988 *
    989 *-------------------------------
    990 flashon
    991  lda lightning
    992  beq :1
    993  lda lightcolor
    994  bne :2
    995 :1 lda ChgKidStr
    996  bpl ]rts
    997  lda #$11 ;Flash red if kid's been hurt
    998 :2 jmp doflashon
    999 
   1000 flashoff
   1001  lda lightning
   1002  beq :1
   1003  dec lightning
   1004  bpl :2
   1005 
   1006 :1 lda ChgKidStr
   1007  bpl ]rts
   1008 :2 jmp doflashoff
   1009 
   1010 *-------------------------------
   1011 *
   1012 *  Initialize collision detection buffers
   1013 *
   1014 *-------------------------------
   1015 initCDbuf
   1016  ldx #9
   1017  lda #$ff
   1018 :zloop sta SNlastframe,x
   1019  sta SNthisframe,x
   1020  sta SNbelow,x
   1021  sta SNabove,x
   1022  dex
   1023  bpl :zloop
   1024 
   1025  sta BlockYlast
   1026 ]rts rts
   1027 
   1028 *-------------------------------
   1029 *
   1030 *  Prepare to cut?
   1031 *
   1032 *  In: VisScrn = current screen
   1033 *      cutscrn = screen we want to be on
   1034 *
   1035 *  If cutscrn <> VisScrn, make necessary preparations
   1036 *  & return cutplan = 1
   1037 *
   1038 *-------------------------------
   1039 PrepCut
   1040  lda cutscrn
   1041  beq ]rts ;never cut to screen 0
   1042  cmp VisScrn
   1043  beq ]rts ;If cutscrn = VisScrn, we don't need to cut
   1044 
   1045  lda cutscrn
   1046  sta VisScrn
   1047  cmp #5
   1048  bne :1
   1049  lda level
   1050  cmp #14
   1051  bne :1
   1052  jmp YouWin ;Level 14, screen 5 is princess's room--you win!
   1053 
   1054 :1 lda #1
   1055  sta cutplan
   1056 
   1057  jsr getscrns ;Get neighboring screen #s
   1058 
   1059  jsr LoadKid
   1060  jsr addslicers
   1061  jsr addtorches
   1062  jsr crumble ;Activate slicers, torches, etc.
   1063 
   1064  jmp addguard ;Add guard (if any)
   1065 
   1066 *-------------------------------
   1067 *
   1068 *  Time's up--you lose
   1069 *
   1070 *-------------------------------
   1071 YouLose
   1072  jsr cutprincess ;cut to princess's room...
   1073  lda #6
   1074  jsr playcut ;& play cut #6
   1075 
   1076  jmp GOATTRACT ;go to title sequence
   1077 
   1078 *-------------------------------
   1079 *
   1080 *  You win
   1081 *
   1082 *-------------------------------
   1083 YouWin jsr cutprincess
   1084  lda #7
   1085  jsr playcut ;Play cut #7
   1086  jmp epilog ;Play epilog (& hang)
   1087 
   1088 *-------------------------------
   1089 *
   1090 *  Control player
   1091 *
   1092 *  In/out: Char vars
   1093 *
   1094 *-------------------------------
   1095 ctrlplayer
   1096  jsr kill0 ;If char is on screen 0, kill him off
   1097 
   1098  jsr PlayerCtrl ;Control player
   1099 
   1100  lda CharLife
   1101  bmi ]rts ;If char is still alive, return
   1102 
   1103 * When player dies, CharLife is set to 0.
   1104 * Inc CharLife until = #deadenough; then put up message
   1105 
   1106 :dead lda CharPosn
   1107  jsr cold?
   1108  bne ]rts ;wait till char has stopped moving
   1109 
   1110  lda CharLife
   1111  bne :inc
   1112  jsr deathsong ;cue death music
   1113 
   1114 :inc lda CharLife
   1115  cmp #deadenough
   1116  bcs :deadenough
   1117  inc CharLife
   1118 ]rts rts
   1119 
   1120 :deadenough
   1121  lda level
   1122  beq :gameover ;Your death ends demo
   1123 
   1124  lda SongCue
   1125  bne ]rts ;wait for song to finish before putting up msg
   1126 
   1127  lda MinLeft
   1128  ora SecLeft
   1129  bne :timeleft
   1130  jmp YouLose ;if you die with time = 0, you lose
   1131 
   1132 * Otherwise: "Press Button to Continue"
   1133 
   1134 :timeleft
   1135  lda message
   1136  cmp #ContMsg
   1137  bne :1
   1138  lda msgtimer
   1139  bne :ok
   1140 
   1141 :1 lda #ContMsg
   1142  sta message
   1143  lda #255
   1144  sta msgtimer ;Put up continue message
   1145 
   1146 :ok cmp #1
   1147  beq :gameover ;End game when msgtimer = 1
   1148 
   1149  do FinalDisk
   1150  else
   1151 
   1152  lda develment
   1153  beq :nodevel
   1154  lda keypress
   1155  cmp #kresurrect
   1156  beq :raise ;TEMP!
   1157 :nodevel
   1158  fin
   1159 
   1160  lda BTN0
   1161  ora BTN1
   1162  bpl ]rts
   1163  jmp RESTART ;Button press restarts level
   1164 
   1165 :gameover
   1166  do EditorDisk
   1167  jmp RESTART
   1168  else
   1169  jmp GOATTRACT
   1170  fin
   1171 
   1172 * Raise kid from the dead (TEMP!)
   1173 
   1174  do FinalDisk
   1175  else
   1176 :raise
   1177  lda #0
   1178  sta msgtimer
   1179  sta SongCue
   1180 
   1181  lda #BTLtimer
   1182  sta backtolife
   1183 
   1184  jsr LoadKid
   1185 
   1186  lda MaxKidStr
   1187  sta ChgKidStr
   1188 
   1189  lda #stand
   1190  jsr jumpseq
   1191  jmp startkid1
   1192 
   1193  fin
   1194 
   1195 *-------------------------------
   1196 *
   1197 * Play death song
   1198 *
   1199 *-------------------------------
   1200 deathsong
   1201  lda ShadID
   1202  cmp #1
   1203  beq :shad ;if opponent was shadowman
   1204  lda heroic ;was kid engaged in battle at time of death?
   1205  bne :1 ;yes--"heroic death" music
   1206  lda #s_Accid ;no--"accidental death" music
   1207  bne :2
   1208 :shad lda #s_Shadow
   1209  bne :2
   1210 :1 lda #s_Heroic
   1211 :2 ldx #255
   1212  jmp cuesong
   1213 ]rts rts
   1214 
   1215 *-------------------------------
   1216 *
   1217 * If char is on screen 0, kill him off
   1218 *
   1219 *-------------------------------
   1220 kill0
   1221  lda CharLife
   1222  bpl ]rts
   1223  lda CharScrn
   1224  bne ]rts
   1225  lda #Splat
   1226  jsr addsound
   1227  lda #100
   1228  jsr decstr
   1229  lda #0
   1230  sta msgtimer
   1231  sta CharLife
   1232  lda #185
   1233  sta CharPosn
   1234 ]rts rts
   1235 
   1236 *-------------------------------
   1237 *
   1238 * Go to attract mode
   1239 *
   1240 *-------------------------------
   1241 GOATTRACT
   1242  do DemoDisk
   1243  else
   1244 
   1245  lda BBundID
   1246  cmp #POPside1 ;does he need to flip disk?
   1247  beq :ok ;no
   1248 
   1249  do ThreeFive
   1250  else
   1251  lda BGset1
   1252  bpl :flip
   1253  ldx #4
   1254  jsr LoadLevelX ;get "FLIP DISK" msg into memory
   1255  fin
   1256 
   1257 :flip jsr flipdisk ;ask him to flip disk
   1258 
   1259  fin
   1260 
   1261  lda #POPside1
   1262  sta BBundID
   1263 
   1264 :ok jmp attractmode
   1265 
   1266 *-------------------------------
   1267 *
   1268 *  Shake loose floors when character jumps
   1269 *
   1270 *-------------------------------
   1271 shakeloose
   1272  lda jarabove
   1273  bmi :jarbelow
   1274  bne :jarabove
   1275 ]rts rts
   1276 
   1277 :jarbelow
   1278  lda #0
   1279  sta jarabove
   1280 
   1281  lda CharBlockY
   1282  jmp shakem ;shake every loose floorboard on level
   1283 
   1284 :jarabove
   1285  lda #0
   1286  sta jarabove
   1287 
   1288  lda CharBlockY
   1289  sec
   1290  sbc #1
   1291  jmp shakem
   1292 
   1293 *-------------------------------
   1294 *
   1295 * If strength meters have changed, mark affected
   1296 * blocks for redraw
   1297 *
   1298 *-------------------------------
   1299 checkmeters
   1300  lda ChgKidStr
   1301  beq :1
   1302  jsr MarkKidMeter
   1303 
   1304 :1 lda ChgOppStr
   1305  beq ]rts
   1306  jmp MarkOppMeter
   1307 
   1308 *-------------------------------
   1309 *
   1310 * Change strength meters as specified
   1311 *
   1312 *-------------------------------
   1313 chgmeters
   1314  lda level
   1315  cmp #12
   1316  bne :cont
   1317  lda OpID
   1318  ora CharID
   1319  cmp #1 ;kid vs. shadowman?
   1320  bne :cont
   1321  ;yes
   1322  lda ChgKidStr
   1323  bpl :1
   1324  sta ChgOppStr
   1325  bne :cont
   1326 
   1327 :1 lda ChgOppStr
   1328  bpl :cont
   1329  sta ChgKidStr
   1330 
   1331 * Kid's meter
   1332 
   1333 :cont lda KidStrength
   1334  clc
   1335  adc ChgKidStr
   1336 
   1337  cmp MaxKidStr
   1338  beq :ok1
   1339  bcs :opp
   1340 
   1341 :ok1 sta KidStrength
   1342 
   1343 * Opponent's meter
   1344 
   1345 :opp lda OppStrength
   1346  clc
   1347  adc ChgOppStr
   1348 
   1349  cmp MaxOppStr
   1350  beq :ok2
   1351  bcs ]rts
   1352 
   1353 :ok2 sta OppStrength
   1354 ]rts rts
   1355 
   1356 *-------------------------------
   1357 *
   1358 * Slam player's entrance shut (add it to trans list)
   1359 *
   1360 *-------------------------------
   1361 entrance
   1362  lda KidScrn
   1363  jsr calcblue
   1364 
   1365  ldy #29
   1366 
   1367 :loop lda (BlueType),y
   1368  and #idmask
   1369  cmp #exit
   1370  bne :cont ;find player's entrance
   1371 
   1372  lda KidScrn
   1373  jmp closeexit ;& return
   1374 
   1375 :cont dey
   1376  bpl :loop
   1377 
   1378 ]rts rts
   1379 
   1380 *-------------------------------
   1381 *
   1382 * Play song cues
   1383 *
   1384 * In: SongCue (0 = none, non0 = song #)
   1385 *     SongCount
   1386 *
   1387 *-------------------------------
   1388 songcues
   1389  do EditorDisk
   1390  rts
   1391  fin
   1392 
   1393  ldx SongCue
   1394  beq ]rts
   1395  lda level
   1396  beq ]rts ;no music in demo
   1397 
   1398  lda SongCount
   1399  bne :cont
   1400  lda #0
   1401  sta SongCue ;when SongCount reaches 0, forget it
   1402 ]rts rts
   1403 :cont dec SongCount
   1404 
   1405  lda KidPosn
   1406  bne :1
   1407  lda NextLevel
   1408  cmp level
   1409  beq ]rts ;Play only one song once kid has reached stairs
   1410 
   1411 :1 lda KidPosn
   1412  jsr static?
   1413  bne ]rts
   1414 
   1415  lda ShadFace
   1416  cmp #86
   1417  beq :ok
   1418  lda ShadScrn
   1419  cmp VisScrn
   1420  bne :ok
   1421  lda ShadPosn
   1422  jsr static?
   1423  bne ]rts
   1424 :ok
   1425  lda trobcount ;(set by animtrans if there are any
   1426  bne ]rts ;slicers or other fast-moving objects
   1427 ;that it wouldn't look good to freeze)
   1428  lda nummob
   1429  bne ]rts
   1430  lda lightning
   1431  bne ]rts ;wait for no MOBs and no lightning
   1432  lda mergetimer
   1433  bmi :ok2
   1434  bne ]rts
   1435  lda ChgKidStr
   1436  ora ChgOppStr
   1437  bne ]rts ;& no impact stars
   1438 :ok2
   1439 
   1440 * Prepare for minimal animation
   1441 
   1442  lda PAGE
   1443  eor #$20
   1444  sta PAGE
   1445 
   1446  jsr listtorches
   1447 
   1448 * Play song
   1449 
   1450  lda SongCue
   1451  jsr minit
   1452 
   1453  sta $c010 ;clr kbd
   1454 
   1455 :loop jsr burn
   1456  jsr musickeys
   1457 
   1458  jsr mplay
   1459  cmp #0
   1460  bne :loop
   1461 
   1462 :done lda #0
   1463  sta SongCue
   1464 
   1465 :rtn lda PAGE
   1466  eor #$20
   1467  sta PAGE
   1468 
   1469  jmp clearjoy
   1470 
   1471 *-------------------------------
   1472 *
   1473 * Add additional sound fx
   1474 *
   1475 *-------------------------------
   1476 addsfx
   1477  lda #167 ;blocked strike
   1478  cmp KidPosn ;if char is striking...
   1479  bne :1
   1480  lda #SwordClash1
   1481  bne :clash
   1482 :1 cmp ShadPosn
   1483  bne :2
   1484  lda #SwordClash2
   1485 :clash jmp addsound
   1486 :2
   1487 ]rts rts
   1488 
   1489 *-------------------------------
   1490 *
   1491 * Display message ("Press button to continue" or "Level #"
   1492 * or "# minutes left")
   1493 *
   1494 *-------------------------------
   1495 dispmsg
   1496  lda msgtimer
   1497  beq ]rts
   1498  dec msgtimer
   1499 
   1500  lda KidLife
   1501  bmi :alive
   1502 
   1503 * Kid is dead -- message is "Press button to continue"
   1504 
   1505  lda msgtimer
   1506  cmp #contoff
   1507  bcc ]rts
   1508 
   1509  cmp #contflash
   1510  bcs :steady
   1511 
   1512  and #7
   1513  cmp #3
   1514  bcs ]rts
   1515  cmp #2
   1516  bne :steady
   1517 
   1518  lda soundon
   1519  bne :2
   1520  jsr gtone ;if sound off
   1521 :2 lda #FlashMsg
   1522  jsr addsound
   1523 
   1524 :steady jmp continuemsg ;Kid is dead--superimpose continue msg
   1525 
   1526 * Kid is alive -- message is "Level #" or "# Minutes"
   1527 
   1528 :alive lda msgtimer
   1529  cmp #leveltimer-2
   1530  bcs ]rts
   1531 
   1532  lda message
   1533  cmp #LevelMsg
   1534  bne :1
   1535  jmp printlevel
   1536 
   1537 :1 cmp #TimeMsg
   1538  bne ]rts
   1539  jmp timeleftmsg
   1540 
   1541 *-------------------------------
   1542 *
   1543 * Display "Turn disk over" and wait for button press
   1544 *
   1545 *-------------------------------
   1546 flipdisk
   1547  do ThreeFive
   1548  lda #1
   1549  sta purpleflag ;pass copy-protect!
   1550  rts
   1551  fin
   1552 
   1553  do DemoDisk
   1554  jmp GOATTRACT
   1555  else
   1556 
   1557 * 1st copy protection check
   1558 
   1559  lda redherring
   1560  eor redherring2
   1561  cmp #POPside1 ;passed 1st check?
   1562  beq :1
   1563  lda #POPside1
   1564  sta BBundID
   1565   jmp attractmode
   1566 
   1567 * Passed copy protection--continue
   1568 
   1569 :1 lda #" "
   1570  jsr lrcls
   1571 
   1572  jsr zerolsts
   1573  jsr zeropeels
   1574  lda #1
   1575  sta genCLS
   1576 
   1577  jsr flipdiskmsg
   1578 
   1579  jsr drawall
   1580 
   1581  jsr vblank
   1582  jsr PageFlip
   1583 
   1584  lda $c010 ;clr kbd strobe
   1585 :loop
   1586  lda $c061
   1587  ora $c062
   1588  ora $c000
   1589  bpl :loop
   1590 
   1591  fin
   1592 
   1593 * Flip to clr text scrn
   1594 
   1595 showtext jsr vblank
   1596  lda PAGE2off
   1597  lda TEXTon
   1598 ]rts rts
   1599 
   1600 *-------------------------------
   1601 *
   1602 * Is character moving?
   1603 *
   1604 * In: A = CharPosn
   1605 * Out: 0 if static, 1 if moving
   1606 *
   1607 *-------------------------------
   1608 static?
   1609  cmp #0
   1610  beq ]ok
   1611  cmp #15 ;stand
   1612  beq ]ok
   1613  cmp #229 ;brandish sword
   1614  beq ]ok
   1615  cmp #109 ;crouching
   1616  beq ]ok
   1617  cmp #171 ;en garde
   1618  beq ]ok
   1619  cmp #166 ;alert stand (for gd.)
   1620  beq ]ok
   1621 cold?
   1622  cmp #185 ;dead
   1623  beq ]ok
   1624  cmp #177 ;impaled
   1625  beq ]ok
   1626  cmp #178 ;halves
   1627  beq ]ok
   1628  lda #1
   1629  rts
   1630 ]ok lda #0
   1631 ]rts rts
   1632 
   1633 *-------------------------------
   1634 *
   1635 * Clear all jstk flags
   1636 *
   1637 *-------------------------------
   1638 clearjoy
   1639  jsr LoadSelect
   1640  lda #0
   1641  sta clrF
   1642  sta clrB
   1643  sta clrU
   1644  sta clrD
   1645  jmp SaveSelect
   1646 
   1647 *-------------------------------
   1648 *
   1649 *  Misc. timers (Call every cycle)
   1650 *
   1651 *-------------------------------
   1652 misctimers
   1653  lda mergetimer
   1654  beq :3
   1655  bmi :3
   1656  dec mergetimer
   1657  bne :3
   1658  dec mergetimer ;goes from 1 to -1
   1659 :3
   1660 
   1661 * Level 8: When you've spent a certain amount of time on
   1662 * screen 16 once exit is open, mouse rescues you
   1663 
   1664  lda level
   1665  cmp #8 ;mouse level
   1666  bne :12
   1667  lda CharScrn
   1668  cmp #16
   1669  bne :12
   1670  lda exitopen
   1671  beq :12
   1672  cmp #mousetimer
   1673  bcc :11
   1674  bne :12
   1675 :10 jsr mouserescue
   1676 :11 inc exitopen
   1677 :12
   1678 ]rts rts
   1679 
   1680 *-------------------------------
   1681 *
   1682 *  Screen flashes towards end of weightlessness period
   1683 *
   1684 *-------------------------------
   1685 wtlessflash
   1686  lda weightless
   1687  beq ]rts
   1688  ldx #0
   1689  sec
   1690  sbc #1
   1691  sta weightless
   1692  beq :3
   1693  ldx #$ff
   1694  cmp #wtlflash
   1695  bcs :3
   1696  lda vibes
   1697  eor #$ff
   1698  tax
   1699 :3 stx vibes ;Screen flashes as weightlessness ends
   1700 ]rts rts
   1701 
   1702 *-------------------------------
   1703 * yellow copy protection
   1704 * (call right before 1st princess cut)
   1705 * In: A = next level
   1706 *-------------------------------
   1707 yellowcheck
   1708  cmp #2
   1709  bne ]rts
   1710  jsr showtext
   1711  ldx #10
   1712  jmp yellow ;in gamebg
   1713  ;sets yellowflag ($7c) hibit
   1714 
   1715 *-------------------------------
   1716 *
   1717 *  Temp development patch for screen redraw
   1718 *  (also used for invert Y)
   1719 *
   1720 *-------------------------------
   1721 develpatch
   1722  do 0
   1723  lda blackflag ;blackout?
   1724  beq :1
   1725  lda #1
   1726  sta genCLS
   1727  fin
   1728 
   1729 :1 lda redrawflg ;forced redraw?
   1730  beq ]rts
   1731  dec redrawflg
   1732 
   1733  jsr markmeters
   1734  jmp sure
   1735 
   1736 *-------------------------------
   1737  lst
   1738  ds 1
   1739  usr $a9,4,$a00,*-org
   1740  lst off