Skip to content

Save File (dksave*.sav)

Each saved game consists of two files:

  • dksave*.sav — world and character data (this document)
  • dksave*.bsv — battle/dungeon data for the last unfinished dungeon
Extension
dksave*.sav
Location
Game root
Byte order
Little-endian (16-bit)
Size
Variable — 0xEF world header + 0x99 roster + (num_chars × 554) + events + 414 locations + cache block
Compression
None
Magic
None
Status
Partial
Source
Wendigo — dksaveXX.sav.xml
Partial. World state header has several undocumented blocks (notably 0x0C–0x14, 0x3E–0x62, 0x84–0x89). The 48-byte event record is only partially decoded — offsets for quest discriminator, dates, and location indices are established, but the remaining fields are unknown. Character records have gap bytes at the start (+0x00–+0x11) and scattered unknown fields.

Canonical source: dksaveXX.sav.xml (Wendigo’s Darklands repo)

Top-Level Layout

World State (0x00–0xee)

OffsetSizeFieldDescription
0x0012curr_location_nameCurrent party location name
0x0c9(unknown)Undocumented block between current location and save label
0x1523save_game_labelSaved game label
0x2c18(constant)Zero-filled block
0x3e55(unknown)Large unknown block; a few words vary near dream-related state
0x631(constant)Always 0x19
0x642city_contents_seedSeed for pseudo-RNG (saints/formulae/items per location)
0x662(constant)Always 07 00
0x688curr_dateCurrent date (date_reversed struct)
0x706party_moneyCash on hand (money struct)
0x764(constant)Zero-filled block
0x7a2reputationGlobal reputation
0x7c2curr_locationCurrent location index (0xffff = wilderness)
0x7e4curr_coordsCurrent map coordinates (coordinates struct)
0x822curr_menuCurrent menu/screen
0x846(unknown)First word is usually 0, 1, or 2
0x8a2prev_menuPrevious menu/screen
0x8c2bank_notesBank notes in florins
0x8e4(unknown)Undocumented block before philosopher’s stone
0x922philosopher_stoneQuality of philosopher’s stone
0x947(unknown)Undocumented block before party order
0x9b5party_order_indicesParty walking order (5 bytes, 0-based indices)
0xa01(unknown)Single unknown byte before party leader
0xa11party_leader_indexParty leader index (0-based)
0xa23(unknown)Undocumented block after party leader
0xa574(constant)Zero-filled tail block before the party roster

Party Roster (0xef–0x188)

OffsetSizeFieldDescription
0xef2num_curr_charactersCharacters currently in party (including NPCs)
0xf12num_charactersTotal characters defined
0xf310party_char_indices[5]Word index per party slot (0xffff = empty)
0xfd20party_images[5]4-byte image group string per slot; empty slots use the byte pattern 00 30 00 30
0x111120party_colors[5]person_colors struct (0x18 bytes) per slot

Character Data and World State (0x189+)

OffsetFieldDescription
0x189characters[num_characters]Character records, each 554 bytes (0x22a)
after charactersnum_events (word)Number of active quest/effect events; file offset depends on character count
after num_eventsevents[num_events]Event records, 0x30 bytes each; include quests and timed effects
after eventsnum_locations (= 0x19e)Number of map locations
after num_locationslocations[0x19e]Map location data copied from DARKLAND.LOC and updated in play
after locationsmax_cache_slot (byte = 0x63)Cache warning/limit marker used by the inn-storage block
after locationsnum_caches (byte)Number of active item caches
after num_cachescache_offsets[0x62]Word offsets into the cache payload
after cache_offsetscaches[num_caches]Inn item caches (known to corrupt on overflow)

Common Structs

date (8 bytes)

OffsetSizeField
0x002hour
0x022day
0x042month
0x062year (e.g. 1402)

date_reversed uses the same fields in reversed order: year, month, day, hour.

money (6 bytes)

OffsetSizeField
0x002florins
0x022groschen
0x042pfenniges

coordinates (4 bytes)

OffsetSizeFieldRange
0x002x_coord0–0x0147
0x022y_coord0–0x03a3

person_colors (24 bytes)

Eight RGB triplets (3 bytes each, values 0x00–0x3f) defining the battle sprite colormap: first_hi, first_lo, second_hi, second_med, second_lo, third_hi, third_med, third_lo.

Character Record

Each character is 554 bytes (0x22a). See Character Struct for the full field layout.

Key landmarks:

  • Names at +0x25 (full) and +0x3e (short)
  • Attributes at +0x5d (current) and +0x64 (max)
  • Skills at +0x6b
  • Saints bitmask at +0x80 (20 bytes / 160 bits)
  • Formulae bitmask at +0x94 (22 bytes)
  • Items array at +0xaa (up to 64 × 6 bytes)

Cache Block

The trailing cache block mirrors CACHE.TMP:

  • max_cache_slot is the constant byte 0x63
  • num_caches is the number of active inn caches
  • cache_offsets[0x62] are word offsets into the cache payload
  • caches[num_caches] contains the actual cache records

Notes:

  • the offsets are relative to the cache payload area, not absolute file offsets
  • only a subset of the 0x62 offset slots are actually used
  • the KB documents an overflow/corruption hazard if inn storage is reused in unlucky ways

Event Record

The KB still treats the 48-byte event structure as only partially decoded, but these anchors are established:

OffsetSizeFieldDescription
+0x002(unknown)Quest/effect discriminator; for Raubritter quests this is tied to the quest giver while active
+0x028create_dateCreation date (date)
+0x0a8(unknown date)Usually identical to create_date
+0x128expire_dateExpiration / trigger date (date)
+0x1a2(unknown)Often the quest-giver location until reward resolution
+0x1c2(unknown)For Raubritter quests, target location then return location
+0x1e2(unknown)Often the city that issued the quest
+0x212(unknown)Common values include 0x63, 0x5f, 0x32, 0
+0x232(unknown)Likely state variable; Raubritter quests move through 0x080x240x07
+0x2510(unknown)Mostly zero
+0x2e2(unknown)Usually the quest item code when an item is required

Cache Structs

cache

OffsetSizeFieldDescription
+0x001num_itemsNumber of items in this inn cache
+0x01variesitems[]Variable-length array of cache_item entries

cache_item

OffsetSizeFieldDescription
+0x002item_codeItem code from darkland.lst
+0x021qualityItem quality
+0x031quantityNumber of items