Save/status file (game.cfg)¶
Crimsonland stores quest progress and several counters in game.cfg (the “status” file). The
format is small but obfuscated and checksummed. This page documents what we know so far and
links the editor script in scripts/save_status.py.
File layout¶
- Total size:
0x26cbytes. - Payload: first
0x268bytes (game_status_blob). - Checksum: final 4 bytes, little‑endian
u32.
Obfuscation¶
Each payload byte is transformed on save using a byte index polynomial and a constant add.
Let i be the byte index and i8 be i wrapped to a signed 8‑bit value.
The loader reverses it with:
Checksum¶
The checksum is computed over the decoded payload. It accumulates in a 32‑bit integer (wrap on overflow).
acc = 0
u = 0
for i, byte in enumerate(decoded):
c = signed8(byte)
acc = (acc + 0x0d + ((c * 7 + i) * c + u)) & 0xffffffff
u += 0x6f
Known fields¶
Offsets are relative to the decoded payload (game_status_blob).
| Offset | Size | Name | Notes |
|---|---|---|---|
0x00 |
u16 | quest_unlock_index |
Max quest unlock index (limited version). |
0x02 |
u16 | quest_unlock_index_full |
Max quest unlock index (full version). |
0x04 |
u32[53] | weapon_usage_counts |
Weapon usage counters indexed by weapon id (1-based; slot 0 unused). Note: id 53 would overlap quest_play_counts[0] if written. |
0xD8 |
u32[91] | quest_play_counts |
Quest play/attempt counters (major * 10 + minor). Length inferred from known tail fields. |
0x244 |
u32 | mode_play_survival |
Incremented when starting Survival (mode 1). |
0x248 |
u32 | mode_play_rush |
Incremented when starting Rush (mode 2). |
0x24C |
u32 | mode_play_typo |
Incremented when starting Typ‑o‑Shooter (mode 4). |
0x250 |
u32 | mode_play_other |
Incremented for other modes (e.g. tutorial). |
0x254 |
u32 | game_sequence_id |
Also written to registry on save. |
0x258 |
0x10 | — | Unknown/reserved tail bytes. |
Editor tool¶
Use the helper script to inspect and edit game.cfg:
uv run python scripts/save_status.py info game_bins/crimsonland/1.9.93-gog/game.cfg
uv run python scripts/save_status.py set game.cfg --set quest_unlock_index=30 --set weapon_usage.5=12
Supported edits:
- quest_unlock_index, quest_unlock_index_full, game_sequence_id
- weapon_usage.<slot> (0–52; slot = weapon_id, 0 unused)
- quest_play.<index> (0–90)
- mode_play.<survival|rush|typo|other>
The script validates the checksum, applies updates to the decoded blob, and rewrites the obfuscated file with a fresh checksum.