kion-dgl / Miku-Legends-2

Source Code for Writing files to the Megaman Legends 2 format to replace Megaman with Miku
https://kion-dgl.github.io/Miku-Legends-2/
GNU General Public License v3.0
4 stars 1 forks source link

Replace Special Weapons for Megaman Legends #27

Closed kion-dgl closed 2 months ago

kion-dgl commented 3 months ago

Adding an issue for updating the special weapons for Miku.

image

kion-dgl commented 2 months ago

I think i want to pick up this one next. The scope of the issue is to encode the different special weapon models and texture i got from SuitNTie22.

This issue can be further broken down into small components.

kion-dgl commented 2 months ago

Here is the picture that i'm using for Miku's face.

face-1

And this is the texture which include the special weapons.

megaman_img_002

The good news is that it looks like the same palette has been applied throughout the second file which means I only need to parse the palette.

The frustrating part is going to generate two palettes and then encode to of the same image respectively.

kion-dgl commented 2 months ago

Taking notes from some of my prior coding om this we have the following files:

// Read Special Weapons
megaman.readWeapon('PL00R02.DAT')
megaman.readWeapon('PL00R03.DAT')
megaman.readWeapon('PL00R04.DAT')
megaman.readWeapon('PL00R05.DAT')
megaman.readWeapon('PL00R06.DAT')
megaman.readWeapon('PL00R07.DAT')
megaman.readWeapon('PL00R08.DAT')
megaman.readWeapon('PL00R09.DAT')
megaman.readWeapon('PL00R0A.DAT')
megaman.readWeapon('PL00R0B.DAT')
megaman.readWeapon('PL00R0C.DAT')
megaman.readWeapon('PL00R0D.DAT')
megaman.readWeapon('PL00R0E.DAT')
megaman.readWeapon('PL00R0F.DAT')
megaman.readWeapon('PL00R10.DAT')

And then a reference for which file is what weapon:

00 - Lifter
01 - Kick
02 - Mega Buster
03 - Crusher
04 - Buster Cannon
05 - Hyper Shell
06 - Homing Missile
07 - Ground Crawler
08 - Vacuum Arm
09 - Reflector Arm
0A - Shield Arm
0B - Blade Arm
0C - Shining Laser
0D - Machinegun Arm
0E - Spread Buster
0F - Aqua Blaster
10 - Hunter Seeker
11 - Drill Arm

This is from: http://viper.shadowflareindustries.com/antigsc/?codes&dev=gs&system=psx&game=mml2

I think we want to pick a file and start somewhere, so we can start with the Shield Arm which should be PL00R0A.BIN and then we can look at the file.

It looks like the model starts at 0x1800. Something like the animation frames starts at 0x2000, potentially the animation tracks start at 0x3000 and the palette is defined at 0x3800.

We could write a test to see if all of the special weapons have the same format. But i think the place to start is to write a test for one of the models to export is as an .OBJ along with the texture.

kion-dgl commented 2 months ago

Shield Arm

The shield arm has three meshes included in it. The first looks like the shoulder.

image

The second object is the weapon itself.

image

The last is a flat plane which is probably used for the sprite of the bullet.

image

kion-dgl commented 2 months ago

I've been making a mental list of things that need to line up for the special weapon swap to work.

Texture

On the texture side of things, we need to pre-encode the palette for the face and special weapon. Then we need to encode and splice the face and special weapon palettes. And then we need to re-compress it to make sure it works in game.

Model

On the model side of things, we need to use the Miku shoulder, and then encode the special weapon, and include the plane, make sure it fits and then update the length in the file. And then update the palette in the special weapon.

Notes

I think we can take this list and then start tackling it in order.

I managed to update the encoding for the face with the updated special weapon, but i'm amazed at just how crusty MegaMan Legend is in terms of writing multiple versions of the same thing everywhere. So I made sure to update the script to write out the decompressed textures to PL00T2 and ST03a2. So we'll have to do a test to see if anything obvious breaks at this stage before encoding an example special weapon.

kion-dgl commented 2 months ago

First pass on this. Luckily nothing blew up.

image

For a second I was wondering why the aqua blaster looked different when i only updated the shield arm. but then i realized thi behavior is expected. Encoding my own texture updated the indexes, so the palette from the aqua blaster will be applied to different places.

Since we've confirmed this step, seems like the next step is to continue to encoding the model. The next step is going to be to add another script to encode weapons. Since the texture and palette are applied to all. That means well needs to take in an .OBJ for the weapons, and then write them to their respective files.

kion-dgl commented 2 months ago

My first pass on replacing the model. It's not like everything needs to go well on the first pass, but having things blow up can at least be confirmation that something happened.

With respect to the shield arm, I'm not seeing anything being updated in game aside from the texture being changed. The shield arm still loads in. One thing that I was able to troubleshoot and track down is that my ROM-patcher wasn't finding and replacing the shield arm, but even tracking that down and fixing it I still don't see anything changed in game.

