!BulletSprNum = $00 	; Sprite number to insert the bullet/skypop as.
!NorvegSprNum = $01	; Sprite number to insert Norveg as.
!ClusSprNum = $09   	; Sprite number to insert the cluster bullet as.
!DeadState = $15	; State which is the initial death state of Norveg.
!DeadState2 = $0A	; State which is the initial death state of Norveg.

!StatusPtr = $C2	; Pointer to status of sprite
!FlameOrNorveg = $1504	; Whether sprite is flame... or Norveg. Big difference!
!FlameTimer = $151C	; Timer of each flame. Low nibble and high nibble.
!LaserVertPos = $1528	; Vertical position of white laser
!FlameNumber = $1534	; Bitwise number of flames. Multiple can be on-screen, too. Bit-wise.
			; NOTE: Regular flame uses this to determine OAM slots. Sort of.
!TimeBfrShtReg = $1540	; Time before shooting another missile, among many other things (status timer).
			; NOTE: Regular flame uses this as a life timer. When zero, the flame is extinguished.
!FlashTimer = $154C	; Norveg flashes when this timer is on.
!LaserPtr = $1558	; Pointer to white laser
!SecStatusPtr = $1564	;
!FlameThrowExcp = $1570 ; Store stuff here if flames are thrown.
!WalkingPosPtr = $1594	; Pointer to where Norveg should walk.
!GraphicsPtr = $1602	; Norveg's pose.
			; The button sprite also uses it in its laser routine.
!NorvegPal = $7FFF00	; Norveg palette.
!DecreasePlayerHP = $7FFFED ;
!DecreaseNorvegHP = $7FFFEE
!WrnSgnlTime = $7FFFF0  ; Timer during the warning signal phase (before flame explosions)
!FlameNo = $7FFFF1	; Flame number when thrown, used in loop only.
!SpecialShot = $7FFFF2	; If non-zero, cluster shots do much more damage. Only occurs in "explosion" attack.
!BossModus = $7FFFF3	; 0 = boss modus 1; 1 = boss modus 2.
!HstFrndLaser = $7FFFF4 ; 0 = laser is hostile; 1 = laser is friendly
!EndOfBoss1 = $7FFFF5	; Indicates the end of the first phase.
!MarioBeaten = $7FFFFD  ; Mario = dead flag
!PlayerHP = $7FFFFE 	; \ Player HP
!NorvegHP = $7FFFFF 	; / Norveg HP

;--------------;
; Init Routine ;
;--------------;

print "INIT ",pc
LDA !FlameOrNorveg,x	; \ Return if a regular flame.
BNE ReturnInit		; /
LDA #$3F		; \ Initialization process. Wait #$3F frames.
STA !TimeBfrShtReg,x	; /
JSR TransferHDMA	; HDMA gradients and such.
LDA #$03		; \ Use pose 3.
STA !GraphicsPtr,x	; /
LDA $D8,x		; \ Actually move up four pixels.
SEC			;  |
SBC #$04		;  |
STA $D8,x		;  |
LDA $14D4,x		;  |
SBC #$00		;  |
STA $14D4,x		; /

ReturnInit:
RTL			; Return. You should know that, silly.

;--------------;
; Main Routine ;
;--------------;

print "MAIN ",pc
LDA !MarioBeaten	; \ Is Mario beaten yet?
BEQ MarioNotDeadYet	; / No? Then run sprite.
STZ $14C8,x		; Kill it otherwise. Like that.
RTL			; And return.

MarioNotDeadYet:
PHB			; \ Wrapper.
PHK			;  |
PLB			;  | So we can use 16-bit addressing. Cool stuff really.
JSR SPRITE_ROUTINE	;  |
PLB			;  |
RTL			; / Return

ClusterBallRoutine:
LDA !StatusPtr,x	; \ Pointers
PHX			;  |
ASL A			;  |
TAX			;  |
JMP (ClusterBallPtr,x)	; /

TriggerRoutine:
LDA !StatusPtr,x	; \ Pointers
PHX			;  |
ASL A			;  |
TAX			;  |
JMP (TriggerPtr,x)	; /

BossModusZero:
LDA !FlameOrNorveg,x	; \ Check if sprite = trigger
CMP #$01		;  |
BEQ TriggerRoutine	; / If so, run completely different routine.
CMP #$02		; \ Check if cluster ball instead.
BEQ ClusterBallRoutine	; / Yes? Okay, run that routine.
LDA !NorvegHP		; \ Is Norveg HP => 1?
CMP #$01		;  |
BPL IsNotDead2		; / Then he's probably healthy and well-fed.
LDA #$08		; \ Disable channel 3.
TRB $0D9F		; /
LDA !StatusPtr,x	; \ Status pointer beyond !DeadState2?
CMP #!DeadState2	;  |
BCS IsNotDead2		; / Then don't keep "dying" when Norveg HP <= 1
LDA !FlashTimer,x	; \ Norveg cannot die if he's still flashing.
BNE IsNotDead2		; /
LDA #!DeadState2	; \ This is Norveg's first "death".
STA !StatusPtr,x	; /
LDA #$3F		; \ Amount of time to wait in that phase.
STA !TimeBfrShtReg,x	; /

IsNotDead2:
JSR SUB_OFF_SCREEN_HB	; Handle off-screen situations
LDA !StatusPtr,x	; \ Pointers
PHX			;  |
ASL A			;  |
TAX			;  |
JMP (StatusPtr2,x)	; /

Return0:
RTS			; Return!

SPRITE_ROUTINE:
JSR SkyPopGFX		; Graphics routine.
LDA $14C8,x		; \ Don't run code if sprite dies.
CMP #$08		;  |
BNE Return0		;  |
LDA $9D			;  | Or if sprite is locked.
BNE Return0		; /
LDA !BossModus		; \ Check if Norveg in phase 1 or 2.
BEQ BossModusZero	; / If in phase 1, go to BossModusZero and do not run following code.
LDA !FlameOrNorveg,x	; \ Check if sprite = flame.
BNE FlameRoutine	; / If so, run completely different routine.
LDA !NorvegHP		; \ Is Norveg HP => 1?
CMP #$01		;  |
BPL IsNotDead		; / Then he's probably healthy and well-fed.
LDA #$08		; \ Disable channel 3.
TRB $0D9F		; /
LDA !StatusPtr,x	; \ Status pointer beyond !DeadState?
CMP #!DeadState		;  |
BCS IsNotDead		; / Then don't keep dying when Norveg HP <= 1
LDA #!DeadState		; \ This is Norveg's ultimate death.
STA !StatusPtr,x	; /
LDA #$3F		; \ Amount of time to wait in that phase.
STA !TimeBfrShtReg,x	; /

IsNotDead:
JSR SUB_OFF_SCREEN_HB	; Handle off-screen situations
LDA !StatusPtr,x	; \ Pointers
PHX			;  |
ASL A			;  |
TAX			;  |
JMP (StatusPtr,x)	; /

;--------------------------------;
; Routine which handles Flames.. ;
;--------------------------------;

FlameRoutine:
LDA !TimeBfrShtReg,x	; \ Flame must be extinguished when his time is over.
BEQ KillFlame		; /
JSL $01802A		; Update positions based on speed.
JSR HurtOnFlameContact	; Hurt player if interacting with flame.
LDA !TimeBfrShtReg,x	; \ If flame's timer is still above...
CMP #$60		;  | this value...
BCS ReturnFlameRt	;  | then branch.
DEC !TimeBfrShtReg,x	; / Otherwise, the timer will run twice as fast (RAM already decrements once per frame + this decrement)

ReturnFlameRt:
RTS			; Come back.

KillFlame:
STZ $14C8,x		; \ Put an end to it.
RTS			; / Then come back.

HurtOnFlameContact:
JSL $03B664		; \ Mario clipping.
JSR GetFlameClipping	;  | Flame clipping.
JSL $03B72B		;  | Compare.
BCC NoContactFlame	; / Carry clear? Return. Carry set? Go on.
LDA $1497		; \ Check if player is immune to attacks
ORA $1490		;  |
ORA $71			;  |
BNE NoContactFlame	; / If so, don't get hurt.
LDA #$04		; \ Sound effect.
STA $1DF9		; /
LDA #$01		; \ Hurt animation.
STA $71			; /
LDA #$12		; \ Decrease a whopping #$12 HP. Ouch!
CLC			;  |
ADC !DecreasePlayerHP	;  |
STA !DecreasePlayerHP	; /

NoContactFlame:
RTS			; And return.

;-------------------------;
; United Status of Norveg ;
;-------------------------;

