Jump to content

Oni (folder)/persist.dat: Difference between revisions

replacing contents with result of a merge between this and the "Persist.dat" page (to be deleted), since each had useful information lacking in the other
No edit summary
(replacing contents with result of a merge between this and the "Persist.dat" page (to be deleted), since each had useful information lacking in the other)
Line 1: Line 1:
{{merge|[[Persist.dat]]}}
As players of Oni are well aware, the game does not allow arbitrary saving ("save anywhere"), but relies on the use of fixed savepoints activated through level scripting by reaching certain places in each level. This means that by setting a maximum number of levels and savepoints for Oni, the developer could store the total state of the player's progress in a single, fixed-size file -- a 206,496 byte file, to be exact. In addition to savepoint data, persist.dat has a header which stores Oni's player settings (besides [[Oni (folder)/key_config.txt|key bindings]]). It also records whether the cheats are enabled (i.e. whether you have beaten the game), and whether you killed Griffin in {{C|13}}.


The savegame file '''persist.dat''' corresponds to a dump of Oni's memory. It is written at specific moments during the game, e.g. after a new level is loaded, or after a new savepoint is reached. It also registers settings from the option menu and remembers whether the cheats are enabled (i.e. whether you have beaten the game) and whether you have killed [[Griffin]].
The persist.dat file has nothing to do with Oni's [[Dat|instance files]] despite the ".dat" extension (it looks like Bungie West simply used .dat for every kind of file Oni read and wrote -- saved_film####.dat, ####_corpse.dat, etc., then later on added .raw and then .sep as unique suffixes when they needed to break out the level data .dats).


