Timer = $16 ; how long until the sprite pops while mario stands on it HowSlow = $03 ; how slow the timer will increase, only these values apply; ;; (Fastest) $00 $01 $03 $07 $0F $1F $3F $7F $FF (slowest) ;rideable_balloon ;by smkdan ;DOESN'T USE EXTRA BIT ;balloon that you can step on for a ride ;Tilemaps for SP4 DIR = $03 PROPRAM = $04 PROPINDEX = $05 XDISPINDEX = $06 YDISPINDEX = $07 FRAMEINDEX = $08 TEMP = $09 XSPD dcb $00,$02,$04,$03,$00,$FE,$FC,$FD XMAR1 dcb $00,$00,$01,$01,$00,$00,$FF,$FF XMAR2 dcb $00,$00,$00,$00,$00,$00,$FF,$FF COUNT dcb $40,$10,$40,$10 PAL dcb $04,$06,$08,$0A SPDCMP dcb $FA,$FD INCDEC dcb $FF,$01 ;C2: riding bit HeightTbl dcw $FFE6,$FFD6,$FFD6 ClipTbl dcw $0016,$0026,$0026 dcb "INIT" LDA $E4,x ; save STA $1510,x ; initial LDA $14E0,x ; positions STA $151C,x ; to LDA $D8,x ; some STA $1570,x ; sprite LDA $14D4,x ; ram so it STA $157C,x ; can respawn LDA $7FAB10,x ;only use custom color if made from generator AND #$04 BEQ NormPal JSL $01ACF9 ;get random AND #$03 ;only low 2 bits TAY ;to be used as index LDA $15F6,x ;load properties AND #$F1 ;all but pal bits PHB PHK PLB ORA PAL,y ;set palette bits PLB STA $15F6,x ;new palette NormPal LDA #$FA ;fixed Yspd STA $AA,x ;initial Yspd RTL dcb "MAIN" PHB PHK PLB JSR Run PLB RTL Respawn STZ $1540,x LDA $1510,x STA $E4,x LDA $151C,x STA $14E0,x LDA $1570,x STA $D8,x LDA $157C,x STA $14D4,x STZ $187B,x STZ $1528,x JSR SUB_IS_OFF_SCREEN BNE Return_l JSR SUB_SMOKE LDA #$1E STA $1DF9 Return_l RTS Run JSR SUB_OFF_SCREEN_X0 JSR GET_DRAW_INFO LDA $1540,x BEQ Normal CMP #$02 BCC Respawn RTS Normal JSR GFX ;draw sprite LDA $14C8,x CMP #$08 BNE Return_l LDA $9D ;locked sprites? BNE Return_l LDA $15D0,x ;yoshi eating? BNE Return_l JSL $018022 JSL $01801A LDA $1528,x CMP #Timer BCC NoPop JSR SUB_SMOKE LDA #$20 STA $1540,x LDA #$19 STA $1DFC NoPop STZ $C2,x ;reset riding sprite, may get set later JSL $01A7DC ;mario interact BCC NoInteraction ;do nothing if there's no contact JSR SUB_VERT_POS LDA $0F CMP #$E4 BMI NoInteraction LDA $7D ;don't interact on rising speed BMI NoInteraction ;interacting, set positions LDA $187B,x AND #HowSlow BNE NoInc INC $1528,x NoInc LDA #$01 STA $C2,x ;set riding sprite for GFX routine LDA #$01 STA $1471 ;'riding sprite' STZ $7D ;no Y speed for mario LDA #$E8 LDY $187A BEQ NOYOSHI LDA #$E8-$10 NOYOSHI CLC ADC $D8,x STA $96 LDA $14D4,x ADC #$FF STA $97 NoInteraction ;apply speed INC $187B,x NoCnt LDA $187B,x LSR : LSR : LSR : LSR AND #$07 TAY LDA XSPD,y STA $B6,x LDA $C2,x BEQ NoMarMov LDA $187B,x AND #$03 BNE NoMarMov LDA $94 CLC ADC XMAR1,y STA $94 LDA $95 ADC XMAR2,y STA $95 NoMarMov LDY $C2,x ;load ride bit as index LDA SPDCMP,y STA $AA,x Return RTS SUB_SMOKE JSR SUB_IS_OFF_SCREEN BNE NoSmoke LDY #$03 LoopSmk LDA $17C0,y BEQ Found DEY BPL LoopSmk RTS Found LDA #$01 STA $17C0,y LDA $E4,x CLC ADC #$08 STA $17C8,y LDA $D8,x STA $17C4,y LDA #$1B STA $17CC,y NoSmoke RTS ;===== TILEMAP dcb $E0,$E2,$C4,$C6 XDISP dcb $00,$10,$00,$10 YDISP dcb $FE,$FE,$0E,$0E dcb $00,$00,$0E,$0E GFX LDA $C2,x ;stepped on? ASL A ;x4 ASL A STA FRAMEINDEX LDA $157C,x ;direction... STA DIR LDA $15F6,x ;properties... STA PROPRAM LDX #$00 ;loop index OAM_Loop LDA $00 CLC ADC XDISP,x STA $0300,y ;xpos TXA CLC ADC FRAMEINDEX ;variable YDISP PHX TAX LDA $01 CLC ADC YDISP,x STA $0301,y ;ypos PLX LDA TILEMAP,x STA $0302,y ;chr LDA PROPRAM ORA $64 STA $0303,y ;properties INY INY INY INY INX CPX #$04 ;4 tiles BNE OAM_Loop LDX $15E9 ;restore sprite index LDY #$02 ;16x16 tiles LDA #$03 ;4 tiles JSL $01B7B3 RTS ;return ;================= ;BORROWED ROUTINES ;================= ;GET_DRAW_INFO ;============== ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $B760 - graphics routine helper - shared ; sets off screen flags and sets index to OAM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SPR_T1 dcb $0C,$1C SPR_T2 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 SPR_T1,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 SPR_T2,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 ; / ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SUB_OFF_SCREEN ; This subroutine deals with sprites that have moved off screen ; It is adapted from the subroutine at $01AC0D ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SPR_T12 dcb $40,$B0 SPR_T13 dcb $01,$FF SPR_T14 dcb $30,$C0,$A0,$C0,$A0,$F0,$60,$90 ;bank 1 sizes dcb $30,$C0,$A0,$80,$A0,$40,$60,$B0 ;bank 3 sizes SPR_T15 dcb $01,$FF,$01,$FF,$01,$FF,$01,$FF ;bank 1 sizes dcb $01,$FF,$01,$FF,$01,$00,$01,$FF ;bank 3 sizes SUB_OFF_SCREEN_X1 LDA #$02 ; \ entry point of routine determines value of $03 BRA STORE_03 ; | (table entry to use on horizontal levels) SUB_OFF_SCREEN_X2 LDA #$04 ; | BRA STORE_03 ; | SUB_OFF_SCREEN_X3 LDA #$06 ; | BRA STORE_03 ; | SUB_OFF_SCREEN_X4 LDA #$08 ; | BRA STORE_03 ; | SUB_OFF_SCREEN_X5 LDA #$0A ; | BRA STORE_03 ; | SUB_OFF_SCREEN_X6 LDA #$0C ; | BRA STORE_03 ; | SUB_OFF_SCREEN_X7 LDA #$0E ; | STORE_03 STA $03 ; | BRA START_SUB ; | SUB_OFF_SCREEN_X0 STZ $03 ; / START_SUB JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return BEQ RETURN_35 ; / LDA $5B ; \ goto VERTICAL_LEVEL if vertical level AND #$01 ; | BNE VERTICAL_LEVEL ; / LDA $14D4,x ; | (if adding 0x50 to the sprite y position would make the high byte underflow... ; | CMP #$FF ; | ;underflowed? BEQ ERASE_SPRITE ; / ...erase the sprite LDA $167A,x ; \ if "process offscreen" flag is set, return AND #$04 ; | BNE RETURN_35 ; / LDA $13 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0756 VC:176 00 FL:205 AND #$01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0780 VC:176 00 FL:205 ORA $03 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0796 VC:176 00 FL:205 STA $01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0820 VC:176 00 FL:205 TAY ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0844 VC:176 00 FL:205 LDA $1A ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0858 VC:176 00 FL:205 CLC ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0882 VC:176 00 FL:205 ADC SPR_T14,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0896 VC:176 00 FL:205 ROL $00 ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizcHC:0928 VC:176 00 FL:205 CMP $E4,x ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:0966 VC:176 00 FL:205 PHP ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:0996 VC:176 00 FL:205 LDA $1B ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizCHC:1018 VC:176 00 FL:205 LSR $00 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdiZCHC:1042 VC:176 00 FL:205 ADC SPR_T15,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizcHC:1080 VC:176 00 FL:205 PLP ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F0 P:eNvMXdizcHC:1112 VC:176 00 FL:205 SBC $14E0,x ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1140 VC:176 00 FL:205 STA $00 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1172 VC:176 00 FL:205 LSR $01 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1196 VC:176 00 FL:205 BCC SPR_L31 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1234 VC:176 00 FL:205 EOR #$80 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1250 VC:176 00 FL:205 STA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1266 VC:176 00 FL:205 SPR_L31 LDA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1290 VC:176 00 FL:205 BPL RETURN_35 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1314 VC:176 00 FL:205 ERASE_SPRITE LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite CMP #$08 ; | BCC KILL_SPRITE ; / LDY $161A,x ;A:FF08 X:0007 Y:0001 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1108 VC:059 00 FL:2878 CPY #$FF ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1140 VC:059 00 FL:2878 BEQ KILL_SPRITE ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1156 VC:059 00 FL:2878 LDA #$00 ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1172 VC:059 00 FL:2878 STA $1938,y ;A:FF00 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZcHC:1188 VC:059 00 FL:2878 KILL_SPRITE LDA #$08 CMP $14C8,x BNE KILL LDA $1540,x BNE RETURN_35 STZ $186C,x JSR Respawn RETURN_35 RTS ; return KILL STZ $14C8,x RTS VERTICAL_LEVEL LDA $167A,x ; \ if "process offscreen" flag is set, return AND #$04 ; | BNE RETURN_35 ; / LDA $13 ; \ LSR A ; | BCS RETURN_35 ; / LDA $E4,x ; \ CMP #$00 ; | if the sprite has gone off the side of the level... LDA $14E0,x ; | SBC #$00 ; | CMP #$02 ; | BCS ERASE_SPRITE ; / ...erase the sprite LDA $13 ;A:0000 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:1218 VC:250 00 FL:5379 LSR A ;A:0016 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1242 VC:250 00 FL:5379 AND #$01 ;A:000B X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1256 VC:250 00 FL:5379 STA $01 ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1272 VC:250 00 FL:5379 TAY ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1296 VC:250 00 FL:5379 LDA $1C ;A:001A X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0052 VC:251 00 FL:5379 CLC ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0076 VC:251 00 FL:5379 ADC SPR_T12,y ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0090 VC:251 00 FL:5379 ROL $00 ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:enVMXdizCHC:0122 VC:251 00 FL:5379 CMP $D8,x ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0160 VC:251 00 FL:5379 PHP ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0190 VC:251 00 FL:5379 LDA.W $001D ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F2 P:eNVMXdizcHC:0212 VC:251 00 FL:5379 LSR $00 ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdiZcHC:0244 VC:251 00 FL:5379 ADC SPR_T13,y ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdizCHC:0282 VC:251 00 FL:5379 PLP ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:envMXdiZCHC:0314 VC:251 00 FL:5379 SBC $14D4,x ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0342 VC:251 00 FL:5379 STA $00 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0374 VC:251 00 FL:5379 LDY $01 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0398 VC:251 00 FL:5379 BEQ SPR_L38 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0422 VC:251 00 FL:5379 EOR #$80 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0438 VC:251 00 FL:5379 STA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0454 VC:251 00 FL:5379 SPR_L38 LDA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0478 VC:251 00 FL:5379 BPL RETURN_35 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0502 VC:251 00 FL:5379 BMI ERASE_SPRITE ;A:8AFF X:0002 Y:0000 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0704 VC:184 00 FL:5490 SUB_IS_OFF_SCREEN LDA $15A0,x ; \ if sprite is on screen, accumulator = 0 ORA $186C,x ; | RTS ; / return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SUB_VERT_POS ; This routine determines if Mario is above or below the sprite. It sets the Y register ; to the direction such that the sprite would face Mario ; It is ripped from $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 SPR_L11 ;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 SPR_L11 RTS ;A:25FF X:0007 Y:0001 D:0000 DB:03 S:01EA P:envMXdizcHC:0324 VC:085 00 FL:924