Townsmen – A Kingdom Rebuilt: save editing guide + HGSV format documented (Gold & Crowns)
There are a few requests around for Townsmen cheats and no answers, so here is the save
editing route instead. I reverse engineered the save format over an evening and it works.
Posting it because I could not find a single line about this format anywhere online.
What this does
Sets Gold and Crowns to whatever you want in Townsmen – A Kingdom Rebuilt (HandyGames)
on Switch. Single player only game, so this only touches your own save on your own console.
Tested and working on real hardware.
Everything below plus a ready to run Python script is here:
https://github.com/thbellath/townsmen-switch-save-editor
Two JKSV gotchas first
Backup layout
There are two last files and both matter. Delete the inner one and the save goes
invisible in game.
The HGSV container
All four files use the same wrapper:
Pitfall 1: the size field is the FULL stream length. Not length minus 4. The game
reads exactly that many bytes and feeds them to the decompressor. Too small means a
truncated stream, which shows up as the save being invisible or the game crashing on load.
This is what broke my first few attempts and the symptom looks exactly like a rejected
checksum, which sent me down the wrong path for a while.
Pitfall 2: keep the original footer. The last 4 bytes are not part of the zlib
stream. Pull them out with decompressobj().unused_data and append them again.
I could not identify the footer hash. CRC-32 (all common variants), CRC-32C, Adler-32,
FNV-1/1a, djb2, sdbm, Jenkins OAAT, Murmur2/3 and xxHash32 were all tested against the
decompressed payload, the compressed stream and the whole file. No match. Turns out it does
not matter: the game happily loads modified content with the old footer still attached, so
it is not validated on load. If anyone recognises it, I would still like to know.
Where the values are
In the decompressed data file, resources are stored as [ID byte][float32 LE] pairs:
The map file holds the HQ warehouse, gold again as 01 + float32 after the
building_hq entry. Change both files or the counter and the warehouse disagree.
All values are float32. Gold 999999 and Crowns 9999 are tested and stable.
Workflow
Script is in the repo, plain Python 3, no dependencies.
Notes
editing route instead. I reverse engineered the save format over an evening and it works.
Posting it because I could not find a single line about this format anywhere online.
What this does
Sets Gold and Crowns to whatever you want in Townsmen – A Kingdom Rebuilt (HandyGames)
on Switch. Single player only game, so this only touches your own save on your own console.
Tested and working on real hardware.
Everything below plus a ready to run Python script is here:
https://github.com/thbellath/townsmen-switch-save-editor
Two JKSV gotchas first
- Launch JKSV in full RAM mode (hold R while starting a game) or it can crash.
- Press L + R + ZL + ZR inside JKSV. Townsmen is a device save, so it is not
listed until you enable that mode. This is why people think the game has no save data.
Backup layout
Code:
JKSV/Townsmen/<BackupName>/
├── profile # achievements, leave alone
├── profile.bak
├── last # points at the town folder, DO NOT DELETE
└── <UUID>/ # one folder per town
├── last # contains "save00", DO NOT DELETE
├── autosave00/
└── save00/
├── data # <- edit (global resource counters)
├── map # <- edit (HQ warehouse stock)
├── save
└── thumbnail.jpg
invisible in game.
The HGSV container
All four files use the same wrapper:
Code:
0x00 4 bytes magic "HGSV"
0x04 5 bytes type flags, differ per file, copy unchanged
0x09 uint32 LE exact length of the zlib stream, including its Adler-32
0x0D ... zlib stream (78 9C)
end 4 bytes footer, 4 byte hash, algorithm unknown
Pitfall 1: the size field is the FULL stream length. Not length minus 4. The game
reads exactly that many bytes and feeds them to the decompressor. Too small means a
truncated stream, which shows up as the save being invisible or the game crashing on load.
This is what broke my first few attempts and the symptom looks exactly like a rejected
checksum, which sent me down the wrong path for a while.
Pitfall 2: keep the original footer. The last 4 bytes are not part of the zlib
stream. Pull them out with decompressobj().unused_data and append them again.
I could not identify the footer hash. CRC-32 (all common variants), CRC-32C, Adler-32,
FNV-1/1a, djb2, sdbm, Jenkins OAAT, Murmur2/3 and xxHash32 were all tested against the
decompressed payload, the compressed stream and the whole file. No match. Turns out it does
not matter: the game happily loads modified content with the old footer still attached, so
it is not validated on load. If anyone recognises it, I would still like to know.
Where the values are
In the decompressed data file, resources are stored as [ID byte][float32 LE] pairs:
- 0x01 = Crowns
- 0x02 = Gold
- 0x14, 0x16, 0x18, 0x32, ... = other resources, not mapped yet
Code:
b'\x01' + struct.pack('<f', crowns) + b'\x02' + struct.pack('<f', gold)
The map file holds the HQ warehouse, gold again as 01 + float32 after the
building_hq entry. Change both files or the counter and the warehouse disagree.
All values are float32. Gold 999999 and Crowns 9999 are tested and stable.
Workflow
- Note your exact current Crowns and Gold in game, the script searches for them
- Save, quit, back up with JKSV (full RAM mode, L+R+ZL+ZR)
- Get the files to your PC. Easiest without ejecting the SD card:
Hekate > Tools > USB Tools > SD Card, then USB-C to the PC - Run the script on data and map from save00
- Copy the two files back into save00, replacing the originals
- JKSV > Restore, start the game
Script is in the repo, plain Python 3, no dependencies.
Notes
- Keep one known good JKSV auto-ZIP as a fallback before you experiment.
- This is a save edit, not a memory freeze. Values drop again as you play, just re-run it.
- Save manually in game, do not rely on the autosave, or you will load the old numbers back.
- The script matches on patterns rather than fixed offsets, so it should survive other maps
and versions, but I could only test my own saves. Reports from other maps welcome. - The remaining resource IDs can be mapped the same way: note an exact in game amount,
search for it as float32, read the ID byte in front of it. If anyone does this, post it and
I will fold it into the repo.





