;Baron Von Zeppelin
;by smkdan

;USES EXTRA BIT
;If set, it will come back after it's dropped it's payload.  Else, it won't come back.

;An enemy from SMW2 that holds a sprite of your choice and drops it when Mario gets near.

;Extra prop 1: How close Mario gets until the payload is dropped

;Tilemaps for SP3

DIR = $03
PROPRAM = $04
PROPINDEX = $05
XDISPINDEX = $06
YDISPINDEX = $07
FRAMEINDEX = $08
TEMP = $09

SINE	dcb $00,$01,$02,$03,$04,$03,$02,$01 
	dcb $00,$FF,$FE,$FD,$FC,$FD,$FE,$FF

Speed	dcb $04,$FC

;===

;Data to use for the sprite to be generated.  It takes a 16x16 sprite for it's dummy graphics.

;Currently set for a Goomba

SPRITE_NUMBER = $03	;Set this to the sprite you want it to hold
SPRITE_GFX = $E0	;Set this to the GFX of the sprite you want it to hold
SPRITE_PROP = $14 ;palette, GFX page etc.

;=====

;C2: YSpd
;1570: Drop / fly flag
;1602: Sine index

dcb "INIT"
	RTL

dcb "MAIN"
	PHB
	PHK
	PLB
	LDA #$FF
	STA $161A,x
	JSR Run
	PLB
	RTL	;also nothing


Run
	JSR SUB_OFF_SCREEN_X0
	JSL $20CA4F
	JSR GFX			;draw sprite
	JSR GFXItem		;draw optional item it's holding

	LDA $14C8,x
	CMP #$08          	 
	BNE Return           
	LDA $9D			;locked sprites?
	BNE Return
	LDA $15D0,x		;yoshi eating?
	BNE Return

	LDY $157C,x
	LDA Speed,y		;speed depending on direction
	STA $B6,x

	LDA $1570,x		;if already generated, fly away
	BEQ CheckProx

FlyAway
	LDA $14
	AND #$01
	BNE SkipFly		;slow ascent

	LDA $C2,x		;Yspd
	DEC A
	STA $C2,x
	STA $AA,x
	CMP #$F0
	BCS SkipFly

	INC $C2,x		;compensate
	STA $C2,x
	STA $AA,x

	BRA SkipFly

CheckProx
	JSR PROXIMITY		;my common proximity routine
	BEQ NoGen
	JSR Generate		;if in range, generate it

	LDA $1570,x		;this is not zero if generation was successful
	BEQ NoGen		;just continue until time comes

	LDA #$49		;play kicking shell sound
	STA $1DFC

	LDA $7FAB10,x		;extra bit
	AND #$04
	BNE NoGen		;if bit is clear, don't come back

	LDA #$FF		;erase sprite permanentley
	STA $161A,x

NoGen
	JSR SINEMOTION		;wavy motion, Xspd
	LDA $AA,x		;keep storing to storage
	STA $C2,x
	
	JSR SUB_HORZ_POS
	TYA
	STA $157C,x		;TEMP: Always face Mario

SkipFly
	JSL $01802A		;speed update

Return
	RTS     

Generate	
	JSL $02A9E4		;grab free sprite slot
	BMI ReturnG		;return if none left...

	PHX			;preserve sprite index

	LDA #$01
	STA $14C8,y		;normal status, run init routine?
	LDA #SPRITE_NUMBER	;load sprite to generate...
	STA $9E,y		;into sprite type table
	
	LDA $E4,x		;same Xpos
	STA $E4,y
	LDA $14E0,x		;share same screen
	STA $14E0,y

	LDA $D8,x
	CLC
	ADC #$19		;below it
	STA $D8,y		;Ypos
	LDA $14D4,x
	ADC #$00		;transfer carry
	STA $14D4,y		;same screen

	TYX			;new sprite slot into X
	JSL $07F7D2		;create

	PLX			;restore sprite index
	
	INC $1570,x		;only does this once
		
ReturnG
	RTS     
		
;=====

TILEMAP	dcb $0C,$17,$17		;balloon, chain, chain

XDISP	dcb $00,$04,$04

YDISP	dcb $00,$0E,$12

XBIAS	dcb $00,$08,$08
SIZE	dcb $02,$00,$00

EORF	dcb $40,$00

GFX
	LDA $15F6,x	;load properties
	STA PROPRAM	;into TEMP

	LDA $157C,x	;direction...
	STA DIR

	LDX #$00	;loop index

OAM_Loop
	TYA
	LSR A
	LSR A
	PHY
	TAY
	LDA SIZE,x
	STA $0460,y		;size table
	PLY			;restore

	LDA DIR
	BNE XLeft

	LDA $00
	SEC
	SBC XDISP,x
	CLC
	ADC XBIAS,x		;add bias since it throws it on the other side
	STA $0300,y
	BRA XNext
XLeft
	LDA $00
	CLC
	ADC XDISP,x
	STA $0300,y
XNext
	LDA $01
	CLC
	ADC YDISP,x
	STA $0301,y

	LDA TILEMAP,x
	STA $0302,y

	LDA $64
	ORA PROPRAM
	PHX
	LDX DIR
	EOR EORF,x
	PLX
	STA $0303,y

	INY
	INY
	INY
	INY
	INX
	CPX #$03	;3 tiles for balloon and chain
	BNE OAM_Loop

	LDX $15E9

	RTS	
	
GFXItem
	LDA $1570,x
	BNE GFXI4_Return	;return if GFX shouldn't be drawn

	PHY
	TYA
	LSR A
	LSR A
	TAY
	LDA #$02
	STA $0460,y	;it's a 16x16 sprite being held
	PLY

	LDA $00
	STA $0300,y	;same x pos

	LDA $01
	CLC
	ADC #$19	;below it
	STA $0301,y

	LDA #SPRITE_GFX
	STA $0302,y	;sprite to gen GFX

	LDA #SPRITE_PROP	;sprite properties to generate
	ORA $64
	PHX
	LDX DIR
	EOR EORF,x
	PLX
	STA $0303,y

GFXI3_Return
	LDY #$FF
	LDA #$03	;4 tiles
	JSL $01B7B3	;bookkeeping
	RTS

GFXI4_Return
	LDY #$FF
	LDA #$02	;only 3 tiles
	JSL $01B7B3	;bookkeeping
	RTS

;=====
;a routine to calculate whether or not Mario is within range of wiggler.  Based off fang.asm
;Z = 0 when in range, 1 when out of range

EORTBLI	dcb $FF,$00
EORTBL	dcb $00,$FF
		
PROXIMITY
	LDA $14E0,x		;sprite x high
	XBA
	LDA $E4,x		;sprite x low
	REP #$20		;16bitA
	SEC
	SBC $94			;sub mario x
	SEP #$20		;8bitA
	PHA			;preserve for routine jump
	JSR SUB_HORZ_POS	;horizontal distance
	PLA			;restore
	EOR EORTBLI,y		;invert if needed
	CMP $7FAB28,x		;range define by Extra Prop 1*
	BCS PRange_Out		;return not within range
	LDA #$01		;Z = 0
	RTS

PRange_Out
	LDA #$00		;Z = 1
	RTS


SINEMOTION
	LDA $1602,x		;dedicated sine index
	INC A			;advance
	STA $1602,x		;and store

	LSR A
	LSR A
	LSR A
	AND #$0F		;only 16 entries
	TAY
	LDA SINE,y		;grab entry
	STA $AA,x		;new Yspd

	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 $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_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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $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