;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Bowser Jr., by dahnamics
;;
;; Credit: mikeyk (Shy Guy), Yoshicookiezeus (Thwomp boss v. 2.0), Schwa (sledge_ex)
;;
;; Description: This sprite is loosely based on Bowser Jr. from NSMB.  He cannot be jumped on
;;		until Mario throws a shell at him.  Just like his form in 4-Tower, 6-Tower2, 7-Tower
;;		and the towers in World 8, he throws a shell at Mario and Mario throws the shell back 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Shy Guy, by mikeyk
;;
;; Description: A Shy Guy with many available configurations.
;;
;; Note: When rideable, clipping tables values should be: 03 0A FE 0E
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Uses first extra bit: NO
;;
;; Extra Property Byte 1
;;    bit 0 - enable spin killing
;;    bit 1 - stay on ledges
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	SPRITE_Y_SPEED  = $AA
	SPRITE_X_SPEED  = $B6
	SPRITE_Y_POS    = $D8
	ORIG_Y_POS	= $151C
	H_OFFSCREEN     = $15A0
	V_OFFSCREEN     = $186C
	FREEZE_TIMER    = $1540
	SMASH_STATUS	= $1602
	STATE_TIMER 	= $163E
	RAM_ThrowTimer	= $1504	
	SPR_OBJ_STATUS	= $1588
	EXTRA_BITS	= $7FAB10
	EXTRA_PROP_1	= $7FAB28
	GetSpriteClippingA = $03B69F
	CheckForContact = $03B72B
	GetSpriteClippingB	= $03B6E5	
	ShowSprContactGfx = $01AB72
	Invuln_Timer	= $1564		; The RAM address for Clawgrip's stun duration
	MAX_Y_SPEED     = $3E
	MAX_Y_SPEED2     = $C2 
; definitions of bits (don't change these)
	IS_ON_GROUND    = $04
	IS_ON_CEILING	= $08
	TIME_ON_GROUND	= $A0
	TIME_TO_SHAKE	= $40
	RISE_SPEED	= $C0
	SOUND_EFFECT	= $09 
	SPRITE_GRAVITY 	= $20
	SPRITE_GRAVITY2 = $04
	TIME_TO_EXPLODE = $00
	X_SPEED		dcb $08,$F8,$10,$F0
	X_SPEED2	dcb $20,$E0
	HURT_SPEED	dcb $20,$E0
	KILLED_X_SPEED	dcb $F0,$10
	SPRITE_STATE    = $C2
	HIT_POINTS = $05        	; being stomped by Mario
	SPHERE = $6F
PROPFLASH:
	dcb $04,$06,$08,$0C,$04,$06,$08,$0C
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite init JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		dcb "INIT"
		LDA SPRITE_Y_POS,x  
		STA ORIG_Y_POS,x
		LDA $E4,x  
		CLC        
		ADC #$08   
		STA $E4,x  
		TXA
		AND #$03
		ASL A
		ASL A
		ASL A
		ASL A
		ASL A                   
		STA STATE_TIMER,x
		CLC
		ADC #$32
		STA RAM_ThrowTimer,x                 
		PHY
		JSR SUB_HORZ_POS
		TYA
		STA $157C,x
		PLY
		LDA $1588,x             ; if on the ground, reset the turn counter
		ORA #$04
		STA $1588,x             ; if on the ground, reset the turn counter
		RTL                 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite code JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		dcb "MAIN"                                    
		PHB                     ; \
		PHK                     ;  | main sprite function, just calls local subroutine
		PLB                     ;  |
		JSR SPRITE_CODE_START   ;  |
		PLB                     ;  |
		RTL                     ; /
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite main code 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RETURN		RTS
SPRITE_CODE_START
		JSR SUB_GFX       ; graphics routine
		LDA $14C8,x             ; return if sprite status != 8
		CMP #$08                ; \ if status != 8, return
		BNE RETURN              ; /
		LDA $9D                 ; \ if sprites locked, return
		BNE RETURN              ; /
		JSR SUB_OFF_SCREEN_X3   ; handle off screen situation
DONE_WITH_SPEED
		JSL $018032             ; interact with sprites
		LDA $1528,x             ; \ if sprite hit counter == 3
		CMP #HIT_POINTS         ;  |   
		BEQ NO_CONTACT        ; /
		JSR HIT_ROUTINE
MARIO_INTERACT	JSL $01A7DC		; interact with mario 
		BCC NO_CONTACT          ; return if no contact
		LDA $154C,x             ; \ if sprite invincibility timer > 0 ...
		BNE NO_CONTACT          ; /    ... goto NO_CONTACT
		LDA #$08                ; \ sprite invincibility timer = $08
		STA $154C,x             ; /
		LDA $7D                 ; \  if Mario's y speed < 10 ...
		CMP #$10                ;  }   ... sprite will DEAD Mario
		BMI SPRITE_WINS         ; /    
		LDA SPRITE_STATE,x	; return if sprite is invulnerable
		CMP #$05
		BNE SPRITE_WINS
MARIO_WINS		
		JSR SUB_STOMP_PTS       ; give Mario points
		JSL $01AA33             ; set Mario speed
		JSL $01AB99             ; display contact graphic
		LDA #$28                ; \ sound effect
		STA $1DFC               ; /
		LDA #$A0		    ; \ Set stunned timer
		STA $1564,x             ; /
		INC $1528,x             ; increment sprite hit counter
		LDA $1528,x             ; \ if sprite hit counter == 3
		CMP #HIT_POINTS         ;  |   
		BNE SMUSH_SPRITE        ; /		
SMUSH_SPRITE	LDA #$0C                ; \ time to show semi-squashed sprite = $0C
		STA $1FE2,x             ; /
		LDA $1528,x             ; \ if sprite hit counter == 3
		CMP #HIT_POINTS         ;  |   
		BEQ SPRITE_DEAD		; /
			
		LDA #$04
		STA SPRITE_STATE,x
		BRA NEW_RETURN
SPRITE_DEAD	LDA #$06
		STA SPRITE_STATE,x
			
NEW_RETURN	RTS                     ; return
SPRITE_WINS         
		LDA $1497               ; \ if Mario is invincible...
		ORA $187A               ;  }  ... or Mario on yoshi...
		BNE NO_CONTACT          ; /   ... return
		JSR SUB_HORZ_POS        ; \  set new sprite direction
		TYA                     ;  }  
		STA $157C,x             ; /
		JSL $00F5B7             ; hurt Mario
