New mods/hud: while a HUD window renders, screen-space vertices passed to D3D7 DrawPrimitive/DrawIndexedPrimitive are shifted by dx; while it handles an event, the UI event point (category 5, +0x48) is shifted by -dx. Applied to cUI_Taskbar2 (centred) and cUI_Mercenary (portrait + health, right edge). 3D belt items line up without help (their projection is screen-centred). re::AttachRuntimeHook hooks functions only known at runtime (COM methods). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
81 lines
2.2 KiB
C++
81 lines
2.2 KiB
C++
#include "re/hook.h"
|
|
|
|
#include <vector>
|
|
|
|
#include <windows.h>
|
|
#include <detours.h>
|
|
|
|
#include "re/config.h"
|
|
#include "re/log.h"
|
|
|
|
namespace re {
|
|
namespace {
|
|
|
|
struct HookDef {
|
|
const char* name;
|
|
uint32_t address;
|
|
void** original;
|
|
void* replacement;
|
|
};
|
|
|
|
// Function-local static: registrations run during static initialisation, in
|
|
// unspecified order across translation units.
|
|
std::vector<HookDef>& Registry() {
|
|
static std::vector<HookDef> hooks;
|
|
return hooks;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
HookRegistration::HookRegistration(const char* name, uint32_t address, void** original, void* replacement) {
|
|
Registry().push_back({name, address, original, replacement});
|
|
}
|
|
|
|
int InstallHooks() {
|
|
int failed = 0;
|
|
int installed = 0;
|
|
for (const HookDef& hook : Registry()) {
|
|
if (!ConfigInt("hooks", hook.name, 1)) {
|
|
Log("hook %-24s 0x%08x disabled by config", hook.name, hook.address);
|
|
continue;
|
|
}
|
|
// One transaction per hook, so a bad hook does not take the others down.
|
|
DetourTransactionBegin();
|
|
DetourUpdateThread(GetCurrentThread());
|
|
LONG error = DetourAttach(hook.original, hook.replacement);
|
|
if (error == NO_ERROR) {
|
|
error = DetourTransactionCommit();
|
|
} else {
|
|
DetourTransactionAbort();
|
|
}
|
|
if (error == NO_ERROR) {
|
|
++installed;
|
|
} else {
|
|
++failed;
|
|
Log("hook %-24s 0x%08x FAILED (error %ld)", hook.name, hook.address, error);
|
|
}
|
|
}
|
|
Log("%d hook(s) installed, %d failed", installed, failed);
|
|
return failed;
|
|
}
|
|
|
|
bool AttachRuntimeHook(const char* name, void** original, void* replacement) {
|
|
const void* target = *original;
|
|
DetourTransactionBegin();
|
|
DetourUpdateThread(GetCurrentThread());
|
|
LONG error = DetourAttach(original, replacement);
|
|
if (error == NO_ERROR) {
|
|
error = DetourTransactionCommit();
|
|
} else {
|
|
DetourTransactionAbort();
|
|
}
|
|
if (error != NO_ERROR) {
|
|
Log("hook %-24s %p FAILED (error %ld)", name, target, error);
|
|
return false;
|
|
}
|
|
Log("hook %-24s %p attached at runtime", name, target);
|
|
return true;
|
|
}
|
|
|
|
} // namespace re
|