forked from Hay1tsme/segatools
Compare commits
1 Commits
2024-04-29
...
2024-02-22
Author | SHA1 | Date | |
---|---|---|---|
d118ef614c
|
@ -1,6 +1,6 @@
|
|||||||
# Segatools
|
# Segatools
|
||||||
|
|
||||||
Version: `2024-03-13`
|
Version: `2024-02-22`
|
||||||
|
|
||||||
Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms.
|
Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms.
|
||||||
|
|
||||||
@ -9,8 +9,6 @@ Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platfo
|
|||||||
* CHUNITHM
|
* CHUNITHM
|
||||||
* up to [CHUNITHM PARADISE LOST](doc/chunihook.md)
|
* up to [CHUNITHM PARADISE LOST](doc/chunihook.md)
|
||||||
* starting from CHUNITHM NEW!!
|
* starting from CHUNITHM NEW!!
|
||||||
* crossbeats REV.
|
|
||||||
* up to crossbeats REV. SUNRISE
|
|
||||||
* Initial D
|
* Initial D
|
||||||
* [Initial D Arcade Stage Zero](doc/idzhook.md)
|
* [Initial D Arcade Stage Zero](doc/idzhook.md)
|
||||||
* Initial D THE ARCADE
|
* Initial D THE ARCADE
|
||||||
|
@ -68,6 +68,7 @@ static void aime_io_config_read(
|
|||||||
cfg->felica_path,
|
cfg->felica_path,
|
||||||
_countof(cfg->felica_path),
|
_countof(cfg->felica_path),
|
||||||
filename);
|
filename);
|
||||||
|
// dprintf("NFC: felicaPath GetLastError %lx\n", GetLastError());
|
||||||
|
|
||||||
cfg->felica_gen = GetPrivateProfileIntW(
|
cfg->felica_gen = GetPrivateProfileIntW(
|
||||||
L"aime",
|
L"aime",
|
||||||
|
@ -25,13 +25,6 @@ struct sg_res_header {
|
|||||||
uint8_t payload_len;
|
uint8_t payload_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* struct to save the version string with its length
|
|
||||||
to fix NUL terminator issues */
|
|
||||||
struct version_info {
|
|
||||||
const char *version;
|
|
||||||
uint8_t length;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef HRESULT (*sg_dispatch_fn_t)(
|
typedef HRESULT (*sg_dispatch_fn_t)(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
const void *req,
|
const void *req,
|
||||||
|
@ -27,11 +27,11 @@ static HRESULT sg_led_cmd_set_color(
|
|||||||
const struct sg_led *led,
|
const struct sg_led *led,
|
||||||
const struct sg_led_req_set_color *req);
|
const struct sg_led_req_set_color *req);
|
||||||
|
|
||||||
static const struct version_info led_version[] = {
|
const char *sg_led_info[] = {
|
||||||
{"15084\xFF\x10\x00\x12", 9},
|
"15084\xFF\x10\x00\x12",
|
||||||
{"000-00000\xFF\x11\x40", 12},
|
"000-00000\xFF\x11\x40",
|
||||||
// maybe the same?
|
// maybe the same?
|
||||||
{"000-00000\xFF\x11\x40", 12}
|
"000-00000\xFF\x11\x40"
|
||||||
};
|
};
|
||||||
|
|
||||||
void sg_led_init(
|
void sg_led_init(
|
||||||
@ -156,10 +156,10 @@ static HRESULT sg_led_cmd_get_info(
|
|||||||
{
|
{
|
||||||
sg_led_dprintf(led, "Get info\n");
|
sg_led_dprintf(led, "Get info\n");
|
||||||
|
|
||||||
const struct version_info *fw = &led_version[led->gen - 1];
|
unsigned int len = strlen(sg_led_info[led->gen - 1]);
|
||||||
|
|
||||||
sg_res_init(&res->res, req, fw->length);
|
sg_res_init(&res->res, req, len);
|
||||||
memcpy(res->payload, fw->version, fw->length);
|
memcpy(res->payload, sg_led_info[led->gen - 1], len);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -65,16 +65,16 @@ static HRESULT sg_nfc_cmd_dummy(
|
|||||||
const struct sg_req_header *req,
|
const struct sg_req_header *req,
|
||||||
struct sg_res_header *res);
|
struct sg_res_header *res);
|
||||||
|
|
||||||
static const struct version_info hw_version[] = {
|
static const char *hw_version[] = {
|
||||||
{"TN32MSEC003S H/W Ver3.0", 23},
|
"TN32MSEC003S H/W Ver3.0",
|
||||||
{"837-15286", 9},
|
"837-15286",
|
||||||
{"837-15396", 9}
|
"837-15396"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct version_info fw_version[] = {
|
static const char *fw_version[] = {
|
||||||
{"TN32MSEC003S F/W Ver1.2", 23},
|
"TN32MSEC003S F/W Ver1.2",
|
||||||
{"\x94", 1},
|
"\x94",
|
||||||
{"\x94", 1}
|
"\x94"
|
||||||
};
|
};
|
||||||
|
|
||||||
void sg_nfc_init(
|
void sg_nfc_init(
|
||||||
@ -217,11 +217,11 @@ static HRESULT sg_nfc_cmd_get_fw_version(
|
|||||||
const struct sg_req_header *req,
|
const struct sg_req_header *req,
|
||||||
struct sg_nfc_res_get_fw_version *res)
|
struct sg_nfc_res_get_fw_version *res)
|
||||||
{
|
{
|
||||||
const struct version_info *fw = &fw_version[nfc->gen - 1];
|
unsigned int len = strlen(fw_version[nfc->gen - 1]);
|
||||||
|
|
||||||
/* Dest version is not NUL terminated, this is intentional */
|
/* Dest version is not NUL terminated, this is intentional */
|
||||||
sg_res_init(&res->res, req, fw->length);
|
sg_res_init(&res->res, req, len);
|
||||||
memcpy(res->version, fw->version, fw->length);
|
memcpy(res->version, fw_version[nfc->gen - 1], len);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -231,11 +231,11 @@ static HRESULT sg_nfc_cmd_get_hw_version(
|
|||||||
const struct sg_req_header *req,
|
const struct sg_req_header *req,
|
||||||
struct sg_nfc_res_get_hw_version *res)
|
struct sg_nfc_res_get_hw_version *res)
|
||||||
{
|
{
|
||||||
const struct version_info *hw = &hw_version[nfc->gen - 1];
|
unsigned int len = strlen(hw_version[nfc->gen - 1]);
|
||||||
|
|
||||||
/* Dest version is not NUL terminated, this is intentional */
|
/* Dest version is not NUL terminated, this is intentional */
|
||||||
sg_res_init(&res->res, req, hw->length);
|
sg_res_init(&res->res, req, len);
|
||||||
memcpy(res->version, hw->version, hw->length);
|
memcpy(res->version, hw_version[nfc->gen - 1], len);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
58
board/vfd.c
58
board/vfd.c
@ -26,7 +26,6 @@ static HRESULT vfd_handle_irp(struct irp *irp);
|
|||||||
static struct uart vfd_uart;
|
static struct uart vfd_uart;
|
||||||
static uint8_t vfd_written[512];
|
static uint8_t vfd_written[512];
|
||||||
static uint8_t vfd_readable[512];
|
static uint8_t vfd_readable[512];
|
||||||
UINT codepage;
|
|
||||||
|
|
||||||
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
|
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
|
||||||
{
|
{
|
||||||
@ -42,7 +41,6 @@ HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
|
|||||||
vfd_uart.readable.bytes = vfd_readable;
|
vfd_uart.readable.bytes = vfd_readable;
|
||||||
vfd_uart.readable.nbytes = sizeof(vfd_readable);
|
vfd_uart.readable.nbytes = sizeof(vfd_readable);
|
||||||
|
|
||||||
codepage = GetACP();
|
|
||||||
dprintf("VFD: hook enabled.\n");
|
dprintf("VFD: hook enabled.\n");
|
||||||
|
|
||||||
return iohook_push_handler(vfd_handle_irp);
|
return iohook_push_handler(vfd_handle_irp);
|
||||||
@ -64,60 +62,8 @@ static HRESULT vfd_handle_irp(struct irp *irp)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t cmd = 0;
|
dprintf("VFD TX:\n");
|
||||||
uint8_t str_1[512];
|
dump_iobuf(&vfd_uart.written);
|
||||||
uint8_t str_2[512];
|
|
||||||
uint8_t str_1_len = 0;
|
|
||||||
uint8_t str_2_len = 0;
|
|
||||||
for (size_t i = 0; i < vfd_uart.written.pos; i++) {
|
|
||||||
if (vfd_uart.written.bytes[i] == 0x1B) {
|
|
||||||
i++;
|
|
||||||
cmd = vfd_uart.written.bytes[i];
|
|
||||||
if (cmd == 0x30) {
|
|
||||||
i += 3;
|
|
||||||
}
|
|
||||||
else if (cmd == 0x50) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cmd == 0x30) {
|
|
||||||
str_1[str_1_len++] = vfd_uart.written.bytes[i];
|
|
||||||
}
|
|
||||||
else if (cmd == 0x50) {
|
|
||||||
str_2[str_2_len++] = vfd_uart.written.bytes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_1_len) {
|
|
||||||
str_1[str_1_len++] = '\0';
|
|
||||||
if (codepage != 932) {
|
|
||||||
WCHAR buffer[512];
|
|
||||||
MultiByteToWideChar(932, 0, (LPCSTR)str_1, str_1_len, buffer, str_1_len);
|
|
||||||
char str_recode[str_1_len * 3];
|
|
||||||
WideCharToMultiByte(codepage, 0, buffer, str_1_len, str_recode, str_1_len * 3, NULL, NULL);
|
|
||||||
dprintf("VFD: %s\n", str_recode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dprintf("VFD: %s\n", str_1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_2_len) {
|
|
||||||
str_2[str_2_len++] = '\0';
|
|
||||||
if (codepage != 932) {
|
|
||||||
WCHAR buffer[512];
|
|
||||||
MultiByteToWideChar(932, 0, (LPCSTR)str_2, str_2_len, buffer, str_2_len);
|
|
||||||
char str_recode[str_2_len * 3];
|
|
||||||
WideCharToMultiByte(codepage, 0, buffer, str_2_len, str_recode, str_2_len * 3, NULL, NULL);
|
|
||||||
dprintf("VFD: %s\n", str_recode);
|
|
||||||
} else {
|
|
||||||
dprintf("VFD: %s\n", str_2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dprintf("VFD TX:\n");
|
|
||||||
// dump_iobuf(&vfd_uart.written);
|
|
||||||
vfd_uart.written.pos = 0;
|
vfd_uart.written.pos = 0;
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -40,5 +40,4 @@ void cm_hook_config_load(
|
|||||||
vfd_config_load(&cfg->vfd, filename);
|
vfd_config_load(&cfg->vfd, filename);
|
||||||
touch_screen_config_load(&cfg->touch, filename);
|
touch_screen_config_load(&cfg->touch, filename);
|
||||||
cm_dll_config_load(&cfg->dll, filename);
|
cm_dll_config_load(&cfg->dll, filename);
|
||||||
unity_config_load(&cfg->unity, filename);
|
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
#include "platform/config.h"
|
#include "platform/config.h"
|
||||||
|
|
||||||
#include "unityhook/config.h"
|
|
||||||
|
|
||||||
struct cm_hook_config {
|
struct cm_hook_config {
|
||||||
struct platform_config platform;
|
struct platform_config platform;
|
||||||
struct aime_config aime;
|
struct aime_config aime;
|
||||||
@ -21,7 +19,6 @@ struct cm_hook_config {
|
|||||||
struct vfd_config vfd;
|
struct vfd_config vfd;
|
||||||
struct cm_dll_config dll;
|
struct cm_dll_config dll;
|
||||||
struct touch_screen_config touch;
|
struct touch_screen_config touch;
|
||||||
struct unity_config unity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void cm_dll_config_load(
|
void cm_dll_config_load(
|
||||||
|
@ -16,11 +16,10 @@
|
|||||||
#include "cmhook/config.h"
|
#include "cmhook/config.h"
|
||||||
#include "cmhook/io4.h"
|
#include "cmhook/io4.h"
|
||||||
#include "cmhook/cm-dll.h"
|
#include "cmhook/cm-dll.h"
|
||||||
|
#include "cmhook/unity.h"
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "unityhook/hook.h"
|
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
static HMODULE cm_hook_mod;
|
static HMODULE cm_hook_mod;
|
||||||
@ -84,7 +83,7 @@ static DWORD CALLBACK cm_pre_startup(void)
|
|||||||
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
||||||
hooked earlier in the `cmhook` initialization. */
|
hooked earlier in the `cmhook` initialization. */
|
||||||
|
|
||||||
unity_hook_init(&cm_hook_cfg.unity, cm_hook_mod);
|
unity_hook_init();
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ shared_library(
|
|||||||
hooklib_lib,
|
hooklib_lib,
|
||||||
cmio_lib,
|
cmio_lib,
|
||||||
platform_lib,
|
platform_lib,
|
||||||
unityhook_lib,
|
|
||||||
util_lib,
|
util_lib,
|
||||||
],
|
],
|
||||||
sources : [
|
sources : [
|
||||||
@ -27,5 +26,7 @@ shared_library(
|
|||||||
'io4.h',
|
'io4.h',
|
||||||
'cm-dll.c',
|
'cm-dll.c',
|
||||||
'cm-dll.h',
|
'cm-dll.h',
|
||||||
|
'unity.h',
|
||||||
|
'unity.c',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
95
cmhook/unity.c
Normal file
95
cmhook/unity.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
#include "hooklib/dll.h"
|
||||||
|
#include "hooklib/path.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static void dll_hook_insert_hooks(HMODULE target);
|
||||||
|
|
||||||
|
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name);
|
||||||
|
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
|
||||||
|
|
||||||
|
static const struct hook_symbol unity_kernel32_syms[] = {
|
||||||
|
{
|
||||||
|
.name = "LoadLibraryW",
|
||||||
|
.patch = my_LoadLibraryW,
|
||||||
|
.link = (void **) &next_LoadLibraryW,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const wchar_t *target_modules[] = {
|
||||||
|
L"mono.dll",
|
||||||
|
L"cri_ware_unity.dll",
|
||||||
|
};
|
||||||
|
static const size_t target_modules_len = _countof(target_modules);
|
||||||
|
|
||||||
|
void unity_hook_init(void)
|
||||||
|
{
|
||||||
|
dll_hook_insert_hooks(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dll_hook_insert_hooks(HMODULE target)
|
||||||
|
{
|
||||||
|
hook_table_apply(
|
||||||
|
target,
|
||||||
|
"kernel32.dll",
|
||||||
|
unity_kernel32_syms,
|
||||||
|
_countof(unity_kernel32_syms));
|
||||||
|
}
|
||||||
|
|
||||||
|
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name)
|
||||||
|
{
|
||||||
|
const wchar_t *name_end;
|
||||||
|
const wchar_t *target_module;
|
||||||
|
bool already_loaded;
|
||||||
|
HMODULE result;
|
||||||
|
size_t name_len;
|
||||||
|
size_t target_module_len;
|
||||||
|
|
||||||
|
if (name == NULL) {
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the module is already loaded
|
||||||
|
already_loaded = GetModuleHandleW(name) != NULL;
|
||||||
|
|
||||||
|
// Must call the next handler so the DLL reference count is incremented
|
||||||
|
result = next_LoadLibraryW(name);
|
||||||
|
|
||||||
|
if (!already_loaded && result != NULL) {
|
||||||
|
name_len = wcslen(name);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < target_modules_len; i++) {
|
||||||
|
target_module = target_modules[i];
|
||||||
|
target_module_len = wcslen(target_module);
|
||||||
|
|
||||||
|
// Check if the newly loaded library is at least the length of
|
||||||
|
// the name of the target module
|
||||||
|
if (name_len < target_module_len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_end = &name[name_len - target_module_len];
|
||||||
|
|
||||||
|
// Check if the name of the newly loaded library is one of the
|
||||||
|
// modules the path hooks should be injected into
|
||||||
|
if (_wcsicmp(name_end, target_module) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("Unity: Loaded %S\n", target_module);
|
||||||
|
|
||||||
|
dll_hook_insert_hooks(result);
|
||||||
|
path_hook_insert_hooks(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
3
cmhook/unity.h
Normal file
3
cmhook/unity.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void unity_hook_init(void);
|
@ -23,32 +23,22 @@ void cxb_dll_config_load(
|
|||||||
struct cxb_dll_config *cfg,
|
struct cxb_dll_config *cfg,
|
||||||
const wchar_t *filename)
|
const wchar_t *filename)
|
||||||
{
|
{
|
||||||
assert(cfg != NULL);
|
|
||||||
assert(filename != NULL);
|
|
||||||
|
|
||||||
GetPrivateProfileStringW(
|
|
||||||
L"cxbio",
|
|
||||||
L"path",
|
|
||||||
L"",
|
|
||||||
cfg->path,
|
|
||||||
_countof(cfg->path),
|
|
||||||
filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void revio_config_load(struct revio_config *cfg, const wchar_t *filename)
|
void revio_config_load(struct revio_config *cfg, const wchar_t *filename)
|
||||||
{
|
{
|
||||||
assert(cfg != NULL);
|
|
||||||
assert(filename != NULL);
|
|
||||||
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"revio", L"enable", 1, filename);
|
}
|
||||||
|
|
||||||
|
void network_config_load(struct network_config *cfg, const wchar_t *filename)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void led_config_load(struct led_config *cfg, const wchar_t *filename)
|
void led_config_load(struct led_config *cfg, const wchar_t *filename)
|
||||||
{
|
{
|
||||||
assert(cfg != NULL);
|
|
||||||
assert(filename != NULL);
|
|
||||||
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"led", L"enable", 1, filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxb_hook_config_load(
|
void cxb_hook_config_load(
|
||||||
@ -66,5 +56,6 @@ void cxb_hook_config_load(
|
|||||||
gfx_config_load(&cfg->gfx, filename);
|
gfx_config_load(&cfg->gfx, filename);
|
||||||
cxb_dll_config_load(&cfg->dll, filename);
|
cxb_dll_config_load(&cfg->dll, filename);
|
||||||
revio_config_load(&cfg->revio, filename);
|
revio_config_load(&cfg->revio, filename);
|
||||||
|
network_config_load(&cfg->network, filename);
|
||||||
led_config_load(&cfg->led, filename);
|
led_config_load(&cfg->led, filename);
|
||||||
}
|
}
|
@ -10,6 +10,7 @@
|
|||||||
#include "cxbhook/cxb-dll.h"
|
#include "cxbhook/cxb-dll.h"
|
||||||
#include "cxbhook/revio.h"
|
#include "cxbhook/revio.h"
|
||||||
#include "cxbhook/led.h"
|
#include "cxbhook/led.h"
|
||||||
|
#include "cxbhook/network.h"
|
||||||
|
|
||||||
#include "gfxhook/gfx.h"
|
#include "gfxhook/gfx.h"
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ struct cxb_hook_config {
|
|||||||
struct gfx_config gfx;
|
struct gfx_config gfx;
|
||||||
struct cxb_dll_config dll;
|
struct cxb_dll_config dll;
|
||||||
struct revio_config revio;
|
struct revio_config revio;
|
||||||
|
struct network_config network;
|
||||||
struct led_config led;
|
struct led_config led;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,6 +32,7 @@ void cxb_dll_config_load(
|
|||||||
const wchar_t *filename);
|
const wchar_t *filename);
|
||||||
|
|
||||||
void revio_config_load(struct revio_config *cfg, const wchar_t *filename);
|
void revio_config_load(struct revio_config *cfg, const wchar_t *filename);
|
||||||
|
void network_config_load(struct network_config *cfg, const wchar_t *filename);
|
||||||
void led_config_load(struct led_config *cfg, const wchar_t *filename);
|
void led_config_load(struct led_config *cfg, const wchar_t *filename);
|
||||||
|
|
||||||
void cxb_hook_config_load(
|
void cxb_hook_config_load(
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "cxbhook/config.h"
|
#include "cxbhook/config.h"
|
||||||
#include "cxbhook/revio.h"
|
#include "cxbhook/revio.h"
|
||||||
#include "cxbhook/led.h"
|
#include "cxbhook/led.h"
|
||||||
|
#include "cxbhook/network.h"
|
||||||
|
|
||||||
#include "cxbio/cxbio.h"
|
#include "cxbio/cxbio.h"
|
||||||
|
|
||||||
@ -102,6 +103,12 @@ static DWORD CALLBACK cxb_pre_startup(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = network_hook_init(&cxb_hook_cfg.network);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
hr = led_hook_init(&cxb_hook_cfg.led);
|
hr = led_hook_init(&cxb_hook_cfg.led);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -49,13 +49,7 @@ static struct hook_symbol lamp_syms[] = {
|
|||||||
|
|
||||||
HRESULT led_hook_init(struct led_config *cfg)
|
HRESULT led_hook_init(struct led_config *cfg)
|
||||||
{
|
{
|
||||||
assert(cfg != NULL);
|
dprintf("LED: Init\n");
|
||||||
|
|
||||||
if (!cfg->enable) {
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("LED: Hook enabled.\n");
|
|
||||||
return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms));
|
return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,5 +30,7 @@ shared_library(
|
|||||||
'revio.h',
|
'revio.h',
|
||||||
'led.c',
|
'led.c',
|
||||||
'led.h',
|
'led.h',
|
||||||
|
'network.c',
|
||||||
|
'network.h',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
13
cxbhook/network.c
Normal file
13
cxbhook/network.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "cxbhook/network.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
HRESULT network_hook_init(struct network_config *cfg)
|
||||||
|
{
|
||||||
|
dprintf("Network: Init\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
13
cxbhook/network.h
Normal file
13
cxbhook/network.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct network_config {
|
||||||
|
bool enable;
|
||||||
|
bool disable_ssl;
|
||||||
|
char title_server[PATH_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT network_hook_init(struct network_config *cfg);
|
@ -82,13 +82,7 @@ static struct hook_symbol revio_syms[] = {
|
|||||||
|
|
||||||
HRESULT revio_hook_init(struct revio_config *cfg)
|
HRESULT revio_hook_init(struct revio_config *cfg)
|
||||||
{
|
{
|
||||||
assert(cfg != NULL);
|
dprintf("Revio: Init\n");
|
||||||
|
|
||||||
if (!cfg->enable) {
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("Revio: Hook enabled.\n");
|
|
||||||
return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms));
|
return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +154,7 @@ static int my_cCommIo_GetTrigger()
|
|||||||
|
|
||||||
out &= ~last_triggers;
|
out &= ~last_triggers;
|
||||||
|
|
||||||
// dprintf("Revio: GetTrigger %X\n", out);
|
dprintf("Revio: GetTrigger %X\n", out);
|
||||||
last_triggers = out;
|
last_triggers = out;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -194,7 +188,7 @@ static int my_cCommIo_GetRelease()
|
|||||||
|
|
||||||
out &= ~btns;
|
out &= ~btns;
|
||||||
|
|
||||||
// dprintf("Revio: GetRelease %X\n", out);
|
dprintf("Revio: GetRelease %X\n", out);
|
||||||
last_triggers = btns;
|
last_triggers = btns;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
5
dist/cm/segatools.ini
vendored
5
dist/cm/segatools.ini
vendored
@ -68,11 +68,6 @@ dipsw1=0
|
|||||||
; Enable/Disable WinTouch emulation
|
; Enable/Disable WinTouch emulation
|
||||||
enable=0
|
enable=0
|
||||||
|
|
||||||
[unity]
|
|
||||||
; Path to a .NET DLL that should run before the game. Useful for loading
|
|
||||||
; modding frameworks such as BepInEx.
|
|
||||||
targetAssembly=
|
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Custom IO settings
|
; Custom IO settings
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
11
dist/cxb/segatools.ini
vendored
11
dist/cxb/segatools.ini
vendored
@ -19,10 +19,10 @@ appdata=
|
|||||||
|
|
||||||
[aime]
|
[aime]
|
||||||
; Aime reader emulation
|
; Aime reader emulation
|
||||||
|
; CXB is stupid, so we have to make the paths go back one
|
||||||
enable=1
|
enable=1
|
||||||
; CXB is stupid, so we have to make the paths go back two directories. This
|
|
||||||
; will load the file from "resource\DEVICE\aime.txt".
|
|
||||||
aimePath=../DEVICE/aime.txt
|
aimePath=../DEVICE/aime.txt
|
||||||
|
felicaPath=../DEVICE/felica.txt
|
||||||
|
|
||||||
[led]
|
[led]
|
||||||
; Emulation for the LED board. Currently it's just dummy responses,
|
; Emulation for the LED board. Currently it's just dummy responses,
|
||||||
@ -39,10 +39,6 @@ enable=1
|
|||||||
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
||||||
default=127.0.0.1
|
default=127.0.0.1
|
||||||
|
|
||||||
; Set the title server hostname or IP address here, as the title server
|
|
||||||
; is hardcoded in the game.
|
|
||||||
title=https://127.0.0.1:9002
|
|
||||||
|
|
||||||
[netenv]
|
[netenv]
|
||||||
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
|
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
|
||||||
; Crossbeats is extremely picky about its LAN environment, so leaving this
|
; Crossbeats is extremely picky about its LAN environment, so leaving this
|
||||||
@ -110,14 +106,13 @@ path=
|
|||||||
|
|
||||||
[revio]
|
[revio]
|
||||||
; Enable emulation of the rev IO board
|
; Enable emulation of the rev IO board
|
||||||
enable=1
|
enabe=1
|
||||||
; 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.
|
||||||
service=0x71
|
service=0x71
|
||||||
; Keyboard button to increment coin counter. Default is the F3 key.
|
; Keyboard button to increment coin counter. Default is the F3 key.
|
||||||
coin=0x72
|
coin=0x72
|
||||||
|
|
||||||
; Menu up key. Default is up arrow.
|
; Menu up key. Default is up arrow.
|
||||||
up=0x26
|
up=0x26
|
||||||
; Menu down key. Default is down arrow.
|
; Menu down key. Default is down arrow.
|
||||||
|
16
dist/fgo/segatools.ini
vendored
16
dist/fgo/segatools.ini
vendored
@ -129,12 +129,12 @@ path=
|
|||||||
|
|
||||||
[io4]
|
[io4]
|
||||||
; Input API selection for JVS input emulator.
|
; 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 1 key.
|
||||||
test=0x70
|
test=0x31
|
||||||
; Service button virtual-key code. Default is the F2 key.
|
; Service button virtual-key code. Default is the 2 key.
|
||||||
service=0x71
|
service=0x32
|
||||||
; Keyboard button to increment coin counter. Default is the F3 key.
|
; Keyboard button to increment coin counter. Default is the 3 key.
|
||||||
coin=0x72
|
coin=0x33
|
||||||
|
|
||||||
; .·:'''''''''''''''''''''''''''''''''''''''''''''':·.
|
; .·:'''''''''''''''''''''''''''''''''''''''''''''':·.
|
||||||
; : : ______ / \ [] : :
|
; : : ______ / \ [] : :
|
||||||
@ -151,8 +151,8 @@ coin=0x72
|
|||||||
;
|
;
|
||||||
; Only XInput is currently supported.
|
; Only XInput is currently supported.
|
||||||
|
|
||||||
; XInput bindings
|
; Controller Button
|
||||||
;
|
; -------------------------------------------------------
|
||||||
; Left Stick Joystick
|
; Left Stick Joystick
|
||||||
; Left Stick Click Reset Camera
|
; Left Stick Click Reset Camera
|
||||||
; Left Trigger Dash
|
; Left Trigger Dash
|
||||||
|
25
dist/idac/start.bat
vendored
25
dist/idac/start.bat
vendored
@ -2,6 +2,20 @@
|
|||||||
|
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM set the APP_DIR to the Y drive
|
||||||
|
set APP_DIR=Y:\SDGT
|
||||||
|
|
||||||
|
REM create the APP_DIR if it doesn't exist and redirect it to the TEMP folder
|
||||||
|
if not exist "%APP_DIR%" (
|
||||||
|
subst Y: %TEMP%
|
||||||
|
REM timeout /t 1
|
||||||
|
if not exist "%APP_DIR%" (
|
||||||
|
mkdir "%APP_DIR%"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Mounted the Y:\ drive to the %TEMP%\SDGT folder
|
||||||
|
|
||||||
set AMDAEMON_CFG=config_common.json ^
|
set AMDAEMON_CFG=config_common.json ^
|
||||||
config_ex.json ^
|
config_ex.json ^
|
||||||
config_jp.json ^
|
config_jp.json ^
|
||||||
@ -26,15 +40,12 @@ config_seat_single_jp.json ^
|
|||||||
config_hook.json
|
config_hook.json
|
||||||
|
|
||||||
start "AM Daemon" /min inject -d -k idachook.dll amdaemon.exe -c %AMDAEMON_CFG%
|
start "AM Daemon" /min inject -d -k idachook.dll amdaemon.exe -c %AMDAEMON_CFG%
|
||||||
|
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject.exe -culture=en launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
|
||||||
rem JP
|
|
||||||
rem inject -d -k idachook.dll ..\WindowsNoEditor\GameProject\Binaries\Win64\GameProject-Win64-Shipping.exe -culture=ja launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
|
|
||||||
|
|
||||||
rem EXP
|
|
||||||
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject\Binaries\Win64\GameProject-Win64-Shipping.exe -culture=en launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
|
|
||||||
|
|
||||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||||
|
|
||||||
|
REM unmount the APP_DIR
|
||||||
|
subst Y: /d > nul 2>&1
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo Game processes have terminated
|
echo Game processes have terminated
|
||||||
pause
|
pause
|
9
dist/mai2/segatools.ini
vendored
9
dist/mai2/segatools.ini
vendored
@ -83,15 +83,6 @@ path=
|
|||||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||||
path=
|
path=
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
|
||||||
; Misc. hook settings
|
|
||||||
; -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[unity]
|
|
||||||
; Path to a .NET DLL that should run before the game. Useful for loading
|
|
||||||
; modding frameworks such as BepInEx.
|
|
||||||
targetAssembly=
|
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Input settings
|
; Input settings
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
3
dist/mai2/start.bat
vendored
3
dist/mai2/start.bat
vendored
@ -3,8 +3,7 @@
|
|||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
start "AM Daemon" /min inject -d -k mai2hook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json
|
start "AM Daemon" /min inject -d -k mai2hook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json
|
||||||
inject -d -k mai2hook.dll sinmai -screen-fullscreen 0 -popupwindow -screen-width 2160 -screen-height 1920 -silent-crashes
|
inject -d -k mai2hook.dll sinmai -screen-fullscreen 0
|
||||||
|
|
||||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
|
7
dist/mu3/segatools.ini
vendored
7
dist/mu3/segatools.ini
vendored
@ -72,11 +72,6 @@ dipsw1=1
|
|||||||
[gfx]
|
[gfx]
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
[unity]
|
|
||||||
; Path to a .NET DLL that should run before the game. Useful for loading
|
|
||||||
; modding frameworks such as BepInEx.
|
|
||||||
targetAssembly=
|
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Custom IO settings
|
; Custom IO settings
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
@ -86,7 +81,7 @@ targetAssembly=
|
|||||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||||
path=
|
path=
|
||||||
|
|
||||||
[mu3io]
|
[fgoio]
|
||||||
; To use a custom O.N.G.E.K.I. IO DLL enter its path here.
|
; To use a custom O.N.G.E.K.I. IO DLL enter its path here.
|
||||||
; Leave empty if you want to use Segatools built-in keyboard/gamepad input.
|
; Leave empty if you want to use Segatools built-in keyboard/gamepad input.
|
||||||
path=
|
path=
|
||||||
|
2
dist/swdc/segatools.ini
vendored
2
dist/swdc/segatools.ini
vendored
@ -63,7 +63,7 @@ enable=1
|
|||||||
; Enable freeplay mode. This will disable the coin slot and set the game to
|
; Enable freeplay mode. This will disable the coin slot and set the game to
|
||||||
; freeplay. Keep in mind that some game modes (e.g. Freedom/Time Modes) will not
|
; freeplay. Keep in mind that some game modes (e.g. Freedom/Time Modes) will not
|
||||||
; allow you to start a game in freeplay mode.
|
; allow you to start a game in freeplay mode.
|
||||||
freeplay=0
|
freeplay=0´
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; Custom IO settings
|
; Custom IO settings
|
||||||
|
@ -153,13 +153,6 @@ setting. Also, loopback addresses are specifically checked for and rejected by
|
|||||||
the games themselves; this needs to be a LAN or WAN IP (or a hostname that
|
the games themselves; this needs to be a LAN or WAN IP (or a hostname that
|
||||||
resolves to one).
|
resolves to one).
|
||||||
|
|
||||||
### `title`
|
|
||||||
|
|
||||||
Default: `title`
|
|
||||||
|
|
||||||
Leave it as `title` to use the title server returned by ALL.Net. Rewrites
|
|
||||||
the title server hostname for certain games, such as crossbeats REV.
|
|
||||||
|
|
||||||
### `router`
|
### `router`
|
||||||
|
|
||||||
Default: Empty string (i.e. use value from `default` setting)
|
Default: Empty string (i.e. use value from `default` setting)
|
||||||
@ -395,29 +388,13 @@ Bit values are:
|
|||||||
- 3: EXP: Export (for Asian markets)
|
- 3: EXP: Export (for Asian markets)
|
||||||
- 4: CHS: China (Simplified Chinese?)
|
- 4: CHS: China (Simplified Chinese?)
|
||||||
|
|
||||||
### `billingCa`
|
|
||||||
|
|
||||||
Default: `DEVICE\\ca.crt`
|
|
||||||
|
|
||||||
Set the billing certificate path. This has to match the one used for the
|
|
||||||
SSL billing server. The DER certificate must fit in 1024 bytes so it must be
|
|
||||||
small.
|
|
||||||
|
|
||||||
### `billingPub`
|
|
||||||
|
|
||||||
Default: `DEVICE\\billing.pub`
|
|
||||||
|
|
||||||
Set the actual keychip RSA public key path. This public key has to match the
|
|
||||||
private key `billing.key` of the billing server in order to decrypt/encrypt
|
|
||||||
the billing transactions.
|
|
||||||
|
|
||||||
### `billingType`
|
### `billingType`
|
||||||
|
|
||||||
Default: `1`
|
Default: `1`
|
||||||
|
|
||||||
Set the billing "type" for the keychip. The type determins what kind of revenue share,
|
Set the billing "type" for the keychip. The type determins what kind of revenue share,
|
||||||
if any, the game maker has with SEGA. Some games may be picky and require types other
|
if any, the game maker has with SEGA. Some games may be picky and require types other
|
||||||
then 1 (ex. crossbeats REV. requires billing type 2), so this option is provided if this
|
then 1 (ex. Crossbeats requires billing type 2), so this option is provided if this
|
||||||
is an issue. Billing types are:
|
is an issue. Billing types are:
|
||||||
|
|
||||||
- 0: No billing?
|
- 0: No billing?
|
||||||
|
127
hooklib/dns.c
127
hooklib/dns.c
@ -3,7 +3,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windns.h>
|
#include <windns.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <winhttp.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -13,8 +12,6 @@
|
|||||||
#include "hook/hr.h"
|
#include "hook/hr.h"
|
||||||
#include "hook/table.h"
|
#include "hook/table.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
|
||||||
|
|
||||||
#include "hooklib/dns.h"
|
#include "hooklib/dns.h"
|
||||||
|
|
||||||
/* Latest w32headers does not include DnsQueryEx, so we'll have to "polyfill"
|
/* Latest w32headers does not include DnsQueryEx, so we'll have to "polyfill"
|
||||||
@ -69,18 +66,6 @@ static int WSAAPI hook_getaddrinfo(
|
|||||||
const ADDRINFOA *pHints,
|
const ADDRINFOA *pHints,
|
||||||
ADDRINFOA **ppResult);
|
ADDRINFOA **ppResult);
|
||||||
|
|
||||||
static HINTERNET WINAPI hook_WinHttpConnect(
|
|
||||||
HINTERNET hSession,
|
|
||||||
const wchar_t *pwszServerName,
|
|
||||||
INTERNET_PORT nServerPort,
|
|
||||||
DWORD dwReserved);
|
|
||||||
|
|
||||||
static bool WINAPI hook_WinHttpCrackUrl(
|
|
||||||
const wchar_t *pwszUrl,
|
|
||||||
DWORD dwUrlLength,
|
|
||||||
DWORD dwFlags,
|
|
||||||
LPURL_COMPONENTS lpUrlComponents);
|
|
||||||
|
|
||||||
/* Link pointers */
|
/* Link pointers */
|
||||||
|
|
||||||
static DNS_STATUS (WINAPI *next_DnsQuery_A)(
|
static DNS_STATUS (WINAPI *next_DnsQuery_A)(
|
||||||
@ -110,18 +95,6 @@ static int (WSAAPI *next_getaddrinfo)(
|
|||||||
const ADDRINFOA *pHints,
|
const ADDRINFOA *pHints,
|
||||||
ADDRINFOA **ppResult);
|
ADDRINFOA **ppResult);
|
||||||
|
|
||||||
static HINTERNET (WINAPI *next_WinHttpConnect)(
|
|
||||||
HINTERNET hSession,
|
|
||||||
const wchar_t *pwszServerName,
|
|
||||||
INTERNET_PORT nServerPort,
|
|
||||||
DWORD dwReserved);
|
|
||||||
|
|
||||||
static bool (WINAPI *next_WinHttpCrackUrl)(
|
|
||||||
const wchar_t *pwszUrl,
|
|
||||||
DWORD dwUrlLength,
|
|
||||||
DWORD dwFlags,
|
|
||||||
LPURL_COMPONENTS lpUrlComponents);
|
|
||||||
|
|
||||||
static const struct hook_symbol dns_hook_syms_dnsapi[] = {
|
static const struct hook_symbol dns_hook_syms_dnsapi[] = {
|
||||||
{
|
{
|
||||||
.name = "DnsQuery_A",
|
.name = "DnsQuery_A",
|
||||||
@ -147,24 +120,10 @@ static const struct hook_symbol dns_hook_syms_ws2[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct hook_symbol dns_hook_syms_winhttp[] = {
|
|
||||||
{
|
|
||||||
.name = "WinHttpConnect",
|
|
||||||
.patch = hook_WinHttpConnect,
|
|
||||||
.link = (void **) &next_WinHttpConnect,
|
|
||||||
}, {
|
|
||||||
.name = "WinHttpCrackUrl",
|
|
||||||
.patch = hook_WinHttpCrackUrl,
|
|
||||||
.link = (void **) &next_WinHttpCrackUrl,
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool dns_hook_initted;
|
static bool dns_hook_initted;
|
||||||
static CRITICAL_SECTION dns_hook_lock;
|
static CRITICAL_SECTION dns_hook_lock;
|
||||||
static struct dns_hook_entry *dns_hook_entries;
|
static struct dns_hook_entry *dns_hook_entries;
|
||||||
static size_t dns_hook_nentries;
|
static size_t dns_hook_nentries;
|
||||||
static char received_title_url[255];
|
|
||||||
|
|
||||||
static void dns_hook_init(void)
|
static void dns_hook_init(void)
|
||||||
{
|
{
|
||||||
@ -186,12 +145,6 @@ static void dns_hook_init(void)
|
|||||||
"ws2_32.dll",
|
"ws2_32.dll",
|
||||||
dns_hook_syms_ws2,
|
dns_hook_syms_ws2,
|
||||||
_countof(dns_hook_syms_ws2));
|
_countof(dns_hook_syms_ws2));
|
||||||
|
|
||||||
hook_table_apply(
|
|
||||||
NULL,
|
|
||||||
"winhttp.dll",
|
|
||||||
dns_hook_syms_winhttp,
|
|
||||||
_countof(dns_hook_syms_winhttp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src)
|
HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src)
|
||||||
@ -507,83 +460,3 @@ end:
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HINTERNET WINAPI hook_WinHttpConnect(
|
|
||||||
HINTERNET hSession,
|
|
||||||
const wchar_t *pwszServerName,
|
|
||||||
INTERNET_PORT nServerPort,
|
|
||||||
DWORD dwReserved)
|
|
||||||
{
|
|
||||||
const struct dns_hook_entry *pos;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (pwszServerName == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnterCriticalSection(&dns_hook_lock);
|
|
||||||
|
|
||||||
for (i = 0 ; i < dns_hook_nentries ; i++) {
|
|
||||||
pos = &dns_hook_entries[i];
|
|
||||||
|
|
||||||
if (_wcsicmp(pwszServerName, pos->from) == 0) {
|
|
||||||
if(pos->to == NULL) {
|
|
||||||
LeaveCriticalSection(&dns_hook_lock);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pwszServerName = pos->to;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LeaveCriticalSection(&dns_hook_lock);
|
|
||||||
|
|
||||||
return next_WinHttpConnect(hSession, pwszServerName, nServerPort, dwReserved);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook to replace CXB title url
|
|
||||||
static bool WINAPI hook_WinHttpCrackUrl(
|
|
||||||
const wchar_t *pwszUrl,
|
|
||||||
DWORD dwUrlLength,
|
|
||||||
DWORD dwFlags,
|
|
||||||
LPURL_COMPONENTS lpUrlComponents)
|
|
||||||
{
|
|
||||||
const struct dns_hook_entry *pos;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
EnterCriticalSection(&dns_hook_lock);
|
|
||||||
|
|
||||||
for (i = 0 ; i < dns_hook_nentries ; i++) {
|
|
||||||
pos = &dns_hook_entries[i];
|
|
||||||
|
|
||||||
if (_wcsicmp(pwszUrl, pos->from) == 0) {
|
|
||||||
wchar_t* toAddr = pos->to;
|
|
||||||
wchar_t titleBuffer[255];
|
|
||||||
|
|
||||||
if(wcscmp(toAddr, L"title") == 0) {
|
|
||||||
size_t wstr_c;
|
|
||||||
mbstowcs_s(&wstr_c, titleBuffer, 255, received_title_url, strlen(received_title_url));
|
|
||||||
toAddr = titleBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool result = next_WinHttpCrackUrl(
|
|
||||||
toAddr,
|
|
||||||
wcslen(toAddr),
|
|
||||||
dwFlags,
|
|
||||||
lpUrlComponents
|
|
||||||
);
|
|
||||||
LeaveCriticalSection(&dns_hook_lock);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LeaveCriticalSection(&dns_hook_lock);
|
|
||||||
return next_WinHttpCrackUrl(
|
|
||||||
pwszUrl,
|
|
||||||
dwUrlLength,
|
|
||||||
dwFlags,
|
|
||||||
lpUrlComponents
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
305
hooklib/path.c
305
hooklib/path.c
@ -101,40 +101,6 @@ static BOOL WINAPI hook_PathFileExistsA(LPCSTR pszPath);
|
|||||||
|
|
||||||
static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath);
|
static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath);
|
||||||
|
|
||||||
static BOOL WINAPI hook_MoveFileA(
|
|
||||||
const char *lpExistingFileName,
|
|
||||||
const char *lpNewFileName);
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_MoveFileW(
|
|
||||||
const wchar_t *lpExistingFileName,
|
|
||||||
const wchar_t *lpNewFileName);
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_MoveFileExA(
|
|
||||||
const char *lpExistingFileName,
|
|
||||||
const char *lpNewFileName,
|
|
||||||
uint32_t dwFlags);
|
|
||||||
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_ReplaceFileA(
|
|
||||||
const char *lpReplacedFileName,
|
|
||||||
const char *lpReplacementFileName,
|
|
||||||
const char *lpBackupFileName,
|
|
||||||
uint32_t dwReplaceFlags,
|
|
||||||
void *lpExclude,
|
|
||||||
void *lpReserved);
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_ReplaceFileW(
|
|
||||||
const wchar_t *lpReplacedFileName,
|
|
||||||
const wchar_t *lpReplacementFileName,
|
|
||||||
const wchar_t *lpBackupFileName,
|
|
||||||
uint32_t dwReplaceFlags,
|
|
||||||
void *lpExclude,
|
|
||||||
void *lpReserved);
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_DeleteFileA(const char *lpFileName);
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_DeleteFileW(const wchar_t *lpFileName);
|
|
||||||
|
|
||||||
/* Link pointers */
|
/* Link pointers */
|
||||||
|
|
||||||
static BOOL (WINAPI *next_CreateDirectoryA)(
|
static BOOL (WINAPI *next_CreateDirectoryA)(
|
||||||
@ -219,39 +185,6 @@ static BOOL (WINAPI *next_PathFileExistsA)(LPCSTR pszPath);
|
|||||||
|
|
||||||
static BOOL (WINAPI *next_PathFileExistsW)(LPCWSTR pszPath);
|
static BOOL (WINAPI *next_PathFileExistsW)(LPCWSTR pszPath);
|
||||||
|
|
||||||
static BOOL (WINAPI *next_MoveFileA)(
|
|
||||||
const char *lpExistingFileName,
|
|
||||||
const char *lpNewFileName);
|
|
||||||
|
|
||||||
static BOOL (WINAPI *next_MoveFileW)(
|
|
||||||
const wchar_t *lpExistingFileName,
|
|
||||||
const wchar_t *lpNewFileName);
|
|
||||||
|
|
||||||
static BOOL (WINAPI *next_MoveFileExA)(
|
|
||||||
const char *lpExistingFileName,
|
|
||||||
const char *lpNewFileName,
|
|
||||||
uint32_t dwFlags);
|
|
||||||
|
|
||||||
static BOOL (WINAPI *next_ReplaceFileA)(
|
|
||||||
const char *lpReplacedFileName,
|
|
||||||
const char *lpReplacementFileName,
|
|
||||||
const char *lpBackupFileName,
|
|
||||||
uint32_t dwReplaceFlags,
|
|
||||||
void *lpExclude,
|
|
||||||
void *lpReserved);
|
|
||||||
|
|
||||||
static BOOL (WINAPI *next_ReplaceFileW)(
|
|
||||||
const wchar_t *lpReplacedFileName,
|
|
||||||
const wchar_t *lpReplacementFileName,
|
|
||||||
const wchar_t *lpBackupFileName,
|
|
||||||
uint32_t dwReplaceFlags,
|
|
||||||
void *lpExclude,
|
|
||||||
void *lpReserved);
|
|
||||||
|
|
||||||
static BOOL (WINAPI *next_DeleteFileA)(const char *lpFileName);
|
|
||||||
|
|
||||||
static BOOL (WINAPI *next_DeleteFileW)(const wchar_t *lpFileName);
|
|
||||||
|
|
||||||
/* Hook table */
|
/* Hook table */
|
||||||
|
|
||||||
static const struct hook_symbol path_hook_syms[] = {
|
static const struct hook_symbol path_hook_syms[] = {
|
||||||
@ -327,34 +260,6 @@ static const struct hook_symbol path_hook_syms[] = {
|
|||||||
.name = "PathFileExistsW",
|
.name = "PathFileExistsW",
|
||||||
.patch = hook_PathFileExistsW,
|
.patch = hook_PathFileExistsW,
|
||||||
.link = (void **) &next_PathFileExistsW,
|
.link = (void **) &next_PathFileExistsW,
|
||||||
}, {
|
|
||||||
.name = "MoveFileA",
|
|
||||||
.patch = hook_MoveFileA,
|
|
||||||
.link = (void **) &next_MoveFileA,
|
|
||||||
}, {
|
|
||||||
.name = "MoveFileW",
|
|
||||||
.patch = hook_MoveFileW,
|
|
||||||
.link = (void **) &next_MoveFileW,
|
|
||||||
}, {
|
|
||||||
.name = "MoveFileExA",
|
|
||||||
.patch = hook_MoveFileExA,
|
|
||||||
.link = (void **) &next_MoveFileExA,
|
|
||||||
}, {
|
|
||||||
.name = "ReplaceFileA",
|
|
||||||
.patch = hook_ReplaceFileA,
|
|
||||||
.link = (void **) &next_ReplaceFileA,
|
|
||||||
}, {
|
|
||||||
.name = "ReplaceFileW",
|
|
||||||
.patch = hook_ReplaceFileW,
|
|
||||||
.link = (void **) &next_ReplaceFileW,
|
|
||||||
}, {
|
|
||||||
.name = "DeleteFileA",
|
|
||||||
.patch = hook_DeleteFileA,
|
|
||||||
.link = (void **) &next_DeleteFileA,
|
|
||||||
}, {
|
|
||||||
.name = "DeleteFileW",
|
|
||||||
.patch = hook_DeleteFileW,
|
|
||||||
.link = (void **) &next_DeleteFileW,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1001,213 +906,3 @@ static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath)
|
|||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL WINAPI hook_MoveFileA(
|
|
||||||
const char *lpExistingFileName,
|
|
||||||
const char *lpNewFileName)
|
|
||||||
{
|
|
||||||
char *oldTrans;
|
|
||||||
char *newTrans;
|
|
||||||
BOOL ok;
|
|
||||||
|
|
||||||
ok = path_transform_a(&oldTrans, lpExistingFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = path_transform_a(&newTrans, lpNewFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
free(oldTrans);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = next_MoveFileA(
|
|
||||||
oldTrans ? oldTrans : lpExistingFileName,
|
|
||||||
newTrans ? newTrans : lpNewFileName);
|
|
||||||
|
|
||||||
free(oldTrans);
|
|
||||||
free(newTrans);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_MoveFileW(
|
|
||||||
const wchar_t *lpExistingFileName,
|
|
||||||
const wchar_t *lpNewFileName)
|
|
||||||
{
|
|
||||||
wchar_t *oldTrans;
|
|
||||||
wchar_t *newTrans;
|
|
||||||
BOOL ok;
|
|
||||||
|
|
||||||
ok = path_transform_w(&oldTrans, lpExistingFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = path_transform_w(&newTrans, lpNewFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
free(oldTrans);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = next_MoveFileW(
|
|
||||||
oldTrans ? oldTrans : lpExistingFileName,
|
|
||||||
newTrans ? newTrans : lpNewFileName);
|
|
||||||
|
|
||||||
free(oldTrans);
|
|
||||||
free(newTrans);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_MoveFileExA(
|
|
||||||
const char *lpExistingFileName,
|
|
||||||
const char *lpNewFileName,
|
|
||||||
uint32_t dwFlags)
|
|
||||||
{
|
|
||||||
char *oldTrans;
|
|
||||||
char *newTrans;
|
|
||||||
BOOL ok;
|
|
||||||
|
|
||||||
ok = path_transform_a(&oldTrans, lpExistingFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = path_transform_a(&newTrans, lpNewFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
free(oldTrans);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = next_MoveFileExA(
|
|
||||||
oldTrans ? oldTrans : lpExistingFileName,
|
|
||||||
newTrans ? newTrans : lpNewFileName,
|
|
||||||
dwFlags);
|
|
||||||
|
|
||||||
free(oldTrans);
|
|
||||||
free(newTrans);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_ReplaceFileA(
|
|
||||||
const char *lpReplacedFileName,
|
|
||||||
const char *lpReplacementFileName,
|
|
||||||
const char *lpBackupFileName,
|
|
||||||
uint32_t dwReplaceFlags,
|
|
||||||
void *lpExclude,
|
|
||||||
void *lpReserved)
|
|
||||||
{
|
|
||||||
char *oldTrans;
|
|
||||||
char *newTrans;
|
|
||||||
BOOL ok;
|
|
||||||
|
|
||||||
ok = path_transform_a(&oldTrans, lpReplacedFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = path_transform_a(&newTrans, lpReplacementFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
free(oldTrans);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = next_ReplaceFileA(
|
|
||||||
oldTrans ? oldTrans : lpReplacedFileName,
|
|
||||||
newTrans ? newTrans : lpReplacementFileName,
|
|
||||||
lpBackupFileName,
|
|
||||||
dwReplaceFlags,
|
|
||||||
lpExclude,
|
|
||||||
lpReserved);
|
|
||||||
|
|
||||||
free(oldTrans);
|
|
||||||
free(newTrans);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_ReplaceFileW(
|
|
||||||
const wchar_t *lpReplacedFileName,
|
|
||||||
const wchar_t *lpReplacementFileName,
|
|
||||||
const wchar_t *lpBackupFileName,
|
|
||||||
uint32_t dwReplaceFlags,
|
|
||||||
void *lpExclude,
|
|
||||||
void *lpReserved)
|
|
||||||
{
|
|
||||||
wchar_t *oldTrans;
|
|
||||||
wchar_t *newTrans;
|
|
||||||
BOOL ok;
|
|
||||||
|
|
||||||
ok = path_transform_w(&oldTrans, lpReplacedFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = path_transform_w(&newTrans, lpReplacementFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
free(oldTrans);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = next_ReplaceFileW(
|
|
||||||
oldTrans ? oldTrans : lpReplacedFileName,
|
|
||||||
newTrans ? newTrans : lpReplacementFileName,
|
|
||||||
lpBackupFileName,
|
|
||||||
dwReplaceFlags,
|
|
||||||
lpExclude,
|
|
||||||
lpReserved);
|
|
||||||
|
|
||||||
free(oldTrans);
|
|
||||||
free(newTrans);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_DeleteFileA(const char *lpFileName)
|
|
||||||
{
|
|
||||||
char *trans;
|
|
||||||
BOOL ok;
|
|
||||||
|
|
||||||
ok = path_transform_a(&trans, lpFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = next_DeleteFileA(trans ? trans: lpFileName);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL WINAPI hook_DeleteFileW(const wchar_t *lpFileName)
|
|
||||||
{
|
|
||||||
wchar_t *trans;
|
|
||||||
BOOL ok;
|
|
||||||
|
|
||||||
ok = path_transform_w(&trans, lpFileName);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = next_DeleteFileW(trans ? trans: lpFileName);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
@ -13,6 +13,7 @@ EXPORTS
|
|||||||
amDllVideoSetResolution @3
|
amDllVideoSetResolution @3
|
||||||
idac_io_get_api_version
|
idac_io_get_api_version
|
||||||
idac_io_init
|
idac_io_init
|
||||||
|
idac_io_poll
|
||||||
idac_io_get_opbtns
|
idac_io_get_opbtns
|
||||||
idac_io_get_gamebtns
|
idac_io_get_gamebtns
|
||||||
idac_io_get_shifter
|
idac_io_get_shifter
|
||||||
|
@ -52,6 +52,10 @@ HRESULT idac_xi_init(const struct idac_xi_config *cfg, const struct idac_io_back
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT idac_io_poll(void) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg) {
|
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg) {
|
||||||
/* Deadzones check */
|
/* Deadzones check */
|
||||||
if (cfg->left_stick_deadzone > 32767 || cfg->left_stick_deadzone < 0) {
|
if (cfg->left_stick_deadzone > 32767 || cfg->left_stick_deadzone < 0) {
|
||||||
|
@ -39,5 +39,4 @@ void mai2_hook_config_load(
|
|||||||
io4_config_load(&cfg->io4, filename);
|
io4_config_load(&cfg->io4, filename);
|
||||||
vfd_config_load(&cfg->vfd, filename);
|
vfd_config_load(&cfg->vfd, filename);
|
||||||
mai2_dll_config_load(&cfg->dll, filename);
|
mai2_dll_config_load(&cfg->dll, filename);
|
||||||
unity_config_load(&cfg->unity, filename);
|
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
#include "platform/config.h"
|
#include "platform/config.h"
|
||||||
|
|
||||||
#include "unityhook/config.h"
|
|
||||||
|
|
||||||
struct mai2_hook_config {
|
struct mai2_hook_config {
|
||||||
struct platform_config platform;
|
struct platform_config platform;
|
||||||
struct aime_config aime;
|
struct aime_config aime;
|
||||||
@ -19,7 +17,6 @@ struct mai2_hook_config {
|
|||||||
struct io4_config io4;
|
struct io4_config io4;
|
||||||
struct vfd_config vfd;
|
struct vfd_config vfd;
|
||||||
struct mai2_dll_config dll;
|
struct mai2_dll_config dll;
|
||||||
struct unity_config unity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void mai2_dll_config_load(
|
void mai2_dll_config_load(
|
||||||
|
@ -12,11 +12,10 @@
|
|||||||
#include "mai2hook/config.h"
|
#include "mai2hook/config.h"
|
||||||
#include "mai2hook/io4.h"
|
#include "mai2hook/io4.h"
|
||||||
#include "mai2hook/mai2-dll.h"
|
#include "mai2hook/mai2-dll.h"
|
||||||
|
#include "mai2hook/unity.h"
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "unityhook/hook.h"
|
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
static HMODULE mai2_hook_mod;
|
static HMODULE mai2_hook_mod;
|
||||||
@ -81,7 +80,7 @@ static DWORD CALLBACK mai2_pre_startup(void)
|
|||||||
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
||||||
hooked earlier in the `mai2hook` initialization. */
|
hooked earlier in the `mai2hook` initialization. */
|
||||||
|
|
||||||
unity_hook_init(&mai2_hook_cfg.unity, mai2_hook_mod);
|
unity_hook_init();
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ shared_library(
|
|||||||
hooklib_lib,
|
hooklib_lib,
|
||||||
mai2io_lib,
|
mai2io_lib,
|
||||||
platform_lib,
|
platform_lib,
|
||||||
unityhook_lib,
|
|
||||||
util_lib,
|
util_lib,
|
||||||
],
|
],
|
||||||
sources : [
|
sources : [
|
||||||
@ -26,5 +25,7 @@ shared_library(
|
|||||||
'io4.h',
|
'io4.h',
|
||||||
'mai2-dll.c',
|
'mai2-dll.c',
|
||||||
'mai2-dll.h',
|
'mai2-dll.h',
|
||||||
|
'unity.h',
|
||||||
|
'unity.c',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -1,23 +1,14 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#include "hook/table.h"
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
#include "hooklib/dll.h"
|
||||||
#include "hooklib/path.h"
|
#include "hooklib/path.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
#include "doorstop.h"
|
|
||||||
#include "hook.h"
|
|
||||||
|
|
||||||
static bool unity_hook_initted;
|
|
||||||
static struct unity_config unity_config;
|
|
||||||
|
|
||||||
static const wchar_t *target_modules[] = {
|
|
||||||
L"mono.dll",
|
|
||||||
L"mono-2.0-bdwgc.dll",
|
|
||||||
L"cri_ware_unity.dll",
|
|
||||||
};
|
|
||||||
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 my_LoadLibraryW(const wchar_t *name);
|
||||||
@ -31,25 +22,19 @@ static const struct hook_symbol unity_kernel32_syms[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void unity_hook_init(const struct unity_config *cfg, HINSTANCE self) {
|
static const wchar_t *target_modules[] = {
|
||||||
assert(cfg != NULL);
|
L"mono-2.0-bdwgc.dll",
|
||||||
|
L"cri_ware_unity.dll",
|
||||||
|
};
|
||||||
|
static const size_t target_modules_len = _countof(target_modules);
|
||||||
|
|
||||||
if (!cfg->enable) {
|
void unity_hook_init(void)
|
||||||
return;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
if (unity_hook_initted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&unity_config, cfg, sizeof(*cfg));
|
|
||||||
dll_hook_insert_hooks(NULL);
|
dll_hook_insert_hooks(NULL);
|
||||||
|
|
||||||
unity_hook_initted = true;
|
|
||||||
dprintf("Unity: Hook enabled.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dll_hook_insert_hooks(HMODULE target) {
|
static void dll_hook_insert_hooks(HMODULE target)
|
||||||
|
{
|
||||||
hook_table_apply(
|
hook_table_apply(
|
||||||
target,
|
target,
|
||||||
"kernel32.dll",
|
"kernel32.dll",
|
||||||
@ -57,7 +42,8 @@ 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 my_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;
|
||||||
@ -80,11 +66,6 @@ static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name) {
|
|||||||
if (!already_loaded && result != NULL) {
|
if (!already_loaded && result != NULL) {
|
||||||
name_len = wcslen(name);
|
name_len = wcslen(name);
|
||||||
|
|
||||||
// mono entrypoint for injecting target_assembly
|
|
||||||
if (GetProcAddress(result, "mono_jit_init_version")) {
|
|
||||||
doorstop_mono_hook_init(&unity_config, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < target_modules_len; i++) {
|
for (size_t i = 0; i < target_modules_len; i++) {
|
||||||
target_module = target_modules[i];
|
target_module = target_modules[i];
|
||||||
target_module_len = wcslen(target_module);
|
target_module_len = wcslen(target_module);
|
3
mai2hook/unity.h
Normal file
3
mai2hook/unity.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void unity_hook_init(void);
|
@ -42,7 +42,6 @@ shlwapi_lib = cc.find_library('shlwapi')
|
|||||||
dinput8_lib = cc.find_library('dinput8')
|
dinput8_lib = cc.find_library('dinput8')
|
||||||
dxguid_lib = cc.find_library('dxguid')
|
dxguid_lib = cc.find_library('dxguid')
|
||||||
xinput_lib = cc.find_library('xinput')
|
xinput_lib = cc.find_library('xinput')
|
||||||
pathcch_lib = cc.find_library('pathcch')
|
|
||||||
|
|
||||||
inc = include_directories('.')
|
inc = include_directories('.')
|
||||||
capnhook = subproject('capnhook')
|
capnhook = subproject('capnhook')
|
||||||
@ -56,7 +55,6 @@ subdir('platform')
|
|||||||
subdir('util')
|
subdir('util')
|
||||||
|
|
||||||
subdir('gfxhook')
|
subdir('gfxhook')
|
||||||
subdir('unityhook')
|
|
||||||
|
|
||||||
subdir('aimeio')
|
subdir('aimeio')
|
||||||
subdir('chuniio')
|
subdir('chuniio')
|
||||||
|
@ -42,5 +42,4 @@ void mu3_hook_config_load(
|
|||||||
gfx_config_load(&cfg->gfx, filename);
|
gfx_config_load(&cfg->gfx, 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);
|
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
|
|
||||||
#include "platform/config.h"
|
#include "platform/config.h"
|
||||||
|
|
||||||
#include "unityhook/config.h"
|
|
||||||
|
|
||||||
struct mu3_hook_config {
|
struct mu3_hook_config {
|
||||||
struct platform_config platform;
|
struct platform_config platform;
|
||||||
struct aime_config aime;
|
struct aime_config aime;
|
||||||
@ -24,7 +22,6 @@ struct mu3_hook_config {
|
|||||||
// 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void mu3_dll_config_load(
|
void mu3_dll_config_load(
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "board/io4.h"
|
||||||
#include "board/sg-reader.h"
|
#include "board/sg-reader.h"
|
||||||
#include "board/vfd.h"
|
#include "board/vfd.h"
|
||||||
|
|
||||||
@ -19,12 +20,10 @@
|
|||||||
#include "mu3hook/config.h"
|
#include "mu3hook/config.h"
|
||||||
#include "mu3hook/io4.h"
|
#include "mu3hook/io4.h"
|
||||||
#include "mu3hook/mu3-dll.h"
|
#include "mu3hook/mu3-dll.h"
|
||||||
|
#include "mu3hook/unity.h"
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "unityhook/config.h"
|
|
||||||
#include "unityhook/hook.h"
|
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
static HMODULE mu3_hook_mod;
|
static HMODULE mu3_hook_mod;
|
||||||
@ -100,7 +99,7 @@ static DWORD CALLBACK mu3_pre_startup(void)
|
|||||||
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
||||||
hooked earlier in the `mu3hook` initialization. */
|
hooked earlier in the `mu3hook` initialization. */
|
||||||
|
|
||||||
unity_hook_init(&mu3_hook_cfg.unity, mu3_hook_mod);
|
unity_hook_init();
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ shared_library(
|
|||||||
hooklib_lib,
|
hooklib_lib,
|
||||||
mu3io_lib,
|
mu3io_lib,
|
||||||
platform_lib,
|
platform_lib,
|
||||||
unityhook_lib,
|
|
||||||
util_lib,
|
util_lib,
|
||||||
],
|
],
|
||||||
sources : [
|
sources : [
|
||||||
@ -28,5 +27,7 @@ shared_library(
|
|||||||
'io4.h',
|
'io4.h',
|
||||||
'mu3-dll.c',
|
'mu3-dll.c',
|
||||||
'mu3-dll.h',
|
'mu3-dll.h',
|
||||||
|
'unity.h',
|
||||||
|
'unity.c',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
95
mu3hook/unity.c
Normal file
95
mu3hook/unity.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
#include "hooklib/dll.h"
|
||||||
|
#include "hooklib/path.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static void dll_hook_insert_hooks(HMODULE target);
|
||||||
|
|
||||||
|
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name);
|
||||||
|
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
|
||||||
|
|
||||||
|
static const struct hook_symbol unity_kernel32_syms[] = {
|
||||||
|
{
|
||||||
|
.name = "LoadLibraryW",
|
||||||
|
.patch = my_LoadLibraryW,
|
||||||
|
.link = (void **) &next_LoadLibraryW,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const wchar_t *target_modules[] = {
|
||||||
|
L"mono.dll",
|
||||||
|
L"cri_ware_unity.dll",
|
||||||
|
};
|
||||||
|
static const size_t target_modules_len = _countof(target_modules);
|
||||||
|
|
||||||
|
void unity_hook_init(void)
|
||||||
|
{
|
||||||
|
dll_hook_insert_hooks(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dll_hook_insert_hooks(HMODULE target)
|
||||||
|
{
|
||||||
|
hook_table_apply(
|
||||||
|
target,
|
||||||
|
"kernel32.dll",
|
||||||
|
unity_kernel32_syms,
|
||||||
|
_countof(unity_kernel32_syms));
|
||||||
|
}
|
||||||
|
|
||||||
|
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name)
|
||||||
|
{
|
||||||
|
const wchar_t *name_end;
|
||||||
|
const wchar_t *target_module;
|
||||||
|
bool already_loaded;
|
||||||
|
HMODULE result;
|
||||||
|
size_t name_len;
|
||||||
|
size_t target_module_len;
|
||||||
|
|
||||||
|
if (name == NULL) {
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the module is already loaded
|
||||||
|
already_loaded = GetModuleHandleW(name) != NULL;
|
||||||
|
|
||||||
|
// Must call the next handler so the DLL reference count is incremented
|
||||||
|
result = next_LoadLibraryW(name);
|
||||||
|
|
||||||
|
if (!already_loaded && result != NULL) {
|
||||||
|
name_len = wcslen(name);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < target_modules_len; i++) {
|
||||||
|
target_module = target_modules[i];
|
||||||
|
target_module_len = wcslen(target_module);
|
||||||
|
|
||||||
|
// Check if the newly loaded library is at least the length of
|
||||||
|
// the name of the target module
|
||||||
|
if (name_len < target_module_len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_end = &name[name_len - target_module_len];
|
||||||
|
|
||||||
|
// Check if the name of the newly loaded library is one of the
|
||||||
|
// modules the path hooks should be injected into
|
||||||
|
if (_wcsicmp(name_end, target_module) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("Unity: Loaded %S\n", target_module);
|
||||||
|
|
||||||
|
dll_hook_insert_hooks(result);
|
||||||
|
path_hook_insert_hooks(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
3
mu3hook/unity.h
Normal file
3
mu3hook/unity.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void unity_hook_init(void);
|
@ -113,14 +113,6 @@ void dns_config_load(struct dns_config *cfg, const wchar_t *filename)
|
|||||||
cfg->aimedb,
|
cfg->aimedb,
|
||||||
_countof(cfg->aimedb),
|
_countof(cfg->aimedb),
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
GetPrivateProfileStringW(
|
|
||||||
L"dns",
|
|
||||||
L"title",
|
|
||||||
L"title",
|
|
||||||
cfg->title,
|
|
||||||
_countof(cfg->title),
|
|
||||||
filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hwmon_config_load(struct hwmon_config *cfg, const wchar_t *filename)
|
void hwmon_config_load(struct hwmon_config *cfg, const wchar_t *filename)
|
||||||
|
@ -82,33 +82,6 @@ HRESULT dns_platform_hook_init(const struct dns_config *cfg)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// crossbeats REV.
|
|
||||||
hr = dns_hook_push(L"https://rev-ent.ac.capcom.jp:443", cfg->title);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AimePay
|
|
||||||
hr = dns_hook_push(L"api-aime.am-all.net", cfg->startup);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// E-MONEY
|
|
||||||
hr = dns_hook_push(L"tasms-api-basis.thincacloud.com", cfg->startup);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = dns_hook_push(L"shop.tfps.thincacloud.com", cfg->startup);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if your ISP resolves bad domains, it will kill the network. These 2
|
// if your ISP resolves bad domains, it will kill the network. These 2
|
||||||
// *cannot* resolve
|
// *cannot* resolve
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ struct dns_config {
|
|||||||
wchar_t startup[128];
|
wchar_t startup[128];
|
||||||
wchar_t billing[128];
|
wchar_t billing[128];
|
||||||
wchar_t aimedb[128];
|
wchar_t aimedb[128];
|
||||||
wchar_t title[128];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT dns_platform_hook_init(const struct dns_config *cfg);
|
HRESULT dns_platform_hook_init(const struct dns_config *cfg);
|
||||||
|
@ -14,22 +14,22 @@
|
|||||||
#include "util/str.h"
|
#include "util/str.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NUSEC_IOCTL_PING = CTL_CODE(0x22, 0x845, METHOD_BUFFERED, FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_PING = 0x22A114,
|
||||||
NUSEC_IOCTL_GET_PLAY_COUNT = CTL_CODE(0x22, 0x854, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_ERASE_TRACE_LOG = 0x22E188,
|
||||||
NUSEC_IOCTL_ADD_PLAY_COUNT = CTL_CODE(0x22, 0x855, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_TD_ERASE_USED = 0x22E18C,
|
||||||
NUSEC_IOCTL_ERASE_TRACE_LOG = CTL_CODE(0x22, 0x862, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_ADD_PLAY_COUNT = 0x22E154,
|
||||||
NUSEC_IOCTL_TD_ERASE_USED = CTL_CODE(0x22, 0x863, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_BILLING_CA_CERT = 0x22E1C4,
|
||||||
NUSEC_IOCTL_PUT_TRACE_LOG_DATA = CTL_CODE(0x22, 0x864, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_BILLING_PUBKEY = 0x22E1C8,
|
||||||
NUSEC_IOCTL_GET_TRACE_LOG_DATA = CTL_CODE(0x22, 0x865, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_NEARFULL = 0x22E20C,
|
||||||
NUSEC_IOCTL_GET_TRACE_LOG_STATE = CTL_CODE(0x22, 0x866, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_NVRAM_AVAILABLE = 0x22E19C,
|
||||||
NUSEC_IOCTL_GET_NVRAM_AVAILABLE = CTL_CODE(0x22, 0x867, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_NVRAM_GEOMETRY = 0x22E24C,
|
||||||
NUSEC_IOCTL_GET_BILLING_CA_CERT = CTL_CODE(0x22, 0x871, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_PLAY_COUNT = 0x22E150,
|
||||||
NUSEC_IOCTL_GET_BILLING_PUBKEY = CTL_CODE(0x22, 0x872, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_PLAY_LIMIT = 0x22E204,
|
||||||
NUSEC_IOCTL_GET_PLAY_LIMIT = CTL_CODE(0x22, 0x881, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_TRACE_LOG_DATA = 0x22E194,
|
||||||
NUSEC_IOCTL_PUT_PLAY_LIMIT = CTL_CODE(0x22, 0x882, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_GET_TRACE_LOG_STATE = 0x22E198,
|
||||||
NUSEC_IOCTL_GET_NEARFULL = CTL_CODE(0x22, 0x883, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_PUT_NEARFULL = 0x22E210,
|
||||||
NUSEC_IOCTL_PUT_NEARFULL = CTL_CODE(0x22, 0x884, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_PUT_PLAY_LIMIT = 0x22E208,
|
||||||
NUSEC_IOCTL_GET_NVRAM_GEOMETRY = CTL_CODE(0x22, 0x893, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
NUSEC_IOCTL_PUT_TRACE_LOG_DATA = 0x22E190,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nusec_log_record {
|
struct nusec_log_record {
|
||||||
|
@ -277,12 +277,11 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count)
|
|||||||
const wchar_t *redir;
|
const wchar_t *redir;
|
||||||
size_t required;
|
size_t required;
|
||||||
size_t redir_len;
|
size_t redir_len;
|
||||||
size_t src_len;
|
|
||||||
|
|
||||||
assert(src != NULL);
|
assert(src != NULL);
|
||||||
assert(count != NULL);
|
assert(count != NULL);
|
||||||
|
|
||||||
if (src[0] == L'\0' || src[1] != L':') {
|
if (src[0] == L'\0' || src[1] != L':' || !path_is_separator_w(src[2])) {
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,15 +304,10 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count)
|
|||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GetFileAttributesW would request the src "E:", so fix the src_len in
|
|
||||||
in order to redirect the drive letter successfully */
|
|
||||||
|
|
||||||
src_len = path_is_separator_w(src[2]) ? 3 : 2;
|
|
||||||
|
|
||||||
/* Cut off <prefix>\, replace with redir path, count NUL terminator */
|
/* Cut off <prefix>\, replace with redir path, count NUL terminator */
|
||||||
|
|
||||||
redir_len = wcslen(redir);
|
redir_len = wcslen(redir);
|
||||||
required = wcslen(src) - src_len + redir_len + 1;
|
required = wcslen(src) - 3 + redir_len + 1;
|
||||||
|
|
||||||
if (dest != NULL) {
|
if (dest != NULL) {
|
||||||
if (required > *count) {
|
if (required > *count) {
|
||||||
@ -321,7 +315,7 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wcscpy_s(dest, *count, redir);
|
wcscpy_s(dest, *count, redir);
|
||||||
wcscpy_s(dest + redir_len, *count - redir_len, src + src_len);
|
wcscpy_s(dest + redir_len, *count - redir_len, src + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
*count = required;
|
*count = required;
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#include "config.h"
|
|
||||||
|
|
||||||
void unity_config_load(struct unity_config *cfg, const wchar_t *filename) {
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"unity", L"enable", 1, filename);
|
|
||||||
|
|
||||||
GetPrivateProfileStringW(
|
|
||||||
L"unity",
|
|
||||||
L"targetAssembly",
|
|
||||||
L"",
|
|
||||||
cfg->target_assembly,
|
|
||||||
_countof(cfg->target_assembly),
|
|
||||||
filename
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
struct unity_config {
|
|
||||||
bool enable;
|
|
||||||
wchar_t target_assembly[MAX_PATH];
|
|
||||||
};
|
|
||||||
|
|
||||||
void unity_config_load(struct unity_config *cfg, const wchar_t *filename);
|
|
@ -1,174 +0,0 @@
|
|||||||
// A simplified version of NeighTools' UnityDoorstop, allowing mod loaders
|
|
||||||
// like BepInEx to be loaded into Unity games.
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: CC0
|
|
||||||
// https://github.com/NeighTools/UnityDoorstop
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <pathcch.h>
|
|
||||||
#include <psapi.h>
|
|
||||||
|
|
||||||
#include "hooklib/procaddr.h"
|
|
||||||
#include "util/dprintf.h"
|
|
||||||
|
|
||||||
#include "doorstop.h"
|
|
||||||
#include "mono.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
static void * my_mono_jit_init_version(const char *root_domain_name, const char *runtime_version);
|
|
||||||
void doorstop_invoke(void *domain);
|
|
||||||
|
|
||||||
static char module_name[MAX_PATH];
|
|
||||||
static bool doorstop_hook_initted;
|
|
||||||
static struct unity_config unity_config;
|
|
||||||
static struct hook_symbol unity_mono_syms[] = {
|
|
||||||
{
|
|
||||||
.name = "mono_jit_init_version",
|
|
||||||
.patch = my_mono_jit_init_version,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void doorstop_mono_hook_init(const struct unity_config *cfg, HINSTANCE module) {
|
|
||||||
if (doorstop_hook_initted || cfg->target_assembly[0] == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetModuleBaseNameA(GetCurrentProcess(), module, module_name, MAX_PATH);
|
|
||||||
|
|
||||||
memcpy(&unity_config, cfg, sizeof(*cfg));
|
|
||||||
load_mono_functions(module);
|
|
||||||
proc_addr_table_push(module_name, unity_mono_syms, _countof(unity_mono_syms));
|
|
||||||
|
|
||||||
doorstop_hook_initted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void * my_mono_jit_init_version(const char *root_domain_name, const char *runtime_version) {
|
|
||||||
dprintf("Unity: Starting Mono domain \"%s\"\n", root_domain_name);
|
|
||||||
|
|
||||||
SetEnvironmentVariableW(L"DOORSTOP_DLL_SEARCH_DIRS", widen(mono_assembly_getrootdir()));
|
|
||||||
|
|
||||||
void* domain = mono_jit_init_version(root_domain_name, runtime_version);
|
|
||||||
|
|
||||||
doorstop_invoke(domain);
|
|
||||||
return domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
void doorstop_invoke(void* domain) {
|
|
||||||
if (GetEnvironmentVariableW(L"DOORSTOP_INITIALIZED", NULL, 0) != 0) {
|
|
||||||
dprintf("Unity: Doorstop is already initialized.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetEnvironmentVariableW(L"DOORSTOP_INITIALIZED", L"TRUE");
|
|
||||||
|
|
||||||
mono_thread_set_main(mono_thread_current());
|
|
||||||
|
|
||||||
if (mono_domain_set_config) {
|
|
||||||
#define CONFIG_EXT L".config"
|
|
||||||
|
|
||||||
wchar_t config_path[MAX_PATH];
|
|
||||||
size_t config_path_len = GetModuleFileNameW(NULL, config_path, MAX_PATH);
|
|
||||||
wchar_t *folder_name = wcsdup(config_path);
|
|
||||||
|
|
||||||
PathCchRemoveFileSpec(folder_name, config_path_len + 1);
|
|
||||||
wmemcpy(config_path + config_path_len, CONFIG_EXT, sizeof(CONFIG_EXT) / sizeof(CONFIG_EXT[0]));
|
|
||||||
|
|
||||||
char *config_path_n = narrow(config_path);
|
|
||||||
char *folder_name_n = narrow(folder_name);
|
|
||||||
|
|
||||||
dprintf("Unity: Setting config paths: base dir: %s; config path: %s\n", folder_name_n, config_path_n);
|
|
||||||
|
|
||||||
mono_domain_set_config(domain, folder_name_n, config_path_n);
|
|
||||||
|
|
||||||
free(folder_name);
|
|
||||||
free(config_path_n);
|
|
||||||
free(folder_name_n);
|
|
||||||
|
|
||||||
#undef CONFIG_EXT
|
|
||||||
}
|
|
||||||
|
|
||||||
SetEnvironmentVariableW(L"DOORSTOP_INVOKE_DLL_PATH", unity_config.target_assembly);
|
|
||||||
|
|
||||||
char *assembly_dir = mono_assembly_getrootdir();
|
|
||||||
dprintf("Unity: Assembly directory: %s\n", assembly_dir);
|
|
||||||
|
|
||||||
SetEnvironmentVariableA("DOORSTOP_MANAGED_FOLDER_DIR", assembly_dir);
|
|
||||||
|
|
||||||
wchar_t app_path[MAX_PATH];
|
|
||||||
GetModuleFileNameW(NULL, app_path, MAX_PATH);
|
|
||||||
SetEnvironmentVariableW(L"DOORSTOP_PROCESS_PATH", app_path);
|
|
||||||
|
|
||||||
char* dll_path = narrow(unity_config.target_assembly);
|
|
||||||
|
|
||||||
dprintf("Unity: Loading assembly: %s\n", dll_path);
|
|
||||||
|
|
||||||
void* assembly = mono_domain_assembly_open(domain, dll_path);
|
|
||||||
|
|
||||||
if (!assembly) {
|
|
||||||
dprintf("Unity: Failed to load assembly\n");
|
|
||||||
free(dll_path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *image = mono_assembly_get_image(assembly);
|
|
||||||
|
|
||||||
if (!image) {
|
|
||||||
dprintf("Unity: Assembly image doesn't exist\n");
|
|
||||||
free(dll_path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *desc = mono_method_desc_new("*:Main", FALSE);
|
|
||||||
void *method = mono_method_desc_search_in_image(desc, image);
|
|
||||||
|
|
||||||
if (!method) {
|
|
||||||
dprintf("Unity: Assembly does not have a valid entrypoint.\n");
|
|
||||||
free(dll_path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *signature = mono_method_signature(method);
|
|
||||||
UINT32 params = mono_signature_get_param_count(signature);
|
|
||||||
void **args = NULL;
|
|
||||||
|
|
||||||
if (params == 1) {
|
|
||||||
// If there is a parameter, it's most likely a string[].
|
|
||||||
void *args_array = mono_array_new(domain, mono_get_string_class(), 0);
|
|
||||||
args = malloc(sizeof(void*) * 1);
|
|
||||||
args[0] = args_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("Unity: Invoking method %p\n", method);
|
|
||||||
|
|
||||||
void *exc = NULL;
|
|
||||||
mono_runtime_invoke(method, NULL, args, &exc);
|
|
||||||
|
|
||||||
if (exc) {
|
|
||||||
dprintf("Unity: Error invoking method!\n");
|
|
||||||
|
|
||||||
void *ex_class = mono_get_exception_class();
|
|
||||||
void *to_string_desc = mono_method_desc_new("*:ToString()", FALSE);
|
|
||||||
void* to_string_method = mono_method_desc_search_in_class(to_string_desc, ex_class);
|
|
||||||
|
|
||||||
mono_method_desc_free(to_string_desc);
|
|
||||||
|
|
||||||
if (to_string_method) {
|
|
||||||
void* real_to_string_method = mono_object_get_virtual_method(exc, to_string_method);
|
|
||||||
void* exc2 = NULL;
|
|
||||||
void* str = mono_runtime_invoke(real_to_string_method, exc, NULL, &exc2);
|
|
||||||
|
|
||||||
if (!exc2) {
|
|
||||||
char* exc_str = mono_string_to_utf8(str);
|
|
||||||
dprintf("Unity: Error message: %s\n", exc_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mono_method_desc_free(desc);
|
|
||||||
free(dll_path);
|
|
||||||
|
|
||||||
if (args) {
|
|
||||||
free(args);
|
|
||||||
args = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
void doorstop_mono_hook_init(const struct unity_config *cfg, HINSTANCE module);
|
|
@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
void unity_hook_init(const struct unity_config *cfg, HINSTANCE self);
|
|
@ -1,20 +0,0 @@
|
|||||||
unityhook_lib = static_library(
|
|
||||||
'unityhook',
|
|
||||||
include_directories: inc,
|
|
||||||
implicit_include_directories: false,
|
|
||||||
c_pch: '../precompiled.h',
|
|
||||||
dependencies: [
|
|
||||||
capnhook.get_variable('hook_dep'),
|
|
||||||
pathcch_lib
|
|
||||||
],
|
|
||||||
sources: [
|
|
||||||
'mono.h',
|
|
||||||
'config.c',
|
|
||||||
'config.h',
|
|
||||||
'doorstop.c',
|
|
||||||
'doorstop.h',
|
|
||||||
'hook.c',
|
|
||||||
'hook.h',
|
|
||||||
'util.h'
|
|
||||||
],
|
|
||||||
)
|
|
100
unityhook/mono.h
100
unityhook/mono.h
@ -1,100 +0,0 @@
|
|||||||
// 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
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
wchar_t *widen(const char *str) {
|
|
||||||
const int reqsz = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
|
|
||||||
wchar_t *result = malloc(reqsz * sizeof(wchar_t));
|
|
||||||
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, str, -1, result, reqsz);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *narrow(const wchar_t *str) {
|
|
||||||
const int reqsz = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
|
|
||||||
char *result = malloc(reqsz * sizeof(char));
|
|
||||||
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, str, -1, result, reqsz, NULL, NULL);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
Reference in New Issue
Block a user