warnings disable W1030
math pri on

lorom

!windowBg12MaskSettings = $60
!window2PositionRight = $66
!windowAreaMainScreenDisable = $6C

!bg2ScrollX = $B5
!bg2ScrollY = $B7

!layer1PositionX = $0911
!layer1PositionY = $0915
!samusPositionX  = $0AF6
!samusPositionY  = $0AFA

!samusHealth    = $09C2
!samusMaxHealth = $09C4

!mbBody_positionX     = $0F7A
!mbBody_positionY     = $0F7E
!mbBody_properties    = $0F86
!mbBody_i_palette     = $0F96
!mbBody_i_vramTiles   = $0F98
!mbBody_function      = $0FA8
!mbBody_functionTimer = $0FB2

!mbBrain_positionX   = $0FBA
!mbBrain_positionY   = $0FBE
!mbBrain_properties  = $0FC6
!mbBrain_health      = $0FCC
!mbBrain_i_palette   = $0FD6
!mbBrain_i_vramTiles = $0FD8
!mbBrain_function    = $0FE8

!powerBombFlag = $0CEE
!enemyBg2TilemapSize = $179A
!fxType = $196E

!mbForm                        = $7E7800
!mbEnabledHitboxes             = $7E7808
!i_mbHdmaObject                = $7E7812
!i_mbNeckPalette               = $7E7818
!i_mbBrainPalette              = $7E781A
!deleteTurretsRinkas           = $7E783A
!mbPauseHookEnabled            = $7E7844
!mbBrainPaletteHandlingEnabled = $7E7860

!mbRainbowBeamAngularWidth = $7E8026

!neckMovementEnabled = $7E8062
!i_lowerNeckMovement = $7E8064
!i_upperNeckMovement = $7E8066
!neckAngleDelta      = $7E8068

!vram_legsTiles = $7400
!vram_shitroid  = $7C00

!bodyInitialPositionX = $0023
!bodyInitialPositionY = $0096
!brainInitialPositionX = $0049
!brainInitialPositionY = $0049
!bg2InitialPositionX = $FFFC
!bg2InitialPositionY = $FFAA
!mbActivationScreenXThreshold = $0080
!legsExtraTileSize = $400
!mbBrainEnemyIndex = $0040


function makeEnemyProjectileGraphicsIndices(i_vram, i_palette) = i_vram|i_palette<<9
function makeEnemyPaletteIndex(i_palette) = i_palette<<9


