;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

incsrc subroutinedefs_trasm.asm

;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
	JSL SubOffscreenX0
	JSL GetDrawInfo
	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
	
	JSL SubHorizPos
	TYA
	STA $157C,x		;TEMP: Always face Mario

SkipFly
	JSL $81802A		;speed update

Return
	RTS     

Generate	
	JSL $82A9E4		;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 $87F7D2		;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 $81B7B3	;bookkeeping
	RTS

GFXI4_Return
	LDY #$FF
	LDA #$02	;only 3 tiles
	JSL $81B7B3	;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
	JSL SubHorizPos	;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

