;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SMB3 Buster Beetle
; Coded by SMWEdit
;
; Uses first extra bit: NO
;
; This sprite will pick up block 12E or any block set to act like 12E
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		SPRITE_NUM = $56		; set this to the sprite # of the custom throw block

		HORZ_RANGE = $0080		; max X distance of mario for throwing
		VERT_RANGE = $0030		; max Y distance downward of mario for throwing

		TILE1 = $08			; run frame 1
		TILE2 = $0C			; run frame 2
		TILE3 = $0E			; holding frame

;; don't change these:

		COUNTER = $1504
		ACTSTATUS = $1528
		TILEINDEX = $1602
		LIFTTIMER = $163E
		PAUSETIMER = $1540

		LIFTTIME = $10
		HOLDTHROWTIME = $0C
		PAUSEMOVETIME = $14

		TMP1 = $00

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

		dcb "INIT"
		JSR SUB_HORZ_POS
		TYA
		STA $157C,x
		RTL		

		dcb "MAIN"
		PHB
		PHK
		PLB
		JSR SPRITE_ROUTINE
		PLB
		RTL


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

SPEED_TABLE	dcb $10,$F0		; speeds (right, left)

THROWXSPEEDS	dcb $30,$C0		; throw speeds (right, left)
		THROWYSPEED = $C0	; how fast upward speed is

PICKUP_INDEXES	dcb $02,$02,$02,$02,$02,$02,$02,$02
		dcb $00,$00,$00,$00,$00,$00,$00,$00

RETURN1		RTS

SPRITE_ROUTINE	JSR SUB_GFX
		LDA $14C8,x		; \  return if
		CMP #$08		;  | sprite status
		BNE RETURN1		; /  is not 8
		LDA $9D			; \ return if
		BNE RETURN1		; / sprites locked
		LDA $15D0,x		; \ return if
		BNE RETURN1		; / being eaten
		JSR SUB_OFF_SCREEN_X0	; only process sprite while on screen             

		STZ $B6,x		; default: not moving X

		LDA PAUSETIMER,x	; \  if movement is
		BEQ NOTPAUSED		;  | paused, then
		JMP RETURNING		; /  ignore all code
NOTPAUSED

		LDA ACTSTATUS,x		; \  which action
		BEQ RUNNING		;  | is being performed
		JMP PICKING_UP		; /  right now?

RUNNING
		LDA $1686,x		; \  change direction
		AND #%11101111		;  | if touched
		STA $1686,x		; /
		LDY $157C,x		; \  set x speed
		LDA SPEED_TABLE,y	;  | depending on
		STA $B6,x		; /  direction
		LDA COUNTER,x		; \
		AND #%00000100		;  | set tile index
		LSR A			;  | according to
		LSR A			;  | a frame counter
		STA TILEINDEX,x		;  |
		INC COUNTER,x		; /
		JSL $01802A		; update position based on speed values, also obj interaction
		LDA $1588,x		; \
		AND #%00000011		;  | not hitting wall? then skip
		BEQ NOT_HIT_SIDE	; /
		LDA $1860		; \
		CMP #$2E		;  | throw blk? (or blk set to act like one)
		BNE NO_PICK_UP		;  | if not, then
		LDA $1862		;  | skip next code
		CMP #$01		;  |
		BNE NO_PICK_UP		; /
		LDA #$02		; \
		STA $9C			;  | destroy blk
		JSL $00BEB0		; /
		LDA #LIFTTIME		; \ lifting timer
		STA LIFTTIMER,x		; / for block
		STZ COUNTER,x		; zero counter for next action
		LDA #$01		; \ set status to
		STA ACTSTATUS,x		; / picking up block
		BRA NOT_HIT_SIDE	; skip dir flip code
NO_PICK_UP
		LDA $157C,x		; \  not picking blk
		EOR #%00000001		;  | up, so hitting a
		STA $157C,x		; /  wall flips dir
NOT_HIT_SIDE
		JMP RETURNING		; end of running code, return

