So, while I’m still figuring out 3D object rendering details (it seems that various object may have their own rendering functions—up to six variants usually—so figuring it all out will take some time), here’s another random format documentation instead.
QfG5 savefile starts with the string "QG5P1.000 "
followed by 16-bit constant 0xDE89
, 16-bit total number of inventory items XORed with 0xBEAD
, 16-bit number of random noise bytes (50-150) XORed with 0xFACE
and 16-bit constant 0xA8A5
.
Then there’s 32-bit player type and some random noise of the length provided above (probably added just for an obfuscation reasons) followed by 1096-byte dump of player state class instance obfuscated by XORing each byte with the following one. That object contains player characteristics like e.g. strength or agility and spell casting skills.
This is followed by the inventory items properties (the number of items is stored in the header) in the following four 32-bit fields per item: sprite ID (in 101xxx range) which also serves as item type, amount, unique flag (e.g. for items), and “applied zap spell on weapon” flag.
The next block is data from the dialogue tree state: 32-bit number of rooms with dialogue options taken, for each of the present room there’s 32-bit room number, 32-bit number of message states and two 32-bit flags per each message state (something like “this line has been said before” and “this line should not be present any longer”, I suppose).
Following that is the object state: 32-bit number of object is followed by each of 133 rooms state. Those state include 32-bit number of objects in the room, followed by object data (32-bit object data size, type and ID plus object-specific data of the provided size—unless object data size is zero).
Then it’s time for 1536-byte engine state. It includes various puzzle flags, current time, the state of bank account and other such stuff.
After that there’s hero-specific data as a generic object (32-bit size plus data bytes). And also equipment: nine 32-bit item IDs for the belt items, 32-bit field with the number of the selected belt item, 32-bit “belt item selected” flag, five 32-bit item IDs for the equipped items (sword, shield, helmet, armour and amulet).
The next block is map state (32-bit data size plus data bytes).
And finally there’s 32-bit current room ID plus 32-bit room data size and room data size bytes (unless room ID is 0 or 900 aka global map).