#include "Hooks_NetImmerse.h" #include "skse64_common/SafeWrite.h" #include "skse64_common/Utilities.h" #include "skse64_common/BranchTrampoline.h" #include "skse64/GameReferences.h" #include "skse64/GameFormComponents.h" #include "skse64/PapyrusEvents.h" #include "common/ICriticalSection.h" #include "xbyak/xbyak.h" // Used by UpdatePlayerTints to create a render target of a particular size // D55B7565783E557DBA232E15687FDD05C35FE3D1+473 RelocPtr g_tintTextureWidth(0x030C7444); // D55B7565783E557DBA232E15687FDD05C35FE3D1+46C RelocPtr g_tintTextureHeight(0x030C7448); UInt32 g_tintTextureResolution = 512; struct RenderTargetInfo { UInt32 width; UInt32 height; UInt32 unk08; UInt32 unk0C; SInt32 unk10; UInt32 unk14; UInt16 unk18; UInt16 unk1A; UInt32 unk1C; }; typedef void ( * _CreateRenderTarget)(void * renderTargetManager, UInt64 type, RenderTargetInfo * info); RelocAddr<_CreateRenderTarget> CreateRenderTarget(0x00DB18B0); _CreateRenderTarget CreateRenderTarget_Original = nullptr; void CreateRenderTarget_Hook(BSRenderManager ** targetManager, UInt64 type, RenderTargetInfo * info) { if (type == 0xF) { info->width = g_tintTextureResolution; info->height = g_tintTextureResolution; *g_tintTextureWidth = g_tintTextureResolution; *g_tintTextureHeight = g_tintTextureResolution; } CreateRenderTarget_Original(targetManager, type, info); } void ActorProcessManager::UpdateEquipment_Hooked(Actor * actor) { CALL_MEMBER_FN(this, UpdateEquipment)(actor); SKSENiNodeUpdateEvent evn(actor); g_ninodeUpdateEventDispatcher.SendEvent(&evn); } void Hooks_NetImmerse_Init(void) { UInt32 tintTextureResolution = 0; if(GetConfigOption_UInt32("Display", "iTintTextureResolution", &tintTextureResolution)) { g_tintTextureResolution = tintTextureResolution; } } RelocAddr UpdateEquipment_Enter(0x006BBB70 + 0x197); void Hooks_NetImmerse_Commit(void) { { struct CreateRenderTarget_Code : Xbyak::CodeGenerator { CreateRenderTarget_Code(void * buf) : Xbyak::CodeGenerator(4096, buf) { Xbyak::Label retnLabel; movups(xmm0, ptr[r8]); movsxd(rax, edx); jmp(ptr[rip + retnLabel]); L(retnLabel); dq(CreateRenderTarget.GetUIntPtr() + 7); } }; void * codeBuf = g_localTrampoline.StartAlloc(); CreateRenderTarget_Code code(codeBuf); g_localTrampoline.EndAlloc(code.getCurr()); CreateRenderTarget_Original = (_CreateRenderTarget)codeBuf; g_branchTrampoline.Write6Branch(CreateRenderTarget.GetUIntPtr(), (uintptr_t)CreateRenderTarget_Hook); } g_branchTrampoline.Write5Call(UpdateEquipment_Enter, GetFnAddr(&ActorProcessManager::UpdateEquipment_Hooked)); }