Metroid Construction
Powered by LOVE

Index--Hacks--Docs--Tools--Hex--Patches--Videos--Forum

-> Documents -> How to add more enemies/PLMs to a room

You should be able to use Lunar Address, a hex editor, and be somewhat comfortable with SMILE. If you haven't already, consider reading this, this, and this. Make a back-up copy of your ROM for peace of mind.

Enemies have two separate pointers, "Enemy Pop/Allowed" and "Enemy Set" - Enemy Pop/Allowed determines the number of enemies you can have in the room, and Enemy Set is the number of different enemies that a room can have (0-4; the "Enemies Allowed" list in the enemy editor). For each new enemy added to the room or list, new bytes are written into the ROM. This data is crammed pretty close together in the original game, so you're eventually gonna wanna know how to point your enemies to free space and adjust how many there are.

What we're mainly looking for is the bank that the data for each of these is in, and the free space available in these banks to write it to instead. As seen in SMILE's Pointers window:

##   = bank
#### = pointer
--------------------------------
$83 | #### | FX1
$A1 | #### | Enemy Pop/Allowed
$B4 | #### | Enemy Set

$8F | #### | Scroll
?** | #### | Unknown1/RoomVar
$8F | #### | FX2
$8F | #### | PLM
$8F | #### | BG_Data
$8F | #### | Layer1_2
$8F | #### | Door Out
--------------------------------


Note the appropriate bank for what you want to repoint. For example, let's add enemies to a room that has no enemies at all. This would be the Enemy Pop/Allowed pointer, located in bank $A1. #### is the pointer that the game currently uses. In other words, the exact address in the ROM that this room's population data will write to. I'm going to use room 7A5ED, which has 9F5E as its Enemy Pop/Allowed pointer.

Fire up Lunar Address, and type A19F5E (A1 = bank, 9F5E = pointer) into the box above "SNES LoROM." You see that the "PC File Address" box displays 109F5E. This is the offset that we'd go to in the hex editor to see the data if we wanted to, but there's no reason to do that right now.

Bank $A1 begins at offset 108000 ($A18000) and ends at 10FFFF ($A1FFFF). It it used for nothing else at all except enemy room population. Each enemy placed in a room is 16 bytes. Free space in bank $A1 begins at 10EBD1 ($A1EBD1) in a clean ROM. You should see something very similiar to this in your hex editor if you haven't messed with anything in this bank yet:

FF = offset 10EBD1 ($A1EBD1); beginning of free space
FF = offset 10EBE0 ($A1EBE0); where I'm choosing to point to
----------------------------------------------------------
0010EBC0 | 00 03 00 00 A8 00 00 03 00 00 00 FF FF 00 FF FF
0010EBD0 | 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0010EBE0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0010EBF0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0010EC00 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
----------------------------------------------------------


For the sake of organization, I'm gonna use the free space one line under, starting at offset 10EBE0 so the rows of enemy data are even. Open Lunar Address again, type 10EBE0 into the PC File Address box, and see that the SNES LoROM box gives us A1EBE0. This means that EBE0 will be the new Enemy Pop/Allowed pointer for room 7A5ED, in place of 9F5E. Don't enter this new pointer in SMILE yet. It's time to get the one for Enemy Set in bank $B4 now, which is done exactly the same way.

Bank $B4 starts at offset 1A0000 ($B48000) and ends at 1A7FFF ($B4FFFF). Free space in a clean ROM begins at offset 1A74B8 ($B4F4B8). Each enemy in the "Enemies Allowed" list only uses 4 bytes. For the sake of organization again, I'll be pointing to 1A74C0 ($B4F4C0). If you've caught on yet, you'd know right away by now that this makes F4C0 the new Enemy Set pointer.

Open SMILE's Pointers window. Replace 9F5E with EBE0 for Enemy Pop/Allowed, 8615 with F4C0 for Enemy Set, and click "Save Pointers." Choose no when it asks you to "copy data or leave it?" The room has no enemies placed (and no data to carry over to the free space), so it doesn't matter.

Click Edit > Special > Enemy/PLM +/- and notice that this little red box says that both the enemies and PLMs in this room are at 00. Leave the PLM box alone. Bump the enemy number up from 00 to 02 for now and click Save Changes. SMILE will warn you about overwriting. This is exactly why we repointed, so click Yes. If SMILE then gives you a notice about having 0 PLMs in the room, just click OK - I'm not sure why it does that, but I doubt it's anything harmful. I checked the ROM to make sure nothing was written that shouldn't be and nothing was.

