;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; INIT and MAIN JSL targets
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Because this is a boss, these don't have to be sprite tables. Don't put more than one of these on screen at a time, obviously.
!Rotation = $0DC3
!RotationAccBits = $5C
!RotSpeed = $58
!FrameNum = $18B4
!TilesDrawn = $18B7
!SprSprInteract = $018032   
!MarioSprInteract = $01A7DC
!DuckFrame = $1473

!SwitchFrame = $1475

!IRQScanline = $87
!BlockCounter = $140B

!SpawnSpriteNumber = $7C

!Health = $145E
!StartHP = #$08

!DuckXPos = $13E6 ;2 Bytes
!DuckYPos = $146C ;2 Bytes
!DuckYAccBits = $13D8
!DuckYSpeed = $13C8
!DuckDirection = $61

!InteractionCallback = $62 ;Needs two bytes

!State = $18BB
!StateTimer = $0AF5
;These are used for the hurt state
!OldState = $1415
!OldStateTimer = $1416
!SwitchDir = $147D
!AccelTo = $147B

!SpriteTableBackupRam = $18C5 ;Requires 5 bytes
!SINTable = $7FB100	;Requires 0x400 bytes
!COSTable = $7FB500	;Requires 0x400 bytes

!DisableCapeAndFire = $79

;8 Byte tables
!LastFrameBucketX = $0F5E
!ThisFrameBucketX = $0F9A

!BucketXDiffTmp = $14B0
!XTmp = $14BE

!SpriteSpawnXLo = $0A
!SpriteSpawnXHi = $0B
!SpriteSpawnYLo = $0C
!SpriteSpawnYHi = $0D
!SpriteSpawnXSpeed = $0E
!SpriteSpawnYSpeed = $0F
!SpriteSpawnDirection = $09

!FireworkSpriteNum = #$BF

print "INIT ",pc
	STZ !RotSpeed
	STZ !RotationAccBits
	STZ !State
	LDA !StartHP
	STA !Health
	stz !SwitchFrame
	LDA $14E0,x
	XBA
	LDA $E4,x
	REP #$20
	STZ !Rotation
	EOR #$FFFF
	INC
	CLC
	ADC #$0038
	CLC
	ADC $1A
	STA $3A
	SEP #$20
	LDA $14D4,x
	XBA
	LDA $D8,x
	REP #$20
	EOR #$FFFF
	INC
	CLC
	ADC #$0038
	CLC
	ADC $1C
	STA $3C
	STZ !BlockCounter
	SEP #$20
	
	JSR BackupSpriteTables
	JSR InitSINCOSTables
	
	LDA #$04
	STA $1908
	REP #$20
	LDA $1C
	SEC
	SBC #$0279
	SEP #$20
	STA !IRQScanline
	;Set mode 7 registers based on mirror values
	RTL
print "MAIN ",pc			
	PHB
	PHK				
	PLB
	JSR SPRITE_ROUTINE			;Jump to the routine to keep organized
	PLB
	RTL   

InitSINCOSTables:
	PHX
	LDA #$A0
	STA $00
	REP #$30
	LDX #$01FF
	.loopy
	STX $01
	JSR SIN
	JSR COS
	PHX
	TXA
	ASL
	TAX
	LDA $03
	STA !SINTable,x
	LDA $05
	STA !COSTable,x
	PLX
	DEX
	BPL .loopy
	SEP #$30
	PLX
	RTS


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SPRITE_ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!InitState = #$00
!LavaRisingState = #$01
!RisingState = #$02
!PosingState = #$03
!RunningState = #$04
!SwitchState = #$05
!CannonAttack = #$06
!AccelerationState = #$07
!HurtState = #$08
!PieAttack = #$09
!FireworkAttack = #$0A
!SwitchStateInit = #$0B

!IdleFrame1 = #$00
!IdleFrame2 = #$01
!PoseFrame1 = #$02
!PoseFrame2 = #$03
!SwitchFrame1 = #$04
!SwitchFrame2 = #$05
!CallFrame = #$06
!ThrowFrame = #$07
!HurtFrameUp = #$08
!HurtFrameHit = #$09
!HurtFrameDown = #$0A
!HurtFrameGround1 = #$0B
!HurtFrameGround2Left = #$0C
!HurtFrameGround2Right = #$0D
!HurtFrameGround3 = #$0E
!HurtFrameGround4 = #$0F

!SwitchFrameCenter = #$00
!SwitchFrameLeft = #$01
!SwitchFrameRight = #$02


!NumAttacks = #$04

StatePointers:
dw InitState
dw LavaRisingState
dw RisingState
dw PosingState
dw RunningState
dw SwitchState
dw CannonAttack
dw AccelerationState
dw HurtState
dw PieAttack
dw FireworkAttack
dw SwitchState

Attacks:
db !SwitchState
db !CannonAttack
db !PieAttack
db !FireworkAttack

InitState:
	REP #$20
	LDA $1C
	SEC
	SBC #$02FC
	EOR #$FFFF
	INC
	CLC
	ADC #$007A
	SEP #$20
	STA !IRQScanline
	JSL $01ACF9 ;Call the random number generator so we can have seemingly more random numbers, based on how long the player takes to get on the wheel.
	LDX $15E9
	LDA $14D4,x
	XBA
	LDA $D8,x
	REP #$20
	SEC
	SBC #$0118
	STA !DuckYPos
	SEP #$20
	LDA $14E0,x
	XBA
	LDA $E4,x
	REP #$20
	STA !DuckXPos
	SEP #$20
	STZ !RotSpeed
	PEA.w .InteractionCallback
	REP #$20
	PLA
	STA !InteractionCallback
	SEP #$20
	RTS
	.InteractionCallback
	SEP #$20
	lda !XTmp
	cmp #$00
	beq +
		pla
		pla
		ply
		rep #$20
		rts
	+
	LDA !LavaRisingState
	STA !State
	LDA #$01
	STA !StateTimer
	LDA #$04
	STA $1887
	LDA #$10
	STA !BlockCounter
	REP #$20
	RTS
	
LavaRisingState:
    REP #$20
	STZ !InteractionCallback

	LDA $1C
	SEC
	SBC #$02FC
	EOR #$FFFF
	CMP #$0060
	BCS .tooBig
	INC
	CLC
	ADC #$007A
	BRA +
	.tooBig
	LDA #$0000
	+
	SEP #$20
	STA !IRQScanline
	STZ $13E0
	LDA #$01
	STA $13FB
	LDA !StateTimer
	DEC
	STA !StateTimer
	BNE +
	LDA #$08
	STA !StateTimer
	LDA #$1A 
	STA $1DFC
	LDA #$04
	STA $1887
	LDA !BlockCounter
	DEC 
	STA !BlockCounter
	BPL +
	LDA !RisingState
	STA !State
	+
	RTS

