From aa147022c6b2875033c47cae06a91cdb0433f57b Mon Sep 17 00:00:00 2001 From: 2d9f8a0741a7573b189035dcb819847ecb5d981d <2d9f8a0741a7573b189035dcb819847ecb5d981d@redacted> Date: Fri, 10 Jun 2022 22:54:13 +0000 Subject: [PATCH] Add iidxhook5-cn, support IIDX tricoro CN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alternative name: (狂热节拍 IIDX 2) --- Module.mk | 18 ++ dist/iidx/gamestart-20-cn.bat | 14 ++ dist/iidx/iidxhook-20-cn.conf | 44 +++++ src/imports/import_32_1304_avs.def | 1 + src/main/iidxhook5-cn/Module.mk | 28 ++++ src/main/iidxhook5-cn/avs-boot.c | 103 ++++++++++++ src/main/iidxhook5-cn/avs-boot.h | 10 ++ src/main/iidxhook5-cn/dllmain.c | 222 +++++++++++++++++++++++++ src/main/iidxhook5-cn/iidxhook5-cn.def | 4 + src/main/iidxhook5-cn/path.c | 104 ++++++++++++ src/main/iidxhook5-cn/path.h | 6 + 11 files changed, 554 insertions(+) create mode 100644 dist/iidx/gamestart-20-cn.bat create mode 100644 dist/iidx/iidxhook-20-cn.conf create mode 100644 src/main/iidxhook5-cn/Module.mk create mode 100644 src/main/iidxhook5-cn/avs-boot.c create mode 100644 src/main/iidxhook5-cn/avs-boot.h create mode 100644 src/main/iidxhook5-cn/dllmain.c create mode 100644 src/main/iidxhook5-cn/iidxhook5-cn.def create mode 100644 src/main/iidxhook5-cn/path.c create mode 100644 src/main/iidxhook5-cn/path.h diff --git a/Module.mk b/Module.mk index 78ae864..5a7f777 100644 --- a/Module.mk +++ b/Module.mk @@ -137,6 +137,7 @@ include src/main/iidxhook2/Module.mk include src/main/iidxhook3/Module.mk include src/main/iidxhook4/Module.mk include src/main/iidxhook5/Module.mk +include src/main/iidxhook5-cn/Module.mk include src/main/iidxhook6/Module.mk include src/main/iidxhook7/Module.mk include src/main/iidxhook8/Module.mk @@ -343,6 +344,22 @@ $(zipdir)/iidx-20.zip: \ $(V)echo ... $@ $(V)zip -j $@ $^ +$(zipdir)/iidx-20-cn.zip: \ + build/bin/avs2_1304-32/iidxhook5-cn.dll \ + build/bin/indep-32/config.exe \ + build/bin/indep-32/eamio.dll \ + build/bin/indep-32/geninput.dll \ + build/bin/indep-32/iidxio.dll \ + build/bin/indep-32/vefxio.dll \ + build/bin/indep-32/inject.exe \ + dist/iidx/config.bat \ + dist/iidx/gamestart-20-cn.bat \ + dist/iidx/iidxhook-20-cn.conf \ + dist/iidx/vefx.txt \ + | $(zipdir)/ + $(V)echo ... $@ + $(V)zip -j $@ $^ + $(zipdir)/iidx-21-to-24.zip: \ build/bin/avs2_1601-32/iidxhook7.dll \ build/bin/avs2_1601-32/launcher.exe \ @@ -764,6 +781,7 @@ $(BUILDDIR)/bemanitools.zip: \ $(zipdir)/iidx-18.zip \ $(zipdir)/iidx-19.zip \ $(zipdir)/iidx-20.zip \ + $(zipdir)/iidx-20-cn.zip \ $(zipdir)/iidx-21-to-24.zip \ $(zipdir)/iidx-25-to-26.zip \ $(zipdir)/iidx-27-to-28.zip \ diff --git a/dist/iidx/gamestart-20-cn.bat b/dist/iidx/gamestart-20-cn.bat new file mode 100644 index 0000000..eb46b1e --- /dev/null +++ b/dist/iidx/gamestart-20-cn.bat @@ -0,0 +1,14 @@ +@echo off + +cd /d %~dp0 + +if not exist d mkdir d +if not exist e mkdir e +if not exist f mkdir f + +if not exist e\avs_conf mkdir e\avs_conf +if not exist e\avs_conf\CONF mkdir e\avs_conf\CONF +if not exist e\avs_conf\CONF\NVRAM mkdir e\avs_conf\CONF\NVRAM +if not exist e\avs_conf\CONF\RAW mkdir e\avs_conf\CONF\RAW + +inject iidxhook5-cn.dll bm2dx.exe -D --config iidxhook-20-cn.conf %* diff --git a/dist/iidx/iidxhook-20-cn.conf b/dist/iidx/iidxhook-20-cn.conf new file mode 100644 index 0000000..b66e7b9 --- /dev/null +++ b/dist/iidx/iidxhook-20-cn.conf @@ -0,0 +1,44 @@ +# PCBID +eamuse.pcbid=0101020304050607086F + +# Fix stretched BG videos on newer GPUs. Might appear on Red and newer +gfx.bgvideo_uv_fix=false + +# Run the game in a framed window (requires windowed option) +gfx.framed=false + +# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit) +gfx.frame_rate_limit=0.0 + +# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450) +gfx.pci_id=1002:7146 + +# Run the game windowed +gfx.windowed=false + +# Windowed width, 0 for default size +gfx.window_width=0 + +# Windowed height, 0 for default size +gfx.window_height=0 + +# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter. +gfx.scale_back_buffer_width=0 + +# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter. +gfx.scale_back_buffer_height=0 + +# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation). +gfx.scale_back_buffer_filter=none + +# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors) +gfx.forced_refresh_rate=-1 + +# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter +gfx.device_adapter=-1 + +# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware +io.disable_io_emu=false + +# Security black plug mcode id string (e.g. GQC02JAA). +sec.black_plug_mcode=GKJDZCAA diff --git a/src/imports/import_32_1304_avs.def b/src/imports/import_32_1304_avs.def index 5a98e5a..2dea570 100644 --- a/src/imports/import_32_1304_avs.def +++ b/src/imports/import_32_1304_avs.def @@ -17,6 +17,7 @@ EXPORTS property_destroy @264 NONAME property_insert_read @23 NONAME property_node_create @316 NONAME + property_node_datasize @249 NONAME property_node_refer @268 NONAME property_node_remove @129 NONAME property_psmap_import @102 NONAME diff --git a/src/main/iidxhook5-cn/Module.mk b/src/main/iidxhook5-cn/Module.mk new file mode 100644 index 0000000..9d09b7f --- /dev/null +++ b/src/main/iidxhook5-cn/Module.mk @@ -0,0 +1,28 @@ +avsdlls += iidxhook5-cn + +ldflags_iidxhook5-cn := \ + -liphlpapi \ + +deplibs_iidxhook5-cn := \ + avs \ + +libs_iidxhook5-cn := \ + iidxhook-util \ + ezusb-emu \ + ezusb2-emu \ + ezusb2-iidx-emu \ + ezusb-iidx-emu \ + security \ + eamio \ + acioemu \ + hook \ + hooklib \ + iidxio \ + cconfig \ + util \ + ezusb \ + +src_iidxhook5-cn := \ + avs-boot.c \ + path.c \ + dllmain.c \ diff --git a/src/main/iidxhook5-cn/avs-boot.c b/src/main/iidxhook5-cn/avs-boot.c new file mode 100644 index 0000000..772832a --- /dev/null +++ b/src/main/iidxhook5-cn/avs-boot.c @@ -0,0 +1,103 @@ +#define LOG_MODULE "avs-boot" + +#include +#include + +#include "hook/table.h" + +#include "imports/avs.h" + +#include "iidxhook5-cn/avs-boot.h" + +#include "util/log.h" + +static void (*real_avs_boot)( + struct property_node *config, + void *std_heap, + size_t sz_std_heap, + void *avs_heap, + size_t sz_avs_heap, + avs_log_writer_t log_writer, + void *log_context); + +static void my_avs_boot( + struct property_node *config, + void *std_heap, + size_t sz_std_heap, + void *avs_heap, + size_t sz_avs_heap, + avs_log_writer_t log_writer, + void *log_context); + +static const struct hook_symbol iidxhook5_cn_log_hook_syms[] = { + {.name = "XC058ba50000f4", + .patch = my_avs_boot, + .link = (void **) &real_avs_boot}, +}; + +static void avs_boot_replace_property_uint32( + struct property_node *node, const char *name, uint32_t val) +{ + struct property_node *tmp; + + tmp = property_search(NULL, node, name); + + if (tmp) { + property_node_remove(tmp); + } + + property_node_create(NULL, node, PSMAP_TYPE_U32, name, val); +} + +static void avs_boot_replace_property_str( + struct property_node *node, const char *name, const char *val) +{ + struct property_node *tmp; + + tmp = property_search(NULL, node, name); + + if (tmp) { + property_node_remove(tmp); + } + + tmp = property_node_create(NULL, node, PROPERTY_TYPE_STR, name, val); + + if (tmp) { + property_node_datasize(tmp); + } +} + +static void my_avs_boot( + struct property_node *config, + void *std_heap, + size_t sz_std_heap, + void *avs_heap, + size_t sz_avs_heap, + avs_log_writer_t log_writer, + void *log_context) +{ + log_info("Called my_avs_boot"); + + avs_boot_replace_property_uint32(config, "log/level", 4); + avs_boot_replace_property_str(config, "fs/root/device", "."); + + real_avs_boot( + config, + std_heap, + sz_std_heap, + avs_heap, + sz_avs_heap, + log_writer_debug, + NULL); +} + +void iidxhook5_cn_avs_boot_init() +{ + hook_table_apply( + NULL, + "libavs-win32.dll", + iidxhook5_cn_log_hook_syms, + lengthof(iidxhook5_cn_log_hook_syms)); + + log_info("Inserted avs log hooks"); +} diff --git a/src/main/iidxhook5-cn/avs-boot.h b/src/main/iidxhook5-cn/avs-boot.h new file mode 100644 index 0000000..d1ce135 --- /dev/null +++ b/src/main/iidxhook5-cn/avs-boot.h @@ -0,0 +1,10 @@ +#ifndef IIDXHOOK5_CN_AVS_BOOT_H +#define IIDXHOOK5_CN_AVS_BOOT_H + +/** + * Initialize hooking of avs_boot. This re-enables avs logging + * and injects a few important settings. + */ +void iidxhook5_cn_avs_boot_init(); + +#endif diff --git a/src/main/iidxhook5-cn/dllmain.c b/src/main/iidxhook5-cn/dllmain.c new file mode 100644 index 0000000..fb0599f --- /dev/null +++ b/src/main/iidxhook5-cn/dllmain.c @@ -0,0 +1,222 @@ +#include + +#include +#include +#include +#include + +#include "bemanitools/eamio.h" +#include "bemanitools/iidxio.h" + +#include "cconfig/cconfig-hook.h" + +#include "ezusb-iidx-emu/node-security-plug.h" + +#include "ezusb2-emu/desc.h" +#include "ezusb2-emu/device.h" + +#include "ezusb2-iidx-emu/msg.h" + +#include "hook/d3d9.h" +#include "hook/table.h" + +#include "hooklib/acp.h" +#include "hooklib/setupapi.h" + +#include "iidxhook5-cn/avs-boot.h" +#include "iidxhook5-cn/path.h" + +#include "iidxhook-util/acio.h" +#include "iidxhook-util/config-eamuse.h" +#include "iidxhook-util/config-gfx.h" +#include "iidxhook-util/config-io.h" +#include "iidxhook-util/config-sec.h" +#include "iidxhook-util/d3d9.h" +#include "iidxhook-util/settings.h" + +#include "security/rp-sign-key.h" + +#include "imports/avs.h" + +#include "util/log.h" + +#define IIDXHOOK5_CN_INFO_HEADER \ + "iidxhook for tricoro CN" \ + ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) +#define IIDXHOOK5_CN_CMD_USAGE \ + "Usage: inject.exe iidxhook5-cn.dll [options...]" + +static ATOM WINAPI my_RegisterClassA(const WNDCLASSA *lpWndClass); +static ATOM(WINAPI *real_RegisterClassA)(const WNDCLASSA *lpWndClass); +static bool iidxhook_init_check; + +static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = { + iidxhook_util_d3d9_irp_handler, +}; + +static const struct hook_symbol init_hook_user32_syms[] = { + {.name = "RegisterClassA", + .patch = my_RegisterClassA, + .link = (void **) &real_RegisterClassA}, +}; + +static struct iidxhook_config_io config_io; + +static void +iidxhook5_cn_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx) +{ + struct iidxhook_util_d3d9_config d3d9_config; + + iidxhook_util_d3d9_init_config(&d3d9_config); + + d3d9_config.windowed = config_gfx->windowed; + d3d9_config.framed = config_gfx->framed; + d3d9_config.override_window_width = config_gfx->window_width; + d3d9_config.override_window_height = config_gfx->window_height; + d3d9_config.framerate_limit = config_gfx->frame_rate_limit; + d3d9_config.pci_vid = config_gfx->pci_id_vid; + d3d9_config.pci_pid = config_gfx->pci_id_pid; + d3d9_config.scale_back_buffer_width = config_gfx->scale_back_buffer_width; + d3d9_config.scale_back_buffer_height = config_gfx->scale_back_buffer_height; + d3d9_config.scale_back_buffer_filter = config_gfx->scale_back_buffer_filter; + d3d9_config.forced_refresh_rate = config_gfx->forced_refresh_rate; + d3d9_config.device_adapter = config_gfx->device_adapter; + + iidxhook_util_d3d9_configure(&d3d9_config); + + hook_d3d9_init(iidxhook_d3d9_handlers, lengthof(iidxhook_d3d9_handlers)); +} + +/** + * OpenProcess is basically used for hooks in exe games, + * but since it does not exist in this game, RegisterClassA is used instead. + */ +static ATOM WINAPI my_RegisterClassA(const WNDCLASSA *lpWndClass) +{ + struct cconfig *config; + + struct iidxhook_util_config_eamuse config_eamuse; + struct iidxhook_config_gfx config_gfx; + struct iidxhook_config_sec config_sec; + + if (iidxhook_init_check) { + return real_RegisterClassA(lpWndClass); + } + + iidxhook_init_check = true; + + log_info("-------------------------------------------------------------"); + log_info("--------------- Begin iidxhook RegisterClassA ---------------"); + log_info("-------------------------------------------------------------"); + + config = cconfig_init(); + + iidxhook_util_config_eamuse_init(config); + iidxhook_config_gfx_init(config); + iidxhook_config_io_init(config); + iidxhook_config_sec_init(config); + + if (!cconfig_hook_config_init( + config, + IIDXHOOK5_CN_INFO_HEADER "\n" IIDXHOOK5_CN_CMD_USAGE, + CCONFIG_CMD_USAGE_OUT_DBG)) { + cconfig_finit(config); + exit(EXIT_FAILURE); + } + + iidxhook_util_config_eamuse_get(&config_eamuse, config); + iidxhook_config_gfx_get(&config_gfx, config); + iidxhook_config_io_get(&config_io, config); + iidxhook_config_sec_get(&config_sec, config); + + cconfig_finit(config); + + log_info(IIDXHOOK5_CN_INFO_HEADER); + log_info("Initializing iidxhook..."); + + /** + * This game is using a black round plug for game license management instead of a black usb dongle. + * No white dongle hooks applies since the game does not have network functionality. + * Also, card readers are not used/checked; no card reader hooks required. + */ + ezusb_iidx_emu_node_security_plug_set_boot_version( + &config_sec.boot_version); + ezusb_iidx_emu_node_security_plug_set_boot_seeds(config_sec.boot_seeds); + ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key( + &security_rp_sign_key_black_iidx); + ezusb_iidx_emu_node_security_plug_set_plug_black_mcode( + &config_sec.black_plug_mcode); + ezusb_iidx_emu_node_security_plug_set_pcbid(&config_eamuse.pcbid); + + iidxhook5_cn_setup_d3d9_hooks(&config_gfx); + + if (!config_io.disable_io_emu) { + log_info("Starting IIDX IO backend"); + + iidx_io_set_loggers( + log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + + if (!iidx_io_init( + avs_thread_create, avs_thread_join, avs_thread_destroy)) { + log_fatal("Initializing IIDX IO backend failed"); + } + } else { + log_info("IIDX IO emulation backend disabled"); + } + + if (!config_io.disable_card_reader_emu) { + log_misc("Initializing card reader backend"); + + eam_io_set_loggers( + log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); + + if (!eam_io_init( + avs_thread_create, avs_thread_join, avs_thread_destroy)) { + log_fatal("Initializing card reader backend failed"); + } + } else { + log_info("Card reader emulation backend disabled"); + } + + /* Set up IO emulation hooks _after_ IO API setup to allow + API implementations with real IO devices */ + iohook_push_handler(ezusb2_emu_device_dispatch_irp); + iohook_push_handler(iidxhook_util_acio_dispatch_irp); + iohook_push_handler(settings_hook_dispatch_irp); + + if (!config_io.disable_io_emu) { + hook_setupapi_init(&ezusb2_emu_desc_device.setupapi); + ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init()); + } + + log_info("-------------------------------------------------------------"); + log_info("---------------- End iidxhook RegisterClassA ----------------"); + log_info("-------------------------------------------------------------"); + + return real_RegisterClassA(lpWndClass); +} + +/** + * Hook library for tricoro CN + */ +BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) +{ + if (reason != DLL_PROCESS_ATTACH) { + return TRUE; + } + + log_to_writer(log_writer_debug, NULL); + + hook_table_apply( + NULL, + "user32.dll", + init_hook_user32_syms, + lengthof(init_hook_user32_syms)); + + iidxhook5_cn_path_init(); + iidxhook5_cn_avs_boot_init(); + acp_hook_init(); + settings_hook_init(); + + return TRUE; +} diff --git a/src/main/iidxhook5-cn/iidxhook5-cn.def b/src/main/iidxhook5-cn/iidxhook5-cn.def new file mode 100644 index 0000000..3ef0454 --- /dev/null +++ b/src/main/iidxhook5-cn/iidxhook5-cn.def @@ -0,0 +1,4 @@ +LIBRARY iidxhook5-cn + +EXPORTS + DllMain@12 @1 NONAME diff --git a/src/main/iidxhook5-cn/path.c b/src/main/iidxhook5-cn/path.c new file mode 100644 index 0000000..13be1d9 --- /dev/null +++ b/src/main/iidxhook5-cn/path.c @@ -0,0 +1,104 @@ +#define LOG_MODULE "path" + +#include +#include +#include + +#include "hook/table.h" + +#include "iidxhook5-cn/path.h" + +#include "util/log.h" +#include "util/str.h" + +#define PATH_A "D:/JDZ-001/contents/" +#define PATH_W L"D:/JDZ-001/contents/" + +static HANDLE WINAPI my_CreateFileW( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile); +static HANDLE(WINAPI *real_CreateFileW)( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile); + +static HANDLE WINAPI my_FindFirstFileA( + LPCSTR lpFileName, + LPWIN32_FIND_DATAA lpFindFileData); +static HANDLE(WINAPI *real_FindFirstFileA)( + LPCSTR lpFileName, + LPWIN32_FIND_DATAA lpFindFileData); + +static const struct hook_symbol iidxhook5_cn_path_hook_syms[] = { + {.name = "CreateFileW", + .patch = my_CreateFileW, + .link = (void **) &real_CreateFileW}, + {.name = "FindFirstFileA", + .patch = my_FindFirstFileA, + .link = (void **) &real_FindFirstFileA}, +}; + +static HANDLE WINAPI my_CreateFileW( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + if (lpFileName != NULL && wcsstr(lpFileName, PATH_W) == lpFileName) { + wchar_t relative[MAX_PATH] = L"."; + wstr_cat(relative, MAX_PATH, lpFileName + wcslen(PATH_W) - 1); + return real_CreateFileW( + relative, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + } + + return real_CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); +} + +static HANDLE WINAPI my_FindFirstFileA( + LPCSTR lpFileName, + LPWIN32_FIND_DATAA lpFindFileData) +{ + if (lpFileName != NULL && strstr(lpFileName, PATH_A) == lpFileName) { + char relative[MAX_PATH] = "."; + str_cat(relative, MAX_PATH, lpFileName + strlen(PATH_A) - 1); + return real_FindFirstFileA(relative, lpFindFileData); + } + + return real_FindFirstFileA(lpFileName, lpFindFileData); +} + +void iidxhook5_cn_path_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + iidxhook5_cn_path_hook_syms, + lengthof(iidxhook5_cn_path_hook_syms)); + + log_info("Inserted path hooks"); +} diff --git a/src/main/iidxhook5-cn/path.h b/src/main/iidxhook5-cn/path.h new file mode 100644 index 0000000..a992bba --- /dev/null +++ b/src/main/iidxhook5-cn/path.h @@ -0,0 +1,6 @@ +#ifndef IIDXHOOK5_CN_PATH_H +#define IIDXHOOK5_CN_PATH_H + +void iidxhook5_cn_path_init(); + +#endif