Initial sacred_re scaffold with borderless fullscreen mod
- Launcher (sacred_re.exe) starts sacred.exe with sacred_re.dll injected via Detours; the DLL verifies the Sacred Gold 2.28 build before hooking. - Hook framework: RE_HOOK for game addresses, RE_HOOK_API for Windows APIs, per-hook enable/disable in sacred_re.ini, sacred_re.log. - Game code: Log (0x66f1c0) hooked, CmdLineHasFlag (0x813140) rewritten. - Borderless mod: forces windowed mode, covers the monitor, scales the 1024x768 image aspect-correct, remaps mouse input, keeps running in the background with keyboard input hidden while unfocused. - CMake/Ninja/MSVC x86 build, VS Code setup, disasm tool, function map. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
d9f5c85430
31 files changed
+1184
No files matched your search
@@ -0,0 +1,75 @@
|
||||
// sacred_re.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/hook.h"
|
||||
#include "re/log.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"sacred_re.log").c_str());
|
||||
re::SetConfigPath(dir + L"sacred_re.ini");
|
||||
re::Log("sacred_re loaded");
|
||||
|
||||
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);
|
||||
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();
|
||||
}
|
||||
|
||||
} // 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;
|
||||
}
|
||||
Reference in new issue
Block a user