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

1516 lines
21 KiB
ArmAsm
Executable File

* coll
org = $4500
tr on
lst off
*-------------------------------
*
* PRINCE OF PERSIA
* Copyright 1989 Jordan Mechner
*
*-------------------------------
org org
jmp CHECKBARR
jmp COLLISIONS
jmp GETFWDDIST
jmp CHECKCOLL
jmp ANIMCHAR
jmp CHECKSLICE
jmp CHECKSLICE2
jmp markmeters ;temp
jmp CHECKGATE
jmp firstguard ;temp
jmp ENEMYCOLL
*-------------------------------
lst
put eq
lst
put gameeq
lst
put seqdata
lst
put soundnames
lst
put movedata
lst off
dum $f0
ztemp ds 1
CollFace ds 1
tempobjid ds 1
tempstate ds 1
dend
*-------------------------------
* Distance in pixels from either edge of block to barrier
* BarL + BarR + BarWidth == 14
*
* Indexed by barrier code:
* 0 = clear, 1 = panel/gate, 2 = flask, 3 = mirror/slicer
* 4 = block
BarL db 0,12,2,0,0
BarR db 0,0,9,11,0
*-------------------------------
DeathVelocity = 33
OofVelocity = 22
gatemargin = 6 ;higher = more generous
]rts rts
*-------------------------------
*
* C H E C K B A R R I E R
*
* Check for collisions with vertical barriers
*
*-------------------------------
CHECKBARR
lda #-1 ;"no-collision" flag
sta collideL
sta collideR
* Check for situations where character is temporarily
* "collision-proof"
lda CharAction
cmp #7 ;turning?
beq ]rts
* Initialize CD/SN buffers
* (Copy "lastframe" data from "thisframe", "above", or "below";
* init "thisframe" with FF)
lda CharBlockY
sta BlockYthis
jsr initCDbufs
lda BlockYthis
sta BlockYlast
* Get beginning & end of range
lda CDRightEj
jsr getblockxp
clc
adc #2
cmp #11
bcc :ok
lda #11
;Last (rightmost) block in range +1
:ok sta endrange
lda CDLeftEj
jsr getblockxp
tax
dex ;First (leftmost) block in range
stx begrange
* Get CD & SN data for every block in range [begrange..endrange]
* on this level (BlockYthis) and on levels below & above
* This level...
lda BlockYthis
sta blocky
lda #SNthisframe
ldx #CDthisframe
jsr getCData
* Level below...
lda BlockYthis
clc
adc #1
sta blocky
lda #SNbelow
ldx #CDbelow
jsr getCData
* ...and level above
lda BlockYthis
sec
sbc #1
sta blocky
lda #SNabove
ldx #CDabove
jsr getCData
* Got new data... now compare thisframe with lastframe
* If a nybble has changed from 0 to 1, we have a collision.
ldx #9
:loop2
lda SNthisframe,x
bmi :no ;ff = no data for this frame
cmp SNlastframe,x
bne :no ;no corresponding data for last frame
lda CDlastframe,x
and #$0f ;low nybble first (L edge of barr)
bne :noL
lda CDthisframe,x
and #$0f
beq :noL
stx collideL ;We have collision w/ L edge
;x = block # (0-9)
:noL lda CDlastframe,x
and #$f0 ;hi nybble (R edge of barr)
bne :noR
lda CDthisframe,x
and #$f0
beq :noR
stx collideR ;collision w/ R edge
:noR
:no dex
bpl :loop2
ldx collideL
ldy collideR
]rts rts
*-------------------------------
*
* G E T C D A T A
*
* Get "thisframe" data for specified blocky
*
*-------------------------------
getCData
sta :smodSN+1
stx :smodCD+1
lda begrange
jsr getblockej ;left edge of block
clc
adc #angle ;perspective
sta blockedge
ldx begrange
:loop stx bufindex
* First compare L edge of barr with R edge of char
lda CharScrn
ldx bufindex
ldy blocky
jsr getleftbar ;Get left edge of barrier
cmp CDRightEj
bcc :RofL
;= means L of L
:LofL lda #0
beq :cont1
:RofL lda #$f
:cont1 sta ztemp
* Now compare R edge of barr with L edge of char
lda CharScrn
ldx bufindex
ldy blocky
jsr getrightbar ;Get right edge of barrier
cmp CDLeftEj
bcc :RofR
beq :RofR ;= means R of R
:LofR lda #$f0
bne :cont2
:RofR lda #0
:cont2 ora ztemp
ldx tempblockx ;guaranteed 0-9 by rdblock
:smodCD sta CDthisframe,x
lda tempscrn
:smodSN sta SNthisframe,x ;screen #
lda blockedge
clc
adc #14
sta blockedge
ldx bufindex
inx
cpx endrange
bne :loop
]rts rts
*-------------------------------
*
* I N I T C D B U F S
*
* Initialize SN and CD buffers
* (Take "lastframe" data from "thisframe", "above", or "below";
* init "thisframe" with FF)
*
*-------------------------------
initCDbufs
lda BlockYthis
cmp BlockYlast ;same BlockY as last frame?
beq :usethis ;yes--copy data from "thisframe"
clc
adc #3
cmp BlockYlast
beq :usethis
sec
sbc #6
cmp BlockYlast
beq :usethis
* BlockY has changed--copy data from "above" or "below"
lda BlockYthis
clc
adc #1
cmp BlockYlast
beq :useabove
sec
sbc #3
cmp BlockYlast
beq :useabove
:usebelow
lda #SNbelow
ldx #CDbelow
jmp :cont
:useabove lda #SNabove
ldx #CDabove
jmp :cont
:usethis lda #SNthisframe
ldx #CDthisframe
:cont sta :smodSN+1
stx :smodCD+1
* Copy contents of appropriate SN & CD buffers (thisframe,
* below, or above) into lastframe buffers...
* and initialize SN buffers with $ff
ldx #9
:zloop
:smodSN lda SNbelow,x
sta SNlastframe,x
:smodCD lda CDbelow,x
sta CDlastframe,x
lda #$ff
sta SNthisframe,x
sta SNabove,x
sta SNbelow,x
dex
bpl :zloop
]rts rts
*-------------------------------
*
* G E T L E F T B A R
*
* Get X-coord of left edge of barrier
*
* In: X/Y/A = blockx/blocky/scrn
* blockedge
*
* Out: A = screen X-coord (140)
* Return A = 255 if this block is no barrier
*
*-------------------------------
getleftbar
jsr rdblock ;get block ID
jsr cmpbarr ;return A = barrier code #
beq :clear ;or -1 if clear
tay
lda blockedge
clc
adc BarL,y ;barr dist from L edge of block
sec
rts
:clear lda #255
clc
rts
*-------------------------------
*
* G E T R I G H T B A R
*
* Get right edge of barrier, 0 if clear
*
*-------------------------------
getrightbar
jsr rdblock
jsr cmpbarr
beq :clear
tay
lda blockedge
clc
adc #13
sec
sbc BarR,y ;barr dist from R edge of block
sec
rts
:clear lda #0
clc
]rts rts
*-------------------------------
*
* C O L L I S I O N S
*
* If a collision was detected, act on it
*
* In: collideL/R: - if no coll, 0-9 refers to block in
* which collision occurred
*
* (CollideL is collision with LEFT EDGE of barrier
* CollideR is collision with RIGHT EDGE of barrier)
*
*-------------------------------
COLLISIONS
lda AMtimer ;antimatter timer
beq :cont
lda $c030
dec AMtimer
rts
:cont
* Check for situations where we let character
* pass thru barrier (e.g., climbing up onto ledge)
lda CharAction
cmp #2 ;hanging?
beq ]rts
cmp #6 ;hanging?
beq ]rts
lda CharPosn
cmp #135
bcc :cont2
cmp #149
bcc ]rts ;climbing?
:cont2
ldx collideL
bmi :noL
stx collX
jmp leftcoll
:noL ldx collideR
bmi :noR
stx collX
jmp rightcoll
:noR
]rts rts
*-------------------------------
*
* R I G H T C O L L I S I O N
*
*-------------------------------
rightcoll
lda CharSword
cmp #2 ;if in fighting mode,
beq :1 ;waive front-facing requirement
lda CharFace
bpl ]rts
:1
jsr checkcoll1
bcc ]rts
lda tempscrn
ldx tempblockx
ldy tempblocky
jsr getrightbar ;edge of barr
sec
sbc CDLeftEj ;dist to char
ldx #0 ;right
jmp collide
*-------------------------------
*
* L E F T C O L L I S I O N
*
*-------------------------------
leftcoll
lda CharSword
cmp #2
beq :1
lda CharFace
bne ]rts
:1
jsr checkcoll1
bcc ]rts
lda tempscrn
ldx tempblockx
ldy tempblocky
jsr getleftbar
sec
sbc CDRightEj ;- dist to char
ldx #-1 ;left
jmp collide
*-------------------------------
*
* Call CHECKCOLL for block #X
*
* In: CD data; X = blockx
*
*-------------------------------
checkcoll1
stx tempblockx
lda CharBlockY
bpl :2
clc
adc #3
bne :1
:2 cmp #3
bcc :1
sec
sbc #3
:1 sta tempblocky
lda SNthisframe,x
sta tempscrn
jsr rdblock1
jmp CHECKCOLL
*-------------------------------
*
* C H E C K C O L L
*
* In: RDBLOCK results (A = objid)
*
* Out: tempblockx,tempblocky,tempscrn
* cs if collision, cc if not
*
*-------------------------------
CHECKCOLL
cmp #flask
beq :no ;flask is not really a barrier
cmp #gate
beq :gate
cmp #slicer
beq :slicer
cmp #mirror
beq :mirror
bne :c1
* You can pass thru mirror from R only if you take a
* running jump
:mirror
lda CharID
bne :c1 ;must be kid
lda CharPosn
cmp #39
bcc :c1
cmp #44
bcs :c1
lda CharFace
bpl :c1
jsr smashmirror
lda #$ff
sta createshad ;set flag
clc
rts
* Is slicer closed?
:slicer lda (BlueSpec),y
cmp #slicerExt
bne :no ;no--pass thru
beq :c1
* Is gate low enough to bar you?
:gate jsr gatebarr? ;return cc if gate bars you
bcc :c1
* no collision--pass thru barrier
:no clc
rts
* Yes, collision--get blockedge & return cs
:c1
lda tempblockx
jsr getblockej
jsr AdjustScrn
clc
adc #angle
sta blockedge
:yes sec
]rts rts
*-------------------------------
*
* AdjustScrn
*
* In: tempscrn, VisScrn
* scrnLeft/Right/BelowL/BelowR
* A = X-coord on tempscrn
*
* Out: A = X=coord on VisScrn
*
*-------------------------------
AdjustScrn
ldx tempscrn
cpx VisScrn
beq ]rts
cpx scrnLeft
beq :osL
cpx scrnBelowL
beq :osL
cpx scrnRight
beq :osR
cpx scrnBelowR
beq :osR
rts
:osR clc
adc #ScrnWidth
rts
:osL sec
sbc #ScrnWidth
]rts rts
*-------------------------------
*
* C O L L I D E
*
* In: A = distance from barrier to character
* X = coll direction (-1 = left, 0 = right)
* tempblockx,y,scrn set for collision block
*
*-------------------------------
collide
stx CollFace ;temp var
ldx CharLife ;dead?
bpl ]rts ;yes--let him finish falling (or whatever)
ldx CharPosn
cpx #177 ;impaled?
beq ]rts ;yes--ignore collision
clc
adc CharX
sta CharX
* In midair or on the ground?
jsr rdblock1
ldx CollFace
bpl :faceL
cmp #block ;If this block has no floor,
beq :2 ;use the one in front of it
bne :1
:2 dec tempblockx
jmp :3
:faceL cmp #panelwof ;Panelwof is only a problem
beq :4 ;when facing L
cmp #panelwif
beq :4
cmp #block
bne :1
:4 inc tempblockx
lda tempscrn
bne :3
lda tempblockx
cmp #10
bne :3
lda CharScrn
sta tempscrn
lda #0
sta tempblockx ;screen 0 block 10 = CharScrn block 0
:3 jsr rdblock1
:1 jsr cmpspace
bne GroundBump
*-------------------------------
* Bump into barrier w/o floor
AirBump
lda #-4
jsr addcharx
sta CharX
lda CharAction
cmp #4 ;already falling?
bne :3
;yes--just rebound off wall
lda #0
sta CharXVel
beq :smackwall
:3 lda #bumpfall
jsr jumpseq
jsr animchar
:smackwall
BumpSound
lda #1
sta alertguard
lda #SmackWall
jmp addsound
*-------------------------------
* Bump into barrier w/floor
GroundBump
ldx CharBlockY
lda CharSword
cmp #2
beq :skipair ;no airbump if en garde
lda FloorY+1,x
sec
sbc CharY
cmp #15 ;constant
bcs AirBump
:skipair
lda FloorY+1,x
sta CharY
lda CharYVel
cmp #OofVelocity
bcc :okvel
lda #-5
jsr addcharx
sta CharX
rts ;let checkfloor take care of it
:okvel lda #0
sta CharYVel
lda CharLife
beq :deadbump
* Is he en garde?
lda CharSword
cmp #2
beq :CollideEng ;yes--collide en garde
* Should it be a hard or a soft bump?
:normal
ldx CharPosn ;last frame
cpx #24
beq :hard
cpx #25
beq :hard ;standjump-->hard
cpx #40
bcc :1
cpx #43
bcc :hard ;runjump-->hard
:1 cpx #102
bcc :2
cpx #107
bcc :hard ;freefall-->hard
:2
:soft lda #bump
jsr jumpseq
jsr BumpSound ;soft bump sound?
jmp animchar
:hard lda #hardbump
:doit jsr jumpseq
jsr animchar
jmp BumpSound
* dead when he hits the wall
:deadbump
]rts rts
*-------------------------------
* Collide en garde
:CollideEng
lda CollFace
cmp CharFace
beq :collback
lda #bumpengfwd
bne :doit
* Char is en garde & trying to back into barrier
:collback
lda #bumpengback
jsr jumpseq
jsr animchar ;get new frame
lda #1
jsr addcharx
sta CharX
rts
*-------------------------------
*
* G E T F W D D I S T
*
* In: Char data
*
* Out: A = size of "careful step" forward (0-14 pixels)
* X = what you're stepping up to
* (0 = edge, 1 = barrier, 2 = clear)
* RDBLOCK results for that block
*
*-------------------------------
GETFWDDIST
* Get edges
jsr GetBaseBlock
jsr setupchar
jsr getedges
* If this block contains barrier, get distance
jsr getunderft ;read block underfoot
sta tempobjid
jsr cmpbarr
beq :nextb ;This block is clear
lda CharBlockX
sta tempblockx
jsr DBarr ;returns A = dist to barrier
tax
bpl :tobarr
* If next block contains barrier, get distance
:nextb
jsr getinfront
sta tempobjid
cmp #panelwof
bne :99 ;Panelwof is special case
ldx CharFace ;if you're facing R
bpl :toEOB
:99 jsr cmpbarr
beq :nobarr
lda infrontx
sta tempblockx
jsr DBarr
tax
bpl :tobarr
* If next block is dangerous (e.g., empty space)
* or sword or potion, step to end of this block
:nobarr
jsr getinfront ;read block in front
sta tempobjid
cmp #loose
beq :toEOB ;step to end of block
cmp #pressplate
beq :toEOB1
cmp #sword
beq :toEOB1
cmp #flask
beq :toEOB1
jsr cmpspace
beq :toEOB
* All clear--take a full step forward
:fullstep lda #11 ;natural step size
ldx #2 ;clear
bne :done
* Step to end of block (no "testfoot")
:toEOB1 jsr getdist
beq :fullstep
ldx #0
beq :done
* Step to end of block
:toEOB jsr getdist ;returns # pixels to end of block (0-13)
ldx #0 ;edge
:done ldy tempobjid
]rts rts
* Step up to barrier
:tobarr
cmp #14
bcs :fullstep
ldx #1 ;barrier
bne :done
*-------------------------------
*
* Get distance to barrier
*
* In: rdblock results; tempobjid
* Must have called setupchar/getedges
* Out: A = distance to barrier (- if barr is behind char)
*
*-------------------------------
DBarr
lda tempobjid
cmp #gate
bne :ok
;treat gate as barrier only if down
jsr gatebarr? ;returns cs if open
bcs :clr
:ok lda tempblockx
jsr getblockej
clc
adc #angle
sta blockedge ;L edge of this block
lda CharFace
bmi :checkL
* Char facing R -- get distance to barrier
:checkR
lda tempobjid ;block ID
jsr cmpbarr ;return A = barrier code #
beq :clr
tay
lda blockedge
clc
adc BarL,y
sta ztemp ;left edge of barr
sec
sbc CDRightEj
rts ;If -, barr is behind char
:clr lda #-1
rts
* Char facing L -- get distance to barr
:checkL
lda tempobjid
jsr cmpbarr
beq :clr
tay
lda blockedge
clc
adc #13
sec
sbc BarR,y
sta ztemp ;R edge of barr
lda CDLeftEj
sec
sbc ztemp
]rts rts
*-------------------------------
*
* A N I M C H A R
*
* Get next frame from sequence table;
* update char data accordingly.
* We're now ready to draw this frame.
*
*-------------------------------
ANIMCHAR
:next jsr getseq ;get next byte from seqtab
;& increment CharSeq
cmp #chx ;"change x" instruction?
bne :no1
jsr getseq ;next byte is delta-x
jsr addcharx
sta CharX
jmp :next
*-------------------------------
:no1 cmp #chy
bne :no2
jsr getseq
clc
adc CharY
sta CharY
jmp :next
*-------------------------------
:no2 cmp #aboutface
bne :no3
lda CharFace
eor #$ff
sta CharFace
jmp :next
*-------------------------------
:no3 cmp #goto
bne :no4
:goto jsr getseq ;low byte of address
pha
jsr getseq ;high byte
sta CharSeq+1
pla
sta CharSeq
jmp :next
*-------------------------------
:no4 cmp #up
bne :no5
dec CharBlockY
jsr addslicers
jmp :next
*-------------------------------
:no5 cmp #down
bne :no6
inc CharBlockY
jsr addslicers
jmp :next
*-------------------------------
:no6 cmp #act
bne :no7
jsr getseq
sta CharAction
jmp :next
:no7 cmp #setfall
bne :no8
jsr getseq
sta CharXVel
jsr getseq
sta CharYVel
jmp :next
:no8 cmp #ifwtless
bne :no9
lda weightless ;weightless?
bne :goto ;yes--branch
jsr getseq
jsr getseq ;skip 2 bytes
jmp :next ;& continue
:no9 cmp #die
bne :no10
jmp :next
:no10 cmp #jaru
bne :no11
lda #1
sta jarabove ;jar floorboards above
jmp :next
:no11 cmp #jard
bne :no12
lda #-1
sta jarabove ;jar floorboards below
jmp :next
*-------------------------------
:no12 cmp #tap
bne :no13
jsr getseq ;sound #
cmp #0 ;0: alert guard
beq :0
cmp #1 ;1: footstep
bne :1
lda #Footstep
:tap jsr addsound
:0 lda #1
sta alertguard
jmp :next
:1 cmp #2 ;2: smack wall
bne :2
lda #SmackWall
bne :tap
:2 jmp :next
:no13 cmp #nextlevel
bne :no14
jsr GoneUpstairs
jmp :next
:no14 cmp #effect
bne :no15
jsr getseq ;effect #
cmp #1
bne :fx0
jsr potioneffect
:fx0 jmp :next
:no15
*-------------------------------
sta CharPosn ;frame #
]rts rts
*-------------------------------
* Char has gone upstairs
* What do we do?
*-------------------------------
GoneUpstairs
lda level
cmp #13
beq :ok ;no music for level 13
cmp #4
bne :1 ;mirror level is special
:3 lda #s_Shadow
bne :2
:1 lda #s_Upstairs
:2 ldx #25
jsr cuesong
:ok inc NextLevel
rts
*-------------------------------
*
* Sliced by slicer? (Does CD buf show char overlapping
* with a closed slicer?)
*
* In: Char data, CD data
*
*-------------------------------
CHECKSLICE
lda CharBlockY
sta tempblocky
ldx #9
:loop stx tempblockx
lda CDthisframe,x
cmp #$ff ;char overlapping barr?
bne :ok ;no
* Yes--is it a slicer?
lda SNthisframe,x
sta tempscrn
jsr rdblock1
cmp #slicer
bne :ok
lda (BlueSpec),y
and #$7f
cmp #slicerExt ;slicer closed?
beq :slice ;yes--slice!
* No--keep checking
:ok ldx tempblockx
dex
bpl :loop
]rts rts
* Slice!
* In: rdblock results for slicer block
:slice
]slice
lda (BlueSpec),y
ora #$80
sta (BlueSpec),y ;set hibit (smear)
:cont lda CharPosn
cmp #178 ;if already cut in half (e.g. by another slicer),
beq ]rts ;leave him alone
lda tempblockx
jsr getblockej ;edge of slicer block
clc
adc #7
sta CharX
lda #8
jsr addcharx
sta CharX ;align char w/slicer
ldx CharBlockY
inx
lda FloorY,x
sta CharY ;align char w/floor
lda #100
jsr decstr
lda #Splat
jsr addsound
lda #halve
jsr jumpseq
jmp animchar
*-------------------------------
*
* Sliced by slicer?
*
* (Use this routine for enemy, who has no CD data)
*
* In: Char data; GETEDGES results
*
*-------------------------------
CHECKSLICE2
jsr getunderft
jsr :slice? ;return cs if sliced
bcs ]rts
inc tempblockx
jsr rdblock1
:slice?
cmp #slicer
bne :safe
lda (BlueSpec),y
and #$7f
cmp #slicerExt
bne :safe ;slicer open
lda tempblockx
jsr getblockej
clc
adc #angle
sta blockedge
lda tempscrn
ldx tempblockx
ldy tempblocky
jsr getleftbar
cmp CDRightEj
bcs :safe
lda tempscrn
ldx tempblockx
ldy tempblocky
jsr getrightbar
cmp CDLeftEj
bcc :safe
beq :safe
jsr rdblock1
jsr ]slice
sec
rts
:safe clc
]rts rts
*-------------------------------
*
* Special situation: If char is standing directly under closing
* gate, it knocks him aside when it shuts.
*
* In: Char data, CD data
*
*-------------------------------
CHECKGATE
lda CharAction
cmp #7 ;turning
beq :1
lda CharPosn
cmp #15 ;standing?
beq :1
cmp #108
bcc ]rts
cmp #111 ;crouching?
bcs ]rts
:1
jsr getunderft
cmp #gate
beq :check
dec tempblockx
jsr rdblock1
cmp #gate
bne ]rts
:check
ldx tempblockx
lda CDthisframe,x
and CDlastframe,x
cmp #$ff
bne ]rts
jsr gatebarr?
bcs ]rts
jsr BumpSound
* bump him left or right?
lda tempblockx
sta collX
jsr getunderft
lda tempblockx
cmp collX
beq :left
bcs :right
:left lda #-5
bne :10
:right lda #5
:10 clc
adc CharX
sta CharX
]rts rts
*-------------------------------
*
* Return cc if gate bars you, cs if clear
*
*-------------------------------
gatebarr?
lda (BlueSpec),y
lsr
lsr
clc
adc #gatemargin
cmp imheight
]rts rts
*-------------------------------
*
* Limited collision detection for enemies
* (backing into wall or gate while fighting)
*
*-------------------------------
ENEMYCOLL
lda AMtimer ;antimatter timer
bne ]rts
lda CharAction
cmp #1
bne ]rts ;must be on ground
lda CharLife
bpl ]rts ;& alive
lda CharSword
cmp #2
bcc ]rts ;& en garde
jsr getunderft
cmp #block
beq :collide
cmp #panelwif
beq :collide
cmp #gate
bne :1
jsr gatebarr?
bcc :collide
* If facing R, check block behind too
:1 lda CharFace
bmi ]rts
dec tempblockx
jsr rdblock1
cmp #panelwif
beq :collide
cmp #gate
bne ]rts
jsr gatebarr?
bcc :collide
]rts rts
* Char is en garde & trying to back into barrier
* Put him right at edge
:collide
jsr setupchar
jsr getedges ;get edges
lda tempscrn
ldx tempblockx
ldy tempblocky
jsr rdblock
sta tempobjid
jsr checkcoll
bcc ]rts
jsr DBarr2 ;get A = dist to barrier
tax
bpl ]rts
eor #$ff
clc
adc #1
jsr addcharx
sta CharX
lda #bumpengback
jsr jumpseq
jsr animchar ;get new frame
jmp rereadblocks
*-------------------------------
*
* Special version of DBarr for enemy collisions
*
* In: checkcoll results; tempobjid
* Must have called setupchar/getedges
* Out: A = distance to barrier (- if barr is behind char)
*
*-------------------------------
DBarr2
lda CharFace
bpl :checkL ;Note: reversed from DBarr
* Char's back facing R -- get distance to barrier
:checkR
lda tempobjid ;block ID
jsr cmpbarr ;return A = barrier code #
beq :clr
tay
lda blockedge
clc
adc BarL,y
sta ztemp ;left edge of barr
sec
sbc CDRightEj
rts ;If -, barr is behind char
:clr lda #-1
rts
* Char facing L -- get distance to barr
:checkL
lda tempobjid
jsr cmpbarr
beq :clr
tay
lda blockedge
clc
adc #13
sec
sbc BarR,y
sta ztemp ;R edge of barr
lda CDLeftEj
sec
sbc ztemp
]rts rts
*-------------------------------
lst
ds 1
usr $a9,16,$b00,*-org
lst off