idzio: Add configuration file

This commit is contained in:
Tau 2019-09-28 23:29:12 -04:00
parent a0664a4008
commit 2907c1a1b5
6 changed files with 324 additions and 24 deletions

78
idzio/config.c Normal file
View File

@ -0,0 +1,78 @@
#include <windows.h>
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include "idzio/config.h"
void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
GetPrivateProfileStringW(
L"dinput",
L"deviceName",
L"",
cfg->device_name,
_countof(cfg->device_name),
filename);
GetPrivateProfileStringW(
L"dinput",
L"brakeAxis",
L"RZ",
cfg->brake_axis,
_countof(cfg->brake_axis),
filename);
GetPrivateProfileStringW(
L"dinput",
L"accelAxis",
L"Y",
cfg->accel_axis,
_countof(cfg->accel_axis),
filename);
cfg->start = GetPrivateProfileIntW(L"dinput", L"start", 0, filename);
cfg->view_chg = GetPrivateProfileIntW(L"dinput", L"viewChg", 0, filename);
cfg->shift_dn = GetPrivateProfileIntW(L"dinput", L"shiftDn", 0, filename);
cfg->shift_up = GetPrivateProfileIntW(L"dinput", L"shiftUp", 0, filename);
}
void idz_io_config_load(struct idz_io_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", '1', filename);
cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", '2', filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", '3', filename);
GetPrivateProfileStringW(
L"io3",
L"mode",
L"xinput",
cfg->mode,
_countof(cfg->mode),
filename);
idz_shifter_config_load(&cfg->shifter, filename);
idz_di_config_load(&cfg->di, filename);
}
void idz_shifter_config_load(
struct idz_shifter_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->auto_neutral = GetPrivateProfileIntW(
L"io3",
L"autoNeutral",
0,
filename);
}

34
idzio/config.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
struct idz_shifter_config {
bool auto_neutral;
};
struct idz_di_config {
wchar_t device_name[64];
wchar_t brake_axis[16];
wchar_t accel_axis[16];
uint8_t start;
uint8_t view_chg;
uint8_t shift_dn;
uint8_t shift_up;
};
struct idz_io_config {
uint8_t vk_test;
uint8_t vk_service;
uint8_t vk_coin;
wchar_t mode[8];
struct idz_shifter_config shifter;
struct idz_di_config di;
};
void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename);
void idz_io_config_load(struct idz_io_config *cfg, const wchar_t *filename);
void idz_shifter_config_load(
struct idz_shifter_config *cfg,
const wchar_t *filename);

View File