Now, look for a little knight wearing gold/brownish armor and holding a red shield. It's an enemy, and it'll probably appear on the top-left corner of the room. If it doesn't, click Help > Offscreen Enemies to Screen and look again. If you still don't see a knight, try the Enemy/PLM +/- again. After you find it, click on it, hold the click and move your mouse. You'll see there's another knight underneath it. Moving the second one doesn't reveal a third, so this means it successfully added 02 enemies to the room.

These knights are used to display unknown/erroneous enemies. Since these enemies were pulled out of the game's ass with no data written for them yet, this is normal. If you try loading the room while these knights are still in it, your game will freeze. Right-click on one of the knights and select "Species."

Pick an enemy that you want to replace these knights with. I'm going to use D0FF ("MERO"). Double-click on the enemy ID (in my case, I double-click on D0FF). This puts that ID into the "Enemies Allowed" box. Click the big "OK" to close the enemy editor and keep this change. Right-click on the other knight, select "Species" again, then click once on D0FF. See where it says "Palette 0000" in the Enemies Allowed box? Double-click on that 0000 and change it to 00001. Now click the big "OK" again. Both knights are now MERO enemies (or whatever enemy you picked).

Click File > Save Room in SMILE, then look in your hex editor at offset 10EBE0 again, where I pointed Enemy Pop/Allowed to. You should now see something like this:

FF = offset 10EBD1 ($A1EBD1); beginning of free space
## = New data written by SMILE (2 enemies)
----------------------------------------------------------
0010EBC0 | 00 03 00 00 A8 00 00 03 00 00 00 FF FF 00 FF FF
0010EBD0 | 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0010EBE0 | FF D0 B0 00 75 00 00 00 00 20 00 00 00 00 00 00 - enemy #0
0010EBF0 | FF D0 AE 00 60 00 00 00 00 20 00 00 00 00 00 00 - enemy #1
0010EC00 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
----------------------------------------------------------


See why I chose offset 10EBE0? Each enemy placed in a room takes 16 bytes of data. By default, most hex editors (I assume) display everything in 16-byte rows, which is why enemy 0 and 1 line up neatly. If I'd started at offset 10EDB1 where the free space first begins, each enemy would occupy part of two lines instead of having one whole line to itself. You don't have to do it this way, I just like to keep things tidy when possible. Over at 1A74C0 in bank $B4, something similiar has happened:

FF = offset 1A74B8 ($B4F4B8); beginning of free space
## = New data written by SMILE (1 enemy allowed)
----------------------------------------------------------
001A74A0 | 00 00 00 FF 00 00 00 00 00 FF 00 00 00 00 00 FF
001A74B0 | 00 00 00 00 00 FF 00 00 FF FF FF FF FF FF FF FF
001A74C0 | FF D0 00 00 FF FF FF FF FF FF FF FF FF FF FF FF
001A74D0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
001A74E0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
----------------------------------------------------------


If you took all that in, you should have no problem converting offsets (PC addresses) into LoROM addresses/pointers using Lunar Address, and having complete control over how many enemies are in each room of your hack. Controlling the number of PLMs in a room is done the same way, except instead of banks $A1 or $B4, room PLMs are in bank $8F.

Bank $8F starts at offset 78000 ($8F8000) and ends at offset 7FFFF ($8FFFFF). Free space in a clean ROM begins at offset 7E99A ($8FE99A). I'm going to point them to 7E9A0 ($8FE9A0) and add 6 PLMs. Since I'm still in room 7A5ED, I'll change its PLM pointer from 8A3C to E9A0. After using the red Enemy/PLM +/- box to add 06 PLMs to the room, look for a red square with a black question mark in it. Click Help > Offscreen PLM's to Screen if you don't see them.

