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

!FrameNum = $C2
!Direction = $157C
!Action = $1510
!ActionTimer = $1540
!Objectclipnum = $7FABAA

                    print "INIT ",pc
					STZ !FrameNum,x
					JSR SUB_HORZ_POS
					TYA
					STA !Direction,x
					STZ !Action,x
					LDA #$60
					STA !ActionTimer,x
					LDA #$00
					STA !Objectclipnum,x
					RTL
	                print "MAIN ",pc			
                    PHB
                    PHK				
                    PLB
                    JSR SPRITE_ROUTINE			;Jump to the routine to keep organized
                    PLB
                    RTL     


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SPRITE_ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

XSpeeds:
db $17,$E9

Actions:
dw PrepJump
dw JumpingAc
dw Crumbling
dw Crumbled
dw UnCrumbling

SquattingFrames:
db $01,$02,$01,$00,$01,$02,$01,$00,$01,$02,$01,$00,$01,$02,$01,$00

CrumblingFrames:
db $06,$05,$04

UnCrumblingFrames:
db $04,$05,$06

Jumpreturn:
JMP return

SPRITE_ROUTINE:	  	
					LDA $9D
					BNE Jumpreturn
					LDA $14C8,x
					CMP #$08
					BNE Jumpreturn
					PHX
					LDA !Action,x
					ASL
					TAX
					REP #$20
					LDA Actions,x
					STA $00
					SEP #$20
					PLX
					JMP ($0000)

					
					PrepJump:
					JSR SUB_HORZ_POS
					TYA
					STA !Direction,x
					JSL $01802A
					JSL $01A7DC
					BCC .NoContact
					JSR SUB_VERT_POS	; \
					LDA $0E			;  | if mario isn't above sprite, and there's vertical contact...
					CMP #$E6		;  |     ... sprite wins
					BPL .SpriteWins		; /
					LDA $7D			; \ if mario speed is upward, return
					BMI .NoContact		; /

					LDA $15		; Save controller state
					PHA
					ORA #$C0	; Set holding X/Y and A/B
					STA $15
					JSL $01AA33	; set mario speed
					PLA
					STA $15

					JSL $01AB99             ; display contact graphic
					LDA #$07
					STA $1DF9
					LDA #$02
					STA !Action,x
					LDA #$30
					STA !ActionTimer,x
					JMP .NoContact 

					.SpriteWins
					LDA $154C,x	; \ if disable interaction set...
					ORA $15D0,x	;  |   ...or sprite being eaten...
					BNE .NoContact	; /   ...return
					LDA $1490	; \ Branch if Mario has a star
					BNE .NoContact	; /
					JSL $00F5B7	; damage Mario
					.NoContact
					LDA !ActionTimer,x
					BNE +
					INC !Action,x
					LDA !Direction,x
					PHX
					TAX
					LDA XSpeeds,x
					PLX
					STA $B6,x
					LDA #$D4
					STA $AA,x
					BRA ++
					+
					LSR #3
					PHX
					TAX
					LDA SquattingFrames,x
					PLX
					STA !FrameNum,x
					++
					JMP return
					
					JumpingAc:
					LDA #$03
					STA !FrameNum,x
					JSL $01802A
					JSL $01A7DC
					BCC .NoContact
					JSR SUB_VERT_POS	; \
					LDA $0E			;  | if mario isn't above sprite, and there's vertical contact...
					CMP #$E6		;  |     ... sprite wins
					BPL .SpriteWins		; /
					LDA $7D			; \ if mario speed is upward, return
					BMI .NoContact		; /

					LDA $15		; Save controller state
					PHA
					ORA #$C0	; Set holding X/Y and A/B
					STA $15
					JSL $01AA33	; set mario speed
					PLA
					STA $15

					JSL $01AB99             ; display contact graphic
					LDA #$02
					STA $1DF9
					JMP .NoContact 

					.SpriteWins
					LDA $154C,x	; \ if disable interaction set...
					ORA $15D0,x	;  |   ...or sprite being eaten...
					BNE .NoContact	; /   ...return
					LDA $1490	; \ Branch if Mario has a star
					BNE .NoContact	; /
					JSL $00F5B7	; damage Mario
					.NoContact
					LDA $1588,x
					BIT #$08
					BEQ +
					STZ $AA,x
					+
					LDA $1588,x
					BIT #$03
					BEQ +
					LDA $B6,x
					EOR #$FF
					INC
					STA $B6,x
					+
					LDA $1588,x
					BIT #$04
					BEQ +
					DEC !Action,x
					STA $AA,x
					STZ $B6,x
					LDA #$60
					STA !ActionTimer,x
					+
					.return
					JMP return
					
					
					Crumbling:
					LDA !ActionTimer,x
					BNE +
					INC !Action,x
					LDA #$50
					STA !ActionTimer,x
					JMP return
					+
					LSR #4
					PHX
					TAX
					LDA CrumblingFrames,x
					PLX
					STA !FrameNum,x
					JMP return
					
					Crumbled:
					LDA !ActionTimer,x
					BNE +
					INC !Action,x
					LDA #$30
					STA !ActionTimer,x
					JMP return
					+
					CMP #$20
					BCS +
					LSR #2
					AND #$01
					PHX
					ASL
					TAX
					LDA .PosOffsets,x
					STA $00
					LDA .PosOffsets+1,x
					STA $01
					PLX
					LDA $14E0,x
					PHA
					XBA
					LDA $E4,x
					PHA
					REP #$20
					CLC
					ADC $00
					SEP #$20
					STA $E4,x
					XBA
					STA $14E0,x
					JSR SUB_OFF_SCREEN_X3
					JSR SUB_GFX	
					PLA
					STA $E4,x
					PLA
					STA $14E0,x
					JMP realreturn
					+
					JMP return
					
					.PosOffsets
					dw $0001,$FFFF
					
					UnCrumbling:
					LDA !ActionTimer,x
					BNE +
					STZ !Action,x
					LDA #$60
					STA !ActionTimer,x
					JMP return
					+
					LSR #4
					PHX
					TAX
					LDA UnCrumblingFrames,x
					PLX
					STA !FrameNum,x
					
					return:
					JSR SUB_OFF_SCREEN_X3
					JSR SUB_GFX					;Draw the graphics
					realreturn:
                    RTS							;End the routine
					
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GRAPHICS ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SUB_HORZ_POS:		LDY #$00
					LDA $94
					SEC
					SBC $E4,x
					STA $0F
					LDA $95
					SBC $14E0,x
					BPL +
					INY
					+
					RTS
