diff --git a/Module.mk b/Module.mk index dc74549..6237435 100644 --- a/Module.mk +++ b/Module.mk @@ -523,7 +523,7 @@ $(zipdir)/jb-01.zip: \ dist/dwarfstack/32/dwarfstack.dll \ dist/jb/config.bat \ dist/jb/gamestart-01.bat \ - dist/jb/jbhook-01.conf \ + dist/jb/inject-01.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -538,7 +538,7 @@ $(zipdir)/jb-02.zip: \ dist/dwarfstack/32/dwarfstack.dll \ dist/jb/config.bat \ dist/jb/gamestart-02.bat \ - dist/jb/jbhook-02.conf \ + dist/jb/inject-02.xml \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ diff --git a/dist/jb/gamestart-01.bat b/dist/jb/gamestart-01.bat index 60d1ca8..84a1cf9 100644 --- a/dist/jb/gamestart-01.bat +++ b/dist/jb/gamestart-01.bat @@ -1,5 +1,41 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: Game doesn't work properly when not run with administrator privileges +>nul 2>&1 net session + +if %errorlevel% neq 0 ( + echo This script requires administrative privileges. + echo Please run the script as an administrator. + pause + exit 1 +) + +:: Script expects to be located in a subfolder "bemanitools" in the root folder +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 -inject jbhook1.dll jubeat.exe --config jbhook-01.conf %* +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is content dir which contains the exe and the data folder +cd /d %CONTENT_DIR% + +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-01.xml^ + %* \ No newline at end of file diff --git a/dist/jb/gamestart-02.bat b/dist/jb/gamestart-02.bat index 6091450..0cc6f32 100644 --- a/dist/jb/gamestart-02.bat +++ b/dist/jb/gamestart-02.bat @@ -1,7 +1,43 @@ @echo off +:: Keep all vars scoped to this script +setlocal + +:: Game doesn't work properly when not run with administrator privileges +>nul 2>&1 net session + +if %errorlevel% neq 0 ( + echo This script requires administrative privileges. + echo Please run the script as an administrator. + pause + exit 1 +) + +:: Script expects to be located in a subfolder "bemanitools" in the root folder +:: next to the folders data, JAA, JAB, etc. cd /d %~dp0 +set CONTENT_DIR=%CD%\.. +set BEMANITOOLS_DIR=%CONTENT_DIR%\bemanitools + +if not exist "%BEMANITOOLS_DIR%" ( + echo The bemanitools directory "%BEMANITOOLS_DIR%" does not exist. + pause + exit 1 +) + +:: Keep that data vanilla, no need to copy these around anymore +:: Just add them to the env PATH so inject can find the libs and game executable +:: Remark: This also requires admin privileges to propage correctly to inject +set PATH=^ +%BEMANITOOLS_DIR%;^ +%PATH% + +:: Current working dir is content dir which contains the exe and the data folder +cd /d %CONTENT_DIR% + if not exist dev\nvram mkdir dev\nvram -inject jbhook1.dll jubeat.exe --config jbhook-02.conf %* +%BEMANITOOLS_DIR%\inject.exe^ + %BEMANITOOLS_DIR%\inject-02.xml^ + %* \ No newline at end of file diff --git a/dist/jb/inject-01.xml b/dist/jb/inject-01.xml new file mode 100644 index 0000000..84ac546 --- /dev/null +++ b/dist/jb/inject-01.xml @@ -0,0 +1,63 @@ + + + 1 + + + jubeat.exe + + + inject + + + + 1 + jbhook1.dll + + + + + 0 + + 1 + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + GCH44JAB + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/jb/inject-02.xml b/dist/jb/inject-02.xml new file mode 100644 index 0000000..ec7a9dd --- /dev/null +++ b/dist/jb/inject-02.xml @@ -0,0 +1,63 @@ + + + 1 + + + jubeat.exe + + + inject + + + + 1 + jbhook1.dll + + + + + 0 + + 1 + + + + localhost:80 + 0101020304050607086F + 0101020304050607086F + + + GCI44JAA + + + + + + + 1 + misc + 8192 + + + 0 + 64 + discard_new + + + 1 + 1 + + + 1 + inject.log + 0 + 0 + 1 + + + + + 1 + 0 + + \ No newline at end of file diff --git a/dist/jb/jbhook-01.conf b/dist/jb/jbhook-01.conf deleted file mode 100755 index 0070a7a..0000000 --- a/dist/jb/jbhook-01.conf +++ /dev/null @@ -1,18 +0,0 @@ -# Run the game windowed -gfx.windowed=false - -# rotate the normally-horizontal game window to be vertical -gfx.vertical=true - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Mcode of the game to run. -security.mcode=GCH44JAB - diff --git a/dist/jb/jbhook-02.conf b/dist/jb/jbhook-02.conf deleted file mode 100644 index aca6d97..0000000 --- a/dist/jb/jbhook-02.conf +++ /dev/null @@ -1,18 +0,0 @@ -# Run the game windowed -gfx.windowed=false - -# rotate the normally-horizontal game window to be vertical -gfx.vertical=true - -# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. -eamuse.server=localhost:80 - -# PCBID -eamuse.pcbid=0101020304050607086F - -# EAMID -eamuse.eamid=0101020304050607086F - -# Mcode of the game to run. -security.mcode=GCI44JAA - diff --git a/src/main/jbhook1/Module.mk b/src/main/jbhook1/Module.mk index fa21940..7de78b3 100644 --- a/src/main/jbhook1/Module.mk +++ b/src/main/jbhook1/Module.mk @@ -9,11 +9,11 @@ ldflags_jbhook1 := \ -lws2_32 \ -liphlpapi \ -lopengl32 \ + -lshlwapi \ libs_jbhook1 := \ core \ acioemu \ - cconfig \ jbhook-util \ jbhook-util-p3io \ p3ioemu \ @@ -26,6 +26,8 @@ libs_jbhook1 := \ iface-io \ iface-core \ module \ + sdk-hook \ + mxml \ src_jbhook1 := \ avs-boot.c \ @@ -33,4 +35,6 @@ src_jbhook1 := \ config-eamuse.c \ config-security.c \ dllmain.c \ + gfx.c \ + jbhook1.c \ log-gftools.c \ diff --git a/src/main/jbhook1/config-eamuse.c b/src/main/jbhook1/config-eamuse.c index 5257915..d3a570b 100644 --- a/src/main/jbhook1/config-eamuse.c +++ b/src/main/jbhook1/config-eamuse.c @@ -1,145 +1,12 @@ -#include - -#include "cconfig/cconfig-util.h" - -#include "iface-core/log.h" +#include "core/config-ext.h" #include "jbhook1/config-eamuse.h" -#include "util/net.h" - -#define JBHOOK1_CONFIG_EAMUSE_SERVER_KEY "eamuse.server" -#define JBHOOK1_CONFIG_EAMUSE_PCBID_KEY "eamuse.pcbid" -#define JBHOOK1_CONFIG_EAMUSE_EAMID_KEY "eamuse.eamid" - -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE "localhost:80" -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE security_id_default -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN \ - sizeof(security_id_default) -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE security_id_default -#define JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN \ - sizeof(security_id_default) - -const struct net_addr jbhook1_eamuse_default_server = { - .type = NET_ADDR_TYPE_HOSTNAME, - .hostname.host = "localhost", - .hostname.port = 80, -}; - -void jbhook1_config_eamuse_init(struct cconfig *config) -{ - cconfig_util_set_str( - config, - JBHOOK1_CONFIG_EAMUSE_SERVER_KEY, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE, - "URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 " - "(e.g. 127.0.0.1:80) of the target eamuse server. The port is " - "optional " - "but defaults to 80."); - - cconfig_util_set_data( - config, - JBHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - "PCBID"); - - cconfig_util_set_data( - config, - JBHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - "EAMID"); -} - void jbhook1_config_eamuse_get( - struct jbhook1_config_eamuse *config_eamuse, struct cconfig *config) + const bt_core_config_t *config, + jbhook1_config_eamuse_t *config_out) { - char server_url[1024]; - char *tmp; - char *tmp2; - - memset(config_eamuse, 0, sizeof(struct jbhook1_config_eamuse)); - - if (!cconfig_util_get_str( - config, - JBHOOK1_CONFIG_EAMUSE_SERVER_KEY, - server_url, - sizeof(server_url), - JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - JBHOOK1_CONFIG_EAMUSE_SERVER_KEY, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_SERVER_VALUE); - } - - if (!net_str_parse(server_url, &config_eamuse->server)) { - memcpy( - &config_eamuse->server, - &jbhook1_eamuse_default_server, - sizeof(config_eamuse->server)); - tmp = net_addr_to_str(&config_eamuse->server); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!cconfig_util_get_data( - config, - JBHOOK1_CONFIG_EAMUSE_PCBID_KEY, - (uint8_t *) &config_eamuse->pcbid, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE_LEN, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } - - if (!cconfig_util_get_data( - config, - JBHOOK1_CONFIG_EAMUSE_EAMID_KEY, - (uint8_t *) &config_eamuse->eamid, - JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE_LEN, - (uint8_t *) &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default", - tmp); - free(tmp); - } - - if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); - } -} + bt_core_config_ext_net_addr_get(config, "eamuse/server", &config_out->server); + bt_core_config_ext_security_id_get(config, "eamuse/pcbid", &config_out->pcbid); + bt_core_config_ext_security_id_get(config, "eamuse/eamid", &config_out->eamid); +} \ No newline at end of file diff --git a/src/main/jbhook1/config-eamuse.h b/src/main/jbhook1/config-eamuse.h index 63df275..f54c6d8 100644 --- a/src/main/jbhook1/config-eamuse.h +++ b/src/main/jbhook1/config-eamuse.h @@ -1,7 +1,7 @@ #ifndef JBHOOK1_CONFIG_EAMUSE_H #define JBHOOK1_CONFIG_EAMUSE_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/id.h" @@ -10,27 +10,14 @@ /** * Struct holding configuration values for eamuse related items. */ -struct jbhook1_config_eamuse { +typedef struct jbhook1_config_eamuse { struct net_addr server; struct security_id pcbid; struct security_id eamid; -}; +} jbhook1_config_eamuse_t; -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void jbhook1_config_eamuse_init(struct cconfig *config); - -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_eamuse Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void jbhook1_config_eamuse_get( - struct jbhook1_config_eamuse *config_eamuse, struct cconfig *config); + const bt_core_config_t *config, + jbhook1_config_eamuse_t *config_out); #endif \ No newline at end of file diff --git a/src/main/jbhook1/config-gfx.c b/src/main/jbhook1/config-gfx.c index 5108bfa..5d512eb 100644 --- a/src/main/jbhook1/config-gfx.c +++ b/src/main/jbhook1/config-gfx.c @@ -1,54 +1,13 @@ #include -#include "cconfig/cconfig-util.h" - -#include "iface-core/log.h" +#include "core/config-ext.h" #include "jbhook1/config-gfx.h" -#define JBHOOK1_CONFIG_GFX_WINDOWED_KEY "gfx.windowed" -#define JBHOOK1_CONFIG_GFX_VERTICAL_KEY "gfx.vertical" - -#define JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false -#define JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE true - -void jbhook1_config_gfx_init(struct cconfig *config) -{ - cconfig_util_set_bool( - config, - JBHOOK1_CONFIG_GFX_WINDOWED_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE, - "Run the game windowed"); - cconfig_util_set_bool( - config, - JBHOOK1_CONFIG_GFX_VERTICAL_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE, - "Adjust the rotation of the game window so it runs vertically"); -} - void jbhook1_config_gfx_get( - struct jbhook1_config_gfx *config_gfx, struct cconfig *config) + const bt_core_config_t *config, + jbhook1_config_gfx_t *config_out) { - if (!cconfig_util_get_bool( - config, - JBHOOK1_CONFIG_GFX_WINDOWED_KEY, - &config_gfx->windowed, - JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - JBHOOK1_CONFIG_GFX_WINDOWED_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE); - } - if (!cconfig_util_get_bool( - config, - JBHOOK1_CONFIG_GFX_VERTICAL_KEY, - &config_gfx->vertical, - JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%d'", - JBHOOK1_CONFIG_GFX_VERTICAL_KEY, - JBHOOK1_CONFIG_GFX_DEFAULT_VERTICAL_VALUE); - } + bt_core_config_ext_bool_get(config, "gfx/windowed", &config_out->windowed); + bt_core_config_ext_bool_get(config, "gfx/vertical", &config_out->vertical); } diff --git a/src/main/jbhook1/config-gfx.h b/src/main/jbhook1/config-gfx.h index e39aece..cc2c7ce 100644 --- a/src/main/jbhook1/config-gfx.h +++ b/src/main/jbhook1/config-gfx.h @@ -1,31 +1,18 @@ #ifndef JBHOOK1_CONFIG_GFX_H #define JBHOOK1_CONFIG_GFX_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" /** * Struct holding configuration values for GFX related items. */ -struct jbhook1_config_gfx { +typedef struct jbhook1_config_gfx { bool windowed; bool vertical; -}; +} jbhook1_config_gfx_t; -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void jbhook1_config_gfx_init(struct cconfig *config); - -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_gfx Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void jbhook1_config_gfx_get( - struct jbhook1_config_gfx *config_gfx, struct cconfig *config); + const bt_core_config_t *config, + jbhook1_config_gfx_t *config_out); #endif diff --git a/src/main/jbhook1/config-security.c b/src/main/jbhook1/config-security.c index debb5f6..1246b34 100644 --- a/src/main/jbhook1/config-security.c +++ b/src/main/jbhook1/config-security.c @@ -1,75 +1,10 @@ -#include - -#include "cconfig/cconfig-util.h" - -#include "iface-core/log.h" +#include "core/config-ext.h" #include "jbhook1/config-security.h" -#include "security/mcode.h" - -#include "util/net.h" - -#define JBHOOK1_CONFIG_SECURITY_MCODE_KEY "security.mcode" - -static const struct security_mcode security_mcode_h44 = { - .header = SECURITY_MCODE_HEADER, - .unkn = SECURITY_MCODE_UNKN_C, - .game = SECURITY_MCODE_GAME_JB_1, - .region = SECURITY_MCODE_REGION_JAPAN, - .cabinet = SECURITY_MCODE_CABINET_A, - .revision = SECURITY_MCODE_REVISION_B, -}; - -void jbhook1_config_security_init(struct cconfig *config) -{ - char *tmp; - - tmp = security_mcode_to_str(&security_mcode_h44); - - cconfig_util_set_str( - config, - JBHOOK1_CONFIG_SECURITY_MCODE_KEY, - tmp, - "Mcode of the game to run."); - - free(tmp); -} - void jbhook1_config_security_get( - struct jbhook1_config_security *config_security, struct cconfig *config) + const bt_core_config_t *config, + jbhook1_config_security_t *config_out) { - char *tmp_default; - char mcode[9]; - - tmp_default = security_mcode_to_str(&security_mcode_h44); - - if (!cconfig_util_get_str( - config, - JBHOOK1_CONFIG_SECURITY_MCODE_KEY, - mcode, - sizeof(mcode) - 1, - tmp_default)) { - log_warning( - "Invalid value for key '%s' specified, fallback " - "to default '%s'", - JBHOOK1_CONFIG_SECURITY_MCODE_KEY, - tmp_default); - } - - mcode[8] = '\0'; - - if (!security_mcode_parse(mcode, &config_security->mcode)) { - log_warning( - "Invalid mcode '%s' specified, fallback to default '%s'", - mcode, - tmp_default); - - memcpy( - &config_security->mcode, - &security_mcode_h44, - sizeof(struct security_mcode)); - } - - free(tmp_default); -} + bt_core_config_ext_security_mcode_get(config, "security/mcode", &config_out->mcode); +} \ No newline at end of file diff --git a/src/main/jbhook1/config-security.h b/src/main/jbhook1/config-security.h index 37e1b12..615e3bb 100644 --- a/src/main/jbhook1/config-security.h +++ b/src/main/jbhook1/config-security.h @@ -1,34 +1,19 @@ #ifndef JBHOOK1_CONFIG_SECURITY_H #define JBHOOK1_CONFIG_SECURITY_H -#include "cconfig/cconfig.h" +#include "api/core/config.h" #include "security/mcode.h" -#include "util/net.h" - /** * Struct holding configuration values for security related items. */ -struct jbhook1_config_security { +typedef struct jbhook1_config_security { struct security_mcode mcode; -}; +} jbhook1_config_security_t; -/** - * Initialize a cconfig structure with the basic structure and default values - * of this configuration. - */ -void jbhook1_config_security_init(struct cconfig *config); - -/** - * Read the module specific config struct values from the provided cconfig - * struct. - * - * @param config_security Target module specific struct to read configuration - * values to. - * @param config cconfig struct holding the intermediate data to read from. - */ void jbhook1_config_security_get( - struct jbhook1_config_security *config_security, struct cconfig *config); + const bt_core_config_t *config, + jbhook1_config_security_t *config_out); #endif \ No newline at end of file diff --git a/src/main/jbhook1/dllmain.c b/src/main/jbhook1/dllmain.c index 1ffe5e6..245e61b 100644 --- a/src/main/jbhook1/dllmain.c +++ b/src/main/jbhook1/dllmain.c @@ -1,137 +1,31 @@ #include -#include -#include -#include -#include - -#include "cconfig/cconfig-hook.h" - -#include "core/log-bt-ext.h" -#include "core/log-bt.h" -#include "core/log-sink-debug.h" -#include "core/thread-crt.h" - #include "hook/table.h" -#include "hooklib/acp.h" -#include "hooklib/adapter.h" -#include "hooklib/rs232.h" +#include "jbhook1/jbhook1.h" -#include "iface-core/log.h" -#include "iface-core/thread.h" - -#include "iface-io/eam.h" -#include "iface-io/jb.h" - -#include "jbhook1/avs-boot.h" -#include "jbhook1/config-eamuse.h" -#include "jbhook1/config-gfx.h" -#include "jbhook1/config-security.h" -#include "jbhook1/log-gftools.h" - -#include "jbhook-util/acio.h" -#include "jbhook-util/eamuse.h" - -#include "jbhook-util-p3io/gfx.h" -#include "jbhook-util-p3io/mixer.h" -#include "jbhook-util-p3io/p3io.h" - -#include "module/io-ext.h" -#include "module/io.h" - -#include "p3ioemu/devmgr.h" -#include "p3ioemu/emu.h" +#include "main/sdk-hook/dllentry.h" #include "util/defs.h" -#define JBHOOK1_INFO_HEADER \ - "jbhook1 for jubeat" \ - ", build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV) -#define JBHOOK1_CMD_USAGE \ - "Usage: inject.exe jbhook1.dll [options...]" - static HWND CDECL -my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); -static HWND(CDECL *real_mwindow_create)( +_jbhook1_dllmain_my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); +static HWND(CDECL *_jbhook1_dllmain_real_mwindow_create)( HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); -static BOOL STDCALL my_CreateProcessA( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation); -static BOOL(STDCALL *real_CreateProcessA)( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation); - -static const struct hook_symbol init_hook_syms[] = { +static const struct hook_symbol _jbhook1_dllmain_hook_syms[] = { { .name = "mwindow_create", - .patch = my_mwindow_create, - .link = (void **) &real_mwindow_create, + .patch = _jbhook1_dllmain_my_mwindow_create, + .link = (void **) &_jbhook1_dllmain_real_mwindow_create, }, }; -static const struct hook_symbol kernel32_hook_syms[] = { - { - .name = "CreateProcessA", - .patch = my_CreateProcessA, - .link = (void **) &real_CreateProcessA, - }, -}; - -// so our CreateProcessA hook can check -static bool vertical; - -static module_io_t *jbhook_module_io_jb; -static module_io_t *jbhook_module_io_eam; - -static void _jbhook1_log_init() -{ - core_log_bt_ext_init_with_debug(); - // TODO change log level support - core_log_bt_level_set(CORE_LOG_BT_LOG_LEVEL_MISC); -} - -static void _jbhook1_io_jb_init(module_io_t **module) -{ - bt_io_jb_api_t api; - - module_io_ext_load_and_init("jbio.dll", "bt_module_io_jb_api_get", module); - module_io_api_get(*module, &api); - bt_io_jb_api_set(&api); -} - -static void _jbhook1_io_eam_init(module_io_t **module) -{ - bt_io_eam_api_t api; - - module_io_ext_load_and_init( - "eamio.dll", "bt_module_io_eam_api_get", module); - module_io_api_get(*module, &api); - bt_io_eam_api_set(&api); -} - /** * This seems to be a good entry point to intercept before the game calls * anything important (very close to the start of WinMain). */ -static HWND CDECL my_mwindow_create( +static HWND CDECL _jbhook1_dllmain_my_mwindow_create( HINSTANCE hinstance, void *callback, const char *window_title, @@ -139,90 +33,9 @@ static HWND CDECL my_mwindow_create( DWORD window_height, BOOL fullscreen) { - struct cconfig *config; + bt_hook_dllentry_main_init(); - struct jbhook1_config_gfx config_gfx; - struct jbhook1_config_eamuse config_eamuse; - struct jbhook1_config_security config_security; - - log_info("-------------------------------------------------------------"); - log_info("---------------- Begin jbhook mwindow_create ----------------"); - log_info("-------------------------------------------------------------"); - - jbhook_util_mixer_hook_init(); - - config = cconfig_init(); - - jbhook1_config_gfx_init(config); - jbhook1_config_eamuse_init(config); - jbhook1_config_security_init(config); - - if (!cconfig_hook_config_init( - config, - JBHOOK1_INFO_HEADER "\n" JBHOOK1_CMD_USAGE, - CCONFIG_CMD_USAGE_OUT_DBG)) { - cconfig_finit(config); - exit(EXIT_FAILURE); - } - - jbhook1_config_gfx_get(&config_gfx, config); - jbhook1_config_eamuse_get(&config_eamuse, config); - jbhook1_config_security_get(&config_security, config); - - cconfig_finit(config); - - log_info(JBHOOK1_INFO_HEADER); - log_info("Initializing jbhook..."); - - jbhook1_avs_boot_init(); - jbhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); - jbhook1_log_gftools_init(); - - fullscreen = !config_gfx.windowed; - vertical = config_gfx.vertical; - - if (config_gfx.vertical) { - DWORD tmp = window_width; - window_width = window_height; - window_height = tmp; - - jbhook_util_gfx_install_vertical_hooks(); - } - - log_info("Starting up jubeat IO backend"); - - _jbhook1_io_jb_init(&jbhook_module_io_jb); - - if (!bt_io_jb_init()) { - log_fatal("Initializing jb IO backend failed"); - } - - log_info("Starting up card reader backend"); - - _jbhook1_io_eam_init(&jbhook_module_io_eam); - - if (!bt_io_eam_init()) { - log_fatal("Initializing card reader backend failed"); - } - - jbhook_util_eamuse_hook_init(); - - iohook_push_handler(p3io_emu_dispatch_irp); - iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp); - - rs232_hook_init(); - jbhook_util_ac_io_port_init(L"COM1"); - jbhook_util_ac_io_set_iccb(); - - p3io_setupapi_insert_hooks(NULL); - jbhook_util_p3io_init( - &config_security.mcode, &config_eamuse.pcbid, &config_eamuse.eamid); - - log_info("-------------------------------------------------------------"); - log_info("----------------- End jbhook mwindow_create -----------------"); - log_info("-------------------------------------------------------------"); - - return real_mwindow_create( + return _jbhook1_dllmain_real_mwindow_create( hinstance, callback, window_title, @@ -231,74 +44,34 @@ static HWND CDECL my_mwindow_create( fullscreen); } -/** - * Hook library for jubeat (1) - */ +// TODO find another call right before main exits to hook cleanup and stuff with +// bt_hook_dllentry_main_fini() + BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) { if (reason == DLL_PROCESS_ATTACH) { - // TODO why not use AVS threads? - core_thread_crt_core_api_set(); - - // TODO init debug logging but with avs available? why not use avs - // logging? - core_log_bt_core_api_set(); - _jbhook1_log_init(); - - /* Bootstrap hook for further init tasks (see above) */ + bt_hook_dllentry_init( + mod, + "jbhook1", + bt_module_core_config_api_set, + bt_module_core_log_api_set, + bt_module_core_thread_api_set, + bt_module_hook_api_get); hook_table_apply( - NULL, "mwindow.dll", init_hook_syms, lengthof(init_hook_syms)); + NULL, "mwindow.dll", _jbhook1_dllmain_hook_syms, lengthof(_jbhook1_dllmain_hook_syms)); - /* Actual hooks for game specific stuff */ + } else if (reason == DLL_PROCESS_DETACH) { + // https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain#remarks + if (ctx == NULL) { + hook_table_revert(NULL, "mwindow.dll", _jbhook1_dllmain_hook_syms, lengthof(_jbhook1_dllmain_hook_syms)); - hook_table_apply( - NULL, - "kernel32.dll", - kernel32_hook_syms, - lengthof(kernel32_hook_syms)); + // Hacky to have this here, should be close/right after application main exits, see TODO above + bt_hook_dllentry_main_fini(); - acp_hook_init(); - adapter_hook_init(); - } - - return TRUE; -} - -static BOOL STDCALL my_CreateProcessA( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation) -{ - LPSTR rot_arg; - - // de-rotate the error window if needed. In theory this should parse the - // commandline properly, in practice this works on all the .exe jubeats. - if (vertical && lpCommandLine) { - if ((rot_arg = strstr(lpCommandLine, " -R90 "))) { // jubeat 01 - memcpy(rot_arg, " -R0 ", strlen(" -R0 ")); - } else if ((rot_arg = - strstr(lpCommandLine, " -rot:90 "))) { // jubeat 02 - memcpy(rot_arg, " -rot:0 ", strlen(" -rot:0 ")); + bt_hook_dllentry_fini(); } } - return real_CreateProcessA( - lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation); -} + return TRUE; +} \ No newline at end of file diff --git a/src/main/jbhook1/gfx.c b/src/main/jbhook1/gfx.c new file mode 100644 index 0000000..74ab4cf --- /dev/null +++ b/src/main/jbhook1/gfx.c @@ -0,0 +1,158 @@ +#define LOG_MODULE "jbhook1-gfx" + +#include + +#include + +#include "hook/table.h" + +#include "iface-core/log.h" + +#include "jbhook1/config-gfx.h" + +#include "jbhook-util-p3io/gfx.h" + +#include "util/defs.h" + +static jbhook1_config_gfx_t _jbhook1_gfx_config; + +static HWND CDECL +my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); +static HWND(CDECL *real_mwindow_create)( + HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); + +static BOOL STDCALL my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); +static BOOL(STDCALL *real_CreateProcessA)( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); + +static const struct hook_symbol mwindow_hook_syms[] = { + { + .name = "mwindow_create", + .patch = my_mwindow_create, + .link = (void **) &real_mwindow_create, + }, +}; + +static const struct hook_symbol kernel32_hook_syms[] = { + { + .name = "CreateProcessA", + .patch = my_CreateProcessA, + .link = (void **) &real_CreateProcessA, + }, +}; + +static HWND CDECL my_mwindow_create( + HINSTANCE hinstance, + void *callback, + const char *window_title, + DWORD window_width, + DWORD window_height, + BOOL fullscreen) +{ + DWORD tmp; + + fullscreen = !_jbhook1_gfx_config.windowed; + + if (_jbhook1_gfx_config.vertical) { + tmp = window_width; + window_width = window_height; + window_height = tmp; + } + + return real_mwindow_create( + hinstance, + callback, + window_title, + window_width, + window_height, + fullscreen); +} + +static BOOL STDCALL my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +{ + LPSTR rot_arg; + + // de-rotate the error window if needed. In theory this should parse the + // commandline properly, in practice this works on all the .exe jubeats. + if (_jbhook1_gfx_config.vertical && lpCommandLine) { + if ((rot_arg = strstr(lpCommandLine, " -R90 "))) { // jubeat 01 + memcpy(rot_arg, " -R0 ", strlen(" -R0 ")); + } else if ((rot_arg = + strstr(lpCommandLine, " -rot:90 "))) { // jubeat 02 + memcpy(rot_arg, " -rot:0 ", strlen(" -rot:0 ")); + } + } + + return real_CreateProcessA( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation); +} + +void jbhook1_gfx_init(const jbhook1_config_gfx_t *config) +{ + memcpy(&_jbhook1_gfx_config, config, sizeof(_jbhook1_gfx_config)); + + hook_table_apply( + NULL, "mwindow.dll", mwindow_hook_syms, lengthof(mwindow_hook_syms)); + hook_table_apply( + NULL, + "kernel32.dll", + kernel32_hook_syms, + lengthof(kernel32_hook_syms)); + + log_info("Inserted gfx hooks"); + + if (_jbhook1_gfx_config.vertical) { + jbhook_util_gfx_install_vertical_hooks(); + } +} + +void jbhook1_gfx_fini() +{ + hook_table_revert( + NULL, "mwindow.dll", mwindow_hook_syms, lengthof(mwindow_hook_syms)); + hook_table_revert( + NULL, + "kernel32.dll", + kernel32_hook_syms, + lengthof(kernel32_hook_syms)); + + log_info("Removed gfx hooks"); +} \ No newline at end of file diff --git a/src/main/jbhook1/gfx.h b/src/main/jbhook1/gfx.h new file mode 100644 index 0000000..5768f8b --- /dev/null +++ b/src/main/jbhook1/gfx.h @@ -0,0 +1,10 @@ +#ifndef JBHOOK1_GFX_H +#define JBHOOK1_GFX_H + +#include "jbhook1/config-gfx.h" + +void jbhook1_gfx_init(const jbhook1_config_gfx_t *config); + +void jbhook1_gfx_fini(); + +#endif \ No newline at end of file diff --git a/src/main/jbhook1/jbhook1.c b/src/main/jbhook1/jbhook1.c new file mode 100644 index 0000000..738de2b --- /dev/null +++ b/src/main/jbhook1/jbhook1.c @@ -0,0 +1,153 @@ +#include + +#include +#include +#include +#include + +#include "hooklib/acp.h" +#include "hooklib/adapter.h" +#include "hooklib/rs232.h" + +#include "iface-core/config.h" +#include "iface-core/log.h" +#include "iface-core/thread.h" + +#include "iface-io/eam.h" +#include "iface-io/jb.h" + +#include "jbhook1/avs-boot.h" +#include "jbhook1/config-eamuse.h" +#include "jbhook1/config-gfx.h" +#include "jbhook1/config-security.h" +#include "jbhook1/gfx.h" +#include "jbhook1/log-gftools.h" + +#include "jbhook-util/acio.h" +#include "jbhook-util/eamuse.h" + +#include "jbhook-util-p3io/mixer.h" +#include "jbhook-util-p3io/p3io.h" + +#include "module/io-ext.h" +#include "module/io.h" + +#include "p3ioemu/devmgr.h" +#include "p3ioemu/emu.h" + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +static module_io_t *jbhook_module_io_jb; +static module_io_t *jbhook_module_io_eam; + +static void _jbhook1_io_jb_init(module_io_t **module) +{ + bt_io_jb_api_t api; + + module_io_ext_load_and_init("jbio.dll", "bt_module_io_jb_api_get", module); + module_io_api_get(*module, &api); + bt_io_jb_api_set(&api); +} + +static void _jbhook1_io_eam_init(module_io_t **module) +{ + bt_io_eam_api_t api; + + module_io_ext_load_and_init( + "eamio.dll", "bt_module_io_eam_api_get", module); + module_io_api_get(*module, &api); + bt_io_eam_api_set(&api); +} + +static bool +_jbhook1_main_init(HMODULE game_module, const bt_core_config_t *config) +{ + jbhook1_config_gfx_t config_gfx; + jbhook1_config_eamuse_t config_eamuse; + jbhook1_config_security_t config_security; + + log_info("jbhook for jubeat and jubeat ripples"); + log_info("build " __DATE__ " " __TIME__ ", gitrev " STRINGIFY(GITREV)); + + jbhook1_config_gfx_get(config, &config_gfx); + jbhook1_config_eamuse_get(config, &config_eamuse); + jbhook1_config_security_get(config, &config_security); + + acp_hook_init(); + adapter_hook_init(); + + // TODO this won't work because it modifies the parameters of the mwindow_create + // call which is also used for bootstrapping this function (_jbhook1_main_init) + // Introducing the additional abstraction and glue code to further separate + // concerns, a different function before mwindow_create must be used in + // dllmain to bootstrap the main hooking code here, so the mwindow_create + // hook can be set up in advance and then be invoked by the game + jbhook1_gfx_init(&config_gfx); + + jbhook1_avs_boot_init(); + jbhook1_avs_boot_set_eamuse_addr(&config_eamuse.server); + jbhook1_log_gftools_init(); + jbhook_util_mixer_hook_init(); + + log_info("Starting up jubeat IO backend"); + + _jbhook1_io_jb_init(&jbhook_module_io_jb); + + if (!bt_io_jb_init()) { + log_fatal("Initializing jb IO backend failed"); + } + + log_info("Starting up card reader backend"); + + _jbhook1_io_eam_init(&jbhook_module_io_eam); + + if (!bt_io_eam_init()) { + log_fatal("Initializing card reader backend failed"); + } + + jbhook_util_eamuse_hook_init(); + + iohook_push_handler(p3io_emu_dispatch_irp); + iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp); + + rs232_hook_init(); + jbhook_util_ac_io_port_init(L"COM1"); + jbhook_util_ac_io_set_iccb(); + + p3io_setupapi_insert_hooks(NULL); + jbhook_util_p3io_init( + &config_security.mcode, &config_eamuse.pcbid, &config_eamuse.eamid); + + return true; +} + +static void _jbhook1_main_fini() +{ + // TODO cleanup +} + +void bt_module_core_config_api_set(const bt_core_config_api_t *api) +{ + bt_core_config_api_set(api); +} + +void bt_module_core_log_api_set(const bt_core_log_api_t *api) +{ + bt_core_log_api_set(api); +} + +void bt_module_core_thread_api_set(const bt_core_thread_api_t *api) +{ + bt_core_thread_api_set(api); +} + +void bt_module_hook_api_get(bt_hook_api_t *api) +{ + api->version = 1; + + api->v1.main_init = _jbhook1_main_init; + api->v1.main_fini = _jbhook1_main_fini; +} \ No newline at end of file diff --git a/src/main/jbhook1/jbhook1.def b/src/main/jbhook1/jbhook1.def index 3f6d499..6d5812c 100644 --- a/src/main/jbhook1/jbhook1.def +++ b/src/main/jbhook1/jbhook1.def @@ -2,3 +2,9 @@ LIBRARY jbhook1 EXPORTS DllMain@12 @1 NONAME + + ; Bemanitools 6 API + bt_module_core_config_api_set + bt_module_core_log_api_set + bt_module_core_thread_api_set + bt_module_hook_api_get \ No newline at end of file diff --git a/src/main/jbhook1/jbhook1.h b/src/main/jbhook1/jbhook1.h new file mode 100644 index 0000000..3f747b1 --- /dev/null +++ b/src/main/jbhook1/jbhook1.h @@ -0,0 +1,9 @@ +#ifndef JBHOOK1_H +#define JBHOOK1_H + +#include "sdk/module/core/config.h" +#include "sdk/module/core/log.h" +#include "sdk/module/core/thread.h" +#include "sdk/module/hook.h" + +#endif \ No newline at end of file