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

			!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 "MAIN ",pc
			PHB
			PHK
			PLB
			JSR Sprite_Code_Start
			PLB
			print "INIT ",pc
			RTL


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

BatTiles:		db $AE,$C0,$E8

Sprite_Code_Start:	JSR Sprite_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
			JSR SUB_OFF_SCREEN_X0
			JSL $01803A			; interact with Mario and with other sprites
			JSL $018022			;\ update sprite position
			JSL $01801A			;/
			LDA !RAM_SpriteState,x		;\ use sprite state to determine which code to go to
			JSL $0086DF

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
			JSR SUB_HORZ_POS
			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 #$E0			;\ 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
			INC !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


Sprite_Graphics:
			JSL $20CA4F

			PHY
			LDY $1602,x
			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 $C2,x
			BEQ YFLIP
			LDY $14C8,x
			CPY #$08
			BEQ No_Y_Flip	
YFLIP:		
			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 $01B7B3		; / don't draw if offscreen
			RTS			; return




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_OFF_SCREEN
; This subroutine deals with sprites that have moved off screen
; It is adapted from the subroutine at $01AC0D
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
			
SPR_T12:		db $40,$B0
SPR_T13:		db $01,$FF
SPR_T14:		db $30,$C0,$A0,$C0,$A0,$F0,$60,$90		;bank 1 sizes
			db $30,$C0,$A0,$80,$A0,$40,$60,$B0		;bank 3 sizes
SPR_T15:		db $01,$FF,$01,$FF,$01,$FF,$01,$FF		;bank 1 sizes
			db $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 $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