


dcb "INIT"
STZ $1510,x
LDA #$40
STA $163E,x
STZ $157C,x
LDA $7FAB10,x
AND #$04
BEQ LEFT_FACING
INC $157C,x
LEFT_FACING
RTL

dcb "MAIN"
PHB
PHK
PLB
JSR SPRITE_SWITCH
PLB
RTL

SPRITE_SWITCH
		LDA $1510,x
		BEQ JSHOOT
		BRA JWAVE
JSHOOT
		JSR SHOOT
		RTS
JWAVE
		JSR WAVE
		RTS
RETURNSHOOT
		RTS
SHOOT
       
	   LDA $14C8,x ;\
       CMP #$08   ; | If the sprite is dead or not it it's normal state, return.
       BNE RETURNSHOOT ;/
       LDA $9D    ;\
       BNE RETURNSHOOT ;/ If sprites are locked, return.
       
	   STZ $AA,x
	   STZ $B6,x
	   JSL $01802A
	   JSR SUB_OFF_SCREEN_X0
	   JSR ASK_SHOOT
	   RTS
ASK_SHOOT
		STZ $15A0,x
		LDA $E4,x               ; \
        CMP $1A                 ;  | set horizontal offscreen if necessary
        LDA $14E0,x             ;  |
        SBC $1B                 ;  |
        BEQ ON_SCR        ;  |
        INC $15A0,x             ; /
ON_SCR
        LDA $15A0,x
		BNE NO_SHOOT
		LDA $163E,x
		BEQ YES_SHOOT
NO_SHOOT
		RTS
XOFF_GEN: dcb $10,$F0
XOFF_FIX: dcb $00,$FF
SLOTS_FULL
		RTS
YES_SHOOT
		LDA #$80
		STA $163E,x
		LDA $157C,x
		TAY
		LDA XOFF_GEN,y
		STA $00
		LDA XOFF_FIX,y
		STA $01
		JSL $02A9DE
		BMI SLOTS_FULL ; If sprite slots are full, don't generate.
		;After this, the sprite to generate is in the Y register.
		
		PHX ; NOTE: We need to use the X register for the generated sprite.
		TYX ; So we preserve the current sprites data.
		LDA #$98
		STA $7FAB9E,x ; The sprite number is stored to the custom sprite RAM Address. STA $7FAB9E,y doesn't exist, that's why we transfered X to Y.
		TXY ; Transfer sprite to spawn back to Y.
		PLX ; Restore X.

		LDA #$08
		STA $14C8,y ; Run sprite's INIT code first.z
		LDA $00E4,x
		CLC
		ADC $00
		STA $00E4,y ; X position.
		LDA $14E0,x
		ADC $01
		STA $14E0,y ; X position high.
		LDA $D8,x
		SEC
		SBC #$0F
		STA $00D8,y ; Y position.
		LDA $14D4,x
		ADC #$FF
		STA $14D4,y ; Y position high.
		STZ $01
		LDA $7FAB10,x
		AND #$04
		BNE LEFT_NOADDGEN
		LDA #$04
		STA $01
LEFT_NOADDGEN
		PHX ; Push current sprite.
		TYX ; Get sprite to generate into X.
		JSL $07F7D2 ; Reset sprite tables, to generate this one.
		JSL $0187A7 ; Reset custom sprite tables, too.
		LDA #$08
		ORA $01
		STA $7FAB10,x ; Setting this to 08 means we are generating a custom sprite.
		LDA #$01
		STA $1510,x
		PLX ; Restore previous sprite.
		LDA $157C,x
		STA $157C,y
		LDA #$02
		STA $163E,y
		LDA #$02
		STA $1DFC
		RTS 
WALL
		;LDA $1504,x
		;BNE INVTIME
		STZ $14C8,x
		JSR DRAW_SMOKE
		RTS
RETURNWAVE
		RTS
		
XSPEED: dcb $18,$E8

WAVE
		JSR GRAFICS
		LDA $14C8,x ;\
        CMP #$08   ; | If the sprite is dead or not it it's normal state, return.
        BNE RETURNWAVE ;/
        LDA $9D    ;\
        BNE RETURNWAVE ;/ If sprites are locked, return.
        JSR SUB_OFF_SCREEN_X0
        LDA $1588,x
        AND #$03
        BNE WALL
		STZ $1504,x
INVTIME
		LDY $157C,x ; Load the direction in Y.
        LDA XSPEED,y ; Speed based on direction.
        STA $B6,x ; Store to sprite's X speed.
        LDA #$01
        STZ $AA,x
        JSL $01802A ;Save new Sprite positions
        JSL $018032 ;Sprite to Sprite interaction
		JSL $01A7DC ;Sprite to Mario interaction
        BCS CONTACT
        RTS
PUSH_SP: dcb $38,$E4,$1C,$C8

