Compare commits

..

12 Commits
5.37 ... 5.39

Author SHA1 Message Date
icex2
85a080e6b3 Update changelog for 5.39 release 2022-05-19 00:02:20 +02:00
95c6cd771e00602e3ec82fccba1b3741fdb7f7ca
28633ded37 jbhook2 and jbhook3 gfx updates
- Fix jbhook3 window mode
- Remove -f option for framed window, no value
- Add -s option to show mouse cursor on window
2022-05-13 19:26:00 +00:00
QCDLZCLW3K
721897d7b0 Separate key algorithm and core code for rp2 and rp3 2022-05-12 10:25:53 +09:00
QCDLZCLW3K
926bbf2e10 Small refactor for rp2 and rp3 + add new sign keys 2022-05-12 05:18:07 +09:00
Will Toohey
ce75e149f7 Sane default for vertical window (true) 2022-04-03 21:40:18 +10:00
Will Toohey
57d9d976ff jbhook2: get p3io sidcode from ea3-config, don't hardcode 2022-04-03 21:32:33 +10:00
Will Toohey
7e731916e2 Move p3io-specific jbhook-util funcs to their own static lib 2022-04-03 21:02:38 +10:00
icex2
dd9b8faafe Bump version to 5.39 for next development cycle 2022-04-02 11:16:58 +02:00
icex2
50ff026b85 Update changelog and docs for 5.38 release 2022-04-02 10:51:43 +02:00
Will Xyen
0ff6134b79 sdvxhook: address comments 2022-03-15 16:50:03 -07:00
Will Xyen
ae35b859d9 sdvxio-kfca: add volume overrides 2022-03-15 00:39:10 -07:00
Will Xyen
3cf3d44945 sdvxhook2: add nvapi and power hooks 2022-03-15 00:38:46 -07:00
59 changed files with 751 additions and 352 deletions

View File

@@ -2,6 +2,14 @@
Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions
given in tags. The pipeline will pick this up and cuts out the relevant section for release notes.
## 5.39
* jbhook3: Fix window mode, remove window frame option, add show cursor on window option
* Code simplification and cleanup round plug modules
* Code structure improvements p3io jubeat
## 5.38
* sdvxhook2: Support sound voltex exceed gear
## 5.37
* jbhook1: Support jubeat (1) and ripples
* jbhook2: Support jubeat knit and copious

View File