NO_CONTACT	LDA SPRITE_STATE,x     
		CMP #$01
		BEQ WALKING0
		CMP #$02
		BEQ FURIOUS0		
		CMP #$03
		BEQ THROWING0
		CMP #$04
		BEQ HURT0
		CMP #$05
		BEQ STUNNED0
		CMP #$06
		BEQ DEAD0
		CMP #$07
		BEQ EXITING0
;-----------------------------------------------------------------------------------------
; state 0
;-----------------------------------------------------------------------------------------
WAITING            
		LDA V_OFFSCREEN,x       ;fall if offscreen vertically
		BNE SET_WALKING
    
		LDA H_OFFSCREEN,x       ;return if offscreen horizontally
		BNE RETURN0
		JSR SUB_HORZ_POS        ;determine if mario is close and act accordingly
		TYA        
		STA $157C,x
		LDA $1588,x             ; \ if sprite is in contact with an object...
		AND #$03                ;  |
		BEQ NO_OBJ_CONTACT0     ;  |
		LDA $157C,x             ;  | flip the direction status
		EOR #$01                ;  |
		STA $157C,x             ; /
NO_OBJ_CONTACT0      
		LDA $1588,x             ; run the subroutine if the sprite is in the air...
		ORA $151C,x             ; ...and not already turning
		BNE ON_GROUND0           ;
		JSR SUB_CHANGE_DIR      ;
		LDA #$01                ; set that we're already turning
		STA $151C,x             ;
ON_GROUND0
		LDA $1588,x             ; if on the ground, reset the turn counter
		AND #$04
		BEQ RETURN0
		STZ $151C,x
		STZ $AA,x
		BRA X_TIME0
                    
FALLING0
		LDA $1588,x             ; if on the ground, reset the turn counter
		AND #$04
		BEQ RETURN0
		LDA #$10                ; \  y speed = 10
		STA $AA,x               ; /
                                        
X_TIME0		STZ $B6,x
		BCS RETURN0
		LDA $0F    
		CLC        
		ADC #$40   
		CMP #$80                
		BCS THWOMP_4
THWOMP_4
		LDA $0F
		CLC
		ADC #$24    
		CMP #$50    
		BCS RETURN0
SET_WALKING
		INC SPRITE_STATE,x          ;chage state to falling
WALKING0	BRA WALKING
RETURN0		JSL $01802A		; update position based on speed values
		RTS                     
THROWING0	JMP THROWING
FURIOUS0	JMP FURIOUS
HURT0		JMP HURT
STUNNED0	JMP STUNNED
DEAD0		JMP DEAD
EXITING0	JMP EXITING
;-----------------------------------------------------------------------------------------
; state 1
;-----------------------------------------------------------------------------------------
WALKING
		LDA #$00		; If timer isn't C0..
		CMP $1534,x		; 
		JSR SUB_HORZ_POS        ;determine if mario is close and act accordingly
		TYA        
		STA $157C,x
		LDA $1588,x             ; \ if sprite is in contact with an object...
		AND #$03                ;  |
		BEQ NO_OBJ_CONTACT      ;  |
		LDA $157C,x             ;  | flip the direction status
		EOR #$01                ;  |
		STA $157C,x             ; /
NO_OBJ_CONTACT      
		LDA $1588,x             ; run the subroutine if the sprite is in the air...
		ORA $151C,x             ; ...and not already turning
		BNE ON_GROUND           ;
		JSR SUB_CHANGE_DIR      ;
		LDA #$01                ; set that we're already turning
		STA $151C,x             ;
ON_GROUND	LDA $1588,x             ; if on the ground, reset the turn counter
		AND #$04
		BEQ IN_AIR
		STZ $151C,x
		STZ $AA,x
		BRA X_TIME
                    
FALLING		LDA $1588,x             ; if on the ground, reset the turn counter
		AND #$04
		BEQ IN_AIR
		LDA #$10                ; \  y speed = 10
		STA $AA,x               ; /
                                        
X_TIME		LDA $1528,x             ; \ set x speed based on total HP
		ASL
		CLC
		ADC $157C,x		; and direction
		TAY
		LDA X_SPEED,y           ;  |
		STA $B6,x               ; /
CONTINUE2	LDA STATE_TIMER,x
		CMP #$28                ; |   just go to normal walking code
		BCS RETURN0          ; /
                    
		LDA Invuln_Timer,x
		CMP #$00
		BNE RETURN0
		LDA STATE_TIMER,x
		CMP #$21
		BNE NO_JUMP2
		LDA $1570,x
		LSR A
		AND #01
		BEQ NO_JUMP2
		STZ STATE_TIMER,x					; x speed = 0                  
		BRA RETURN2
NO_JUMP2	CMP #$00
		BNE RETURN2
SET_FALLING	STZ SPRITE_X_SPEED,x
		LDA #$03
		STA SPRITE_STATE,x
		LDA #$00     
		STA SPRITE_Y_SPEED,x	;set initial speed
IN_AIR		JSL $01802A             ; update position based on speed values
RETURN2		RTS	
;-----------------------------------------------------------------------------------------
; state 2
;-----------------------------------------------------------------------------------------
FURIOUS
		LDA $1588,x		; \ if sprite is in contact with an object...
		AND #$03		;  |
		BEQ NO_OBJ_CONTACT2	;  |
		LDA $157C,x		;  | flip the direction status
		EOR #$01		;  |
		STA $157C,x		; /
