* auto DemoDisk = 0 org = $5400 tr on lst off *------------------------------- * * PRINCE OF PERSIA * Copyright 1989 Jordan Mechner * *------------------------------- org org jmp AUTOCTRL jmp CHECKSTRIKE jmp CHECKSTAB jmp AUTOPLAYBACK jmp CUTCHECK jmp CUTGUARD jmp ADDGUARD jmp CUT *------------------------------- lst put eq lst put gameeq lst put seqdata lst put soundnames lst put movedata lst off dum $f0 ztemp ds 1 prob ds 1 ]cutdir ds 1 ProgStart ds 2 dend plus1 db -1,1 minus1 db 1,-1 * Thresholds for cut to new screen TopCutEdgePl = ScrnTop+10 TopCutEdgeMi = ScrnTop-16 BotCutEdge = ScrnBottom+24 LeftCutEdge = ScrnLeft-4 RightCutEdge = ScrnRight+4 *------------------------------- * Locations of special objects flaskscrn = 24 flaskx = 3 flasky = 0 mirscrn = 4 mirx = 4 miry = 0 swordscrn = 15 swordx = 1 swordy = 0 mousetimer = 150 ;from topctrl *------------------------------- * Strike/block ranges strikerange1 = 12 strikerange2 = 29 blockrange1 = 0 blockrange2 = 29 ;from TestStrike *------------------------------- * Other constants: swordthres = 90 engardethres = 60 strikethres1 = strikerange1 strikethres2 = strikerange2 blockthres1 = 10 blockthres2 = blockrange2 tooclose = strikethres1 toofar = strikethres2+6 ;min dist at which you can advance safely offguardthres = 8 jumpthres = 50 runthres = 40 blocktime = 4 *------------------------------- * * Fighter params (indexed by guardprog #) * * strikeprob = probability x255 of striking from ready posn * restrikeprob = prob x 255 of restriking after blocking * blockprob = prob x255 of blocking opponent's strike * advprob = of advancing to within striking range * refractimer = length of refractory period after being hit * * 0 1 2 3 4 5 6 7 8 9 10 11 strikeprob db 075,100,075,075,075,050,100,220,000,060,040,060 restrikeprob db 000,000,000,005,005,175,020,010,000,255,255,150 blockprob db 000,150,150,200,200,255,200,250,000,255,255,255 impblockprob db 000,075,075,100,100,145,100,250,000,145,255,175 advprob db 255,200,200,200,255,255,200,000,000,255,100,100 refractimer db 020,020,020,020,010,010,010,010,000,010,000,000 specialcolor db 000,000,000,001,000,001,001,000,000,000,000,001 extrastrength db 000,000,000,000,001,000,000,000,000,000,000,000 numprogs = 12 *------------------------------- * Basic guard strength & uniform color (indexed by level #) basicstrength db 4,3,3,3,3,4,5 ;levels 0-6 db 4,4,5,5,5,4,6 ;levels 7-13 basiccolor db 1,0,0,0,1,1,1 ;0 = blue, 1 = red db 0,0,0,1,1,0,0 shadstrength = 4 *------------------------------- * * 10: kid (demo) * 11: enemy (demo) * *------------------------------- * * Automatic enemy control routine * * In: Char vars reflect position in PRECEDING frame; * Op vars reflect position in UPCOMING frame * guardprog = program # * * (Exception: When used by kid fighting in demo, both * Char & Op vars reflect preceding frame.) * *------------------------------- ]rts rts AUTOCTRL jsr DoRelease lda CharID beq :5 ;control kid in demo lda justblocked beq :jb0 dec justblocked :jb0 lda gdtimer beq :gt0 dec gdtimer :gt0 lda refract ;refractory period after being hit beq :2 dec refract :2 lda CharID cmp #24 ;mouse? beq :6 cmp #4 ;skel? beq :3 cmp #2 ;guard? bcc :1 lda level cmp #13 ;vizier? beq :4 jmp GuardProg :1 jmp ShadowProg :3 jmp SkelProg :4 jmp VizierProg :5 jmp KidProg :6 jmp MouseProg *------------------------------- * M O U S E *------------------------------- MouseProg lda CharFace cmp #86 beq ]rts lda CharAction beq :1 ;already stopped lda CharX cmp #166 bcs ]rts lda #Mleave jsr jumpseq jmp animchar ;sets CharAction = 0 :1 lda CharX cmp #200 bcc ]rts jmp VanishChar *------------------------------- * S H A D O W M A N *------------------------------- do DemoDisk ShadowProg SkelProg VizierProg brk else ShadowProg lda level cmp #4 bne :0 jmp ShadLevel4 :0 cmp #5 bne :1 jmp ShadLevel5 :1 cmp #6 bne :2 jmp ShadLevel6 :2 cmp #12 bne :3 jmp FinalShad :3 ]rts rts *------------------------------- * Level-specific code for: * Level 6 (plunge) *------------------------------- ShadLevel6 lda CharScrn cmp #1 beq Shad6a rts * Level 6, screen 1 * When kid jumps chasm, step on plate Shad6a lda KidPosn cmp #43 bne ]rts lda KidX cmp #$80 bcs ]rts jsr DoPress jmp DoFwd ;step fwd *------------------------------- * Level 5 (THIEF) *------------------------------- ShadLevel5 lda CharScrn cmp #flaskscrn beq Shad5 ]rts rts * Level 5, screen 24 * When gate opens, steal potion Shad5 lda PlayCount bne :1 ;continue playback lda #flaskscrn ldx #1 ;x ldy #0 ;y jsr rdblock ;gate lda (BlueSpec),y cmp #20 bcc ]rts ;begin playback lda #0 sta PreRecPtr :1 lda #ShadProg5 ldx #>ShadProg5 jsr AutoPlayback lda CharX cmp #15 bcs ]rts jmp VanishChar *------------------------------- * Level 4 (mirror) *------------------------------- ShadLevel4 lda CharScrn cmp #4 bne ]rts lda CharX cmp #80 bcc :gone jmp DoFwd ;run o.s. :gone jmp VanishChar *------------------------------- * Level 12 (final battle) *------------------------------- FinalShad * Screen 15: Jump on top of kid lda CharScrn cmp #swordscrn bne :cont lda shadowaction bne :cont ;already did it lda OpX cmp #150 bcs :hold ;hold shad at top until kid arrives lda #1 sta shadowaction bne :cont :hold lda #shadpos12 ldx #>shadpos12 jmp csps ]rts rts * Continue :cont lda CharSword cmp #2 bcs :fight lda OpSword cmp #2 bcs :hostile lda offguard bne :face :hostile lda EnemyAlert cmp #2 bcc :2 jsr getopdist cmp #swordthres bcs :2 ;wait until kid gets close lda CharPosn cmp #15 bne ]rts jmp DoEngarde ;draw on kid * turn to face kid :2 jsr getopdist bpl ]rts jmp DoBack * Normal fighting :fight lda offguard beq :1 ;has kid put up sword? lda refract bne :1 ;yes--wait a moment-- jmp DoDown ;--then lower your guard :1 jmp EnGarde ;normal fighting * Face to face--swords down :face jsr getopdist bmi :merge ;whammo! lda EnemyAlert cmp #2 bne :wait lda OpPosn cmp #3 bcc :wait cmp #15 bcc :go cmp #127 bcc :wait cmp #133 bcs :wait * If kid starts moving towards you, reciprocate * (Accept startrun & stepfwd) :go jmp DoFwd * Kid & shadow reunite :merge lda #$ff ;white sta lightcolor lda #10 sta lightning jsr boostmeter lda #s_Rejoin ldx #85 jsr cuesong lda #42 sta mergetimer lda #0 sta CharID jsr SaveKid ;shadow turns into kid jmp VanishChar :wait ]rts rts *------------------------------- * S K E L E T O N *------------------------------- SkelProg lda #2 sta CharSword jmp GuardProg *------------------------------- * V I Z I E R *------------------------------- VizierProg jmp GuardProg fin ;DemoDisk *------------------------------- * K I D (in demo) *------------------------------- KidProg jmp GuardProg *------------------------------- * G U A R D *------------------------------- GuardProg lda CharSword cmp #2 ;Are you already en garde? bcc Alert ;no jmp EnGarde ;yes ]rts rts *------------------------------- * * Alert (not en garde) * *------------------------------- Alert lda KidLife bpl ]rts ;kid's dead--relax * If kid is behind you, turn to face him jsr getopdist ldx OpBlockY cpx CharBlockY bne :difflevel cmp #-8 ;if kid is right on top of you, go en garde! bcs :eng :difflevel ldx alertguard beq :ok ;otherwise wait for a sound to alert you ldx #0 stx alertguard :alert cmp #128 bcc :eng cmp #-4 bcs :ok ;overlapping--stand still jmp DoTurn ;turn around * If you can see kid, go en garde :ok cmp #128 bcs ]rts ;kid is behind you :eng lda EnemyAlert beq ]rts lda level cmp #13 bne :1 ;Vizier only: wait for music to finish lda SongCue bne ]rts :1 jmp DoEngarde ]rts rts *------------------------------- * * En garde * *------------------------------- EnGarde lda CharPosn cmp #166 beq ]rts cmp #150 bcc ]rts ;wait till you're ready lda EnemyAlert cmp #2 bcs :ea2 cmp #1 ;EnemyAlert = 1: Kid is in sight, but a beq ]rts ;gap or barrier separates you--stay put * Kid is out of sight (EnemyAlert = 0) * If kid has "dropped out" of fight, follow him down lda droppedout ;flag set by CHECKFLOOR beq :1 jmp FollowKid * else return to alert position :1 lda CharID cmp #4 beq ]rts ;(except skeleton) jmp DoDropguard * EnemyAlert = 2: Clear stretch of floor to player * If kid is stunned, let him recover... :ea2 jsr getopdist bmi :norec cmp #12 bcc :norec ;unless he's right on top of you lda OpPosn cmp #102 bcc :norec cmp #118 bcs :norec lda OpAction cmp #5 beq ]rts :norec * Advance to closest safe distance jsr getopdist cmp #toofar bcs :outofrange ldx CharSword cpx #2 bcc :offg cmp #tooclose bcc :tooclose jmp InRange :offg cmp #offguardthres bcc :tooclose jmp InRange ]rts rts * Out of range :outofrange lda refract bne ]rts lda CharFace cmp OpFace beq :nojump ;chase him lda OpPosn cmp #7 bcc :norun cmp #15 bcc :runwait :norun cmp #34 bcc :nojump cmp #44 bcc :jumpwait ;If kid is running towards you, stay put :nojump jsr getinfront jsr cmpspace ;Don't advance unless solid floor beq :gap jsr get2infront jsr cmpspace bne :solid :gap jmp DoRetreat :solid jmp DoAdvance * Kid is trying to get past you--cut him down! :jumpwait jsr getopdist cmp #jumpthres bcs ]rts ;wait jmp DoStrike :runwait jsr getopdist cmp #runthres bcs ]rts :strike jmp DoStrike * Too close to hit him :tooclose lda CharFace cmp OpFace beq :ret jmp DoAdvance :ret jmp DoRetreat *------------------------------- * * Kid has "dropped out" of fight * Advance until you run out of floor-- * then decide whether to jump down after him * *------------------------------- FollowKid lda OpAction cmp #2 beq :hanging cmp #6 beq :hanging ;wait--kid is hanging on ledge jsr getinfront sta ztemp jsr cmpbarr bne :stopped lda ztemp jsr cmpspace beq :atedge jmp DoAdvance * At edge of floor. Follow kid down ONLY if: * (1) it's a 1-story drop to solid floor * (2) kid is still down there :atedge jsr getinfront inc tempblocky jsr rdblock1 sta ztemp ;is it safe? cmp #spikes beq :stopped cmp #loose beq :stopped jsr cmpbarr bne :stopped lda ztemp jsr cmpspace beq :stopped lda CharBlockY clc adc #1 cmp OpBlockY bne :stopped ;kid's not down there * It looks safe--follow him down jmp DoAdvance :stopped lda #0 sta droppedout jmp DoRetreat ;so you can kill him if he climbs up :hanging ]rts rts *------------------------------- * * In range * *------------------------------- InRange lda OpSword ;is opponent armed & en garde? cmp #2 beq :fight ;yes * Opponent is unarmed or off guard--maul him! lda refract bne ]rts jsr getopdist cmp #strikethres2 bcc :1 jmp DoAdvance ;advance until within range... :1 jmp DoStrike ;then strike * Opponent is en garde--use strategy :fight jmp GenFight *------------------------------- * * General Fighting Routine * * (Fighters are en garde, face to face, and too close to * advance safely) * *------------------------------- GenFight jsr getopdist cmp #blockthres1 bcc :outofrange cmp #blockthres2 bcs :outofrange jsr MaybeBlock ;block opponent's strike? lda refract bne ]rts jsr getopdist cmp #strikethres1 bcc :outofrange cmp #strikethres2 bcs :outofrange jmp MaybeStrike ;strike? :outofrange jmp MaybeAdvance ;advance to within strike range? ]rts rts *------------------------------- * * Advance to within strike range? * (Only consider it if gdtimer = 0) * *------------------------------- MaybeAdvance lda guardprog beq :dumb ;Guard #0 is too dumb to care lda gdtimer bne ]rts :dumb jsr rndp cmp advprob,x bcs ]rts jmp DoAdvance *------------------------------- * * Block opponent's strike? * *------------------------------- MaybeBlock lda OpPosn cmp #152 ;guy4 beq :99 cmp #153 ;guy5 beq :99 cmp #162 ;guy22 (block to strike) bne ]rts :99 lda justblocked bne :impaired jsr rndp cmp blockprob,x bcc :block ]rts rts :impaired jsr rndp cmp impblockprob,x bcs ]rts :block jmp DoBlock *------------------------------- * * Strike? * *------------------------------- MaybeStrike ldx OpPosn cpx #169 beq ]rts cpx #151 ;opponent starting to strike? beq ]rts ;yes--don't strike ldx CharPosn cpx #161 ;have I just blocked? beq :restrike cpx #150 beq :restrike ;yes--restrike? jsr rndp cmp strikeprob,x bcs ]rts jmp DoStrike :restrike jsr rndp cmp restrikeprob,x bcs ]rts jmp DoStrike *------------------------------- DoRelease lda #0 sta clrF sta clrB sta clrU sta clrD sta clrbtn sta JSTKX sta JSTKY sta btn rts DoAdvance DoFwd lda #-1 sta clrF sta JSTKX rts DoRetreat DoBack lda #-1 sta clrB lda #1 sta JSTKX rts DoBlock DoUp lda #-1 sta clrU sta JSTKY rts DoTurn DoDown lda #-1 sta clrD lda #1 sta JSTKY rts DoStandup lda #-1 sta clrU jmp DoBack DoDropguard DoRunaway lda #-1 sta clrD jmp DoBack DoEngarde lda #-1 sta clrD jmp DoFwd DoStrike DoPress lda #-1 sta clrbtn sta btn rts DoRelBtn lda #0 sta btn ]rts rts *------------------------------- * * R N D P * * Return X = guardprog, A = rnd # * *------------------------------- rndp ldx guardprog jmp rnd *------------------------------- * * C H E C K S T R I K E * * Check for sword contact * * Going in: Kid & Shad vars represent position in * UPCOMING frame * * Out: Kid & Shad vars * (Return Action = 99 if stabbed) * *------------------------------- CHECKSTRIKE lda KidPosn beq ]rts cmp #219 bcc :noclimb cmp #229 bcc ]rts ;on staircase :noclimb jsr LoadShadwOp jsr TestStrike jsr SaveShadwOp jsr LoadKidwOp jsr TestStrike jsr SaveKidwOp ]rts rts *------------------------------- TestStrike lda CharSword cmp #2 ;in fighting mode? bne ]rts ;no lda CharBlockY cmp OpBlockY bne ]rts * Am I on a test (strike) frame? lda CharPosn cmp #153 ;guy5 (frame before full ext.) beq :test cmp #154 ;guy6 (full ext.) bne ]rts * I'm striking--is opponent blocking? :test jsr getopdist cmp #blockrange1 bcc :nobloc cmp #blockrange2 bcs :nobloc lda OpPosn cmp #161 beq :11 cmp #150 ;blocking? bne :nobloc ;no * Yes -- opponent blocks my strike :1 lda #161 sta OpPosn ;change opp to "successful block" :11 lda CharID beq :12 ;am I a guard? lda #blocktime ;yes--impair my blocking ability for a while sta justblocked :12 lda #blockedstrike jsr jumpseq jmp animchar * Skewer opponent? :nobloc lda CharPosn cmp #154 ;full ext bne ]rts jsr getopdist ldx OpSword cpx #2 bcs :ong cmp #offguardthres bcs :cont1 rts :ong cmp #strikerange1 bcc ]rts :cont1 cmp #strikerange2 bcs ]rts lda #99 "stabbed" sta OpAction ]rts rts *------------------------------- * C H E C K S T A B *------------------------------- CHECKSTAB lda ShadAction cmp #99 bne :1 lda KidAction cmp #99 beq :doublestab :2 jsr LoadShad jsr StabChar jsr SaveShad jsr rndp lda refractimer,x sta refract :1 lda KidAction cmp #99 bne ]rts jsr LoadKid jsr StabChar jmp SaveKid * Both chars finish lunge simultaneously :doublestab lda #1 sta KidAction bne :2 ;player wins a tie ]rts rts *------------------------------- * Change shadowman posn * In: A-X = shadpos L-H * Out: Char data *------------------------------- chgshadposn sta ztemp stx ztemp+1 ldy #6 :loop lda (ztemp),y sta Char,y dey bpl :loop ldy #7 lda (ztemp),y jsr jumpseq lda #1 sta CharID lda #0 sta PlayCount ;zero playback counter rts * ... & save csps jsr chgshadposn lda #3 sta guardprog lda #shadstrength sta MaxOppStr sta OppStrength jmp SaveShad *------------------------------- * (Posn, X, Y, Face, BlockX, BlockY, Action) * 0 1 2 3 4 5 6 shadpos6a hex 0f,51,76,00,00,01,00 db stand shadpos5 hex 0f,37,37,00,ff,00,00 db stand ;just o.s. to L shadpos12 hex 0f,51,f0,00,00,00,00 db stepfall *------------------------------- EndProg = -2 EndDemo = -1 Ctr = 0 Fwd = 1 Back = 2 Up = 3 Down = 4 Upfwd = 5 Press = 6 Release = 7 * Commands: * * -2 - end of programmed sequence * -1 - end of demo * 0 - center jstk & release btn * 1 - jstk fwd * 2 - jstk back * 3 - jstk up * 4 - jstk down * 5 - jstk up & fwd * 6 - press & hold btn * 7 - release btn *------------------------------- * * Prerecorded sequence format: * * 1. Frame # (1 byte) * 2. Command (1 byte) * * 255 frames = approx. 25-30 seconds * *------------------------------- * Level 5 (THIEF): Steal potion ShadProg5 db 0,Ctr db 1,Fwd db 14,Ctr db 18,Press db 29,Release db 45,Back db 49,Fwd db 255,EndProg *------------------------------- * * Play back prerecorded movement sequence * * In: A-X = program start addr * PlayCount = frame # * PreRecPtr = pointer to next command * *------------------------------- AUTOPLAYBACK sta ProgStart stx ProgStart+1 * Inc frame counter lda PlayCount cmp #254 bcs :rts inc PlayCount * Look up time of next command ldy PreRecPtr lda PlayCount cmp (ProgStart),y bcs :next * Not there yet--repeat last command dey lda (ProgStart),y jmp :ex * We're there-- :next iny lda (ProgStart),y ;command iny sty PreRecPtr * Execute command :ex cmp #-1 beq :enddemo cmp #0 beq :ctr cmp #1 beq :fwd cmp #2 beq :back cmp #3 beq :up cmp #4 beq :down cmp #5 beq :upfwd cmp #6 beq :press cmp #7 beq :release :rts ]rts rts * Commands :ctr jmp DoRelease :fwd jmp DoFwd :back jmp DoBack :up jmp DoUp :down jmp DoDown :upfwd jsr DoUp jmp DoFwd :press jmp DoPress :release jmp DoRelBtn :enddemo ; lda autopilot ; bne :endpb jmp attractmode ;Game: end demo :endpb ; lda #0 ;Editor: end playback ; sta autopilot ; rts *------------------------------- * * C U T C H E C K * * Cut with kid * *------------------------------- CUTCHECK lda CUTTIMER beq :ok dec CUTTIMER ]rts rts :ok jsr LoadKid jsr setupchar jsr getedges jsr cutchar ;cut with character bmi ]rts ;no cut sta ]cutdir jsr SaveKid lda CharScrn sta cutscrn lda ShadFace cmp #86 ;is there a guard on old screen? beq ]rts ;no * What to do with guard? Two choices: * * (1) UPDATE -- leave guard behind on old screen (& update * his coords so he'll still be there when we come back) * (2) TRANSFER -- transfer guard to new screen (& delete his * coords from old screen) lda ShadLife bpl :update ;dead guard on old screen--leave him behind lda ShadSword cmp #2 bne :update * Is there a live guard on new screen? ldx KidScrn lda GdStartBlock-1,x cmp #30 bcs :nonew ;no lda GdStartSeqH-1,x beq :update ;yes * If guard is too far o.s., leave him behind :nonew lda ]cutdir beq :left cmp #1 beq :right cmp #2 beq :up :down lda ShadBlockY cmp #3 bcs :transfer bcc :update :up lda ShadBlockY bmi :transfer bpl :update :right lda ShadX cmp #ScrnWidth+25 ;25 is safety factor bcc :update bcs :transfer :left lda ShadX cmp #256-ScrnWidth-25 bcs :update * Take him with us :transfer jmp transferguard * Leave him behind :update jmp updateguard *------------------------------- * * Transfer guard from old screen to new screen * (Also remove any dead guards from new scrn) * *------------------------------- transferguard lda #-1 ldx KidScrn ;new scrn sta GdStartBlock-1,x ldx ShadScrn ;old scrn sta GdStartBlock-1,x jsr LoadShad lda ]cutdir jsr cut jmp SaveShad ]rts rts *------------------------------- * * Leaving guard behind on old screen-- * update guard coords * *------------------------------- updateguard lda ShadFace cmp #86 beq ]rts ;no guard lda ShadID cmp #1 beq ]rts ;not for shadman cmp #24 beq ]rts ;or mouse :gd lda #0 ;arbitrary--ADDGUARD will reconstruct sta tempblockx ;CharBlockX from CharX lda ShadBlockY sta tempblocky jsr indexblock tya ldx ShadScrn sta GdStartBlock-1,x lda ShadX sta GdStartX-1,x lda ShadFace sta GdStartFace-1,x lda guardprog sta GdStartProg-1,x lda ShadLife bpl :ok lda #0 sta GdStartSeqH-1,x beq :cont :ok lda ShadSeq sta GdStartSeqL-1,x lda ShadSeq+1 sta GdStartSeqH-1,x * and deactivate enemy char :cont lda #86 sta ShadFace lda #0 sta OppStrength ]rts rts *------------------------------- * * If enemy has fallen to screen below, catch him before * he wraps around to top of VisScrn * *------------------------------- CUTGUARD lda ShadFace cmp #86 beq ]rts lda ShadY cmp #BotCutEdge bcc ]rts * If guard, remove him altogether lda ShadID cmp #4 beq :skel cmp #1 beq :shad ]RemoveGd jsr deadenemy ;music, etc. ldx VisScrn lda #-1 sta GdStartBlock-1,x lda #86 sta ShadFace lda #0 sta OppStrength lda #-1 sta ChgOppStr ]rts rts * If shad, vanish him :shad lda ShadAction cmp #4 bne ]rts jsr LoadShad jsr VanishChar jmp SaveShad * If skel, change scrn :skel lda ShadScrn jsr getdown sta ShadScrn cmp #3 bne ]RemoveGd * Skel lands on scrn 3 lda #Splat jsr addsound lda #$85 sta ShadX lda #1 sta ShadBlockY lda #0 sta ShadFace lda #-1 sta ShadLife jmp updateguard *------------------------------- * * C U T C H A R * * Is character passing o.s.? If so, cut with him to next scrn * * Change CharX,Y,BlockY,Scrn to reflect posn on new scrn * * Return A = direction of cut, -1 if no cut * *------------------------------- cutchar lda CharY ldx CharAction cpx #5 beq :notup cpx #4 beq :notup ;In freefall--cut only down cpx #3 beq :notup * Cut up/down? cmp #TopCutEdgePl bcc :CUTUP cmp #TopCutEdgeMi bcs :CUTUP :notup cmp #BotCutEdge bcs :CUTDOWN * Cut left/right? ldx CharPosn cpx #135 bcc :nocu cpx #150 bcc :nocut ;don't cut L/R on climbup :nocu cpx #110 bcc :nosu cpx #120 bcc :nocut ;or on standup :nosu cpx #150 bcc :nost cpx #163 bcc :nocut cpx #166 bcc :nost cpx #169 bcc :nocut ;or on strike/block :nost lda CharAction cmp #7 beq :nocut ;or on turning ldx CharFace ;-1=left, 0=right beq :faceR ;facing left lda leftej cmp #LeftCutEdge bcc :CUTLEFT beq :CUTLEFT cmp #ScrnRight+1 bcs :CUTRIGHT bcc :nocut :faceR lda CharScrn ldx #9 ldy CharBlockY jsr rdblock cmp #panelwif beq :nocutr cmp #panelwof beq :nocutr ;don't cut R if a panel blocks view lda rightej cmp #RightCutEdge bcs :CUTRIGHT :nocutr lda rightej cmp #ScrnLeft-1 bcc :CUTLEFT beq :CUTLEFT :nocut lda #-1 rts :CUTLEFT jsr mirrmusic jsr milestone3 lda #0 bpl :cut :CUTRIGHT jsr stealsword jsr jaffmusic lda #1 bpl :cut :CUTUP lda #2 bpl :cut * Level 6 ("Plunge"): Kid falls off screen 1 into next level :CUTDOWN jsr infinity lda level cmp #6 bne :no6 lda CharScrn cmp #1 beq :nocut :no6 lda #3 :cut pha jsr cut pla ]rts rts *------------------------------- * Level 12--fall off into infinity *------------------------------- infinity rts *------------------------------- * Passed Level 3 milestone? *------------------------------- milestone3 lda level cmp #3 bne ]rts lda #7 ;scrn to R of gate ]mcheck cmp CharScrn bne ]rts lda #1 sta milestone lda MaxKidStr sta origstrength rts *------------------------------- * Level 12: Shadow steals sword *------------------------------- stealsword lda level cmp #12 bne ]rts lda CharScrn cmp #18 ;scrn below swordscrn bne ]rts lda #swordscrn ldx #swordx ldy #swordy jsr rdblock lda #floor sta (BlueType),y rts *------------------------------- * Level 13: Play Jaffar's Theme *------------------------------- jaffmusic lda level cmp #13 bne ]rts lda exitopen bne ]rts lda CharScrn cmp #3 bne ]rts lda #s_Jaffar ldx #25 jmp cuesong *------------------------------- * Level 4 ("Mirror"): Play danger theme for mirror *------------------------------- mirrmusic lda exitopen beq :no4 cmp #77 beq :no4 lda level cmp #4 bne :no4 lda CharBlockY cmp #miry bne :no4 lda CharScrn cmp #11 ;scrn to R of mirscrn bne :no4 lda #s_Danger ldx #50 jsr cuesong lda #77 sta exitopen ;so we don't repeat theme :no4 ]rts rts *------------------------------- * * C U T * * Move char from CharScrn to adjacent screen * * In: A = cut dir: 0 = left, 1 = right, 2 = up, 3 = down * *------------------------------- CUT cmp #3 beq Cdown cmp #1 beq Cright cmp #2 beq Cup Cleft lda CharScrn jsr getleft ;get new screen # sta CharScrn lda #140 clc adc CharX sta CharX ldx #1 ;new FromDir rts Cright lda CharScrn jsr getright sta CharScrn lda CharX sec sbc #140 sta CharX ldx #0 rts Cup lda CharScrn jsr getup sta CharScrn lda CharBlockY clc adc #3 sta CharBlockY lda CharY clc adc #189 sta CharY ldx #3 rts Cdown lda CharScrn jsr getdown sta CharScrn lda CharBlockY sec sbc #3 sta CharBlockY lda CharY sec sbc #189 sta CharY ldx #2 ]rts rts *------------------------------- * * A D D G U A R D * * On cut to new screen--if guard is there, bring him to life * Also handles hard-wired shadowman appearances * * In: VisScrn * *------------------------------- ADDGUARD lda #0 sta offguard * Level 12 lda level cmp #12 bne :not12 lda exitopen ;set when shadow drops bne ]rts lda mergetimer bne :1 ;shadow has been reabsorbed lda VisScrn cmp #swordscrn :1 bne ]rts sta CharScrn ldx #swordx ldy #swordy jsr rdblock cmp #sword beq ]rts ;sword is still there lda #0 sta shadowaction lda #1 sta exitopen lda #shadpos12 ldx #>shadpos12 jmp csps * Level 6 (Plunge) :not12 lda level cmp #6 ;plunge bne :not6 lda VisScrn sta CharScrn cmp #1 bne AddNormalGd lda exitopen cmp #77 beq :norepeat lda #s_Danger ldx #50 jsr cuesong lda #77 sta exitopen :norepeat lda #shadpos6a ldx #>shadpos6a jmp csps * Level 5 (Thief) :not6 lda level cmp #5 ;thief bne :not5 lda VisScrn sta CharScrn cmp #flaskscrn bne AddNormalGd ldx #flaskx ldy #flasky jsr rdblock cmp #flask bne ]rts ;potion is gone lda #shadpos5 ldx #>shadpos5 jmp csps ]rts rts :not5 *------------------------------- AddNormalGd ldx VisScrn lda GdStartBlock-1,x cmp #30 bcs ]rts ;no guard on this scrn * Bring guard to life (or death) stx CharScrn jsr unindex ;return A = blockx, X = blocky stx CharBlockY lda FloorY+1,x sta CharY ldx VisScrn lda GdStartX-1,x sta CharX jsr getblockxp sta CharBlockX ldx VisScrn lda GdStartFace-1,x sta CharFace lda level cmp #3 bne :3 lda #4 ;skel bne :4 :3 lda #2 ;guard :4 sta CharID lda GdStartSeqH-1,x bne :1 ;0 is code for fresh start lda CharID cmp #4 bne :5 lda #2 sta CharSword lda #landengarde ;skel (ready) bne :6 :5 lda #0 sta CharSword lda #alertstand ;guard :6 jsr jumpseq jmp :2 :1 sta CharSeq+1 lda GdStartSeqL-1,x sta CharSeq :2 jsr animchar lda CharPosn cmp #185 ;killed beq :dead cmp #177 ;impaled beq :dead cmp #178 ;halved beq :dead * Live guard lda #-1 sta CharLife lda #0 sta alertguard sta refract sta justblocked jsr getgdstrength jmp :cont * Dead guard :dead lda #1 sta CharLife lda #0 sta OppStrength * Continue :cont lda #0 sta CharXVel sta CharYVel lda #1 sta CharAction ldx VisScrn lda GdStartProg-1,x cmp #numprogs bcc :ok lda #3 ;default :ok sta guardprog ldx level lda basiccolor,x ldx guardprog eor specialcolor,x ;0 = normal, 1 = special sta GuardColor ;0 = blue, 1 = red jmp SaveShad ;save ShadVars *------------------------------- * Get guard fighting strength *------------------------------- getgdstrength ldx level lda basicstrength,x ldx guardprog clc adc extrastrength,x sta MaxOppStr sta OppStrength ]rts rts *------------------------------- lst ds 1 usr $a9,17,$800,*-org lst off