From 517469a60c49c14c47ba238a4e00a2be915a8ed9 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 12 May 2024 19:36:08 +0200 Subject: [PATCH] switched to new capnhook, updated unityhook, added LED 15093 to MU3 --- cxbhook/led.c | 4 +- cxbhook/revio.c | 4 +- dist/fgo/segatools.ini | 1 - dist/mu3/segatools.ini | 3 + fgohook/fgo-dll.c | 2 +- fgohook/fgohook.def | 2 +- fgoio/fgoio.c | 4 +- fgoio/fgoio.h | 2 +- hooklib/meson.build | 2 - hooklib/procaddr.c | 125 ----------------------------- hooklib/procaddr.h | 18 ----- hooklib/reg.c | 165 +++++++++++++++++++++++++++++++++++++- hooklib/reg.h | 2 + hooklib/touch.c | 11 ++- hooklib/touch.h | 1 + meson.build | 7 +- mu3hook/config.c | 61 ++++++++++++++ mu3hook/config.h | 4 +- mu3hook/dllmain.c | 18 ++--- mu3hook/mu3-dll.c | 38 +++++++-- mu3hook/mu3-dll.h | 2 + mu3hook/mu3hook.def | 2 + mu3io/mu3io.c | 12 ++- mu3io/mu3io.h | 49 +++++++++++ subprojects/capnhook.wrap | 4 +- unityhook/doorstop.c | 4 +- unityhook/hook.c | 45 ++++++++++- 27 files changed, 406 insertions(+), 186 deletions(-) delete mode 100644 hooklib/procaddr.c delete mode 100644 hooklib/procaddr.h diff --git a/cxbhook/led.c b/cxbhook/led.c index be3f26f..b7d4f9b 100644 --- a/cxbhook/led.c +++ b/cxbhook/led.c @@ -5,7 +5,7 @@ #include "cxbhook/led.h" #include "cxbhook/cxb-dll.h" -#include "hooklib/procaddr.h" +#include "hook/procaddr.h" #include "hook/table.h" @@ -56,7 +56,7 @@ HRESULT led_hook_init(struct led_config *cfg) } dprintf("LED: Hook enabled.\n"); - return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms)); + return proc_addr_table_push(NULL, "CommLamp.dll", lamp_syms, _countof(lamp_syms)); } static int my_cCommLamp_Open(char *port) diff --git a/cxbhook/revio.c b/cxbhook/revio.c index 601c75a..7b3d25b 100644 --- a/cxbhook/revio.c +++ b/cxbhook/revio.c @@ -6,7 +6,7 @@ #include "cxbhook/revio.h" #include "cxbhook/cxb-dll.h" -#include "hooklib/procaddr.h" +#include "hook/procaddr.h" #include "hook/table.h" @@ -89,7 +89,7 @@ HRESULT revio_hook_init(struct revio_config *cfg) } dprintf("Revio: Hook enabled.\n"); - return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms)); + return proc_addr_table_push(NULL, "CommIo.dll", revio_syms, _countof(revio_syms)); } static int my_cCommIo_Open(char *port) diff --git a/dist/fgo/segatools.ini b/dist/fgo/segatools.ini index 2afe1fe..0884c2d 100644 --- a/dist/fgo/segatools.ini +++ b/dist/fgo/segatools.ini @@ -128,7 +128,6 @@ path= ; world. An improved solution will be provided later. [io4] -; Input API selection for JVS input emulator. ; Test button virtual-key code. Default is the F1 key. test=0x70 ; Service button virtual-key code. Default is the F2 key. diff --git a/dist/mu3/segatools.ini b/dist/mu3/segatools.ini index c55cbbb..1da77e9 100644 --- a/dist/mu3/segatools.ini +++ b/dist/mu3/segatools.ini @@ -73,6 +73,9 @@ dipsw1=1 enable=1 [unity] +; Enable Unity hook. This will allow you to run custom .NET code before the game +enable=1 + ; Path to a .NET DLL that should run before the game. Useful for loading ; modding frameworks such as BepInEx. targetAssembly= diff --git a/fgohook/fgo-dll.c b/fgohook/fgo-dll.c index dce25ab..991ec06 100644 --- a/fgohook/fgo-dll.c +++ b/fgohook/fgo-dll.c @@ -28,7 +28,7 @@ const struct dll_bind_sym fgo_dll_syms[] = { .sym = "fgo_io_led_init", .off = offsetof(struct fgo_dll, led_init), }, { - .sym = "fgo_io_led_set_leds", + .sym = "fgo_io_led_set_colors", .off = offsetof(struct fgo_dll, led_set_leds), } }; diff --git a/fgohook/fgohook.def b/fgohook/fgohook.def index 2f4c1c6..4f769fe 100644 --- a/fgohook/fgohook.def +++ b/fgohook/fgohook.def @@ -18,7 +18,7 @@ EXPORTS fgo_io_init fgo_io_poll fgo_io_led_init - fgo_io_led_set_leds + fgo_io_led_set_colors fwdlusb_open fwdlusb_close fwdlusb_listupPrinter diff --git a/fgoio/fgoio.c b/fgoio/fgoio.c index ff3e953..faba36c 100644 --- a/fgoio/fgoio.c +++ b/fgoio/fgoio.c @@ -145,7 +145,7 @@ HRESULT fgo_io_led_init(void) return S_OK; } -void fgo_io_led_set_leds(uint8_t board, uint8_t *rgb) +void fgo_io_led_set_colors(uint8_t board, uint8_t *rgb) { return; -} \ No newline at end of file +} diff --git a/fgoio/fgoio.h b/fgoio/fgoio.h index 5a815a7..1adf6b7 100644 --- a/fgoio/fgoio.h +++ b/fgoio/fgoio.h @@ -83,4 +83,4 @@ HRESULT fgo_io_led_init(void); Exact layout is TBD. */ -void fgo_io_led_set_leds(uint8_t board, uint8_t *rgb); +void fgo_io_led_set_colors(uint8_t board, uint8_t *rgb); diff --git a/hooklib/meson.build b/hooklib/meson.build index 4f7f762..4a74e05 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -23,8 +23,6 @@ hooklib_lib = static_library( 'fdshark.h', 'path.c', 'path.h', - 'procaddr.c', - 'procaddr.h', 'reg.c', 'reg.h', 'setupapi.c', diff --git a/hooklib/procaddr.c b/hooklib/procaddr.c deleted file mode 100644 index 2409f28..0000000 --- a/hooklib/procaddr.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include - -#include "hooklib/procaddr.h" - -#include "hook/table.h" - -#include "util/dprintf.h" - -static struct proc_addr_table *proc_addr_hook_list; -static size_t proc_addr_hook_count; -static CRITICAL_SECTION proc_addr_hook_lock; -static bool proc_addr_hook_initted; - -static FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name); -static FARPROC (WINAPI *next_GetProcAddress)(HMODULE hModule, const char *name); -static void proc_addr_hook_init(void); - -static const struct hook_symbol win32_hooks[] = { - { - .name = "GetProcAddress", - .patch = my_GetProcAddress, - .link = (void **) &next_GetProcAddress - } -}; - -HRESULT proc_addr_table_push( - const char *target, - struct hook_symbol *syms, - size_t nsyms -) -{ - HRESULT hr; - struct proc_addr_table *new_item; - struct proc_addr_table *new_mem; - - proc_addr_hook_init(); - - EnterCriticalSection(&proc_addr_hook_lock); - - new_mem = realloc( - proc_addr_hook_list, - (proc_addr_hook_count + 1) * sizeof(struct proc_addr_table)); - - if (new_mem == NULL) { - hr = E_OUTOFMEMORY; - - LeaveCriticalSection(&proc_addr_hook_lock); - return hr; - } - - new_item = &new_mem[proc_addr_hook_count]; - new_item->name = target; - new_item->nsyms = nsyms; - new_item->syms = syms; - - proc_addr_hook_list = new_mem; - proc_addr_hook_count++; - hr = S_OK; - - LeaveCriticalSection(&proc_addr_hook_lock); - - return hr; -} - -static void proc_addr_hook_init(void) -{ - if (proc_addr_hook_initted) { - return; - } - - dprintf("ProcAddr: Hook init\n"); - proc_addr_hook_initted = true; - - InitializeCriticalSection(&proc_addr_hook_lock); - - hook_table_apply( - NULL, - "kernel32.dll", - win32_hooks, - _countof(win32_hooks)); -} - -FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name) -{ - uintptr_t ordinal = (uintptr_t) name; - char mod_path[PATH_MAX]; - char *mod_name; - const struct hook_symbol *sym; - FARPROC result = next_GetProcAddress(hModule, name); - - GetModuleFileNameA(hModule, mod_path, PATH_MAX); - mod_name = basename(mod_path); - - for (int i = 0; i < proc_addr_hook_count; i++) { - - if (strcmp(proc_addr_hook_list[i].name, mod_name) == 0) { - - for (int j = 0; j < proc_addr_hook_list[i].nsyms; j++) { - sym = &proc_addr_hook_list[i].syms[j]; - - if (ordinal > 0xFFFF) { - - if (strcmp(sym->name, name) == 0) { - - dprintf("ProcAddr: Hooking %s from %s\n", name, mod_name); - result = (FARPROC) sym->patch; - } - } - - else { - if (sym->ordinal == ordinal) { - - dprintf("ProcAddr: Hooking Ord %p from %s\n", (void *)ordinal, mod_name); - result = (FARPROC) sym->patch; - } - } - } - } - } - - return result; -} \ No newline at end of file diff --git a/hooklib/procaddr.h b/hooklib/procaddr.h deleted file mode 100644 index 750e154..0000000 --- a/hooklib/procaddr.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include -#include - -#include "hook/table.h" - -struct proc_addr_table { - const char *name; - size_t nsyms; - struct hook_symbol *syms; -}; - -HRESULT proc_addr_table_push( - const char *target, - struct hook_symbol *syms, - size_t nsyms -); \ No newline at end of file diff --git a/hooklib/reg.c b/hooklib/reg.c index cc3c584..bc18dbb 100644 --- a/hooklib/reg.c +++ b/hooklib/reg.c @@ -7,6 +7,7 @@ #include "hook/table.h" #include "hooklib/reg.h" +#include "hook/procaddr.h" #include "util/dprintf.h" #include "util/str.h" @@ -99,6 +100,29 @@ static LSTATUS WINAPI hook_RegGetValueW( uint32_t *numData ); +static LSTATUS WINAPI hook_RegQueryInfoKeyW( + HKEY hKey, + LPWSTR lpClass, + LPDWORD lpcchClass, + LPDWORD lpReserved, + LPDWORD lpcSubKeys, + LPDWORD lpcbMaxSubKeyLen, + LPDWORD lpcbMaxClassLen, + LPDWORD lpcValues, + LPDWORD lpcbMaxValueNameLen, + LPDWORD lpcbMaxValueLen, + LPDWORD lpcbSecurityDescriptor, + PFILETIME lpftLastWriteTime); + +static LSTATUS WINAPI hook_RegEnumValueW( + HKEY hkey, + DWORD dwIndex, + LPWSTR lpValueName, + LPDWORD lpcchValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData); /* Link pointers */ static LSTATUS (WINAPI *next_RegOpenKeyExW)( @@ -155,6 +179,30 @@ static LSTATUS (WINAPI *next_RegGetValueW)( uint32_t *numData ); +static LSTATUS (WINAPI *next_RegQueryInfoKeyW)( + HKEY hKey, + LPWSTR lpClass, + LPDWORD lpcchClass, + LPDWORD lpReserved, + LPDWORD lpcSubKeys, + LPDWORD lpcbMaxSubKeyLen, + LPDWORD lpcbMaxClassLen, + LPDWORD lpcValues, + LPDWORD lpcbMaxValueNameLen, + LPDWORD lpcbMaxValueLen, + LPDWORD lpcbSecurityDescriptor, + PFILETIME lpftLastWriteTime); + +static LSTATUS (WINAPI *next_RegEnumValueW)( + HKEY hkey, + DWORD dwIndex, + LPWSTR lpValueName, + LPDWORD lpcchValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData); + static const struct hook_symbol reg_hook_syms[] = { { .name = "RegOpenKeyExW", @@ -184,6 +232,14 @@ static const struct hook_symbol reg_hook_syms[] = { .name = "RegGetValueW", .patch = hook_RegGetValueW, .link = (void **) &next_RegGetValueW, + }, { + .name = "RegQueryInfoKeyW", + .patch = hook_RegQueryInfoKeyW, + .link = (void **) &next_RegQueryInfoKeyW, + }, { + .name = "RegEnumValueW", + .patch = hook_RegEnumValueW, + .link = (void **) &next_RegEnumValueW, } }; @@ -254,11 +310,24 @@ static void reg_hook_init(void) InitializeCriticalSection(®_hook_lock); dprintf("Reg hook init\n"); + reg_hook_insert_hooks(NULL); + + proc_addr_table_push( + NULL, + "ADVAPI32.dll", + (struct hook_symbol *) reg_hook_syms, + _countof(reg_hook_syms)); + +} + +void reg_hook_insert_hooks(HMODULE target) +{ hook_table_apply( - NULL, + target, "advapi32.dll", reg_hook_syms, _countof(reg_hook_syms)); + } static LRESULT reg_hook_propagate_hr(HRESULT hr) @@ -331,6 +400,7 @@ static LSTATUS reg_hook_open_locked( /* Assume reg keys are referenced from a root key and not from some intermediary key */ key = ®_hook_keys[i]; + //dprintf("Reg: %ls vs %ls\n", name, key->name); if (key->root == parent && wstr_ieq(key->name, name)) { break; @@ -821,6 +891,99 @@ static LSTATUS WINAPI hook_RegGetValueW( return err; } +static LSTATUS WINAPI hook_RegQueryInfoKeyW( + HKEY hKey, + LPWSTR lpClass, + LPDWORD lpcchClass, + LPDWORD lpReserved, + LPDWORD lpcSubKeys, + LPDWORD lpcbMaxSubKeyLen, + LPDWORD lpcbMaxClassLen, + LPDWORD lpcValues, + LPDWORD lpcbMaxValueNameLen, + LPDWORD lpcbMaxValueLen, + LPDWORD lpcbSecurityDescriptor, + PFILETIME lpftLastWriteTime) +{ + struct reg_hook_key *key; + LSTATUS err; + + EnterCriticalSection(®_hook_lock); + + key = reg_hook_match_key_locked(hKey); + + /* Check if this is a virtualized registry key */ + + if (key == NULL) { + LeaveCriticalSection(®_hook_lock); + + return next_RegQueryInfoKeyW( + hKey, + lpClass, + lpcchClass, + lpReserved, + lpcSubKeys, + lpcbMaxSubKeyLen, + lpcbMaxClassLen, + lpcValues, + lpcbMaxValueNameLen, + lpcbMaxValueLen, + lpcbSecurityDescriptor, + lpftLastWriteTime); + } + + // This is the only one I've seen even be changed, so it's all I'm doing + // until I see otherwise. + *lpcValues = key->nvals; + LeaveCriticalSection(®_hook_lock); + return ERROR_SUCCESS; +} + +static LSTATUS WINAPI hook_RegEnumValueW( + HKEY hkey, + DWORD dwIndex, + LPWSTR lpValueName, + LPDWORD lpcchValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData) +{ + struct reg_hook_key *key; + HRESULT hr; + LSTATUS err; + + EnterCriticalSection(®_hook_lock); + + key = reg_hook_match_key_locked(hkey); + + /* Check if this is a virtualized registry key */ + + if (key == NULL) { + LeaveCriticalSection(®_hook_lock); + + return next_RegEnumValueW( + hkey, + dwIndex, + lpValueName, + lpcchValueName, + lpReserved, + lpType, + lpData, + lpcbData); + } + + if (dwIndex >= key->nvals) { + LeaveCriticalSection(®_hook_lock); + return ERROR_NO_MORE_ITEMS; // Pretty sure this is what it actually returns here? + } + + wcscpy_s(lpValueName, *lpcchValueName, key->vals[dwIndex].name); + *lpcchValueName = wcslen(key->vals[dwIndex].name); + LeaveCriticalSection(®_hook_lock); + return ERROR_SUCCESS; +} + HRESULT reg_hook_read_bin( void *bytes, uint32_t *nbytes, diff --git a/hooklib/reg.h b/hooklib/reg.h index eb280c6..20e3dda 100644 --- a/hooklib/reg.h +++ b/hooklib/reg.h @@ -12,6 +12,8 @@ struct reg_hook_val { uint32_t type; }; +void reg_hook_insert_hooks(HMODULE target); + HRESULT reg_hook_push_key( HKEY root, const wchar_t *name, diff --git a/hooklib/touch.c b/hooklib/touch.c index df6a9ea..a76692a 100644 --- a/hooklib/touch.c +++ b/hooklib/touch.c @@ -119,10 +119,19 @@ void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE sel defaultCursor = LoadCursorA(NULL, IDC_CROSS); memcpy(&touch_config, cfg, sizeof(*cfg)); - hook_table_apply(NULL, "user32.dll", touch_hooks, _countof(touch_hooks)); + touch_hook_insert_hooks(NULL); dprintf("TOUCH: hook enabled.\n"); } +void touch_hook_insert_hooks(HMODULE target) +{ + hook_table_apply( + target, + "user32.dll", + touch_hooks, + _countof(touch_hooks)); +} + static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor) { if (cursor == 0 && touch_config.cursor) return next_SetCursor(defaultCursor); diff --git a/hooklib/touch.h b/hooklib/touch.h index dad00ad..dcb9082 100644 --- a/hooklib/touch.h +++ b/hooklib/touch.h @@ -14,3 +14,4 @@ struct touch_screen_config { blah blah you know the drill by now. */ void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self); +void touch_hook_insert_hooks(HMODULE target); diff --git a/meson.build b/meson.build index 90ac292..d5d28a6 100644 --- a/meson.build +++ b/meson.build @@ -14,6 +14,7 @@ add_project_arguments( '-D_WIN32_WINNT=_WIN32_WINNT_WIN7', '-DMINGW_HAS_SECURE_API=1', '-Wno-unused', + # '-ggdb', # Add debug information language: 'c', ) @@ -23,7 +24,6 @@ if cc.get_id() != 'msvc' add_project_arguments( '-ffunction-sections', '-fdata-sections', - '-flto', # Enable Link-Time Optimization language: 'c', ) @@ -32,8 +32,9 @@ if cc.get_id() != 'msvc' '-Wl,--exclude-all-symbols', '-Wl,--gc-sections', '-static-libgcc', - '-flto', # Enable Link-Time Optimization - '-Wl,-s', # Strip debug symbols + # '-ggdb', # Add debug information + '-lcrypt32', # Bcrypt needed for prashook + # '-Wl,-s', # Strip debug symbols language: 'c', ) endif diff --git a/mu3hook/config.c b/mu3hook/config.c index 290d5ae..32d4341 100644 --- a/mu3hook/config.c +++ b/mu3hook/config.c @@ -28,6 +28,66 @@ void mu3_dll_config_load( filename); } +void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + wchar_t tmpstr[16]; + + memset(cfg->board_number, ' ', sizeof(cfg->board_number)); + memset(cfg->chip_number, ' ', sizeof(cfg->chip_number)); + memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); + + cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); + cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); + cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); + cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); + + GetPrivateProfileStringW( + L"led15093", + L"boardNumber", + L"15093-06", + tmpstr, + _countof(tmpstr), + filename); + + size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number)); + for (int i = n; i < sizeof(cfg->board_number); i++) + { + cfg->board_number[i] = ' '; + } + + GetPrivateProfileStringW( + L"led15093", + L"chipNumber", + L"6710A", + tmpstr, + _countof(tmpstr), + filename); + + n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number)); + for (int i = n; i < sizeof(cfg->chip_number); i++) + { + cfg->chip_number[i] = ' '; + } + + GetPrivateProfileStringW( + L"led15093", + L"bootChipNumber", + L"6709 ", + tmpstr, + _countof(tmpstr), + filename); + + n = wcstombs(cfg->boot_chip_number, tmpstr, sizeof(cfg->boot_chip_number)); + for (int i = n; i < sizeof(cfg->boot_chip_number); i++) + { + cfg->boot_chip_number[i] = ' '; + } +} + void mu3_hook_config_load( struct mu3_hook_config *cfg, const wchar_t *filename) @@ -40,6 +100,7 @@ void mu3_hook_config_load( dvd_config_load(&cfg->dvd, filename); io4_config_load(&cfg->io4, filename); gfx_config_load(&cfg->gfx, filename); + led15093_config_load(&cfg->led15093, filename); vfd_config_load(&cfg->vfd, filename); mu3_dll_config_load(&cfg->dll, filename); unity_config_load(&cfg->unity, filename); diff --git a/mu3hook/config.h b/mu3hook/config.h index 930a766..b2094c2 100644 --- a/mu3hook/config.h +++ b/mu3hook/config.h @@ -3,7 +3,7 @@ #include #include "board/config.h" -// #include "board/led15093.h" +#include "board/led15093.h" #include "gfxhook/gfx.h" @@ -21,7 +21,7 @@ struct mu3_hook_config { struct dvd_config dvd; struct io4_config io4; struct gfx_config gfx; - // struct led15093_config led15093; + struct led15093_config led15093; struct vfd_config vfd; struct mu3_dll_config dll; struct unity_config unity; diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index bd1ec2b..c4495c1 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -62,14 +62,18 @@ static DWORD CALLBACK mu3_pre_startup(void) goto fail; } - /* - // Does not work, Unity moment - hr = led15093_hook_init(&mu3_hook_cfg.led15093, 3, 1, 1, 2); + hr = mu3_dll_init(&mu3_hook_cfg.dll, mu3_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + + hr = led15093_hook_init(&mu3_hook_cfg.led15093, + mu3_dll.led_init, mu3_dll.led_set_leds, 3, 1, 1, 2); if (FAILED(hr)) { return hr; } - */ hr = sg_reader_hook_init(&mu3_hook_cfg.aime, 1, 1, mu3_hook_mod); @@ -83,12 +87,6 @@ static DWORD CALLBACK mu3_pre_startup(void) goto fail; } - hr = mu3_dll_init(&mu3_hook_cfg.dll, mu3_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - hr = mu3_io4_hook_init(&mu3_hook_cfg.io4); if (FAILED(hr)) { diff --git a/mu3hook/mu3-dll.c b/mu3hook/mu3-dll.c index 9e8e93e..6acf929 100644 --- a/mu3hook/mu3-dll.c +++ b/mu3hook/mu3-dll.c @@ -24,9 +24,28 @@ const struct dll_bind_sym mu3_dll_syms[] = { }, { .sym = "mu3_io_get_lever", .off = offsetof(struct mu3_dll, get_lever), + }, { + .sym = "mu3_io_led_init", + .off = offsetof(struct mu3_dll, led_init), + }, { + .sym = "mu3_io_led_set_colors", + .off = offsetof(struct mu3_dll, led_set_leds), } }; +/* Helper function to determine upon dll_bind failure whether the required functions were found + NOTE: relies on symbols order declared above */ +static HRESULT has_enough_symbols(uint16_t version, uint8_t count) +{ + if ( version <= 0x0100 && count == 5 ) + return S_OK; + + if ( version >= 0x0101 && count == 7 ) + return S_OK; + + return E_FAIL; +} + struct mu3_dll mu3_dll; // Copypasta DLL binding and diagnostic message boilerplate. @@ -86,16 +105,25 @@ HRESULT mu3_dll_init(const struct mu3_dll_config *cfg, HINSTANCE self) } sym = mu3_dll_syms; + const struct dll_bind_sym *init_sym = &sym[0]; + hr = dll_bind(&mu3_dll, src, &sym, _countof(mu3_dll_syms)); if (FAILED(hr)) { if (src != self) { - dprintf("Ongeki IO: Custom IO DLL does not provide function " - "\"%s\". Please contact your IO DLL's developer for " - "further assistance.\n", - sym->sym); + // Might still be ok depending on external dll API version + int bind_count = sym - init_sym; + if (has_enough_symbols(mu3_dll.api_version, bind_count) == S_OK) + { + hr = S_OK; + } else { + dprintf("Ongeki IO: Custom IO DLL does not provide function " + "\"%s\". Please contact your IO DLL's developer for " + "further assistance.\n", + sym->sym); - goto end; + goto end; + } } else { dprintf("Internal error: could not reflect \"%s\"\n", sym->sym); } diff --git a/mu3hook/mu3-dll.h b/mu3hook/mu3-dll.h index 41f280f..2a919ea 100644 --- a/mu3hook/mu3-dll.h +++ b/mu3hook/mu3-dll.h @@ -11,6 +11,8 @@ struct mu3_dll { void (*get_opbtns)(uint8_t *opbtn); void (*get_gamebtns)(uint8_t *left, uint8_t *right); void (*get_lever)(int16_t *pos); + HRESULT (*led_init)(void); + void (*led_set_leds)(uint8_t board, uint8_t *rgb); }; struct mu3_dll_config { diff --git a/mu3hook/mu3hook.def b/mu3hook/mu3hook.def index d90abd5..0393a2e 100644 --- a/mu3hook/mu3hook.def +++ b/mu3hook/mu3hook.def @@ -23,3 +23,5 @@ EXPORTS mu3_io_get_opbtns mu3_io_init mu3_io_poll + mu3_io_led_init + mu3_io_led_set_colors diff --git a/mu3io/mu3io.c b/mu3io/mu3io.c index cb8d6e3..918c22d 100644 --- a/mu3io/mu3io.c +++ b/mu3io/mu3io.c @@ -21,7 +21,7 @@ const double MOUSE_SENSITIVITY = 0.5; uint16_t mu3_io_get_api_version(void) { - return 0x0100; + return 0x0101; } HRESULT mu3_io_init(void) @@ -195,3 +195,13 @@ void mu3_io_get_lever(int16_t *pos) *pos = mu3_lever_xpos; } } + +HRESULT mu3_io_led_init(void) +{ + return S_OK; +} + +void mu3_io_led_set_colors(uint8_t board, uint8_t *rgb) +{ + return; +} diff --git a/mu3io/mu3io.h b/mu3io/mu3io.h index a156038..522ef1b 100644 --- a/mu3io/mu3io.h +++ b/mu3io/mu3io.h @@ -1,5 +1,15 @@ #pragma once +/* + MU3 CUSTOM IO API + + Changelog: + + - 0x0100: Initial API version (assumed if chuni_io_get_api_version is not + exported) + - 0x0101: Added mu3_io_led_init and mu3_io_set_leds +*/ + #include #include @@ -18,6 +28,29 @@ enum { MU3_IO_GAMEBTN_MENU = 0x10, }; +enum { + /* These are the bitmasks to use when checking which + lights are triggered on incoming IO4 GPIO writes. */ + MU3_IO_LED_L1_R = 1 << 31, + MU3_IO_LED_L1_G = 1 << 28, + MU3_IO_LED_L1_B = 1 << 30, + MU3_IO_LED_L2_R = 1 << 27, + MU3_IO_LED_L2_G = 1 << 29, + MU3_IO_LED_L2_B = 1 << 26, + MU3_IO_LED_L3_R = 1 << 25, + MU3_IO_LED_L3_G = 1 << 24, + MU3_IO_LED_L3_B = 1 << 23, + MU3_IO_LED_R1_R = 1 << 22, + MU3_IO_LED_R1_G = 1 << 21, + MU3_IO_LED_R1_B = 1 << 20, + MU3_IO_LED_R2_R = 1 << 19, + MU3_IO_LED_R2_G = 1 << 18, + MU3_IO_LED_R2_B = 1 << 17, + MU3_IO_LED_R3_R = 1 << 16, + MU3_IO_LED_R3_G = 1 << 15, + MU3_IO_LED_R3_B = 1 << 14, +}; + /* Get the version of the Ongeki IO API that this DLL supports. This function should return a positive 16-bit integer, where the high byte is the major version and the low byte is the minor version (as defined by the @@ -83,3 +116,19 @@ void mu3_io_get_gamebtns(uint8_t *left, uint8_t *right); Minimum API version: 0x0100 */ void mu3_io_get_lever(int16_t *pos); + + +/* Initialize LED emulation. This function will be called before any + other mu3_io_led_*() function calls. + + All subsequent calls may originate from arbitrary threads and some may + overlap with each other. Ensuring synchronization inside your IO DLL is + your responsibility. */ + +HRESULT mu3_io_led_init(void); + +/* Update the RGB LEDs. + + Exact layout is TBD. */ + +void mu3_io_led_set_colors(uint8_t board, uint8_t *rgb); diff --git a/subprojects/capnhook.wrap b/subprojects/capnhook.wrap index af30eae..584b4a1 100644 --- a/subprojects/capnhook.wrap +++ b/subprojects/capnhook.wrap @@ -1,4 +1,4 @@ [wrap-git] directory = capnhook -url = https://github.com/decafcode/capnhook -revision = 69f7e3b48c2e0ff5be1d7a83cdcc2597a458357b +url = https://github.com/Hay1tsme/capnhook +revision = 09306229f1fd09bae0e617865a26778d3537ff93 diff --git a/unityhook/doorstop.c b/unityhook/doorstop.c index ff4d269..1b94ad5 100644 --- a/unityhook/doorstop.c +++ b/unityhook/doorstop.c @@ -8,7 +8,7 @@ #include #include -#include "hooklib/procaddr.h" +#include "hook/procaddr.h" #include "util/dprintf.h" #include "doorstop.h" @@ -37,7 +37,7 @@ void doorstop_mono_hook_init(const struct unity_config *cfg, HINSTANCE module) { memcpy(&unity_config, cfg, sizeof(*cfg)); load_mono_functions(module); - proc_addr_table_push(module_name, unity_mono_syms, _countof(unity_mono_syms)); + proc_addr_table_push(NULL, module_name, unity_mono_syms, _countof(unity_mono_syms)); doorstop_hook_initted = true; } diff --git a/unityhook/hook.c b/unityhook/hook.c index 060233b..02a1e38 100644 --- a/unityhook/hook.c +++ b/unityhook/hook.c @@ -2,7 +2,16 @@ #include #include "hook/table.h" +#include "hook/procaddr.h" +#include "hook/iohook.h" + +#include "hooklib/dll.h" #include "hooklib/path.h" +#include "hooklib/printer.h" +#include "hooklib/reg.h" +#include "hooklib/touch.h" +#include "hooklib/serial.h" + #include "util/dprintf.h" #include "doorstop.h" @@ -15,22 +24,35 @@ static const wchar_t *target_modules[] = { L"mono.dll", L"mono-2.0-bdwgc.dll", L"cri_ware_unity.dll", + L"SerialPortAPI.dll", + L"C300usb.dll", + L"C300FWDLusb.dll", + L"apmled.dll", + L"apmmount.dll", }; + static const size_t target_modules_len = _countof(target_modules); static void dll_hook_insert_hooks(HMODULE target); -static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name); +static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name); static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name); +static HMODULE WINAPI hook_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags); +static HMODULE (WINAPI *next_LoadLibraryExW)(const wchar_t *name, HANDLE hFile, DWORD dwFlags); static const struct hook_symbol unity_kernel32_syms[] = { { .name = "LoadLibraryW", - .patch = my_LoadLibraryW, + .patch = hook_LoadLibraryW, .link = (void **) &next_LoadLibraryW, - }, + }, { + .name = "LoadLibraryExW", + .patch = hook_LoadLibraryExW, + .link = (void **) &next_LoadLibraryExW, + } }; + void unity_hook_init(const struct unity_config *cfg, HINSTANCE self) { assert(cfg != NULL); @@ -57,7 +79,14 @@ static void dll_hook_insert_hooks(HMODULE target) { _countof(unity_kernel32_syms)); } -static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name) { +static HMODULE WINAPI hook_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags) +{ + // dprintf("Unity: LoadLibraryExW %ls\n", name); + return hook_LoadLibraryW(name); +} + +static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name) +{ const wchar_t *name_end; const wchar_t *target_module; bool already_loaded; @@ -107,6 +136,14 @@ static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name) { dll_hook_insert_hooks(result); path_hook_insert_hooks(result); + + // printer_hook_insert_hooks(result); + + reg_hook_insert_hooks(result); + + proc_addr_insert_hooks(result); + serial_hook_apply_hooks(result); + iohook_apply_hooks(result); } }