Which means that we need to come up with an approach for diagnosing why we're not seeing a change and be more heavy handed until we see something observable. The two main options we have available at the moment are dumping the memory and see if we can see our change in memory, and the other approach is to try replacing everything.

I think the first approach is to dump the memory and see if we can see our changes at the expected offset. We can also try patching our special weapon into memory, or we can go crazy and replace everything, put in a debug string and dig down until we've figured stuff out.

kion-dgl commented 2 months ago

I went back and started writing tests for the various special weapons to export them as .obj files and one thing that I can confirm is that the numbering from cheats i was referring to isn't correct. It's probably close, but the shield arm is 0x09 and the blade arm is 0x0a.

So I'm going to finish writing tests for each of the files, and then pull up the game to make sure I've confirmed they map. The next step will be to extract part of the mesh and see if it shows up in multiple locations or not. But for now it looks like I managed to get the mesh patched in and i need to figure out what's going on.

image

Possible problems:

  1. UV's are wrong
  2. Texture is not being encoded correctly
  3. Material index is not being assigned correctly.

The two things I can think of are, to first see if the texture is being encoded correctly and then check my uv values to see if the blade arm is referencing the expected location.

I tried rendering the texture. Good news is that it looks correct. Bad news is also that it looks correct.

0-weapons

Which means that while we're narrowing down the possibilities of what it could be, i'm still confused about what it could actually be. I'm fairly confident in the texture and the geometry. Which means that we can try to narrow down and eliminate other possibilities.

We can try to include use our debug texture to see if that's what we see in game.

kion-dgl commented 2 months ago

I tried the debug texture and found no change in game.

image

But weirdly enough the viewer in the game is showing my debug colors for the textures.

image

Which likely means that the material index for the texture isn't being applied correctly and the game is using my updated palette likely with the body texture. A weird error to have but at least we've tracked down something plausible.

kion-dgl commented 2 months ago

I've spent half the day in the corner with my dunce cap on thinking about approaches or options for debugging and breaking down how the game manages special weapons. And I think I've come up with a strategy of two small things I can sanity check before moving on.

Fist sanity check is going to be confirming the location for the palette. I'm going to keep the existing blade arm weapon in the game and update the palette to be all red to make sure the file is the location being referenced. Nothing amazing, but we need to start somewhere.

The other sanity check we can do is to search for the vertices of one of the models against the ROM to see where it is stored for the viewer in the menu because we're going to want to update that too.

kion-dgl commented 2 months ago

image

And it turns out that when doing that, I found that I wasn't actually writing the updated weapon palette and that turned out to be it. It looks like there might be another issue with the leek missing a face or something. But I'm going to prioritize encoding more weapons to see if the same issue occurs somewhere else and if it's more visible and easier to debug.

Also there is still the viewer in the menu. I don't want to dig through the ROM for this, so I'll focus on that once i have the other models swapped out, and I can potentially use it as a mechanism for debugging.

kion-dgl commented 2 months ago

Why does clean code never work? Stashing this in case I can use it.


  const weapons = [
    {
      name: "  - 0x09 Shield Arm",
      src: readFileSync("out/PL00R09.BIN"),
      mod: readFileSync("bin/wpn_PL00R09.BIN"),
      modelOffset: 0x2000,
      textureOffset: 0x2800,
    },
    {
      name: "  - 0x0A Blade Arm",
      src: readFileSync("out/PL00R0A.BIN"),
      mod: readFileSync("bin/wpn_PL00R0A.BIN"),
      modelOffset: 0x1800,
      textureOffset: 0x3800,
    },
  ];

  weapons.forEach((weapon) => {
    const { name, src, mod, modelOffset, textureOffset } = weapon;
    console.log(name);
    replaceSegment(
      rom,
      [
        Buffer.from(src.subarray(modelOffset, modelOffset + 0x800)),
        Buffer.from(src.subarray(textureOffset, textureOffset + 0x800)),
      ],
      [
        Buffer.from(mod.subarray(modelOffset, modelOffset + 0x800)),
        Buffer.from(mod.subarray(textureOffset, textureOffset + 0x800)),
      ],
    );
  });
kion-dgl commented 2 months ago

image

I started somewhere in the middle with 0x0A, which turned out to be the blade arm. Andthen started working my way down. I got stuck on the hypershell, which the mod ended up being too big.

It wasn't quite enough to merge the vertex colors for the shoulder and the hypershell to get the bytes I needed. Weirdly enough, the game starts the offsets for the special weapon model at 0x2b88, which i think might share the same starting reference as the player model.

When I actually tried this the game blew up really quickly, and I'm not sure if it's an approach that can actually be used. For now I'm going to continue to try to move over more model models going up from the blade arm this time.

That means that I should write test cases to get obj objects to test against.

kion-dgl commented 2 months ago

I'm running into an issue where loading specific weapons will break the walk cycle for the animation. I think that what's going on is that while the file length has a limit of 0x800 bytes, the game is probably copying the animations into memory around 0x700 bytes or something.

image

This means that once I finish porting over the weapons I need to do a comparison of which weapons are working and which ones aren't and compare them in memory.