RisingState:
	REP #$20
	LDA $1C
	SEC
	SBC #$02FC
	EOR #$FFFF
	CMP #$0060
	BCS .tooBig
	INC
	CLC
	ADC #$007A
	BRA +
	.tooBig
	LDA #$0000
	+
	SEP #$20
	STA !IRQScanline
	STZ $13E0
	LDA #$01
	STA $13FB
	LDA #$08
	STA !RotSpeed
	REP #$20
	STZ !InteractionCallback
	LDA !Rotation
	CMP #$0100
	BCC +
	SEP #$20
	LDA #$80
	STA !StateTimer
	LDA !PosingState
	STA !State
	+
	SEP #$20
	STZ $7D
	STZ $7B
	
	RTS
	
PosingState:
	LDA #$01
	STA $13FB
	STZ $13F1
	STZ $1412
	STZ !RotSpeed
	lda #$FF
	sta $154C,x
	LDA !StateTimer
	DEC
	STA !StateTimer
	cmp #$60
	bcs +
	lda !PoseFrame1
	sta !DuckFrame
	LDA !StateTimer
	cmp #$20
	bcs +
	lda !PoseFrame2
	sta !DuckFrame
	;Make him pose
	lda !StateTimer
	BNE +
	JSL $01ACF9
	AND #$01
	STA !SwitchDir	;Get random direction
	sta !DuckDirection
	LDA !SwitchStateInit
	STA !State
	LDA #$60
	STA !StateTimer
	STZ $13FB
	+
	RTS

RunningState:
	REP #$20
	STZ !InteractionCallback
	SEP #$20
	lda $14
	lsr #5
	and #$01
	phx
	tax
	lda .frames,x
	STA !DuckFrame
	plx
	LDA !StateTimer
	DEC
	STA !StateTimer
	BNE .return
	JSL $01ACF9
	LDA #$00
	STA $4205
	LDA $148D
	STA $4204
	LDA !NumAttacks
	STA $4206
	NOP #12
	PHX
	LDX $4216
	LDA Attacks,x
	PLX
	STA !State
	CMP !SwitchState
	BEQ .SwitchState
	CMP !CannonAttack
	BEQ .CannonAttack
	CMP !PieAttack
	BEQ .PieAttack
	CMP !FireworkAttack
	BEQ .FireworkAttack
	BRA .return
	.SwitchState
		LDA !SwitchDir
		EOR #$01
		STA !SwitchDir
		sta !DuckDirection
		LDA #$60
		STA !StateTimer
		BRA .return
	.CannonAttack
		LDA #$60
		STA !StateTimer
		BRA .return
	.PieAttack
		LDA #$80
		STA !StateTimer
		BRA .return
	.FireworkAttack
		LDA #$C0
		STA !StateTimer
	.return
	RTS
	.frames
	db !IdleFrame1, !IdleFrame2
	
SwitchState:
	REP #$20
	STZ !InteractionCallback
	SEP #$20
	lda !State
	cmp !SwitchStateInit
	bne +
	ldx $15E9
	lda #$01
	sta $154C,x
	+
	lda $14
	lsr #2
	and #$01
	tax
	lda .frames,x
	STA !DuckFrame
	ldx $15E9
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	ldy !SwitchDir
	bne .right
	.left
		clc
		adc #$0010
		sta $00
		sep #$20
		lda !SwitchFrame
		cmp !SwitchFrameCenter
		beq +
		rep #$20
		lda $00
		clc
		adc #$0008
		bra .rldone
		+
		rep #$20
		lda $00
		bra .rldone
	.right
		sec
		sbc #$0010
		sta $00
		sep #$20
		lda !SwitchFrame
		cmp !SwitchFrameCenter
		beq +
		rep #$20
		lda $00
		sec
		sbc #$0008
		bra .rldone
		+
		rep #$20
		lda $00
	.rldone
	sta !DuckXPos
	sep #$20
	LDA !StateTimer
	DEC
	STA !StateTimer
	;Switch animation
	CMP #$10
	BCS .return
	sta $00
	stz $01
	;If this is the first switch, we don't want him to look like he's pushing air
	lda !SwitchFrame
	cmp !SwitchFrameCenter
	bne +
		lda $00
		cmp #$08
		bcc +
		 lda #$08
		 sta $00
	+
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	ldy !SwitchDir
	bne .rightin
	.leftin
		clc
		adc $00
		adc #$0008
		bra .rlindone
	.rightin
		sec
		sbc $00
		sbc #$0008
	.rlindone
	sta !DuckXPos
	sep #$20
	LDA !StateTimer
	cmp #$08
	bcs .return
	lda !SwitchFrameCenter
	sta !SwitchFrame
	LDA !StateTimer
	BNE .return
	;LDX !SwitchDir
	;LDA .SwitchSpeeds,x
	ldx !SwitchDir
	lda .SwitchFrames,x
	sta !SwitchFrame
	lda #$10
	sec
	sbc !Health
	ldx !SwitchDir
	bne +
	eor #$FF
	inc
	+
	STA !AccelTo		;Add Acceleration state
	LDA !AccelerationState
	STA !State
	LDA #$80	;Get Random later
	STA !StateTimer
	.return
	RTS
	;This is temporary
	.SwitchSpeeds
	db $F8,$08
	.frames
	db !SwitchFrame1, !SwitchFrame2
	.SwitchFrames
	db !SwitchFrameLeft, !SwitchFrameRight
	
	
CannonAttack:
	LDX $15E9
	REP #$20
	STZ !InteractionCallback
	SEP #$20
	LDA !CallFrame
	STA !DuckFrame
	LDA !StateTimer
	DEC
	STA !StateTimer
	BEQ +
	JMP .return
	+
	JSL $01ACF9
	LDA #$00
	STA $4205
	LDA $148D
	STA $4204
	LDA #$05
	STA $4206
	;Using up time for division to take place
	LDA $D8,x
	SEC
	SBC #$10
	STA !SpriteSpawnYLo
	LDA $14D4,x
	SBC #$00
	STA !SpriteSpawnYHi
	LDA $14E0,x
	XBA
	LDA $E4,x
	REP #$20
	STA $00
	LDA $148D
	XBA ;Grabbing the high byte
	AND #$0001
	BNE .SpawnLeft
	.SpawnRight
		LDA $00
		CLC
		ADC #$00A0
		SEP #$20
		STA !SpriteSpawnXLo
		XBA
		STA !SpriteSpawnXHi
		LDA #$C0
		STA !SpriteSpawnXSpeed
		lda #$01
		sta !SpriteSpawnDirection
		BRA .EndSpawn
	.SpawnLeft
		LDA $00
		SEC
		SBC #$00A0
		SEP #$20
		STA !SpriteSpawnXLo
		XBA
		STA !SpriteSpawnXHi
		LDA #$40
		STA !SpriteSpawnXSpeed
		STZ !SpriteSpawnDirection
		;BRA .EndSpawn
	.EndSpawn
	LDA #$80
	STA !SpriteSpawnYSpeed
	PHX
	LDX $4216
	LDA .Sprites,x
	PLX
	STA !SpawnSpriteNumber
	JSR SpawnNormalSprite
	LDA #$09
	STA $1DFC
	LDA !RunningState
	STA.w !State
	LDA #$80	;Get Random later
	STA.w !StateTimer

	.return
	RTS
	;This is temporary
	.Sprites
	db $04,$05,$06,$07,$0F
	
