;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Doc Croc, by yoshicookiezeus
; for ASMWCP2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

			!BulletNbr		= $0E	; cluster sprite number for bullet_croc.asm
			!MiscSpriteNbr		= $B8	; sprite number for croc_misc.asm

			!FreeRAM		= $7EC400	; needs to be at least 20 (decimal) bytes
								; THIS MUST BE SET TO THE SAME VALUE AS THE DEFINE IN croc_bullet.asm!

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RAM address defines - don't change these
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

			!RAM_FrameCounter	= $13
			!RAM_FrameCounterB	= $14
			!RAM_ScreenBndryXLo	= $1A
			!RAM_ScreenBndryYLo	= $1C
			!RAM_ScreensInLvl	= $5D
			!RAM_MarioAnimation	= $71
			!RAM_MarioDirection	= $76
			!RAM_MarioObjStatus	= $77
			!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_ExtendedDispX	= $0200
			!OAM_ExtendedDispY	= $0201
			!OAM_ExtendedTile	= $0202
			!OAM_ExtendedProp	= $0203
			!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_IsBehindScenery	= $13F9
			!RAM_RandomByte1	= $148D
			!RAM_RandomByte2	= $148E
			!RAM_KickImgTimer	= $149A
			!RAM_SpriteYHi		= $14D4
			!RAM_SpriteXHi		= $14E0
			!RAM_DisableInter	= $154C
			!RAM_SpriteDir		= $157C
			!RAM_SprObjStatus	= $1588
			!RAM_OffscreenHorz	= $15A0
			!RAM_SprOAMIndex	= $15EA
			!RAM_SpritePal		= $15F6
			!RAM_Tweaker1662	= $1662
			!RAM_Tweaker1686	= $1686
			!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
			!RAM_ShakeGrndTimer	= $1887
			!RAM_ClusterSpriteNum	= $1892
			!RAM_LockMarioTimer	= $18BD
			!RAM_ClusterYPosLo	= $1E02
			!RAM_ClusterYPosHi	= $1E2A
			!RAM_ClusterXPosLo	= $1E16
			!RAM_ClusterXPosHi	= $1E3E
			!RAM_ClusterYSpeed	= $1E52
			!RAM_ClusterXSpeed	= $1E66

			!RAM_DirectionTimer	= !FreeRAM

			!RAM_ExtraBits 		= $7FAB10
			!RAM_CustSpriteNum	= $7FAB9E


			!CurrentAction		= $151C
			!GlassType		= $1528

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ShockWaveAccel:		db $02,$FE
DroneMaxSpeed:		db $10,$F0
DroneAccel:		db $02,$FE

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

			print "INIT ",pc
			RTL

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

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


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

Main:			JSR SpriteGraphics
			LDA $14C8,x			;\ if sprite state not normal,
			CMP #$08			; |
			BNE .Return			;/ return
			LDA !RAM_SpritesLocked		;\ if sprites locked,
			BNE .Return			;/ return
			LDA !RAM_SpriteState,x		;\ jump to current action
			JSL $0086DF			;/

.Pointers:		dw Bomb
			dw ShockWave
			dw Jaw
			dw Doc
			dw Drone
			dw Glass

.Return			RTS

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

Bomb:			JSL $01802A			; update sprite position and apply gravity
			JSL $01A7DC			;\ interact with Mario
			BCC .NoContact			;/ if no contact, branch
			JSL $00F5B7			; hurt Mario

.NoContact		JSL $019138			; interact with objects
			LDA !RAM_SprObjStatus,x		;\ if sprite isn't touching floor,
			AND #$04			; |
			BEQ .Return			;/ branch

			LDA #$18			;\ play sound effect
			STA $1DFC			;/

			LDA #$20			;\ set ground shake timer
			STA $1887			;/

			LDY #$01			; setup loop

.LoopStart		PHY
			JSR FindSpriteSlot		;\ get index for empty sprite slot
			BMI .Return			;/ if no empty slots, branch

			LDA #$08			;\ set new sprite status
			STA $14C8,y			;/

			LDA !RAM_SpriteXLo,x		;\ set new sprite position
			STA.w !RAM_SpriteXLo,y		; |
			LDA !RAM_SpriteXHi,x		; |
			STA !RAM_SpriteXHi,y		; |
			LDA !RAM_SpriteYLo,x		; |
			STA.w !RAM_SpriteYLo,y		; |
			LDA !RAM_SpriteYHi,x		; |
			STA !RAM_SpriteYHi,y		;/

			LDA #!MiscSpriteNbr		;\ set new sprite number
			PHX				; |
			TYX				; |
			STA !RAM_CustSpriteNum,x	;/

			JSL $07F7D2			; clear out old sprite table values
			JSL $0187A7			;  get table values for custom sprite
			LDA #$08			;\ mark sprite as custom
			STA !RAM_ExtraBits,x		;/
			PLX

			LDA #$01
			STA.w !RAM_SpriteState,y

			STY $00
			PLY
			PHY
			TYA
			LDY $00
			STA.w !RAM_SpriteDir,y

			LDA #$2A
			STA !RAM_Tweaker1662,y

			PLY
			DEY				;\ if sprites left to spawn,
			BPL .LoopStart			;/ branch

			JSR Explode