; Tweaks
{
; Get rid of glass tube
org $8FDD6E ; MB room default state header
skip $14
dw $0000 ; PLM population

; Fix rinka graphics by moving them back to VRAM $7C00 so that legs tiles can be pre-loaded
org $A0EC3F ; Mother Brain's brain enemy header
dw $1400+!legsExtraTileSize ; Tile data size

; Fix turret graphics
org $86BE4F ; Initialisation AI - enemy projectile $C17E (Mother Brain's room turrets)
LDA.w #makeEnemyProjectileGraphicsIndices(!legsExtraTileSize/$10, 2)

org $86BF5F ; Initialisation AI - enemy projectile $C18C (Mother Brain's room turret bullets)
LDA.w #makeEnemyProjectileGraphicsIndices(!legsExtraTileSize/$10, 2)

; Fix zebetite graphics
org $A6FB8D ; Initialisation AI - enemy $E27F (zebetites)
LDA #read2($A6FB8E)+!legsExtraTileSize/$10 ; VRAM graphics index

; Shorten movement delays
{
; Shorten rainbow beam time
org $A9BA2D ; Mother Brain's body function - second phase - firing rainbow beam - start draining Samus
LDA #$0040

org $A9BAFF ; Mother Brain's body function - second phase - firing rainbow beam - lower head
LDA #$0001

org $A9BDA3 ; Mother Brain's body function - second phase - finish Samus off - stand up
LDA #$0001

org $A9BDBA ; Mother Brain's body function - second phase - finish Samus off - admire job well done
LDA #$0001

org $A9BDE6 ; Mother Brain's body function - second phase - finish Samus off - charge final rainbow beam / load Shitroid
LDA #$0020

; Shorten drained by Shitroid time
org $A9BE57 ; Mother Brain's body function - drained by Shitroid - taken aback by Shitroid
LDA #$0001

org $A9BEBB ; Mother Brain's body function - drained by Shitroid - firing rainbow beam
LDA #$0002 : STA $7E784E ; Mother Brain painful walking walk animation delay = 2 (really fast)

; Neck retraction speed
org $A9BF23 ; Mother Brain's body function - drained by Shitroid - rainbow beam has run out
LDA #$0400

org $A9BF76 ; Mother Brain's body function - drained by Shitroid - go into low power mode
LDA #$0001

org $A9BF8F ; Mother Brain's body function - drained by Shitroid - prepare transition to grey
LDA #$0001

org $A9C041 ; Set Mother Brain painful walking function timer
LDA #$0002 : STA $7E7852

; Shorten wake up time
org $A9C05F ; Mother Brain's body function - second phase - revive self - inanimate grey
LDA #$0001

org $A9C07C ; Mother Brain's body function - second phase - revive self - show signs of life
LDA #$0001

org $A9C0DE ; Mother Brain's body function - second phase - revive self - wake up
LDA #$0001

org $A9C0F5 ; Mother Brain's body function - second phase - revive self - wake-up stretch
LDA #$0001

org $A9C17B ; Mother Brain's body function - second phase - murder Shitroid - attack Shitroid
LDA #$0040

; Shorten Shitroid arrival delay
org $A9C760 ; Initialisation AI - enemy $ECBF (Shitroid in cutscene)
LDA #$0018
}

; Skip idling after healing Samus
org $A9CAAF ; Shitroid function - heal Samus up to full health
LDA #$CAEA

; Do final charge immediately
org $A9CB21 ; Shitroid function - release Samus
LDA #$CBD8

; Use Samus' X position for the target
org $A9CBD8 ; Shitroid function - final charge
LDA $0AF6

; Shorten Samus rainbow palette time
org $A9CCD8 ; Shitroid function - unload Shitroid tiles
LDA #$0001
}


org $88E7B5 ; Initialise rainbow beam
JSL CalculateScrollingRainbowBeamHdmaTables

org $88E7DB ; Rainbow beam pre-instruction
JSL CalculateScrollingRainbowBeamHdmaTables

org $A98687 ; Initialisation AI - enemy $EC7F (Mother Brain's body)
JMP BodyInitAi


org $A98705 ; Initialisation AI - enemy $EC3F (Mother Brain's brain)
BrainInitAi:
{
; Same as vanilla for now
LDX #!mbBrainEnemyIndex : LDY #MbCorpseRottingDefinition : JSR InitCorpseRotting
LDA.w #3000 : STA !mbBrain_health
LDA #$9C13 : JSR SetUnusedBrainInstructionList
STZ !mbBrain_i_vramTiles
LDA #$1100 : TSB !mbBrain_properties

LDA.w #makeEnemyPaletteIndex(1)
STA !mbBrain_i_palette
STA !i_mbNeckPalette
STA !i_mbBrainPalette

LDA #BrainInstructionList_Initial : JSR SetBrainInstructionList
JSR SetUpMbBrainNormalPalette

RTL

warnpc $A9873E
}

org $A9C57D ; Damage Samus due to rainbow beam
{
; Halve Samus' health, minimum of 1
LSR !samusHealth : BNE + : INC !samusHealth : +

; Handle playing gaining/losing incremental health sound effect
JSR HandlePlayingLosingHealthSfx

SEC : RTL

warnpc $A9C59F
}

org $A9C59F ; Heal Samus due to Shitroid
{
; Handle playing gaining/losing incremental health sound effect
JSR HandlePlayingLosingHealthSfx

; Double Samus' health, return carry clear if reached max
LDA !samusHealth : ASL
CMP !samusMaxHealth : BCS +
STA !samusHealth : SEC : RTL
+
LDA !samusMaxHealth : STA !samusHealth : CLC : RTL

warnpc $A9C5BE
}

org $A9FB70 ; Free space
BodyInitAi:
{
; Clear BG2 tilemap
PHB
PEA $7E7E : PLB : PLB
LDA #$0338
LDX #$0FFE
-
STA $2000,x
DEX : DEX : BPL -
PLB

; Use dummy body instruction list
LDA #$9C13 : JSR SetBodyInstructionList

STZ !mbBody_i_vramTiles

; Set Mother Brain's body to block plasma beam, be intangible, and be invisible
LDA #$1500 : TSB !mbBody_properties

LDA #$0000
STA !mbBody_i_palette
STA !mbPauseHookEnabled
LDA #$0002 : STA !mbEnabledHitboxes ; Brain only
LDA #$0800 : STA !enemyBg2TilemapSize
LDA #$0001 : STA !mbBrainPaletteHandlingEnabled
LDA #$0002 : STA !mbForm
LDA #BrainFunction_DrawBrainAndNeck : STA !mbBrain_function
LDA #BodyFunction_Custom : STA !mbBody_function

; Position Mother Brain for rainbow beam
LDA #!bodyInitialPositionX : STA !mbBody_positionX
LDA #!bodyInitialPositionY : STA !mbBody_positionY
LDA #!bg2InitialPositionY : STA !bg2ScrollY
LDA #!brainInitialPositionX : STA !mbBrain_positionX
LDA #!brainInitialPositionY : STA !mbBrain_positionY

; Load FX entry index 1
LDA #$0001 : JSL $89AB02

; Spawn 12 room turret enemy projectiles
LDA #$0000
-
PHA : LDY #$C17E : JSL $868097 : PLA
INC A : CMP #$000C : BCC -

; Write legs tiles
LDX $0330
LDA.w #Tiles_MbLegs_End-Tiles_MbLegs : STA $D0,x
LDA.w #Tiles_MbLegs : STA $D2,x
LDA.w #bank(Tiles_MbLegs) : STA $D4,x
LDA #!vram_legsTiles : STA $D5,x
TXA : CLC : ADC #$0007 : STA $0330

RTL
}

BodyFunction_Custom:
{
JSR UpdateScrollingBodyPosition

; Set up the BG1 background
JSL $8483D7 : db $02, $02 : dw $B67B : JSL $8483D7 : db $02, $03 : dw $B67F ; : LDA #+ : STA !mbBody_function : + : RTS
JSL $8483D7 : db $02, $04 : dw $B683 : JSL $8483D7 : db $02, $05 : dw $B687 ; : LDA #+ : STA !mbBody_function : + : RTS
JSL $8483D7 : db $02, $06 : dw $B68B : JSL $8483D7 : db $02, $07 : dw $B68F ; : LDA #+ : STA !mbBody_function : + : RTS
JSL $8483D7 : db $02, $08 : dw $B693 : JSL $8483D7 : db $02, $09 : dw $B697 ; : LDA #+ : STA !mbBody_function : + : RTS
JSL $8483D7 : db $02, $0A : dw $B69B : JSL $8483D7 : db $02, $0B : dw $B69F ; : LDA #+ : STA !mbBody_function : + : RTS
JSL $8483D7 : db $02, $0C : dw $B6A3 : JSL $8483D7 : db $02, $0D : dw $B6A7 : LDA #+ : STA !mbBody_function : +

+
; Wait for Samus to arrive
LDA !samusPositionX : CMP #$00EC : BCC ++
LDA #!mbActivationScreenXThreshold : CMP !layer1PositionX : BCC + : STA !layer1PositionX : +
RTS

++
; Scroll 0 = blue, 1 = red
LDA #$0001 : STA $7ECD20

; Layer 2 scroll X = layer 2 scroll Y = 1 (library background, no scrolling)
LDA #$0101 : STA $091B

; BG2 tilemap size = 32x32
LDA #$0003 : TRB $59

; Fix BG2 X scroll
LDA #!bg2InitialPositionY : STA !bg2ScrollY

; Set Mother Brain's body to be visible
LDA #$0100 : TRB !mbBody_properties

; Fill wall / clear ceiling block
JSL $8483D7 : db $0F, $04 : dw $B673
JSL $8483D7 : db $0F, $09 : dw $B673
JSL $8483D7 : db $0E, $02 : dw $B6B3

; Delete turrets and rinkas
LDA #$0001 : STA !deleteTurretsRinkas

; Lower acid
;LDA #$0002 : JSL $89AB02
STZ !fxType

LDA #BodyInstructionList_Initial : JSR SetBodyInstructionList

LDA #BrainFunction_DrawBrainAndNeck : STA !mbBrain_function
JSR $903F ; Set up Mother Brain's neck

; Disable acid (should check if acid finished lowering first, but this needs to be done for rainbow beam to work)
STZ $18B4 ; Disable HDMA object 0
STZ $18B6 ; Disable HDMA object 1

; Write palettes
LDY #MbPalettes_attacks+2 : LDX #$0142 : LDA #$000F : JSL WriteColours
LDY #MbPalettes_backLeg+2 : LDX #$0162 : LDA #$000F : JSL WriteColours

; Change music
LDA #$0000 : JSL $808FC1
LDA #$FF21 : LDY #$0028 : JSL $808FF7
LDA #$0005 : JSL $808FC1

; Write Shitroid tiles
LDX $0330
LDA.w #Tiles_Shitroid_End-Tiles_Shitroid : STA $D0,x
LDA.w #Tiles_Shitroid : STA $D2,x
LDA.w #bank(Tiles_Shitroid) : STA $D4,x
LDA #!vram_shitroid : STA $D5,x
TXA : CLC : ADC #$0007 : STA $0330

; Enable neck movement
LDA #$0001 : STA !neckMovementEnabled
LDA #$0002 : STA !i_lowerNeckMovement
LDA #$0004 : STA !i_upperNeckMovement
LDA #$0040 : STA !neckAngleDelta

LDA #BrainInstructionList_ChargingRainbowBeam : JSR SetBrainInstructionList

LDA #$0071 : JSL $8090CB ; Queue sound 71h, sound library 2, max queued sounds allowed = 6 (silence)
LDA #$0006 : STA !i_lowerNeckMovement : STA !i_upperNeckMovement
LDA #$0500 : STA !neckAngleDelta
LDA #+ : STA !mbBody_function

+
JSR UpdateScrollingBodyPosition
JSR $BB6E ; Aim Mother Brain rainbow beam
LDA !powerBombFlag : BEQ + : RTS : + ; Wait until power bomb inactive

JSR $BCC6 ; Mother Brain's body rainbow beam palette animation index = 0
LDA #$9C77 : JSR SetBrainInstructionList ; Set Mother Brain's brain instruction list to $9C77 (firing rainbow beam)
LDA #$0200 : STA !mbRainbowBeamAngularWidth ; Mother Brain rainbow beam angular width = 200h
JSL $88E748 : STA !i_mbHdmaObject ; Spawn Mother Brain rainbow beam HDMA object
LDA #$0040 : STA !neckAngleDelta
LDA #$0001 : STA !neckMovementEnabled
LDA #$0002 : STA !i_lowerNeckMovement
LDA #$0004 : STA !i_upperNeckMovement
STZ $0FB4 ; Mother Brain rainbow beam explosion index = 0
STZ $0FB6 ; Mother Brain rainbow beam explosion timer = 0

LDA #$0005 : LDY !samusHealth : CPY.w #700 : BPL + : LDA #$0018 : +
JSL $90F084
LDA #$0006 : STA $7E782A ; Number of times to queue rainbow beam sound effect = 6
LDA #+ : STA !mbBody_function

+
JSR UpdateScrollingBodyPosition
JSR $B9E5 ; Mother Brain's body function - second phase - firing rainbow beam - move Samus towards wall
BCS + : RTS : + ; Wait until Samus reaches wall
LDA #+ : STA !mbBody_function

+
LDA !layer1PositionX : BEQ + ; Wait for screen to finish scrolling
JSR UpdateScrollingBodyPosition
RTS

+
JMP $BA27 ; Mother Brain's body function - second phase - firing rainbow beam - start draining Samus
}

UpdateScrollingBodyPosition:
{
LDA !layer1PositionX : BEQ .done

; Make a window for BG2 during the scrolling
LDA !mbBody_positionX : SEC : SBC !layer1PositionX : CLC : ADC #$0080 : BPL + : LDA #$0000 : + : CMP #$0100 : BCC + : LDA #$00FF : +
PHP : SEP #$20
STA !window2PositionRight ; Window 2 right position
LDA #$02 : STA !windowAreaMainScreenDisable ; Disable BG2 in main screen window area
LDA #$C0 : TSB !windowBg12MaskSettings ; Enable BG2 window 2 exclusive mask
PLP
LDA #!bg2InitialPositionX : CLC : ADC !layer1PositionX : STA !bg2ScrollX
RTS

.done
PHP : SEP #$20
STZ !windowAreaMainScreenDisable ; Enable main screen window
LDA #$C0 : TRB !windowBg12MaskSettings ; Disable BG2 window 2 exclusive mask
PLP
RTS
}

CalculateScrollingRainbowBeamHdmaTables:
{
LDA !mbBrain_positionX : PHA
SEC : SBC !layer1PositionX : STA !mbBrain_positionX
JSL CalculateRainbowBeamHdmaTables
PLA : STA !mbBrain_positionX
RTL
}

BodyInstructionList_Initial:
{
dw $9700        ; Mother Brain's pose = standing
dw $0001,$9FA0
dw $812F        ; Sleep
}


; Labels
{
org $A987A2
BrainFunction_DrawBrainAndNeck:

org $A987D0
BrainFunction_DrawBrain:

org $A987E1
BodyFunction_FirstPhase:

org $A99466
CalculateRainbowBeamHdmaTables:

org $A99492
MbPalettes:
{
    .backLeg : skip $20
    .attacks : skip $20
    .shitroid : skip $20
    .tubeEnemyProjectiles : skip $20
    .glassShards : skip $20
    .explodedEscapeDoorParticles : skip $20
}

org $A9B8EB
BodyFunction_SecondPhase_FiringRainbowBeam:

org $A99C21
BrainInstructionList_Initial:

org $A99C87
BrainInstructionList_Neutral:

org $A99F6C
BrainInstructionList_ChargingRainbowBeam:

org $A9C42D
SetBodyInstructionList:

org $A9C43A
SetUnusedBrainInstructionList:

org $A9C447
SetBrainInstructionList:

org $A9C546
HandlePlayingLosingHealthSfx:

org $A9D2E4
WriteColours:

org $A9D2F6
WriteTargetColours:

org $A9DC5F
InitCorpseRotting:

org $A9D1F8
SetUpMbBrainNormalPalette:

org $A9DE08
MbCorpseRottingDefinition:

org $B18800
Tiles_Shitroid:
skip $800
Tiles_Shitroid_End:

org $B79000
Tiles_MbLegs:
skip $1000
Tiles_MbLegs_End:
}