NO_OBJ_CONTACT2
		LDA $1588,x		; run the subroutine if the sprite is in the air...
		ORA $151C,x		; ...and not already turning
		BNE X_TIME2		;
		JSR SUB_CHANGE_DIR	;
		LDA #$01		; set that we're already turning
		STA $151C,x		;
                                        
X_TIME2		LDY $157C,x		; \ set x speed based on direction
		LDA X_SPEED2,y		;  |
		STA $B6,x		; /
		JSR Hop		; Jump to custom code
IN_AIR2		JSL $01802A             ; update position based on speed values
Hop:
        LDA #$C0		; If timer isn't C0..
        CMP $1504,x		; 
        BNE IncreaseHop	; Increase it.
        LDA $1588,x		; Don't jump if already on ground.
        AND #$04		; 
        BEQ RETURN4	; 
	JSR SUB_HAMMER_THROW2
        LDA #$C0		; Set jump height.
        STA $AA,x		; Store it too. 
        STZ $1504,x		; Reset timer.
        RTS		; Return
IncreaseHop:
        INC $1504,x		; Increase timer.
RETURN4		RTS	
;-----------------------------------------------------------------------------------------
; state 3
;-----------------------------------------------------------------------------------------
THROWING	LDA #$00     
		STA SPRITE_Y_SPEED,x	;set initial speed
		JSL $01801A		;apply speed
			
		LDA SPRITE_Y_SPEED,x	;increase speed if below the max
		CMP #MAX_Y_SPEED
		BCS DONT_INC_SPEED
		ADC #SPRITE_GRAVITY2
		STA SPRITE_Y_SPEED,x    
DONT_INC_SPEED
		JSL $019138		;interact with objects
		
		LDA $1564,x	; return if sprite is invulnerable
		CMP #$00
		BNE RETURN67
		JSR SUB_HAMMER_THROW
		LDA #$F0		; set the time of flight to F0
		STA STATE_TIMER,x
			
		LDA #$01		
		STA SPRITE_STATE,x	
		STZ SMASH_STATUS,x
RETURN67	RTS     	 
;-----------------------------------------------------------------------------------------
; state 4
;-----------------------------------------------------------------------------------------
HURT		LDA $1588,x             ; \ if sprite is in contact with an object...
		AND #$03                ;  |
		BEQ NO_OBJ_CONTACT1      ;  |
		LDA $157C,x             ;  | flip the direction status
		EOR #$01                ;  |
		STA $157C,x             ; /
NO_OBJ_CONTACT1
		LDY $157C,x             ; \ set x speed based on direction
		LDA HURT_SPEED,y           ;  |
		STA $B6,x 
		
		LDA $1564,x	; return if sprite is invulnerable
		CMP #$00
		BNE RETURN68
		LDA $1528,x
		CMP #$02
		BCC ATTACK1
		
		LDA #$02
		STA SPRITE_STATE,x	
		BRA RETURN68
ATTACK1
		LDA #$01		
		STA SPRITE_STATE,x	
RETURN68	JSL $01802A		;apply speed
		RTS     	    	 
;-----------------------------------------------------------------------------------------
; state 5
;-----------------------------------------------------------------------------------------
STUNNED		LDA $1588,x             ; \ if sprite is in contact with an object...
		AND #$03                ;  |
		BEQ NO_OBJ_CONTACT3      ;  |
		LDA $157C,x             ;  | flip the direction status
		EOR #$01                ;  |
		STA $157C,x             ; /
NO_OBJ_CONTACT3
		STZ $B6,x
	
Hop3:
		LDA #$C0		; If timer isn't C0..
		CMP $1534,x		; 
		BNE IncreaseHop3	; Increase it.
		STZ $1534,x		; Reset timer.
		LDA #$01
		STA SPRITE_STATE,x	
		RTS			; Return
IncreaseHop3:
		INC $1534,x		; Increase timer.
RETURN65	JSL $01802A		;apply speed
		RTS     	    	 
;-----------------------------------------------------------------------------------------
; state 6
;-----------------------------------------------------------------------------------------
DEAD		LDA FREEZE_TIMER,x
		BNE RETURN10
		STZ SPRITE_X_SPEED,x
		LDA $0F30
		BNE RETURN10
		LDA $0F33
		AND $01
		BNE RETURN10
		INC SMASH_STATUS,X
		LDA SMASH_STATUS,x
		CMP #$02
		BNE RETURN10
		INC SPRITE_STATE,x	;chage state to falling
RETURN10	RTS	
;-----------------------------------------------------------------------------------------
; state 7
;-----------------------------------------------------------------------------------------
EXITING
		LDA V_OFFSCREEN,x       ;fall if offscreen vertically
		BNE GOAL
    
		LDA H_OFFSCREEN,x       ;return if offscreen horizontally
		BNE RETURN1
		JSL $01801A             ;apply speed
                    
		LDA SPRITE_Y_SPEED,x    ;increase speed if below the max
		CMP #MAX_Y_SPEED2
		BMI DONT_INC_SPEED2
		SEC
		SBC #SPRITE_GRAVITY2
		STA SPRITE_Y_SPEED,x    
DONT_INC_SPEED2
		JSL $019138             ;interact with objects
                    
		LDA SPR_OBJ_STATUS,x    ;return if not on the ceiling
		AND #IS_ON_CEILING
		BEQ RETURN1
                    
		JSR SUB_9A04            ; ?? speed related
                    
		LDA #TIME_TO_SHAKE      ;shake ground
		STA $1887    
                    
		LDA #TIME_ON_GROUND     ;set time to stay on ground
		STA FREEZE_TIMER,x  
		
