
; Note that { and } are used to delimit sections of code (their purposes are given through the comments above them).
; It doesn't really help much unless you're using an editor with folding support.

; Defines
{
!state =    $1934   ;0 = idle 
                    ;1 = hurt
                    ;2 = flying up to prepare attack
                    ;3 = bullet bill attack prep
                    ;4 = bullet bill attack
                    ;5 = bullet bill attack end
                    ;6 = dash attack right prep
                    ;7 = dash attack right
                    ;8 = dash attack left prep
                    ;9 = dash attack left
                    ;A = Enemy summon
                    ;B = smash attack going down
                    ;C = smash attack returning
                    ;D = smash attack looking
                    ;F = Defeated, falling
               
                    
!stateTime = $1936   ;How long we've been in the current state (16-bit)
!timeLeft = $1869   ;Time until the next state (16-bit).
!health = $0F3A     ;Starts at 0; at 3 he is defeated.


!xspeed = $B6,x		;\
!yspeed = $AA,x		;| For convenience purposes.
!xpos = $1926		;|
!ypos = $1923		;/
;!rand1 = $1487
!nextAttack = $14BE	;Used to store the next attack while in the "fly off" state
!attacked = $0F70 	;The attacks the boss will dodge, in the order of shoot dash smash.  3 bytes.
!side = $1FFA		;Which side of the screen the boss will attack from.  0 = left, 1 = right.
!attackTimes = $0DA1	;How many times the boss has "sub-attacked" within the same attack (number of times dashed and number of enemies spawned specifically).
!canFreeFall = $0DD9	;Used during the idle state to allow the boss to return quickly to the screen after dodging a thrown item.
!prevAttack = $13C8	;Because the PRNG is TERRIBLE, we need this to prevent the same attack 10 times in a row.
!facing	= $1570,x	;Which direction the boss is facing (either #$00 or #$40).
!forceXSpeed = $1696	; Used during the smash attack dodge.  If the boss hits
			; a screen edge, this is set to the direction to move.
!blink = $13D8		; Set if the boss should be blinking with invincibility.
!attackPref = $0DC3	; For each attack, 0 = Prefer this attack, 1 = avoid this attack.  3 bytes, as shoot, dash, smash.
!timeToSpawn = $13F2	; During the idle state, an enemy will spawn when this hits 0.  Set to a random number.

StateJumpTable: dw Idle
                dw Hurt
                dw FlyOff
                dw BulletBillPrep 
                dw BulletBillAttack 
                dw $0000
                dw DashRightPrep 
                dw DashRight
                dw DashLeftPrep
                dw DashLeft
                dw Summon
                dw SmashDown
                dw SmashReturn
                dw SmashLook
                dw $0000
                dw Defeat

GFXJumpTable:	dw IdleGFX
                dw HurtGFX
                dw FlyOffGFX
                dw BulletBillPrepGFX
                dw BulletBillAttackGFX
                dw $0000
                dw DashRightPrepGFX
                dw DashRightGFX
                dw DashLeftPrepGFX
                dw DashLeftGFX
                dw SummonGFX
                dw SmashDownGFX
                dw SmashReturnGFX
                dw SmashLookGFX
                dw $0000
                dw DefeatGFX
                
Attacks: db $03, $06, $0B, $00, $00

SpawnableSprites:	db $04, $07, $09, $0C
             
SineBob:                
db $00, $01, $01, $02, $03, $03, $04, $04, $05, $05, $06, $06, $06, $07, $07, $07 
db $07, $07, $07, $07, $06, $06, $06, $05, $05, $04, $04, $03, $03, $02, $01, $01 
db $00, $FF, $FF, $FE, $FD, $FD, $FC, $FC, $FB, $FB, $FA, $FA, $FA, $F9, $F9, $F9 
db $F9, $F9, $F9, $F9, $FA, $FA, $FA, $FB, $FB, $FC, $FC, $FD, $FD, $FE, $FF, $FF 

FireSFX:
db $2D,$2E,$2F,$30,$31,$32,$33,$34

}

DetermineNextAttack:
{
	PHX			;
	LDY #$FF		; Set Y to #$00
.getRandom			;
	INY			; 
	JSL $01ACF9		; \ 
	LDA $148D		; |
	AND #$03		; |
	CMP #$03		; | Get a random number between 0 and 2.
	BEQ .getRandom		; /
	CMP !prevAttack		; \ Don't repeat the current attack.
	BEQ .getRandom		; /
	TAX			; > Potential attack into X.
	LDA !attackPref,x	; \ If this attack's status is 0, then this attack is okay.
	BEQ .doAttack		; /
	INY			; \ If we've gotten this attack twice in a row, then do it.
	BNE .doAttack		; /
	BRA .getRandom		; Otherwise, get a new one.
				;
.doAttack			;
	STX !nextAttack		;
	STX !prevAttack		;
	PLX			;
	RTS			;
}

SetToIdle:
{
 STZ $0F6B
 STZ !stateTime
 STZ $14D4,x
 LDA #$40
 STA $D8,x
 JSL $01ACF9
 REP #$20
 LDA $148D
 AND #$00FF
 CLC
 ADC #$017F
 STA !timeLeft
 LDA #$0080
 STA !xpos
 LDA #$0040
 STA !ypos
 SEP #$20
 STZ !attackTimes
 STZ !canFreeFall
RTS
}

EndAttackFly:
{
    LDA #$02
    STA !state
    LDA #$30
    STA $AA,x
    STZ !xspeed
    LDA #$40
    STA !timeLeft
    STZ !stateTime
RTS
}

print "INIT ",pc
{
	JSR SUB_HORZ_POS
	TYA	
	STA $157C,x

 JSR SetToIdle
 LDA #$FF
 STA !prevAttack
 STZ $15DC,x		; Don't interact with objects
 
 ;JSL $01ACF9        ;Set up the order for the attacks the boss is vulnerable to.
 ;LDA $148D
 ;STA $4204
 ;LDA $148E
 ;STA $4205
 ;LDA #$03
 ;STA $4206
 ;NOP #8
 ;LDA $4216
 ;STA !vulnerable
 ;.loop
 ;   JSL $01ACF9
 ;   LDA $148D
 ;   STA $4204
 ;   LDA $148E
 ;   STA $4205
 ;   LDA #$03
 ;   STA $4206
 ;   NOP #8
 ;   LDA $4216
 ;   CMP !vulnerable
 ;   BEQ .loop
 ;   STA !vulnerable+1
 ;   
 ;.loop2
 ;   JSL $01ACF9
 ;   LDA $148D
 ;   STA $4204
 ;   LDA $148E
 ;   STA $4205
 ;   LDA #$03
 ;   STA $4206
 ;   NOP #8
 ;   LDA $4216
 ;   CMP !vulnerable
 ;   BEQ .loop2
 ;   CMP !vulnerable+1
 ;   BEQ .loop2
 ;   STA !vulnerable+2

    LDA #$FF
    STA !timeToSpawn
STZ !health
STZ !attacked
STZ !attacked+1
STZ !attacked+2
STZ !attacked+3
STZ !attacked+4
STZ !attacked+5
STZ !attacked+6
STZ !attacked+7
STZ !attacked+8
STZ !attacked+9
STZ !attacked+10
STZ !attacked+11
STZ !attacked+12
STZ !attacked+13
STZ !attacked+14
STZ !attacked+15
 
 
 
 
.return
 RTL
}

print "MAIN ",pc
{
	PHB
	PHK
	PLB
	JSR Run
	PLB
	RTL
}

Return:
	RTS

Run:
{
	LDA $9D
	BNE GFXJump
	LDA $14C8,x
	CMP #$08
	BNE Return

    REP #$20
    INC !stateTime
    SEP #$20
    LDA $E4,x
    STA !xpos
    LDA $14E0,x
    STA !xpos+1
    LDA $D8,x
    STA !ypos
    LDA $14D4,x
    STA !ypos+1
    JSL $018032

    PHX
    LDA !state
    TAX
    STA $7FFFF0,x
    ASL
    TAX
    REP #$20
    LDA.w StateJumpTable,x
    STA $00
    SEP #$20
    PLX
    JMP ($0000)

GFXJump:
    JMP graphics

    Finish:
    
        LDA !xpos
        STA $E4,x
        LDA !xpos+1
        STA $14E0,x
        LDA !ypos
        STA $D8,x
        LDA.w !ypos+1
        STA $14D4,x
        JSL $01802A
	
	
    JSR PlayerInteract

        LDA !state
        BNE GFXJump	; If the state is 0 (idle), do a bunch of misc. stuff before we handle graphics.
	STA $7FFFE5
        LDA $14E0,x
        XBA
        LDA $E4,x
        REP #$20
        STA $00
        LDA $00
	
	BMI .moveToRightSnap
	CMP #$0018
	BCC .moveToRight
	CMP #$00D8
	BCC .skip
.moveToLeft
	SEP #$20
	LDA !xspeed
	BMI +
	LDA !xspeed
	SEC
	SBC #$06
	STA !xspeed
	+
	BRA .skip

.moveToRightSnap
STZ $E4,x
STZ $14E0,x
.moveToRight
	SEP #$20
	LDA !xspeed
	BPL +
	LDA !xspeed
	CLC
	ADC #$06
	STA !xspeed
	+
.skip
	SEP #$20
        ;BMI .moveToLeft
	;CMP #$0018
	;BCC .moveToRight
        ;CMP #$00F0
        ;BCS .moveToRight
	;CMP #$00D8
	;BCS .moveToLeft
        ;SEP #$20
        ;BRA .Finish2
    
;.snapToLeft
;        SEP #$20
;        STZ $14E0,x
;        STZ $E4,x
;        BRA .Finish2
;.snapToRight
;        SEP #$20
;        STZ $14E0,x
;        LDA #$F0
;        STA $E4,x
;        BRA .Finish2

;.moveToLeft
;	SEP #$20
;	LDA !xspeed
;	SEC
;	SBC #$04
;	STA !xspeed
 ;       BRA .Finish2
;	
;.moveToRight
;	SEP #$20
;	LDA !xspeed
;	CLC
;	ADC #$04
;	STA !xspeed







.Finish2
	LDY #$FF
        REP #$20
	LDA $D3
	CLC
	ADC #$0010
        ;LDA #$FF
        STA $00
        ;STA $01
        SEP #$20
        
        PHX         ;Loop through all sprites in order to dodge thrown sprites.
        LDX #$00
.loop   CPX #$0C
        BEQ .Finish3
        LDA $14C8,x
        CMP #$0A
        BEQ .getY
CMP #$09
BEQ .getY
.returnFromGetY
.NoGetY INX
        BRA .loop
.Finish3

PLX

REP  #$20
LDA !ypos
CLC
ADC #$0028
SEC
SBC $00
;BPL +
;EOR #$FFFF
;INC
;+
CMP #$0005
BPL .dodge
BCS .dontDodge
.dodge
LDA $00
CMP #$00A8
BCS .dontDodge
LDA $00
SEC
SBC #$0028
STA $00
SEP #$20
LDA $01
STA $14D4,x
LDA $00
STA $D8,x
LDA #$01
STA !canFreeFall
.dontDodge
SEP #$20
BRA graphics
      
        
.getY
LDA $14D4,x
XBA
LDA $D8,x
REP #$20
CMP $00
BCS .no
STA $00
TXY
.no
SEP #$20
BRA .returnFromGetY

AddBob:

    LDA $14
    AND #$3F
    TAX
    LDA SineBob,x
    CLC
    ADC $01
    STA $01

    BRA ReturnFromBobbing
        
        ;LDA !xpos
        ;STA $E4,x
        ;LDA !xpos+1
        ;STA $14E0,x
        ;LDA !ypos
        ;STA $D8,x
        ;LDA !ypos+1
        ;STA $14D4,x
        	;JSR SUB_OFF_SCREEN_X0
graphics:

JSR Lightning
LDA $9D
BNE +
LDA $14
AND #$01
BNE +
DEC $1466
PHX
LDA $14
LSR
LSR
TAX
LDA SineBob,x
CLC
ADC #$08
STA $1468
PLX
+
	
LDA !blink
    BEQ +
    LDA $14
    AND #$04
    BEQ +
    RTS
+

    JSR GET_DRAW_INFO
    PHX
    
    LDA !state
    BEQ AddBob
    CMP #$04
    BEQ AddBob
    CMP #$0D
    BEQ AddBob
ReturnFromBobbing:

    LDA !state
    TAX
    ASL
    TAX
    REP #$20
    LDA.w GFXJumpTable,x
    STA $0E
    SEP #$20
    PLX
    JMP ($000E)



incsrc Sprites\BlimpDuckGFX.asm

}


; Run when the boss is idle.  Just handles hovering above Mario and switching to new attacks when appropriate.
Idle:
{
    LDA !timeToSpawn
    BNE +
    JSR SpawnEnemy
    JSL $01ACF9
    LDA $148D
    AND #$60
    STA !timeToSpawn
    +
    CMP #$09
    BNE +
    LDA #$06
    STA $1DFC
+
    DEC !timeToSpawn
    JSR GetXFlip

    STZ !blink
    STZ !yspeed
    REP #$20
    LDA !ypos
    BMI .AdjustY
    CMP #$0080
    BCS .NoAdjustY
.AdjustY
    SEP #$20
    LDA #$04
    LDY !canFreeFall
    BEQ .fourIsOkay
    LDA #$10
.fourIsOkay
    STA !yspeed  
.NoAdjustY
    REP #$20
    ;INC !stateTime
    LDA !xpos
    SEC
    SBC $D1
    SEP #$20
    BPL .GoLeft
    BRA .GoRight
 
 .GoLeft
    DEC !xspeed
    LDA !xspeed
    BPL .done1
    CMP #$F9
    BCC .done1
    LDA #$F9
    STA !xspeed
    BRA .done1
 .GoRight
    INC !xspeed
    LDA !xspeed
    BMI .done1
    CMP #$08
    BCS .done1
    LDA #$08
    STA !xspeed

 .done1
 
    REP #$20
    
    LDA !timeToSpawn
    CMP #$10
    BCC .dontTouchTime
    DEC !timeLeft
    LDA !timeLeft
    SEP #$20
    BEQ +
.dontTouchTime
    JMP Finish    
 +   
 JSR DetermineNextAttack   
; .switchToAttack
;    JSL $01ACF9
;    LDA $148D
;
;    AND #$03
;    CMP !prevAttack
;    BEQ .switchToAttack
;    ;CMP #$03
;    ;BEQ .switchToAttack
;    ;LDA #$03
;    STA !nextAttack
;    STA !prevAttack
JSR EndAttackFly
    JMP Finish
    
}

; Run when the boss is hurt (and stunned briefly).  Nothing much happens here.
Hurt:
{
	LDA !health
	CMP #$02
	BCC +
	LDA !stateTime
	CMP #$01
	BNE +
	JSL $83A6CA		; Code that kills most sprites.  Do this now instead of waiting for time to run out.
	+
	
	LDA !stateTime
	CMP #$1D
	BCS +
	;LDA #$15
	;STA $9D
	;STA !stateTime
	STZ !yspeed
	JMP Finish
+	    
	LDA #$04
	STA !nextAttack
	LDA #$02
	STA !state
	
	LDA !health
	CMP #$02
	BCS .kill
	JSR EndAttackFly
	INC !health
	
	
	
	LDA #$12
	STA !yspeed
	REP #$20
	LDA $148D
	AND #$00FF
	CLC
	ADC #$017F
	STA !timeLeft
	
	SEP #$20
	STZ !attackTimes
	STZ !canFreeFall
	INC !blink
	JMP Finish
	
.kill

	STZ !stateTime
	STZ !stateTime+1
	LDA #$0F
	STA !state
	STZ !attacked+$D		; Needed for the graphics routine.
	STZ !yspeed
	
	STA $7FFFE2
	REP #$20
	
	LDA !xpos		; \
	BPL +			; |
	STZ !xpos		; |
+				; | Limit the boss's X position to on the screen.
	CMP #$0100		; |
	BCC +			; |
	LDA #$00FF		; |
	STA !xpos		; |
+				; / 

	LDA !ypos		; \
	BPL +			; |
	STZ !ypos		; |
+				; | Limit the boss's Y position to on the screen.
	CMP #$0100		; |
	BCC +			; |
	LDA #$00FF		; |
	STA !ypos		; |
+				; / 

	SEP #$20
	
	LDA !xpos		; \
	CMP #$80		; |
	BCC +			; |
	EOR #$FF		; | Get the distance to the center of the screen, x
	INC			; |
	INC $140C		; |
	+			; |
	STA $140B		; /
	
	LDA !ypos		; \
	CMP #$80		; |
	BCC +			; |
	EOR #$FF		; | Get the distance to the center of the screen, y
	INC			; |
	INC $1416		; |
	+			; |
	STA $1415		; /
	
	
	
	JMP Finish
	;LDA #$15
	;STA $1887	; shake the ground
	;LDA #$0D	;/
	;STA $9E,x	;\ Sprite = Bob-omb.
	;LDA #$08	;/
	;STA $14C8,x	;\ Set status for new sprite.
	;JSL $07F7D2	;/ Reset sprite tables (sprite becomes bob-omb)..
	;LDA #$01	;\ .. and flag explosion status.
	;STA $1534,x	;/
	;LDA #$40	;\ Time for explosion.
	;STA $1540,x
	;LDA #$09	;\
	;STA $1DFC	;/ Sound effect.
	;LDA #$1B
	;STA $167A,x
	
	;LDA #$FF		; \
	;STA $1493		; |
	;STA $0DDA		; |end the level.
	;LDA #$0B		; |
	;STA $1DFB		; / Change music 
	;JMP Finish
	
}
 
; Run when the boss is zooming off the top of the screen. 
FlyOff:
{
    DEC !timeLeft
    LDA $AA,x
    SEC
    ;CLV
    SBC #$06
    BVS .no
    STA $AA,x
 .no   
 
 REP #$20
 LDA !ypos
 CMP #$0020
 SEP #$20
 BMI .BeginAttack
    ;LDA !timeLeft
    ;BEQ .BeginAttack
    JMP Finish
    
 .BeginAttack
 
 STZ !stateTime
 STZ !stateTime+1
 
 PHX
    
 ;JSR BulletSpawnerExists
 ;BCC .noSummon
 ;   LDX #$02
 ;   BRA +
 ;.noSummon

    LDX !nextAttack
;    +
    LDA Attacks,X
    PLX
    STA !state
    LDA !nextAttack
    CMP #$04
    BNE .no2
JSR SetToIdle
.no2
    JMP Finish
 }
 
 ; Handles the entirety of the bullet bill attack.
BulletBillPrep:
{
    LDY !state		; \
    LDA !attacked,y	; |
    BEQ +		; | If this Mario has scored a hit on this attack AND we're doing this attack a second time, then try not to do it any more.
    LDA #$01		; |
    STA !attackPref	; |
+			; /
    STZ !ypos
    STZ !ypos+1
    STZ $AA,x
    REP #$20
    LDA !stateTime
    CMP #$01F0
    SEP #$20
    BEQ .showSelf
 
    LDA $14
    AND #$1F
    BNE .return
    LDA #$09
    STA $1DFC
    STZ $00
    JSR ShootBulletBill
.return
    JMP Finish
    
 .showSelf
    LDA #$04
    STA !state
    STZ $AA,x
    REP #$20
    LDA #$00DA
    STA !ypos
    LDA $D1
    ;BMI .shootFromLeft
    CMP #$0080
    BCC .shootFromRight
    ;BRA .shootFromLeft
    
 .shootFromLeft
;JSR GetXFlip
    SEP #$20
    PHY
    LDA #$00
    LDY !attacked+4
    BEQ +
    LDA #$40
    +
    STA !facing
    PLY
    
    REP #$20
    LDA #$FFF0
    STA !xpos
    SEP #$20
    STZ !side
    LDA #$FF
    JMP Finish
 .shootFromRight
    SEP #$20
    PHY
    LDA #$40
    LDY !attacked+4
    BEQ +
    LDA #$00
    +
    STA !facing
    PLY
;JSR GetXFlip

    REP #$20
    LDA #$0100
    STA !xpos
    SEP #$20
    LDA #$01
    STA !side
    JMP Finish

BulletBillAttack:

    STZ $AA,x
    REP #$20
        LDA #$00DA
    STA !ypos
    LDA !xpos
    BMI .goRight
    CMP #$0003
    BCC .goRight
    CMP #$00ED
    BCC .done
    DEC !xpos
    BRA .done
    .goRight
    INC !xpos  
    
 .done 
    LDA !side
    BEQ .checkLeft
;.checkRight
    REP #$20
    LDA $D1
    CMP #$00C5
    SEP #$20
    BCC .doNothing
    LDY !state
    LDA !attacked,y
    BEQ .doNothing
    LDA #$04
    STA !nextAttack
    LDA #$02
    STA !state
    JSR EndAttackFly
    STZ $AA,x
    LDA #$08
    STA !xspeed
BRA .doNothing

 .checkLeft
    REP #$20
    LDA $D1
    CMP #$002B
    SEP #$20
    BCS .doNothing
    LDY !state
    LDA !attacked,y
    BEQ .doNothing
    LDA #$04
    STA !nextAttack
    LDA #$02
    STA !state
    JSR EndAttackFly
    STZ !yspeed
    LDA #$F8
    STA !xspeed
 
 .doNothing
    SEP #$20
    LDA $14
    AND #$1F
    BNE .return
    LDA #$09
    STA $1DFC
    LDA #$01
    STA $00
    JSR ShootBulletBill
.return
    JMP Finish
    
    
    
    
ShootBulletBill:
    LDA $00
    BNE .manual
    REP #$20
    LDA $D1
    CLC
    ADC #$0008
    LSR #7
    BNE .shootFromLeft
    BRA .shootFromRight
    
 .manual
 LDA !side
 BNE .shootFromRight
 
    
 .shootFromLeft
 SEP #$20
 LDA #$1C
 STA $00
 LDA #$E0
 STA $01
 LDA #$FF
 STA $02
 REP #$20
 
 LDA $D3
 CLC
 ADC #$0008
 SEP #$20
 STA $03
 XBA
 STA $04
 STZ $05
 JSR GenerateSprite
RTS

 .shootFromRight
 SEP #$20
 LDA #$1C
 STA $00
 LDA #$10
 STA $01
 LDA #$01
 STA $02
 REP #$20
 
 LDA $D3
 CLC
 ADC #$0008
 SEP #$20
 STA $03
 XBA
 STA $04
 STZ $05
 JSR GenerateSprite
RTS
 }  


; Handles the entirety of the dashing attack.
DashRightPrep:
{

    LDY !state		; \
    LDA !attacked,y	; |
    BEQ +		; | If this Mario has scored a hit on this attack AND we're doing this attack a second time, then try not to do it any more.
    LDA #$01		; |
    STA !attackPref+1	; |
+			; /

LDA $148D
AND #$01
BEQ +
JMP DashLeftPrep
+
LDA #$40
STA !facing
LDA !attackTimes
CMP #$05
BCC .doAttack

    LDA #$04
    STA !nextAttack
    LDA #$02
    STA !state
    JSR EndAttackFly
    JMP Finish

.doAttack
REP #$20
STZ !xpos
STZ !stateTime
SEP #$20
INC !state
			;RTS intentionally left out.

DashRight:
LDA !attackTimes
CMP #$05
BCC .doAttack
    LDA #$04
    STA !nextAttack
    LDA #$02
    STA !state
    JSR EndAttackFly
    JMP Finish

.doAttack
REP #$20
LDA !stateTime
CMP #$0050
BCS .notAiming
LDA $D3
;CLC : ADC #$0008
STA !ypos
BRA .done


.notAiming
CMP #$0070
BEQ .startAttacking
BCS .attacking
BRA .done

.startAttacking
LDA #$FFE0
STA !xpos
BRA .done

.attacking
LDA !xpos
CLC : ADC #$0008
STA !xpos


CMP #$0100
BCS .noSFX
LSR #5
PHX
TAX
LDA FireSFX,x
STA $1DFC
PLX
.noSFX

LDA #$0180
SEC
SBC !xpos
BPL .done
SEP #$20
STZ !facing
LDA #$08
STA !state
INC !attackTimes
LDA !attackTimes
BEQ .done
LDA #$09
STA !state
REP #$20
LDA #$0070
STA !stateTime
LDA $D3
;CLC : ADC #$0008
STA !ypos
SEP #$20
.done
REP #$20
;INC !stateTime
SEP #$20
STZ !yspeed
JMP Finish








DashLeftPrep:

    LDY !state		; \
    LDA !attacked,y	; |
    BEQ +		; | If this Mario has scored a hit on this attack AND we're doing this attack a second time, then try not to do it any more.
    LDA #$01		; |
    STA !attackPref+1	; |
+			; /
STZ !facing


LDA !attackTimes
CMP #$05
BCC .doAttack

    LDA #$04
    STA !nextAttack
    LDA #$02
    STA !state
    JSR EndAttackFly
    JMP Finish

.doAttack
REP #$20
LDA #$00F0
STA !xpos
STZ !stateTime
SEP #$20
LDA #$09
STA !state

			;RTS intentionally left out.

DashLeft:
LDA !attackTimes
CMP #$05
BCC .doAttack
    LDA #$04
    STA !nextAttack
    LDA #$02
    STA !state
    JSR EndAttackFly
    JMP Finish

.doAttack
REP #$20
LDA !stateTime
CMP #$0050
BCS .notAiming
LDA $D3
;CLC : ADC #$0008
STA !ypos
BRA .done


.notAiming
CMP #$0070
BEQ .startAttacking
BCS .attacking
BRA .done

.startAttacking
LDA #$0110
STA !xpos
BRA .done

.attacking
LDA !xpos
SEC : SBC #$0008
STA !xpos
CMP #$0100
BCS .noSFX
LSR #5
PHX
TAX
LDA FireSFX,x
STA $1DFC
PLX
.noSFX


LDA #$FF80
SEC
SBC !xpos
BMI .done
SEP #$20
LDA #$40
STA !facing

LDA #$06
STA !state
INC !attackTimes
LDA !attackTimes
BEQ .done
LDA #$07
STA !state
REP #$20
LDA #$0070
STA !stateTime
LDA $D3
;CLC : ADC #$0008
STA !ypos
SEP #$20
.done
REP #$20
;INC !stateTime
SEP #$20
STZ !yspeed
JMP Finish
}


BulletSpawnerExists:
{
	PHX
	LDX #$0C
	
-
	LDA $7FAB9E,x
	CMP #$41
	BEQ .maybeEndSpawn
.returnToLoop
	DEX
	BPL -
	BRA .exists
	
.maybeEndSpawn
LDA $14C8,x
CMP #$08
BEQ .noneExists
BRA .returnToLoop
	
	.noneExists
	PLX
	CLC
	RTS
	.exists
	PLX
	SEC
	RTS
	}

; Handles the entirety of the summoning attack.
StopSummoning:
{
					; Spawn the bullet shooter.
	;LDA $186C,x
	;BNE EndSpawn
;	PHX
;	LDX #$0C
;	
;-
;	LDA $7FAB9E,x
;	CMP #$41
;	BEQ .maybeEndSpawn
;.returnToLoop
;	DEX
;	BPL -
;	BRA +
	
;.maybeEndSpawn
;LDA $14C8,x
;CMP #$08
;BEQ .EndSpawn2
;BRA .returnToLoop
	
;	+
	
;	PLX
	
;	JSR BulletSpawnerExists
;	BCC .noSpawnShooter
;	JSL $02A9DE
;	BMI .EndSpawn
;	LDA #$01				; Sprite state ($14C8,x).
;	STA $14C8,y
;	PHX
;	TYX
;	LDA #$41		; This the sprite number to spawn.
;	STA $7FAB9E,x
;	PLX
;	LDA #$80
;	STA $00E4,y
;	LDA #$00
;	STA $14E0,y
;	LDA #$80
;	STA $00D8,y
;	LDA #$00
;	STA $14D4,y
;	PHX
;	TYX
;	JSL $07F7D2
;	JSL $0187A7
;	LDA #$08
;	STA $7FAB10,x
;	PLX
;	LDA #$10
;	STA $1DF9
;.noSpawnShooter	
;    LDA #$04
;    STA !nextAttack
;    LDA #$02
;    STA !state
;    JSR EndAttackFly
;.EndSpawn
;    JMP Finish
;.EndSpawn2
;    PLX
;    BRA -


Summon:
;STZ !yspeed
;LDA !attackTimes
;CMP #$04
;BEQ StopSummoning
;LDA $14
;AND #$1F
;BNE .return

;JSL $01ACF9
;LDA $148D
;AND #$03
;PHX
;TAX
;LDA SpawnableSprites,x
;PLX
;STA $00
;REP #$20
;LDA #$0020
;STA $03
;
;.loop
;SEP #$20
;JSL $01ACF9
;REP #$20
;LDA $148D
;AND #$00FF
;STA $01
;LDA $D1
;SEC : SBC $01
;BPL .noInvert
;EOR #$FFFF
;INC
;.noInvert
;CMP #$0040
;BCC .loop

;SEP #$20
;CLC		;ROLL WITH CARRY ASDFDSAFDFAFASD
;ROL		;Make the spawned sprite face the correct direction
;AND #$01
;STA $05
;JSR GenerateSprite
;BMI .return
;LDA #$23
;STA $1DF9
;INC !attackTimes
;.return

;JMP Finish
}


; Handles the entirety of the smashing attack
{

; Handles when the player should be launched upwards.
PlayerLaunch:
{
LDA $0F6B		; 
BEQ .noLaunch		; 
			; 
DEC $0F6B		;

REP #$20		; 
LDA $96			; \
CMP #$0040		; | If the player is offscreen, don't move him upwards.
BCC .offscreen		; /
SEC			; 
SBC #$0008		; 
STA $96			; 
SEP #$20		; 
LDA $7D			; 
BPL +			; 
LDA #$80		; 
STA $7D			; 
+			; 
RTS			; 
.offscreen		; 
LDA #$0040		; 
STA $96			; 
SEP #$20		; 

.noLaunch
RTS
}

; Handles the boss's dodging maneuver for when the player tries to jump on him.
DodgePlayer:
{
	STZ !yspeed


	REP #$20
	STZ $00			; $00 indicates if the boss is aligned horizontally with the player.
				; $01 indicates if the player is about to hit the boss vertically.
	LDA $94
	CMP !xpos
	BMI +
	SEP #$20
	LDA #$40
	STA !facing
	BRA ++
+
	SEP #$20
	STZ !facing
++
	
	REP #$20
	LDA $94			; \
	CLC			; | Player x + 16 goes into $02
	ADC #$0010		; |
	STA $02			; /
	LDA !xpos		; \
	CLC			; | Boss x + 16 goes into $04
	ADC #$0010		; |
	STA $04			; /
	
	LDA $94			; \
	CMP !xpos		; | If player x < boss x, second check. 
	BCC .secondCheck	; /
	LDA $94			; \
	CMP $04			; | If player x > boss x + 16, second check. 
	BCS .secondCheck	; /
	INC $00			; The player is above the boss
	BRA .doneCheckingX	;

.secondCheck	
	LDA $02			; \
	CMP !xpos		; | If the player x + 16 < boss x, second check.
	BCC .doneCheckingX	; /
	LDA $02			; \
	CMP $04			; | If the player x + 16 > boss x + 16, second check.
	BCS .doneCheckingX	; /
	
	INC $00			; The player is above the boss
				; Some sort of maneuvering is required.
				
.doneCheckingX

+
	
	LDA $96			; \
	CLC			; |
	ADC #$0024		; | If player y + 36 < boss y, nothing
	CMP !ypos		; |
	BCC +			; /
	INC $01	
	
+

	SEP #$20
	LDA $00
	BNE .dodgeRequired
	BRA .noDodgeRequired
.dodgeRequired


	REP #$20
	LDA !xpos
	BMI .setForceDodgeRight
	CMP #$0008
	BCC .setForceDodgeRight
	CMP #$00F8
	BCS .setForceDodgeLeft
	BRA .noForceDodge
.setForceDodgeRight
	SEP #$20
	LDA #$30
	STA !forceXSpeed
	BRA .noForceDodge
.setForceDodgeLeft
	SEP #$20
	LDA #$D0
	STA !forceXSpeed
.noForceDodge
	SEP #$20
	LDA !forceXSpeed
	BEQ +
	LDA !forceXSpeed
	STA !xspeed
	BRA .skipManualSpeed
	
+
				; Right now, the player is at the same
				; x position as the boss (within 16 pixels).
				; If the boss is to the left of the player,
				; dodge left.  Otherwise, dodge right
	
	REP #$20		;
	LDA !xpos		; \
	CMP $94			; | 
	SEP #$20		; |
	BCS .moveRight		; /
.moveLeft			;
	LDA #$E0		; \
	STA !xspeed		; /
	BRA +			;
.moveRight			;
	LDA #$20		; \
	STA !xspeed		; /
+
.skipManualSpeed

	;LDA $01			; \
	;BEQ .noMoveDown		; |
	;LDA $7D			; |
	;STA !yspeed		; /
	
.noMoveDown
	RTS
.noDodgeRequired
	JSR LimitX
	RTS
}

LimitX:
{
	STA $7FFFC2
	REP #$20
	LDA !xpos
	BMI .limitLeft
	CMP #$0008
	BCC .limitLeft
	CMP #$00F8
	BCS .limitRight
	BRA .noLimit
.limitLeft
	LDA #$0008
	STA !xpos
	BRA .noLimit
.limitRight
	LDA #$00F8
	STA !xpos
.noLimit
	SEP #$20
	
	LDA !xspeed
	BEQ +
	BMI ++
	LDA !xspeed
	CLC
	ADC #$04
	STA !xspeed
	BVS .setToZero
++
	LDA !xspeed
	SEC
	SBC #$04
	STA !xspeed
	BVC .setToZero
	
+
	RTS
	
.setToZero
	STZ !xspeed
	RTS
}


SmashDown:
{

    LDY !state		; \
    LDA !attacked,y	; |
    BEQ +		; | If this Mario has scored a hit on this attack AND we're doing this attack a second time, then try not to do it any more.
    LDA #$01		; |
    STA !attackPref+2	; |
+			; /

STZ !yspeed

JSR PlayerLaunch

REP #$20
LDA !stateTime
CMP #$0070
BCS +
JMP .return2
+
LDA !ypos
BPL +
STZ !ypos	; If the ypos is negative, zero it.
SEP #$20
JMP Finish
+
CLC
ADC #$001B
STA !ypos
CMP #$00F0
SEP #$20
BCC .doNotStartSmash
LDA $1B97
BNE .doNotStartSmash
LDA #$FF
STA $1B97		; 1B97 is used as a timer for the wave effect.
LDA !xpos		; Intentionally 8-bit.
LSR #3
EOR #$1F
STA $1B98		; 1B98 is used for the offset of the wave effect.

REP #$20		;
LDA !xpos		; Launches the player.
CLC			;
ADC #$0060		;
CMP $D1			;
BCS .doNotLaunchPlayer	;
CLC			;
ADC #$0040		;
CMP $D1			;
BCC .doNotLaunchPlayer	;
SEP #$20		;
LDA #$80		; Set the "player fly offscreen" timer.
STA $0F6B		;
STA $7D

.doNotLaunchPlayer
STA $7FFFE4
REP #$20		;
LDA !xpos		; Launches the player, but tests if the player is to the left.
SEC			;
SBC #$0060		;
CMP $D1			;
BCS .doNotLaunchPlayer2	;
SEC			;
SBC #$0040		;
CMP $D1			;
BCC .doNotLaunchPlayer2	;
SEP #$20		;
LDA #$80		; Set the "player fly offscreen" timer.
STA $0F6B		;
STA $7D

.doNotLaunchPlayer2

.doNotStartSmash
REP #$20
LDA !ypos
CMP #$0190	; If the boss is significantly below the screen, fly back to the top of the screen.
SEP #$20
BCC .return
LDA #$0C
STA !state
.return
JMP Finish
.return2
LDA #$0080
STA !ypos
SEP #$20
JMP Finish
}



SmashReturn:
{
JSR PlayerLaunch

REP #$20
LDA !ypos
CMP #$00A0
SEP #$20
BCS .keepMovingUp
LDA !yspeed
CLC
ADC #$08
STA !yspeed
BMI .return		; Don't change the state until the yspeed has become 0.
LDA #$0D		; Change the state to SmashLook
STA !state
.return
JMP Finish

.keepMovingUp
LDA #$80
STA !yspeed
JMP Finish



}
SmashLook:
{
STZ !yspeed
JSR PlayerLaunch


.noPlayerControl
REP #$20
LDA $D3
SEC
SBC #$0030
BMI .exit
CMP !ypos
SEP #$20
BCS .finishAndSetToIdle

	LDY !state
	LDA !attacked,y
	BEQ +
JSR DodgePlayer
+
JMP Finish


.finishAndSetToIdle
 REP #$20
 LDA !ypos
 CMP #$0080
 SEP #$20
 BCC +
 DEC !yspeed
 RTS
+
 STZ !yspeed
 STZ !stateTime
 STZ !state
 REP #$20
 LDA $148D
 AND #$00FF
 CLC
 ADC #$017F
 STA !timeLeft
 
 SEP #$20
 STZ !attackTimes
 STZ !canFreeFall
.exit
SEP #$20
JMP Finish
}
}

AlreadyHit:
{
PLX
	LDA $1656,x
	PHA
	LDY !state
	CPY #$07
	BEQ +
	CPY #$09
	BEQ +
	BRA .end
+	
	ORA #$10
	STA $1656,x
	JSL $81A7DC			; Check for player contact

	BCC .end
	
	REP #$20
	LDA $D3
	CLC
	ADC #$0014
	CMP !ypos
	SEP #$20
	BPL .spriteWins
	
	LDA $140D
	BNE .spinJump
.spriteWins
	JSL $80F5B7	; hurt the player
	BRA .end
.spinJump
	JSL $81AB99	; display contact GFX
	JSL $81AA33	; boost the player's Y speed
	LDA #$02
	STA $1DF9
	

.end
	PLA
	STA $1656,x
RTS
}

PlayerInteract:
{
	LDA !state		;
	CMP #$07		;
	BEQ +			;
	CMP #$09		;
	BEQ +			;
	BRA .nevermind		;
	+			; No collision if the boss is just displaying an arrow.
	REP #$20		;
	LDA !stateTime		;
	CMP #$0070		;
	SEP #$20		;
	BCS .nevermind		;
	RTS			;
.nevermind			;
	
	
	STA $7FFFC4
	PHX
	LDX !state	;
	LDA !attacked,x	;
	BNE AlreadyHit	; Cannot be hurt twice during the same attack.
	
	CPX #$04	; Only allow the boss to be hurt
	BEQ +		; during certain phases.
	CPX #$07	;
	BEQ +		;
	CPX #$09	;
	BEQ +		;
	CPX #$0B	;
	BEQ +		;
	CPX #$0D	;
	BEQ +		;
	BRA .exit
+
	PLX
	;REP #$20
	;LDA $94			; \
	;CLC			; | Player x + 16 goes into $02
	;ADC #$0010		; |
	;STA $02			; /
	;LDA !xpos		; \
	;CLC			; | Boss x + 16 goes into $04
	;ADC #$0010		; |
	;STA $04			; /
	
	;LDA $94			; \
	;CMP !xpos		; | If player x < boss x, second check. 
	;BCC .secondCheck	; /
	;LDA $94			; \
	;CMP $04			; | If player x > boss x + 16, second check. 
	;BCS .secondCheck	; /
	;INC $00			; The player is above the boss
	;BRA .noXContact		;

.secondCheck	
	;LDA $02			; \
	;CMP !xpos		; | If the player x + 16 < boss x, second check.
	;BCC .noXContact		; /
	;LDA $02			; \
	;CMP $04			; | If the player x + 16 > boss x + 16, second check.
	;BCS .noXContact		; /
	
	REP #$20
	LDA $96
	PHA
	CLC
	ADC #$0008
	STA $96
	SEP #$20

	JSL $81A7DC			; Check for player contact
	REP #$20
	PLA
	STA $96
	SEP #$20
	BCC .exit2
	LDA !state			; If the boss is smashing down, it always wins.
	CMP #$0B			;
	BEQ .spriteWins			;
	REP #$20
	LDA $D3
	CLC
	ADC #$0014
	CMP !ypos
	SEP #$20
	BPL .spriteWins
	JSL $81AB99	; display contact GFX
	JSL $81AA33	; boost the player's Y speed

	PHX
	LDX !state
	STZ !stateTime
	LDA #$01
	STA !attacked,x
	CPX #$07
	BNE +
	STA !attacked+9
	BRA ++
+
	CPX #$09
	BNE ++
	STA !attacked+7
++
	
	
	LDA #$20
	STA $1DF9
	LDA #$48
	STA $1DFC
	
	LDA #$01
	STA !state
.exit
	PLX
	RTS
.exit2	
	;REP #$20
	;LDA $96
	;SEC
	;SBC #$0008
	;STA $96
	;SEP #$20
	RTS
.noXContact
	RTS
.spriteWins
	JSL $80F5B7	; hurt the player
	RTS
}

; Handles everything related to the the boss falling off the screen in defeat.
{
Defeat:
	LDA #$FF	; Turn lightning off.
	STA $1FFC	;
	
	REP #$20
	LDA !ypos
	CMP #$0140
	BCC +
	SEP #$20
	STZ $14C8,x	; Destroy self.
	LDA #$FF		; \
	STA $1493		; |
	STA $0DDA		; |end the level.
	LDA #$06		; |:::::::::::::::::::::::was 80
	STA $1DFB		; / Change music 
	INC $13C6		; Prevent Mario from doing goal walk
	RTS
+
	
	LDA !stateTime
	CMP #$0020
	BCC +
	JMP .noMove
	+
	
	SEP #$20		; \
	LDA #$80		; |
	SEC			; |
	SBC $140B		; |
	STA $4202		; |
	LDA !stateTime		; |
	STA $4203		; |
	REP #$20		; |
	NOP #3			; |
	LDA $4216		; |
	STA $4204		; |
	SEP #$20		; |
	LDA #$20		; |
	STA $4206		; |
	NOP #8			; |
	LDA $4214		; |
				; |
	LDY $140C		; |
	BEQ +			; |
	STA $00			; |
	LDA #$00		; |
	SEC			; |
	SBC $140B		; |
	SEC			; |
	SBC $00			; |
	BRA ++			; |
	+			; |
	CLC			; |
	ADC $140B		; |
++				; |
	STA !xpos		; /
	
	
	SEP #$20		; \
	LDA #$80		; |
	SEC			; |
	SBC $1415		; |
	STA $4202		; |
	LDA !stateTime		; |
	STA $4203		; |
	REP #$20		; |
	NOP #3			; |
	LDA $4216		; |
	STA $4204		; |
	SEP #$20		; |
	LDA #$20		; |
	STA $4206		; |
	NOP #8			; |
	LDA $4214		; |
				; |
	LDY $1416		; |
	BEQ +			; |
	STA $00			; |
	LDA #$00		; |
	SEC			; |
	SBC $1415		; |
	SEC			; |
	SBC $00			; |
	BRA ++			; |
	+			; |
	CLC			; |
	ADC $1415		; |
++				; |
	STA !ypos		; /
.noMove
	REP #$20
	LDA !stateTime
	CMP #$0001
	BEQ .smoke
	CMP #$0030
	BEQ .smoke
	CMP #$0060
	BEQ .smoke
	CMP #$0068
	BEQ .smoke
	CMP #$0070
	BEQ .smoke
	CMP #$007C
	BEQ .smoke
	CMP #$0090
	BEQ .smoke
	CMP #$00A8
	BEQ .smoke
	CMP #$0100
	BEQ .kill
	BCS .falling
	SEP #$20
	STZ !yspeed
-	JMP Finish

.smoke
	SEP #$20
	JSR SpawnSmoke
	BRA -
.falling
	SEP #$20
	LDA $14
	AND #$03
	BNE +
	JSR SpawnSmoke
	STZ $1DFC
	+
	BRA -
	
.kill
	SEP #$20
	
	LDA #$C0		; "Jump" up, as if killed by an explosion.
	STA !yspeed		;
	
	PHX
	LDX #$00		; A bob-omb WILL spawn.  No matter what (0 is the most likely to not be used).
	
	LDA #$08		; \ No init
	STA $14C8,x		; /
	 
	LDA #$0D		; \ Sprite = bob-omb
	STA $9E,x		; /
	LDA !xpos		; \ 
	STA $E4,x		; | X pos
	LDA !xpos+1		; |
	STA $14E0,x		; /
	LDA !ypos		; \
	STA $D8,x		; | Y pos
	LDA !ypos+1		; |
	STA $14D4,x		; /
	 
	JSL $07F7D2		; Clear sprite tables
	LDA #$15		; \
	STA $1887		; / shake the ground
	LDA #$01		; \ .. and flag explosion status.
	STA $1534,x		; /
	LDA #$40		; \ Time for explosion.
	STA $1540,x		; /
	LDA #$09		; \
	STA $1DFC		; / Sound effect.
	LDA #$1B		;
	STA $167A,x		;
	PLX			;
	JMP Finish
}

SpawnSmoke:
{
	PHY                       
	LDY #$03		; \ loop that checks for free smoke image slot
-	LDA $17C0,y		; |
	BEQ .foundSlot		; |
	DEY			; |
	BPL -			; /
	INY			; if no free slot found, overwrite slot 0 ($17C0)
.foundSlot			;
	LDA #$01		; \ set smoke image
	STA $17C0,y		; /
	JSL $81ACF9		; \
	LDA $148D		; |
	AND #$0F		; |
	CLC			; |
	ADC !xpos		; | 
	SEC			; |
	SBC #$07		; |
	STA $17C8,y		; | set smoke position
	LDA $148E		; |
	AND #$0F		; |
	CLC			; |
	ADC !ypos		; |
	CLC			; |
	ADC #$08		; |
	STA $17C4,y		; /
	LDA #$13		; \ set time for smoke to be displayed
	STA $17CC,y		; /
	PLY                     ;
	LDA #$25
	STA $1DFC
	RTS                       ; Return 
}


SpawnEnemy:
{
	JSL $01ACF9
	LDA $148D
	AND #$03
	PHX
	TAX
	LDA SpawnableSprites,x
	PLX
	STA $00
	REP #$20
	LDA #$0020
	STA $03
	
	.loop
	SEP #$20
	JSL $01ACF9
	REP #$20
	LDA $148D
	AND #$00FF
	STA $01
	LDA $D1
	SEC : SBC $01
	BPL .noInvert
	EOR #$FFFF
	INC
	.noInvert
	CMP #$0040
	BCC .loop

	SEP #$20
	CLC		;ROLL WITH CARRY ASDFDSAFDFAFASD
	ROL		;Make the spawned sprite face the correct direction
	AND #$01
	STA $05
	JSR GenerateSprite
	BMI .return
	;LDA #$23
	;STA $1DF9
	;INC !attackTimes
.return
	RTS
}





































; Helper routines and such (sprite spawning, SUB_OFF_SCREEN, etc.)
{

DATA_04F6F8:        db $20,$58,$43,$CF,$18,$34,$A2,$5E
DATA_04F700:        db $07,$05,$06,$07,$04,$06,$07,$05
ADDR_04F708:        db $A9

Lightning:
		PHX                       
		LDX.w $0681               
		LDA.b #$10                
		STA.w $0682,X             
		STZ.w $0683,X             
		STZ.w $0684,X             
		STZ.w $0685,X             
		TXY                       
		LDX.w $1FFB               
		BNE ADDR_03E01B           
		LDA.w $190D               
		BEQ ADDR_03DFF0           
		REP #$20                  ; Accum (16 bit) 
		LDA.w $0701               
		BRA ADDR_03E031           
ADDR_03DFF0:	LDA $14                   ; Accum (8 bit) 
		LSR                       
		BCC ADDR_03E036           
		DEC $1FFC               
		BNE ADDR_03E036           
		TAX                       
		LDA ADDR_04F708,X       
		AND #$07                
		TAX                       
		LDA DATA_04F6F8,X       
		STA $1FFC               
		LDA DATA_04F700,X       
		STA $1FFB               
		TAX                       
		LDA #$08                
		STA $1FFD               
		LDA #$18                
		STA $1DFC               ; / Play sound effect 
ADDR_03E01B:	DEC $1FFD               
		BPL ADDR_03E028           
		DEC $1FFB               
		LDA #$04                
		STA $1FFD               
ADDR_03E028:	TXA                       
		ASL                       
		TAX                       
		REP #$20                  ; Accum (16 bit) 
		LDA.l $00B5DE,X       
ADDR_03E031:	STA $0684,Y 
		SEP #$20                  ; Accum (8 bit) 
ADDR_03E036:	LDX $1429               
		LDA #$00       
		TAX                       
		LDA #$0E                
		STA $00                   
ADDR_03E042:	LDA $0705,X
		STA $0686,Y             
		INX                       
		INY                       
		DEC $00                   
		BNE ADDR_03E042           
		TYX                       
		STZ $0686,X             
		INX                       
		INX                       
		INX                       
		INX                       
		STX $0681
		PLX                                      
		RTS                       ; Return 




GenerateSprite:    ;$00 = sprite to spawn, $01-$02 = x pos, $03-$04 = ypos, $05 = direction to face
 JSL $02A9DE
 BMI .return
 LDA #$01
 STA $14C8,y
 
 LDA $00
 STA $009E,y
 LDA $01
 STA $00E4,y
 LDA $02
 STA $14E0,y
 LDA $03
 STA $00D8,y
 LDA $04
 STA $14D4,y
 
 LDA $05
 STA $00C2,y
 
 PHX
 TYX
 JSL $07F7D2
 PLX
LDA #$00
 .return
RTS

;region Sprite Routines

;=================;
;SUB_HORZ_POS
;=================;

SUB_HORZ_POS:
	LDY #$00
	LDA $D1
	SEC
	SBC $E4,x
	STA $0F
	LDA $D2
	SBC $14E0,x
	BPL SPR_L16
	INY
SPR_L16:
	RTS

;=================;
;SUB_VERT_POS
;=================;

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

;=================;
;SUB_OFF_SCREEN
;=================;

SPR_T12:
	db $40,$B0
SPR_T13:
	db $01,$FF
SPR_T14:
	db $30,$C0,$A0,$C0,$A0,$F0,$60,$90
	db $30,$C0,$A0,$80,$A0,$40,$60,$B0
SPR_T15:
	db $01,$FF,$01,$FF,$01,$FF,$01,$FF
	db $01,$FF,$01,$FF,$01,$00,$01,$FF

SUB_OFF_SCREEN_X1:
	LDA #$02
	BRA STORE_03
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
	BEQ RETURN_35
	LDA $5B
	AND #$01
	BNE VERTICAL_LEVEL
	LDA $D8,x
	CLC
	ADC #$50
	LDA $14D4,x
	ADC #$00
	CMP #$02
	BPL ERASE_SPRITE
	LDA $167A,x
	AND #$04
	BNE RETURN_35
	LDA $13
	AND #$01
	ORA $03
	STA $01
	TAY
	LDA $1A
	CLC
	ADC SPR_T14,y
	ROL $00
	CMP $E4,x
	PHP
	LDA $1B
	LSR $00
	ADC SPR_T15,y
	PLP
	SBC $14E0,x
	STA $00
	LSR $01
	BCC SPR_L31
	EOR #$80
	STA $00
SPR_L31:
	LDA $00
	BPL RETURN_35
	ERASE_SPRITE:
	LDA $14C8,x
	CMP #$08
	BCC KILL_SPRITE
	LDY $161A,x
	CPY #$FF
	BEQ KILL_SPRITE
	LDA #$00
	STA $1938,y
KILL_SPRITE:
	STZ $14C8,x
RETURN_35:
	RTS

VERTICAL_LEVEL:
	LDA $167A,x
	AND #$04
	BNE RETURN_35
	LDA $13
	LSR A
	BCS RETURN_35
	LDA $E4,x
	CMP #$00
	LDA $14E0,x
	SBC #$00
	CMP #$02
	BCS ERASE_SPRITE
	LDA $13
	LSR A
	AND #$01
	STA $01
	TAY
	LDA $1C
	CLC
	ADC SPR_T12,y
	ROL $00
	CMP $D8,x
	PHP
	LDA $001D
	LSR $00
	ADC SPR_T13,y
	PLP
	SBC $14D4,x
	STA $00
	LDY $01
	BEQ SPR_L38
	EOR #$80
	STA $00
SPR_L38:
	LDA $00
	BPL RETURN_35
	BMI ERASE_SPRITE

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

;================;
;GET_DRAW_INFO
;================;

SPR_T1:
	db $0C,$1C
SPR_T2:
	db $01,$02

GET_DRAW_INFO:
	STZ $186C,x
	STZ $15A0,x
	LDA $E4,x
	CMP $1A
	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
	CLC
	ADC.w #$0040
	CMP.w #$0180
	SEP #$20
	ROL A
	AND #$01
	STA $15C4,x
	BNE INVALID

	LDY #$00
	LDA $1662,x
	AND #$20
	BEQ ON_SCREEN_LOOP
	INY
ON_SCREEN_LOOP:
	LDA $D8,x
	CLC
	ADC SPR_T1,y
	PHP
	CMP $1C
	ROL $00
	PLP
	LDA $14D4,x
	ADC #$00
	LSR $00
	SBC $1D
	BEQ ON_SCREEN_Y
	LDA $186C,x
	ORA SPR_T2,y
	STA $186C,x
ON_SCREEN_Y:
	DEY
	BPL ON_SCREEN_LOOP
	LDY $15EA,x
	LDA $E4,x
	SEC
	SBC $1A
	STA $00
	LDA $D8,x
	SEC
	SBC $1C
	STA $01
	RTS

INVALID:
	PLA
	PLA
	RTS
;endregion
}