@ -6,20 +6,47 @@
#include <wchar.h> #include <wchar.h>
#include "idzio/backend.h" #include "idzio/backend.h"
#include "idzio/config.h"
#include "idzio/di.h"
#include "idzio/idzio.h" #include "idzio/idzio.h"
#include "idzio/shifter.h" #include "idzio/shifter.h"
#include "idzio/wnd.h" #include "idzio/wnd.h"
#include "util/dprintf.h" #include "util/dprintf.h"
#include "util/str.h"
struct idz_di_axis {
wchar_t name[4];
size_t off;
};
union idz_di_state {
DIJOYSTATE st;
uint8_t bytes[sizeof(DIJOYSTATE)];
};
static HRESULT idz_di_config_apply(const struct idz_di_config *cfg);
static const struct idz_di_axis *idz_di_get_axis(const wchar_t *name);
static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx); static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx);
static void idz_di_try_fx(void); static void idz_di_try_fx(void);
static HRESULT idz_di_poll(DIJOYSTATE *out); static HRESULT idz_di_poll(union idz_di_state *state);
static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out); static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out);
static uint8_t idz_di_decode_pov(DWORD pov); static uint8_t idz_di_decode_pov(DWORD pov);
static void idz_di_jvs_read_shifter(uint8_t *gear); static void idz_di_jvs_read_shifter(uint8_t *gear);
static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out); static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out);
static const struct idz_di_axis idz_di_axes[] = {
/* Just map DIJOYSTATE for now, we can map DIJOYSTATE2 later if needed */
{ .name = L"X", .off = DIJOFS_X },
{ .name = L"Y", .off = DIJOFS_Y },
{ .name = L"Z", .off = DIJOFS_Z },
{ .name = L"RX", .off = DIJOFS_RX },
{ .name = L"RY", .off = DIJOFS_RY },
{ .name = L"RZ", .off = DIJOFS_RZ },
{ .name = L"U", .off = DIJOFS_SLIDER(0) },
{ .name = L"V", .off = DIJOFS_SLIDER(1) },
};
static const struct idz_io_backend idz_di_backend = { static const struct idz_io_backend idz_di_backend = {
.jvs_read_buttons = idz_di_jvs_read_buttons, .jvs_read_buttons = idz_di_jvs_read_buttons,
.jvs_read_shifter = idz_di_jvs_read_shifter, .jvs_read_shifter = idz_di_jvs_read_shifter,
@ -30,8 +57,17 @@ static HWND idz_di_wnd;
static IDirectInput8W *idz_di_api; static IDirectInput8W *idz_di_api;
static IDirectInputDevice8W *idz_di_dev; static IDirectInputDevice8W *idz_di_dev;
static IDirectInputEffect *idz_di_fx; static IDirectInputEffect *idz_di_fx;
static size_t idz_di_off_brake;
static size_t idz_di_off_accel;
static uint8_t idz_di_shift_dn;
static uint8_t idz_di_shift_up;
static uint8_t idz_di_view_chg;
static uint8_t idz_di_start;
HRESULT idz_di_init(HINSTANCE inst, const struct idz_io_backend **backend) HRESULT idz_di_init(
const struct idz_di_config *cfg,
HINSTANCE inst,
const struct idz_io_backend **backend)
{ {
HRESULT hr; HRESULT hr;
HMODULE dinput8; HMODULE dinput8;
@ -39,10 +75,17 @@ HRESULT idz_di_init(HINSTANCE inst, const struct idz_io_backend **backend)
wchar_t dll_path[MAX_PATH]; wchar_t dll_path[MAX_PATH];
UINT path_pos; UINT path_pos;
assert(cfg != NULL);
assert(backend != NULL); assert(backend != NULL);
*backend = NULL; *backend = NULL;
hr = idz_di_config_apply(cfg);
if (FAILED(hr)) {
return hr;
}
hr = idz_io_wnd_create(inst, &idz_di_wnd); hr = idz_io_wnd_create(inst, &idz_di_wnd);
if (FAILED(hr)) { if (FAILED(hr)) {
@ -96,15 +139,21 @@ HRESULT idz_di_init(HINSTANCE inst, const struct idz_io_backend **backend)
idz_di_api, idz_di_api,
DI8DEVCLASS_GAMECTRL, DI8DEVCLASS_GAMECTRL,
idz_di_enum_callback, idz_di_enum_callback,
NULL, (void *) cfg,
DIEDFL_ATTACHEDONLY); DIEDFL_ATTACHEDONLY);
if (FAILED(hr) || idz_di_dev == NULL) { if (FAILED(hr)) {
dprintf("Wheel: Could not find a controller: %08x\n", (int) hr); dprintf("Wheel: EnumDevices failed: %08x\n", (int) hr);
return hr; return hr;
} }
if (idz_di_dev == NULL) {
dprintf("Wheel: Controller not found\n");
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
hr = IDirectInputDevice8_SetCooperativeLevel( hr = IDirectInputDevice8_SetCooperativeLevel(
idz_di_dev, idz_di_dev,
idz_di_wnd, idz_di_wnd,
@ -139,8 +188,101 @@ HRESULT idz_di_init(HINSTANCE inst, const struct idz_io_backend **backend)
return S_OK; return S_OK;
} }
static HRESULT idz_di_config_apply(const struct idz_di_config *cfg)
{
const struct idz_di_axis *brake_axis;
const struct idz_di_axis *accel_axis;
brake_axis = idz_di_get_axis(cfg->brake_axis);
accel_axis = idz_di_get_axis(cfg->accel_axis);
if (brake_axis == NULL) {
dprintf("Wheel: Invalid brake axis: %S\n", cfg->brake_axis);
return E_INVALIDARG;
}
if (accel_axis == NULL) {
dprintf("Wheel: Invalid accel axis: %S\n", cfg->accel_axis);
return E_INVALIDARG;
}
if (cfg->start > 32) {
dprintf("Wheel: Invalid start button: %i\n", cfg->start);
return E_INVALIDARG;
}
if (cfg->view_chg > 32) {
dprintf("Wheel: Invalid view change button: %i\n", cfg->view_chg);
return E_INVALIDARG;
}
if (cfg->shift_dn > 32) {
dprintf("Wheel: Invalid shift down button: %i\n", cfg->shift_dn);
return E_INVALIDARG;
}
if (cfg->shift_up > 32) {
dprintf("Wheel: Invalid shift up button: %i\n", cfg->shift_up);
return E_INVALIDARG;
}
/* Print some debug output to make sure config works... */
dprintf("Wheel: --- Begin configuration ---\n");
dprintf("Wheel: Device name . . . . : Contains \"%S\"\n",
cfg->device_name);
dprintf("Wheel: Brake axis . . . . : %S\n", accel_axis->name);
dprintf("Wheel: Accelerator axis . : %S\n", brake_axis->name);
dprintf("Wheel: Start button . . . : %i\n", cfg->start);
dprintf("Wheel: View Change button : %i\n", cfg->view_chg);
dprintf("Wheel: Shift Down button . : %i\n", cfg->shift_dn);
dprintf("Wheel: Shift Up button . . : %i\n", cfg->shift_up);
dprintf("Wheel: --- End configuration ---\n");
idz_di_off_brake = accel_axis->off;
idz_di_off_accel = brake_axis->off;
idz_di_start = cfg->start;
idz_di_view_chg = cfg->view_chg;
idz_di_shift_dn = cfg->shift_dn;
idz_di_shift_up = cfg->shift_up;
return S_OK;
}
static const struct idz_di_axis *idz_di_get_axis(const wchar_t *name)
{
const struct idz_di_axis *axis;
size_t i;
for (i = 0 ; i < _countof(idz_di_axes) ; i++) {
axis = &idz_di_axes[i];
if (wstr_ieq(name, axis->name)) {
return axis;
}
}
return NULL;
}
static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx) static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx)
{ {
const struct idz_di_config *cfg;
cfg = ctx;
if (wcsstr(dev->tszProductName, cfg->device_name) == NULL) {
return DIENUM_CONTINUE;
}
dprintf("Wheel: Using DirectInput device \"%S\"\n", dev->tszProductName);
IDirectInput8_CreateDevice( IDirectInput8_CreateDevice(
idz_di_api, idz_di_api,
&dev->guidInstance, &dev->guidInstance,
@ -222,7 +364,7 @@ static void idz_di_try_fx(void)
dprintf("Wheel: Force feedback initialized and set to zero\n"); dprintf("Wheel: Force feedback initialized and set to zero\n");
} }
static HRESULT idz_di_poll(DIJOYSTATE *out) static HRESULT idz_di_poll(union idz_di_state *out)
{ {
HRESULT hr; HRESULT hr;
MSG msg; MSG msg;
@ -241,7 +383,10 @@ static HRESULT idz_di_poll(DIJOYSTATE *out)
DispatchMessage(&msg); DispatchMessage(&msg);
} }
hr = IDirectInputDevice8_GetDeviceState(idz_di_dev, sizeof(*out), out); hr = IDirectInputDevice8_GetDeviceState(
idz_di_dev,
sizeof(out->st),
&out->st);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("Wheel: I/O error: %08x\n", (int) hr); dprintf("Wheel: I/O error: %08x\n", (int) hr);
@ -255,8 +400,8 @@ static HRESULT idz_di_poll(DIJOYSTATE *out)
static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out) static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out)
{ {
union idz_di_state state;
uint8_t gamebtn; uint8_t gamebtn;
DIJOYSTATE state;
HRESULT hr; HRESULT hr;
assert(gamebtn_out != NULL); assert(gamebtn_out != NULL);
@ -267,13 +412,13 @@ static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out)
return; return;
} }
gamebtn = idz_di_decode_pov(state.rgdwPOV[0]); gamebtn = idz_di_decode_pov(state.st.rgdwPOV[0]);
if (state.rgbButtons[2]) { if (idz_di_start && state.st.rgbButtons[idz_di_start - 1]) {
gamebtn |= IDZ_IO_GAMEBTN_START; gamebtn |= IDZ_IO_GAMEBTN_START;
} }
if (state.rgbButtons[9]) { if (idz_di_view_chg && state.st.rgbButtons[idz_di_view_chg - 1]) {
gamebtn |= IDZ_IO_GAMEBTN_VIEW_CHANGE; gamebtn |= IDZ_IO_GAMEBTN_VIEW_CHANGE;
} }
@ -297,7 +442,9 @@ static uint8_t idz_di_decode_pov(DWORD pov)
static void idz_di_jvs_read_shifter(uint8_t *gear) static void idz_di_jvs_read_shifter(uint8_t *gear)
{ {
DIJOYSTATE state; union idz_di_state state;
bool shift_dn;
bool shift_up;
HRESULT hr; HRESULT hr;
assert(gear != NULL); assert(gear != NULL);
@ -308,18 +455,28 @@ static void idz_di_jvs_read_shifter(uint8_t *gear)
return; return;
} }
if (state.rgbButtons[2]) { if (idz_di_shift_dn) {
idz_shifter_reset(); shift_dn = state.st.rgbButtons[idz_di_shift_dn - 1];
} else {
shift_dn = false;
} }
idz_shifter_update(state.rgbButtons[0], state.rgbButtons[1]); if (idz_di_shift_up) {
shift_up = state.st.rgbButtons[idz_di_shift_up - 1];
} else {
shift_up = false;
}
idz_shifter_update(shift_dn, shift_up);
*gear = idz_shifter_current_gear(); *gear = idz_shifter_current_gear();
} }
static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out) static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out)
{ {
DIJOYSTATE state; union idz_di_state state;
const LONG *brake;
const LONG *accel;
HRESULT hr; HRESULT hr;
assert(out != NULL); assert(out != NULL);
@ -330,7 +487,10 @@ static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out)
return; return;
} }
out->wheel = state.lX - 32768; brake = (LONG *) &state.bytes[idz_di_off_brake];
out->accel = 65535 - state.lRz; accel = (LONG *) &state.bytes[idz_di_off_accel];
out->brake = 65535 - state.lY;
out->wheel = state.st.lX - 32768;
out->brake = 65535 - *brake;
out->accel = 65535 - *accel;
} }

