new minimaid auxiliary input ddrio variant. Allows use of the minimaid in conjunction with the default hid-based implementation. Useful for setups that no longer use the standard old cabinet buttons via jamma

This commit is contained in:
daydensteve 2026-02-01 21:53:30 -05:00
parent 0d0e22de61
commit 325ee72014
5 changed files with 289 additions and 0 deletions

View File

@ -110,6 +110,7 @@ include src/main/ddrhook2/Module.mk
include src/main/ddrio-async/Module.mk
include src/main/ddrio-p3io/Module.mk
include src/main/ddrio-mm/Module.mk
include src/main/ddrio-mm-aux/Module.mk
include src/main/ddrio-smx/Module.mk
include src/main/ddriotest/Module.mk
include src/main/ddrio/Module.mk
@ -761,6 +762,7 @@ $(zipdir)/ddr-hwio-x86.zip: \
build/bin/indep-32/ddrio-async.dll \
build/bin/indep-32/ddrio-p3io.dll \
build/bin/indep-32/ddrio-mm.dll \
build/bin/indep-32/ddrio-mm-aux.dll \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/extiotest.exe \
build/bin/indep-32/p3io-ddr-tool.exe \
@ -773,6 +775,7 @@ $(zipdir)/ddr-hwio-x64.zip: \
build/bin/indep-64/ddrio-async.dll \
build/bin/indep-64/ddrio-p3io.dll \
build/bin/indep-64/ddrio-mm.dll \
build/bin/indep-64/ddrio-mm-aux.dll \
build/bin/indep-64/ddrio-smx.dll \
build/bin/indep-64/extiotest.exe \
build/bin/indep-64/p3io-ddr-tool.exe \

View File

@ -40,6 +40,7 @@ use:
- `ddrio`: Default implementation supporting keyboard, mouse and USB game controllers
- ddrio-mm: Support Minimaid custom interface
- ddrio-mm-aux: Minimaid custom interface + default implementation (i.e. augment minimaid with normal hid use)
- [ddrio-smx](ddrio-smx.md): Support for StepManiaX dance platforms
- [ddrio-p3io](ddrio-p3io.md): P3IO + EXTIO driver implementation
- [ddrio-async](ddrio-async.md): Wrapper/shim library to drive another ddrio in a dedicated IO

View File

@ -0,0 +1,14 @@
dlls += ddrio-mm-aux
ldflags_ddrio-mm-aux:= \
-lhid \
-lsetupapi \
libs_ddrio-mm-aux := \
geninput \
mm \
util \
src_ddrio-mm-aux := \
ddrio.c \

View File

@ -0,0 +1,11 @@
LIBRARY ddrio-mm-aux
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

View File