The savegame file is a memory dump and has nothing to do with [[dat|instance files]] despite the ".dat" extension (same for saved_film####.dat, ####_corpse.dat, etc). The binary format of a savegame file is detailed below. It applies to PC and PC demo; the Mac build writes all numbers as [[wikipedia:Big Endian|Big Endian]], e.g., the 0x08 field in the header will appear as 00 0C 7F 5C for a Mac savegame. Therefore, savegames are not interchangeable between PC and Mac versions of Oni.
The original Mac game application and the Omni Group build were for PPC Macs, thus numbers were written big-endian (e.g., the 0x08 field in the header would be 00 0C 7F 5C). This meant that the saved-game files were not interchangeable between PC and Mac versions of Oni. However, with modern Macs running a [[AE:FERAL|native Intel build]], the files are now all in little-endian format.


The header of the savegame file is 0x60=612 bytes long. It is followed by an array of 400 savepoints, 0x204=516 bytes each, grouped implicitly into 40 levels, 10 savepoints per level. The first 10 savepoints belong to level 0 and are never written to. The savepoints of the original 14 levels follow. This leaves 25 unused levels at the end of the savegame file.
The header of the file is 0x60=96 bytes long. It is followed by an array of 400 savepoints, 0x204=516 bytes each, grouped implicitly into 40 levels, 10 savepoints per level. The first 10 savepoints belong to level 0 and are never written to. The savepoints of the original 14 levels follow. This leaves 25 unused levels at the end of the saved-game file.


The level names are taken from the [[ONLD]] files of level 0, except for Chapters 0 and 1: "TCTF Training" (level 1, savepoint 0) and "Syndicate Warehouse" (level 1 savepoint 1) are hardcoded in the engine.
Only savepoint names are stored in this file (and they are all named uniformly as "Save Point x" even though they could say anything). The actual level names are taken from the [[ONLD]] files of level 0, except for Chapters 0 and 1: "TCTF Training" (level 1, savepoint 0) and "Syndicate Warehouse" (level 1 savepoint 1) are hard-coded into the engine.
{{table}}{{OBDtable}}
 
==Unlocking more levels==
To unlock all possible levels, fill the range 0x08 to 0x28 with "FF". So far this has caused no problems, and allows you to add more levels to the game. Levels will not be visible unless there is a corresponding LevelX_Final.dat in the GameDataFolder, and an ONLD that matches the level number in the level0_final.dat. Levels above 39 are not currently unlockable due to the 40-level savepoint limit in the persist.dat (probably reflecting an underlying engine restriction).
 
==Header==
[[Image:Persist_header.gif]]
 
{{Table}}
{{OBDth}}
{{OBDth}}
{{OBDtr|0x00|int32|FF0000|0F 00 00 00|15|unknown, maybe 15 levels; if not 15, file is invalid}}
{{OBDtr| 0x00 | int32 |FF0000| 0F 00 00 00 | 15         | version }}
{{OBDtr|0x04|int32|FF0000|0E 0B D0 D0|???|unknown}}
{{OBDtr| 0x04 | int32 |FF0000| 0E 0B D0 D0 | 0xD0D00B0E | signature }}
{{OBDtr|0x08|int32|FF0000|5C 7F 0C 00|2<sup>19</sup>+2<sup>18</sup>+2<sup>14</sup>+2<sup>13</sup>+2<sup>12</sup>+2<sup>11</sup><br>+2<sup>10</sup>+2<sup>9</sup>+2<sup>8</sup>+2<sup>6</sup>+2<sup>4</sup>+2<sup>3</sup>+2<sup>2</sup>|visibility lock for levels 2 through 31; 0 and 1 unaffected}}
{{OBDtr| 0x08 | int32 |FF0000| 5C 7F 0C 00 | 0x000C7F5C | level unlock flag for levels 0-31; each level has a corresponding bit:
{{OBDtr|0x0C|int32|FF0000|00 00 00 00|none|visibility lock for levels 32 through 63}}
:0x'''01''' 00 00 00 - level 0 (always unlocked, ignored)
{{OBDtr|0x10|int32|FF0000|00 00 00 00|none|visibility lock for levels 64 through 95}}
:0x'''02''' 00 00 00 - level 1 (always unlocked, ignored)
{{OBDtr|0x14|int32|FF0000|00 00 00 00|none|visibility lock for levels 96 through 127}}
:0x'''04''' 00 00 00 - level 2
{{OBDtr|0x18|int32|FF0000|00 00 00 00|none|visibility lock for levels 128 through 159}}
:...
{{OBDtr|0x1C|int32|FF0000|00 00 00 00|none|visibility lock for levels 160 through 191}}
:0x00 00 '''08''' 00 - level 19 }}
{{OBDtr|0x20|int32|FF0000|00 00 00 00|none|visibility lock for levels 192 through 223}}
{{OBDtr| 0x0C | int32 |FF0000| 00 00 00 00 |     | level unlock flag for levels 32-63 }}
{{OBDtr|0x24|int32|FF0000|00 00 00 00|none|visibility lock for levels 224 through 255}}
{{OBDtr| 0x10 | int32 |FF0000| 00 00 00 00 |     | level unlock flag for levels 64-95 }}
{{OBDtr|0x28|int32|FFFF00|01 00 00 00|true|whether Griffin was killed: used in Chapters {{C|13|13}} and {{C|14|14}}; set with [[BSL:Functions|func]] [[killed_griffen]](bool), read with [[BSL:Functions|func]] [[did_kill_griffen]]()}}
{{OBDtr| 0x14 | int32 |FF0000| 00 00 00 00 |     | level unlock flag for levels 96-127 }}
{{OBDtr|0x2C|int32|00FF00|FE 1B 00 00|2<sup>12</sup>+2<sup>11</sup>+2<sup>9</sup>+2<sup>8</sup>+2<sup>7</sup><br>+2<sup>6</sup>+2<sup>5</sup>+2<sup>4</sup>+2<sup>3</sup>+2<sup>2</sup>+2<sup>1</sup>|unknown}}
{{OBDtr| 0x18 | int32 |FF0000| 00 00 00 00 |     | level unlock flag for levels 128-159 }}
{{OBDtr|0x30|int32|00FFFF|1F 00 00 00|31|unknown}}
{{OBDtr| 0x1C | int32 |FF0000| 00 00 00 00 |     | level unlock flag for levels 160-191 }}
{{OBDtr|0x34|int32|FF00FF|13 00 00 00|19|unknown}}
{{OBDtr| 0x20 | int32 |FF0000| 00 00 00 00 |     | level unlock flag for levels 192-223 }}
{{OBDtr|0x38|int32|FFC8C8|01 00 00 00|01|unknown}}
{{OBDtr| 0x24 | int32 |FF0000| 00 00 00 00 |     | level unlock flag for levels 224-255 }}
{{OBDtr|0x3C|int32|FFFFC8|04 00 00 00|4|quality: from superlow (0) to superhigh (4)}}
{{OBDtr| 0x28 | int32 |FFFF00| 01 00 00 00 | | killed Griffin (0 <nowiki>=</nowiki> no, 1 <nowiki>=</nowiki> yes) }}
{{OBDtr|0x40|float|C8FFC8|00 00 80 3F|1.000000|sound volume: from 0.0 to 1.0}}
{{OBDtr| 0x2C |       |00FF00| FE 1B 00 00 | 7166 | unlocked weapons; one bit for each weapon; the number of corresponding bit is given by the skill index value in the primary firing mode block of each [[ONWC]] }}
{{OBDtr|0x44|bool32|C8FFFF|06 00 00 00|2<sup>2</sup>+2<sup>1</sup>|bitset: 1 - show subtitles; 2 - invert aiming; 4 - enable cheats}}
{{OBDtr| 0x30 |       |00FFFF| 1F 00 00 00 | 31 | unlocked items; one bit for each item type (hypo, ammo etc.)  }}
{{OBDtr|0x48|int32|FFC8FF|02 00 00 00|2|quality: from Easy (0) to Hard (2)}}
{{OBDtr| 0x34 |       |FF00FF| 13 00 00 00 | 19 | last read diary page (level) }}
{{OBDtr|0x4C|int16|FFC800|20 03|800|horizontal screen resolution}}
{{OBDtr| 0x38 |       |FFC8C8| 01 00 00 00 | | last read diary page (page) }}
{{OBDtr|0x4E|int16|FFC800|02 58|600|vertical screen resolution}}
{{OBDtr| 0x3C | int32 |FFFFC8| 04 00 00 00 | 4   | level of graphical detail; the following options are possible:
{{OBDtr|0x50|int32|C800C8|20 00 00 00|32|color depth}}
:0 - extra low
{{OBDtr|0x54|float|C87C64|00 00 00 3F|0.500000|gamma correction; from 0.0 to 1.0, 0.5 means no correction}}
:1 - low
{{OBDtr|0x58|int32|B0C3D4|03 00 00 00|3|last loaded level; written at level load}}
:2 - medium
{{OBDtr|0x5C|int32|E7CEA5|02 00 00 00|2|last saved savepoint}}
:3 - high
:4 - extra high }}
{{OBDtr| 0x40 | float |C8FFC8| 00 00 80 3F | 1.| sound volume (0.0 <nowiki>=</nowiki> min, 1.0 <nowiki>=</nowiki> max) }}
{{OBDtr| 0x44 | int32 |C8FFFF| 06 00 00 00 | 6    | option flags; the following values are possible:
:0x'''01''' 00 00 00 - show subtitles
:0x'''02''' 00 00 00 - invert mouse
:0x'''04''' 00 00 00 - game won (aka cheats enabled) }}
{{OBDtr| 0x48 | int32 |FFC8FF| 02 00 00 00 | 2   | difficulty; the following values are possible:
:0 - easy
:1 - medium
:2 - hard }}
{{OBDtr| 0x4C | int16 |FFC800| 20 03       | 800 | resolution: width }}
{{OBDtr| 0x4E | int16 |FFC800| 02 58       | 800 | resolution: height }}
{{OBDtr| 0x50 | int16 |C800C8| 20 00       | 32 | color depth }}
{{OBDtr| 0x52 |      |C800C8| 00 00      |    | padding }}
{{OBDtr| 0x54 | float |C87C64| 00 00 00 3F | 0.5 | gamma correction; from 0.0 to 1.0, 0.5 means no correction }}
{{OBDtr| 0x58 | int32 |B0C3D4| 03 00 00 00 | 3   | last loaded (saved?) level }}
{{OBDtr| 0x5C | int32 |E7CEA5| 02 00 00 00 | | last saved savepoint }}
|}
|}




