User folders: save games and Settings.cfg in Documents\Sacred

The game's ANSI file API calls are hooked; paths under save\ and
Settings.cfg are redirected to Documents\Sacred\save and
Documents\Sacred\config, copied there once from the game folder.
The shared chest uses the same save folder.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-20 00:14:36 +02:00
1 parent 198c21dbfa
commit 6c467e22c4
7 files changed
+337 -9

No files matched your search

+2 -1
View File
@@ -4,7 +4,8 @@
The chest gets a second tab that belongs to no single hero: a chest shared by
all characters. Decided: stored in one file in the save folder
(`save\shared_chest.json`), two tabs ("Truhe" / "Gemeinsam"), same size as the
(`shared_chest.json` in the save folder, `Documents\Sacred\save`, see
`user-folders.md`), two tabs ("Truhe" / "Gemeinsam"), same size as the
chest (20 x 10). Potions stack in it like in every player inventory
(docs/item-stacks.md). Follow-up (same day): text tabs were barely visible;
use the inventory's Rucksack / Kampfkünste / Combos header look with its
+55
View File
@@ -0,0 +1,55 @@
# User folders (Documents\Sacred)
Request (2026-10-19): the game keeps its save games and settings in the
user's Documents folder instead of the game folder:
| Folder | Contents |
|---|---|
| `Documents\Sacred\save\` | `GAMEnn.PAK` (save rows), `Heronn.pax` (exported heroes), `shared_chest.json` (sacredK) |
| `Documents\Sacred\config\` | `Settings.cfg` (the game's options) |
`sacredK.ini` (key bindings, loot filter, game folder) stays next to the DLL.
## Measured
Vanilla keeps everything inside the game folder: no AppData, Documents or
registry use (the `Ascaron Entertainment` folders there belong to Sacred 2).
`sacred.exe` names the files with paths relative to the working directory
(the game folder), from 37 code sites:
| String | Address | Users |
|---|---|---|
| `./SAVE/GAME%.2d.PAK` | 0x95c530 | 0x60b58b, 0x60c0d3, 0x60e38f, 0x60e645, 0x71cda7 |
| `SAVE/GAME%.2d.PAK` | 0x95c884 | 0x60e35a, 0x60e60a, 0x619c38 |
| `./SAVE/GAMEF%d.PAK` | 0x95c870 | 0x60e3b9, 0x60e674 |
| `./SAVE/SAVE02.PAK` | 0x95c85c | 0x60dc2c |
| `Save\Hero%.2d.pax` | 0x95c4ec | 0x60bf16, 0x614ceb, 0x70d96c, 0x70dd8d, 0x70df1b, 0x70e091 |
| `.\Save`, `Save` | 0x95d5f4, 0x95d5ec | 0x619cd4/ec, 0x61cdc0/d1 |
| `SAVE\` | 0x9e15a0 | 0x70bf07 |
| `Settings.cfg` | 0xa18dc4 | 0x7ed6a2..0x7eeab3 (13), WinMain 0x816dc0..0x816dd6 |
All file access goes through kernel32's ANSI functions: `CreateFileA`,
`DeleteFileA`, `FindFirstFileA`, `GetFileAttributes(Ex)A`,
`SetFileAttributesA`, `CreateDirectoryA`, `CopyFileA` (no `MoveFile*`, no
`SetCurrentDirectory`).
## How the mod works (`src/mods/userfolders.cpp`)
- Those eight functions are hooked (`RE_HOOK_API`). A path is rewritten when,
after an optional game-folder prefix and `.\`/`./`, its first component is
`save` (any case) or it is exactly `Settings.cfg`; every other path passes
unchanged. One choke point instead of 37 patched operands, and no long
absolute path in the game's fixed-size buffers.
- The Documents folder comes from `SHGetKnownFolderPath(FOLDERID_Documents)`
(follows OneDrive/redirected Documents), looked up on the first redirected
path: the hooks are installed under the loader lock, where shell calls must
not run. If it is unusable (lookup fails, or a character outside the ANSI
code page), the game folder stays in use.
- Migration: when `save\` or `config\` does not exist yet, the game folder's
save files / `Settings.cfg` are copied there once with the wide file
functions (not hooked). The originals stay in the game folder.
- `mods::userfolders::SaveDir()` gives sacredK's own files the same folder
(shared chest).
Not covered: `Config.exe` and `gameserver.exe` (`GameServer.cfg`) are
separate programs without the DLL and still use the game folder.