segatools/unityhook/mono.h
beerpsi 4041844ea9 mai2/mu3/cm: Integrate UnityDoorstop with segatools (#11)
[UnityDoorstop](https://github.com/NeighTools/UnityDoorstop) is a tool to execute managed code (.NET DLLs) before Unity does, useful for modding frameworks such as BepInEx.

This PR integrates parts of its code into segatools, so loading BepInEx is as simple as adding 2 lines to `segatools.ini`:
```ini
[unity]
targetAssembly=BepInEx\core\BepInEx.Preloader.dll
```

This PR also factors out the Unity path redirection hooks to its own module.

Reviewed-on: Dniel97/segatools#11
Co-authored-by: beerpsi <beerpsi@duck.com>
Co-committed-by: beerpsi <beerpsi@duck.com>
2024-04-15 19:30:28 +00:00

100 lines
4.1 KiB
C

// SPDX-License-Identifier: CC0
// https://github.com/NeighTools/UnityDoorstop
#pragma once
#include <windows.h>
// Here we define the pointers to some functions within mono.dll
// Note to C learners: these are not signature definitions, but rather "variable"
// definitions with the function pointer type.
// Note: we use void* instead of the real intented structs defined in mono API
// This way we don't need to include or define any of Mono's structs, which saves space
// This, obviously, comes with a drawback of not being able to easily access the contents of the structs
void * (*mono_thread_current)();
void (*mono_thread_set_main)(void *);
void *(*mono_jit_init_version)(const char *root_domain_name, const char *runtime_version);
void *(*mono_domain_assembly_open)(void *domain, const char *name);
void *(*mono_assembly_get_image)(void *assembly);
void *(*mono_runtime_invoke)(void *method, void *obj, void **params, void **exc);
void *(*mono_method_desc_new)(const char *name, int include_namespace);
void* (*mono_method_desc_search_in_image)(void* desc, void* image);
void *(*mono_method_desc_search_in_class)(void *desc, void *klass);
void (*mono_method_desc_free)(void *desc);
void *(*mono_method_signature)(void *method);
UINT32 (*mono_signature_get_param_count)(void *sig);
void (*mono_domain_set_config)(void *domain, char *base_dir, char *config_file_name);
void *(*mono_array_new)(void *domain, void *eclass, uintptr_t n);
void *(*mono_get_string_class)();
char *(*mono_assembly_getrootdir)();
// Additional funcs to bootstrap custom MONO
void (*mono_set_dirs)(const char* assembly_dir, const char* config_dir);
void (*mono_config_parse)(const char* filename);
void (*mono_set_assemblies_path)(const char* path);
void *(*mono_object_to_string)(void* obj, void** exc);
char *(*mono_string_to_utf8)(void* s);
void *(*mono_image_open_from_data_with_name)(void *data, DWORD data_len, int need_copy, void *status, int refonly,
const char *name);
void* (*mono_get_exception_class)();
void* (*mono_object_get_virtual_method)(void* obj_raw, void* method);
void* (*mono_jit_parse_options)(int argc, const char** argv);
typedef enum {
MONO_DEBUG_FORMAT_NONE,
MONO_DEBUG_FORMAT_MONO,
/* Deprecated, the mdb debugger is not longer supported. */
MONO_DEBUG_FORMAT_DEBUGGER
} MonoDebugFormat;
void* (*mono_debug_init)(MonoDebugFormat format);
void* (*mono_debug_domain_create)(void* domain);
/**
* \brief Loads Mono C API function pointers so that the above definitions can be called.
* \param mono_lib Mono.dll module.
*/
void load_mono_functions(HMODULE mono_lib) {
// Enjoy the fact that C allows such sloppy casting
// In C++ you would have to cast to the precise function pointer type
#define GET_MONO_PROC(name) name = (void*)GetProcAddress(mono_lib, #name)
// Find and assign all our functions that we are going to use
GET_MONO_PROC(mono_domain_assembly_open);
GET_MONO_PROC(mono_assembly_get_image);
GET_MONO_PROC(mono_runtime_invoke);
GET_MONO_PROC(mono_jit_init_version);
GET_MONO_PROC(mono_method_desc_new);
GET_MONO_PROC(mono_method_desc_search_in_class);
GET_MONO_PROC(mono_method_desc_search_in_image);
GET_MONO_PROC(mono_method_desc_free);
GET_MONO_PROC(mono_method_signature);
GET_MONO_PROC(mono_signature_get_param_count);
GET_MONO_PROC(mono_array_new);
GET_MONO_PROC(mono_get_string_class);
GET_MONO_PROC(mono_assembly_getrootdir);
GET_MONO_PROC(mono_thread_current);
GET_MONO_PROC(mono_thread_set_main);
GET_MONO_PROC(mono_domain_set_config);
GET_MONO_PROC(mono_set_dirs);
GET_MONO_PROC(mono_config_parse);
GET_MONO_PROC(mono_set_assemblies_path);
GET_MONO_PROC(mono_object_to_string);
GET_MONO_PROC(mono_string_to_utf8);
GET_MONO_PROC(mono_image_open_from_data_with_name);
GET_MONO_PROC(mono_get_exception_class);
GET_MONO_PROC(mono_object_get_virtual_method);
GET_MONO_PROC(mono_jit_parse_options);
GET_MONO_PROC(mono_debug_init);
GET_MONO_PROC(mono_debug_domain_create);
#undef GET_MONO_PROC
}