@@ -142,6 +142,7 @@ include src/main/jbio-p4io/Module.mk
include src/main/jbio/Module.mk
include src/main/jbiotest/Module.mk
include src/main/jbhook-util/Module.mk
include src/main/jbhook-util-p3io/Module.mk
include src/main/jbhook1/Module.mk
include src/main/jbhook2/Module.mk
include src/main/jbhook3/Module.mk
@@ -517,7 +518,7 @@ $(zipdir)/sdvx-01-to-04.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx-05.zip: \
$(zipdir)/sdvx-05-to-06.zip: \
build/bin/avs2_1700-64/launcher.exe \
build/bin/avs2_1700-64/sdvxhook2.dll \
build/bin/indep-64/config.exe \
@@ -671,7 +672,7 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/jb-08.zip \
$(zipdir)/jb-hwio.zip \
$(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-to-06.zip \
$(zipdir)/sdvx-05-cn.zip \
$(zipdir)/sdvx-hwio-x86.zip \
$(zipdir)/sdvx-hwio-x64.zip \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5
[![pipeline status](https://dev.s-ul.net/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.net/djhackers/bemanitools/commits/master)
Version: 5.37
Version: 5.39
[Release history](CHANGELOG.md)
@@ -72,7 +72,8 @@ The tl;dr version and golden rules of the sections in the document:
* SOUND VOLTEX II -infinite infection- (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX III GRAVITY WARS (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx-01-to-04.zip) using sdvxhook
* SOUND VOLTEX Vivid Wave (sdvx-05.zip) using sdvxhook2
* SOUND VOLTEX Vivid Wave (sdvx-05-to-06) using sdvxhook2
* SOUND VOLTEX EXCEED GEAR (sdvx-05-to-06) using sdvxhook2
## ViGEm clients: Expose BT5 APIs as XBOX game controllers
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that

View File

@@ -46,8 +46,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GQGLDJAA
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQGLDJA
sec.black_plug_mcode=GQGLDJAA

View File

@@ -46,8 +46,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GQHDDJAA
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQHDDJA
sec.black_plug_mcode=GQHDDJAA

View File

@@ -49,8 +49,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GQI00JAA
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GQI00JA
sec.black_plug_mcode=GQI00JAA

View File

@@ -49,8 +49,5 @@ gfx.device_adapter=-1
# Disable operator clock setting system clock time
misc.disable_clock_set=false
# Security boot version (e.g. GEC02).
sec.boot_version=GCJDJJAA
# Security black plug mcode id string (e.g. GQC02JAA).
sec.black_plug_mcode=GCJDJJA
sec.black_plug_mcode=GCJDJJAA

View File

@@ -7,4 +7,4 @@ if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
if not exist dev\raw mkdir dev\raw
launcher -H 33554432 -K jbhook2.dll jubeat.dll
launcher -H 33554432 -K jbhook2.dll jubeat.dll -v

View File

@@ -2,7 +2,7 @@
gfx.windowed=false
# rotate the normally-horizontal game window to be vertical
gfx.vertical=false
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

View File

@@ -2,7 +2,7 @@
gfx.windowed=false
# rotate the normally-horizontal game window to be vertical
gfx.vertical=false
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

View File

@@ -13,6 +13,15 @@ io.force_headphones=false
# Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest)
io.disable_file_hooks=false
# Disables the built in power control hooks, allowing game to modify system power settings
io.disable_power_hooks=false
# Disables the built in NVAPI control hooks, allowing game to modify system monitor settings
io.disable_nvapi_hooks=false
# Emulates the card reader on COM1 instead of COM2
io.com1_card_reader=false
# Run the game in a framed window (requires windowed option)
gfx.framed=true
@@ -43,6 +52,12 @@ gfx.device_adapter=-1
# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees
gfx.force_orientation=-1
# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.width=-1
# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
gfx.force_screen_res.height=-1
# Disables the camera emulation
cam.disable_emu=false

View File

@@ -52,7 +52,7 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
config,
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE,
"Confine mouse coursor to window");
"Confine mouse cursor to window");
cconfig_util_set_int(
config,

View File

@@ -16,6 +16,9 @@
static struct security_mcode ezusb_iidx_emu_node_security_plug_boot_version;
static uint32_t ezusb_iidx_emu_node_security_plug_boot_seeds[3];
static struct security_rp_sign_key ezusb_iidx_emu_node_security_plug_black_sign_key;
static struct security_rp_sign_key ezusb_iidx_emu_node_security_plug_white_sign_key;
static struct security_mcode ezusb_iidx_emu_node_security_plug_black_mcode;
static struct security_mcode ezusb_iidx_emu_node_security_plug_white_mcode;
@@ -62,6 +65,28 @@ void ezusb_iidx_emu_node_security_plug_set_boot_seeds(const uint32_t *seeds)
sizeof(ezusb_iidx_emu_node_security_plug_boot_seeds));
}
void ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key(
const struct security_rp_sign_key *sign_key)
{
log_misc("black sign key: %s", sign_key->data);
memcpy(
&ezusb_iidx_emu_node_security_plug_black_sign_key,
sign_key,
sizeof(struct security_rp_sign_key));
}
void ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key(
const struct security_rp_sign_key *sign_key)
{
log_misc("white sign key: %s", sign_key->data);
memcpy(
&ezusb_iidx_emu_node_security_plug_white_sign_key,
sign_key,
sizeof(struct security_rp_sign_key));
}
void ezusb_iidx_emu_node_security_plug_set_plug_black_mcode(
const struct security_mcode *mcode)
{
@@ -373,7 +398,7 @@ bool ezusb_iidx_emu_node_security_plug_read_packet_v2(
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&ezusb_iidx_emu_node_security_plug_boot_version,
&ezusb_iidx_emu_node_security_plug_black_sign_key,
&ezusb_iidx_emu_node_security_plug_black_mcode,
&ezusb_iidx_emu_node_security_plug_pcbid,
(struct security_rp2_eeprom *) pkg->payload);
@@ -415,7 +440,7 @@ bool ezusb_iidx_emu_node_security_plug_read_packet_v2(
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&ezusb_iidx_emu_node_security_plug_boot_version,
&ezusb_iidx_emu_node_security_plug_white_sign_key,
&ezusb_iidx_emu_node_security_plug_white_mcode,
&ezusb_iidx_emu_node_security_plug_eamid,
(struct security_rp2_eeprom *) pkg->payload);

View File

@@ -5,6 +5,7 @@
#include "security/id.h"
#include "security/mcode.h"
#include "security/rp-sign-key.h"
/**
* Set the boot version of the game. The boot version mcode is used for
@@ -23,6 +24,22 @@ void ezusb_iidx_emu_node_security_plug_set_boot_version(
*/
void ezusb_iidx_emu_node_security_plug_set_boot_seeds(const uint32_t *seeds);
/**
* Set the signing key for the black dongle.
*
* @param sign_key Pointer to the black dongle sign key.
*/
void ezusb_iidx_emu_node_security_plug_set_plug_black_sign_key(
const struct security_rp_sign_key *sign_key);
/**
* Set the signing key for the white dongle.
*
* @param sign_key Pointer to the white dongle sign key.
*/
void ezusb_iidx_emu_node_security_plug_set_plug_white_sign_key(
const struct security_rp_sign_key *sign_key);
/**
* The mcode of the target game to boot. This mcode is typically printed onto
* the black plug corresponding to the game to boot.

View File

@@ -38,6 +38,8 @@
#include "iidxhook-util/eamuse.h"
#include "iidxhook-util/settings.h"
#include "security/rp-sign-key.h"
#include "util/log.h"
#include "util/str.h"
#include "util/thread.h"
@@ -163,6 +165,10 @@ my_OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
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_white_sign_key(
&security_rp_sign_key_white_eamuse);
ezusb_iidx_emu_node_security_plug_set_plug_black_mcode(
&config_sec.black_plug_mcode);
ezusb_iidx_emu_node_security_plug_set_plug_white_mcode(
@@ -235,7 +241,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
{
if (reason == DLL_PROCESS_ATTACH) {
log_to_writer(log_writer_debug, NULL);
/* Bootstrap hook for further init tasks (see above) */
hook_table_apply(

View File

@@ -0,0 +1,6 @@
libs += jbhook-util-p3io
src_jbhook-util-p3io := \
gfx.c \
mixer.c \
p3io.c \

View File

@@ -14,7 +14,7 @@
#include "imports/glhelper.h"
#include "jbhook-util/gfx.h"
#include "jbhook-util-p3io/gfx.h"
#include "util/defs.h"
#include "util/log.h"
@@ -47,71 +47,6 @@ static const struct hook_symbol jbhook_infodisp_hook_syms[] = {
.patch = hook_infodispcore_set_angle},
};
static DWORD STDCALL my_GetGlyphOutline(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2);
static DWORD(STDCALL *real_GetGlyphOutline)(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2);
static const struct hook_symbol gfx_hook_syms[] = {
{.name = "GetGlyphOutlineA",
.patch = my_GetGlyphOutline,
.link = (void **) &real_GetGlyphOutline},
{
.name = "IsDBCSLeadByteEx",
.patch = my_GetGlyphOutline, // !??
.link = (void **) &real_GetGlyphOutline // !??
},
};
static DWORD STDCALL my_GetGlyphOutline(
HDC hdc,
UINT uChar,
UINT uFormat,
LPGLYPHMETRICS lpgm,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2)
{
if (IsDBCSLeadByteEx(CP_ACP, uChar & 0xFF)) {
log_warning("!!!!!!!!");
char tmp[2];
tmp[0] = uChar & 0xFF;
tmp[1] = (uChar >> 8) & 0xFF;
MultiByteToWideChar(
CP_ACP, MB_USEGLYPHCHARS, tmp, 2, lpvBuffer, cbBuffer);
}
return real_GetGlyphOutline(
hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, lpmat2);
}
void jbhook_util_gfx_hook_init(void)
{
hook_table_apply(NULL, "gdi32.dll", gfx_hook_syms, lengthof(gfx_hook_syms));
log_info("Inserted gfx hooks");
}
void jbhook_util_gfx_set_windowed(bool framed)
{
}
void jbhook_util_gfx_install_vertical_hooks(void) {
hook_table_apply(
NULL,

View File

@@ -0,0 +1,4 @@
/**
* Rotate a horizontal-by-default jubeat window to vertical
*/
void jbhook_util_gfx_install_vertical_hooks(void);

View File

@@ -5,7 +5,7 @@
#include "bemanitools/jbio.h"
#include "jbhook-util/p3io.h"
#include "jbhook-util-p3io/p3io.h"
#include "p3ioemu/emu.h"
#include "p3ioemu/uart.h"

View File

@@ -6,8 +6,5 @@ libs_jbhook-util := \
src_jbhook-util := \
acio.c \
eamuse.c \
gfx.c \
mixer.c \
locale.c \
p3io.c \
p4io.c \

View File

@@ -1,25 +0,0 @@
#ifndef JBHOOK_D3D8_H
#define JBHOOK_D3D8_H
#include <stdbool.h>
/**
* Hook some gfx related functions to patch gfx related stuff
* like enabling window mode.
*/
void jbhook_util_gfx_hook_init(void);
/**
* Set the game to window mode.
*
* @param framed True to add a window frame and make the window
* movable, resizable, minizable. False for no frame.
*/
void jbhook_util_gfx_set_windowed(bool framed);
/**
* Rotate a horizontal-by-default jubeat window to vertical
*/
void jbhook_util_gfx_install_vertical_hooks(void);
#endif

View File

@@ -2,7 +2,7 @@ avsdlls += jbhook1
imps += glhelper
deplibs_jbhook1 := \
avs \
avs \
glhelper \
ldflags_jbhook1 := \
@@ -15,7 +15,8 @@ libs_jbhook1 := \
cconfig \
eamio \
jbio \
jbhook-util \
jbhook-util \
jbhook-util-p3io \
p3ioemu \
p3io \
hook \

View File

@@ -24,9 +24,10 @@
#include "jbhook-util/acio.h"
#include "jbhook-util/eamuse.h"
#include "jbhook-util/gfx.h"
#include "jbhook-util/mixer.h"
#include "jbhook-util/p3io.h"
#include "jbhook-util-p3io/gfx.h"
#include "jbhook-util-p3io/mixer.h"
#include "jbhook-util-p3io/p3io.h"
#include "p3ioemu/devmgr.h"
#include "p3ioemu/emu.h"

View File

@@ -14,6 +14,7 @@ libs_jbhook2 := \
eamio \
jbio \
jbhook-util \
jbhook-util-p3io \
p3ioemu \
p3io \
p4ioemu \

View File

@@ -22,8 +22,9 @@
#include "jbhook-util/acio.h"
#include "jbhook-util/eamuse.h"
#include "jbhook-util/gfx.h"
#include "jbhook-util/p3io.h"
#include "jbhook-util-p3io/gfx.h"
#include "jbhook-util-p3io/p3io.h"
#include "p3ioemu/devmgr.h"
#include "p3ioemu/emu.h"
@@ -40,15 +41,6 @@
static struct options options;
static const struct security_mcode security_mcode_j44 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_C,
.game = SECURITY_MCODE_GAME_JB_3,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_C,
.revision = SECURITY_MCODE_REVISION_A,
};
static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{
bool eam_io_ok;
@@ -59,6 +51,8 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
log_info("--- Begin jbhook dll_entry_init ---");
log_assert(sidcode != NULL);
if(options.vertical) {
jbhook_util_gfx_install_vertical_hooks();
}
@@ -67,12 +61,20 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
iohook_push_handler(p3io_emu_dispatch_irp);
p3io_setupapi_insert_hooks(NULL);
log_assert(sidcode != NULL);
// pcbid and eamid are only used here for sec check, the ones used for
// network access are taken from ea3-config.xml.
// When booting knit append (and on no other version), the code must
// actually match, so the ID used is for append (JCA)
// actually match, so we use the one from ea3-config as well.
// Example sidcode format: `K44JBA2012072301`
struct security_mcode security_mcode_j44 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_C,
.game = {sidcode[0], sidcode[1], sidcode[2]},
.region = sidcode[3],
.cabinet = sidcode[4],
.revision = sidcode[5],
};
jbhook_util_p3io_init(
&security_mcode_j44,
&security_id_default, &security_id_default);
@@ -111,8 +113,22 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
log_info("--- End jbhook dll_entry_init ---");
char *sidcode_in_ea3_config = strdup(sidcode);
bool ret = app_hook_invoke_init(sidcode, param);
// If the game is append, the mcode `cabinet` is forced to C. This is bad if
// p3io was configured to respond as A! Help the user help themsevles...
if(strcmp(sidcode_in_ea3_config, sidcode) != 0) {
log_warning("sidcode changed after running game DLL init (%s -> %s)", sidcode_in_ea3_config, sidcode);
log_warning("This will trigger a security error. Modify ea3-config.xml <soft> section to match the second value!");
// abort the boot
return false;
}
free(sidcode_in_ea3_config);
return ret;
fail:
@@ -183,6 +199,10 @@ static HWND CDECL my_mwindow_create(
window_height = tmp;
}
if(options.show_cursor) {
ShowCursor(TRUE);
}
fullscreen = !options.windowed;
return real_mwindow_create(
@@ -214,7 +234,6 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
adapter_hook_init();
}
jbhook_util_gfx_hook_init();
jbhook_util_eamuse_hook_init();
return TRUE;

View File

@@ -34,10 +34,10 @@ void options_init_from_cmdline(struct options *options)
void options_init(struct options *options)
{
options->windowed = false;
options->window_framed = false;
options->disable_p3ioemu = false;
options->disable_cardemu = false;
options->disable_adapteremu = false;
options->show_cursor = false;
}
bool options_read_cmdline(struct options *options, int argc, const char **argv)
@@ -60,11 +60,6 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
break;
}
case 'f': {
options->window_framed = true;
break;
}
case 'v': {
options->vertical = true;
break;
@@ -84,6 +79,11 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
options->disable_p3ioemu = true;
break;
}
case 's': {
options->show_cursor = true;
break;
}
}
}
@@ -106,7 +106,8 @@ void options_print_usage(void)
" -c Disable card emulation (e.g. when running on a "
"real cab)\n"
" -p Disable p3io emulation (e.g. when running on a "
"real cab)\n");
"real cab)\n"
" -s Show mouse cursor on game window\n");
}
void options_fini(struct options *options)

