feat(jbhook1): Use sdk-hook and new config api

Summary:

Test Plan:
This commit is contained in:
icex2 2024-08-17 12:51:00 +02:00
parent c03f5d3909
commit f9f930112d
20 changed files with 605 additions and 610 deletions

View File

@ -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 $@ $^

View File

@ -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^
%*

View File

@ -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^
%*

63
dist/jb/inject-01.xml vendored Normal file
View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="Shift-JIS"?>
<inject>
<version __type="u32">1</version>
<debugger>
<app>
<path __type="str">jubeat.exe</path>
<args __type="str"></args>
</app>
<attach_type __type="str">inject</attach_type>
</debugger>
<hooks>
<hook>
<enable __type="bool">1</enable>
<path __type="str">jbhook1.dll</path>
<config kind="inline">
<hook>
<gfx>
<!-- Run the game windowed -->
<windowed __type="bool">0</windowed>
<!-- rotate the normally-horizontal game window to be vertical -->
<vertical __type="bool">1</vertical>
</gfx>
<eamuse>
<!-- 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. -->
<server __type="str">localhost:80</server>
<pcbid __type="bin">0101020304050607086F</pcbid>
<eamid __type="bin">0101020304050607086F</eamid>
</eamuse>
<security>
<mcode __type="str">GCH44JAB</mcode>
</security>
</hook>
</config>
</hook>
</hooks>
<logger>
<enable __type="bool">1</enable>
<level __type="str">misc</level>
<msg_buffer_size_bytes __type="u32">8192</msg_buffer_size_bytes>
<sinks>
<async>
<enable __type="bool">0</enable>
<queue_length __type="u8">64</queue_length>
<overflow_policy __type="str">discard_new</overflow_policy>
</async>
<console>
<enable __type="bool">1</enable>
<color __type="bool">1</color>
</console>
<file>
<enable __type="bool">1</enable>
<path __type="str">inject.log</path>
<append __type="bool">0</append>
<rotate __type="bool">0</rotate>
<max_rotations __type="u8">1</max_rotations>
</file>
</sinks>
</logger>
<debug>
<property_configs_log __type="bool">1</property_configs_log>
<property_api_trace_log __type="bool">0</property_api_trace_log>
</debug>
</inject>

63
dist/jb/inject-02.xml vendored Normal file
View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="Shift-JIS"?>
<inject>
<version __type="u32">1</version>
<debugger>
<app>
<path __type="str">jubeat.exe</path>
<args __type="str"></args>
</app>
<attach_type __type="str">inject</attach_type>
</debugger>
<hooks>
<hook>
<enable __type="bool">1</enable>
<path __type="str">jbhook1.dll</path>
<config kind="inline">
<hook>
<gfx>
<!-- Run the game windowed -->
<windowed __type="bool">0</windowed>
<!-- rotate the normally-horizontal game window to be vertical -->
<vertical __type="bool">1</vertical>
</gfx>
<eamuse>
<!-- 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. -->
<server __type="str">localhost:80</server>
<pcbid __type="bin">0101020304050607086F</pcbid>
<eamid __type="bin">0101020304050607086F</eamid>
</eamuse>
<security>
<mcode __type="str">GCI44JAA</mcode>
</security>
</hook>
</config>
</hook>
</hooks>
<logger>
<enable __type="bool">1</enable>
<level __type="str">misc</level>
<msg_buffer_size_bytes __type="u32">8192</msg_buffer_size_bytes>
<sinks>
<async>
<enable __type="bool">0</enable>
<queue_length __type="u8">64</queue_length>
<overflow_policy __type="str">discard_new</overflow_policy>
</async>
<console>
<enable __type="bool">1</enable>
<color __type="bool">1</color>
</console>
<file>
<enable __type="bool">1</enable>
<path __type="str">inject.log</path>
<append __type="bool">0</append>
<rotate __type="bool">0</rotate>
<max_rotations __type="u8">1</max_rotations>
</file>
</sinks>
</logger>
<debug>
<property_configs_log __type="bool">1</property_configs_log>
<property_api_trace_log __type="bool">0</property_api_trace_log>
</debug>
</inject>

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -1,145 +1,12 @@
#include <string.h>
#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);
}

View File

@ -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

View File

@ -1,54 +1,13 @@
#include <string.h>
#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);
}

View File

@ -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

View File

@ -1,75 +1,10 @@
#include <string.h>
#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);
}

View File

@ -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

View File

@ -1,137 +1,31 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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 <jubeat.exe> [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;
}

158
src/main/jbhook1/gfx.c Normal file
View File

@ -0,0 +1,158 @@
#define LOG_MODULE "jbhook1-gfx"
#include <windows.h>
#include <stdlib.h>
#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");
}

10
src/main/jbhook1/gfx.h Normal file
View File

@ -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

153
src/main/jbhook1/jbhook1.c Normal file
View File

@ -0,0 +1,153 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@ -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

View File

@ -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