diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index ad27475..56c0116 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -18,16 +18,18 @@ #include "hooklib/serial.h" #include "hooklib/spike.h" -#include "platform/hwmon.h" -#include "platform/nusec.h" +#include "platform/config.h" +#include "platform/platform.h" #include "util/dprintf.h" +static HMODULE chuni_hook_mod; static process_entry_t chuni_startup; static DWORD CALLBACK chuni_pre_startup(void) { struct amex_config amex_cfg; + struct nu_config nu_cfg; HMODULE d3dc; dprintf("--- Begin chuni_pre_startup ---\n"); @@ -50,8 +52,8 @@ static DWORD CALLBACK chuni_pre_startup(void) /* Initialize platform API emulation */ - hwmon_hook_init(); - nusec_hook_init(); + nu_config_load(&nu_cfg, L".\\segatools.ini"); + platform_hook_init_nu(&nu_cfg, "SDBT", "AAV1", chuni_hook_mod); /* Initialize AMEX emulation */ @@ -90,6 +92,8 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) return TRUE; } + chuni_hook_mod = mod; + hr = process_hijack_startup(chuni_pre_startup, &chuni_startup); if (!SUCCEEDED(hr)) { diff --git a/divahook/dllmain.c b/divahook/dllmain.c index f725be2..c7fadba 100644 --- a/divahook/dllmain.c +++ b/divahook/dllmain.c @@ -18,16 +18,18 @@ #include "hooklib/serial.h" #include "hooklib/spike.h" -#include "platform/hwmon.h" -#include "platform/nusec.h" +#include "platform/config.h" +#include "platform/platform.h" #include "util/dprintf.h" +static HMODULE diva_hook_mod; static process_entry_t diva_startup; static DWORD CALLBACK diva_pre_startup(void) { struct amex_config amex_cfg; + struct nu_config nu_cfg; dprintf("--- Begin diva_pre_startup ---\n"); @@ -38,8 +40,8 @@ static DWORD CALLBACK diva_pre_startup(void) /* Initialize platform API emulation */ - hwmon_hook_init(); - nusec_hook_init(); + nu_config_load(&nu_cfg, L".\\segatools.ini"); + platform_hook_init_nu(&nu_cfg, "SBZV", "AAV0", diva_hook_mod); /* Initialize AMEX emulation */ @@ -74,6 +76,8 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) return TRUE; } + diva_hook_mod = mod; + hr = process_hijack_startup(diva_pre_startup, &diva_startup); if (!SUCCEEDED(hr)) { diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index 9db8c51..a96ef96 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -17,9 +17,8 @@ #include "idzhook/jvs.h" -#include "platform/amvideo.h" -#include "platform/hwmon.h" -#include "platform/nusec.h" +#include "platform/config.h" +#include "platform/platform.h" #include "util/dprintf.h" @@ -28,6 +27,7 @@ static process_entry_t idz_startup; static DWORD CALLBACK idz_pre_startup(void) { + struct nu_config nu_cfg; struct amex_config amex_cfg; dprintf("--- Begin idz_pre_startup ---\n"); @@ -39,9 +39,8 @@ static DWORD CALLBACK idz_pre_startup(void) /* Initialize platform API emulation */ - amvideo_hook_init(idz_hook_mod); - hwmon_hook_init(); - nusec_hook_init(); + nu_config_load(&nu_cfg, L".\\segatools.ini"); + platform_hook_init_nu(&nu_cfg, "SDDF", "AAV2", idz_hook_mod); /* Initialize AMEX emulation */ diff --git a/minihook/dllmain.c b/minihook/dllmain.c index 3505bc9..2bf7dae 100644 --- a/minihook/dllmain.c +++ b/minihook/dllmain.c @@ -8,6 +8,7 @@ #include "hooklib/clock.h" #include "hooklib/spike.h" +#include "platform/config.h" #include "platform/nusec.h" #include "util/dprintf.h" @@ -16,14 +17,17 @@ static process_entry_t app_startup; static DWORD CALLBACK app_pre_startup(void) { + struct nusec_config nusec_cfg; struct ds_config ds_cfg; dprintf("--- Begin %s ---\n", __func__); + nusec_config_load(&nusec_cfg, L".\\segatools.ini"); ds_config_load(&ds_cfg, L".\\segatools.ini"); + clock_hook_init(); + nusec_hook_init(&nusec_cfg, "SSSS", "AAV0"); ds_hook_init(&ds_cfg); - nusec_hook_init(); spike_hook_init("minispike.txt"); diff --git a/platform/amvideo.c b/platform/amvideo.c index 8c7d1e2..6f4b2e4 100644 --- a/platform/amvideo.c +++ b/platform/amvideo.c @@ -8,6 +8,8 @@ #include "hooklib/dll.h" #include "hooklib/reg.h" +#include "platform/amvideo.h" + #include "util/dprintf.h" /* Hook functions */ @@ -96,10 +98,16 @@ static const struct hook_symbol amvideo_syms[] = { } }; -HRESULT amvideo_hook_init(HMODULE redir_mod) +HRESULT amvideo_hook_init(const struct amvideo_config *cfg, HMODULE redir_mod) { HRESULT hr; + assert(cfg != NULL); + + if (!cfg->enable) { + return S_FALSE; + } + hr = reg_hook_push_key( HKEY_LOCAL_MACHINE, L"SYSTEM\\SEGA\\SystemProperty\\amVideo", diff --git a/platform/amvideo.h b/platform/amvideo.h index d81fc82..d14268f 100644 --- a/platform/amvideo.h +++ b/platform/amvideo.h @@ -2,4 +2,6 @@ #include -HRESULT amvideo_hook_init(HMODULE redir_mod); +#include "platform/config.h" + +HRESULT amvideo_hook_init(const struct amvideo_config *cfg, HMODULE redir_mod); diff --git a/platform/hwmon.c b/platform/hwmon.c index 15e5da9..8b4560b 100644 --- a/platform/hwmon.c +++ b/platform/hwmon.c @@ -5,6 +5,7 @@ #include "hook/iohook.h" +#include "platform/config.h" #include "platform/hwmon.h" #include "util/dprintf.h" @@ -23,10 +24,17 @@ static HRESULT hwmon_ioctl_read_cpu_temp(struct irp *irp); static HANDLE hwmon_fd; -void hwmon_hook_init(void) +HRESULT hwmon_hook_init(const struct hwmon_config *cfg) { + assert(cfg != NULL); + + if (!cfg->enable) { + return S_FALSE; + } + hwmon_fd = iohook_open_dummy_fd(); - iohook_push_handler(hwmon_handle_irp); + + return iohook_push_handler(hwmon_handle_irp); } static HRESULT hwmon_handle_irp(struct irp *irp) diff --git a/platform/hwmon.h b/platform/hwmon.h index 49d457d..a0274e6 100644 --- a/platform/hwmon.h +++ b/platform/hwmon.h @@ -1,3 +1,7 @@ #pragma once -void hwmon_hook_init(void); +#include + +#include "platform/config.h" + +HRESULT hwmon_hook_init(const struct hwmon_config *cfg); diff --git a/platform/meson.build b/platform/meson.build index e36c4bb..7dbd46c 100644 --- a/platform/meson.build +++ b/platform/meson.build @@ -13,9 +13,11 @@ platform_lib = static_library( 'config.h', 'hwmon.c', 'hwmon.h', - 'pcbid.c', - 'pcbid.h', 'nusec.c', 'nusec.h', + 'pcbid.c', + 'pcbid.h', + 'platform.c', + 'platform.h', ], ) diff --git a/platform/nusec.c b/platform/nusec.c index 49e3444..cf2a19f 100644 --- a/platform/nusec.c +++ b/platform/nusec.c @@ -1,9 +1,13 @@ #include #include +#include #include #include "hook/iohook.h" +#include "hooklib/reg.h" + +#include "platform/config.h" #include "platform/nusec.h" #include "util/dprintf.h" @@ -53,6 +57,51 @@ static HRESULT nusec_ioctl_put_nearfull(struct irp *irp); static HRESULT nusec_ioctl_put_play_limit(struct irp *irp); static HRESULT nusec_ioctl_put_trace_log_data(struct irp *irp); +static HRESULT nusec_reg_read_game_id(void *bytes, uint32_t *nbytes); +static HRESULT nusec_reg_read_keychip_id(void *bytes, uint32_t *nbytes); +static HRESULT nusec_reg_read_model_type(void *bytes, uint32_t *nbytes); +static HRESULT nusec_reg_read_platform_id(void *bytes, uint32_t *nbytes); +static HRESULT nusec_reg_read_region(void *bytes, uint32_t *nbytes); +static HRESULT nusec_reg_read_server_ip_ipv4(void *bytes, uint32_t *nbytes); +static HRESULT nusec_reg_read_server_ip_ipv6(void *bytes, uint32_t *nbytes); +static HRESULT nusec_reg_read_system_flag(void *bytes, uint32_t *nbytes); + +static const struct reg_hook_val nusec_reg_vals[] = { + { + .name = L"gameId", + .read = nusec_reg_read_game_id, + .type = REG_BINARY, + }, { + .name = L"keychipId", + .read = nusec_reg_read_keychip_id, + .type = REG_BINARY, + }, { + .name = L"modelType", + .read = nusec_reg_read_model_type, + .type = REG_DWORD, + }, { + .name = L"platformId", + .read = nusec_reg_read_platform_id, + .type = REG_BINARY, + }, { + .name = L"region", + .read = nusec_reg_read_region, + .type = REG_DWORD, + }, { + .name = L"serverIpIpv4", + .read = nusec_reg_read_server_ip_ipv4, + .type = REG_BINARY, + }, { + .name = L"serverIpIpv6", + .read = nusec_reg_read_server_ip_ipv6, + .type = REG_BINARY, + }, { + .name = L"systemFlag", + .read = nusec_reg_read_system_flag, + .type = REG_DWORD, + } +}; + static HANDLE nusec_fd; static uint32_t nusec_nearfull; static uint32_t nusec_play_count; @@ -60,14 +109,55 @@ static uint32_t nusec_play_limit; static struct nusec_log_record nusec_log[7154]; static size_t nusec_log_head; static size_t nusec_log_tail; +static struct nusec_config nusec_cfg; -void nusec_hook_init(void) +HRESULT nusec_hook_init( + const struct nusec_config *cfg, + const char *game_id, + const char *platform_id) { + HRESULT hr; + + assert(cfg != NULL); + assert(game_id != NULL && strlen(game_id) == sizeof(cfg->game_id)); + assert(platform_id != NULL && strlen(platform_id) == sizeof(cfg->platform_id)); + + if (!cfg->enable) { + return S_FALSE; + } + + memcpy(&nusec_cfg, cfg, sizeof(*cfg)); + + if (nusec_cfg.game_id[0] == '\0') { + memcpy(nusec_cfg.game_id, game_id, sizeof(nusec_cfg.game_id)); + } + + if (nusec_cfg.platform_id[0] == '\0') { + memcpy(nusec_cfg.platform_id, platform_id, sizeof(nusec_cfg.platform_id)); + } + nusec_nearfull = 0x00010200; nusec_play_count = 0; nusec_play_limit = 1024; nusec_fd = iohook_open_dummy_fd(); - iohook_push_handler(nusec_handle_irp); + + hr = iohook_push_handler(nusec_handle_irp); + + if (FAILED(hr)) { + return hr; + } + + hr = reg_hook_push_key( + HKEY_LOCAL_MACHINE, + L"SYSTEM\\SEGA\\SystemProperty\\keychip", + nusec_reg_vals, + _countof(nusec_reg_vals)); + + if (FAILED(hr)) { + return hr; + } + + return S_OK; } static HRESULT nusec_handle_irp(struct irp *irp) @@ -222,7 +312,7 @@ static HRESULT nusec_ioctl_get_billing_ca_cert(struct irp *irp) dprintf("Security: %s\n", __func__); fd = CreateFileW( - L"DEVICE\\ca.crt", + nusec_cfg.billing_ca, GENERIC_READ, FILE_SHARE_READ, NULL, @@ -271,7 +361,7 @@ static HRESULT nusec_ioctl_get_billing_pubkey(struct irp *irp) dprintf("Security: %s\n", __func__); fd = CreateFileW( - L"DEVICE\\billing.pub", + nusec_cfg.billing_pub, GENERIC_READ, FILE_SHARE_READ, NULL, @@ -460,3 +550,77 @@ static HRESULT nusec_ioctl_put_trace_log_data(struct irp *irp) return S_OK; } + +static HRESULT nusec_reg_read_game_id(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_bin( + bytes, + nbytes, + &nusec_cfg.game_id, + sizeof(nusec_cfg.game_id)); +} + +static HRESULT nusec_reg_read_keychip_id(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_bin( + bytes, + nbytes, + &nusec_cfg.keychip_id, + sizeof(nusec_cfg.keychip_id)); +} + +static HRESULT nusec_reg_read_model_type(void *bytes, uint32_t *nbytes) +{ + uint32_t u32; + char c; + + c = nusec_cfg.platform_id[3]; + + if (c >= '0' && c <= '9') { + u32 = c - '0'; + } else { + u32 = 0; + } + + return reg_hook_read_u32(bytes, nbytes, u32); +} + +static HRESULT nusec_reg_read_platform_id(void *bytes, uint32_t *nbytes) +{ + /* Fourth byte is a separate registry val (modelType). + We store it in the same config field for ease of configuration. */ + + return reg_hook_read_bin( + bytes, + nbytes, + &nusec_cfg.platform_id, + 3); +} + +static HRESULT nusec_reg_read_region(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_u32(bytes, nbytes, nusec_cfg.region); +} + +static HRESULT nusec_reg_read_server_ip_ipv4(void *bytes, uint32_t *nbytes) +{ + uint32_t subnet; + + subnet = _byteswap_ulong(nusec_cfg.subnet); + + return reg_hook_read_bin(bytes, nbytes, &subnet, sizeof(subnet)); +} + +static HRESULT nusec_reg_read_server_ip_ipv6(void *bytes, uint32_t *nbytes) +{ + uint8_t subnet[16]; + + memset(subnet, 0, sizeof(subnet)); + + return reg_hook_read_bin(bytes, nbytes, subnet, sizeof(subnet)); +} + +static HRESULT nusec_reg_read_system_flag(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_u32(bytes, nbytes, nusec_cfg.system_flag); +} diff --git a/platform/nusec.h b/platform/nusec.h index b826536..68f54ed 100644 --- a/platform/nusec.h +++ b/platform/nusec.h @@ -1,3 +1,10 @@ #pragma once -void nusec_hook_init(void); +#include + +#include "platform/config.h" + +HRESULT nusec_hook_init( + const struct nusec_config *cfg, + const char *game_id, + const char *platform_id); diff --git a/platform/platform.c b/platform/platform.c new file mode 100644 index 0000000..193729b --- /dev/null +++ b/platform/platform.c @@ -0,0 +1,43 @@ +#include + +#include + +#include "platform/amvideo.h" +#include "platform/config.h" +#include "platform/hwmon.h" +#include "platform/nusec.h" +#include "platform/platform.h" + +HRESULT platform_hook_init_nu( + const struct nu_config *cfg, + const char *game_id, + const char *platform_id, + HMODULE redir_mod) +{ + HRESULT hr; + + assert(cfg != NULL); + assert(game_id != NULL); + assert(platform_id != NULL); + assert(redir_mod != NULL); + + hr = amvideo_hook_init(&cfg->amvideo, redir_mod); + + if (FAILED(hr)) { + return hr; + } + + hr = hwmon_hook_init(&cfg->hwmon); + + if (FAILED(hr)) { + return hr; + } + + hr = nusec_hook_init(&cfg->nusec, game_id, platform_id); + + if (FAILED(hr)) { + return hr; + } + + return S_OK; +} diff --git a/platform/platform.h b/platform/platform.h new file mode 100644 index 0000000..bf948a3 --- /dev/null +++ b/platform/platform.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "platform/config.h" + +HRESULT platform_hook_init_nu( + const struct nu_config *cfg, + const char *game_id, + const char *platform_id, + HMODULE redir_mod);