Dungeons of the Unforgiven Player Character

From ModdingWiki
Jump to: navigation, search
Dungeons of the Unforgiven Player Character
Format typeSaved game
Save locationsUnknown
Elements savedPlayer character data
Games

The saved game format for Dungeons of the Unforgiven appears to be a simple dump of the game's internal structures, with a couple of checksum bytes added on, presumably to slow cheaters down a bit. Some of the chunks of data are in a very peculiar order (such as some of the items being in radically different spots of the file), which makes it somewhat annoying to try to directly load into a C struct or similar data structure.

If you're parsing this format, be very mindful of the data types. Signed and unsigned data types, as well as differing field sizes, are used even with related fields. For example, Rings of Protection are stored in an unsigned byte while Potions of Healing are stored in a signed byte.

File Layout

Data type Name Description
char[19] playerName The name of the player character (including a null terminator).
BYTE[22] unknown ! Unknown.
INT8 playerRace The race of the player character.
INT8 playerGender The player character's gender (0x00 == male; 0x01 == female)
INT8 playerClass The player character's class.
BYTE[6] unknown ! Unknown.
INT16LE playerCurrentHP The player character's current hit points.
INT16LE playerMaxHP The player character's maximum hit points.
INT32LE playerCurrentSP The player character's current spell points.
INT32LE playerMaxSP The player character's maximum spell points.
BYTE[2] unknown ! Unknown.
INT16LE nakedWeight The player's base weight.
INT16LE loadedWeight The player's loaded weight (note: this always gets updated by the game).
BYTE[62] unknown ! Unknown.
BYTE weaponFists Player character has their fists (normally these cannot be dropped).
BYTE weaponStick Player character has the stick.
BYTE weaponClub Player character has the club.
BYTE weaponMace Player character has the mace.
BYTE weaponKnife Player character has the knife.
BYTE weaponShortSword Player character has the short sword.
BYTE weaponLongSword Player character has the long sword.
BYTE weaponGreatSword Player character has the great sword.
BYTE[18] unknown ! Unknown.
INT8 equippedWeapon The weapon that the player character currently has equipped. See the Weapon IDs section for valid values.
BYTE[20] unknown ! Unknown.
BYTE armorSkin Player character has their skin (normally this cannot be dropped).
BYTE armorLeather Player character has leather armor.
BYTE armorChain Player character has chain armor.
BYTE armorScale Player character has scale armor.
BYTE armorBreastPlate Player character has the breast plate.
BYTE armorFieldPlate Player character has field plate.
BYTE armorTitanium Player character has the titanium armor.
BYTE armorSlot8 This "armor" is not implemented in the game and points to garbage data. See the notes below for a little bit more information. ! Figure out exactly what in the executable this is pointing to, as it is technically fully usable.
INT8 equippedArmor The armor that the player character currently has equipped. See the Armor IDs section for valid values.
BYTE[156] unknown ! Unknown.
INT8 orangePotions The number of orange potions in the player's inventory (+6 Strength / -3 Luck)
INT8 greenPotions The number of green potions in the player's inventory (+6 Intelligence / -3 Agility)
INT8 bluePotions The number of blue potions in the player's inventory (+6 Wisdom / -3 Constitution)
INT8 redPotions The number of red potions in the player's inventory (+6 Constitution / -3 Wisdom)
INT8 whitePotions The number of white potions in the player's inventory (+6 Agility / -3 Intelligence)
INT8 yellowPotions The number of yellow potions in the player's inventory (+6 Luck / -3 Strength)
BYTE[20] unknown ! Unknown.
SPELL_LIST spellbook The spells that the player has learned and can cast at any time at the cost of spell power.
SPELL_LIST scrolls The spells that the player can cast from a scroll.
SPELL_LIST wands The spell wands that the player possesses.
SPELL_LIST papers The spell papers that the player owns.
BYTE[13] unknown ! Unknown.
INT32LE rublesInPocket The number of rubles that the player has on hand.
INT32LE rublesInBank The number of rubles that the player has in the bank.
BYTE[8] unknown ! Unknown.
INT32LE cultureStock The amount of culture stock that the player owns.
INT32LE childrenHelped The number of children that the player helped (at the temple).
INT32LE magicCrystals The number of magic crystals that the player owns.
INT32LE americanDollars The number of American Dollars that the player has.
BYTE[816] unknown ! Unknown.
Double experiencePoints The number of experience points that the player has.
INT16LE playerLevel The player character's current level.
INT16LE playerDirection The direction that the player character is facing (0x00 == north; 0x01 == south; 0x02 == west; 0x03 == east).
INT16LE playerPositionX The X coordinate of the player in the current dungeon floor.
INT16LE playerPositionY The Y coordinate of the player in the current dungeon floor.
INT16LE playerFloor The floor of the dungeon that the player is currently on (0 is the town).
INT16LE playerModule The module that the player is currently playing.
BYTE[18] unknown ! Unknown.
UINT8 ringsOfRegeneration The number of rings of regeneration that the player has.
BYTE unknown ! Unknown.
UINT8 nuclearHandGrenade The number of nuclear hand grenades that the player has.
UINT8 stonesOfSeeing The number of stones of seeing that the player has.
INT16LE diseaseTimer The number of turns until poison damages constitution (0 or -1 disables the timer).
INT16LE poisonTimer The number of turns until poison damages strength (0 or -1 disables the timer).
BYTE[2] unknown ! Unknown.
UINT8 bodyArmor The number of body armor items that the player has (not related to the gear, listed above).
UINT8 ringOfProtection The number of rings of protection that the player has.
UINT8 antiMagicRing The number of anti-magic rings that the player has.
BYTE[3] unknown ! Unknown.
INT32LE playerAge The current age of the player character.
BYTE[36] unknown ! Unknown.
INT8 floorSloshers The number of floor sloshers that the player has.
INT8 potionsOfHealing The number of potions of healing that the player has.
INT8 stonesOfTeleportation The number of stones of teleportation that the player has.
INT16LE playerStrength The number of strength points that the player has.
INT16LE playerIntelligence The number of intelligence points that the player has.
INT16LE playerWisdom The number of wisdom points that the player has.
INT16LE playerConstitution The number of constitution points that the player has.
INT16LE playerAgility The number of agility points that the player has.
INT16LE playerLuck The number of luck points that the player has.
BYTE[49] unknown ! Unknown.
INT8 gauntlets The number of gauntlets that the player has.
BYTE[162] unknown ! Unknown.
BYTE difficulty The difficulty level that the player is playing on. (0x00 == normal; 0x01 == "I can handle anything!")
UINT32LE gameTimer This appears to be some sort of hidden in-game timer. ! Figure out when this is incremented and whether or not it actually does anything.
BYTE[274] unknown ! Unknown.
UINT8[2] checksum The checksum of the saved game file. See below for more information.

