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

From OniGalore
Jump to navigation Jump to search
No edit summary
(improved phrasing for diary page fields, added a table for the item bits)
 
(13 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{merge|[[Persist.dat]]}}
{{UpdatedForOniX|1.0.0}}
persist.dat, found next to the game application, is the save-game and preference file for Oni. It can be edited most easily with GUI tools such as [[OSGE]] for Windows and [http://mods.oni2.net/node/155 OniLib] for Mac, though [[OBD]]-style hex-based documentation of this file is given below.


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|.dat level 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, lvl_#_###_corpse.dat, etc. – until they later added .raw and then .sep as unique suffixes when they needed to break out some resource data from levelX_Final.dat).


Note that for Windows Vista, the file, along with three others( debugger.txt, key_config.txt & startup.txt ) are located at C:\Users\*your username*\AppData\Local\VirtualStore\Program Files\Oni, rather than in the same directory as Oni.exe by virtue of OS's handling of the game's installation. This does not apply to Oni: AE.
==Progress saving==
As players of Oni are well aware, the game does not allow arbitrary saving ("save anywhere"), but relies on the use of fixed save points activated by reaching certain places in each level, at which point the level scripting uses the [[BSL]] function <tt>save_game</tt> to mark your progress. This means that by deciding on a maximum number of levels and save points, Bungie West could store the total state of the player's progress in a fixed-size file – 206,496 bytes, to be exact.


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.
As you will see below, many aspects of the game world are ''not'' saved in persist.dat; essentially, anything not pertaining to Konoko herself, such as the position of AIs and the presence of power-ups on the ground. What <u>is</u> stored is Konoko's position, health and inventory. Everything else is determined by the level scripting and the game data, and will always be in the same place when that save point is loaded.


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.
==Game preferences==
In addition to save point data, persist.dat has a header section which stores Oni's preferences as chosen on the Options screen (note that this omits key bindings since they're stored in [[key_config.txt]]). It also records whether the [[cheats]] are enabled, i.e. whether you have beaten the game (however, cheats are unlocked at all times when playing with the [[Anniversary Edition]] or [[Daodan DLL]] installed or when using the [[FERAL|Intel Mac build]]), as well as whether you killed Griffin in {{C|13}}.


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.
==Endianness==
{{table}}{{OBDtable}}
The Windows version of persist.dat stores its numbers in little-endian format. Bungie's original Mac game application and The Omni Group's Mac OS X port were built for PowerPC 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 save-game files were not compatible between Windows and Mac versions of Oni. However, with modern Macs running a native Intel build, the files are now saved in little-endian format and are thus interchangeable between Windows and Mac Oni.
 
==Overview==
The header of the file is 0x60=96 bytes long. It is followed by an array of 400 save points, 0x204=516 bytes each, grouped implicitly into 40 levels with 10 save points per level for a total of 206,400 bytes. The first 10 save points belong to level 0, which contains global game data rather than a specific level, thus they are never written to. The save points of the game's 14 levels follow. This leaves 25 unused level slots at the end of the save-game file.
 
Only the names of save points, not levels, are stored in this file (and they are all named uniformly as "Save Point ''n''" even though they could say anything). The actual level names are taken from the ONLD resources in level0_Final, except for Chapter 1's name, "Syndicate Warehouse", which was hard-coded into the engine for a reason explained on the [[ONLD]] page.
 
==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 which matches this level number is found in level0_Final.dat. Levels above 39 are not unlockable due to the 40-level save point limit in the persist.dat.
 