StatusPtr:
dw GeneralState			; 0 - "Static" state
dw GeneratePartOfCluster	; 1 - Generate a part of the cluster laser stream
dw GeneratePartOfCluster	; 2 - Generate a part of the cluster laser stream
dw GeneratePartOfCluster	; 3 - Generate a part of the cluster laser stream
dw GeneratePartOfCluster	; 4 - Generate a part of the cluster laser stream
dw GeneralState			; 5 - "Static" state
dw DetermineAttack		; 6 - Runs one of Norveg's other attacks. This can be quite variable
dw ResetLaserGen1		; 7 - Initialize laser 1
dw GenerateWhiteLaser1		; 8 - Generate laser 1
dw ResetState			; 9 - Reset state (back to zero)
dw ResetLaserGen2		; A - Initialize laser 2
dw GenerateWhiteLaser2		; B - Generate laser 2
dw ResetState			; C - Reset state (back to zero)
dw HomeInBegin			; D - Home in on player while shooting - first phase
dw HomeInMid			; E - Home in on player while shooting - second pmhase
dw HomeInMid			; F - Home in on player while shooting - third phase
dw HomeInStop			; 10 - Stop the "homing in" phase
dw MoveInPlace			; 11 - Move in place to shoot small laser bullets
dw ResetState			; 12 - Reset state (back to zero)
dw ThrowFlame			; 13 - Throw bomb
dw ResetState			; 14 - Reset state (back to zero)
dw IsDeadWait			; 15 - Wait before dying
dw IsDeadWarningSignal		; 16 - Gives off warning signal
dw IsDeadExplosion		; 17 - Explode (actually just flames).
dw IsDeadExplosion		; 18 - Explode (actually just flames).
dw IsDeadExplosion		; 19 - Explode (actually just flames).
dw EndExplosions		; 1A - Explode, but end it.
dw FallDown			; 1B - Norveg falls down after being burnt to a crisp.
dw FirstState			; 1C - Initial state in phase two.

StatusPtr2:
dw OnGroundState		; 0 - "Static" state
dw DetermineAttack2		; 1 - Runs one of Norveg's other attacks. This can be quite variable.
dw GenerateLaserTrigger		; 2 - Generate laser trigger sprite.
dw ResetState2			; 3 - Reset state (back to zero)
dw HoldUpCluster1616		; 4 - Shoot 16x16 cluster ball
dw GenerateCluster1616		; 5 - Shoot 16x16 cluster ball
dw ResetState2			; 6 - Reset state (back to zero)
dw GroundLaser			; 7 - Shoot ground laser
dw HomingClusterBall		; 8 - Shoot homing cluster ball
dw NorvegClone			; 9 - Norveg gets a clone
dw NorvegDead			; A - Norveg is "dying"

TriggerPtr:
dw StaticTrigger		; 0 - "Static" state
dw ResetLaserGen3		; 1 - Initialize laser 1
dw GenerateWhiteLaser3		; 2 - Generate laser 1
dw KillButton

ClusterBallPtr:
dw MoveTowardsCenter		; 0 - Move rapidly
dw AMillionLittleFibres		; 1 - Explode. Erradicate sprite.

;--------------------;
; Cluster Ball Ptr   ;
;--------------------;

ClusterMarioInt:
JSL $03B664			; \ Get Mario clipping.
JSR GetButton1Clipping		;  | Cluster ball clipping.
JSL $03B72B			;  | Compare
BCC NoContact536		; / No contact? Branch. Contact? Go on.
LDA $1497			; \ Flashing blah
ORA $1490			;  | Immunity blah
ORA $71				;  | Animating blah
BNE NoContact536		; / Branch blah blah
LDA #$10			; \ Subtract #$10 off Mario's HP. Not too nice.
CLC				;  |
ADC !DecreasePlayerHP		;  |
STA !DecreasePlayerHP		; /
LDA #$04			; \ SFX
STA $1DF9			; /
LDA #$01			; \ Ani
STA $71				; /

NoContact536:
RTS				; Return To SubRouTIne. Also RTL.

MoveTowardsCenter:
PLX				; Pull X? What sorcery is this? (This is to keep the original sprite slot right)
JSR ClusterMarioInt		; Cluster ball must interact with Mario. Otherwise he's lame.
LDA !TimeBfrShtReg,x		; \ As long as his time isn't running out yet, he can still survive and move.
BNE Move			; /
INC !StatusPtr,x		; Uh-oh, next state.

Move:
JSL $01802A			; Update positions and speeds
LDA $14D4,x			; \ Seal off borderline Y.
BEQ DontMessWithYPos		;  |
BMI DontMessWithYPos		;  |
LDA $D8,x			;  |
CMP #$A0			;  |
BCC DontMessWithYPos		;  |
LDA #$A0			;  | #$01A0 is the right position.
STA $D8,x			; /

DontMessWithYPos:
LDA $14E0,x			; \ Seal off borderline X.
BMI ResetXPos			;  |
BNE ResetXPos2			;  |
LDA $E4,x			;  |
CMP #$F1			;  |
BCC NoResetXPos			;  |

ResetXPos2:
STZ $14E0,x			;  |
LDA #$F0			;  |
STA $E4,x			;  |
BRA NoResetXPos			;  |

ResetXPos:
STZ $14E0,x			;  |
STZ $E4,x			; /

NoResetXPos:
RTS				; Return.

AMillionLittleFibres:
PLX				; Pull X so we get correct sprite slots.
JSR ExplodeClusters		; Ho boy, fireworks.
STZ $14C8,x			; Kill it instantly.
RTS				; Return.

;--------------------;
; Button Physics.... ;
;--------------------;

ReturnBecauseOfAir:
RTS

StaticTrigger:
PLX
JSL $01802A
LDA $1588,x
AND #$04
BEQ ReturnBecauseOfAir
PHX
LDX #$0B

NorvegButtonLoop:
LDA $14C8,x
CMP #$08
BCC IncreaseNorvegButtonLoop
LDA $7FAB9E,x
CMP #!NorvegSprNum
BNE IncreaseNorvegButtonLoop
LDA !FlameOrNorveg,x
BNE IncreaseNorvegButtonLoop
JSR GetNorvegClipping
PLX
JSR GetButton2Clipping
PHX
JSL $03B72B
BCC IncreaseNorvegButtonLoop
PLX
INC !StatusPtr,x
LDA #$00
STA !HstFrndLaser
RTS

IncreaseNorvegButtonLoop:
DEX
BPL NorvegButtonLoop
PLX
JSL $03B664
JSR GetButton1Clipping
JSL $03B72B
BCC NoContact535
LDA $7D
CMP #$10
BMI NoContact535
INC !StatusPtr,x
LDA #$01
STA !HstFrndLaser

NoContact535:
RTS

ResetLaserGen3:
PLX
LDA !TimeBfrShtReg,x
BNE ResetLaserGeneric2
LDA #$60
STA !LaserVertPos,x
LDA #$17
STA $1DFC

ResetLaserGeneric2:
LDA !TimeBfrShtReg,x
BNE Return645
INC !StatusPtr,x
LDA #$FF
STA !TimeBfrShtReg,x
STA !LaserPtr,x
JSR TransferHDMA

Return645:
RTS

KillButton:
PLX
STZ $14C8,x
RTS

;---------------------------------;
; The beginning of the beginning! ;
;---------------------------------;

HoldUpCluster1616:
PLX
JSR CollisionLazor
LDA #$04
STA !GraphicsPtr,x
LDA !TimeBfrShtReg,x
BNE NoInc1616
INC !StatusPtr,x

NoInc1616:
RTS

GenerateCluster1616:
PLX
JSR CollisionLazor
LDA #$03
STA !GraphicsPtr,x
PHX
LDX #$0B

LoopForButton2:
LDA $14C8,x
CMP #$08
BCC IncreaseButtonLoop2
LDA $7FAB9E,x
CMP #!NorvegSprNum
BNE IncreaseButtonLoop2
LDA !FlameOrNorveg,x
CMP #$02
BNE IncreaseButtonLoop2
PLX
BRA RtrnFlameLoop3

XSpeedToGive:
db $CF,$30

XDispGen:
db $14,$FC

XDispHiGen:
db $00,$FF

IncreaseButtonLoop2:
DEX
BPL LoopForButton2
PLX
JSL $02A9DE			; \ get an index to an unused sprite slot, return if all slots full
BMI RtrnFlameLoop3 		; / after: Y has index of sprite being generated   
LDA #$08                	; \ set sprite status for new sprite
STA $14C8,y             	; /
PHX
LDA #!NorvegSprNum
TYX
STA $7FAB9E,x
PLX
LDA $E4,x
PHY
LDY $157C,x
SEC
SBC XDispGen,y
PLY
STA $00E4,y      
LDA $14E0,x
PHY
LDY $157C,x
SBC XDispHiGen,y
PLY
STA $14E0,y
LDA $D8,x
SEC
SBC #$0C      
STA $00D8,y 
LDA $14D4,x
SBC #$00 
STA $14D4,y         
PHX                 
TYX                 
JSL $07F7D2         
JSL $0187A7         
LDA #$88
STA $7FAB10,x
PLX             
LDA #$02
STA !FlameOrNorveg,y
LDA $157C,x
PHX
TAX
LDA #$B8
STA $00AA,y
LDA XSpeedToGive,x
STA $00B6,y
PLX
LDA #$2F
JSR RANDOM
CLC
ADC #$10
STA !TimeBfrShtReg,y

