;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Goomba Boss, by imamelia ;; ;; This sprite will walk around, always facing and following the player, ;; and it can be stomped. It takes three hits to defeat, and it gets faster ;; after every hit. ;; ;; Uses first extra bit: YES ;; ;; If the first extra bit is set, the sprite will end the level or activate ;; the current screen exit, depending on what the extra property 1 ;; is set to. You can also set it to play the boss music when it comes ;; onscreen. ;; ;; Extra Property Byte 1: ;; ;; Bits 0 and 1-- ;; ;; 00: end level the normal way (if the extra bit is set) ;; 01: end level via secret exit (if the extra bit is set) <-- doesn't work for some reason; activates the normal exit ;; 02: activate the current screen exit (if the extra bit is set) ;; 03: activate the screen exit of screen 00 (if the extra bit is set) ;; ;; Known bugs: ;; ;; Although this sprite is compatible with slopes and walls ;; (I had to add a little bit of extra code for the second thing), ;; if two sprites are right next to a wall, the one closer to the ;; wall will go through it. And, as I said before, the secret exit ;; setting doesn't seem to work. ;; ;; Based on the following sprite: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Giant Goomba, by mikeyk ;; ;; Description: A large, squashable enemy. ;; ;; Uses first extra bit: NO ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; goomba init JSL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dcb "INIT" RTL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; goomba main JSL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dcb "MAIN" PHB ; \ PHK ; | main sprite function, just calls local subroutine PLB ; | JSR CODE_START ; | PLB ; | RTL ; / ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; goomba main code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X_SPEEDS dcb $08,$F8,$10,$F0,$18,$E8 KILLED_X_SPEED dcb $F0,$10 BounceSpeeds: dcb $18,$E8 HitPoints = $C2 TotalHP = $03 StompDisability = $1534 TimeToDisable = $60 ExtraBits = $7FAB10 ExtraProperty1 = $7FAB28 BounceCheck = $1594 BounceTime = $20 CODE_START JSR SUB_GFX ; graphics routine LDA $14C8,x ; \ CMP #$08 ; | if status != 8, return BNE RETURN ; / JSR SUB_OFF_SCREEN_X0 ; handle off screen situation LDA BounceCheck,x BNE NoFollow PHY JSR SUB_GET_DIR TYA PLY STA $157C,x ; always face the player NoFollow: LDA StompDisability,x ; BEQ NoDec1 ; decrement stomp disability timer if it is set DEC StompDisability,x NoDec1: LDA BounceCheck,x BEQ NoDec2 DEC BounceCheck,x NoDec2: LDA HitPoints,x ; \ set x speed based on total HP ASL CLC ADC $157C,x ; and direction TAY LDA X_SPEEDS,y ; | STA $B6,x ; / LDA $9D ; \ if sprites locked, return BNE RETURN ; / LDA $1558,x ; \ if sprite not defeated (timer to show remains > 0)... BEQ ALIVE ; / ... goto ALIVE STA $15D0,x ; \ DEC A ; } if sprite remains don't disappear next frame... BNE RETURN ; / ... return STZ $14C8,x ; this is the last frame to show remains, so set sprite status = 0 (not alive) RETURN RTS ; return ALIVE LDA $1588,x ; AND #$04 ; ; PHA ; preserve sprite blocked status as far as the ground goes LDA $1588,x AND #$03 ; if the sprite is touching a wall... BEQ DontJumpAway LDA $157C,x ; change the direction EOR #$01 STA $157C,x TAY LDA BounceSpeeds,y STA $B6,x ; set a new speed LDA #BounceTime ; and set the bounce timer STA BounceCheck,x ; (This is to prevent the sprite going through walls.) DontJumpAway: JSL $01802A ; update position based on speed values JSL $018032 ; interact with other sprites LDA $1588,x ; AND #$04 ; if the sprite is not touching the ground... BEQ IN_AIR ; branch to IN_AIR STZ $AA,x ; if the sprite is touching the ground, set its Y speed to 0 PLA ; ; pull blocked status from before BRA ON_GROUND ; branch to "ON_GROUND" IN_AIR PLA ; pull blocked status from before: if it is also 00.. BEQ WAS_IN_AIR ; then the sprite was in the air before updating its position LDA #$0A ; set the spin jump death animation frame counter STA $1540,x ; to 0A WAS_IN_AIR LDA $1540,x ; if the SDAFC is zero... BEQ ON_GROUND ; branch to "ON_GROUND" STZ $AA,x ; if not, reset the Y speed again ON_GROUND LDA $1588,x ; \ if sprite is in contact with an object... AND #$03 ; | BEQ DONT_UPDATE ; | LDA $157C,x ; | flip the direction status EOR #$01 ; | STA $157C,x ; / DONT_UPDATE JSL $01A7DC ; check for mario/sprite contact BCC RETURN_24 ; (carry set = contact) LDA $1490 ; \ if mario star timer > 0 ... BNE Star1 ; / ... goto HAS_STAR LDA $7D ; \ if mario's y speed < 10 ... CMP #$10 ; } ... sprite will hurt mario BMI GOOB_WINS ; / MARIO_WINS JSL $01AA33 ; set mario speed JSL $01AB99 ; display contact graphic LDA StompDisability,x ; if stomp disability timer isn't at 0... BNE Return54 ; don't play hurt sound effect, give points, or increment HP counter JSR SUB_STOMP_PTS ; give mario points INC HitPoints,x ; increment HP LDA #$28 ; play "jump on boss" sound effect STA $1DFC ; LDA HitPoints,x ; CMP #TotalHP ; if the sprite's HP has maxed out... BEQ BossDefeated ; kill the sprite LDA #TimeToDisable ; if not, STA StompDisability,x ; set stomp disable timer Return54: LDA #$02 STA $1DF9 ; play stomp sound effect RETURN_24 RTS ; return GOOB_WINS LDA $1497 ; \ if mario is invincible... ORA $187A ; } ... or mario on yoshi... ORA $15D0,x ; | ...or sprite being eaten... BNE RETURN2 ; / ... return JSR SUB_GET_DIR ; \ set new sprite direction TYA ; } STA $157C,x ; / JSL $00F5B7 ; hurt mario RETURN2 RTS ; return Star1: JMP HAS_STAR BossDefeated: LDA #$02 ; set sprite state: STA $14C8,x ; killed with spin jump LDA ExtraBits,x ; check to see AND #$04 ; if the extra bit is set BEQ RETURN2 ; and if not, don't bother to teleport or end the level LDA ExtraProperty1,x ; the extra property byte 1 determines how to end AND #$02 ; bit 1 determines whether to teleport or end the level BNE Teleport ; if it is set (extra prop.1 = 02 or 03), teleport LDA #$FF ; if not, just end the level STA $1493 ; (via goal sphere) DEC $13C6 ; prevent the player from walking at level end LDA #$0B ; set ending music STA $1DFB LDA ExtraProperty1,x ; AND #$01 ; check bit 0 of extra property byte STA $141C ; store this bit to the secret exit flag RTS Teleport: LDA ExtraProperty1,x ; AND #$01 ; check bit 0 of extra property 1 BEQ NormalScreen ; if it isn't set, just use the current screen exit setting LDA $19B8 ; screen exit setting of screen 00 PHY ; LDY $95 ; load Y with the current screen number (in a horizontal level) STA $19B8,y ; store screen exit 00 into the current screen exit PLY NormalScreen: LDA #$06 ; STA $71 ; set teleporting action RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; spin and star kill (still part of above routine) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; STAR_SOUNDS dcb $00,$13,$14,$15,$16,$17,$18,$19 SPIN_KILL LDA #$04 ; \ status = 4 (being killed by spin jump) STA $14C8,x ; / LDA #$1F ; \ set spin jump animation timer STA $1540,x ; / JSL $07FC3B ; show star animation LDA #$08 ; \ play sound effect STA $1DF9 ; / RTS ; return HAS_STAR LDA #$02 ; \ status = 2 (being killed by star) STA $14C8,x ; / LDA #$D0 ; \ set y speed STA $AA,x ; / JSR SUB_HORZ_POS ; get new direction LDA KILLED_X_SPEED,y ; \ set x speed based on direction STA $B6,x ; / INC $18D2 ; increment number consecutive enemies killed LDA $18D2 ; \ CMP #$08 ; | if consecutive enemies stomped >= 8, reset to 8 BCC NO_RESET2 ; | LDA #$08 ; | STA $18D2 ; / NO_RESET2 JSL $02ACE5 ; give mario points LDY $18D2 ; \ CPY #$08 ; | if consecutive enemies stomped < 8 ... BCS NO_SOUND2 ; | LDA STAR_SOUNDS,y ; | ... play sound effect STA $1DF9 ; / NO_SOUND2 RTS ; final return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; graphics routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;frame 1, frame 2, squashed (4 bytes each) TILE_SIZE dcb $02,$00,$00,$02,$02,$00,$00,$02,$00,$00,$00,$00 HORIZ_DISP dcb $04,$0C,$FC,$FC,$FC,$FC,$0C,$04,$04,$FC,$04,$0C VERT_DISP dcb $F8,$08,$F8,$00,$F8,$08,$F8,$00,$08,$08,$08,$08 TILEMAP dcb $8A,$AB,$8A,$8C,$8A,$AB,$8A,$8C,$AD,$AC,$AD,$AC PROPERTIES dcb $40,$00,$00,$00,$00,$40,$40,$40,$00,$00,$00,$40 SUB_GFX JSR GET_DRAW_INFO ;A:87BF X:0007 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZCHC:1102 VC:066 00 FL:665 LDA $157C,x ; \ $02 = direction STA $02 ; / LDA $14 ;\ LSR A ; | LSR A ; | LSR A ; | CLC ; | ADC $15E9 ; | AND #$01 ; | ASL A ; | ASL A ; | STA $03 ; | $03 = index to frame start (0 or 4) PHX ; / LDA $14C8,x CMP #$02 BNE NO_STAR STZ $03 NO_STAR LDA $1558,x ; \ if time to show sprite remains > 0... BEQ NOT_DEAD ; | LDA #$08 ; | $03 = 8 STA $03 ; / STX $15E9 NOT_DEAD LDX #$03 ; run loop 4 times, cuz 4 tiles per frame LOOP_START_2 PHX ; push, current tile TXA ; \ X = index of frame start + current tile CLC ; | ADC $03 ; | TAX ; / PHY ; set tile to be 8x8 or 16x16 TYA ; LSR A ; LSR A ; TAY ; LDA TILE_SIZE,x ; STA $0460,y ; PLY ; LDA $00 ; \ tile x position = sprite x location ($00) + tile displacement CLC ; | ADC HORIZ_DISP,x ; | STA $0300,y ; / LDA $01 ; | CLC ; | tile y position = sprite y location ($01) + tile displacement ADC VERT_DISP,x ; | STA $0301,y ; / LDA TILEMAP,x ; \ store tile STA $0302,y ; / PHX ; LDX $15E9 LDA $15F6,x ; get palette info PLX ; ORA PROPERTIES,x ; flip tile if necessary ORA $64 ; add in tile priority of level STA $0303,y ; store tile properties NoFlash: PLX ; \ pull, current tile INY ; | increase index to sprite tile map ($300)... INY ; | ...we wrote 1 16x16 tile... INY ; | ...sprite OAM is 8x8... INY ; | ...so increment 4 times DEX ; | go to next tile of frame and loop BPL LOOP_START_2 ; / PLX ; pull, X = sprite index LDY #$FF ; \ we've already set 460 so use FF LDA #$03 ; | A = number of tiles drawn - 1 JSL $01B7B3 ; / don't draw if offscreen RTS ; return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; points routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; routines below can be shared by all sprites. they are ripped from original ; SMW and poorly documented ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $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 ; / ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $B817 - horizontal mario/sprite check - shared ; Y = 1 if mario left of sprite?? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;org $03B817 ; Y = 1 if contact SUB_GET_DIR 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $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_HB 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 NOP