Skip to content

File format

Savegames

Nine sections, no compression, no encryption — and a leak of the game's own memory into every file you share.

.sav .lom

In short

A savegame is nine labelled sections written back to back, with no length or count between a label and its contents. Five sections decode completely. Four decode in part, and the bytes that are not understood are carried through unchanged rather than guessed at.

What was found

Savegames leak process memory

Measured

The game copies each player's name into a fixed 32-byte field without clearing it first, so whatever happened to be in that buffer goes to disk behind the terminating byte.

This was measured, not supposed. Two saves of the identical game state have different checksums, and every one of the 356 differing bytes lies past the end of a name. The leaked content is recognisable Windows stack and heap addresses.

Three consequences. A savegame is not a pure function of the game state, so no tool may assume two saves of one state match. Any save-comparison tool must mask that padding or it will report identical states as different. And a file you share carries fragments of your machine's memory — harmless in everything examined here, but worth knowing before you post one.

Nothing is compressed or encrypted

Measured

Established four independent ways, including finding the writer dumping raw structure memory to disk. Unit names are readable in a hex editor. One section carries a caveat and is noted separately.

Twenty files, seven game states

We were wrong about this

The save corpus passes every structural check on every file, 20 for 20. That line is misleading and the document says so: six of the saves are demo scenarios shipped identically in all three installs, and two more are one state written twice.

Twenty files are seven states, and six of those seven were authored together and may share a generator. Exactly one is real play. Where a rule holds, it holding there is worth more than the other six combined.

This is the inflated-denominator trap, caught in the project's own work and left written down.

A total that added up, over a structure that was wrong

We were wrong about this

The map section's size was explained for a while by a formula that produced exactly the right byte count out of exactly the wrong structure: one array of twelve-byte cells, where the file really holds one array of eight-byte cells and a second, separately counted array of four-byte values.

Eight plus four is twelve, so any regrouping of the two arrays gives the identical bulk figure, and the whole difference between the right reading and the wrong one was four bytes of bookkeeping — small enough to wave through.

The lesson recorded is not 'check your arithmetic'. It is that a check comparing only a sum cannot fail on a regrouping of its terms. The parser now also asserts that the second array's own count matches the cell count, which no regrouping can satisfy.

The save sections were read out of the game, not guessed from the files

Measured

All nine sections of a savegame are now described field by field, recovered by following the game's own reading and writing code rather than by pattern-matching the files. Every section accounts for its bytes exactly across all the saves examined, and the whole file can be rebuilt from the decoded model byte for byte.

That last fact proves less than it appears to, and the research says so with a worked example: shifting two adjacent field widths in compensating directions leaves every boundary wrong and the total unchanged, and the rebuilt file still matches. A round trip tests the arithmetic, not the layout. What supports the layouts is the instruction stream.

One question was answered by being dissolved. The per-player record has no fixed size at any version — it is a tree of counted lists, and two players in the same file differ in length. A save that appeared to show a clean stride was a turn-one scenario where every player happened to be empty.

The game loads a savegame written by this project

Measured

A save decoded and written back out — checked byte for byte against the original first, so that nothing about the writing could explain a later failure — loaded, and the game played on from it.

Then one field was changed. The lord's name is the only field in that section whose meaning was already established, and it is the only one that reaches the screen without interpreting anything, so it was the subject: eight lords renamed, the file the same length, and the party roster showed the new name. The game read a field this project authored.

A lord's name is stored three times, and two screens disagree

Measured

The rename above was meant only to be visible. It changed the party roster and left the overworld panel showing the original name — so the name is not one field but three copies, in three different sections of the save.

Giving each copy a different value settled which screen reads which: the player section feeds the party roster, the sprite section feeds the overworld unit panel, and the third copy, in the multiplayer setup block, is shown by neither.

These are the first fields in either of those sections whose meaning comes from watching the game rather than from reading the code that writes them. Everything else in them remains unknown. A rename of a single lord would have shown the new name and looked like a complete answer.

Still unknown

Named as open rather than guessed at.

  • What the fields of the unit-and-army records mean. The record layouts themselves were recovered from the game's own reader, but almost nothing says what the values are.
  • Three of the record classes have never appeared in any save file examined, so their layouts rest on the disassembly alone with nothing to check them against.
  • What the six bytes of a region grid cell hold.
  • Two of the six callback queues are empty in every save examined, so a misreading of their layout would be invisible.
  • Whether a save whose sections change length is accepted. Every save put in front of the game so far kept its exact size.

All file formats