;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 $FC,$00,$04,$00
COUNT	dcb $40,$10,$40,$10
XADJUST	dcb $FF,$00,$01,$00
PAL	dcb $04,$06,$08,$0A

SPDCMP	dcb $F8,$FB
INCDEC	dcb $FF,$01

;C2: riding bit
;1570: behaviour count
;1602: X scroll counter


HeightTbl dcw $FFE6,$FFD6,$FFD6
ClipTbl	dcw $0016,$0026,$0026

dcb "INIT"

	;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

Return_l
	RTS

Run
	JSR SUB_OFF_SCREEN_X0
        JSL $20CA4F
	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

	STZ $C2,x		;reset riding sprite, may get set later

	JSL $01A7DC		;mario interact
	BCC NoInteraction	;do nothing if there's no contact

        LDA $7D			;don't interact on rising speed
        BMI NoInteraction


	LDA $187A		;yoshi flag
	CLC
	ASL A
	TAY			;into Y

;control height required to be on top of sprite

	LDA $14D4,x		;sprite high Y
	XBA
	LDA $D8,x		;sprite low Y
	REP #$20		;16bit math
	SEC
	SBC $96			;sub mario Y pos.  Mario is OVER the sprite.  Mario Y < sprite Y
	CMP ClipTbl,y		;compare depending on mario or yoshi mario
	SEP #$20
	BCC Return_I		;return if he's too low (underflows)

;interacting, set positions

	LDA #$01
	STA $C2,x		;set riding sprite for GFX routine

	LDA #$01
	STA $1471		;'riding sprite'
	STZ $7D			;no Y speed

	LDA $187A		;yoshi flag
	CLC
	ASL A			;2 bytes
	TAY			;into Y reg

	LDA $14D4,x		;sprite high Y
	XBA
	LDA $D8,x		;sprite low Y
	REP #$20
	CLC
	ADC HeightTbl,y		;stepped on height
	STA $96			;new mario Y position
	SEP #$20

NoInteraction
	INC $1602,x		;advance counter
	LDA $1602,x
	LDY $1570,x		;load behaviour as index
	CMP COUNT,y		;X frames
	BCC NoChange		;if count not yet reached, maintain C2

;advance behaviour since count was reached

	LDA $1570,x		;load scroll behaviour...
	INC A
	AND #$03		;4 variables
	STA $1570,x		;...new scroll behaviour
	STZ $1602,x		;reset counter

;apply speed

NoChange
	LDY $1570,x		;load as index
	LDA XSPD,y		;speed value
	STA $B6,x		;new Xspd

	LDA $C2,x		;load riding bit
	BEQ LeaveMario

;adjust Mario position
	
	LDA $1602,x		;load counter...
	AND #$03
	BNE LeaveMario		;every 2nd frame

	LDY $1570,x		;load balloon behaviour as index
	LDA XADJUST,y		;load adjustment
	CLC
	ADC $94			;MarioX low added
	STA $94			;store

;DO HIGH

LeaveMario
Return_I
	LDA $AA,x		;load Yspd
	LDY $C2,x		;load ride bit as index
	CMP SPDCMP,y		;load targetspeed
	BEQ StoreY

	CLC
	ADC INCDEC,y		;add or dec to Yspd

StoreY
	STA $AA,x		;store Yspd

UpdateXPosNoGrvty
	JSL $018022
	JSL $01801A		;update Y pos no gravity
	;JSL $01802A		;update speed

;-----------------------------------------------
;This bit of code will cause the sprite to "pop"
;-----------------------------------------------
	LDA $14D4,x
	XBA
	LDA $D8,x
	SEC
	SBC $1C
	CMP #$30
	BCC EraseSprite
	LDA $1588,x	; If not, check object interaction.
	AND #%00001000	; If the sprite is touching walls..
	BNE EraseSprite	; Explode.
	RTS

EraseSprite	
	STZ $14C8,x
	LDA #$19
	STA $1DFC

;==================================================================
;Draw Smoke
;==================================================================

;DrawSmoke:
		    LDY #$03                ; \ find a free slot to display effect
FINDFREE:           LDA $17C0,y             ;  |
                    BEQ FOUNDONE            ;  |
                    DEY                     ;  |
                    BPL FINDFREE            ;  |
                    RTS                     ; / return if no slots open

FOUNDONE:           LDA #$01                ; \ set effect graphic to smoke graphic
                    STA $17C0,y             ; /
                    LDA #$1B                ; \ set time to show smoke
                    STA $17CC,y             ; /
                    LDA $D8,x               ; \ smoke y position = generator y position
		    CLC
		    ADC #$08
                    STA $17C4,y             ; /
                    LDA $E4,x               ; \ load generator x position and store it for later
		    CLC
		    ADC #$08
                    STA $17C8,y             ; /
;                   RTS
;RTS

Return
	RTS
			
;=====

TILEMAP	dcb $E0,$E2,$A8,$AA

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 $01
;CMP #$40
;BNE Continue
;STZ $14C8,x
;Continue

	LDA TILEMAP,x
	STA $0302,y	;chr

	;LDA PROPRAM
	LDA #$39
	;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
;=================

	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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         STZ $14C8,x             ; erase sprite
RETURN_35           RTS                     ; return

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