Welcome to this series of tutorials on how to use the Metroid II disassembly. Please download and compile the disassembly beforehand. Make sure you have the correct version of RGBDS, because it tends to do breaking changes between versions. The disassembly's “build.bat” script will automatically download the correct version for you before compiling the disassembly. https://github.com/alex-west/M2RoS
Disassemblies are powerful tools in ROM hacking. They allow you to modify any data or behavior in the game with flexibility not found in other methods. I will be editing a missile refill to trigger the credits when touched. Follow along with me on your own copy of the disassembly.
Everything that is not the terrain or Samus is an enemy. This includes things that do not attack you, like power-ups or collectibles. A missile refill is a very simple enemy that can be found in Samus's gunship. If Samus does not have max missiles when she collides with it, it will refill Samus's missiles to max. But, did you know of its secret ability? When you have killed all metroids (excluding baby), the missile refill will trigger the credits when touched. The devs knew that spending missiles to beat the Queen Metroid was necessary. Therefore, Samus will not have max missiles and she will be able to trigger the missile refill when she touches it in the gunship.
The routine that runs when a missile refill is triggered is pickup_missileRefill
in “SRC/bank_000.asm”. Open “SRC/bank_000.asm” in your favorite code editor and go find that routine. (There are two instances of the string “pickup_missileRefill” in that file: the first is a pointer inside a jumptable, the second is the label for the routine)
Let's see what's going on in that routine. Luckily, there are comments to help us understand the logic behind the routine's code.
First, the routine checks whether or not the metroids are dead.
The metroidCountReal
variable contains the real quantity of metroids (including the regular metroids in the Queen's lab, but excluding the baby). So if that value is zero, it means that no metroid is alive and the credits will be triggered.
Here's what the ASM instructions relating to this mean. ld a, [metroidCountReal]
loads metroidCountReal
's value into the a
register, then and a
compares that value to zero : the zero flag is assigned the boolean value of (a == 0). jr nz, .else
will jump execution of code to the .else
label of the routine if zero flag is unset (metroids still remain).
The if branch, reached when zero flag is set, triggers the credits. The else branch, reached when zero flag is unset, refills Samus's missiles. We don't need to understand how they work, but you can look at the code of those branches anyway if you want.
If we change the value loaded into a
from metroidCountReal
's value to $00
, the missile refill should always trigger credits regardless of the quantity of alive metroids.
Replace ld a, [metroidCountReal]
with ld a, $00
and save the file. Now compile the ROM by running “build.bat” (don't use the makefile, it's incomplete) and test it out. Start a new game, shoot a missile so that Samus will no longer have max missiles, then enter the gunship and touch the missile refill. If everything went nicely, it should trigger the credits.
Extra challenge: Can you remove the now unused branches of code and the check, so that the routine will only contain the code to trigger the credits? If you did it right, the routine's line count should decrease from 23 to 12, and the credits should still trigger when you touch the missile refill.