.Return			RTS

Explode:		LDA #$0D			;\ turn sprite
			STA $9E,x			;/ into bob-omb
			JSL $07F7D2			; reset sprite tables
			LDA #$08			;\ sprite status:
			STA $14C8,x			;/ normal
			LDA #$01			;\ make it
			STA $1534,x			;/ explode
			LDA #$30			;\ set time for
			STA $1540,x			;/ explosion
			RTS

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

ShockWave:		LDA !RAM_SpriteDir,x		;\ set sprite speed
			TAY				; |
			LDA ShockWaveAccel,y		; |
			CLC				; |
			ADC !RAM_SpriteSpeedX,x		; |
			STA !RAM_SpriteSpeedX,x		;/
			JSL $018022			; update sprite position

			JSL $019138			; interact with objects
			LDA !RAM_SprObjStatus,x		;\ if sprite isn't touching walls,
			AND #$03			; |
			BEQ .NoContact			;/ branch
			STZ $14C8,x			; erase sprite

.NoContact		JSL $01A7DC			;\ interact with Mario
			BCC .Return			;/ if no contact, branch
			JSL $00F5B7			; hurt Mario

.Return			RTS

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

Jaw:			JSL $01802A			; update sprite position and apply gravity
			RTS

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

Doc:			JSL $01802A			; update sprite position and apply gravity
			RTS

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

Drone:			JSL $01A7DC		;\ interact with Mario
			BCC .NoContact		;/ if no contact, branch
			JSL $00F5B7		; hurt Mario

.NoContact		LDA $14			;\ only change speeds every second frame
			AND #$01		; |
			BNE .ApplySpeed		;/

			JSR SubHorzPos		;\  if max horizontal speed in the appropriate
			LDA !RAM_SpriteSpeedX,x	; | direction achieved,
			CMP DroneMaxSpeed,y	; |
			BEQ .MaxXSpeedReached	;/  don't change horizontal speed
			CLC			;\  else,
			ADC DroneAccel,y	; | accelerate in appropriate direction
			STA !RAM_SpriteSpeedX,x	;/

.MaxXSpeedReached	JSR SubVertPos		;\  if max vertical speed in the appropriate
			LDA !RAM_SpriteSpeedY,x	; | direction achieved,
			CMP DroneMaxSpeed,y	; |
			BEQ .ApplySpeed		;/  don't change vertical speed
			CLC			;\  else,
			ADC DroneAccel,y	; | accelerate in appropriate direction
			STA !RAM_SpriteSpeedY,x	;/

.ApplySpeed		JSL $018022		; apply x speed
			JSL $01801A		; apply y speed

			RTS			         

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

Glass:			JSL $01802A			; update sprite position and apply gravity
			RTS

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

TableOffset:		db $00,$01,$03,$06
NbrOfTiles:		db $00,$01,$02,$03

OffsetX:		db $00,$00,$00,$F0,$00,$10,$F8,$08,$F8,$08
OffsetY:		db $00,$00,$F0,$00,$00,$00,$F8,$F8,$08,$08
Tilemap:		db $80,$C0,$A0,$4C,$4E,$4E,$44,$46,$64,$66
Properties:		db $2F,$2F,$2F,$2F,$2F,$6F,$2D,$2D,$2D,$2D


SpriteGraphics:		JSR GetDrawInfo

			LDA !RAM_SpriteDir,x
			STA $05

			LDA !RAM_SpriteState,x
			CMP #$04
			BEQ DroneGFX
			CMP #$05
			BNE .Other
			JMP GlassGFX

.Other			STA $02

			PHX
			TAX
			LDA TableOffset,x
			STA $03

			LDA NbrOfTiles,x
			STA $04
			TAX

.LoopStart		PHX

			TXA			
			CLC
			ADC $03
			TAX

			LDA $00				;\ set tile x position
			CLC				; |
			ADC OffsetX,x			; |
			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			;/

			LDA Properties,x		;\ set tile properties
			LDX $02				; |
			CPX #$01			; |
			BNE .Continue			; |
			LDX $05				; |
			BNE .Continue			; |
			ORA #$40			; |