RtrnFlameLoop3:
INC !StatusPtr,x
RTS

GroundLaser:
PLX
LDA #$03
STA !GraphicsPtr,x
STZ !StatusPtr,x
RTS

HomingClusterBall:
PLX
LDA #$03
STA !GraphicsPtr,x
STZ !StatusPtr,x
RTS

NorvegClone:
PLX
LDA #$03
STA !GraphicsPtr,x
STZ !StatusPtr,x
RTS

OnGroundState:
PLX
LDA #$03
STA !GraphicsPtr,x
JSR MoveNorvegFixed
JSR CollisionLazor
STZ $AA,x
STZ $B6,x
JSL $01802A
LDA !TimeBfrShtReg,x
BNE ReturnOnGround
INC !StatusPtr,x

ReturnOnGround:
RTS

XTableFixedNorveg:
db $D0,$80,$30,$08,$F8

YTableFixedNorveg:
db $2C,$2C,$2C,$5C,$5C

DoHorizontalFirst:
LDA $E4,x
SEC
SBC XTableFixedNorveg,y
INC A
CMP #$03
BCS ProblemsWithXCoordinate
LDA $D8,x
CMP #$2C
BEQ DrawPosition
BRA ProblemsWithYCoordinate

MoveNorvegFixed:
LDY !WalkingPosPtr,x
LDA YTableFixedNorveg,y
CMP #$2C
BEQ DoHorizontalFirst
LDA $D8,x
CMP #$5C
BNE ProblemsWithYCoordinate
LDA $E4,x
SEC
SBC XTableFixedNorveg,y
INC A
CMP #$03
BCC DrawPosition

ProblemsWithXCoordinate:
LDA $E4,x
CMP XTableFixedNorveg,y
BCS MoveToTheLeftNorveg
LDA #$20
STA $B6,x
STZ $AA,x
LDA #$01
STA $157C,x
BRA EndSpeedsNorveg

MoveToTheLeftNorveg:
LDA #$DF
STA $B6,x
STZ $AA,x
STZ $157C,x

EndSpeedsNorveg:
JSL $01802A
RTS

DrawPosition:
LDA #$04
JSR RANDOM
CMP !WalkingPosPtr,x
BEQ DrawPosition
STA !WalkingPosPtr,x
RTS

ProblemsWithYCoordinate:
LDA YTableFixedNorveg,y
CMP #$2C
BEQ GoUpIfNotCorrect
LDA $14D4,x
BEQ GoDownIfNotCorrect
LDA $D8,x
CMP #$5C
BCC GoDownIfNotCorrect
BEQ EndSpeedsNorveg

GoUpIfNotCorrect2:
LDA #$E0
STA $AA,x
BRA EndSpeedsNorveg

GoDownIfNotCorrect:
LDA #$20
STA $AA,x
BRA EndSpeedsNorveg

GoUpIfNotCorrect:
LDA $14D4,x
BEQ GoDownIfNotCorrect
LDA $D8,x
CMP #$2C
BCC GoDownIfNotCorrect
BEQ EndSpeedsNorveg
BRA GoUpIfNotCorrect2

XPosButton:
db $28,$78,$C8

GenerateLaserTrigger:
PLX
LDA #$03
STA !GraphicsPtr,x
PHX
LDX #$0B

LoopForButton:
LDA $14C8,x
CMP #$08
BCC IncreaseButtonLoop
LDA $7FAB9E,x
CMP #!NorvegSprNum
BNE IncreaseButtonLoop
LDA !FlameOrNorveg,x
CMP #$01
BNE IncreaseButtonLoop
PLX
BRA RtrnFlameLoop2

IncreaseButtonLoop:
DEX
BPL LoopForButton
PLX
JSL $02A9DE			; \ get an index to an unused sprite slot, return if all slots full
BMI RtrnFlameLoop2 		; / after: Y has index of sprite being generated   
LDA #$08                	; \ set sprite status for new sprite
STA $14C8,y             	; /
PHX
LDA #!NorvegSprNum
TYX
STA $7FAB9E,x
PLX
LDA #$02
JSR RANDOM
PHY
TAY
LDA XPosButton,y
PLY
STA $00E4,y  
LDA #$40         
STA $00D8,y     
LDA #$00
STA $14E0,y
INC A       
STA $14D4,y         
PHX                 
TYX                 
JSL $07F7D2         
JSL $0187A7         
LDA #$88
STA $7FAB10,x
PLX             
LDA #$01
STA !FlameOrNorveg,y
LDA $1686,y
AND #$7F
STA $1686,y
LDA #$E0
STA $00AA,y

RtrnFlameLoop2:
INC !StatusPtr,x
RTS

;-----------------;
; Is he dead now? ;
;-----------------;

NorvegDead:
PLX
LDA !EndOfBoss1
BNE DontSetThatFlag
LDA #$01
STA !EndOfBoss1
LDY #$03

SmokeaLoop2:
LDA $17C0,y
BEQ BreakSmoka2
DEY
BPL SmokeaLoop2
BRA DontSetThatFlag

BreakSmoka2:
LDA #$01
STA $17C0,y
LDA #$F0
STA $17C4,y
LDA #$08
STA $17C8,y
LDA #$1C
STA $17CC,y

DontSetThatFlag:
STZ !GraphicsPtr,x
LDA $14D4,x
BEQ ClearSpeedOut
LDA $AA,x
CMP #$C0
BMI DontDecreaseYFurther
SEC
SBC #$04

DontDecreaseYFurther:
STA $AA,x
BRA UpdateSpeedsNorveg1

ClearSpeedOut:
STZ $AA,x

UpdateSpeedsNorveg1:
LDA $1887
BNE Return3506
LDA #$FF
STA $1887

Return3506:
JSL $01802A
RTS

;------------------;
; Reset status II. ;
;------------------;

ResetState2:
PLX
JSR CollisionLazor
LDA #$03
STA !GraphicsPtr,x
LDA #$1F
STA !TimeBfrShtReg,x
STZ !StatusPtr,x
RTS

;-----------------;
; Choose attack 2 ;
;-----------------;

AttackTable2:
db $02,$04,$07,$08,$09		; List of pointer values that can be chosen.

