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.

Still unknown

Named as open rather than guessed at.

  • The record layouts inside the unit-and-army section, which are variable-length and polymorphic.
  • The per-player section's record size in the current format version.
  • The trailing part of the region section, and the record layout of the pending-callback section.

All file formats