switched to new capnhook, updated unityhook, added LED 15093 to MU3

This commit is contained in:
Dniel97 2024-05-12 19:36:08 +02:00
parent 1069cfee26
commit 517469a60c
Signed by untrusted user: Dniel97
GPG Key ID: 6180B3C768FB2E08
27 changed files with 406 additions and 186 deletions

View File

@ -5,7 +5,7 @@
#include "cxbhook/led.h" #include "cxbhook/led.h"
#include "cxbhook/cxb-dll.h" #include "cxbhook/cxb-dll.h"
#include "hooklib/procaddr.h" #include "hook/procaddr.h"
#include "hook/table.h" #include "hook/table.h"
@ -56,7 +56,7 @@ HRESULT led_hook_init(struct led_config *cfg)
} }
dprintf("LED: Hook enabled.\n"); 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) static int my_cCommLamp_Open(char *port)

View File

@ -6,7 +6,7 @@
#include "cxbhook/revio.h" #include "cxbhook/revio.h"
#include "cxbhook/cxb-dll.h" #include "cxbhook/cxb-dll.h"
#include "hooklib/procaddr.h" #include "hook/procaddr.h"
#include "hook/table.h" #include "hook/table.h"
@ -89,7 +89,7 @@ HRESULT revio_hook_init(struct revio_config *cfg)
} }
dprintf("Revio: Hook enabled.\n"); 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) static int my_cCommIo_Open(char *port)

View File

@ -128,7 +128,6 @@ path=
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Input API selection for JVS input emulator.
; Test button virtual-key code. Default is the F1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x70 test=0x70
; Service button virtual-key code. Default is the F2 key. ; Service button virtual-key code. Default is the F2 key.

View File

@ -73,6 +73,9 @@ dipsw1=1
enable=1 enable=1
[unity] [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 ; Path to a .NET DLL that should run before the game. Useful for loading
; modding frameworks such as BepInEx. ; modding frameworks such as BepInEx.
targetAssembly= targetAssembly=

View File

@ -28,7 +28,7 @@ const struct dll_bind_sym fgo_dll_syms[] = {
.sym = "fgo_io_led_init", .sym = "fgo_io_led_init",
.off = offsetof(struct fgo_dll, 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), .off = offsetof(struct fgo_dll, led_set_leds),
} }
}; };

View File

@ -18,7 +18,7 @@ EXPORTS
fgo_io_init fgo_io_init
fgo_io_poll fgo_io_poll
fgo_io_led_init fgo_io_led_init
fgo_io_led_set_leds fgo_io_led_set_colors
fwdlusb_open fwdlusb_open
fwdlusb_close fwdlusb_close
fwdlusb_listupPrinter fwdlusb_listupPrinter

View File

@ -145,7 +145,7 @@ HRESULT fgo_io_led_init(void)
return S_OK; 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; return;
} }

View File

@ -83,4 +83,4 @@ HRESULT fgo_io_led_init(void);
Exact layout is TBD. */ 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);

View File

@ -23,8 +23,6 @@ hooklib_lib = static_library(
'fdshark.h', 'fdshark.h',
'path.c', 'path.c',
'path.h', 'path.h',
'procaddr.c',
'procaddr.h',
'reg.c', 'reg.c',
'reg.h', 'reg.h',
'setupapi.c', 'setupapi.c',

View File

@ -1,125 +0,0 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <libgen.h>
#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;
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#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
);

View File

