From 62cd6df8f658bd465b7b4c732085eabe0725a6f6 Mon Sep 17 00:00:00 2001 From: din Date: Fri, 5 Sep 2025 19:07:17 -0500 Subject: [PATCH] wip ddrio-p4io --- Module.mk | 3 + src/main/ddrio-p4io/Module.mk | 17 +++ src/main/ddrio-p4io/config.c | 55 +++++++++ src/main/ddrio-p4io/config.h | 18 +++ src/main/ddrio-p4io/ddrio-p4io.def | 11 ++ src/main/ddrio-p4io/ddrio.c | 179 +++++++++++++++++++++++++++++ 6 files changed, 283 insertions(+) create mode 100644 src/main/ddrio-p4io/Module.mk create mode 100644 src/main/ddrio-p4io/config.c create mode 100644 src/main/ddrio-p4io/config.h create mode 100644 src/main/ddrio-p4io/ddrio-p4io.def create mode 100644 src/main/ddrio-p4io/ddrio.c diff --git a/Module.mk b/Module.mk index 99892a0..f87bc31 100644 --- a/Module.mk +++ b/Module.mk @@ -109,6 +109,7 @@ include src/main/ddrhook1/Module.mk include src/main/ddrhook2/Module.mk include src/main/ddrio-async/Module.mk include src/main/ddrio-p3io/Module.mk +include src/main/ddrio-p4io/Module.mk include src/main/ddrio-mm/Module.mk include src/main/ddrio-smx/Module.mk include src/main/ddriotest/Module.mk @@ -760,6 +761,7 @@ $(zipdir)/ddr-16-to-18-x64.zip: \ $(zipdir)/ddr-hwio-x86.zip: \ build/bin/indep-32/ddrio-async.dll \ build/bin/indep-32/ddrio-p3io.dll \ + build/bin/indep-32/ddrio-p4io.dll \ build/bin/indep-32/ddrio-mm.dll \ build/bin/indep-32/ddrio-smx.dll \ build/bin/indep-32/extiotest.exe \ @@ -772,6 +774,7 @@ $(zipdir)/ddr-hwio-x86.zip: \ $(zipdir)/ddr-hwio-x64.zip: \ build/bin/indep-64/ddrio-async.dll \ build/bin/indep-64/ddrio-p3io.dll \ + build/bin/indep-64/ddrio-p4io.dll \ build/bin/indep-64/ddrio-mm.dll \ build/bin/indep-64/ddrio-smx.dll \ build/bin/indep-64/extiotest.exe \ diff --git a/src/main/ddrio-p4io/Module.mk b/src/main/ddrio-p4io/Module.mk new file mode 100644 index 0000000..00c142a --- /dev/null +++ b/src/main/ddrio-p4io/Module.mk @@ -0,0 +1,17 @@ +dlls += ddrio-p4io + +deplibs_ddrio-p4io := \ + +ldflags_ddrio-p4io := \ + -lsetupapi \ + +libs_ddrio-p4io := \ + p4iodrv \ + aciodrv \ + cconfig \ + util \ + +src_ddrio-p4io := \ + ddrio.c \ + config.c \ + diff --git a/src/main/ddrio-p4io/config.c b/src/main/ddrio-p4io/config.c new file mode 100644 index 0000000..a5b7743 --- /dev/null +++ b/src/main/ddrio-p4io/config.c @@ -0,0 +1,55 @@ +#include "cconfig/cconfig-util.h" + +#include "config.h" + +#include "util/log.h" + +#define DDRIO_CONFIG_P4IO_MDXF_PORT_KEY "mdxf.port" +#define DDRIO_CONFIG_P4IO_MDXF_BAUD_KEY "mdxf.baud" + +#define DDRIO_CONFIG_P4IO_MDXF_DEFAULT_PORT_VALUE "COM2" +#define DDRIO_CONFIG_P4IO_MDXF_DEFAULT_BAUD_VALUE 115200 + +void ddrio_config_p4io_mdxf_init(struct cconfig *config) +{ + cconfig_util_set_str( + config, + DDRIO_CONFIG_P4IO_MDXF_PORT_KEY, + DDRIO_CONFIG_P4IO_MDXF_DEFAULT_PORT_VALUE, + "P4IO_MDXF serial port"); + + cconfig_util_set_int( + config, + DDRIO_CONFIG_P4IO_MDXF_BAUD_KEY, + DDRIO_CONFIG_P4IO_MDXF_DEFAULT_BAUD_VALUE, + "P4IO_MDXF bus baudrate (115200 is high speed, but will respond at 57600)"); +} + +void ddrio_config_p4io_mdxf_get( + struct p4io_mdxf_config *config_p4io_mdxf, struct cconfig *config) +{ + if (!cconfig_util_get_str( + config, + DDRIO_CONFIG_P4IO_MDXF_PORT_KEY, + config_p4io_mdxf->port, + sizeof(config_p4io_mdxf->port) - 1, + DDRIO_CONFIG_P4IO_MDXF_DEFAULT_PORT_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%s'", + DDRIO_CONFIG_P4IO_MDXF_PORT_KEY, + DDRIO_CONFIG_P4IO_MDXF_DEFAULT_PORT_VALUE); + } + + if (!cconfig_util_get_int( + config, + DDRIO_CONFIG_P4IO_MDXF_BAUD_KEY, + &config_p4io_mdxf->baud, + DDRIO_CONFIG_P4IO_MDXF_DEFAULT_BAUD_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%d'", + DDRIO_CONFIG_P4IO_MDXF_BAUD_KEY, + DDRIO_CONFIG_P4IO_MDXF_DEFAULT_BAUD_VALUE); + } +} diff --git a/src/main/ddrio-p4io/config.h b/src/main/ddrio-p4io/config.h new file mode 100644 index 0000000..e152d99 --- /dev/null +++ b/src/main/ddrio-p4io/config.h @@ -0,0 +1,18 @@ +#ifndef DDRIO_CONFIG_P4IO_MDXF_M +#define DDRIO_CONFIG_P4IO_MDXF_M + +#include + +#include "cconfig/cconfig.h" + +struct p4io_mdxf_config { + char port[64]; + int32_t baud; +}; + +void ddrio_config_p4io_mdxf_init(struct cconfig *config); + +void ddrio_config_p4io_mdxf_get( + struct p4io_mdxf_config *config_p4io_mdxf, struct cconfig *config); + +#endif diff --git a/src/main/ddrio-p4io/ddrio-p4io.def b/src/main/ddrio-p4io/ddrio-p4io.def new file mode 100644 index 0000000..146cd70 --- /dev/null +++ b/src/main/ddrio-p4io/ddrio-p4io.def @@ -0,0 +1,11 @@ +LIBRARY ddrio-p4io + +EXPORTS + ddr_io_set_loggers + ddr_io_fini + ddr_io_init + ddr_io_read_pad + ddr_io_set_lights_extio + ddr_io_set_lights_p3io + ddr_io_set_lights_hdxs_panel + ddr_io_set_lights_hdxs_rgb diff --git a/src/main/ddrio-p4io/ddrio.c b/src/main/ddrio-p4io/ddrio.c new file mode 100644 index 0000000..ffdbc9b --- /dev/null +++ b/src/main/ddrio-p4io/ddrio.c @@ -0,0 +1,179 @@ +#include + +#include +#include + +#include "bemanitools/ddrio.h" +#include "bemanitools/input.h" + +#include "cconfig/cconfig-main.h" + +#include "imports/avs.h" + +#include "util/defs.h" +#include "util/log.h" + +#include "config.h" + +#include "aciodrv/device.h" +#include "aciodrv/mdxf.h" +#include "p4iodrv/device.h" + +#include + +static struct p4iodrv_ctx *p4io_ctx; +static struct aciodrv_device_ctx *device; + +uint8_t light_buff[16] = {0}; +uint8_t coin_buff[4] = {0}; +uint32_t jamma[4] = {0}; + +void ddr_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 ddr_io_init( + thread_create_t thread_create, + thread_join_t thread_join, + thread_destroy_t thread_destroy) +{ + log_warning("ddr_io_init"); + + struct cconfig *config; + struct p4io_mdxf_config config_mdxf; + + config = cconfig_init(); + ddrio_config_p4io_mdxf_init(config); + + if (!cconfig_main_config_init( + config, + "--ddrio-p4io-config", + "ddrio-p4io.conf", + "--help", + "-h", + "ddrio-p4io", + CCONFIG_CMD_USAGE_OUT_STDOUT)) { + cconfig_finit(config); + exit(EXIT_FAILURE); + } + + ddrio_config_p4io_mdxf_get(&config_mdxf, config); + + cconfig_finit(config); + + p4io_ctx = p4iodrv_open(); + + if (!p4io_ctx) { + log_warning("Could not open p4io"); + // return false; + } + + device = aciodrv_device_open_path(config_mdxf.port, config_mdxf.baud); + + if (!device) { + log_warning("Opening acio device failed"); + // return false; + } + + int nodes = aciodrv_device_get_node_count(device); + + if (nodes != 2) { + log_warning("WARNING: only %d MDXF(s) found, expected 2", nodes); + } + + for (int i = 0; i < nodes; i++) { + if (!aciodrv_mdxf_init(device, i)) { + log_warning("Opening mdxf device %d failed", i); + return false; + } + } + + return true; +} + +uint32_t ddr_io_read_pad(void) +{ + uint32_t pad = 0; + + /* Sleep first: input is timestamped immediately AFTER the ioctl returns. + + Which is the right thing to do, for once. We sleep here because + the game polls input in a tight loop. Can't complain, at there isn't + an artificial limit on the poll frequency. */ + Sleep(1); + + // pull the state of the p4io & get the state of the mdxfs + if (p4io_ctx) { + p4iodrv_read_jamma(p4io_ctx, jamma); + } + + struct ac_io_mdxf_poll_in foot_p1 = {0}; + struct ac_io_mdxf_poll_in foot_p2 = {0}; + + if (device) { + aciodrv_mdxf_poll(device, 0, &foot_p1); + aciodrv_mdxf_poll(device, 1, &foot_p2); + } + + pad |= (foot_p1.panel.up > 0) ? (1 << DDR_P1_UP) : 0; + pad |= (foot_p1.panel.down > 0) ? (1 << DDR_P1_DOWN) : 0; + pad |= (foot_p1.panel.left > 0) ? (1 << DDR_P1_LEFT) : 0; + pad |= (foot_p1.panel.right > 0) ? (1 << DDR_P1_RIGHT) : 0; + + pad |= (foot_p2.panel.up > 0) ? (1 << DDR_P2_UP) : 0; + pad |= (foot_p2.panel.down > 0) ? (1 << DDR_P2_DOWN) : 0; + pad |= (foot_p2.panel.left > 0) ? (1 << DDR_P2_LEFT) : 0; + pad |= (foot_p2.panel.right > 0) ? (1 << DDR_P2_RIGHT) : 0; + + return pad; +} + +void ddr_io_set_lights_extio(uint32_t lights) +{ + // Python4/white cab setup does not have pad lights. + + // TODO: pull the NEON light out and map to the bass lights. + + if (p4io_ctx) { + p4iodrv_cmd_portout(p4io_ctx, (uint8_t *) &light_buff); + } +} + +void ddr_io_set_lights_p3io(uint32_t lights) +{ + // TODO: map the marquee lights to the RGB of the p4io. + + if (p4io_ctx) { + p4iodrv_cmd_portout(p4io_ctx, (uint8_t *) &light_buff); + } +} + +void ddr_io_set_lights_hdxs_panel(uint32_t lights) +{ + // TODO: Map the player button lights to the p4io menu lights. + + if (p4io_ctx) { + p4iodrv_cmd_portout(p4io_ctx, (uint8_t *) &light_buff); + } +} + +void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +{ + // TODO +} + +void ddr_io_fini(void) +{ + if (device) { + aciodrv_device_close(device); + } + + if (p4io_ctx) { + p4iodrv_close(p4io_ctx); + } +}