
;;----------------------------------------------------------------------------------------
;; Customizable Constants
;;----------------------------------------------------------------------------------------

                HIT_POINTS = $04        ; Customizable Hit Point Bar
                SPIT_TIME  = $02        ; Spit When Dryad's below this HP
		PILLAR_NUM = $01	; Pillar Number for Plants (CHANGE THIS!!!!!)
		BLINKING_TIME = $70
		FOOTBALL_NUM = $1B

;;----------------------------------------------------------------------------------------

dcb "INIT"
		LDA #HIT_POINTS 
		STA $1528,x
		LDA #$E0
		STA $AA,x
		LDA #$01
		STA $15E8
		LDA #$FF
		STA $0DD9
		STZ $1564,x
		RTL

dcb "MAIN"
		PHB         	; \
		PHK         	;  | main sprite function, just calls local subroutine
		PLB        	;  |
		JSR S_START   	;  |
		PLB        	;  |
		RTL    		; /


S_START:	JSR SUB_GFX
		LDA $9D                 ; \ if sprites not locked, return
		BNE NOT_NEXT

		JSR CHECK_HIT
		JSR PILLAR_MOVE
		JSR PIRAN_COLOR
		JSR APPLE_COLOR
		JSR BRAMB_COLOR
		JSR FALL_SPIKES
		JSR SLOW_BERRIES

		LDA $1528,x
		CMP #$02
		BCS GO_STATE
		LDA $C2,x
		BNE GO_STATE
		JSR SPIT_START

GO_STATE:	JSR CHOOSE_STATE
		LDA $C2,x
		CMP #$03
		BEQ NOT_NEXT
		LDA $1564,x
		BNE NOT_NEXT
		JSR NEXT_STATE
NOT_NEXT:	RTS

;;--------------------------------------------------------------------------------
;; Next State Routine
;;--------------------------------------------------------------------------------

STATE_MACH:	db $00,$02,$00,$03,$00,$01,$00,$07	;2,3,1,7
STATE_TIMER:	db $81,$41,$81,$FF,$FF,$81,$FF,$21

NEXT_STATE:	LDA $0DD9
		CLC
		ADC #$01
		AND #$07
		STA $0DD9
		TAY
		LDA STATE_MACH,y
		STA $C2,x
		TAY
		LDA STATE_TIMER,y
		STA $1564,x
		RTS

CHOOSE_STATE:	LDA $C2,x
		BEQ STATE_0
		CMP #$01
		BEQ STATE_1
		CMP #$02
		BEQ STATE_2
		CMP #$03
		BEQ STATE_3
		CMP #$04
		BEQ STATE_4
		CMP #$05
		BEQ STATE_5
		CMP #$06
		BEQ STATE_6
		CMP #$07
		BEQ STATE_7
		RTS
		
STATE_0:	JMP BOBBING
STATE_1:	JMP CREATE_PILLAR
STATE_2:	JMP FALL_STUFF
STATE_3:	JMP SMASH_WALL
STATE_4:	JMP KILL_DRYAD
STATE_5:	JMP THROW_STUFF
STATE_6:	JMP LESS_THROW
STATE_7:	JMP DELETE_FRUITS
RETURN:		RTS

