diff --git a/dist/idac/segatools.ini b/dist/idac/segatools.ini index 367d27e..aa408c5 100644 --- a/dist/idac/segatools.ini +++ b/dist/idac/segatools.ini @@ -13,14 +13,6 @@ appdata= ; Note that 127.0.0.1, localhost etc are specifically rejected. 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] ; 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 @@ -33,25 +25,24 @@ enable=1 ; that subnet must start with 192.168. 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] ; To use a custom card reader IO DLL enter its path here. ; Leave empty if you want to use Segatools built-in keyboard input. path= -[idzio] -; To use a custom Initial D Zero IO DLL enter its path here. +[idacio] +; 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. path= -[io3] -; Input API selection for JVS input emulator. +[io4] +; 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. mode=xinput ; Automatically reset the simulated shifter to Neutral when XInput Start is @@ -59,7 +50,7 @@ mode=xinput autoNeutral=1 ; 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 -singleStickSteering=0 +singleStickSteering=1 ; Adjust scaling for steering wheel input. ; ; This setting scales the steering wheel input so that the maximum positive diff --git a/dist/idac/start.bat b/dist/idac/start.bat index 61ed927..022d5ec 100644 --- a/dist/idac/start.bat +++ b/dist/idac/start.bat @@ -2,8 +2,10 @@ 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 -inject -d -k idachook.dll ../WindowsNoEditor/GameProject/Binaries/Win64/GameProject-Win64-Shipping.exe +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 +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 Game processes have terminated diff --git a/idachook/config.c b/idachook/config.c index 7e648bf..5452bf6 100644 --- a/idachook/config.c +++ b/idachook/config.c @@ -1,14 +1,9 @@ #include #include -#include "amex/amex.h" -#include "amex/config.h" - #include "board/config.h" #include "board/sg-reader.h" -#include "gfxhook/config.h" - #include "hooklib/config.h" #include "hooklib/dvd.h" @@ -26,7 +21,7 @@ void idac_dll_config_load( assert(filename != NULL); GetPrivateProfileStringW( - L"idzio", + L"idacio", L"path", L"", cfg->path, @@ -42,12 +37,11 @@ void idac_hook_config_load( assert(filename != NULL); platform_config_load(&cfg->platform, filename); - amex_config_load(&cfg->amex, 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); 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) diff --git a/idachook/config.h b/idachook/config.h index 674797e..9c7dfd7 100644 --- a/idachook/config.h +++ b/idachook/config.h @@ -3,11 +3,7 @@ #include #include -#include "amex/amex.h" - -#include "board/sg-reader.h" - -#include "gfxhook/gfx.h" +#include "board/config.h" #include "hooklib/dvd.h" @@ -18,9 +14,9 @@ struct idac_hook_config { struct platform_config platform; - struct amex_config amex; struct aime_config aime; struct dvd_config dvd; + struct io4_config io4; struct idac_dll_config dll; struct zinput_config zinput; }; diff --git a/idachook/dllmain.c b/idachook/dllmain.c index fcf44d9..ed64515 100644 --- a/idachook/dllmain.c +++ b/idachook/dllmain.c @@ -1,17 +1,11 @@ #include #include -#include #include -#include - -#include "amex/amex.h" #include "board/sg-reader.h" - -// #include "gfxhook/d3d11.h" -// #include "gfxhook/dxgi.h" -// #include "gfxhook/gfx.h" +#include "board/io4.h" +#include "board/vfd.h" #include "hook/process.h" @@ -21,13 +15,12 @@ #include "idachook/config.h" #include "idachook/idac-dll.h" -#include "idachook/jvs.h" +#include "idachook/io4.h" #include "idachook/zinput.h" #include "platform/platform.h" #include "util/dprintf.h" -#include "util/lib.h" static HMODULE idac_hook_mod; 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) { - wchar_t *module_path; - wchar_t *file_name; HRESULT hr; dprintf("--- Begin idac_pre_startup ---\n"); @@ -44,34 +35,10 @@ static DWORD CALLBACK idac_pre_startup(void) /* Config load */ 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 */ 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); 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( &idac_hook_cfg.platform, "SDGT", - "ACA2", + "ACA4", idac_hook_mod); if (FAILED(hr)) { 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); if (FAILED(hr)) { goto fail; } - hr = amex_hook_init(&idac_hook_cfg.amex, idac_jvs_init); - - if (FAILED(hr)) { - goto fail; - } - - hr = sg_reader_hook_init(&idac_hook_cfg.aime, 10, idac_hook_mod); + hr = idac_io4_hook_init(&idac_hook_cfg.io4); if (FAILED(hr)) { goto fail; @@ -109,7 +83,7 @@ static DWORD CALLBACK idac_pre_startup(void) spike_hook_init(L".\\segatools.ini"); - dprintf("--- End idac_pre_startup ---\n"); + dprintf("--- End idac_pre_startup ---\n"); /* Jump to EXE start address */ diff --git a/idachook/idac-dll.c b/idachook/idac-dll.c index 6346089..03a6a3e 100644 --- a/idachook/idac-dll.c +++ b/idachook/idac-dll.c @@ -10,20 +10,23 @@ const struct dll_bind_sym idac_dll_syms[] = { { - .sym = "idac_io_jvs_init", - .off = offsetof(struct idac_dll, jvs_init), + .sym = "idac_io_init", + .off = offsetof(struct idac_dll, init), }, { - .sym = "idac_io_jvs_read_analogs", - .off = offsetof(struct idac_dll, jvs_read_analogs), + .sym = "idac_io_poll", + .off = offsetof(struct idac_dll, poll), }, { - .sym = "idac_io_jvs_read_buttons", - .off = offsetof(struct idac_dll, jvs_read_buttons), + .sym = "idac_io_get_opbtns", + .off = offsetof(struct idac_dll, get_opbtns), }, { - .sym = "idac_io_jvs_read_shifter", - .off = offsetof(struct idac_dll, jvs_read_shifter), + .sym = "idac_io_get_gamebtns", + .off = offsetof(struct idac_dll, get_gamebtns), }, { - .sym = "idac_io_jvs_read_coin_counter", - .off = offsetof(struct idac_dll, jvs_read_coin_counter), + .sym = "idac_io_get_shifter", + .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) { 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, cfg->path); 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; } else { owned = NULL; @@ -78,7 +81,7 @@ HRESULT idac_dll_init(const struct idac_dll_config *cfg, HINSTANCE self) if (idac_dll.api_version >= 0x0200) { 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", idac_dll.api_version); @@ -90,7 +93,7 @@ HRESULT idac_dll_init(const struct idac_dll_config *cfg, HINSTANCE self) if (FAILED(hr)) { 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 " "further assistance.\n", sym->sym); diff --git a/idachook/idac-dll.h b/idachook/idac-dll.h index 88902ed..7db5639 100644 --- a/idachook/idac-dll.h +++ b/idachook/idac-dll.h @@ -6,11 +6,12 @@ struct idac_dll { uint16_t api_version; - HRESULT (*jvs_init)(void); - void (*jvs_read_analogs)(struct idac_io_analog_state *out); - void (*jvs_read_buttons)(uint8_t *opbtn, uint8_t *gamebtn); - void (*jvs_read_shifter)(uint8_t *gear); - void (*jvs_read_coin_counter)(uint16_t *total); + HRESULT (*init)(void); + HRESULT (*poll)(void); + void (*get_opbtns)(uint8_t *opbtn); + void (*get_gamebtns)(uint8_t *gamebtn); + void (*get_shifter)(uint8_t *gear); + void (*get_analogs)(struct idac_io_analog_state *out); }; struct idac_dll_config { diff --git a/idachook/idachook copy.def b/idachook/idachook copy.def deleted file mode 100644 index a46fa06..0000000 --- a/idachook/idachook copy.def +++ /dev/null @@ -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 diff --git a/idachook/idachook.def b/idachook/idachook.def index 68ed1d0..4c944fd 100644 --- a/idachook/idachook.def +++ b/idachook/idachook.def @@ -12,8 +12,9 @@ EXPORTS 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 + idac_io_init + idac_io_poll + idac_io_get_opbtns + idac_io_get_gamebtns + idac_io_get_shifter + idac_io_get_analogs diff --git a/idachook/io4.c b/idachook/io4.c new file mode 100644 index 0000000..3d2eec5 --- /dev/null +++ b/idachook/io4.c @@ -0,0 +1,138 @@ +#include + +#include +#include +#include + +#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; +} diff --git a/idachook/io4.h b/idachook/io4.h new file mode 100644 index 0000000..af2ded1 --- /dev/null +++ b/idachook/io4.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "board/io4.h" + +HRESULT idac_io4_hook_init(const struct io4_config *cfg); diff --git a/idachook/jvs.c b/idachook/jvs.c deleted file mode 100644 index 2192c24..0000000 --- a/idachook/jvs.c +++ /dev/null @@ -1,177 +0,0 @@ -#include - -#include -#include -#include - -#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); -} diff --git a/idachook/jvs.h b/idachook/jvs.h deleted file mode 100644 index f0781a4..0000000 --- a/idachook/jvs.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -#include "jvs/jvs-bus.h" - -HRESULT idac_jvs_init(struct jvs_node **root); diff --git a/idachook/meson.build b/idachook/meson.build index 3a3369d..81c2c7b 100644 --- a/idachook/meson.build +++ b/idachook/meson.build @@ -13,12 +13,9 @@ shared_library( ], link_with : [ aimeio_lib, - amex_lib, board_lib, - # gfxhook_lib, hooklib_lib, idacio_lib, - jvs_lib, platform_lib, util_lib, ], @@ -28,8 +25,8 @@ shared_library( 'dllmain.c', 'idac-dll.c', 'idac-dll.h', - 'jvs.c', - 'jvs.h', + 'io4.c', + 'io4.h', 'zinput.c', 'zinput.h', ], diff --git a/idacio/backend.h b/idacio/backend.h index 46daa0b..b9833a1 100644 --- a/idacio/backend.h +++ b/idacio/backend.h @@ -5,7 +5,8 @@ #include "idacio/idacio.h" struct idac_io_backend { - void (*jvs_read_buttons)(uint8_t *gamebtn); - void (*jvs_read_shifter)(uint8_t *gear); - void (*jvs_read_analogs)(struct idac_io_analog_state *state); + void (*get_opbtns)(uint8_t *opbtn); + void (*get_gamebtns)(uint8_t *gamebtn); + void (*get_shifter)(uint8_t *gear); + void (*get_analogs)(struct idac_io_analog_state *state); }; diff --git a/idacio/config.c b/idacio/config.c index 5df7971..700f18b 100644 --- a/idacio/config.c +++ b/idacio/config.c @@ -77,7 +77,7 @@ void idac_xi_config_load(struct idac_xi_config *cfg, const wchar_t *filename) assert(filename != NULL); cfg->single_stick_steering = GetPrivateProfileIntW( - L"io3", + L"io4", L"singleStickSteering", 0, filename); @@ -88,13 +88,13 @@ void idac_io_config_load(struct idac_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); - cfg->restrict_ = GetPrivateProfileIntW(L"io3", L"restrict", 97, filename); + cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", '1', filename); + cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", '2', filename); + cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", '3', filename); + cfg->restrict_ = GetPrivateProfileIntW(L"io4", L"restrict", 97, filename); GetPrivateProfileStringW( - L"io3", + L"io4", L"mode", L"xinput", cfg->mode, @@ -114,7 +114,7 @@ void idac_shifter_config_load( assert(filename != NULL); cfg->auto_neutral = GetPrivateProfileIntW( - L"io3", + L"io4", L"autoNeutral", 0, filename); diff --git a/idacio/di.c b/idacio/di.c index b2d0d3d..110a2ed 100644 --- a/idacio/di.c +++ b/idacio/di.c @@ -29,12 +29,12 @@ static BOOL CALLBACK idac_di_enum_callback( static BOOL CALLBACK idac_di_enum_callback_shifter( const DIDEVICEINSTANCEW *dev, 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 void idac_di_jvs_read_shifter(uint8_t *gear); -static void idac_di_jvs_read_shifter_pos(uint8_t *gear); -static void idac_di_jvs_read_shifter_virt(uint8_t *gear); -static void idac_di_jvs_read_analogs(struct idac_io_analog_state *out); +static void idac_di_get_shifter(uint8_t *gear); +static void idac_di_get_shifter_pos(uint8_t *gear); +static void idac_di_get_shifter_virt(uint8_t *gear); +static void idac_di_get_analogs(struct idac_io_analog_state *out); static const struct idac_di_axis idac_di_axes[] = { /* 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 = { - .jvs_read_buttons = idac_di_jvs_read_buttons, - .jvs_read_shifter = idac_di_jvs_read_shifter, - .jvs_read_analogs = idac_di_jvs_read_analogs, + .get_gamebtns = idac_di_get_buttons, + .get_shifter = idac_di_get_shifter, + .get_analogs = idac_di_get_analogs, }; 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 - particularly useful. idzhook shorts this out by redirecting dinput8.dll - to a no-op implementation of DirectInput. However, idzio does need to + particularly useful. idachook shorts this out by redirecting dinput8.dll + to a no-op implementation of DirectInput. However, idacio does need to talk to the real operating system implementation of DirectInput without the stub DLL interfering, so build a path to C:\Windows\System32\dinput.dll here. */ @@ -374,7 +374,7 @@ static BOOL CALLBACK idac_di_enum_callback_shifter( 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; 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); if (idac_di_shifter != NULL) { - idac_di_jvs_read_shifter_pos(gear); + idac_di_get_shifter_pos(gear); } 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; uint8_t btn_no; @@ -457,7 +457,7 @@ static void idac_di_jvs_read_shifter_pos(uint8_t *out) *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; bool shift_dn; @@ -489,7 +489,7 @@ static void idac_di_jvs_read_shifter_virt(uint8_t *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; const LONG *brake; diff --git a/idacio/dllmain.c b/idacio/dllmain.c index fdf1004..f524139 100644 --- a/idacio/dllmain.c +++ b/idacio/dllmain.c @@ -16,14 +16,13 @@ static struct idac_io_config idac_io_cfg; static const struct idac_io_backend *idac_io_backend; static bool idac_io_coin; -static uint16_t idac_io_coins; uint16_t idac_io_get_api_version(void) { return 0x0100; } -HRESULT idac_io_jvs_init(void) +HRESULT idac_io_init(void) { HINSTANCE inst; HRESULT hr; @@ -47,20 +46,19 @@ HRESULT idac_io_jvs_init(void) hr = idac_xi_init(&idac_io_cfg.xi, &idac_io_backend); } else { 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); } 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; assert(idac_io_backend != NULL); assert(opbtn_out != NULL); - assert(gamebtn_out != NULL); 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_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(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; assert(out != 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 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->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; -} diff --git a/idacio/idacio.def b/idacio/idacio.def new file mode 100644 index 0000000..18839b2 --- /dev/null +++ b/idacio/idacio.def @@ -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 diff --git a/idacio/idacio.h b/idacio/idacio.h index 10fff60..035c5c4 100644 --- a/idacio/idacio.h +++ b/idacio/idacio.h @@ -1,17 +1,5 @@ #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 #include @@ -19,6 +7,7 @@ enum { IDAC_IO_OPBTN_TEST = 0x01, IDAC_IO_OPBTN_SERVICE = 0x02, + IDAC_IO_OPBTN_COIN = 0x04, }; enum { @@ -49,7 +38,7 @@ struct idac_io_analog_state { 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 the major version and the low byte is the minor version (as defined by the Semantic Versioning standard). @@ -58,33 +47,48 @@ struct idac_io_analog_state { uint16_t idac_io_get_api_version(void); -/* Initialize JVS-based input. This function will be called before any other - idac_io_jvs_*() function calls. Errors returned from this function will - manifest as a disconnected JVS bus. +/* Initialize the IO DLL. This is the second function that will be called on + your DLL, after mu3_io_get_api_version. - All subsequent calls may originate from arbitrary threads and some may - overlap with each other. Ensuring synchronization inside your IO DLL is - your responsibility. + All subsequent calls to this API may originate from arbitrary threads. 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 definition above for details. Minimum API version: 0x0100 */ -void idac_io_jvs_read_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); +void idac_io_get_analogs(struct idac_io_analog_state *out); /* 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. @@ -95,12 +99,4 @@ void idac_io_jvs_read_buttons(uint8_t *opbtn, uint8_t *gamebtn); Minimum API version: 0x0100 */ -void idac_io_jvs_read_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); +void idac_io_get_shifter(uint8_t *gear); \ No newline at end of file diff --git a/idacio/idzio.def b/idacio/idzio.def deleted file mode 100644 index b495482..0000000 --- a/idacio/idzio.def +++ /dev/null @@ -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 diff --git a/idacio/shifter.c b/idacio/shifter.c index 02d8a54..55de837 100644 --- a/idacio/shifter.c +++ b/idacio/shifter.c @@ -1,14 +1,14 @@ #include #include -#include "idzio/shifter.h" +#include "idacio/shifter.h" static bool idac_shifter_shifting; 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) diff --git a/idacio/shifter.h b/idacio/shifter.h index 523a9a6..c32dcf1 100644 --- a/idacio/shifter.h +++ b/idacio/shifter.h @@ -3,6 +3,6 @@ #include #include -void idac_shifter_reset(void); +void idac_shifter_set(uint8_t gear); void idac_shifter_update(bool shift_dn, bool shift_up); uint8_t idac_shifter_current_gear(void); diff --git a/idacio/wnd.c b/idacio/wnd.c index 7353273..68720b4 100644 --- a/idacio/wnd.c +++ b/idacio/wnd.c @@ -31,13 +31,13 @@ HRESULT idac_io_wnd_create(HINSTANCE inst, HWND *out) wcx.cbSize = sizeof(wcx); wcx.lpfnWndProc = idac_io_wnd_proc; wcx.hInstance = inst; - wcx.lpszClassName = L"IDZIO"; + wcx.lpszClassName = L"IDACIO"; atom = RegisterClassExW(&wcx); if (atom == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); - dprintf("IDZIO: RegisterClassExW failed: %08x\n", (int) hr); + dprintf("IDACIO: RegisterClassExW failed: %08x\n", (int) hr); goto fail; } @@ -58,7 +58,7 @@ HRESULT idac_io_wnd_create(HINSTANCE inst, HWND *out) if (hwnd == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); - dprintf("IDZIO: CreateWindowExW failed: %08x\n", (int) hr); + dprintf("IDACIO: CreateWindowExW failed: %08x\n", (int) hr); goto fail; } diff --git a/idacio/xi.c b/idacio/xi.c index 63e4242..87f3fbd 100644 --- a/idacio/xi.c +++ b/idacio/xi.c @@ -13,16 +13,16 @@ #include "util/dprintf.h" -static void idac_xi_jvs_read_buttons(uint8_t *gamebtn_out); -static void idac_xi_jvs_read_shifter(uint8_t *gear); -static void idac_xi_jvs_read_analogs(struct idac_io_analog_state *out); +static void idac_xi_get_gamebtns(uint8_t *gamebtn_out); +static void idac_xi_get_shifter(uint8_t *gear); +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 const struct idac_io_backend idac_xi_backend = { - .jvs_read_buttons = idac_xi_jvs_read_buttons, - .jvs_read_shifter = idac_xi_jvs_read_shifter, - .jvs_read_analogs = idac_xi_jvs_read_analogs, + .get_gamebtns = idac_xi_get_gamebtns, + .get_shifter = idac_xi_get_shifter, + .get_analogs = idac_xi_get_analogs, }; 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; } +HRESULT idac_io_poll(void) +{ + return S_OK; +} + static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg) { dprintf("XInput: --- Begin configuration ---\n"); @@ -56,7 +61,7 @@ static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg) 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; XINPUT_STATE xi; @@ -97,7 +102,7 @@ static void idac_xi_jvs_read_buttons(uint8_t *gamebtn_out) *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_up; @@ -112,9 +117,25 @@ static void idac_xi_jvs_read_shifter(uint8_t *gear) if (xb & XINPUT_GAMEPAD_START) { /* 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_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(); } -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; int left; @@ -154,7 +175,7 @@ static void idac_xi_jvs_read_analogs(struct idac_io_analog_state *out) right = 0; } - if(idac_xi_single_stick_steering) { + if (idac_xi_single_stick_steering) { out->wheel = left; } else { out->wheel = (left + right) / 2;