RETURN1		RTS                     
GOAL    STZ $14C8,x
	DEC $13C6               ; prevent Mario from walking at the level end
	LDA #$FF                ; \ set goal
	STA $1493               ; /
	LDA #$0B                ; \ set ending music
	STA $1DFB               ; /
        RTS                     ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; hammer routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X_OFFSET            dcb $F9,$07
X_OFFSET2           dcb $FF,$00
X_THROW_SPEED       dcb $18,$E8
RETURN21            RTS     
SUB_HAMMER_THROW    LDA $15A0,x             ; \ no egg if off screen
                    ORA $186C,x             ;  |
                    ORA $15D0,x
                    BNE RETURN21
                    
                    JSL $02A9DE             ; \ get an index to an unused sprite slot, return if all slots full
                    BMI RETURN21            ; / after: Y has index of sprite being generated
                    LDA #$0A                ; \ set sprite status for new sprite
                    STA $14C8,y             ; /
                    LDA #$04
                    STA $9E,y
                    PHY                     ; set x position for new sprite
                    LDA $157C,x
                    TAY
                    LDA $E4,x               
                    CLC
                    ADC X_OFFSET,y
                    PLY
                    STA $00E4,y
    
                    PHY                     ; set x position for new sprite
                    LDA $157C,x
                    TAY
                    LDA $14E0,x             
                    ADC X_OFFSET2,y
                    PLY
                    STA $14E0,y      
                    LDA $D8,x               ; \ set y position for new sprite
                    SEC                     ;  | (y position of generator - 1)
                    SBC #$0E                ;  |
                    STA $00D8,y             ;  |
                    LDA $14D4,x             ;  |
                    SBC #$00                ;  |
                    STA $14D4,y             ; /
                    PHX                     ; \ before: X must have index of sprite being generated
                    TYX                     ;  | routine clears *all* old sprite values...
                    JSL $07F7D2             ;  | ...and loads in new values for the 6 main sprite tables
                    PLX                     ; / 
                    PHY                   
                    LDA $157C,x
                    TAY
                    LDA X_THROW_SPEED,y
                    PLY
                    STA $B6,y
                    
                    LDA #$C0
                    STA $AA,y     
                    
RETURN20            RTS                     ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; hammer routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
X_OFFSET3	dcb $F9,$07
X_OFFSET4	dcb $FF,$00
X_THROW_SPEED2	dcb $30,$D0
RETURN58	RTS     
SUB_HAMMER_THROW2
		LDA $15A0,x             ; \ no egg if off screen
		ORA $186C,x             ;  |
		ORA $15D0,x
		BNE RETURN58
		JSL $02A9DE             ; \ get an index to an unused sprite slot, return if all slots full
		BMI RETURN58            ; / after: Y has index of sprite being generated
		LDA #$0A                ; \ set sprite status for new sprite
		STA $14C8,y             ; /
		LDA #$04
		STA $9E,y
		PHY                     ; set x position for new sprite
		LDA $157C,x
		TAY
		LDA $E4,x               
		CLC
		ADC X_OFFSET3,y
		PLY
		STA $00E4,y
		PHY                     ; set x position for new sprite
		LDA $157C,x
		TAY
		LDA $14E0,x             
		ADC X_OFFSET4,y
		PLY
		STA $14E0,y      
		LDA $D8,x               ; \ set y position for new sprite
		SEC                     ;  | (y position of generator - 1)
		SBC #$0E                ;  |
		STA $00D8,y             ;  |
		LDA $14D4,x             ;  |
		SBC #$00                ;  |
		STA $14D4,y             ; /
		PHX                     ; \ before: X must have index of sprite being generated
		TYX                     ;  | routine clears *all* old sprite values...
		JSL $07F7D2             ;  | ...and loads in new values for the 6 main sprite tables
		PLX                     ; / 
		PHY                   
		LDA $157C,x
		TAY
		LDA X_THROW_SPEED2,y
		PLY
		STA $B6,y
		LDA #$C0
		STA $AA,y 
		LDA #TIME_TO_EXPLODE
		STA $1540,y         
RETURN57	RTS                     ; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Be killed by shells
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HIT_ROUTINE:
	
HITPOINTS:
		;TXA			; \ Process every 4 frames 
		;EOR $13			; | 
		;AND #$03		; | 
		;BNE RETURN_BOB		; /
		LDY #$09		; \ Loop over sprites: 
KILLED_X_SPEED:
	dcb $FF,$00
	
SpriteInteract:
	ldy #$0b
InteractLoop:	
	lda $14c8,y
	cmp #$09
	bcs ProcessSprite
NextSprite:	
	dey
	bpl InteractLoop
	rts
ProcessSprite:
	PHX                       
        TYX                       
        JSL GetSpriteClippingB  
        PLX                       
        JSL GetSpriteClippingA  
        JSL CheckForContact
	bcc NextSprite
	PHX
	TYX
	
	JSL ShowSprContactGfx
	LDA #$02		    ; \ Kill thrown sprite
	STA $14C8,x             ; /
	LDA #$D0                ; \ Set killed Y speed
	STA $AA,x               ; /
	LDY #$00		    ; Set killed X speed
	LDA $B6,x
	BPL SET_SPEED
	INY 
SET_SPEED
	LDA KILLED_X_SPEED,y
	STA $B6,x
	PLX
HandleBirdoHit:	
	LDA #$13                ; \ sound effect
	STA $1DF9               ; /
	LDA SPRITE_STATE,x		; If jumping up
	CMP #$03
	BCS Return3
SHELL_CONTACT
	LDA #$05		
	STA SPRITE_STATE,x
Return3:
	rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PROPERTIES: dcb $7F,$3F