@ -7,6 +7,7 @@
#include "hook/table.h" #include "hook/table.h"
#include "hooklib/reg.h" #include "hooklib/reg.h"
#include "hook/procaddr.h"
#include "util/dprintf.h" #include "util/dprintf.h"
#include "util/str.h" #include "util/str.h"
@ -99,6 +100,29 @@ static LSTATUS WINAPI hook_RegGetValueW(
uint32_t *numData 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 */ /* Link pointers */
static LSTATUS (WINAPI *next_RegOpenKeyExW)( static LSTATUS (WINAPI *next_RegOpenKeyExW)(
@ -155,6 +179,30 @@ static LSTATUS (WINAPI *next_RegGetValueW)(
uint32_t *numData 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[] = { static const struct hook_symbol reg_hook_syms[] = {
{ {
.name = "RegOpenKeyExW", .name = "RegOpenKeyExW",
@ -184,6 +232,14 @@ static const struct hook_symbol reg_hook_syms[] = {
.name = "RegGetValueW", .name = "RegGetValueW",
.patch = hook_RegGetValueW, .patch = hook_RegGetValueW,
.link = (void **) &next_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(&reg_hook_lock); InitializeCriticalSection(&reg_hook_lock);
dprintf("Reg hook init\n"); 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( hook_table_apply(
NULL, target,
"advapi32.dll", "advapi32.dll",
reg_hook_syms, reg_hook_syms,
_countof(reg_hook_syms)); _countof(reg_hook_syms));
} }
static LRESULT reg_hook_propagate_hr(HRESULT hr) 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 /* Assume reg keys are referenced from a root key and not from some
intermediary key */ intermediary key */
key = &reg_hook_keys[i]; key = &reg_hook_keys[i];
//dprintf("Reg: %ls vs %ls\n", name, key->name);
if (key->root == parent && wstr_ieq(key->name, name)) { if (key->root == parent && wstr_ieq(key->name, name)) {
break; break;
@ -821,6 +891,99 @@ static LSTATUS WINAPI hook_RegGetValueW(
return err; 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(&reg_hook_lock);
key = reg_hook_match_key_locked(hKey);
/* Check if this is a virtualized registry key */
if (key == NULL) {
LeaveCriticalSection(&reg_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(&reg_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(&reg_hook_lock);
key = reg_hook_match_key_locked(hkey);
/* Check if this is a virtualized registry key */
if (key == NULL) {
LeaveCriticalSection(&reg_hook_lock);
return next_RegEnumValueW(
hkey,
dwIndex,
lpValueName,
lpcchValueName,
lpReserved,
lpType,
lpData,
lpcbData);
}
if (dwIndex >= key->nvals) {
LeaveCriticalSection(&reg_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(&reg_hook_lock);
return ERROR_SUCCESS;
}
HRESULT reg_hook_read_bin( HRESULT reg_hook_read_bin(
void *bytes, void *bytes,
uint32_t *nbytes, uint32_t *nbytes,

View File

@ -12,6 +12,8 @@ struct reg_hook_val {
uint32_t type; uint32_t type;
}; };
void reg_hook_insert_hooks(HMODULE target);
HRESULT reg_hook_push_key( HRESULT reg_hook_push_key(
HKEY root, HKEY root,
const wchar_t *name, const wchar_t *name,

View File

@ -119,10 +119,19 @@ void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE sel
defaultCursor = LoadCursorA(NULL, IDC_CROSS); defaultCursor = LoadCursorA(NULL, IDC_CROSS);
memcpy(&touch_config, cfg, sizeof(*cfg)); 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"); 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) { static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor) {
if (cursor == 0 && touch_config.cursor) if (cursor == 0 && touch_config.cursor)
return next_SetCursor(defaultCursor); return next_SetCursor(defaultCursor);

View File

@ -14,3 +14,4 @@ struct touch_screen_config {
blah blah you know the drill by now. */ blah blah you know the drill by now. */
void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self); void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self);
void touch_hook_insert_hooks(HMODULE target);

View File

@ -14,6 +14,7 @@ add_project_arguments(
'-D_WIN32_WINNT=_WIN32_WINNT_WIN7', '-D_WIN32_WINNT=_WIN32_WINNT_WIN7',
'-DMINGW_HAS_SECURE_API=1', '-DMINGW_HAS_SECURE_API=1',
'-Wno-unused', '-Wno-unused',
# '-ggdb', # Add debug information
language: 'c', language: 'c',
) )
@ -23,7 +24,6 @@ if cc.get_id() != 'msvc'
add_project_arguments( add_project_arguments(
'-ffunction-sections', '-ffunction-sections',
'-fdata-sections', '-fdata-sections',
'-flto', # Enable Link-Time Optimization
language: 'c', language: 'c',
) )
@ -32,8 +32,9 @@ if cc.get_id() != 'msvc'
'-Wl,--exclude-all-symbols', '-Wl,--exclude-all-symbols',
'-Wl,--gc-sections', '-Wl,--gc-sections',
'-static-libgcc', '-static-libgcc',
'-flto', # Enable Link-Time Optimization # '-ggdb', # Add debug information
'-Wl,-s', # Strip debug symbols '-lcrypt32', # Bcrypt needed for prashook
# '-Wl,-s', # Strip debug symbols
language: 'c', language: 'c',
) )
endif endif

View File

@ -28,6 +28,66 @@ void mu3_dll_config_load(
filename); 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( void mu3_hook_config_load(
struct mu3_hook_config *cfg, struct mu3_hook_config *cfg,
const wchar_t *filename) const wchar_t *filename)
@ -40,6 +100,7 @@ void mu3_hook_config_load(
dvd_config_load(&cfg->dvd, filename); dvd_config_load(&cfg->dvd, filename);
io4_config_load(&cfg->io4, filename); io4_config_load(&cfg->io4, filename);
gfx_config_load(&cfg->gfx, filename); gfx_config_load(&cfg->gfx, filename);
led15093_config_load(&cfg->led15093, filename);
vfd_config_load(&cfg->vfd, filename); vfd_config_load(&cfg->vfd, filename);
mu3_dll_config_load(&cfg->dll, filename); mu3_dll_config_load(&cfg->dll, filename);
unity_config_load(&cfg->unity, filename); unity_config_load(&cfg->unity, filename);

View File

@ -3,7 +3,7 @@
#include <stddef.h> #include <stddef.h>
#include "board/config.h" #include "board/config.h"
// #include "board/led15093.h" #include "board/led15093.h"
#include "gfxhook/gfx.h" #include "gfxhook/gfx.h"
@ -21,7 +21,7 @@ struct mu3_hook_config {
struct dvd_config dvd; struct dvd_config dvd;
struct io4_config io4; struct io4_config io4;
struct gfx_config gfx; struct gfx_config gfx;
// struct led15093_config led15093; struct led15093_config led15093;
struct vfd_config vfd; struct vfd_config vfd;
struct mu3_dll_config dll; struct mu3_dll_config dll;
struct unity_config unity; struct unity_config unity;

View File

@ -62,14 +62,18 @@ static DWORD CALLBACK mu3_pre_startup(void)
goto fail; goto fail;
} }
/* hr = mu3_dll_init(&mu3_hook_cfg.dll, mu3_hook_mod);
// Does not work, Unity moment
hr = led15093_hook_init(&mu3_hook_cfg.led15093, 3, 1, 1, 2); 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)) { if (FAILED(hr)) {
return hr; return hr;
} }
*/
hr = sg_reader_hook_init(&mu3_hook_cfg.aime, 1, 1, mu3_hook_mod); 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; 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); hr = mu3_io4_hook_init(&mu3_hook_cfg.io4);
if (FAILED(hr)) { if (FAILED(hr)) {

View File

@ -24,9 +24,28 @@ const struct dll_bind_sym mu3_dll_syms[] = {
}, { }, {
.sym = "mu3_io_get_lever", .sym = "mu3_io_get_lever",
.off = offsetof(struct mu3_dll, 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; struct mu3_dll mu3_dll;
// Copypasta DLL binding and diagnostic message boilerplate. // 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; sym = mu3_dll_syms;
const struct dll_bind_sym *init_sym = &sym[0];
hr = dll_bind(&mu3_dll, src, &sym, _countof(mu3_dll_syms)); hr = dll_bind(&mu3_dll, src, &sym, _countof(mu3_dll_syms));
if (FAILED(hr)) { if (FAILED(hr)) {
if (src != self) { if (src != self) {
dprintf("Ongeki IO: Custom IO DLL does not provide function " // Might still be ok depending on external dll API version
"\"%s\". Please contact your IO DLL's developer for " int bind_count = sym - init_sym;
"further assistance.\n", if (has_enough_symbols(mu3_dll.api_version, bind_count) == S_OK)
sym->sym); {
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 { } else {
dprintf("Internal error: could not reflect \"%s\"\n", sym->sym); dprintf("Internal error: could not reflect \"%s\"\n", sym->sym);
} }

View File

@ -11,6 +11,8 @@ struct mu3_dll {
void (*get_opbtns)(uint8_t *opbtn); void (*get_opbtns)(uint8_t *opbtn);
void (*get_gamebtns)(uint8_t *left, uint8_t *right); void (*get_gamebtns)(uint8_t *left, uint8_t *right);
void (*get_lever)(int16_t *pos); void (*get_lever)(int16_t *pos);
HRESULT (*led_init)(void);
void (*led_set_leds)(uint8_t board, uint8_t *rgb);
}; };
struct mu3_dll_config { struct mu3_dll_config {

View File

@ -23,3 +23,5 @@ EXPORTS
mu3_io_get_opbtns mu3_io_get_opbtns
mu3_io_init mu3_io_init
mu3_io_poll mu3_io_poll
mu3_io_led_init
mu3_io_led_set_colors

View File

@ -21,7 +21,7 @@ const double MOUSE_SENSITIVITY = 0.5;
uint16_t mu3_io_get_api_version(void) uint16_t mu3_io_get_api_version(void)
{ {
return 0x0100; return 0x0101;
} }
HRESULT mu3_io_init(void) HRESULT mu3_io_init(void)
@ -195,3 +195,13 @@ void mu3_io_get_lever(int16_t *pos)
*pos = mu3_lever_xpos; *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;
}

View File

@ -1,5 +1,15 @@
#pragma once #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 <windows.h> #include <windows.h>
#include <stdint.h> #include <stdint.h>
@ -18,6 +28,29 @@ enum {
MU3_IO_GAMEBTN_MENU = 0x10, 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 /* 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 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 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 */ Minimum API version: 0x0100 */
void mu3_io_get_lever(int16_t *pos); 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);

View File

@ -1,4 +1,4 @@
[wrap-git] [wrap-git]
directory = capnhook directory = capnhook
url = https://github.com/decafcode/capnhook url = https://github.com/Hay1tsme/capnhook
revision = 69f7e3b48c2e0ff5be1d7a83cdcc2597a458357b revision = 09306229f1fd09bae0e617865a26778d3537ff93

View File

@ -8,7 +8,7 @@
#include <pathcch.h> #include <pathcch.h>
#include <psapi.h> #include <psapi.h>
#include "hooklib/procaddr.h" #include "hook/procaddr.h"
#include "util/dprintf.h" #include "util/dprintf.h"
#include "doorstop.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)); memcpy(&unity_config, cfg, sizeof(*cfg));
load_mono_functions(module); 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; doorstop_hook_initted = true;
} }

View File

@ -2,7 +2,16 @@
#include <stdbool.h> #include <stdbool.h>
#include "hook/table.h" #include "hook/table.h"
#include "hook/procaddr.h"
#include "hook/iohook.h"
#include "hooklib/dll.h"
#include "hooklib/path.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 "util/dprintf.h"
#include "doorstop.h" #include "doorstop.h"
@ -15,22 +24,35 @@ static const wchar_t *target_modules[] = {
L"mono.dll", L"mono.dll",
L"mono-2.0-bdwgc.dll", L"mono-2.0-bdwgc.dll",
L"cri_ware_unity.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 const size_t target_modules_len = _countof(target_modules);
static void dll_hook_insert_hooks(HMODULE target); 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 *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[] = { static const struct hook_symbol unity_kernel32_syms[] = {
{ {
.name = "LoadLibraryW", .name = "LoadLibraryW",
.patch = my_LoadLibraryW, .patch = hook_LoadLibraryW,
.link = (void **) &next_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) { void unity_hook_init(const struct unity_config *cfg, HINSTANCE self) {
assert(cfg != NULL); assert(cfg != NULL);
@ -57,7 +79,14 @@ static void dll_hook_insert_hooks(HMODULE target) {
_countof(unity_kernel32_syms)); _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 *name_end;
const wchar_t *target_module; const wchar_t *target_module;
bool already_loaded; bool already_loaded;
@ -107,6 +136,14 @@ static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name) {
dll_hook_insert_hooks(result); dll_hook_insert_hooks(result);
path_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);
} }
} }