1
0
mirror of https://gitea.tendokyu.moe/Dniel97/segatools.git synced 2024-11-27 22:40:48 +01:00

add half-working CXB support

This commit is contained in:
Kevin Trocolli 2022-12-11 17:01:51 -05:00
parent d565e50b8a
commit c7fe5189cf
25 changed files with 1082 additions and 0 deletions

View File

@ -19,6 +19,8 @@ COPY amex amex
COPY board board COPY board board
COPY chunihook chunihook COPY chunihook chunihook
COPY chuniio chuniio COPY chuniio chuniio
COPY cxbhook cxbhook
COPY cxbio cxbio
COPY dist dist COPY dist dist
COPY divahook divahook COPY divahook divahook
COPY divaio divaio COPY divaio divaio

View File

@ -13,6 +13,21 @@ $(BUILD_DIR_ZIP)/chuni.zip:
$(V)strip $(BUILD_DIR_ZIP)/chuni/*.{exe,dll} $(V)strip $(BUILD_DIR_ZIP)/chuni/*.{exe,dll}
$(V)cd $(BUILD_DIR_ZIP)/chuni ; zip -r ../chuni.zip * $(V)cd $(BUILD_DIR_ZIP)/chuni ; zip -r ../chuni.zip *
$(BUILD_DIR_ZIP)/cxb.zip:
$(V)echo ... $@
$(V)mkdir -p $(BUILD_DIR_ZIP)/cxb
$(V)mkdir -p $(BUILD_DIR_ZIP)/cxb/DEVICE
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
$(BUILD_DIR_32)/cxbhook/cxbhook.dll \
$(DIST_DIR)/cxb/segatools.ini \
$(DIST_DIR)/cxb/start.bat \
$(BUILD_DIR_ZIP)/cxb
$(V)cp pki/billing.pub \
pki/ca.crt \
$(BUILD_DIR_ZIP)/cxb/DEVICE
$(V)strip $(BUILD_DIR_ZIP)/cxb/*.{exe,dll}
$(V)cd $(BUILD_DIR_ZIP)/cxb ; zip -r ../cxb.zip *
$(BUILD_DIR_ZIP)/diva.zip: $(BUILD_DIR_ZIP)/diva.zip:
$(V)echo ... $@ $(V)echo ... $@
$(V)mkdir -p $(BUILD_DIR_ZIP)/diva $(V)mkdir -p $(BUILD_DIR_ZIP)/diva
@ -99,6 +114,7 @@ $(BUILD_DIR_ZIP)/doc.zip: \
$(BUILD_DIR_ZIP)/segatools.zip: \ $(BUILD_DIR_ZIP)/segatools.zip: \
$(BUILD_DIR_ZIP)/chuni.zip \ $(BUILD_DIR_ZIP)/chuni.zip \
$(BUILD_DIR_ZIP)/cxb.zip \
$(BUILD_DIR_ZIP)/carol.zip \ $(BUILD_DIR_ZIP)/carol.zip \
$(BUILD_DIR_ZIP)/diva.zip \ $(BUILD_DIR_ZIP)/diva.zip \
$(BUILD_DIR_ZIP)/doc.zip \ $(BUILD_DIR_ZIP)/doc.zip \

View File

@ -62,6 +62,7 @@ static void aime_io_config_read(
cfg->felica_path, cfg->felica_path,
_countof(cfg->felica_path), _countof(cfg->felica_path),
filename); filename);
dprintf("NFC: felicaPath GetLastError %lx\n", GetLastError());
cfg->felica_gen = GetPrivateProfileIntW( cfg->felica_gen = GetPrivateProfileIntW(
L"aime", L"aime",

61
cxbhook/config.c Normal file
View File

@ -0,0 +1,61 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include "amex/amex.h"
#include "amex/config.h"
#include "board/config.h"
#include "board/sg-reader.h"
#include "cxbhook/config.h"
#include "gfxhook/config.h"
#include "hooklib/config.h"
#include "platform/config.h"
#include "platform/platform.h"
void cxb_dll_config_load(
struct cxb_dll_config *cfg,
const wchar_t *filename)
{
}
void revio_config_load(struct revio_config *cfg, const wchar_t *filename)
{
}
void network_config_load(struct network_config *cfg, const wchar_t *filename)
{
}
void led_config_load(struct led_config *cfg, const wchar_t *filename)
{
}
void cxb_hook_config_load(
struct cxb_hook_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
memset(cfg, 0, sizeof(*cfg));
platform_config_load(&cfg->platform, filename);
amex_config_load(&cfg->amex, filename);
aime_config_load(&cfg->aime, filename);
gfx_config_load(&cfg->gfx, filename);
cxb_dll_config_load(&cfg->dll, filename);
revio_config_load(&cfg->revio, filename);
network_config_load(&cfg->network, filename);
led_config_load(&cfg->led, filename);
}

40
cxbhook/config.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include "amex/amex.h"
#include "board/sg-reader.h"
#include "cxbhook/cxb-dll.h"
#include "cxbhook/revio.h"
#include "cxbhook/led.h"
#include "cxbhook/network.h"
#include "gfxhook/gfx.h"
#include "platform/platform.h"
struct cxb_hook_config {
struct platform_config platform;
struct amex_config amex;
struct aime_config aime;
struct gfx_config gfx;
struct cxb_dll_config dll;
struct revio_config revio;
struct network_config network;
struct led_config led;
};
void cxb_dll_config_load(
struct cxb_dll_config *cfg,
const wchar_t *filename);
void revio_config_load(struct revio_config *cfg, const wchar_t *filename);
void network_config_load(struct network_config *cfg, const wchar_t *filename);
void led_config_load(struct led_config *cfg, const wchar_t *filename);
void cxb_hook_config_load(
struct cxb_hook_config *cfg,
const wchar_t *filename);

120
cxbhook/cxb-dll.c Normal file
View File

@ -0,0 +1,120 @@
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include "cxbhook/cxb-dll.h"
#include "util/dll-bind.h"
#include "util/dprintf.h"
const struct dll_bind_sym cxb_dll_syms[] = {
{
.sym = "cxb_io_revio_init",
.off = offsetof(struct cxb_dll, revio_init),
},
{
.sym = "cxb_io_revio_poll",
.off = offsetof(struct cxb_dll, revio_poll),
},
{
.sym = "cxb_io_revio_get_coins",
.off = offsetof(struct cxb_dll, revio_get_coins),
},
{
.sym = "cxb_io_revio_set_coins",
.off = offsetof(struct cxb_dll, revio_set_coins),
},
{
.sym = "cxb_io_led_init",
.off = offsetof(struct cxb_dll, led_init),
},
{
.sym = "cxb_io_led_update",
.off = offsetof(struct cxb_dll, led_update),
},
};
struct cxb_dll cxb_dll;
// Copypasta DLL binding and diagnostic message boilerplate.
// Not much of this lends itself to being easily factored out. Also there
// will be a lot of API-specific branching code here eventually as new API
// versions get defined, so even though these functions all look the same
// now this won't remain the case forever.
HRESULT cxb_dll_init(const struct cxb_dll_config *cfg, HINSTANCE self)
{
uint16_t (*get_api_version)(void);
const struct dll_bind_sym *sym;
HINSTANCE owned;
HINSTANCE src;
HRESULT hr;
assert(cfg != NULL);
assert(self != NULL);
if (cfg->path[0] != L'\0') {
owned = LoadLibraryW(cfg->path);
if (owned == NULL) {
hr = HRESULT_FROM_WIN32(GetLastError());
dprintf("Crossbeats IO: Failed to load IO DLL: %lx: %S\n",
hr,
cfg->path);
goto end;
}
dprintf("Crossbeats IO: Using custom IO DLL: %S\n", cfg->path);
src = owned;
} else {
owned = NULL;
src = self;
}
get_api_version = (void *) GetProcAddress(src, "cxb_io_get_api_version");
if (get_api_version != NULL) {
cxb_dll.api_version = get_api_version();
} else {
cxb_dll.api_version = 0x0100;
dprintf("Custom IO DLL does not expose cxb_io_get_api_version, "
"assuming API version 1.0.\n"
"Please ask the developer to update their DLL.\n");
}
if (cxb_dll.api_version >= 0x0200) {
hr = E_NOTIMPL;
dprintf("Crossbeats IO: Custom IO DLL implements an unsupported "
"API version (%#04x). Please update Segatools.\n",
cxb_dll.api_version);
goto end;
}
sym = cxb_dll_syms;
hr = dll_bind(&cxb_dll, src, &sym, _countof(cxb_dll_syms));
if (FAILED(hr)) {
if (src != self) {
dprintf("Crossbeats IO: Custom IO DLL does not provide function "
"\"%s\". Please contact your IO DLL's developer for "
"further assistance.\n",
sym->sym);
goto end;
} else {
dprintf("Internal error: could not reflect \"%s\"\n", sym->sym);
}
}
owned = NULL;
end:
if (owned != NULL) {
FreeLibrary(owned);
}
return hr;
}

24
cxbhook/cxb-dll.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include <windows.h>
#include <stdint.h>
#include "cxbio/cxbio.h"
struct cxb_dll {
uint16_t api_version;
HRESULT (*revio_init)(void);
void (*revio_poll)(uint16_t *opbtn);
void (*revio_get_coins)(long *coins);
void (*revio_set_coins)(int coins);
HRESULT (*led_init)(void);
void (*led_update)(int id, int color);
};
struct cxb_dll_config {
wchar_t path[MAX_PATH];
};
extern struct cxb_dll cxb_dll;
HRESULT cxb_dll_init(const struct cxb_dll_config *cfg, HINSTANCE self);

21
cxbhook/cxbhook.def Normal file
View File

@ -0,0 +1,21 @@
LIBRARY cxbhook
EXPORTS
Direct3DCreate9
aime_io_get_api_version
aime_io_init
aime_io_led_set_color
aime_io_nfc_get_aime_id
aime_io_nfc_get_felica_id
aime_io_nfc_poll
amDllVideoClose @2
amDllVideoGetVBiosVersion @4
amDllVideoOpen @1
amDllVideoSetResolution @3
cxb_io_get_api_version
cxb_io_revio_init
cxb_io_revio_poll
cxb_io_revio_get_coins
cxb_io_revio_set_coins
cxb_io_led_init
cxb_io_led_update

149
cxbhook/dllmain.c Normal file
View File

@ -0,0 +1,149 @@
#include <windows.h>
#include <stdlib.h>
#include "amex/amex.h"
#include "board/sg-reader.h"
#include "cxbhook/config.h"
#include "cxbhook/revio.h"
#include "cxbhook/led.h"
#include "cxbhook/network.h"
#include "cxbio/cxbio.h"
#include "gfxhook/gfx.h"
#include "gfxhook/d3d9.h"
#include "hook/process.h"
#include "hooklib/serial.h"
#include "hooklib/spike.h"
#include "platform/platform.h"
#include "util/dprintf.h"
static HMODULE cxb_hook_mod;
static process_entry_t cxb_startup;
static struct cxb_hook_config cxb_hook_cfg;
static DWORD CALLBACK cxb_pre_startup(void)
{
HMODULE d3dc;
HMODULE dbghelp;
HRESULT hr;
dprintf("--- Begin cxb_pre_startup ---\n");
/* Pin the D3D shader compiler. This makes startup much faster. */
d3dc = LoadLibraryW(L"D3DCompiler_43.dll");
if (d3dc != NULL) {
dprintf("Pinned shader compiler, hMod=%p\n", d3dc);
} else {
dprintf("Failed to load shader compiler!\n");
}
/* Pin dbghelp so the path hooks apply to it. */
dbghelp = LoadLibraryW(L"dbghelp.dll");
if (dbghelp != NULL) {
dprintf("Pinned debug helper library, hMod=%p\n", dbghelp);
} else {
dprintf("Failed to load debug helper library!\n");
}
/* Config load */
cxb_hook_config_load(&cxb_hook_cfg, L".\\segatools.ini");
/* Hook Win32 APIs */
gfx_hook_init(&cxb_hook_cfg.gfx);
gfx_d3d9_hook_init(&cxb_hook_cfg.gfx, cxb_hook_mod);
serial_hook_init();
/* Initialize emulation hooks */
hr = platform_hook_init(
&cxb_hook_cfg.platform,
"SDCA",
"AAV1",
cxb_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = cxb_dll_init(&cxb_hook_cfg.dll, cxb_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = amex_hook_init(&cxb_hook_cfg.amex, NULL);
if (FAILED(hr)) {
goto fail;
}
hr = sg_reader_hook_init(&cxb_hook_cfg.aime, 12, cxb_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = revio_hook_init(&cxb_hook_cfg.revio);
if (FAILED(hr)) {
goto fail;
}
hr = network_hook_init(&cxb_hook_cfg.network);
if (FAILED(hr)) {
goto fail;
}
hr = led_hook_init(&cxb_hook_cfg.led);
if (FAILED(hr)) {
goto fail;
}
/* Initialize debug helpers */
spike_hook_init(L".\\segatools.ini");
dprintf("--- End cxb_pre_startup ---\n");
/* Jump to EXE start address */
return cxb_startup();
fail:
ExitProcess(EXIT_FAILURE);
}
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
{
HRESULT hr;
if (cause != DLL_PROCESS_ATTACH) {
return TRUE;
}
cxb_hook_mod = mod;
hr = process_hijack_startup(cxb_pre_startup, &cxb_startup);
if (!SUCCEEDED(hr)) {
dprintf("Failed to hijack process startup: %x\n", (int) hr);
}
return SUCCEEDED(hr);
}

93
cxbhook/led.c Normal file
View File

@ -0,0 +1,93 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "cxbhook/led.h"
#include "cxbhook/cxb-dll.h"
#include "hooklib/procaddr.h"
#include "hook/table.h"
#include "util/dprintf.h"
static int my_cCommLamp_Open(char *port);
static void my_cCommLamp_Close();
static int my_cCommLamp_Setup(int led_id);
static int my_cCommLamp_SetColor(int led_id, int color);
static int my_cCommLamp_Update();
static int my_cCommLamp_UpdateDelta(float delta);
static struct hook_symbol lamp_syms[] = {
{
.name = "cCommLamp_Open",
.patch = my_cCommLamp_Open
},
{
.name = "cCommLamp_Close",
.patch = my_cCommLamp_Close
},
{
.name = "cCommLamp_Setup",
.patch = my_cCommLamp_Setup,
},
{
.name = "cCommLamp_SetColor",
.patch = my_cCommLamp_SetColor
},
{
.name = "cCommLamp_Update",
.patch = my_cCommLamp_Update
},
{
.name = "cCommLamp_UpdateDelta",
.patch = my_cCommLamp_UpdateDelta
},
};
HRESULT led_hook_init(struct led_config *cfg)
{
dprintf("LED: Init\n");
return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms));
}
static int my_cCommLamp_Open(char *port)
{
HRESULT hr = cxb_dll.led_init();
dprintf("LED: Open %s (DLL init result %lx)\n", port, hr);
if (FAILED(hr)) {
return 0;
}
return 1;
}
static void my_cCommLamp_Close()
{
dprintf("LED: Close\n");
}
static int my_cCommLamp_Setup(int led_id)
{
dprintf("LED: Setup %d\n", led_id);
return 0;
}
static int my_cCommLamp_SetColor(int led_id, int color)
{
cxb_dll.led_update(led_id, color);
return 1;
}
static int my_cCommLamp_Update()
{
return 0;
}
static int my_cCommLamp_UpdateDelta(float delta)
{
return 0;
}