SUB_VERT_POS:		LDY #$00
					LDA $96
					SEC
					SBC $D8,x
					STA $0F
					LDA $97
					SBC $14D4,x
					BPL +
					INY
					+
					RTS

					
TileNums:
db $02,$02,$02,$03,$02,$02,$02

TilePointers:
dw Standing
dw Bend1
dw Bend2
dw Jumping
dw Crumble1
dw Crumble2
dw Crumble3

XOffPointers:
dw StandingX
dw Bend1X
dw Bend2X
dw JumpingX
dw Crumble1X
dw Crumble2X
dw Crumble3X

YOffPointers:
dw StandingY
dw Bend1Y
dw Bend2Y
dw JumpingY
dw Crumble1Y
dw Crumble2Y
dw Crumble3Y

Standing:
db $84,$A4,$EA

Bend1:
db $86,$A6,$EA

Bend2:
db $88,$A8,$EA

Jumping:
db $84,$94,$C6,$EA

Crumble1:
db $C0,$E0,$EA

Crumble2:
db $D2,$E2,$E3

Crumble3:
db $E5,$E5,$E6


StandingX:
Bend1X:
Bend2X:
Crumble1X:
db $00,$00,$10

JumpingX:
db $00,$00,$00,$10

Crumble2X:
Crumble3X:
db $00,$00,$08


StandingY:
db $F0,$00,$F8

Bend1Y:
db $F0,$00,$F9

Bend2Y:
db $F0,$00,$FB

JumpingY:
db $F0,$F8,$08,$F8

Crumble1Y:
db $F0,$00,$FC

Crumble2Y:
db $F8,$00,$00

Crumble3Y:
db $00,$00,$00



SUB_GFX:            JSL $20CA4F       	;Get all the drawing info, duh
					LDA !Direction,x
					STA $09
					LDA !FrameNum,x
					PHX
					TAX
					LDA TileNums,x
					STA $02
					TXA
					ASL
					TAX
					REP #$20
					LDA TilePointers,x
					STA $03
					LDA XOffPointers,x
					STA $05
					LDA YOffPointers,x
					STA $07
					SEP #$20
					LDX $02
					.GFXLoop
					
					LDA $09
					BEQ +
					LDA $00
					PHY
					TXY
					CLC
					ADC ($05),y
					PLY
					BRA ++
					+
					LDA $00
					PHY
					TXY
					SEC
					SBC ($05),y
					PLY
					++
					STA $0300,y
					
					LDA $01
					PHY
					TXY
					CLC
					ADC ($07),y
					PLY
					STA $0301,y
					
					PHY
					TXY
					LDA ($03),y
					PLY
					STA $0302,y
					PHX
					LDX $15E9
					LDA $15F6,x
					PLX
					ORA $64
					PHX
					LDX $09
					BNE +
					ORA #$40
					+
					PLX
					STA $0303,y
					INY
					INY
					INY
					INY
					DEX
					BPL .GFXLoop
					PLX
					LDA $02
					LDY #$02
					JSL $01B7B3					;/and then draw em
					EndIt:
					RTS
					
					
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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
                    AND #$01
                    ORA $03
                    STA $01
                    TAY
                    LDA $1A
                    CLC
                    ADC SPR_T14,y
                    ROL $00
                    CMP $E4,x
                    PHP
                    LDA $1B
                    LSR $00
                    ADC SPR_T15,y
                    PLP
                    SBC $14E0,x
                    STA $00
                    LSR $01
                    BCC SPR_L31
                    EOR #$80
                    STA $00
SPR_L31:             LDA $00
                    BPL RETURN_35
ERASE_SPRITE:        LDA $14C8,x             ; \ if sprite status < 8, permanently erase sprite
                    CMP #$08                ; |
                    BCC KILL_SPRITE         ; /    
                    LDY $161A,x
                    CPY #$FF
                    BEQ KILL_SPRITE
                    LDA #$00
                    STA $1938,y
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
                    LSR A
                    AND #$01
                    STA $01
                    TAY
                    LDA $1C
                    CLC
                    ADC SPR_T12,y
                    ROL $00
                    CMP $D8,x
                    PHP
                    LDA.w $001D 
                    LSR $00
                    ADC SPR_T13,y
                    PLP
                    SBC $14D4,x
                    STA $00
                    LDY $01
                    BEQ SPR_L38
                    EOR #$80
                    STA $00
SPR_L38:             
					LDA $00
                    BPL RETURN_35
                    BMI ERASE_SPRITE

SUB_IS_OFF_SCREEN:   LDA $15A0,x             ; \ if sprite is on screen, accumulator = 0 
                    ORA $186C,x             ; |  
                    RTS                     ; / return