PICKING_UP
		LDA $1686,x		; \  don't change
		ORA #%00010000		;  | direction if
		STA $1686,x		; /  touched
		JSL $01802A		; update position based on speeds, with gravity
		LDY LIFTTIMER,x		; \  set tile index
		LDA PICKUP_INDEXES,y	;  | according to how
		STA TILEINDEX,x		; /  far into lifting
		LDA LIFTTIMER,x		; \ skip to end unless
		BNE RETURNING		; / picking up is done
		JSR SUB_HORZ_POS	; \  must face
		TYA			;  | Mario if
		STA $157C,x		; /  ready to throw
		LDA COUNTER,x		; \ counter != 0 means
		BNE BEGINTHROW		; / throwing already started
		LDA $E4,x		; \
		CMP $1A			;  | if slightly
		LDA $14E0,x		;  | off screen (H)
		SBC $1B			;  | then throw
		BNE BEGINTHROW		; /
		LDY #$00		; \
		LDA $E4,x		;  | check H
		STA TMP1		;  | range
		LDA $14E0,x		;  |
		STA TMP1+1		;  |
		PHP			;  |
		REP #%00100000		;  |
		LDA $94			;  |
		SEC			;  |
		SBC TMP1		;  |
		BPL HRESULTISPLUS	;  |
		EOR.w #$FFFF		;  |
		INC A			;  |
HRESULTISPLUS	CMP.w #HORZ_RANGE	;  |
		BCC HRANGE_OK		;  |
		LDY #$01		;  |
HRANGE_OK	PLP			;  |
		CPY #$00		;  |
		BNE RETURNING		; /
		LDY #$00		; \
		LDA $D8,x		;  | check V
		STA TMP1		;  | range
		LDA $14D4,x		;  |
		STA TMP1+1		;  |
		PHP			;  |
		REP #%00100000		;  |
		LDA $96			;  |
		SEC			;  |
		SBC TMP1		;  |
		BMI VRANGE_OK		;  |
		CMP.w #VERT_RANGE	;  |
		BCC VRANGE_OK		;  |
		LDY #$01		;  |
VRANGE_OK	PLP			;  |
		CPY #$00		;  |
		BNE RETURNING		; /
BEGINTHROW	INC COUNTER,x		; increment counter to get closer to throwing
		LDA COUNTER,x		; \  if throw pause time
		CMP #HOLDTHROWTIME	;  | has not expired, then
		BCC RETURNING		; /  don't throw the block
		JSR THROW		; throw the block
		STZ ACTSTATUS,x		; status back to running
		STZ COUNTER,x		; reset counter
		STZ TILEINDEX,x		; tile index = 0 for pause
		LDA #PAUSEMOVETIME	; \ set timer for
		STA PAUSETIMER,x	; / movement pause

RETURNING
		JSL $018032		; interact with other sprites
		JSL $01A7DC		; check for mario/sprite contact       
RETURN		RTS

THROW		JSL $02A9DE		; \ get slot or else
		BMI ENDTHROW		; / end if no slots
		LDA #$01		; \ set sprite status
		STA $14C8,y		; / as a new sprite
		PHX			; back up X
		TYX			; new sprite index to X
		LDA #SPRITE_NUM		; \ store custom
		STA $7FAB9E,x		; / sprite number
		JSL $07F7D2		; reset sprite properties
		JSL $0187A7		; get table values for custom sprite
		LDA #$08		; \ mark as a
		STA $7FAB10,x		; / custom sprite
		PLX			; load backed up X
		LDA $E4,x		; \
		STA $E4,y		;  | set position
		LDA $14E0,x		;  | of block to
		STA $14E0,y		;  | be thrown
		LDA $D8,x		;  |
		SEC			;  |
		SBC #$0E		;  |
		STA $D8,y		;  |
		LDA $14D4,x		;  |
		SBC #$00		;  |
		STA $14D4,y		; /
		LDA #$60		;
		JSR CODE_01BF6A		;
		LDA $01			; \
		STA $B6,y		; /
		LDA $00			; \
		STA $AA,y		; / speed