11
cxbhook/led.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct led_config {
bool enable;
};
HRESULT led_hook_init(struct led_config *cfg);

36
cxbhook/meson.build Normal file
View File

@ -0,0 +1,36 @@
shared_library(
'cxbhook',
name_prefix : '',
include_directories : inc,
implicit_include_directories : false,
vs_module_defs : 'cxbhook.def',
c_pch : '../precompiled.h',
dependencies : [
capnhook.get_variable('hook_dep'),
capnhook.get_variable('hooklib_dep'),
],
link_with : [
aimeio_lib,
amex_lib,
board_lib,
cxbio_lib,
gfxhook_lib,
hooklib_lib,
jvs_lib,
platform_lib,
util_lib,
],
sources : [
'cxb-dll.c',
'cxb-dll.h',
'config.c',
'config.h',
'dllmain.c',
'revio.c',
'revio.h',
'led.c',
'led.h',
'network.c',
'network.h',
],
)

13
cxbhook/network.c Normal file
View File

@ -0,0 +1,13 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "cxbhook/network.h"
#include "util/dprintf.h"
HRESULT network_hook_init(struct network_config *cfg)
{
dprintf("Network: Init\n");
return S_OK;
}

13
cxbhook/network.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct network_config {
bool enable;
bool disable_ssl;
char title_server[PATH_MAX];
};
HRESULT network_hook_init(struct network_config *cfg);