;The tables must now have 16 bytes.
;THE LAST 8 ARE ONLY CREATED BECAUSE OF XDISP.
;0-4 BYTE   - FRAME 1 RIGHT
;4-8 BYTE   - FRAME 2 RIGHT
;8-12 BYTE  - FRAME 1 LEFT
;12-16 BYTE - FRAME 2 LEFT
TILEMAP:
	dcb $00,$02,$20,$22 ; WALKING 1	;\ RIGHT
	dcb $04,$06,$24,$26 ; WALKING 2	;/ RIGHT
	dcb $00,$02,$20,$22 ; WAITING 1	;\ RIGHT
	dcb $84,$86,$A4,$A6 ; WAITING 2	;/ RIGHT
	dcb $40,$42,$60,$62 ; RETREAT 1	;\ RIGHT
	dcb $44,$46,$64,$66 ; RETREAT 2	;/ RIGHT
	dcb $08,$0A,$28,$2A ; THROW 1	;\ RIGHT
	dcb $0C,$0E,$2C,$2E ; THROW 2	;/ RIGHT
	dcb $80,$82,$A0,$A2 ; LEAPING 1	;\ RIGHT
	dcb $80,$82,$A0,$A2 ; LEAPING 2	;/ RIGHT
	dcb $8C,$8E,$AC,$AE ; STUNNED 1	;\ RIGHT
	dcb $C0,$C2,$E0,$E2 ; STUNNED 2	;/ RIGHT
	dcb $48,$4A,$68,$6A ; DYING 1	;\ RIGHT
	dcb $48,$4A,$68,$6A ; DYING 2	;/ RIGHT
	dcb $00,$02,$20,$22 ; WALKING 1	;\ LEFT
	dcb $04,$06,$24,$26 ; WALKING 2	;/ LEFT
	dcb $00,$02,$20,$22 ; WAITING 1	;\ LEFT
	dcb $84,$86,$A4,$A6 ; WAITING 2	;/ LEFT
	dcb $40,$42,$60,$62 ; RETREAT 1	;\ LEFT
	dcb $44,$46,$64,$66 ; RETREAT 2	;/ LEFT
	dcb $08,$0A,$28,$2A ; THROW 1	;\ LEFT
	dcb $0C,$0E,$2C,$2E ; THROW 2	;/ LEFT
	dcb $80,$82,$A0,$A2 ; LEAPING 1	;\ LEFT
	dcb $80,$82,$A0,$A2 ; LEAPING 2	;/ LEFT
	dcb $8C,$8E,$AC,$AE ; STUNNED 1	;\ LEFT
	dcb $C0,$C2,$E0,$E2 ; STUNNED 2	;/ LEFT
	dcb $48,$4A,$68,$6A ; DYING 1	;\ LEFT
	dcb $48,$4A,$68,$6A ; DYING 2	;/ LEFT
YDISP: 	
	dcb $F0,$F0,$00,$00 ; WALKING 1	;\ RIGHT
	dcb $F0,$F0,$00,$00 ; WALKING 2	;/ RIGHT
	dcb $F0,$F0,$00,$00 ; WAITING 1	;\ RIGHT
	dcb $F0,$F0,$00,$00 ; WAITING 2	;/ RIGHT
	dcb $F0,$F0,$00,$00 ; RETREAT 1	;\ RIGHT
	dcb $F0,$F0,$00,$00 ; RETREAT 2	;/ RIGHT
	dcb $F0,$F0,$00,$00 ; THROW 1	;\ RIGHT
	dcb $F0,$F0,$00,$00 ; THROW 2	;/ RIGHT
	dcb $F0,$F0,$00,$00 ; LEAPING 1	;\ RIGHT
	dcb $F0,$F0,$00,$00 ; LEAPING 2	;/ RIGHT
	dcb $F0,$F0,$00,$00 ; STUNNED 1	;\ RIGHT
	dcb $F0,$F0,$00,$00 ; STUNNED 2	;/ RIGHT
	dcb $F0,$F0,$00,$00 ; DYING 1	;\ RIGHT
	dcb $F0,$F0,$00,$00 ; DYING 2	;/ RIGHT
	dcb $F0,$F0,$00,$00 ; WALKING 1	;\ LEFT
	dcb $F0,$F0,$00,$00 ; WALKING 2	;/ LEFT
	dcb $F0,$F0,$00,$00 ; WAITING 1	;\ LEFT
	dcb $F0,$F0,$00,$00 ; WAITING 2	;/ LEFT
	dcb $F0,$F0,$00,$00 ; RETREAT 1	;\ LEFT
	dcb $F0,$F0,$00,$00 ; RETREAT 2	;/ LEFT
	dcb $F0,$F0,$00,$00 ; THROW 1	;\ LEFT
	dcb $F0,$F0,$00,$00 ; THROW 2	;/ LEFT
	dcb $F0,$F0,$00,$00 ; LEAPING 1	;\ LEFT
	dcb $F0,$F0,$00,$00 ; LEAPING 2	;/ LEFT
	dcb $F0,$F0,$00,$00 ; STUNNED 1	;\ LEFT
	dcb $F0,$F0,$00,$00 ; STUNNED 2	;/ LEFT
	dcb $F0,$F0,$00,$00 ; DYING 1	;\ LEFT
	dcb $F0,$F0,$00,$00 ; DYING 2	;/ LEFT
