Bemanitools v5.26 release
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
avsdlls += jbhook1
|
||||
|
||||
deplibs_jbhook1 := \
|
||||
avs \
|
||||
|
||||
ldflags_jbhook1 := \
|
||||
-lws2_32 \
|
||||
-liphlpapi \
|
||||
|
||||
libs_jbhook1 := \
|
||||
acioemu \
|
||||
cconfig \
|
||||
eamio \
|
||||
jbio \
|
||||
p3ioemu \
|
||||
p3io \
|
||||
hook \
|
||||
hooklib \
|
||||
security \
|
||||
util \
|
||||
|
||||
src_jbhook1 := \
|
||||
acio.c \
|
||||
avs-boot.c \
|
||||
config-gfx.c \
|
||||
config-eamuse.c \
|
||||
config-security.c \
|
||||
dllmain.c \
|
||||
log-gftools.c \
|
||||
p3io.c \
|
||||
@@ -0,0 +1,95 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntdef.h>
|
||||
#include <devioctl.h>
|
||||
#include <ntddser.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "acioemu/addr.h"
|
||||
#include "acioemu/emu.h"
|
||||
#include "acioemu/h44b.h"
|
||||
#include "acioemu/icca.h"
|
||||
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "jbhook/acio.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/hex.h"
|
||||
#include "util/iobuf.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static struct ac_io_emu ac_io_emu;
|
||||
static struct ac_io_emu_icca ac_io_emu_icca;
|
||||
static struct ac_io_emu_h44b ac_io_emu_h44b;
|
||||
|
||||
void ac_io_port_init(void)
|
||||
{
|
||||
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_h44b_init(&ac_io_emu_h44b, &ac_io_emu, 1);
|
||||
}
|
||||
|
||||
void ac_io_port_fini(void)
|
||||
{
|
||||
ac_io_emu_fini(&ac_io_emu);
|
||||
}
|
||||
|
||||
HRESULT ac_io_port_dispatch_irp(struct irp *irp)
|
||||
{
|
||||
const struct ac_io_message *msg;
|
||||
HRESULT hr;
|
||||
|
||||
log_assert(irp != NULL);
|
||||
|
||||
if (!ac_io_emu_match_irp(&ac_io_emu, irp)) {
|
||||
return irp_invoke_next(irp);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
hr = ac_io_emu_dispatch_irp(&ac_io_emu, irp);
|
||||
|
||||
if (hr != S_OK) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
msg = ac_io_emu_request_peek(&ac_io_emu);
|
||||
|
||||
switch (msg->addr) {
|
||||
case 0:
|
||||
ac_io_emu_cmd_assign_addrs(&ac_io_emu, msg, 2);
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ac_io_emu_icca_dispatch_request(&ac_io_emu_icca, msg);
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ac_io_emu_h44b_dispatch_request(&ac_io_emu_h44b, msg);
|
||||
|
||||
break;
|
||||
|
||||
case AC_IO_BROADCAST:
|
||||
log_warning("Broadcast(?) message on jubeat ACIO bus?");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning("ACIO message on unhandled bus address: %d",
|
||||
msg->addr);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ac_io_emu_request_pop(&ac_io_emu);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef JBHOOK1_ACIO_H
|
||||
#define JBHOOK1_ACIO_H
|
||||
|
||||
#include "hook/iohook.h"
|
||||
|
||||
/**
|
||||
* Initialize the ACIO backend for jubeat.
|
||||
*/
|
||||
void ac_io_port_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown the ACIO backend.
|
||||
*/
|
||||
void ac_io_port_fini(void);
|
||||
|
||||
/**
|
||||
* ACIO backend dispatch irp function. This needs to be hooked up to the iohook
|
||||
* module in order to receive system calls to dispatch for emulation.
|
||||
*/
|
||||
HRESULT ac_io_port_dispatch_irp(struct irp *irp);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,157 @@
|
||||
#define LOG_MODULE "avs-boot"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "jbhook1/avs-boot.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
static void (*real_avs_boot)(
|
||||
struct property_node *config, void *std_heap, size_t sz_std_heap,
|
||||
void *avs_heap, size_t sz_avs_heap, avs_log_writer_t log_writer,
|
||||
void *log_context);
|
||||
static int (*real_log_change_level)(int level);
|
||||
static int (*real_ea3_boot)(struct property_node *config);
|
||||
|
||||
static void my_avs_boot(
|
||||
struct property_node *config, void *std_heap, size_t sz_std_heap,
|
||||
void *avs_heap, size_t sz_avs_heap, avs_log_writer_t log_writer,
|
||||
void *log_context);
|
||||
static int my_log_change_level(int level);
|
||||
static int my_ea3_boot(struct property_node *config);
|
||||
|
||||
static struct net_addr jbhook1_avs_boot_eamuse_server_addr;
|
||||
|
||||
static const struct hook_symbol jbhook1_log_gftools_hook_syms[] = {
|
||||
{
|
||||
.name = "avs_boot",
|
||||
.patch = my_avs_boot,
|
||||
.link = (void **) &real_avs_boot
|
||||
},
|
||||
{
|
||||
.name = "log_change_level",
|
||||
.patch = my_log_change_level,
|
||||
.link = (void **) &real_log_change_level
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hook_symbol jbhook1_log_gftools_hook_syms2[] = {
|
||||
{
|
||||
.name = "ea3_boot",
|
||||
.patch = my_ea3_boot,
|
||||
.link = (void **) &real_ea3_boot
|
||||
},
|
||||
};
|
||||
|
||||
static void avs_boot_replace_property_uint32(struct property_node* node,
|
||||
const char* name, uint32_t val)
|
||||
{
|
||||
struct property_node* tmp;
|
||||
|
||||
tmp = property_search(NULL, node, name);
|
||||
|
||||
if (tmp) {
|
||||
property_node_remove(tmp);
|
||||
}
|
||||
|
||||
property_node_create(NULL, node, PSMAP_TYPE_U32, name, val);
|
||||
}
|
||||
|
||||
static void avs_boot_replace_property_str(struct property_node* node,
|
||||
const char* name, const char* val)
|
||||
{
|
||||
struct property_node* tmp;
|
||||
|
||||
tmp = property_search(NULL, node, name);
|
||||
|
||||
if (tmp) {
|
||||
property_node_remove(tmp);
|
||||
}
|
||||
|
||||
tmp = property_node_create(NULL, node, PSMAP_TYPE_STR_LEGACY, name, val);
|
||||
|
||||
if (tmp) {
|
||||
property_node_datasize(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void my_avs_boot(
|
||||
struct property_node *config, void *std_heap, size_t sz_std_heap,
|
||||
void *avs_heap, size_t sz_avs_heap, avs_log_writer_t log_writer,
|
||||
void *log_context)
|
||||
{
|
||||
log_info("Called my_avs_boot");
|
||||
|
||||
avs_boot_replace_property_uint32(config, "log/level", 4);
|
||||
avs_boot_replace_property_str(config, "/config/fs/nvram/device",
|
||||
"./CONF/NVRAM");
|
||||
avs_boot_replace_property_str(config, "/config/fs/raw/device",
|
||||
"./CONF/RAW");
|
||||
|
||||
real_avs_boot(config, std_heap, sz_std_heap, avs_heap, sz_avs_heap,
|
||||
log_writer_debug, NULL);
|
||||
}
|
||||
|
||||
static int my_ea3_boot(struct property_node *config)
|
||||
{
|
||||
char* server_addr;
|
||||
|
||||
log_info("Called my_ea3_boot");
|
||||
|
||||
if (jbhook1_avs_boot_eamuse_server_addr.type != NET_ADDR_TYPE_INVALID) {
|
||||
log_misc("Injecting network server address");
|
||||
|
||||
server_addr = net_addr_to_str(&jbhook1_avs_boot_eamuse_server_addr);
|
||||
|
||||
avs_boot_replace_property_str(config, "network/services", server_addr);
|
||||
|
||||
free(server_addr);
|
||||
}
|
||||
|
||||
return real_ea3_boot(config);
|
||||
}
|
||||
|
||||
static int my_log_change_level(int level)
|
||||
{
|
||||
log_misc("Log change level: %d", level);
|
||||
|
||||
return real_log_change_level(level);
|
||||
}
|
||||
|
||||
void jbhook1_avs_boot_init()
|
||||
{
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"libavs-win32.dll",
|
||||
jbhook1_log_gftools_hook_syms,
|
||||
lengthof(jbhook1_log_gftools_hook_syms));
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"libavs-win32-ea3.dll",
|
||||
jbhook1_log_gftools_hook_syms2,
|
||||
lengthof(jbhook1_log_gftools_hook_syms2));
|
||||
|
||||
memset(&jbhook1_avs_boot_eamuse_server_addr, 0, sizeof(struct net_addr));
|
||||
|
||||
log_info("Inserted avs log hooks");
|
||||
}
|
||||
|
||||
void jbhook1_avs_boot_set_eamuse_addr(const struct net_addr* server_addr)
|
||||
{
|
||||
char* str;
|
||||
|
||||
str = net_addr_to_str(server_addr);
|
||||
log_info("Setting eamuse server: %s", str);
|
||||
free(str);
|
||||
|
||||
memcpy(&jbhook1_avs_boot_eamuse_server_addr, server_addr,
|
||||
sizeof(struct net_addr));
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef JBHOOK1_AVS_BOOT_H
|
||||
#define JBHOOK1_AVS_BOOT_H
|
||||
|
||||
#include "util/net.h"
|
||||
|
||||
/**
|
||||
* Initialize hooking of avs_boot and ea3_boot. This re-enables avs logging
|
||||
* and injects a few important settings.
|
||||
*/
|
||||
void jbhook1_avs_boot_init();
|
||||
|
||||
/**
|
||||
* Set the target eamuse server address.
|
||||
*
|
||||
* @param server_addr Address to target eamuse server.
|
||||
*/
|
||||
void jbhook1_avs_boot_set_eamuse_addr(const struct net_addr* server_addr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "jbhook1/config-eamuse.h"
|
||||
|
||||
#include "util/log.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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef JBHOOK1_CONFIG_EAMUSE_H
|
||||
#define JBHOOK1_CONFIG_EAMUSE_H
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
#include "security/id.h"
|
||||
|
||||
#include "util/net.h"
|
||||
|
||||
/**
|
||||
* Struct holding configuration values for eamuse related items.
|
||||
*/
|
||||
struct jbhook1_config_eamuse {
|
||||
struct net_addr server;
|
||||
struct security_id pcbid;
|
||||
struct security_id eamid;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "jbhook1/config-gfx.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define JBHOOK1_CONFIG_GFX_WINDOWED_KEY "gfx.windowed"
|
||||
|
||||
#define JBHOOK1_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
void jbhook1_config_gfx_get(struct jbhook1_config_gfx* config_gfx,
|
||||
struct cconfig* config)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef JBHOOK1_CONFIG_GFX_H
|
||||
#define JBHOOK1_CONFIG_GFX_H
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
/**
|
||||
* Struct holding configuration values for GFX related items.
|
||||
*/
|
||||
struct jbhook1_config_gfx {
|
||||
bool windowed;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "jbhook1/config-security.h"
|
||||
|
||||
#include "security/mcode.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/net.h"
|
||||
|
||||
#define JBHOOK1_CONFIG_SECURITY_MCODE_KEY "security.mcode"
|
||||
|
||||
#define JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE jbhook1_config_security_default_mcode
|
||||
|
||||
static const struct security_mcode jbhook1_config_security_default_mcode = {
|
||||
.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(&JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE);
|
||||
|
||||
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)
|
||||
{
|
||||
char* tmp_default;
|
||||
char mcode[9];
|
||||
|
||||
tmp_default =
|
||||
security_mcode_to_str(&JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE);
|
||||
|
||||
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,
|
||||
&JBHOOK1_CONFIG_SECURITY_DEFAULT_MCODE_VALUE,
|
||||
sizeof(struct security_mcode));
|
||||
}
|
||||
|
||||
free(tmp_default);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef JBHOOK1_CONFIG_SECURITY_H
|
||||
#define JBHOOK1_CONFIG_SECURITY_H
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
#include "security/mcode.h"
|
||||
|
||||
#include "util/net.h"
|
||||
|
||||
/**
|
||||
* Struct holding configuration values for security related items.
|
||||
*/
|
||||
struct jbhook1_config_security {
|
||||
struct security_mcode mcode;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bemanitools/eamio.h"
|
||||
#include "bemanitools/jbio.h"
|
||||
|
||||
#include "cconfig/cconfig-hook.h"
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/adapter.h"
|
||||
#include "hooklib/acp.h"
|
||||
#include "hooklib/rs232.h"
|
||||
|
||||
#include "jbhook1/avs-boot.h"
|
||||
#include "jbhook1/acio.h"
|
||||
#include "jbhook1/config-gfx.h"
|
||||
#include "jbhook1/config-eamuse.h"
|
||||
#include "jbhook1/config-security.h"
|
||||
#include "jbhook1/log-gftools.h"
|
||||
#include "jbhook1/p3io.h"
|
||||
|
||||
#include "p3ioemu/devmgr.h"
|
||||
#include "p3ioemu/emu.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/thread.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 const irp_handler_t jbhook1_handlers[] = {
|
||||
p3io_emu_dispatch_irp,
|
||||
ac_io_port_dispatch_irp,
|
||||
};
|
||||
|
||||
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 const struct hook_symbol init_hook_syms[] = {
|
||||
{
|
||||
.name = "mwindow_create",
|
||||
.patch = my_mwindow_create,
|
||||
.link = (void **) &real_mwindow_create,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 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(HINSTANCE hinstance, void* callback,
|
||||
const char* window_title, DWORD window_width, DWORD window_height,
|
||||
BOOL fullscreen)
|
||||
{
|
||||
struct cconfig* config;
|
||||
|
||||
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("-------------------------------------------------------------");
|
||||
|
||||
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;
|
||||
|
||||
log_info("Starting up jubeat IO backend");
|
||||
|
||||
jb_io_set_loggers(log_impl_misc, log_impl_info, log_impl_warning,
|
||||
log_impl_fatal);
|
||||
|
||||
if (!jb_io_init(thread_create, thread_join, thread_destroy)) {
|
||||
log_fatal("Initializing jb IO backend failed");
|
||||
}
|
||||
|
||||
log_info("Starting up card reader backend");
|
||||
|
||||
eam_io_set_loggers(log_impl_misc, log_impl_info, log_impl_warning,
|
||||
log_impl_fatal);
|
||||
|
||||
if (!eam_io_init(thread_create, thread_join, thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
}
|
||||
|
||||
iohook_init(jbhook1_handlers, lengthof(jbhook1_handlers));
|
||||
|
||||
rs232_hook_init();
|
||||
ac_io_port_init();
|
||||
|
||||
p3io_setupapi_insert_hooks(NULL);
|
||||
jbhook1_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(hinstance, callback, window_title, window_width,
|
||||
window_height, fullscreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook library for jubeat (1)
|
||||
*/
|
||||
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH) {
|
||||
#ifdef DEBUG_HOOKING
|
||||
FILE* file = fopen("jbhook.dllmain.log", "w+");
|
||||
log_to_writer(log_writer_file, file);
|
||||
#else
|
||||
log_to_writer(log_writer_null, NULL);
|
||||
#endif
|
||||
|
||||
/* Bootstrap hook for further init tasks (see above) */
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"mwindow.dll",
|
||||
init_hook_syms,
|
||||
lengthof(init_hook_syms));
|
||||
|
||||
|
||||
/* Actual hooks for game specific stuff */
|
||||
|
||||
acp_hook_init();
|
||||
adapter_hook_init();
|
||||
|
||||
#ifdef DEBUG_HOOKING
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
#endif
|
||||
|
||||
/* Logging to file and other destinations is handled by inject */
|
||||
log_to_writer(log_writer_debug, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
LIBRARY jbhook1
|
||||
|
||||
EXPORTS
|
||||
DllMain@12 @1 NONAME
|
||||
@@ -0,0 +1,43 @@
|
||||
#define LOG_MODULE "log-gftools"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
static int CDECL my_GFReportPuts(int level, const char* source_file, int a3,
|
||||
const char* func, const char* msg);
|
||||
|
||||
static int (CDECL *real_GFReportPuts)(int level, const char* source_file,
|
||||
int a3, const char* func, const char* msg);
|
||||
|
||||
static const struct hook_symbol jbhook1_log_gftools_hook_syms[] = {
|
||||
{
|
||||
.name = "GFReportPuts",
|
||||
.patch = my_GFReportPuts,
|
||||
.link = (void **) &real_GFReportPuts
|
||||
},
|
||||
};
|
||||
|
||||
static int CDECL my_GFReportPuts(int level, const char* source_file, int a3,
|
||||
const char* func, const char* msg)
|
||||
{
|
||||
log_misc("[%d][%s][%d][%s]: %s", level, source_file, a3, func, msg);
|
||||
|
||||
return real_GFReportPuts(level, source_file, a3, func, msg);
|
||||
}
|
||||
|
||||
void jbhook1_log_gftools_init(void)
|
||||
{
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"gftools.dll",
|
||||
jbhook1_log_gftools_hook_syms,
|
||||
lengthof(jbhook1_log_gftools_hook_syms));
|
||||
|
||||
log_info("Inserted gftools log hooks");
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef JBHOOK1_LOG_GFTOOLS_H
|
||||
#define JBHOOK1_LOG_GFTOOLS_H
|
||||
|
||||
/**
|
||||
* Initialize the gftools hook module. This hooks a function which is used
|
||||
* to report errors and redirects the output to our logger.
|
||||
*/
|
||||
void jbhook1_log_gftools_init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,163 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bemanitools/jbio.h"
|
||||
|
||||
#include "jbhook1/p3io.h"
|
||||
|
||||
#include "p3ioemu/emu.h"
|
||||
#include "p3ioemu/uart.h"
|
||||
|
||||
#include "security/rp3.h"
|
||||
#include "security/rp-sign-key.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
static HRESULT jbhook1_p3io_read_jamma(void *ctx, uint32_t *state);
|
||||
static HRESULT jbhook1_p3io_get_roundplug(void *ctx, uint8_t plug_id,
|
||||
uint8_t* rom, uint8_t* eeprom);
|
||||
|
||||
/*
|
||||
0:0 b13
|
||||
0:1 -
|
||||
0:2 b15
|
||||
0:3 -
|
||||
0:4 test
|
||||
0:5 coin
|
||||
0:6 service
|
||||
0:7 -
|
||||
|
||||
1:0 -
|
||||
1:1 b4
|
||||
1:2 b8
|
||||
1:3 b12
|
||||
1:4 b16
|
||||
1:5 b3
|
||||
1:6 b7
|
||||
1:7 b11
|
||||
|
||||
2:0 -
|
||||
2:1 b2
|
||||
2:2 b6
|
||||
2:3 b10
|
||||
2:4 b14
|
||||
2:5 b1
|
||||
2:6 b5
|
||||
2:7 b9
|
||||
|
||||
3:0 -
|
||||
3:1 -
|
||||
3:2 -
|
||||
3:3 -
|
||||
3:4 -
|
||||
3:5 -
|
||||
3:6 -
|
||||
3:7 -
|
||||
*/
|
||||
static const uint32_t jbhook1_p3io_panel_mappings[] = {
|
||||
(1 << 21),
|
||||
(1 << 17),
|
||||
(1 << 13),
|
||||
(1 << 9),
|
||||
(1 << 22),
|
||||
(1 << 18),
|
||||
(1 << 14),
|
||||
(1 << 10),
|
||||
(1 << 23),
|
||||
(1 << 19),
|
||||
(1 << 15),
|
||||
(1 << 11),
|
||||
(1 << 0),
|
||||
(1 << 20),
|
||||
(1 << 2),
|
||||
(1 << 12),
|
||||
};
|
||||
|
||||
static const uint32_t jbhook1_p3io_sys_button_mappings[] = {
|
||||
(1 << 4),
|
||||
(1 << 6),
|
||||
(1 << 5),
|
||||
};
|
||||
|
||||
static struct security_mcode jbhook1_p3io_mcode;
|
||||
static struct security_id jbhook1_p3io_pcbid;
|
||||
static struct security_id jbhook1_p3io_eamid;
|
||||
|
||||
static const struct p3io_ops p3io_ddr_ops = {
|
||||
.read_jamma = jbhook1_p3io_read_jamma,
|
||||
.get_roundplug = jbhook1_p3io_get_roundplug,
|
||||
};
|
||||
|
||||
void jbhook1_p3io_init(const struct security_mcode* mcode,
|
||||
const struct security_id* pcbid, const struct security_id* eamid)
|
||||
{
|
||||
memcpy(&jbhook1_p3io_mcode, mcode, sizeof(struct security_mcode));
|
||||
memcpy(&jbhook1_p3io_pcbid, pcbid, sizeof(struct security_id));
|
||||
memcpy(&jbhook1_p3io_eamid, eamid, sizeof(struct security_id));
|
||||
|
||||
p3io_emu_init(&p3io_ddr_ops, NULL);
|
||||
}
|
||||
|
||||
void jbhook1_p3io_finit(void)
|
||||
{
|
||||
p3io_emu_fini();
|
||||
}
|
||||
|
||||
static HRESULT jbhook1_p3io_read_jamma(void *ctx, uint32_t *state)
|
||||
{
|
||||
uint16_t panels;
|
||||
uint8_t buttons;
|
||||
|
||||
log_assert(state != NULL);
|
||||
|
||||
/* lower three bytes low active, highest byte high active */
|
||||
*state = 0;
|
||||
|
||||
if (!jb_io_read_inputs()) {
|
||||
log_warning("Reading inputs from jbio failed");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
panels = jb_io_get_panel_inputs();
|
||||
buttons = jb_io_get_sys_inputs();
|
||||
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (panels & (1 << i)) {
|
||||
*state |= jbhook1_p3io_panel_mappings[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
if (buttons & (1 << i)) {
|
||||
*state |= jbhook1_p3io_sys_button_mappings[i];
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT jbhook1_p3io_get_roundplug(void *ctx, uint8_t plug_id,
|
||||
uint8_t* rom, uint8_t* eeprom)
|
||||
{
|
||||
struct security_rp3_eeprom eeprom_out;
|
||||
|
||||
if (plug_id == 0) {
|
||||
/* black */
|
||||
memcpy(rom, jbhook1_p3io_pcbid.id, sizeof(jbhook1_p3io_pcbid.id));
|
||||
security_rp3_generate_signed_eeprom_data(
|
||||
SECURITY_RP_UTIL_RP_TYPE_BLACK, &security_rp_sign_key_black_gfdmv4,
|
||||
&jbhook1_p3io_mcode, &jbhook1_p3io_pcbid, &eeprom_out);
|
||||
} else {
|
||||
/* white */
|
||||
memcpy(rom, jbhook1_p3io_eamid.id, sizeof(jbhook1_p3io_eamid.id));
|
||||
security_rp3_generate_signed_eeprom_data(
|
||||
SECURITY_RP_UTIL_RP_TYPE_WHITE, &security_rp_sign_key_white_eamuse,
|
||||
&security_mcode_eamuse, &jbhook1_p3io_eamid, &eeprom_out);
|
||||
}
|
||||
|
||||
memcpy(eeprom, &eeprom_out, sizeof(struct security_rp3_eeprom));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef JBHOOK1_P3IO_H
|
||||
#define JBHOOK1_P3IO_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "security/id.h"
|
||||
#include "security/mcode.h"
|
||||
|
||||
/**
|
||||
* Initialize the jbhook1 specific p3io emulation backend.
|
||||
*
|
||||
* @param mcode Mcode of the target game to run. Required for dongle emulation.
|
||||
* @param pcbid PCBDID
|
||||
* @param eamid EAMID
|
||||
*/
|
||||
void jbhook1_p3io_init(const struct security_mcode* mcode,
|
||||
const struct security_id* pcbid, const struct security_id* eamid);
|
||||
|
||||
/**
|
||||
* Shutdown the p3io emulation backend.
|
||||
*/
|
||||
void jbhook1_p3io_fini(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user