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
	
	 Wiseguy
						Wiseguy