;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite BE - Swooper
; adapted for Romi's Spritetool and commented by yoshicookiezeus
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

incsrc subroutinedefs_xkas.asm

			!RAM_FrameCounter	= $13
			!RAM_FrameCounterB	= $14
			!RAM_MarioSpeedX	= $7B
			!RAM_MarioXPos		= $94
			!RAM_MarioXPosHi	= $95
			!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_TileSize		= $0460
			!RAM_SpriteYHi		= $14D4
			!RAM_SpriteXHi		= $14E0
			!RAM_SpriteDir		= $157C
			!RAM_SprObjStatus	= $1588
			!RAM_OffscreenHorz	= $15A0
			!RAM_SprOAMIndex	= $15EA
			!RAM_SpritePal		= $15F6
			!RAM_OffscreenVert	= $186C

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

			print "INIT ",pc
			LDA $7FAB10,x
			AND #$04
			BEQ EndInit
			LDA #$10
			STA $1656,x
			LDA #$80
			STA $1662,x
			LDA #$07
			STA $166E,x
			AND #$0F
			STA $15F6,x
			LDA #$01
			STA $167A,x
			LDA #$10
			STA $1686,x
			STZ $190F,x
			LDA #$51
			STA $9E,x
			JSL !SubHorizPos
			TYA
			STA $157C,x
			EndInit:
			RTL
			
			print "MAIN ",pc
			PHB
			PHK
			PLB
			JSR Sprite_Code_Start
			PLB
			RTL


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

BatTiles:		db $22,$C0,$24
			db $C0,$C2,$C4
NinjiTiles:	db $22,$24
NinjiYSpeed:	db $D0,$C0,$B0,$D0

Sprite_Code_Start:
			LDA $7FAB10,x
			AND #$04
			BEQ Swooper
			JMP Ninji

Swooper:		JSR Swooper_Graphics
			LDA $14C8,x			;\ if sprite status normal,
			CMP #$08			; |
			BEQ CODE_0388C0			;/ go to main code
			RTS

CODE_0388C0:
			LDA !RAM_SpritesLocked		;\ if sprites locked,
			BNE Return0388DF		;/ return
			JSL !SubOffscreenX0
			JSL $81803A			; interact with Mario and with other sprites
			JSL $818022			;\ update sprite position
			JSL $81801A			;/
			LDA !RAM_SpriteState,x		;\ use sprite state to determine which code to go to
			JSL $8086DF

SwooperPtrs:		dw CODE_0388E4			; waiting
			dw CODE_038905			; swooping down
			dw CODE_038936			; flying horizontally

Return0388DF:
			RTS				; return


Max_X_Speed:		db $10,$F0
Max_Y_Speed:		db $04,$FC
X_Acceleration:		db $01,$FF
Y_Acceleration:		db $01,$FF

CODE_0388E4:
			LDA !RAM_OffscreenHorz,x	;\ if sprite offscreen horizontally,
			BNE Return038904		;/ return
			JSL !SubHorizPos
			LDA $0F				;\ if Mario more than 0x50 pixels (5 16x16 tiles) from sprite,
			CLC				; |
			ADC #$50			; |
			CMP #$A0			; |
			BCS Return038904		;/ return
			INC !RAM_SpriteState,x		; sprite state = swooping down
			TYA				;\ make sprite face Mario
			STA !RAM_SpriteDir,x		;/
			LDA #$20			;\ set initial y speed
			STA !RAM_SpriteSpeedY,x		;/
			LDA #$26			;\ play sound effect 
			STA $1DFC			;/
Return038904:
			RTS				; return 

CODE_038905:
			LDA !RAM_FrameCounter		;\ three out of four frames,
			AND #$03			; |
			BNE CODE_038915			;/ branch
			LDA !RAM_SpriteSpeedY,x		;\ if sprite y speed == 0,
			BEQ CODE_038915			;/ branch
			DEC !RAM_SpriteSpeedY,x
			BNE CODE_038915			; if new sprite y speed =/= 0, branch
			INC !RAM_SpriteState,x		; else, sprite state = flying horizontally
CODE_038915:
			LDA !RAM_FrameCounter		;\ three out of four frames,
			AND #$03			; |
			BNE CODE_03892B			;/ branch
			LDY !RAM_SpriteDir,x		;\ set sprite x speed according to direction
			LDA !RAM_SpriteSpeedX,x		;/
			CMP Max_X_Speed,y		;\ if max x speed achieved,
			BEQ CODE_03892B			;/ skip accelerating sprite
			CLC				;\ else,
			ADC X_Acceleration,y		; |
			STA !RAM_SpriteSpeedX,x		;/ accelerate sprite
