Rename project to sacredK

sacred_re.dll/.exe/.ini/.log/_crash files are now sacredK.*; inventory saves
with the old "sacred_re.inventory" format id still load.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-19 22:07:14 +02:00
1 parent 462ebf8c0b
commit 70673dc301
34 files changed
+95 -93

No files matched your search

+1 -1
View File
@@ -3,6 +3,6 @@
/.idea/
/cmake-build-*/
*.rea-snapshot
sacred_re.ini
sacredK.ini
/ghidra/
/screenshots/
+3 -3
View File
@@ -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/<preset>/sacred_re.ini, start "Run Sacred", then run this and
// build/<preset>/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",
+6 -6
View File
@@ -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
+16 -16
View File
@@ -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)
+7 -7
View File
@@ -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
+2 -2
View File
@@ -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.
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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) |
+1 -1
View File
@@ -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"
+9 -9
View File
@@ -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 <dir>] [game arguments...]
// sacredK.exe [--game-dir <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 <string>
@@ -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 \"<Sacred Gold folder>\"");
L"\n\nRun once with: sacredK.exe --game-dir \"<Sacred Gold folder>\"");
}
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];
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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 {
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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", ...).
+4 -2
View File
@@ -193,7 +193,7 @@ void PutArtSlot(const json& variants, uint8_t* slot) {
json ToJson(const std::vector<uint8_t>& 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<uint8_t>& block, const uint8_t* shadow) {
// The original block for slots 1-5; slots 6-7 are applied afterwards.
std::vector<uint8_t> ToBlock(const json& j) {
if (j.at("format") != "sacred_re.inventory" || j.at("version").get<int>() > kVersion) {
// "sacred_re.inventory": saves from before the project was renamed to sacredK.
const auto format = j.at("format").get<std::string>();
if ((format != "sacredK.inventory" && format != "sacred_re.inventory") || j.at("version").get<int>() > kVersion) {
throw std::runtime_error("unknown inventory format / version");
}
Writer w;
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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";
{
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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 <string>
@@ -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);
+7 -7
View File
@@ -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");
}
+2 -2
View File
@@ -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).
+6 -6
View File
@@ -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)) {
+2 -2
View File
@@ -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( \
+1 -1
View File
@@ -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 {
+1 -1
View File
@@ -1,4 +1,4 @@
LIBRARY sacred_re
LIBRARY sacredK
EXPORTS
; Detours requires ordinal 1 on any DLL injected via DetourCreateProcessWithDll.
DetourFinishHelperProcess @1 NONAME
+1 -1
View File
@@ -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"
+3 -3
View File
@@ -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 }
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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"
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "sacred-re-tools",
"name": "sacredk-tools",
"private": true,
"type": "module",
"dependencies": {