diff --git a/.gitignore b/.gitignore index 9c8a85d..828724f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,6 @@ /.idea/ /cmake-build-*/ *.rea-snapshot -sacred_re.ini +sacredK.ini /ghidra/ /screenshots/ diff --git a/.vscode/launch.json b/.vscode/launch.json index ae94e9c..cb4287f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,10 +3,10 @@ "configurations": [ { // Builds, then starts the game through the launcher (no debugger in the game). - "name": "Run Sacred (sacred_re)", + "name": "Run Sacred (sacredK)", "type": "cppvsdbg", "request": "launch", - "program": "${workspaceFolder}/build/x86-debug/sacred_re.exe", + "program": "${workspaceFolder}/build/x86-debug/sacredK.exe", "args": ["--game-dir", "D:\\Gaming\\Sacred Gold", "log"], "cwd": "${workspaceFolder}/build/x86-debug", "preLaunchTask": "CMake: build", @@ -14,7 +14,7 @@ }, { // Debug our DLL inside the game: set [debug] WaitForDebugger=1 in - // build//sacred_re.ini, start "Run Sacred", then run this and + // build//sacredK.ini, start "Run Sacred", then run this and // pick sacred.exe. The DLL waits (up to 60 s) before installing hooks. "name": "Attach to sacred.exe", "type": "cppvsdbg", diff --git a/CLAUDE.md b/CLAUDE.md index 2151147..9384a39 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,8 +6,8 @@ project, autotest) first; this file adds how we work and what we learned. ## What this is -`sacred_re.dll` is injected into the original **Sacred Gold 2.28** -`sacred.exe` (2006, 32-bit, MSVC 6) by the launcher `sacred_re.exe`. It +`sacredK.dll` is injected into the original **Sacred Gold 2.28** +`sacred.exe` (2006, 32-bit, MSVC 6) by the launcher `sacredK.exe`. It hooks and patches the running game: some functions are rewritten, most of the work so far is **mods** — behaviour changes on top of the original (widescreen, HUD layout, 7 weapon sets / art slots, key bindings, WASD, @@ -15,7 +15,7 @@ auto-attack, skill reworks, respec, map fixes, ...). The game stays playable at every step; the user plays it to test. - Target binary: the original `sacred.exe` in `D:\Gaming\Sacred Gold\` - (path in `build\x86-debug\sacred_re.ini`, `[paths] GameDir`). Ignore the + (path in `build\x86-debug\sacredK.ini`, `[paths] GameDir`). Ignore the `SacredReborn*` files in that folder. - Game texts are German (Fertigkeiten, Attribute, Blitzschlag, ...); keep the game's names when talking about features. @@ -65,12 +65,12 @@ at every step; the user plays it to test. ```powershell .\build.ps1 # x86-debug -> build\x86-debug\ -build\x86-debug\sacred_re.exe log # start the game with the DLL +build\x86-debug\sacredK.exe log # start the game with the DLL ``` New source files must be added to `CMakeLists.txt`. Output to check: -`build\x86-debug\sacred_re.log` (written anew each start; our lines plus the -game's own log). Crashes: `sacred_re_crash.txt` / `.dmp` next to the DLL +`build\x86-debug\sacredK.log` (written anew each start; our lines plus the +game's own log). Crashes: `sacredK_crash.txt` / `.dmp` next to the DLL (exception, module+offset, ebp chain); Windows also records the faulting offset in the Application event log (`Get-WinEvent`, provider "Application Error"). The debug build's run-time checks turn calling-convention mistakes diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c3bf76..478a98b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 3.24) -project(sacred_re LANGUAGES C CXX) +project(sacredK LANGUAGES C CXX) # sacred.exe is a 32-bit process; everything we inject into it must be 32-bit too. if(NOT CMAKE_SIZEOF_VOID_P EQUAL 4) - message(FATAL_ERROR "sacred_re must be built for 32-bit x86 (use the 'x86-*' presets / an x86 MSVC environment).") + message(FATAL_ERROR "sacredK must be built for 32-bit x86 (use the 'x86-*' presets / an x86 MSVC environment).") endif() if(NOT MSVC) - message(FATAL_ERROR "sacred_re requires MSVC (the game's C++ ABI is MSVC's).") + message(FATAL_ERROR "sacredK requires MSVC (the game's C++ ABI is MSVC's).") endif() set(CMAKE_CXX_STANDARD 20) @@ -19,17 +19,17 @@ add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX _CRT_SECURE_NO_WARNINGS) include(cmake/Detours.cmake) include(cmake/Json.cmake) -set(SACRED_RE_CXX_FLAGS /W4 /permissive- /utf-8) +set(SACREDK_CXX_FLAGS /W4 /permissive- /utf-8) -# --- sacred_re.dll: injected into sacred.exe, installs the hooks ------------- -add_library(sacred_re SHARED +# --- sacredK.dll: injected into sacred.exe, installs the hooks ------------- +add_library(sacredK SHARED src/re/dllmain.cpp src/re/hook.cpp src/re/log.cpp src/re/config.cpp src/re/patch.cpp src/re/crash.cpp - src/re/sacred_re.def + src/re/sacredK.def src/game/engine/log.cpp src/game/engine/cmdline.cpp src/game/engine/events.cpp @@ -70,13 +70,13 @@ add_library(sacred_re SHARED src/mods/charexport.cpp src/mods/options.cpp ) -target_include_directories(sacred_re PRIVATE src) -target_compile_options(sacred_re PRIVATE ${SACRED_RE_CXX_FLAGS}) -target_link_libraries(sacred_re PRIVATE detours nlohmann_json::nlohmann_json dbghelp) +target_include_directories(sacredK PRIVATE src) +target_compile_options(sacredK PRIVATE ${SACREDK_CXX_FLAGS}) +target_link_libraries(sacredK PRIVATE detours nlohmann_json::nlohmann_json dbghelp) -# --- sacred_re.exe: launches sacred.exe with sacred_re.dll injected ---------- -add_executable(sacred_re_launcher WIN32 src/launcher/main.cpp) -set_target_properties(sacred_re_launcher PROPERTIES OUTPUT_NAME sacred_re) -target_compile_options(sacred_re_launcher PRIVATE ${SACRED_RE_CXX_FLAGS}) -target_link_libraries(sacred_re_launcher PRIVATE detours) -add_dependencies(sacred_re_launcher sacred_re) +# --- sacredK.exe: launches sacred.exe with sacredK.dll injected ---------- +add_executable(sacredK_launcher WIN32 src/launcher/main.cpp) +set_target_properties(sacredK_launcher PROPERTIES OUTPUT_NAME sacredK) +target_compile_options(sacredK_launcher PRIVATE ${SACREDK_CXX_FLAGS}) +target_link_libraries(sacredK_launcher PRIVATE detours) +add_dependencies(sacredK_launcher sacredK) diff --git a/README.md b/README.md index 4b13448..3463a5a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# sacred_re +# sacredK An incremental reimplementation of **Sacred Gold 2.28** (`sacred.exe`, 2006). -`sacred_re.dll` is injected into the original game at startup and replaces game +`sacredK.dll` is injected into the original game at startup and replaces game functions with rewritten C++ one by one. Everything not yet rewritten keeps running as original machine code, so the game stays playable at every step and each rewrite can be tested in-game immediately. Once enough is rewritten, the @@ -42,14 +42,14 @@ the CMake presets. ## Running ```powershell -build\x86-debug\sacred_re.exe --game-dir "D:\Gaming\Sacred Gold" # first run; remembered in sacred_re.ini -build\x86-debug\sacred_re.exe log # later runs; extra args go to the game +build\x86-debug\sacredK.exe --game-dir "D:\Gaming\Sacred Gold" # first run; remembered in sacredK.ini +build\x86-debug\sacredK.exe log # later runs; extra args go to the game ``` -`sacred_re.log` (next to the DLL) records what was hooked plus every message the +`sacredK.log` (next to the DLL) records what was hooked plus every message the game sends to its internal logger, even when the game's own logging is off. -Hooks can be switched off individually in `sacred_re.ini` (next to the DLL) +Hooks can be switched off individually in `sacredK.ini` (next to the DLL) to compare a rewrite against the original: ```ini @@ -61,7 +61,7 @@ CmdLineHasFlag=0 ``` src/re/ hook framework, injection-side startup, logging, config -src/launcher/ sacred_re.exe — starts sacred.exe with the DLL injected +src/launcher/ sacredK.exe — starts sacred.exe with the DLL injected src/game/ rewritten game code and original-layout structs, by subsystem src/mods/ behaviour changes on top of the original (e.g. borderless.cpp) docs/ reverse-engineering notes; function-map.md tracks progress diff --git a/docs/options.md b/docs/options.md index c9d0b1b..b14a82f 100644 --- a/docs/options.md +++ b/docs/options.md @@ -3,7 +3,7 @@ Request (2026-10-18): the settings screen gets three tabs: *Allgemein*, *Beute* (loot filter; first iteration: the game's loot options moved there from the common page) and *Tastenbelegung* (key bindings, so far only -settable in `sacred_re.ini`). Code: `src/mods/options.cpp`; bindings in +settable in `sacredK.ini`). Code: `src/mods/options.cpp`; bindings in `src/mods/input.cpp`. ## The window (cUI_Options) @@ -42,7 +42,7 @@ settable in `sacred_re.ini`). Code: `src/mods/options.cpp`; bindings in a box captures the next key press (`input::SetKeyCapture`, swallowed before the game sees it): Esc cancels, Backspace unbinds, a bindable key is taken (and removed from any other action). The page works on a copy loaded when - the window opens; OK (`0x717460`) saves it to `[keys]` in `sacred_re.ini`, + the window opens; OK (`0x717460`) saves it to `[keys]` in `sacredK.ini`, Cancel drops it. - Movement keys (W/A/S/D) are bindings now (`MoveUp/Left/Down/Right`); `mods/wasd.cpp` polls the bound keys. diff --git a/docs/shared-chest.md b/docs/shared-chest.md index 1c812b2..6085f6f 100644 --- a/docs/shared-chest.md +++ b/docs/shared-chest.md @@ -55,7 +55,7 @@ was empty after loading another character (in-game saves don't call saveHero). the chest drew at the wrong spot after some loads. Both tabs' grids are put back to the constructor's values every tick and on each tab switch. - `MoveItem` from/to 0x11 while the shared tab is open moves from/to it. -- File: `{"format": "sacred_re.shared_chest", "version": 1, "items": [{cell, +- File: `{"format": "sacredK.shared_chest", "version": 1, "items": [{cell, w, h, type, data (hex of vf1c), count}]}`; written after each successful `saveHero` and after each save-game write (in-game saves don't call saveHero; via a temp file), read on the first engine tick with a hero after a session diff --git a/docs/todo.md b/docs/todo.md index 529e128..c761eed 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -93,7 +93,7 @@ mouse/keyboard like `tools/autotest-load.ps1`: 2. play scripted input through the existing hooks (keys, casting arts, weapon set switches, save + reload); 3. take back-buffer screenshots at checkpoints and log checks to - `sacred_re.log` (aura effect present after reload, slot 6-7 inventories + `sacredK.log` (aura effect present after reload, slot 6-7 inventories survive a save, ...); 4. exit the game. @@ -116,7 +116,7 @@ W, A and S were game hotkeys. With WASD movement (`src/mods/wasd.cpp`) their actions moved to other keys for now; choose final bindings (and update the in-game texts/tooltips that name the old keys): -| Key | Action | Temporary key (sacred_re.ini) | +| Key | Action | Temporary key (sacredK.ini) | |---|---|---| | W | potion kind 3 (`cEngine::UseActionSlot`, like Q/E/R/B/Space) | game potion keys switched off; `[keys] Potion1-5` (docs/options.md) | | A | pick up items nearby (creature event 0x113) | Q (`[keys] PickUp`, 2026-10-17; was V) | diff --git a/src/game/engine/log.cpp b/src/game/engine/log.cpp index 23192bc..17e818a 100644 --- a/src/game/engine/log.cpp +++ b/src/game/engine/log.cpp @@ -7,7 +7,7 @@ // optional callback (0x017e5ee4) and to either OutputDebugString or the // in-game console object (0x017e5edc). // -// Status: hooked, not rewritten. Every message is mirrored into sacred_re.log +// Status: hooked, not rewritten. Every message is mirrored into sacredK.log // whether or not the game's own logging is enabled, then forwarded. #include "game/engine/log.h" diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index d026249..1b4c2b4 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -1,11 +1,11 @@ -// sacred_re.exe: starts sacred.exe with sacred_re.dll injected. +// sacredK.exe: starts sacred.exe with sacredK.dll injected. // -// sacred_re.exe [--game-dir ] [game arguments...] +// sacredK.exe [--game-dir ] [game arguments...] // // The game directory comes from --game-dir (which is then remembered in -// sacred_re.ini), else from [paths] GameDir in sacred_re.ini, else the +// sacredK.ini), else from [paths] GameDir in sacredK.ini, else the // launcher's own directory. Remaining arguments are passed to the game -// unchanged, e.g. `sacred_re.exe log` enables the game's DEBUG.LOG. +// unchanged, e.g. `sacredK.exe log` enables the game's DEBUG.LOG. #include @@ -35,7 +35,7 @@ std::wstring WithTrailingSlash(std::wstring dir) { } int Fail(const std::wstring& message) { - MessageBoxW(nullptr, message.c_str(), L"sacred_re", MB_OK | MB_ICONERROR); + MessageBoxW(nullptr, message.c_str(), L"sacredK", MB_OK | MB_ICONERROR); return 1; } @@ -43,7 +43,7 @@ int Fail(const std::wstring& message) { int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) { const std::wstring launcherDir = ExeDir(); - const std::wstring ini = launcherDir + L"sacred_re.ini"; + const std::wstring ini = launcherDir + L"sacredK.ini"; int argc = 0; wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc); @@ -71,12 +71,12 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) { const std::wstring gameExe = gameDir + L"sacred.exe"; if (!FileExists(gameExe)) { return Fail(L"sacred.exe not found in\n" + gameDir + - L"\n\nRun once with: sacred_re.exe --game-dir \"\""); + L"\n\nRun once with: sacredK.exe --game-dir \"\""); } - const std::wstring dllPath = launcherDir + L"sacred_re.dll"; + const std::wstring dllPath = launcherDir + L"sacredK.dll"; if (!FileExists(dllPath)) { - return Fail(L"sacred_re.dll not found next to the launcher:\n" + dllPath); + return Fail(L"sacredK.dll not found next to the launcher:\n" + dllPath); } // Detours takes the DLL path as ANSI. char dllPathA[MAX_PATH]; diff --git a/src/mods/borderless.cpp b/src/mods/borderless.cpp index 9eade17..954cc96 100644 --- a/src/mods/borderless.cpp +++ b/src/mods/borderless.cpp @@ -9,7 +9,7 @@ // Mouse positions are mapped back from that rectangle to game pixels, both in // GetMouseClientPos (polled by the game) and in mouse window messages. // -// sacred_re.ini: +// sacredK.ini: // [borderless] // Enabled=1 ; 0 = original behaviour // IntegerScale=0 ; 1 = scale by whole multiples only (sharper, larger bars) diff --git a/src/mods/guards.cpp b/src/mods/guards.cpp index 0357dd8..93f341e 100644 --- a/src/mods/guards.cpp +++ b/src/mods/guards.cpp @@ -11,7 +11,7 @@ namespace game { // cParticleSystem_burningBone::Render (vf04 0x774e10, vtable 0x895b84): // crashed reading the device it was given, which was null (2026-10-16, Esc // pressed while walking; Windows reported sacred.exe+0x374e39). Who renders -// it without a device is not known yet (sacred_re_crash.txt will tell). With +// it without a device is not known yet (sacredK_crash.txt will tell). With // no device there is nothing to draw. // (device, a 4x4 matrix by value; ret 0x44). struct Matrix4 { diff --git a/src/mods/hud.cpp b/src/mods/hud.cpp index 791146b..5b0a1e7 100644 --- a/src/mods/hud.cpp +++ b/src/mods/hud.cpp @@ -16,7 +16,7 @@ // inside both. // The world never sees these offsets: they are only active inside the hooks. // -// sacred_re.ini: +// sacredK.ini: // [hud] // Enabled=1 diff --git a/src/mods/input.cpp b/src/mods/input.cpp index 1b1ffe2..4e71479 100644 --- a/src/mods/input.cpp +++ b/src/mods/input.cpp @@ -16,7 +16,7 @@ // off. Alt+key arrives as WM_SYSKEYDOWN and is not handled here anyway.) // // The bindings are set on the options window's key bindings tab -// (mods/options.cpp) and kept in sacred_re.ini (key names: kKeyNames below, +// (mods/options.cpp) and kept in sacredK.ini (key names: kKeyNames below, // None): // [keys] // SkillSlot0=0 ... SkillSlot6=6 ; cast combat-art slot (0 = right mouse button art) diff --git a/src/mods/input.h b/src/mods/input.h index 89c2d38..8cd11fd 100644 --- a/src/mods/input.h +++ b/src/mods/input.h @@ -33,7 +33,7 @@ const wchar_t* BindingGroup(int index); int BindingKey(int index); // virtual key, 0 = none int DefaultBindingKey(int index); -// Sets all bindings (`keys[BindingCount()]`) and writes them to sacred_re.ini. +// Sets all bindings (`keys[BindingCount()]`) and writes them to sacredK.ini. void SetBindingKeys(const int* keys); // Whether `vk` can be bound, and its name as shown ("Leertaste", "F1", ...). diff --git a/src/mods/inventory_save.cpp b/src/mods/inventory_save.cpp index 3f65652..4b91df0 100644 --- a/src/mods/inventory_save.cpp +++ b/src/mods/inventory_save.cpp @@ -193,7 +193,7 @@ void PutArtSlot(const json& variants, uint8_t* slot) { json ToJson(const std::vector& block, const uint8_t* shadow) { Reader r(block); json j; - j["format"] = "sacred_re.inventory"; + j["format"] = "sacredK.inventory"; j["version"] = kVersion; j["player"] = r.U16(); j["flags"] = r.U16(); @@ -262,7 +262,9 @@ json ToJson(const std::vector& block, const uint8_t* shadow) { // The original block for slots 1-5; slots 6-7 are applied afterwards. std::vector ToBlock(const json& j) { - if (j.at("format") != "sacred_re.inventory" || j.at("version").get() > kVersion) { + // "sacred_re.inventory": saves from before the project was renamed to sacredK. + const auto format = j.at("format").get(); + if ((format != "sacredK.inventory" && format != "sacred_re.inventory") || j.at("version").get() > kVersion) { throw std::runtime_error("unknown inventory format / version"); } Writer w; diff --git a/src/mods/options.cpp b/src/mods/options.cpp index 4d5f899..3cc9aeb 100644 --- a/src/mods/options.cpp +++ b/src/mods/options.cpp @@ -1,7 +1,7 @@ // Options window in three tabs: Allgemein, Beute, Tastenbelegung (request of // 2026-10-18). Beute holds the game's auto-pickup settings (first iteration: // moved there from the common page); Tastenbelegung sets the key bindings of -// mods/input.cpp, which had only been settable in sacred_re.ini. +// mods/input.cpp, which had only been settable in sacredK.ini. // // The window (cUI_Options, vtable 0x89505c, constructor 0x716570 building its // controls in 0x7184e0) is laid out for 1024x768: six frames in two columns diff --git a/src/mods/sharedchest.cpp b/src/mods/sharedchest.cpp index fd0b291..9ae8fe3 100644 --- a/src/mods/sharedchest.cpp +++ b/src/mods/sharedchest.cpp @@ -334,7 +334,7 @@ void Save() { } } } - const json j = {{"format", "sacred_re.shared_chest"}, {"version", kFileVersion}, {"items", items}}; + const json j = {{"format", "sacredK.shared_chest"}, {"version", kFileVersion}, {"items", items}}; const std::string path = FilePath(); const std::string temp = path + ".tmp"; { diff --git a/src/mods/widescreen.cpp b/src/mods/widescreen.cpp index 2bd92d9..e38a6f5 100644 --- a/src/mods/widescreen.cpp +++ b/src/mods/widescreen.cpp @@ -8,7 +8,7 @@ // 1024x768 layout, and set the variables from the render size. // See docs/widescreen.md. // -// sacred_re.ini: +// sacredK.ini: // [widescreen] // Enabled=1 // Height=768 ; world pixels visible vertically (768 = original look); diff --git a/src/re/config.h b/src/re/config.h index 71a887f..644994a 100644 --- a/src/re/config.h +++ b/src/re/config.h @@ -1,5 +1,5 @@ #pragma once -// sacred_re.ini next to sacred_re.dll / sacred_re.exe. +// sacredK.ini next to sacredK.dll / sacredK.exe. #include @@ -7,7 +7,7 @@ namespace re { void SetConfigPath(const std::wstring& path); const std::wstring& ConfigPath(); -// Folder of sacred_re.dll (with trailing separator), derived from the config path. +// Folder of sacredK.dll (with trailing separator), derived from the config path. std::wstring ModuleDirectory(); int ConfigInt(const char* section, const char* key, int fallback); std::string ConfigString(const char* section, const char* key, const char* fallback); diff --git a/src/re/crash.cpp b/src/re/crash.cpp index 725e182..fd6d60e 100644 --- a/src/re/crash.cpp +++ b/src/re/crash.cpp @@ -1,10 +1,10 @@ -// Crash report: on an unhandled exception, writes sacred_re_crash.txt (code, +// Crash report: on an unhandled exception, writes sacredK_crash.txt (code, // address as module + offset, registers, return addresses found on the stack) -// and sacred_re_crash.dmp next to the DLL. The game may install its own +// and sacredK_crash.dmp next to the DLL. The game may install its own // filter later; SetUnhandledExceptionFilter is hooked so ours stays first and // passes the crash on to the game's afterwards. // -// Hangs: a watchdog thread writes sacred_re_hang.dmp (all threads) when the +// Hangs: a watchdog thread writes sacredK_hang.dmp (all threads) when the // engine tick (re::EngineHeartbeat) has stopped for kHangMs while the game // window is in front; once per hang. The game freezing on F2 while walking // (2026-10-18) left no report. @@ -52,7 +52,7 @@ bool IsCode(uintptr_t address) { } void WriteReport(EXCEPTION_POINTERS* info) { - FILE* file = _wfopen((g_dir + L"sacred_re_crash.txt").c_str(), L"w"); + FILE* file = _wfopen((g_dir + L"sacredK_crash.txt").c_str(), L"w"); if (!file) { return; } @@ -100,7 +100,7 @@ void WriteReport(EXCEPTION_POINTERS* info) { } fclose(file); - HANDLE dump = CreateFileW((g_dir + L"sacred_re_crash.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, + HANDLE dump = CreateFileW((g_dir + L"sacredK_crash.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (dump != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION exception = {GetCurrentThreadId(), info, FALSE}; @@ -120,7 +120,7 @@ bool GameInFront() { } void WriteHangDump() { - HANDLE dump = CreateFileW((g_dir + L"sacred_re_hang.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, + HANDLE dump = CreateFileW((g_dir + L"sacredK_hang.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (dump != INVALID_HANDLE_VALUE) { MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dump, @@ -142,7 +142,7 @@ DWORD WINAPI Watchdog(void*) { } if (!reported && GameInFront()) { reported = true; - Log("hang: no engine tick for %lu ms, writing sacred_re_hang.dmp", GetTickCount() - beat); + Log("hang: no engine tick for %lu ms, writing sacredK_hang.dmp", GetTickCount() - beat); WriteHangDump(); Log("hang: dump written"); } diff --git a/src/re/crash.h b/src/re/crash.h index 9585b04..a717d5f 100644 --- a/src/re/crash.h +++ b/src/re/crash.h @@ -4,8 +4,8 @@ namespace re { -// Writes sacred_re_crash.txt / .dmp into `dir` when the game crashes, and -// sacred_re_hang.dmp when the engine stops ticking (see EngineHeartbeat). +// Writes sacredK_crash.txt / .dmp into `dir` when the game crashes, and +// sacredK_hang.dmp when the engine stops ticking (see EngineHeartbeat). void InstallCrashHandler(const std::wstring& dir); // The engine ticked (running), or the game ended (not running). diff --git a/src/re/dllmain.cpp b/src/re/dllmain.cpp index 3bf8f08..af3660d 100644 --- a/src/re/dllmain.cpp +++ b/src/re/dllmain.cpp @@ -1,4 +1,4 @@ -// sacred_re.dll entry point. Loaded into sacred.exe by the launcher before the +// sacredK.dll entry point. Loaded into sacred.exe by the launcher before the // game's own entry point runs, so every hook is in place from the first // instruction of game code. @@ -40,17 +40,17 @@ bool IsSupportedGameBuild() { void Startup(HMODULE module) { std::wstring dir = ModuleDir(module); - re::OpenLog((dir + L"sacred_re.log").c_str()); - re::SetConfigPath(dir + L"sacred_re.ini"); - re::Log("sacred_re loaded"); + re::OpenLog((dir + L"sacredK.log").c_str()); + re::SetConfigPath(dir + L"sacredK.ini"); + re::Log("sacredK loaded"); re::InstallCrashHandler(dir); if (!IsSupportedGameBuild()) { re::Log("unsupported sacred.exe build, no hooks installed"); MessageBoxW(nullptr, L"This sacred.exe is not the supported Sacred Gold 2.28 build.\n" - L"sacred_re will not patch it; the game runs unmodified.", - L"sacred_re", MB_OK | MB_ICONWARNING); + L"sacredK will not patch it; the game runs unmodified.", + L"sacredK", MB_OK | MB_ICONWARNING); return; } if (re::ConfigInt("debug", "WaitForDebugger", 0)) { diff --git a/src/re/hook.h b/src/re/hook.h index b944c97..4a4e3f5 100644 --- a/src/re/hook.h +++ b/src/re/hook.h @@ -13,7 +13,7 @@ // // The signature, including the calling convention, must match the original // exactly (`__cdecl`, `__stdcall`, `__thiscall` / `__fastcall` stand-in, ...). -// Hooks can be disabled individually at runtime in sacred_re.ini: +// Hooks can be disabled individually at runtime in sacredK.ini: // // [hooks] // Log=0 @@ -40,7 +40,7 @@ bool AttachRuntimeHook(const char* name, void** original, void* replacement); // Hooks a Windows API function for the whole process (game and DLLs alike). // `replacement` must have the API's exact signature; defines -// `replacement##_original`. Disabled in sacred_re.ini under the API's name. +// `replacement##_original`. Disabled in sacredK.ini under the API's name. #define RE_HOOK_API(api, replacement) \ static decltype(&replacement) replacement##_original = &api; \ static ::re::HookRegistration replacement##_registration( \ diff --git a/src/re/log.h b/src/re/log.h index 4fbc7b2..d3ec9f3 100644 --- a/src/re/log.h +++ b/src/re/log.h @@ -1,5 +1,5 @@ #pragma once -// sacred_re's own log: sacred_re.log next to sacred_re.dll, plus OutputDebugString. +// sacredK's own log: sacredK.log next to sacredK.dll, plus OutputDebugString. namespace re { diff --git a/src/re/sacred_re.def b/src/re/sacredK.def similarity index 88% rename from src/re/sacred_re.def rename to src/re/sacredK.def index a9c1b62..c8aeb4c 100644 --- a/src/re/sacred_re.def +++ b/src/re/sacredK.def @@ -1,4 +1,4 @@ -LIBRARY sacred_re +LIBRARY sacredK EXPORTS ; Detours requires ordinal 1 on any DLL injected via DetourCreateProcessWithDll. DetourFinishHelperProcess @1 NONAME diff --git a/tools/README.md b/tools/README.md index 45c6997..eae5718 100644 --- a/tools/README.md +++ b/tools/README.md @@ -30,7 +30,7 @@ $env:GHIDRA_HEADLESS_MAXMEM = "8G" `autotest-load.ps1` starts the game through the launcher, clicks "Spiel laden" -> "Laden" -> "Ok" (first save game), takes screenshots in-game and with the ESC menu open, and stops the game. `-Ini` appends temporary -settings to `build\x86-debug\sacred_re.ini` (restored afterwards), e.g. +settings to `build\x86-debug\sacredK.ini` (restored afterwards), e.g. ```powershell .\tools\autotest-load.ps1 -Name ws_off -Ini "[widescreen]`r`nEnabled=0" diff --git a/tools/autotest-load.ps1 b/tools/autotest-load.ps1 index 9e8427f..9143fd8 100644 --- a/tools/autotest-load.ps1 +++ b/tools/autotest-load.ps1 @@ -2,10 +2,10 @@ # the list, 1 = the first, selected by default), take # screenshots in-game and with the ESC menu open, then stop the game. # -# .\tools\autotest-load.ps1 -Name ws_on # current sacred_re.ini +# .\tools\autotest-load.ps1 -Name ws_on # current sacredK.ini # .\tools\autotest-load.ps1 -Name ws_off -Ini "[widescreen]`r`nEnabled=0" # -# -Ini temporarily appends settings to build\x86-debug\sacred_re.ini. +# -Ini temporarily appends settings to build\x86-debug\sacredK.ini. # Click positions are for the classic (menu) layout scaled onto a 3440x1440 # monitor; adjust for other monitors. Don't touch mouse/keyboard while it runs. param( @@ -21,7 +21,7 @@ $ErrorActionPreference = "Stop" . (Join-Path $PSScriptRoot "game-input.ps1") $root = Split-Path $PSScriptRoot -$iniPath = Join-Path $root "build\x86-debug\sacred_re.ini" +$iniPath = Join-Path $root "build\x86-debug\sacredK.ini" $iniBackup = if (Test-Path $iniPath) { Get-Content $iniPath -Raw } else { "" } if ($Ini) { Set-Content $iniPath ($iniBackup + "`r`n" + $Ini + "`r`n") -Encoding ASCII } diff --git a/tools/game-input.ps1 b/tools/game-input.ps1 index 4dac3ff..ee514eb 100644 --- a/tools/game-input.ps1 +++ b/tools/game-input.ps1 @@ -31,9 +31,9 @@ function Focus-Sacred($Game) { [SacredRe.Input]::SetForegroundWindow($Game.MainWindowHandle) } -$script:LogPath = Join-Path $script:Root "build\x86-debug\sacred_re.log" +$script:LogPath = Join-Path $script:Root "build\x86-debug\sacredK.log" -# Waits until sacred_re.log (written anew at every start) has at least $Count +# Waits until sacredK.log (written anew at every start) has at least $Count # lines containing $Pattern, focusing the game meanwhile; then waits $AfterMs. function Wait-Log([string]$Pattern, [int]$Count = 1, [int]$TimeoutSeconds = 60, [int]$AfterMs = 500, $Game = $null) { $deadline = (Get-Date).AddSeconds($TimeoutSeconds) @@ -46,7 +46,7 @@ function Wait-Log([string]$Pattern, [int]$Count = 1, [int]$TimeoutSeconds = 60, if ($found -ge $Count) { Start-Sleep -Milliseconds $AfterMs; return } Start-Sleep -Milliseconds 200 } - throw "timeout waiting for '$Pattern' in sacred_re.log" + throw "timeout waiting for '$Pattern' in sacredK.log" } # Starts the game and returns once its main menu is up (the UI manager @@ -54,7 +54,7 @@ function Wait-Log([string]$Pattern, [int]$Count = 1, [int]$TimeoutSeconds = 60, function Start-Sacred([string]$Arguments = "log") { if (Get-Process sacred -ErrorAction SilentlyContinue) { throw "sacred.exe is already running" } if (Test-Path $script:LogPath) { Remove-Item $script:LogPath -ErrorAction SilentlyContinue } - $null = Start-Process (Join-Path $script:Root "build\x86-debug\sacred_re.exe") -ArgumentList $Arguments + $null = Start-Process (Join-Path $script:Root "build\x86-debug\sacredK.exe") -ArgumentList $Arguments $game = $null for ($i = 0; $i -lt 80 -and -not $game; $i++) { Start-Sleep -Milliseconds 250 diff --git a/tools/ghidra/ApplyRtti.java b/tools/ghidra/ApplyRtti.java index f05fb8e..e4f0b2c 100644 --- a/tools/ghidra/ApplyRtti.java +++ b/tools/ghidra/ApplyRtti.java @@ -6,7 +6,7 @@ // // Ghidra's own RecoverClassesFromRTTIScript finds nothing in this binary. // Run once, headless, without -readOnly (see tools/README.md). -// @category sacred_re +// @category sacredK import java.util.ArrayList; import java.util.HashMap; diff --git a/tools/ghidra/Decompile.java b/tools/ghidra/Decompile.java index cd6e31c..24a84d7 100644 --- a/tools/ghidra/Decompile.java +++ b/tools/ghidra/Decompile.java @@ -6,7 +6,7 @@ // // Addresses without a function (e.g. methods only reachable via a vtable) get // one created first; run without -readOnly to keep those in the project. -// @category sacred_re +// @category sacredK import java.io.File; import java.io.PrintWriter; diff --git a/tools/ghidra/Rename.java b/tools/ghidra/Rename.java index f10bdc2..4843444 100644 --- a/tools/ghidra/Rename.java +++ b/tools/ghidra/Rename.java @@ -9,7 +9,7 @@ // into a class namespace; "#" starts a comment. Functions are created where // none starts at the address yet. Names starting with "g_" label data // (globals, tables) instead of functions. -// @category sacred_re +// @category sacredK import java.nio.charset.StandardCharsets; import java.nio.file.Files; diff --git a/tools/package-lock.json b/tools/package-lock.json index e4ad02b..5b44cda 100644 --- a/tools/package-lock.json +++ b/tools/package-lock.json @@ -1,10 +1,10 @@ { - "name": "sacred-re-tools", + "name": "sacredk-tools", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "sacred-re-tools", + "name": "sacredk-tools", "dependencies": { "iced-x86": "1.21.0" } diff --git a/tools/package.json b/tools/package.json index ab14351..e6926d5 100644 --- a/tools/package.json +++ b/tools/package.json @@ -1,5 +1,5 @@ { - "name": "sacred-re-tools", + "name": "sacredk-tools", "private": true, "type": "module", "dependencies": {