Skip to content

Commit

Permalink
Merge pull request #21 from TinManTex/dev
Browse files Browse the repository at this point in the history
r17
  • Loading branch information
TinManTex authored Jul 12, 2022
2 parents c9b43d2 + f787dd6 commit 71801f1
Show file tree
Hide file tree
Showing 64 changed files with 5,504 additions and 191,216 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -346,4 +346,6 @@ ASALocalRun/
healthchecksdb

# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
MigrationBackup/
makebite/GameDir/dinput8.dll
makebite/Readme.txt
10 changes: 9 additions & 1 deletion ...ite/GameDir/mod/docs/IHHook-Changelog.txt → Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
IHHook changelog
- just the changes that are most likely to be added to IH readme, otherwise just look at the github commits.
- just broad sweep changes, otherwise just look at the github commits.

Version r17 - 2022-07-02 (see github for full changes)
FoxString hook.
Bunch of character, buddy, vehicle change hooks.
ihhook_config.lua (next to ihhook/dinput8 dll) - allows some startup settings of ihhook to be set.
FNV Hash logging.
Ghidra scripts to export addresses, func defs, and a refactor and reduction of required steps to get hooks running.

r16 - 2021-08-04
InfCamHook/FOV module moved from IH.
Settings line combined InputText plus Combobox.
Expand Down
47 changes: 47 additions & 0 deletions Developers.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Notes for developers
Further notes at top of IHHook.h

## Developing a new IHHook version:

Work for a new version should be done on a seperate development branch than main.

Bump the Version in IHHook.h and FileVersion in Resource Files/IHHook.rc

Try and get some Modders Heaven community members to test build builds for you
https://discord.gg/3rVFWf2vbj

## Documentation:
Make sure Changelog.txt has a synopsis of major changes.
Copy the latest changelog on to the top of the ReadMe.md
As Readme.md is coppied to txt (since most users wont have the filetype associated to open it) remember to add two spaces at the end of lines you want to linebreak in .md rather than double breaking which will space out txt weird.
The readme should be directly copied into into the nexusmods description page on release.

## Releases:
Make sure VS is set to release build.
Visual Studio post-build step should copy and rename the dll to the makebite folder.
It also copies ReadMe.md and Changelog.md to makebite/GameDir/mod/docs
Simply use makebite on the makebite folder.
And zip the .mgsv

Compare the .mgsv against a previous build
and test installation for good measure.

When you're sure of a release make a pull of the development branch to main.

## Exporting functions to hook
IHHook has a ghidra script to export function signatures/addresses for IHHook.
Get access to the mgsv ghidra project by asking at the Modders Heaven discord.
Read the notes in IHHook\ghidra\ExportInfo.py
Specifically about committing the function parameter types in ghidra for the function you want.
Add an entry to ExportInfo.py (again follow the notes)
Run IHHook\ghidra\ExportHooksToHeader.py in ghidra via
window menu > script manager,
find the manage script directories and point it to IHHook/ghidra folder,
then find the script in scripts\IHHook (or type in the name in filter).
Any functions you're hooking need to be found in the jp exe too before the actual IHHook release, where ExportHooksToHeader needs to be run on the jp exe first, then on the eng exe.

## Using IHHook lua functions:
Lua code can check for the global _IHHook to see if IHHook is running. It will be nil if not, or the IHHook version number if so.
Which you can also use to guard against user running versions before the IHHook functions you're using.
IH menus and Ivars can set a .requiresIHHook bool to exclude themselves if IHH is not running.

6 changes: 3 additions & 3 deletions IHHook/D3D11Hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ bool D3D11Hook::hook() {
swap_chain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swap_chain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

spdlog::info("Creating dummy D3D11 device.");
HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_NULL, nullptr, 0, &feature_level, 1, D3D11_SDK_VERSION, &swap_chain_desc, &swap_chain, &device, &device_max_feature_level, &context);
if (FAILED(hr)) {
spdlog::error("Failed to create dummy D3D11 device. HRESULT={0:x} max_feature={1:x}", hr, device_max_feature_level);
return false;
}
//spdlog::info("Created dummy D3D11 device. HRESULT={0:x} max_feature={1:x}", hr, device_max_feature_level);
spdlog::info("Created dummy D3D11 device. HRESULT={0:x} max_feature={1:x}", hr, device_max_feature_level);