View File

@@ -6,11 +6,11 @@
struct options {
bool windowed;
bool window_framed;
bool vertical;
bool disable_p3ioemu;
bool disable_cardemu;
bool disable_adapteremu;
bool show_cursor;
};
void options_init_from_cmdline(struct options *options);

View File

@@ -22,4 +22,5 @@ libs_jbhook3 := \
src_jbhook3 := \
dllmain.c \
gfx.c \
options.c

View File

@@ -9,6 +9,7 @@
#include "bemanitools/jbio.h"
#include "hook/iohook.h"
#include "hook/table.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h"
@@ -17,11 +18,11 @@
#include "imports/avs.h"
#include "jbhook3/gfx.h"
#include "jbhook3/options.h"
#include "jbhook-util/acio.h"
#include "jbhook-util/eamuse.h"
#include "jbhook-util/gfx.h"
#include "jbhook-util/p4io.h"
#include "p4ioemu/device.h"
@@ -48,6 +49,16 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
iohook_push_handler(p4ioemu_dispatch_irp);
iohook_push_handler(jbhook_util_ac_io_port_dispatch_irp);
jbhook3_gfx_init();
if(options.windowed) {
jbhook3_gfx_set_windowed();
}
if(options.show_cursor) {
jbhook3_gfx_set_show_cursor();
}
if (!options.disable_p4ioemu) {
log_info("Starting up jubeat IO backend");
@@ -120,7 +131,7 @@ static bool my_dll_entry_main(void)
if (!options.disable_p4ioemu) {
p4ioemu_fini();
}
options_fini(&options);
return result;
@@ -142,8 +153,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
if (!options.disable_adapteremu) {
adapter_hook_init();
}
jbhook_util_gfx_hook_init();
jbhook_util_eamuse_hook_init();
return TRUE;

73
src/main/jbhook3/gfx.c Normal file
View File

@@ -0,0 +1,73 @@
#define LOG_MODULE "jbhook-gfx"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "hook/table.h"
#include "jbhook3/options.h"
#include "util/log.h"
static bool jbhook3_gfx_windowed;
static bool jbhook3_gfx_show_cursor;
void jbhook3_gfx_set_windowed(void)
{
jbhook3_gfx_windowed = true;
}
void jbhook3_gfx_set_show_cursor(void)
{
jbhook3_gfx_show_cursor = true;
}
static HWND CDECL my_GFWin32MainWindowRun(
HINSTANCE,
const char *,
long,
long,
DWORD);
static HWND(CDECL *real_GFWin32MainWindowRun)(
HINSTANCE,
const char *,
long,
long,
DWORD);
static const struct hook_symbol init_hook_syms[] = {
{.name = "GFWin32MainWindowRun",
.patch = my_GFWin32MainWindowRun,
.link = (void **) &real_GFWin32MainWindowRun,},
};
static HWND CDECL my_GFWin32MainWindowRun(
HINSTANCE hInstance,
const char *lpWindowName,
long X,
long Y,
DWORD dwStyle
)
{
if(jbhook3_gfx_windowed) {
log_info("--- Begin jbhook GFWin32MainWindowRun ---");
dwStyle |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE;
}
if(jbhook3_gfx_show_cursor) {
ShowCursor(TRUE);
}
return real_GFWin32MainWindowRun(hInstance, lpWindowName, X, Y, dwStyle);
}
void jbhook3_gfx_init(void)
{
hook_table_apply(
NULL, "gftools.dll", init_hook_syms, lengthof(init_hook_syms));
log_info("Inserted gfx hooks");
}

3
src/main/jbhook3/gfx.h Normal file
View File

@@ -0,0 +1,3 @@
void jbhook3_gfx_init(void);
void jbhook3_gfx_set_windowed(void);
void jbhook3_gfx_set_show_cursor(void);

View File

@@ -34,10 +34,10 @@ void options_init_from_cmdline(struct options *options)
void options_init(struct options *options)
{
options->windowed = false;
options->window_framed = false;
options->disable_p4ioemu = false;
options->disable_cardemu = false;
options->disable_adapteremu = false;
options->show_cursor = false;
}
bool options_read_cmdline(struct options *options, int argc, const char **argv)
@@ -60,11 +60,6 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
break;
}
case 'f': {
options->window_framed = true;
break;
}
case 'a': {
options->disable_adapteremu = true;
break;
@@ -79,6 +74,11 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
options->disable_p4ioemu = true;
break;
}
case 's': {
options->show_cursor = true;
break;
}
}
}
@@ -95,13 +95,13 @@ void options_print_usage(void)
"\n"
" -h Print this usage message\n"
" -w Run the game windowed\n"
" -f Run the game in a framed window (needs -w option)\n"
" -a Disable adapter hook\n"
" -c Disable card emulation (e.g. when running on a "
"real cab)\n"
" -p Disable p4io emulation (e.g. when running on a "
"real cab or on a bare "
"p4io)\n");
"p4io)\n"
" -s Show mouse cursor on game window\n");
}
void options_fini(struct options *options)