Example of a savepoint (chapter 1, savepoint 2)
;Killed Griffin
{{table}}{{OBDtable}}
:Used in Chapters 13 and 14; set with [[killed_griffen]], read with [[did_kill_griffen]].
 
 
After this header is an array of 400 savepoints (40 levels, 10 savepoints per level). The size of a savepoint is 516 bytes so the array size is 206,400 bytes.
 
 
==Savepoint==
[[Image:Persist dat.gif]]
 
 
{{Table}}
{{OBDth}}
{{OBDth}}
{{OBDtr2|0x00|char[64]|FF0000|"Save Point 2"|name of the savepoint in the Load Game dialog}}
{{OBDtr2|0x00 | char[64] |FF0000| "Save Point 2" | name of the save point in Load Game dialog }}
{{OBDtr|0x40|int32|FFFF00|01 00 00 00|true|whether the savepoint is visible in the Load Game dialog}}
{{OBDtr| 0x40 | int32   |FFFF00| 01 00 00 00 | 1 | valid (was saved previously), i.e. "Should we display this in Load Game?" (0 <nowiki>=</nowiki> no, 1 <nowiki>=</nowiki> yes) }}
{{OBDtr|0x44|int32|00FF00|BE 00 00 00|190|current health in hitpoints}}
{{OBDtr| 0x44 | int32   |00FF00| BE 00 00 00 | 190       | current player health (HP) }}
{{OBDtr|0x48|int32|00FFFF|C8 00 00 00|200|max. health in hitpoints}}
{{OBDtr| 0x48 | int32   |00FFFF| C8 00 00 00 | 200       | max player health (HP) }}
{{OBDtr|0x4C|float|FF00FF|AE 20 FB 43|502.255310|x-position}}
{{OBDtr| 0x4C | float   |FF00FF| AE 20 FB 43 | 502.255310 | x position of the player }}
{{OBDtr|0x50|float|FF00FF|03 32 4B 42|50.798839|y-position (height)}}
{{OBDtr| 0x50 | float   |FF00FF| 03 32 4B 42 | 50.798839 | y position of the player }}
{{OBDtr|0x54|float|FF00FF|55 12 25 C4|-660.286437|z-position}}
{{OBDtr| 0x54 | float   |FF00FF| 55 12 25 C4 | -660.286437| z position of the player }}
{{OBDtr|0x58|float|FFC8C8|80 06 C1 3F|1.508010|y-rotation (facing)}}
{{OBDtr| 0x58 | float   |FFC8C8| 80 06 C1 3F | 1.508010   | player facing direction (radians) }}
{{OBDtr|0x5C|int32|FFFFC8|00 00 00 00|0|amount of ballistic ammo (red clips)}}
{{OBDtr| 0x5C | int32   |FFFFC8| 00 00 00 00 | 0         | number of ballistic ammo clips }}
{{OBDtr|0x60|int32|C8FFC8|01 00 00 00|1|amount of energy cells (green clips)}}
{{OBDtr| 0x60 | int32   |C8FFC8| 01 00 00 00 | 1         | number of energy cells }}
{{OBDtr|0x64|int32|C8FFFF|00 00 00 00|0|shield in percent}}
{{OBDtr| 0x64 | int32   |C8FFFF| 00 00 00 00 | 0         | shield (percent) }}
{{OBDtr|0x68|int32|FFC8FF|00 00 00 00|0|phase cloak in frames (1/60 s)}}
{{OBDtr| 0x68 | int32   |FFC8FF| 00 00 00 00 | 0         | invisibility (1/60 seconds) }}
{{OBDtr|0x6C|int32|FFC800|01 00 00 00|1|amount of hypos}}
{{OBDtr| 0x6C | int32   |FFC800| 01 00 00 00 | 1         | number of hypos }}
{{OBDtr|0x70|int32|C800C8|00 00 00 00|0|unknown; always 0}}
{{OBDtr| 0x70 | int32   |C800C8| 00 00 00 00 | 0         | door keys}}
{{OBDtr|0x74|int32|C87C64|01 00 00 00|true|whether the player has an [[LSI]]}}
{{OBDtr| 0x74 | int32   |C87C64| 01 00 00 00 | 1          | whether player has [[LSI]] (0 <nowiki>=</nowiki> no, 1 <nowiki>=</nowiki> yes) }}
{{OBDtr|0x78|int32|B0C3D4|00 00 00 00|0|unknown; always 0}}
{{OBDtr2| 0x78 | char[128]|B0C3D4| ""                      | weapon name (unused) }}
{{OBDtr|0x7C|int32|E7CEA5|00 00 00 00|0|unknown; always 0}}
{{OBDtr | 0xF8 | int32   |FFDDDD| 00 00 00 00 | 0         | weapon ammo (unused) }}
{{OBDtr2|0x80|char[256]|FFDDDD|&nbsp;|unknown, always 0}}
{{OBDtr2| 0xFC | char[128]|FFDDDD| ""                      | weapon name (unused) }}
{{OBDtr2|0x180|char[128]|64AAAA|w2_sap|name of player's [[ONWC]] (weapon class) if any}}
{{OBDtr | 0x17C| int32    |FFDDDD| 00 00 00 00 | 0         | weapon ammo (unused) }}
{{OBDtr|0x200|int32|EBEBEB|1E 00 00 00|30|ammo filling of the weapon (shots or percent?)}}
{{OBDtr2| 0x180| char[128]|64AAAA| "w2_sap"                | weapon name }}
{{OBDtr | 0x200| int32   |EBEBEB| 1E 00 00 00 | 30         | weapon ammo }}
|}
|}
;Weapon slots
:Yes, Oni does seem to support saved data for three weapons, even though the player can only carry one in the final game. Perhaps the three weapon slots were planned to allow for, say, [[:Image:Oni_box_art-front.jpg|dual-wielded guns and a holstered weapon]]....


[[Category:Oni binary data docs]]
[[Category:Oni binary data docs]]