PieAttack:
    LDX $15E9
	REP #$20
	STZ !InteractionCallback
	SEP #$20
	LDA !StateTimer
	DEC
	STA !StateTimer
	CMP #$60
	BEQ +
	CMP #$40
	BEQ +
	CMP #$20
	BEQ +
	CMP #$00
	BEQ +
	JMP .return
	+
	LDA !ThrowFrame
	STA !DuckFrame
	INC !DuckDirection
	JSL $01ACF9
	LDA #$00
	STA $4205
	LDA $148D
	STA $4204
	LDA #$18
	STA $4206
	;Using up time for division to take place
	REP #$20
	LDA !DuckYPos
	SEP #$20
	STA !SpriteSpawnYLo
	XBA
	STA !SpriteSpawnYHi
	REP #$20
	LDA !DuckXPos
	SEP #$20
	STA !SpriteSpawnXLo
	XBA
	STA !SpriteSpawnXHi
	LDA !DuckDirection
	AND #$01
	BNE .sub
	LDA $4216
	EOR #$FF
	INC
	BRA +
	.sub
	LDA $4216
	+
	STA !SpriteSpawnXSpeed
	LDA #$F0
	STA !SpriteSpawnYSpeed
	LDA #$04
	STA !SpawnSpriteNumber
	JSR SpawnExtendedSprite
	LDA #$2B
	STA $1DFC
	LDA !StateTimer
	BNE .return
	LDA !RunningState
	STA.w !State
	LDA #$80	;Get Random later
	STA.w !StateTimer

	.return
	RTS
	.PieXSpeed
	db $E8,$18
	
FireworkAttack:
    LDX $15E9
	REP #$20
	STZ !InteractionCallback
	SEP #$20
	LDA !CallFrame
	STA !DuckFrame
	LDA !StateTimer
	DEC
	STA !StateTimer
	CMP #$90
	BEQ +
	CMP #$60
	BEQ +
	CMP #$30
	BEQ +
	CMP #$00
	BEQ +
	JMP .return
	+
	JSL $01ACF9
	LDA #$00
	STA $4205
	LDA $148D
	STA $4204
	LDA #$20
	STA $4206
	;Using up time for division to take place
	LDA #$26
	STA $1DF9
	LDA !FireworkSpriteNum
	STA !SpawnSpriteNumber
	rep #$20
	lda $D1
	sep #$20
	sta !SpriteSpawnXLo
	xba
	sta !SpriteSpawnXHi
	lda $4216
	cmp #$10
	bcc .plusY
	.minusY
	    sec
		sbc #$10
		sta $00
		lda $D8,x
		sec
		sbc $00
		sta !SpriteSpawnYLo
		lda $14D4,x
		sbc #$00
		sta !SpriteSpawnYHi
		bra .FinishY
	.plusY
	    sta $00
	    lda $D8,x
		clc
		adc $00
		sta !SpriteSpawnYLo
		lda $14D4,x
		adc #$00
		sta !SpriteSpawnYHi
	.FinishY
	JSR SpawnCustomSprite
	LDA !StateTimer
	BNE .return
	LDA !RunningState
	STA.w !State
	LDA #$80	;Get Random later
	STA.w !StateTimer

	.return
	RTS
	
AccelerationState:
	LDA !RotSpeed
	BPL PositiveSpeed
	NegativeSpeed:
		LDA !AccelTo
		BPL .PositiveAccel
			CMP !RotSpeed
			BCC +
				LDA !RunningState
				STA !State
				INC !RotSpeed
				RTS
			+
			DEC !RotSpeed
			RTS
		.PositiveAccel
			INC !RotSpeed
			RTS
	PositiveSpeed:
		LDA !AccelTo
		BPL .PositiveAccel
			DEC !RotSpeed
			RTS
		.PositiveAccel
			CMP !RotSpeed
			BCS +
				LDA !RunningState
				STA !State
				RTS
			+
			INC !RotSpeed
			RTS

HurtState:
	LDX $15E9
	REP #$20
	STZ !InteractionCallback
	SEP #$20
	lda #$C0
	sta $154C,x
	LDA #$00
	XBA
	LDA !StateTimer
	BPL .afterhit
	JSR BackupSpriteTables
	lda !DuckYSpeed
	sta $AA,x
	lda !DuckYAccBits
	sta $14EC,x
	lda !DuckYPos
	sta $D8,x
	lda !DuckYPos+1
	sta $14D4,x
	stz $B6,x
	jsl $01802A
	lda $14EC,x
	sta !DuckYAccBits
	lda $D8,x
	sta !DuckYPos
	lda $14D4,x
	sta !DuckYPos+1
	lda $AA,x
	sta !DuckYSpeed	
	jsr RestoreSpriteTables
	lda !DuckYSpeed
	bmi .going_up
	.going_down
		
		lda !HurtFrameDown
		sta !DuckFrame
		bra +
	.going_up
		lda !HurtFrameUp
		sta !DuckFrame
		;!HurtFrameHit
	+
	lda !Health
	beq +
	LDA $14D4,x
	XBA
	LDA $D8,x
	REP #$20
	SEC
	SBC #$0118
	SEC
	rep #$20
	cmp !DuckYPos
	bcs +
	sta !DuckYPos
	sep #$20
	lda #$7F
	sta !StateTimer
	+
	sep #$20
	rts
	.afterhit
	lda !HurtFrameGround1
	sta !DuckFrame
	lda !StateTimer
	cmp #$60
	bcs .done_with_frame
		phx
		ldx !DuckDirection
		lda .HurtFrames2,x
		plx
		sta !DuckFrame
		lda !StateTimer
		cmp #$40
		bcs .done_with_frame
			lda !HurtFrameGround3
			sta !DuckFrame
			lda !StateTimer
			cmp #$20
			bcs .done_with_frame
				lda !HurtFrameGround4
				sta !DuckFrame
	.done_with_frame
	
	;REP #$20
	;STA $00
	;SEP #$20
	;LDA $14D4,x
	;XBA
	;LDA $D8,x
	;REP #$20
	;SEC
	;SBC #$0108
	;SEC
	;SBC $00
	;STA !DuckYPos
	SEP #$20
	LDA !OldState
	CMP !AccelerationState
	BNE .NotAccelerating
	LDA !State
	PHA
	LDA !OldState
	STA !State
	JSR AccelerationState
	LDA !State
	STA !OldState
	PLA
	STA !State
	.NotAccelerating
	LDA !OldState
	CMP !SwitchState
	BNE .NotSwitch
	LDA #$80
	STA !OldStateTimer
	LDA !RunningState
	STA !OldState
	LDA !SwitchDir
	EOR #$01
	STA !SwitchDir
	.NotSwitch
	LDA !StateTimer
	DEC
	STA !StateTimer
	BNE +
	LDA !OldState
	STA !State
	LDA !OldStateTimer
	STA !StateTimer
	+
	RTS
	
	.HurtFrames2
	db !HurtFrameGround2Left, !HurtFrameGround2Right
	

CartRots:
dw $0000,$0040,$0080,$00C0,$0100,$0140,$0180,$01C0

SPRITE_ROUTINE:
	;state stuff
	lda $9D
	bne .dontmove
	PHX
	LDA !State
	ASL
	TAX
	REP #$20
	LDA StatePointers,x
	LDX #$00
	STA $0000
	SEP #$20
	JSR ($0000,x)
	PLX
	
	LDA !RotationAccBits
	CLC
	ADC !RotSpeed
	STA !RotationAccBits
	.RotateLoop
	CMP #$10
	BCC .BreakRotateLoop
	CMP #$F0
	BCS .BreakRotateLoop
	BPL .RotatePositive
	REP #$20
	DEC !Rotation
	SEP #$20
	CLC
	ADC #$10
	BRA .RotateLoop
	.RotatePositive
	REP #$20
	INC !Rotation
	SEP #$20
	SEC
	SBC #$10
	BRA .RotateLoop
	.BreakRotateLoop
	STA !RotationAccBits
	.dontmove
	
	LDA $14E0,x
	XBA
	LDA $E4,x
	REP #$20
	EOR #$FFFF
	INC
	CLC
	ADC #$0038
	CLC
	ADC $1A
	STA $3A
	SEP #$20
	LDA $14D4,x
	XBA
	LDA $D8,x
	REP #$20
	EOR #$FFFF
	INC
	CLC
	ADC #$0038
	CLC
	ADC $1C
	STA $3C
	SEP #$20
	LDA #$FF
	STA !TilesDrawn
	JSR GET_DRAW_INFO
	PHX
	LDX #$07
	.offsetloop
	STX !XTmp
	TXA
	ASL
	TAX
	REP #$20
	LDA !ThisFrameBucketX,x
	STA !LastFrameBucketX,x
	LDA CartRots,x
	REP #$10
	SEC
	SBC !Rotation
	AND #$01FF
	ASL
	
	TAX
	LDA !SINTable,x
	STA $03
	LDA !COSTable,x
	STA $05
	SEP #$30
	LDX $15E9
	LDA $14D4,x
	STA $0B
	LDA $D8,x
	STA $0A
	LDA $14E0,x
	STA $0D
	LDA $E4,x
	STA $0C
	LDX !XTmp
	TXA
	ASL
	TAX
	REP #$20
	LDA $0A
	CLC
	ADC $05
	STA $0A
	LDA $0C
	CLC
	ADC $03
	STA $0C
	STA !ThisFrameBucketX,x
	SEC
	SBC !LastFrameBucketX,x
	STA !BucketXDiffTmp
	SEP #$20
	LDX $15E9
	LDA $0B
	STA $14D4,x
	LDA $0A
	STA $D8,x
	LDA $0D
	STA $14E0,x
	LDA $0C
	STA $E4,x
	JSR DrawBucket
	;interaction stuff
	JSR InteractWithMario
	
	JSR RestoreSpriteTables
	LDX !XTmp
	DEX
	BMI +
	JMP .offsetloop
	+
	PLX
	;Ducky, Ducky, Ducky...
	;Clipping
	
	REP #$20
	LDA !DuckYPos
	SEP #$20
	STA $D8,x
	XBA
	STA $14D4,x
	REP #$20
	LDA !DuckXPos
	SEP #$20
	STA $E4,x
	XBA
	STA $14E0,x
	JSR DrawDuck
	JSR RestoreSpriteTables
	;Platform
	LDA $14D4,x
	XBA
	LDA $D8,x
	REP #$20
	SEC
	SBC #$00F8
	SEP #$20
	sta $D8,x
	XBA
	sta $14D4,x
	LDA $1662,x
	PHA
	LDA #$33
	STA $1662,x
	JSR DrawPlatform
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0020
	sep #$20
	sta $E4,x
	xba
	sta $14E0,x
	JSR InteractDuck
	PLA
	STA $1662,x
	;Switch
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	clc
	adc #$0020
	sep #$20
	sta $E4,x
	xba
	sta $14E0,x
	LDA $14D4,x
	XBA
	LDA $D8,x
	REP #$20
	SEC
	SBC #$0020
	SEP #$20
	sta $D8,x
	XBA
	sta $14D4,x
	JSR DrawSwitch
	JSR RestoreSpriteTables
	.return
	lda $14D4,x
	xba
	lda $D8,x
	rep #$20
	cmp !DuckYPos
	bcs +
		inc
		sta !DuckYPos
		sep #$20
		jmp EndLevel
	+
	sep #$20
	RTS

SubVertPos:
	LDY #$00
	LDA $96
	SEC
	SBC $D8,x
	STA $0F
	LDA $97
	SBC $14D4,x
	BPL +
	INY
	+
    RTS   
	
EndLevel:
	;If this is the running state, then we are done, end the level
	
	lda !State
	cmp !RunningState
	bne ++
		lda $1493
		bne +
			lda #$03
			sta $1DFB
			lda #$FF
			sta $1493
		+
		rts
	++
	lda !AccelerationState
	sta !State
	lda #$00
	sta !AccelTo
	rts
	
BackupSpriteTables:
LDA $D8,x
STA !SpriteTableBackupRam
LDA $E4,x
STA !SpriteTableBackupRam+1
LDA $14C8,x
STA !SpriteTableBackupRam+2
LDA $14D4,x
STA !SpriteTableBackupRam+3
LDA $14E0,x
STA !SpriteTableBackupRam+4
RTS

RestoreSpriteTables:
LDA !SpriteTableBackupRam
STA $D8,x
LDA !SpriteTableBackupRam+1
STA $E4,x
LDA !SpriteTableBackupRam+2
STA $14C8,x
LDA !SpriteTableBackupRam+3
STA $14D4,x
LDA !SpriteTableBackupRam+4
STA $14E0,x
RTS
	
SIN:		
		PHX
		PHP
		REP #$30		;16bitモード
		LDA $01
		AND #$00FF
		ASL A
		TAX				
		LDA $07F7DB,x
		STA $03

		SEP #$30		;8bitモード
		LDA $02			;$02を保存
		PHA
		LDA $03			;|sin|を
		STA $4202		;「かけられる数」とする。
		LDA $00			;半径を呼ぶ
		LDX $04			;|sin| = 1.00 だったら計算不要（Rsin = 半径）
		BNE IF1_SIN
		STA $4203		;半径を「かける数」とする。
		ASL $4216		;出た答えの小数点以下を四捨五入
		LDA $4217		
		ADC #$00
IF1_SIN:
		LSR $02			;絶対値を外す
		BCC IF_SIN_PLUS

		EOR #$FF
		INC A
		STA $03
		BEQ IF0_SIN
		LDA #$FF
		STA $04
		BRA END_SIN

IF_SIN_PLUS:
		STA $03
IF0_SIN:
		STZ $04

END_SIN:
		PLA
		STA $02			;$02を復元
		PLP
		PLX
		RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;コサインJSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

COS:		
		PHX
		PHP
		REP #$31		;16bitモード
		LDA $01			;$01 = θ
		;CLC
		ADC #$0080
		AND #$01FF		
		STA $07			;$07 = θ + 90°
		;LDA $07
		AND #$00FF
		ASL A
		TAX
		LDA $07F7DB,x
		STA $05

		SEP #$30
		LDA $05			;|cos|を
		STA $4202		;「かけられる数」とする。
		LDA $00			;半径を呼ぶ
		LDX $06			;|cos| = 1.00 だったら計算不要（Rsin = 半径）
		BNE IF1_COS
		STA $4203		;半径を「かける数」とする。
		ASL $4216		;出た答えの小数点以下を四捨五入
		LDA $4217		
		ADC #$00
IF1_COS:	
		LSR $08			;絶対値を外す
		BCC IF_COS_PLUS
		EOR #$FF
		INC A
		STA $05
		BEQ IF0_COS
		LDA #$FF
		STA $06
		BRA END_COS

IF_COS_PLUS:
		STA $05
IF0_COS:
		STZ $06

END_COS:
		PLP
		PLX
		RTS
		
InteractWithMario:
	PHY
	lda !State
	cmp !RisingState
	bne +
	lda !XTmp
	beq .carry
	+
	JSL !MarioSprInteract	; Check for mario/sprite contact (carry set = contact)
    BCC .NotInteract        ; return if no contact
	JSR SubVertPos          ; \
    LDA $0E                 ;  | if mario isn't above sprite, and there's vertical contact...
    CMP #$E6                ;  |     ... sprite wins
    BPL .NotInteract          ; /
    LDA $7D                 ; \ if mario speed is upward, return
    BMI .NotInteract             ; /
	rep #$20
	LDA !InteractionCallback
	BEQ +
	PEA.w +
	PLA
	DEC
	PHA
	LDA !InteractionCallback
	DEC
	PHA
	rts
	+
	sep #$20
	.carry
	LDA #$01                ; \ set "on sprite" flag
	STA $1471               ; /
	;LDA #$06                ; Disable interactions for a few frames
	;STA $154C,x             
	STZ $7D                 ; Y speed = 0
	LDA #$E1                ; \
	LDY $187A               ;  | mario's y position += E1 or D1 depending if on yoshi
	BEQ +      		 		;  |
	LDA #$D1                ;  |
	+
	CLC                     ;  |
	ADC $D8,x               ;  |
	STA $96                 ;  |
	LDA $14D4,x             ;  |
	ADC #$FF                ;  |
	STA $97                 ; /
	REP #$20
	LDA $94
	CLC
	ADC !BucketXDiffTmp
	STA $94
	sep #$20
	.NotInteract
	PLY
	RTS
	
InteractDuck:
	PHY
	JSL !MarioSprInteract	; Check for mario/sprite contact (carry set = contact)
    BCC .NotInteract        ; return if no contact
	JSR SubVertPos          ; \
    LDA $0E                 ;  | if mario isn't above sprite, and there's vertical contact...
    CMP #$E6                ;  |     ... sprite wins
    BMI .NotInteract          ; /
	LDA #$10
	STA $7D                 ; Y speed = 0
	LDA $154C,x
	bne +
		rep #$20
		lda !DuckXPos
		sec
		sbc #$0008
		cmp $D1
		bcs +
			clc
			adc #$0020
			cmp $D1
			bcc +
				sep #$20
				JSL $01AB99	
				LDA #$20
				STA $1DF9
				;Back these values up, so the hurt routine can put them back when it's done
				LDA !State
				STA !OldState
				LDA !StateTimer
				STA !OldStateTimer
				LDA !HurtState
				STA !State
				LDA #$80
				STA !StateTimer
				lda #$C0
				sta !DuckYSpeed
				dec !Health
				ply
				rts
	+
	sep #$20
	lda $1DF9
	bne +
		lda #$01
		sta $1DF9
	+
	.NotInteract
	ply
	rts
	
	RTS
		

BucketTiles:
db $EC,$EE

BucketTileProps:
db $0F,$0F

XOff:
db $F8,$08

YOff:
db $00,$00

BucketTileSizes:
db $02,$02

DrawBucket:
	PHY
	JSR GET_DRAW_INFO
	PLY
	LDA $15C4,x
	ora $186C,x
	BEQ +
	RTS
	+
	;Get whether the sprite is on the bottom of the screen or not
	lda $14D4,x
	xba
	lda $D8,x
	rep #$20
	sec
	sbc #$00B0
	cmp $1C
	sep #$20
	rol $0E
	;Get whether the sprite is on the left side of the screen or not, if it is, we don't skip drawing on carry
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0080
	bcc + ;If we overflow back, then we are definitely on the left side
	cmp $1A
	+
	sep #$20
	rol $0F
	REP #$20
	LDA #BucketTiles
	STA $05
	LDA #BucketTileProps
	STA $07
	LDA #XOff
	STA $09
	LDA #YOff
	STA $0B
	lda #BucketTileSizes
	sta $03
	SEP #$20
	;PHX
	LDA #$01
	sta $0D
	.sharedgfx
	phx
	ldx $0D
	.GFXLoop
	stz $02
	lda $0F
	ror
	bcc .left
	.right
		lda !DuckDirection
		cmp #$03
		beq .right_facing_right
		.right_facing_left
			PHY
			TXY
			LDA ($09),y
			bpl .right_facing_left_positive
			.right_facing_left_negative
				PLY
				eor #$FF
				inc
				sta $0D
				lda $00
				sec
				sbc $0D
				rol
				eor #$01
				ror
				bra .right_finish_x
			.right_facing_left_positive
				PLY
				CLC
				ADC $00
				bra .right_finish_x
		.right_facing_right
			PHY
			TXY
			LDA ($09),y
			bpl .right_facing_right_positive
			.right_facing_right_negative
				PLY
				eor #$FF
				inc
				clc
				adc $00
				bra .right_finish_x
			.right_facing_right_positive
				PLY
				sta $0D
				lda $00
				sec
				sbc $0D
				rol
				eor #$01
				ror
				bra .right_finish_x
		.right_finish_x
		bcc +
		jmp .endofloop
		+
		bra .xdone
	.left
		lda !DuckDirection
		cmp #$03
		beq .left_facing_right
		.left_facing_left
			PHY
			TXY
			LDA ($09),y
			PLY
			CLC
			ADC $00
			bra .left_finish_x
		.left_facing_right
			lda $00
			sec
			PHY
			TXY
			sbc ($09),y
			PLY
		.left_finish_x
		cmp #$D0
		bcc .xdone
		;$02 = #$01, but preserve A, X, and Y
		sec
		rol $02
	.xdone
	STA $0300,y
	
	lda $0E
	ror
	bcc .top
	.bottomW
		PHY
		TXY
		LDA ($0B),y
		PLY
		CLC
		ADC $01
		cmp #$F0
		bcs +
		bmi ++
		+
		jmp .endofloop
		++
		bra .ydone
	.top
		PHY
		TXY
		LDA ($0B),y
		PLY
		CLC
		ADC $01
		cmp #$F0
		bcs .ydone
		cmp #$B0
		bcc .ydone
		jmp .endofloop
	.ydone
	STA $0301,y
	
	PHY
	TXY
	LDA ($05),y
	PLY
	STA $0302,y
	
	INC !TilesDrawn
	PHX
	LDX $15E9
	LDA $15F6,x
	PLX
	ORA $64
	PHY
	TXY
	ora ($07),y
	PLY
	sta $0D
	lda !DuckDirection
	cmp #$03
	bne .prop_facing_left
	.prop_facing_right
		lda $0D
		ora #$40
		bra .prop_finish
	.prop_facing_left
		lda $0D
	.prop_finish
	STA $0303,y
	lda $0F
	ror
	bcs .overflow
	lda $0300,y
	bpl .notoverflow
	.overflow
		PHY
		TYA
		LSR #2
		TAY
		phy
		txy
		lda ($03),y
		ply
		PHX
		LDX $15E9
		ORA $15A0,x
		ORA $02
		PLX
		STA $0460,y	;
		PLY
		bra .overflowdone
	.notoverflow
		PHY
		TYA
		LSR #2
		TAY
		phy
		txy
		lda ($03),y
		ply
		STA $0460,y
		PLY
	.overflowdone
	
	INY
	INY
	INY
	INY
	.endofloop ;When we jump to the end, we don't want to take up this sprite slot.
	DEX
	bmi +
	jmp .GFXLoop
	+
	PLX	
	
	RTS

;Gonna be more of these. Many, many more.
DuckTilePointers:
dw DuckIdleTiles1
dw DuckIdleTiles2
dw DuckPoseTiles1
dw DuckPoseTiles2
dw DuckSwitchTiles1
dw DuckSwitchTiles2
dw DuckCallTiles
dw DuckThrowTiles
dw DuckHurtFrameUpTiles
dw DuckHurtFrameHitTiles
dw DuckHurtFrameDownTiles
dw DuckHurtFrameGroundTiles1
;Double because the second frame needs a left and a right
dw DuckHurtFrameGroundTiles2
dw DuckHurtFrameGroundTiles2
dw DuckHurtFrameGroundTiles3
dw DuckHurtFrameGroundTiles4

DuckIdleTiles1:
db $C0,$A6,$88,$C6
DuckIdleTiles2:
db $C0,$A6,$EC,$C6

DuckPoseTiles1:
db $AC,$AE,$CC,$C6
DuckPoseTiles2:
db $C8,$CA,$CE,$C6

DuckSwitchTiles1:
db $00,$02,$20,$22
DuckSwitchTiles2:
db $04,$06,$24,$26

DuckCallTiles:
db $08,$0A,$28,$2A

DuckThrowTiles:
db $48,$4A,$68,$6A

DuckHurtFrameUpTiles:
db $0C,$0E,$2C,$2E
DuckHurtFrameHitTiles:
db $40,$42,$60,$62
DuckHurtFrameDownTiles:
db $44,$46,$64,$66
DuckHurtFrameGroundTiles1:
db $A0,$A2
DuckHurtFrameGroundTiles2:
db $94,$80,$82
DuckHurtFrameGroundTiles3:
db $4C,$4E,$6C,$6E
DuckHurtFrameGroundTiles4:
db $C8,$CA,$E8,$EA

DuckTilesPropPointers:
dw DuckIdleProps1
dw DuckIdleProps2
dw DuckPoseProps1
dw DuckPoseProps2
dw DuckSwitchProps1
dw DuckSwitchProps2
dw DuckCallProps
dw DuckThrowProps
dw DuckHurtFrameUpProps
dw DuckHurtFrameHitProps
dw DuckHurtFrameDownProps
dw DuckHurtFrameGroundProps1
dw DuckHurtFrameGroundProps2
dw DuckHurtFrameGroundProps2
dw DuckHurtFrameGroundProps3
dw DuckHurtFrameGroundProps4

DuckIdleProps1:
db $3E,$3E,$3E,$3E
DuckIdleProps2:
db $3E,$3E,$3E,$3E

DuckPoseProps1:
db $3E,$3E,$3E,$3E
DuckPoseProps2:
db $3E,$3E,$3E,$3E

DuckSwitchProps1:
db $3F,$3F,$3F,$3F
DuckSwitchProps2:
db $3F,$3F,$3F,$3F

DuckCallProps:
db $3F,$3F,$3F,$3F

DuckThrowProps:
db $3F,$3F,$3F,$3F

DuckHurtFrameUpProps:
db $3F,$3F,$3F,$3F
DuckHurtFrameHitProps:
db $3F,$3F,$3F,$3F
DuckHurtFrameDownProps:
db $3F,$3F,$3F,$3F
DuckHurtFrameGroundProps1:
db $3F,$3F
DuckHurtFrameGroundProps2:
db $3F,$3F,$3F
DuckHurtFrameGroundProps3:
db $3F,$3F,$3F,$3F
DuckHurtFrameGroundProps4:
db $3F,$3F,$3F,$3F

DuckTilesXOffPointers:
dw DuckIdleXOff1
dw DuckIdleXOff2
dw DuckPoseXOff1
dw DuckPoseXOff2
dw DuckSwitchXOff1
dw DuckSwitchXOff2
dw DuckCallXOff
dw DuckThrowXOff
dw DuckHurtFrameUpXOff
dw DuckHurtFrameHitXOff
dw DuckHurtFrameDownXOff
dw DuckHurtFrameGroundXOff1
dw DuckHurtFrameGroundXOff2Left
dw DuckHurtFrameGroundXOff2Right
dw DuckHurtFrameGroundXOff3
dw DuckHurtFrameGroundXOff4