ENDTHROW	RTS

CODE_01BF6A:		STA $01
			PHX					;\ preserve sprite indexes of Magikoopa and magic
			PHY					;/
			JSR CODE_01AD42				; $0E = vertical distance to Mario
			STY $02					; $02 = vertical direction to Mario
			LDA $0E					;\ $0C = vertical distance to Mario, positive
			BPL CODE_01BF7C				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
CODE_01BF7C:		STA $0C					;/
			JSR SUB_HORZ_POS			; $0F = horizontal distance to Mario
			STY $03					; $03 = horizontal direction to Mario
			LDA $0F					;\ $0D = horizontal distance to Mario, positive
			BPL CODE_01BF8C				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
CODE_01BF8C:		STA $0D					;/
			LDY #$00
			LDA $0D					;\ if vertical distance less than horizontal distance,
			CMP $0C					; |
			BCS CODE_01BF9F				;/ branch
			INY					; set y register
			PHA					;\ switch $0C and $0D
			LDA $0C					; |
			STA $0D					; |
			PLA					; |
			STA $0C					;/
CODE_01BF9F:		LDA #$00				;\ zero out $00 and $0B
			STA $0B					; | ...what's wrong with STZ?
			STA $00					;/
			LDX $01					;\ divide $0C by $0D?
CODE_01BFA7:		LDA $0B					; |\ if $0C + loop counter is less than $0D,
			CLC					; | |
			ADC $0C					; | |
			CMP $0D					; | |
			BCC CODE_01BFB4				; |/ branch
			SBC $0D					; | else, subtract $0D
			INC $00					; | and increase $00
CODE_01BFB4:		STA $0B					; |
			DEX					; |\ if still cycles left to run,
			BNE CODE_01BFA7				;/ / go to start of loop
			TYA					;\ if $0C and $0D was not switched,
			BEQ CODE_01BFC6				;/ branch
			LDA $00					;\ else, switch $00 and $01
			PHA					; |
			LDA $01					; |
			STA $00					; |
			PLA					; |
			STA $01					;/
CODE_01BFC6:		LDA $00					;\ if horizontal distance was inverted,
			LDY $02					; | invert $00
			BEQ CODE_01BFD3				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
			STA $00					;/
CODE_01BFD3:		LDA $01					;\ if vertical distance was inverted,
			LDY $03					; | invert $01
			BEQ CODE_01BFE0				; |
			EOR #$FF				; |
			CLC					; |
			ADC #$01				; |
			STA $01					;/
CODE_01BFE0:		PLY					;\ retrieve Magikoopa and magic sprite indexes
			PLX					;/
			RTS					; return

CODE_01AD42:		LDY #$00
			LDA $D3
			SEC
			SBC $D8,x
			STA $0E
			LDA $D4
			SBC $14D4,x
			BPL Return01AD53
			INY
Return01AD53:		RTS					; return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GRAPHICS ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		TILESDRAWN = $04
		COORDINDEX = $05

XCOORDS		dcb $00,$00,$00,$00,$00,$00,$00,$00
		dcb $00,$03,$05,$08,$0A,$0C,$0D,$0E
		dcb $02

YCOORDS		dcb $F2,$F2,$F2,$F2,$F2,$F2,$F2,$F2
		dcb $F6,$F7,$F8,$F9,$FB,$FC,$FD,$FF
		dcb $F3

TILES		dcb TILE1,TILE2,TILE3

SUB_GFX		JSL $20CA4F

		STZ TILESDRAWN		; zero tiles drawn so far

		LDA $157C,x		; \ direction into
		STA $02			; / scratch RAM

		LDA $14C8,x		; \  vertical flip
		SEC			;  | based on whether or
		SBC #$02		;  | not sprite is dying.
		STA $03			; /  dying means flip

		LDA $00			; \ beetle X
		STA $0300,y		; / position

		LDA $01			; \
		PHX			;  | beetle Y
		LDX $03			;  | position,
		BNE NOTDEAD		;  | subtract 10
		SEC			;  | if dying
		SBC #$10		;  |
