;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Bowser Jr., by dahnamics
;;
;; Credit: mikeyk (Shy Guy), Yoshicookiezeus (Thwomp boss v. 2.0), Schwa (sledge_ex)
;;
;; Description: This sprite is loosely based on Bowser Jr. from NSMB. He cannot be jumped on
;; until Mario throws a shell at him. Just like his form in 4-Tower, 6-Tower2, 7-Tower
;; and the towers in World 8, he throws a shell at Mario and Mario throws the shell back
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Shy Guy, by mikeyk
;;
;; Description: A Shy Guy with many available configurations.
;;
;; Note: When rideable, clipping tables values should be: 03 0A FE 0E
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Uses first extra bit: NO
;;
;; Extra Property Byte 1
;; bit 0 - enable spin killing
;; bit 1 - stay on ledges
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SPRITE_Y_SPEED = $AA
SPRITE_X_SPEED = $B6
SPRITE_Y_POS = $D8
ORIG_Y_POS = $151C
H_OFFSCREEN = $15A0
V_OFFSCREEN = $186C
FREEZE_TIMER = $1540
SMASH_STATUS = $1602
STATE_TIMER = $163E
RAM_ThrowTimer = $1504
SPR_OBJ_STATUS = $1588
EXTRA_BITS = $7FAB10
EXTRA_PROP_1 = $7FAB28
GetSpriteClippingA = $03B69F
CheckForContact = $03B72B
GetSpriteClippingB = $03B6E5
ShowSprContactGfx = $01AB72
Invuln_Timer = $1564 ; The RAM address for Clawgrip's stun duration
MAX_Y_SPEED = $3E
MAX_Y_SPEED2 = $C2
; definitions of bits (don't change these)
IS_ON_GROUND = $04
IS_ON_CEILING = $08
TIME_ON_GROUND = $A0
TIME_TO_SHAKE = $40
RISE_SPEED = $C0
SOUND_EFFECT = $09
SPRITE_GRAVITY = $20
SPRITE_GRAVITY2 = $04
TIME_TO_EXPLODE = $00
X_SPEED dcb $08,$F8,$10,$F0
X_SPEED2 dcb $20,$E0
HURT_SPEED dcb $20,$E0
KILLED_X_SPEED dcb $F0,$10
SPRITE_STATE = $C2
HIT_POINTS = $05 ; being stomped by Mario
SPHERE = $6F
PROPFLASH:
dcb $04,$06,$08,$0C,$04,$06,$08,$0C
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite init JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dcb "INIT"
LDA SPRITE_Y_POS,x
STA ORIG_Y_POS,x
LDA $E4,x
CLC
ADC #$08
STA $E4,x
TXA
AND #$03
ASL A
ASL A
ASL A
ASL A
ASL A
STA STATE_TIMER,x
CLC
ADC #$32
STA RAM_ThrowTimer,x
PHY
JSR SUB_HORZ_POS
TYA
STA $157C,x
PLY
LDA $1588,x ; if on the ground, reset the turn counter
ORA #$04
STA $1588,x ; if on the ground, reset the turn counter
RTL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite code JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dcb "MAIN"
PHB ; \
PHK ; | main sprite function, just calls local subroutine
PLB ; |
JSR SPRITE_CODE_START ; |
PLB ; |
RTL ; /
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite main code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RETURN RTS
SPRITE_CODE_START
JSR SUB_GFX ; graphics routine
LDA $14C8,x ; return if sprite status != 8
CMP #$08 ; \ if status != 8, return
BNE RETURN ; /
LDA $9D ; \ if sprites locked, return
BNE RETURN ; /
JSR SUB_OFF_SCREEN_X3 ; handle off screen situation
DONE_WITH_SPEED
JSL $018032 ; interact with sprites
LDA $1528,x ; \ if sprite hit counter == 3
CMP #HIT_POINTS ; |
BEQ NO_CONTACT ; /
JSR HIT_ROUTINE
MARIO_INTERACT JSL $01A7DC ; interact with mario
BCC NO_CONTACT ; return if no contact
LDA $154C,x ; \ if sprite invincibility timer > 0 ...
BNE NO_CONTACT ; / ... goto NO_CONTACT
LDA #$08 ; \ sprite invincibility timer = $08
STA $154C,x ; /
LDA $7D ; \ if Mario's y speed < 10 ...
CMP #$10 ; } ... sprite will DEAD Mario
BMI SPRITE_WINS ; /
LDA SPRITE_STATE,x ; return if sprite is invulnerable
CMP #$05
BNE SPRITE_WINS
MARIO_WINS
JSR SUB_STOMP_PTS ; give Mario points
JSL $01AA33 ; set Mario speed
JSL $01AB99 ; display contact graphic
LDA #$28 ; \ sound effect
STA $1DFC ; /
LDA #$A0 ; \ Set stunned timer
STA $1564,x ; /
INC $1528,x ; increment sprite hit counter
LDA $1528,x ; \ if sprite hit counter == 3
CMP #HIT_POINTS ; |
BNE SMUSH_SPRITE ; /
SMUSH_SPRITE LDA #$0C ; \ time to show semi-squashed sprite = $0C
STA $1FE2,x ; /
LDA $1528,x ; \ if sprite hit counter == 3
CMP #HIT_POINTS ; |
BEQ SPRITE_DEAD ; /
LDA #$04
STA SPRITE_STATE,x
BRA NEW_RETURN
SPRITE_DEAD LDA #$06
STA SPRITE_STATE,x
NEW_RETURN RTS ; return
SPRITE_WINS
LDA $1497 ; \ if Mario is invincible...
ORA $187A ; } ... or Mario on yoshi...
BNE NO_CONTACT ; / ... return
JSR SUB_HORZ_POS ; \ set new sprite direction
TYA ; }
STA $157C,x ; /
JSL $00F5B7 ; hurt Mario
NO_CONTACT LDA SPRITE_STATE,x
CMP #$01
BEQ WALKING0
CMP #$02
BEQ FURIOUS0
CMP #$03
BEQ THROWING0
CMP #$04
BEQ HURT0
CMP #$05
BEQ STUNNED0
CMP #$06
BEQ DEAD0
CMP #$07
BEQ EXITING0
;-----------------------------------------------------------------------------------------
; state 0
;-----------------------------------------------------------------------------------------
WAITING
LDA V_OFFSCREEN,x ;fall if offscreen vertically
BNE SET_WALKING
LDA H_OFFSCREEN,x ;return if offscreen horizontally
BNE RETURN0
JSR SUB_HORZ_POS ;determine if mario is close and act accordingly
TYA
STA $157C,x
LDA $1588,x ; \ if sprite is in contact with an object...
AND #$03 ; |
BEQ NO_OBJ_CONTACT0 ; |
LDA $157C,x ; | flip the direction status
EOR #$01 ; |
STA $157C,x ; /
NO_OBJ_CONTACT0
LDA $1588,x ; run the subroutine if the sprite is in the air...
ORA $151C,x ; ...and not already turning
BNE ON_GROUND0 ;
JSR SUB_CHANGE_DIR ;
LDA #$01 ; set that we're already turning
STA $151C,x ;
ON_GROUND0
LDA $1588,x ; if on the ground, reset the turn counter
AND #$04
BEQ RETURN0
STZ $151C,x
STZ $AA,x
BRA X_TIME0
FALLING0
LDA $1588,x ; if on the ground, reset the turn counter
AND #$04
BEQ RETURN0
LDA #$10 ; \ y speed = 10
STA $AA,x ; /
X_TIME0 STZ $B6,x
BCS RETURN0
LDA $0F
CLC
ADC #$40
CMP #$80
BCS THWOMP_4
THWOMP_4
LDA $0F
CLC
ADC #$24
CMP #$50
BCS RETURN0
SET_WALKING
INC SPRITE_STATE,x ;chage state to falling
WALKING0 BRA WALKING
RETURN0 JSL $01802A ; update position based on speed values
RTS
THROWING0 JMP THROWING
FURIOUS0 JMP FURIOUS
HURT0 JMP HURT
STUNNED0 JMP STUNNED
DEAD0 JMP DEAD
EXITING0 JMP EXITING
;-----------------------------------------------------------------------------------------
; state 1
;-----------------------------------------------------------------------------------------
WALKING
LDA #$00 ; If timer isn't C0..
CMP $1534,x ;
JSR SUB_HORZ_POS ;determine if mario is close and act accordingly
TYA
STA $157C,x
LDA $1588,x ; \ if sprite is in contact with an object...
AND #$03 ; |
BEQ NO_OBJ_CONTACT ; |
LDA $157C,x ; | flip the direction status
EOR #$01 ; |
STA $157C,x ; /
NO_OBJ_CONTACT
LDA $1588,x ; run the subroutine if the sprite is in the air...
ORA $151C,x ; ...and not already turning
BNE ON_GROUND ;
JSR SUB_CHANGE_DIR ;
LDA #$01 ; set that we're already turning
STA $151C,x ;
ON_GROUND LDA $1588,x ; if on the ground, reset the turn counter
AND #$04
BEQ IN_AIR
STZ $151C,x
STZ $AA,x
BRA X_TIME
FALLING LDA $1588,x ; if on the ground, reset the turn counter
AND #$04
BEQ IN_AIR
LDA #$10 ; \ y speed = 10
STA $AA,x ; /
X_TIME LDA $1528,x ; \ set x speed based on total HP
ASL
CLC
ADC $157C,x ; and direction
TAY
LDA X_SPEED,y ; |
STA $B6,x ; /
CONTINUE2 LDA STATE_TIMER,x
CMP #$28 ; | just go to normal walking code
BCS RETURN0 ; /
LDA Invuln_Timer,x
CMP #$00
BNE RETURN0
LDA STATE_TIMER,x
CMP #$21
BNE NO_JUMP2
LDA $1570,x
LSR A
AND #01
BEQ NO_JUMP2
STZ STATE_TIMER,x ; x speed = 0
BRA RETURN2
NO_JUMP2 CMP #$00
BNE RETURN2
SET_FALLING STZ SPRITE_X_SPEED,x
LDA #$03
STA SPRITE_STATE,x
LDA #$00
STA SPRITE_Y_SPEED,x ;set initial speed
IN_AIR JSL $01802A ; update position based on speed values
RETURN2 RTS
;-----------------------------------------------------------------------------------------
; state 2
;-----------------------------------------------------------------------------------------
FURIOUS
LDA $1588,x ; \ if sprite is in contact with an object...
AND #$03 ; |
BEQ NO_OBJ_CONTACT2 ; |
LDA $157C,x ; | flip the direction status
EOR #$01 ; |
STA $157C,x ; /
NO_OBJ_CONTACT2
LDA $1588,x ; run the subroutine if the sprite is in the air...
ORA $151C,x ; ...and not already turning
BNE X_TIME2 ;
JSR SUB_CHANGE_DIR ;
LDA #$01 ; set that we're already turning
STA $151C,x ;
X_TIME2 LDY $157C,x ; \ set x speed based on direction
LDA X_SPEED2,y ; |
STA $B6,x ; /
JSR Hop ; Jump to custom code
IN_AIR2 JSL $01802A ; update position based on speed values
Hop:
LDA #$C0 ; If timer isn't C0..
CMP $1504,x ;
BNE IncreaseHop ; Increase it.
LDA $1588,x ; Don't jump if already on ground.
AND #$04 ;
BEQ RETURN4 ;
JSR SUB_HAMMER_THROW2
LDA #$C0 ; Set jump height.
STA $AA,x ; Store it too.
STZ $1504,x ; Reset timer.
RTS ; Return
IncreaseHop:
INC $1504,x ; Increase timer.
RETURN4 RTS
;-----------------------------------------------------------------------------------------
; state 3
;-----------------------------------------------------------------------------------------
THROWING LDA #$00
STA SPRITE_Y_SPEED,x ;set initial speed
JSL $01801A ;apply speed
LDA SPRITE_Y_SPEED,x ;increase speed if below the max
CMP #MAX_Y_SPEED
BCS DONT_INC_SPEED
ADC #SPRITE_GRAVITY2
STA SPRITE_Y_SPEED,x
DONT_INC_SPEED
JSL $019138 ;interact with objects
LDA $1564,x ; return if sprite is invulnerable
CMP #$00
BNE RETURN67
JSR SUB_HAMMER_THROW
LDA #$F0 ; set the time of flight to F0
STA STATE_TIMER,x
LDA #$01
STA SPRITE_STATE,x
STZ SMASH_STATUS,x
RETURN67 RTS
;-----------------------------------------------------------------------------------------
; state 4
;-----------------------------------------------------------------------------------------
HURT LDA $1588,x ; \ if sprite is in contact with an object...
AND #$03 ; |
BEQ NO_OBJ_CONTACT1 ; |
LDA $157C,x ; | flip the direction status
EOR #$01 ; |
STA $157C,x ; /
NO_OBJ_CONTACT1
LDY $157C,x ; \ set x speed based on direction
LDA HURT_SPEED,y ; |
STA $B6,x
LDA $1564,x ; return if sprite is invulnerable
CMP #$00
BNE RETURN68
LDA $1528,x
CMP #$02
BCC ATTACK1
LDA #$02
STA SPRITE_STATE,x
BRA RETURN68
ATTACK1
LDA #$01
STA SPRITE_STATE,x
RETURN68 JSL $01802A ;apply speed
RTS
;-----------------------------------------------------------------------------------------
; state 5
;-----------------------------------------------------------------------------------------
STUNNED LDA $1588,x ; \ if sprite is in contact with an object...
AND #$03 ; |
BEQ NO_OBJ_CONTACT3 ; |
LDA $157C,x ; | flip the direction status
EOR #$01 ; |
STA $157C,x ; /
NO_OBJ_CONTACT3
STZ $B6,x
Hop3:
LDA #$C0 ; If timer isn't C0..
CMP $1534,x ;
BNE IncreaseHop3 ; Increase it.
STZ $1534,x ; Reset timer.
LDA #$01
STA SPRITE_STATE,x
RTS ; Return
IncreaseHop3:
INC $1534,x ; Increase timer.
RETURN65 JSL $01802A ;apply speed
RTS
;-----------------------------------------------------------------------------------------
; state 6
;-----------------------------------------------------------------------------------------
DEAD LDA FREEZE_TIMER,x
BNE RETURN10
STZ SPRITE_X_SPEED,x
LDA $0F30
BNE RETURN10
LDA $0F33
AND $01
BNE RETURN10
INC SMASH_STATUS,X
LDA SMASH_STATUS,x
CMP #$02
BNE RETURN10
INC SPRITE_STATE,x ;chage state to falling
RETURN10 RTS
;-----------------------------------------------------------------------------------------
; state 7
;-----------------------------------------------------------------------------------------
EXITING
LDA V_OFFSCREEN,x ;fall if offscreen vertically
BNE GOAL
LDA H_OFFSCREEN,x ;return if offscreen horizontally
BNE RETURN1
JSL $01801A ;apply speed
LDA SPRITE_Y_SPEED,x ;increase speed if below the max
CMP #MAX_Y_SPEED2
BMI DONT_INC_SPEED2
SEC
SBC #SPRITE_GRAVITY2
STA SPRITE_Y_SPEED,x
DONT_INC_SPEED2
JSL $019138 ;interact with objects
LDA SPR_OBJ_STATUS,x ;return if not on the ceiling
AND #IS_ON_CEILING
BEQ RETURN1
JSR SUB_9A04 ; ?? speed related
LDA #TIME_TO_SHAKE ;shake ground
STA $1887
LDA #TIME_ON_GROUND ;set time to stay on ground
STA FREEZE_TIMER,x
RETURN1 RTS
GOAL STZ $14C8,x
DEC $13C6 ; prevent Mario from walking at the level end
LDA #$FF ; \ set goal
STA $1493 ; /
LDA #$0B ; \ set ending music
STA $1DFB ; /
RTS ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; hammer routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X_OFFSET dcb $F9,$07
X_OFFSET2 dcb $FF,$00
X_THROW_SPEED dcb $18,$E8
RETURN21 RTS
SUB_HAMMER_THROW LDA $15A0,x ; \ no egg if off screen
ORA $186C,x ; |
ORA $15D0,x
BNE RETURN21
JSL $02A9DE ; \ get an index to an unused sprite slot, return if all slots full
BMI RETURN21 ; / after: Y has index of sprite being generated
LDA #$0A ; \ set sprite status for new sprite
STA $14C8,y ; /
LDA #$04
STA $9E,y
PHY ; set x position for new sprite
LDA $157C,x
TAY
LDA $E4,x
CLC
ADC X_OFFSET,y
PLY
STA $00E4,y
PHY ; set x position for new sprite
LDA $157C,x
TAY
LDA $14E0,x
ADC X_OFFSET2,y
PLY
STA $14E0,y
LDA $D8,x ; \ set y position for new sprite
SEC ; | (y position of generator - 1)
SBC #$0E ; |
STA $00D8,y ; |
LDA $14D4,x ; |
SBC #$00 ; |
STA $14D4,y ; /
PHX ; \ before: X must have index of sprite being generated
TYX ; | routine clears *all* old sprite values...
JSL $07F7D2 ; | ...and loads in new values for the 6 main sprite tables
PLX ; /
PHY
LDA $157C,x
TAY
LDA X_THROW_SPEED,y
PLY
STA $B6,y
LDA #$C0
STA $AA,y
RETURN20 RTS ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; hammer routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X_OFFSET3 dcb $F9,$07
X_OFFSET4 dcb $FF,$00
X_THROW_SPEED2 dcb $30,$D0
RETURN58 RTS
SUB_HAMMER_THROW2
LDA $15A0,x ; \ no egg if off screen
ORA $186C,x ; |
ORA $15D0,x
BNE RETURN58
JSL $02A9DE ; \ get an index to an unused sprite slot, return if all slots full
BMI RETURN58 ; / after: Y has index of sprite being generated
LDA #$0A ; \ set sprite status for new sprite
STA $14C8,y ; /
LDA #$04
STA $9E,y
PHY ; set x position for new sprite
LDA $157C,x
TAY
LDA $E4,x
CLC
ADC X_OFFSET3,y
PLY
STA $00E4,y
PHY ; set x position for new sprite
LDA $157C,x
TAY
LDA $14E0,x
ADC X_OFFSET4,y
PLY
STA $14E0,y
LDA $D8,x ; \ set y position for new sprite
SEC ; | (y position of generator - 1)
SBC #$0E ; |
STA $00D8,y ; |
LDA $14D4,x ; |
SBC #$00 ; |
STA $14D4,y ; /
PHX ; \ before: X must have index of sprite being generated
TYX ; | routine clears *all* old sprite values...
JSL $07F7D2 ; | ...and loads in new values for the 6 main sprite tables
PLX ; /
PHY
LDA $157C,x
TAY
LDA X_THROW_SPEED2,y
PLY
STA $B6,y
LDA #$C0
STA $AA,y
LDA #TIME_TO_EXPLODE
STA $1540,y
RETURN57 RTS ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Be killed by shells
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HIT_ROUTINE:
HITPOINTS:
;TXA ; \ Process every 4 frames
;EOR $13 ; |
;AND #$03 ; |
;BNE RETURN_BOB ; /
LDY #$09 ; \ Loop over sprites:
KILLED_X_SPEED:
dcb $FF,$00
SpriteInteract:
ldy #$0b
InteractLoop:
lda $14c8,y
cmp #$09
bcs ProcessSprite
NextSprite:
dey
bpl InteractLoop
rts
ProcessSprite:
PHX
TYX
JSL GetSpriteClippingB
PLX
JSL GetSpriteClippingA
JSL CheckForContact
bcc NextSprite
PHX
TYX
JSL ShowSprContactGfx
LDA #$02 ; \ Kill thrown sprite
STA $14C8,x ; /
LDA #$D0 ; \ Set killed Y speed
STA $AA,x ; /
LDY #$00 ; Set killed X speed
LDA $B6,x
BPL SET_SPEED
INY
SET_SPEED
LDA KILLED_X_SPEED,y
STA $B6,x
PLX
HandleBirdoHit:
LDA #$13 ; \ sound effect
STA $1DF9 ; /
LDA SPRITE_STATE,x ; If jumping up
CMP #$03
BCS Return3
SHELL_CONTACT
LDA #$05
STA SPRITE_STATE,x
Return3:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PROPERTIES: dcb $7F,$3F
;The tables must now have 16 bytes.
;THE LAST 8 ARE ONLY CREATED BECAUSE OF XDISP.
;0-4 BYTE - FRAME 1 RIGHT
;4-8 BYTE - FRAME 2 RIGHT
;8-12 BYTE - FRAME 1 LEFT
;12-16 BYTE - FRAME 2 LEFT
TILEMAP:
dcb $00,$02,$20,$22 ; WALKING 1 ;\ RIGHT
dcb $04,$06,$24,$26 ; WALKING 2 ;/ RIGHT
dcb $00,$02,$20,$22 ; WAITING 1 ;\ RIGHT
dcb $84,$86,$A4,$A6 ; WAITING 2 ;/ RIGHT
dcb $40,$42,$60,$62 ; RETREAT 1 ;\ RIGHT
dcb $44,$46,$64,$66 ; RETREAT 2 ;/ RIGHT
dcb $08,$0A,$28,$2A ; THROW 1 ;\ RIGHT
dcb $0C,$0E,$2C,$2E ; THROW 2 ;/ RIGHT
dcb $80,$82,$A0,$A2 ; LEAPING 1 ;\ RIGHT
dcb $80,$82,$A0,$A2 ; LEAPING 2 ;/ RIGHT
dcb $8C,$8E,$AC,$AE ; STUNNED 1 ;\ RIGHT
dcb $C0,$C2,$E0,$E2 ; STUNNED 2 ;/ RIGHT
dcb $48,$4A,$68,$6A ; DYING 1 ;\ RIGHT
dcb $48,$4A,$68,$6A ; DYING 2 ;/ RIGHT
dcb $00,$02,$20,$22 ; WALKING 1 ;\ LEFT
dcb $04,$06,$24,$26 ; WALKING 2 ;/ LEFT
dcb $00,$02,$20,$22 ; WAITING 1 ;\ LEFT
dcb $84,$86,$A4,$A6 ; WAITING 2 ;/ LEFT
dcb $40,$42,$60,$62 ; RETREAT 1 ;\ LEFT
dcb $44,$46,$64,$66 ; RETREAT 2 ;/ LEFT
dcb $08,$0A,$28,$2A ; THROW 1 ;\ LEFT
dcb $0C,$0E,$2C,$2E ; THROW 2 ;/ LEFT
dcb $80,$82,$A0,$A2 ; LEAPING 1 ;\ LEFT
dcb $80,$82,$A0,$A2 ; LEAPING 2 ;/ LEFT
dcb $8C,$8E,$AC,$AE ; STUNNED 1 ;\ LEFT
dcb $C0,$C2,$E0,$E2 ; STUNNED 2 ;/ LEFT
dcb $48,$4A,$68,$6A ; DYING 1 ;\ LEFT
dcb $48,$4A,$68,$6A ; DYING 2 ;/ LEFT
YDISP:
dcb $F0,$F0,$00,$00 ; WALKING 1 ;\ RIGHT
dcb $F0,$F0,$00,$00 ; WALKING 2 ;/ RIGHT
dcb $F0,$F0,$00,$00 ; WAITING 1 ;\ RIGHT
dcb $F0,$F0,$00,$00 ; WAITING 2 ;/ RIGHT
dcb $F0,$F0,$00,$00 ; RETREAT 1 ;\ RIGHT
dcb $F0,$F0,$00,$00 ; RETREAT 2 ;/ RIGHT
dcb $F0,$F0,$00,$00 ; THROW 1 ;\ RIGHT
dcb $F0,$F0,$00,$00 ; THROW 2 ;/ RIGHT
dcb $F0,$F0,$00,$00 ; LEAPING 1 ;\ RIGHT
dcb $F0,$F0,$00,$00 ; LEAPING 2 ;/ RIGHT
dcb $F0,$F0,$00,$00 ; STUNNED 1 ;\ RIGHT
dcb $F0,$F0,$00,$00 ; STUNNED 2 ;/ RIGHT
dcb $F0,$F0,$00,$00 ; DYING 1 ;\ RIGHT
dcb $F0,$F0,$00,$00 ; DYING 2 ;/ RIGHT
dcb $F0,$F0,$00,$00 ; WALKING 1 ;\ LEFT
dcb $F0,$F0,$00,$00 ; WALKING 2 ;/ LEFT
dcb $F0,$F0,$00,$00 ; WAITING 1 ;\ LEFT
dcb $F0,$F0,$00,$00 ; WAITING 2 ;/ LEFT
dcb $F0,$F0,$00,$00 ; RETREAT 1 ;\ LEFT
dcb $F0,$F0,$00,$00 ; RETREAT 2 ;/ LEFT
dcb $F0,$F0,$00,$00 ; THROW 1 ;\ LEFT
dcb $F0,$F0,$00,$00 ; THROW 2 ;/ LEFT
dcb $F0,$F0,$00,$00 ; LEAPING 1 ;\ LEFT
dcb $F0,$F0,$00,$00 ; LEAPING 2 ;/ LEFT
dcb $F0,$F0,$00,$00 ; STUNNED 1 ;\ LEFT
dcb $F0,$F0,$00,$00 ; STUNNED 2 ;/ LEFT
dcb $F0,$F0,$00,$00 ; DYING 1 ;\ LEFT
dcb $F0,$F0,$00,$00 ; DYING 2 ;/ LEFT
XDISP:
dcb $00,$10,$00,$10 ; WALKING 1 ;\ RIGHT
dcb $00,$10,$00,$10 ; WALKING 2 ;/ RIGHT
dcb $00,$10,$00,$10 ; WALKING 1 ;\ RIGHT
dcb $00,$10,$00,$10 ; WALKING 2 ;/ RIGHT
dcb $00,$10,$00,$10 ; RETREAT 1 ;\ RIGHT
dcb $00,$10,$00,$10 ; RETREAT 2 ;/ RIGHT
dcb $00,$10,$00,$10 ; THROW 1 ;\ RIGHT
dcb $00,$10,$00,$10 ; THROW 2 ;/ RIGHT
dcb $00,$10,$00,$10 ; LEAPING 1 ;\ RIGHT
dcb $00,$10,$00,$10 ; LEAPING 2 ;/ RIGHT
dcb $00,$10,$00,$10 ; STUNNED 1 ;\ RIGHT
dcb $00,$10,$00,$10 ; STUNNED 2 ;/ RIGHT
dcb $00,$10,$00,$10 ; DYING 1 ;\ RIGHT
dcb $00,$10,$00,$10 ; DYING 2 ;/ RIGHT
dcb $10,$00,$10,$00 ; WALKING 1 ;\ LEFT
dcb $10,$00,$10,$00 ; WALKING 2 ;/ LEFT
dcb $10,$00,$10,$00 ; WALKING 1 ;\ LEFT
dcb $10,$00,$10,$00 ; WALKING 2 ;/ LEFT
dcb $10,$00,$10,$00 ; RETREAT 1 ;\ LEFT
dcb $10,$00,$10,$00 ; RETREAT 2 ;/ LEFT
dcb $10,$00,$10,$00 ; THROW 1 ;\ LEFT
dcb $10,$00,$10,$00 ; THROW 2 ;/ LEFT
dcb $10,$00,$10,$00 ; LEAPING 1 ;\ LEFT
dcb $10,$00,$10,$00 ; LEAPING 2 ;/ LEFT
dcb $10,$00,$10,$00 ; STUNNED 1 ;\ LEFT
dcb $10,$00,$10,$00 ; STUNNED 2 ;/ LEFT
dcb $10,$00,$10,$00 ; DYING 1 ;\ LEFT
dcb $10,$00,$10,$00 ; DYING 2 ;/ LEFT
SUB_GFX:
JSR GET_DRAW_INFO
LDA $1602,x
STA $03 ; | $03 = index to frame start (0 or 4)
LDA $14 ;\ Frame counter ..
LSR A ; |
LSR A ; | Add in frame animation rate; More LSRs for slower animation.
LSR A ; |
AND #$01 ; | 01 means we animate between 2 frames (00 and 01).
ASL A ; |
ASL A ; | ASL x2 (0-4) makes it switch between the first byte and fifth byte,
STA $03 ;/ i.e. first animation and second animation. The result is stored into $03.
LDA SPRITE_STATE,x ; If jumping up
CMP #$06
BNE NOT_DEAD
LDA $03
CLC
ADC #$30 ; ...set killed frame
STA $03
LDA $15F6,x ; \
ORA #$80 ; | ...flip vertically
STA $15F6,x ; /
BRA DONE_WALKING
NOT_DEAD:
LDA SPRITE_STATE,x ; if retreating into shell
CMP #$04
BNE KNOCKED_BACK ; |
LDA $03 ; |
CLC ; |
ADC #$10 ; | ...use stun frames.
STA $03 ; /
BRA DONE_WALKING
KNOCKED_BACK:
LDA SPRITE_STATE,x ; if retreating into shell
CMP #$05
BNE YELLING ; |
LDA $03 ; |
CLC ; |
ADC #$28 ; | ...use stun frames.
STA $03 ; /
BRA DONE_WALKING
YELLING:
LDA SPRITE_STATE,x ; if yelling at Mario
CMP #$00
BNE JUMPING ; |
LDA $03 ; |
CLC ; |
ADC #$08 ; | ...use stun frames.
STA $03 ; /
BRA DONE_WALKING
JUMPING:
LDA SPRITE_STATE,x ; if exiting the level
CMP #$07
BNE IN_THE_AIR ; |
LDA $03 ; |
CLC ; |
ADC #$20 ; | ...use stun frames.
STA $03 ; /
BRA DONE_WALKING
IN_THE_AIR:
LDA SPR_OBJ_STATUS,x ;return if on the ground
CMP #$04 ; |
BEQ THROWING_SHELL ; |
LDA $03 ; |
CLC ; |
ADC #$20 ; | ...use stun frames.
STA $03 ; /
BRA DONE_WALKING
THROWING_SHELL:
LDA SPRITE_STATE,x ; If throwing shell
CMP #$03
BNE DONE_WALKING ; |
LDA $03 ; |
CLC ; |
ADC #$18 ; | ...use stun frames.
STA $03 ; /
; BRA DONE_WALKING
DONE_WALKING:
LDA $157C,x
STA $02 ; Store direction to $02 for use with property routine later.
BNE NoAdd
LDA $03 ;\
CLC ; | If sprite faces left ..
ADC #$38 ; | Adding 16 more bytes to the table.
STA $03 ;/ So we can invert XDISP to not mess up the sprite's appearance.
NoAdd:
PHX ;\ Push sprite index ..
LDX #$03 ;/ And load X with number of tiles to loop through.
Loop:
PHX ; Push number of tiles to loop through.
TXA ;\
ORA $03 ;/ Transfer it to X and add in the "left displacement" if necessary.
TAX ;\ Get it back into X for an index.
LDA $00 ;\
CLC ; | Apply X displacement of the sprite.
ADC XDISP,x ; |
STA $0300,y ;/
LDA $01 ;\
CLC ; | Y displacement is added for the Y position, so one tile is higher than the other.
ADC YDISP,x ; | Otherwise, both tiles would have been drawn to the same position!
STA $0301,y ; | If X is 00, i.e. first tile, then load the first value from the table and apply that
;/ as the displacement. For the second tile, F0 is added to make it higher than the first.
LDA TILEMAP,x
STA $0302,y
PHX ; Push number of times to go through loop + "left" displacement if necessary.
LDX $02 ;\
LDA PROPERTIES,x ; | Set properties based on direction.
STA $0303,y ;/
PLX ; Pull number of times to go through loop.
INY ;\
INY ; | The OAM is 8x8, but our sprite is 16x16 ..
INY ; | So increment it 4 times.
INY ;/
PLX ; Pull current tile back.
DEX ; After drawing this tile, decrease number of tiles to go through loop. If the second tile
; is drawn, then loop again to draw the first tile.
BPL Loop ; Loop until X becomes negative (FF).
PLX ; Pull back the sprite index! We pushed it at the beginning of the routine.
LDY #$02 ; Y ends with the tile size .. 02 means it's 16x16
LDA #$03 ; A -> number of tiles drawn - 1.
; I drew 2 tiles, so 2-1 = 1. A = 01.
JSL $01B7B3 ; Call the routine that draws the sprite.
RTS ; Never forget this!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_CHANGE_DIR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;org $019098
SUB_CHANGE_DIR ;LDA $15AC,x
;BNE LABEL41
;LDA #$08
;STA $15AC,x
LDA $B6,x
EOR #$FF
INC A
STA $B6,x
LDA $157C,x
EOR #$01
STA $157C,x
LABEL41 RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; speed related
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SUB_9A04 LDA SPR_OBJ_STATUS,x
BMI THWOMP_1
LDA #$00
LDY $15B8,x
BEQ THWOMP_2
THWOMP_1 LDA #$18
THWOMP_2 STA SPRITE_Y_SPEED,x
RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routines below can be shared by all sprites. they are ripped from original
; SMW and poorly documented
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; points routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STAR_SOUNDS dcb $00,$13,$14,$15,$16,$17,$18,$19
SUB_STOMP_PTS PHY ;
LDA $1697 ; \
CLC ; |
ADC $1626,x ; / some enemies give higher pts/1ups quicker??
INC $1697 ; increase consecutive enemies stomped
TAY ;
INY ;
CPY #$08 ; \ if consecutive enemies stomped >= 8 ...
BCS NO_SOUND ; / ... don't play sound
LDA STAR_SOUNDS,y ; \ play sound effect
STA $1DF9 ; /
NO_SOUND TYA ; \
CMP #$08 ; | if consecutive enemies stomped >= 8, reset to 8
BCC NO_RESET ; |
LDA #$08 ; /
NO_RESET JSL $02ACE5 ; give mario points
PLY ;
RTS ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B760 - graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;org $03B75C
TABLE1 dcb $0C,$1C
TABLE2 dcb $01,$02
GET_DRAW_INFO STZ $186C,x ; reset sprite offscreen flag, vertical
STZ $15A0,x ; reset sprite offscreen flag, horizontal
LDA $E4,x ; \
CMP $1A ; | set horizontal offscreen if necessary
LDA $14E0,x ; |
SBC $1B ; |
BEQ ON_SCREEN_X ; |
INC $15A0,x ; /
ON_SCREEN_X LDA $14E0,x ; \
XBA ; |
LDA $E4,x ; |
REP #$20 ; |
SEC ; |
SBC $1A ; | mark sprite invalid if far enough off screen
CLC ; |
ADC.W #$0040 ; |
CMP.W #$0180 ; |
SEP #$20 ; |
ROL A ; |
AND #$01 ; |
STA $15C4,x ; /
BNE INVALID ;
LDY #$00 ; \ set up loop:
LDA $1662,x ; |
AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ON_SCREEN_LOOP ; | else, go through loop once
INY ; /
ON_SCREEN_LOOP LDA $D8,x ; \
CLC ; | set vertical offscreen if necessary
ADC TABLE1,y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,x ; |
ADC #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ON_SCREEN_Y ; |
LDA $186C,x ; | (vert offscreen)
ORA TABLE2,y ; |
STA $186C,x ; |
ON_SCREEN_Y DEY ; |
BPL ON_SCREEN_LOOP ; /
LDY $15EA,x ; get offset to sprite OAM
LDA $E4,x ; \
SEC ; |
SBC $1A ; | $00 = sprite x position relative to screen boarder
STA $00 ; /
LDA $D8,x ; \
SEC ; |
SBC $1C ; | $01 = sprite y position relative to screen boarder
STA $01 ; /
RTS ; return
INVALID PLA ; \ return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B829 - vertical mario/sprite position check - shared
; Y = 1 if mario below sprite??
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;org $03B829
SUB_VERT_POS LDY #$00 ;A:25A1 X:0007 Y:0001 D:0000 DB:03 S:01EA P:envMXdizCHC:0130 VC:085 00 FL:924
LDA $96 ;A:25A1 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdiZCHC:0146 VC:085 00 FL:924
SEC ;A:2546 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizCHC:0170 VC:085 00 FL:924
SBC $D8,x ;A:2546 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizCHC:0184 VC:085 00 FL:924
STA $0F ;A:25D6 X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0214 VC:085 00 FL:924
LDA $97 ;A:25D6 X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0238 VC:085 00 FL:924
SBC $14D4,x ;A:2501 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizcHC:0262 VC:085 00 FL:924
BPL LABEL11 ;A:25FF X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0294 VC:085 00 FL:924
INY ;A:25FF X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0310 VC:085 00 FL:924
LABEL11 RTS ;A:25FF X:0007 Y:0001 D:0000 DB:03 S:01EA P:envMXdizcHC:0324 VC:085 00 FL:924
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B817 - horizontal mario/sprite check - shared
; Y = 1 if mario left of sprite??
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;org $03B817
SUB_HORZ_POS LDY #$00 ;A:25D0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1020 VC:097 00 FL:31642
LDA $94 ;A:25D0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZCHC:1036 VC:097 00 FL:31642
SEC ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1060 VC:097 00 FL:31642
SBC $E4,x ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1074 VC:097 00 FL:31642
STA $0F ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1104 VC:097 00 FL:31642
LDA $95 ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1128 VC:097 00 FL:31642
SBC $14E0,x ;A:2500 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZcHC:1152 VC:097 00 FL:31642
BPL LABEL16 ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1184 VC:097 00 FL:31642
INY ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1200 VC:097 00 FL:31642
LABEL16 RTS ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B85D - off screen processing code - shared
; sprites enter at different points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;org $03B83B
TABLE3 dcb $40,$B0
TABLE6 dcb $01,$FF
TABLE4 dcb $30,$C0,$A0,$80,$A0,$40,$60,$B0
TABLE5 dcb $01,$FF,$01,$FF,$01,$00,$01,$FF
SUB_OFF_SCREEN_X0 LDA #$06 ; \ entry point of routine determines value of $03
BRA STORE_03 ; |
SUB_OFF_SCREEN_X1 LDA #$04 ; |
BRA STORE_03 ; |
SUB_OFF_SCREEN_X2 LDA #$02 ; |
STORE_03 STA $03 ; |
BRA START_SUB ; |
SUB_OFF_SCREEN_X3 STZ $03 ; /
START_SUB JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return
BEQ RETURN_2 ; /
LDA $5B ; \ goto VERTICAL_LEVEL if vertical level
AND #$01 ; |
BNE VERTICAL_LEVEL ; /
LDA $D8,x ; \
CLC ; |
ADC #$50 ; | if the sprite has gone off the bottom of the level...
LDA $14D4,x ; | (if adding 0x50 to the sprite y position would make the high byte >= 2)
ADC #$00 ; |
CMP #$02 ; |
BPL ERASE_SPRITE ; / ...erase the sprite
LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_2 ; /
LDA $13 ; \
AND #$01 ; |
ORA $03 ; |
STA $01 ; |
TAY ; /
LDA $1A ;x boundry ;A:0101 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0256 VC:090 00 FL:16953
CLC ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0280 VC:090 00 FL:16953
ADC TABLE4,y ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0294 VC:090 00 FL:16953
ROL $00 ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0326 VC:090 00 FL:16953
CMP $E4,x ;x pos ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0364 VC:090 00 FL:16953
PHP ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0394 VC:090 00 FL:16953
LDA $1B ;x boundry hi ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizCHC:0416 VC:090 00 FL:16953
LSR $00 ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0440 VC:090 00 FL:16953
ADC TABLE5,y ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdizcHC:0478 VC:090 00 FL:16953
PLP ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0510 VC:090 00 FL:16953
SBC $14E0,x ;x pos high ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0538 VC:090 00 FL:16953
STA $00 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0570 VC:090 00 FL:16953
LSR $01 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0594 VC:090 00 FL:16953
BCC LABEL20 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0632 VC:090 00 FL:16953
EOR #$80 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0648 VC:090 00 FL:16953
STA $00 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0664 VC:090 00 FL:16953
LABEL20 LDA $00 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0688 VC:090 00 FL:16953
BPL RETURN_2 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0712 VC:090 00 FL:16953
ERASE_SPRITE LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite
CMP #$08 ; |
BCC KILL_SPRITE ; /
LDY $161A,x ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0140 VC:071 00 FL:21152
CPY #$FF ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0172 VC:071 00 FL:21152
BEQ KILL_SPRITE ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0188 VC:071 00 FL:21152
LDA #$00 ; \ mark sprite to come back A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0204 VC:071 00 FL:21152
STA $1938,y ; / A:FF00 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0220 VC:071 00 FL:21152
KILL_SPRITE STZ $14C8,x ; erase sprite
RETURN_2 RTS ; return
VERTICAL_LEVEL LDA $167A,x ; \ if "process offscreen" flag is set, return
AND #$04 ; |
BNE RETURN_2 ; /
LDA $13 ; \ only handle every other frame??
LSR A ; |
BCS RETURN_2 ; /
AND #$01 ;A:0227 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0228 VC:112 00 FL:1142
STA $01 ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0244 VC:112 00 FL:1142
TAY ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0268 VC:112 00 FL:1142
LDA $1C ;A:0201 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0282 VC:112 00 FL:1142
CLC ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0306 VC:112 00 FL:1142
ADC TABLE3,y ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0320 VC:112 00 FL:1142
ROL $00 ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0352 VC:112 00 FL:1142
CMP $D8,x ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0390 VC:112 00 FL:1142
PHP ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0420 VC:112 00 FL:1142
LDA.W $001D ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNVMXdizcHC:0442 VC:112 00 FL:1142
LSR $00 ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdiZcHC:0474 VC:112 00 FL:1142
ADC TABLE6,y ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdizCHC:0512 VC:112 00 FL:1142
PLP ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0544 VC:112 00 FL:1142
SBC $14D4,x ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0572 VC:112 00 FL:1142
STA $00 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0604 VC:112 00 FL:1142
LDY $01 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0628 VC:112 00 FL:1142
BEQ LABEL22 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0652 VC:112 00 FL:1142
EOR #$80 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0668 VC:112 00 FL:1142
STA $00 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0684 VC:112 00 FL:1142
LABEL22 LDA $00 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0708 VC:112 00 FL:1142
BPL RETURN_2 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0732 VC:112 00 FL:1142
BMI ERASE_SPRITE ;A:0280 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0170 VC:064 00 FL:1195
SUB_IS_OFF_SCREEN LDA $15A0,x ; \ if sprite is on screen, accumulator = 0
ORA $186C,x ; |
RTS ; / return