View File

@@ -6,10 +6,10 @@
struct options {
bool windowed;
bool window_framed;
bool disable_p4ioemu;
bool disable_cardemu;
bool disable_adapteremu;
bool show_cursor;
};
void options_init_from_cmdline(struct options *options);

View File

@@ -28,3 +28,5 @@ src_sdvxhook2 := \
bi2a.c \
dllmain.c \
config-io.c \
nvapi.c \
power.c \

View File

@@ -30,11 +30,16 @@
static struct ac_io_emu ac_io_emu;
static struct ac_io_emu_icca ac_io_emu_icca;
void ac_io_port_init(void)
void ac_io_port_init(bool use_new_reader)
{
ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2");
ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0);
if (use_new_reader) {
ac_io_emu_init(&ac_io_emu, L"COM1");
ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0);
ac_io_emu_icca_set_version(&ac_io_emu_icca, v170);
} else {
ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2");
ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0);
}
rs232_hook_add_fd(ac_io_emu.fd);
}

View File

@@ -7,7 +7,7 @@
#include "hook/iohook.h"
void ac_io_port_init(void);
void ac_io_port_init(bool use_new_reader);
void ac_io_port_fini(void);
HRESULT ac_io_port_dispatch_irp(struct irp *irp);

View File

@@ -10,12 +10,19 @@
#define SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter"
#define SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY "io.force_headphones"
#define SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY "io.disable_file_hooks"
#define SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY "io.disable_power_hooks"
#define SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY "io.disable_nvapi_hooks"
#define SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY "io.com1_card_reader"
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE false
void sdvxhook2_config_io_init(struct cconfig *config)
{
@@ -49,6 +56,24 @@ void sdvxhook2_config_io_init(struct cconfig *config)
SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE,
"Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest)");
cconfig_util_set_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE,
"Disables the built in power control hooks, allowing game to modify system power settings");
cconfig_util_set_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE,
"Disables the built in NVAPI control hooks, allowing game to modify system monitor settings");
cconfig_util_set_bool(
config,
SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE,
"Emulates the card reader on COM1 instead of COM2");
}
void sdvxhook2_config_io_get(
@@ -113,4 +138,40 @@ void sdvxhook2_config_io_get(
SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE);
}
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY,
&config_io->disable_power_hooks,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE);
}
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY,
&config_io->disable_nvapi_hooks,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE);
}
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY,
&config_io->com1_card_reader,
SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE);
}
}

View File

@@ -11,6 +11,9 @@ struct sdvxhook2_config_io {
bool disable_poll_limiter;
bool force_headphones;
bool disable_file_hooks;
bool disable_power_hooks;
bool disable_nvapi_hooks;
bool com1_card_reader;
};
void sdvxhook2_config_io_init(struct cconfig *config);

View File

@@ -22,6 +22,8 @@
#include "sdvxhook2/acio.h"
#include "sdvxhook2/bi2a.h"
#include "sdvxhook2/config-io.h"
#include "sdvxhook2/nvapi.h"
#include "sdvxhook2/power.h"
#include "camhook/cam.h"
#include "camhook/config-cam.h"
@@ -147,14 +149,21 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
}
if (!config_io.disable_card_reader_emu) {
ac_io_port_init();
ac_io_port_init(config_io.com1_card_reader);
}
// camera hooks
if (!config_cam.disable_emu) {
camhook_init(&config_cam);
}
if (!config_io.disable_power_hooks) {
powerhook_init();
}
if (!config_io.disable_nvapi_hooks) {
nvapihook_init();
}
adapter_hook_override(config_adapter.override_ip);
log_info("--- End sdvxhook dll_entry_init ---");

View File

