Managed to track nail down the vertex format, and managed to export the meseta model. Though to be complete, should probably add vertex color to the faces for the complete look.
Interesting notes.
I would normally just use the memory viewer and then the dump option from there.
Also if you use the ge debugger you’ll be able to see the vertex format (the files store the data in the same order it is used if I remember correctly so it shouldn’t be too bad). Main things to find is how to tell where each mesh starts and ends.
At this point all of my computers are running Debian. I set up a windows machine as a virtual client on the network running on a Latte Panda, but I continue to forget that it exists. What I like about using save states is that it allows for writing scripts for searching inside or writing to memory. For example, for testing to find out if the vertex color alpha uses argb1555 format or not, I wrote this short script:
Code:
const meseta = "meseta.unj";
const state = "/home/kion/.config/ppsspp/PSP/PPSSPP_STATE/NPJH50332_1.02_0.ppst";
const needle = fs.readFileSync(meseta).subarray(0x180, 0x360);
const haystack = fs.readFileSync(state);
let vertices = [];
let colors = [];
let lookup = {
'f7ee' : 0b1111110000000000, // red
'f0ad' : 0b1000001111100000, // green
'f0bd' : 0b1000000000011111, // blue
'f0cf' : 0b0111111111111111 // white with 50% alpha?
}
for(let i = 0; i < needle.length; i += 0x10) {
console.log(i.toString(16));
const c = needle.readUInt16LE(i);
let color = c.toString(16);
needle.writeUInt16LE(lookup[color], i)
const x = needle.readFloatLE(i + 4).toFixed(2);
const y = needle.readFloatLE(i + 8).toFixed(2);
const z = needle.readFloatLE(i + 12).toFixed(2);
}
let index = 0x138a171;
needle.copy(haystack, index);
My current notes look something like this. The file starts with a normal magic number and length. Following that is a pointer towards the end of the file, followed by the int value of 3 (or at least in the files I've looked at so far). The top of the file looks like it's the bone. The four 1.0f floats in a diagonal is pretty telling as a 4x4 transformation matrix. It seems to have the three 1.0f floats above it. And then files with multiple bones have 0x20 of information above and below the matrix, so that's how I segmented that off.
For the materials, this is easier to look at with models with multiple materials. The patterns starting with 02000100 and ending with FFFFFFFF seems to repeat in model. So i think that's about the right length, though I can't be sure if it's materials and what each byte does without more comparison and testing.
After that there seems to be 0x20 of space between the materials and vertex list. I'm guessing these are draw calls. Just a guess, but the general idea is that you try to identify structs, make hypothesis about what each struct does, test, and refine. So I'll try removing that value or changing it to see what happens.
After this is the vertex list. For meseta the format ended up being really easy. It's argb1555 for the vertex color, the space following that could potentially be the weight index (zero, since we only have one bone), followed by float values for x, y, z. I expect most models to follow a similar format, likely with the addition of normals and uv-diffuse when applicable. Also now that I know how many vertices there are, I can scan the bytes in the file to look for where the vertex list length is declared.
Following the vertex list are what I'm guessing are uniforms. I've only changed one of the values so far. Changing the bit flags had different effects such as changing the strip order, putting the model into normal debug mode and turning off vertex colors. So it's my guess that these are a series of values that are passed into the shader to describe how to render the model. A side note is that there don't seem to be any indices, so I think the models are using direct buffer geometry.
And then after that is the end of the file, which is pointed to by the header. Since there's no other place to put it, i would expect this area to be used for describing the model attributes like how many bones there are, how many materials, or how many vertices there are. One thing I find pretty quirky about this model format is the complete lack of pointers. It looks like they really went out of their way to design a file format that stack attributes and offsets are probably managed by the program by the offset of the start of the model, plus the size and count of the structs to skip over to read the attribute they want to work with.