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_event_setup(const ModContext& context); | ||||||
|         void finish_hook_setup(const ModContext& context); |         void finish_hook_setup(const ModContext& context); | ||||||
|         void reset_hooks(); |         void reset_hooks(); | ||||||
|  |         void register_hook_exports(); | ||||||
|         void run_hook(uint8_t* rdram, recomp_context* ctx, size_t hook_slot_index); |         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); |         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.
 | // Vector of individual hooks for each hook slot.
 | ||||||
| std::vector<HookTableEntry> hook_table{}; | 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) { | void recomp::mods::run_hook(uint8_t* rdram, recomp_context* ctx, size_t hook_slot_index) { | ||||||
|     // Sanity check the hook slot index.
 |     // Sanity check the hook slot index.
 | ||||||
|     if (hook_slot_index >= hook_table.size()) { |     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.
 |     // 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.
 |     // Call every hook attached to the hook slot.
 | ||||||
|     const std::vector<HookEntry>& hooks = hook_table[hook_slot_index].hooks; |     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); |         }, hook.func); | ||||||
| 
 | 
 | ||||||
|         // Restore the original context.
 |         // 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) { | 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() { | void recomp::mods::reset_hooks() { | ||||||
|     hook_table.clear(); |     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::register_heap_exports(); | ||||||
|     recomp::mods::register_config_exports(); |     recomp::mods::register_config_exports(); | ||||||
|  |     recomp::mods::register_hook_exports(); | ||||||
| 
 | 
 | ||||||
|     std::thread game_thread{[](ultramodern::renderer::WindowHandle window_handle, uint8_t* rdram) { |     std::thread game_thread{[](ultramodern::renderer::WindowHandle window_handle, uint8_t* rdram) { | ||||||
|         debug_printf("[Recomp] Starting\n"); |         debug_printf("[Recomp] Starting\n"); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Wiseguy
						Wiseguy