@@ -0,0 +1,71 @@
#define LOG_MODULE "power-hook"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <initguid.h>
// clang-format on
#include <powrprof.h>
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "sdvxhook2/nvapi.h"
#include "util/log.h"
static void *my_GetProcAddress(HMODULE dll, const char *name);
static void *(*real_GetProcAddress)(HMODULE dll, const char *name);
// nvapi64.dll
static void *my_nvapi_QueryInterface(uint32_t FunctionOffset);
static void *(*real_nvapi_QueryInterface)(uint32_t FunctionOffset);
static struct hook_symbol nvapihook_kernel_syms[] = {
{.name = "GetProcAddress",
.patch = my_GetProcAddress,
.link = (void *) &real_GetProcAddress},
};
static void *my_GetProcAddress(HMODULE dll, const char *name)
{
if (strcmp("nvapi_QueryInterface", name) == 0) {
log_info("Request for stub %s", name);
real_nvapi_QueryInterface = real_GetProcAddress(dll, name);
return &my_nvapi_QueryInterface;
}
// log_warning("Request for unknown stub %s", name);
return real_GetProcAddress(dll, name);
}
#define OFFSET_NvAPI_DISP_SetDisplayConfig 0x5D8CF8DE
static void *my_nvapi_QueryInterface(uint32_t FunctionOffset) {
if (FunctionOffset == OFFSET_NvAPI_DISP_SetDisplayConfig) {
log_info("Request for interface %x intercepted", FunctionOffset);
// no point stubbing this, the error checking for now doesn't check the response anyways
return NULL;
}
log_info("Request for interface %x passed", FunctionOffset);
return real_nvapi_QueryInterface(FunctionOffset);
}
void nvapihook_init()
{
hook_table_apply(
NULL,
"kernel32.dll",
nvapihook_kernel_syms,
lengthof(nvapihook_kernel_syms));
}
void nvapihook_fini(void)
{
return;
}

View File

@@ -0,0 +1,8 @@
#ifndef NVAPIHOOK_H
#define NVAPIHOOK_H
void nvapihook_init();
void nvapihook_fini(void);
#endif

View File

@@ -0,0 +1,86 @@
#define LOG_MODULE "power-hook"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <initguid.h>
// clang-format on
#include <powrprof.h>
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "sdvxhook2/power.h"
#include "util/log.h"
static DWORD
my_PowerSetActiveScheme(HKEY UserRootPowerKey, const GUID *SchemeGuid);
static DWORD my_PowerWriteACValueIndex(
HKEY RootPowerKey,
const GUID *SchemeGuid,
const GUID *SubGroupOfPowerSettingsGuid,
const GUID *PowerSettingGuid,
DWORD AcValueIndex);
static DWORD
my_PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **ActivePolicyGuid);
static DWORD (*real_PowerSetActiveScheme)(
HKEY UserRootPowerKey, const GUID *SchemeGuid);
static DWORD (*real_PowerWriteACValueIndex)(
HKEY RootPowerKey,
const GUID *SchemeGuid,
const GUID *SubGroupOfPowerSettingsGuid,
const GUID *PowerSettingGuid,
DWORD AcValueIndex);
static DWORD (*real_PowerGetActiveScheme)(
HKEY UserRootPowerKey, GUID **ActivePolicyGuid);
static const struct hook_symbol powerhook_pp_syms[] = {
{.name = "PowerGetActiveScheme",
.patch = my_PowerGetActiveScheme,
.link = (void **) &real_PowerGetActiveScheme},
{.name = "PowerWriteACValueIndex",
.patch = my_PowerWriteACValueIndex,
.link = (void **) &real_PowerWriteACValueIndex},
{.name = "PowerSetActiveScheme",
.patch = my_PowerSetActiveScheme,
.link = (void **) &real_PowerSetActiveScheme},
};
static DWORD
my_PowerSetActiveScheme(HKEY UserRootPowerKey, const GUID *SchemeGuid)
{
// stubbed
return 0;
}
static DWORD my_PowerWriteACValueIndex(
HKEY RootPowerKey,
const GUID *SchemeGuid,
const GUID *SubGroupOfPowerSettingsGuid,
const GUID *PowerSettingGuid,
DWORD AcValueIndex)
{
// stubbed
return 0;
}
static DWORD
my_PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **ActivePolicyGuid)
{
// stubbed
return 0;
}
void powerhook_init()
{
hook_table_apply(
NULL, "PowrProf.dll", powerhook_pp_syms, lengthof(powerhook_pp_syms));
}
void powerhook_fini(void)
{
return;
}

View File

@@ -0,0 +1,8 @@
#ifndef POWERHOOK_H
#define POWERHOOK_H
void powerhook_init();
void powerhook_fini(void);
#endif

View File

@@ -6,9 +6,15 @@
#define SDVXIO_KFCA_CONFIG_KFCA_PORT_KEY "kfca.port"
#define SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY "kfca.baud"
#define SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY "kfca.main_override"
#define SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY "kfca.headphone_override"
#define SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY "kfca.subwoofer_override"
#define SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_PORT_VALUE "COM3"
#define SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE 57600
#define SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE -1
#define SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE -1
#define SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE -1
void sdvxio_kfca_config_kfca_init(struct cconfig *config)
{
@@ -23,6 +29,24 @@ void sdvxio_kfca_config_kfca_init(struct cconfig *config)
SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY,
SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE,
"KFCA ACIO bus baudrate (real devices expect 57600)");
cconfig_util_set_int(
config,
SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE,
"SDVXIO digital amp main volume (0-96) 0 is high, 96 is low. -1 is no override.");
cconfig_util_set_int(
config,
SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE,
"SDVXIO digital amp headphone volume (0-96) 0 is high, 96 is low. -1 is no override.");
cconfig_util_set_int(
config,
SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE,
"SDVXIO digital amp subwoofer volume (0-96) 0 is high, 96 is low. -1 is no override.");
}
void sdvxio_kfca_config_kfca_get(
@@ -52,4 +76,40 @@ void sdvxio_kfca_config_kfca_get(
SDVXIO_KFCA_CONFIG_KFCA_BAUD_KEY,
SDVXIO_KFCA_CONFIG_KFCA_DEFAULT_BAUD_VALUE);
}
if (!cconfig_util_get_int(
config,
SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY,
&config_kfca->override_main_volume,
SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXIO_KFCA_CONFIG_MAIN_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_MAIN_AMP_VOLUME_VALUE);
}
if (!cconfig_util_get_int(
config,
SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY,
&config_kfca->override_headphone_volume,
SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXIO_KFCA_CONFIG_HEADPHONE_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_HEADPHONE_AMP_VOLUME_VALUE);
}
if (!cconfig_util_get_int(
config,
SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY,
&config_kfca->override_sub_volume,
SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXIO_KFCA_CONFIG_SUBWOOFER_AMP_VOLUME_KEY,
SDVXIO_KFCA_CONFIG_DEFAULT_SUBWOOFER_AMP_VOLUME_VALUE);
}
}

View File

@@ -8,6 +8,9 @@
struct sdvxio_kfca_config_kfca {
char port[64];
int32_t baud;
int32_t override_main_volume;
int32_t override_headphone_volume;
int32_t override_sub_volume;
};
void sdvxio_kfca_config_kfca_init(struct cconfig *config);

View File

