Files
sacred_k/src/re/dllmain.cpp
T
khallaandClaude Opus 5.5 70673dc301 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>
2026-10-19 22:07:14 +02:00

80 lines
2.6 KiB
C++

// 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.
#include <string>
#include <windows.h>
#include <detours.h>
#include "re/config.h"
#include "re/crash.h"
#include "re/hook.h"
#include "re/log.h"
#include "re/patch.h"
namespace {
// The only build we support: Sacred Gold 2.28, sacred.exe
// sha256 fe774c6f985b02c9ce03103c2e55e5d853258c0cc3c737ccd211219c74460cb9.
// Every hook address in this project is specific to it.
constexpr DWORD kExpectedTimestamp = 0x451BBE74;
constexpr DWORD kExpectedSizeOfImage = 0x01999000;
std::wstring ModuleDir(HMODULE module) {
wchar_t path[MAX_PATH];
DWORD length = GetModuleFileNameW(module, path, MAX_PATH);
std::wstring dir(path, length);
return dir.substr(0, dir.find_last_of(L"\\/") + 1);
}
bool IsSupportedGameBuild() {
auto base = reinterpret_cast<const BYTE*>(GetModuleHandleW(nullptr));
auto dos = reinterpret_cast<const IMAGE_DOS_HEADER*>(base);
auto nt = reinterpret_cast<const IMAGE_NT_HEADERS32*>(base + dos->e_lfanew);
re::Log("game image: timestamp 0x%08lx, size 0x%08lx", nt->FileHeader.TimeDateStamp,
nt->OptionalHeader.SizeOfImage);
return nt->FileHeader.TimeDateStamp == kExpectedTimestamp &&
nt->OptionalHeader.SizeOfImage == kExpectedSizeOfImage;
}
void Startup(HMODULE module) {
std::wstring dir = ModuleDir(module);
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"sacredK will not patch it; the game runs unmodified.",
L"sacredK", MB_OK | MB_ICONWARNING);
return;
}
if (re::ConfigInt("debug", "WaitForDebugger", 0)) {
re::Log("waiting up to 60 s for a debugger to attach");
for (int i = 0; i < 600 && !IsDebuggerPresent(); ++i) {
Sleep(100);
}
re::Log(IsDebuggerPresent() ? "debugger attached" : "no debugger, continuing");
}
re::InstallHooks();
re::RunStartupFunctions();
}
} // namespace
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID) {
if (DetourIsHelperProcess()) {
return TRUE;
}
if (reason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(module);
DetourRestoreAfterWith();
Startup(module);
}
return TRUE;
}