View File

@ -1,5 +1,9 @@
#pragma once #pragma once
#include "idzio/backend.h" #include "idzio/backend.h"
#include "idzio/config.h"
HRESULT idz_di_init(HINSTANCE inst, const struct idz_io_backend **backend); HRESULT idz_di_init(
const struct idz_di_config *cfg,
HINSTANCE inst,
const struct idz_io_backend **backend);

View File

@ -5,20 +5,39 @@
#include <stdint.h> #include <stdint.h>
#include "idzio/backend.h" #include "idzio/backend.h"
#include "idzio/config.h"
#include "idzio/di.h" #include "idzio/di.h"
#include "idzio/idzio.h" #include "idzio/idzio.h"
#include "idzio/xi.h" #include "idzio/xi.h"
#include "util/dprintf.h"
#include "util/str.h"
static HMODULE idz_io_hmodule; static HMODULE idz_io_hmodule;
static struct idz_io_config idz_io_cfg;
static const struct idz_io_backend *idz_io_backend; static const struct idz_io_backend *idz_io_backend;
static bool idz_io_coin; static bool idz_io_coin;
static uint16_t idz_io_coins; static uint16_t idz_io_coins;
HRESULT idz_io_init(void) HRESULT idz_io_init(void)
{ {
HRESULT hr;
assert(idz_io_backend == NULL); assert(idz_io_backend == NULL);
return idz_di_init(idz_io_hmodule, &idz_io_backend); idz_io_config_load(&idz_io_cfg, L".\\segatools.ini");
if (wstr_ieq(idz_io_cfg.mode, L"dinput")) {
hr = idz_di_init(&idz_io_cfg.di, idz_io_hmodule, &idz_io_backend);
} else if (wstr_ieq(idz_io_cfg.mode, L"xinput")) {
hr = idz_xi_init(&idz_io_backend);
} else {
hr = E_INVALIDARG;
dprintf("IDZ IO: Invalid IO mode \"%S\", use dinput or xinput\n",
idz_io_cfg.mode);
}
return hr;
} }
void idz_io_jvs_read_buttons(uint8_t *opbtn_out, uint8_t *gamebtn_out) void idz_io_jvs_read_buttons(uint8_t *opbtn_out, uint8_t *gamebtn_out)
@ -31,11 +50,13 @@ void idz_io_jvs_read_buttons(uint8_t *opbtn_out, uint8_t *gamebtn_out)
opbtn = 0; opbtn = 0;
if (GetAsyncKeyState('1')) { if ( idz_io_cfg.vk_test &&
(GetAsyncKeyState(idz_io_cfg.vk_test) & 0x8000)) {
opbtn |= IDZ_IO_OPBTN_TEST; opbtn |= IDZ_IO_OPBTN_TEST;
} }
if (GetAsyncKeyState('2')) { if ( idz_io_cfg.vk_service &&
(GetAsyncKeyState(idz_io_cfg.vk_service) & 0x8000)) {
opbtn |= IDZ_IO_OPBTN_SERVICE; opbtn |= IDZ_IO_OPBTN_SERVICE;
} }
@ -66,7 +87,8 @@ void idz_io_jvs_read_coin_counter(uint16_t *out)
/* Coin counter is not backend-specific */ /* Coin counter is not backend-specific */
if (GetAsyncKeyState('3')) { if ( idz_io_cfg.vk_coin &&
(GetAsyncKeyState(idz_io_cfg.vk_coin) & 0x8000)) {
if (!idz_io_coin) { if (!idz_io_coin) {
idz_io_coin = true; idz_io_coin = true;
idz_io_coins++; idz_io_coins++;

View File

@ -15,6 +15,8 @@ idzio_dll = shared_library(
], ],
sources : [ sources : [
'backend.h', 'backend.h',
'config.c',
'config.h',
'di.c', 'di.c',
'di.h', 'di.h',
'dllmain.c', 'dllmain.c',