Spells

Spells are stored in the save file per the following table. In all cases, the spells are stored in order from left-to-right, top-to-bottom, with respect to the in-game spell browser. Each spell category has 15 unused bytes at the end.

Data type Name Description
INT8[45] spellsPermanent The permanent spells that the player has access to.
INT8[45] spellsPreparation The preparation spells that the player has access to.
INT8[45] spellsWizard The wizard battle spells that the player has access to.
INT8[45] spellsPriest The priest battle spells that the player has access to.
  • ! Do a bit more bounds checking on some of the fields to work out whether they're signed or unsigned.
  • The eighth armor slot always appears in the armor list of the game as a blank slot, but only seven armor types appear within the game world. If the set of armor is hacked into the game with a hex editor or memory editor, it appears as jumbled text and provides a currently-unknown amount of protection.

Weapon IDs

The following weapon IDs can be used in the equippedWeapon field.

ID Weapon Type
0x00 Fists
0x01 Stick
0x02 Club
0x03 Mace
0x04 Knife
0x05 Short Sword
0x06 Long Sword
0x07 Great Sword
  • Note: the player does not have to own the specified weapon type in order to have it equipped. The equipment check is only performed when the player switches their weapon in-game.

Armor IDs

The following weapon IDs can be used in the equippedArmor field.

ID Armor Type
0x00 Skin
0x01 Leather
0x02 Chain
0x03 Scale
0x04 Breast Plate
0x05 Field Plate
0x06 Titanium
0x07 Glitchy Armor
  • Note: the player does not have to own the specified armor type in order to have it equipped. The equipment check is only performed when the player switches their armor in-game.

Checksum

The checksum is calculated as follows (example in C# and assuming saveBytes is the saved game data, sans checksum):

checksum[0] = checksum[1] = 0;
foreach(var b in saveBytes) {
    checksum[0] += b;
    checksum[1] += checksum[0] - checksum[0] * checksum[0];
}

If the checksum is incorrect for the saved game file, the player will be immediately booted back to the DOS prompt with a "corrupted character" error.

Credits

This file format was reverse engineered and documented by Spectere. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)