==Header data==
[[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 flags 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 flags 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 flags 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 flags 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 flags for levels 128-159 }}
{{OBDtr|0x30|int32|00FFFF|1F 00 00 00|31|unknown}}
{{OBDtr| 0x1C | int32 |FF0000| 00 00 00 00 |     | level unlock flags for levels 160-191 }}
{{OBDtr|0x34|int32|FF00FF|13 00 00 00|19|unknown}}
{{OBDtr| 0x20 | int32 |FF0000| 00 00 00 00 |     | level unlock flags for levels 192-223 }}
{{OBDtr|0x38|int32|FFC8C8|01 00 00 00|01|unknown}}
{{OBDtr| 0x24 | int32 |FF0000| 00 00 00 00 |     | level unlock flags 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 diary weapon pages, one bit for each weapon; these bits match the skill index values in the primary firing mode block of each [[ONWC]] (see 0x13E in ONWC for the weapon table) }}
{{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 diary item pages; one bit for each item type:
{{OBDtr|0x48|int32|FFC8FF|02 00 00 00|2|quality: from Easy (0) to Hard (2)}}
:0x'''01''' 00 00 00 - ballistic ammo
{{OBDtr|0x4C|int16|FFC800|20 03|800|horizontal screen resolution}}
:0x'''02''' 00 00 00 - energy ammo
{{OBDtr|0x4E|int16|FFC800|02 58|600|vertical screen resolution}}
:0x'''04''' 00 00 00 - hypo
{{OBDtr|0x50|int32|C800C8|20 00 00 00|32|color depth}}
:0x'''08''' 00 00 00 - force shield
{{OBDtr|0x54|float|C87C64|00 00 00 3F|0.500000|gamma correction; from 0.0 to 1.0, 0.5 means no correction}}
:0x'''10''' 00 00 00 - phase cloak
{{OBDtr|0x58|int32|B0C3D4|03 00 00 00|3|last loaded level; written at level load}}
:0x'''20''' 00 00 00 - LSI (unused because LSIs are level-specific and the diary page for an LSI can only be read while it's in your inventory) }}
{{OBDtr|0x5C|int32|E7CEA5|02 00 00 00|2|last saved savepoint}}
{{OBDtr| 0x34 |       |FF00FF| 13 00 00 00 | 19 | last read diary page (level) }}
{{OBDtr| 0x38 |       |FFC8C8| 01 00 00 00 | | last read diary page (page) }}
{{OBDtr| 0x3C | int32 |FFFFC8| 04 00 00 00 | 4   | level of graphical detail; the following options are possible:
:0 - extra low
:1 - low
:2 - medium
: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 modes|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       | 600 | 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 saved level }}
{{OBDtr| 0x5C | int32 |E7CEA5| 02 00 00 00 | | last saved save point }}
|}
|}




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 save points (40 levels, 10 save points per level). The size of a save point is 516 bytes so the array size is 206,400 bytes.
 
==Save point data==
[[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 }}
|}
|}


[[Category:Oni binary data docs]]
 
;Player health
:Storing both the player's current HP and max HP allows the game to scale your health appropriately if the difficulty level is changed between saving the game and restoring from it.
 
;Weapon slots
:Yes, Virginia, 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, [[Fully Armed Konoko|dual-wielded guns and a holstered weapon]]....
 
{{OBD}}[[Category:Game directory map]]

Latest revision as of 18:19, 19 May 2024

persist.dat, found next to the game application, is the save-game and preference file for Oni. It can be edited most easily with GUI tools such as OSGE for Windows and OniLib for Mac, though OBD-style hex-based documentation of this file is given below.

The persist.dat file has nothing to do with Oni's .dat level 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, lvl_#_###_corpse.dat, etc. – until they later added .raw and then .sep as unique suffixes when they needed to break out some resource data from levelX_Final.dat).

Progress saving

As players of Oni are well aware, the game does not allow arbitrary saving ("save anywhere"), but relies on the use of fixed save points activated by reaching certain places in each level, at which point the level scripting uses the BSL function save_game to mark your progress. This means that by deciding on a maximum number of levels and save points, Bungie West could store the total state of the player's progress in a fixed-size file – 206,496 bytes, to be exact.

As you will see below, many aspects of the game world are not saved in persist.dat; essentially, anything not pertaining to Konoko herself, such as the position of AIs and the presence of power-ups on the ground. What is stored is Konoko's position, health and inventory. Everything else is determined by the level scripting and the game data, and will always be in the same place when that save point is loaded.

Game preferences

In addition to save point data, persist.dat has a header section which stores Oni's preferences as chosen on the Options screen (note that this omits key bindings since they're stored in key_config.txt). It also records whether the cheats are enabled, i.e. whether you have beaten the game (however, cheats are unlocked at all times when playing with the Anniversary Edition or Daodan DLL installed or when using the Intel Mac build), as well as whether you killed Griffin in CHAPTER 13 . PHOENIX RISING.

Endianness

The Windows version of persist.dat stores its numbers in little-endian format. Bungie's original Mac game application and The Omni Group's Mac OS X port were built for PowerPC 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 save-game files were not compatible between Windows and Mac versions of Oni. However, with modern Macs running a native Intel build, the files are now saved in little-endian format and are thus interchangeable between Windows and Mac Oni.

Overview

The header of the file is 0x60=96 bytes long. It is followed by an array of 400 save points, 0x204=516 bytes each, grouped implicitly into 40 levels with 10 save points per level for a total of 206,400 bytes. The first 10 save points belong to level 0, which contains global game data rather than a specific level, thus they are never written to. The save points of the game's 14 levels follow. This leaves 25 unused level slots at the end of the save-game file.

Only the names of save points, not levels, are stored in this file (and they are all named uniformly as "Save Point n" even though they could say anything). The actual level names are taken from the ONLD resources in level0_Final, except for Chapter 1's name, "Syndicate Warehouse", which was hard-coded into the engine for a reason explained on the ONLD page.

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 which matches this level number is found in level0_Final.dat. Levels above 39 are not unlockable due to the 40-level save point limit in the persist.dat.

Header data

Persist header.gif

