20,504
edits
(looking at this checksum statement again, I do think this was written for OniSplit v1.0, but that never left alpha so it's more useful to document v0.99's format) |
(discovered the hard way that the "+1" on the instance ID actually has value) |
||
| Line 262: | Line 262: | ||
This example is taken from level 3 so that the file ID is more instructive. In the OBD documentation, these fields are called res_id and lev_id as seen above. | This example is taken from level 3 so that the file ID is more instructive. In the OBD documentation, these fields are called res_id and lev_id as seen above. | ||
The '''instance's ID''' is stored as "(instance descriptor index << 8) | 1". Thus the ID for item #1,035 (0x40B) in the instance descriptor index will be encoded as 0x40B01. The '1' is used by the engine | The '''instance's ID''' is stored as "(instance descriptor index << 8) | 1". Thus the ID for item #1,035 (0x40B) in the instance descriptor index will be encoded as 0x40B01. The official purpose of the '1' is that it was a marker used by the engine at runtime signifying that this instance ID had already been converted to a pointer to a live instance in memory (an instance pointer will always be 8-byte aligned, so it will never have the zero bit set). These pointer flags were retained when the file was written to disk, where they seemingly serve no purpose, but in fact they allow us to differentiate link fields which are truly unused (all zeroes) from a link field which points to instance #0 (since this would be encoded as 01 00 00 00 on disk). At level-load time the flags are cleared and then set again when Oni allocates memory for each instance. The purpose of left-shifting the index number is simply to leave the lowest byte open for the pointer flag. | ||
The '''file ID''' is computed from the number found in the name of the instance file: "(level number << 25) | 1". Thus instances found in level3_Final.dat will have the file ID encoded as 0x6000001. Again, the '1' | The '''file ID''' is computed from the number found in the name of the instance file: "(level number << 25) | 1". Thus instances found in level3_Final.dat will have the file ID encoded as 0x6000001. Again, the '1' was used by the engine at runtime to know which file IDs had been converted to pointers at runtime, but it does allow us to tell the difference between a reference to level0_Final (01 00 00 00) and a file ID field that has somehow not been filled in (though this should not happen). The reason for left-shifting the level number so far might have originally been to store it alongside the instance ID and the pointer flag in a single int32, but they are separate int32s now, perhaps so that both IDs can have their own pointer flag. | ||
After the header, the size of each instance's data is of a somewhat arbitrary length depending on the template this instance falls under. As mentioned under "Instance descriptors", the data size given by the descriptor includes the 8-byte resource header and the padding at the end of the data to align the next instance on 32 bytes. | After the header, the size of each instance's data is of a somewhat arbitrary length depending on the template this instance falls under. As mentioned under "Instance descriptors", the data size given by the descriptor includes the 8-byte resource header and the padding at the end of the data to align the next instance on 32 bytes. | ||