mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-09-14 11:25:09 -05:00
adds example libaio ios
This commit is contained in:
@@ -160,6 +160,7 @@ include src/main/iidxio-async/Module.mk
|
||||
include src/main/iidxio-bio2/Module.mk
|
||||
include src/main/iidxio-ezusb/Module.mk
|
||||
include src/main/iidxio-ezusb2/Module.mk
|
||||
include src/main/iidxio-lightning/Module.mk
|
||||
include src/main/iidxio/Module.mk
|
||||
include src/main/iidxiotest/Module.mk
|
||||
include src/main/imgui/Module.mk
|
||||
@@ -195,6 +196,8 @@ include src/main/sdvxhook2-cn/Module.mk
|
||||
include src/main/sdvxhook2/Module.mk
|
||||
include src/main/sdvxio-bio2/Module.mk
|
||||
include src/main/sdvxio-kfca/Module.mk
|
||||
include src/main/sdvxio-tbs/Module.mk
|
||||
include src/main/sdvxio-valk/Module.mk
|
||||
include src/main/sdvxio/Module.mk
|
||||
include src/main/security/Module.mk
|
||||
include src/main/unicorntail/Module.mk
|
||||
@@ -490,6 +493,7 @@ $(zipdir)/iidx-hwio-x64.zip: \
|
||||
build/bin/indep-64/iidxio-bio2.dll \
|
||||
build/bin/indep-64/iidxio-ezusb.dll \
|
||||
build/bin/indep-64/iidxio-ezusb2.dll \
|
||||
build/bin/indep-64/iidxio-lightning.dll \
|
||||
dist/iidx/iidxio-bio2.conf \
|
||||
build/bin/indep-64/vigem-iidxio.exe \
|
||||
dist/iidx/vigem-iidxio.conf \
|
||||
@@ -644,6 +648,8 @@ $(zipdir)/sdvx-hwio-x64.zip: \
|
||||
build/bin/indep-64/eamio-icca.dll \
|
||||
build/bin/indep-64/sdvxio-kfca.dll \
|
||||
build/bin/indep-64/sdvxio-bio2.dll \
|
||||
build/bin/indep-64/sdvxio-tbs.dll \
|
||||
build/bin/indep-64/sdvxio-valk.dll \
|
||||
build/bin/indep-64/vigem-sdvxio.exe \
|
||||
| $(zipdir)/
|
||||
$(V)echo ... $@
|
||||
|
||||
12
src/main/iidxio-lightning/Module.mk
Normal file
12
src/main/iidxio-lightning/Module.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
dlls += iidxio-lightning
|
||||
|
||||
ldflags_iidxio-lightning := \
|
||||
-lsetupapi \
|
||||
|
||||
libs_iidxio-lightning := \
|
||||
cconfig \
|
||||
util \
|
||||
|
||||
src_iidxio-lightning := \
|
||||
iidxio.c \
|
||||
load_aio.c \
|
||||
48
src/main/iidxio-lightning/aio.h
Normal file
48
src/main/iidxio-lightning/aio.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct AIO_NODE;
|
||||
struct AIO_NMGR;
|
||||
struct AIO_SCI;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct AIO_IOB2_BI2X_TDJ__DEVSTATUS {
|
||||
uint8_t unk1[4];
|
||||
uint8_t b_test;
|
||||
uint8_t b_service;
|
||||
uint8_t b_coinmech;
|
||||
uint8_t unk2;
|
||||
uint8_t b_start[2];
|
||||
uint8_t b_vefx;
|
||||
uint8_t b_effect;
|
||||
uint8_t b_headphone[2];
|
||||
|
||||
uint8_t unk3[6]; // 0x10-0x13
|
||||
uint8_t a_turntable[2];
|
||||
uint8_t unk4;
|
||||
uint8_t unk6[4];
|
||||
uint8_t b_p1[7];
|
||||
uint8_t b_p2[7];
|
||||
uint8_t unk7[7];
|
||||
|
||||
uint8_t unk8[0x9A]; // 0x30-0xC9
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
_Static_assert(
|
||||
sizeof(struct AIO_IOB2_BI2X_TDJ__DEVSTATUS) == 202,
|
||||
"bi2x_device_status is the wrong size");
|
||||
|
||||
typedef void (*t_aioNodeCtl_UpdateDevicesStatus)(void);
|
||||
typedef unsigned int (*t_aioNodeCtl_Destroy)(struct AIO_NODE *node);
|
||||
typedef unsigned int (*t_aioNodeMgr_Destroy)(struct AIO_NMGR *mgr);
|
||||
typedef unsigned int (*t_aioSci_Destroy)(struct AIO_SCI *sci);
|
||||
|
||||
typedef struct AIO_SCI* (*t_aioIob2Bi2x_OpenSciUsbCdc)(uint8_t unk);
|
||||
typedef struct AIO_NMGR* (*t_aioNMgrIob2_Create)(struct AIO_SCI *port, unsigned int delay);
|
||||
|
||||
typedef struct AIO_NODE* (*t_aioIob2Bi2xTDJ_Create)(struct AIO_NMGR *node_mgr, uint8_t param);
|
||||
typedef void (*t_aioIob2Bi2xTDJ_IoReset)(struct AIO_NODE *AIO_IOB2_BI2X_TDJ_this, int value);
|
||||
typedef void (*t_AIO_IOB2_BI2X_TDJ__GetDeviceStatus)(struct AIO_NODE *AIO_IOB2_BI2X_TDJ_this, struct AIO_IOB2_BI2X_TDJ__DEVSTATUS *status);
|
||||
typedef void (*t_AIO_IOB2_BI2X_TDJ__SetTurnTableResist)(struct AIO_NODE *AIO_IOB2_BI2X_TDJ_this, int side, uint8_t resist);
|
||||
18
src/main/iidxio-lightning/iidxio-lightning.def
Normal file
18
src/main/iidxio-lightning/iidxio-lightning.def
Normal file
@@ -0,0 +1,18 @@
|
||||
LIBRARY iidxio
|
||||
|
||||
EXPORTS
|
||||
iidx_io_ep1_send
|
||||
iidx_io_ep1_set_deck_lights
|
||||
iidx_io_ep1_set_panel_lights
|
||||
iidx_io_ep1_set_top_lamps
|
||||
iidx_io_ep1_set_top_neons
|
||||
iidx_io_ep2_get_keys
|
||||
iidx_io_ep2_get_panel
|
||||
iidx_io_ep2_get_sys
|
||||
iidx_io_ep2_get_slider
|
||||
iidx_io_ep2_get_turntable
|
||||
iidx_io_ep2_recv
|
||||
iidx_io_ep3_write_16seg
|
||||
iidx_io_fini
|
||||
iidx_io_init
|
||||
iidx_io_set_loggers
|
||||
205
src/main/iidxio-lightning/iidxio.c
Normal file
205
src/main/iidxio-lightning/iidxio.c
Normal file
@@ -0,0 +1,205 @@
|
||||
#include <windows.h>
|
||||
|
||||
#define LOG_MODULE "iidxio-lightning"
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bemanitools/glue.h"
|
||||
#include "bemanitools/iidxio.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#include "load_aio.h"
|
||||
|
||||
static atomic_bool running;
|
||||
static atomic_bool processing_io;
|
||||
|
||||
static struct AIO_IOB2_BI2X_TDJ__DEVSTATUS pin_cur;
|
||||
|
||||
static struct bi2x_ctx *bi2x_ctx;
|
||||
|
||||
|
||||
static bool _bio2_iidx_io_poll(struct AIO_IOB2_BI2X_TDJ__DEVSTATUS *pin)
|
||||
{
|
||||
if (!running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
processing_io = true;
|
||||
|
||||
poll_bi2x(bi2x_ctx, pin);
|
||||
|
||||
processing_io = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void iidx_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal)
|
||||
{
|
||||
log_to_external(misc, info, warning, fatal);
|
||||
}
|
||||
|
||||
bool iidx_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy)
|
||||
{
|
||||
init_aio_handles();
|
||||
|
||||
bi2x_ctx = setup_bi2x();
|
||||
if (!bi2x_ctx) {
|
||||
log_warning("Unable to start BI2X?");
|
||||
return false;
|
||||
}
|
||||
running = true;
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
void iidx_io_fini(void)
|
||||
{
|
||||
running = false;
|
||||
|
||||
while (processing_io) {
|
||||
// avoid banging
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
close_bi2x(bi2x_ctx);
|
||||
|
||||
bi2x_ctx = NULL;
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_deck_lights(uint16_t deck_lights)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_panel_lights(uint8_t panel_lights)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_top_lamps(uint8_t top_lamps)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_top_neons(bool top_neons)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool iidx_io_ep1_send(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iidx_io_ep2_recv(void)
|
||||
{
|
||||
if (!_bio2_iidx_io_poll(&pin_cur)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_turntable(uint8_t player_no)
|
||||
{
|
||||
switch (player_no) {
|
||||
case 0:
|
||||
return pin_cur.a_turntable[0];
|
||||
case 1:
|
||||
return pin_cur.a_turntable[1];
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_slider(uint8_t slider_no)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_sys(void)
|
||||
{
|
||||
uint8_t state;
|
||||
|
||||
state = 0;
|
||||
|
||||
if (pin_cur.b_test) {
|
||||
state |= (1 << IIDX_IO_SYS_TEST);
|
||||
}
|
||||
|
||||
if (pin_cur.b_service) {
|
||||
state |= (1 << IIDX_IO_SYS_SERVICE);
|
||||
}
|
||||
|
||||
if (pin_cur.b_coinmech) {
|
||||
state |= (1 << IIDX_IO_SYS_COIN);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_panel(void)
|
||||
{
|
||||
uint8_t state;
|
||||
|
||||
state = 0;
|
||||
|
||||
if (pin_cur.b_start[0]) {
|
||||
state |= (1 << IIDX_IO_PANEL_P1_START);
|
||||
}
|
||||
|
||||
if (pin_cur.b_start[1]) {
|
||||
state |= (1 << IIDX_IO_PANEL_P2_START);
|
||||
}
|
||||
|
||||
if (pin_cur.b_vefx) {
|
||||
state |= (1 << IIDX_IO_PANEL_VEFX);
|
||||
}
|
||||
|
||||
if (pin_cur.b_effect) {
|
||||
state |= (1 << IIDX_IO_PANEL_EFFECT);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
uint16_t iidx_io_ep2_get_keys(void)
|
||||
{
|
||||
uint16_t state;
|
||||
|
||||
state = 0;
|
||||
|
||||
state |= ((pin_cur.b_p1[0] > 0) << IIDX_IO_KEY_P1_1);
|
||||
state |= ((pin_cur.b_p1[1] > 0) << IIDX_IO_KEY_P1_2);
|
||||
state |= ((pin_cur.b_p1[2] > 0) << IIDX_IO_KEY_P1_3);
|
||||
state |= ((pin_cur.b_p1[3] > 0) << IIDX_IO_KEY_P1_4);
|
||||
state |= ((pin_cur.b_p1[4] > 0) << IIDX_IO_KEY_P1_5);
|
||||
state |= ((pin_cur.b_p1[5] > 0) << IIDX_IO_KEY_P1_6);
|
||||
state |= ((pin_cur.b_p1[6] > 0) << IIDX_IO_KEY_P1_7);
|
||||
|
||||
state |= ((pin_cur.b_p2[0] > 0) << IIDX_IO_KEY_P2_1);
|
||||
state |= ((pin_cur.b_p2[1] > 0) << IIDX_IO_KEY_P2_2);
|
||||
state |= ((pin_cur.b_p2[2] > 0) << IIDX_IO_KEY_P2_3);
|
||||
state |= ((pin_cur.b_p2[3] > 0) << IIDX_IO_KEY_P2_4);
|
||||
state |= ((pin_cur.b_p2[4] > 0) << IIDX_IO_KEY_P2_5);
|
||||
state |= ((pin_cur.b_p2[5] > 0) << IIDX_IO_KEY_P2_6);
|
||||
state |= ((pin_cur.b_p2[6] > 0) << IIDX_IO_KEY_P2_7);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool iidx_io_ep3_write_16seg(const char *text)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
161
src/main/iidxio-lightning/load_aio.c
Normal file
161
src/main/iidxio-lightning/load_aio.c
Normal file
@@ -0,0 +1,161 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LOG_MODULE "load_aio"
|
||||
#include "util/log.h"
|
||||
|
||||
#include "load_aio.h"
|
||||
|
||||
#define DECLARE_MODULE_FUNCTION(NAME) t_ ## NAME NAME
|
||||
|
||||
struct aio_module {
|
||||
// "libaio.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioNodeCtl_UpdateDevicesStatus);
|
||||
DECLARE_MODULE_FUNCTION(aioNodeCtl_Destroy);
|
||||
DECLARE_MODULE_FUNCTION(aioNodeMgr_Destroy);
|
||||
DECLARE_MODULE_FUNCTION(aioSci_Destroy);
|
||||
// "libaio-iob.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2x_OpenSciUsbCdc);
|
||||
DECLARE_MODULE_FUNCTION(aioNMgrIob2_Create);
|
||||
// "libaio-iob2_video.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xTDJ_Create);
|
||||
// technically the game uses the C++ one, but this one doesn't incur a penalty unlike the C version of AIO_IOB2_BI2X_TDJ__GetDeviceStatus
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xTDJ_IoReset);
|
||||
DECLARE_MODULE_FUNCTION(AIO_IOB2_BI2X_TDJ__GetDeviceStatus);
|
||||
DECLARE_MODULE_FUNCTION(AIO_IOB2_BI2X_TDJ__SetTurnTableResist);
|
||||
};
|
||||
|
||||
void warn_module(const char *function_name) {
|
||||
log_warning("Could not load %s!", function_name);
|
||||
}
|
||||
|
||||
#define LOAD_MODULE_FUNCTION(TARGET, HANDLE, NAME) do {TARGET.NAME = (t_ ## NAME)GetProcAddress(HANDLE, #NAME); if (TARGET.NAME == NULL) {warn_module(#NAME); return;}} while(0)
|
||||
#define LOAD_MODULE_FUNCTION_EX(TARGET, HANDLE, NAME, REAL_NAME) do {TARGET.NAME = (t_ ## NAME)GetProcAddress(HANDLE, REAL_NAME); if (TARGET.NAME == NULL) {warn_module(#NAME); return;}} while(0)
|
||||
|
||||
static struct aio_module module_handles;
|
||||
|
||||
void init_aio_handles(void) {
|
||||
HMODULE h_aio = LoadLibrary("libaio.dll");
|
||||
HMODULE h_aio_iob = LoadLibrary("libaio-iob.dll");
|
||||
HMODULE h_aio_iob2_video = LoadLibrary("libaio-iob2_video.dll");
|
||||
|
||||
if (!h_aio) {
|
||||
log_warning("Could not load libaio.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!h_aio_iob) {
|
||||
log_warning("Could not load libaio-iob.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!h_aio_iob2_video) {
|
||||
log_warning("Could not load libaio-iob2_video.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
// "libaio.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeCtl_UpdateDevicesStatus);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeCtl_Destroy);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeMgr_Destroy);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioSci_Destroy);
|
||||
|
||||
// "libaio-iob.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob, aioIob2Bi2x_OpenSciUsbCdc);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob, aioNMgrIob2_Create);
|
||||
|
||||
|
||||
// "libaio-iob2_video.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xTDJ_Create);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xTDJ_IoReset);
|
||||
LOAD_MODULE_FUNCTION_EX(module_handles, h_aio_iob2_video, AIO_IOB2_BI2X_TDJ__GetDeviceStatus, "?GetDeviceStatus@AIO_IOB2_BI2X_TDJ@@QEBAXAEAUDEVSTATUS@1@@Z");
|
||||
LOAD_MODULE_FUNCTION_EX(module_handles, h_aio_iob2_video, AIO_IOB2_BI2X_TDJ__SetTurnTableResist, "?SetTurnTableResist@AIO_IOB2_BI2X_TDJ@@QEAAXIE@Z");
|
||||
|
||||
log_misc("Done loading all libaio functions required.");
|
||||
}
|
||||
|
||||
struct AIO_NMGR_VTABLE {
|
||||
void *_dtor;
|
||||
void *AddNodeCtl;
|
||||
void *RemoveNodeCtl;
|
||||
void *PacketCreate;
|
||||
void *PacketSend;
|
||||
void *QueryPktRecvTimeout;
|
||||
void *PacketRecv;
|
||||
void *_GetCommStatus;
|
||||
void *_Reconnect;
|
||||
void *_unk;
|
||||
void (*BeginManage)(struct AIO_NMGR *);
|
||||
};
|
||||
|
||||
struct AIO_NMGR {
|
||||
struct AIO_NMGR_VTABLE *vtbl;
|
||||
uint8_t data[0x9F0];
|
||||
};
|
||||
|
||||
struct bi2x_ctx {
|
||||
struct AIO_SCI *sci_usb;
|
||||
struct AIO_NMGR *iob2_mgr;
|
||||
struct AIO_NODE *iob_bi2x_node;
|
||||
};
|
||||
|
||||
struct bi2x_ctx *setup_bi2x(void) {
|
||||
struct bi2x_ctx *ctx = malloc(sizeof(struct bi2x_ctx));
|
||||
|
||||
ctx->sci_usb = module_handles.aioIob2Bi2x_OpenSciUsbCdc(0);
|
||||
if (!ctx->sci_usb) {
|
||||
log_warning("Unable to aioIob2Bi2x_OpenSciUsbCdc");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob2_mgr = module_handles.aioNMgrIob2_Create(ctx->sci_usb, 0);
|
||||
if (!ctx->iob2_mgr) {
|
||||
log_warning("Unable to aioNMgrIob2_Create");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob_bi2x_node = module_handles.aioIob2Bi2xTDJ_Create(ctx->iob2_mgr, 1u);
|
||||
if (!ctx->iob_bi2x_node) {
|
||||
log_warning("Unable to aioIob2Bi2xTDJ_Create?");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob2_mgr->vtbl->BeginManage(ctx->iob2_mgr);
|
||||
log_misc("BeginManage iob2_mgr");
|
||||
|
||||
// never actually called
|
||||
// module_handles.aioIob2Bi2xTDJ_IoReset(ctx->iob_bi2x_node, 0x11);
|
||||
|
||||
// TODO: set these
|
||||
// module_handles.AIO_IOB2_BI2X_TDJ__SetTurnTableResist(ctx->iob_bi2x_node, 0, 127);
|
||||
// module_handles.AIO_IOB2_BI2X_TDJ__SetTurnTableResist(ctx->iob_bi2x_node, 1, 127);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void close_bi2x(struct bi2x_ctx *ctx) {
|
||||
if (ctx->iob_bi2x_node) {
|
||||
module_handles.aioNodeCtl_Destroy(ctx->iob_bi2x_node);
|
||||
}
|
||||
|
||||
if (ctx->iob2_mgr) {
|
||||
module_handles.aioNodeMgr_Destroy(ctx->iob2_mgr);
|
||||
}
|
||||
|
||||
if (ctx->sci_usb) {
|
||||
module_handles.aioSci_Destroy(ctx->sci_usb);
|
||||
}
|
||||
}
|
||||
|
||||
void poll_bi2x(struct bi2x_ctx *ctx, struct AIO_IOB2_BI2X_TDJ__DEVSTATUS *status) {
|
||||
module_handles.aioNodeCtl_UpdateDevicesStatus();
|
||||
|
||||
// technically we should do some checking here
|
||||
|
||||
module_handles.AIO_IOB2_BI2X_TDJ__GetDeviceStatus(ctx->iob_bi2x_node, status);
|
||||
}
|
||||
13
src/main/iidxio-lightning/load_aio.h
Normal file
13
src/main/iidxio-lightning/load_aio.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "aio.h"
|
||||
|
||||
void init_aio_handles(void);
|
||||
|
||||
struct bi2x_ctx;
|
||||
|
||||
struct bi2x_ctx *setup_bi2x(void);
|
||||
|
||||
void close_bi2x(struct bi2x_ctx *ctx);
|
||||
|
||||
void poll_bi2x(struct bi2x_ctx *ctx, struct AIO_IOB2_BI2X_TDJ__DEVSTATUS *status);
|
||||
12
src/main/sdvxio-tbs/Module.mk
Normal file
12
src/main/sdvxio-tbs/Module.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
dlls += sdvxio-tbs
|
||||
|
||||
ldflags_sdvxio-tbs := \
|
||||
-lsetupapi \
|
||||
|
||||
libs_sdvxio-tbs := \
|
||||
cconfig \
|
||||
util \
|
||||
|
||||
src_sdvxio-tbs := \
|
||||
sdvxio.c \
|
||||
load_aio.c \
|
||||
72
src/main/sdvxio-tbs/aio.h
Normal file
72
src/main/sdvxio-tbs/aio.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct AIO_NODE;
|
||||
struct AIO_NMGR;
|
||||
struct AIO_SCI;
|
||||
|
||||
struct INPUT
|
||||
{
|
||||
char DevIoCounter;
|
||||
char bExIoAErr;
|
||||
char bExIoBErr;
|
||||
char bPcPowerOn;
|
||||
char bPcPowerCheck;
|
||||
char CoinCount;
|
||||
char bTest;
|
||||
char bService;
|
||||
char bCoinSw;
|
||||
char bCoinJam;
|
||||
char bHPDetect;
|
||||
uint16_t StickX;
|
||||
uint16_t StickY;
|
||||
char bStickBtn;
|
||||
char bTrigger1;
|
||||
char bTrigger2;
|
||||
char bButton0;
|
||||
char bButton1;
|
||||
char bButton2;
|
||||
char bButton3;
|
||||
};
|
||||
|
||||
struct INPUTDATA
|
||||
{
|
||||
char Data[10];
|
||||
};
|
||||
|
||||
struct OUTPUTDATA
|
||||
{
|
||||
char Data[8];
|
||||
};
|
||||
|
||||
struct IORESETDATA
|
||||
{
|
||||
char Data[4];
|
||||
};
|
||||
|
||||
struct AIO_IOB2_BI2X_TBS__DEVSTATUS {
|
||||
char InputCounter;
|
||||
char OutputCounter;
|
||||
char TapeLedCounter;
|
||||
struct INPUT Input;
|
||||
struct INPUTDATA InputData;
|
||||
struct OUTPUTDATA OutputData;
|
||||
struct IORESETDATA IoResetData;
|
||||
};
|
||||
|
||||
_Static_assert(
|
||||
sizeof(struct AIO_IOB2_BI2X_TBS__DEVSTATUS) == 50,
|
||||
"bi2x_device_status is the wrong size");
|
||||
|
||||
typedef void (*t_aioNodeCtl_UpdateDevicesStatus)(void);
|
||||
typedef unsigned int (*t_aioNodeCtl_Destroy)(struct AIO_NODE *node);
|
||||
typedef unsigned int (*t_aioNodeMgr_Destroy)(struct AIO_NMGR *mgr);
|
||||
typedef unsigned int (*t_aioSci_Destroy)(struct AIO_SCI *sci);
|
||||
|
||||
typedef struct AIO_SCI* (*t_aioIob2Bi2x_OpenSciUsbCdc)(uint8_t unk);
|
||||
typedef struct AIO_NMGR* (*t_aioNMgrIob2_Create)(struct AIO_SCI *port, unsigned int delay);
|
||||
|
||||
typedef struct AIO_NODE* (*t_aioIob2Bi2xTBS_Create)(struct AIO_NMGR *node_mgr, uint8_t param);
|
||||
typedef void (*t_aioIob2Bi2xTBS_IoReset)(struct AIO_NODE *i_pNodeCtl, int value);
|
||||
typedef void (*t_aioIob2Bi2xTBS_GetDeviceStatus)(struct AIO_NODE *i_pNodeCtl, struct AIO_IOB2_BI2X_TBS__DEVSTATUS *status, int size);
|
||||
156
src/main/sdvxio-tbs/load_aio.c
Normal file
156
src/main/sdvxio-tbs/load_aio.c
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LOG_MODULE "load_aio"
|
||||
#include "util/log.h"
|
||||
|
||||
#include "load_aio.h"
|
||||
|
||||
#define DECLARE_MODULE_FUNCTION(NAME) t_ ## NAME NAME
|
||||
|
||||
struct aio_module {
|
||||
// "libaio.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioNodeCtl_UpdateDevicesStatus);
|
||||
DECLARE_MODULE_FUNCTION(aioNodeCtl_Destroy);
|
||||
DECLARE_MODULE_FUNCTION(aioNodeMgr_Destroy);
|
||||
DECLARE_MODULE_FUNCTION(aioSci_Destroy);
|
||||
// "libaio-iob.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2x_OpenSciUsbCdc);
|
||||
DECLARE_MODULE_FUNCTION(aioNMgrIob2_Create);
|
||||
// "libaio-iob2_video.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xTBS_Create);
|
||||
// technically the game uses the C++ one, but this one doesn't incur a penalty unlike the C version of aioIob2Bi2xTBS_GetDeviceStatus
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xTBS_IoReset);
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xTBS_GetDeviceStatus);
|
||||
};
|
||||
|
||||
void warn_module(const char *function_name) {
|
||||
log_warning("Could not load %s!", function_name);
|
||||
}
|
||||
|
||||
#define LOAD_MODULE_FUNCTION(TARGET, HANDLE, NAME) do {TARGET.NAME = (t_ ## NAME)GetProcAddress(HANDLE, #NAME); if (TARGET.NAME == NULL) {warn_module(#NAME); return;}} while(0)
|
||||
#define LOAD_MODULE_FUNCTION_EX(TARGET, HANDLE, NAME, REAL_NAME) do {TARGET.NAME = (t_ ## NAME)GetProcAddress(HANDLE, REAL_NAME); if (TARGET.NAME == NULL) {warn_module(#NAME); return;}} while(0)
|
||||
|
||||
static struct aio_module module_handles;
|
||||
|
||||
void init_aio_handles(void) {
|
||||
HMODULE h_aio = LoadLibrary("libaio.dll");
|
||||
HMODULE h_aio_iob = LoadLibrary("libaio-iob.dll");
|
||||
HMODULE h_aio_iob2_video = LoadLibrary("libaio-iob2_video.dll");
|
||||
|
||||
if (!h_aio) {
|
||||
log_warning("Could not load libaio.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!h_aio_iob) {
|
||||
log_warning("Could not load libaio-iob.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!h_aio_iob2_video) {
|
||||
log_warning("Could not load libaio-iob2_video.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
// "libaio.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeCtl_UpdateDevicesStatus);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeCtl_Destroy);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeMgr_Destroy);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioSci_Destroy);
|
||||
|
||||
// "libaio-iob.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob, aioIob2Bi2x_OpenSciUsbCdc);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob, aioNMgrIob2_Create);
|
||||
|
||||
|
||||
// "libaio-iob2_video.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xTBS_Create);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xTBS_IoReset);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xTBS_GetDeviceStatus);
|
||||
// LOAD_MODULE_FUNCTION_EX(module_handles, h_aio_iob2_video, aioIob2Bi2xTBS_GetDeviceStatus, "?GetDeviceStatus@AIO_IOB2_BI2X_TDJ@@QEBAXAEAUDEVSTATUS@1@@Z");
|
||||
|
||||
log_misc("Done loading all libaio functions required.");
|
||||
}
|
||||
|
||||
struct AIO_NMGR_VTABLE {
|
||||
void *_dtor;
|
||||
void *AddNodeCtl;
|
||||
void *RemoveNodeCtl;
|
||||
void *PacketCreate;
|
||||
void *PacketSend;
|
||||
void *QueryPktRecvTimeout;
|
||||
void *PacketRecv;
|
||||
void *_GetCommStatus;
|
||||
void *_Reconnect;
|
||||
void *_unk;
|
||||
void (*BeginManage)(struct AIO_NMGR *);
|
||||
};
|
||||
|
||||
struct AIO_NMGR {
|
||||
struct AIO_NMGR_VTABLE *vtbl;
|
||||
uint8_t data[0x9F0];
|
||||
};
|
||||
|
||||
struct bi2x_ctx {
|
||||
struct AIO_SCI *sci_usb;
|
||||
struct AIO_NMGR *iob2_mgr;
|
||||
struct AIO_NODE *iob_bi2x_node;
|
||||
};
|
||||
|
||||
struct bi2x_ctx *setup_bi2x(void) {
|
||||
struct bi2x_ctx *ctx = malloc(sizeof(struct bi2x_ctx));
|
||||
|
||||
ctx->sci_usb = module_handles.aioIob2Bi2x_OpenSciUsbCdc(0);
|
||||
if (!ctx->sci_usb) {
|
||||
log_warning("Unable to aioIob2Bi2x_OpenSciUsbCdc");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob2_mgr = module_handles.aioNMgrIob2_Create(ctx->sci_usb, 0);
|
||||
if (!ctx->iob2_mgr) {
|
||||
log_warning("Unable to aioNMgrIob2_Create");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob_bi2x_node = module_handles.aioIob2Bi2xTBS_Create(ctx->iob2_mgr, 1u);
|
||||
if (!ctx->iob_bi2x_node) {
|
||||
log_warning("Unable to aioIob2Bi2xTBS_Create?");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob2_mgr->vtbl->BeginManage(ctx->iob2_mgr);
|
||||
log_misc("BeginManage iob2_mgr");
|
||||
|
||||
// never actually called
|
||||
// module_handles.aioIob2Bi2xTBS_IoReset(ctx->iob_bi2x_node, 0x11);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void close_bi2x(struct bi2x_ctx *ctx) {
|
||||
if (ctx->iob_bi2x_node) {
|
||||
module_handles.aioNodeCtl_Destroy(ctx->iob_bi2x_node);
|
||||
}
|
||||
|
||||
if (ctx->iob2_mgr) {
|
||||
module_handles.aioNodeMgr_Destroy(ctx->iob2_mgr);
|
||||
}
|
||||
|
||||
if (ctx->sci_usb) {
|
||||
module_handles.aioSci_Destroy(ctx->sci_usb);
|
||||
}
|
||||
}
|
||||
|
||||
void poll_bi2x(struct bi2x_ctx *ctx, struct AIO_IOB2_BI2X_TBS__DEVSTATUS *status) {
|
||||
module_handles.aioNodeCtl_UpdateDevicesStatus();
|
||||
|
||||
// technically we should do some checking here
|
||||
|
||||
module_handles.aioIob2Bi2xTBS_GetDeviceStatus(ctx->iob_bi2x_node, status, sizeof(struct AIO_IOB2_BI2X_TBS__DEVSTATUS));
|
||||
}
|
||||
13
src/main/sdvxio-tbs/load_aio.h
Normal file
13
src/main/sdvxio-tbs/load_aio.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "aio.h"
|
||||
|
||||
void init_aio_handles(void);
|
||||
|
||||
struct bi2x_ctx;
|
||||
|
||||
struct bi2x_ctx *setup_bi2x(void);
|
||||
|
||||
void close_bi2x(struct bi2x_ctx *ctx);
|
||||
|
||||
void poll_bi2x(struct bi2x_ctx *ctx, struct AIO_IOB2_BI2X_TBS__DEVSTATUS *status);
|
||||
14
src/main/sdvxio-tbs/sdvxio-tbs.def
Normal file
14
src/main/sdvxio-tbs/sdvxio-tbs.def
Normal file
@@ -0,0 +1,14 @@
|
||||
LIBRARY sdvxio
|
||||
|
||||
EXPORTS
|
||||
sdvx_io_fini
|
||||
sdvx_io_get_input_gpio
|
||||
sdvx_io_get_input_gpio_sys
|
||||
sdvx_io_get_spinner_pos
|
||||
sdvx_io_init
|
||||
sdvx_io_read_input
|
||||
sdvx_io_set_gpio_lights
|
||||
sdvx_io_set_loggers
|
||||
sdvx_io_set_pwm_light
|
||||
sdvx_io_write_output
|
||||
sdvx_io_set_amp_volume
|
||||
173
src/main/sdvxio-tbs/sdvxio.c
Normal file
173
src/main/sdvxio-tbs/sdvxio.c
Normal file
@@ -0,0 +1,173 @@
|
||||
#include <windows.h>
|
||||
|
||||
#define LOG_MODULE "iidxio-lightning"
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bemanitools/glue.h"
|
||||
#include "bemanitools/sdvxio.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#include "load_aio.h"
|
||||
|
||||
static atomic_bool running;
|
||||
static atomic_bool processing_io;
|
||||
|
||||
static struct AIO_IOB2_BI2X_TBS__DEVSTATUS pin_cur;
|
||||
|
||||
static struct bi2x_ctx *bi2x_ctx;
|
||||
|
||||
|
||||
static bool _bio2_iidx_io_poll(struct AIO_IOB2_BI2X_TBS__DEVSTATUS *pin)
|
||||
{
|
||||
if (!running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
processing_io = true;
|
||||
|
||||
poll_bi2x(bi2x_ctx, pin);
|
||||
|
||||
processing_io = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void sdvx_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal)
|
||||
{
|
||||
log_to_external(misc, info, warning, fatal);
|
||||
}
|
||||
|
||||
bool sdvx_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy)
|
||||
{
|
||||
init_aio_handles();
|
||||
|
||||
bi2x_ctx = setup_bi2x();
|
||||
if (!bi2x_ctx) {
|
||||
log_warning("Unable to start BI2X?");
|
||||
return false;
|
||||
}
|
||||
running = true;
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
void sdvx_io_fini(void)
|
||||
{
|
||||
running = false;
|
||||
|
||||
while (processing_io) {
|
||||
// avoid banging
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
close_bi2x(bi2x_ctx);
|
||||
|
||||
bi2x_ctx = NULL;
|
||||
}
|
||||
|
||||
void sdvx_io_set_gpio_lights(uint32_t gpio_lights)
|
||||
{
|
||||
// wow ignore
|
||||
return;
|
||||
}
|
||||
|
||||
void sdvx_io_set_pwm_light(uint8_t light_no, uint8_t intensity)
|
||||
{
|
||||
// wow ignore
|
||||
return;
|
||||
}
|
||||
|
||||
bool sdvx_io_write_output(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sdvx_io_read_input(void)
|
||||
{
|
||||
if (!_bio2_iidx_io_poll(&pin_cur)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no)
|
||||
{
|
||||
// spinner_no
|
||||
int32_t raw_value = 0;
|
||||
if (spinner_no == 0) {
|
||||
raw_value = pin_cur.Input.StickX;
|
||||
}
|
||||
if (spinner_no == 1) {
|
||||
raw_value = pin_cur.Input.StickY;
|
||||
}
|
||||
int32_t value = raw_value - 32767;
|
||||
|
||||
float converted = value / 32767.0f;
|
||||
|
||||
converted *= 2.0;
|
||||
|
||||
if (converted > 1.0f) {
|
||||
converted = 1.0f;
|
||||
} else if (converted < -1.0f) {
|
||||
converted = -1.0f;
|
||||
}
|
||||
|
||||
int32_t final = - 32767 * converted;
|
||||
|
||||
return (uint16_t)final/64;
|
||||
}
|
||||
|
||||
static uint8_t shift_pin(uint16_t value, uint8_t pin)
|
||||
{
|
||||
if (value) {
|
||||
return (1 << pin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t sdvx_io_get_input_gpio_sys(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank)
|
||||
{
|
||||
if (gpio_bank > 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t data = 0;
|
||||
|
||||
if (gpio_bank == 0) {
|
||||
data |= shift_pin(pin_cur.Input.bStickBtn, SDVX_IO_IN_GPIO_0_START);
|
||||
data |= shift_pin(pin_cur.Input.bButton0, SDVX_IO_IN_GPIO_0_A);
|
||||
data |= shift_pin(pin_cur.Input.bButton1, SDVX_IO_IN_GPIO_0_B);
|
||||
data |= shift_pin(pin_cur.Input.bButton2, SDVX_IO_IN_GPIO_0_C);
|
||||
} else if (gpio_bank == 1) {
|
||||
data |= shift_pin(pin_cur.Input.bButton3, SDVX_IO_IN_GPIO_1_D);
|
||||
data |= shift_pin(pin_cur.Input.bTrigger1, SDVX_IO_IN_GPIO_1_FX_L);
|
||||
data |= shift_pin(pin_cur.Input.bTrigger2, SDVX_IO_IN_GPIO_1_FX_R);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool sdvx_io_set_amp_volume(
|
||||
uint8_t primary, uint8_t headphone, uint8_t subwoofer)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
12
src/main/sdvxio-valk/Module.mk
Normal file
12
src/main/sdvxio-valk/Module.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
dlls += sdvxio-valk
|
||||
|
||||
ldflags_sdvxio-valk := \
|
||||
-lsetupapi \
|
||||
|
||||
libs_sdvxio-valk := \
|
||||
cconfig \
|
||||
util \
|
||||
|
||||
src_sdvxio-valk := \
|
||||
sdvxio.c \
|
||||
load_aio.c \
|
||||
27
src/main/sdvxio-valk/aio.h
Normal file
27
src/main/sdvxio-valk/aio.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct AIO_NODE;
|
||||
struct AIO_NMGR;
|
||||
struct AIO_SCI;
|
||||
|
||||
struct AIO_IOB2_BI2X_UFC__DEVSTATUS {
|
||||
char buffer[414];
|
||||
};
|
||||
|
||||
_Static_assert(
|
||||
sizeof(struct AIO_IOB2_BI2X_UFC__DEVSTATUS) == 414,
|
||||
"bi2x_device_status is the wrong size");
|
||||
|
||||
typedef void (*t_aioNodeCtl_UpdateDevicesStatus)(void);
|
||||
typedef unsigned int (*t_aioNodeCtl_Destroy)(struct AIO_NODE *node);
|
||||
typedef unsigned int (*t_aioNodeMgr_Destroy)(struct AIO_NMGR *mgr);
|
||||
typedef unsigned int (*t_aioSci_Destroy)(struct AIO_SCI *sci);
|
||||
|
||||
typedef struct AIO_SCI* (*t_aioIob2Bi2x_OpenSciUsbCdc)(uint8_t unk);
|
||||
typedef struct AIO_NMGR* (*t_aioNMgrIob2_Create)(struct AIO_SCI *port, unsigned int delay);
|
||||
|
||||
typedef struct AIO_NODE* (*t_aioIob2Bi2xUFC_Create)(struct AIO_NMGR *node_mgr, uint8_t param);
|
||||
typedef void (*t_aioIob2Bi2xUFC_IoReset)(struct AIO_NODE *i_pNodeCtl, int value);
|
||||
typedef void (*t_aioIob2Bi2xUFC_GetDeviceStatus)(struct AIO_NODE *i_pNodeCtl, struct AIO_IOB2_BI2X_UFC__DEVSTATUS *status, int size);
|
||||
155
src/main/sdvxio-valk/load_aio.c
Normal file
155
src/main/sdvxio-valk/load_aio.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LOG_MODULE "load_aio"
|
||||
#include "util/log.h"
|
||||
|
||||
#include "load_aio.h"
|
||||
|
||||
#define DECLARE_MODULE_FUNCTION(NAME) t_ ## NAME NAME
|
||||
|
||||
struct aio_module {
|
||||
// "libaio.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioNodeCtl_UpdateDevicesStatus);
|
||||
DECLARE_MODULE_FUNCTION(aioNodeCtl_Destroy);
|
||||
DECLARE_MODULE_FUNCTION(aioNodeMgr_Destroy);
|
||||
DECLARE_MODULE_FUNCTION(aioSci_Destroy);
|
||||
// "libaio-iob.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2x_OpenSciUsbCdc);
|
||||
DECLARE_MODULE_FUNCTION(aioNMgrIob2_Create);
|
||||
// "libaio-iob2_video.dll"
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xUFC_Create);
|
||||
// technically the game uses the C++ one, but this one doesn't incur an extra function call unlike the C version
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xUFC_IoReset);
|
||||
DECLARE_MODULE_FUNCTION(aioIob2Bi2xUFC_GetDeviceStatus);
|
||||
};
|
||||
|
||||
void warn_module(const char *function_name) {
|
||||
log_warning("Could not load %s!", function_name);
|
||||
}
|
||||
|
||||
#define LOAD_MODULE_FUNCTION(TARGET, HANDLE, NAME) do {TARGET.NAME = (t_ ## NAME)GetProcAddress(HANDLE, #NAME); if (TARGET.NAME == NULL) {warn_module(#NAME); return;}} while(0)
|
||||
#define LOAD_MODULE_FUNCTION_EX(TARGET, HANDLE, NAME, REAL_NAME) do {TARGET.NAME = (t_ ## NAME)GetProcAddress(HANDLE, REAL_NAME); if (TARGET.NAME == NULL) {warn_module(#NAME); return;}} while(0)
|
||||
|
||||
static struct aio_module module_handles;
|
||||
|
||||
void init_aio_handles(void) {
|
||||
HMODULE h_aio = LoadLibrary("libaio.dll");
|
||||
HMODULE h_aio_iob = LoadLibrary("libaio-iob.dll");
|
||||
HMODULE h_aio_iob2_video = LoadLibrary("libaio-iob2_video.dll");
|
||||
|
||||
if (!h_aio) {
|
||||
log_warning("Could not load libaio.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!h_aio_iob) {
|
||||
log_warning("Could not load libaio-iob.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!h_aio_iob2_video) {
|
||||
log_warning("Could not load libaio-iob2_video.dll!");
|
||||
return;
|
||||
}
|
||||
|
||||
// "libaio.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeCtl_UpdateDevicesStatus);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeCtl_Destroy);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioNodeMgr_Destroy);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio, aioSci_Destroy);
|
||||
|
||||
// "libaio-iob.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob, aioIob2Bi2x_OpenSciUsbCdc);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob, aioNMgrIob2_Create);
|
||||
|
||||
|
||||
// "libaio-iob2_video.dll"
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xUFC_Create);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xUFC_IoReset);
|
||||
LOAD_MODULE_FUNCTION(module_handles, h_aio_iob2_video, aioIob2Bi2xUFC_GetDeviceStatus);
|
||||
|
||||
log_misc("Done loading all libaio functions required.");
|
||||
}
|
||||
|
||||
struct AIO_NMGR_VTABLE {
|
||||
void *_dtor;
|
||||
void *AddNodeCtl;
|
||||
void *RemoveNodeCtl;
|
||||
void *PacketCreate;
|
||||
void *PacketSend;
|
||||
void *QueryPktRecvTimeout;
|
||||
void *PacketRecv;
|
||||
void *_GetCommStatus;
|
||||
void *_Reconnect;
|
||||
void *_unk;
|
||||
void (*BeginManage)(struct AIO_NMGR *);
|
||||
};
|
||||
|
||||
struct AIO_NMGR {
|
||||
struct AIO_NMGR_VTABLE *vtbl;
|
||||
uint8_t data[0x9F0];
|
||||
};
|
||||
|
||||
struct bi2x_ctx {
|
||||
struct AIO_SCI *sci_usb;
|
||||
struct AIO_NMGR *iob2_mgr;
|
||||
struct AIO_NODE *iob_bi2x_node;
|
||||
};
|
||||
|
||||
struct bi2x_ctx *setup_bi2x(void) {
|
||||
struct bi2x_ctx *ctx = malloc(sizeof(struct bi2x_ctx));
|
||||
|
||||
ctx->sci_usb = module_handles.aioIob2Bi2x_OpenSciUsbCdc(0);
|
||||
if (!ctx->sci_usb) {
|
||||
log_warning("Unable to aioIob2Bi2x_OpenSciUsbCdc");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob2_mgr = module_handles.aioNMgrIob2_Create(ctx->sci_usb, 0);
|
||||
if (!ctx->iob2_mgr) {
|
||||
log_warning("Unable to aioNMgrIob2_Create");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob_bi2x_node = module_handles.aioIob2Bi2xUFC_Create(ctx->iob2_mgr, 1u);
|
||||
if (!ctx->iob_bi2x_node) {
|
||||
log_warning("Unable to aioIob2Bi2xUFC_Create?");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->iob2_mgr->vtbl->BeginManage(ctx->iob2_mgr);
|
||||
log_misc("BeginManage iob2_mgr");
|
||||
|
||||
// never actually called
|
||||
// module_handles.aioIob2Bi2xUFC_IoReset(ctx->iob_bi2x_node, 0x11);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void close_bi2x(struct bi2x_ctx *ctx) {
|
||||
if (ctx->iob_bi2x_node) {
|
||||
module_handles.aioNodeCtl_Destroy(ctx->iob_bi2x_node);
|
||||
}
|
||||
|
||||
if (ctx->iob2_mgr) {
|
||||
module_handles.aioNodeMgr_Destroy(ctx->iob2_mgr);
|
||||
}
|
||||
|
||||
if (ctx->sci_usb) {
|
||||
module_handles.aioSci_Destroy(ctx->sci_usb);
|
||||
}
|
||||
}
|
||||
|
||||
void poll_bi2x(struct bi2x_ctx *ctx, struct AIO_IOB2_BI2X_UFC__DEVSTATUS *status) {
|
||||
module_handles.aioNodeCtl_UpdateDevicesStatus();
|
||||
|
||||
// technically we should do some checking here
|
||||
|
||||
module_handles.aioIob2Bi2xUFC_GetDeviceStatus(ctx->iob_bi2x_node, status, sizeof(struct AIO_IOB2_BI2X_UFC__DEVSTATUS));
|
||||
}
|
||||
13
src/main/sdvxio-valk/load_aio.h
Normal file
13
src/main/sdvxio-valk/load_aio.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "aio.h"
|
||||
|
||||
void init_aio_handles(void);
|
||||
|
||||
struct bi2x_ctx;
|
||||
|
||||
struct bi2x_ctx *setup_bi2x(void);
|
||||
|
||||
void close_bi2x(struct bi2x_ctx *ctx);
|
||||
|
||||
void poll_bi2x(struct bi2x_ctx *ctx, struct AIO_IOB2_BI2X_TBS__DEVSTATUS *status);
|
||||
14
src/main/sdvxio-valk/sdvxio-valk.def
Normal file
14
src/main/sdvxio-valk/sdvxio-valk.def
Normal file
@@ -0,0 +1,14 @@
|
||||
LIBRARY sdvxio-valk
|
||||
|
||||
EXPORTS
|
||||
sdvx_io_fini
|
||||
sdvx_io_get_input_gpio
|
||||
sdvx_io_get_input_gpio_sys
|
||||
sdvx_io_get_spinner_pos
|
||||
sdvx_io_init
|
||||
sdvx_io_read_input
|
||||
sdvx_io_set_gpio_lights
|
||||
sdvx_io_set_loggers
|
||||
sdvx_io_set_pwm_light
|
||||
sdvx_io_write_output
|
||||
sdvx_io_set_amp_volume
|
||||
137
src/main/sdvxio-valk/sdvxio.c
Normal file
137
src/main/sdvxio-valk/sdvxio.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <windows.h>
|
||||
|
||||
#define LOG_MODULE "iidxio-lightning"
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bemanitools/glue.h"
|
||||
#include "bemanitools/sdvxio.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#include "load_aio.h"
|
||||
|
||||
static atomic_bool running;
|
||||
static atomic_bool processing_io;
|
||||
|
||||
static struct AIO_IOB2_BI2X_UFC__DEVSTATUS pin_cur;
|
||||
|
||||
static struct bi2x_ctx *bi2x_ctx;
|
||||
|
||||
|
||||
static bool _bio2_iidx_io_poll(struct AIO_IOB2_BI2X_UFC__DEVSTATUS *pin)
|
||||
{
|
||||
if (!running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
processing_io = true;
|
||||
|
||||
poll_bi2x(bi2x_ctx, pin);
|
||||
|
||||
processing_io = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void sdvx_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal)
|
||||
{
|
||||
log_to_external(misc, info, warning, fatal);
|
||||
}
|
||||
|
||||
bool sdvx_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy)
|
||||
{
|
||||
init_aio_handles();
|
||||
|
||||
bi2x_ctx = setup_bi2x();
|
||||
if (!bi2x_ctx) {
|
||||
log_warning("Unable to start BI2X?");
|
||||
return false;
|
||||
}
|
||||
running = true;
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
void sdvx_io_fini(void)
|
||||
{
|
||||
running = false;
|
||||
|
||||
while (processing_io) {
|
||||
// avoid banging
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
close_bi2x(bi2x_ctx);
|
||||
|
||||
bi2x_ctx = NULL;
|
||||
}
|
||||
|
||||
void sdvx_io_set_gpio_lights(uint32_t gpio_lights)
|
||||
{
|
||||
// wow ignore
|
||||
return;
|
||||
}
|
||||
|
||||
void sdvx_io_set_pwm_light(uint8_t light_no, uint8_t intensity)
|
||||
{
|
||||
// wow ignore
|
||||
return;
|
||||
}
|
||||
|
||||
bool sdvx_io_write_output(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sdvx_io_read_input(void)
|
||||
{
|
||||
if (!_bio2_iidx_io_poll(&pin_cur)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no)
|
||||
{
|
||||
// todo: implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t shift_pin(uint16_t value, uint8_t pin)
|
||||
{
|
||||
if (value) {
|
||||
return (1 << pin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t sdvx_io_get_input_gpio_sys(void)
|
||||
{
|
||||
// todo: implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank)
|
||||
{
|
||||
// todo: implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool sdvx_io_set_amp_volume(
|
||||
uint8_t primary, uint8_t headphone, uint8_t subwoofer)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user