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 (25807B)


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