mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2025-10-30 08:02:29 +00:00
Add exports to get the return value of functions from return hooks (#116)
Some checks failed
validate / ubuntu (arm64, Debug) (push) Has been cancelled
validate / ubuntu (arm64, Release) (push) Has been cancelled
validate / ubuntu (x64, Debug) (push) Has been cancelled
validate / ubuntu (x64, Release) (push) Has been cancelled
validate / windows (x64, Debug) (push) Has been cancelled
validate / windows (x64, Release) (push) Has been cancelled
validate / macos (arm64, Debug) (push) Has been cancelled
validate / macos (arm64, Release) (push) Has been cancelled
validate / macos (x64, Debug) (push) Has been cancelled
validate / macos (x64, Release) (push) Has been cancelled
Some checks failed
validate / ubuntu (arm64, Debug) (push) Has been cancelled
validate / ubuntu (arm64, Release) (push) Has been cancelled
validate / ubuntu (x64, Debug) (push) Has been cancelled
validate / ubuntu (x64, Release) (push) Has been cancelled
validate / windows (x64, Debug) (push) Has been cancelled
validate / windows (x64, Release) (push) Has been cancelled
validate / macos (arm64, Debug) (push) Has been cancelled
validate / macos (arm64, Release) (push) Has been cancelled
validate / macos (x64, Debug) (push) Has been cancelled
validate / macos (x64, Release) (push) Has been cancelled
This commit is contained in:
parent
4ba1b54d22
commit
94b30d7061
3 changed files with 73 additions and 2 deletions
|
|
@ -591,6 +591,7 @@ namespace recomp {
|
|||
void finish_event_setup(const ModContext& context);
|
||||
void finish_hook_setup(const ModContext& context);
|
||||
void reset_hooks();
|
||||
void register_hook_exports();
|
||||
void run_hook(uint8_t* rdram, recomp_context* ctx, size_t hook_slot_index);
|
||||
|
||||
ModOpenError parse_manifest(ModManifest &ret, const std::vector<char> &manifest_data, std::string &error_param);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ struct HookTableEntry {
|
|||
// Vector of individual hooks for each hook slot.
|
||||
std::vector<HookTableEntry> hook_table{};
|
||||
|
||||
// Holds the recomp context to restore after running each hook. This is a vector because a hook may end up calling another hooked function,
|
||||
// so this acts as a stack of contexts to handle that recursion.
|
||||
thread_local std::vector<recomp_context> hook_contexts = { recomp_context{} };
|
||||
|
||||
void recomp::mods::run_hook(uint8_t* rdram, recomp_context* ctx, size_t hook_slot_index) {
|
||||
// Sanity check the hook slot index.
|
||||
if (hook_slot_index >= hook_table.size()) {
|
||||
|
|
@ -31,7 +35,7 @@ void recomp::mods::run_hook(uint8_t* rdram, recomp_context* ctx, size_t hook_slo
|
|||
}
|
||||
|
||||
// Copy the initial context state to restore it after running each callback.
|
||||
recomp_context initial_context = *ctx;
|
||||
hook_contexts.emplace_back(*ctx);
|
||||
|
||||
// Call every hook attached to the hook slot.
|
||||
const std::vector<HookEntry>& hooks = hook_table[hook_slot_index].hooks;
|
||||
|
|
@ -44,8 +48,11 @@ void recomp::mods::run_hook(uint8_t* rdram, recomp_context* ctx, size_t hook_slo
|
|||
}, hook.func);
|
||||
|
||||
// Restore the original context.
|
||||
*ctx = initial_context;
|
||||
*ctx = hook_contexts.back();
|
||||
}
|
||||
|
||||
// Pop the context after the hook is done.
|
||||
hook_contexts.pop_back();
|
||||
}
|
||||
|
||||
void recomp::mods::setup_hooks(size_t num_hook_slots) {
|
||||
|
|
@ -85,3 +92,65 @@ void recomp::mods::finish_hook_setup(const ModContext& context) {
|
|||
void recomp::mods::reset_hooks() {
|
||||
hook_table.clear();
|
||||
}
|
||||
|
||||
void recomphook_get_return_s32(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->r2 = (gpr)(int32_t)hook_contexts.back().r2;
|
||||
}
|
||||
|
||||
void recomphook_get_return_u32(uint8_t* rdram, recomp_context* ctx) {
|
||||
recomphook_get_return_s32(rdram, ctx);
|
||||
}
|
||||
|
||||
void recomphook_get_return_ptr(uint8_t* rdram, recomp_context* ctx) {
|
||||
recomphook_get_return_s32(rdram, ctx);
|
||||
}
|
||||
|
||||
void recomphook_get_return_s16(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->r2 = (gpr)(int16_t)hook_contexts.back().r2;
|
||||
}
|
||||
|
||||
void recomphook_get_return_u16(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->r2 = (gpr)(uint16_t)hook_contexts.back().r2;
|
||||
}
|
||||
|
||||
void recomphook_get_return_s8(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->r2 = (gpr)(int8_t)hook_contexts.back().r2;
|
||||
}
|
||||
|
||||
void recomphook_get_return_u8(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->r2 = (gpr)(uint8_t)hook_contexts.back().r2;
|
||||
}
|
||||
|
||||
void recomphook_get_return_s64(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->r2 = (gpr)(int32_t)hook_contexts.back().r2;
|
||||
ctx->r3 = (gpr)(int32_t)hook_contexts.back().r3;
|
||||
}
|
||||
|
||||
void recomphook_get_return_u64(uint8_t* rdram, recomp_context* ctx) {
|
||||
recomphook_get_return_s64(rdram, ctx);
|
||||
}
|
||||
|
||||
void recomphook_get_return_float(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->f0.fl = hook_contexts.back().f0.fl;
|
||||
}
|
||||
|
||||
void recomphook_get_return_double(uint8_t* rdram, recomp_context* ctx) {
|
||||
ctx->f0.fl = (gpr)(uint8_t)hook_contexts.back().f0.fl;
|
||||
ctx->f1.fl = (gpr)(uint8_t)hook_contexts.back().f1.fl;
|
||||
}
|
||||
|
||||
#define REGISTER_FUNC(name) recomp::overlays::register_base_export(#name, name)
|
||||
|
||||
void recomp::mods::register_hook_exports() {
|
||||
REGISTER_FUNC(recomphook_get_return_s32);
|
||||
REGISTER_FUNC(recomphook_get_return_u32);
|
||||
REGISTER_FUNC(recomphook_get_return_ptr);
|
||||
REGISTER_FUNC(recomphook_get_return_s16);
|
||||
REGISTER_FUNC(recomphook_get_return_u16);
|
||||
REGISTER_FUNC(recomphook_get_return_s8);
|
||||
REGISTER_FUNC(recomphook_get_return_u8);
|
||||
REGISTER_FUNC(recomphook_get_return_s64);
|
||||
REGISTER_FUNC(recomphook_get_return_u64);
|
||||
REGISTER_FUNC(recomphook_get_return_float);
|
||||
REGISTER_FUNC(recomphook_get_return_double);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -780,6 +780,7 @@ void recomp::start(
|
|||
|
||||
recomp::register_heap_exports();
|
||||
recomp::mods::register_config_exports();
|
||||
recomp::mods::register_hook_exports();
|
||||
|
||||
std::thread game_thread{[](ultramodern::renderer::WindowHandle window_handle, uint8_t* rdram) {
|
||||
debug_printf("[Recomp] Starting\n");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue