;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Blue Elite Koopa
; by yoshicookiezeus
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

incsrc subroutinedefs_xkas.asm

			!RAM_FrameCounter	= $13
			!RAM_FrameCounterB	= $14
			!RAM_ScreenBndryXLo	= $1A
			!RAM_ScreenBndryYLo	= $1C
			!RAM_MarioDirection	= $76
			!RAM_MarioSpeedX	= $7B
			!RAM_MarioSpeedY	= $7D
			!RAM_MarioXPos		= $94
			!RAM_MarioXPosHi	= $95
			!RAM_MarioYPos		= $96
			!RAM_SpritesLocked	= $9D
			!RAM_SpriteNum		= $9E
			!RAM_SpriteSpeedY	= $AA
			!RAM_SpriteSpeedX	= $B6
			!RAM_SpriteState	= $C2
			!RAM_SpriteYLo		= $D8
			!RAM_SpriteXLo		= $E4
			!OAM_DispX		= $0300
			!OAM_DispY		= $0301
			!OAM_Tile		= $0302
			!OAM_Prop		= $0303
			!OAM_Tile2DispX		= $0304
			!OAM_Tile2DispY		= $0305
			!OAM_Tile2		= $0306
			!OAM_Tile2Prop		= $0307
			!OAM_TileSize		= $0460
			!RAM_RandomByte1	= $148D
			!RAM_RandomByte2	= $148E
			!RAM_KickImgTimer	= $149A
			!RAM_SpriteYHi		= $14D4
			!RAM_SpriteXHi		= $14E0
			!RAM_Reznor1Dead	= $1520
			!RAM_Reznor2Dead	= $1521
			!RAM_Reznor3Dead	= $1522
			!RAM_Reznor4Dead	= $1523
			!RAM_DisableInter	= $154C
			!RAM_SpriteDir		= $157C
			!RAM_SprObjStatus	= $1588
			!RAM_OffscreenHorz	= $15A0
			!RAM_SprOAMIndex	= $15EA
			!RAM_SpritePal		= $15F6
			!RAM_Tweaker1662	= $1662
			!RAM_ExSpriteNum	= $170B
			!RAM_ExSpriteYLo	= $1715
			!RAM_ExSpriteXLo	= $171F
			!RAM_ExSpriteYHi	= $1729
			!RAM_ExSpriteXHi	= $1733
			!RAM_ExSprSpeedY	= $173D
			!RAM_ExSprSpeedX	= $1747
			!RAM_OffscreenVert	= $186C
			!RAM_OnYoshi		= $187A

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite init JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

			print "INIT ",pc
			JSL !SubHorizPos
			TYA
			STA !RAM_SpriteDir,x
			LDA #$40			;\
			STA $1540,x			;/ set time before attacking
			RTL				; return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite code JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

			print "MAIN ",pc
			PHB
			PHK
			PLB
			JSR MainCode
			PLB
			RTL


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MainCode:		JSR SpriteGraphics
			LDA $14C8,x			;\ if sprite status not normal,
			CMP #$08			; |
			BNE Return1			;/ branch
			LDA !RAM_SpritesLocked		;\ if sprites locked,
			BNE Return0			;/ branch
			JSL !SubOffscreenX0
			LDA $151C,x			;\ call pointer for current action
			JSL $8086DF			;/

Pointers:		dw Waiting
			dw Attack
			dw Hurt
			dw Dead

Return0:		RTS				; return

Return1:		INC $1540,x
			RTS

HurtInState:		db $01,$01,$00,$00
!Hitpoints		= $03

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Waiting:		STZ !RAM_SpriteSpeedX,x		;
			STZ !RAM_SpriteSpeedY,x		;
			JSL $819138			; interact with objects
			JSL $818032			; interact with sprites
			LDA $1558,x			;\ if rising,
			BNE Rising			;/ branch
			LDA $1540,x			;\ if not yet time to attack,
			BNE StillState0			;/ branch
			LDA #$01			;\ set new sprite state (attacking)
			STA $151C,x			;/
			JSR SetNewSpeed
			STZ $1594,x
			BRA StillState0

Rising:			LDA !RAM_SprObjStatus,x
			AND #$08
			BNE StillState0
			LDA #$F0
			STA !RAM_SpriteSpeedY,x
			JSL $81801A			;\ update sprite position
			JSL $818022			;/

StillState0:		JSR MarioInteract
			RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Attack:			JSL $81801A			;\ update sprite position
			JSL $818022			;/
			JSL $819138			; interact with objects
			JSL $818032			; interact with sprites
			JSR MarioInteract
			LDA $1540,x
			BNE DontSetSpeed
			JSR SetNewSpeed
DontSetSpeed:		LDA !RAM_SprObjStatus,x
			AND #$03
			BEQ DontFlipX
			LDA !RAM_SpriteSpeedX,x
			BEQ DontFlipX
			LDA !RAM_SpriteSpeedX,x
			EOR #$FF
			INC A
			STA !RAM_SpriteSpeedX,x
			LDA !RAM_SpriteDir,x
			EOR #$01
			STA !RAM_SpriteDir,x
			LDA #$09
			STA $1DFC

DontFlipX:		LDA !RAM_SprObjStatus,x
			AND #$0C
			BEQ DontFlipY
			LDA !RAM_SpriteSpeedY,x
			BEQ DontFlipY
			LDA !RAM_SpriteSpeedY,x
			EOR #$FF
			INC A
			STA !RAM_SpriteSpeedY,x
			LDA #$09
			STA $1DFC
DontFlipY:		RTS

SetNewSpeed:		LDA #$40			;\ set time to attack
			STA $1540,x			;/
			INC $1594,x
			LDA $1594,x
			CMP #$04
			BEQ StopAttacking
			JSL !SubHorizPos
			TYA
			STA !RAM_SpriteDir,x
			LDA #$30
			JSR CODE_01BF6A
			LDA $01
			STA !RAM_SpriteSpeedX,x
			LDA $00
			STA !RAM_SpriteSpeedY,x
			RTS
StopAttacking:		STZ $151C,x
			RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Hurt:			STZ !RAM_SpriteSpeedX,x		; clear sprite speed
			JSL $81802A			; update sprite position
			JSL $819138			; interact with objects
			JSL $818032			; interact with sprites
			LDA $1540,x			; if not yet time to stop being hurt,
			BNE StillState2			; branch

			STZ $151C,x			; set new sprite state (waiting)
			LDA #$10			;\ set time to wait before attacking
			STA $1540,x			;/
			LDA #$08			;\ set time to rise
			STA $1558,x			;/
			STZ $1594,x
			JSR SetNewSpeed
			JSL !SubHorizPos
			TYA
			STA !RAM_SpriteDir,x
StillState2:		JSR MarioInteract
			RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Dead:			RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mario interaction routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MarioInteract:		JSL $81A7DC			;\ interact with Mario
			BCC Return03CEF1		;/ if no contact, branch
			LDA $1490			;\ if star timer isn't zero,
			BNE KillSprite			;/ branch
			LDA $154C,x
			BNE Return03CEF1
			LDA !RAM_MarioSpeedY		;\ if Mario is moving upwards,
			CMP #$10			; |
			BMI CODE_03CEED			;/  branch
			JSL $81AB99			; display contact graphic
			JSL $81AA33			; boost Mario upwards
			LDA #$02			;\ play sound effect
			STA $1DF9			;/
			LDA #$08
			STA $154C,x
			LDY $151C,x			;\ if current state is set to be invincible,
			LDA HurtInState,y		; |
			BEQ Return03CEEC		;/ branch
			INC $1534,x			; increase hitpoint counter
			LDA $1534,x			;\ if sprite hasn't been hit enough times,
			CMP #!Hitpoints			; |
			BNE CODE_03CEDB			;/ branch
KillSprite:		LDA #$02			;\ kill sprite
			STA $14C8,x			;/
			LDA #$E0
			STA !RAM_SpriteSpeedY,x
			LDA #$13			;\ play sound effect
			STA $1DF9			;/
			LDA #$03			;\ set new action (dead)
			STA $151C,x			;/
			LDA #$04			;\ give Mario 400 points
			JSL $82ACE5			;/
			RTS
CODE_03CEDB:		LDA #$02			;\ set action (stomped)
			STA $151C,x			;/
			LDA #$13			;\ play sound effect
			STA $1DF9			;/
			LDA #$40			;\ set time to stay in hurt state
			STA $1540,x			;/
			STZ !RAM_SpriteSpeedY,x		;
Return03CEEC:		RTS				; return

CODE_03CEED:		JSL $80F5B7			; hurt Mario
Return03CEF1:		RTS				; return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Tilemap:		db $08,$28			; walking frame 1, right
			db $06,$26			; walking frame 2, right
			db $20,$40			; walking frame 1, left
			db $22,$42			; walking frame 2, left
			db $08,$28			; attacking frame 1, right
			db $06,$26			; attacking frame 2, right
			db $20,$40			; attacking frame 1, left
			db $22,$42			; attacking frame 2, left
			db $0C				; hurt frame
			db $64				; dead frame

OffsetY:		db $F0,$00
			db $F0,$00
			db $F0,$00
			db $F0,$00
			db $F0,$00
			db $F0,$00
			db $F0,$00
			db $F0,$00
			db $00
			db $00

TilesToDraw:		db $01,$01,$00,$00		; walking, attacking, hurt, dead

StartOffset:		db $00,$08,$10,$11		; walking, attacking, hurt, dead

FrameDeterminatorBits:	db $02,$02,$00,$00		; walking, attacking, hurt, dead

Properties:		db $40,$00			; left, right

DirectionOffset:	db $04,$04,$00,$00

WingTiles:		db $4E,$6D
WingOffsetX:		db $F7,$09
WingOffsetY:		db $F4
			

