OBD:Instance file format: Difference between revisions

discovered the hard way that the "+1" on the instance ID actually has value
(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 to mark which IDs have already been converted to pointers (an instance pointer will always be 8-byte aligned, so it will never have the zero bit already set). These pointer flags were retained when the file was written to disk but are meaningless now. 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 '''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' is used by the engine to know which file IDs have been converted to pointers at runtime, but on disk this is a relic which has no meaning to us. The reason for left-shifting the level number might have originally been to store it alongside the instance ID and the pointer flag in a single int32, but they are separate numbers now, perhaps so that both IDs can have their own 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' 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.