CODE_03892B:
			LDA !RAM_FrameCounterB		;\ use frame counter to determine graphics frame to use
			AND #$04			; |
			LSR				; |
			LSR				; |
			INC A				; |
			STA $1602,x			;/
			RTS				; return

CODE_038936:
			LDA !RAM_FrameCounter		;\ if number of current frame is odd,
			AND #$01			; |
			BNE CODE_038952			;/ branch
			LDA $151C,X			;\ use sprite vertical direction to determine vertical acceleration
			AND #$01			; |
			TAY				; |
			LDA !RAM_SpriteSpeedY,x		; |
			CLC				; |
			ADC Y_Acceleration,y		; |
			STA !RAM_SpriteSpeedY,x		;/
			CMP Max_Y_Speed,y		;\ if max y speed in current direction not achieved,
			BNE CODE_038952			;/ branch
			INC $151C,X			; else, swap sprite vertical direction
CODE_038952:
			BRA CODE_038915			; reuse normal movement routine from the previous sprite state


Swooper_Graphics:
			JSL !GetDrawInfo

LDA $1602,x
STA $02
LDA $13BF
CMP #$5D
BNE .Skip
LDA $02
CLC
ADC #$03
STA $02
.Skip
			PHY
			LDY $02
			LDA BatTiles,y
			PLY
			STA !OAM_Tile,y
			LDA $00
			STA !OAM_DispX,y
			LDA $01
			STA !OAM_DispY,Y
			LDA $15F6,x

			PHY
			LDY !RAM_SpriteDir,X
			BNE No_X_Flip
			EOR #$40
No_X_Flip:
			LDY $14C8,x
			CPY #$08
			BEQ No_Y_Flip
			ORA #$80
No_Y_Flip:
			PLY
			ORA $64
			STA !OAM_Prop,Y

			LDY #$02		; \ 460 = 2 (all 16x16 tiles)
			LDA #$00		;  | A = (number of tiles drawn - 1)
			JSL $81B7B3		; / don't draw if offscreen
			RTS			; return

Ninji:

LDA $14C8,x
CMP #$02
BNE .Continue
LDA $15F6,x		;
ORA #$80		;
STA $15F6,x		;
.Continue

JSR NinjiGFX			; draw the sprite

LDA $9D			; if sprites are locked...
BNE .Return			; return

LDA $14C8,x		;
CMP #$08		;
BNE .Return		;

JSL !SubOffscreenX0	; offscreen processing
JSL $81802A		; update sprite position with gravity
JSL $81803A		; interact with the player and with other sprites

JSL !SubHorizPos		;
TYA				; always face the player
STA $157C,x		;

LDA $1588,x		;
AND #$08			; these 5 lines of code were not in the original sprite
BEQ .NoTouchCeiling	; this prevents the Ninji from jumping through the ceiling
STZ $AA,x			;
.NoTouchCeiling		;

LDA $1588,x		;
AND #$04			; if the sprite is not on the ground...
BEQ .SetFrame		; don't set its Y speed

STZ $AA,x			; initialize the Y speed to 0
LDA $1540,x		; if the sprite has just jumped and isn't ready to jump again...
BNE .SetFrame		; don't set its Y speed
LDA #$60			;
STA $1540,x		; if it is ready to jump, set the timer between jumps
INC $C2,x			; increment the sprite state
LDA $C2,x			;
AND #$03			; only the lowest 2 bits of the sprite state matter
TAY					; these will be used to index the Y speed table
LDA NinjiYSpeed,y	; and the four possible Y speeds will cycle
STA $AA,x		;

.SetFrame			;

LDA #$00			;
LDY $AA,x			; if the sprite is moving upward, use the first frame;
BMI $01			; if the sprite is moving downward or is stationary,
INC				; use the second frame
STA $1602,x		;

.Return			;
RTS				;

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

NinjiGFX:

JSL !GetDrawInfo

LDA $1602,x		;
TAX				;
LDA NinjiTiles,x	; set the sprite tilemap
STA $0302,y		;

LDX $15E9			;
LDA $00			;
STA $0300,y		; no X displacement
LDA $01			;
STA $0301,y		; no Y displacement

LDA $157C,x		;
LSR				; if the sprite is facing right...
LDA $15F6,x		;
BCS .NoXFlip		; X-flip it
EOR #$40			;
.NoXFlip			;
ORA $64			;
STA $0303,y		;

TYA				;
LSR #2			;
TAY				;

LDA #$02			;
ORA $15A0,x		;
STA $0460,y		; set the tile size

PHK				;
PEA.w .EndGFX-$01	;
PEA $8020			;
JML $81A3DF		; set up some stuff in OAM
.EndGFX			;

RTS