SpriteGraphics:		JSL !GetDrawInfo
			LDA !RAM_SpriteDir,x
			STA $02

			STZ $07
			LDA $151C,x
			CMP #$02
			BCS NoWings

			PHX

			LDX $02
			LDA $00
			CLC
			ADC WingOffsetX,x
			STA !OAM_DispX,y

			LDA $01
			CLC
			ADC WingOffsetY
			STA !OAM_DispY,y

			PLX
			LDA $1540,x
			LSR
			LSR
			LSR
			AND #$01
			TAX
			LDA WingTiles,x
			STA !OAM_Tile,y

			LDX $02
			LDA Properties,x
			LDX $15E9			; |
			ORA $15F6,x			; |
			ORA $64				; |
			STA !OAM_Prop,y			;/

			INC $07

			INY
			INY
			INY
			INY

NoWings:		LDA !RAM_SpriteDir,x
			BEQ Right
			LDA $151C,x
			PHX
			TAX
			LDA DirectionOffset,x
			STA $02
			PLX

Right:			PHX
			LDA $151C,x
			TAX
			LDA FrameDeterminatorBits,x
			STA $03

			LDA StartOffset,x
			STA $04

			PLX
			LDA $1540,x
			LSR
			LSR
			AND $03
			CLC
			ADC $02
			CLC
			ADC $04
			STA $05
			PHX
			LDA $151C,x
			TAX
			LDA TilesToDraw,x
			STA $06
			TAX

Loop_Start:		PHX				; preserve loop counter

			LDX $05

			LDA $00				;\ set tile x position
			STA !OAM_DispX,y		;/

			LDA $01				;\ set tile y position
			CLC				; |
			ADC OffsetY,x			; |
			STA !OAM_DispY,y		;/

			LDA Tilemap,x			;\ set tile number
			STA !OAM_Tile,y			;/

			LDX $15E9			;\ set tile properties
			LDA $15F6,x			; |
			ORA $64				; |
			STA !OAM_Prop,y			;/

			INY				;\ increase OAM index by four, so that the next tile can be drawn
			INY				; |
			INY				; |
			INY				;/

			INC $05
			PLX				; retrieve loop counter
			DEX				; decrease loop counter
			BPL Loop_Start			; if more tiles left to draw, branch

			PLX

			LDY #$02
			LDA $06
			CLC
			ADC $07
			JSL $81B7B3
			
			RTS				; return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; aiming routine
; input: accumulator should be set to total speed (x+y)
; output: $00 = y speed, $01 = x speed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

CODE_01BF6A:		STA $01
			PHX					;\ preserve sprite indexes of Magikoopa and magic
			PHY					;/
			JSR CODE_01AD42				; $0E = vertical distance to Mario
			STY $02					; $02 = vertical direction to Mario
			LDA $0E					;\ $0C = vertical distance to Mario, positive
			BPL CODE_01BF7C				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
CODE_01BF7C:		STA $0C					;/
			JSL !SubHorizPos			; $0F = horizontal distance to Mario
			STY $03					; $03 = horizontal direction to Mario
			LDA $0F					;\ $0D = horizontal distance to Mario, positive
			BPL CODE_01BF8C				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
CODE_01BF8C:		STA $0D					;/
			LDY #$00
			LDA $0D					;\ if vertical distance less than horizontal distance,
			CMP $0C					; |
			BCS CODE_01BF9F				;/ branch
			INY					; set y register
			PHA					;\ switch $0C and $0D
			LDA $0C					; |
			STA $0D					; |
			PLA					; |
			STA $0C					;/
CODE_01BF9F:		LDA #$00				;\ zero out $00 and $0B
			STA $0B					; | ...what's wrong with STZ?
			STA $00					;/
			LDX $01					;\ divide $0C by $0D?
CODE_01BFA7:		LDA $0B					; |\ if $0C + loop counter is less than $0D,
			CLC					; | |
			ADC $0C					; | |
			CMP $0D					; | |
			BCC CODE_01BFB4				; |/ branch
			SBC $0D					; | else, subtract $0D
			INC $00					; | and increase $00
CODE_01BFB4:		STA $0B					; |
			DEX					; |\ if still cycles left to run,
			BNE CODE_01BFA7				;/ / go to start of loop
			TYA					;\ if $0C and $0D was not switched,
			BEQ CODE_01BFC6				;/ branch
			LDA $00					;\ else, switch $00 and $01
			PHA					; |
			LDA $01					; |
			STA $00					; |
			PLA					; |
			STA $01					;/
CODE_01BFC6:		LDA $00					;\ if horizontal distance was inverted,
			LDY $02					; | invert $00
			BEQ CODE_01BFD3				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
			STA $00					;/
CODE_01BFD3:		LDA $01					;\ if vertical distance was inverted,
			LDY $03					; | invert $01
			BEQ CODE_01BFE0				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
			STA $01					;/
CODE_01BFE0:		PLY					;\ retrieve Magikoopa and magic sprite indexes
			PLX					;/
			RTS					; return

CODE_01AD42:		LDY #$00
			LDA $D3
			CLC					;\ make subroutine use position of Mario's lower half instead of the upper one
			ADC #$10				;/ this wasn't in the original routine
			SEC
			SBC !RAM_SpriteYLo,x
			STA $0E
			LDA $D4
			SBC !RAM_SpriteYHi,x
			BPL Return01AD53
			INY
Return01AD53:		RTS					; return