NOTDEAD		PLX			;  |
		STA $0301,y		; /

		PHY			; \
		LDY TILEINDEX,x		;  | beetle tile based on table
		LDA TILES,y		;  | entry corresponding to the
		PLY			;  | index set in the main code
		STA $0302,y		; /

		LDA $15F6,x		; sprite properties
		PHX			; \
		LDX $02			;  | flip if
		BNE NOFLIPX1		;  | sprite is
		ORA #%01000000		;  | flipped
NOFLIPX1	;PLX			; /
		;PHX			; \
		LDX $03			;  | flip V if
		BNE NOFLIPY1		;  | sprite is
		ORA #%10000000		;  | dying
NOFLIPY1	PLX			; /
		ORA $64			; add in priority bits
		STA $0303,y             ; set properties

		INC TILESDRAWN		; indicate a tile was drawn

		LDA ACTSTATUS,x		; \ if status is zero, only other status than
		BEQ FINALIZEGFX		; / block lifting/throwing, don't show block

		LDA LIFTTIMER,x		; \ default coordinate index
		STA COORDINDEX		; / is amt left in lift time
		LDA COUNTER,x		; \
		CMP #$04		;  | if counter for
		BCC NO_OVERRIDE_INDEX	;  | throw wait time
		CMP #$08		;  | elapsed is 4-7,
		BCS NO_OVERRIDE_INDEX	;  | then use slightly
		LDA #LIFTTIME		;  | shifted block
		STA COORDINDEX		; /
NO_OVERRIDE_INDEX

		INY			; \
		INY			;  | for next tile, get
		INY			;  | next OAM tile index
		INY			; /

		PHY			; \
		LDY COORDINDEX		;  | get X
		LDA XCOORDS,y		;  | coordinate
		LDY $02			;  | for block
		BEQ NOFLIPXC		;  | and flip
		EOR #%11111111		;  | if sprite
		INC A			;  | is flipped
NOFLIPXC	PLY			; /
		CLC			; \ then add it to
		ADC $00			; / tile position
		STA $0300,y		; and store the X position 

		PHY			; \
		LDY COORDINDEX		;  | get Y
		LDA YCOORDS,y		;  | coordinate
		LDY $03			;  | for block
		BNE NOFLIPYC		;  | and flip
		EOR #%11111111		;  | and subtract
		INC A			;  | #$10 if
		SEC			;  | sprite is
		SBC #$10		;  | dying
NOFLIPYC	PLY			; /
		CLC			; \ then add it to
		ADC $01			; / tile position
		STA $0301,y		; and store the Y position 

		LDA #$40		; \ set block
		STA $0302,y		; / tile number

		LDA $13			; \
		AND #%00000111		;  | cycle through palettes
		ASL A			; /
		PHX			; \	NOTE: you can cut out the block flipping code, I just thought it might look better with it because the beetle in SMB3 has it
		LDX $02			;  | flip if
		BNE NOFLIPX2		;  | sprite is
		ORA #%01000000		;  | flipped
NOFLIPX2	;PLX			; /
		;PHX			; \
		LDX $03			;  | flip V if
		BNE NOFLIPY2		;  | sprite is
		ORA #%10000000		;  | dying
NOFLIPY2	PLX			; /
		ORA $64                 ; add in the priority bits from the level settings
		STA $0303,y             ; set properties

		INC TILESDRAWN		; indicate a tile was drawn

FINALIZEGFX
		LDY #$02		; #$02 means the tiles are 16x16
		LDA TILESDRAWN		; \ A = tiles-1
		DEC A			; /
		JSL $01B7B3		; don't draw if offscreen, set tile size
		RTS



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ROUTINES FROM THE LIBRARY ARE PASTED BELOW
; You should never have to modify this code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;






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


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_HORZ_POS
; This routine determines which side of the sprite Mario is on.  It sets the Y register
; to the direction such that the sprite would face Mario
; It is ripped from $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 SPR_L16             ;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
SPR_L16				RTS                     ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642