PIRAN_COLOR:	LDY #$0B
COLOR_LOOP:	LDA $9E,y		; \ if the sprite number is
		CMP #$B2		;  | key
		BNE NEXT_LOOP		; /
		LDA #$3F
		STA $15F6,y	; / make it red (if it's gold or red)
NEXT_LOOP:	DEY		;
		BPL COLOR_LOOP	; ...otherwise, loop
		RTS

APPLE_COLOR:	LDY #$0B
COLOR_LOOP_2:	LDA $9E,y		; \ if the sprite number is
		CMP #$1B		;  | key
		BNE NEXT_LOOP_2		; /
		LDA #$3D
		STA $15F6,y	; / make it red (if it's gold or red)
NEXT_LOOP_2:	DEY		;
		BPL COLOR_LOOP_2	; ...otherwise, loop
		RTS

BRAMB_COLOR:	PHX
		LDX #$0B
COLOR_LOOP_3:	LDA $7FAB9E,x		; \ if the sprite number is
		CMP #PILLAR_NUM		;  | key
		BNE NEXT_LOOP_3		; /
		LDA $15F6,x
		AND #$F0
		ORA #$07
		STA $15F6,x	; / make it red (if it's gold or red)
NEXT_LOOP_3:	DEX		;
		BPL COLOR_LOOP_3	; ...otherwise, loop
		PLX
		RTS

FALL_SPIKES:	PHX
		LDX #$0B 
FALL_LOOP:	LDA $9E,x	
		CMP #$B2
		BNE NO_SPIKE
		STZ $1540,x 
NO_SPIKE:	DEX
		BPL FALL_LOOP
		PLX
		RTS

SLOW_BERRIES:	PHX
		LDX #$0B 
SLOW_LOOP:	LDA $9E,x	
		CMP #$1B
		BNE NO_BERRY		
		LDA $AA,x
		CMP #$80
		BCS NO_BERRY
		CMP #$40
		BCC NO_BERRY
		LSR
		STA $AA,x 
NO_BERRY:	DEX
		BPL SLOW_LOOP
		PLX
		RTS

;;--------------------------------------------------------------------------------
;; Change Route (State 6)
;;--------------------------------------------------------------------------------

LESS_THROW:	LDA $1528,x
		CMP #SPIT_TIME
		BCC MUNCH
		LDA #$03
		BRA STORE_LESS
MUNCH:		LDA #$02
STORE_LESS:	STA $C2,x
		TAY
		LDA STATE_TIMER,y
		STA $1564,x
		RTS

;;--------------------------------------------------------------------------------
;; Delete Fruits (State 7)
;;--------------------------------------------------------------------------------

DELETE_FRUITS:	LDA $1564,x
		CMP #$20
		BEQ CHARGE
		CMP #$1B
		BEQ REMOVE_APPLES
		RTS

CHARGE:		LDA #$0A
		STA $1DF9
		RTS

REMOVE_APPLES:	PHX
		LDX #$07
LOOP_REMOVE:	TXA
		BEQ ELIM_REMOVE
		LDA $14C8,x
		BEQ DEC_X
		LDA $9E,x
		CMP #FOOTBALL_NUM
		BNE DEC_X
		LDA #$04
		STA $14C8,x
		LDA #$1F
		STA $1540,x
		LDA #$08
		STA $1DF9
DEC_X:		DEX
		BRA LOOP_REMOVE
ELIM_REMOVE:	PLX
		RTS

;;--------------------------------------------------------------------------------
;; Hit Detection Routine
;;--------------------------------------------------------------------------------

CHECK_HIT:	JSL $018032             ; interact with other sprites               
		JSL $01A7DC 
		BCC NO_CONTACT
		LDA $15AC,x
		BNE NO_CONTACT
		JSR $03B69F                    
		LDA $7D                 ; \  if Mario's y speed < 10 ...
		CMP #$18                ;  }   ... sprite will hurt Mario
		BMI SPRITE_WINS         ; /  
		JSL $01AA33
		JSL $01AB99
		LDA #BLINKING_TIME
		STA $15AC,x
		LDA #$28
		STA $1DFC
		DEC $1528,x
		LDA $1528,x
		BEQ MAKE_DEAD
NO_CONTACT:	RTS
SPRITE_WINS:	JSL $00F5B7
		RTS
MAKE_DEAD:	LDA #$04
		STA $C2,x
		LDA #$FF
		STA $1564,x
		RTS

KILL_DRYAD:	LDA $1564,x
		CMP #$FE
		BEQ ELIMALL
		CMP #$80
		BNE ANIMATE_DRYAD
		LDA #$04
		STA $14C8,x             ; Destroy Sprite 
		LDA #$1F
		STA $1540,x
		LDA #$08
		STA $1DF9
		INC $13C6               ; Prevent Mario from walking.
		LDA #$FF                ; \ Set Goal
		STA $1493               ; /
		LDA #$06                ; \ Set Ending Eusic
		STA $1DFB               ; /
ANIMATE_DRYAD:	RTS

ELIMALL:	PHX 
		LDX #$07
LOOPALL:	TXA
		BEQ ELIMALLDONE
		LDA $14C8,x 
		BEQ DEC_X4
		LDA #$04
		STA $14C8,x  
		LDA #$1F
		STA $1540,x		;
DEC_X4:		STZ $170B,x
		DEX
		BRA LOOPALL
ELIMALLDONE:	PLX
		RTS

;;--------------------------------------------------------------------------------
;; Bobbing/Weaving Motion
;;--------------------------------------------------------------------------------

MAX_YVELOCITY = $11	;$19
MIN_YVELOCITY = $F0	;$E8
XSPEED: 	dcb $E8,$18		; Speeds of Sprite's X Speed

BOBBING:	LDA $AA,x
		CLC
		ADC $15E8
		STA $AA,x
		CMP #$80
		BCS DOWN_BOB
		CMP #MAX_YVELOCITY
		BCC END_BOB
		LDA #$FF
		STA $15E8
		BRA END_BOB
DOWN_BOB:	CMP #MIN_YVELOCITY
		BCS END_BOB
		LDA #$01
		STA $15E8
END_BOB:	JSL $01801A		; Apply speed.
WEAVING:	LDA $14E0,x		; Load the current MAX_HIGH into A.
		BNE DONTSTOP		; If not met yet, keep walking.
		LDY $157C,x		
		TYA
		BNE RIGHT_WALK
		LDA $E4,x		; Compare to its current position.
		CMP #$25
		BCC STOP_WALK		; If not met yet, keep walking.
		BRA DONTSTOP
RIGHT_WALK:	LDA $E4,x		; Compare to its current position.
		CMP #$CB
		BCS STOP_WALK
		BRA DONTSTOP
STOP_WALK:	LDA $157C,x		;
		EOR #$01		; Flip sprite's direction to turn around.
		STA $157C,x		;
		LDA #$0B
		STA $C2,x
		RTS
DONTSTOP:	LDA XSPEED,y		; Load X speed indexed by Y (done before).
		STA $B6,x		; Store Sprite'x X Speed from XSPEED.
		JSL $018022		; Apply speed.
MOVERET:	RTS			; Return

;;--------------------------------------------------------------------------------
;; Pillar Creation
;;--------------------------------------------------------------------------------

CREATE_PILLAR:	LDA $1528,x
		CMP #$02
		BCS END_PIL
		LDA $1564,x
		CMP #$08
		BNE END_PIL
		JSR PILLAR
END_PIL:	LDA $1564,x
		CMP #$38
		BEQ PILLAR
		RTS

;;--------------------------------------------------------------------------------
;; Move/Kill Plant Pillar
;;--------------------------------------------------------------------------------

PILLAR_MOVE:	PHX
		LDX #$0B
LOOP_PIL:	TXA
		CMP #$FF
		BEQ END_PILLAR
		LDA $14C8,x             ; \ if the sprite status is..
		BEQ NEXT_SPRITE_P
		LDA $7FAB10,x		;
		AND #$08		;
		BEQ NEXT_SPRITE_P
		LDA $7FAB9E,x
		CMP #PILLAR_NUM
		BNE NEXT_SPRITE_P
		LDA $C2,x
		BEQ MINIMUM_PILL
		CMP #$03
		BEQ KILL_PILL
NEXT_SPRITE_P:	DEX
		BRA LOOP_PIL	
END_PILLAR:	PLX
		RTS

MINIMUM_PILL:	LDA $7E
		STA $E4,x
		BRA NEXT_SPRITE_P

KILL_PILL:	LDA $1570,x
		CMP #$01
		BNE NEXT_SPRITE_P
		STZ $14C8,x
		BRA NEXT_SPRITE_P

;;--------------------------------------------------------------------------------
;; Create Plant Pillar
;;--------------------------------------------------------------------------------

PILLAR:		;LDA $15A0,x             ; \ no egg if off screen
              	;ORA $186C,x             ;  |
             	;ORA $15D0,x            
		;BNE NOROOMPIL
            	JSL $02A9DE             ; \ get an index to an unused sprite slot, return if all slots full
                BMI NOROOMPIL            ; / after: Y has index of sprite being generated

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

              	PHX
		LDA #PILLAR_NUM
               	TYX
               	STA $7FAB9E,x
		LDA #$08
		STA $7FAB10,x
               	PLX

		LDA $7E
		STA $00E4,y 
           	LDA #$00
               	STA $14E0,y             ; /

		LDA #$70
		STA $00D8,y
		LDA #$01
		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
                JSL $0187A7             ;  get table values for custom sprite
             	LDA #$88
             	STA $7FAB10,x
		PLX                     ; / 
                LDA $157C,x
                STA $157C,y

		LDA #$70
		STA $1558,y
		LDA #$00
		STA $1570,y

NOROOMPIL:	RTS

;;--------------------------------------------------------------------------------
;; Throw Routine
;;--------------------------------------------------------------------------------

THROW_STUFF:	LDA $1564,x
		CMP #$80
		BNE NO_BERR
		JSR SMALLBERRIES
		JSR SMALLBERRIES
		JSR SMALLBERRIES
		LDA $1528,x
		CMP #$04
		BCS NO_BERR
		JSR SMALLBERRIES
NO_BERR:	RTS

;;--------------------------------------------------------------------------------
;; Throw Small Berries
;;--------------------------------------------------------------------------------

SMALLBERRIES:	JSL $02A9DE             ; \ get an index to an unused sprite slot, return if all slots full
                BMI NOROOMSBER          ; / after: Y has index of sprite being generated
		LDA #$08                ; \ set sprite status for new sprite
                STA $14C8,y             ; /
                LDA #$1B                ; \ set sprite number for new sprite
                STA $9E,y		; /

		JSL $01ACF9
		LDA $148D
		AND #$7F
		CLC
		ADC #$40
		STA $E4,y
		LDA #$00
		STA $14E0,y            

             	LDA #$40                ; \ set y position for new sprite
             	STA $D8,y               ;  |
            	LDA #$00
		STA $14D4,y             ; /
	
		LDA #$10
		STA $B6,y
		
		LDA #$88
		STA $7FAB10,x
	
            	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                     ; / 
                LDA $157C,x
        	STA $C2,y
NOROOMSBER:	RTS

;;--------------------------------------------------------------------------------
;; Smash Routine
;;--------------------------------------------------------------------------------

SMASH_WALL:	LDA #$1C
		STA $1DF9
		LDA #$05
		STA $C2,x
		LDA #$FF
		STA $1887
		LDY #$05
		LDA STATE_TIMER,y
		STA $1564,x
SKIP_FREEZE:	RTS

;;--------------------------------------------------------------------------------
;; Fall Routine
;;--------------------------------------------------------------------------------

FALL_STUFF:	LDA $1564,x
		AND #$1F
		BNE NO_PIRANHA
		JSR PIRANHA
NO_PIRANHA:	RTS

;;--------------------------------------------------------------------------------
;; Throw Falling Piranha
;;--------------------------------------------------------------------------------

PIRANHA:	JSL $02A9DE             ; \ get an index to an unused sprite slot, return if all slots full
                BMI NOROOMPIRA          ; / after: Y has index of sprite being generated
		LDA #$08                ; \ set sprite status for new sprite
                STA $14C8,y             ; /
                LDA #$B2                ; \ set sprite number for new sprite
                STA $9E,y		; /

		;LDA $7E
		;JSL $01ACF9
		;LDA $148D
		LDA $7E
		STA $E4,y
		LDA #$00
		STA $14E0,y            

             	LDA #$B0                ; \ set y position for new sprite
             	STA $D8,y               ;  |
            	LDA #$00
		STA $14D4,y             ; /
	
		LDA $15F6,x
		STA $15F6,y

		;LDA #$00
		;STA $1540,y
		
		LDA #$10
		STA $AA,y
	
		LDA #$88
		STA $7FAB10,x
	
            	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                     ; / 
NOROOMPIRA:	RTS

;;--------------------------------------------------------------------------------
;; Spit Leaves/Flowers
;;--------------------------------------------------------------------------------

THROW_DATX: 	db $10,$F0,$06,$FA
THROW_DATY:  	db $EC,$EC,$E8,$E8

SPIT_START:	LDA $AA,x
		BEQ SPIT_END
		LDA $14
		AND #$3F
		BNE SPIT_END
		LDA $15A0,x 
             	ORA $186C,x 
              	BNE SPIT_END            
SPIT_LEAVES:	LDY #$07                     ; \ Find a free extended sprite slot 
SPIT_SLOT:  	LDA $170B,y                  ;  | 
             	BEQ SPIT_CREATE              ;  | 
               	DEY                          ;  | 
              	BPL SPIT_SLOT	             ;  | 
             	RTS                          ; / Return if no free slots 
SPIT_CREATE: 	LDA #$0C                     ; \ Extended sprite = Volcano Lotus fire 
            	STA $170B,y                  ; / 
           	LDA $E4,x       
           	CLC                       
          	ADC #$04                
             	STA $171F,y   
              	LDA $14E0,x     
            	ADC #$00                
         	STA $1733,y   
            	LDA $D8,x       
           	STA $1715,y   
           	LDA $14D4,x     
        	STA $1729,y   
            	PHX     
		JSL $01ACF9    
		LDA $148D
		AND #$03
		TAX
             	LDA THROW_DATX,x       
            	STA $1747,y  
             	LDA THROW_DATY,x       
            	STA $173D,y   
            	PLX                       
              	DEC $00                   
              	BPL SPIT_LEAVES        
SPIT_END: 	RTS                          ; Return 

;;--------------------------------------------------------------------------------
;; Graphics Routine
;;--------------------------------------------------------------------------------

NORM_TILE:	db $44,$46,$64,$66,$00,$02
		db $C2,$C4,$E2,$E4,$08,$0A
		db $88,$8E,$A8,$AE,$24,$26
		db $82,$84,$A2,$A4,$08,$0A

SUMM_TILE:	db $0C,$0E,$2C,$2E,$04,$06
PIRA_TILE:	db $48,$4A,$68,$6A,$24,$26
DIED_TILE:	db $4C,$4E,$6C,$6E,$08,$0A

ALL_XPOS:	db $F8,$08,$F8,$08,$F8,$08
ALL_YPOS:	db $00,$00,$10,$10,$20,$20
PROP_TILE:	db $37,$37,$37,$37,$37,$37
TWIRL_NUM:	db $00,$06,$0C,$12

SUB_GFX:	LDA $C2,x
		STA $1DEF
		LDA $15AC,x
		BEQ GET_DRAW
		AND #$03
		BNE SPIT_END
GET_DRAW:	JSR GET_DRAW_INFO       ; sets y = OAM offset
GET_BOTTOM:	PHX
		LDX #$05
SUB_LOOP:	LDA $00
		CLC
		ADC ALL_XPOS,x
		STA $0300,y	

		LDA $01
		CLC
		ADC ALL_YPOS,x
		STA $0301,y

		JSR DRAW_TILES

		LDA $1DEF
		CMP #$04
		BEQ DEAD_COLOR1
		LDA PROP_TILE,x
		BRA STORE1_Y
DEAD_COLOR1:	LDA #$39	
STORE1_Y:	STA $0303,y
		
		INY
		INY
		INY
		INY
		DEX

		BPL SUB_LOOP
		PLX
		LDY #$02
		LDA #$05
		JSL $01B7B3		; Call the routine that draws the sprite.
		RTS			; Never forget this!

DRAW_TILES:	LDA $1DEF
		BEQ TWIRL_TILES
		CMP #$01
		BEQ BRAM_TILES
		CMP #$02
		BEQ FALL_TILES	
		CMP #$04
		BEQ DEAD_TILES
		CMP #$05
		BEQ THROW_TILES
		BRA IDLE_TILES
		
TWIRL_TILES:	PHX
		TXA
		STA $1B7F
		LDA $14
		LSR : LSR : LSR
		AND #$03
		TAX
		LDA TWIRL_NUM,x
		CLC
		ADC $1B7F
		TAX
		LDA NORM_TILE,x
		PLX
		STA $0302,y
		RTS
		
BRAM_TILES:	LDA SUMM_TILE,x
		STA $0302,y
		RTS		

FALL_TILES:	LDA PIRA_TILE,x
		STA $0302,y
		RTS	

DEAD_TILES:	LDA DIED_TILE,x
		STA $0302,y
		RTS		

IDLE_TILES:	LDA NORM_TILE,x
		STA $0302,y
		RTS

THROW_TILES:	PHX
		TXA
		STA $1B7F
		LDA $14
		LSR
		AND #$03
		TAX
		LDA TWIRL_NUM,x
		CLC
		ADC $1B7F
		TAX
		LDA NORM_TILE,x
		PLX
		STA $0302,y
		RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $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
                    



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GET_DRAW_INFO
; This is a helper for the graphics routine.  It sets off screen flags, and sets up
; variables.  It will return with the following:
;
;       Y = index to sprite OAM ($300)
;       $00 = sprite x position relative to screen boarder
;       $01 = sprite y position relative to screen boarder  
;
; It is adapted from the subroutine at $03B760
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SPR_T1              dcb $0C,$1C
SPR_T2              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 SPR_T1,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 SPR_T2,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                     ; /

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; hammer routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NEW_SPRITE_NUM = $7FAB9E
EXTRA_BITS = $7FAB10
X_OFFSET            dcb $06,$FA
X_OFFSET2           dcb $00,$FF
                    
SUB_HAMMER_THROW    LDA $15A0,x             ; \ no egg if off screen
                    ORA $186C,x             ;  |
                    ORA $15D0,x
                    BNE RETURN67
                    
                    JSL $02A9DE             ; \ get an index to an unused sprite slot, return if all slots full
                    BMI RETURN67            ; / after: Y has index of sprite being generated

                    lda #$10
		    sta $1df9 
                    
                    LDA #$08                ; \ set sprite status for new sprite
                    STA $14C8,y             ; /

                    PHX
                    LDA NEW_SPRITE_NUM,x
                    INC A
                    TYX
                    STA NEW_SPRITE_NUM,x
                    PLX

                    PHY
                    LDA $157C,x
                    TAY
                    LDA $E4,x               ; \ set x position for new sprite
                    CLC
                    ADC X_OFFSET,y
                    PLY
                    STA $00E4,y

                    PHY
                    LDA $157C,x
                    TAY
                    LDA $14E0,x             ;  |
                    ADC X_OFFSET2,y
                    PLY
                    STA $14E0,y             ; /

                    LDA $D8,x               ; \ set y position for new sprite
                    SBC #$00                ;  |
                    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
                    JSL $0187A7             ;  get table values for custom sprite
                    LDA #$88
                    STA EXTRA_BITS,x
                    PLX                       ; / 

                    LDA $157C,x
                    STA $157C,y
                
                    
                    
RETURN67            RTS                     ; return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_OFF_SCREEN
; This subroutine deals with sprites that have moved off screen
; It is adapted from the subroutine at $01AC0D
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    
SPR_T12             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

SUB_VERT_POS:	LDY #$00
		LDA $96
		SEC
		SBC $D8,x
		STA $0F
		LDA $97
		SBC $14D4,x
		BPL SPR_L11
		INY
SPR_L11:	RTS