XDISP: 	
	dcb $00,$10,$00,$10 ; WALKING 1	;\ RIGHT
	dcb $00,$10,$00,$10 ; WALKING 2	;/ RIGHT
	dcb $00,$10,$00,$10 ; WALKING 1	;\ RIGHT
	dcb $00,$10,$00,$10 ; WALKING 2	;/ RIGHT
	dcb $00,$10,$00,$10 ; RETREAT 1	;\ RIGHT
	dcb $00,$10,$00,$10 ; RETREAT 2	;/ RIGHT
	dcb $00,$10,$00,$10 ; THROW 1	;\ RIGHT
	dcb $00,$10,$00,$10 ; THROW 2	;/ RIGHT
	dcb $00,$10,$00,$10 ; LEAPING 1	;\ RIGHT
	dcb $00,$10,$00,$10 ; LEAPING 2	;/ RIGHT
	dcb $00,$10,$00,$10 ; STUNNED 1	;\ RIGHT
	dcb $00,$10,$00,$10 ; STUNNED 2	;/ RIGHT
	dcb $00,$10,$00,$10 ; DYING 1	;\ RIGHT
	dcb $00,$10,$00,$10 ; DYING 2	;/ RIGHT
	dcb $10,$00,$10,$00 ; WALKING 1	;\ LEFT
	dcb $10,$00,$10,$00 ; WALKING 2	;/ LEFT
	dcb $10,$00,$10,$00 ; WALKING 1	;\ LEFT
	dcb $10,$00,$10,$00 ; WALKING 2	;/ LEFT
	dcb $10,$00,$10,$00 ; RETREAT 1	;\ LEFT
	dcb $10,$00,$10,$00 ; RETREAT 2	;/ LEFT
	dcb $10,$00,$10,$00 ; THROW 1	;\ LEFT
	dcb $10,$00,$10,$00 ; THROW 2	;/ LEFT
	dcb $10,$00,$10,$00 ; LEAPING 1	;\ LEFT
	dcb $10,$00,$10,$00 ; LEAPING 2	;/ LEFT
	dcb $10,$00,$10,$00 ; STUNNED 1	;\ LEFT
	dcb $10,$00,$10,$00 ; STUNNED 2	;/ LEFT
	dcb $10,$00,$10,$00 ; DYING 1	;\ LEFT
	dcb $10,$00,$10,$00 ; DYING 2	;/ LEFT
SUB_GFX:
	JSR GET_DRAW_INFO
	LDA $1602,x
	STA $03                 ; | $03 = index to frame start (0 or 4) 
	LDA $14			;\ Frame counter ..
	LSR A			; |
	LSR A			; | Add in frame animation rate; More LSRs for slower animation.
	LSR A			; |
	AND #$01		; | 01 means we animate between 2 frames (00 and 01).
	ASL A 			; | 
	ASL A			; | ASL x2 (0-4) makes it switch between the first byte and fifth byte,
	STA $03 		;/ i.e. first animation and second animation. The result is stored into $03.
	LDA SPRITE_STATE,x		; If jumping up
	CMP #$06
	BNE NOT_DEAD
	LDA $03
	CLC
	ADC #$30                ;    ...set killed frame
        STA $03			
        LDA $15F6,x				; \
        ORA #$80				; | ...flip vertically
        STA $15F6,x				; /
        BRA DONE_WALKING
NOT_DEAD:
	LDA SPRITE_STATE,x		; if retreating into shell
	CMP #$04
	BNE KNOCKED_BACK			; |
	LDA $03					; |
	CLC						; |
	ADC #$10				; | ...use stun frames.
	STA $03					; /
	BRA DONE_WALKING
KNOCKED_BACK:
	LDA SPRITE_STATE,x		; if retreating into shell
	CMP #$05
	BNE YELLING				; |
	LDA $03					; |
	CLC						; |
	ADC #$28				; | ...use stun frames.
	STA $03					; /
	BRA DONE_WALKING
YELLING:
	LDA SPRITE_STATE,x		; if yelling at Mario
	CMP #$00
	BNE JUMPING				; |
	LDA $03					; |
	CLC						; |
	ADC #$08				; | ...use stun frames.
	STA $03					; /
	BRA DONE_WALKING
JUMPING:
	LDA SPRITE_STATE,x		; if exiting the level
	CMP #$07
	BNE IN_THE_AIR				; |
	LDA $03					; |
	CLC						; |
	ADC #$20				; | ...use stun frames.
	STA $03					; /
	BRA DONE_WALKING
IN_THE_AIR:
	LDA SPR_OBJ_STATUS,x	;return if on the ground
	CMP #$04				; |
	BEQ THROWING_SHELL			; |
	LDA $03					; |
	CLC						; |
	ADC #$20				; | ...use stun frames.
	STA $03					; /
	BRA DONE_WALKING
THROWING_SHELL:
	LDA SPRITE_STATE,x		; If throwing shell
	CMP #$03
	BNE DONE_WALKING				; |
	LDA $03					; |
	CLC						; |
	ADC #$18				; | ...use stun frames.
	STA $03					; /
;	BRA DONE_WALKING
DONE_WALKING:
	LDA $157C,x
	STA $02			; Store direction to $02 for use with property routine later.
	BNE NoAdd
	LDA $03			;\
	CLC			; | If sprite faces left ..
	ADC #$38		; | Adding 16 more bytes to the table.
	STA $03			;/ So we can invert XDISP to not mess up the sprite's appearance.
NoAdd:
	PHX			;\ Push sprite index ..
	LDX #$03		;/ And load X with number of tiles to loop through.
Loop:
	PHX			; Push number of tiles to loop through.
	TXA			;\
	ORA $03			;/ Transfer it to X and add in the "left displacement" if necessary.
	TAX			;\ Get it back into X for an index.
	LDA $00			;\
	CLC			; | Apply X displacement of the sprite.
	ADC XDISP,x		; |
	STA $0300,y		;/ 
	LDA $01			;\
	CLC			; | Y displacement is added for the Y position, so one tile is higher than the other.
	ADC YDISP,x		; | Otherwise, both tiles would have been drawn to the same position!
	STA $0301,y		; | If X is 00, i.e. first tile, then load the first value from the table and apply that
				;/ as the displacement. For the second tile, F0 is added to make it higher than the first.
	LDA TILEMAP,x
	STA $0302,y
	PHX			; Push number of times to go through loop + "left" displacement if necessary.
	LDX $02			;\
	LDA PROPERTIES,x	; | Set properties based on direction.
	STA $0303,y		;/
	PLX			; Pull number of times to go through loop.
	INY			;\
	INY			; | The OAM is 8x8, but our sprite is 16x16 ..
	INY			; | So increment it 4 times.
	INY			;/
		
	PLX			; Pull current tile back.
	DEX			; After drawing this tile, decrease number of tiles to go through loop. If the second tile
				; is drawn, then loop again to draw the first tile.
	BPL Loop		; Loop until X becomes negative (FF).
	
	PLX			; Pull back the sprite index! We pushed it at the beginning of the routine.
	LDY #$02		; Y ends with the tile size .. 02 means it's 16x16
	LDA #$03		; A -> number of tiles drawn - 1.
				; I drew 2 tiles, so 2-1 = 1. A = 01.
	JSL $01B7B3		; Call the routine that draws the sprite.
	RTS			; Never forget this!       
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_CHANGE_DIR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    ;org $019098
SUB_CHANGE_DIR      ;LDA $15AC,x
                    ;BNE LABEL41
                    ;LDA #$08   
                    ;STA $15AC,x
                    LDA $B6,x  
                    EOR #$FF   
                    INC A      
                    STA $B6,x  
                    LDA $157C,x
                    EOR #$01   
                    STA $157C,x
