forked from Dniel97/segatools
idac: first segatools support
This commit is contained in:
parent
ee6675dd73
commit
da97d23b51
31
dist/idac/segatools.ini
vendored
31
dist/idac/segatools.ini
vendored
@ -13,14 +13,6 @@ appdata=
|
|||||||
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
||||||
default=127.0.0.1
|
default=127.0.0.1
|
||||||
|
|
||||||
[ds]
|
|
||||||
; Region code on the emulated AMEX board DS EEPROM.
|
|
||||||
; 1: Japan
|
|
||||||
; 4: Export (some UI elements in English)
|
|
||||||
;
|
|
||||||
; NOTE: Changing this setting causes a factory reset.
|
|
||||||
region=1
|
|
||||||
|
|
||||||
[netenv]
|
[netenv]
|
||||||
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
|
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
|
||||||
; SEGA games are somewhat picky about their LAN environment, so leaving this
|
; SEGA games are somewhat picky about their LAN environment, so leaving this
|
||||||
@ -33,25 +25,24 @@ enable=1
|
|||||||
; that subnet must start with 192.168.
|
; that subnet must start with 192.168.
|
||||||
subnet=192.168.100.0
|
subnet=192.168.100.0
|
||||||
|
|
||||||
[gpio]
|
|
||||||
; Emulated Nu DIP switch for Distribution Server setting.
|
|
||||||
;
|
|
||||||
; If multiple machines are present on the same LAN then set this to 1 on
|
|
||||||
; exactly one machine and set this to 0 on all others.
|
|
||||||
dipsw1=1
|
|
||||||
|
|
||||||
[aimeio]
|
[aimeio]
|
||||||
; To use a custom card reader IO DLL enter its path here.
|
; To use a custom card reader IO DLL enter its path here.
|
||||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||||
path=
|
path=
|
||||||
|
|
||||||
[idzio]
|
[idacio]
|
||||||
; To use a custom Initial D Zero IO DLL enter its path here.
|
; To use a custom Initial D The Arcade IO DLL enter its path here.
|
||||||
; Leave empty if you want to use Segatools built-in gamepad/wheel input.
|
; Leave empty if you want to use Segatools built-in gamepad/wheel input.
|
||||||
path=
|
path=
|
||||||
|
|
||||||
[io3]
|
[io4]
|
||||||
; Input API selection for JVS input emulator.
|
; Test button virtual-key code. Default is the 1 key.
|
||||||
|
test=0x31
|
||||||
|
; Service button virtual-key code. Default is the 2 key.
|
||||||
|
service=0x32
|
||||||
|
; Keyboard button to increment coin counter. Default is the 3 key.
|
||||||
|
coin=0x33
|
||||||
|
; Input API selection for IO4 input emulator.
|
||||||
; Set "xinput" to use a gamepad and "dinput" to use a steering wheel.
|
; Set "xinput" to use a gamepad and "dinput" to use a steering wheel.
|
||||||
mode=xinput
|
mode=xinput
|
||||||
; Automatically reset the simulated shifter to Neutral when XInput Start is
|
; Automatically reset the simulated shifter to Neutral when XInput Start is
|
||||||
@ -59,7 +50,7 @@ mode=xinput
|
|||||||
autoNeutral=1
|
autoNeutral=1
|
||||||
; Use the left thumbstick for steering instead of both on XInput Controllers.
|
; Use the left thumbstick for steering instead of both on XInput Controllers.
|
||||||
; Not recommended as it will not give you the precision needed for this game
|
; Not recommended as it will not give you the precision needed for this game
|
||||||
singleStickSteering=0
|
singleStickSteering=1
|
||||||
; Adjust scaling for steering wheel input.
|
; Adjust scaling for steering wheel input.
|
||||||
;
|
;
|
||||||
; This setting scales the steering wheel input so that the maximum positive
|
; This setting scales the steering wheel input so that the maximum positive
|
||||||
|
6
dist/idac/start.bat
vendored
6
dist/idac/start.bat
vendored
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
start inject.exe -d -k idachook.dll amdaemon.exe -c config_common.json config_jp.json config_seat_1_jp.json config_seat_2_jp.json config_ex.json config_seat_1_ex.json config_seat_2_ex.json
|
REM start /min inject.exe -d -k idachook.dll amdaemon.exe -f -c config_aime_high_ex.json config_aime_high_jp.json config_aime_normal_ex.json config_aime_normal_jp.json config_common.json config_ex.json config_jp.json config_laninstall_client_ex.json config_laninstall_client_jp.json config_laninstall_server_ex.json config_laninstall_server_jp.json config_seat_1_ex.json config_seat_1_jp.json config_seat_2_ex.json config_seat_2_jp.json config_seat_3_ex.json config_seat_3_jp.json config_seat_4_ex.json config_seat_4_jp.json config_seat_single_ex.json config_seat_single_jp.json
|
||||||
inject -d -k idachook.dll ../WindowsNoEditor/GameProject/Binaries/Win64/GameProject-Win64-Shipping.exe
|
start /min inject -d -k idachook.dll amdaemon.exe -f -c config_aime_normal_jp.json config_common.json config_jp.json config_laninstall_server_jp.json config_seat_1_jp.json
|
||||||
|
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject.exe -culture=ja launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
|
||||||
|
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo Game processes have terminated
|
echo Game processes have terminated
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "amex/amex.h"
|
|
||||||
#include "amex/config.h"
|
|
||||||
|
|
||||||
#include "board/config.h"
|
#include "board/config.h"
|
||||||
#include "board/sg-reader.h"
|
#include "board/sg-reader.h"
|
||||||
|
|
||||||
#include "gfxhook/config.h"
|
|
||||||
|
|
||||||
#include "hooklib/config.h"
|
#include "hooklib/config.h"
|
||||||
#include "hooklib/dvd.h"
|
#include "hooklib/dvd.h"
|
||||||
|
|
||||||
@ -26,7 +21,7 @@ void idac_dll_config_load(
|
|||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
GetPrivateProfileStringW(
|
GetPrivateProfileStringW(
|
||||||
L"idzio",
|
L"idacio",
|
||||||
L"path",
|
L"path",
|
||||||
L"",
|
L"",
|
||||||
cfg->path,
|
cfg->path,
|
||||||
@ -42,12 +37,11 @@ void idac_hook_config_load(
|
|||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
platform_config_load(&cfg->platform, filename);
|
platform_config_load(&cfg->platform, filename);
|
||||||
amex_config_load(&cfg->amex, filename);
|
|
||||||
aime_config_load(&cfg->aime, filename);
|
aime_config_load(&cfg->aime, filename);
|
||||||
dvd_config_load(&cfg->dvd, filename);
|
|
||||||
// gfx_config_load(&cfg->gfx, filename);
|
|
||||||
idac_dll_config_load(&cfg->dll, filename);
|
idac_dll_config_load(&cfg->dll, filename);
|
||||||
zinput_config_load(&cfg->zinput, filename);
|
zinput_config_load(&cfg->zinput, filename);
|
||||||
|
dvd_config_load(&cfg->dvd, filename);
|
||||||
|
io4_config_load(&cfg->io4, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void zinput_config_load(struct zinput_config *cfg, const wchar_t *filename)
|
void zinput_config_load(struct zinput_config *cfg, const wchar_t *filename)
|
||||||
|
@ -3,11 +3,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "amex/amex.h"
|
#include "board/config.h"
|
||||||
|
|
||||||
#include "board/sg-reader.h"
|
|
||||||
|
|
||||||
#include "gfxhook/gfx.h"
|
|
||||||
|
|
||||||
#include "hooklib/dvd.h"
|
#include "hooklib/dvd.h"
|
||||||
|
|
||||||
@ -18,9 +14,9 @@
|
|||||||
|
|
||||||
struct idac_hook_config {
|
struct idac_hook_config {
|
||||||
struct platform_config platform;
|
struct platform_config platform;
|
||||||
struct amex_config amex;
|
|
||||||
struct aime_config aime;
|
struct aime_config aime;
|
||||||
struct dvd_config dvd;
|
struct dvd_config dvd;
|
||||||
|
struct io4_config io4;
|
||||||
struct idac_dll_config dll;
|
struct idac_dll_config dll;
|
||||||
struct zinput_config zinput;
|
struct zinput_config zinput;
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,11 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wchar.h>
|
|
||||||
|
|
||||||
#include "amex/amex.h"
|
|
||||||
|
|
||||||
#include "board/sg-reader.h"
|
#include "board/sg-reader.h"
|
||||||
|
#include "board/io4.h"
|
||||||
// #include "gfxhook/d3d11.h"
|
#include "board/vfd.h"
|
||||||
// #include "gfxhook/dxgi.h"
|
|
||||||
// #include "gfxhook/gfx.h"
|
|
||||||
|
|
||||||
#include "hook/process.h"
|
#include "hook/process.h"
|
||||||
|
|
||||||
@ -21,13 +15,12 @@
|
|||||||
|
|
||||||
#include "idachook/config.h"
|
#include "idachook/config.h"
|
||||||
#include "idachook/idac-dll.h"
|
#include "idachook/idac-dll.h"
|
||||||
#include "idachook/jvs.h"
|
#include "idachook/io4.h"
|
||||||
#include "idachook/zinput.h"
|
#include "idachook/zinput.h"
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/lib.h"
|
|
||||||
|
|
||||||
static HMODULE idac_hook_mod;
|
static HMODULE idac_hook_mod;
|
||||||
static process_entry_t idac_startup;
|
static process_entry_t idac_startup;
|
||||||
@ -35,8 +28,6 @@ static struct idac_hook_config idac_hook_cfg;
|
|||||||
|
|
||||||
static DWORD CALLBACK idac_pre_startup(void)
|
static DWORD CALLBACK idac_pre_startup(void)
|
||||||
{
|
{
|
||||||
wchar_t *module_path;
|
|
||||||
wchar_t *file_name;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
dprintf("--- Begin idac_pre_startup ---\n");
|
dprintf("--- Begin idac_pre_startup ---\n");
|
||||||
@ -45,33 +36,9 @@ static DWORD CALLBACK idac_pre_startup(void)
|
|||||||
|
|
||||||
idac_hook_config_load(&idac_hook_cfg, L".\\segatools.ini");
|
idac_hook_config_load(&idac_hook_cfg, L".\\segatools.ini");
|
||||||
|
|
||||||
/*
|
|
||||||
module_path = module_file_name(NULL);
|
|
||||||
|
|
||||||
if (module_path != NULL) {
|
|
||||||
file_name = PathFindFileNameW(module_path);
|
|
||||||
|
|
||||||
_wcslwr(file_name);
|
|
||||||
|
|
||||||
if (wcsstr(file_name, L"serverbox") != NULL) {
|
|
||||||
dprintf("Executable filename contains 'ServerBox', disabling full-screen mode\n");
|
|
||||||
|
|
||||||
idac_hook_cfg.gfx.windowed = true;
|
|
||||||
idac_hook_cfg.gfx.framed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(module_path);
|
|
||||||
|
|
||||||
module_path = NULL;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Hook Win32 APIs */
|
/* Hook Win32 APIs */
|
||||||
|
|
||||||
serial_hook_init();
|
serial_hook_init();
|
||||||
// gfx_hook_init(&idac_hook_cfg.gfx);
|
|
||||||
// gfx_d3d11_hook_init(&idac_hook_cfg.gfx, idac_hook_mod);
|
|
||||||
// gfx_dxgi_hook_init(&idac_hook_cfg.gfx, idac_hook_mod);
|
|
||||||
zinput_hook_init(&idac_hook_cfg.zinput);
|
zinput_hook_init(&idac_hook_cfg.zinput);
|
||||||
dvd_hook_init(&idac_hook_cfg.dvd, idac_hook_mod);
|
dvd_hook_init(&idac_hook_cfg.dvd, idac_hook_mod);
|
||||||
|
|
||||||
@ -80,26 +47,33 @@ static DWORD CALLBACK idac_pre_startup(void)
|
|||||||
hr = platform_hook_init(
|
hr = platform_hook_init(
|
||||||
&idac_hook_cfg.platform,
|
&idac_hook_cfg.platform,
|
||||||
"SDGT",
|
"SDGT",
|
||||||
"ACA2",
|
"ACA4",
|
||||||
idac_hook_mod);
|
idac_hook_mod);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = sg_reader_hook_init(&idac_hook_cfg.aime, 3, idac_hook_mod);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not needed?
|
||||||
|
hr = vfd_hook_init(4);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod);
|
hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = amex_hook_init(&idac_hook_cfg.amex, idac_jvs_init);
|
hr = idac_io4_hook_init(&idac_hook_cfg.io4);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = sg_reader_hook_init(&idac_hook_cfg.aime, 10, idac_hook_mod);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -10,20 +10,23 @@
|
|||||||
|
|
||||||
const struct dll_bind_sym idac_dll_syms[] = {
|
const struct dll_bind_sym idac_dll_syms[] = {
|
||||||
{
|
{
|
||||||
.sym = "idac_io_jvs_init",
|
.sym = "idac_io_init",
|
||||||
.off = offsetof(struct idac_dll, jvs_init),
|
.off = offsetof(struct idac_dll, init),
|
||||||
}, {
|
}, {
|
||||||
.sym = "idac_io_jvs_read_analogs",
|
.sym = "idac_io_poll",
|
||||||
.off = offsetof(struct idac_dll, jvs_read_analogs),
|
.off = offsetof(struct idac_dll, poll),
|
||||||
}, {
|
}, {
|
||||||
.sym = "idac_io_jvs_read_buttons",
|
.sym = "idac_io_get_opbtns",
|
||||||
.off = offsetof(struct idac_dll, jvs_read_buttons),
|
.off = offsetof(struct idac_dll, get_opbtns),
|
||||||
}, {
|
}, {
|
||||||
.sym = "idac_io_jvs_read_shifter",
|
.sym = "idac_io_get_gamebtns",
|
||||||
.off = offsetof(struct idac_dll, jvs_read_shifter),
|
.off = offsetof(struct idac_dll, get_gamebtns),
|
||||||
}, {
|
}, {
|
||||||
.sym = "idac_io_jvs_read_coin_counter",
|
.sym = "idac_io_get_shifter",
|
||||||
.off = offsetof(struct idac_dll, jvs_read_coin_counter),
|
.off = offsetof(struct idac_dll, get_shifter),
|
||||||
|
}, {
|
||||||
|
.sym = "idac_io_get_analogs",
|
||||||
|
.off = offsetof(struct idac_dll, get_analogs),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -51,14 +54,14 @@ HRESULT idac_dll_init(const struct idac_dll_config *cfg, HINSTANCE self)
|
|||||||
|
|
||||||
if (owned == NULL) {
|
if (owned == NULL) {
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
dprintf("IDZ IO: Failed to load IO DLL: %lx: %S\n",
|
dprintf("IDAC IO: Failed to load IO DLL: %lx: %S\n",
|
||||||
hr,
|
hr,
|
||||||
cfg->path);
|
cfg->path);
|
||||||
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf("IDZ IO: Using custom IO DLL: %S\n", cfg->path);
|
dprintf("IDAC IO: Using custom IO DLL: %S\n", cfg->path);
|
||||||
src = owned;
|
src = owned;
|
||||||
} else {
|
} else {
|
||||||
owned = NULL;
|
owned = NULL;
|
||||||
@ -78,7 +81,7 @@ HRESULT idac_dll_init(const struct idac_dll_config *cfg, HINSTANCE self)
|
|||||||
|
|
||||||
if (idac_dll.api_version >= 0x0200) {
|
if (idac_dll.api_version >= 0x0200) {
|
||||||
hr = E_NOTIMPL;
|
hr = E_NOTIMPL;
|
||||||
dprintf("IDZ IO: Custom IO DLL implements an unsupported "
|
dprintf("IDAC IO: Custom IO DLL implements an unsupported "
|
||||||
"API version (%#04x). Please update Segatools.\n",
|
"API version (%#04x). Please update Segatools.\n",
|
||||||
idac_dll.api_version);
|
idac_dll.api_version);
|
||||||
|
|
||||||
@ -90,7 +93,7 @@ HRESULT idac_dll_init(const struct idac_dll_config *cfg, HINSTANCE self)
|
|||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
if (src != self) {
|
if (src != self) {
|
||||||
dprintf("IDZ IO: Custom IO DLL does not provide function "
|
dprintf("IDAC IO: Custom IO DLL does not provide function "
|
||||||
"\"%s\". Please contact your IO DLL's developer for "
|
"\"%s\". Please contact your IO DLL's developer for "
|
||||||
"further assistance.\n",
|
"further assistance.\n",
|
||||||
sym->sym);
|
sym->sym);
|
||||||
|
@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
struct idac_dll {
|
struct idac_dll {
|
||||||
uint16_t api_version;
|
uint16_t api_version;
|
||||||
HRESULT (*jvs_init)(void);
|
HRESULT (*init)(void);
|
||||||
void (*jvs_read_analogs)(struct idac_io_analog_state *out);
|
HRESULT (*poll)(void);
|
||||||
void (*jvs_read_buttons)(uint8_t *opbtn, uint8_t *gamebtn);
|
void (*get_opbtns)(uint8_t *opbtn);
|
||||||
void (*jvs_read_shifter)(uint8_t *gear);
|
void (*get_gamebtns)(uint8_t *gamebtn);
|
||||||
void (*jvs_read_coin_counter)(uint16_t *total);
|
void (*get_shifter)(uint8_t *gear);
|
||||||
|
void (*get_analogs)(struct idac_io_analog_state *out);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct idac_dll_config {
|
struct idac_dll_config {
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
LIBRARY idachook
|
|
||||||
|
|
||||||
EXPORTS
|
|
||||||
CreateDXGIFactory
|
|
||||||
CreateDXGIFactory1
|
|
||||||
CreateDXGIFactory2
|
|
||||||
D3D11CreateDevice
|
|
||||||
D3D11CreateDeviceAndSwapChain
|
|
||||||
aime_io_get_api_version
|
|
||||||
aime_io_init
|
|
||||||
aime_io_led_set_color
|
|
||||||
aime_io_nfc_get_aime_id
|
|
||||||
aime_io_nfc_get_felica_id
|
|
||||||
aime_io_nfc_poll
|
|
||||||
amDllVideoClose @2
|
|
||||||
amDllVideoGetVBiosVersion @4
|
|
||||||
amDllVideoOpen @1
|
|
||||||
amDllVideoSetResolution @3
|
|
||||||
idac_io_get_api_version
|
|
||||||
idac_io_jvs_init
|
|
||||||
idac_io_jvs_read_analogs
|
|
||||||
idac_io_jvs_read_buttons
|
|
||||||
idac_io_jvs_read_coin_counter
|
|
||||||
idac_io_jvs_read_shifter
|
|
@ -12,8 +12,9 @@ EXPORTS
|
|||||||
amDllVideoOpen @1
|
amDllVideoOpen @1
|
||||||
amDllVideoSetResolution @3
|
amDllVideoSetResolution @3
|
||||||
idac_io_get_api_version
|
idac_io_get_api_version
|
||||||
idac_io_jvs_init
|
idac_io_init
|
||||||
idac_io_jvs_read_analogs
|
idac_io_poll
|
||||||
idac_io_jvs_read_buttons
|
idac_io_get_opbtns
|
||||||
idac_io_jvs_read_coin_counter
|
idac_io_get_gamebtns
|
||||||
idac_io_jvs_read_shifter
|
idac_io_get_shifter
|
||||||
|
idac_io_get_analogs
|
||||||
|
138
idachook/io4.c
Normal file
138
idachook/io4.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "board/io4.h"
|
||||||
|
|
||||||
|
#include "idachook/idac-dll.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static HRESULT idac_io4_poll(void *ctx, struct io4_state *state);
|
||||||
|
static uint16_t coins;
|
||||||
|
|
||||||
|
static const struct io4_ops idac_io4_ops = {
|
||||||
|
.poll = idac_io4_poll,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint16_t idac_gear_signals[] = {
|
||||||
|
/* Neutral */
|
||||||
|
0x0000,
|
||||||
|
/* 1: Left|Up */
|
||||||
|
0x0028,
|
||||||
|
/* 2: Left|Down */
|
||||||
|
0x0018,
|
||||||
|
/* 3: Up */
|
||||||
|
0x0020,
|
||||||
|
/* 4: Down */
|
||||||
|
0x0010,
|
||||||
|
/* 5: Right|Up */
|
||||||
|
0x0024,
|
||||||
|
/* 6: Right|Down */
|
||||||
|
0x0014,
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT idac_io4_hook_init(const struct io4_config *cfg)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(idac_dll.init != NULL);
|
||||||
|
|
||||||
|
hr = io4_hook_init(cfg, &idac_io4_ops, NULL);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idac_dll.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT idac_io4_poll(void *ctx, struct io4_state *state)
|
||||||
|
{
|
||||||
|
uint8_t opbtn;
|
||||||
|
uint8_t gamebtn;
|
||||||
|
uint8_t gear;
|
||||||
|
struct idac_io_analog_state analog_state;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(idac_dll.poll != NULL);
|
||||||
|
assert(idac_dll.get_opbtns != NULL);
|
||||||
|
assert(idac_dll.get_gamebtns != NULL);
|
||||||
|
assert(idac_dll.get_analogs != NULL);
|
||||||
|
assert(idac_dll.get_shifter != NULL);
|
||||||
|
|
||||||
|
memset(state, 0, sizeof(*state));
|
||||||
|
memset(&analog_state, 0, sizeof(analog_state));
|
||||||
|
|
||||||
|
hr = idac_dll.poll();
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
opbtn = 0;
|
||||||
|
gamebtn = 0;
|
||||||
|
gear = 0;
|
||||||
|
|
||||||
|
idac_dll.get_opbtns(&opbtn);
|
||||||
|
idac_dll.get_gamebtns(&gamebtn);
|
||||||
|
idac_dll.get_shifter(&gear);
|
||||||
|
idac_dll.get_analogs(&analog_state);
|
||||||
|
|
||||||
|
if (opbtn & IDAC_IO_OPBTN_TEST) {
|
||||||
|
state->buttons[0] |= IO4_BUTTON_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opbtn & IDAC_IO_OPBTN_SERVICE) {
|
||||||
|
state->buttons[0] |= IO4_BUTTON_SERVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opbtn & IDAC_IO_OPBTN_COIN) {
|
||||||
|
coins++;
|
||||||
|
}
|
||||||
|
state->chutes[0] = coins << 8;
|
||||||
|
|
||||||
|
if (gamebtn & IDAC_IO_GAMEBTN_START) {
|
||||||
|
state->buttons[0] |= 1 << 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & IDAC_IO_GAMEBTN_VIEW_CHANGE) {
|
||||||
|
state->buttons[0] |= 1 << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & IDAC_IO_GAMEBTN_UP) {
|
||||||
|
state->buttons[0] |= 1 << 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & IDAC_IO_GAMEBTN_DOWN) {
|
||||||
|
state->buttons[0] |= 1 << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & IDAC_IO_GAMEBTN_LEFT) {
|
||||||
|
state->buttons[0] |= 1 << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & IDAC_IO_GAMEBTN_RIGHT) {
|
||||||
|
state->buttons[0] |= 1 << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update simulated six-speed shifter */
|
||||||
|
|
||||||
|
if (gear > 6) {
|
||||||
|
gear = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->buttons[1] = idac_gear_signals[gear];
|
||||||
|
|
||||||
|
/* Steering wheel increases left-to-right.
|
||||||
|
|
||||||
|
Use 0x8000 as the center point. */
|
||||||
|
|
||||||
|
state->adcs[0] = 0x8000 + analog_state.wheel;
|
||||||
|
state->adcs[1] = analog_state.accel;
|
||||||
|
state->adcs[2] = analog_state.brake;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
7
idachook/io4.h
Normal file
7
idachook/io4.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "board/io4.h"
|
||||||
|
|
||||||
|
HRESULT idac_io4_hook_init(const struct io4_config *cfg);
|
177
idachook/jvs.c
177
idachook/jvs.c
@ -1,177 +0,0 @@
|
|||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "amex/jvs.h"
|
|
||||||
|
|
||||||
#include "board/io3.h"
|
|
||||||
|
|
||||||
#include "idachook/idac-dll.h"
|
|
||||||
#include "idachook/jvs.h"
|
|
||||||
|
|
||||||
#include "jvs/jvs-bus.h"
|
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
|
||||||
|
|
||||||
static void idac_jvs_read_analogs(
|
|
||||||
void *ctx,
|
|
||||||
uint16_t *analogs,
|
|
||||||
uint8_t nanalogs);
|
|
||||||
static void idac_jvs_read_switches(void *ctx, struct io3_switch_state *out);
|
|
||||||
static void idac_jvs_read_coin_counter(
|
|
||||||
void *ctx,
|
|
||||||
uint8_t slot_no,
|
|
||||||
uint16_t *out);
|
|
||||||
|
|
||||||
static const struct io3_ops idac_jvs_io3_ops = {
|
|
||||||
.read_switches = idac_jvs_read_switches,
|
|
||||||
.read_analogs = idac_jvs_read_analogs,
|
|
||||||
.read_coin_counter = idac_jvs_read_coin_counter,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint16_t idac_jvs_gear_signals[] = {
|
|
||||||
/* Neutral */
|
|
||||||
0x0000,
|
|
||||||
/* 1: Left|Up */
|
|
||||||
0x2800,
|
|
||||||
/* 2: Left|Down */
|
|
||||||
0x1800,
|
|
||||||
/* 3: Up */
|
|
||||||
0x2000,
|
|
||||||
/* 4: Down */
|
|
||||||
0x1000,
|
|
||||||
/* 5: Right|Up */
|
|
||||||
0x2400,
|
|
||||||
/* 6: Right|Down */
|
|
||||||
0x1400,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct io3 idac_jvs_io3;
|
|
||||||
|
|
||||||
HRESULT idac_jvs_init(struct jvs_node **out)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
assert(out != NULL);
|
|
||||||
assert(idac_dll.jvs_init != NULL);
|
|
||||||
|
|
||||||
dprintf("JVS I/O: Starting Initial D Zero backend DLL\n");
|
|
||||||
hr = idac_dll.jvs_init();
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dprintf("JVS I/O: Backend error, I/O disconnected; %x\n", (int) hr);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
io3_init(&idac_jvs_io3, NULL, &idac_jvs_io3_ops, NULL);
|
|
||||||
*out = io3_to_jvs_node(&idac_jvs_io3);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void idac_jvs_read_switches(void *ctx, struct io3_switch_state *out)
|
|
||||||
{
|
|
||||||
uint8_t opbtn;
|
|
||||||
uint8_t gamebtn;
|
|
||||||
uint8_t gear;
|
|
||||||
|
|
||||||
assert(out != NULL);
|
|
||||||
assert(idac_dll.jvs_read_buttons != NULL);
|
|
||||||
assert(idac_dll.jvs_read_shifter != NULL);
|
|
||||||
|
|
||||||
opbtn = 0;
|
|
||||||
gamebtn = 0;
|
|
||||||
gear = 0;
|
|
||||||
|
|
||||||
idac_dll.jvs_read_buttons(&opbtn, &gamebtn);
|
|
||||||
idac_dll.jvs_read_shifter(&gear);
|
|
||||||
|
|
||||||
/* Update gameplay buttons */
|
|
||||||
|
|
||||||
if (gamebtn & IDAC_IO_GAMEBTN_UP) {
|
|
||||||
out->p1 |= 1 << 13;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamebtn & IDAC_IO_GAMEBTN_DOWN) {
|
|
||||||
out->p1 |= 1 << 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamebtn & IDAC_IO_GAMEBTN_LEFT) {
|
|
||||||
out->p1 |= 1 << 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamebtn & IDAC_IO_GAMEBTN_RIGHT) {
|
|
||||||
out->p1 |= 1 << 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamebtn & IDAC_IO_GAMEBTN_START) {
|
|
||||||
out->p1 |= 1 << 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamebtn & IDAC_IO_GAMEBTN_VIEW_CHANGE) {
|
|
||||||
out->p1 |= 1 << 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update simulated six-speed shifter */
|
|
||||||
|
|
||||||
if (gear > 6) {
|
|
||||||
gear = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
out->p2 = idac_jvs_gear_signals[gear];
|
|
||||||
|
|
||||||
/* Update test/service buttons */
|
|
||||||
|
|
||||||
if (opbtn & IDAC_IO_OPBTN_TEST) {
|
|
||||||
out->system = 0x80;
|
|
||||||
} else {
|
|
||||||
out->system = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opbtn & IDAC_IO_OPBTN_SERVICE) {
|
|
||||||
out->p1 |= 1 << 14;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void idac_jvs_read_analogs(
|
|
||||||
void *ctx,
|
|
||||||
uint16_t *analogs,
|
|
||||||
uint8_t nanalogs)
|
|
||||||
{
|
|
||||||
struct idac_io_analog_state state;
|
|
||||||
|
|
||||||
assert(analogs != NULL);
|
|
||||||
assert(idac_dll.jvs_read_analogs != NULL);
|
|
||||||
|
|
||||||
memset(&state, 0, sizeof(state));
|
|
||||||
idac_dll.jvs_read_analogs(&state);
|
|
||||||
|
|
||||||
if (nanalogs > 0) {
|
|
||||||
analogs[0] = 0x8000 + state.wheel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nanalogs > 1) {
|
|
||||||
analogs[1] = state.accel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nanalogs > 2) {
|
|
||||||
analogs[2] = state.brake;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void idac_jvs_read_coin_counter(
|
|
||||||
void *ctx,
|
|
||||||
uint8_t slot_no,
|
|
||||||
uint16_t *out)
|
|
||||||
{
|
|
||||||
assert(idac_dll.jvs_read_coin_counter != NULL);
|
|
||||||
|
|
||||||
if (slot_no > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
idac_dll.jvs_read_coin_counter(out);
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "jvs/jvs-bus.h"
|
|
||||||
|
|
||||||
HRESULT idac_jvs_init(struct jvs_node **root);
|
|
@ -13,12 +13,9 @@ shared_library(
|
|||||||
],
|
],
|
||||||
link_with : [
|
link_with : [
|
||||||
aimeio_lib,
|
aimeio_lib,
|
||||||
amex_lib,
|
|
||||||
board_lib,
|
board_lib,
|
||||||
# gfxhook_lib,
|
|
||||||
hooklib_lib,
|
hooklib_lib,
|
||||||
idacio_lib,
|
idacio_lib,
|
||||||
jvs_lib,
|
|
||||||
platform_lib,
|
platform_lib,
|
||||||
util_lib,
|
util_lib,
|
||||||
],
|
],
|
||||||
@ -28,8 +25,8 @@ shared_library(
|
|||||||
'dllmain.c',
|
'dllmain.c',
|
||||||
'idac-dll.c',
|
'idac-dll.c',
|
||||||
'idac-dll.h',
|
'idac-dll.h',
|
||||||
'jvs.c',
|
'io4.c',
|
||||||
'jvs.h',
|
'io4.h',
|
||||||
'zinput.c',
|
'zinput.c',
|
||||||
'zinput.h',
|
'zinput.h',
|
||||||
],
|
],
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#include "idacio/idacio.h"
|
#include "idacio/idacio.h"
|
||||||
|
|
||||||
struct idac_io_backend {
|
struct idac_io_backend {
|
||||||
void (*jvs_read_buttons)(uint8_t *gamebtn);
|
void (*get_opbtns)(uint8_t *opbtn);
|
||||||
void (*jvs_read_shifter)(uint8_t *gear);
|
void (*get_gamebtns)(uint8_t *gamebtn);
|
||||||
void (*jvs_read_analogs)(struct idac_io_analog_state *state);
|
void (*get_shifter)(uint8_t *gear);
|
||||||
|
void (*get_analogs)(struct idac_io_analog_state *state);
|
||||||
};
|
};
|
||||||
|
@ -77,7 +77,7 @@ void idac_xi_config_load(struct idac_xi_config *cfg, const wchar_t *filename)
|
|||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
cfg->single_stick_steering = GetPrivateProfileIntW(
|
cfg->single_stick_steering = GetPrivateProfileIntW(
|
||||||
L"io3",
|
L"io4",
|
||||||
L"singleStickSteering",
|
L"singleStickSteering",
|
||||||
0,
|
0,
|
||||||
filename);
|
filename);
|
||||||
@ -88,13 +88,13 @@ void idac_io_config_load(struct idac_io_config *cfg, const wchar_t *filename)
|
|||||||
assert(cfg != NULL);
|
assert(cfg != NULL);
|
||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", '1', filename);
|
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", '1', filename);
|
||||||
cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", '2', filename);
|
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", '2', filename);
|
||||||
cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", '3', filename);
|
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", '3', filename);
|
||||||
cfg->restrict_ = GetPrivateProfileIntW(L"io3", L"restrict", 97, filename);
|
cfg->restrict_ = GetPrivateProfileIntW(L"io4", L"restrict", 97, filename);
|
||||||
|
|
||||||
GetPrivateProfileStringW(
|
GetPrivateProfileStringW(
|
||||||
L"io3",
|
L"io4",
|
||||||
L"mode",
|
L"mode",
|
||||||
L"xinput",
|
L"xinput",
|
||||||
cfg->mode,
|
cfg->mode,
|
||||||
@ -114,7 +114,7 @@ void idac_shifter_config_load(
|
|||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
cfg->auto_neutral = GetPrivateProfileIntW(
|
cfg->auto_neutral = GetPrivateProfileIntW(
|
||||||
L"io3",
|
L"io4",
|
||||||
L"autoNeutral",
|
L"autoNeutral",
|
||||||
0,
|
0,
|
||||||
filename);
|
filename);
|
||||||
|
34
idacio/di.c
34
idacio/di.c
@ -29,12 +29,12 @@ static BOOL CALLBACK idac_di_enum_callback(
|
|||||||
static BOOL CALLBACK idac_di_enum_callback_shifter(
|
static BOOL CALLBACK idac_di_enum_callback_shifter(
|
||||||
const DIDEVICEINSTANCEW *dev,
|
const DIDEVICEINSTANCEW *dev,
|
||||||
void *ctx);
|
void *ctx);
|
||||||
static void idac_di_jvs_read_buttons(uint8_t *gamebtn_out);
|
static void idac_di_get_buttons(uint8_t *gamebtn_out);
|
||||||
static uint8_t idac_di_decode_pov(DWORD pov);
|
static uint8_t idac_di_decode_pov(DWORD pov);
|
||||||
static void idac_di_jvs_read_shifter(uint8_t *gear);
|
static void idac_di_get_shifter(uint8_t *gear);
|
||||||
static void idac_di_jvs_read_shifter_pos(uint8_t *gear);
|
static void idac_di_get_shifter_pos(uint8_t *gear);
|
||||||
static void idac_di_jvs_read_shifter_virt(uint8_t *gear);
|
static void idac_di_get_shifter_virt(uint8_t *gear);
|
||||||
static void idac_di_jvs_read_analogs(struct idac_io_analog_state *out);
|
static void idac_di_get_analogs(struct idac_io_analog_state *out);
|
||||||
|
|
||||||
static const struct idac_di_axis idac_di_axes[] = {
|
static const struct idac_di_axis idac_di_axes[] = {
|
||||||
/* Just map DIJOYSTATE for now, we can map DIJOYSTATE2 later if needed */
|
/* Just map DIJOYSTATE for now, we can map DIJOYSTATE2 later if needed */
|
||||||
@ -49,9 +49,9 @@ static const struct idac_di_axis idac_di_axes[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct idac_io_backend idac_di_backend = {
|
static const struct idac_io_backend idac_di_backend = {
|
||||||
.jvs_read_buttons = idac_di_jvs_read_buttons,
|
.get_gamebtns = idac_di_get_buttons,
|
||||||
.jvs_read_shifter = idac_di_jvs_read_shifter,
|
.get_shifter = idac_di_get_shifter,
|
||||||
.jvs_read_analogs = idac_di_jvs_read_analogs,
|
.get_analogs = idac_di_get_analogs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static HWND idac_di_wnd;
|
static HWND idac_di_wnd;
|
||||||
@ -98,8 +98,8 @@ HRESULT idac_di_init(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initial D Zero has some built-in DirectInput support that is not
|
/* Initial D Zero has some built-in DirectInput support that is not
|
||||||
particularly useful. idzhook shorts this out by redirecting dinput8.dll
|
particularly useful. idachook shorts this out by redirecting dinput8.dll
|
||||||
to a no-op implementation of DirectInput. However, idzio does need to
|
to a no-op implementation of DirectInput. However, idacio does need to
|
||||||
talk to the real operating system implementation of DirectInput without
|
talk to the real operating system implementation of DirectInput without
|
||||||
the stub DLL interfering, so build a path to
|
the stub DLL interfering, so build a path to
|
||||||
C:\Windows\System32\dinput.dll here. */
|
C:\Windows\System32\dinput.dll here. */
|
||||||
@ -374,7 +374,7 @@ static BOOL CALLBACK idac_di_enum_callback_shifter(
|
|||||||
return DIENUM_STOP;
|
return DIENUM_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_di_jvs_read_buttons(uint8_t *gamebtn_out)
|
static void idac_di_get_buttons(uint8_t *gamebtn_out)
|
||||||
{
|
{
|
||||||
union idac_di_state state;
|
union idac_di_state state;
|
||||||
uint8_t gamebtn;
|
uint8_t gamebtn;
|
||||||
@ -416,18 +416,18 @@ static uint8_t idac_di_decode_pov(DWORD pov)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_di_jvs_read_shifter(uint8_t *gear)
|
static void idac_di_get_shifter(uint8_t *gear)
|
||||||
{
|
{
|
||||||
assert(gear != NULL);
|
assert(gear != NULL);
|
||||||
|
|
||||||
if (idac_di_shifter != NULL) {
|
if (idac_di_shifter != NULL) {
|
||||||
idac_di_jvs_read_shifter_pos(gear);
|
idac_di_get_shifter_pos(gear);
|
||||||
} else {
|
} else {
|
||||||
idac_di_jvs_read_shifter_virt(gear);
|
idac_di_get_shifter_virt(gear);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_di_jvs_read_shifter_pos(uint8_t *out)
|
static void idac_di_get_shifter_pos(uint8_t *out)
|
||||||
{
|
{
|
||||||
union idac_di_state state;
|
union idac_di_state state;
|
||||||
uint8_t btn_no;
|
uint8_t btn_no;
|
||||||
@ -457,7 +457,7 @@ static void idac_di_jvs_read_shifter_pos(uint8_t *out)
|
|||||||
*out = gear;
|
*out = gear;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_di_jvs_read_shifter_virt(uint8_t *gear)
|
static void idac_di_get_shifter_virt(uint8_t *gear)
|
||||||
{
|
{
|
||||||
union idac_di_state state;
|
union idac_di_state state;
|
||||||
bool shift_dn;
|
bool shift_dn;
|
||||||
@ -489,7 +489,7 @@ static void idac_di_jvs_read_shifter_virt(uint8_t *gear)
|
|||||||
*gear = idac_shifter_current_gear();
|
*gear = idac_shifter_current_gear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_di_jvs_read_analogs(struct idac_io_analog_state *out)
|
static void idac_di_get_analogs(struct idac_io_analog_state *out)
|
||||||
{
|
{
|
||||||
union idac_di_state state;
|
union idac_di_state state;
|
||||||
const LONG *brake;
|
const LONG *brake;
|
||||||
|
@ -16,14 +16,13 @@
|
|||||||
static struct idac_io_config idac_io_cfg;
|
static struct idac_io_config idac_io_cfg;
|
||||||
static const struct idac_io_backend *idac_io_backend;
|
static const struct idac_io_backend *idac_io_backend;
|
||||||
static bool idac_io_coin;
|
static bool idac_io_coin;
|
||||||
static uint16_t idac_io_coins;
|
|
||||||
|
|
||||||
uint16_t idac_io_get_api_version(void)
|
uint16_t idac_io_get_api_version(void)
|
||||||
{
|
{
|
||||||
return 0x0100;
|
return 0x0100;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT idac_io_jvs_init(void)
|
HRESULT idac_io_init(void)
|
||||||
{
|
{
|
||||||
HINSTANCE inst;
|
HINSTANCE inst;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
@ -47,20 +46,19 @@ HRESULT idac_io_jvs_init(void)
|
|||||||
hr = idac_xi_init(&idac_io_cfg.xi, &idac_io_backend);
|
hr = idac_xi_init(&idac_io_cfg.xi, &idac_io_backend);
|
||||||
} else {
|
} else {
|
||||||
hr = E_INVALIDARG;
|
hr = E_INVALIDARG;
|
||||||
dprintf("IDZ IO: Invalid IO mode \"%S\", use dinput or xinput\n",
|
dprintf("IDAC IO: Invalid IO mode \"%S\", use dinput or xinput\n",
|
||||||
idac_io_cfg.mode);
|
idac_io_cfg.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idac_io_jvs_read_buttons(uint8_t *opbtn_out, uint8_t *gamebtn_out)
|
void idac_io_get_opbtns(uint8_t *opbtn_out)
|
||||||
{
|
{
|
||||||
uint8_t opbtn;
|
uint8_t opbtn;
|
||||||
|
|
||||||
assert(idac_io_backend != NULL);
|
assert(idac_io_backend != NULL);
|
||||||
assert(opbtn_out != NULL);
|
assert(opbtn_out != NULL);
|
||||||
assert(gamebtn_out != NULL);
|
|
||||||
|
|
||||||
opbtn = 0;
|
opbtn = 0;
|
||||||
|
|
||||||
@ -72,27 +70,43 @@ void idac_io_jvs_read_buttons(uint8_t *opbtn_out, uint8_t *gamebtn_out)
|
|||||||
opbtn |= IDAC_IO_OPBTN_SERVICE;
|
opbtn |= IDAC_IO_OPBTN_SERVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*opbtn_out = opbtn;
|
if (GetAsyncKeyState(idac_io_cfg.vk_coin) & 0x8000) {
|
||||||
|
if (!idac_io_coin) {
|
||||||
|
idac_io_coin = true;
|
||||||
|
opbtn |= IDAC_IO_OPBTN_COIN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
idac_io_coin = false;
|
||||||
|
}
|
||||||
|
|
||||||
idac_io_backend->jvs_read_buttons(gamebtn_out);
|
*opbtn_out = opbtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idac_io_jvs_read_shifter(uint8_t *gear)
|
|
||||||
|
void idac_io_get_gamebtns(uint8_t *gamebtn_out)
|
||||||
|
{
|
||||||
|
assert(idac_io_backend != NULL);
|
||||||
|
assert(gamebtn_out != NULL);
|
||||||
|
|
||||||
|
idac_io_backend->get_gamebtns(gamebtn_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idac_io_get_shifter(uint8_t *gear)
|
||||||
{
|
{
|
||||||
assert(gear != NULL);
|
assert(gear != NULL);
|
||||||
assert(idac_io_backend != NULL);
|
assert(idac_io_backend != NULL);
|
||||||
|
|
||||||
idac_io_backend->jvs_read_shifter(gear);
|
idac_io_backend->get_shifter(gear);
|
||||||
}
|
}
|
||||||
|
|
||||||
void idac_io_jvs_read_analogs(struct idac_io_analog_state *out)
|
void idac_io_get_analogs(struct idac_io_analog_state *out)
|
||||||
{
|
{
|
||||||
struct idac_io_analog_state tmp;
|
struct idac_io_analog_state tmp;
|
||||||
|
|
||||||
assert(out != NULL);
|
assert(out != NULL);
|
||||||
assert(idac_io_backend != NULL);
|
assert(idac_io_backend != NULL);
|
||||||
|
|
||||||
idac_io_backend->jvs_read_analogs(&tmp);
|
idac_io_backend->get_analogs(&tmp);
|
||||||
|
|
||||||
/* Apply steering wheel restriction. Real cabs only report about 77% of
|
/* Apply steering wheel restriction. Real cabs only report about 77% of
|
||||||
the IO-3's max ADC output value when the wheel is turned to either of
|
the IO-3's max ADC output value when the wheel is turned to either of
|
||||||
@ -104,22 +118,3 @@ void idac_io_jvs_read_analogs(struct idac_io_analog_state *out)
|
|||||||
out->accel = tmp.accel;
|
out->accel = tmp.accel;
|
||||||
out->brake = tmp.brake;
|
out->brake = tmp.brake;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idac_io_jvs_read_coin_counter(uint16_t *out)
|
|
||||||
{
|
|
||||||
assert(out != NULL);
|
|
||||||
|
|
||||||
/* Coin counter is not backend-specific */
|
|
||||||
|
|
||||||
if (idac_io_cfg.vk_coin &&
|
|
||||||
(GetAsyncKeyState(idac_io_cfg.vk_coin) & 0x8000)) {
|
|
||||||
if (!idac_io_coin) {
|
|
||||||
idac_io_coin = true;
|
|
||||||
idac_io_coins++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
idac_io_coin = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out = idac_io_coins;
|
|
||||||
}
|
|
||||||
|
9
idacio/idacio.def
Normal file
9
idacio/idacio.def
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
LIBRARY idacio
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
idac_io_init
|
||||||
|
idac_io_poll
|
||||||
|
idac_io_get_opbtns
|
||||||
|
idac_io_get_gamebtns
|
||||||
|
idac_io_get_shifter
|
||||||
|
idac_io_get_analogs
|
@ -1,17 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/* INITIAL D THE ARCADE CUSTOM IO API
|
|
||||||
|
|
||||||
This API definition allows custom driver DLLs to be defined for the
|
|
||||||
emulation of Initial D The Arcade cabinets. To be honest, there is very
|
|
||||||
little reason to want to do this, since driving game controllers are a
|
|
||||||
mostly-standardized PC peripheral which can be adequately controlled by the
|
|
||||||
built-in DirectInput and XInput support in idzhook. However, previous
|
|
||||||
versions of Segatools broke this functionality out into a separate DLL just
|
|
||||||
like all of the other supported games, so in the interests of maintaining
|
|
||||||
backwards compatibility we provide the option to load custom IDZIO
|
|
||||||
implementations as well. */
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -19,6 +7,7 @@
|
|||||||
enum {
|
enum {
|
||||||
IDAC_IO_OPBTN_TEST = 0x01,
|
IDAC_IO_OPBTN_TEST = 0x01,
|
||||||
IDAC_IO_OPBTN_SERVICE = 0x02,
|
IDAC_IO_OPBTN_SERVICE = 0x02,
|
||||||
|
IDAC_IO_OPBTN_COIN = 0x04,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -49,7 +38,7 @@ struct idac_io_analog_state {
|
|||||||
uint16_t brake;
|
uint16_t brake;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Get the version of the IDZ IO API that this DLL supports. This
|
/* Get the version of the IDAC IO API that this DLL supports. This
|
||||||
function should return a positive 16-bit integer, where the high byte is
|
function should return a positive 16-bit integer, where the high byte is
|
||||||
the major version and the low byte is the minor version (as defined by the
|
the major version and the low byte is the minor version (as defined by the
|
||||||
Semantic Versioning standard).
|
Semantic Versioning standard).
|
||||||
@ -58,33 +47,48 @@ struct idac_io_analog_state {
|
|||||||
|
|
||||||
uint16_t idac_io_get_api_version(void);
|
uint16_t idac_io_get_api_version(void);
|
||||||
|
|
||||||
/* Initialize JVS-based input. This function will be called before any other
|
/* Initialize the IO DLL. This is the second function that will be called on
|
||||||
idac_io_jvs_*() function calls. Errors returned from this function will
|
your DLL, after mu3_io_get_api_version.
|
||||||
manifest as a disconnected JVS bus.
|
|
||||||
|
|
||||||
All subsequent calls may originate from arbitrary threads and some may
|
All subsequent calls to this API may originate from arbitrary threads.
|
||||||
overlap with each other. Ensuring synchronization inside your IO DLL is
|
|
||||||
your responsibility.
|
|
||||||
|
|
||||||
Minimum API version: 0x0100 */
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
HRESULT idac_io_jvs_init(void);
|
HRESULT idac_io_init(void);
|
||||||
|
|
||||||
|
/* Send any queued outputs (of which there are currently none, though this may
|
||||||
|
change in subsequent API versions) and retrieve any new inputs.
|
||||||
|
|
||||||
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
HRESULT idac_io_poll(void);
|
||||||
|
|
||||||
|
/* Get the state of the cabinet's operator buttons as of the last poll. See
|
||||||
|
MU3_IO_OPBTN enum above: this contains bit mask definitions for button
|
||||||
|
states returned in *opbtn. All buttons are active-high.
|
||||||
|
|
||||||
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
void idac_io_get_opbtns(uint8_t *opbtn);
|
||||||
|
|
||||||
|
/* Get the state of the cabinet's gameplay buttons as of the last poll. See
|
||||||
|
MU3_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into
|
||||||
|
a left hand side set of inputs and a right hand side set of inputs: the bit
|
||||||
|
mappings are the same in both cases.
|
||||||
|
|
||||||
|
All buttons are active-high, even though some buttons' electrical signals
|
||||||
|
on a real cabinet are active-low.
|
||||||
|
|
||||||
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
void idac_io_get_gamebtns(uint8_t *gamebtn);
|
||||||
|
|
||||||
/* Poll the current state of the cabinet's JVS analog inputs. See structure
|
/* Poll the current state of the cabinet's JVS analog inputs. See structure
|
||||||
definition above for details.
|
definition above for details.
|
||||||
|
|
||||||
Minimum API version: 0x0100 */
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
void idac_io_jvs_read_analogs(struct idac_io_analog_state *out);
|
void idac_io_get_analogs(struct idac_io_analog_state *out);
|
||||||
|
|
||||||
/* Poll the current state of the cabinet's JVS input buttons and return them
|
|
||||||
through the opbtn and gamebtn out parameters. See enum definitions at the
|
|
||||||
top of this file for a list of bit masks to be used with these out
|
|
||||||
parameters.
|
|
||||||
|
|
||||||
Minimum API version: 0x0100 */
|
|
||||||
|
|
||||||
void idac_io_jvs_read_buttons(uint8_t *opbtn, uint8_t *gamebtn);
|
|
||||||
|
|
||||||
/* Poll the current position of the six-speed shifter and return it via the
|
/* Poll the current position of the six-speed shifter and return it via the
|
||||||
gear out parameter. Valid values are 0 for neutral and 1-6 for gears 1-6.
|
gear out parameter. Valid values are 0 for neutral and 1-6 for gears 1-6.
|
||||||
@ -95,12 +99,4 @@ void idac_io_jvs_read_buttons(uint8_t *opbtn, uint8_t *gamebtn);
|
|||||||
|
|
||||||
Minimum API version: 0x0100 */
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
void idac_io_jvs_read_shifter(uint8_t *gear);
|
void idac_io_get_shifter(uint8_t *gear);
|
||||||
|
|
||||||
/* Read the current state of the coin counter. This value should be incremented
|
|
||||||
for every coin detected by the coin acceptor mechanism. This count does not
|
|
||||||
need to persist beyond the lifetime of the process.
|
|
||||||
|
|
||||||
Minimum API version: 0x0100 */
|
|
||||||
|
|
||||||
void idac_io_jvs_read_coin_counter(uint16_t *total);
|
|
@ -1,8 +0,0 @@
|
|||||||
LIBRARY idacio
|
|
||||||
|
|
||||||
EXPORTS
|
|
||||||
idac_io_jvs_init
|
|
||||||
idac_io_jvs_read_analogs
|
|
||||||
idac_io_jvs_read_buttons
|
|
||||||
idac_io_jvs_read_coin_counter
|
|
||||||
idac_io_jvs_read_shifter
|
|
@ -1,14 +1,14 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "idzio/shifter.h"
|
#include "idacio/shifter.h"
|
||||||
|
|
||||||
static bool idac_shifter_shifting;
|
static bool idac_shifter_shifting;
|
||||||
static uint8_t idac_shifter_gear;
|
static uint8_t idac_shifter_gear;
|
||||||
|
|
||||||
void idac_shifter_reset(void)
|
void idac_shifter_set(uint8_t gear)
|
||||||
{
|
{
|
||||||
idac_shifter_gear = 0;
|
idac_shifter_gear = gear;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idac_shifter_update(bool shift_dn, bool shift_up)
|
void idac_shifter_update(bool shift_dn, bool shift_up)
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void idac_shifter_reset(void);
|
void idac_shifter_set(uint8_t gear);
|
||||||
void idac_shifter_update(bool shift_dn, bool shift_up);
|
void idac_shifter_update(bool shift_dn, bool shift_up);
|
||||||
uint8_t idac_shifter_current_gear(void);
|
uint8_t idac_shifter_current_gear(void);
|
||||||
|
@ -31,13 +31,13 @@ HRESULT idac_io_wnd_create(HINSTANCE inst, HWND *out)
|
|||||||
wcx.cbSize = sizeof(wcx);
|
wcx.cbSize = sizeof(wcx);
|
||||||
wcx.lpfnWndProc = idac_io_wnd_proc;
|
wcx.lpfnWndProc = idac_io_wnd_proc;
|
||||||
wcx.hInstance = inst;
|
wcx.hInstance = inst;
|
||||||
wcx.lpszClassName = L"IDZIO";
|
wcx.lpszClassName = L"IDACIO";
|
||||||
|
|
||||||
atom = RegisterClassExW(&wcx);
|
atom = RegisterClassExW(&wcx);
|
||||||
|
|
||||||
if (atom == 0) {
|
if (atom == 0) {
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
dprintf("IDZIO: RegisterClassExW failed: %08x\n", (int) hr);
|
dprintf("IDACIO: RegisterClassExW failed: %08x\n", (int) hr);
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ HRESULT idac_io_wnd_create(HINSTANCE inst, HWND *out)
|
|||||||
|
|
||||||
if (hwnd == NULL) {
|
if (hwnd == NULL) {
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
dprintf("IDZIO: CreateWindowExW failed: %08x\n", (int) hr);
|
dprintf("IDACIO: CreateWindowExW failed: %08x\n", (int) hr);
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
43
idacio/xi.c
43
idacio/xi.c
@ -13,16 +13,16 @@
|
|||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
static void idac_xi_jvs_read_buttons(uint8_t *gamebtn_out);
|
static void idac_xi_get_gamebtns(uint8_t *gamebtn_out);
|
||||||
static void idac_xi_jvs_read_shifter(uint8_t *gear);
|
static void idac_xi_get_shifter(uint8_t *gear);
|
||||||
static void idac_xi_jvs_read_analogs(struct idac_io_analog_state *out);
|
static void idac_xi_get_analogs(struct idac_io_analog_state *out);
|
||||||
|
|
||||||
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg);
|
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg);
|
||||||
|
|
||||||
static const struct idac_io_backend idac_xi_backend = {
|
static const struct idac_io_backend idac_xi_backend = {
|
||||||
.jvs_read_buttons = idac_xi_jvs_read_buttons,
|
.get_gamebtns = idac_xi_get_gamebtns,
|
||||||
.jvs_read_shifter = idac_xi_jvs_read_shifter,
|
.get_shifter = idac_xi_get_shifter,
|
||||||
.jvs_read_analogs = idac_xi_jvs_read_analogs,
|
.get_analogs = idac_xi_get_analogs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool idac_xi_single_stick_steering;
|
static bool idac_xi_single_stick_steering;
|
||||||
@ -45,6 +45,11 @@ HRESULT idac_xi_init(const struct idac_xi_config *cfg, const struct idac_io_back
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT idac_io_poll(void)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg)
|
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg)
|
||||||
{
|
{
|
||||||
dprintf("XInput: --- Begin configuration ---\n");
|
dprintf("XInput: --- Begin configuration ---\n");
|
||||||
@ -56,7 +61,7 @@ static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_xi_jvs_read_buttons(uint8_t *gamebtn_out)
|
static void idac_xi_get_gamebtns(uint8_t *gamebtn_out)
|
||||||
{
|
{
|
||||||
uint8_t gamebtn;
|
uint8_t gamebtn;
|
||||||
XINPUT_STATE xi;
|
XINPUT_STATE xi;
|
||||||
@ -97,7 +102,7 @@ static void idac_xi_jvs_read_buttons(uint8_t *gamebtn_out)
|
|||||||
*gamebtn_out = gamebtn;
|
*gamebtn_out = gamebtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_xi_jvs_read_shifter(uint8_t *gear)
|
static void idac_xi_get_shifter(uint8_t *gear)
|
||||||
{
|
{
|
||||||
bool shift_dn;
|
bool shift_dn;
|
||||||
bool shift_up;
|
bool shift_up;
|
||||||
@ -112,9 +117,25 @@ static void idac_xi_jvs_read_shifter(uint8_t *gear)
|
|||||||
|
|
||||||
if (xb & XINPUT_GAMEPAD_START) {
|
if (xb & XINPUT_GAMEPAD_START) {
|
||||||
/* Reset to Neutral when start is pressed */
|
/* Reset to Neutral when start is pressed */
|
||||||
idac_shifter_reset();
|
idac_shifter_set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Alternative shifting mode
|
||||||
|
if (xb & XINPUT_GAMEPAD_X) {
|
||||||
|
// Set to Gear 2 when X is pressed
|
||||||
|
idac_shifter_set(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xb & XINPUT_GAMEPAD_Y) {
|
||||||
|
// Set to Gear 3 when Y is pressed
|
||||||
|
idac_shifter_set(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
shift_dn = xb & XINPUT_GAMEPAD_LEFT_SHOULDER;
|
||||||
|
shift_up = xb & XINPUT_GAMEPAD_RIGHT_SHOULDER;
|
||||||
|
*/
|
||||||
|
|
||||||
shift_dn = xb & (XINPUT_GAMEPAD_Y | XINPUT_GAMEPAD_LEFT_SHOULDER);
|
shift_dn = xb & (XINPUT_GAMEPAD_Y | XINPUT_GAMEPAD_LEFT_SHOULDER);
|
||||||
shift_up = xb & (XINPUT_GAMEPAD_X | XINPUT_GAMEPAD_RIGHT_SHOULDER);
|
shift_up = xb & (XINPUT_GAMEPAD_X | XINPUT_GAMEPAD_RIGHT_SHOULDER);
|
||||||
|
|
||||||
@ -123,7 +144,7 @@ static void idac_xi_jvs_read_shifter(uint8_t *gear)
|
|||||||
*gear = idac_shifter_current_gear();
|
*gear = idac_shifter_current_gear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idac_xi_jvs_read_analogs(struct idac_io_analog_state *out)
|
static void idac_xi_get_analogs(struct idac_io_analog_state *out)
|
||||||
{
|
{
|
||||||
XINPUT_STATE xi;
|
XINPUT_STATE xi;
|
||||||
int left;
|
int left;
|
||||||
@ -154,7 +175,7 @@ static void idac_xi_jvs_read_analogs(struct idac_io_analog_state *out)
|
|||||||
right = 0;
|
right = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(idac_xi_single_stick_steering) {
|
if (idac_xi_single_stick_steering) {
|
||||||
out->wheel = left;
|
out->wheel = left;
|
||||||
} else {
|
} else {
|
||||||
out->wheel = (left + right) / 2;
|
out->wheel = (left + right) / 2;
|
||||||
|
Loading…
Reference in New Issue
Block a user