226
cxbhook/revio.c Normal file
View File

@ -0,0 +1,226 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <winuser.h>
#include "cxbhook/revio.h"
#include "cxbhook/cxb-dll.h"
#include "hooklib/procaddr.h"
#include "hook/table.h"
#include "util/dprintf.h"
static int my_cCommIo_Open(char *port);
static int my_cCommIo_Close();
static long my_cCommIo_GetCoin();
static int my_cCommIo_SetCoin(int coin_ct);
static int my_cCommIo_GetStatus();
static int my_cCommIo_GetSwitch();
static int my_cCommIo_GetTrigger();
static int my_cCommIo_GetRelease();
static long my_cCommIo_GetVolume();
static int my_cCommIo_SetAmpVolume(int amp_id, long new_volume);
static int my_cCommIo_GetAmpVolume(int amp_id);
static int my_cCommIo_SetAmpMute(int amp_id, int a2);
int amp_volume[] = {20, 20, 20};
int last_triggers = 0;
int last_is_mouse_down = false;
static struct hook_symbol revio_syms[] = {
{
.name = "cCommIo_Open",
.patch = my_cCommIo_Open
},
{
.name = "cCommIo_Close",
.patch = my_cCommIo_Close
},
{
.name = "cCommIo_GetStatus",
.patch = my_cCommIo_GetStatus
},
{
.name = "cCommIo_GetCoin",
.patch = my_cCommIo_GetCoin
},
{
.name = "cCommIo_SetCoin",
.patch = my_cCommIo_SetCoin
},
{
.name = "cCommIo_GetSwitch",
.patch = my_cCommIo_GetSwitch
},
{
.name = "cCommIo_GetTrigger",
.patch = my_cCommIo_GetTrigger
},
{
.name = "cCommIo_GetRelease",
.patch = my_cCommIo_GetRelease
},
{
.name = "cCommIo_GetVolume",
.patch = my_cCommIo_GetVolume
},
{
.name = "cCommIo_SetAmpVolume",
.patch = my_cCommIo_SetAmpVolume
},
{
.name = "cCommIo_GetAmpVolume",
.patch = my_cCommIo_GetAmpVolume
},
{
.name = "cCommIo_SetAmpMute",
.patch = my_cCommIo_SetAmpMute
},
};
HRESULT revio_hook_init(struct revio_config *cfg)
{
dprintf("Revio: Init\n");
return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms));
}
static int my_cCommIo_Open(char *port)
{
dprintf("Revio: Open port %s\n", port);
cxb_dll.revio_init();
return 1;
}
static int my_cCommIo_Close()
{
dprintf("Revio: Close\n");
return 0;
}
static int my_cCommIo_GetStatus()
{
return 1;
}
static long my_cCommIo_GetCoin()
{
long coins;
cxb_dll.revio_get_coins(&coins);
return coins;
}
static int my_cCommIo_SetCoin(int coin_ct)
{
// does some weird shit, not sure
//dprintf("Revio: Set coin %d\n", coin_ct);
cxb_dll.revio_set_coins(coin_ct);
return 1;
}
static int my_cCommIo_GetSwitch()
{
return 0;
}
static int my_cCommIo_GetTrigger()
{
uint16_t btns = 0;
int out = 0;
cxb_dll.revio_poll(&btns);
if (btns & 0x01) {
out |= 1 << 4; // test
}
if (btns & 0x02) {
out |= 1 << 5; // service?
}
if (btns & 0x04) {
out |= 1 << 1; // up
}
if (btns & 0x08) {
out |= 1 << 3; // down
}
if (btns & 0x0F) {
out |= 1 << 2; // cancel
}
out &= ~last_triggers;
dprintf("Revio: GetTrigger %X\n", out);
last_triggers = out;
return out;
}
static int my_cCommIo_GetRelease()
{
uint16_t btns = 0;
int out = last_triggers;
cxb_dll.revio_poll(&btns);
if (btns & 0x01) {
out |= 1 << 4; // test
}
if (btns & 0x02) {
out |= 1 << 5; // service?
}
if (btns & 0x04) {
out |= 1 << 1; // up
}
if (btns & 0x08) {
out |= 1 << 3; // down
}
if (btns & 0x0F) {
out |= 1 << 2; // cancel
}
out &= ~btns;
dprintf("Revio: GetRelease %X\n", out);
last_triggers = btns;
return out;
}
static long my_cCommIo_GetVolume()
{
return 0;
}
static int my_cCommIo_SetAmpVolume(int amp_id, long new_volume)
{
dprintf("Revio: SetAmpVolume id %d -> vol %ld\n", amp_id, new_volume);
if (amp_id > _countof(amp_volume)) {
return 0;
}
amp_volume[amp_id] = new_volume;
return 0;
}
static int my_cCommIo_GetAmpVolume(int amp_id)
{
dprintf("Revio: GetAmpVolume id %d\n", amp_id);
if (amp_id > _countof(amp_volume)) {
return 0;
}
return amp_volume[amp_id];
}
static int my_cCommIo_SetAmpMute(int amp_id, int a2)
{
dprintf("Revio: GetAmpVolume id %d unknown %d\n", amp_id, a2);
return 0;
}

