Compare commits
No commits in common. "7a6d154d3e74bd4d6b7db6a69d6babd70361432d" and "d263cf9e84d8ab861f975b365aec525705bd5a35" have entirely different histories.
7a6d154d3e
...
d263cf9e84
@ -9,4 +9,3 @@ AttachLightHitEffectCrashFix = true
|
|||||||
AutoScaleHeroMenu = true
|
AutoScaleHeroMenu = true
|
||||||
WarnFormTypeCollisions = true
|
WarnFormTypeCollisions = true
|
||||||
GogVramLeakFix = true
|
GogVramLeakFix = true
|
||||||
ExperimentalCrashFixes = false
|
|
||||||
|
|||||||
@ -1,85 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Fix crash in MovementAgentPathFollowerVirtual when [RDI+0x48] is NULL
|
|
||||||
// Crash occurs when MOVSS tries to read from [RAX+0x8C] with RAX=NULL
|
|
||||||
// Address Library ID: 92556 (MovementAgentPathFollowerVirtual::sub_1115090)
|
|
||||||
//
|
|
||||||
// Original crash flow:
|
|
||||||
// MOV RAX, [RDI+0x48] ; RAX can be NULL
|
|
||||||
// LEA RDX, [RAX+0x58]
|
|
||||||
// MOVSS XMM2, [RAX+0x8C] ; CRASH if RAX is NULL
|
|
||||||
//
|
|
||||||
// Fix: Add null check after loading RAX, skip to safe exit if NULL
|
|
||||||
namespace MovementPathFollowerCrashFix
|
|
||||||
{
|
|
||||||
// Address Library ID for MovementAgentPathFollowerVirtual::sub_1115090
|
|
||||||
constexpr REL::RelocationID FuncID(92556, 92556);
|
|
||||||
|
|
||||||
// Offsets from function start to hook point (MOV RAX, [RDI+0x48])
|
|
||||||
// SE: 0x428, AE: 0x41F, VR: 0x428
|
|
||||||
constexpr REL::VariantOffset HookOffset(0x428, 0x41F, 0x428);
|
|
||||||
|
|
||||||
// Offsets from function start to skip point (safe exit label)
|
|
||||||
// SE: 0x518, AE: 0x50F, VR: 0x518
|
|
||||||
constexpr REL::VariantOffset SkipOffset(0x518, 0x50F, 0x518);
|
|
||||||
|
|
||||||
// Hook size: MOV (4 bytes) + LEA (4 bytes) = 8 bytes
|
|
||||||
constexpr std::size_t HookSize = 8;
|
|
||||||
|
|
||||||
inline void Install()
|
|
||||||
{
|
|
||||||
const REL::Relocation<std::uintptr_t> funcBase{ FuncID };
|
|
||||||
const std::uintptr_t hookAddr = funcBase.address() + HookOffset.offset();
|
|
||||||
const std::uintptr_t skipAddr = funcBase.address() + SkipOffset.offset();
|
|
||||||
const std::uintptr_t returnAddr = hookAddr + HookSize;
|
|
||||||
|
|
||||||
// Generate the patch code using xbyak
|
|
||||||
struct PatchCode : Xbyak::CodeGenerator
|
|
||||||
{
|
|
||||||
PatchCode(std::uintptr_t a_skipAddr, std::uintptr_t a_returnAddr)
|
|
||||||
{
|
|
||||||
// Original: MOV RAX, [RDI+0x48]
|
|
||||||
mov(rax, qword[rdi + 0x48]);
|
|
||||||
|
|
||||||
// Add null check
|
|
||||||
test(rax, rax);
|
|
||||||
jz("skip_label");
|
|
||||||
|
|
||||||
// Original: LEA RDX, [RAX+0x58]
|
|
||||||
lea(rdx, qword[rax + 0x58]);
|
|
||||||
|
|
||||||
// Jump back to original code after LEA (continue with MOVSS)
|
|
||||||
jmp(ptr[rip]);
|
|
||||||
dq(a_returnAddr);
|
|
||||||
|
|
||||||
// Skip label - jump to safe exit point
|
|
||||||
L("skip_label");
|
|
||||||
jmp(ptr[rip]);
|
|
||||||
dq(a_skipAddr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
PatchCode patchCode(skipAddr, returnAddr);
|
|
||||||
patchCode.ready();
|
|
||||||
|
|
||||||
// Allocate trampoline space and copy our patch code
|
|
||||||
SKSE::AllocTrampoline(patchCode.getSize() + 14);
|
|
||||||
auto& trampoline = SKSE::GetTrampoline();
|
|
||||||
|
|
||||||
void* codeCave = trampoline.allocate(patchCode.getSize());
|
|
||||||
std::memcpy(codeCave, patchCode.getCode(), patchCode.getSize());
|
|
||||||
|
|
||||||
// Write jump from original location to our patch code
|
|
||||||
trampoline.write_branch<5>(hookAddr, reinterpret_cast<std::uintptr_t>(codeCave));
|
|
||||||
|
|
||||||
// NOP remaining bytes
|
|
||||||
if (HookSize > 5) {
|
|
||||||
REL::safe_fill(hookAddr + 5, REL::NOP, HookSize - 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* version = REL::Module::IsVR() ? "VR" :
|
|
||||||
(REL::Module::get().version() <= REL::Version(1, 5, 97, 0) ? "SE" : "AE");
|
|
||||||
logger::info("MovementPathFollowerCrashFix: Patched {} at 0x{:X}, code cave at 0x{:X}",
|
|
||||||
version, hookAddr, reinterpret_cast<std::uintptr_t>(codeCave));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -16,8 +16,7 @@
|
|||||||
#include "Patches/PluginsTxtPatch.h"
|
#include "Patches/PluginsTxtPatch.h"
|
||||||
#include "Patches/FormTypeCollisionDetector.h"
|
#include "Patches/FormTypeCollisionDetector.h"
|
||||||
#include "Patches/GogVramLeakFix.h"
|
#include "Patches/GogVramLeakFix.h"
|
||||||
#include "CrashFixes/CrosshairPickDataCrashFix.h"
|
#include "Patches/CrosshairPickDataCrashFix.h"
|
||||||
#include "CrashFixes/MovementPathFollowerCrashFix.h"
|
|
||||||
|
|
||||||
using namespace SKSE;
|
using namespace SKSE;
|
||||||
|
|
||||||
@ -33,7 +32,7 @@ static std::map<std::string, bool> g_settings{
|
|||||||
{ "AttachLightHitEffectCrashFix", true },
|
{ "AttachLightHitEffectCrashFix", true },
|
||||||
{ "AutoScaleHeroMenu", true },
|
{ "AutoScaleHeroMenu", true },
|
||||||
{ "GogVramLeakFix", true },
|
{ "GogVramLeakFix", true },
|
||||||
{ "ExperimentalCrashFixes", false }
|
{ "CrosshairPickDataCrashFix", true }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -83,11 +82,9 @@ namespace {
|
|||||||
logger::info("Installing light attach crash fix...");
|
logger::info("Installing light attach crash fix...");
|
||||||
AttachLightHitEffectCrash::Install();
|
AttachLightHitEffectCrash::Install();
|
||||||
}
|
}
|
||||||
if (g_settings.at("ExperimentalCrashFixes")) {
|
if (g_settings.at("CrosshairPickDataCrashFix")) {
|
||||||
logger::info("Installing crosshair pick data crash fix...");
|
logger::info("Installing crosshair pick data crash fix...");
|
||||||
CrosshairPickDataCrashFix::Install();
|
CrosshairPickDataCrashFix::Install();
|
||||||
logger::info("Installing movement path follower crash fix...");
|
|
||||||
MovementPathFollowerCrashFix::Install();
|
|
||||||
}
|
}
|
||||||
if (g_settings.at("StayAtSystemPage")) {
|
if (g_settings.at("StayAtSystemPage")) {
|
||||||
if (const auto pluginInfo = GetLoadInterface()->GetPluginInfo("StayAtSystemPage"); pluginInfo) {
|
if (const auto pluginInfo = GetLoadInterface()->GetPluginInfo("StayAtSystemPage"); pluginInfo) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user