-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
On Vehicle Updated Hook #14
Open
XertroV
wants to merge
2
commits into
main
Choose a base branch
from
OnVehicleUpdateHook
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
namespace VehicleState | ||
{ | ||
OnVehicleStateUpdated@[] callbacks; | ||
string[] callbackPlugins; | ||
|
||
void RegisterOnVehicleStateUpdateCallback(OnVehicleStateUpdated@ func) | ||
{ | ||
if (func is null) { | ||
warn("Null function passed to RegisterOnVehicleStateUpdateCallback"); | ||
return; | ||
} | ||
auto pluginId = Meta::ExecutingPlugin().ID; | ||
callbacks.InsertLast(func); | ||
callbackPlugins.InsertLast(pluginId); | ||
trace('Added OVSU callback for ' + pluginId); | ||
} | ||
|
||
void RunCallbacks(uint visEntId, uint64 visStatePtr) | ||
{ | ||
for (uint i = 0; i < callbacks.Length; i++) { | ||
auto f = callbacks[i]; | ||
if (f is null) continue; | ||
f(visEntId, visStatePtr); | ||
} | ||
} | ||
|
||
void DeregisterCallbacksFrom(Meta::Plugin@ plugin) | ||
{ | ||
#if DEV | ||
trace('Checking OVSU callbacks plugin for dereg'); | ||
#endif | ||
uint[] removeIxs = {}; | ||
for (uint i = 0; i < callbackPlugins.Length; i++) { | ||
auto p = callbackPlugins[i]; | ||
if (p == plugin.ID) { | ||
removeIxs.InsertLast(i); | ||
trace('Found CB to remove at index ' + i); | ||
} | ||
} | ||
for (int i = removeIxs.Length - 1; i >= 0; i--) { | ||
callbacks.RemoveAt(i); | ||
callbackPlugins.RemoveAt(i); | ||
} | ||
#if DEV | ||
trace('Unregistered OVSU callbacks ('+removeIxs.Length+' total) for ' + plugin.ID); | ||
#endif | ||
} | ||
|
||
void DeregisterVehicleStateUpdateCallbacks() | ||
{ | ||
DeregisterCallbacksFrom(Meta::ExecutingPlugin()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//remove any hooks | ||
void OnDestroyed() { _Unload(); } | ||
void OnDisabled() { _Unload(); } | ||
void _Unload() | ||
{ | ||
CheckUnhookAllRegisteredHooks(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
dictionary warnTracker; | ||
void warn_every_60_s(const string &in msg) | ||
{ | ||
if (warnTracker is null) return; | ||
if (warnTracker.Exists(msg)) { | ||
uint lastWarn = uint(warnTracker[msg]); | ||
if (Time::Now - lastWarn < 60000) return; | ||
} else { | ||
warn(msg); | ||
} | ||
warnTracker[msg] = Time::Now; | ||
warn(msg); | ||
} | ||
|
||
class HookHelper | ||
{ | ||
protected Dev::HookInfo@ hookInfo; | ||
protected uint64 patternPtr; | ||
|
||
// protected string name; | ||
protected string pattern; | ||
protected uint offset; | ||
protected uint padding; | ||
protected string functionName; | ||
|
||
// const string &in name, | ||
HookHelper(const string &in pattern, uint offset, uint padding, const string &in functionName) | ||
{ | ||
this.pattern = pattern; | ||
this.offset = offset; | ||
this.padding = padding; | ||
this.functionName = functionName; | ||
} | ||
|
||
~HookHelper() | ||
{ | ||
Unapply(); | ||
} | ||
|
||
bool Apply() | ||
{ | ||
if (hookInfo !is null) return false; | ||
if (patternPtr == 0) patternPtr = Dev::FindPattern(pattern); | ||
if (patternPtr == 0) { | ||
warn_every_60_s("Failed to apply hook for " + functionName); | ||
return false; | ||
} | ||
@hookInfo = Dev::Hook(patternPtr + offset, padding, functionName, Dev::PushRegisters::SSE); | ||
RegisterUnhookFunction(UnapplyHookFn(this.Unapply)); | ||
return true; | ||
} | ||
|
||
bool Unapply() | ||
{ | ||
if (hookInfo is null) return false; | ||
Dev::Unhook(hookInfo); | ||
@hookInfo = null; | ||
return true; | ||
} | ||
} | ||
|
||
funcdef bool UnapplyHookFn(); | ||
|
||
UnapplyHookFn@[] unapplyHookFns; | ||
void RegisterUnhookFunction(UnapplyHookFn@ fn) | ||
{ | ||
if (fn is null) throw("null fn passted to reg unhook fn"); | ||
unapplyHookFns.InsertLast(fn); | ||
} | ||
|
||
void CheckUnhookAllRegisteredHooks() | ||
{ | ||
for (uint i = 0; i < unapplyHookFns.Length; i++) { | ||
unapplyHookFns[i](); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#if TMNEXT | ||
// rdx has vehicle vis state ptr | ||
const string VEHICLE_VIS_UPDATED_HOOK_PATTERN = "4C 8B DA F3 0F 59 15 ?? ?? ?? ?? 4C 8B D1 F3 0F 10 89 ?? ?? 00 00 0F 2F D1"; | ||
const uint VVU_OFFSET = 11; | ||
const uint VVU_PADDING = 6; | ||
#elif MP4 | ||
// rcx has vehicle vis state ptr | ||
const string VEHICLE_VIS_UPDATED_HOOK_PATTERN = "48 8B 43 38 48 8B 0C 07 F6 81 90 00 00 00 01 0F 84 95 00 00 00 4C 8D 81 B4 04 00 00"; | ||
const uint VVU_OFFSET = 0; | ||
const uint VVU_PADDING = 3; | ||
#elif TURBO | ||
// can't find a hook that allows you to overrides skids | ||
|
||
// edi has vehicle vis state ptr | ||
// const string VEHICLE_VIS_UPDATED_HOOK_PATTERN = "8B 42 0C 8B 3C 88 F6 47 74 0F"; | ||
// edx | ||
// const string VEHICLE_VIS_UPDATED_HOOK_PATTERN = "8B 14 B0 8B 43 24 8B 4A 58 6B C9 4C 83 C0 40 03 C1 50"; | ||
// const uint VVU_PADDING = 1; | ||
// esi | ||
// const string VEHICLE_VIS_UPDATED_HOOK_PATTERN = "8B 44 24 44 41 89 74 88 FC 89 4C 24 78 8B 4E 74 8B C1"; | ||
// const uint VVU_PADDING = 0; | ||
// const uint VVU_OFFSET = 0; | ||
#else | ||
// unsupported platform | ||
#endif | ||
|
||
HookHelper@ g_VehicleUpdateHook; | ||
|
||
#if TMNEXT || MP4 | ||
HookHelper@ CreateAndApplyVehicleUpdateHookHelper() { | ||
auto hh = HookHelper( | ||
VEHICLE_VIS_UPDATED_HOOK_PATTERN, VVU_OFFSET, VVU_PADDING, "OnVehicleUpdate" | ||
); | ||
if (!hh.Apply()) return null; | ||
return hh; | ||
} | ||
|
||
void InstallVehicleUpdateHook() { | ||
if (g_VehicleUpdateHook is null) { | ||
@g_VehicleUpdateHook = CreateAndApplyVehicleUpdateHookHelper(); | ||
trace('Vehicle Update hook installed: ' + (g_VehicleUpdateHook !is null)); | ||
} | ||
} | ||
#endif | ||
|
||
#if TMNEXT | ||
// rdx -> CSceneVehicleVisState; rdx - 0x130 -> CSceneVehicleVis | ||
void OnVehicleUpdate(uint64 rdx) | ||
{ | ||
// trace('on vehicle update: ' + Text::FormatPointer(rdx)); | ||
// sanity check pointer. The slightly odd numbers are chosen for ease of reading since `_` in numbers isn't supported. groups of 4 nibbles are used. | ||
if (rdx < 0xff00001111 || rdx & 0x7 != 0 || rdx > 0xdddffffeeee) return; | ||
// sanity check vehicle entity ID. | ||
auto id = Dev::ReadUInt32(rdx); | ||
// id & 0x06000000 == 0 means it does not start with 0x04 or 0x02 (ghosts and players respectively). id & 0xF0000000 != 0 means anything in that nibble results in a failure. | ||
if (id != 0x0FF00000 && (id & 0x06000000 == 0 || id & 0xF0000000 != 0)) return; | ||
// run registered callbacks. | ||
VehicleState::RunCallbacks(id, rdx); | ||
} | ||
#elif MP4 | ||
// rcx has vehicle state ptr | ||
void OnVehicleUpdate(uint64 rcx) | ||
{ | ||
// trace('on vehicle update: ' + Text::FormatPointer(rcx)); | ||
// sanity check pointer. The slightly odd numbers are chosen for ease of reading since `_` in numbers isn't supported. groups of 4 nibbles are used. | ||
if (rcx < 0xff1111 || rcx & 0x7 != 0 || rcx > 0xffffeeee) return; | ||
// sanity check vehicle entity ID. | ||
auto id = Dev::ReadUInt32(rcx); | ||
// run registered callbacks. | ||
VehicleState::RunCallbacks(id, rcx); | ||
} | ||
#elif TURBO | ||
// edi has vehicle state ptr | ||
// turbo register names are wrong?! | ||
// eax is edi :YEK: | ||
// ebx is esi | ||
// ecx is ebp | ||
// edx is esp | ||
// esi is edx | ||
// edi is ecx | ||
// ebp is ebx | ||
// esp unknown hook register | ||
// eip unknown hook register | ||
void OnVehicleUpdate(uint64 esi) | ||
{ | ||
// can't find a hook that allows you to overrides skids | ||
|
||
// trace('on vehicle update: ' + Text::FormatPointer(eax) + " + 4 * " + Text::FormatPointer(ecx)); | ||
// trace('on vehicle update eax: ' + Text::FormatPointer(eax)); | ||
// trace('on vehicle update ebx: ' + Text::FormatPointer(ebx)); | ||
// trace('on vehicle update ecx: ' + Text::FormatPointer(ecx)); | ||
// trace('on vehicle update edx: ' + Text::FormatPointer(edx)); | ||
// trace('on vehicle update esi: ' + Text::FormatPointer(esi)); | ||
// trace('on vehicle update edi: ' + Text::FormatPointer(edi)); | ||
// trace('on vehicle update ebp: ' + Text::FormatPointer(ebp)); | ||
// !! not found trace('on vehicle update eip: ' + Text::FormatPointer(eip)); | ||
// return; | ||
|
||
|
||
// sanity check pointer. The slightly odd numbers are chosen for ease of reading since `_` in numbers isn't supported. groups of 4 nibbles are used. | ||
if (esi < 0xff1111 || esi & 0x3 != 0 || esi > 0xffffeeee) return; | ||
// sanity check vehicle entity ID. | ||
auto id = Dev::ReadUInt32(esi); | ||
// run registered callbacks. | ||
VehicleState::RunCallbacks(id, esi); | ||
} | ||
#endif | ||
|
||
|
||
#if TMNEXT || MP4 | ||
void Main() { | ||
startnew(InstallVehicleUpdateHook); | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did I break Maniaplanet/Turbo with this change? 😅 Perhaps this would be good in its own PR if there's a compiler error on the other games.