17
cxbhook/revio.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct revio_config {
bool enable;
uint8_t test;
uint8_t service;
uint8_t coin;
uint8_t up;
uint8_t down;
uint8_t cancel;
};
HRESULT revio_hook_init(struct revio_config *cfg);

22
cxbio/config.c Normal file
View File

@ -0,0 +1,22 @@
#include <windows.h>
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include "cxbio/config.h"
void cxb_io_config_load(
struct cxb_io_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->test = GetPrivateProfileIntW(L"revio", L"test", '1', filename);
cfg->service = GetPrivateProfileIntW(L"revio", L"service", '2', filename);
cfg->coin = GetPrivateProfileIntW(L"revio", L"coin", '3', filename);
cfg->cancel = GetPrivateProfileIntW(L"revio", L"cancel", '4', filename);
cfg->up = GetPrivateProfileIntW(L"revio", L"up", VK_UP, filename);
cfg->down = GetPrivateProfileIntW(L"revio", L"down", VK_DOWN, filename);
}

17
cxbio/config.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct cxb_io_config {
uint8_t test;
uint8_t service;
uint8_t coin;
uint8_t cancel;
uint8_t up;
uint8_t down;
};
void cxb_io_config_load(
struct cxb_io_config *cfg,
const wchar_t *filename);

