Bemanitools v5.26 release

This commit is contained in:
icex2
2019-09-27 22:36:50 +02:00
commit cbd7720349
718 changed files with 62731 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
dlls += ddrio-smx
imps += SMX
deplibs_ddrio-smx := \
SMX \
libs_ddrio-smx := \
geninput \
util \
src_ddrio-smx := \
ddrio.c \
+9
View File
@@ -0,0 +1,9 @@
LIBRARY ddrio-smx
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
+212
View File
@@ -0,0 +1,212 @@
#include <windows.h>
#include <stdatomic.h>
#include <stdlib.h>
#include "bemanitools/ddrio.h"
#include "bemanitools/input.h"
#include "imports/avs.h"
#include "imports/SMX.h"
#include "util/defs.h"
#include "util/log.h"
struct ddr_io_smx_pad_map {
int pad_no;
uint16_t smx_bit;
uint32_t ddr_bit;
};
struct ddr_io_smx_light_map {
uint32_t extio_bit;
int smx_light_offset;
unsigned char r;
unsigned char g;
unsigned char b;
};
static void ddr_io_smx_callback(
int pad_no,
enum SMXUpdateCallbackReason reason,
void *ctx);
static const struct ddr_io_smx_pad_map ddr_io_smx_pad_map[] = {
{ 0, 1 << 1, 1 << DDR_P1_UP },
{ 0, 1 << 3, 1 << DDR_P1_LEFT },
{ 0, 1 << 5, 1 << DDR_P1_RIGHT },
{ 0, 1 << 7, 1 << DDR_P1_DOWN },
{ 1, 1 << 1, 1 << DDR_P2_UP },
{ 1, 1 << 3, 1 << DDR_P2_LEFT },
{ 1, 1 << 5, 1 << DDR_P2_RIGHT },
{ 1, 1 << 7, 1 << DDR_P2_DOWN },
};
static const struct ddr_io_smx_light_map ddr_io_smx_light_map[] = {
/* Light L/R blue and U/D red to match DDR pad color scheme */
{ 1 << LIGHT_P1_UP, 48 * 1, 0xFF, 0x00, 0x00 },
{ 1 << LIGHT_P1_LEFT, 48 * 3, 0x00, 0x00, 0xFF },
{ 1 << LIGHT_P1_RIGHT, 48 * 5, 0x00, 0x00, 0xFF },
{ 1 << LIGHT_P1_DOWN, 48 * 7, 0xFF, 0x00, 0x00 },
{ 1 << LIGHT_P2_UP, 48 * 10, 0xFF, 0x00, 0x00 },
{ 1 << LIGHT_P2_LEFT, 48 * 12, 0x00, 0x00, 0xFF },
{ 1 << LIGHT_P2_RIGHT, 48 * 14, 0x00, 0x00, 0xFF },
{ 1 << LIGHT_P2_DOWN, 48 * 16, 0xFF, 0x00, 0x00 },
};
static _Atomic uint32_t ddr_io_smx_pad_state[2];
static CRITICAL_SECTION ddr_io_smx_lights_lock;
static uint8_t ddr_io_smx_lights_counter;
static char ddr_io_smx_lights[864];
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);
/* We would need a log server thread to accept log messages from SMX, since
it uses raw Win32 threads and not AVS threads (only AVS threads are
permitted to use the AVS logging API). So it's not really worth it. */
}
bool ddr_io_init(
thread_create_t thread_create,
thread_join_t thread_join,
thread_destroy_t thread_destroy)
{
/* Use geninput for menu/operator btns */
input_init(thread_create, thread_join, thread_destroy);
mapper_config_load("ddr");
/* Start up SMX API */
log_info("Starting SMX.DLL");
log_info("SMX.DLL version: %s", "[predates SMX_Version()]");
SMX_Start(ddr_io_smx_callback, NULL);
log_info("Started SMX.DLL");
InitializeCriticalSection(&ddr_io_smx_lights_lock);
return true;
}
uint32_t ddr_io_read_pad(void)
{
/* SMX pads require a constant stream of lighting updates or they will
quickly revert to autonomous lighting control. Here is a hacky way of
feeding that light data to the pad. Hopefully it won't starve anything
important.
Changing the light state causes the counter to reset, and the counter
itself ought to roll over at a rate of about 4 Hz. */
EnterCriticalSection(&ddr_io_smx_lights_lock);
if (ddr_io_smx_lights_counter == 0) {
SMX_SetLights(ddr_io_smx_lights);
}
ddr_io_smx_lights_counter++;
LeaveCriticalSection(&ddr_io_smx_lights_lock);
/* 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);
/* We don't atomically read both pads, but they are separate USB devices
so they don't update in lockstep anyway. */
return mapper_update() |
atomic_load(&ddr_io_smx_pad_state[0]) |
atomic_load(&ddr_io_smx_pad_state[1]) ;
}
void ddr_io_set_lights_extio(uint32_t lights)
{
const struct ddr_io_smx_light_map *map;
size_t offset;
size_t i;
size_t j;
EnterCriticalSection(&ddr_io_smx_lights_lock);
ddr_io_smx_lights_counter = 0;
memset(ddr_io_smx_lights, 0, sizeof(ddr_io_smx_lights));
for (i = 0 ; i < lengthof(ddr_io_smx_light_map) ; i++) {
map = &ddr_io_smx_light_map[i];
if (lights & map->extio_bit) {
offset = map->smx_light_offset;
for (j = 0 ; j < 48 ; j += 3) {
ddr_io_smx_lights[offset + j ] = map->r;
ddr_io_smx_lights[offset + j + 1] = map->g;
ddr_io_smx_lights[offset + j + 2] = map->b;
}
}
}
LeaveCriticalSection(&ddr_io_smx_lights_lock);
}
void ddr_io_set_lights_p3io(uint32_t lights)
{
uint8_t i;
for (i = 0x0E; i <= 0x1E; i++) {
mapper_write_light(i, lights & (1 << i) ? 255 : 0);
}
}
void ddr_io_fini(void)
{
log_info("Stopping SMX.DLL");
SMX_Stop();
log_info("Stopped SMX.DLL");
DeleteCriticalSection(&ddr_io_smx_lights_lock);
input_fini();
}
static void ddr_io_smx_callback(
int pad_no,
enum SMXUpdateCallbackReason reason,
void *ctx)
{
const struct ddr_io_smx_pad_map *map;
uint16_t smx_state;
uint32_t ddr_state;
size_t i;
if (pad_no < 0 || pad_no > 1) {
return;
}
smx_state = SMX_GetInputState(pad_no);
ddr_state = 0;
for (i = 0 ; i < lengthof(ddr_io_smx_pad_map) ; i++) {
map = &ddr_io_smx_pad_map[i];
if (pad_no == map->pad_no && (smx_state & map->smx_bit) != 0) {
ddr_state |= map->ddr_bit;
}
}
atomic_store(&ddr_io_smx_pad_state[pad_no], ddr_state);
}