static void FixInfixToPostfixOverflow(void) { // this function uses a statically allocated 64 byte work buffer that overflows really quickly // hook replaces the buffer, safe to use a static buffer because it isn't re-entrant and can't be called from multiple threads WriteRelJump(kInfixToPostfixHookAddr_1, (UInt32)&InfixToPostfixHook_1); WriteRelJump(kInfixToPostfixHookAddr_2, (UInt32)&InfixToPostfixHook_2); }
void PatchEndOfLineCheck(bool bDisableCheck) { if (bDisableCheck) WriteRelJump(kEndOfLineCheckPatchAddr, kEndOfLineCheckJumpAddr); else { SafeWrite8(kEndOfLineCheckPatchAddr, 0x0F); SafeWrite8(kEndOfLineCheckPatchAddr + 1, 0x83); SafeWrite32(kEndOfLineCheckPatchAddr + 2, kEndOfLineCheckJumpDelta); } }
void Hook_Script_Init() { WriteRelJump(ExtractStringPatchAddr, (UInt32)&ExtractStringHook); // patch the "apple bug" // game caches information about the most recently retrieved RefVariable for the current executing script // if same refIdx requested twice in a row returns previously returned ref without // bothering to check if form stored in ref var has changed // this fixes it by overwriting a conditional jump with an unconditional one SafeWrite8(kResolveRefVarPatchAddr, 0xEB); // game also caches information about the most recently retrieved local numeric variable for // currently executing script. Causes issues with function scripts. As above, overwrite conditional jump with unconditional SafeWrite8(kResolveNumericVarPatchAddr, 0xEB); // hook code in the vanilla expression parser's subroutine to fix the buffer overflow WriteRelJump(kExpressionParserBufferOverflowHookAddr_1, (UInt32)&ExpressionParserBufferOverflowHook_1); WriteRelJump(kExpressionParserBufferOverflowHookAddr_2, (UInt32)&ExpressionParserBufferOverflowHook_2); // hook ExtractArgs() to handle commands normally compiled with Cmd_Default_Parse which were instead compiled with Cmd_Expression_Parse ExtractArgsOverride::Init_Hooks(); }
void __stdcall ToggleOverride(bool bOverride) { static const UInt32 patchLoc = 0x005C67E0; // editor default parse routine (g_defaultParseCommand in CommandTable) (F3:0x005C01F0) // ToggleOverride() only gets invoked when we parse a begin or end statement, so set mode accordingly s_currentMode = kOverride_BlockType; // overwritten instructions static const UInt8 s_patchedInstructions[5] = { 0x81, 0xEC, 0x30, 0x02, 0x00 }; // same first five bytes as Oblivion if (bOverride) { WriteRelJump(patchLoc, (UInt32)&Hook_Cmd_Default_Parse); } else { for (UInt32 i = 0; i < sizeof(s_patchedInstructions); i++) { SafeWrite8(patchLoc+i, s_patchedInstructions[i]); } } }
void CreateSleepingModeHook() { #if defined(OBLIVION) *((int *)&RemoveWornItems) = 0x0064BAC0; TrackRemoveWornItems = &SleepingMode::TrackRemoveWornItems; *((int *)&ServeSentence) = 0x00670700; TrackServeSentence = &SleepingMode::TrackServeSentence; #elif defined (SKYRIM) *((int *)&SetFurnitureCameraState) = 0x0083D6E0; TrackSetFurnitureCameraState = &SleepingMode::TrackSetFurnitureCameraState; *((int *)&ProcessSleepWaitMenu) = 0x00887F90; TrackProcessSleepWaitMenu = &SleepingMode::TrackProcessSleepWaitMenu; *((int *)&ServeSentence) = 0x0074B7E0; TrackServeSentence = &SleepingMode::TrackServeSentence; #endif DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); #if defined(OBLIVION) DetourAttach(&(PVOID&)RemoveWornItems, *((PVOID *)&TrackRemoveWornItems)); DetourAttach(&(PVOID&)ServeSentence, *((PVOID *)&TrackServeSentence)); DetourAttach(&(PVOID&)ProcessSleepWaitMenu, &TrackProcessSleepWaitMenu); DetourAttach(&(PVOID&)CloseSleepWaitMenu, &TrackCloseSleepWaitMenu); #elif defined(SKYRIM) DetourAttach(&(PVOID&)SetFurnitureCameraState, *((PVOID *)&TrackSetFurnitureCameraState)); DetourAttach(&(PVOID&)ProcessSleepWaitMenu, *((PVOID *)&TrackProcessSleepWaitMenu)); DetourAttach(&(PVOID&)ServeSentence, *((PVOID *)&TrackServeSentence)); #endif DetourAttach(&(PVOID&)ShowSleepWaitMenu, &TrackShowSleepWaitMenu); DetourTransactionCommit(); #if defined(NEWVEGAS) WriteRelJump(0x00509830, 0x0050983C); // Enables the Player to get into the bed WriteRelJump(0x00942E0C, 0x00942E36); // Skips the possibility to get up by directional controls #elif defined(OBLIVION) WriteRelJump(0x004AEA1C, 0x004AEAEE); // Enables the Player to get into the bed WriteRelJump(0x004AE961, 0x004AEAEE); // Enables the Player to get into the bed when in prison WriteRelJump(0x00672BFF, 0x00672C18); // Enables the rest key when in prison #elif defined(SKYRIM) WriteRelJump(0x0049A351, 0x0049A367); // Enables the Player to get into the bed WriteRelJump(0x0049A30F, 0x0049A367); // Enables the Player to get into the bed when in prison #endif }