@ -0,0 +1,260 @@
#include <windows.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "bemanitools/ddrio.h"
#include "bemanitools/input.h"
#include "mm/mm.h"
#include "util/cmdline.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/mem.h"
struct ddr_bittrans {
uint32_t mm;
uint32_t p3io;
};
static const struct ddr_bittrans input_map[] = {
{0x00000001, 1 << DDR_SERVICE},
{0x00000002, 1 << DDR_TEST},
{0x00100000, 1 << DDR_P1_MENU_LEFT},
{0x00400000, 1 << DDR_P1_MENU_RIGHT},
{0x00000100, 1 << DDR_P1_START},
{0x00200000, 1 << DDR_P2_MENU_LEFT},
{0x00800000, 1 << DDR_P2_MENU_RIGHT},
{0x00000200, 1 << DDR_P2_START},
{0x00004000, 1 << DDR_P1_LEFT},
{0x00010000, 1 << DDR_P1_RIGHT},
{0x00000400, 1 << DDR_P1_UP},
{0x00001000, 1 << DDR_P1_DOWN},
{0x00008000, 1 << DDR_P2_LEFT},
{0x00020000, 1 << DDR_P2_RIGHT},
{0x00000800, 1 << DDR_P2_UP},
{0x00002000, 1 << DDR_P2_DOWN},
/* Nonstandard */
{0x01000000, 1 << DDR_P1_MENU_UP},
{0x04000000, 1 << DDR_P1_MENU_DOWN},
{0x02000000, 1 << DDR_P2_MENU_UP},
{0x08000000, 1 << DDR_P2_MENU_DOWN},
};
static const struct ddr_bittrans extio_light_map[] = {
{0x00000100, 1 << LIGHT_P1_UP},
{0x00000200, 1 << LIGHT_P1_DOWN},
{0x00000400, 1 << LIGHT_P1_LEFT},
{0x00000800, 1 << LIGHT_P1_RIGHT},
{0x00010000, 1 << LIGHT_P2_UP},
{0x00020000, 1 << LIGHT_P2_DOWN},
{0x00040000, 1 << LIGHT_P2_LEFT},
{0x00080000, 1 << LIGHT_P2_RIGHT},
{0x01000000, 1 << LIGHT_NEONS},
};
static const struct ddr_bittrans p3io_light_map[] = {
{0x00000004, 1 << LIGHT_P1_MENU},
{0x00000008, 1 << LIGHT_P2_MENU},
{0x00000010, 1 << LIGHT_P2_LOWER_LAMP},
{0x00000020, 1 << LIGHT_P2_UPPER_LAMP},
{0x00000040, 1 << LIGHT_P1_LOWER_LAMP},
{0x00000080, 1 << LIGHT_P1_UPPER_LAMP},
};
static bool initted;
static CRITICAL_SECTION cs;
static struct mm_output out;
static int ddr_io_get_lag_param(void)
{
int argc;
char **argv;
int result;
int i;
result = 0;
args_recover(&argc, &argv);
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
continue;
}
switch (argv[i][1]) {
case 'a':
if (i + 1 == argc) {
continue;
}
result = atoi(argv[i + 1]);
break;
}
}
args_free(argc, argv);
if (result < 0) {
/* snark snark */
log_warning(
"This PCB is incapable of seeing into the future. "
"Defaulting to 0 injected lag samples");
result = 0;
}
return result;
}
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);
input_set_loggers(misc, info, warning, fatal);
}
bool ddr_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy)
{
bool ok;
log_assert(!initted);
/* Use geninput for menu/operator btns */
input_init(thread_create, thread_join, thread_destroy);
mapper_config_load("ddr");
ok = mm_init(2 + ddr_io_get_lag_param());
if (!ok) {
return false;
}
InitializeCriticalSection(&cs);
out.lights = 0x00101000; /* Hold pad IO board FSMs in reset */
//out.kbd_enable = 1; /* allow kb input */
initted = true;
return true;
}
uint32_t ddr_io_read_pad(void)
{
struct mm_input in;
uint32_t i;
uint32_t pad;
EnterCriticalSection(&cs);
mm_update(&out, &in);
pad = 0;
for (i = 0; i < lengthof(input_map); i++) {
if (in.jamma & input_map[i].mm) {
pad |= input_map[i].p3io;
}
}
LeaveCriticalSection(&cs);
// or results from minimaid and normal bt5 input mappings
return pad | mapper_update();
}
void ddr_io_set_lights_extio(uint32_t extio_lights)
{
// MINIMAID LIGHTS
uint32_t clr;
uint32_t set;
int i;
clr = 0;
set = 0;
for (i = 0; i < lengthof(extio_light_map); i++) {
if (extio_lights & extio_light_map[i].p3io /* misnomer but w/e */) {
set |= extio_light_map[i].mm;
} else {
clr |= extio_light_map[i].mm;
}
}
atomic_fetch_or(&out.lights, set);
atomic_fetch_and(&out.lights, ~clr);
// NORMAL HID LIGHTS
uint8_t j;
for (j = 0x0E; j <= 0x1E; j++) {
mapper_write_light(j, extio_lights & (1 << j) ? 255 : 0);
}
}
void ddr_io_set_lights_p3io(uint32_t p3io_lights)
{
// MINIMAID LIGHTS
uint32_t clr;
uint32_t set;
int i;
clr = 0;
set = 0;
for (i = 0; i < lengthof(p3io_light_map); i++) {
if (p3io_lights & p3io_light_map[i].p3io) {
set |= p3io_light_map[i].mm;
} else {
clr |= p3io_light_map[i].mm;
}
}
atomic_fetch_or(&out.lights, set);
atomic_fetch_and(&out.lights, ~clr);
// NORMAL HID LIGHTS
uint8_t j;
for (j = 0x00; j <= 0x07; j++) {
mapper_write_light(j, p3io_lights & (1 << j) ? 255 : 0);
}
}
void ddr_io_set_lights_hdxs_panel(uint32_t lights)
{
// NORMAL HID LIGHTS
uint8_t i;
for (i = 0x08; i <= 0x0D; i++) {
mapper_write_light(i, lights & (1 << i) ? 255 : 0);
}
}
void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
// NORMAL HID LIGHTS
if (idx < 4) {
uint8_t base = 0x20 + idx * 3;
mapper_write_light(base + 0, r);
mapper_write_light(base + 1, g);
mapper_write_light(base + 2, b);
}
}
void ddr_io_fini(void)
{
input_fini();
if (initted) {
mm_fini();
DeleteCriticalSection(&cs);
initted = false;
}
}