Baby Bowser - brunovalads/yoshisisland-disassembly GitHub Wiki
States
; baby bowser states
dw $C7D5 ; $0DC50D | 00: prepare to jump attack / idle
dw $C81A ; $0DC50F | 01: jump attack
dw $C834 ; $0DC511 | 02: pre-slam flip at apex of jump
dw $C876 ; $0DC513 | 03: jump slam
dw $C916 ; $0DC515 | 04: idle after slam attack
dw $C985 ; $0DC517 | 05: prepare to idle jump
dw $C9B3 ; $0DC519 | 06: idle jump to prepare for next slam attack
dw $C9E4 ; $0DC51B | 07:
dw $CA06 ; $0DC51D | 08:
dw $CA0E ; $0DC51F | 09: idle animations after non-attack (flying off yoshi / hit by eggs)
dw $CADC ; $0DC521 | 0A: hit by yoshi
dw $CAFD ; $0DC523 | 0B: flip around on ground after being hit
dw $CB4C ; $0DC525 | 0C: laying on ground after being hit
dw $CB6C ; $0DC527 | 0D: prepare to jump attack after being hit
dw $CB82 ; $0DC529 | 0E: idle after last hit (before cutscene)
dw $CBC9 ; $0DC52B | 0F: idle after last (during cutscene)
dw $CC11 ; $0DC52D | 10: prepare to expand
dw $CC28 ; $0DC52F | 11: fade baby bowser's color to black
dw $CE3C ; $0DC531 | 12: pre-fight cutscene (with kamek)
; midpoint respawn cutscene states
dw $EBAA ; $0DC533 | 13: pre-cutscene idle (without kamek)
dw $EBE7 ; $0DC535 | 14: pre-cutscene centering screen on baby bowser (without kamek)
dw $CE3C ; $0DC537 | 15: pre-fight cutscene (without kamek)
; prepare mecha bowser states
dw $D267 ; $0DC539 | 16: baby bowser expanding
dw $D300 ; $0DC53B | 17: prepare fight (black screen)
dw $D4AC ; $0DC53D | 18: prepare fade in (black screen)
dw $D617 ; $0DC53F | 19: idle before fight (no bowser)
dw $D65E ; $0DC541 | 1A: mecha-bowser rising into frame
dw $D71D ; $0DC543 | 1B: idle (summon rocks)
dw $DA15 ; $0DC545 | 1C: walk forward
; mecha bowser states
dw $D77B ; $0DC547 | 1D: shoot fireballs
dw $D913 ; $0DC549 | 1E: knockback after hit by egg
dw $F1A9 ; $0DC54B | 1F: explode after final hit
; post-fight cutscene states
dw $D617 ; $0DC54D | 20: fade into victory cutscene (no bowser)
dw $F32A ; $0DC54F | 21: baby bowser falling in frame
dw $F358 ; $0DC551 | 22: flopping around on the ground
dw $F360 ; $0DC553 | 23: cutscene with kamek
dw $F383 ; $0DC555 | 24: unload baby bowser sprite
dw $F4F7 ; $0DC557 | 25: prepare stork cutscene
dw $F5B2 ; $0DC559 | 26: stork cutscene
Baron von Zeppelin w/ Egg Spawning
Balloons with eggs spawn in during the Final Bowser fight to allow Yoshi to harm Bowser. The first balloon immediately spawns once Bowser's state (address $701A2E) reaches $1B and $7E1070 >= $08, so after the initial intro sequence. Each time a new balloon spawns, the timer at address $701AF0 restarts to $0100 (256 frames, roughly 4.2 seconds). A new balloon shall not spawn until this timer hits $0000. Upon hitting $0000, there are some extra conditions checked before the next balloon spawns:
cache ; $09F757 |\
ibt r12,#$0018 ; $09F758 | | begin loop of all sprites
move r13,r15 ; $09F75A |/
ldw (r2) ; $09F75C |\
lob ; $09F75D | | if sprite's state is uninitialized
beq .next_sprite ; $09F75E | | skip to next
nop ; $09F760 |/
ldw (r3) ; $09F761 |\
sub r5 ; $09F762 | | if sprite ID is balloon w/ bowser egg
beq .return_flag_on ; $09F763 | | flag on return value and go to next
add r5 ; $09F765 |/
sub r6 ; $09F766 |\ if sprite ID is NOT bowser egg
bne .next_sprite ; $09F767 | | skip to next
nop ; $09F769 |/
ldw (r4) ; $09F76A |\ if bowser egg's collision state
sub #0 ; $09F76B | | is anything but $00, meaning
bne .next_sprite ; $09F76D | | tonguable/collidable with everything
nop ; $09F76F |/ then skip to next
.return_flag_on
inc r1 ; $09F770 | return value flag on
To summarize, if there is currently no balloon sprite or egg sprite (unless the egg is being thrown), then we're good to spawn a new balloon. The return flag is r1, $0000 means we're good to spawn, anything else means do not spawn. This can be clearly seen after GSU returns:
; this routine checks to see if a new balloon w/ egg
; needs to be spawned and if so, spawns it
spawn_balloon_egg:
LDA $7A98,x ; $0DD8D3 |\ balloon timer not expired?
BNE .ret ; $0DD8D6 |/ skip balloon spawning
LDX #$09 ; $0DD8D8 |\
LDA #$F743 ; $0DD8DA | | gsu_check_bowser_egg_spawn
JSL $7EDE44 ; $0DD8DD |/
LDX $12 ; $0DD8E1 |
LDA $3002 ; $0DD8E3 |\
BNE .ret ; $0DD8E6 | | spawn Baron von Zeppelin w/ bowser egg
LDA #$00CD ; $0DD8E8 | | if GSU r1 flag returned 0
JSL $03A34C ; $0DD8EB | |
BCC .ret ; $0DD8EF |/
Upon spawning, a 50/50 random dice roll is done to determine which side the balloon spawns on, left or right. If left, it spawns at camera X - 48 pixels, if right, camera X + 288 pixels, and Y is always $0770. The timer also restarts upon spawning:
LDA $10 ; $0DD8F1 |\
AND #$0002 ; $0DD8F3 | | 50/50 random facing direction
STA $7400,y ; $0DD8F6 | |
TAX ; $0DD8F9 |/
LDA $0039 ; $0DD8FA |\
CLC ; $0DD8FD | | spawn at camera X + 288 (right)
ADC $D8CF,x ; $0DD8FE | | or - 48 (left)
STA $70E2,y ; $0DD901 |/
LDA #$0770 ; $0DD904 |\ exactly $0770 y position
STA $7182,y ; $0DD907 |/
LDX $12 ; $0DD90A |\
LDA #$0100 ; $0DD90C | | restart balloon timer
STA $7A98,x ; $0DD90F |/ at 256 frames
.ret
RTS ; $0DD912 |
This timer also gets cleared to $0000 during the second falling rock near the beginning, explicitly:
STZ $7A98,x ; $0DDAD0 | clear balloon timer
This will be after the first balloon already spawned, meaning another one can spawn just as soon as you throw the first egg after the second rock, which is much earlier than the full 256 frames it normally has to wait.