DuckIdleXOff1:
db $F8,$08,$F8,$08
DuckIdleXOff2:
db $F8,$08,$F8,$08

DuckPoseXOff1:
db $F8,$08,$F8,$08
DuckPoseXOff2:
db $F8,$08,$F8,$08

DuckSwitchXOff1:
db $F8,$08,$F8,$08
DuckSwitchXOff2:
db $F8,$08,$F8,$08

DuckCallXOff:
db $F8,$08,$F8,$08

DuckThrowXOff:
db $F8,$08,$F8,$08

DuckHurtFrameUpXOff:
db $F8,$08,$F8,$08
DuckHurtFrameHitXOff:
db $F8,$08,$F8,$08
DuckHurtFrameDownXOff:
db $F8,$08,$F8,$08
DuckHurtFrameGroundXOff1:
db $F8,$08
DuckHurtFrameGroundXOff2Left:
db $F8,$F8,$08
DuckHurtFrameGroundXOff2Right:
db $F8,$00,$08
DuckHurtFrameGroundXOff3:
db $F8,$08,$F8,$08
DuckHurtFrameGroundXOff4:
db $F8,$08,$F8,$08

DuckTilesYOffPointers:
dw DuckIdleYOff1
dw DuckIdleYOff2
dw DuckPoseYOff1
dw DuckPoseYOff2
dw DuckSwitchYOff1
dw DuckSwitchYOff2
dw DuckCallYOff
dw DuckThrowYOff
dw DuckHurtFrameUpYOff
dw DuckHurtFrameHitYOff
dw DuckHurtFrameDownYOff
dw DuckHurtFrameGroundYOff1
dw DuckHurtFrameGroundYOff2
dw DuckHurtFrameGroundYOff2
dw DuckHurtFrameGroundYOff3
dw DuckHurtFrameGroundYOff4

DuckIdleYOff1:
db $00,$00,$10,$10
DuckIdleYOff2:
db $00,$00,$10,$10

DuckPoseYOff1:
db $00,$00,$10,$10
DuckPoseYOff2:
db $00,$00,$10,$10

DuckSwitchYOff1:
db $00,$00,$10,$10
DuckSwitchYOff2:
db $00,$00,$10,$10

DuckCallYOff:
db $00,$00,$10,$10

DuckThrowYOff:
db $00,$00,$10,$10

DuckHurtFrameUpYOff:
db $00,$00,$10,$10
DuckHurtFrameHitYOff:
db $00,$00,$10,$10
DuckHurtFrameDownYOff:
db $00,$00,$10,$10
DuckHurtFrameGroundYOff1:
db $10,$10
DuckHurtFrameGroundYOff2:
db $08,$10,$10
DuckHurtFrameGroundYOff3:
db $00,$00,$10,$10
DuckHurtFrameGroundYOff4:
db $00,$00,$10,$10

DuckTileNums:
db $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$01,$02,$02,$03,$03

DuckTileSizePointers:
dw DuckIdleSizes1
dw DuckIdleSizes2
dw DuckPoseSizes1
dw DuckPoseSizes2
dw DuckSwitchSizes1
dw DuckSwitchSizes2
dw DuckCallSizes
dw DuckThrowSizes
dw DuckHurtFrameUpSizes
dw DuckHurtFrameHitSizes
dw DuckHurtFrameDownSizes
dw DuckHurtFrameGroundSizes1
dw DuckHurtFrameGroundSizes2
dw DuckHurtFrameGroundSizes2
dw DuckHurtFrameGroundSizes3
dw DuckHurtFrameGroundSizes4

DuckIdleSizes1:
db $02,$02,$02,$02
DuckIdleSizes2:
db $02,$02,$02,$02
DuckPoseSizes1:
db $02,$02,$02,$02
DuckPoseSizes2:
db $02,$02,$02,$02
DuckSwitchSizes1:
db $02,$02,$02,$02
DuckSwitchSizes2:
db $02,$02,$02,$02
DuckCallSizes:
db $02,$02,$02,$02
DuckThrowSizes:
db $02,$02,$02,$02
DuckHurtFrameUpSizes:
db $02,$02,$02,$02
DuckHurtFrameHitSizes:
db $02,$02,$02,$02
DuckHurtFrameDownSizes:
db $02,$02,$02,$02
DuckHurtFrameGroundSizes1:
db $02,$02
DuckHurtFrameGroundSizes2:
db $00,$02,$02
DuckHurtFrameGroundSizes3:
db $02,$02,$02,$02
DuckHurtFrameGroundSizes4:
db $02,$02,$02,$02
	
DrawDuck:
	PHY
	JSR GET_DRAW_INFO
	PLY
	;Get whether the sprite is on the left side of the screen or not, if it is, we don't skip drawing on carry
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0080
	bcc + ;If we overflow back, then we are definitely on the left side
	cmp $1A
	+
	sep #$20
	rol $0F
	;Get whether the sprite is on the bottom of the screen or not
	lda $14D4,x
	xba
	lda $D8,x
	rep #$20
	sec
	sbc #$00B0
	cmp $1C
	sep #$20
	rol $0E
	lda $14D4,x
	xba
	lda $d8,x
	rep #$20
	clc
	adc #$0020
	cmp $1C
	sep #$20
	lda #$00
	rol
	eor #$01
	ora $15C4,x
	;ora $186C,x
	BEQ +
	RTS
	+
	lda $154C,x
	;lsr #3
	and #$04
	beq +
	rts
	+
	PHX
	LDX !DuckFrame
	lda DuckTileNums,x
	sta $0D
	txa
	ASL
	TAX
	REP #$20
	LDA DuckTilePointers,x
	STA $05
	LDA DuckTilesPropPointers,x
	STA $07
	LDA DuckTilesXOffPointers,x
	sta $09
	lda DuckTilesYOffPointers,x
	sta $0B
	lda DuckTileSizePointers,x
	sta $03
	SEP #$20
	plx
	;Using bit 1 of the direction to say that this is the duck, since nothing else needs to be flipped
	lda !DuckDirection
	ora #$02
	sta !DuckDirection
	JSR DrawBucket_sharedgfx
	lda !DuckDirection
	and #$01
	sta !DuckDirection
	rts
	
	
PlatformXOff:
db $E8,$F8,$08,$18,$E8,$E8,$E8,$E8,$E8,$E8,$20,$20,$20,$20,$20,$20

PlatformYOff:
db $00,$00,$00,$00,$D0,$D8,$E0,$E8,$F0,$F8,$D0,$D8,$E0,$E8,$F0,$F8