CONTACT    
		LDA $163E,x
		BNE INVTIME2
		LDA #$10
		STA $163E,x
		LDA $0E		; is mario above the sprite?
		CMP #$E8	; cause if he is.
		BMI NOHORZ_PUSH	; sprite should not push him horz.
		CMP #$0C
		BPL NOHORZ_PUSH
		JSR SUB_HORZ2_POS
		LDA $157C,x
		BEQ NOADDFLIP
		INY
		INY
NOADDFLIP
		LDA PUSH_SP,y
        STA $7B ;Mario X speed
NOHORZ_PUSH
		LDA $0E		; is mario above the sprite?
		CMP #$E8	; cause if he is.
		BMI DOWN_CONTACT	; sprite should not push upwards (down contact)
		CMP #$00
		BPL UP_CONTACT
CONTINUE_CONTACT
        LDA #$01
        STA $1DF9 ;Sound
CONTINUE_CONTACT2		
		;JSR DRAW_SMOKE
INVTIME2
        RTS
DOWN_CONTACT
		LDA $77
		AND #$04
		BNE CONTINUE_CONTACT2
		LDA #$B0
		STA $7D
		LDA $75
		BNE WATER_CONTACT
		LDA $15
		AND #$80
		BNE EXTRA_BOOST
		BRA CONTINUE_CONTACT
WATER_CONTACT
		LDA #$D0
		STA $7D
		BRA CONTINUE_CONTACT
EXTRA_BOOST
		LDA #$A3
		STA $7D
		BRA CONTINUE_CONTACT
UP_CONTACT
		LDA #$09
		STA $7D
		BRA CONTINUE_CONTACT

;;;;;;;;;;;;;;;;;;;;;;;;;;
; GRAFICS   routine      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;

TILES:  dcb $86,$88,$A6,$A8
		dcb $80,$C0,$A4,$AA
XOFF: 	dcb $00,$10,$00,$10
		dcb $10,$00,$10,$00
YOFF:   dcb $00,$00,$10,$10
		dcb $00,$00,$10,$10
FLIP:   dcb $40,$00

GRAFICS JSL $20CA4F

        STZ $07
		LDA $157C,x
		BNE NOFLIP
		LDA #$40
		STA $07
NOFLIP
        PHX
		LDX #$03
LOOP
		PHX
		LDA $07
		BEQ NOADD_1
		INX
		INX
		INX
		INX
NOADD_1
		LDA $00
		CLC
		ADC XOFF,x
        STA $0300,y
        LDA $01
		CLC
		ADC YOFF,x
        STA $0301,y
		PLX
        PHX
		LDA $14
        LSR
        LSR
		LSR
        AND #$01
        BEQ NOADD
		INX
		INX
		INX
		INX
NOADD
        LDA TILES,x
        STA $0302,y
        PLX
		
        LDA #%0000111
        ORA $07
        ORA $64
        STA $0303,y
		
		INY
        INY
        INY
        INY
		
		DEX
		BPL LOOP
		PLX
        
        LDY #$02 
        LDA #$03 
        JSL $01B7B3
        RTS



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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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_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_HORZ2_POS		LDA $157C,x
					BEQ RIGHT_SUB
					LDY #$00				;A:25D0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1020 VC:097 00 FL:31642
					LDA $E4,x
					CLC
					ADC #$10
					STA $00
					LDA $14E0,x
					ADC #$00
					STA $01
					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 $00				;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 $01			;A:2500 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZcHC:1152 VC:097 00 FL:31642
					BPL SPR2_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
SPR2_L16				
					RTS                     ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642
RIGHT_SUB
					;LDA #$14
					;STA $1dFC
					LDY #$00				;A:25D0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1020 VC:097 00 FL:31642
					LDA $E4,x
					STA $00
					LDA $14E0,x
					STA $01
					REP #$20
					LDA $94					;A:25D0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZCHC:1036 VC:097 00 FL:31642
					SEC
					SBC $00
					;SEC                     ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1060 VC:097 00 FL:31642
					BPL SPR2R_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
SPR2R_L16				
                    SEP #$20
					RTS                     ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642
;==================================================================
;Draw Smoke Routine
;==================================================================
NODRAW_SMOKE
					RTS
DRAW_SMOKE:         LDA $15A0,x
					ORA $186C,x
					BNE NODRAW_SMOKE  ;No draw if offscreen horz/vert.
					LDY #$03                ; \ find a free slot to display effect
FINDFREE:           LDA $17C0,y             ;  |
                    BEQ FOUNDONE            ;  |
                    DEY                     ;  |
                    BPL FINDFREE            ;  |
                    RTS                     ; / return if no slots open

FOUNDONE:           LDA #$01                ; \ set effect graphic to smoke graphic
                    STA $17C0,y             ; /
                    LDA #$1B                ; \ set time to show smoke
                    STA $17CC,y             ; /
                    LDA $D8,x               ; \ smoke y position = generator y position
                    STA $17C4,y             ; /
                    LDA $E4,x               ; \ load generator x position and store it for later
                    STA $17C8,y             ; /
                    RTS