LABEL41             RTS        
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; speed related
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    
SUB_9A04            LDA SPR_OBJ_STATUS,x
                    BMI THWOMP_1
                    LDA #$00                
                    LDY $15B8,x
                    BEQ THWOMP_2
THWOMP_1            LDA #$18
THWOMP_2            STA SPRITE_Y_SPEED,x  
                    RTS       
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routines below can be shared by all sprites.  they are ripped from original
; SMW and poorly documented
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; points routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STAR_SOUNDS         dcb $00,$13,$14,$15,$16,$17,$18,$19
SUB_STOMP_PTS       PHY                     ; 
                    LDA $1697               ; \
                    CLC                     ;  | 
                    ADC $1626,x             ; / some enemies give higher pts/1ups quicker??
                    INC $1697               ; increase consecutive enemies stomped
                    TAY                     ;
                    INY                     ;
                    CPY #$08                ; \ if consecutive enemies stomped >= 8 ...
                    BCS NO_SOUND            ; /    ... don't play sound 
                    LDA STAR_SOUNDS,y       ; \ play sound effect
                    STA $1DF9               ; /   
NO_SOUND            TYA                     ; \
                    CMP #$08                ;  | if consecutive enemies stomped >= 8, reset to 8
                    BCC NO_RESET            ;  |
                    LDA #$08                ; /
NO_RESET            JSL $02ACE5             ; give mario points
                    PLY                     ;
                    RTS                     ; return
                
                    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B760 - graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    ;org $03B75C
TABLE1              dcb $0C,$1C
TABLE2              dcb $01,$02
GET_DRAW_INFO       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 ON_SCREEN_X         ;  |
                    INC $15A0,x             ; /
ON_SCREEN_X         LDA $14E0,x             ; \
                    XBA                     ;  |
                    LDA $E4,x               ;  |
                    REP #$20                ;  |
                    SEC                     ;  |
                    SBC $1A                 ;  | mark sprite invalid if far enough off screen
                    CLC                     ;  |
                    ADC.W #$0040            ;  |
                    CMP.W #$0180            ;  |
                    SEP #$20                ;  |
                    ROL A                   ;  |
                    AND #$01                ;  |
                    STA $15C4,x             ; / 
                    BNE INVALID             ; 
                    
                    LDY #$00                ; \ set up loop:
                    LDA $1662,x             ;  | 
                    AND #$20                ;  | if not smushed (1662 & 0x20), go through loop twice
                    BEQ ON_SCREEN_LOOP      ;  | else, go through loop once
                    INY                     ; / 
ON_SCREEN_LOOP      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 ON_SCREEN_Y         ;  |
                    LDA $186C,x             ;  | (vert offscreen)
                    ORA TABLE2,y            ;  |
                    STA $186C,x             ;  |
ON_SCREEN_Y         DEY                     ;  |
                    BPL ON_SCREEN_LOOP      ; /
                    LDY $15EA,x             ; get offset to sprite OAM
                    LDA $E4,x               ; \ 
                    SEC                     ;  | 
                    SBC $1A                 ;  | $00 = sprite x position relative to screen boarder
                    STA $00                 ; / 
                    LDA $D8,x               ; \ 
                    SEC                     ;  | 
                    SBC $1C                 ;  | $01 = sprite y position relative to screen boarder
                    STA $01                 ; / 
                    RTS                     ; return
INVALID             PLA                     ; \ return from *main gfx routine* subroutine...
                    PLA                     ;  |    ...(not just this subroutine)
                    RTS                     ; /
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B829 - vertical mario/sprite position check - shared
; Y = 1 if mario below sprite??
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    ;org $03B829 
SUB_VERT_POS        LDY #$00               ;A:25A1 X:0007 Y:0001 D:0000 DB:03 S:01EA P:envMXdizCHC:0130 VC:085 00 FL:924
                    LDA $96                ;A:25A1 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdiZCHC:0146 VC:085 00 FL:924
                    SEC                    ;A:2546 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizCHC:0170 VC:085 00 FL:924
                    SBC $D8,x              ;A:2546 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizCHC:0184 VC:085 00 FL:924
                    STA $0F                ;A:25D6 X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0214 VC:085 00 FL:924
                    LDA $97                ;A:25D6 X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0238 VC:085 00 FL:924
                    SBC $14D4,x            ;A:2501 X:0007 Y:0000 D:0000 DB:03 S:01EA P:envMXdizcHC:0262 VC:085 00 FL:924
                    BPL LABEL11            ;A:25FF X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0294 VC:085 00 FL:924
                    INY                    ;A:25FF X:0007 Y:0000 D:0000 DB:03 S:01EA P:eNvMXdizcHC:0310 VC:085 00 FL:924
