1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2025-02-17 19:19:16 +01:00

Feature: vigem driver for ddrio (#247)

Reads state of ddrio and updates vigem pads. Similar in vein to
viggem-sdvxio and vigem-iidxio

Useful for playing xinput related games with official hardware.
This commit is contained in:
din 2023-04-11 11:04:36 -05:00 committed by GitHub
parent c4e77a9152
commit b864c0dcfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 356 additions and 0 deletions

View File

@ -183,6 +183,7 @@ include src/main/util/Module.mk
include src/main/vefxio/Module.mk
include src/main/vigem-iidxio/Module.mk
include src/main/vigem-sdvxio/Module.mk
include src/main/vigem-ddrio/Module.mk
include src/main/vigemstub/Module.mk
include src/test/cconfig/Module.mk
@ -615,6 +616,18 @@ $(zipdir)/sdvx-hwio-x64.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-hwio-x86.zip: \
build/bin/indep-32/vigem-ddrio.exe \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-hwio-x64.zip: \
build/bin/indep-64/vigem-ddrio.exe \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/ddr-11.zip: \
build/bin/indep-32/inject.exe \
build/bin/avs2_803-32/ddrhook1.dll \
@ -794,6 +807,8 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/ddr-13.zip \
$(zipdir)/ddr-14-to-16.zip \
$(zipdir)/ddr-16-x64.zip \
$(zipdir)/ddr-hwio-x86.zip \
$(zipdir)/ddr-hwio-x64.zip \
$(zipdir)/doc.zip \
$(zipdir)/iidx-09-to-12.zip \
$(zipdir)/iidx-13.zip \

View File

@ -0,0 +1,20 @@
exes += vigem-ddrio
deplibs_vigem-ddrio := \
ViGEmClient \
cppflags_vigem-ddrio := \
-I src/imports \
ldflags_vigem-ddrio := \
-lsetupapi \
libs_vigem-ddrio := \
cconfig \
ddrio \
util \
vigemstub \
src_vigem-ddrio := \
main.c \
config-vigem-ddrio.c \

View File

@ -0,0 +1,63 @@
#include "cconfig/cconfig-main.h"
#include "cconfig/cconfig-util.h"
#include "vigem-ddrio/config-vigem-ddrio.h"
#include "util/log.h"
#define VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY \
"ddrio.enable_reactive_light"
#define VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE true
static void vigem_ddrio_config_init(struct cconfig *config)
{
cconfig_util_set_bool(
config,
VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY,
VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE,
"Enable reactive lights based on input.");
}
static void vigem_ddrio_config_get(
struct vigem_ddrio_config *vigem_config, struct cconfig *config)
{
if (!cconfig_util_get_bool(
config,
VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY,
&vigem_config->enable_reactive_light,
VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
VIGEM_DDRIO_CONFIG_ENABLE_REACTIVE_LIGHT_KEY,
VIGEM_DDRIO_CONFIG_DEFAULT_ENABLE_REACTIVE_LIGHT_VALUE);
}
}
bool get_vigem_ddrio_config(struct vigem_ddrio_config *config_out)
{
struct cconfig *config;
config = cconfig_init();
vigem_ddrio_config_init(config);
if (!cconfig_main_config_init(
config,
"--config",
"vigem-ddrio.conf",
"--help",
"-h",
"vigem-ddrio",
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
cconfig_finit(config);
return false;
}
vigem_ddrio_config_get(config_out, config);
cconfig_finit(config);
return true;
}

View File

@ -0,0 +1,14 @@
#ifndef VIGEM_DDRIO_CONFIG_H
#define VIGEM_DDRIO_CONFIG_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct vigem_ddrio_config {
bool enable_reactive_light;
};
bool get_vigem_ddrio_config(struct vigem_ddrio_config *config_out);
#endif

244
src/main/vigem-ddrio/main.c Normal file
View File

@ -0,0 +1,244 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "ViGEm/Client.h"
#include "bemanitools/ddrio.h"
#include "util/log.h"
#include "util/math.h"
#include "util/thread.h"
#include "vigemstub/helper.h"
#include "vigem-ddrio/config-vigem-ddrio.h"
#define NUM_PADS 2
bool check_key(uint32_t input, size_t idx_in)
{
if ((input >> idx_in) & 1) {
return true;
}
return false;
}
uint32_t check_assign_key(uint32_t input, size_t idx_in, size_t bit_out)
{
if (check_key(input, idx_in)) {
return bit_out;
}
return 0;
}
uint32_t check_assign_light(uint32_t input, size_t idx_in, size_t gpio_out)
{
if (check_key(input, idx_in)) {
return 1 << gpio_out;
}
return 0;
}
void set_all_lights(bool on)
{
ddr_io_set_lights_extio(on ? UINT32_MAX : 0);
ddr_io_set_lights_p3io(on ? UINT32_MAX : 0);
ddr_io_set_lights_hdxs_panel(on ? UINT32_MAX : 0);
for (int i = 0; i < 4; i++) {
uint8_t val = on ? UINT8_MAX : 0;
ddr_io_set_lights_hdxs_rgb(i, val, val, val);
}
}
void set_reactive_lights(uint32_t input_state)
{
uint32_t new_extio_state = 0;
uint32_t new_p3io_state = 0;
uint32_t new_hdxs_state = 0;
new_extio_state |= check_assign_light(input_state, DDR_P1_UP, LIGHT_P1_UP);
new_extio_state |=
check_assign_light(input_state, DDR_P1_DOWN, LIGHT_P1_DOWN);
new_extio_state |=
check_assign_light(input_state, DDR_P1_LEFT, LIGHT_P1_LEFT);
new_extio_state |=
check_assign_light(input_state, DDR_P1_RIGHT, LIGHT_P1_RIGHT);
new_extio_state |= check_assign_light(input_state, DDR_P2_UP, LIGHT_P2_UP);
new_extio_state |=
check_assign_light(input_state, DDR_P2_DOWN, LIGHT_P2_DOWN);
new_extio_state |=
check_assign_light(input_state, DDR_P2_LEFT, LIGHT_P2_LEFT);
new_extio_state |=
check_assign_light(input_state, DDR_P2_RIGHT, LIGHT_P2_RIGHT);
new_p3io_state |=
check_assign_light(input_state, DDR_P1_START, LIGHT_P1_MENU);
new_p3io_state |=
check_assign_light(input_state, DDR_P2_START, LIGHT_P2_MENU);
new_hdxs_state |=
check_assign_light(input_state, DDR_P1_START, LIGHT_HD_P1_START);
new_hdxs_state |=
check_assign_light(input_state, DDR_P1_MENU_UP, LIGHT_HD_P1_UP_DOWN);
new_hdxs_state |=
check_assign_light(input_state, DDR_P1_MENU_DOWN, LIGHT_HD_P1_UP_DOWN);
new_hdxs_state |= check_assign_light(
input_state, DDR_P1_MENU_LEFT, LIGHT_HD_P1_LEFT_RIGHT);
new_hdxs_state |= check_assign_light(
input_state, DDR_P1_MENU_RIGHT, LIGHT_HD_P1_LEFT_RIGHT);
new_hdxs_state |=
check_assign_light(input_state, DDR_P2_START, LIGHT_HD_P2_START);
new_hdxs_state |=
check_assign_light(input_state, DDR_P2_MENU_UP, LIGHT_HD_P2_UP_DOWN);
new_hdxs_state |=
check_assign_light(input_state, DDR_P2_MENU_DOWN, LIGHT_HD_P2_UP_DOWN);
new_hdxs_state |= check_assign_light(
input_state, DDR_P2_MENU_LEFT, LIGHT_HD_P2_LEFT_RIGHT);
new_hdxs_state |= check_assign_light(
input_state, DDR_P2_MENU_RIGHT, LIGHT_HD_P2_LEFT_RIGHT);
ddr_io_set_lights_extio(new_extio_state);
ddr_io_set_lights_p3io(new_p3io_state);
ddr_io_set_lights_hdxs_panel(new_hdxs_state);
}
int main(int argc, char **argv)
{
log_to_writer(log_writer_stdout, NULL);
struct vigem_ddrio_config config;
if (!get_vigem_ddrio_config(&config)) {
exit(EXIT_FAILURE);
}
ddr_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
if (!ddr_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) {
log_warning("Initializing ddrio failed");
return -1;
}
// go ahead and turn lights off as some are on during boot.
set_all_lights(false);
PVIGEM_CLIENT client = vigem_helper_setup();
if (!client) {
log_warning("client failed to connect failed");
return -1;
}
PVIGEM_TARGET pad[NUM_PADS];
bool failed = false;
for (uint8_t i = 0; i < NUM_PADS; i++) {
pad[i] = vigem_helper_add_pad(client);
if (!pad[i]) {
log_warning("vigem_alloc pad %d failed", i);
failed = true;
}
}
if (failed) {
ddr_io_fini();
return -1;
}
bool loop = true;
uint32_t pad_state = 0;
XUSB_REPORT state[NUM_PADS] = {0};
log_info("vigem init succeeded, beginning poll loop");
while (loop) {
pad_state = ddr_io_read_pad();
for (uint8_t i = 0; i < NUM_PADS; i++) {
memset(&state[i], 0, sizeof(state[i]));
}
state[0].wButtons |=
check_assign_key(pad_state, DDR_TEST, XUSB_GAMEPAD_LEFT_THUMB);
state[0].wButtons |=
check_assign_key(pad_state, DDR_SERVICE, XUSB_GAMEPAD_RIGHT_THUMB);
state[0].wButtons |=
check_assign_key(pad_state, DDR_COIN, XUSB_GAMEPAD_BACK);
// assign arrows to face buttons due to jumps / hat interpretation
state[0].wButtons |=
check_assign_key(pad_state, DDR_P1_UP, XUSB_GAMEPAD_Y);
state[0].wButtons |=
check_assign_key(pad_state, DDR_P1_DOWN, XUSB_GAMEPAD_A);
state[0].wButtons |=
check_assign_key(pad_state, DDR_P1_LEFT, XUSB_GAMEPAD_X);
state[0].wButtons |=
check_assign_key(pad_state, DDR_P1_RIGHT, XUSB_GAMEPAD_B);
state[0].wButtons |=
check_assign_key(pad_state, DDR_P1_START, XUSB_GAMEPAD_START);
state[0].wButtons |=
check_assign_key(pad_state, DDR_P1_MENU_UP, XUSB_GAMEPAD_DPAD_UP);
state[0].wButtons |= check_assign_key(
pad_state, DDR_P1_MENU_DOWN, XUSB_GAMEPAD_DPAD_DOWN);
state[0].wButtons |= check_assign_key(
pad_state, DDR_P1_MENU_LEFT, XUSB_GAMEPAD_DPAD_LEFT);
state[0].wButtons |= check_assign_key(
pad_state, DDR_P1_MENU_RIGHT, XUSB_GAMEPAD_DPAD_RIGHT);
state[1].wButtons |=
check_assign_key(pad_state, DDR_P2_UP, XUSB_GAMEPAD_Y);
state[1].wButtons |=
check_assign_key(pad_state, DDR_P2_DOWN, XUSB_GAMEPAD_A);
state[1].wButtons |=
check_assign_key(pad_state, DDR_P2_LEFT, XUSB_GAMEPAD_X);
state[1].wButtons |=
check_assign_key(pad_state, DDR_P2_RIGHT, XUSB_GAMEPAD_B);
state[1].wButtons |=
check_assign_key(pad_state, DDR_P2_START, XUSB_GAMEPAD_START);
state[1].wButtons |=
check_assign_key(pad_state, DDR_P2_MENU_UP, XUSB_GAMEPAD_DPAD_UP);
state[1].wButtons |= check_assign_key(
pad_state, DDR_P2_MENU_DOWN, XUSB_GAMEPAD_DPAD_DOWN);
state[1].wButtons |= check_assign_key(
pad_state, DDR_P2_MENU_LEFT, XUSB_GAMEPAD_DPAD_LEFT);
state[1].wButtons |= check_assign_key(
pad_state, DDR_P2_MENU_RIGHT, XUSB_GAMEPAD_DPAD_RIGHT);
for (uint8_t i = 0; i < NUM_PADS; i++) {
vigem_target_x360_update(client, pad[i], state[i]);
}
if (config.enable_reactive_light) {
set_reactive_lights(pad_state);
}
if (check_key(pad_state, DDR_TEST) &&
check_key(pad_state, DDR_SERVICE)) {
loop = false;
}
// avoid CPU banging
Sleep(1);
}
for (uint8_t i = 0; i < NUM_PADS; i++) {
vigem_target_remove(client, pad[i]);
vigem_target_free(pad[i]);
}
vigem_free(client);
ddr_io_fini();
return 0;
}