DetermineAttack2:
PLX				; Pull X back (we pushed that prior to the pointer)
LDA #$03
STA !GraphicsPtr,x
JSR CollisionLazor
LDA #$04			; \ So there are 5 (#$04+1) options
JSR RANDOM			;  |
TAY				;  |
LDA AttackTable2,y		;  | For the attack.
STA !StatusPtr,x		; /
LDA #$20			; \ #$20 frames to wait at the beginning of the attack.
STA !TimeBfrShtReg,x		; / (That's for initializing)
RTS				; Return.

;---------------------;
; The end of the end! ;
;---------------------;

FallDown:
PLX
JSL $01802A
RTS

ToNextStatusPtr:
STZ $AA,x
STZ $B6,x
LDA #$2B
STA $1DFC
INC !StatusPtr,x
RTS

EndExplosions:
PLX
JSR DecreaseTimers
LDA !FlameNumber,x
BEQ ToNextStatusPtr
LDA !FlameTimer,x
AND #$F0
BNE NoStopOddFlame
LDA !FlameNumber,x
AND #$55
STA !FlameNumber,x

NoStopOddFlame:
LDA !FlameTimer,x
AND #$0F
BNE ReturnReturnFlames
LDA !FlameNumber,x
AND #$AA
STA !FlameNumber,x

ReturnReturnFlames:
RTS

DecreaseTimers:
LDA !TimeBfrShtReg,x
AND #$03
BNE DontDecreaseThatTimer
LDA !FlameTimer,x
AND #$0F
BEQ ZeroThere
DEC !FlameTimer,x

ZeroThere:
LDA !FlameTimer,x
AND #$F0
BEQ DontDecreaseThatTimer
LDA !FlameTimer,x
SEC
SBC #$10
STA !FlameTimer,x

DontDecreaseThatTimer:
RTS

OddBits:
db $02,$08,$20,$80

EvenBits:
db $01,$04,$10,$40

IsDeadExplosion:
LDX #$14

ClearOutPal:
STZ $0680,x
DEX
BPL ClearOutPal
LDX $15E9
LDA $13
AND #$0F
CMP #$02
BCS TheThingStarts
LDA !StatusPtr,x
CMP.b #!DeadState+3
BCS NoProblem
LDA !TimeBfrShtReg,x
CMP #$80
BCS TheThingStarts

NoProblem:
LDA $13
AND #$01
ASL A
ASL A
ASL A
CLC
ADC #$F3
STA $0683
LDY #$10
LDX #$0E
LDA $13
AND #$01
BEQ IsEvenFrame
LDY #$0A
LDX #$18

IsEvenFrame:
STY $0682
DEY
DEY
REP #$20

LoopPaletteChange:
LDA.l !NorvegPal,x
PHA
AND #$7C00
BEQ DontDoThisOne
SEC
SBC #$0400
STA $0684,y
STA !NorvegPal,x

DontDoThisOne:
LDA $01,s
AND #$03E0
BEQ DontDoThisTwo
SEC
SBC #$0020
ORA $0684,y
STA $0684,y
STA !NorvegPal,x

DontDoThisTwo:
LDA $01,s
AND #$001F
BEQ DontDoThisPLA
DEC A
ORA $0684,y
STA $0684,y
STA !NorvegPal,x

DontDoThisPLA:
PLA
BRA EndItNow

DontDoThisEnd:
STA $0684,y
STA !NorvegPal,x

EndItNow:
DEX
DEX
DEY
DEY
BPL LoopPaletteChange
SEP #$20

TheThingStarts:
PLX
LDA !TimeBfrShtReg,x
BEQ RepeatForever
JSR DecreaseTimers
LDA !SecStatusPtr,x
BNE NoAddOddFlame
LDA !FlameTimer,x
AND #$F0
BNE NoAddOddFlame
LDA #$03
JSR RANDOM
TAY
LDA !FlameTimer,x
ORA #$F0
STA !FlameTimer,x
LDA !FlameNumber,x
AND #$55
ORA OddBits,y
STA !FlameNumber,x

NoAddOddFlame:
LDA !FlameTimer,x
AND #$0F
BNE ReturnFrames
LDA #$03
JSR RANDOM
TAY
LDA !FlameTimer,x
ORA #$0F
STA !FlameTimer,x
LDA !FlameNumber,x
AND #$AA
ORA EvenBits,y
STA !FlameNumber,x
LDA #$17
STA $1DFC

ReturnFrames:
RTS

RepeatForever:
INC !StatusPtr,x
LDA #$FF
STA !TimeBfrShtReg,x
RTS

;---------------------------;
; The end of the beginning? ;
;---------------------------;

NowExplode:
INC !StatusPtr,x
LDA #$FF
STA !TimeBfrShtReg,x
LDA #$20
STA !SecStatusPtr,x
RTS

IsDeadWarningSignal:
PLX
LDA !TimeBfrShtReg,x
BEQ NowExplode
AND #$01
BNE NoIncreaseInRedness
LDA !TimeBfrShtReg,x
AND #$40
BNE IncreaseRedness
LDA !WrnSgnlTime
BEQ NoIncreaseInRedness
DEC A
STA !WrnSgnlTime
BRA NoIncreaseInRedness

IncreaseRedness:
LDA !WrnSgnlTime
CMP #$1F
BCS NoIncreaseInRedness
INC A
STA !WrnSgnlTime

NoIncreaseInRedness:
STZ $2121
LDA !WrnSgnlTime
STA $2122
STZ $2122
RTS

IsDeadWait:
PLX
LDA !TimeBfrShtReg,x
BNE Return1
INC !StatusPtr,x
LDA #$FF
STA !TimeBfrShtReg,x
LDA #$00
STA !WrnSgnlTime
LDA #$16
STA $1DFC
RTS

;-------------------;
; The generic state ;
;-------------------;

FirstState:
PLX
JSR CollisionBullets		; Norveg must have collision with Mario's bullets.
JSR SUB_GET_DIR			; \ Norveg's direction is dependant on Mario's position.
TYA				;  |
STA $157C,x			; /
LDA $0DAE
CMP #$0F
BEQ IncreaseStatueee
INC $0DAE
RTS

IncreaseStatueee:
STZ !StatusPtr,x
LDA #$20
STA !TimeBfrShtReg,x
RTS

GeneralState:
PLX				; Pull X back (we pushed that prior to the pointer)
STZ !GraphicsPtr,x		; Static Norveg pose.
LDA !TimeBfrShtReg,x		; \ Keep showing pose until this counter hits <= #$14
CMP #$14			;  |
BCS RegularPose			; /
LDA !StatusPtr,x
CMP #$05
BNE DefinitelyShoot
LDA !FlameThrowExcp,x
BNE DefinitelyFlame
LDA !TimeBfrShtReg,x
CMP #$13
BNE DefinitelyShoot
LDA #$04
JSR RANDOM
CMP #$04
BNE DefinitelyShoot
STA !FlameThrowExcp,x

DefinitelyFlame:
LDA #$02
STA !GraphicsPtr,x
BRA RegularPose

DefinitelyShoot:
LDA #$01			; \ Shooting Norveg pose.
STA !GraphicsPtr,x		; /

RegularPose:
JSR CollisionBullets		; Norveg must have collision with Mario's bullets.
JSR SUB_GET_DIR			; \ Norveg's direction is dependant on Mario's position.
TYA				;  |
STA $157C,x			; /
LDA !TimeBfrShtReg,x		; \ Timer zero?
BNE Return1			; / If not, return.
INC !StatusPtr,x		; Go to next pose.

Return1:
RTS				; Gee, I wonder what this does.


;----------------------------------;
; Throw flame routine. Neat stuff. ;
;----------------------------------;

ThrownFlameXLo:
db $F4,$20

ThrownFlameXHi:
db $FF,$00

IncreaseThisFieryState:
INC !StatusPtr,x
RTS

ThrowFlame:
PLX
STZ !FlameThrowExcp,x
JSR CollisionBullets
LDA #$02
STA !GraphicsPtr,x
LDA !TimeBfrShtReg,x
BEQ IncreaseThisFieryState
AND #$1F
CMP #$1F
BNE Return1
LDA #$17
STA $1DFC
LDA #$02
STA !FlameNo

LoopFlameThrower:
JSL $02A9DE			; \ get an index to an unused sprite slot, return if all slots full
BPL FlameLoops			; / after: Y has index of sprite being generated   
JMP RtrnFlameLoop

FlameLoops:
LDA #$08                	; \ set sprite status for new sprite
STA $14C8,y             	; /
PHX
LDA #!NorvegSprNum
TYX
STA $7FAB9E,x
PLX
PHY
LDA $157C,x
TAY
LDA $E4,x
CLC
ADC ThrownFlameXLo,y
PLY
STA $00E4,y
PHY
LDA $157C,x
TAY
LDA $14E0,x         
ADC ThrownFlameXHi,y
PLY
STA $14E0,y        
LDA $D8,x           
SEC                 
SBC #$0E            
STA $00D8,y         
LDA $14D4,x         
SBC #$00            
STA $14D4,y         
PHX                 
TYX                 
JSL $07F7D2         
JSL $0187A7         
LDA #$88
STA $7FAB10,x
PLX                 
LDA $157C,x
STA $157C,y
LDA #$01
STA !FlameOrNorveg,y
LDA #$80
STA !TimeBfrShtReg,y
LDA #$04
JSR RANDOM
CLC
ADC !FlameNo
ASL A
ASL A
ASL A
ASL A
EOR #$FF
INC A
STA $00AA,y
LDA #$0C
JSR RANDOM
CLC
ADC !FlameNo
ASL A
ASL A
PHA
LDA $157C,x
BNE FacingOtherDir
PLA
EOR #$FF
INC A
BRA FacingSameDir

FacingOtherDir:
PLA

FacingSameDir:
STA $00B6,y
LDA !FlameNo
STA !FlameNumber,y

RtrnFlameLoop:
LDA !FlameNo
DEC A
STA !FlameNo
BMI ReturnFlame45
JMP LoopFlameThrower

ReturnFlame45:
RTS

;---------------;
; Choose attack ;
;---------------;

AttackTable:
db $07,$0A,$0D,$01,$13		; List of pointer values that can be chosen.

DetermineAttack:
PLX				; Pull X back (we pushed that prior to the pointer)
JSR CollisionBullets		; Norveg must have collision with Mario's bullets.
JSR SUB_GET_DIR			; \ Norveg's direction is dependant on Mario's position.
TYA				;  |
STA $157C,x			; /
LDA !FlameThrowExcp,x
BNE ItsFlameAnyhow
LDA #$04			; \ So there are 5 (#$04+1) options
JSR RANDOM			;  |
CMP #$04
BNE ItsFlameAnyhow
LDA #$01

ItsFlameAnyhow:
TAY				;  |
LDA AttackTable,y		;  | For the attack.
STA !StatusPtr,x		; /
LDA #$20			; \ #$20 frames to wait at the beginning of the attack.
STA !TimeBfrShtReg,x		; / (That's for initializing)
RTS				; Return.

;---------------;
; Reset status. ;
;---------------;

ResetState:
PLX
JSR CollisionBullets
JSR SUB_GET_DIR
TYA
STA $157C,x
STZ !StatusPtr,x
LDA #$1F
STA !TimeBfrShtReg,x
RTS

;----------------------------------;
; Cluster laser generation routine ;
;----------------------------------;

GeneratePartOfCluster:
PLX
LDA !StatusPtr,x
CMP #$01
BNE NoSound
LDA #$00
STA !SpecialShot
LDA #$09
STA $1DFC

NoSound:
LDA #$01
STA !GraphicsPtr,x
JSR SUB_GET_DIR
TYA
STA $157C,x
JSR GenerateCluster
JSR CollisionBullets
INC !StatusPtr,x
LDA !StatusPtr,x
CMP #$05		; Status = #$05.
BCC Return2
LDA #$7F
STA !TimeBfrShtReg,x

Return2:
RTS

;-------------------;
; Norveg Homing In. ;
;-------------------;

HomingSpeedX:
db $D8,$27
HomingSpeedY:
db $E0,$1F

TargetDispYLo:
db $30,$AC
TargetDispYHi:
db $00,$FF
TargetDispXLo:
db $80,$80
TargetDispXHi:
db $FF,$00

CircleXDispLo:
db $EC,$6C,$6C,$6C,$EC,$6C,$6C,$6C
CircleXDispHi:
db $FF,$00,$00,$00,$FF,$FF,$FF,$FF
CircleYDispLo:
db $60,$40,$D8,$A0,$80,$A0,$D8,$40
CircleYDispHi:
db $00,$00,$FF,$FF,$FF,$FF,$FF,$00

HomeInBegin:
PLX
JSR CollisionBullets
LDA #$FF
STA !TimeBfrShtReg,x
INC !StatusPtr,x
JSL $01802A
RTS

HomeInMid:
PLX
JSR CollisionBullets
LDA $E4,x
CMP #$18
BCC DoFlip
CMP #$E8
BCC NoFlip

DoFlip:
LDA $157C,x
EOR #$01
STA $157C,x

NoFlip:
LDA !TimeBfrShtReg,x
BNE KeepHoming
LDA #$FF
STA !TimeBfrShtReg,x
INC !StatusPtr,x
JMP UpdateSpeeds

KeepHoming:
LDA $157C,x
AND #$01
TAY
LDA HomingSpeedX,y
STA $B6,x
LDA !TimeBfrShtReg,x
AND #$20
LSR A
LSR A
LSR A
LSR A
LSR A
TAY
LDA HomingSpeedY,y
CMP $AA,x
BEQ IsAlreadyGood
BPL IsMore
LDA $AA,x
SEC
SBC #$0C
BRA IsAlreadyGood

IsMore:
LDA $AA,x
CLC
ADC #$0C

IsAlreadyGood:
STA $AA,x
LDA !TimeBfrShtReg,x
AND #$1F
BNE NoSound1
LDA #$09
STA $1DFC

NoSound1:
LDA !TimeBfrShtReg,x
AND #$07
BNE UpdateSpeeds
LDA $94
PHA
LDA $95
PHA
LDA $96
PHA
LDA $97
PHA
LDA $157C,x
TAY
LDA $E4,x
CLC
ADC TargetDispXLo,y
STA $94
LDA $14E0,x
ADC TargetDispXHi,y
STA $95
STZ $01
LDA #$1F
JSR RANDOM
SEC
SBC #$10
STA $00
BCS CarryIsSet
LDA #$FF
STA $01

CarryIsSet:
LDA !TimeBfrShtReg,x
AND #$08
LSR A
LSR A
LSR A
TAY
LDA $D8,x
CLC
ADC TargetDispYLo,y
CLC
ADC $00
STA $96
LDA $14D4,x
ADC TargetDispYHi,y
CLC
ADC $01
STA $97
JSR GenerateCluster
PLA
STA $97
PLA
STA $96
PLA
STA $95
PLA
STA $94
LDA #$01
STA !SpecialShot

UpdateSpeeds:
JSL $01802A
RTS

HomeInStop:
PLX
JSR CollisionBullets
LDA !TimeBfrShtReg,x
BEQ NoReturnYet
CMP #$B0
BCC Explosions
STZ $157C,x
STZ $AA,x
LDA $E4,x
STA $00
LDA $14E0,x
STA $01
STZ $B6,x
REP #$20
LDA $00
CMP #$0080
SEP #$20
BCC MoveToRight
REP #$20
CMP #$0088
SEP #$20
BCC UpdateSpeeds
LDA #$E0
STA $B6,x
BRA UpdateSpeeds

MoveToRight:
LDA #$1F
STA $B6,x
BRA UpdateSpeeds

NoReturnYet:
LDA #$7F
STA !TimeBfrShtReg,x
INC !StatusPtr,x
RTS

Explosions:
AND #$1F
BNE Return7
JSR ExplodeClusters

Return7:
RTS

ExplodeClusters:
LDA #$09
STA $1DFC
LDA #$02
STA !SpecialShot
LDA $94
PHA
LDA $95
PHA
LDA $96
PHA
LDA $97
PHA
LDA $E4,x
PHA
LDA $14E0,x
PHA
LDA $D8,x
PHA
LDA $14D4,x
PHA
LDA !BossModus
BNE DontAlterPositions
LDA $E4,x
CLC
ADC #$24
STA $E4,x
LDA $14E0,x
ADC #$00
STA $14E0,x
LDA $D8,x
CLC
ADC #$1C
STA $D8,x
LDA $14D4,x
ADC #$00
STA $14D4,x

DontAlterPositions:
LDY #$07

LoopCircleShot:
LDA $E4,x
CLC
ADC CircleXDispLo,y
STA $94
LDA $14E0,x
ADC CircleXDispHi,y
STA $95
LDA $D8,x
ADC CircleYDispLo,y
STA $96
LDA $14D4,x
ADC CircleYDispHi,y
STA $97
PHY
JSR GenerateCluster
PLY
DEY
BPL LoopCircleShot
PLA
STA $14D4,x
PLA
STA $D8,x
PLA
STA $14E0,x
PLA
STA $E4,x
PLA
STA $97
PLA
STA $96
PLA
STA $95
PLA
STA $94
RTS

GoToReset:
INC !StatusPtr,x
RTS

MoveInPlace:
PLX
JSR CollisionBullets
STZ !GraphicsPtr,x
LDA !TimeBfrShtReg,x
BEQ GoToReset
LDA $E4,x
STA $00
LDA $14E0,x
STA $01
STZ $B6,x
REP #$20
LDA $00
CMP #$00D0
SEP #$20
BCC MoveTowardsEnd
REP #$20
CMP #$00D8
SEP #$20
BCC RejoinEnd
LDA #$E0
STA $B6,x
BRA RejoinEnd

MoveTowardsEnd:
LDA #$1F
STA $B6,x

RejoinEnd:
LDA $D8,x
STA $00
LDA $14D4,x
STA $01
STZ $AA,x
REP #$20
LDA $00
CMP #$010C
SEP #$20
BCC MoveToMid
REP #$20
CMP #$0114
SEP #$20
BCC RejoinUpdate
LDA #$EC
STA $AA,x
BRA RejoinUpdate

MoveToMid:
LDA #$13
STA $AA,x

RejoinUpdate:
JSL $01802A
RTS

;-------------------;
; HDMA in RAM table ;
;-------------------;

IncDecVPos1:
db $FD,$01,$02,$03,$03,$FE,$FE,$FE,$FE,$00,$01,$01,$01,$01,$02,$02
IncDecVPos2:
db $FE,$FE,$FD,$02,$01,$02,$FA,$FC,$02,$03,$02,$00,$FE,$FF,$FF,$FF
IncDecVPos3:
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00

TransferHDMA:
STZ $4300
LDA #$7F
STA $2183
INC A
STA $4301
STZ $2181
LDA #$E0
STA $2182
REP #$20
LDA.w #HDMA1
STA $4302
LDY.b #HDMA1/65536
STY $4304
LDA.w #HDMAEnd-HDMA1
STA $4305
SEP #$20
LDA #$01
STA $420B
RTS

;----------------------------------------------------------;
; This is a routine that initializes big lasers and stuff. ;
;----------------------------------------------------------;

ResetLaserGen2:
PLX
LDA #$70
STA $03FC
LDA #$C0
STA $03FD
LDA #$6B
STA $03FE
LDA #$B3
STA $03FF
LDA #$02
STA $049F
LDA !TimeBfrShtReg,x
BNE ResetLaserGeneric
LDA #$B7
STA !LaserVertPos,x
LDA #$17
STA $1DFC
BRA ResetLaserGeneric

ResetLaserGen1:
PLX
LDA #$70
STA $03FC
LDA #$10
STA $03FD
LDA #$6B
STA $03FE
LDA #$33
STA $03FF
LDA #$02
STA $049F
LDA !TimeBfrShtReg,x
BNE ResetLaserGeneric
STZ !LaserVertPos,x
LDA #$17
STA $1DFC

ResetLaserGeneric:
JSR CollisionBullets
LDA #$01
STA !GraphicsPtr,x
LDA !TimeBfrShtReg,x
BNE Return6
INC !StatusPtr,x
LDA #$FF
STA !TimeBfrShtReg,x
STA !LaserPtr,x
JSR TransferHDMA

Return6:
RTS

;--------------------------------------------------------;
; This is a routine that generates big lasers and stuff. ;
;--------------------------------------------------------;

GenerateWhiteLaser3:
PLX
LDA !TimeBfrShtReg,x
BEQ ThisBeAlreadyZero
DEC !TimeBfrShtReg,x

ThisBeAlreadyZero:
LDA !LaserPtr,x
BEQ ThisBeAlreadyZeroII
DEC !LaserPtr,x

ThisBeAlreadyZeroII:
PHX
LDA #$01
STA $0F
REP #$20
LDA.w #IncDecVPos3
STA $00
SEP #$20
BRA GenerateWhiteLaserGeneric

GenerateWhiteLaser2:
STZ $0F
REP #$20
LDA.w #IncDecVPos2
STA $00
SEP #$20
BRA GenerateWhiteLaserGeneric

GenerateWhiteLaser1:
STZ $0F
REP #$20
LDA.w #IncDecVPos1
STA $00
SEP #$20

GenerateWhiteLaserGeneric:
PLX
LDA !BossModus
BNE LaserExceptionNo
LDA !FlameOrNorveg,x
BNE NoSuchThingAsAFlame

LaserExceptionNo:
LDA $00
PHA
LDA $01
PHA
JSR CollisionBullets
PLA
STA $01
PLA
STA $00

NoSuchThingAsAFlame:
LDA !TimeBfrShtReg,x
BNE ContinueGenerating
INC !StatusPtr,x
RTS

ContinueGenerating:
STZ !GraphicsPtr,x
LDA !LaserPtr,x
AND #$F0
LSR A
LSR A
LSR A
LSR A
TAY
LDA !LaserVertPos,x
CLC
ADC ($00),y
STA !LaserVertPos,x
LDA !LaserPtr,x		; \ This is a time pointer for the laz0r.
AND #$F8		;  | every 8 frames something new.
LSR A			;  | i.e. growing or shrinking laser
LSR A			;  | or simply none or maximum laser
TAY			; / yep
REP #$20		; A = 16-bit
LDA #$2103		; CGRAM is to be affected
STA $4330		;
LDA HDMAPointer,y	; get pointer to RAM table
STA $4332		;
STA $00			; also store pointer for [$00]
SEC			; the result of this one is used as index in $03
SBC #$E000		;
STA $03			; it will be handy to read from the table here inside the sprite file
SEP #$20		; A = 8-bit
LDA #$7F		; Bank is 7F. Quite about right
STA $4334		;
STA $02			; [$00]
REP #$10		; XY = 16-bit
LDY $03			; $03 is an index right here.
LDA HDMA1,y		; Alright, so this is relevant for moving the table up and down. The first scanline count is variable.
SEP #$10		; XY = 8-bit
CLC			; Add $1528,x to that
ADC !LaserVertPos,x	;
BPL NoLimits		; note: if result above #$80, things screw up. So prevent that.
SEC
SBC #$80
STA $05
LDA #$7F		; no higher than #$7F
STA [$00]
REP #$20
LDA $00
CLC
ADC #$0005
STA $00
SEP #$20
REP #$10
LDY $03
LDA HDMA1+5,y
SEP #$10
CLC
ADC $05
BRA ReallyNone

NoLimits:
STA [$00]
REP #$20
LDA $00
CLC
ADC #$0005
STA $00
SEP #$20
LDA #$01

ReallyNone:
STA [$00]		; Store that in the RAM table which is uploaded to CGRAM
REP #$10
LDY $03
LDA HDMA1,y
SEP #$10
CLC
ADC !LaserVertPos,x
SEC
SBC #$18
PHA
LDA #$08
TSB $0D9F

;<---- Laser interaction code here

LDA !HstFrndLaser
BEQ IsJustHostile
LDA $96
STA $0E
LDA $97
STA $0F
PHX
LDX #$0B

NorvegButtonLoop2:
LDA $14C8,x
CMP #$08
BCC IncreaseNorvegButtonLoop2
LDA $7FAB9E,x
CMP #!NorvegSprNum
BNE IncreaseNorvegButtonLoop2
LDA !FlameOrNorveg,x
BEQ CopyTempPositions

IncreaseNorvegButtonLoop2:
DEX
BPL NorvegButtonLoop2

CopyTempPositions:
LDA $D8,x
SEC
SBC #$10
STA $96
LDA $14D4,x
SBC #$00
STA $97
TXA
PLX
STA !GraphicsPtr,x			; Norveg Index!

IsJustHostile:
REP #$20
LDA $96
SEC
SBC $1C
STA $00
SEP #$20
SEC
SBC $01,s
STA $7EC100
PLY
TAY
LDA $01
BNE RETURNINTER
TYA
BMI RETURNINTER
PHA
LDA !LaserPtr,x
LSR A
LSR A
LSR A
TAY
LDA !HstFrndLaser
BEQ IsJustHostile2
PLA
CMP NorvegInteractionHDMA,y
BRA TryThisComparison

IsJustHostile2:
PLA
CMP InterActionHDMA,y

TryThisComparison:
BCS RETURNINTER
LDA !HstFrndLaser
BEQ CheckForMario
PHX
LDA !GraphicsPtr,x
TAX
LDA !FlashTimer,x
PLX
CMP #$00
BNE RETURNINTER
LDA #$18
CLC
ADC !DecreaseNorvegHP
STA !DecreaseNorvegHP
PHX
LDA !GraphicsPtr,x
TAX
LDA #$80
STA !FlashTimer,x
PLX

RETURNINTER:
LDA !HstFrndLaser
BEQ NoTroubleHere
LDA $0F
STA $97
LDA $0E
STA $96
RTS

NoTroubleHere:
RTS
CheckForMario:
LDA $1497
ORA $1490
ORA $71
BNE Nawkst
LDY #$03

SmokeaLoop:
LDA $17C0,y
BEQ BreakSmoka
DEY
BPL SmokeaLoop
BRA Nawkst

BreakSmoka:
LDA #$01
STA $17C0,y
LDA $96
CLC
ADC #$10
STA $17C4,y
LDA $94
STA $17C8,y
LDA #$1C
STA $17CC,y

Nawkst:
LDA $1497
ORA $1490
ORA $71
BNE RETURNINTER
LDA #$18
CLC
ADC !DecreasePlayerHP
STA !DecreasePlayerHP
LDA #$04
STA $1DF9
LDA #$01
STA $71
BRA RETURNINTER

;-------------------------;
; Generate a Cluster Sprt ;
;-------------------------;

ClusXDispLo:
db $21,$EC

ClusXDispHi:
db $00,$FF

GenerateCluster:
LDY #$13
-
LDA $1892,y
BEQ +
DEY
BPL -
RTS

+
LDA #!ClusSprNum
STA $1892,y
LDA $E4,x
PHY
LDY $157C,x
SEC
SBC ClusXDispLo,y
PLY
STA $1E16,y
LDA $14E0,x
PHY
LDY $157C,x
SBC ClusXDispHi,y
PLY
STA $1E3E,y
LDA $D8,x
SEC
SBC #$10
STA $1E02,y
LDA $14D4,x
SBC #$00
STA $1E2A,y
STZ $00
LDA $1E2A,y
XBA
LDA $1E02,y
REP #$20
PHA
LDA $96
CLC
ADC #$0018
STA $00
PLA
SEC
SBC $00
CLC
ADC #$0100
ASL A
ASL A
ASL A
ASL A
ASL A
ASL A
ASL A
SEC
SBC #$8000
EOR #$FFFF
SEP #$20
STA $1E52,y
XBA
STA $1E66,y
LDA $1E3E,y
XBA
LDA $1E16,y
REP #$20
PHA
LDA $94
STA $00
PLA
SEC
SBC $00
CLC
ADC #$0100
ASL A
ASL A
ASL A
ASL A
ASL A
ASL A
ASL A
SEC
SBC #$8000
EOR #$FFFF
SEP #$20
STA $0F4A,y
XBA
STA $0F72,y
LDA #$01
STA $18B8
RTS

;-------------------------;
; Interact with lasers... ;
;-------------------------;

CollisionLazor:
JSR MarioNorveg
RTS

;-------------------------;
; Interact with bullets.. ;
;-------------------------;

CollisionBullets:
JSR ActualBullet

MarioNorveg:
JSL $03B664
JSR GetNorvegClipping
JSL $03B72B
BCC NoContact
LDA $1497
ORA $1490
ORA $71
BNE NoContact
LDA #$04
STA $1DF9
LDA #$01
STA $71
LDA #$10
CLC
ADC !DecreasePlayerHP
STA !DecreasePlayerHP

NoContact:
RTS

ActualBullet:
PHX
LDX #$0B

LoopBullet:
LDA $14C8,x
CMP #$08
BCC DecreaseLoop
LDA $1528,x
BEQ DecreaseLoop
LDA $7FAB9E,x
CMP #!BulletSprNum
BEQ BreakLoop

DecreaseLoop:
DEX
BPL LoopBullet
PLX
RTS

BreakLoop:
JSR GetBulletClipping
PHX
LDX $15E9
JSR GetNorvegClipping
PLX
JSL $03B72B
BCC DecreaseLoop
LDA #$01
CLC
ADC !DecreaseNorvegHP
STA !DecreaseNorvegHP
STZ $14C8,x
JMP DecreaseLoop

;--------------------------;
; Sprite Clipping Routine  ;
; Mostly borrowed from SMW ;
;--------------------------;

GetButton1Clipping:
LDA $E4,x
STA $04
LDA $14E0,x
STA $0A
LDA #$0E                ; Width of sprite clipping
STA $06
STA $07
LDA $D8,x
STA $05
LDA $14D4,x
STA $0B
RTS

GetButton2Clipping:
LDA $E4,x
STA $00
LDA $14E0,x
STA $08
LDA #$0E                ; Width of sprite clipping
STA $02
STA $03
LDA $D8,x
STA $01
LDA $14D4,x
STA $09
RTS

GetBulletClipping:
LDA $E4,x
STA $00
LDA $14E0,x
STA $08
LDA #$06                ; Width of sprite clipping
STA $02
STA $03
LDA $D8,x
CLC
ADC #$08
STA $01
LDA $14D4,x
ADC #$00
STA $09
RTS

GetNorvegClipping:
LDA $E4,x
SEC
SBC #$0A
STA $04
LDA $14E0,x
SBC #$00
STA $0A
LDA #$18                ; Width of sprite clipping
STA $06
LDA $D8,x
SEC
SBC #$1A
STA $05
LDA $14D4,x
SBC #$00
STA $0B
LDA #$36                ; Height of sprite clipping
STA $07
RTS

FlameXLoDisp:
db $0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$0C,$10,$0B,$0B,$0B
FlameXHiDisp:
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
FlameYLoDisp:
db $F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$FC,$FC,$00,$05,$12,$12,$12
FlameYHiDisp:
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00
FlameXWidth:
db $05,$05,$06,$06,$07,$07,$08,$07,$08,$08,$08,$08,$0E,$04,$04,$03
FlameYHeight:
db $20,$20,$20,$20,$20,$20,$20,$20,$20,$17,$17,$15,$0E,$04,$04,$03

GetFlameClipping:
LDA !TimeBfrShtReg,x
AND #$7F
LSR A
LSR A
LSR A
TAY
LDA $E4,x
SEC
SBC FlameXLoDisp,y
STA $04
LDA $14E0,x
SBC FlameXHiDisp,y
STA $0A
LDA FlameXWidth,y                ; Width of sprite clipping
STA $06
LDA $D8,x
CLC
ADC FlameYLoDisp,y
STA $05
LDA $14D4,x
ADC FlameYHiDisp,y
STA $0B
LDA FlameYHeight,y                ; Height of sprite clipping
STA $07
RTS

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

XDisp:
db $F0,$00,$F0,$00,$F0,$00,$F8,$00,$08
db $00,$F0,$00,$F0,$00,$F0,$00,$F8,$F0
db $F0,$00,$F0,$00,$F0,$00,$F8,$00,$08,$E0
db $00,$F0,$00,$F0,$00,$F0,$00,$F8,$F0,$10
db $F0,$00,$F0,$00,$F0,$00,$F8,$00,$08,$E8,$E8
db $00,$F0,$00,$F0,$00,$F0,$00,$F8,$F0,$10,$10
db $F0,$00,$F0,$00,$F0,$00,$F0,$F8,$00,$08
db $00,$F0,$00,$F0,$00,$F0,$08,$00,$F8,$F0
db $F0,$00,$F0,$00,$F0,$00,$F0,$F8,$00,$08,$E8,$E8
db $00,$F0,$00,$F0,$00,$F0,$08,$00,$F8,$F0,$10,$10

YDisp:
db $E0,$E0,$F0,$F0,$00,$00,$10,$10,$10
db $E0,$E0,$F0,$F0,$00,$00,$10,$10,$10,$F0
db $E0,$E0,$F0,$F0,$00,$00,$10,$10,$10,$F0,$F8
db $E0,$E0,$F0,$F0,$00,$00,$10,$10,$10,$10
db $E0,$E0,$F0,$F0,$00,$00,$10,$10,$10,$10,$F0,$F8

Index4Tbl:
db $00,$12,$26,$3C,$50				; Indices to XDisp per pose.
Index3Tbl:
db $00,$09,$00,$0A,$00,$0B,$00,$0A,$00,$0C	; Used in the loop.
Index2Tbl:
db $08,$09,$0A,$09,$0B				; Used in the loop (determine tile count)
IndexTbl:
db $00,$09,$13,$1E,$28				; Indices to YDisp, TileNum and TileSize per pose.

TileNum:
db $C6,$C8,$E6,$E8,$CA,$CC,$FD,$EC,$ED			; 0 - Not shooting
db $C6,$C8,$EE,$E8,$CA,$CC,$FD,$EC,$ED,$CE		; 1 - Shooting
db $C6,$C8,$EE,$E8,$CA,$CC,$FD,$EC,$ED,$FC,$F5		; 2 - Flaming
db $C6,$AB,$AD,$44,$CA,$CC,$EA,$EB,$FA,$FB		; 3 - Not shooting, no jetpack
db $C6,$AB,$84,$44,$CA,$CC,$EA,$EB,$FA,$FB,$FC,$F5	; 4 - Shooting electrical stuff, no jetpack

TileSize:
db $02,$02,$02,$02,$02,$02,$00,$00,$00			; 0 - Not shooting
db $02,$02,$02,$02,$02,$02,$00,$00,$00,$02		; 1 - Shooting
db $02,$02,$02,$02,$02,$02,$00,$00,$00,$00,$00		; 2 - Flaming
db $02,$02,$02,$02,$02,$02,$00,$00,$00,$00		; 3 - Not shooting, no jetpack
db $02,$02,$02,$02,$02,$02,$00,$00,$00,$00,$00,$00	; 4 - Shooting electrical stuff, no jetpack

FlamesAmountOfTiles:
db $03,$03,$03,$03,$03,$03,$03,$03
db $03,$02,$02,$02,$00,$00,$00,$00

FlamesTileNumbers:
db $3F,$2F,$1F,$0F,$3F,$2F,$1F,$0F ; Frames 16 & 15
db $3E,$2E,$1E,$0E,$3D,$2D,$1D,$0D ; 14 13
db $3C,$2C,$1C,$0C,$3B,$2B,$1B,$0B ; 12 11
db $3A,$2A,$1A,$0A,$58,$48,$38,$28 ; 10 9
db $57,$47,$37,$27,$59,$49,$39,$00 ; 8 7
db $56,$46,$36,$00,$29,$19,$09,$00 ; 6 5
db $07,$00,$00,$00,$26,$00,$00,$00 ; 4 3
db $16,$00,$00,$00,$06,$00,$00,$00 ; 2 1

YDispFlames:
db $08,$00,$F8,$F0

SeperateFlameXDisp:
db $F4,$06,$00,$F9,$FC,$F6,$03,$04

SeperateFlameYDisp:
db $00,$E8,$F0,$E0,$F4,$00,$F8,$E0

ANDTable:
db $01,$02,$04,$08,$10,$20,$40,$80

;------------------;
; Flame Subroutine ;
;------------------;

StoreToX:
STA $05
TAX
ASL A
ASL A
STA $03
LDA FlamesAmountOfTiles,x
TAX
CLC
ADC $06
STA $06

LoopFlames:
LDA $05
CMP #$0C
BNE RegularFlameXDisp
LDA $00
CLC
ADC #$FC
PHY
LDY $07
CLC
ADC SeperateFlameXDisp,y
PLY
BRA BothFlamesXJoin

RegularFlameXDisp:
LDA $00
PHY
LDY $07
CLC
ADC SeperateFlameXDisp,y
PLY

BothFlamesXJoin:
STA $0300,y
LDA $05
CMP #$0C
BNE RegularFlameYDisp
LDA $01
PHY
LDY $07
CLC
ADC SeperateFlameYDisp,y
PLY
BRA BothFlamesJoin

RegularFlameYDisp:
LDA $01
CLC
ADC YDispFlames,x
PHY
LDY $07
CLC
ADC SeperateFlameYDisp,y
PLY

BothFlamesJoin:
STA $0301,y
PHX
TXA
CLC
ADC $03
TAX
LDA FlamesTileNumbers,x
STA $0302,y
PLX
LDA #$35
STA $0303,y
PHY
TYA
LSR A
LSR A
TAY
LDA $05
CMP #$0C
BNE RegularFlameSize
LDA #$02
BRA BothFlameSizes

RegularFlameSize:
LDA #$00

BothFlameSizes:
STA $0460,y
PLY
INY
INY
INY
INY
DEX
BPL LoopFlames
RTS

ClusterBallGFX:
LDA $14
AND #$02
ASL A
ASL A
ASL A
ASL A
CLC
ADC #$86
STA $0302,y
LDA #$25
BRA SameEnding

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

ButtonGFX:
LDA $00
STA $0300,y
LDA $01
STA $0301,y
LDA !FlameOrNorveg,x
CMP #$01
BNE ClusterBallGFX
LDA !StatusPtr,x
BNE LoadPressedButton
LDA #$04
BRA LoadOtherButton

LoadPressedButton:
LDA #$24

LoadOtherButton:
STA $0302,y
LDA #$2B

SameEnding:
STA $0303,y
LDY #$02
LDA #$00
JMP TilesDrawn

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

FlameGFX:
LDA !BossModus
BEQ ButtonGFX
PHX
STZ $07
LDA !TimeBfrShtReg,x
AND #$7F
LSR A
LSR
LSR A
JSR StoreToX
PLX
LDY #$FF
LDA #$00
JMP TilesDrawn

;-----------------------;
; Regular Graphics Rtne ;
;-----------------------;

DontDoAnything:
RTS

RegularStuffJMP:
LDA !FlashTimer,x
AND #$02
BNE DontDoAnything
JMP RegularStuff

SkyPopGFX:
JSR GET_DRAW_INFO
STZ $06
LDA !FlameOrNorveg,x
BNE FlameGFX
LDA !FlameNumber,x
BEQ RegularStuffJMP
LDA #$07
STA $07

LoopTableFlameNum:
PHY
LDY $07
LDA !FlameNumber,x
AND ANDTable,y
BNE IsAnOption
PLY
LDA $07
BEQ RegularStuffJMP

DecreaseFlameCount:
DEC $07
BRA LoopTableFlameNum

IsAnOption:
PLY
PHX
LDA $07
AND #$01
BEQ LowerNybble
LDA !FlameTimer,x
AND #$F0
LSR A
LSR A
LSR A
LSR A
BRA StoreToFive

LowerNybble:
LDA !FlameTimer,x
AND #$0F

StoreToFive:
JSR StoreToX
PLX
LDA $07
BEQ RegularStuff
DEC $07
JMP LoopTableFlameNum

RegularStuff:
LDA !GraphicsPtr,x
STA $03
LDA $157C,x
LSR A
ROR A
ROR A
STA $05
PHX
LDA $03
ASL A
CLC
ADC $157C,x
TAX
LDA.l Index3Tbl,x
STA $04
LDX $03
LDA.l Index2Tbl,x
TAX

GFXLoop:
PHX
PHX
LDX $03
LDA.l Index4Tbl,x
CLC
ADC $01,s
PLX
CLC
ADC $04
TAX
LDA $00
CLC
ADC XDisp,x
PLX
STA $0300,y

PHX
PHX
LDX $03
LDA.l IndexTbl,x
CLC
ADC $01,s
PLX
TAX
LDA $01
CLC
ADC YDisp,x
STA $0301,Y

LDA TileNum,x
STA $0302,y

PHY
TYA
LSR A
LSR A
TAY
LDA TileSize,x
STA $0460,y
PLY

LDX $15E9
LDA $15F6,x
PLX
ORA $64
ORA $05
STA $0303,y

INY
INY
INY
INY
DEX
BPL GFXLoop

PLX
LDY #$FF                ; \ why FF? (460 &= 2) 8x8 tiles maintained
PHX
LDX $03
LDA.l IndexTbl,x
PLX                ;  | A = number of tiles drawn - 1

TilesDrawn:
CLC
ADC $06
JSL $01B7B3             ; / don't draw if offscreen
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B760 - graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B75C

TABLE1:
db $0C,$1C

TABLE2:
db $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 #$0040            	;  |
CMP #$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 TABLE1,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 TABLE2,y            ;  |
STA $186C,x             ;  |

ON_SCREEN_Y:
DEY 			;  |
BPL ON_SCREEN_LOOP      ; /

LDY $15EA,x
LDA !FlameOrNorveg,x
BEQ IsNorvegOAMIndex
LDA !BossModus
BNE ThisOneIsARealFlame
LDA !FlameOrNorveg,x
ASL A
ASL A
CLC
ADC #$60
STA $15EA,x
TAY
BRA IsNorvegOAMIndex

ThisOneIsARealFlame:
LDA !FlameNumber,x
ASL A
ASL A
ASL A
ASL A
CLC
ADC #$D0
STA $15EA,x
TAY

IsNorvegOAMIndex:
LDA $E4,x               ; \ 
SEC 			;  | 
SBC $1A                 ;  | $00 = sprite x position relative to screen border
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 			; /

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B85D - off screen processing code - shared
; sprites enter at different points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B83B             

TABLE3:             db $40,$B0
TABLE6:             db $01,$FF 
TABLE4:             db $30,$C0,$A0,$80,$A0,$40,$60,$B0 
TABLE5:             db $01,$FF,$01,$FF,$01,$00,$01,$FF
 
SUB_OFF_SCREEN_HB:  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 $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


	;---------------;
	; HDMA Gradient ;
	;---------------;

HDMAPointer:
dw $E000,HDMA2-HDMA1+$E000,HDMA3-HDMA1+$E000,HDMA4-HDMA1+$E000,HDMA5-HDMA1+$E000,HDMA6-HDMA1+$E000,HDMA7-HDMA1+$E000,HDMA8-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000 ; 00-7F
dw HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA9-HDMA1+$E000,HDMA8-HDMA1+$E000,HDMA7-HDMA1+$E000,HDMA6-HDMA1+$E000,HDMA5-HDMA1+$E000,HDMA4-HDMA1+$E000,HDMA3-HDMA1+$E000,HDMA2-HDMA1+$E000,$E000 ; 80-FF

NorvegInteractionHDMA:
db $00,$01,$03,$05,$08,$0C,$11,$18,$26,$32,$32,$32,$32,$32,$32,$32,$32,$32,$32,$32,$32,$26,$18,$11,$0C,$08,$05,$03,$01,$00

InterActionHDMA:
db $00,$01,$03,$05,$07,$09,$0D,$12,$1A,$22,$22,$22,$22,$22,$22,$22,$22,$22,$22,$22,$22,$1A,$12,$0D,$09,$07,$05,$03,$01,$00

HDMA1: db $11 : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $00

HDMA2: db $10 : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMA3: db $0F : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMA4: db $0E : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMA5: db $0D : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMA6: db $0C : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$6318
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMA7: db $0A : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$6318
       db $03 : dw $0000,$739C
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMA8: db $07 : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$6318
       db $09 : dw $0000,$739C
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMA9: db $04 : dw $0000,$0000
       db $01 : dw $0000,$0000
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$6318
       db $0F : dw $0000,$739C
       db $01 : dw $0000,$5294
       db $01 : dw $0000,$4210
       db $01 : dw $0000,$318C
       db $01 : dw $0000,$2108
       db $01 : dw $0000,$1084
       db $01 : dw $0000,$0000
       db $00

HDMAEnd:

;---------------------;
; Get direction...... ;
;---------------------;

SUB_GET_DIR:        LDY #$01                ;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
                    DEY                     ;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

;---------------------;
; Randomizer	      ;
;---------------------;

RANDOM:
	PHX
	PHP
	SEP #$30
	PHA
	JSL $01ACF9
	PLX
	CPX #$FF
	BNE NORMALRT
	LDA $148B
	BRA ENDRANDOM
NORMALRT:
	INX
	LDA $148B
	STA $4202
	STX $4203
	NOP #4
	LDA $4217	
ENDRANDOM:
	PLP
	PLX
	RTS