Prince-of-Persia-Apple-II/01 POP Source/Source/CTRL.S

2169 lines
29 KiB
ArmAsm
Executable File

* ctrl
org = $3a00
tr on
lst off
*-------------------------------
org org
jmp PLAYERCTRL
jmp CHECKFLOOR
jmp SHADCTRL
jmp REREADBLOCKS
jmp CHECKPRESS
jmp DOIMPALE
jmp GENCTRL
jmp CHECKIMPALE
*-------------------------------
lst
put eq
lst
put gameeq
lst
put seqdata
lst
put soundnames
lst
put movedata
lst off
dum $f0
ztemp ds 1
jxtemp ds 1
jytemp ds 1
jbtemp ds 1
atemp ds 1
dend
*-------------------------------
* Misc. changeable parameters
DeathVelocity = 33
OofVelocity = 22
grabreach = -8
grabspeed = 32 ;max Y-vel to grab ledge
grablead = 25 ;increase to grab ledge earlier
stuntime = 12
jumpupreach = 0
jumpupangle = -6
JumpBackThres = 6
StepOffFwd = 3
StepOffBack = 8
swordthres = 90 ;to go en garde (facing fwd)
swordthresN = -10 ;" " (behind you)
blockthres = 32
graceperiod = 9
gdpatience = 15
gclimbthres = 6
stairthres = 30
plus1 db -1,1
minus1 db 1,-1
*-------------------------------
*
* If he's passed thru floor plane, change CharBlockY
* If floor is solid, stop him
*
*-------------------------------
falling
lda CharY
ldx CharBlockY
inx
cmp FloorY,x
bcs :1
jmp fallon ;Hasn't reached floor yet
* Character is passing thru floor plane
:1 jsr getunderft ;Check if there's
;solid floor underfoot
cmp #block
bne :2 ;Solid block is special case--
jsr InsideBlock ;reset him to either side of block
:2 jsr cmpspace
bne hitflr
inc CharBlockY ;Fall thru floor plane
]rts rts
*-------------------------------
*
* C H E C K F L O O R
*
*-------------------------------
CHECKFLOOR
lda CharAction
cmp #6 ;hanging?
beq ]rts
cmp #5 ;bumped?
bne :2
lda CharPosn
cmp #109 ;crouched (e.g. on loose floor)
beq :ong
cmp #185 ;dead
bne ]rts
:ong jmp onground
:2 cmp #4 ;freefall
beq falling
cmp #3
bne :1
lda CharPosn
cmp #102
bcc ]rts
cmp #106
bcs ]rts
jmp fallon
:1 cmp #2 ;hanging
beq ]rts
jmp onground ;7, 0, or 1: on the ground
*-------------------------------
*
* Floor stops him -- Choose appropriate landing
*
*-------------------------------
hitflr
ldx CharBlockY
inx
lda FloorY,x
sta CharY ;align char w/floor
jsr getunderft
cmp #spikes
beq :hitspikes
* Has he landed too close to edge?
jsr getinfront
jsr cmpspace
bne :cont ;no
jsr getdist ;# pixels to edge
cmp #4 ;was 2
bcs :cont
;Yes--move him back a little
lda #-3
jsr addcharx
sta CharX
:cont jsr addslicers ;trigger slicers on this level
lda CharLife
bpl :hardland ;dead before he hits the ground
jsr getdist
cmp #12
bcc :nc
jsr getbehind
cmp #spikes
beq :hitspikes ;check block behind if dist>=12
:nc jsr getunderft ;what has he landed on?
cmp #spikes
bne :notspikes
:hitspikes
jsr getspikes ;are spikes lethal?
bne :impale ;yes
:notspikes
lda CharYVel
cmp #OofVelocity
bcc :softland
cmp #DeathVelocity
bcc :medland
:hardland
lda #100
jsr decstr
:hdland1
lda #Splat
jsr addsound
lda #hardland
bne :doland
:medland
lda CharID
cmp #1
beq :softland ;shad lands easy
cmp #2
bcs :hardland ;guards can't survive 2 stories
lda #1
jsr decstr
beq :hdland1
lda #Splat
jsr addsound
lda #medland
bne :doland
:softland
lda CharID
cmp #2
bcs :gd ;guard always lands en garde
lda CharSword
cmp #2
bne :1
:gd lda #2
sta CharSword
lda #landengarde
bne :doland
:1 lda #softland
bne :doland
:impale jmp DoImpale
:doland jsr jumpseq
jsr animchar
lda #0
sta CharYVel
]rts rts
*-------------------------------
*
* Hasn't hit floor yet -- can he grab edge above?
*
*-------------------------------
fallon
lda btn ;is button down?
and CharLife ;& is he alive?
bpl ]rts
;yes--can he grab edge?
lda CharYVel
cmp #grabspeed
bcs ]rts ;no--falling too fast
lda CharY
clc
adc #grablead
ldx CharBlockY
inx
cmp FloorY,x
bcc ]rts ;not within grabbing range yet
* Char is within vertical range, and button is down
* Is there a ledge within reach?
lda CharX
sta savekidx
lda #grabreach
jsr addcharx
sta CharX
jsr rereadblocks
jsr :test ;can you grab ledge?
bne :ok ;yes--do it
lda savekidx
sta CharX
jmp rereadblocks
:ok ;do it!
* Align char with block
jsr getdist
jsr addcharx
sta CharX
ldx CharBlockY
inx
lda FloorY,x
sta CharY
lda #0
sta CharYVel
lda #fallhang
jsr jumpseq
jsr animchar
lda #stuntime
sta stunned
]rts rts
:test jsr getabove
sta blockid
jsr getaboveinf
jmp checkledge
*-------------------------------
* Is there floor underfoot? If not, start to fall
onground
lda Fcheck
and #fcheckmark
beq ]rts ;0--no need to check
jsr getunderft
cmp #block
bne :1
jsr InsideBlock ;If "inside" block, bump him outside
:1
jsr cmpspace
bne ]rts
* Level 12: Phantom bridge
lda level
cmp #12
bne :no
lda mergetimer
bpl :no
lda CharBlockY
bne :no
lda CharScrn
cmp #2
beq :yes
cmp #13
bne :no
lda tempblockx
cmp #6
bcc :no
;Create floorboards on the fly
:yes lda #floor
sta (BlueType),y
jsr indexblock
lda #2
jsr :sub
iny
:sub jsr markwipe
jmp markred
:no
*-------------------------------
* No floor underfoot--commence falling
startfall
lda #0
sta rjumpflag
sta CharSword ;so you can grab on
inc CharBlockY ;# of floor just below your feet
jsr addslicers
lda CharPosn ;upcoming frame
;(the one we're about to replace
;with first frame of falling seq)
sta rjumpflag
cmp #9 ;run-12
beq :stepfall
cmp #13 ;run-16
beq :stepfall2
cmp #26 ;standjump-19
beq :jumpfall
cmp #44 ;runjump-11
beq :rjumpfall
cmp #81
bcc :2
cmp #86
bcc :hdropfall
:2 cmp #150
bcc :1
cmp #180
bcc :fightfall ;from fighting stance
:1
:stepfall lda #stepfall
bne :doit
:stepfall2 lda #stepfall2
bne :doit
:jumpfall lda #jumpfall
bne :doit
:rjumpfall lda #rjumpfall
bne :doit
:hdropfall
lda #5
jsr addcharx
sta CharX
jsr rereadblocks
jmp :stepfall2
]rts rts
:fightfall lda CharID
cmp #2
bcc :player
lda CharXVel
bmi :fb ;did gd step off fwd or bkwd?
lda #0
sta droppedout
lda #efightfallfwd
bne :doit
:fb lda #efightfall
bne :doit
:player lda #1
sta droppedout ;for guard's benefit
lda #fightfall
bne :doit
*-------------------------------
:doit jsr jumpseq
jsr animchar ;advance 1 frame into fall
jsr rereadblocks
jsr getunderft
jsr cmpwall
beq :bump
jsr getinfront
jsr cmpwall
bne ]rts
jmp CDpatch
:bump jmp InsideBlock ;If "inside" block, bump him outside
CDpatch
lda rjumpflag
cmp #44 ;running jump?
bne :patchX
jsr getdist
cmp #6
bcs :patchX ;dist >= 6...we're OK
lda #patchfall
jsr jumpseq
jsr animchar
jmp rereadblocks
:patchX lda #-1
:1 jsr addcharx
sta CharX
jmp rereadblocks
*-------------------------------
*
* Char is "inside" a block--bump him outside
* (hopefully the same side from which he entered)
*
* Change Char X & return rdblock results
*
*-------------------------------
InsideBlock
jsr getdist ;to EOB
cmp #8
bcs :bumpback
:bumpfwd
jsr getinfront
cmp #block
beq :bumpback
jsr getdist ;to EOB
clc
adc #4
:reland
jsr addcharx
sta CharX
jsr rereadblocks ;reposition char
jmp getunderft
:bumpback
jsr getbehind
cmp #block
bne :1
;we're screwed
;bump 2 back (what the hell)
jsr getdist
clc
adc #14
eor #$ff
clc
adc #8
jmp :reland
:1
jsr getdist
eor #$ff
clc
adc #8
jmp :reland
*-------------------------------
*
* S H A D O W C O N T R O L
*
*-------------------------------
SHADCTRL
lda CharID
cmp #24 ;mouse?
bne :1
jmp AutoCtrl
:1 lda CharLife
bpl :dead
;Has char's life run out?
lda OppStrength
bne :cont
lda #0
sta CharLife
jsr deadenemy
:dead lda CharID
cmp #1 ;shadow man?
bne :cont
jmp VanishChar
:cont lda ManCtrl
bne :manualctrl
jsr AutoCtrl
jmp GenCtrl
* Manual ctrl: enemy controlled by deselected device
:manualctrl
jsr LoadDesel
jsr getdesel
jsr clrjstk
jsr UserCtrl
jmp SaveDesel
*-------------------------------
*
* P L A Y E R C O N T R O L
*
*-------------------------------
PLAYERCTRL
lda CharLife
bpl :cont1 ;dead
lda KidStrength
bne :cont1
lda #0
sta CharLife
:cont1
lda stunned
beq :cont
dec stunned
:cont lda level
bne :game
:demo jsr DemoCtrl
jmp GenCtrl
* Character controlled by selected device
:game jsr LoadSelect ;load jstk-push flags for selected device
jsr getselect ;get current input from selected device
jsr clrjstk ;clear appropriate jstk-push flags
lda #2
jsr UserCtrl
jmp SaveSelect ;save updated jstk-push flags
*-------------------------------
* Player ctrl in demo
DemoCtrl
lda milestone
bne :finish
lda CharSword
beq :preprog
lda #10
sta guardprog
jsr AutoCtrl
lda #11
sta guardprog
rts
:preprog jmp demo
:finish jsr clrall
sta clrbtn
lda #-1
sta clrF
sta JSTKX ;run o.s.
]rts rts
*-------------------------------
UserCtrl
lda CharFace
bpl :faceL
jmp GenCtrl
* If char is facing right, reverse JSTK & clrF/clrB
:faceL jsr facejstk
jsr GenCtrl
jmp facejstk
*-------------------------------
clrall
lda #0
sta clrB
sta clrF
sta clrU
sta clrD
lda #1
]rts rts
*-------------------------------
*
* G E N E R A L C O N T R O L
*
* In: Raw input
* JSTKX (- fwd, + back, 0 center)
* JSTKY (- up, + down, 0 center)
* btn (- down, + up)
* Smart input
* clrF-B-U-D-btn (- = fresh press)
*
* Set clr = 1 after using a press
*
*-------------------------------
GENCTRL
lda CharLife
bmi :alive
* Dead character (If he's standing, collapse)
:dead lda CharPosn
cmp #15
beq :drop
cmp #166
beq :drop
cmp #158
beq :drop
cmp #171
bne ]rts
:drop lda #dropdead
jmp jumpseq
* Live character
:alive lda CharAction
cmp #5 ;is char in mid-bump?
beq :clr
cmp #4 ;or falling?
beq :clr
bne :underctrl
:clr
]clr jmp clrall
:underctrl
lda CharSword
cmp #2 ;in fighting mode?
beq FightCtrl ;yes
lda CharID
cmp #2 ;kid or shadowman?
bcc :cont
jmp GuardCtrl ;no
* First question: what is char doing now?
:cont ldx CharPosn ;previous frame #
cpx #15
beq :standing
cpx #48
beq :turning
cpx #50
bcc :0
cpx #53
bcc :standing ;turn7-8-9/crouch
:0
cpx #4
bcc :starting ;run4-5-6
cpx #67
bcc :4
cpx #70
bcc :stjumpup ;starting to jump up
:4 cpx #15
bcs :2
jmp :running ;run8-17
:2 cpx #87
bcc :1
cpx #100
bcs :1
jmp :hanging ;jumphang22-34
:1 cpx #109 ;crouching?
beq :crouching
:3
]rts rts
:standing jmp standing
:starting jmp starting
:stjumpup jmp stjumpup
:running jmp arunning
:hanging jmp hanging
:turning jmp turning
:crouching jmp crouching
*-------------------------------
* Similar routine for guard
GuardCtrl
ldx CharPosn
cpx #166 ;standing?
beq :alert
]rts rts
:alert
lda clrD
bpl ]rts
lda clrF
bmi :engarde
bpl :turn
:engarde jmp DoEngarde
:turn lda #1
sta clrD
lda #alertturn
jmp jumpseq
*-------------------------------
* Char is en garde (CharSword = 2)
FightCtrl
lda CharAction
cmp #2
bcs ]rts ;Must be on level ground (Action = 1)
* If Enemy Alert is over, put away your sword
jsr getunderft
cmp #loose
beq :skip ;unless you're standing on loose floor
lda EnemyAlert
cmp #2
bcc :dropgd
* If opponent is behind you, turn to face him
:skip jsr getopdist ;fwd distance to opponent
cmp #swordthres
bcc :onalert
cmp #128
bcc :dropgd
cmp #-4
bcs :onalert ;overlapping
jmp DoTurnEng
* Enemy out of range--drop your guard
* (kid & shadman only)
:dropgd lda CharID
bne :1
sta heroic
beq :2
:1 cmp #2
bcs :onalert ;guard: remain en garde
:2
ldx CharPosn
cpx #171 ;wait for ready posn
bne ]rts
lda #0
sta CharSword
lda #resheathe
jmp jumpseq
]rts rts
*-------------------------------
* Remain en garde
:onalert
ldx CharPosn ;prev frame #
cpx #161 ;successful block?
bne :nobloc
lda clrbtn ;yes--restrike or retreat?
bmi :bts
lda #retreat
jmp jumpseq
* Fresh button press to strike
:nobloc lda clrbtn
bpl :10
:bts
lda CharID
bne :11
lda #gdpatience
sta gdtimer
:11 jsr DoStrike
lda clrbtn
cmp #1
beq ]rts ;struck
:10 ;else didn't strike
* Down to lower your sword
lda clrD
bpl :nodrop
ldx CharPosn
cpx #158 ;ready
beq :ready1
cpx #170
beq :ready1
cpx #171
bne ]rts
:ready1
lda #1
sta clrD
lda #0
sta CharSword
lda CharID
beq :drop ;for kid
cmp #1
beq :sstand ;for shadman
:alert lda #goalertstand
jmp jumpseq ;for guard
:drop lda #1
sta offguard
lda #graceperiod
sta refract
lda #0
sta heroic
lda #fastsheathe
jmp jumpseq
:sstand lda #resheathe
jmp jumpseq
* Fwd to advance, up to block, back to retreat
:nodrop
lda clrU
bmi :up
lda clrF
bmi :fwd
lda clrB
bmi :back
]rts rts
:fwd jmp DoAdvance
:up jmp DoBlock
:back jmp DoRetreat
*-------------------------------
DoTurnEng
lda #turnengarde
jmp jumpseq
*-------------------------------
DoBlock
ldx CharPosn
cpx #158 ;ready
beq :2
cpx #170
beq :2
cpx #171
beq :2
cpx #168 ;guy-2
beq :2
cpx #165 ;adv
beq :2
cpx #167 ;blocked strike
beq :3
]rts rts
* From ready position: Block if appropriate
:2 jsr getopdist
cmp #blockthres
bcs :blockmiss ;too far
lda #readyblock
ldx CharID
beq :kid
ldx OpPosn ;enemy sees kid 1 frame ahead
cpx #152 ;guy4
beq :doit
]rts rts
:kid ldx OpPosn
cpx #168 ;1 frame too early?
beq ]rts ;yes--wait 1 frame
cpx #151 ;guy3
beq :doit
cpx #152 ;guy4
beq :doit
cpx #162 ;guy22
beq :doit
cpx #153 ;1 frame too late?
bne :blockmiss
;yes--skip 1 frame
jsr :doit
jmp animchar
* Strike-to-block
:3 lda #strikeblock
:doit ldx #1
stx clrU
jmp jumpseq
:blockmiss
lda CharID
bne DoRetreat ;enemy doesn't waste blocks
lda #readyblock
bne :doit
*-------------------------------
DoStrike
cpx #157
beq :1
cpx #158
beq :1
cpx #170
beq :1
cpx #171
beq :1 ;strike from ready posn
cpx #165
beq :1 ;from advance
cpx #150
beq :2 ;from missed block
cpx #161
beq :2 ;from successful block
]rts rts
:1 lda CharID
bne :slo ;kid is fast, others slow
lda #faststrike
bne :dostr
:slo lda #strike
:dostr ldx #1
stx clrbtn
jmp jumpseq
:2 lda #blocktostrike
bne :dostr
*-------------------------------
DoRetreat
ldx CharPosn
cpx #158
beq :1 ;strike from ready posn
cpx #170
beq :1
cpx #171
beq :1
]rts rts
:1 lda #retreat
ldx #1
stx clrB
jmp jumpseq
*-------------------------------
DoAdvance
ldx CharPosn
cpx #158
beq :1
cpx #170
beq :1
cpx #171
beq :1
]rts rts
:1 lda CharID
bne :slo ;kid is faster
lda #fastadvance
bne :doit
:slo lda #advance
:doit ldx #1
stx clrF
jmp jumpseq
*-------------------------------
*
* S T A N D I N G
*
*-------------------------------
standing
* Fresh button click: pick up object?
lda clrbtn
bpl :noclick
lda btn
bpl :noclick
jsr TryPickup
bne ]rts ;yes
:noclick
* Shadman only: down & fwd to go en garde
lda CharID
beq :kid
lda clrD
bpl :1
lda clrF
bpl :1
jmp DoEngarde
* If opponent is within range, go en garde
* (For kid only)
:kid lda gotsword
beq :1 ;no sword
lda offguard
beq :notoffg
lda btn ;off guard--push btn to draw sword
bpl :btnup
:notoffg
lda EnemyAlert
cmp #2
bcc :safe
jsr getopdist ;fwd distance to opponent
cmp #swordthresN
bcs :danger
cmp #swordthres
bcs :safe
:danger ldx #1
stx heroic
cmp #-6
bcs :behindyou
lda OpID
cmp #1
bne :engarde
lda OpAction
cmp #3
beq :safe
lda OpPosn
cmp #107
bcc :engarde
cmp #118
bcc :safe ;let shadow land
:engarde jmp DoEngarde
:behindyou jmp DoTurn
:safe lda #0
sta offguard
:1 lda btn
bpl :btnup
*-------------------------------
* Standing, button down
:2 lda clrB
bmi :backB
lda clrU
bmi :up
lda clrD
bmi :down
lda JSTKX
bpl :rts
lda clrF
bmi :fwdB
:rts
]rts rts
*-------------------------------
* Standing, button up
:btnup
lda clrF
bmi :fwd
lda clrB
bmi :back
lda clrU
bmi :up
lda clrD
bmi :down
lda JSTKX
bmi :fwd
]rts rts
:fwd jmp DoStartrun
:fwdB jmp DoStepfwd
:back jmp DoTurn
:backB jmp DoTurn
:fwdup jmp DoStandjump
*-------------------------------
* Standing, joystick up
:up
* In front of open stairs?
jsr getunderft
cmp #exit
beq :stairs
jsr getbehind
cmp #exit
beq :stairs
jsr getinfront
cmp #exit
bne :nostairs
:stairs lda (BlueSpec),y
lsr
lsr
cmp #stairthres
bcc :nostairs
jmp Stairs
* No -- normal control
:nostairs
lda JSTKX
bmi :fwdup
* Straight up...jump up & grab ledge if you can
jmp DoJumpup
*-------------------------------
* Standing, joystick down
:down
lda #1
sta clrD
* If you're standing w/back to edge, down
* means "climb down & hang from ledge"
* If facing edge, "down" means "step off"
jsr getinfront
jsr cmpspace
bne :notfwd ;no cliff in front of you
jsr getdist
cmp #StepOffFwd
bcs :notfwd ;not close enough to edge
lda #5
jsr addcharx
sta CharX
jmp rereadblocks ;move fwd
:notfwd jsr getbehind
jsr cmpspace
bne :no ;no cliff behind you
jsr getdist
cmp #StepOffBack
bcc :no ;not close enough to edge
* Climb down & hang from ledge
jsr getbehind
sta blockid
jsr getunderft
jsr checkledge
beq :no
ldx CharFace
bpl :succeed
jsr getunderft
cmp #gate
bne :succeed
lda (BlueSpec),y
lsr
lsr
cmp #gclimbthres
bcc :no
:succeed jsr getdist
sec
sbc #9
jsr addcharx
sta CharX
lda #climbdown
jmp jumpseq
* Otherwise "down" means "crouch"
:no jmp DoCrouch
*-------------------------------
* Climb stairs
Stairs
lda tempblockx ;stairs block
jsr getblockej
clc
adc #10
sta CharX
lda #-1
sta CharFace
lda #climbstairs
jmp jumpseq
]rts rts
*-------------------------------
*
* C R O U C H I N G
*
*-------------------------------
crouching
* Fresh button click?
lda clrbtn
bpl :noclick
jsr TryPickup
bne ]rts
* Still crouching?
:noclick
lda JSTKY
cmp #1
beq :1
lda #standup
jmp jumpseq
:1 lda clrF
bpl ]rts
lda #1
sta clrF
lda #crawl
jmp jumpseq
*-------------------------------
*
* S T A R T I N G
*
* First few frames of "startrun"
*
*-------------------------------
starting
lda JSTKY
bmi :jump
]rts rts
:jump
lda JSTKX
bpl ]rts
jmp DoStandjump
*-------------------------------
* First few frames of "jumpup"
stjumpup
lda JSTKX
bmi :fwd
lda clrF
bmi :fwd
]rts rts
:fwd jmp DoStandjump
*-------------------------------
*
* T U R N I N G
*
*-------------------------------
turning
lda btn
bmi ]rts
lda JSTKX
bpl ]rts
lda JSTKY
bmi ]rts
* Jstk still fwd--convert turn to turnrun
lda #turnrun
jmp jumpseq
*-------------------------------
*
* R U N N I N G
*
*-------------------------------
arunning
lda JSTKX
beq :runstop ;jstk centered...stop running
bpl :runturn ;jstk back...turn around
* Jstk is forward... keep running
* & wait for signal to runjump or diveroll
lda JSTKY
bmi :runjump ;jstk up... take a running jump
lda clrD
bmi :diveroll ;jstk down... running dive & roll
]rts rts
* Running dive & roll
:diveroll lda #1
sta clrD
lda #rdiveroll
jmp jumpseq
* Running jump
:runjump
lda clrU
bpl ]rts
jmp DoRunjump
* Stop running
:runstop lda CharPosn
cmp #7 ;run-10
beq :rs
cmp #11 ;run-14
bne ]rts
:rs jsr ]clr
sta clrF
lda #runstop
jmp jumpseq
* Turn around & run the other way
:runturn
jsr ]clr
sta clrB
lda #runturn
jmp jumpseq
*-------------------------------
*
* H A N G I N G
*
*-------------------------------
hanging
lda stunned
bne :9 ;can't climb up
lda JSTKY
bmi :climbup ;jstk up-->climb up
:9
lda btn
bpl :drop
* If hanging on right-hand side of a panel
* or either side of block,
* switch to "hangstraight"
lda CharAction
cmp #6
beq :cont ;already hanging straight
jsr getunderft
cmp #block
beq :hangstrt
ldx CharFace
cpx #-1 ;left
bne :cont
cmp #panelwif
beq :hangstrt
cmp #panelwof
beq :hangstrt
* If ledge crumbles away, fall with it
:cont
jsr getabove
jsr cmpspace ;still there?
beq :drop ;no
* just keep swinging
:rts
]rts rts
:hangstrt lda #hangstraight
jmp jumpseq
*-------------------------------
* climb up (if you can)
:climbup
jsr ]clr
sta clrU
sta clrbtn
jsr getabove
cmp #mirror
beq :10
cmp #slicer
bne :1
:10 ldx CharFace
beq :fail
bne :succeed ;can only mount mirror facing L
:1 cmp #gate
bne :2
ldx CharFace
beq :succeed
;can only mount closed gate facing R
lda (BlueSpec),y
lsr
lsr
cmp #gclimbthres
bcc :fail
bcs :succeed
:2
:succeed lda #climbup
jmp jumpseq
:fail lda #climbfail
jmp jumpseq
*-------------------------------
:drop
jsr ]clr
sta clrD ;clrD = 1, all others = 0
jsr getbehind
jsr cmpspace
bne :hangdrop
jsr getunderft
jsr cmpspace
beq :hangfall
:hangdrop
jsr getunderft
cmp #block
beq :sheer
ldx CharFace
bpl :clear
cmp #panelwof
beq :sheer
cmp #panelwif
bne :clear
:sheer lda #-7
jsr addcharx
sta CharX
:clear lda #hangdrop
jmp jumpseq
:hangfall
lda #hangfall
jmp jumpseq
]rts rts
*-------------------------------
*
* D o S t a r t r u n
*
*-------------------------------
DoStartrun
* If very close to a barrier, do a Stepfwd instead
* (Exceptions: slicer & open gate)
jsr getfwddist
cpx #1 ;barrier?
bne :startrun ;no
cpy #slicer
beq :startrun
:solidbarr
jsr getfwddist
cmp #8
bcs :startrun
lda clrF
bpl ]rts
jmp DoStepfwd
:startrun
lda #startrun
jmp jumpseq ;...start running
DoTurn jsr ]clr
sta clrB
;if enemy is behind you, draw as you turn
lda gotsword
beq :1
lda EnemyAlert
cmp #2
bcc :1
jsr getopdist
bpl :1
jsr getdist ;to EOB
cmp #2
bcc :1
lda #2
sta CharSword ;en garde
lda #0
sta offguard
lda #turndraw
bne :2
:1 lda #turn
:2 jmp jumpseq ;...turn around
DoStandjump lda #1
sta clrU
sta clrF
lda #standjump
jmp jumpseq ;...standing jump
DoSdiveroll lda #1
sta clrD
lda #sdiveroll
jmp jumpseq ;...standing dive & roll
DoCrouch
lda #stoop
jsr jumpseq
jsr ]clr
sta clrD
rts
DoEngarde
jsr ]clr
sta clrF
sta clrbtn
lda #2
sta CharSword ;en garde
lda CharID
beq :1
cmp #1
beq :3 ;shad
lda #guardengarde
bne :2
:1 lda #0
sta offguard
:3 lda #engarde
:2 jmp jumpseq
*-------------------------------
*
* D o J u m p u p
*
* & grab ledge if you can
*
*-------------------------------
DoJumpup
jsr ]clr
sta clrU
jsr getabove
sta blockid
jsr getaboveinf
jsr checkledge ;Can you jump up & grab ledge?
;Returns 1 if you can, 0 if you can't
bne DoJumphang ;yes--do it
jsr getabovebeh
sta blockid
jsr getabove
jsr checkledge ;could you do it if you were 1 space back?
bne :jumpback ;yes--move back & do it
:jumphi jmp DoJumphigh
*-------------------------------
* Jump up & back to grab block directly overhead
:jumpback
jsr getdist ;dist to front of block
cmp #JumpBackThres
bcc :jumphi ;too far to fudge
jsr getbehind
jsr cmpspace ;floor behind you?
beq DoJumpedge ;no
* "Jump back" to block behind you & then proceed as usual
jsr getdist
sec
sbc #14
jsr addcharx
sta CharX
jsr rereadblocks
jmp DoJumphang
*-------------------------------
* Your back is to ledge -- so do a "jumpbackhang"
DoJumpedge
jsr getabove
* Get all the way back on this block
jsr getdist
sec
sbc #10
jsr addcharx
sta CharX
* now jump
lda #jumpbackhang
jmp jumpseq
*-------------------------------
DoJumphang
jsr getaboveinf
* Choose the jumphang sequence (Long/Med) that
* will bring us closest to edge, then fudge the X-coord
* to make it come out exactly
jsr getdist ;get distance to front of block
sta atemp ;# pixels (0-13) returned in A
cmp #4
bcc :Med
:Long lda atemp
sec ;"Long" will add 4 to CharX
sbc #4
jsr addcharx
sta CharX
lda #jumphangLong
jmp jumpseq
:Med
jsr getfwddist
cmp #4
bcs :okMed
cpx #1 ;close to wall?
beq :Long ;yes--step back & do Long
:okMed lda atemp
jsr addcharx
sta CharX
lda #jumphangMed
jmp jumpseq
]rts rts
*-------------------------------
*
* D o R u n J u m p
*
* Calibrate jump so that foot will push off at edge.
*
*-------------------------------
RJChange = 4 ;projected change in CharX
RJLookahead = 1 ;# blocks you can look ahead
RJLeadDist = 14 ;required leading distance in pixels
RJMaxFujBak = 8 ;# pixels we're willing to fudge back
RJMaxFujFwd = 2 ;and forward
DoRunjump
lda CharPosn
cmp #7
bcc ]rts ;must be in full run
* Count # of blocks to edge
* (Use actual CharX)
lda #0
sta bufindex ;block counter
lda #RJChange
jsr addcharx
sta ztemp ;projected CharX
jsr getblockxp
sta blockx
:loop lda blockx
ldx CharFace
inx
clc
adc plus1,x
sta blockx
tax
ldy CharBlockY
lda CharScrn
jsr rdblock
cmp #spikes
beq :done
jsr cmpspace
beq :done
inc bufindex
lda bufindex
cmp #RJLookahead+1
bcc :loop
bcs :noedge ;no edge in sight--jump anyway
:done
* Calculate # of pixels to end of floor
lda ztemp
jsr getdist1 ;# pixels to end of block
ldx bufindex ;# of blocks to end of floor
clc
adc Mult7,x
clc
adc Mult7,x ;# of pixels to end of floor
sec
sbc #RJLeadDist
;A = difference between actual dist to edge
;and distance covered by RunJump
cmp #-RJMaxFujBak
bcs :ok ;move back a little & jump
cmp #RJMaxFujFwd
bcc :ok ;move fwd a little & jump
cmp #$80
bcc ]rts ;still too far away--wait till next frame
lda #-3 ;He jumped too late; he'll miss edge
;But let's make it look good anyway
:ok clc
adc #RJChange
jsr addcharx
sta CharX
* No edge in sight -- just do any old long jump
:noedge
jsr ]clr
sta clrU
lda #runjump
jmp jumpseq
]rts rts
*-------------------------------
*
* D o S t e p F o r w a r d
*
*-------------------------------
DoStepfwd
lda #1
sta clrF
sta clrbtn
jsr getfwddist ;returns A = distance to step (0-13)
cmp #0
beq :1
:2 sta CharRepeat ;non-0 value
clc
adc #stepfwd1-1
jmp jumpseq
:1 cpx #1
beq :thru ;If barrier, step thru
cmp CharRepeat
bne :3 ;First time, test w/foot
:thru lda #11
bne :2 ;Second time, step off edge
:3 sta CharRepeat ;0
lda #testfoot
jmp jumpseq
*-------------------------------
*
* D o J u m p H i g h
*
*-------------------------------
DoJumphigh
jsr ]clr
sta clrU
jsr getfwddist
cmp #4
bcs :ok
cpx #1 ;barrier?
bne :ok ;no
sec
sbc #3
jsr addcharx
sta CharX
:ok
lda #jumpupreach
jsr facedx
sta ztemp
jsr getbasex ;assume char standing still
clc
adc #jumpupangle
clc
adc ztemp ;get X-coord at which hand touches ceiling
jsr getblockx
tax
ldy CharBlockY
dey
lda CharScrn
jsr rdblock ;read this block
cmp #block
beq :jumpup
jsr cmpspace
bne :jumpup
lda #highjump
jmp jumpseq ;no ceiling above
:jumpup lda #jumpup
jsr jumpseq ;touch ceiling
]rts rts ;& don't forget to crop top
*-------------------------------
* reread blocks
*-------------------------------
REREADBLOCKS
jsr GetFrameInfo
jmp GetBaseBlock
*-------------------------------
*
* Is character stepping on a pressure plate?
* or on loose floor?
*
*-------------------------------
CHECKPRESS
lda CharPosn
cmp #87
bcc :1
cmp #100
bcc :hanging ;87-99: jumphang22-34
cmp #135
bcc :1
cmp #141
bcc :hanging ;135-140: climb up/down
:1
lda CharAction
cmp #7
beq :ground ;turning
cmp #5
beq :ground ;bumped
cmp #2
bcs ]rts
* Action code 7, 0 or 1: on the ground
:ground
lda CharPosn
cmp #79 ;jumpup/touch ceiling
beq :touchceil
lda Fcheck
and #fcheckmark
beq ]rts ;foot isn't touching floor
* Standing on a pressplate?
jsr getunderft
:checkit
cmp #upressplate
beq :PP
cmp #pressplate
bne :notPP
:PP lda CharLife
bmi :push
jmp jampp ;dead weight
:push jmp pushpp
:notPP cmp #loose
bne ]rts
lda #1
sta alertguard
jmp breakloose
* Hanging on a pressplate?
:hanging
jsr getabove
jmp :checkit
]rts rts
* Jumping up to touch ceiling?
:touchceil
jsr getabove
cmp #loose
bne ]rts
jmp breakloose
*-------------------------------
*
* C H E C K I M P A L E
*
* Impalement by running or jumping onto spikes
* (Impalement by landing on spikes is covered by
* CHECKFLOOR:falling)
*
*-------------------------------
CHECKIMPALE
ldx CharBlockX
ldy CharBlockY
lda CharScrn
jsr rdblock
cmp #spikes
bne ]rts ;not spikes
ldx CharPosn
cpx #7
bcc ]rts
cpx #15
bcs :2
jmp :running
:2 cpx #43 ;runjump-10
beq :jumpland
cpx #26 ;standjump-19
beq :jumpland
]rts rts
:running
jsr getspikes
cmp #2
bcc ]rts ;must be springing
bcs :impale
:jumpland
jsr getspikes ;are spikes lethal?
beq ]rts ;no
:impale jmp DoImpale
*-------------------------------
* Impale char on spikes
*
* In: rdblock results
*-------------------------------
DOIMPALE
jsr jamspikes
ldx CharBlockY
inx
lda FloorY,x
sta CharY ;align char w/floor
lda tempblockx
jsr getblockej ;edge of spikes
clc
adc #10
sta CharX
lda #8
jsr addcharx
sta CharX ;center char on spikes
lda #0
sta CharYVel
lda #Impaled
jsr addsound
lda #100
jsr decstr
lda #impale
jsr jumpseq
jmp animchar
*-------------------------------
*
* Pick up object
* Return 0 if no result
*
*-------------------------------
TryPickup
jsr getunderft
cmp #flask
beq :2
cmp #sword
bne :1
:2 jsr getbehind
jsr cmpspace
beq :no
lda CharX
lda #-14
jsr addcharx
sta CharX ;move char 1 block back
jsr rereadblocks
:1 jsr getinfront
cmp #flask
beq :pickup
cmp #sword
beq :pickup
:no lda #0
rts
:pickup jsr PickItUp
lda #1
rts
*-------------------------------
*
* Pick something up
*
* In: rdblock results for object block ("infront")
*
*-------------------------------
PickItUp
ldx CharPosn
cpx #109 ;crouch first, then pick up obj
beq :ok
jsr getfwddist
cpx #2
beq :0 ;right at edge
jsr addcharx
sta CharX
:0 lda CharFace
bmi :1
lda #-2
jsr addcharx
sta CharX ;put char within reach of obj
:1 jmp DoCrouch
:ok cmp #sword
beq :PickupSword
lda (BlueSpec),y
lsr
lsr
lsr
lsr
lsr ;potion # (0-7)
jsr RemoveObj
lda #drinkpotion ;pick up & drink potion
jmp jumpseq
:PickupSword
lda #-1 ;sword
jsr RemoveObj
lda #pickupsword
jmp jumpseq ;pick up, brandish & sheathe sword
*-------------------------------
lst
ds 1
usr $a9,16,$00,*-org
lst off