PlatformTiles:
db $E0,$E2,$E2,$E4,$A4,$B4,$A5,$A4,$B4,$A5,$A4,$B4,$A5,$A4,$B4,$A5
	
PlatformProps:
db $0F,$0F,$0F,$0F,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D

PlatformSizes:
db $02,$02,$02,$02,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
	
DrawPlatform:
	PHY
	JSR GET_DRAW_INFO
	PLY
	;Get whether the sprite is on the left side of the screen or not, if it is, we don't skip drawing on carry
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0080
	bcc + ;If we overflow back, then we are definitely on the left side
	cmp $1A
	+
	sep #$20
	rol $0F
	;Get whether the sprite is on the bottom of the screen or not
	lda $14D4,x
	xba
	lda $D8,x
	rep #$20
	sec
	sbc #$00B0
	cmp $1C
	sep #$20
	rol $0E
	lda $14D4,x
	xba
	lda $d8,x
	rep #$20
	clc
	adc #$0020
	cmp $1C
	sep #$20
	lda #$00
	rol
	eor #$01
	ora $15C4,x
	BEQ +
	RTS
	+
	rep #$20
	LDA #PlatformTiles
	STA $05
	LDA #PlatformProps
	STA $07
	LDA #PlatformXOff
	sta $09
	lda #PlatformYOff
	sta $0B
	lda #PlatformSizes
	sta $03
	sep #$20
	lda #$0F
	sta $0D
	jmp DrawBucket_sharedgfx
	
SwitchTilePointers:
dw SwitchCenterTiles
dw SwitchLeftTiles
dw SwitchRightTiles

SwitchCenterTiles:
db $88,$8A,$A8,$AA
SwitchLeftTiles:
db $8E,$AC,$AE
SwitchRightTiles:
db $8E,$AC,$AE

SwitchTilesPropPointers:
dw SwitchCenterProps
dw SwitchLeftProps
dw SwitchRightProps

SwitchCenterProps:
db $0F,$0F,$0F,$0F
SwitchLeftProps:
db $4F,$4F,$4F
SwitchRightProps:
db $0F,$0F,$0F

SwitchTilesXPointers:
dw SwitchCenterX
dw SwitchLeftX
dw SwitchRightX

SwitchCenterX:
db $F8,$08,$F8,$08
SwitchLeftX:
db $F8,$08,$F8
SwitchRightX:
db $08,$F8,$08

SwitchTilesYPointers:
dw SwitchCenterY
dw SwitchLeftY
dw SwitchRightY

SwitchCenterY:
db $00,$00,$10,$10
SwitchLeftY:
db $00,$10,$10
SwitchRightY:
db $00,$10,$10

SwitchNumTiles:
db $03,$02,$02

SwitchSizes:
db $02,$02,$02,$02
	
DrawSwitch:
	PHY
	JSR GET_DRAW_INFO
	PLY
	;Get whether the sprite is on the left side of the screen or not, if it is, we don't skip drawing on carry
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0080
	bcc + ;If we overflow back, then we are definitely on the left side
	cmp $1A
	+
	sep #$20
	rol $0F
	stz $0E
	lda $14D4,x
	xba
	lda $d8,x
	rep #$20
	clc
	adc #$0020
	cmp $1C
	sep #$20
	lda #$00
	rol
	eor #$01
	ora $15C4,x
	;ora $186C,x
	BEQ +
	RTS
	+
	PHX
	LDX !SwitchFrame
	lda SwitchNumTiles,x
	sta $0D
	txa
	ASL
	TAX
	REP #$20
	LDA SwitchTilePointers,x
	STA $05
	LDA SwitchTilesPropPointers,x
	STA $07
	LDA SwitchTilesXPointers,x
	sta $09
	lda SwitchTilesYPointers,x
	sta $0B
	lda #SwitchSizes
	sta $03
	SEP #$20
	plx
	jmp DrawBucket_sharedgfx
	
;Spawn a normal sprite.
SpawnNormalSprite:
	LDA !SpriteSpawnXSpeed
	PHA
	LDA !SpriteSpawnYSpeed
	PHA
	LDA $186C,x
	BNE .return
	JSL $02A9DE
	BMI .return	
	LDA #$01
	STA $14C8,y
	LDA !SpawnSpriteNumber
	STA $009E,y
	LDA !SpriteSpawnXLo
	STA $00E4,y
	LDA !SpriteSpawnXHi
	STA $14E0,y
	LDA !SpriteSpawnYLo
	STA $00D8,y
	LDA !SpriteSpawnYHi
	STA $14D4,y
	PHX
	TYX
	JSL $07F7D2
	PLX
	lda #$01
	sta $151C,y
	PLA
	STA $00AA,y
	PLA
	STA $00B6,y
	.return
	RTS

SpawnCustomSprite:
	LDA $186C,x
	BNE .return
	JSL $02A9DE
	BMI .return
	LDA #$01				; Sprite state ($14C8,x).
	STA $14C8,y
	PHX
	TYX
	LDA !SpawnSpriteNumber
	STA $7FAB9E,x
	PLX
	LDA !SpriteSpawnXLo
	STA $00E4,y
	LDA !SpriteSpawnXHi
	STA $14E0,y
	LDA !SpriteSpawnYLo
	STA $00D8,y
	LDA !SpriteSpawnYHi
	STA $14D4,y
	PHX
	TYX
	JSL $07F7D2
	JSL $0187A7
	LDA #$08
	STA $7FAB10,x
	PLX
.return
	RTS

;Spawn extended sprite
SpawnExtendedSprite:
	LDY #$07
.ExtraLoop
	LDA $170B,y
	BEQ .Extra1
	DEY
	BPL .ExtraLoop
	RTS
.Extra1
	LDA !SpawnSpriteNumber
	STA $170B,y
	LDA !SpriteSpawnXLo
	STA $171F,y
	LDA !SpriteSpawnXHi
	STA $1733,y
	LDA !SpriteSpawnYLo
	STA $1715,y
	LDA !SpriteSpawnYHi
	STA $1729,y
	LDA !SpriteSpawnYSpeed
	STA $173D,y
	LDA !SpriteSpawnXSpeed
	STA $1747,y
	LDA #$FF
	STA $176F,y
	RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GET_DRAW_INFO
; This is a helper for the graphics routine.  It sets off screen flags, and sets up
; variables.  It will return with the following:
;
;       Y = index to sprite OAM ($300)
;       $00 = sprite x position relative to screen boarder
;       $01 = sprite y position relative to screen boarder  
;
; It is adapted from the subroutine at $03B760
; DO NOT POINT THIS TO THE SHARED SUBROUTINES, IT IS CHANGED AND THE SPRITE WILL BREAK IF YOU DO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SPR_T1:              db $0C,$1C
SPR_T2:              db $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                 ; / 
INVALID:                     RTS                     ; return