.Continue		STA !OAM_Prop,y			;/

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

			PLX
			DEX				; decrease loop counter
			BPL .LoopStart			; if more tiles left to draw, branch

			PLX

			LDA $04				; number of tiles drawn - 1
			LDY #$02			; the tiles drawn were 16x16
			JSL $01B7B3			; finish OAM write
			
.Return			RTS				; return


DroneTiles:		db $82,$84
DroneProps:		db $6F,$2F


DroneGFX:		JSR GetDrawInfo

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

			PHX
			LDA !RAM_FrameCounterB		;\ set tile number
			LSR				; |
			AND #$01			; |
			TAX				; |
			LDA DroneTiles,x		; |
			STA !OAM_Tile,y			;/
			PLX

			PHY				;\ set tile properties
			JSR SubHorzPos			; |
			LDA DroneProps,y		; |
			PLY				; |
			STA !OAM_Prop,y			;/

			LDA #$00			; one tile was drawn
			LDY #$02			; the tiles drawn were 16x16
			JSL $01B7B3			; finish OAM write

			RTS


GlassTiles:		db $08,$28,$7E,$7F
GlassSizes:		db $02,$02,$00,$00
GlassProps:		db $2F,$4F,$8F,$6F

GlassGFX:		JSR GetDrawInfo

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

			PHX
			LDA !GlassType,x		;\ set tile number
			TAX				; |
			LDA GlassTiles,x		; |
			STA !OAM_Tile,y			;/

			PHX
			TXA				;\ set tile properties
			CLC				; |
			ADC !RAM_FrameCounterB		; |
			AND #$03			; |
			TAX				; |
			LDA GlassProps,x		; |
			STA !OAM_Prop,y			;/

			PLX
			LDA GlassSizes,x		;\ set tile size
			PHA				; |
			TYA				; |
			LSR				; |
			LSR				; |
			TAY				; |
			PLA				; |
			STA !OAM_TileSize,y		;/

			PLX
			
			LDA #$00			; one tile was drawn
			LDY #$FF			; the tile sizes were written to $0460
			JSL $01B7B3			; finish OAM write

			RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routine for finding a free sprite slot
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

FindSpriteSlot:		LDY #$09
.LoopStart		LDA $14C8,y
			BEQ .Return
			DEY
			BPL .LoopStart
.Return			RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B760 - graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B75C

Table1:			db $0C,$1C
Table2:			db $01,$02

GetDrawInfo:		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 OnScreenX			; |
			INC $15A0,x			;/

OnScreenX:		LDA $14E0,x			;\
			XBA				; |
			LDA $E4,x			; |
			REP #$20			; |
			SEC				; |
			SBC $1A				; | mark sprite invalid if far enough off screen
			CLC				; |
			ADC #$0040			; |
			CMP #$0180			; |
			SEP #$20			; |
			ROL A				; |
			AND #$01			; |
			STA $15C4,x			;/
			BNE Invalid			;
			
			LDY #$00			;\ set up loop:
			LDA $1662,x			; |
			AND #$20			; | if not squished (1662 & 0x20), go through loop twice
			BEQ OnScreenLoop		; | else, go through loop once
			INY				;/
OnScreenLoop:		LDA $D8,x			;\
			CLC				; | set vertical offscreen if necessary
			ADC Table1,y			; |
			PHP				; |
			CMP $1C				; | (vert screen boundry)
			ROL $00				; |
			PLP				; |
			LDA $14D4,x			; |
			ADC #$00			; |
			LSR $00				; |
			SBC $1D				; |
			BEQ OnScreenY			; |
			LDA $186C,x			; | (vert offscreen)
			ORA Table2,y			; |
			STA $186C,x			; |
OnScreenY:		DEY				; |
			BPL OnScreenLoop		;/

			LDY $15EA,x			; get offset to sprite OAM
			LDA $E4,x			;\
			SEC				; | 
			SBC $1A				; | $00 = sprite x position relative to screen border
			STA $00				;/
			LDA $D8,x			;\
			SEC				; | 
			SBC $1C				; | $01 = sprite y position relative to screen border
			STA $01				;/
			RTS				; return

Invalid:		PLA				;\ return from *main gfx routine* subroutine...
			PLA				; |    ...(not just this subroutine)
			RTS				;/

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B817 - horizontal mario/sprite check - shared
; Y = 1 if mario left of sprite??
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B817        

SubHorzPos:		LDY #$00
			LDA $94
			SEC
			SBC $E4,x
			STA $0F
			LDA $95
			SBC $14E0,x
			BPL .Return
			INY
.Return			RTS

SubVertPos:		REP #$20
			LDA $96
			CLC
			ADC.w #$0010
			STA $0C
			SEP #$20

			LDY #$00
			LDA $0C
			SEC
			SBC $D8,x
			STA $0E
			LDA $D4
			SBC !RAM_SpriteYHi,x
			BPL .Return
			INY
.Return			RTS