Offset Type Raw Hex Value Description
0x00 int32 0F 00 00 00 15 version
0x04 int32 0E 0B D0 D0 0xD0D00B0E signature
0x08 int32 5C 7F 0C 00 0x000C7F5C level unlock flags for levels 0-31; each level has a corresponding bit:
0x01 00 00 00 - level 0 (always unlocked, ignored)
0x02 00 00 00 - level 1 (always unlocked, ignored)
0x04 00 00 00 - level 2
...
0x00 00 08 00 - level 19
0x0C int32 00 00 00 00 level unlock flags for levels 32-63
0x10 int32 00 00 00 00 level unlock flags for levels 64-95
0x14 int32 00 00 00 00 level unlock flags for levels 96-127
0x18 int32 00 00 00 00 level unlock flags for levels 128-159
0x1C int32 00 00 00 00 level unlock flags for levels 160-191
0x20 int32 00 00 00 00 level unlock flags for levels 192-223
0x24 int32 00 00 00 00 level unlock flags for levels 224-255
0x28 int32 01 00 00 00 1 killed Griffin (0 = no, 1 = yes)
0x2C FE 1B 00 00 7166 unlocked diary weapon pages, one bit for each weapon; these bits match the skill index values in the primary firing mode block of each ONWC (see 0x13E in ONWC for the weapon table)
0x30 1F 00 00 00 31 unlocked diary item pages; one bit for each item type:
0x01 00 00 00 - ballistic ammo
0x02 00 00 00 - energy ammo
0x04 00 00 00 - hypo
0x08 00 00 00 - force shield
0x10 00 00 00 - phase cloak
0x20 00 00 00 - LSI (unused because LSIs are level-specific and the diary page for an LSI can only be read while it's in your inventory)
0x34 13 00 00 00 19 last read diary page (level)
0x38 01 00 00 00 1 last read diary page (page)
0x3C int32 04 00 00 00 4 level of graphical detail; the following options are possible:
0 - extra low
1 - low
2 - medium
3 - high
4 - extra high
0x40 float 00 00 80 3F 1.0 sound volume (0.0 = min, 1.0 = max)
0x44 int32 06 00 00 00 6 option flags; the following values are possible:
0x01 00 00 00 - show subtitles
0x02 00 00 00 - invert mouse
0x04 00 00 00 - game won (aka cheats enabled)
0x48 int32 02 00 00 00 2 difficulty; the following values are possible:
0 - easy
1 - medium
2 - hard
0x4C int16 20 03 800 resolution: width
0x4E int16 02 58 600 resolution: height
0x50 int16 20 00 32 color depth
0x52 00 00 padding
0x54 float 00 00 00 3F 0.5 gamma correction; from 0.0 to 1.0, 0.5 means no correction
0x58 int32 03 00 00 00 3 last saved level
0x5C int32 02 00 00 00 3 last saved save point


Killed Griffin
Used in Chapters 13 and 14; set with killed_griffen, read with did_kill_griffen.


After this header is an array of 400 save points (40 levels, 10 save points per level). The size of a save point is 516 bytes so the array size is 206,400 bytes.

Save point data

Persist dat.gif


Offset Type Raw Hex Value Description
0x00 char[64] "Save Point 2" name of the save point in Load Game dialog
0x40 int32 01 00 00 00 1 valid (was saved previously), i.e. "Should we display this in Load Game?" (0 = no, 1 = yes)
0x44 int32 BE 00 00 00 190 current player health (HP)
0x48 int32 C8 00 00 00 200 max player health (HP)
0x4C float AE 20 FB 43 502.255310 x position of the player
0x50 float 03 32 4B 42 50.798839 y position of the player
0x54 float 55 12 25 C4 -660.286437 z position of the player
0x58 float 80 06 C1 3F 1.508010 player facing direction (radians)
0x5C int32 00 00 00 00 0 number of ballistic ammo clips
0x60 int32 01 00 00 00 1 number of energy cells
0x64 int32 00 00 00 00 0 shield (percent)
0x68 int32 00 00 00 00 0 invisibility (1/60 seconds)
0x6C int32 01 00 00 00 1 number of hypos
0x70 int32 00 00 00 00 0 door keys
0x74 int32 01 00 00 00 1 whether player has LSI (0 = no, 1 = yes)
0x78 char[128] "" weapon name (unused)
0xF8 int32 00 00 00 00 0 weapon ammo (unused)
0xFC char[128] "" weapon name (unused)
0x17C int32 00 00 00 00 0 weapon ammo (unused)
0x180 char[128] "w2_sap" weapon name
0x200 int32 1E 00 00 00 30 weapon ammo


Player health
Storing both the player's current HP and max HP allows the game to scale your health appropriately if the difficulty level is changed between saving the game and restoring from it.
Weapon slots
Yes, Virginia, 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, dual-wielded guns and a holstered weapon....