;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Fire Pillar, by imamelia
;;
;; This sprite creates a 1-tile wide pillar of fire that bursts up, stays up for a bit,
;; and then goes back down, over and over again.
;;
;; Uses first extra bit: NO
;; Uses extra property bytes: YES
;;
;; The extra property byte 1 sets its priority, while the extra property byte 2 sets
;; how many tiles it will rise.
;;
;; Made on mszegedy's request.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; defines and tables
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

!TimeToStayUp = $70	; number of frames it will stay at maximum height
!TimeToStayDown = $A0	; number of frames that it will stay on the ground
!YSpeed = $10		; its movement speed
!TopTile = $20		; the tile used for the top of the sprite
!BottomTile = $40		; the tile used for all other tiles
!CoverUpTile = $C0		; the tile (on page 0) used to cover up the bottom tiles
; Note: This tile should be as square as possible.  The message box tile is the default;
; it can completely cover up any tile put below it when it is using vanilla graphics.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; init routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

print "INIT ",pc

LDA #!TimeToStayDown	; set the time to stay down
STA $1558,x		;

LDA $D8,x		;
CLC			;
ADC #$10		;
STA $1528,x		;
LDA $E4,x		;
STA $1534,x		;

RTL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine wrapper
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

print "MAIN ",pc
PHB
PHK
PLB
JSR GiantFirePillarMain
PLB
RTL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GiantFirePillarMain:

LDA $1570,x	; rising/falling frame timer
CLC		;
ADC #$0F		;
LSR #4		;
INC		;
STA $151C,x	; this will indicate the number of tiles to draw

JSR GiantFirePillarGFX

LDA $14C8,x	;
CMP #$08		;
BNE Return00	; return if the sprite is not in normal status or if sprites are locked
LDA $9D		;
BNE Return00	;

JSR SubOffscreenX0	;

LDA $C2,x	; sprite state
JSL $8086DF	; 16-bit pointer routine

dw RestAtBottom	; 00 - at minimum height
dw MovingUp	; 01 - spreading upward
dw RestAtTop	; 02 - at maximum height
dw MovingDown	; 03 - retreating back

Return00:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; sprite state 00: at minimum height
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

RestAtBottom:

LDA $1558,x	; if it is time to start going up...
BNE Return01	;
INC $C2,x	; then change the sprite state to 01
LDA #$17		;
STA $1DFC	; and play a fiery sound effect
Return01:		;
RTS		;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; sprite state 01: shooting up
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MovingUp:

INC $1570,x	; increment the height counter
LDA $7FAB34,x	; extra property byte 2
ASL #4		; x16
CMP $1570,x	; if the sprite has reached maximum height...
BEQ AtMax	; then change the sprite state

LDA #!YSpeed	; set the sprite Y speed for moving up
EOR #$FF		;
INC		; flip it, since the sprite is going upward
STA $AA,x	;
JSL $81801A	; update sprite Y position
JSR Interact	; interact with the player
RTS		;

AtMax:			;
INC $C2,x		; change the sprite state to 02
LDA #!TimeToStayUp	; set the time to stay at maximum height
STA $1558,x		;
RTS			;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; sprite state 02: at maximum height
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

RestAtTop:

LDA $1558,x	; if the sprite is not supposed to stay up any longer...
BEQ BackDown	; then make it start moving back down
JSR Interact	; otherwise, just interact with the player
RTS		; and return
BackDown:	;
INC $C2,x	; change the sprite state to 03
RTS		;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; sprite state 03: ebbing back down
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MovingDown:

DEC $1570,x	; decrement the height counter
BEQ AtMin	; if the sprite is back at 0 height, change the sprite state
LDA #!YSpeed	; set the sprite Y speed for moving down
STA $AA,x	;
JSL $81801A	; update sprite Y position
JSR Interact	; interact with the player
RTS		;

AtMin:			;
STZ $C2,x		; change the sprite state to 00
LDA #!TimeToStayDown	; set the time to stay at maximum height
STA $1558,x		;
RTS			;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; graphics routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GiantFirePillarGFX:

JSL $20CA4F

LDA $14		;
ASL #4		;
AND #$40	; make the sprite animate by X-flipping
STA $02		;

LDA $15F6,x	; sprite palette and GFX page
ORA $7FAB28,x	; extra property byte 1 (priority setting)
STA $03		;

LDA $151C,x	;
STA $04		;

LDA $1570,x	; height frame counter
AND #$0F	; pixel offsets
SEC		;
SBC #$10		;
STA $06		;
STZ $05		;

LDX #$00		; start the tile counter at 0

GFXLoop:		;

INY #4		;

LDA $00		; base X position
STA $0300,y	; no X displacement for the tiles on the left

LDA $01		; base Y position
CPX #$01		; if the tile counter is 00...
BCC NoYDisp	; there is no need to set any Y displacement for the tiles
CLC		;
ADC $05		;
NoYDisp:		;
STA $0301,y	;

LDA #!TopTile	;
CPX #$01		;
BCC StoreTile	;
LDA #!BottomTile	;
StoreTile:		;
STA $0302,y	;

LDA $03		;
ORA $02		;
STA $0303,y	;

LDA $05		;
CLC		;
ADC #$10	;
STA $05		;

INX		; increment the tile counter
CPX $04		; compare to the wanted number of tiles
BCC GFXLoop	; loop the routine if there are more tiles to draw

LDX $15E9	;
LDY $15EA,x	;

LDA $1534,x	;
SEC		;
SBC $1A		;
STA $0300,y	;

LDA $1528,x	;
SEC		;
SBC $1C		;
STA $0301,y	;

LDA #!CoverUpTile	;
STA $0302,y	;
LDA #$00		;
STA $0303,y	;

