Code: Select all
## 80 ?? 6*
## C0 ?? 7*
The ordering and contents of the block are specific to each developer. So you would have to determine that visually, as has already been done. But even then there are times when the data will not be entirely complete until it is fully unpacked due to things like masking, where data can be partially written between multiple unpack blocks.
For formats that are nicely structured for us, a lot of this information can be glossed over, because in those cases even in the packed form, it still resembles the standard in order list of values we are used to. Simply decipher the counts from the commands and process normally. But if the developer decided to get more creative with their use of the commands, it can get far more interesting.
The ## ## 00 01 specifiers, basically tell how often to read and write elements within each unpack block. So you can essentially read data and write it to memory one after the other, or every other line, etc.
The memory in the vu on the ps2 is aligned to 16-byte boundaries, and the unpack commands write this data out 16 bytes (four 32-bit values) at a time, using masking to specify which, if any, of the "x", "y", "z", or "w" data should be written each time.
This allows for either writing data consecutively one after the other, or interleaving the data between multiple unpack operations.
For example, lets say you have 10 vertices, normals, and uvs.
Using:
Code: Select all
01 01 00 01
You could write the vertices to address 0x0000, and they would appear one after the other, causing the normals to have to be written to address 0x00A0, and the uvs need to be written at 0x0140, to avoid overwriting previously written data.
But these commands can also be used to write the data interleaved in a way the the order is [vert1, norm1, uv1, vert2, norm2, uv2, ...] using:
Code: Select all
03 01 00 01
This would cause the start addresses of the write operations to be different as well. The vertices could still start at 0x0000, but the normals would now start at 0x0010, and the uvs at 0x0020. Because of the skipping the space for the normals and uvs, would be untouched during the vertex unpacking, in the same manner when writing the normals, the uv and next vertex value would be skipped over, and so.
This can also be used for he inverse of writing more data than you have read, i.e. reading data and writing it multiple times, and various other combinations.
To top it all of if that wasn't deep enough, masking can change which values are even written in the first place, even being able to replace masked out values with constants in other registers. So you could write to the "x" and "y" locations in one unpack command, masking the "z" and "w" so that they will be untouched, and use another unpack command with the masking reverse to write only to the "z" and "w" areas with completely different data. Or the more common case of writing out the xyz position of a 3d vector, and masking the "w" location so that a constant value of 1.0 is written.
There are a lot of things possible with the ways this works, and unfortunately even with a way to unpack them the way the ps2 does, they way they are order and the data contained within the commands are completely up to the developer to choose for each game. The values don't even have to be geometry related, you can pack the entire header of another self-contained format within these commands, where after unpacking you have a completely different format to parse.
Whew, sorry for the long description...while not xenosaga specific, its the main reason why there is still a little more work involved than simply unpacking the data in a lot of cases. Will see if i can post something more useful, heh.