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
@@ -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