auto present_fn = (*(uintptr_t**)swap_chain)[8];
auto resize_buffers_fn = (*(uintptr_t**)swap_chain)[13];
Expand All @@ -54,7 +54,7 @@ bool D3D11Hook::hook() {
device->Release();
context->Release();
swap_chain->Release();
//spdlog::info("Released dummy D3D11 device");
spdlog::info("Released dummy D3D11 device");

m_hooked = m_present_hook->create() && m_resize_buffers_hook->create();

Expand Down
112 changes: 19 additions & 93 deletions IHHook/HookMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include "Hooking.Patterns/Hooking.Patterns.h"//DEBUGNOW

#include "spdlog/spdlog.h"

namespace IHHook {
extern std::map<std::string, int64_t> addressSet;
}
Expand Down Expand Up @@ -51,112 +53,36 @@ namespace IHHook {
#define TOKENPASTE(x, y) STRINGIFY(x ## y)



//typedef for the function pointer,
//and an extern function pointer of the type
//so you can include a header with the hookfunc in other files and use the function
//TODO CULL still in the lua headers, which I can revert/comment out the hooked
#define FUNCPTRDEF(ret, name, ...)\
typedef ret ( __fastcall name##Func ) (__VA_ARGS__);\
extern name##Func* name;\
extern intptr_t* name##BaseAddr;\
extern intptr_t* name##Addr;\
extern const char* name##Sig;\
extern const char* name##Mask;\
extern const char* name##Pattern;
//Example use:
//FUNCPTRDEF(lua_newstate, 0x14cdd7ab0, LuaState*, lua_Alloc f, void *ud);
//Expands to:
//typedef lua_State* (__fastcall *lua_newstateFunc)(lua_Alloc f, void *ud);
//extern lua_newstateFunc lua_newstate;
//extern intptr_t* lua_newstateBaseAddr;
//extern intptr_t* lua_newstateAddr;
//extern const char* lua_newstateSig;
//extern const char * lua_newstateMask;
//extern const char * lua_newstatePattern;

//Define signature and mask
#define FUNC_DECL_SIG(name, sig, mask)\
const char * name##Sig = sig;\
const char * name##Mask = mask;
//Example use:
//FUNC_DECL_SIG(lua_newstate,
//FUNC_DECL_SIG(lua_newstate,
// "\x4C\x8B\x00\x49\x89\x00\x00\x55\x56\x57\x41\x00\x41",
// "xx?xx??xxxx?x")
//Expands to:
//const char* lua_newstateSig = "\x4C\x8B\x00\x49\x89\x00\x00\x55\x56\x57\x41\x00\x41";
//const char * lua_newstateMask = "xx?xx??xxxx?x";

//Define pattern
#define FUNC_DECL_PATTERN(name, pattern)\
const char * name##Pattern = pattern;
//Example use:
//FUNC_DECL_PATTERN(lua_newstate, "4C 8B ? 49 89 ? ? 55 56 57 41 ? 41")
//Expands to:
//const char * lua_newstate = "4C 8B ? 49 89 ? ? 55 56 57 41 ? 41";

//base address of func, and actually declare the function pointer -- can be in header or code (as long as later code using it can see its declaration)
#define FUNC_DECL_ADDR(name)\
name##Func* name;\
intptr_t* name##Addr;
//Example use:
//FUNC_DECL_ADDR(lua_newstate);
//Expands to:
//lua_newstateFunc lua_newstate;
//lua_newstateFunc lua_newstateBaseAddr;

//DEBUGNOW rename CREATE addrs (sig as well) GET_<>_ADDR
//Rebases an address an puts it in var for CREATE_HOOK macro
#define GET_REBASED_ADDR(name)\
name##Addr = (intptr_t*)((addressSet[#name] - BaseAddr) + RealBaseAddr);
//OLD name##Addr = (intptr_t*)((name##BaseAddr - BaseAddr) + RealBaseAddr);
//Example use:
//GET_REBASED_ADDR(lua_newstate);
//Expands to:
//lua_newstateAddr = (intptr_t*)((addressSet["lua_newstate"] - BaseAddr) + RealBaseAddr);

//ASSUMPTION name##Addr defined, FUNC_DECL_SIG declared
//sigscans for an address an puts it in var for CREATE_HOOK macro
#define GET_SIG_ADDR(name)\
name##Addr = (intptr_t*)MemoryUtils::sigscan(#name, name##Sig, name##Mask);
//ALT name##Addr = (intptr_t*)MemoryUtils::PatternScan(#name, name##Pattern);
//ALT name##Addr = (intptr_t*)MemoryUtils::ScanModIn(name##Sig, name##Mask, "mgsvtpp.exe");//DEBUG exeName?
//Example use:
//GET_SIG_ADDR(lua_newstate);
//Expands to:
//lua_newstateAddr = (intptr_t*)MemoryUtils::sigscan("lua_newstate", lua_newstateSig, lua_newstateMask);

//just want to use original function
//sets the pointer to the rebased address so the function pointer is usable
#define CREATE_FUNCPTR(name)\
name = (name##Func*)name##Addr;
//Example use:
//CREATE_FUNCPTR(lua_newstate);
//Expands to:
//lua_newstate = (lua_newstateFunc*)lua_newstateFuncAddr;
//

//detour and trampoline via MH_CreateHook
//detour and trampoline via MH_CreateHook,
//original function is at the <name> function ptr (just like createptr)
//while the hook/detour is at <name>Hook function pointer.
//ASSUMPTION must have a name##Addr of the runtime location of the function, either via GET_REBASED_ADDR or some other means (like a sig scan or other method)
//TODO: rethink, could iterate over a map if I have a lookup of name to detour function (name##Hook)
#define CREATE_HOOK(name)\
MH_STATUS name##CreateStatus = MH_CreateHook((LPVOID*)name##Addr, name##Hook, (LPVOID*)&name);\
if (name##CreateStatus != MH_OK) {\
spdlog::error("MH_CreateHook failed for {} with code {}", #name, name##CreateStatus);\
if (addressSet[#name]==NULL) {\
spdlog::error("CREATE_HOOK addressSet[{}]==NULL", #name);\
} else {\
spdlog::debug("MH_CreateHook MH_OK for {}", #name);\
MH_STATUS name##CreateStatus = MH_CreateHook((LPVOID*)addressSet[#name], name##Hook, (LPVOID*)&name);\
if (name##CreateStatus != MH_OK) {\
spdlog::error("MH_CreateHook failed for {} with code {}", #name, name##CreateStatus);\
} else {\
spdlog::debug("MH_CreateHook MH_OK for {}", #name);\
}\
}
//Example use:
//CREATE_HOOK(lua_newstate);
//Expands to:
//MH_STATUS lua_newstateCreateStatus = MH_CreateHook(lua_newstateAddr, lua_newstateHook, (LPVOID*)&lua_newstate);
//MH_STATUS lua_newstateCreateStatus = MH_CreateHook((LPVOID*)addressSet["lua_newstate"], lua_newstateHook, (LPVOID*)&lua_newstate);
//if (lua_newstateCreateStatus != MH_OK) {
// spdlog::error("MH_CreateHook failed for {} with code {}", "lua_newstate", lua_newstateCreateStatus);\
//}

//ASSUMPTION name##Addr of runtime memory address has been defined
#define ENABLEHOOK(name)\
MH_STATUS name##EnableStatus = MH_EnableHook((LPVOID*)name##Addr);\
MH_STATUS name##EnableStatus = MH_EnableHook((LPVOID*)addressSet[#name]);\
if (name##EnableStatus != MH_OK) {\
spdlog::error("MH_EnableHook failed for {} with code {}", #name, name##EnableStatus);\
} else {\
Expand All @@ -165,14 +91,14 @@ if (name##EnableStatus != MH_OK) {\
//Example use:
//ENABLEHOOK(lua_newstate);
//Expands to:
//MH_STATUS lua_newstateEnableStatus = MH_EnableHook(lua_newstateAddr);
//MH_STATUS lua_newstateEnableStatus = MH_EnableHook((LPVOID*)addressSet["lua_newstate"]);
//if (lua_newstateEnableStatus != MH_OK) {
// spdlog::error("MH_EnableHook failed for {} with code {}", "lua_newstate", lua_newstateEnableStatus);\
//}

//ASSUMES CREATEDETOUR has defined name##Addr
#define DISABLEHOOK(name)\
MH_STATUS name##DisableStatus = MH_DisableHook((LPVOID*)name##Addr);\
MH_STATUS name##DisableStatus = MH_DisableHook((LPVOID*)addressSet[#name]);\
if (name##DisableStatus != MH_OK) {\
spdlog::error("MH_DisableHook failed for {} with code {}", #name, name##DisableStatus);\
} else {\
Expand All @@ -181,7 +107,7 @@ if (name##DisableStatus != MH_OK) {\
//Example use:
//ENABLEHOOK(lua_newstate);
//Expands to:
//MH_STATUS lua_newstateDisableStatus = MH_DisableHook(lua_newstateAddr);
//MH_STATUS lua_newstateDisableStatus = MH_DisableHook((LPVOID*)addressSet["lua_newstate"]);
//if (DisableStatus != MH_OK) {
// spdlog::error("MH_DisableHook failed for {} with code {}", "lua_newstate", lua_newstateDisableStatus);\
//}
Expand Down
Loading

0 comments on commit 71801f1

Please sign in to comment.