@@ -120,9 +120,24 @@ bool sdvx_io_init(
if (kfca_node_id != -1) {
log_warning("Using KFCA on node: %d", kfca_node_id);
bool init_result = aciodrv_kfca_init(
uint8_t primary = 0;
uint8_t headphone = 0;
uint8_t subwoofer = 0;
if (config_kfca.override_main_volume >= 0) {
primary = config_kfca.override_main_volume;
}
if (config_kfca.override_headphone_volume >= 0) {
headphone = config_kfca.override_headphone_volume;
}
if (config_kfca.override_sub_volume >= 0) {
subwoofer = config_kfca.override_sub_volume;
}
bool init_result = aciodrv_kfca_amp(
aciomgr_port_checkout(acio_manager_ctx),
kfca_node_id);
kfca_node_id,
primary, headphone, 0, subwoofer);
aciomgr_port_checkin(acio_manager_ctx);
if (!init_result) {
@@ -240,7 +255,7 @@ bool sdvx_io_set_amp_volume(
bool amp_result = aciodrv_kfca_amp(
aciomgr_port_checkout(acio_manager_ctx),
kfca_node_id,
primary, 96, headphone, subwoofer);
primary, headphone, 96, subwoofer);
aciomgr_port_checkin(acio_manager_ctx);
if (!amp_result) {

View File

@@ -67,7 +67,7 @@ bool sdvx_io_read_input(void)
sdvx_io_gpio[0] = (pack >> 8) & 0x00FF;
sdvx_io_gpio[1] = (pack >> 16) & 0x00FF;
return 0;
return true;
}
uint8_t sdvx_io_get_input_gpio_sys(void)

View File

@@ -53,6 +53,15 @@
#define SECURITY_MCODE_GAME_JB_1 "H44"
#define SECURITY_MCODE_GAME_JB_3 "J44"
/* DDR */
#define SECURITY_MCODE_GAME_DDR_X "HDX"
/* pop'n music */
#define SECURITY_MCODE_GAME_POPN_15 "G15"
#define SECURITY_MCODE_GAME_POPN_16 "H16"
#define SECURITY_MCODE_GAME_POPN_17 "I17"
#define SECURITY_MCODE_GAME_POPN_18 "J39"
/* Region */
#define SECURITY_MCODE_REGION_ASIA 'A'
#define SECURITY_MCODE_REGION_JAPAN 'J'

View File

@@ -3,8 +3,20 @@
const struct security_rp_sign_key security_rp_sign_key_white_eamuse = {
.data = "E-AMUSE3"};
const struct security_rp_sign_key security_rp_sign_key_black_ps2 = {
const struct security_rp_sign_key security_rp_sign_key_black_python2 = {
.data = "GENTAKAH"};
const struct security_rp_sign_key security_rp_sign_key_black_gfdmv4 = {
.data = "UDONHRKI"};
.data = "UDONHRKI"};
const struct security_rp_sign_key security_rp_sign_key_black_gfdmv8 = {
.data = "SHAMOSAN"};
const struct security_rp_sign_key security_rp_sign_key_black_ddrx = {
.data = "573PROJE"};
const struct security_rp_sign_key security_rp_sign_key_black_iidx = {
.data = "2DXGLDAC"};
const struct security_rp_sign_key security_rp_sign_key_black_popn = {
.data = "POPNG15A"};

View File

@@ -11,23 +11,55 @@ struct security_rp_sign_key {
};
/**
* Signing key used to create eeprom signitures for all white eamuse dongles.
* Signing key used to create eeprom signatures for all white eamuse dongles
*/
extern const struct security_rp_sign_key security_rp_sign_key_white_eamuse;
/**
* Signing key used to create eeprom signitures for all black dongles used
* on PS2 games (as far as we are aware of).
* Signing key used to create eeprom signatures for all black dongles used
* on Python 2 games.
*/
extern const struct security_rp_sign_key security_rp_sign_key_black_ps2;
extern const struct security_rp_sign_key security_rp_sign_key_black_python2;
/**
* Signing key used to create eeprom signitures for all black dongles used
* Signing key used to create eeprom signatures for all black dongles used
* on the following games:
*
* - GF & DM V4 to V8 (TODO needs verification)
* - GF & DM V4 to V7
* - jubeat (1)
*/
extern const struct security_rp_sign_key security_rp_sign_key_black_gfdmv4;
/**
* Signing key used to create eeprom signatures for all black dongles used
* on the following games:
*
* - GF & DM V8, XG to XG3, Gitadora series
*/
extern const struct security_rp_sign_key security_rp_sign_key_black_gfdmv8;
/**
* Signing key used to create eeprom signatures for all black dongles used
* on the following games:
*
* - DDR X
*/
extern const struct security_rp_sign_key security_rp_sign_key_black_ddrx;
/**
* Signing key used to create eeprom signatures for all black dongles used
* on the following games:
*
* - IIDX 14 to 17
*/
extern const struct security_rp_sign_key security_rp_sign_key_black_iidx;
/**
* Signing key used to create eeprom signatures for all black dongles used
* on the following games:
*
* - pop'n music 15 to 17
*/
extern const struct security_rp_sign_key security_rp_sign_key_black_popn;
#endif

View File

@@ -10,7 +10,7 @@
/**
* Structure for data which is usually stored in the eeprom section of the
* dongle. This contains a signiture to verify the ROM's contents as well as
* dongle. This contains a signature to verify the ROM's contents as well as
* the game this dongle is signed for.
*/
struct security_rp_eeprom {

View File

@@ -1,15 +1,12 @@
#include <string.h>
#include "security/rp2.h"
#include "security/rp-util.h"
#include "security/util.h"
#include "util/crypto.h"
#include "util/log.h"
static const uint8_t security_rp2_sign_key_base_black[] = {
0x32, 0x44, 0x58, 0x47, 0x4C, 0x44, 0x41, 0x43};
static const uint8_t security_rp2_sign_key_base_white[] = {
0x45, 0x2D, 0x41, 0x4D, 0x55, 0x53, 0x45, 0x33};
static uint8_t security_rp2_signature_scramble_table[16] = {0x0C,
0x02,
0x0F,
@@ -27,7 +24,7 @@ static uint8_t security_rp2_signature_scramble_table[16] = {0x0C,
0x08,
0x06};
static void security_rp2_create_signiture(
void security_rp2_create_signature(
const uint8_t *plug_id_enc, const uint8_t *sign_key_packed, uint8_t *out)
{
uint8_t data[14];
@@ -53,70 +50,51 @@ static void security_rp2_create_signiture(
}
}
void security_rp2_generate_signed_eeprom_data_core(
const uint8_t *sign_key,
const uint8_t *plug_mcode,
const uint8_t *plug_id,
uint8_t *signature,
uint8_t *packed_payload)
{
uint8_t sign_key_tmp[8];
security_util_8_to_6_encode(sign_key, sign_key_tmp);
security_rp2_create_signature(plug_id, sign_key_tmp, signature);
security_util_8_to_6_encode(plug_mcode, packed_payload);
}
void security_rp2_generate_signed_eeprom_data(
enum security_rp_util_rp_type type,
const struct security_mcode *boot_version,
const struct security_rp_sign_key *sign_key,
const struct security_mcode *plug_mcode,
const struct security_id *plug_id,
struct security_rp2_eeprom *out)
{
uint8_t sign_key[8];
uint8_t sign_key_tmp[8];
uint8_t plug_id_enc[8];
char *boot_version_str;
const uint8_t *plug_mcode_raw = (const uint8_t *) plug_mcode;
log_assert(boot_version);
log_assert(sign_key);
log_assert(plug_mcode);
log_assert(plug_id);
log_assert(out);
boot_version_str = (char *) boot_version;
for (int i = 0; i < sizeof(sign_key_tmp); i++) {
sign_key_tmp[i] = sign_key->data[i] ^ 0x40;
/* -------------------------------- */
switch (type) {
case SECURITY_RP_UTIL_RP_TYPE_BLACK:
memcpy(
sign_key, security_rp2_sign_key_base_black, sizeof(sign_key));
sign_key[0] = boot_version_str[0] ^ sign_key[0];
sign_key[1] ^= boot_version_str[1];
sign_key[2] = boot_version_str[2] ^ sign_key[2];
sign_key[3] = boot_version_str[3] ^ sign_key[3];
sign_key[4] = boot_version_str[4] ^ sign_key[4];
sign_key[5] ^= boot_version_str[5];
sign_key[6] = boot_version_str[6] ^ sign_key[6];
sign_key[7] = boot_version_str[7] ^ sign_key[7];
break;
case SECURITY_RP_UTIL_RP_TYPE_WHITE:
memcpy(
sign_key, security_rp2_sign_key_base_white, sizeof(sign_key));
break;
default:
log_assert(false);
break;
if (type == SECURITY_RP_UTIL_RP_TYPE_BLACK) {
sign_key_tmp[i] ^= plug_mcode_raw[i];
}
}
for (uint8_t i = 0; i < sizeof(sign_key); i++) {
sign_key[i] ^= 0x40;
}
security_util_8_to_6_encode(sign_key, sign_key);
plug_id_enc[0] = plug_id->checksum;
plug_id_enc[1] = plug_id->id[2];
plug_id_enc[2] = plug_id->id[3];
plug_id_enc[3] = plug_id->id[4];
plug_id_enc[4] = plug_id->id[5];
plug_id_enc[5] = plug_id->id[6];
plug_id_enc[6] = plug_id->id[7];
memcpy(&plug_id_enc[1], &plug_id->id[2], 6);
plug_id_enc[7] = plug_id->id[1];
security_rp2_create_signiture(plug_id_enc, sign_key, (uint8_t *) out);
security_util_8_to_6_encode(
(const uint8_t *) plug_mcode, out->packed_payload);
}
security_rp2_generate_signed_eeprom_data_core(
sign_key_tmp,
plug_mcode_raw,
plug_id_enc,
out->signature,
out->packed_payload);
}

View File

@@ -6,11 +6,12 @@
#include "security/id.h"
#include "security/mcode.h"
#include "security/rp-sign-key.h"
#include "security/rp-util.h"
/**
* Structure for data which is usually stored in the eeprom section of the
* dongle. This contains a signiture to verify the ROM's contents as well as
* dongle. This contains a signature to verify the ROM's contents as well as
* the game this dongle is signed for.
*/
struct security_rp2_eeprom {
@@ -18,6 +19,24 @@ struct security_rp2_eeprom {
uint8_t packed_payload[6];
};
/**
* This is the core of the algorithm shared between rp2 and rp3 dongles.
* The keys passed to this function are assumed to already be mutated
* as required.
*
* @param sign_key The key to use for generating the signature.
* @param plug_mcode The mcode of the game to boot.
* @param plug_id The id stored on the plug.
* @param signature Pointer to the signature buffer for the resulting data.
* @param packed_payload Pointer to the payload buffer for the resulting data.
*/
void security_rp2_generate_signed_eeprom_data_core(
const uint8_t *sign_key,
const uint8_t *plug_mcode,
const uint8_t *plug_id,
uint8_t *signature,
uint8_t *packed_payload);
/**
* Generate signed eeprom data from non encrypted and unobfuscated data required
* to pass security checks on games using black (game specific) and white
@@ -25,10 +44,12 @@ struct security_rp2_eeprom {
*
* This implementation (rp 2) is used by the following games
* - iidx 14 to 17
* - pop'n music 15 to 18
*
* @param type Type of plug to sign eeprom data for (black or white).
* @param boot_version The boot version mcode that is used for bootstrapping
* the security backend (of the ezusb.dll).
* @param sign_key The key to use for generating the signature.
* This key can be extracted from the executables of the games and might
* be re-used for multiple games of the same series or generation.
* @param plug_mcode The mcode of the game to boot. Typically, this code is
* printed onto the housing of the black dongle. For white
* dongles, the "mcode" @@@@@@@@ is used.
@@ -39,7 +60,7 @@ struct security_rp2_eeprom {
*/
void security_rp2_generate_signed_eeprom_data(
enum security_rp_util_rp_type type,
const struct security_mcode *boot_version,
const struct security_rp_sign_key *sign_key,
const struct security_mcode *plug_mcode,
const struct security_id *plug_id,
struct security_rp2_eeprom *out);

View File

@@ -1,54 +1,13 @@
#include <string.h>
#include "security/rp2.h"
#include "security/rp3.h"
#include "security/rp-util.h"
#include "security/util.h"
#include "util/crc.h"
#include "util/crypto.h"
#include "util/log.h"
static uint8_t security_rp3_signature_scramble_table[] = {0x0C,
0x02,
0x0F,
0x01,
0x07,
0x09,
0x04,
0x0A,
0x00,
0x0E,
0x03,
0x0D,
0x0B,
0x05,
0x08,
0x06};
static void security_rp3_create_signature(
const uint8_t *plug_id, const uint8_t *sign_key_packed, uint8_t *out)
{
uint8_t data[14];
uint8_t md5[16];
uint8_t buffer[18];
memcpy(data, plug_id, 8);
memcpy(data + 8, sign_key_packed, 6);
crypto_init();
md5_compute(data, 14, md5, sizeof(md5));
crypto_fini();
for (int i = 0; i < 16; i++) {
buffer[i] = md5[security_rp3_signature_scramble_table[i]];
}
buffer[16] = 0xDE;
buffer[17] = 0xAD;
for (int i = 0; i < 6; i++) {
out[i] = buffer[i + 12] ^ buffer[i + 6] ^ buffer[i];
}
}
void security_rp3_generate_signed_eeprom_data(
enum security_rp_util_rp_type type,
const struct security_rp_sign_key *sign_key,
@@ -57,8 +16,8 @@ void security_rp3_generate_signed_eeprom_data(
struct security_rp3_eeprom *out)
{
uint8_t sign_key_tmp[8];
uint8_t sign_key_packed[6];
uint8_t plug_id_reversed[8];
const uint8_t *plug_mcode_raw = (const uint8_t *) plug_mcode;
log_assert(sign_key);
log_assert(plug_mcode);
@@ -66,24 +25,23 @@ void security_rp3_generate_signed_eeprom_data(
log_assert(out);
memcpy(sign_key_tmp, sign_key, sizeof(sign_key_tmp));
if (type == SECURITY_RP_UTIL_RP_TYPE_BLACK) {
for (int i = 0; i < sizeof(sign_key_tmp); i++) {
sign_key_tmp[i] ^= ((const uint8_t *) plug_mcode)[i];
sign_key_tmp[i] ^= plug_mcode_raw[i];
}
}
security_util_8_to_6_encode(sign_key_tmp, sign_key_packed);
for (int i = 0; i < sizeof(plug_id_reversed); i++) {
plug_id_reversed[i] = plug_id->id[7 - i];
}
security_util_8_to_6_encode(
(const uint8_t *) plug_mcode, out->packed_payload);
memset(out->zeros, 0, sizeof(out->zeros));
security_rp2_generate_signed_eeprom_data_core(
sign_key_tmp,
plug_mcode_raw,
plug_id_reversed,
out->signature,
out->packed_payload);
security_rp3_create_signature(
plug_id_reversed, sign_key_packed, out->signature);
memset(out->zeros, 0, sizeof(out->zeros));
out->crc = crc8((uint8_t *) out, sizeof(*out) - 1, 0);
}

View File

@@ -11,7 +11,7 @@
/**
* Structure for data which is usually stored in the eeprom section of the
* dongle. This contains a signiture to verify the ROM's contents as well as
* dongle. This contains a signature to verify the ROM's contents as well as
* the game this dongle is signed for.
*/
struct security_rp3_eeprom {
@@ -26,11 +26,16 @@ struct security_rp3_eeprom {
* to pass security checks on games using black (game specific) and white
* (eamuse) roundplugs.
*
* Algorithm is the same as RP2 but plug ID is handled in reverse order
* and response has additional padding + checksum at the end of the message.
*
* Used on the following games:
* - jubeat
* - jubeat series
* - DDR series
* - GFDM V series, XG series, Gitadora series
*
* @param type Type of plug to sign eeprom data for (black or white).
* @param sign_key The key to use for generating the signiture.
* @param sign_key The key to use for generating the signature.
* This key can be extracted from the executables of the games and might
* be re-used for multiple games of the same series or generation.
* @param plug_mcode The mcode of the game to boot. Typically, this code is

View File

@@ -1,52 +1,17 @@
#include "security/id.h"
#include "security/rp2.h"
#include "security/rp-sign-key.h"
#include "test/check.h"
#include "test/test.h"
static const struct security_mcode boot_version_iidx_14 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_Q,
.game = SECURITY_MCODE_GAME_IIDX_14,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_mcode boot_version_iidx_15 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_Q,
.game = SECURITY_MCODE_GAME_IIDX_15,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_mcode boot_version_iidx_16 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_Q,
.game = SECURITY_MCODE_GAME_IIDX_16,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_mcode boot_version_iidx_17 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_C,
.game = SECURITY_MCODE_GAME_IIDX_17,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_mcode black_plug_mcode_iidx_14 = {
.header = SECURITY_MCODE_HEADER,
.unkn = SECURITY_MCODE_UNKN_Q,
.game = SECURITY_MCODE_GAME_IIDX_14,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_FIELD_NULL,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_mcode black_plug_mcode_iidx_15 = {
@@ -55,7 +20,7 @@ static const struct security_mcode black_plug_mcode_iidx_15 = {
.game = SECURITY_MCODE_GAME_IIDX_15,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_FIELD_NULL,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_mcode black_plug_mcode_iidx_16 = {
@@ -64,7 +29,7 @@ static const struct security_mcode black_plug_mcode_iidx_16 = {
.game = SECURITY_MCODE_GAME_IIDX_16,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_FIELD_NULL,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_mcode black_plug_mcode_iidx_17 = {
@@ -73,27 +38,27 @@ static const struct security_mcode black_plug_mcode_iidx_17 = {
.game = SECURITY_MCODE_GAME_IIDX_17,
.region = SECURITY_MCODE_REGION_JAPAN,
.cabinet = SECURITY_MCODE_CABINET_A,
.revision = SECURITY_MCODE_FIELD_NULL,
.revision = SECURITY_MCODE_REVISION_A,
};
static const struct security_rp2_eeprom exp_iidx_14_black_eeprom = {
.signature = {0x17, 0xC6, 0x2B, 0x6A, 0xDA, 0x29},
.packed_payload = {0x67, 0x7C, 0xB2, 0xA4, 0x1A, 0x82},
.packed_payload = {0x67, 0x7C, 0xB2, 0xA4, 0x1A, 0x86},
};
static const struct security_rp2_eeprom exp_iidx_15_black_eeprom = {
.signature = {0xCE, 0xF8, 0xC7, 0xEF, 0xA6, 0xDF},
.packed_payload = {0x67, 0x8C, 0x92, 0xA4, 0x1A, 0x82},
.packed_payload = {0x67, 0x8C, 0x92, 0xA4, 0x1A, 0x86},
};
static const struct security_rp2_eeprom exp_iidx_16_black_eeprom = {
.signature = {0xE0, 0x58, 0xDA, 0xE4, 0x61, 0xF9},
.packed_payload = {0x67, 0x9C, 0x42, 0x90, 0x1A, 0x82},
.packed_payload = {0x67, 0x9C, 0x42, 0x90, 0x1A, 0x86},
};
static const struct security_rp2_eeprom exp_iidx_17_black_eeprom = {
.signature = {0xC3, 0x4B, 0xF8, 0xAA, 0xC1, 0x3E},
.packed_payload = {0xE7, 0xA8, 0x92, 0xAA, 0x1A, 0x82},
.packed_payload = {0xE7, 0xA8, 0x92, 0xAA, 0x1A, 0x86},
};
static const struct security_rp2_eeprom exp_iidx_14_white_eeprom = {
@@ -122,7 +87,7 @@ static void test_encode_iidx_14_black_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&boot_version_iidx_14,
&security_rp_sign_key_black_iidx,
&black_plug_mcode_iidx_14,
&security_id_default,
&result);
@@ -140,7 +105,7 @@ static void test_encode_iidx_14_white_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&boot_version_iidx_14,
&security_rp_sign_key_white_eamuse,
&security_mcode_eamuse,
&security_id_default,
&result);
@@ -158,7 +123,7 @@ static void test_encode_iidx_15_black_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&boot_version_iidx_15,
&security_rp_sign_key_black_iidx,
&black_plug_mcode_iidx_15,
&security_id_default,
&result);
@@ -176,7 +141,7 @@ static void test_encode_iidx_15_white_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&boot_version_iidx_15,
&security_rp_sign_key_white_eamuse,
&security_mcode_eamuse,
&security_id_default,
&result);
@@ -194,7 +159,7 @@ static void test_encode_iidx_16_black_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&boot_version_iidx_16,
&security_rp_sign_key_black_iidx,
&black_plug_mcode_iidx_16,
&security_id_default,
&result);
@@ -212,7 +177,7 @@ static void test_encode_iidx_16_white_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&boot_version_iidx_16,
&security_rp_sign_key_white_eamuse,
&security_mcode_eamuse,
&security_id_default,
&result);
@@ -230,7 +195,7 @@ static void test_encode_iidx_17_black_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_BLACK,
&boot_version_iidx_17,
&security_rp_sign_key_black_iidx,
&black_plug_mcode_iidx_17,
&security_id_default,
&result);
@@ -248,7 +213,7 @@ static void test_encode_iidx_17_white_dongle()
security_rp2_generate_signed_eeprom_data(
SECURITY_RP_UTIL_RP_TYPE_WHITE,
&boot_version_iidx_17,
&security_rp_sign_key_white_eamuse,
&security_mcode_eamuse,
&security_id_default,
&result);