LDY #$02		; all tiles were 16x16
LDA $151C,x	; number of tiles drawn
INC		; plus 1 for the cover-up tile
JSL $81B7B3	;
RTS		;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; sprite interaction/hit routine (includes player interaction)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Interact:

;LDA $167A,x	;
;AND #$20	;
;BNE ProcessInteract;
TXA		;
EOR $13		;
AND #$01	;
ORA $15A0,x	;
BEQ ProcessInteract	;
NoContact:	;
CLC		;
RTS		;

ProcessInteract:	;

JSR SubHorizPos	;

LDA $0F		;
CLC		;
ADC #$50	;
CMP #$A0	;
BCS NoContact	;

;JSR SubVertPos2	;

;LDA $0E		;
;CLC		;
;ADC #$60	;
;CMP #$C0	;
;BCS NoContact	;

LDA $71		;
BNE NoContact	;
LDA #$00		;
BIT $0D9B	;
BVS SkipCheckP	;
LDA $13F9,x	;
EOR $1632,x	;
SkipCheckP:	;
BNE NoContact2	;

JSL $83B664		; get player clipping routine
JSR SetSpriteClipping	; use custom sprite clipping values here
JSR CheckForContact	;
PHK			;
PER $0006		;
PEA $8020		;
JML $01A830		; finish up with the regular code

RTS

NoContact2:		;
CLC			;
RTS			;

SetSpriteClipping:	; custom sprite clipping routine, based off $03B69F

LDA #$02		;
CLC		;
ADC $E4,x	;
STA $04		; $04 = sprite X position low byte + X displacement value
LDA $14E0,x	;
ADC #$00	;
STA $0A		; $0A = sprite X position high byte + X displacement high byte (00 or FF)
LDA #$0C		;
STA $06		; $06 = sprite clipping width (a little less than 16 pixels)
LDA #$06		;
CLC		;
ADC $D8,x	;
STA $05		; $05 = sprite Y position low byte + Y displacement value
LDA $14D4,y	;
ADC #$00	;
STA $0B		; $0B = sprite Y position high byte + Y displacement high byte (00 or FF)
LDA $1570,x	;
CLC		;
ADC #$06	;
STA $07		; $07 = sprite clipping height
RTS		;

CheckForContact:	;

PHX		;
LDX #$01		;

ContactLoop:	;

LDA $04,x	;
SEC		;
SBC $00,x		;
CLC		;
ADC $06,x	;
STA $0F		;
LDA $02,x	;
CLC		;
ADC $06,x	;
CMP $0F		;
BCC EndCLoop	;
DEX		;
BPL ContactLoop	;

EndCLoop:	;
PLX		;
RTS		;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; miscellaneous standard subroutines
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Table1:              db $0C,$1C
Table2:              db $01,$02
Table3:              db $40,$B0
Table6:              db $01,$FF
Table4:              db $30,$C0,$A0,$C0,$A0,$F0,$60,$90,$30,$C0,$A0,$80,$A0,$40,$60,$B0
Table5:              db $01,$FF,$01,$FF,$01,$FF,$01,$FF,$01,$FF,$01,$FF,$01,$00,$01,$FF

SubOffscreenX0:
LDA #$00
;BRA SubOffscreenMain
;SubOffscreenX1:
;LDA #$02
;BRA SubOffscreenMain
;SubOffscreenX2:
;LDA #$04
;BRA SubOffscreenMain
;SubOffscreenX3:
;LDA #$06
;BRA SubOffscreenMain
;SubOffscreenX4:
;LDA #$08
;BRA SubOffscreenMain
;SubOffscreenX5:
;LDA #$0A
;BRA SubOffscreenMain
;SubOffscreenX6:
;LDA #$0C
;BRA SubOffscreenMain
;SubOffscreenX7:
;LDA #$0E

SubOffscreenMain:

STA $03

JSR SubIsOffscreen
BEQ Return2

LDA $5B
LSR
BCS VerticalLevel
LDA $D8,x
CLC
ADC #$50
LDA $14D4,x
ADC #$00
CMP #$02
BPL EraseSprite
LDA $167A,x
AND #$04
BNE Return2
LDA $13
AND #$01
ORA $03
STA $01
TAY
LDA $1A
CLC
ADC Table4,y
ROL $00
CMP $E4,x
PHP
LDA $1B
LSR $00
ADC Table5,y
PLP
SBC $14E0,x
STA $00
LSR $01
BCC Label20
EOR #$80
STA $00
Label20:
LDA $00
BPL Return2

EraseSprite:
LDA $14C8,x
CMP #$08
BCC KillSprite
LDY $161A,x
CPY #$FF
BEQ KillSprite
LDA #$00
STA $1938,y
KillSprite:
STZ $14C8,x
Return2:
RTS

VerticalLevel:

LDA $167A,x
AND #$04
BNE Return2
LDA $13
LSR
BCS Return2
AND #$01
STA $01
TAY
LDA $1C
CLC
ADC Table3,y
ROL $00
CMP $D8,x
PHP
LDA $1D
LSR $00
ADC Table6,y
PLP
SBC $14D4,x
STA $00
LDY $02
BEQ Label22
EOR #$80
STA $00
Label22:
LDA $00
BPL Return2
BMI EraseSprite

SubIsOffscreen:
LDA $15A0,x
ORA $186C,x
RTS



SubHorizPos:

LDY #$00
LDA $94
SEC
SBC $E4,x
STA $0F
LDA $95
SBC $14E0,x
BPL $01
INY
RTS

SubVertPos2:

LDY #$00
LDA $D3
SEC
SBC $D8,x
STA $0E
LDA $D4
SBC $14D4,x
BPL $01
INY
RTS