78
cxbio/cxbio.c Normal file
View File

@ -0,0 +1,78 @@
#include <windows.h>
#include <process.h>
#include <stdbool.h>
#include <stdint.h>
#include "cxbio/cxbio.h"
#include "cxbio/config.h"
#include "util/dprintf.h"
static bool cxb_io_coin;
static int cxb_io_coins;
static struct cxb_io_config cxb_io_cfg;
uint16_t cxb_io_get_api_version(void)
{
return 0x0100;
}
HRESULT cxb_io_revio_init(void)
{
dprintf("CXB IO: REVIO init\n");
cxb_io_config_load(&cxb_io_cfg, L".\\segatools.ini");
return S_OK;
}
void cxb_io_revio_poll(uint16_t *opbtn)
{
if (GetAsyncKeyState(cxb_io_cfg.test)) {
*opbtn |= 0x01; /* Test */
}
if (GetAsyncKeyState(cxb_io_cfg.service)) {
*opbtn |= 0x02; /* Service */
}
if (GetAsyncKeyState(cxb_io_cfg.cancel)) {
*opbtn |= 0x04; /* Cancel */
}
if (GetAsyncKeyState(cxb_io_cfg.up)) {
*opbtn |= 0x08; /* Up */
}
if (GetAsyncKeyState(cxb_io_cfg.down)) {
*opbtn |= 0x10; /* Down */
}
}
void cxb_io_revio_get_coins(long *coins)
{
if (GetAsyncKeyState(cxb_io_cfg.coin)) {
if (!cxb_io_coin) {
cxb_io_coin = true;
cxb_io_coins++;
}
} else {
cxb_io_coin = false;
}
*coins = cxb_io_coins;
}
void cxb_io_revio_set_coins(int coins)
{
cxb_io_coins = coins;
}
HRESULT cxb_io_led_init(void)
{
dprintf("CXB IO: LED init\n");
return S_OK;
}
void cxb_io_led_update(int id, int color)
{}

