kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Mar 10, 2019 18:47:46 GMT -5
Okay, now that I know how the game sets the offset for the stage vertices and uv's I guess it's time to start making a program to debug this stuff. - I can re-use the character viewer and gut most of the content - I removed the pre-porgrammed values in favor of having the client look for STG files - And now I'm emulating the PSX memory, so we'll see how well this approach works Edit: Okay, so next update. I changed the left sidebar from pre-set values to having the page search through the saved files in IndexedDB and looking for files that have IDX/MDT/STG information declared inside of them. After a stage is click, the program reads the MDT file to get the number of Z and X tiles and the offset to the room declaration, and populates the room list. When a stage is clicked, room 0 is automatically loaded as well. When a room is clicked, the page calls the function to load the room. Loading the room will have the page look at the number of Z and X tiles, and then the offset to the room. The page will then create an array to store all of the tiles, and read the tile type and tile height for each tile in the room. To display the stage geometry, the page then creates a list of unique tile types declared in the room, and then jumps to the IDX offset. The IDX offset contains the Z and X location (which needs to be debugged), and the pointer to the STG file which contains the vertices, faces and UV for the actual stage geometry. MDT - defines stage dimensions with tiles, and defines the tile type and tile height IDX - defines the absolute position of stage geometry, and the pointer to where the geometry is defined in the STG file STG - defines the actual geometry that makes up the stage the player is in, as well as the collision hull So in the above screenshot, we're reading from the file ST04.BIN, and we're reading room 0, which is the Apple Market. And to start with, I wanted to see if I could draw one tile type, specifically the one I've been doing testing with, which is tile type 5, and the results are as seen above, it turned out to be not too hard to display a stage geometry, now that I know where everything is. Now the next step is to figure out how to start piecing the different tiles together. Tile type 5 spans the entire width of the Apple market, which is two tiles in length. So if I take the x-width, and z-depth, then I should be able to figure out how large the game defines one tile as. Also one thing to mention is that the tile is multiplied by four. { "min": { "x": -32, "y": 0, "z": -16 }, "max": { "x": 32, "y": 0, "z": 16 } } So here we have the dimensions of the floor tile, which is 64 units wide in the x direction, and 32 units long in the z direction. Since the tile of the tile is multiplied by four (or is it?) that means a single tile is 128 by 128. Actually hmmm, 0x10 is 2-times scale, 0x20 is 4-time scale and 0x40 is probably 8-time scale. So a single tile is 256x256 of what ever units the game uses. pastebin.com/VVfJcXrf[/code]
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Mar 12, 2019 11:55:34 GMT -5
Okay so this last edit went both better and worse than expected. Better than expected in the field of placing tiles together. I didn't have any idea of what the tile size ahead of time was, but it turns out that multipliying the tile location by 128 and then scaling the tiles placed them in the right position in a lot of cases. And worse in the fact that doing this doesn't work for other rooms, so I could just be doing it wrong, or there could be more values that I need to test, debug and find. I think the next thing to work on is applying textures and UV. When I load the stage file, I check to see if there are any TIM files in the archive. I need to add in the framebuffer image and pallet position. And then I need to add a look up from the stage textures to see if the textures needed are included in the file. And if they are included, go ahead and render and apply them. Edit: Looking up texture coords: var image_coords = fp.getUint16(ofs + 0, true); var pallet_coords = fp.getUint16(ofs + 2, true); ofs += 4;
var y_ofs = image_coords & 0x10 ? 256 : 0; texture_list[i] = { "image_x": (image_coords & 0x0f) << 6, "image_y": y_ofs, "pallet_x": (pallet_coords & 0x3f) << 4, "pallet_y": pallet_coords >> 6 }; Reading texture header var tim = { "offset": ofs, "pallet_x": fp.readUInt32LE(ofs + 0x0c), "pallet_y": fp.readUInt32LE(ofs + 0x10), "nb_colors": fp.readUInt32LE(ofs + 0x14), "nb_pallet": fp.readUInt32LE(ofs + 0x18), "image_x": fp.readUInt32LE(ofs + 0x1C), "image_y": fp.readUInt32LE(ofs + 0x20), "width": fp.readUInt32LE(ofs + 0x24), "height": fp.readUInt32LE(ofs + 0x28), "name": str }; Render Image function api_renderImage(tex) {
// Create Canvas
let canvas = document.createElement("canvas"); canvas.width = 256; canvas.height = 256; let ctx = canvas.getContext("2d");
// Create Texture
let texture = new THREE.Texture(canvas); texture.flipY = false;
// Read the pallet
let view = new DataView(tex.pallet_file.data);
let pallet = null; let ofs = 0;
do {
let name = ""; for (let i = 0; i < 0x20; i++) { let byte = view.getUint8(ofs + 0x40 + i); if (!byte) { break; } name += String.fromCharCode(byte); }
if (name !== tex.pallet_name) { continue; }
let nbColors = view.getUint32(ofs + 0x14, true); pallet = new Array(nbColors);
ofs += 0x100; for (let i = 0; i < nbColors; i++) { let color = view.getUint16(ofs + i * 2, true); let r = ((color >> 0x00) & 0x1f) << 3; let g = ((color >> 0x05) & 0x1f) << 3; let b = ((color >> 0x0a) & 0x1f) << 3; let a = color > 0 ? 1 : 0; pallet[i] = "rgba(" + r + "," + g + "," + b + "," + a + ")"; }
break;
} while ((ofs += 0x400) < view.byteLength);
// Return null if pallet doesn't exist
if (!pallet) { throw new Error("Could not find: " + tex.pallet_name); }
// Read the Image
ofs = 0; view = new DataView(tex.image_file.data);
let image = null;
do {
let name = ""; for (let i = 0; i < 0x20; i++) { let byte = view.getUint8(ofs + 0x40 + i); if (!byte) { break; } name += String.fromCharCode(byte); }
if (name !== tex.image_name) { continue; }
image = {}; image.inc = 1; image.block_width = 64; image.block_height = 32; image.colors = view.getUint32(ofs + 0x14, true); image.x = view.getUint32(ofs + 0x1c, true); image.y = view.getUint32(ofs + 0x20, true); image.width = view.getUint32(ofs + 0x24, true) * 2; image.height = view.getUint32(ofs + 0x28, true);
if (image.colors === 16) { image.inc *= 2; image.block_width *= 2; image.width *= 2; }
image.body = new Array(image.width * image.height); image.offset = ofs + 0x800;
break;
} while ((ofs += 0x400) < view.byteLength);
if (!image) { throw new Error("Could not find: " + tex.image_name); }
for (let y = 0; y < image.height; y += image.block_height) { for (let x = 0; x < image.width; x += image.block_width) { for (let by = 0; by < image.block_height; by++) { for (let bx = 0; bx < image.block_width; bx += image.inc) {
let byte = view.getUint8(image.offset++); let pos;
switch (image.colors) { case 16:
pos = ((y + by) * image.width) + (x + bx); image.body[pos] = pallet[byte & 0xf]; pos = ((y + by) * image.width) + (x + bx + 1); image.body[pos] = pallet[byte >> 4];
break; case 256:
pos = ((y + by) * image.width) + (x + bx); image.body[pos] = pallet[byte];
break; }
} } } }
let y_ofs = image.y % 256; let x_ofs = 0;
// Draw Image to canvas
for (let y = 0; y < image.height; y++) { for (let x = 0; x < image.width; x++) { ctx.fillStyle = image.body[y * image.width + x]; ctx.fillRect(x + x_ofs, y + y_ofs, 1, 1); } }
// Return texture
texture.needsUpdate = true; return texture;
}
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Mar 15, 2019 1:16:20 GMT -5
Since I made my post too long posting code, notes I'll make a new post for these updates: So I implemented the searching and rendering of textures. Right now at least the textures are being rendered correctly, that's not something that I would be too happy about having a bug to work out. It looks like I have a function that I can copy and paste to render textures, so that isn't the issue. The issue seems to be correctly matching the textures to the geometry. And that's where I seem to have an issue. One problem I have is that the pallet can't be found in a lot of cases. So it could be the game expects to have things like INIT_DAT.BIN, or SUPPORT.BIN loaded into memory. Right now I'm creating a default texture when either the pallet or image can't be matched to a framebuffer coordinate. Though one thing I'm slightly more concerned about is false positives, but i think one reason for that is I'm currently not adjusting for multiple textures drawn in one region of the framebuffer. I think I can go back and fine tune textures later, so right now I'm going to stay focused on improving what I can with drawing the geometry. The starter dungeon outside the Apple Market shows two of the issues I still have pretty clearly. One is that I'm not drawing tiles yet. So I think adding those in will provide some structure and allow me to see the floor of how the stage is laid out, and the second is elevation. So I need to look at the height of tiles and adjust accordingly.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Mar 17, 2019 10:18:02 GMT -5
Kion is confused. He hurt himself in confusion. (placeholder for notes) Okay, now I have a chance to comeback and add come context to these images. So looking through my stage exports, I'm finding that large portions of the map are generally missing, and that rooms will often be duplicates of other rooms. And I think these might be two problems with my interpretation. The MDT define the tiles for stages. Each tile type seems to have a index in the IDX file which points to the STG file which draws the geometry in the actual stage. Since the IDX file defines the absolute position of the geometry that gets drawn, this seems to indicate that its the unique tile types end up defining what geometry gets drawn in the scene. This seems to be either wrong or incomplete. As we see in the image above which should be the area outside of City Hall, we only see the lower area in front of the South Gate defined, but none of the buildings on the hill. After adding placeholder tiles into the map, we can see that the whole map is much larger than the geometry being drawn into the scene. Which completely confuses me on how this game actually manages the index. As when I tested the Apple Market, parts of the stage would either appear or disappear if any tile type was defined any where in the MDT file once. However using this approach has two major issues. One it looks like that there are more parts of the stage that aren't included in the MDT file, that still need to be drawn, and second is that the game re-uses the same tile types several times. Since I can edit the source for pcsxr, one approach would be to log all of the indices that the game calls for drawing areas of the map, run them though the application and see what results that provides. On the condition that this approach works, the next step would be to either brute force the entire game, or try to figure out where the game is referencing these indices from. This is mostly another map thrown out there. One thing I'm finding is that I think the game uses a size of 256x256 (units) for their tile size. And the tiles generally should match up with the size of the geometry being drawn on top of that. But in addition to positioning, scaling and texture look up, this isn't so important right now. I think one cheat I might implement is rather than trying to get the entire stage all at once, I might add a "one tile at a time" approach to allow the different tile types to be viewed, and assembled manually (if needed/desired).
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Mar 19, 2019 0:48:47 GMT -5
Okay, I split up the stage viewer to only view one tile at a tile, and I found what I originally expected to see. And that's that the game vertically slices parts of the geometry to fit into a square area. So the next question is how these are actually placed. Originally I thought the entries in the MDT file were read by the IDX file and then looked up in the STG file from there, but that only seems to be one way that the game defines absolute geometry. There also seems to be a direct lookup. So the next step will be to look at the MDT files again and see how the numbers match up with the individual tiles. Edit: Might as well update this post. Got the tile viewing mostly working. Ended up going with a single tile viewer with the option to debug and swap out textures. Fixed the flutter after watching this video back, it turns out the y coord is unsigned while the x and z coordinates are fine. Things to do: - Add an option to make textures transparent. Right now transparent textures show up as black because geometry will disappear entirely if the wrong image is referenced. So having black will show something there. I think I might add a checkbox under the image select element. - Add an option for double sided faces. Right now things like the Apple Market banner and plants are single sided even tough they're probably double sided in game. There is a byte for each quad where I think the game declares flags (common ones are 4, c4 and 20), so one of these might be for double side or not. If something is double sided I think the easiest way to implement it would be to add the same face backwards. Edit: - Added a manual toggle to make textures transparent or not. - Right now I'm using 0x04 as the flag for double sided. Not sure if this is correct or not, but this was the only bit that was consistently set on quads that needed to be double sided. The problem is if that's the case, then the dev's were double-side crazy, because that bit is set pretty much everywhere.
|
|
|
Post by uradamus on Mar 29, 2019 18:00:36 GMT -5
I finally got caught up with this thread and one thing that came to mind for me is that in most cases the level textures use the palettes to fake lighting transitions. Though sometimes they seem to be animated lighting effects and in a few special cases are very different color scheme palette swaps (but even these may be lighting effects, for like explosions or something). For instance in the demo dungeon at the start of the game, you will notice some of the wall tiles have some pulsing lights embedded in their cracks, that seems to be handled by a steady palette swap animation.
I bet some of that section where you found values that played with the scene lighting levels are using palette indexes to make further away stuff appear darker or lighter (depending on if you are above or below ground, above ground gets lighter for a distance fog like effect while below ground gets darker the further away tiles get). I'd imagine the engine does some basic math to determine a tile's distance from the player and which range that falls into to provide a palette index. The depth shading ones always seems to go in descending order from nearest to furthest.
In any case, for export purposes, you would generally always want the first correct palette option as that will generally be the base fully lit/saturated one while the remaining ones will generally be lighting effect animation frames or depth shading transitions and you wouldn't want any of that baked into the exports.
|
|
|
Post by murdertrain7848 on Apr 8, 2019 19:11:24 GMT -5
I just wanted to say that you all are doing an amazing job. I hope y'all keep up the good work and when it's finished, I can't wait to play it. I wish I knew more about this so I could help so, I figured I'd help you guys get a swollen head, lol. Seriously, thanks for the effort.
|
|
|
Post by uradamus on May 13, 2019 3:47:33 GMT -5
For getting accurate UV conversions from 0-255 to the 0-1 space used by most tools today, it would be preferable to switch away from the current divide by 255 method. Considering the game used 256x256 image buffers and 256 possible UV values in each axis, that tells us they intended UVs to fall in the center of pixels. So we can divide 1 by 256 to get the width of a pixel within the 0-1 space. Which turns out to be 0.00390625 and since we want the middle of a pixel, half of that value is 0.001953125. So the best way to convert would be to multiply each UV component by the width of a pixel, which will bring us to the leading edge of the desired pixel and to that we want to add half a pixel width to get to its center. So the equation for this would look something like:
value * 0.00390625 + 0.001953125
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on May 14, 2019 21:05:20 GMT -5
For getting accurate UV conversions from 0-255 to the 0-1 space used by most tools today, it would be preferable to switch away from the current divide by 255 method. Considering the game used 256x256 image buffers and 256 possible UV values in each axis, that tells us they intended UVs to fall in the center of pixels. So we can divide 1 by 256 to get the width of a pixel within the 0-1 space. Which turns out to be 0.00390625 and since we want the middle of a pixel, half of that value is 0.001953125. So the best way to convert would be to multiply each UV component by the width of a pixel, which will bring us to the leading edge of the desired pixel and to that we want to add half a pixel width to get to its center. So the equation for this would look something like: value * 0.00390625 + 0.001953125 UV values in megamanlegends.gitlab.io/mml1-psx/ebd/ and megamanlegends.gitlab.io/mml1-psx/mdt/ have been changed to this format. fs = prim.quadOfs; for (let i = 0; i < prim.nbQuad; i++) {
let au = view.getUint8(ofs + 0x00) * 0.00390625 + 0.001953125; let av = view.getUint8(ofs + 0x01) * 0.00390625 + 0.001953125;
let bu = view.getUint8(ofs + 0x02) * 0.00390625 + 0.001953125; let bv = view.getUint8(ofs + 0x03) * 0.00390625 + 0.001953125;
let cu = view.getUint8(ofs + 0x04) * 0.00390625 + 0.001953125; let cv = view.getUint8(ofs + 0x05) * 0.00390625 + 0.001953125;
let du = view.getUint8(ofs + 0x06) * 0.00390625 + 0.001953125; let dv = view.getUint8(ofs + 0x07) * 0.00390625 + 0.001953125;
let ai = view.getUint8(ofs + 0x08) + vertexOfs; let bi = view.getUint8(ofs + 0x09) + vertexOfs; let ci = view.getUint8(ofs + 0x0a) + vertexOfs; let di = view.getUint8(ofs + 0x0b) + vertexOfs;
let face = new THREE.Face3(ai, bi, ci); face.materialIndex = prim.texId; geometry.faces.push(face);
face = new THREE.Face3(bi, di, ci); face.materialIndex = prim.texId; geometry.faces.push(face);
let a = new THREE.Vector2(au, 1 - av); let b = new THREE.Vector2(bu, 1 - bv); let c = new THREE.Vector2(cu, 1 - cv); let d = new THREE.Vector2(du, 1 - dv); geometry.faceVertexUvs[0].push([a, b, c]); geometry.faceVertexUvs[0].push([b, d, c]);
ofs += 0x0c }
For the palette issues my intention is to start testing that with save states now that I've rounded out the texture editor.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on May 16, 2019 9:07:48 GMT -5
Okay, now that I'm at a stopping point with the texture editor, I can go back to taking things out instead of putting them back in. Which means the next step is to start playing around with save states. Generally I've been using Pcsxr, which has the advantage of being open source, so I can look at the code and specifically find what is stored in the save state where. If I can find similar information for epsxe later, then that might be a possibility. But unless there's documentation for it, I would prefer not having to spend time to reverse engineer epsxe's save state format, when I could be spending time on reading information from the save state itself. As for how save states are managed in pcsxr, the source file in which save states are handled is libpcsxcore/misc.c int SaveStateGz(gzFile f, long* gzsize) { ... gzwrite(f, (void *)PcsxrHeader, sizeof(PcsxrHeader)); gzwrite(f, (void *)&SaveVersion, sizeof(u32)); gzwrite(f, (void *)&Config.HLE, sizeof(boolean)); gzwrite(f, pMemGpuPic, SZ_GPUPIC); gzwrite(f, psxM, 0x00200000); gzwrite(f, psxR, 0x00080000); gzwrite(f, psxH, 0x00010000); gzwrite(f, (void *)&psxRegs, sizeof(psxRegs)); gzwrite(f, gpufP, sizeof(GPUFreeze_t)); gzwrite(f, &(spufP->Size), 4); gzwrite(f, spufP, spufP->Size); }
So the nice part is that we can see the source to see where everything is stored in the save state file. Trying to work with this blind would really suck, because there isn't any attention put into padding and everything is stacked on thing on top of the last with nothing fitting into their proper four byte boundaries. Though random complaints aside, the information we're interested in is psxM and gpufP, so we can pop in the gztell(f) as a way to print out the offset this data is put in the save state. Something that's kind of weird or interesting is that the vram is defined inside GPUFreeze_t, so we can lookup the definition in plugins.h. typedef struct { uint32_t ulFreezeVersion; uint32_t ulStatus; uint32_t ulControl[256]; unsigned char psxVRam[1024*512*2]; } GPUFreeze_t; So since the vram is defined at the end of the struct, we can use ftell afterwards and subtract the difference to get the start offset of the vram. And then to double-check that we have the right offsets, we can write psxM and vram to their own files, and then get the offset from the save state to make sure they're correct. Edit: Okay we have some numbers. Psx Memory Offset: 0x9025 Psx Vram Offset: 0x29B749 The Psx Memory has a length of 0x200000 and the vram has a length of 0x100000. So we can unpack and double check the offsets with a script. But before we do that, we can take a look at the files to make sure we have the data that we want to work with in the first place. Okay I checked the raw files. The memory had stuff where I expected it to be and the vram rendered nicely. I guess pcsxr doesn't use vram for rendering the output. As for epsxe save state format, I could try asking on the forums: www.ngemu.com/forums/epsxe.7/
|
|
|
Post by uradamus on May 16, 2019 23:46:50 GMT -5
I found a few tiles that the viewer may have failed to load properly, they belong to the library's interior in ST05.BIN. Tiles 63 and 64. Tile 65 is also part of the library interior, but seems fine with all of it's geometry present.
The two problem tiles both contain basically the same floor and 64 additionally has 1 wall, presumably the entrance to the library. But nothing else. Yet they both have 7 textures associated with them. Considering the lack of most of the walls and any furnishings, I can only conclude that there is something different about these models that the viewer isn't accounting for. So they should be a useful test case.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on May 17, 2019 12:30:25 GMT -5
I managed to get another proof of concept test out of the way. First I wrote the psx cpu memory and psx gpu memory into their own files, and then gunzipped the save state to check their respective offsets in the file, and I was able to confirm the values I printed out from the console in pcsxr. psxM : 0x9025 vRam : 0x29b749 For working with save states, I'd like to be able to gunzip in the browser to be able to skip the step of having to decompress before working with the tool. So I came across this library that supports a lot of different compression methods: github.com/imaya/zlib.js. And tested to see that I could gunzip a save state, and then gunzip a save state with javascript and compare the output of the two files, and I was able to get the same result. So it looks like I can load in a save state. If I can get the offsets for ePsxe, then I think that could be viable as well. Other random things to take note of atm: 1. I wrote a boat load of documentation for the ebd format. It can be found here: gitlab.com/megamanlegends/mml1-psx/wikis/04-EBD-Models2. Played around with fixing the flipped models. It looks using mesh.setScale(-1,1,1) will mirror flip the mesh in the x direction, though the changes are only cosmetic. Otherwise it looks like I can flip the x vertex value, but that causes issues with animations. 3. Looks like I need to play around with uv y values some more. I'm not sure which direction is which but for textures zero can be declared as either from the top or from the bottom. I'm trying to find values that play nice with blender, noesis and other formats. 4. The ST05 library tile sounds super broken, i'll use it as a test case when implementing tiles. Edit: Noticed this when writing documentation for the EBD format. In most cases the game copies the EBD file into the RAM at offset: 0x8016c000. However, after going back and checking I have determined this to be false. In most cases the EBD file will be copied into 0x8016c000, however there are a few exceptions, and they are listed below along with the offset (mostly ending credits and support car). Starting read: ST0D_00.BIN Found: ..\EMBIN\ST0D_00B.EBD Memory: 0x80190000 Starting read: ST0D_00C.BIN Found: ..\EMBIN\ST0D_00B.EBD Memory: 0x80190000 Starting read: ST0D_00D.BIN Found: ..\EMBIN\ST0D_00B.EBD Memory: 0x80190000 Starting read: ST17.BIN Found: ..\EMBIN\ST17_00B.EBD Memory: 0x80190000 Starting read: SUPPORT.BIN Found: ..\EMBIN\SUPPORT.EBD Memory: 0x801f2000 Starting read: SUPPORT2.BIN Found: ..\EMBIN\SUPPORT.EBD Memory: 0x801f2000
Edit: I decided to take another look at the models being mirrored on the X-axis. And as far as I can tell this seems to be intentional on the part of the developers. One option I tried was forcing quads to render is a defined order so that the "POLICE" sign would come out correctly. And that's about the only thing that get's fixed, as everything else like the tire rims get completely messed.
I also tried flipped x = -x to try and flip the orientation of the model. That flips the render order of the faces, to render on the inside of the model. However, those can be fixed by changing the indices order on each face. The issue is the animations break, because by reversing the positions of the bones and vertices, bones are now on the opposite side of where they are intended to be. So as far as I can tell after checking, this does seem to be the "intended" way the models are stored as this is the only orientation for how they work. As for why, my best guess is that the function they used to render the game flipped the models, and rather than have their programmers fix it, they had their animators adjust the assets accordingly. This can be fixed cosmetically by scaling x by -1, but not something I want to spend time on by trying to tweak the geometry. Never mind, I think I have an idea of why this is wrong, I'll make another post if I end up being right about it.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on May 24, 2019 10:44:45 GMT -5
Okay, new tool: megamanlegends.gitlab.io/mml1-psx/saves/To be lazy I'll copy explanation from discord. right now it only works for pcsxr save states and the states don't need to be decompressed pcsxr uses gzip to compress the save state files, but it turns out there is a javascript implementation for gunzip so the save state from pcsxr can be loaded in as-is you can then preview the models and tiles and then download with proceed to batch export everything that can be previewed the download button is still very janky it doesn't have any hover effects, and i didn't add any loading or icon to show it's working i recommend opening the console to see the debug messages in there and it will take a decent amount of time to loop through everything depending on your computer's clock s my laptop is a fanless core M, and it takes about four minutes or more for the batch process to complete not sure how good or shitty that is spec-wise (probably more on the shitty side), but just be aware it's more on the slow side than instant Edit:
Map tile grid is now being exported, as a mock-up tile and as json. Thanks to Trege, stage and room number as read from save state as well. Next steps for mml1 - implement animations - read pbd files from memory - look into font file format
Edit: A few slight tweaks to the save state page. Thanks to Trege i was able to add in the label for the current stage and room that the save state was taken in. And I addressed an issue with the ebd uv's being off by a single pixel. I also changed around the order of the download function. Rather than the batch conversion I had which parsed all of the models, and then exported them in one loop, I changed the function to parse and add each mesh to the zip one at a time. Javascript seems to handle this approach better as it doesn't seem to slow down the browser as much. I also added in a progress bar since the process isn't instance. I also need to add a value that indicates if a batch export is in progress or not to avoid double-exports. Added a button to export the 2MB of playstation memory being used. Added a button to export the Playstation vram as an image. Two minor issues that I want to work on. One for STG files I added in a check to see if transparent pixels were being used in the model to set the use alpha flag in the material. I should add that into the EBD models as well. And second is when I was creating the transparent check for the stage tiles I noticed some suspicious tile faces that didn't look like they do anything, So I want to try filtering those out. Edit: Okay added the transparency check on the ebd models. As for the uv's, the reason is the game uses a single pixel to define a solid color and re-uses the same coords. These faces don't need to be removed from the tile models. Next I think I'll start poking at PBD models. Which means 1) I need to fetch a list of all of the PBD models and 2) I need to scan the psx memory to find out exactly where these models are stored. Edit: Next I think I'll start looking into pdb files. First step is to find all of the pbd files in the DAT folder: { '..\\PLBIN\\PL00L00S.PBD': { matches: [ 'ARM00L.BIN', 'INIT_DAT.BIN' ], length: '0xf8', memory: '0xdcd00' }, '..\\PLBIN\\PL00L00M.PBD': { matches: [ 'ARM00L.BIN', 'INIT_DAT.BIN' ], length: '0x440', memory: '0xf1600' }, '..\\PLBIN\\PL00L00P.PBD': { matches: [ 'ARM00L.BIN', 'INIT_DAT.BIN' ], length: '0x1088', memory: '0xfca00' }, '..\\PLBIN\\PL00R00S.PBD': { matches: [ 'ARM00R.BIN', 'INIT_DAT.BIN' ], length: '0xf8', memory: '0xdc400' }, '..\\PLBIN\\PL00R00M.PBD': { matches: [ 'ARM00R.BIN', 'INIT_DAT.BIN' ], length: '0x440', memory: '0xed600' }, '..\\PLBIN\\PL00R00P.PBD': { matches: [ 'ARM00R.BIN', 'INIT_DAT.BIN' ], length: '0x1088', memory: '0xfa000' }, '..\\PLBIN\\PL00R01S.PBD': { matches: [ 'ARM01R.BIN' ], length: '0x2c0', memory: '0xdc880' }, '..\\PLBIN\\PL00R01M.PBD': { matches: [ 'ARM01R.BIN' ], length: '0x1280', memory: '0xef600' }, '..\\PLBIN\\PL00R01P.PBD': { matches: [ 'ARM01R.BIN' ], length: '0x10dc', memory: '0xfb500' }, '..\\PLBIN\\PL00R02S.PBD': { matches: [ 'ARM02R.BIN' ], length: '0x2c0', memory: '0xdc880' }, '..\\PLBIN\\PL00R02M.PBD': { matches: [ 'ARM02R.BIN' ], length: '0x1280', memory: '0xef600' }, '..\\PLBIN\\PL00R02P.PBD': { matches: [ 'ARM02R.BIN' ], length: '0x1028', memory: '0xfb500' }, '..\\PLBIN\\PL00R03S.PBD': { matches: [ 'ARM03R.BIN' ], length: '0x198', memory: '0xdc880' }, '..\\PLBIN\\PL00R03M.PBD': { matches: [ 'ARM03R.BIN' ], length: '0x940', memory: '0xef600' }, '..\\PLBIN\\PL00R03P.PBD': { matches: [ 'ARM03R.BIN' ], length: '0x11a0', memory: '0xfb500' }, '..\\PLBIN\\PL00L04S.PBD': { matches: [ 'ARM04L.BIN', 'INIT_DAT.BIN' ], length: '0x300', memory: '0xdd180' }, '..\\PLBIN\\PL00L04M.PBD': { matches: [ 'ARM04L.BIN', 'INIT_DAT.BIN' ], length: '0x1480', memory: '0xf3600' }, '..\\PLBIN\\PL00L04P.PBD': { matches: [ 'ARM04L.BIN', 'INIT_DAT.BIN' ], length: '0x10b8', memory: '0xfdf00' }, '..\\PLBIN\\PL00R04S.PBD': { matches: [ 'ARM04R.BIN' ], length: '0x340', memory: '0xdc880' }, '..\\PLBIN\\PL00R04M.PBD': { matches: [ 'ARM04R.BIN' ], length: '0x1680', memory: '0xef600' }, '..\\PLBIN\\PL00R04P.PBD': { matches: [ 'ARM04R.BIN' ], length: '0x105c', memory: '0xfb500' }, '..\\PLBIN\\PL00R05S.PBD': { matches: [ 'ARM05R.BIN', 'ARM13R.BIN' ], length: '0x360', memory: '0xdc880' }, '..\\PLBIN\\PL00R05M.PBD': { matches: [ 'ARM05R.BIN', 'ARM13R.BIN' ], length: '0x1780', memory: '0xef600' }, '..\\PLBIN\\PL00R05P.PBD': { matches: [ 'ARM05R.BIN', 'ARM12R.BIN', 'ARM13R.BIN' ], length: '0x1088', memory: '0xfb500' }, '..\\PLBIN\\PL00R06S.PBD': { matches: [ 'ARM06R.BIN' ], length: '0x198', memory: '0xdc880' }, '..\\PLBIN\\PL00R06M.PBD': { matches: [ 'ARM06R.BIN' ], length: '0x940', memory: '0xef600' }, '..\\PLBIN\\PL00R06P.PBD': { matches: [ 'ARM06R.BIN' ], length: '0x1144', memory: '0xfb500' }, '..\\PLBIN\\PL00R07S.PBD': { matches: [ 'ARM07R.BIN' ], length: '0x2c0', memory: '0xdc880' }, '..\\PLBIN\\PL00R07M.PBD': { matches: [ 'ARM07R.BIN' ], length: '0x1280', memory: '0xef600' }, '..\\PLBIN\\PL00R07P.PBD': { matches: [ 'ARM07R.BIN' ], length: '0x1114', memory: '0xfb500' }, '..\\PLBIN\\PL00R08S.PBD': { matches: [ 'ARM08R.BIN' ], length: '0x138', memory: '0xdc880' }, '..\\PLBIN\\PL00R08M.PBD': { matches: [ 'ARM08R.BIN' ], length: '0x640', memory: '0xef600' }, '..\\PLBIN\\PL00R08P.PBD': { matches: [ 'ARM08R.BIN' ], length: '0x11a8', memory: '0xfb500' }, '..\\PLBIN\\PL00R09S.PBD': { matches: [ 'ARM09R.BIN' ], length: '0x140', memory: '0xdc880' }, '..\\PLBIN\\PL00R09M.PBD': { matches: [ 'ARM09R.BIN' ], length: '0x680', memory: '0xef600' }, '..\\PLBIN\\PL00R09P.PBD': { matches: [ 'ARM09R.BIN' ], length: '0x103c', memory: '0xfb500' }, '..\\PLBIN\\PL00R10S.PBD': { matches: [ 'ARM10R.BIN' ], length: '0x100', memory: '0xdc880' }, '..\\PLBIN\\PL00R10M.PBD': { matches: [ 'ARM10R.BIN' ], length: '0x480', memory: '0xef600' }, '..\\PLBIN\\PL00R10P.PBD': { matches: [ 'ARM10R.BIN' ], length: '0x10b0', memory: '0xfb500' }, '..\\PLBIN\\PL00R11S.PBD': { matches: [ 'ARM11R.BIN' ], length: '0x100', memory: '0xdc880' }, '..\\PLBIN\\PL00R11M.PBD': { matches: [ 'ARM11R.BIN' ], length: '0x480', memory: '0xef600' }, '..\\PLBIN\\PL00R11P.PBD': { matches: [ 'ARM11R.BIN' ], length: '0x121c', memory: '0xfb500' }, '..\\PLBIN\\PL00R12S.PBD': { matches: [ 'ARM12R.BIN' ], length: '0xf8', memory: '0xdc880' }, '..\\PLBIN\\PL00R12M.PBD': { matches: [ 'ARM12R.BIN' ], length: '0x440', memory: '0xef600' }, '..\\PLBIN\\PL00H00P.PBD': { matches: [ 'HEAD00.BIN' ], length: '0x267c', memory: '0xf7800' }, '..\\PLBIN\\PL00H01P.PBD': { matches: [ 'HEAD01.BIN' ], length: '0x24f4', memory: '0xf7800' }, '..\\PLBIN\\PL00M00S.PBD': { matches: [ 'INIT_DAT.BIN' ], length: '0x1b08', memory: '0xd9d00' }, '..\\PLBIN\\PL00M00M.PBD': { matches: [ 'INIT_DAT.BIN' ], length: '0xbfbc', memory: '0xdd600' }, '..\\PLBIN\\PL00B00P.PBD': { matches: [ 'INIT_DAT.BIN' ], length: '0x1d74', memory: '0xf5600' }, '..\\PLBIN\\PL00F00P.PBD': { matches: [ 'LEG00.BIN' ], length: '0x8f8', memory: '0xff400' }, '..\\PLBIN\\PL00F01P.PBD': { matches: [ 'LEG01.BIN' ], length: '0x8f8', memory: '0xff400' }, '..\\PLBIN\\PL00D03S.PBD': { matches: [ 'ST03_00.BIN' ], length: '0x1a0', memory: '0xdba00' }, '..\\PLBIN\\PL00D03M.PBD': { matches: [ 'ST03_00.BIN' ], length: '0xb40', memory: '0xe9600' }, '..\\PLBIN\\PL00D05S.PBD': { matches: [ 'ST05_00B.BIN' ], length: '0x558', memory: '0xdba00' }, '..\\PLBIN\\PL00D05M.PBD': { matches: [ 'ST05_00B.BIN' ], length: '0x2900', memory: '0xe9600' }, '..\\PLBIN\\PL00D06S.PBD': { matches: [ 'ST05_01C.BIN' ], length: '0x268', memory: '0xdba00' }, '..\\PLBIN\\PL00D06M.PBD': { matches: [ 'ST05_01C.BIN' ], length: '0x1180', memory: '0xe9600' }, '..\\PLBIN\\PL00S06S.PBD': { matches: [ 'ST06_02.BIN', 'ST06_02D.BIN' ], length: '0x258', memory: '0xdba00' }, '..\\PLBIN\\PL00S06M.PBD': { matches: [ 'ST06_02.BIN', 'ST06_02D.BIN' ], length: '0x1100', memory: '0xe9600' }, '..\\PLBIN\\PL00D15S.PBD': { matches: [ 'ST0A_00.BIN' ], length: '0x3b0', memory: '0xdba00' }, '..\\PLBIN\\PL00D15M.PBD': { matches: [ 'ST0A_00.BIN' ], length: '0x1bc0', memory: '0xe9600' }, '..\\PLBIN\\PL00D18S.PBD': { matches: [ 'ST0B_00B.BIN', 'ST0CB.BIN' ], length: '0xb0', memory: '0xdba00' }, '..\\PLBIN\\PL00D18M.PBD': { matches: [ 'ST0B_00B.BIN', 'ST0CB.BIN' ], length: '0x3c0', memory: '0xe9600' }, '..\\PLBIN\\PL00D33S.PBD': { matches: [ 'ST13_00.BIN' ], length: '0x348', memory: '0xdba00' }, '..\\PLBIN\\PL00D33M.PBD': { matches: [ 'ST13_00.BIN' ], length: '0x1880', memory: '0xe9600' }, '..\\PLBIN\\PL00D34S.PBD': { matches: [ 'ST17.BIN' ], length: '0x4a8', memory: '0xdba00' }, '..\\PLBIN\\PL00D34M.PBD': { matches: [ 'ST17.BIN' ], length: '0x2380', memory: '0xe9600' }, '..\\PLBIN\\PL00D42S.PBD': { matches: [ 'ST19C.BIN' ], length: '0x398', memory: '0xdba00' }, '..\\PLBIN\\PL00D42M.PBD': { matches: [ 'ST19C.BIN' ], length: '0x1b00', memory: '0xe9600' }, '..\\PLBIN\\PL00D41S.PBD': { matches: [ 'ST19_00.BIN' ], length: '0x600', memory: '0xdba00' }, '..\\PLBIN\\PL00D41M.PBD': { matches: [ 'ST19_00.BIN' ], length: '0x2e40', memory: '0xe9600' }, '..\\PLBIN\\PL00D45S.PBD': { matches: [ 'ST1A_02.BIN' ], length: '0x758', memory: '0xdba00' }, '..\\PLBIN\\PL00D45M.PBD': { matches: [ 'ST1A_02.BIN' ], length: '0x3900', memory: '0xe9600' }, '..\\PLBIN\\PL00DE1S.PBD': { matches: [ 'ST1A_02C.BIN' ], length: '0x4e8', memory: '0xdba00' }, '..\\PLBIN\\PL00DE1M.PBD': { matches: [ 'ST1A_02C.BIN' ], length: '0x2580', memory: '0xe9600' }, '..\\PLBIN\\PL00DE2S.PBD': { matches: [ 'ST1A_02D.BIN' ], length: '0x748', memory: '0xdba00' }, '..\\PLBIN\\PL00DE2M.PBD': { matches: [ 'ST1A_02D.BIN' ], length: '0x3880', memory: '0xe9600' } }
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on May 26, 2019 12:28:32 GMT -5
Some PBD values, grouped by the location in memory where they can be copied in:
{ '0xd9d00': [ { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00M00S.PBD', len: '0x1b08' } ], '0xdba00': [ { bin: 'ST03_00.BIN', pbd: '..\\PLBIN\\PL00D03S.PBD', len: '0x1a0' }, { bin: 'ST05_00B.BIN', pbd: '..\\PLBIN\\PL00D05S.PBD', len: '0x558' }, { bin: 'ST05_01C.BIN', pbd: '..\\PLBIN\\PL00D06S.PBD', len: '0x268' }, { bin: 'ST06_02.BIN', pbd: '..\\PLBIN\\PL00S06S.PBD', len: '0x258' }, { bin: 'ST06_02D.BIN', pbd: '..\\PLBIN\\PL00S06S.PBD', len: '0x258' }, { bin: 'ST0A_00.BIN', pbd: '..\\PLBIN\\PL00D15S.PBD', len: '0x3b0' }, { bin: 'ST0B_00B.BIN', pbd: '..\\PLBIN\\PL00D18S.PBD', len: '0xb0' }, { bin: 'ST0CB.BIN', pbd: '..\\PLBIN\\PL00D18S.PBD', len: '0xb0' }, { bin: 'ST13_00.BIN', pbd: '..\\PLBIN\\PL00D33S.PBD', len: '0x348' }, { bin: 'ST17.BIN', pbd: '..\\PLBIN\\PL00D34S.PBD', len: '0x4a8' }, { bin: 'ST19C.BIN', pbd: '..\\PLBIN\\PL00D42S.PBD', len: '0x398' }, { bin: 'ST19_00.BIN', pbd: '..\\PLBIN\\PL00D41S.PBD', len: '0x600' }, { bin: 'ST1A_02.BIN', pbd: '..\\PLBIN\\PL00D45S.PBD', len: '0x758' }, { bin: 'ST1A_02C.BIN', pbd: '..\\PLBIN\\PL00DE1S.PBD', len: '0x4e8' }, { bin: 'ST1A_02D.BIN', pbd: '..\\PLBIN\\PL00DE2S.PBD', len: '0x748' } ], '0xdc400': [ { bin: 'ARM00R.BIN', pbd: '..\\PLBIN\\PL00R00S.PBD', len: '0xf8' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00R00S.PBD', len: '0xf8' } ], '0xdc880': [ { bin: 'ARM01R.BIN', pbd: '..\\PLBIN\\PL00R01S.PBD', len: '0x2c0' }, { bin: 'ARM02R.BIN', pbd: '..\\PLBIN\\PL00R02S.PBD', len: '0x2c0' }, { bin: 'ARM03R.BIN', pbd: '..\\PLBIN\\PL00R03S.PBD', len: '0x198' }, { bin: 'ARM04R.BIN', pbd: '..\\PLBIN\\PL00R04S.PBD', len: '0x340' }, { bin: 'ARM05R.BIN', pbd: '..\\PLBIN\\PL00R05S.PBD', len: '0x360' }, { bin: 'ARM06R.BIN', pbd: '..\\PLBIN\\PL00R06S.PBD', len: '0x198' }, { bin: 'ARM07R.BIN', pbd: '..\\PLBIN\\PL00R07S.PBD', len: '0x2c0' }, { bin: 'ARM08R.BIN', pbd: '..\\PLBIN\\PL00R08S.PBD', len: '0x138' }, { bin: 'ARM09R.BIN', pbd: '..\\PLBIN\\PL00R09S.PBD', len: '0x140' }, { bin: 'ARM10R.BIN', pbd: '..\\PLBIN\\PL00R10S.PBD', len: '0x100' }, { bin: 'ARM11R.BIN', pbd: '..\\PLBIN\\PL00R11S.PBD', len: '0x100' }, { bin: 'ARM12R.BIN', pbd: '..\\PLBIN\\PL00R12S.PBD', len: '0xf8' }, { bin: 'ARM13R.BIN', pbd: '..\\PLBIN\\PL00R05S.PBD', len: '0x360' } ], '0xdcd00': [ { bin: 'ARM00L.BIN', pbd: '..\\PLBIN\\PL00L00S.PBD', len: '0xf8' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00L00S.PBD', len: '0xf8' } ], '0xdd180': [ { bin: 'ARM04L.BIN', pbd: '..\\PLBIN\\PL00L04S.PBD', len: '0x300' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00L04S.PBD', len: '0x300' } ], '0xdd600': [ { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00M00M.PBD', len: '0xbfbc' } ], '0xe9600': [ { bin: 'ST03_00.BIN', pbd: '..\\PLBIN\\PL00D03M.PBD', len: '0xb40' }, { bin: 'ST05_00B.BIN', pbd: '..\\PLBIN\\PL00D05M.PBD', len: '0x2900' }, { bin: 'ST05_01C.BIN', pbd: '..\\PLBIN\\PL00D06M.PBD', len: '0x1180' }, { bin: 'ST06_02.BIN', pbd: '..\\PLBIN\\PL00S06M.PBD', len: '0x1100' }, { bin: 'ST06_02D.BIN', pbd: '..\\PLBIN\\PL00S06M.PBD', len: '0x1100' }, { bin: 'ST0A_00.BIN', pbd: '..\\PLBIN\\PL00D15M.PBD', len: '0x1bc0' }, { bin: 'ST0B_00B.BIN', pbd: '..\\PLBIN\\PL00D18M.PBD', len: '0x3c0' }, { bin: 'ST0CB.BIN', pbd: '..\\PLBIN\\PL00D18M.PBD', len: '0x3c0' }, { bin: 'ST13_00.BIN', pbd: '..\\PLBIN\\PL00D33M.PBD', len: '0x1880' }, { bin: 'ST17.BIN', pbd: '..\\PLBIN\\PL00D34M.PBD', len: '0x2380' }, { bin: 'ST19C.BIN', pbd: '..\\PLBIN\\PL00D42M.PBD', len: '0x1b00' }, { bin: 'ST19_00.BIN', pbd: '..\\PLBIN\\PL00D41M.PBD', len: '0x2e40' }, { bin: 'ST1A_02.BIN', pbd: '..\\PLBIN\\PL00D45M.PBD', len: '0x3900' }, { bin: 'ST1A_02C.BIN', pbd: '..\\PLBIN\\PL00DE1M.PBD', len: '0x2580' }, { bin: 'ST1A_02D.BIN', pbd: '..\\PLBIN\\PL00DE2M.PBD', len: '0x3880' } ], '0xed600': [ { bin: 'ARM00R.BIN', pbd: '..\\PLBIN\\PL00R00M.PBD', len: '0x440' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00R00M.PBD', len: '0x440' } ], '0xef600': [ { bin: 'ARM01R.BIN', pbd: '..\\PLBIN\\PL00R01M.PBD', len: '0x1280' }, { bin: 'ARM02R.BIN', pbd: '..\\PLBIN\\PL00R02M.PBD', len: '0x1280' }, { bin: 'ARM03R.BIN', pbd: '..\\PLBIN\\PL00R03M.PBD', len: '0x940' }, { bin: 'ARM04R.BIN', pbd: '..\\PLBIN\\PL00R04M.PBD', len: '0x1680' }, { bin: 'ARM05R.BIN', pbd: '..\\PLBIN\\PL00R05M.PBD', len: '0x1780' }, { bin: 'ARM06R.BIN', pbd: '..\\PLBIN\\PL00R06M.PBD', len: '0x940' }, { bin: 'ARM07R.BIN', pbd: '..\\PLBIN\\PL00R07M.PBD', len: '0x1280' }, { bin: 'ARM08R.BIN', pbd: '..\\PLBIN\\PL00R08M.PBD', len: '0x640' }, { bin: 'ARM09R.BIN', pbd: '..\\PLBIN\\PL00R09M.PBD', len: '0x680' }, { bin: 'ARM10R.BIN', pbd: '..\\PLBIN\\PL00R10M.PBD', len: '0x480' }, { bin: 'ARM11R.BIN', pbd: '..\\PLBIN\\PL00R11M.PBD', len: '0x480' }, { bin: 'ARM12R.BIN', pbd: '..\\PLBIN\\PL00R12M.PBD', len: '0x440' }, { bin: 'ARM13R.BIN', pbd: '..\\PLBIN\\PL00R05M.PBD', len: '0x1780' } ], '0xf1600': [ { bin: 'ARM00L.BIN', pbd: '..\\PLBIN\\PL00L00M.PBD', len: '0x440' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00L00M.PBD', len: '0x440' } ], '0xf3600': [ { bin: 'ARM04L.BIN', pbd: '..\\PLBIN\\PL00L04M.PBD', len: '0x1480' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00L04M.PBD', len: '0x1480' } ], '0xf5600': [ { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00B00P.PBD', len: '0x1d74' } ], '0xf7800': [ { bin: 'HEAD00.BIN', pbd: '..\\PLBIN\\PL00H00P.PBD', len: '0x267c' }, { bin: 'HEAD01.BIN', pbd: '..\\PLBIN\\PL00H01P.PBD', len: '0x24f4' } ], '0xfa000': [ { bin: 'ARM00R.BIN', pbd: '..\\PLBIN\\PL00R00P.PBD', len: '0x1088' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00R00P.PBD', len: '0x1088' } ], '0xfb500': [ { bin: 'ARM01R.BIN', pbd: '..\\PLBIN\\PL00R01P.PBD', len: '0x10dc' }, { bin: 'ARM02R.BIN', pbd: '..\\PLBIN\\PL00R02P.PBD', len: '0x1028' }, { bin: 'ARM03R.BIN', pbd: '..\\PLBIN\\PL00R03P.PBD', len: '0x11a0' }, { bin: 'ARM04R.BIN', pbd: '..\\PLBIN\\PL00R04P.PBD', len: '0x105c' }, { bin: 'ARM05R.BIN', pbd: '..\\PLBIN\\PL00R05P.PBD', len: '0x1088' }, { bin: 'ARM06R.BIN', pbd: '..\\PLBIN\\PL00R06P.PBD', len: '0x1144' }, { bin: 'ARM07R.BIN', pbd: '..\\PLBIN\\PL00R07P.PBD', len: '0x1114' }, { bin: 'ARM08R.BIN', pbd: '..\\PLBIN\\PL00R08P.PBD', len: '0x11a8' }, { bin: 'ARM09R.BIN', pbd: '..\\PLBIN\\PL00R09P.PBD', len: '0x103c' }, { bin: 'ARM10R.BIN', pbd: '..\\PLBIN\\PL00R10P.PBD', len: '0x10b0' }, { bin: 'ARM11R.BIN', pbd: '..\\PLBIN\\PL00R11P.PBD', len: '0x121c' }, { bin: 'ARM12R.BIN', pbd: '..\\PLBIN\\PL00R05P.PBD', len: '0x1088' }, { bin: 'ARM13R.BIN', pbd: '..\\PLBIN\\PL00R05P.PBD', len: '0x1088' } ], '0xfca00': [ { bin: 'ARM00L.BIN', pbd: '..\\PLBIN\\PL00L00P.PBD', len: '0x1088' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00L00P.PBD', len: '0x1088' } ], '0xfdf00': [ { bin: 'ARM04L.BIN', pbd: '..\\PLBIN\\PL00L04P.PBD', len: '0x10b8' }, { bin: 'INIT_DAT.BIN', pbd: '..\\PLBIN\\PL00L04P.PBD', len: '0x10b8' } ], '0xff400': [ { bin: 'LEG00.BIN', pbd: '..\\PLBIN\\PL00F00P.PBD', len: '0x8f8' }, { bin: 'LEG01.BIN', pbd: '..\\PLBIN\\PL00F01P.PBD', len: '0x8f8' } ] }
Which means the possible values where pbd files can be copied in are as follows:
[ "0xd9d00", "0xdba00", "0xdc400", "0xdc880", "0xdcd00", "0xdd180", "0xdd600", "0xe9600", "0xed600", "0xef600", "0xf1600", "0xf3600", "0xf5600", "0xf7800", "0xfa000", "0xfb500", "0xfca00", "0xfdf00", "0xff400" ]
So the next step is to check the game memory against the PBD files to see if they can actually be found in these addresses. The other thing to check will be the number of bones for the cutscene version of megaman to see if the number of PBD files in memory match up with each polygon in megaman.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Jun 5, 2019 20:23:42 GMT -5
Cross post from Twitter: In general I can think of two potential issues: 1. Gltf Importer for Unreal is still new and doesn't work correctly. 2. Unreal doesn't like the root bone being the chest and not a point at the origin. I don't know if doing the port-around of using Noesis or something would get the assets into a format that Unreal is able to work with. I don't know if Adam would want to port his work over to Godot or Unity engines. Godot seems to have good support for Gltf, and with Unity I can support my own format directly. So I'll see how to follow this up depending on feedback from Adam, right now I'm working on finding the quickest and dirtiest way to edit text in the game.
|
|