These red question blocks are to PLMs what those knights are to enemies. If you load the room with these dataless PLMs present, your game will probably freeze. Turn these 6 question blocks into whatever normal PLMs you want (they'll be stacked on top of each other like the knights were, at the very top-left), then click File > Save Room.

This is what the hex is looking like for me after adding 06 PLMs to the room (1 missile, 1 super missile, 1 power bomb, 1 red door, 1 green door, 1 yellow door):

FF = offset 7E99A ($8FE99A); beginning of free space
## = New data written by SMILE (6 PLMs; 38 bytes)
----------------------------------------------------------
0007E980 | 00 02 00 00 00 FE FF FE FF FE FF FE FF FE FF 00
0007E990 | 00 02 00 02 00 02 00 00 00 FE FF FF FF FF FF FF
0007E9A0 | DB EE 13 06 B0 00 DF EE 15 06 B1 00 E3 EE 17 06
0007E9B0 | B2 00 72 C8 4E 06 B4 00 90 C8 01 06 B5 00 00 00
0007E9C0 | 25 03 97 00 00 00 FF FF FF FF FF FF FF FF FF FF
----------------------------------------------------------


Might seem complicated, but it's all very simple after you do it a few times. The most important thing is knowing what offsets are, converting offsets to LoROM addresses using Lunar Address, and knowing that the last 4 digits of the LoROM address will be your pointer. Your hex editor should tell you which offset you're on, probably somewhere along the bottom of the window.

To further illustrate how it works, let's assume you've made a sweet new room. It has just the right number of enemies and PLMs that you wanted it to have. Let's just say... 09 enemies placed in it, 3 different enemies in the "Enemies Allowed" list, and 06 PLMs. The room is done, and you're ready to add enemies/PLMs to another room. All you have to do is pick a spot somewhere in the free space (shown as FF FF in the hex editor) of the appropriate bank that you want your enemies/PLMs/whatever to write to. Write down the offset for this spot.

I'll use PLMs as an example this time instead of enemies. As we know, PLMs are in bank $8F. Look at my hex editor again, where I wrote 6 new PLMs by pointing to E9A0. The PLM data starts at offset 7E9A0 and stops at offset 7E9C5, meaning it's 38 bytes long. So, each PLM wrote about 6 bytes each. I'm sure it varies more depending which PLMs you choose to use in your room, unlike enemy population, which is always 16 bytes per enemy.

Okay, so we have one of two scenarios now: you're either 100% satisfied with your room and have no intention of adding any more enemies/PLMs, or you think you'll want to come back to this room later and adjust them. Maybe a mixture of both. If you're 100% satisfied, you'll want to write the PLMs you add to your next room right after where the 6 PLMs for room 7A5ED end. Since 7A5ED's PLMs take 38 bytes that start and end at offsets 7E9A0-7E9C5, you could write the next room's PLMs to offset 7E9C6. This is assuming that you will be making absolutely NO adjustments to your PLMs at all! This might include moving them or changing the type of PLM used.

You should only do this if you're confident that you are finished. On the other hand, if you think you might want to change them later, it's just a matter of moving farther ahead to another offset instead of 7E9C6, which is the very next byte after 7A5ED's 6 PLMs. Let's say you think you might even decide to throw 2-3 more PLMs in later. Go with a safe number like 16 bytes. Move 16 bytes right and write down the offset.

FF = offset 7E9C6 ($8FE9C6); NEW beginning of free space
FF = offset 7E9D6 ($8FE9D5); +16 bytes
----------------------------------------------------------
0007E9A0 | DB EE 13 06 B0 00 DF EE 15 06 B1 00 E3 EE 17 06
0007E9B0 | B2 00 72 C8 4E 06 B4 00 90 C8 01 06 B5 00 6C C8
0007E9C0 | 25 03 97 00 00 00 FF FF FF FF FF FF FF FF FF FF
0007E9D0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0007E9E0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
----------------------------------------------------------


Just like that, there's the next pointer. E9D6. The 16 bytes between it and E9C6 are for the edits to room 7A5ED's PLMs. As you add more PLMs or make certain changes, those 16 FF FF bytes will be overwritten by other values. Keep your hex editor open and watch these 16 bytes while you're PLM editing. Save your room often and check out what the hex is doing. Make sure that whatever you do with the room's PLMs doesn't write more than 16 new bytes of data, otherwise it begins (over)writing past the data at pointer E9D6. You really don't want that. I don't know about other hex editors, but HxD instantly displays changes made to the hex by SMILE after I save the room and un-minimize HxD's window.

That's about as well as I can explain pointers and repointing. This knowledge applies to every pointer in SMILE's Pointers window. Get comfortable with doing this, and you'll almost be without limits on what you can do to a room. Most of them are in bank $8F, so give each new thing you point there plenty of FF FF bytes to overwrite. I'll end this with a tiny bank reference and free space locations.

Bank $83: 18000-1FFFF / $838000-$83FFFF
Bank $8F: 78000-7FFFF / $8F8000-$8FFFFF
Bank $A1: 108000-10FFFF / $A18000-$A1FFFF
Bank $B4: 1A0000-1A7FFF / $B48000-$B4FFFF

Bank $83: free space @ 1AD66-1FFFF / $83AD66-$83FFFF
Bank $8F: free space @ 7E99A-7FFFF / $8FE99A-$8FFFFF
Bank $A1: free space @ 10EDB1-10FFFF / $A1EDB1-$A1FFFF
Bank $B4: free space @ 1A74B8-1A7FFF / $B4F4B8-$B4FFFF
Site design by begrimed