19
cxbio/cxbio.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
uint16_t cxb_io_get_api_version(void);
HRESULT cxb_io_revio_init(void);
void cxb_io_revio_poll(uint16_t *opbtn);
void cxb_io_revio_get_coins(long *coins);
void cxb_io_revio_set_coins(int coins);
HRESULT cxb_io_led_init(void);
void cxb_io_led_update(int id, int color);

13
cxbio/meson.build Normal file
View File

@ -0,0 +1,13 @@
cxbio_lib = static_library(
'cxbio',
name_prefix : '',
include_directories : inc,
implicit_include_directories : false,
c_pch : '../precompiled.h',
sources : [
'cxbio.c',
'cxbio.h',
'config.c',
'config.h',
],
)

4
dist/cxb/resource/segatools.ini vendored Normal file
View File

@ -0,0 +1,4 @@
[aime]
; CXB is stupid, so we have to make the paths go back one
aimePath=../DEVICE/aime.txt
felicaPath=../DEVICE/felica.txt

75
dist/cxb/segatools.ini vendored Normal file
View File

@ -0,0 +1,75 @@
[vfs]
; Make sure theses are full paths and not relative or you will have a bad time
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs=
; Insert the path to the game Option directory here (contains Axxx directories)
option=
; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %APPDATA%.
appdata=
[dns]
; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected.
default=127.0.0.1
[netenv]
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
; Crossbeats is extremely picky about its LAN environment, so leaving this
; setting enabled is strongly recommended.
enable=1
[keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168.
subnet=192.168.100.0
billingCa=../DEVICE/ca.crt
billingPub=../DEVICE/billing.pub
billingType=2
[gfx]
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.
framed=1
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
monitor=0
[aime]
; Aime reader emulation
; CXB is stupid, so we have to make the paths go back one
enable=1
aimePath=../DEVICE/aime.txt
felicaPath=../DEVICE/felica.txt
[eeprom]
; See above
path=../DEVICE/eeprom.bin
[sram]
; See above
path=../DEVICE/sram.bin
[led]
; Emulation for the LED board. Currently it's just dummy responses,
; but if somebody wants to make their keyboard or whatever light
; up with the game they can
enable=1
[revio]
; Enable emulation of the rev IO board
enabe=1
; Test button virtual-key code. Default is the 1 key.
test=0x31
; Service button virtual-key code. Default is the 2 key.
service=0x32
; Keyboard button to increment coin counter. Default is the 3 key.
coin=0x33
; Menu up key. Default is up arrow.
up=0x26
; Menu down key. Default is down arrow.
down=0x28
; Menu cancel key. Default is the 4 key.
cancel=0x34

9
dist/cxb/start.bat vendored Normal file
View File

@ -0,0 +1,9 @@
@echo off
pushd %~dp0
inject -d -k cxbhook.dll Rev_v11.exe
echo.
echo Game processes have terminated
pause

View File

@ -59,6 +59,7 @@ subdir('carolio')
subdir('idzio') subdir('idzio')
subdir('mu3io') subdir('mu3io')
subdir('mercuryio') subdir('mercuryio')
subdir('cxbio')
subdir('chunihook') subdir('chunihook')
subdir('divahook') subdir('divahook')
@ -67,3 +68,4 @@ subdir('idzhook')
subdir('minihook') subdir('minihook')
subdir('mu3hook') subdir('mu3hook')
subdir('mercuryhook') subdir('mercuryhook')
subdir('cxbhook')