LABEL11             RTS                    ;A:25FF X:0007 Y:0001 D:0000 DB:03 S:01EA P:envMXdizcHC:0324 VC:085 00 FL:924
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B85D - off screen processing code - shared
; sprites enter at different points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    ;org $03B83B             
TABLE3              dcb $40,$B0
TABLE6              dcb $01,$FF 
TABLE4              dcb $30,$C0,$A0,$80,$A0,$40,$60,$B0 
TABLE5              dcb $01,$FF,$01,$FF,$01,$00,$01,$FF
SUB_OFF_SCREEN_X0   LDA #$06                ; \ entry point of routine determines value of $03
                    BRA STORE_03            ;  | 
SUB_OFF_SCREEN_X1   LDA #$04                ;  |
                    BRA STORE_03            ;  |
SUB_OFF_SCREEN_X2   LDA #$02                ;  |
STORE_03            STA $03                 ;  |
                    BRA START_SUB           ;  |
SUB_OFF_SCREEN_X3   STZ $03                 ; /
START_SUB           JSR SUB_IS_OFF_SCREEN   ; \ if sprite is not off screen, return
                    BEQ RETURN_2            ; /    
                    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_2            ; /
                    LDA $13                 ; \ 
                    AND #$01                ;  | 
                    ORA $03                 ;  | 
                    STA $01                 ;  |
                    TAY                     ; /
                    LDA $1A                 ;x boundry ;A:0101 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0256 VC:090 00 FL:16953
                    CLC                     ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0280 VC:090 00 FL:16953
                    ADC TABLE4,y            ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0294 VC:090 00 FL:16953
                    ROL $00                 ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0326 VC:090 00 FL:16953
                    CMP $E4,x               ;x pos ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0364 VC:090 00 FL:16953
                    PHP                     ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0394 VC:090 00 FL:16953
                    LDA $1B                 ;x boundry hi ;A:01C0 X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizCHC:0416 VC:090 00 FL:16953
                    LSR $00                 ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0440 VC:090 00 FL:16953
                    ADC TABLE5,y            ;A:0100 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdizcHC:0478 VC:090 00 FL:16953
                    PLP                     ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0510 VC:090 00 FL:16953
                    SBC $14E0,x             ;x pos high ;A:01FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0538 VC:090 00 FL:16953
                    STA $00                 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0570 VC:090 00 FL:16953
                    LSR $01                 ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0594 VC:090 00 FL:16953
                    BCC LABEL20             ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0632 VC:090 00 FL:16953
                    EOR #$80                ;A:01FE X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0648 VC:090 00 FL:16953
                    STA $00                 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0664 VC:090 00 FL:16953
LABEL20             LDA $00                 ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0688 VC:090 00 FL:16953
                    BPL RETURN_2            ;A:017E X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0712 VC:090 00 FL:16953
ERASE_SPRITE        LDA $14C8,x             ; \ if sprite status < 8, permanently erase sprite
                    CMP #$08                ;  |
                    BCC KILL_SPRITE         ; /
                    LDY $161A,x             ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZCHC:0140 VC:071 00 FL:21152
                    CPY #$FF                ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizCHC:0172 VC:071 00 FL:21152
                    BEQ KILL_SPRITE         ;A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0188 VC:071 00 FL:21152
                    LDA #$00                ; \ mark sprite to come back    A:FF08 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0204 VC:071 00 FL:21152
                    STA $1938,y             ; /                             A:FF00 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdiZcHC:0220 VC:071 00 FL:21152
KILL_SPRITE         STZ $14C8,x             ; erase sprite
RETURN_2            RTS                     ; return
VERTICAL_LEVEL      LDA $167A,x             ; \ if "process offscreen" flag is set, return
                    AND #$04                ;  |
                    BNE RETURN_2            ; /
                    LDA $13                 ; \ only handle every other frame??
                    LSR A                   ;  | 
                    BCS RETURN_2            ; /
                    AND #$01                ;A:0227 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0228 VC:112 00 FL:1142
                    STA $01                 ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0244 VC:112 00 FL:1142
                    TAY                     ;A:0201 X:0006 Y:00EC D:0000 DB:03 S:01ED P:envMXdizcHC:0268 VC:112 00 FL:1142
                    LDA $1C                 ;A:0201 X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0282 VC:112 00 FL:1142
                    CLC                     ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0306 VC:112 00 FL:1142
                    ADC TABLE3,y            ;A:02BD X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0320 VC:112 00 FL:1142
                    ROL $00                 ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0352 VC:112 00 FL:1142
                    CMP $D8,x               ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:enVMXdizCHC:0390 VC:112 00 FL:1142
                    PHP                     ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0420 VC:112 00 FL:1142
                    LDA.W $001D             ;A:026D X:0006 Y:0001 D:0000 DB:03 S:01EC P:eNVMXdizcHC:0442 VC:112 00 FL:1142
                    LSR $00                 ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdiZcHC:0474 VC:112 00 FL:1142
                    ADC TABLE6,y            ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:enVMXdizCHC:0512 VC:112 00 FL:1142
                    PLP                     ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01EC P:envMXdiZCHC:0544 VC:112 00 FL:1142
                    SBC $14D4,x             ;A:0200 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNVMXdizcHC:0572 VC:112 00 FL:1142
                    STA $00                 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0604 VC:112 00 FL:1142
                    LDY $01                 ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizcHC:0628 VC:112 00 FL:1142
                    BEQ LABEL22             ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0652 VC:112 00 FL:1142
                    EOR #$80                ;A:02FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0668 VC:112 00 FL:1142
                    STA $00                 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0684 VC:112 00 FL:1142
LABEL22             LDA $00                 ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0708 VC:112 00 FL:1142
                    BPL RETURN_2            ;A:027F X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:0732 VC:112 00 FL:1142
                    BMI ERASE_SPRITE        ;A:0280 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:0170 VC:064 00 FL:1195
SUB_IS_OFF_SCREEN   LDA $15A0,x             ; \ if sprite is on screen, accumulator = 0 
                    ORA $186C,x             ;  |  
                    RTS                     ; / return