diff --git a/Module.mk b/Module.mk index 96db938..c44caa0 100644 --- a/Module.mk +++ b/Module.mk @@ -136,6 +136,7 @@ include src/main/p4ioemu/Module.mk include src/main/pcbidgen/Module.mk include src/main/sdvxhook/Module.mk include src/main/sdvxhook2/Module.mk +include src/main/sdvxhook2-cn/Module.mk include src/main/sdvxio/Module.mk include src/main/sdvxio-kfca/Module.mk include src/main/security/Module.mk @@ -436,6 +437,20 @@ $(zipdir)/sdvx-05.zip: \ $(V)echo ... $@ $(V)zip -j $@ $^ +$(zipdir)/sdvx-05-cn.zip: \ + build/bin/avs2_1700-64/launcher.exe \ + build/bin/avs2_1700-64/sdvxhook2-cn.dll \ + build/bin/indep-64/config.exe \ + build/bin/indep-64/eamio.dll \ + build/bin/indep-64/geninput.dll \ + build/bin/indep-64/sdvxio.dll \ + dist/sdvx5/config.bat \ + dist/sdvx5/gamestart-cn.bat \ + dist/sdvx5/sdvxhook2-cn.conf \ + | $(zipdir)/ + $(V)echo ... $@ + $(V)zip -j $@ $^ + $(zipdir)/ddr-12-to-16.zip: \ build/bin/avs2_1508-32/launcher.exe \ build/bin/avs2_1508-32/ddrhook.dll \ @@ -523,6 +538,7 @@ $(BUILDDIR)/bemanitools.zip: \ $(zipdir)/src.zip \ $(zipdir)/sdvx-01-to-04.zip \ $(zipdir)/sdvx-05.zip \ + $(zipdir)/sdvx-05-cn.zip \ $(zipdir)/tools.zip \ $(zipdir)/tools-x64.zip \ CHANGELOG.md \ diff --git a/dist/sdvx5/gamestart-cn.bat b/dist/sdvx5/gamestart-cn.bat new file mode 100644 index 0000000..8435bd7 --- /dev/null +++ b/dist/sdvx5/gamestart-cn.bat @@ -0,0 +1,17 @@ +@echo off +cd /d %~dp0 + +if not exist dev mkdir dev +if not exist dev\e mkdir dev\e +if not exist dev\g mkdir dev\g +if not exist dev\nvram mkdir dev\nvram +if not exist dev\raw mkdir dev\raw +if not exist dev\raw\c.dest echo $null >> dev\raw\c.dest +if not exist dev\raw\log mkdir dev\raw\log +if not exist dev\raw\fscache mkdir dev\raw\fscache + +for /R prop\defaults %%D in (*.*) do ( + if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram +) + +launcher -H 268435456 -K sdvxhook2-cn.dll soundvoltex.dll --config sdvxhook2-cn.conf %* diff --git a/dist/sdvx5/sdvxhook2-cn.conf b/dist/sdvx5/sdvxhook2-cn.conf new file mode 100644 index 0000000..c02c139 --- /dev/null +++ b/dist/sdvx5/sdvxhook2-cn.conf @@ -0,0 +1,24 @@ +# Disable IO emulation and enable usage of real KFCA hardware +io.disable_io_emu=false + +# Path to unis version file under the prop.s folder +cn.unis_path=prop/unis.xml + +# Run the game in a framed window (requires windowed option) +gfx.framed=true + +# Run the game windowed +gfx.windowed=false + +# Windowed width, -1 for default size +gfx.window_width=720 + +# Windowed height, -1 for default size +gfx.window_height=1280 + +# Disables the camera emulation +cam.disable_emu=false + +# Override camera device ID detection (copy from device manager, do not escape) +cam.device_id1= + diff --git a/src/main/sdvxhook2-cn/Module.mk b/src/main/sdvxhook2-cn/Module.mk new file mode 100644 index 0000000..fd00fc6 --- /dev/null +++ b/src/main/sdvxhook2-cn/Module.mk @@ -0,0 +1,29 @@ +avsdlls += sdvxhook2-cn + +ldflags_sdvxhook2-cn := \ + -liphlpapi \ + -lsetupapi \ + -lcfgmgr32 \ + -lmf \ + -lmfplat \ + -lole32 \ + +deplibs_sdvxhook2-cn := \ + avs \ + +libs_sdvxhook2-cn := \ + acioemu \ + camhook \ + d3d9exhook \ + sdvxio \ + hook \ + hooklib \ + cconfig \ + util \ + +src_sdvxhook2-cn := \ + acio.c \ + kfca.c \ + dllmain.c \ + config-cn.c \ + unis-version.c \ diff --git a/src/main/sdvxhook2-cn/acio.c b/src/main/sdvxhook2-cn/acio.c new file mode 100644 index 0000000..7043276 --- /dev/null +++ b/src/main/sdvxhook2-cn/acio.c @@ -0,0 +1,92 @@ +// clang-format off +// Don't format because the order is important here +#include +#include +#include +#include +// clang-format on + +#include +#include +#include +#include + +#include "acioemu/addr.h" +#include "acioemu/emu.h" + +#include "hook/iohook.h" +#include "hooklib/rs232.h" + +#include "sdvxhook2-cn/acio.h" +#include "sdvxhook2-cn/kfca.h" + +#include "imports/avs.h" + +#include "util/defs.h" +#include "util/iobuf.h" +#include "util/log.h" +#include "util/str.h" + +static struct ac_io_emu ac_io_emu; + +void ac_io_port_init(void) +{ + ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2"); + + kfca_init(&ac_io_emu); + + rs232_hook_add_fd(ac_io_emu.fd); +} + +void ac_io_port_fini(void) +{ + ac_io_emu_fini(&ac_io_emu); +} + +HRESULT ac_io_port_dispatch_irp(struct irp *irp) +{ + const struct ac_io_message *msg; + HRESULT hr; + + log_assert(irp != NULL); + + if (!ac_io_emu_match_irp(&ac_io_emu, irp)) { + return irp_invoke_next(irp); + } + + for (;;) { + hr = ac_io_emu_dispatch_irp(&ac_io_emu, irp); + + if (hr != S_OK) { + return hr; + } + + msg = ac_io_emu_request_peek(&ac_io_emu); + + switch (msg->addr) { + case 0: + ac_io_emu_cmd_assign_addrs(&ac_io_emu, msg, 1); + log_warning("ac_io_emu_cmd_assign_addrs"); + + break; + + case 1: + kfca_dispatch_request(msg); + + break; + + case AC_IO_BROADCAST: + log_warning("Broadcast? (0x70) message on ACIO bus"); + + break; + + default: + log_warning( + "ACIO message on unhandled bus address: %d", msg->addr); + + break; + } + + ac_io_emu_request_pop(&ac_io_emu); + } +} diff --git a/src/main/sdvxhook2-cn/acio.h b/src/main/sdvxhook2-cn/acio.h new file mode 100644 index 0000000..7146c47 --- /dev/null +++ b/src/main/sdvxhook2-cn/acio.h @@ -0,0 +1,14 @@ +#ifndef SDVXHOOK2_5_AC_IO_H +#define SDVXHOOK2_5_AC_IO_H + +#include + +#include + +#include "hook/iohook.h" + +void ac_io_port_init(void); +void ac_io_port_fini(void); +HRESULT ac_io_port_dispatch_irp(struct irp *irp); + +#endif diff --git a/src/main/sdvxhook2-cn/config-cn.c b/src/main/sdvxhook2-cn/config-cn.c new file mode 100644 index 0000000..c492603 --- /dev/null +++ b/src/main/sdvxhook2-cn/config-cn.c @@ -0,0 +1,55 @@ +#include "cconfig/cconfig-util.h" + +#include "sdvxhook2-cn/config-cn.h" + +#include "util/log.h" + +#define SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY "io.disable_io_emu" +#define SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY "cn.unis_path" + +#define SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE false +#define SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE "prop/unis.xml" + +void sdvxhook2_cn_config_init(struct cconfig *config) +{ + cconfig_util_set_bool( + config, + SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY, + SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE, + "Disable IO emulation and enable usage of real KFCA hardware"); + + cconfig_util_set_str( + config, + SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY, + SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE, + "Path to unis version file under the prop.s folder"); +} + +void sdvxhook2_cn_config_get( + struct sdvxhook2_cn_config *cn_config, struct cconfig *config) +{ + if (!cconfig_util_get_bool( + config, + SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY, + &cn_config->disable_io_emu, + SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%d'", + SDVXHOOK2_CN_CONFIG_DISABLE_IO_EMU_KEY, + SDVXHOOK2_CN_CONFIG_DEFAULT_DISABLE_IO_EMU_VALUE); + } + + if (!cconfig_util_get_str( + config, + SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY, + cn_config->unis_path, + sizeof(cn_config->unis_path), + SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%s'", + SDVXHOOK2_CN_CONFIG_UNIS_PATH_KEY, + SDVXHOOK2_CN_CONFIG_DEFAULT_UNIS_PATH_VALUE); + } +} diff --git a/src/main/sdvxhook2-cn/config-cn.h b/src/main/sdvxhook2-cn/config-cn.h new file mode 100644 index 0000000..7458b11 --- /dev/null +++ b/src/main/sdvxhook2-cn/config-cn.h @@ -0,0 +1,18 @@ +#ifndef SDVXHOOK2_CN_CONFIG_H +#define SDVXHOOK2_CN_CONFIG_H + +#include + +#include "cconfig/cconfig.h" + +struct sdvxhook2_cn_config { + bool disable_io_emu; + char unis_path[256]; +}; + +void sdvxhook2_cn_config_init(struct cconfig *config); + +void sdvxhook2_cn_config_get( + struct sdvxhook2_cn_config *cn_config, struct cconfig *config); + +#endif \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/dllmain.c b/src/main/sdvxhook2-cn/dllmain.c new file mode 100644 index 0000000..bd389e6 --- /dev/null +++ b/src/main/sdvxhook2-cn/dllmain.c @@ -0,0 +1,151 @@ +#include + +#include +#include +#include +#include + +#include "bemanitools/eamio.h" +#include "bemanitools/sdvxio.h" + +#include "cconfig/cconfig-hook.h" + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/app.h" +#include "hooklib/rs232.h" + +#include "sdvxhook2-cn/acio.h" +#include "sdvxhook2-cn/config-cn.h" +#include "sdvxhook2-cn/unis-version.h" + +#include "camhook/cam.h" +#include "camhook/config-cam.h" + +#include "d3d9exhook/config-gfx.h" +#include "d3d9exhook/d3d9ex.h" + +#include "imports/avs.h" + +#include "util/log.h" +#include "util/str.h" +#include "util/thread.h" + +#define SDVXHOOK2_CN_INFO_HEADER \ + "sdvxhook for VW CN" \ + ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) "\n" +#define SDVXHOOK2_CN_CMD_USAGE \ + "Usage: launcher.exe -K sdvxhook2.dll [options...]" + +static const irp_handler_t sdvxhook_handlers[] = { + ac_io_port_dispatch_irp, +}; + +struct sdvxhook2_cn_config config_cn; +struct camhook_config_cam config_cam; +struct d3d9exhook_config_gfx config_gfx; + +static bool my_dll_entry_init(char *sidcode, struct property_node *param) +{ + struct cconfig *config; + + log_info("--- Begin sdvxhook dll_entry_init ---"); + + config = cconfig_init(); + + sdvxhook2_cn_config_init(config); + d3d9exhook_config_gfx_init(config); + camhook_config_cam_init(config, 1); + + if (!cconfig_hook_config_init( + config, + SDVXHOOK2_CN_INFO_HEADER "\n" SDVXHOOK2_CN_CMD_USAGE, + CCONFIG_CMD_USAGE_OUT_STDOUT)) { + cconfig_finit(config); + exit(EXIT_FAILURE); + } + + sdvxhook2_cn_config_get(&config_cn, config); + camhook_config_cam_get(&config_cam, config, 1); + d3d9exhook_config_gfx_get(&config_gfx, config); + + cconfig_finit(config); + + log_info(SDVXHOOK2_CN_INFO_HEADER); + log_info("Initializing sdvxhook2-cn..."); + + d3d9ex_configure(&config_gfx); + + /* Start up sdvxio.DLL */ + if (!config_cn.disable_io_emu) { + log_info("Starting sdvx IO backend"); + sdvx_io_set_loggers( + log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + + if (!sdvx_io_init( + avs_thread_create, avs_thread_join, avs_thread_destroy)) { + log_fatal("Initializing sdvx IO backend failed"); + } + } + + /* iohooks are okay, even if emu is diabled since the fake handlers won't be + * used */ + iohook_init(sdvxhook_handlers, lengthof(sdvxhook_handlers)); + rs232_hook_init(); + rs232_hook_limit_hooks(); + + if (!config_cn.disable_io_emu) { + ac_io_port_init(); + } + + // camera hooks + if (!config_cam.disable_emu) { + camhook_init(&config_cam); + } + + unis_version_hook_init(config_cn.unis_path); + + log_info("--- End sdvxhook dll_entry_init ---"); + + return app_hook_invoke_init(sidcode, param); +} + +static bool my_dll_entry_main(void) +{ + bool result; + + result = app_hook_invoke_main(); + + if (!config_cam.disable_emu) { + camhook_fini(); + } + + if (!config_cn.disable_io_emu) { + log_misc("Shutting down sdvx IO backend"); + sdvx_io_fini(); + } + + return result; +} + +/** + * Hook library Resort Anthem onwards + */ +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ + if (reason != DLL_PROCESS_ATTACH) { + goto end; + } + + log_to_external( + log_body_misc, log_body_info, log_body_warning, log_body_fatal); + + app_hook_init(my_dll_entry_init, my_dll_entry_main); + + acp_hook_init(); + adapter_hook_init(); + d3d9ex_hook_init(); + +end: + return TRUE; +} diff --git a/src/main/sdvxhook2-cn/kfca.c b/src/main/sdvxhook2-cn/kfca.c new file mode 100644 index 0000000..f4d8894 --- /dev/null +++ b/src/main/sdvxhook2-cn/kfca.c @@ -0,0 +1,196 @@ +#include + +#include +#include + +#include "acio/acio.h" + +#include "acioemu/emu.h" + +#include "bemanitools/sdvxio.h" + +#include "util/defs.h" +#include "util/log.h" +#include "util/time.h" + +static void kfca_send_version(const struct ac_io_message *req); +static void kfca_report_status(const struct ac_io_message *req, uint8_t status); +static void kfca_report_0128(const struct ac_io_message *req); +static void kfca_poll(const struct ac_io_message *req); +static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp); + +static struct ac_io_emu *kfca_ac_io_emu; + +void kfca_init(struct ac_io_emu *emu) +{ + log_assert(emu != NULL); + + kfca_ac_io_emu = emu; +} + +void kfca_dispatch_request(const struct ac_io_message *req) +{ + uint16_t cmd_code; + + cmd_code = ac_io_u16(req->cmd.code); + + switch (cmd_code) { + case AC_IO_CMD_GET_VERSION: + log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr); + kfca_send_version(req); + + break; + + case AC_IO_CMD_START_UP: + log_misc("AC_IO_CMD_START_UP(%d)", req->addr); + kfca_report_status(req, 0x00); + + break; + + case AC_IO_CMD_KFCA_POLL: + kfca_poll(req); + + break; + + case AC_IO_CMD_KFCA_WATCHDOG: + log_misc("AC_IO_CMD_KFCA_WATCHDOG(%d)", req->addr); + kfca_report_status(req, 0x00); + + break; + + case AC_IO_CMD_KFCA_AMP_CONTROL: + log_misc("AC_IO_CMD_KFCA_AMP_CONTROL(%d)", req->addr); + kfca_report_0128(req); + + break; + + default: + log_warning( + "Unknown ACIO message %04x on KFCA mode, addr=%d", + cmd_code, + req->addr); + + break; + } +} + +static void kfca_send_version(const struct ac_io_message *req) +{ + struct ac_io_message resp; + + resp.addr = req->addr | AC_IO_RESPONSE_FLAG; + resp.cmd.code = req->cmd.code; + resp.cmd.seq_no = req->cmd.seq_no; + resp.cmd.nbytes = sizeof(resp.cmd.version); + resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_KFCA); + resp.cmd.version.flag = 0x00; + resp.cmd.version.major = 0x01; + resp.cmd.version.minor = 0x01; + resp.cmd.version.revision = 0x00; + memcpy( + resp.cmd.version.product_code, + "KFCA", + sizeof(resp.cmd.version.product_code)); + strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date)); + strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time)); + + ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0); +} + +static void kfca_report_status(const struct ac_io_message *req, uint8_t status) +{ + struct ac_io_message resp; + + resp.addr = req->addr | AC_IO_RESPONSE_FLAG; + resp.cmd.code = req->cmd.code; + resp.cmd.seq_no = req->cmd.seq_no; + resp.cmd.nbytes = sizeof(resp.cmd.status); + resp.cmd.status = status; + + ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0); +} + +static void kfca_report_0128(const struct ac_io_message *req) +{ + struct ac_io_message resp; + + resp.addr = req->addr | AC_IO_RESPONSE_FLAG; + resp.cmd.code = req->cmd.code; + resp.cmd.seq_no = req->cmd.seq_no; + resp.cmd.nbytes = req->cmd.nbytes; + memcpy(resp.cmd.raw, req->cmd.raw, req->cmd.nbytes); + + ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0); +} + +static void kfca_poll(const struct ac_io_message *req) +{ + static uint32_t last_poll = 0; + uint64_t delay; + const struct ac_io_kfca_poll_out *pout; + uintptr_t ctx; + size_t i; + + /* Handle lighting output immediately */ + + pout = &req->cmd.kfca_poll_out; + + sdvx_io_set_gpio_lights(ac_io_u32(pout->gpio)); + + for (i = 0; i < lengthof(pout->pwm); i++) { + sdvx_io_set_pwm_light(i, pout->pwm[i]); + } + + sdvx_io_write_output(); + + /* SDVX expects only one poll response per frame. + + We use a thunk here to defer polling until right before the response + is due. */ + + delay = time_get_elapsed_ms(last_poll) < 16 ? 16000 : 0; + last_poll = time_get_counter(); + ctx = req->addr | (req->cmd.code << 8) | (req->cmd.seq_no << 24); + + ac_io_emu_response_push_thunk( + kfca_ac_io_emu, kfca_poll_thunk, (void *) ctx, delay); +} + +static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp) +{ + struct ac_io_kfca_poll_in *pin; + uintptr_t ctx; + uint8_t req_addr; + uint16_t req_code; + uint8_t req_seq_no; + + /* Unpack context "pointer" for relevant response information */ + + ctx = (uintptr_t) ctx_ptr; + req_addr = ctx; + req_code = ctx >> 8; + req_seq_no = ctx >> 24; + + /* Poll input now and construct an immediate response */ + + pin = &resp->cmd.kfca_poll_in; + + resp->addr = req_addr | AC_IO_RESPONSE_FLAG; + resp->cmd.code = req_code; + resp->cmd.seq_no = req_seq_no; + resp->cmd.nbytes = sizeof(*pin); + + sdvx_io_read_input(); + + memset(pin, 0, sizeof(*pin)); + + pin->adc[0] = sdvx_io_get_spinner_pos(0) << 6; + pin->adc[1] = sdvx_io_get_spinner_pos(1) << 6; + + pin->gpio_sys |= sdvx_io_get_input_gpio_sys() & 0x3F; + + pin->adc[0] = ac_io_u16(pin->adc[0]); + pin->adc[1] = ac_io_u16(pin->adc[1]); + pin->gpio[0] = ac_io_u16(sdvx_io_get_input_gpio(0)); + pin->gpio[1] = ac_io_u16(sdvx_io_get_input_gpio(1)); +} diff --git a/src/main/sdvxhook2-cn/kfca.h b/src/main/sdvxhook2-cn/kfca.h new file mode 100644 index 0000000..7a3b91a --- /dev/null +++ b/src/main/sdvxhook2-cn/kfca.h @@ -0,0 +1,11 @@ +#ifndef SDVXHOOK_KFCA_H +#define SDVXHOOK_KFCA_H + +#include "acio/acio.h" + +#include "acioemu/emu.h" + +void kfca_init(struct ac_io_emu *emu); +void kfca_dispatch_request(const struct ac_io_message *req); + +#endif diff --git a/src/main/sdvxhook2-cn/sdvxhook2-cn.def b/src/main/sdvxhook2-cn/sdvxhook2-cn.def new file mode 100644 index 0000000..dc4610b --- /dev/null +++ b/src/main/sdvxhook2-cn/sdvxhook2-cn.def @@ -0,0 +1,4 @@ +LIBRARY sdvxhook2-cn + +EXPORTS + DllMain@12 @1 NONAME diff --git a/src/main/sdvxhook2-cn/unis-version.c b/src/main/sdvxhook2-cn/unis-version.c new file mode 100644 index 0000000..57e75c9 --- /dev/null +++ b/src/main/sdvxhook2-cn/unis-version.c @@ -0,0 +1,84 @@ +#define LOG_MODULE "unis-version" + +// clang-format off +// Don't format because the order is important here +#include +#include +// clang-format on + +#include + +#include "hook/com-proxy.h" +#include "hook/table.h" + +#include "util/defs.h" +#include "util/log.h" +#include "util/str.h" +#include "util/time.h" + +LPWSTR *(*real_CommandLineToArgvW)(LPCWSTR lpCmdLine, int *pNumArgs); + +LPWSTR *my_CommandLineToArgvW(LPCWSTR lpCmdLine, int *pNumArgs); + +static const struct hook_symbol unis_shell32_syms[] = { + {.name = "CommandLineToArgvW", + .patch = my_CommandLineToArgvW, + .link = (void **) &real_CommandLineToArgvW}, +}; + +bool (*real_IsInComm)(void); +bool my_IsInComm(void); + +bool (*real_IsConnectServer)(void); +bool my_IsConnectServer(void); + +bool (*real_IsPlayerForbidState)(int pnum); +bool my_IsPlayerForbidState(int pnum); + +static wchar_t unis_cmd_path[256 + 16]; + +static const struct hook_symbol unis_unisintr_syms[] = { + {.name = "IsInComm", + .patch = my_IsInComm, + .link = (void **) &real_IsInComm}, + {.name = "IsConnectServer", + .patch = my_IsConnectServer, + .link = (void **) &real_IsConnectServer}, + {.name = "IsPlayerForbidState", + .patch = my_IsPlayerForbidState, + .link = (void **) &real_IsPlayerForbidState}, +}; + +LPWSTR *my_CommandLineToArgvW(LPCWSTR lpCmdLine, int *pNumArgs) +{ + return real_CommandLineToArgvW(unis_cmd_path, pNumArgs); +} + +bool my_IsInComm(void) +{ + return true; +} + +bool my_IsConnectServer(void) +{ + return true; +} + +bool my_IsPlayerForbidState(int pnum) +{ + return false; +} + +void unis_version_hook_init(const char* unis_path) +{ + hook_table_apply( + NULL, "Shell32.dll", unis_shell32_syms, lengthof(unis_shell32_syms)); + hook_table_apply( + NULL, "unisintr.dll", unis_unisintr_syms, lengthof(unis_unisintr_syms)); + + wcscpy(unis_cmd_path, L"launcher.exe "); + wchar_t *end = wcsrchr(unis_cmd_path, L'\0'); + mbstowcs(end, unis_path, 256); + + log_info("Inserted hooks for unis version detection"); +} \ No newline at end of file diff --git a/src/main/sdvxhook2-cn/unis-version.h b/src/main/sdvxhook2-cn/unis-version.h new file mode 100644 index 0000000..be3cdde --- /dev/null +++ b/src/main/sdvxhook2-cn/unis-version.h @@ -0,0 +1,6 @@ +#ifndef SDVXHOOK2_5_UNIS_VERSION_H +#define SDVXHOOK2_5_UNIS_VERSION_H + +void unis_version_hook_init(const char* unis_path); + +#endif