-
Notifications
You must be signed in to change notification settings - Fork 20
Hookbill the Koopa
Hookbill is the most technically complex boss in the game. He has a whopping 56 AI states, a skeleton for his body parts, one of which is drawn on a background layer, his body parts each have separate rotational values per animation frame, his graphics are mostly Super FX, and much of his processing is on the Super FX as well, despite even his 65816 code being over a quarter of a bank long. He touches on many, many aspects of the game's coding, lookup tables, etc.
crawl sequence:
00: restart crawl sequence - check if run needed (if yoshi is close)
01: crawling a little bit on all fours
jumping on head sequence:
02: spit egg (head goes down a bit)
03: head nudge back up
04: head go back to normal, stay frozen a bit, go back to 01
jumping on shell sequence:
05: spit egg (head goes down a bit)
06: head nudge back up
07: head go back to normal, stay frozen a bit, go back to 01
run sequence:
08: bob head slightly up (from the crawl)
09: stare forward not moving for a few
0A: stand up
0B: walk forward until yoshi close
0C: hunch forward
0D: (hit with egg while in the midst of standing up, closes eyes for a bit and skips to 0A afterward)
0E: run forward until yoshi close
0F: dives at yoshi
10: landing on ground, bobbing a bit
11: more landing/bobbing
12: more landing/bobbing
13: more landing/bobbing
14: blinking after landing
15: gets up back to a crawl
turn around on all fours sequence:
16: body into shell
17: jump up and turn around
turn around while standing sequence:
18: jump up and retract body into shell
19: rotate slightly
1A: rotate again, turning fully around
1B: fall back down and body comes back out, switch to 09
getting egged sequence:
1C: first two egg hits (init & jump to 1D immediately)
1D: angle backward, cry & wobble arms, ready for the next hit
1E: if not egged again, retract back to standing, switch to 09
1F: third egg hit (init & jump to 20 immediately)
20: hop up in the air from the third egg hit
21: fall back down while leaning backward
22: lean back to center
23: wobbling on back helpless
24: frozen on back
hopping in shell sequence:
25: wobbling back and forth after getting hit
26: one hop toward yoshi, turning around 180 degrees
27: two hops toward yoshi in the same fashion
28: pound onto ground, wait a bit, body come out of shell
ground pounded sequence:
29: initial hit, squishes & turns yellow
2A: flashes yellow then stretches back to normal
beginning cinematic sequence:
2B: small hookbill walking over
2C: waits on kamek routine to finish (via a flag)
2D: init/prep for growing
2E: init/prep for growing
2F: small hookbill crouching down ready to grow
30: turns into real hookbill shell
31: shell growing (and bobbing back and forth)
32: body comes out of shell, fight begin prep
death sequence:
33: initially dead, turn yellow
34: flashes yellow and squishes down a bit
35: squishes down and down into a pancake
36: shell break, small koopa goes up then down middle
37: dead, final state, do boss key bullshit etc.
Upon Yoshi's final hit onto Hookbill, there is code that governs exactly how much to move Yoshi's Y coordinate by. The basic formula comes down to this:
$700058 - $700056 - $700122 + 3
The main two SRAM addresses here ($0058 and $0056) get computed/stored in Hookbill's Super FX code:
CODE_08A636: iwt r0,#1C18 ;
CODE_08A639: add r10 ;
CODE_08A63A: to r7 ;
CODE_08A63B: ldw (r0) ;
CODE_08A63C: lms r0,(004E) ;
CODE_08A63F: to r8 ;
CODE_08A640: add r7 ;
CODE_08A641: sms (0058),r8 ;
CODE_08A644: lms r7,(0122) ;
CODE_08A647: lms r0,(0002) ;
CODE_08A64A: sms (0056),r0 ;
This code is necessary to be run each frame on Hookbill's final hit for proper placement of Yoshi. Blastoff occurs when this code is not run, and this happens because of a check:
CODE_08A61C: iwt r0,#1C16 ;
CODE_08A61F: add r10 ;
CODE_08A620: to r7 ;
CODE_08A621: ldw (r0) ;
CODE_08A622: lms r0,(004C) ;
CODE_08A625: to r8 ;
CODE_08A626: add r7 ;
CODE_08A627: lms r7,(0120) ;
CODE_08A62A: lms r0,(0000) ;
CODE_08A62D: add r7 ;
CODE_08A62E: to r4 ;
CODE_08A62F: add r0 ;
CODE_08A630: add r8 ;
CODE_08A631: cmp r4 ;
CODE_08A633: bcs CODE_08A65B ;
That last bcs can branch PAST the above code, therefore NOT running it and NOT properly placing Yoshi's Y coordinate. Because of this, and because address $700058 is written to elsewhere for completely different purposes, most if not all of the time you will get something like these values (taken from an actual trace):
$700058: $0001
$700056: $000F
Because $700058 was not properly computed (because the code was was branched past), it gets this "garbage" value of $0001 which it never would normally get. Because of this, our formula to move Yoshi goes like this:
$0001 - $000F - $000C + 3
This comes out to $FFE9, or -23! Now we are moving 23 pixels BACKWARDS, or in this case up, each frame. Which of course causes Yoshi to blast off to the moon.
So what causes this branch to go past the necessary code? That code simply checks to make sure Yoshi's X coordinate is within range of his shell. In brief, if Yoshi's X moves off the shell, he blasts off. Normally, this wouldn't happen, but it can if you ground pound him early because that would bypass AI states which zero out his X velocity (the process of him landing after falling, etc.), therefore he can retain his X velocity and keep moving left or right, while Yoshi stays stationary. This causes Yoshi to be outside the X bounds of his shell, which causes the check to branch past the necessary code.