From a1611afffcdbb3e83e920a870c0fe719c61be985 Mon Sep 17 00:00:00 2001 From: Mahuyo Date: Sun, 16 Feb 2025 12:49:58 +0000 Subject: [PATCH 1/9] Mai2: Add touch and led15070 hook (#55) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this PR, I have added the `mai2` touch and `led15070` hooks to provide an example for handling custom peripherals. This change allows users to implement the touch and `led15070` logic by writing appropriate `mai2io` scripts. #### **Touch Hook**: - The touch hook simulates touch points based on keyboard combinations. For example, to trigger the A1 touch point, the user must press the A and 1 keys on the keyboard. Input for the 1p requires Caps Lock to be off, while 2p requires Caps Lock to be on. - The hook allows for independent control of whether device simulation is enabled for "1p" and "2p" and whether keyboard input mapping is enabled. - **Note**: The current touch hook is not yet functional as it requires modifications to the `capnhook` for proper completion of the `sinmai` hook. #### **LED15070 Hook**: - This hook implements basic device simulation. Peripherals requiring lighting data should complete the logic as needed. - **Note**: The LED data refresh can flood the console logs, so I’ve added a `DEBUG` flag to control whether the debug logging is enabled or not. #### **Other Changes**: - In certain versions of `sinmai`, key inputs for 1p and 2p can be directly read from the keyboard without requiring simulation via the `amdaemon io4` hook. I’ve added a switch to control this behavior to prevent redundant input. - **Benefit**: This ensures that key input is only read when `sinmai` is in the foreground. If you'd like to learn more about the touch and `led15070` features, my research findings are available here: [Mai2Touch](https://github.com/Sucareto/Mai2Touch) Co-authored-by: Sucareto <28331534+Sucareto@users.noreply.github.com> Reviewed-on: https://gitea.tendokyu.moe/TeamTofuShop/segatools/pulls/55 Co-authored-by: Mahuyo Co-committed-by: Mahuyo --- board/led15070.c | 83 ++++++++++---- dist/mai2/segatools.ini | 28 ++++- hooklib/reg.c | 2 +- mai2hook/config.c | 68 +++++++++-- mai2hook/config.h | 22 +++- mai2hook/dllmain.c | 44 +++++-- mai2hook/mai2-dll.c | 25 +++- mai2hook/mai2-dll.h | 7 ++ mai2hook/mai2hook.def | 9 +- mai2hook/meson.build | 2 + mai2hook/touch.c | 248 ++++++++++++++++++++++++++++++++++++++++ mai2hook/touch.h | 43 +++++++ mai2io/config.c | 65 ++++++++--- mai2io/config.h | 5 + mai2io/mai2io.c | 163 +++++++++++++++++++++++++- mai2io/mai2io.h | 118 +++++++++++++++++++ mai2io/meson.build | 3 + meson.build | 6 + meson_options.txt | 10 ++ platform/epay.c | 2 +- 20 files changed, 877 insertions(+), 76 deletions(-) create mode 100644 mai2hook/touch.c create mode 100644 mai2hook/touch.h diff --git a/board/led15070.c b/board/led15070.c index c2d62a5..579de7c 100644 --- a/board/led15070.c +++ b/board/led15070.c @@ -238,7 +238,7 @@ static HRESULT led15070_handle_irp_locked(int board, struct irp *irp) } for (;;) { -#if 0 +#if defined(LOG_LED15070) dprintf("TX Buffer:\n"); dump_iobuf(&boarduart->written); #endif @@ -257,7 +257,7 @@ static HRESULT led15070_handle_irp_locked(int board, struct irp *irp) return hr; } -#if 0 +#if defined(LOG_LED15070) dprintf("Deframe Buffer:\n"); dump_iobuf(&req_iobuf); #endif @@ -385,7 +385,9 @@ static HRESULT led15070_req_reset(int board, const struct led15070_req_any *req) static HRESULT led15070_req_set_input(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set input (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -408,9 +410,10 @@ static HRESULT led15070_req_set_input(int board, const struct led15070_req_any * static HRESULT led15070_req_set_normal_12bit(int board, const struct led15070_req_any *req) { uint8_t idx = req->payload[0]; - +#if defined(LOG_LED15070) dprintf("LED 15070: Set LED - Normal 12bit (board %u, index %u)\n", board, idx); +#endif // TODO: Data for this command. Seen with Carol @@ -435,9 +438,10 @@ static HRESULT led15070_req_set_normal_12bit(int board, const struct led15070_re static HRESULT led15070_req_set_normal_8bit(int board, const struct led15070_req_any *req) { uint8_t idx = req->payload[0]; - - // dprintf("LED 15070: Set LED - Normal 8bit (board %u, index %u)\n", - // board, idx); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set LED - Normal 8bit (board %u, index %u)\n", + board, idx); +#endif led15070_per_board_vars[board].gs[idx][0] = req->payload[1]; // R led15070_per_board_vars[board].gs[idx][1] = req->payload[2]; // G @@ -468,8 +472,10 @@ static HRESULT led15070_req_set_multi_flash_8bit(int board, const struct led1507 uint8_t idx_skip = req->payload[2]; // TODO: useful? - // dprintf("LED 15070: Set LED - Multi flash 8bit (board %u, start %u, end %u, skip %u)\n", - // board, idx_start, idx_end, idx_skip); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set LED - Multi flash 8bit (board %u, start %u, end %u, skip %u)\n", + board, idx_start, idx_end, idx_skip); +#endif if (idx_skip > 0 && idx_skip <= (idx_end - idx_start + 1)) { idx_start += idx_skip; @@ -508,9 +514,10 @@ static HRESULT led15070_req_set_multi_fade_8bit(int board, const struct led15070 uint8_t idx_start = req->payload[0]; uint8_t idx_end = req->payload[1]; uint8_t idx_skip = req->payload[2]; - - // dprintf("LED 15070: Set LED - Multi fade 8bit (board %u, start %u, end %u, skip %u)\n", - // board, idx_start, idx_end, idx_skip); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set LED - Multi fade 8bit (board %u, start %u, end %u, skip %u)\n", + board, idx_start, idx_end, idx_skip); +#endif if (idx_skip > 0 && idx_skip <= (idx_end - idx_start + 1)) { idx_start += idx_skip; @@ -545,7 +552,9 @@ static HRESULT led15070_req_set_multi_fade_8bit(int board, const struct led15070 static HRESULT led15070_req_set_palette_7_normal_led(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set palette - 7 Normal LED (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -567,7 +576,9 @@ static HRESULT led15070_req_set_palette_7_normal_led(int board, const struct led static HRESULT led15070_req_set_palette_6_flash_led(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set palette - 6 Flash LED (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -589,7 +600,9 @@ static HRESULT led15070_req_set_palette_6_flash_led(int board, const struct led1 static HRESULT led15070_req_set_15dc_out(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set 15DC out (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -611,7 +624,9 @@ static HRESULT led15070_req_set_15dc_out(int board, const struct led15070_req_an static HRESULT led15070_req_set_15gs_out(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set 15GS out (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -633,7 +648,9 @@ static HRESULT led15070_req_set_15gs_out(int board, const struct led15070_req_an static HRESULT led15070_req_set_psc_max(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set PSC max (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -655,7 +672,9 @@ static HRESULT led15070_req_set_psc_max(int board, const struct led15070_req_any static HRESULT led15070_req_set_fet_output(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Set FET output (board %u)\n", board); +#endif led15070_per_board_vars[board].fet[0] = req->payload[0]; // R or FET0 intensity led15070_per_board_vars[board].fet[1] = req->payload[1]; // G or FET1 intensity @@ -685,8 +704,9 @@ static HRESULT led15070_req_set_fet_output(int board, const struct led15070_req_ static HRESULT led15070_req_set_gs_palette(int board, const struct led15070_req_any *req) { uint8_t idx = req->payload[0]; - +#if defined(LOG_LED15070) dprintf("LED 15070: Set GS palette (board %u, index %u)\n", board, idx); +#endif led15070_per_board_vars[board].gs_palette[idx][0] = req->payload[1]; // R led15070_per_board_vars[board].gs_palette[idx][1] = req->payload[2]; // G @@ -712,7 +732,9 @@ static HRESULT led15070_req_set_gs_palette(int board, const struct led15070_req_ static HRESULT led15070_req_dc_update(int board, const struct led15070_req_any *req) { - // dprintf("LED 15070: DC update (board %u)\n", board); +#if defined(LOG_LED15070) + dprintf("LED 15070: DC update (board %u)\n", board); +#endif if (led_dc_update) led_dc_update((const uint8_t*)led15070_per_board_vars[board].dc); @@ -737,7 +759,9 @@ static HRESULT led15070_req_dc_update(int board, const struct led15070_req_any * static HRESULT led15070_req_gs_update(int board, const struct led15070_req_any *req) { - // dprintf("LED 15070: GS update (board %u)\n", board); +#if defined(LOG_LED15070) + dprintf("LED 15070: GS update (board %u)\n", board); +#endif if (led_gs_update) led_gs_update((const uint8_t*)led15070_per_board_vars[board].gs); @@ -762,7 +786,9 @@ static HRESULT led15070_req_gs_update(int board, const struct led15070_req_any * static HRESULT led15070_req_rotate(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Rotate (board %u)\n", board); +#endif if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -787,9 +813,10 @@ static HRESULT led15070_req_set_dc_data(int board, const struct led15070_req_any uint8_t idx_start = req->payload[0]; uint8_t idx_end = req->payload[1]; uint8_t idx_skip = req->payload[2]; - - // dprintf("LED 15070: Set DC data (board %u, start %u, end %u, skip %u)\n", - // board, idx_start, idx_end, idx_skip); +#if defined(LOG_LED15070) + dprintf("LED 15070: Set DC data (board %u, start %u, end %u, skip %u)\n", + board, idx_start, idx_end, idx_skip); +#endif if (idx_skip > 0 && idx_skip <= (idx_end - idx_start + 1)) { idx_start += idx_skip; @@ -829,9 +856,10 @@ static HRESULT led15070_req_eeprom_write(int board, const struct led15070_req_an uint8_t addr = req->payload[0]; uint8_t data = req->payload[1]; - +#if defined(LOG_LED15070) dprintf("LED 15070: EEPROM write (board %u, address %02x, data %02x)\n", board, addr, data); +#endif if (addr > 0x07) { dprintf("LED 15070: Error -- Invalid EEPROM write address %02x\n", @@ -919,8 +947,9 @@ static HRESULT led15070_req_eeprom_read(int board, const struct led15070_req_any uint8_t addr = req->payload[0]; uint8_t data = 0; - +#if defined(LOG_LED15070) dprintf("LED 15070: EEPROM read (board %u, address %02x)\n", board, addr); +#endif if (addr > 0x07) { dprintf("LED 15070: Error -- Invalid EEPROM read address %02x\n", @@ -1002,7 +1031,9 @@ static HRESULT led15070_req_eeprom_read(int board, const struct led15070_req_any static HRESULT led15070_req_ack_on(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Acknowledge commands ON (board %u)\n", board); +#endif led15070_per_board_vars[board].enable_response = true; @@ -1023,7 +1054,9 @@ static HRESULT led15070_req_ack_on(int board, const struct led15070_req_any *req static HRESULT led15070_req_ack_off(int board, const struct led15070_req_any *req) { +#if defined(LOG_LED15070) dprintf("LED 15070: Acknowledge commands OFF (board %u)\n", board); +#endif led15070_per_board_vars[board].enable_response = false; @@ -1044,7 +1077,9 @@ static HRESULT led15070_req_ack_off(int board, const struct led15070_req_any *re static HRESULT led15070_req_board_info(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get board info (board %u)\n", board); +#endif struct led15070_resp_board_info resp; @@ -1067,7 +1102,9 @@ static HRESULT led15070_req_board_info(int board) static HRESULT led15070_req_board_status(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get board status (board %u)\n", board); +#endif struct led15070_resp_any resp; @@ -1091,7 +1128,9 @@ static HRESULT led15070_req_board_status(int board) static HRESULT led15070_req_fw_sum(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get firmware checksum (board %u)\n", board); +#endif struct led15070_resp_any resp; @@ -1113,7 +1152,9 @@ static HRESULT led15070_req_fw_sum(int board) static HRESULT led15070_req_protocol_ver(int board) { +#if defined(LOG_LED15070) dprintf("LED 15070: Get protocol version (board %u)\n", board); +#endif struct led15070_resp_any resp; @@ -1187,7 +1228,7 @@ static HRESULT led15070_eeprom_open(int board, wchar_t *path, HANDLE *handle) HRESULT hr; BOOL ok; -#if 0 +#if defined(LOG_LED15070) dprintf("LED 15070: Opening EEPROM file '%S' handle (board %u)\n", path, board); #endif @@ -1233,7 +1274,7 @@ static HRESULT led15070_eeprom_close(int board, wchar_t *path, HANDLE *handle) HRESULT hr; BOOL ok; -#if 0 +#if defined(LOG_LED15070) dprintf("LED 15070: Closing EEPROM file '%S' handle (board %u)\n", path, board); #endif diff --git a/dist/mai2/segatools.ini b/dist/mai2/segatools.ini index c253334..46fb4e5 100644 --- a/dist/mai2/segatools.ini +++ b/dist/mai2/segatools.ini @@ -126,11 +126,27 @@ coin=0x72 ; Uncomment and complete the following sequence of settings to configure a ; custom keybinding. [button] -;1p_btn1=0x53 -;1p_btn2=0x53 -;1p_btn3=0x53 +enable=1 +;p1Btn1=0x53 +;p1Btn2=0x53 +;p1Btn3=0x53 ; ... etc ... -;2p_btn1=0x53 -;2p_btn2=0x53 -;2p_btn3=0x53 +;p2Btn1=0x53 +;p2Btn2=0x53 +;p2Btn3=0x53 ; ... etc ... + +[touch] +p1Enable=1 +;p1DebugInput=0 +p2Enable=1 +;p2DebugInput=0 +;p1TouchA1=0x53 +;p1TouchA2=0x53 +; ... etc ... +;p1TouchE8=0x53 + +[led15070] +; Enable emulation of the 837-15070-02 controlled lights, which handle the +; cabinet and seat LEDs. +enable=1 \ No newline at end of file diff --git a/hooklib/reg.c b/hooklib/reg.c index bc18dbb..d4a3bc3 100644 --- a/hooklib/reg.c +++ b/hooklib/reg.c @@ -308,7 +308,7 @@ static void reg_hook_init(void) reg_hook_initted = true; InitializeCriticalSection(®_hook_lock); - dprintf("Reg hook init\n"); + dprintf("Reg: hook init.\n"); reg_hook_insert_hooks(NULL); diff --git a/mai2hook/config.c b/mai2hook/config.c index 27e19ec..48c0c6e 100644 --- a/mai2hook/config.c +++ b/mai2hook/config.c @@ -12,24 +12,70 @@ #include "platform/config.h" void mai2_dll_config_load( - struct mai2_dll_config *cfg, - const wchar_t *filename) + struct mai2_dll_config *cfg, + const wchar_t *filename) { assert(cfg != NULL); assert(filename != NULL); GetPrivateProfileStringW( - L"mai2io", - L"path", - L"", - cfg->path, - _countof(cfg->path), - filename); + L"mai2io", + L"path", + L"", + cfg->path, + _countof(cfg->path), + filename); +} + +void touch_config_load( + struct touch_config *cfg, + const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + cfg->enable_1p = GetPrivateProfileIntW(L"touch", L"p1Enable", 1, filename); + cfg->enable_2p = GetPrivateProfileIntW(L"touch", L"p2Enable", 1, filename); +} + +void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + wchar_t tmpstr[16]; + + cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); + cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); + cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x00, filename); + + GetPrivateProfileStringW( + L"led15070", + L"boardNumber", + L"15070-04", + tmpstr, + _countof(tmpstr), + filename); + + size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number)); + for (int i = n; i < sizeof(cfg->board_number); i++) + { + cfg->board_number[i] = ' '; + } + + GetPrivateProfileStringW( + L"led15070", + L"eepromPath", + L"DEVICE", + cfg->eeprom_path, + _countof(cfg->eeprom_path), + filename); } void mai2_hook_config_load( - struct mai2_hook_config *cfg, - const wchar_t *filename) + struct mai2_hook_config *cfg, + const wchar_t *filename) { assert(cfg != NULL); assert(filename != NULL); @@ -40,5 +86,7 @@ void mai2_hook_config_load( io4_config_load(&cfg->io4, filename); vfd_config_load(&cfg->vfd, filename); mai2_dll_config_load(&cfg->dll, filename); + touch_config_load(&cfg->touch, filename); + led15070_config_load(&cfg->led15070, filename); unity_config_load(&cfg->unity, filename); } diff --git a/mai2hook/config.h b/mai2hook/config.h index 7e86822..1055b81 100644 --- a/mai2hook/config.h +++ b/mai2hook/config.h @@ -10,6 +10,10 @@ #include "platform/config.h" +#include "mai2hook/touch.h" + +#include "board/led15070.h" + #include "unityhook/config.h" struct mai2_hook_config { @@ -19,13 +23,23 @@ struct mai2_hook_config { struct io4_config io4; struct vfd_config vfd; struct mai2_dll_config dll; + struct touch_config touch; + struct led15070_config led15070; struct unity_config unity; }; void mai2_dll_config_load( - struct mai2_dll_config *cfg, - const wchar_t *filename); + struct mai2_dll_config *cfg, + const wchar_t *filename); + +void touch_config_load( + struct touch_config *cfg, + const wchar_t *filename); + +void led15070_config_load( + struct led15070_config *cfg, + const wchar_t *filename); void mai2_hook_config_load( - struct mai2_hook_config *cfg, - const wchar_t *filename); + struct mai2_hook_config *cfg, + const wchar_t *filename); diff --git a/mai2hook/dllmain.c b/mai2hook/dllmain.c index 193467f..ac0e3a1 100644 --- a/mai2hook/dllmain.c +++ b/mai2hook/dllmain.c @@ -67,16 +67,44 @@ static DWORD CALLBACK mai2_pre_startup(void) /* Initialize emulation hooks */ hr = platform_hook_init( - &mai2_hook_cfg.platform, - "SDEZ", - "ACA1", - mai2_hook_mod); + &mai2_hook_cfg.platform, + "SDEZ", + "ACA1", + mai2_hook_mod); if (FAILED(hr)) { goto fail; } - hr = sg_reader_hook_init(&mai2_hook_cfg.aime, 1, 1, mai2_hook_mod); + /* Initialize DLLs */ + + hr = mai2_dll_init(&mai2_hook_cfg.dll, mai2_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + + // Touch Panel uses COM3 and COM4 + + hr = touch_hook_init(&mai2_hook_cfg.touch); + + if (FAILED(hr)) { + goto fail; + } + + // LED board uses COM21 and COM23 + hr = led15070_hook_init(&mai2_hook_cfg.led15070, + mai2_dll.led_init, + mai2_dll.led_set_fet_output, + mai2_dll.led_dc_update, + mai2_dll.led_gs_update, + 21, 2); + + if (FAILED(hr)) { + goto fail; + } + + hr = sg_reader_hook_init(&mai2_hook_cfg.aime, 1, 3, mai2_hook_mod); if (FAILED(hr)) { goto fail; @@ -88,12 +116,6 @@ static DWORD CALLBACK mai2_pre_startup(void) goto fail; } - hr = mai2_dll_init(&mai2_hook_cfg.dll, mai2_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - hr = mai2_io4_hook_init(&mai2_hook_cfg.io4); if (FAILED(hr)) { diff --git a/mai2hook/mai2-dll.c b/mai2hook/mai2-dll.c index dd172c3..121750e 100644 --- a/mai2hook/mai2-dll.c +++ b/mai2hook/mai2-dll.c @@ -21,7 +21,28 @@ const struct dll_bind_sym mai2_dll_syms[] = { }, { .sym = "mai2_io_get_gamebtns", .off = offsetof(struct mai2_dll, get_gamebtns), - } + }, { + .sym = "mai2_io_touch_init", + .off = offsetof(struct mai2_dll, touch_init), + }, { + .sym = "mai2_io_touch_set_sens", + .off = offsetof(struct mai2_dll, touch_set_sens), + }, { + .sym = "mai2_io_touch_update", + .off = offsetof(struct mai2_dll, touch_update), + }, { + .sym = "mai2_io_led_init", + .off = offsetof(struct mai2_dll, led_init), + }, { + .sym = "mai2_io_led_set_fet_output", + .off = offsetof(struct mai2_dll, led_set_fet_output), + }, { + .sym = "mai2_io_led_dc_update", + .off = offsetof(struct mai2_dll, led_dc_update), + }, { + .sym = "mai2_io_led_gs_update", + .off = offsetof(struct mai2_dll, led_gs_update), + }, }; struct mai2_dll mai2_dll; @@ -67,7 +88,7 @@ HRESULT mai2_dll_init(const struct mai2_dll_config *cfg, HINSTANCE self) if (get_api_version != NULL) { mai2_dll.api_version = get_api_version(); } else { - mai2_dll.api_version = 0x0100; + mai2_dll.api_version = 0x0101; dprintf("Custom IO DLL does not expose mai2_io_get_api_version, " "assuming API version 1.0.\n" "Please ask the developer to update their DLL.\n"); diff --git a/mai2hook/mai2-dll.h b/mai2hook/mai2-dll.h index 6e53454..6c205c8 100644 --- a/mai2hook/mai2-dll.h +++ b/mai2hook/mai2-dll.h @@ -10,6 +10,13 @@ struct mai2_dll { HRESULT (*poll)(void); void (*get_opbtns)(uint8_t *opbtn); void (*get_gamebtns)(uint16_t *player1, uint16_t *player2); + HRESULT (*touch_init)(mai2_io_touch_callback_t callback); + void (*touch_set_sens)(uint8_t *bytes); + void (*touch_update)(bool player1, bool player2); + HRESULT (*led_init)(void); + void (*led_set_fet_output)(const uint8_t *rgb); + void (*led_dc_update)(const uint8_t *rgb); + void (*led_gs_update)(const uint8_t *rgb); }; struct mai2_dll_config { diff --git a/mai2hook/mai2hook.def b/mai2hook/mai2hook.def index 2d0ac8b..50e4058 100644 --- a/mai2hook/mai2hook.def +++ b/mai2hook/mai2hook.def @@ -15,4 +15,11 @@ EXPORTS mai2_io_get_gamebtns mai2_io_get_opbtns mai2_io_init - mai2_io_poll \ No newline at end of file + mai2_io_poll + mai2_io_touch_init + mai2_io_touch_set_sens + mai2_io_touch_update + mai2_io_led_init + mai2_io_led_set_fet_output + mai2_io_led_dc_update + mai2_io_led_gs_update diff --git a/mai2hook/meson.build b/mai2hook/meson.build index eba0c19..ed47793 100644 --- a/mai2hook/meson.build +++ b/mai2hook/meson.build @@ -23,6 +23,8 @@ shared_library( 'dllmain.c', 'io4.c', 'io4.h', + 'touch.c', + 'touch.h', 'mai2-dll.c', 'mai2-dll.h', ], diff --git a/mai2hook/touch.c b/mai2hook/touch.c new file mode 100644 index 0000000..75bbded --- /dev/null +++ b/mai2hook/touch.c @@ -0,0 +1,248 @@ +#include "mai2hook/touch.h" + +static HRESULT read_reg_touch_1p(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L"COM3"); +} + +static HRESULT read_reg_touch_2p(void *bytes, uint32_t *nbytes) +{ + return reg_hook_read_wstr(bytes, nbytes, L"COM4"); +} + +static const struct reg_hook_val touch_reg_key[] = { + { + .name = L"\\Device\\RealTouchBoard0", + .read = read_reg_touch_1p, + .type = REG_SZ, + }, + { + .name = L"\\Device\\RealTouchBoard1", + .read = read_reg_touch_2p, + .type = REG_SZ, + }, +}; + +const char *sensor_map[34] = { + "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", // 0x41 - 0x48 + "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", // 0x49 - 0x50 + "C1", "C2", // 0x51 - 0x52 + "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", // 0x53 - 0x5A + "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8" // 0x5B - 0x62 +}; + +const char *sensor_to_str(uint8_t sensor) +{ + if (sensor < 0x41 || sensor > 0x62) + { + return "Invalid"; + } + + return sensor_map[sensor - 0x41]; +} + +static CRITICAL_SECTION touch_1p_lock; +static struct uart touch_1p_uart; +static uint8_t touch_1p_written_bytes[64]; +static uint8_t touch_1p_readable_bytes[64]; +static bool touch_1p_status = false; + +static CRITICAL_SECTION touch_2p_lock; +static struct uart touch_2p_uart; +static uint8_t touch_2p_written_bytes[64]; +static uint8_t touch_2p_readable_bytes[64]; +static bool touch_2p_status = false; + +HRESULT touch_hook_init(const struct touch_config *cfg) +{ + assert(cfg != NULL); + + if (!cfg->enable_1p && !cfg->enable_2p) + { + return S_FALSE; + } + + HRESULT hr = reg_hook_push_key(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", touch_reg_key, _countof(touch_reg_key)); + + if (FAILED(hr)) + { + return hr; + } + + if (cfg->enable_1p) + { + dprintf("Mai2 touch 1P: Init.\n"); + + InitializeCriticalSection(&touch_1p_lock); + uart_init(&touch_1p_uart, 3); + touch_1p_uart.written.bytes = touch_1p_written_bytes; + touch_1p_uart.written.nbytes = sizeof(touch_1p_written_bytes); + touch_1p_uart.readable.bytes = touch_1p_readable_bytes; + touch_1p_uart.readable.nbytes = sizeof(touch_1p_readable_bytes); + } + + if (cfg->enable_2p) + { + dprintf("Mai2 touch port 2P: Init.\n"); + + InitializeCriticalSection(&touch_2p_lock); + uart_init(&touch_2p_uart, 4); + touch_2p_uart.written.bytes = touch_2p_written_bytes; + touch_2p_uart.written.nbytes = sizeof(touch_2p_written_bytes); + touch_2p_uart.readable.bytes = touch_2p_readable_bytes; + touch_2p_uart.readable.nbytes = sizeof(touch_2p_readable_bytes); + } + + return iohook_push_handler(touch_handle_irp); +} + +static HRESULT touch_handle_irp(struct irp *irp) +{ + HRESULT hr; + + assert(irp != NULL); + + if (uart_match_irp(&touch_1p_uart, irp)) + { + EnterCriticalSection(&touch_1p_lock); + hr = touch_handle_irp_locked(irp, &touch_1p_uart); + LeaveCriticalSection(&touch_1p_lock); + } + else if (uart_match_irp(&touch_2p_uart, irp)) + { + EnterCriticalSection(&touch_2p_lock); + hr = touch_handle_irp_locked(irp, &touch_2p_uart); + LeaveCriticalSection(&touch_2p_lock); + } + else + { + return iohook_invoke_next(irp); + } + + return hr; +} + +static HRESULT touch_handle_irp_locked(struct irp *irp, struct uart *uart) +{ + HRESULT hr; + + if (irp->op == IRP_OP_OPEN) + { + dprintf("Mai2 touch port %d: Starting backend\n", uart->port_no); + hr = mai2_dll.touch_init(touch_auto_scan); + + if (FAILED(hr)) + { + dprintf("Mai2 touch port %d: Backend error: %x\n", uart->port_no, (int)hr); + return hr; + } + } + + hr = uart_handle_irp(uart, irp); + + if (FAILED(hr) || irp->op != IRP_OP_WRITE) + { + return hr; + } + +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch port %d WRITE:\n", uart->port_no); + dump_iobuf(&uart->written); +#endif + uint8_t port_no = uart->port_no; + uint8_t *src = uart->written.bytes; + uint8_t *dest = uart->readable.bytes; + + switch (src[3]) + { + case commandRSET: + dprintf("Mai2 touch port %d: Reset\n", port_no); + break; + + case commandHALT: // Enter Conditioning mode and stop sending touch data. + dprintf("Mai2 touch port %d: Halt\n", port_no); + assert(mai2_dll.touch_update != NULL); + if (port_no == 3) + { + EnterCriticalSection(&touch_1p_lock); + touch_1p_status = false; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_1p_lock); + } + else + { + EnterCriticalSection(&touch_2p_lock); + touch_2p_status = false; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_2p_lock); + } + break; + + case commandSTAT: // Exit Conditioning mode and resume sending touch data. + dprintf("Mai2 touch port %d: Stat\n", port_no); + assert(mai2_dll.touch_update != NULL); + if (port_no == 3) + { + EnterCriticalSection(&touch_1p_lock); + touch_1p_status = true; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_1p_lock); + } + else + { + EnterCriticalSection(&touch_2p_lock); + touch_2p_status = true; + mai2_dll.touch_update(touch_1p_status, touch_2p_status); + LeaveCriticalSection(&touch_2p_lock); + } + break; + + case commandRatio: +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch side %c: set sensor %s ratio to %d\n", src[1], sensor_to_str(src[2]), src[4]); +#endif + dest[0] = res_start; + dest[1] = src[1]; // L,R + dest[2] = src[2]; // sensor + dest[3] = commandRatio; + dest[4] = src[4]; // Ratio + dest[5] = res_end; + uart->readable.pos = 6; + // The Ratio is fixed at 0x72 and does not need to be sent to mai2io for processing. + break; + + case commandSens: +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch side %c: set sensor %s sensitivity to %d\n", src[1], sensor_to_str(src[2]), src[4]); +#endif + dest[0] = res_start; + dest[1] = src[1]; // L,R + dest[2] = src[2]; // sensor + dest[3] = commandSens; + dest[4] = src[4]; // Sensitivity + dest[5] = res_end; + uart->readable.pos = 6; + mai2_dll.touch_set_sens(dest); + break; + + default: + dprintf("Mai2 touch port %d: Unknow %02x\n", port_no, src[3]); + break; + } +#if defined(LOG_MAI2_TOUCH) + dprintf("Mai2 touch port %d READ:\n", uart->port_no); + dump_iobuf(&uart->readable); +#endif + uart->written.pos = 0; + + return hr; +} + +static void touch_auto_scan(const uint8_t player, const uint8_t state[7]) +{ + struct uart *touch_uart = player == 1 ? &touch_1p_uart : &touch_2p_uart; + touch_uart->readable.bytes[0] = res_start; + memcpy(&touch_uart->readable.bytes[1], state, 7); + touch_uart->readable.bytes[8] = res_end; + touch_uart->readable.pos = 9; +} \ No newline at end of file diff --git a/mai2hook/touch.h b/mai2hook/touch.h new file mode 100644 index 0000000..e25487e --- /dev/null +++ b/mai2hook/touch.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include +#include +#include + +#include "hooklib/fdshark.h" +#include "hooklib/reg.h" +#include "hooklib/uart.h" +#include "mai2hook/mai2-dll.h" +#include "util/dprintf.h" +#include "util/dump.h" + +struct touch_config +{ + bool enable_1p; + bool enable_2p; +}; + +enum +{ + commandRSET = 0x45, // E + commandHALT = 0x4C, // L + commandSTAT = 0x41, // A + commandRatio = 0x72, // r + commandSens = 0x6B, // k + req_start = 0x7b, // { + req_end = 0x7d, // } + res_start = 0x28, // ( + res_end = 0x29, // ) +}; + +extern const char *sensor_map[34]; +const char *sensor_to_str(uint8_t sensor); + +HRESULT touch_hook_init(const struct touch_config *cfg); +static HRESULT touch_handle_irp(struct irp *irp); +static HRESULT touch_handle_irp_locked(struct irp *irp, struct uart *uart); + +/* Called in mai2io to send touch data. + Similar to chuni slider_res_auto_scan, but the host does not require periodic updates. + Touch data is sent only when there is a change. */ +static void touch_auto_scan(const uint8_t player, const uint8_t state[7]); \ No newline at end of file diff --git a/mai2io/config.c b/mai2io/config.c index 3578338..c6c9913 100644 --- a/mai2io/config.c +++ b/mai2io/config.c @@ -6,6 +6,7 @@ #include #include "mai2io/config.h" +#include "mai2hook/touch.h" /* Maimai DX Default key binding @@ -15,9 +16,24 @@ Maimai DX Default key binding static const int mai2_io_1p_default[] = {'W', 'E', 'D', 'C', 'X', 'Z', 'A', 'Q', '3'}; static const int mai2_io_2p_default[] = {0x68, 0x69, 0x66, 0x63, 0x62, 0x61, 0x64, 0x67, 0x54}; +static const int mai2_io_1p_touch_default[] = { + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', + 'G', 'G', + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', + 'T', 'Y', 'H', 'N', 'B', 'V', 'F', 'R', +}; +static const int mai2_io_2p_touch_default[] = { + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', + 'K', 'K', + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', + 'I', 'O', 'L', VK_OEM_PERIOD, VK_OEM_COMMA, 'M', 'J', 'U', +}; + void mai2_io_config_load( - struct mai2_io_config *cfg, - const wchar_t *filename) + struct mai2_io_config *cfg, + const wchar_t *filename) { wchar_t key[16]; int i; @@ -28,22 +44,41 @@ void mai2_io_config_load( cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", VK_F1, filename); cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", VK_F2, filename); cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", VK_F3, filename); + cfg->vk_btn_enable = GetPrivateProfileIntW(L"button", L"enable", 1, filename); - for (i = 0 ; i < 9 ; i++) { - swprintf_s(key, _countof(key), L"1p_btn%i", i + 1); + for (i = 0; i < 9; i++) + { + swprintf_s(key, _countof(key), L"p1Btn%i", i + 1); cfg->vk_1p_btn[i] = GetPrivateProfileIntW( - L"button", - key, - mai2_io_1p_default[i], - filename); + L"button", + key, + mai2_io_1p_default[i], + filename); + + swprintf_s(key, _countof(key), L"p2Btn%i", i + 1); + cfg->vk_2p_btn[i] = GetPrivateProfileIntW( + L"button", + key, + mai2_io_2p_default[i], + filename); } - for (i = 0 ; i < 9 ; i++) { - swprintf_s(key, _countof(key), L"2p_btn%i", i + 1); - cfg->vk_2p_btn[i] = GetPrivateProfileIntW( - L"button", - key, - mai2_io_2p_default[i], - filename); + cfg->debug_input_1p = GetPrivateProfileIntW(L"touch", L"p1DebugInput", 0, filename); + cfg->debug_input_2p = GetPrivateProfileIntW(L"touch", L"p2DebugInput", 0, filename); + for (i = 0; i < 34; i++) + { + swprintf_s(key, _countof(key), L"p1Touch%S", sensor_map[i]); + cfg->vk_1p_touch[i] = GetPrivateProfileIntW( + L"touch", + key, + mai2_io_1p_touch_default[i], + filename); + + swprintf_s(key, _countof(key), L"p2Touch%S", sensor_map[i]); + cfg->vk_2p_touch[i] = GetPrivateProfileIntW( + L"touch", + key, + mai2_io_2p_touch_default[i], + filename); } } diff --git a/mai2io/config.h b/mai2io/config.h index 568b832..ce765ed 100644 --- a/mai2io/config.h +++ b/mai2io/config.h @@ -9,8 +9,13 @@ struct mai2_io_config { uint8_t vk_test; uint8_t vk_service; uint8_t vk_coin; + bool vk_btn_enable; uint8_t vk_1p_btn[9]; uint8_t vk_2p_btn[9]; + bool debug_input_1p; + bool debug_input_2p; + uint8_t vk_1p_touch[34]; + uint8_t vk_2p_touch[34]; }; void mai2_io_config_load( diff --git a/mai2io/mai2io.c b/mai2io/mai2io.c index ffdbfcf..554e8dd 100644 --- a/mai2io/mai2io.c +++ b/mai2io/mai2io.c @@ -1,10 +1,9 @@ -#include - +#include #include -#include #include "mai2io/mai2io.h" #include "mai2io/config.h" +#include "mai2hook/touch.h" #include "util/env.h" static uint8_t mai2_opbtn; @@ -12,10 +11,15 @@ static uint16_t mai2_player1_btn; static uint16_t mai2_player2_btn; static struct mai2_io_config mai2_io_cfg; static bool mai2_io_coin; +mai2_io_touch_callback_t _callback; +static HANDLE mai2_io_touch_1p_thread; +static bool mai2_io_touch_1p_stop_flag; +static HANDLE mai2_io_touch_2p_thread; +static bool mai2_io_touch_2p_stop_flag; uint16_t mai2_io_get_api_version(void) { - return 0x0100; + return 0x0101; } HRESULT mai2_io_init(void) @@ -47,6 +51,10 @@ HRESULT mai2_io_poll(void) } else { mai2_io_coin = false; } + // If sinmai has enabled DebugInput, there is no need to input buttons through hook amdaemon. + if (!mai2_io_cfg.vk_btn_enable) { + return S_OK; + } //Player 1 if (GetAsyncKeyState(mai2_io_cfg.vk_1p_btn[0])) { @@ -142,3 +150,150 @@ void mai2_io_get_gamebtns(uint16_t *player1, uint16_t *player2) *player2 = mai2_player2_btn; } } + +HRESULT mai2_io_touch_init(mai2_io_touch_callback_t callback) +{ + _callback = callback; + return S_OK; +} + +void mai2_io_touch_set_sens(uint8_t *bytes) +{ +#if 0 + dprintf("Mai2 touch side %c: set sensor %s sensitivity to %d\n", bytes[1], sensor_to_str(bytes[2]), bytes[4]); +#endif + return; +} + +void mai2_io_touch_update(bool player1, bool player2) +{ + if (mai2_io_cfg.debug_input_1p) + { + if (player1 && mai2_io_touch_1p_thread == NULL) + { + mai2_io_touch_1p_thread = (HANDLE)_beginthreadex( + NULL, + 0, + mai2_io_touch_1p_thread_proc, + _callback, + 0, + NULL); + } + else if (!player1 && mai2_io_touch_1p_thread != NULL) + { + mai2_io_touch_1p_stop_flag = true; + + WaitForSingleObject(mai2_io_touch_1p_thread, INFINITE); + CloseHandle(mai2_io_touch_1p_thread); + mai2_io_touch_1p_thread = NULL; + + mai2_io_touch_1p_stop_flag = false; + } + } + if (mai2_io_cfg.debug_input_2p) + { + if (player2 && mai2_io_touch_2p_thread == NULL) + { + mai2_io_touch_2p_thread = (HANDLE)_beginthreadex( + NULL, + 0, + mai2_io_touch_2p_thread_proc, + _callback, + 0, + NULL); + } + else if (!player2 && mai2_io_touch_2p_thread != NULL) + { + mai2_io_touch_2p_stop_flag = true; + + WaitForSingleObject(mai2_io_touch_2p_thread, INFINITE); + CloseHandle(mai2_io_touch_2p_thread); + mai2_io_touch_2p_thread = NULL; + + mai2_io_touch_2p_stop_flag = false; + } + } +} + +static unsigned int __stdcall mai2_io_touch_1p_thread_proc(void *ctx) +{ + mai2_io_touch_callback_t callback = ctx; + + while (!mai2_io_touch_1p_stop_flag) + { + uint8_t state[7] = {0, 0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < 34; i++) + { + if (GetAsyncKeyState(mai2_io_cfg.vk_1p_touch[i])) + { + int byteIndex = i / 5; + int bitIndex = i % 5; + state[byteIndex] |= (1 << bitIndex); + } + } + callback(1, state); + Sleep(1); + } + return 0; +} + +static unsigned int __stdcall mai2_io_touch_2p_thread_proc(void *ctx) +{ + mai2_io_touch_callback_t callback = ctx; + + while (!mai2_io_touch_2p_stop_flag) + { + uint8_t state[7] = {0, 0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < 34; i++) + { + if (GetAsyncKeyState(mai2_io_cfg.vk_2p_touch[i])) + { + int byteIndex = i / 5; + int bitIndex = i % 5; + state[byteIndex] |= (1 << bitIndex); + } + } + callback(2, state); + Sleep(1); + } + return 0; +} + +HRESULT mai2_io_led_init(void) +{ + return S_OK; +} + +void mai2_io_led_set_fet_output(const uint8_t *rgb) +{ +#if 0 + dprintf("mai2 LED: BodyLed brightness: %d%%\n", (rgb[0] * 100) / 255); + dprintf("mai2 LED: ExtLed brightness: %d%%\n", (rgb[1] * 100) / 255); + dprintf("mai2 LED: SideLed brightness: %d%%\n", (rgb[2] * 100) / 255); +#endif + return; +} + +void mai2_io_led_dc_update(const uint8_t *rgb) +{ +#if 0 + for (int i = 0; i < 10; i++) { + dprintf("mai2 LED: LED %d: %02X %02X %02X Speed: %02X\n", + i, rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]); + } +#endif + return; +} + +void mai2_io_led_gs_update(const uint8_t *rgb) +{ +#if 0 + for (int i = 0; i < 8; i++) { + dprintf("mai2 LED: LED %d: %02X %02X %02X Speed: %02X\n", + i, rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]); + } +#endif + return; +} diff --git a/mai2io/mai2io.h b/mai2io/mai2io.h index 084228c..039094b 100644 --- a/mai2io/mai2io.h +++ b/mai2io/mai2io.h @@ -3,6 +3,7 @@ #include #include +#include enum { MAI2_IO_OPBTN_TEST = 0x01, @@ -66,3 +67,120 @@ void mai2_io_get_opbtns(uint8_t *opbtn); Minimum API version: 0x0100 */ void mai2_io_get_gamebtns(uint16_t *player1, uint16_t *player2); + +/* Callback function used by mai2_io_touch_1p/2p_thread_proc. + + The 'player'(1 or 2) parameter indicates which player the touch data is for. + + The 'state' represents a complete response packet. + The format of the state array is as follows: + uint8_t state[7] = { + bytes[0] - bit(0 , 0 , 0 , A5, A4, A3, A2, A1) + bytes[1] - bit(0 , 0 , 0 , B2, B1, A8, A7, A6) + bytes[2] - bit(0 , 0 , 0 , B7, B6, B5, B4, B3) + bytes[3] - bit(0 , 0 , 0 , D2, D1, C2, C1, B8) + bytes[4] - bit(0 , 0 , 0 , D7, D6, D5, D4, D3) + bytes[5] - bit(0 , 0 , 0 , E4, E3, E2, E1, D8) + bytes[6] - bit(0 , 0 , 0 , 0 , E8, E7, E6, E5) + } + The 7 bytes are the touch data, with each byte storing the touch state in the lower 5 bits. + A value of 1 indicates that the corresponding touch area is pressed. + The touch areas are ordered from A1 to E8, and the binary values are stored from low to high. */ + +typedef void (*mai2_io_touch_callback_t)(const uint8_t player, const uint8_t state[7]); + +/** + * @brief Initializes the touch input callback function + * + * This function accepts a callback function as a parameter and stores it in the global variable `_callback` + * for later handling of touch input events. + * + * @param callback The touch input callback function that takes two parameters: player number and the touch state array. + * @return HRESULT Returns the result of the operation, S_OK on success. + */ + +HRESULT mai2_io_touch_init(mai2_io_touch_callback_t callback); + +/* Send sensitivity setting data to the touch device. + Format: + bytes[0] - Header + bytes[1] - Target device, ASCII characters 'L' or 'R' + bytes[2] - Target touch point + bytes[3] - commandRatio identifier + bytes[4] - Ratio value to be set, within a fixed range + bytes[5] - Footer + + Example function, not actually used. The sensitivity range can be determined + based on the Ratio set within the game. */ + +void mai2_io_touch_set_sens(uint8_t *bytes); + +/** + * @brief Updates the touch input acceptance state + * + * This function determines whether the game is ready to accept touch input based on the states of player 1 and player 2. + * If the game is ready, it creates or stops the corresponding threads to handle touch data for each player. + * Whether or not threads are created for each player is controlled by `mai2_io_cfg.debug_input_1p` and `mai2_io_cfg.debug_input_2p` configuration. + * + * @param player1 If `true`, indicates the game is ready to accept touch data from player 1, `false` means the game is not ready. + * @param player2 If `true`, indicates the game is ready to accept touch data from player 2, `false` means the game is not ready. + */ + +void mai2_io_touch_update(bool player1, bool player2); + +/** + * @brief Player touch input handling thread + * + * This function runs in a separate thread, continuously monitoring player touch status and passing the state data + * to the main thread via a callback function. Each time a touch input is detected, it updates the `state` array and calls the callback. + * The thread stops when `mai2_io_touch_1p/2p_stop_flag` is `true`. + * + * @param ctx The callback function context, of type `mai2_io_touch_callback_t`, used to handle the touch input events. + * @return The thread's return value, typically `0`. + */ + +static unsigned int __stdcall mai2_io_touch_1p_thread_proc(void *ctx); + +static unsigned int __stdcall mai2_io_touch_2p_thread_proc(void *ctx); + +/* Initialize LED emulation. This function will be called before any + other mai2_io_led_*() function calls. + + All subsequent calls may originate from arbitrary threads and some may + overlap with each other. Ensuring synchronization inside your IO DLL is + your responsibility. + + Minimum API version: 0x0101 */ + +HRESULT mai2_io_led_init(void); + +/* Update the FET outputs. rgb is a pointer to an array up to 3 bytes. + + Set the brightness of the white light on the machine's outer shell. + The program will continuously send changed values to request the blinking effect. + + [0]: BodyLed + [1]: ExtLed + [2]: SideLed + + The LED is truned on when the byte is 255 and turned off when the byte is 0. + + Minimum API version: 0x0101 */ + +void mai2_io_led_set_fet_output(const uint8_t *rgb); + +/* The effect of this command is unknown, it is triggered after LED_15070_CMD_EEPROM_READ. */ + +void mai2_io_led_dc_update(const uint8_t *rgb); + +/* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. + + The LEDs are laid out as follows: + [0-7]: 8 button LED + + Each rgb value is comprised for 4 bytes in the order of R, G, B, Speed. + Speed is a value from 0 to 255, where 0 is the fastest speed and 255 is the slowest. + + Minimum API version: 0x0101 */ + +void mai2_io_led_gs_update(const uint8_t *rgb); diff --git a/mai2io/meson.build b/mai2io/meson.build index cdbfd35..3d06b9f 100644 --- a/mai2io/meson.build +++ b/mai2io/meson.build @@ -3,6 +3,9 @@ mai2io_lib = static_library( name_prefix : '', include_directories : inc, implicit_include_directories : false, + dependencies : [ + capnhook.get_variable('hook_dep'), + ], sources : [ 'mai2io.c', 'mai2io.h', diff --git a/meson.build b/meson.build index 41b49f4..da9b427 100644 --- a/meson.build +++ b/meson.build @@ -46,6 +46,9 @@ endif if get_option('log_all') or get_option('log_io3') add_project_arguments('-DLOG_IO3', language: 'c') endif +if get_option('log_all') or get_option('log_led15070') + add_project_arguments('-DLOG_LED15070', language: 'c') +endif if get_option('log_all') or get_option('log_led15093') add_project_arguments('-DLOG_LED15093', language: 'c') endif @@ -61,6 +64,9 @@ endif if get_option('log_all') or get_option('log_carol_touch') add_project_arguments('-DLOG_CAROL_TOUCH', language: 'c') endif +if get_option('log_all') or get_option('log_mai2_touch') + add_project_arguments('-DLOG_MAI2_TOUCH', language: 'c') +endif if get_option('log_all') or get_option('log_chuni_slider') add_project_arguments('-DLOG_CHUNI_SLIDER', language: 'c') endif diff --git a/meson_options.txt b/meson_options.txt index fb39b10..de9aefc 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -13,6 +13,11 @@ option('log_io3', value : false, description : 'Enable debug logging for JVS' ) +option('log_led15070', + type : 'boolean', + value : false, + description : 'Enable debug logging for the 15070 LED board emulation' +) option('log_led15093', type : 'boolean', value : false, @@ -38,6 +43,11 @@ option('log_carol_touch', value : false, description : 'Enable debug logging for the Carlo Touchscreen' ) +option('log_mai2_touch', + type : 'boolean', + value : false, + description : 'Enable debug logging for the mai2 TouchPanel' +) option('log_chuni_slider', type : 'boolean', value : false, diff --git a/platform/epay.c b/platform/epay.c index 0faf145..4a231c2 100644 --- a/platform/epay.c +++ b/platform/epay.c @@ -189,7 +189,7 @@ HRESULT epay_hook_init(const struct epay_config *cfg) { thinca_stub->impl1->unk220 = thinca_unk; thinca_stub->impl1->unk228 = thinca_unk; - dprintf("Epay: Init\n"); + dprintf("Epay: Init.\n"); return hr; } From 004a2f6dcdfc9b218718e690df98938350d77508 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Fri, 21 Feb 2025 19:37:54 -0500 Subject: [PATCH 2/9] docs: fix playformID and billingType config docs --- dist/cxb/segatools.ini | 2 +- doc/config/common.md | 38 ++++++++++++++++++-------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/dist/cxb/segatools.ini b/dist/cxb/segatools.ini index 1fe70c8..40589de 100644 --- a/dist/cxb/segatools.ini +++ b/dist/cxb/segatools.ini @@ -60,7 +60,7 @@ enable=1 subnet=192.168.150.0 billingCa=../DEVICE/ca.crt billingPub=../DEVICE/billing.pub -billingType=2 +billingType=0 [eeprom] ; See above diff --git a/doc/config/common.md b/doc/config/common.md index 2796ded..a25e353 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -420,18 +420,22 @@ Default: (Varies depending on game) Override the game's four-character platform code (e.g. `AAV2` for Nu 2). This is actually supposed to be a separate three-character `platformId` and -integer `modelType` setting, but they are combined here for convenience. Valid -values include: +integer `modelType` setting, but they are combined here for convenience. -- `AAV0`: Nu 1 (Project DIVA) -- `AAV1`: Nu 1.1 (Chunithm) -- `AAV2`: Nu 2 (Initial D Zero) -- `AAW0`: NuSX 1 -- `AAW1`: NuSX 1.1 -- `ACA0`: ALLS UX -- `ACA1`: ALLS HX -- `ACA2`: ALLS UX (without dedicated GPU) -- `ACA4`: ALLS MX +`platformId` is one of the following: +- `AAV`: Nu 1/1.1/2 +- `AAW`: NuSX 1/1.1 +- `ACA`: ALLS UX/HX/MX + +`modelType` is one of the following: +- `1`: Server (SV) +- `2`: Satalite (ST) +- `3`: Live (LV) +- `4`: Terminal (TN) + +It's safe to assume that every game you'll be playing with these tools will be a Satalite. +Some games care, others don't. Some even change how they run based on this value (Wonderland Wars +will boot into terminal mode if `modelType` is 4). ### `region` @@ -468,15 +472,9 @@ the billing transactions. Default: `1` -Set the billing "type" for the keychip. The type determins what kind of revenue share, -if any, the game maker has with SEGA. Some games may be picky and require types other -then 1 (ex. crossbeats REV. requires billing type 2), so this option is provided if this -is an issue. Billing types are: - -- 0: No billing? -- 1: Billing type A -- 2: Billing type B1 -- 3: Billing type B2 +Sets the billing type, a single bit value that flags the cabinet as a rental if set to `1`, or `0` otherwise. +Certian games that were only sold officially as full purchases (that is, non-rentals) must have this value set to 0. +NOTE: Crossbeats erroniously displays Billing modes A/B1/B2, but this value comes from the `modelType` and NOT this value! ### `systemFlag` From efe01d92a65a4f63fdc7975121e389c896653298 Mon Sep 17 00:00:00 2001 From: kyoubate-haruka <46010460+kyoubate-haruka@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:49:22 +0000 Subject: [PATCH 3/9] Fix MSVC build again, add support for standalone MSVC compiler (#59) After switching away from VS, I realized the buildscript wouldn't detect the standalone MSVC compiler, because for whatever genius reason, MS installs that in the x86 program files directory... Also fixes some duplicate definitions and a missing library that MSVC doesn't like ah compilers... Reviewed-on: https://gitea.tendokyu.moe/TeamTofuShop/segatools/pulls/59 Co-authored-by: kyoubate-haruka <46010460+kyoubate-haruka@users.noreply.github.com> Co-committed-by: kyoubate-haruka <46010460+kyoubate-haruka@users.noreply.github.com> --- .gitignore | 3 +++ amex/gpio.c | 1 - hooklib/meson.build | 1 + meson.build | 1 + msvc-build.bat | 9 ++++----- platform/system.c | 1 - unityhook/doorstop.c | 1 + 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index d42760f..f5d9008 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ subprojects/capnhook # For enabling debug logging on local builds MesonLocalOptions.mk + +# Some meson cache thing +.meson-subproject-wrap-hash.txt diff --git a/amex/gpio.c b/amex/gpio.c index 86eadad..5d6ead1 100644 --- a/amex/gpio.c +++ b/amex/gpio.c @@ -1,5 +1,4 @@ #include -#include #include #include diff --git a/hooklib/meson.build b/hooklib/meson.build index 7d5e7b8..e6908d6 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -4,6 +4,7 @@ hooklib_lib = static_library( implicit_include_directories : false, dependencies : [ capnhook.get_variable('hook_dep'), + Ws2_32_lib ], sources : [ 'cursor.c', diff --git a/meson.build b/meson.build index 41b49f4..40a99c4 100644 --- a/meson.build +++ b/meson.build @@ -83,6 +83,7 @@ dxguid_lib = cc.find_library('dxguid') xinput_lib = cc.find_library('xinput') pathcch_lib = cc.find_library('pathcch') imagehlp_lib = cc.find_library('imagehlp') +Ws2_32_lib = cc.find_library('Ws2_32') inc = include_directories('.') capnhook = subproject('capnhook') diff --git a/msvc-build.bat b/msvc-build.bat index ae060f0..fac3925 100644 --- a/msvc-build.bat +++ b/msvc-build.bat @@ -52,17 +52,16 @@ exit /b rem This should works for Visual Studio 2017+ :detect-visual-studio ( - rem Who the hell on earth is still using a 32bit Windows in 2024 - if "%ProgramFiles(x86)%"=="" ( - set VSWHERE="%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" - ) else ( + rem Fall back to x86 program directory for MSVC standalone if it can't be found in x64, because even though it's x64 compilers, they install in x86 program files for whatever dumb reason + set VSWHERE="%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" + if not exist %VSWHERE% ( set VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ) if exist %VSWHERE% ( REM get vcvarsall by using vswhere set VSVARSALL="" - for /f "tokens=* usebackq" %%i in (`%VSWHERE% -find VC\Auxiliary\Build\vcvarsall.bat`) do set VSVARSALL="%%i" + for /f "tokens=* usebackq" %%i in (`%VSWHERE% -products * -find VC\Auxiliary\Build\vcvarsall.bat`) do set VSVARSALL="%%i" ) else ( REM fallback to old method set VSVARSALL="%VS_INSTALLATION%\VC\Auxiliary\Build\vcvarsall.bat" diff --git a/platform/system.c b/platform/system.c index a82c326..dbc832f 100644 --- a/platform/system.c +++ b/platform/system.c @@ -1,5 +1,4 @@ #include -#include #include #include diff --git a/unityhook/doorstop.c b/unityhook/doorstop.c index d2cbd5c..04dee02 100644 --- a/unityhook/doorstop.c +++ b/unityhook/doorstop.c @@ -5,6 +5,7 @@ // https://github.com/NeighTools/UnityDoorstop #include #include +#include #include #include From 4cb76dd1ee8682a517cf210624b4971bb47c1fda Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 2 Mar 2025 00:01:45 +0100 Subject: [PATCH 4/9] mai2: update all LED boards to use two boards --- board/led15070.c | 30 +++++---- board/led15070.h | 11 ++-- board/led15093.c | 63 +++++++------------ board/led15093.h | 4 +- chunihook/config.c | 3 +- chunihook/dllmain.c | 3 +- chuniio/chuniio.c | 16 ++++- chusanhook/config.c | 3 +- chusanhook/dllmain.c | 49 ++++++++------- dist/mai2/segatools.ini | 14 +++-- fgohook/config.c | 3 +- fgohook/dllmain.c | 3 +- idachook/config.c | 3 +- idachook/dllmain.c | 3 +- idachook/idac-dll.h | 6 +- idachook/io4.c | 2 +- idacio/dllmain.c | 6 +- idacio/idacio.h | 6 +- idzhook/config.c | 3 +- idzhook/dllmain.c | 3 +- idzhook/idz-dll.h | 6 +- idzhook/jvs.c | 2 +- idzio/dllmain.c | 6 +- idzio/idzio.h | 6 +- kemonohook/config.c | 3 +- kemonohook/dllmain.c | 55 ++++++++-------- mai2hook/config.c | 3 +- mai2hook/dllmain.c | 3 +- mai2hook/mai2-dll.h | 6 +- mai2hook/touch.c | 15 ++++- mai2hook/touch.h | 11 +--- mai2io/mai2io.c | 136 +++++++++++++++------------------------- mai2io/mai2io.h | 14 +++-- mu3hook/config.c | 3 +- mu3hook/dllmain.c | 3 +- swdchook/config.c | 3 +- swdchook/dllmain.c | 3 +- swdchook/io4.c | 2 +- swdchook/swdc-dll.h | 6 +- swdcio/dllmain.c | 6 +- swdcio/swdcio.h | 6 +- tokyohook/config.c | 3 +- tokyohook/dllmain.c | 3 +- 43 files changed, 273 insertions(+), 265 deletions(-) diff --git a/board/led15070.c b/board/led15070.c index 579de7c..43a015d 100644 --- a/board/led15070.c +++ b/board/led15070.c @@ -103,19 +103,30 @@ HRESULT led15070_hook_init( io_led_set_fet_output_t _led_set_fet_output, io_led_dc_update_t _led_dc_update, io_led_gs_update_t _led_gs_update, - unsigned int first_port, - unsigned int num_boards) + unsigned int port_no[2]) { + unsigned int num_boards = 0; + assert(cfg != NULL); + assert(_led_init != NULL); if (!cfg->enable) { return S_FALSE; } - if (cfg->port_no != 0) { - first_port = cfg->port_no; + for (int i = 0; i < led15070_nboards; i++) + { + if (cfg->port_no[i] != 0) { + port_no[i] = cfg->port_no[i]; + } + + if (port_no[i] != 0) { + num_boards++; + } } + assert(num_boards != 0); + led_init = _led_init; led_set_fet_output = _led_set_fet_output; led_dc_update = _led_dc_update; @@ -131,10 +142,7 @@ HRESULT led15070_hook_init( InitializeCriticalSection(&v->lock); - // TODO: IMPROVE! - first_port = i == 1 ? first_port + 2 : first_port; - - uart_init(&v->boarduart, first_port); + uart_init(&v->boarduart, port_no[i]); v->boarduart.baud.BaudRate = 115200; v->boarduart.written.bytes = v->written_bytes; v->boarduart.written.nbytes = sizeof(v->written_bytes); @@ -681,7 +689,7 @@ static HRESULT led15070_req_set_fet_output(int board, const struct led15070_req_ led15070_per_board_vars[board].fet[2] = req->payload[2]; // B or FET2 intensity if (led_set_fet_output) - led_set_fet_output((const uint8_t*)led15070_per_board_vars[board].fet); + led_set_fet_output(board, (const uint8_t*)led15070_per_board_vars[board].fet); if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -737,7 +745,7 @@ static HRESULT led15070_req_dc_update(int board, const struct led15070_req_any * #endif if (led_dc_update) - led_dc_update((const uint8_t*)led15070_per_board_vars[board].dc); + led_dc_update(board, (const uint8_t*)led15070_per_board_vars[board].dc); if (!led15070_per_board_vars[board].enable_response) return S_OK; @@ -764,7 +772,7 @@ static HRESULT led15070_req_gs_update(int board, const struct led15070_req_any * #endif if (led_gs_update) - led_gs_update((const uint8_t*)led15070_per_board_vars[board].gs); + led_gs_update(board, (const uint8_t*)led15070_per_board_vars[board].gs); if (!led15070_per_board_vars[board].enable_response) return S_OK; diff --git a/board/led15070.h b/board/led15070.h index a2ad863..ae237b4 100644 --- a/board/led15070.h +++ b/board/led15070.h @@ -7,7 +7,7 @@ struct led15070_config { bool enable; - unsigned int port_no; + unsigned int port_no[2]; char board_number[8]; uint8_t fw_ver; uint16_t fw_sum; @@ -15,9 +15,9 @@ struct led15070_config { }; typedef HRESULT (*io_led_init_t)(void); -typedef void (*io_led_set_fet_output_t)(const uint8_t *rgb); -typedef void (*io_led_dc_update_t)(const uint8_t *rgb); -typedef void (*io_led_gs_update_t)(const uint8_t *rgb); +typedef void (*io_led_set_fet_output_t)(uint8_t board, const uint8_t *rgb); +typedef void (*io_led_dc_update_t)(uint8_t board, const uint8_t *rgb); +typedef void (*io_led_gs_update_t)(uint8_t board, const uint8_t *rgb); HRESULT led15070_hook_init( const struct led15070_config *cfg, @@ -25,5 +25,4 @@ HRESULT led15070_hook_init( io_led_set_fet_output_t _led_set_fet_output, io_led_dc_update_t _led_dc_update, io_led_gs_update_t _led_gs_update, - unsigned int first_port, - unsigned int num_boards); + unsigned int port_no[2]); diff --git a/board/led15093.c b/board/led15093.c index a070a24..31ccb4e 100644 --- a/board/led15093.c +++ b/board/led15093.c @@ -107,9 +107,13 @@ static uint8_t led15093_host_adr = 1; static io_led_init_t led_init; static io_led_set_leds_t set_leds; -HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init, - io_led_set_leds_t _set_leds, unsigned int first_port, unsigned int num_boards, uint8_t board_adr, uint8_t host_adr) +HRESULT led15093_hook_init( + const struct led15093_config *cfg, + io_led_init_t _led_init, + io_led_set_leds_t _set_leds, + unsigned int port_no[2]) { + unsigned int num_boards = 0; assert(cfg != NULL); assert(_led_init != NULL); @@ -119,14 +123,24 @@ HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led return S_FALSE; } - if (cfg->port_no != 0) { - first_port = cfg->port_no; + for (int i = 0; i < led15093_nboards; i++) + { + if (cfg->port_no[i] != 0) { + port_no[i] = cfg->port_no[i]; + } + + if (port_no[i] != 0) { + num_boards++; + } } + assert(num_boards != 0); + + led15093_board_adr = num_boards; + led15093_host_adr = num_boards == 2 ? 1 : 2; + led_init = _led_init; set_leds = _set_leds; - led15093_board_adr = board_adr; - led15093_host_adr = host_adr; memcpy(led15093_board_num, cfg->board_number, sizeof(led15093_board_num)); memcpy(led15093_chip_num, cfg->chip_number, sizeof(led15093_chip_num)); @@ -140,7 +154,7 @@ HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led InitializeCriticalSection(&vb->lock); - uart_init(&vb->boarduart, first_port + i); + uart_init(&vb->boarduart, port_no[i]); if (cfg->high_baudrate) { vb->boarduart.baud.BaudRate = 460800; } else { @@ -209,7 +223,6 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp) _led15093_per_board_vars *v = &led15093_per_board_vars[board]; struct uart *boarduart = &led15093_per_board_vars[board].boarduart; - /* if (irp->op == IRP_OP_OPEN) { // Unfortunately the LED board UART gets opened and closed repeatedly @@ -236,30 +249,6 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp) } } } - */ - - if (irp->op == IRP_OP_OPEN) { - dprintf("LED 15093: Starting backend DLL\n"); - // int res = led_init(); - hr = led_init(); - - /* - if (res != 0) { - dprintf("LED 15093: Backend error, LED board disconnected: " - "%d\n", - res); - - return E_FAIL; - } - */ - if (FAILED(hr)) { - dprintf("LED 15093: Backend error, LED board disconnected: " - "%x\n", - (int) hr); - - return hr; - } - } hr = uart_handle_irp(boarduart, irp); @@ -688,16 +677,6 @@ static HRESULT led15093_req_set_imm_led(int board, const struct led15093_req_set return E_INVALIDARG; } - /* - if (board == 0) { - dprintf("board %d: red: %d, green: %d, blue: %d\n", board, req->data[0x96], req->data[0x97], req->data[0x98]); - } - else if (board == 1) - { - dprintf("board %d: red: %d, green: %d, blue: %d\n", board, req->data[0xb4], req->data[0xb5], req->data[0xb6]); - } - */ - // Return the current LED data, remove const qualifier set_leds(board, (uint8_t *) req->data); diff --git a/board/led15093.h b/board/led15093.h index 869a11b..5ff930b 100644 --- a/board/led15093.h +++ b/board/led15093.h @@ -8,7 +8,7 @@ struct led15093_config { bool enable; bool high_baudrate; - unsigned int port_no; + unsigned int port_no[2]; char board_number[8]; char chip_number[5]; char boot_chip_number[5]; @@ -20,5 +20,5 @@ typedef HRESULT (*io_led_init_t)(void); typedef void (*io_led_set_leds_t)(uint8_t board, uint8_t *rgb); HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init, - io_led_set_leds_t _set_leds, unsigned int first_port, unsigned int num_boards, uint8_t board_adr, uint8_t host_adr); + io_led_set_leds_t _set_leds, unsigned int port_no[2]); diff --git a/chunihook/config.c b/chunihook/config.c index 2ad959e..d711fec 100644 --- a/chunihook/config.c +++ b/chunihook/config.c @@ -56,7 +56,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = 0; + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename); diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index d421e23..a3fa8ab 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -114,8 +114,9 @@ static DWORD CALLBACK chuni_pre_startup(void) { dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n"); } else { + unsigned int led_port_no[2] = {10, 11}; hr = led15093_hook_init(&chuni_hook_cfg.led15093, - chuni_dll.led_init, chuni_dll.led_set_leds, 10, 2, 2, 1); + chuni_dll.led_init, chuni_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/chuniio/chuniio.c b/chuniio/chuniio.c index 614dc47..a2c0336 100644 --- a/chuniio/chuniio.c +++ b/chuniio/chuniio.c @@ -174,6 +174,20 @@ HRESULT chuni_io_led_init(void) } void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) -{ +{ +#if 0 + if (board == 0) { + dprintf("CHUNI LED: Left Air 1: red: %d, green: %d, blue: %d\n", rgb[0x96], rgb[0x97], rgb[0x98]); + dprintf("CHUNI LED: Left Air 2: red: %d, green: %d, blue: %d\n", rgb[0x99], rgb[0x9A], rgb[0x9B]); + dprintf("CHUNI LED: Left Air 3: red: %d, green: %d, blue: %d\n", rgb[0x9C], rgb[0x9D], rgb[0x9E]); + } + else if (board == 1) + { + dprintf("CHUNI LED: Right Air 1: red: %d, green: %d, blue: %d\n", rgb[0xB4], rgb[0xB5], rgb[0xB6]); + dprintf("CHUNI LED: Right Air 2: red: %d, green: %d, blue: %d\n", rgb[0xB7], rgb[0xB8], rgb[0xB9]); + dprintf("CHUNI LED: Right Air 3: red: %d, green: %d, blue: %d\n", rgb[0xBA], rgb[0xBB], rgb[0xBC]); + } +#endif + led_output_update(board, rgb); } diff --git a/chusanhook/config.c b/chusanhook/config.c index 0ec8c61..691e8f7 100644 --- a/chusanhook/config.c +++ b/chusanhook/config.c @@ -96,7 +96,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = 0; + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename); diff --git a/chusanhook/dllmain.c b/chusanhook/dllmain.c index 9a2f5da..e29bf7f 100644 --- a/chusanhook/dllmain.c +++ b/chusanhook/dllmain.c @@ -22,32 +22,23 @@ COM4: 837-15396 "Gen 3" Aime Reader */ -#include - #include #include +#include #include "amex/amex.h" - #include "board/sg-reader.h" #include "board/vfd.h" - +#include "chuniio/chuniio.h" #include "chusanhook/config.h" #include "chusanhook/io4.h" #include "chusanhook/slider.h" - -#include "chuniio/chuniio.h" - -#include "hook/process.h" - #include "gfxhook/d3d9.h" #include "gfxhook/gfx.h" - +#include "hook/process.h" #include "hooklib/serial.h" #include "hooklib/spike.h" - #include "platform/platform.h" - #include "util/dprintf.h" #include "util/env.h" @@ -55,8 +46,7 @@ static HMODULE chusan_hook_mod; static process_entry_t chusan_startup; static struct chusan_hook_config chusan_hook_cfg; -static DWORD CALLBACK chusan_pre_startup(void) -{ +static DWORD CALLBACK chusan_pre_startup(void) { HMODULE d3dc; HMODULE dbghelp; HRESULT hr; @@ -88,7 +78,7 @@ static DWORD CALLBACK chusan_pre_startup(void) chusan_hook_config_load(&chusan_hook_cfg, get_config_path()); /* Hook Win32 APIs */ - + dvd_hook_init(&chusan_hook_cfg.dvd, chusan_hook_mod); gfx_hook_init(&chusan_hook_cfg.gfx); gfx_d3d9_hook_init(&chusan_hook_cfg.gfx, chusan_hook_mod); @@ -154,19 +144,31 @@ static DWORD CALLBACK chusan_pre_startup(void) } } - if ( chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL ) - { - dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n"); + unsigned int led_port_no[2]; + + if (is_cvt) { + led_port_no[0] = 2; + led_port_no[1] = 3; } else { - hr = led15093_hook_init(&chusan_hook_cfg.led15093, - chuni_dll.led_init, chuni_dll.led_set_leds, first_port, 2, 2, 1); + led_port_no[0] = 20; + led_port_no[1] = 21; + } + + if (chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL) { + dprintf( + "IO DLL doesn't support led_init/led_set_leds, cannot start " + "LED15093 hook\n"); + } else { + hr = led15093_hook_init(&chusan_hook_cfg.led15093, chuni_dll.led_init, + chuni_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; } } - hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_cvt ? 2: 3, chusan_hook_mod); + hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_cvt ? 2 : 3, + chusan_hook_mod); if (FAILED(hr)) { goto fail; @@ -186,8 +188,7 @@ fail: ExitProcess(EXIT_FAILURE); } -BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) -{ +BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) { HRESULT hr; if (cause != DLL_PROCESS_ATTACH) { @@ -199,7 +200,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) hr = process_hijack_startup(chusan_pre_startup, &chusan_startup); if (!SUCCEEDED(hr)) { - dprintf("Failed to hijack process startup: %x\n", (int) hr); + dprintf("Failed to hijack process startup: %x\n", (int)hr); } return SUCCEEDED(hr); diff --git a/dist/mai2/segatools.ini b/dist/mai2/segatools.ini index 46fb4e5..dde853f 100644 --- a/dist/mai2/segatools.ini +++ b/dist/mai2/segatools.ini @@ -69,6 +69,15 @@ freeplay=0 ; this to 1 on exactly one machine and set this to 0 on all others. dipsw1=1 +; ----------------------------------------------------------------------------- +; LED settings +; ----------------------------------------------------------------------------- + +[led15070] +; Enable emulation of the 837-15070-04 controlled lights, which handle the +; cabinet and button LEDs. +enable=1 + ; ----------------------------------------------------------------------------- ; Misc. hook settings ; ----------------------------------------------------------------------------- @@ -145,8 +154,3 @@ p2Enable=1 ;p1TouchA2=0x53 ; ... etc ... ;p1TouchE8=0x53 - -[led15070] -; Enable emulation of the 837-15070-02 controlled lights, which handle the -; cabinet and seat LEDs. -enable=1 \ No newline at end of file diff --git a/fgohook/config.c b/fgohook/config.c index 30dbf86..766240c 100644 --- a/fgohook/config.c +++ b/fgohook/config.c @@ -48,7 +48,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); diff --git a/fgohook/dllmain.c b/fgohook/dllmain.c index e82423f..a65cbcd 100644 --- a/fgohook/dllmain.c +++ b/fgohook/dllmain.c @@ -133,8 +133,9 @@ static DWORD CALLBACK fgo_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {17, 0}; hr = led15093_hook_init(&fgo_hook_cfg.led15093, - fgo_dll.led_init, fgo_dll.led_set_leds, 17, 1, 1, 2); + fgo_dll.led_init, fgo_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/idachook/config.c b/idachook/config.c index 279aba7..0e8dc88 100644 --- a/idachook/config.c +++ b/idachook/config.c @@ -23,7 +23,8 @@ void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) wchar_t tmpstr[16]; cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); /* TODO: Unknown, no firmware file available */ cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x0000, filename); diff --git a/idachook/dllmain.c b/idachook/dllmain.c index 0e955e8..71a4ccd 100644 --- a/idachook/dllmain.c +++ b/idachook/dllmain.c @@ -94,8 +94,9 @@ static DWORD CALLBACK idac_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {2, 0}; hr = led15070_hook_init(&idac_hook_cfg.led15070, idac_dll.led_init, - idac_dll.led_set_fet_output, NULL, idac_dll.led_gs_update, 2, 1); + idac_dll.led_set_fet_output, NULL, idac_dll.led_gs_update, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/idachook/idac-dll.h b/idachook/idac-dll.h index 88ac299..92aa664 100644 --- a/idachook/idac-dll.h +++ b/idachook/idac-dll.h @@ -12,9 +12,9 @@ struct idac_dll { void (*get_shifter)(uint8_t *gear); void (*get_analogs)(struct idac_io_analog_state *out); HRESULT (*led_init)(void); - void (*led_set_fet_output)(const uint8_t *rgb); - void (*led_gs_update)(const uint8_t *rgb); - void (*led_set_leds)(const uint8_t *rgb); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); + void (*led_set_leds)(uint8_t board, const uint8_t *rgb); HRESULT (*ffb_init)(void); void (*ffb_toggle)(bool active); void (*ffb_constant_force)(uint8_t direction, uint8_t force); diff --git a/idachook/io4.c b/idachook/io4.c index 1e4d990..3861ef8 100644 --- a/idachook/io4.c +++ b/idachook/io4.c @@ -159,7 +159,7 @@ static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len) lights_data & IDAC_IO_LED_LEFT ? 0xFF : 0x00, }; - idac_dll.led_set_leds(rgb_out); + idac_dll.led_set_leds(0, rgb_out); return S_OK; } diff --git a/idacio/dllmain.c b/idacio/dllmain.c index 6a5dba8..fe8246e 100644 --- a/idacio/dllmain.c +++ b/idacio/dllmain.c @@ -127,7 +127,7 @@ HRESULT idac_io_led_init(void) return S_OK; } -void idac_io_led_set_fet_output(const uint8_t *rgb) +void idac_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDAC LED: LEFT SEAT LED: %02X\n", rgb[0]); @@ -137,7 +137,7 @@ void idac_io_led_set_fet_output(const uint8_t *rgb) return; } -void idac_io_led_gs_update(const uint8_t *rgb) +void idac_io_led_gs_update(uint8_t board, const uint8_t *rgb) { #if 0 for (int i = 0; i < 9; i++) { @@ -149,7 +149,7 @@ void idac_io_led_gs_update(const uint8_t *rgb) return; } -void idac_io_led_set_leds(const uint8_t *rgb) +void idac_io_led_set_leds(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDAC LED: START: %02X\n", rgb[0]); diff --git a/idacio/idacio.h b/idacio/idacio.h index 513c9d1..bc58a34 100644 --- a/idacio/idacio.h +++ b/idacio/idacio.h @@ -127,7 +127,7 @@ HRESULT idac_io_led_init(void); Minimum API version: 0x0101 */ -void idac_io_led_set_fet_output(const uint8_t *rgb); +void idac_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); /* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. @@ -144,7 +144,7 @@ void idac_io_led_set_fet_output(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idac_io_led_gs_update(const uint8_t *rgb); +void idac_io_led_gs_update(uint8_t board, const uint8_t *rgb); /* Update the cabinet button LEDs. rgb is a pointer to an array up to 6 bytes. @@ -160,7 +160,7 @@ void idac_io_led_gs_update(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idac_io_led_set_leds(const uint8_t *rgb); +void idac_io_led_set_leds(uint8_t board, const uint8_t *rgb); /* Initialize FFB emulation. This function will be called before any other idac_io_ffb_*() function calls. diff --git a/idzhook/config.c b/idzhook/config.c index 0378cbe..6bbc0ed 100644 --- a/idzhook/config.c +++ b/idzhook/config.c @@ -27,7 +27,8 @@ void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) wchar_t tmpstr[16]; cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); /* TODO: Unknown, no firmware file available */ cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x0000, filename); diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index edf6cbb..534f4d0 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -128,8 +128,9 @@ static DWORD CALLBACK idz_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {11, 0}; hr = led15070_hook_init(&idz_hook_cfg.led15070, idz_dll.led_init, - idz_dll.led_set_fet_output, NULL, idz_dll.led_gs_update, 11, 1); + idz_dll.led_set_fet_output, NULL, idz_dll.led_gs_update, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/idzhook/idz-dll.h b/idzhook/idz-dll.h index e827f8e..4084d84 100644 --- a/idzhook/idz-dll.h +++ b/idzhook/idz-dll.h @@ -12,9 +12,9 @@ struct idz_dll { void (*jvs_read_shifter)(uint8_t *gear); void (*jvs_read_coin_counter)(uint16_t *total); HRESULT (*led_init)(void); - void (*led_set_fet_output)(const uint8_t *rgb); - void (*led_gs_update)(const uint8_t *rgb); - void (*led_set_leds)(const uint8_t *rgb); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); + void (*led_set_leds)(uint8_t board, const uint8_t *rgb); HRESULT (*ffb_init)(void); void (*ffb_toggle)(bool active); void (*ffb_constant_force)(uint8_t direction, uint8_t force); diff --git a/idzhook/jvs.c b/idzhook/jvs.c index 3531d55..2ded71c 100644 --- a/idzhook/jvs.c +++ b/idzhook/jvs.c @@ -192,5 +192,5 @@ static void idz_jvs_write_gpio(void *ctx, uint32_t state) state & IDZ_IO_LED_LEFT ? 0xFF : 0x00, }; - idz_dll.led_set_leds(rgb_out); + idz_dll.led_set_leds(0, rgb_out); } diff --git a/idzio/dllmain.c b/idzio/dllmain.c index 39d08fc..322d194 100644 --- a/idzio/dllmain.c +++ b/idzio/dllmain.c @@ -130,7 +130,7 @@ HRESULT idz_io_led_init(void) return S_OK; } -void idz_io_led_set_fet_output(const uint8_t *rgb) +void idz_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDZ LED: LEFT SEAT LED: %02X\n", rgb[0]); @@ -140,7 +140,7 @@ void idz_io_led_set_fet_output(const uint8_t *rgb) return; } -void idz_io_led_gs_update(const uint8_t *rgb) +void idz_io_led_gs_update(uint8_t board, const uint8_t *rgb) { #if 0 for (int i = 0; i < 9; i++) { @@ -152,7 +152,7 @@ void idz_io_led_gs_update(const uint8_t *rgb) return; } -void idz_io_led_set_leds(const uint8_t *rgb) +void idz_io_led_set_leds(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("IDZ LED: START: %02X\n", rgb[0]); diff --git a/idzio/idzio.h b/idzio/idzio.h index 8fd01d8..db64c44 100644 --- a/idzio/idzio.h +++ b/idzio/idzio.h @@ -138,7 +138,7 @@ HRESULT idz_io_led_init(void); Minimum API version: 0x0101 */ -void idz_io_led_set_fet_output(const uint8_t *rgb); +void idz_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); /* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. @@ -155,7 +155,7 @@ void idz_io_led_set_fet_output(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idz_io_led_gs_update(const uint8_t *rgb); +void idz_io_led_gs_update(uint8_t board, const uint8_t *rgb); /* Update the cabinet button LEDs. rgb is a pointer to an array up to 6 bytes. @@ -171,7 +171,7 @@ void idz_io_led_gs_update(const uint8_t *rgb); Minimum API version: 0x0101 */ -void idz_io_led_set_leds(const uint8_t *rgb); +void idz_io_led_set_leds(uint8_t board, const uint8_t *rgb); /* Initialize FFB emulation. This function will be called before any other idz_io_ffb_*() function calls. diff --git a/kemonohook/config.c b/kemonohook/config.c index ec00aa1..c008d88 100644 --- a/kemonohook/config.c +++ b/kemonohook/config.c @@ -65,7 +65,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 1, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); diff --git a/kemonohook/dllmain.c b/kemonohook/dllmain.c index 83a4290..3373489 100644 --- a/kemonohook/dllmain.c +++ b/kemonohook/dllmain.c @@ -1,28 +1,21 @@ -#include - #include +#include #include "board/io4.h" #include "board/sg-reader.h" #include "board/vfd.h" - +#include "hook/iohook.h" #include "hook/process.h" #include "hook/table.h" -#include "hook/iohook.h" - #include "hooklib/printer.h" #include "hooklib/serial.h" #include "hooklib/spike.h" - #include "kemonohook/config.h" #include "kemonohook/hooks.h" #include "kemonohook/jvs.h" #include "kemonohook/kemono-dll.h" - #include "platform/platform.h" - #include "unityhook/hook.h" - #include "util/dprintf.h" #include "util/env.h" @@ -47,29 +40,38 @@ static DWORD CALLBACK kemono_pre_startup(void) { // 2.02 does not call printer update functions uint16_t ret; - fwdlusb_updateFirmware_main(1, "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223100-014E-C300-MAINAPP.BIN", &ret); - if (ret != 0){ + fwdlusb_updateFirmware_main( + 1, + "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223100-014E-C300-" + "MAINAPP.BIN", + &ret); + if (ret != 0) { goto fail; } - fwdlusb_updateFirmware_dsp(2, "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223200-0101-C300-DSPAPP.BIN", &ret); - if (ret != 0){ + fwdlusb_updateFirmware_dsp( + 2, + "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\E0223200-0101-C300-" + "DSPAPP.BIN", + &ret); + if (ret != 0) { goto fail; } - fwdlusb_updateFirmware_param(3, "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\D0460700-0101-C300-PARAM.BIN", &ret); - if (ret != 0){ + fwdlusb_updateFirmware_param( + 3, + "UnityApp\\Parade_Data\\StreamingAssets\\Printer\\D0460700-0101-C300-" + "PARAM.BIN", + &ret); + if (ret != 0) { goto fail; } printer_hook_init(&kemono_hook_cfg.printer, 0, kemono_hook_mod); - printer_set_dimensions(720, 1028); // printer doesn't call setimageformat + printer_set_dimensions(720, 1028); // printer doesn't call setimageformat /* Initialize emulation hooks */ - hr = platform_hook_init( - &kemono_hook_cfg.platform, - "SDFL", - "AAW1", - kemono_hook_mod); + hr = platform_hook_init(&kemono_hook_cfg.platform, "SDFL", "AAW1", + kemono_hook_mod); if (FAILED(hr)) { goto fail; @@ -93,7 +95,9 @@ static DWORD CALLBACK kemono_pre_startup(void) { goto fail; } - hr = led15093_hook_init(&kemono_hook_cfg.led15093, kemono_dll.led_init, kemono_dll.led_set_leds, 10, 1, 1, 2); + unsigned int led_port_no[2] = {10, 0}; + hr = led15093_hook_init(&kemono_hook_cfg.led15093, kemono_dll.led_init, + kemono_dll.led_set_leds, led_port_no); if (FAILED(hr)) { goto fail; @@ -106,7 +110,8 @@ static DWORD CALLBACK kemono_pre_startup(void) { There seems to be an issue with other DLL hooks if `LoadLibraryW` is hooked earlier in the `kemonohook` initialization. */ - unity_hook_init(&kemono_hook_cfg.unity, kemono_hook_mod, kemono_extra_hooks_load); + unity_hook_init(&kemono_hook_cfg.unity, kemono_hook_mod, + kemono_extra_hooks_load); /* Initialize debug helpers */ @@ -118,7 +123,7 @@ static DWORD CALLBACK kemono_pre_startup(void) { return kemono_startup(); - fail: +fail: ExitProcess(EXIT_FAILURE); } @@ -134,7 +139,7 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) { hr = process_hijack_startup(kemono_pre_startup, &kemono_startup); if (!SUCCEEDED(hr)) { - dprintf("Failed to hijack process startup: %x\n", (int) hr); + dprintf("Failed to hijack process startup: %x\n", (int)hr); } return SUCCEEDED(hr); diff --git a/mai2hook/config.c b/mai2hook/config.c index 48c0c6e..5435ada 100644 --- a/mai2hook/config.c +++ b/mai2hook/config.c @@ -46,7 +46,8 @@ void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) wchar_t tmpstr[16]; cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x00, filename); diff --git a/mai2hook/dllmain.c b/mai2hook/dllmain.c index ac0e3a1..cb8a240 100644 --- a/mai2hook/dllmain.c +++ b/mai2hook/dllmain.c @@ -93,12 +93,13 @@ static DWORD CALLBACK mai2_pre_startup(void) } // LED board uses COM21 and COM23 + unsigned int led_port_no[2] = {21, 23}; hr = led15070_hook_init(&mai2_hook_cfg.led15070, mai2_dll.led_init, mai2_dll.led_set_fet_output, mai2_dll.led_dc_update, mai2_dll.led_gs_update, - 21, 2); + led_port_no); if (FAILED(hr)) { goto fail; diff --git a/mai2hook/mai2-dll.h b/mai2hook/mai2-dll.h index 6c205c8..599d44a 100644 --- a/mai2hook/mai2-dll.h +++ b/mai2hook/mai2-dll.h @@ -14,9 +14,9 @@ struct mai2_dll { void (*touch_set_sens)(uint8_t *bytes); void (*touch_update)(bool player1, bool player2); HRESULT (*led_init)(void); - void (*led_set_fet_output)(const uint8_t *rgb); - void (*led_dc_update)(const uint8_t *rgb); - void (*led_gs_update)(const uint8_t *rgb); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_dc_update)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); }; struct mai2_dll_config { diff --git a/mai2hook/touch.c b/mai2hook/touch.c index 75bbded..305d005 100644 --- a/mai2hook/touch.c +++ b/mai2hook/touch.c @@ -1,5 +1,16 @@ +#include +#include + +#include "hooklib/fdshark.h" +#include "hooklib/reg.h" + +#include "mai2hook/mai2-dll.h" #include "mai2hook/touch.h" +#include "util/dprintf.h" +#include "util/dump.h" + + static HRESULT read_reg_touch_1p(void *bytes, uint32_t *nbytes) { return reg_hook_read_wstr(bytes, nbytes, L"COM3"); @@ -83,7 +94,7 @@ HRESULT touch_hook_init(const struct touch_config *cfg) if (cfg->enable_2p) { - dprintf("Mai2 touch port 2P: Init.\n"); + dprintf("Mai2 touch 2P: Init.\n"); InitializeCriticalSection(&touch_2p_lock); uart_init(&touch_2p_uart, 4); @@ -245,4 +256,4 @@ static void touch_auto_scan(const uint8_t player, const uint8_t state[7]) memcpy(&touch_uart->readable.bytes[1], state, 7); touch_uart->readable.bytes[8] = res_end; touch_uart->readable.pos = 9; -} \ No newline at end of file +} diff --git a/mai2hook/touch.h b/mai2hook/touch.h index e25487e..f6fc72a 100644 --- a/mai2hook/touch.h +++ b/mai2hook/touch.h @@ -1,15 +1,10 @@ #pragma once -#include + +#include #include #include -#include -#include "hooklib/fdshark.h" -#include "hooklib/reg.h" #include "hooklib/uart.h" -#include "mai2hook/mai2-dll.h" -#include "util/dprintf.h" -#include "util/dump.h" struct touch_config { @@ -40,4 +35,4 @@ static HRESULT touch_handle_irp_locked(struct irp *irp, struct uart *uart); /* Called in mai2io to send touch data. Similar to chuni slider_res_auto_scan, but the host does not require periodic updates. Touch data is sent only when there is a change. */ -static void touch_auto_scan(const uint8_t player, const uint8_t state[7]); \ No newline at end of file +static void touch_auto_scan(const uint8_t player, const uint8_t state[7]); diff --git a/mai2io/mai2io.c b/mai2io/mai2io.c index 554e8dd..57404cb 100644 --- a/mai2io/mai2io.c +++ b/mai2io/mai2io.c @@ -1,9 +1,11 @@ -#include -#include - #include "mai2io/mai2io.h" -#include "mai2io/config.h" + +#include +#include + #include "mai2hook/touch.h" +#include "mai2io/config.h" +#include "util/dprintf.h" #include "util/env.h" static uint8_t mai2_opbtn; @@ -17,20 +19,15 @@ static bool mai2_io_touch_1p_stop_flag; static HANDLE mai2_io_touch_2p_thread; static bool mai2_io_touch_2p_stop_flag; -uint16_t mai2_io_get_api_version(void) -{ - return 0x0101; -} +uint16_t mai2_io_get_api_version(void) { return 0x0101; } -HRESULT mai2_io_init(void) -{ +HRESULT mai2_io_init(void) { mai2_io_config_load(&mai2_io_cfg, get_config_path()); return S_OK; } -HRESULT mai2_io_poll(void) -{ +HRESULT mai2_io_poll(void) { mai2_opbtn = 0; mai2_player1_btn = 0; mai2_player2_btn = 0; @@ -51,12 +48,13 @@ HRESULT mai2_io_poll(void) } else { mai2_io_coin = false; } - // If sinmai has enabled DebugInput, there is no need to input buttons through hook amdaemon. + // If sinmai has enabled DebugInput, there is no need to input buttons + // through hook amdaemon. if (!mai2_io_cfg.vk_btn_enable) { return S_OK; } - //Player 1 + // Player 1 if (GetAsyncKeyState(mai2_io_cfg.vk_1p_btn[0])) { mai2_player1_btn |= MAI2_IO_GAMEBTN_1; } @@ -93,7 +91,7 @@ HRESULT mai2_io_poll(void) mai2_player1_btn |= MAI2_IO_GAMEBTN_SELECT; } - //Player 2 + // Player 2 if (GetAsyncKeyState(mai2_io_cfg.vk_2p_btn[0])) { mai2_player2_btn |= MAI2_IO_GAMEBTN_1; } @@ -133,54 +131,40 @@ HRESULT mai2_io_poll(void) return S_OK; } -void mai2_io_get_opbtns(uint8_t *opbtn) -{ +void mai2_io_get_opbtns(uint8_t *opbtn) { if (opbtn != NULL) { *opbtn = mai2_opbtn; } } -void mai2_io_get_gamebtns(uint16_t *player1, uint16_t *player2) -{ +void mai2_io_get_gamebtns(uint16_t *player1, uint16_t *player2) { if (player1 != NULL) { *player1 = mai2_player1_btn; } - if (player2 != NULL ){ + if (player2 != NULL) { *player2 = mai2_player2_btn; } } -HRESULT mai2_io_touch_init(mai2_io_touch_callback_t callback) -{ +HRESULT mai2_io_touch_init(mai2_io_touch_callback_t callback) { _callback = callback; return S_OK; } -void mai2_io_touch_set_sens(uint8_t *bytes) -{ +void mai2_io_touch_set_sens(uint8_t *bytes) { #if 0 dprintf("Mai2 touch side %c: set sensor %s sensitivity to %d\n", bytes[1], sensor_to_str(bytes[2]), bytes[4]); #endif return; } -void mai2_io_touch_update(bool player1, bool player2) -{ - if (mai2_io_cfg.debug_input_1p) - { - if (player1 && mai2_io_touch_1p_thread == NULL) - { +void mai2_io_touch_update(bool player1, bool player2) { + if (mai2_io_cfg.debug_input_1p) { + if (player1 && mai2_io_touch_1p_thread == NULL) { mai2_io_touch_1p_thread = (HANDLE)_beginthreadex( - NULL, - 0, - mai2_io_touch_1p_thread_proc, - _callback, - 0, - NULL); - } - else if (!player1 && mai2_io_touch_1p_thread != NULL) - { + NULL, 0, mai2_io_touch_1p_thread_proc, _callback, 0, NULL); + } else if (!player1 && mai2_io_touch_1p_thread != NULL) { mai2_io_touch_1p_stop_flag = true; WaitForSingleObject(mai2_io_touch_1p_thread, INFINITE); @@ -190,20 +174,12 @@ void mai2_io_touch_update(bool player1, bool player2) mai2_io_touch_1p_stop_flag = false; } } - if (mai2_io_cfg.debug_input_2p) - { - if (player2 && mai2_io_touch_2p_thread == NULL) - { + + if (mai2_io_cfg.debug_input_2p) { + if (player2 && mai2_io_touch_2p_thread == NULL) { mai2_io_touch_2p_thread = (HANDLE)_beginthreadex( - NULL, - 0, - mai2_io_touch_2p_thread_proc, - _callback, - 0, - NULL); - } - else if (!player2 && mai2_io_touch_2p_thread != NULL) - { + NULL, 0, mai2_io_touch_2p_thread_proc, _callback, 0, NULL); + } else if (!player2 && mai2_io_touch_2p_thread != NULL) { mai2_io_touch_2p_stop_flag = true; WaitForSingleObject(mai2_io_touch_2p_thread, INFINITE); @@ -215,18 +191,14 @@ void mai2_io_touch_update(bool player1, bool player2) } } -static unsigned int __stdcall mai2_io_touch_1p_thread_proc(void *ctx) -{ +static unsigned int __stdcall mai2_io_touch_1p_thread_proc(void *ctx) { mai2_io_touch_callback_t callback = ctx; - while (!mai2_io_touch_1p_stop_flag) - { + while (!mai2_io_touch_1p_stop_flag) { uint8_t state[7] = {0, 0, 0, 0, 0, 0, 0}; - for (int i = 0; i < 34; i++) - { - if (GetAsyncKeyState(mai2_io_cfg.vk_1p_touch[i])) - { + for (int i = 0; i < 34; i++) { + if (GetAsyncKeyState(mai2_io_cfg.vk_1p_touch[i])) { int byteIndex = i / 5; int bitIndex = i % 5; state[byteIndex] |= (1 << bitIndex); @@ -238,18 +210,14 @@ static unsigned int __stdcall mai2_io_touch_1p_thread_proc(void *ctx) return 0; } -static unsigned int __stdcall mai2_io_touch_2p_thread_proc(void *ctx) -{ +static unsigned int __stdcall mai2_io_touch_2p_thread_proc(void *ctx) { mai2_io_touch_callback_t callback = ctx; - while (!mai2_io_touch_2p_stop_flag) - { + while (!mai2_io_touch_2p_stop_flag) { uint8_t state[7] = {0, 0, 0, 0, 0, 0, 0}; - for (int i = 0; i < 34; i++) - { - if (GetAsyncKeyState(mai2_io_cfg.vk_2p_touch[i])) - { + for (int i = 0; i < 34; i++) { + if (GetAsyncKeyState(mai2_io_cfg.vk_2p_touch[i])) { int byteIndex = i / 5; int bitIndex = i % 5; state[byteIndex] |= (1 << bitIndex); @@ -261,38 +229,38 @@ static unsigned int __stdcall mai2_io_touch_2p_thread_proc(void *ctx) return 0; } -HRESULT mai2_io_led_init(void) -{ - return S_OK; -} +HRESULT mai2_io_led_init(void) { return S_OK; } -void mai2_io_led_set_fet_output(const uint8_t *rgb) -{ +void mai2_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { #if 0 - dprintf("mai2 LED: BodyLed brightness: %d%%\n", (rgb[0] * 100) / 255); - dprintf("mai2 LED: ExtLed brightness: %d%%\n", (rgb[1] * 100) / 255); - dprintf("mai2 LED: SideLed brightness: %d%%\n", (rgb[2] * 100) / 255); + uint8_t player = board + 1; + dprintf("MAI2 LED %dP: BodyLed brightness: %d%%\n", player, + (rgb[0] * 100) / 255); + dprintf("MAI2 LED %dP: ExtLed brightness: %d%%\n", player, + (rgb[1] * 100) / 255); + dprintf("MAI2 LED %dP: SideLed brightness: %d%%\n", player, + (rgb[2] * 100) / 255); #endif return; } -void mai2_io_led_dc_update(const uint8_t *rgb) -{ +void mai2_io_led_dc_update(uint8_t board, const uint8_t *rgb) { #if 0 + uint8_t player = board + 1; for (int i = 0; i < 10; i++) { - dprintf("mai2 LED: LED %d: %02X %02X %02X Speed: %02X\n", + dprintf("Mai2 LED %dP: LED %d: %02X %02X %02X Speed: %02X\n", player i, rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]); } #endif return; } -void mai2_io_led_gs_update(const uint8_t *rgb) -{ +void mai2_io_led_gs_update(uint8_t board, const uint8_t *rgb) { #if 0 + uint8_t player = board + 1; for (int i = 0; i < 8; i++) { - dprintf("mai2 LED: LED %d: %02X %02X %02X Speed: %02X\n", - i, rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]); + dprintf("Mai2 LED %dP: LED %d: %02X %02X %02X Speed: %02X\n", player, i, + rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]); } #endif return; diff --git a/mai2io/mai2io.h b/mai2io/mai2io.h index 039094b..9c0a7f0 100644 --- a/mai2io/mai2io.h +++ b/mai2io/mai2io.h @@ -156,6 +156,9 @@ HRESULT mai2_io_led_init(void); /* Update the FET outputs. rgb is a pointer to an array up to 3 bytes. + maimai DX uses two boards. Board 0 is for the player 1 side (left) and board 1 + is for the player 2 side (right). + Set the brightness of the white light on the machine's outer shell. The program will continuously send changed values to request the blinking effect. @@ -167,13 +170,16 @@ HRESULT mai2_io_led_init(void); Minimum API version: 0x0101 */ -void mai2_io_led_set_fet_output(const uint8_t *rgb); +void mai2_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); /* The effect of this command is unknown, it is triggered after LED_15070_CMD_EEPROM_READ. */ -void mai2_io_led_dc_update(const uint8_t *rgb); +void mai2_io_led_dc_update(uint8_t board, const uint8_t *rgb); -/* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. +/* Update the RGB LEDs. rgb is a pointer to an array up to 8 * 4 = 32 bytes. + + maimai DX uses two boards. Board 0 is for the player 1 side (left) and board 1 + is for the player 2 side (right). The LEDs are laid out as follows: [0-7]: 8 button LED @@ -183,4 +189,4 @@ void mai2_io_led_dc_update(const uint8_t *rgb); Minimum API version: 0x0101 */ -void mai2_io_led_gs_update(const uint8_t *rgb); +void mai2_io_led_gs_update(uint8_t board, const uint8_t *rgb); diff --git a/mu3hook/config.c b/mu3hook/config.c index 93957ea..6c52446 100644 --- a/mu3hook/config.c +++ b/mu3hook/config.c @@ -41,7 +41,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index e4336e9..4b35aa3 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -81,8 +81,9 @@ static DWORD CALLBACK mu3_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {3, 0}; hr = led15093_hook_init(&mu3_hook_cfg.led15093, - mu3_dll.led_init, mu3_dll.led_set_leds, 3, 1, 1, 2); + mu3_dll.led_init, mu3_dll.led_set_leds, led_port_no); if (FAILED(hr)) { return hr; diff --git a/swdchook/config.c b/swdchook/config.c index fcfa251..e64654e 100644 --- a/swdchook/config.c +++ b/swdchook/config.c @@ -23,7 +23,8 @@ void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename) wchar_t tmpstr[16]; cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15070", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15070", L"portNo2", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename); /* TODO: Unknown, no firmware file available */ cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0xdead, filename); diff --git a/swdchook/dllmain.c b/swdchook/dllmain.c index d83798c..5932a69 100644 --- a/swdchook/dllmain.c +++ b/swdchook/dllmain.c @@ -100,8 +100,9 @@ static DWORD CALLBACK swdc_pre_startup(void) } /* Not working, different board -04 instead of -02? */ + unsigned int led_port_no[2] = {2, 0}; hr = led15070_hook_init(&swdc_hook_cfg.led15070, swdc_dll.led_init, - swdc_dll.led_set_fet_output, NULL, swdc_dll.led_gs_update, 2, 1); + swdc_dll.led_set_fet_output, NULL, swdc_dll.led_gs_update, led_port_no); if (FAILED(hr)) { goto fail; diff --git a/swdchook/io4.c b/swdchook/io4.c index be1d4b9..679a646 100644 --- a/swdchook/io4.c +++ b/swdchook/io4.c @@ -203,7 +203,7 @@ static HRESULT swdc_io4_write_gpio(uint8_t* payload, size_t len) lights_data & SWDC_IO_LED_LEFT ? 0xFF : 0x00, }; - swdc_dll.led_set_leds(rgb_out); + swdc_dll.led_set_leds(0, rgb_out); return S_OK; } diff --git a/swdchook/swdc-dll.h b/swdchook/swdc-dll.h index 1b81e26..7539d1c 100644 --- a/swdchook/swdc-dll.h +++ b/swdchook/swdc-dll.h @@ -11,9 +11,9 @@ struct swdc_dll { void (*get_gamebtns)(uint16_t *gamebtn); void (*get_analogs)(struct swdc_io_analog_state *out); HRESULT (*led_init)(void); - void (*led_set_fet_output)(const uint8_t *rgb); - void (*led_gs_update)(const uint8_t *rgb); - void (*led_set_leds)(const uint8_t *rgb); + void (*led_set_fet_output)(uint8_t board, const uint8_t *rgb); + void (*led_gs_update)(uint8_t board, const uint8_t *rgb); + void (*led_set_leds)(uint8_t board, const uint8_t *rgb); HRESULT (*ffb_init)(void); void (*ffb_toggle)(bool active); void (*ffb_constant_force)(uint8_t direction, uint8_t force); diff --git a/swdcio/dllmain.c b/swdcio/dllmain.c index 8057e23..a35b8e8 100644 --- a/swdcio/dllmain.c +++ b/swdcio/dllmain.c @@ -119,7 +119,7 @@ HRESULT swdc_io_led_init(void) return S_OK; } -void swdc_io_led_set_fet_output(const uint8_t *rgb) +void swdc_io_led_set_fet_output(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("SWDC LED: LEFT SEAT LED: %02X\n", rgb[0]); @@ -129,7 +129,7 @@ void swdc_io_led_set_fet_output(const uint8_t *rgb) return; } -void swdc_io_led_gs_update(const uint8_t *rgb) +void swdc_io_led_gs_update(uint8_t board, const uint8_t *rgb) { #if 0 for (int i = 0; i < 9; i++) { @@ -141,7 +141,7 @@ void swdc_io_led_gs_update(const uint8_t *rgb) return; } -void swdc_io_led_set_leds(const uint8_t *rgb) +void swdc_io_led_set_leds(uint8_t board, const uint8_t *rgb) { #if 0 dprintf("SWDC LED: START: %02X\n", rgb[0]); diff --git a/swdcio/swdcio.h b/swdcio/swdcio.h index 6843634..9d069f3 100644 --- a/swdcio/swdcio.h +++ b/swdcio/swdcio.h @@ -123,7 +123,7 @@ HRESULT swdc_io_led_init(void); Minimum API version: 0x0101 */ -void swdc_io_led_set_fet_output(const uint8_t *rgb); +void swdc_io_led_set_fet_output(uint8_t board, const uint8_t *rgb); /* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes. @@ -140,7 +140,7 @@ void swdc_io_led_set_fet_output(const uint8_t *rgb); Minimum API version: 0x0101 */ -void swdc_io_led_gs_update(const uint8_t *rgb); +void swdc_io_led_gs_update(uint8_t board, const uint8_t *rgb); /* Update the cabinet button LEDs. rgb is a pointer to an array up to 6 bytes. @@ -156,7 +156,7 @@ void swdc_io_led_gs_update(const uint8_t *rgb); Minimum API version: 0x0101 */ -void swdc_io_led_set_leds(const uint8_t *rgb); +void swdc_io_led_set_leds(uint8_t board, const uint8_t *rgb); /* Initialize FFB emulation. This function will be called before any other swdc_io_ffb_*() function calls. diff --git a/tokyohook/config.c b/tokyohook/config.c index 304cbc2..3ab387a 100644 --- a/tokyohook/config.c +++ b/tokyohook/config.c @@ -40,7 +40,8 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename) memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number)); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); - cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); + cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename); + cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAED9, filename); diff --git a/tokyohook/dllmain.c b/tokyohook/dllmain.c index 19a1517..3ba9b36 100644 --- a/tokyohook/dllmain.c +++ b/tokyohook/dllmain.c @@ -66,8 +66,9 @@ static DWORD CALLBACK tokyo_pre_startup(void) goto fail; } + unsigned int led_port_no[2] = {1, 0}; hr = led15093_hook_init(&tokyo_hook_cfg.led15093, - tokyo_dll.led_init, tokyo_dll.led_set_leds, 1, 1, 1, 2); + tokyo_dll.led_init, tokyo_dll.led_set_leds, led_port_no); if (FAILED(hr)) { return hr; From 4d0ef542792f18b64f33dd1b182763a6cbed6afc Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 2 Mar 2025 00:23:53 +0100 Subject: [PATCH 5/9] system: add dip switch label configurations --- chusanhook/dllmain.c | 39 ++++++++-------------- cmhook/dllmain.c | 8 +++++ dist/fgo/segatools.ini | 2 +- hooklib/meson.build | 2 +- idachook/dllmain.c | 12 +++++++ mai2hook/dllmain.c | 8 +++++ mercuryhook/dllmain.c | 8 +++++ meson.build | 2 +- mu3hook/dllmain.c | 8 +++++ platform/system.c | 75 +++++++++++++++++++++--------------------- platform/system.h | 10 ++++++ tokyohook/dllmain.c | 10 ++++++ 12 files changed, 117 insertions(+), 67 deletions(-) diff --git a/chusanhook/dllmain.c b/chusanhook/dllmain.c index e29bf7f..6e3308f 100644 --- a/chusanhook/dllmain.c +++ b/chusanhook/dllmain.c @@ -86,11 +86,18 @@ static DWORD CALLBACK chusan_pre_startup(void) { /* Initialize emulation hooks */ - hr = platform_hook_init( - &chusan_hook_cfg.platform, - "SDHD", - "ACA2", - chusan_hook_mod); + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + {L"Monitor Type", L"60FPS", L"120FPS"}, + {L"Cabinet Type", L"CVT", L"SP"}, + }; + + // Set the system dip switch configuration + memcpy(chusan_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + + hr = platform_hook_init(&chusan_hook_cfg.platform, "SDHD", "ACA2", + chusan_hook_mod); if (FAILED(hr)) { goto fail; @@ -114,27 +121,7 @@ static DWORD CALLBACK chusan_pre_startup(void) { goto fail; } - bool *dipsw = &chusan_hook_cfg.platform.system.dipsw[0]; - bool is_cvt = dipsw[2]; - - for (int i = 0; i < 3; i++) { - switch (i) { - case 0: - dprintf("DipSw: NetInstall: %s\n", dipsw[0] ? "Server" : "Client"); - break; - - case 1: - dprintf("DipSw: Monitor Type: %dFPS\n", dipsw[1] ? 60 : 120); - break; - - case 2: - dprintf("DipSw: Cab Type: %s\n", is_cvt ? "CVT" : "SP"); - - break; - } - } - - unsigned int first_port = is_cvt ? 2 : 20; + bool is_cvt = chusan_hook_cfg.platform.system.dipsw[2]; if (!is_cvt) { hr = vfd_hook_init(&chusan_hook_cfg.vfd, 2); diff --git a/cmhook/dllmain.c b/cmhook/dllmain.c index 03ace58..29d93af 100644 --- a/cmhook/dllmain.c +++ b/cmhook/dllmain.c @@ -63,6 +63,14 @@ static DWORD CALLBACK cm_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Client", L"Server"}, + }; + + // Set the system dip switch configuration + memcpy(cm_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &cm_hook_cfg.platform, "SDED", diff --git a/dist/fgo/segatools.ini b/dist/fgo/segatools.ini index e9c7c20..4e846ee 100644 --- a/dist/fgo/segatools.ini +++ b/dist/fgo/segatools.ini @@ -41,7 +41,7 @@ portNo=17 ; 837-15093-06 LED board emulation setting. enable=1 ; COM port number for the LED board. Has to be the same as the FTDI port. -portNo=17 +portNo1=17 ; ----------------------------------------------------------------------------- ; Network settings diff --git a/hooklib/meson.build b/hooklib/meson.build index e6908d6..b0ad6c2 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -4,7 +4,7 @@ hooklib_lib = static_library( implicit_include_directories : false, dependencies : [ capnhook.get_variable('hook_dep'), - Ws2_32_lib + ws2_32_lib ], sources : [ 'cursor.c', diff --git a/idachook/dllmain.c b/idachook/dllmain.c index 71a4ccd..a7b3c86 100644 --- a/idachook/dllmain.c +++ b/idachook/dllmain.c @@ -60,6 +60,18 @@ static DWORD CALLBACK idac_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + {L"Cabinet Type", L"SWDC CVT", L"DZero CVT"}, + {L"Single Seat", L"ON", L"OFF"}, + {L"Seat Setting 1", L"ON", L"OFF"}, + {L"Seat Setting 2", L"ON", L"OFF"}, + }; + + // Set the system dip switch configuration + memcpy(idac_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &idac_hook_cfg.platform, "SDGT", diff --git a/mai2hook/dllmain.c b/mai2hook/dllmain.c index cb8a240..cecc01e 100644 --- a/mai2hook/dllmain.c +++ b/mai2hook/dllmain.c @@ -66,6 +66,14 @@ static DWORD CALLBACK mai2_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + }; + + // Set the system dip switch configuration + memcpy(mai2_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &mai2_hook_cfg.platform, "SDEZ", diff --git a/mercuryhook/dllmain.c b/mercuryhook/dllmain.c index 64b5707..37030d3 100644 --- a/mercuryhook/dllmain.c +++ b/mercuryhook/dllmain.c @@ -64,6 +64,14 @@ static DWORD CALLBACK mercury_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + }; + + // Set the system dip switch configuration + memcpy(mercury_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &mercury_hook_cfg.platform, "SDFE", diff --git a/meson.build b/meson.build index 6bb86fc..aada974 100644 --- a/meson.build +++ b/meson.build @@ -89,7 +89,7 @@ dxguid_lib = cc.find_library('dxguid') xinput_lib = cc.find_library('xinput') pathcch_lib = cc.find_library('pathcch') imagehlp_lib = cc.find_library('imagehlp') -Ws2_32_lib = cc.find_library('Ws2_32') +ws2_32_lib = cc.find_library('ws2_32') inc = include_directories('.') capnhook = subproject('capnhook') diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c index 4b35aa3..1b57e5d 100644 --- a/mu3hook/dllmain.c +++ b/mu3hook/dllmain.c @@ -65,6 +65,14 @@ static DWORD CALLBACK mu3_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + }; + + // Set the system dip switch configuration + memcpy(mu3_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &mu3_hook_cfg.platform, "SDDT", diff --git a/platform/system.c b/platform/system.c index dbc832f..4928e05 100644 --- a/platform/system.c +++ b/platform/system.c @@ -1,40 +1,37 @@ -#include +#include "platform/system.h" #include -#include +#include #include +#include #include +#include -#include "platform/system.h" #include "platform/vfs.h" - +#include "util/crc.h" #include "util/dprintf.h" #include "util/str.h" -#include "util/crc.h" #define DATA_SIZE 503 #define BLOCK_SIZE (sizeof(uint32_t) + 4 + 1 + DATA_SIZE) #pragma pack(push, 1) -typedef struct -{ +typedef struct { uint32_t checksum; char padding[6]; uint8_t freeplay; char data[DATA_SIZE - 2]; } CreditBlock; -typedef struct -{ +typedef struct { uint32_t checksum; char padding[4]; uint8_t dip_switches; char data[DATA_SIZE]; } DipSwBlock; -typedef struct -{ +typedef struct { CreditBlock credit_block; DipSwBlock dip_switch_block; char *data; @@ -50,16 +47,15 @@ static struct vfs_config vfs_config; static void system_read_sysfile(const wchar_t *sys_file); static void system_save_sysfile(const wchar_t *sys_file); -HRESULT system_init(const struct system_config *cfg, const struct vfs_config *vfs_cfg) -{ +HRESULT system_init(const struct system_config *cfg, + const struct vfs_config *vfs_cfg) { HRESULT hr; wchar_t sys_file_path[MAX_PATH]; assert(cfg != NULL); assert(vfs_cfg != NULL); - if (!cfg->enable) - { + if (!cfg->enable) { return S_FALSE; } @@ -78,13 +74,13 @@ HRESULT system_init(const struct system_config *cfg, const struct vfs_config *vf return S_OK; } -static void system_read_sysfile(const wchar_t *sys_file) -{ +static void system_read_sysfile(const wchar_t *sys_file) { FILE *f = _wfopen(sys_file, L"r"); - if (f == NULL) - { - dprintf("System: First run detected, system settings can only be applied AFTER the first run\n"); + if (f == NULL) { + dprintf( + "System: First run detected, system settings can only be applied " + "AFTER the first run\n"); return; } @@ -92,8 +88,7 @@ static void system_read_sysfile(const wchar_t *sys_file) long file_size = ftell(f); fseek(f, 0, SEEK_SET); - if (file_size != 0x6000) - { + if (file_size != 0x6000) { dprintf("System: Invalid sysfile.dat file size\n"); fclose(f); @@ -106,11 +101,11 @@ static void system_read_sysfile(const wchar_t *sys_file) // copy the credit_block and dip_switch_block from the sysfile.dat memcpy(&system_info.credit_block, system_info.data, BLOCK_SIZE); - memcpy(&system_info.dip_switch_block, system_info.data + 0x2800, BLOCK_SIZE); + memcpy(&system_info.dip_switch_block, system_info.data + 0x2800, + BLOCK_SIZE); } -static void system_save_sysfile(const wchar_t *sys_file) -{ +static void system_save_sysfile(const wchar_t *sys_file) { char block[BLOCK_SIZE]; uint8_t system = 0; uint8_t freeplay = 0; @@ -118,24 +113,28 @@ static void system_save_sysfile(const wchar_t *sys_file) // open the sysfile.dat for writing in bytes mode FILE *f = _wfopen(sys_file, L"rb+"); - if (f == NULL) - { + if (f == NULL) { return; } // write the system_config.system to the dip_switch_block - for (int i = 0; i < 8; i++) - { - if (system_config.dipsw[i]) - { - // print which system is enabled + for (int i = 0; i < 8; i++) { + // print the dip switch configuration with labels if present + if (system_config.dipsw_config[i].label[0] != L'\0') { + dprintf("System: %ls: %ls\n", system_config.dipsw_config[i].label, + system_config.dipsw[i] ? system_config.dipsw_config[i].on + : system_config.dipsw_config[i].off); + } else if (system_config.dipsw[i]) { dprintf("System: DipSw%d=1 set\n", i + 1); + } + + // set the system variable to the dip switch configuration + if (system_config.dipsw[i]) { system |= (1 << i); } } - if (system_config.freeplay) - { + if (system_config.freeplay) { // print that freeplay is enabled dprintf("System: Freeplay enabled\n"); freeplay = 1; @@ -149,10 +148,10 @@ static void system_save_sysfile(const wchar_t *sys_file) // calculate the new checksum, skip the old crc32 value // which is at the beginning of the block, thats's why the +4 // conver the struct to chars in order for the crc32 calculation to work - system_info.credit_block.checksum = crc32( - (char *)&system_info.credit_block + 4, BLOCK_SIZE - 4, 0); - system_info.dip_switch_block.checksum = crc32( - (char *)&system_info.dip_switch_block + 4, BLOCK_SIZE - 4, 0); + system_info.credit_block.checksum = + crc32((char *)&system_info.credit_block + 4, BLOCK_SIZE - 4, 0); + system_info.dip_switch_block.checksum = + crc32((char *)&system_info.dip_switch_block + 4, BLOCK_SIZE - 4, 0); // build the new credit block memcpy(block, (char *)&system_info.credit_block, BLOCK_SIZE); diff --git a/platform/system.h b/platform/system.h index ba0f2a6..e69ce90 100644 --- a/platform/system.h +++ b/platform/system.h @@ -7,10 +7,20 @@ #include "platform/vfs.h" + +struct dipsw_config +{ + wchar_t label[MAX_PATH]; + wchar_t on[MAX_PATH]; + wchar_t off[MAX_PATH]; +}; + + struct system_config { bool enable; bool freeplay; bool dipsw[8]; + struct dipsw_config dipsw_config[8]; }; HRESULT system_init(const struct system_config *cfg, const struct vfs_config *vfs_cfg); diff --git a/tokyohook/dllmain.c b/tokyohook/dllmain.c index 3ba9b36..5f46615 100644 --- a/tokyohook/dllmain.c +++ b/tokyohook/dllmain.c @@ -50,6 +50,16 @@ static DWORD CALLBACK tokyo_pre_startup(void) /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"Delivery Server", L"Server", L"Client"}, + {L"Cabinet ID Setting", L"ON", L"OFF"}, + {L"Cabinet ID Setting", L"ON", L"OFF"}, + }; + + // Set the system dip switch configuration + memcpy(tokyo_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &tokyo_hook_cfg.platform, "SDFV", From e850346b79a670e115b1cdd336393684453197ae Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 9 Feb 2025 00:13:33 +0100 Subject: [PATCH 6/9] renamed start.bat to launch.bat --- Package.mk | 30 +++++++++++++------------- dist/carol/{start.bat => launch.bat} | 4 ++-- dist/chuni/{start.bat => launch.bat} | 2 ++ dist/chusan/{start.bat => launch.bat} | 0 dist/cm/{start.bat => launch.bat} | 0 dist/cxb/{start.bat => launch.bat} | 0 dist/diva/{start.bat => launch.bat} | 0 dist/fgo/{start.bat => launch.bat} | 0 dist/idac/{start.bat => launch.bat} | 0 dist/idz/{start.bat => launch.bat} | 2 +- dist/kemono/{start.bat => launch.bat} | 0 dist/mai2/{start.bat => launch.bat} | 0 dist/mercury/{start.bat => launch.bat} | 4 +--- dist/mercury/segatools.ini | 2 +- dist/mu3/{start.bat => launch.bat} | 0 dist/swdc/{start.bat => launch.bat} | 0 dist/tokyo/{start.bat => launch.bat} | 0 doc/chunihook.md | 2 +- doc/config/common.md | 2 +- doc/idzhook.md | 2 +- 20 files changed, 25 insertions(+), 25 deletions(-) rename dist/carol/{start.bat => launch.bat} (80%) rename dist/chuni/{start.bat => launch.bat} (96%) rename dist/chusan/{start.bat => launch.bat} (100%) rename dist/cm/{start.bat => launch.bat} (100%) rename dist/cxb/{start.bat => launch.bat} (100%) rename dist/diva/{start.bat => launch.bat} (100%) rename dist/fgo/{start.bat => launch.bat} (100%) rename dist/idac/{start.bat => launch.bat} (100%) rename dist/idz/{start.bat => launch.bat} (87%) rename dist/kemono/{start.bat => launch.bat} (100%) rename dist/mai2/{start.bat => launch.bat} (100%) rename dist/mercury/{start.bat => launch.bat} (55%) rename dist/mu3/{start.bat => launch.bat} (100%) rename dist/swdc/{start.bat => launch.bat} (100%) rename dist/tokyo/{start.bat => launch.bat} (100%) diff --git a/Package.mk b/Package.mk index 9d907b1..5647e9b 100644 --- a/Package.mk +++ b/Package.mk @@ -5,7 +5,7 @@ $(BUILD_DIR_ZIP)/chuni.zip: $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_32)/chunihook/chunihook.dll \ $(DIST_DIR)/chuni/segatools.ini \ - $(DIST_DIR)/chuni/start.bat \ + $(DIST_DIR)/chuni/launch.bat \ $(BUILD_DIR_ZIP)/chuni $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -20,7 +20,7 @@ $(BUILD_DIR_ZIP)/cxb.zip: $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_32)/cxbhook/cxbhook.dll \ $(DIST_DIR)/cxb/segatools.ini \ - $(DIST_DIR)/cxb/start.bat \ + $(DIST_DIR)/cxb/launch.bat \ $(BUILD_DIR_ZIP)/cxb $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -35,7 +35,7 @@ $(BUILD_DIR_ZIP)/diva.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/divahook/divahook.dll \ $(DIST_DIR)/diva/segatools.ini \ - $(DIST_DIR)/diva/start.bat \ + $(DIST_DIR)/diva/launch.bat \ $(BUILD_DIR_ZIP)/diva $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -50,7 +50,7 @@ $(BUILD_DIR_ZIP)/carol.zip: $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_32)/carolhook/carolhook.dll \ $(DIST_DIR)/carol/segatools.ini \ - $(DIST_DIR)/carol/start.bat \ + $(DIST_DIR)/carol/launch.bat \ $(BUILD_DIR_ZIP)/carol $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -65,7 +65,7 @@ $(BUILD_DIR_ZIP)/idz.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/idzhook/idzhook.dll \ $(DIST_DIR)/idz/segatools.ini \ - $(DIST_DIR)/idz/start.bat \ + $(DIST_DIR)/idz/launch.bat \ $(BUILD_DIR_ZIP)/idz $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -80,7 +80,7 @@ $(BUILD_DIR_ZIP)/fgo.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/fgohook/fgohook.dll \ $(DIST_DIR)/fgo/segatools.ini \ - $(DIST_DIR)/fgo/start.bat \ + $(DIST_DIR)/fgo/launch.bat \ $(BUILD_DIR_ZIP)/fgo $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -96,7 +96,7 @@ $(BUILD_DIR_ZIP)/idac.zip: $(BUILD_DIR_64)/idachook/idachook.dll \ $(DIST_DIR)/idac/segatools.ini \ $(DIST_DIR)/idac/config_hook.json \ - $(DIST_DIR)/idac/start.bat \ + $(DIST_DIR)/idac/launch.bat \ $(BUILD_DIR_ZIP)/idac $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -112,7 +112,7 @@ $(BUILD_DIR_ZIP)/swdc.zip: $(BUILD_DIR_64)/swdchook/swdchook.dll \ $(DIST_DIR)/swdc/segatools.ini \ $(DIST_DIR)/swdc/config_hook.json \ - $(DIST_DIR)/swdc/start.bat \ + $(DIST_DIR)/swdc/launch.bat \ $(BUILD_DIR_ZIP)/swdc $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -127,7 +127,7 @@ $(BUILD_DIR_ZIP)/mercury.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/mercuryhook/mercuryhook.dll \ $(DIST_DIR)/mercury/segatools.ini \ - $(DIST_DIR)/mercury/start.bat \ + $(DIST_DIR)/mercury/launch.bat \ $(BUILD_DIR_ZIP)/mercury $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -141,7 +141,7 @@ $(BUILD_DIR_ZIP)/chusan.zip: $(V)mkdir -p $(BUILD_DIR_ZIP)/chusan/DEVICE $(V)cp $(DIST_DIR)/chusan/segatools.ini \ $(DIST_DIR)/chusan/config_hook.json \ - $(DIST_DIR)/chusan/start.bat \ + $(DIST_DIR)/chusan/launch.bat \ $(BUILD_DIR_ZIP)/chusan $(V)cp $(BUILD_DIR_32)/chusanhook/chusanhook.dll \ $(BUILD_DIR_ZIP)/chusan/chusanhook_x86.dll @@ -164,7 +164,7 @@ $(BUILD_DIR_ZIP)/mu3.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/mu3hook/mu3hook.dll \ $(DIST_DIR)/mu3/segatools.ini \ - $(DIST_DIR)/mu3/start.bat \ + $(DIST_DIR)/mu3/launch.bat \ $(BUILD_DIR_ZIP)/mu3 $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -179,7 +179,7 @@ $(BUILD_DIR_ZIP)/mai2.zip: $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(BUILD_DIR_64)/mai2hook/mai2hook.dll \ $(DIST_DIR)/mai2/segatools.ini \ - $(DIST_DIR)/mai2/start.bat \ + $(DIST_DIR)/mai2/launch.bat \ $(BUILD_DIR_ZIP)/mai2 $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -195,7 +195,7 @@ $(BUILD_DIR_ZIP)/cm.zip: $(BUILD_DIR_64)/cmhook/cmhook.dll \ $(DIST_DIR)/cm/config_hook.json \ $(DIST_DIR)/cm/segatools.ini \ - $(DIST_DIR)/cm/start.bat \ + $(DIST_DIR)/cm/launch.bat \ $(BUILD_DIR_ZIP)/cm $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -211,7 +211,7 @@ $(BUILD_DIR_ZIP)/tokyo.zip: $(BUILD_DIR_64)/tokyohook/tokyohook.dll \ $(DIST_DIR)/tokyo/config_hook.json \ $(DIST_DIR)/tokyo/segatools.ini \ - $(DIST_DIR)/tokyo/start.bat \ + $(DIST_DIR)/tokyo/launch.bat \ $(BUILD_DIR_ZIP)/tokyo $(V)cp pki/billing.pub \ pki/ca.crt \ @@ -224,7 +224,7 @@ $(BUILD_DIR_ZIP)/kemono.zip: $(V)mkdir -p $(BUILD_DIR_ZIP)/kemono $(V)mkdir -p $(BUILD_DIR_ZIP)/kemono/DEVICE $(V)cp $(DIST_DIR)/kemono/segatools.ini \ - $(DIST_DIR)/kemono/start.bat \ + $(DIST_DIR)/kemono/launch.bat \ $(BUILD_DIR_ZIP)/kemono $(V)cp $(BUILD_DIR_32)/kemonohook/kemonohook.dll \ $(BUILD_DIR_ZIP)/kemono/kemonohook_x86.dll diff --git a/dist/carol/start.bat b/dist/carol/launch.bat similarity index 80% rename from dist/carol/start.bat rename to dist/carol/launch.bat index 0fab950..4e75aa0 100644 --- a/dist/carol/start.bat +++ b/dist/carol/launch.bat @@ -2,10 +2,10 @@ pushd %~dp0 -taskkill /f /im aimeReaderHost.exe > nul 2>&1 - start /min inject -d -k carolhook.dll aimeReaderHost.exe -p 10 + inject -d -k carolhook.dll carol_nu.exe + taskkill /f /im aimeReaderHost.exe > nul 2>&1 echo. diff --git a/dist/chuni/start.bat b/dist/chuni/launch.bat similarity index 96% rename from dist/chuni/start.bat rename to dist/chuni/launch.bat index 0c942e9..a1c54ef 100644 --- a/dist/chuni/start.bat +++ b/dist/chuni/launch.bat @@ -3,7 +3,9 @@ pushd %~dp0 start /min inject -d -k chunihook.dll aimeReaderHost.exe -p 12 + inject -d -k chunihook.dll chuniApp.exe + taskkill /f /im aimeReaderHost.exe > nul 2>&1 echo. diff --git a/dist/chusan/start.bat b/dist/chusan/launch.bat similarity index 100% rename from dist/chusan/start.bat rename to dist/chusan/launch.bat diff --git a/dist/cm/start.bat b/dist/cm/launch.bat similarity index 100% rename from dist/cm/start.bat rename to dist/cm/launch.bat diff --git a/dist/cxb/start.bat b/dist/cxb/launch.bat similarity index 100% rename from dist/cxb/start.bat rename to dist/cxb/launch.bat diff --git a/dist/diva/start.bat b/dist/diva/launch.bat similarity index 100% rename from dist/diva/start.bat rename to dist/diva/launch.bat diff --git a/dist/fgo/start.bat b/dist/fgo/launch.bat similarity index 100% rename from dist/fgo/start.bat rename to dist/fgo/launch.bat diff --git a/dist/idac/start.bat b/dist/idac/launch.bat similarity index 100% rename from dist/idac/start.bat rename to dist/idac/launch.bat diff --git a/dist/idz/start.bat b/dist/idz/launch.bat similarity index 87% rename from dist/idz/start.bat rename to dist/idz/launch.bat index d64aa9b..4f6ea5e 100644 --- a/dist/idz/start.bat +++ b/dist/idz/launch.bat @@ -2,7 +2,7 @@ pushd %~dp0 -start /min "AM Daemon" inject -d -k idzhook.dll amdaemon.exe -c configDHCP_Final_Common.json configDHCP_Final_JP.json configDHCP_Final_JP_ST1.json configDHCP_Final_JP_ST2.json configDHCP_Final_EX.json configDHCP_Final_EX_ST1.json configDHCP_Final_EX_ST2.json +start "AM Daemon" /min inject -d -k idzhook.dll amdaemon.exe -c configDHCP_Final_Common.json configDHCP_Final_JP.json configDHCP_Final_JP_ST1.json configDHCP_Final_JP_ST2.json configDHCP_Final_EX.json configDHCP_Final_EX_ST1.json configDHCP_Final_EX_ST2.json rem Set dipsw1=0 and uncomment the ServerBox for in store battle? rem inject -k idzhook.dll ServerBoxD8_Nu_x64.exe diff --git a/dist/kemono/start.bat b/dist/kemono/launch.bat similarity index 100% rename from dist/kemono/start.bat rename to dist/kemono/launch.bat diff --git a/dist/mai2/start.bat b/dist/mai2/launch.bat similarity index 100% rename from dist/mai2/start.bat rename to dist/mai2/launch.bat diff --git a/dist/mercury/start.bat b/dist/mercury/launch.bat similarity index 55% rename from dist/mercury/start.bat rename to dist/mercury/launch.bat index a9a3f22..4a64365 100644 --- a/dist/mercury/start.bat +++ b/dist/mercury/launch.bat @@ -1,10 +1,8 @@ @echo off pushd %~dp0 -taskkill /f /im amdaemon.exe > nul 2>&1 - REM USA -start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_usa.json +REM start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_usa.json REM JP start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_jpn.json diff --git a/dist/mercury/segatools.ini b/dist/mercury/segatools.ini index 4e24489..5e10634 100644 --- a/dist/mercury/segatools.ini +++ b/dist/mercury/segatools.ini @@ -5,7 +5,7 @@ [vfs] ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) amfs= -; Insert the path to the game Option directory here (contains Axxx directories) +; Insert the path to the game Option directory here (unused in Mercury) option= ; Create an empty directory somewhere and insert the path here. ; This directory may be shared between multiple SEGA games. diff --git a/dist/mu3/start.bat b/dist/mu3/launch.bat similarity index 100% rename from dist/mu3/start.bat rename to dist/mu3/launch.bat diff --git a/dist/swdc/start.bat b/dist/swdc/launch.bat similarity index 100% rename from dist/swdc/start.bat rename to dist/swdc/launch.bat diff --git a/dist/tokyo/start.bat b/dist/tokyo/launch.bat similarity index 100% rename from dist/tokyo/start.bat rename to dist/tokyo/launch.bat diff --git a/doc/chunihook.md b/doc/chunihook.md index 57e19b0..7b68a20 100644 --- a/doc/chunihook.md +++ b/doc/chunihook.md @@ -44,7 +44,7 @@ option=../../option 1. In the `[dns]` section, set `default=` to your computer's hostname or LAN IP. Do not put `127.0.0.1` here, the game specifically checks for and rejects loopback addresses. This setting controls the address of the network services server -1. Right click `start.bat` in `app/bin` and run it as Administrator. I think you need to run it as +1. Right click `launch.bat` in `app/bin` and run it as Administrator. I think you need to run it as admin at least once, but once you have done that you can run the game as a regular user 1. A sequence of several start-up screens will be displayed. You should also see a bunch of debug output in a command line window; if you're seeing hex dumps here then that's a good sign. There diff --git a/doc/config/common.md b/doc/config/common.md index a25e353..89c48c6 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -11,7 +11,7 @@ The default file path for config file is `./segatools.ini`. You can modify environment variable `SEGATOOLS_CONFIG_PATH` to another path. -For example, You can have another `start.bat` with following code in it, +For example, You can have another `launch.bat` with following code in it, Then you can copy `segatools.ini` to `another_config.ini` but with different dns host in it ```bat set SEGATOOLS_CONFIG_PATH=.\another_config.ini diff --git a/doc/idzhook.md b/doc/idzhook.md index e23c18c..1686458 100644 --- a/doc/idzhook.md +++ b/doc/idzhook.md @@ -65,7 +65,7 @@ felicaGen=0 and fill it with 20 digits, for example `01234567891234567890`. Make sure to save the file. -1. Right click `start.bat` in `package` and run it as Administrator. After the +1. Right click `launch.bat` in `package` and run it as Administrator. After the first run you may be able to run the game as a normal user. 1. Once you're at the title screen, press 2 or 3 a few times to add some credits, then _hold_ the Enter key for a few seconds to scan a card and start From 27116a7a4105a54e1b40be50906536c27a997979 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 2 Mar 2025 00:36:13 +0100 Subject: [PATCH 7/9] idac, tokyo: improve dipsw cabinet id config --- chusanhook/dllmain.c | 14 +++++++++++--- idachook/dllmain.c | 10 +++++++++- tokyohook/dllmain.c | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/chusanhook/dllmain.c b/chusanhook/dllmain.c index 6e3308f..6ba4cd4 100644 --- a/chusanhook/dllmain.c +++ b/chusanhook/dllmain.c @@ -26,19 +26,24 @@ #include #include -#include "amex/amex.h" #include "board/sg-reader.h" #include "board/vfd.h" + #include "chuniio/chuniio.h" #include "chusanhook/config.h" #include "chusanhook/io4.h" #include "chusanhook/slider.h" + #include "gfxhook/d3d9.h" #include "gfxhook/gfx.h" + #include "hook/process.h" + #include "hooklib/serial.h" #include "hooklib/spike.h" + #include "platform/platform.h" + #include "util/dprintf.h" #include "util/env.h" @@ -96,8 +101,11 @@ static DWORD CALLBACK chusan_pre_startup(void) { memcpy(chusan_hook_cfg.platform.system.dipsw_config, new_dipsw_config, sizeof(new_dipsw_config)); - hr = platform_hook_init(&chusan_hook_cfg.platform, "SDHD", "ACA2", - chusan_hook_mod); + hr = platform_hook_init( + &chusan_hook_cfg.platform, + "SDHD", + "ACA2", + chusan_hook_mod); if (FAILED(hr)) { goto fail; diff --git a/idachook/dllmain.c b/idachook/dllmain.c index a7b3c86..448ea5b 100644 --- a/idachook/dllmain.c +++ b/idachook/dllmain.c @@ -82,13 +82,21 @@ static DWORD CALLBACK idac_pre_startup(void) goto fail; } + bool *dipsw = &idac_hook_cfg.platform.system.dipsw[0]; + bool is_swdc_cvt = dipsw[1]; + + if (!dipsw[2]) { + // the next two bit are the seat number most significant bit first + dprintf("System: Seat Number: %d\n", ((dipsw[4] << 1) | dipsw[3]) + 1); + } + hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod); if (FAILED(hr)) { goto fail; } - hr = sg_reader_hook_init(&idac_hook_cfg.aime, 3, 3, idac_hook_mod); + hr = sg_reader_hook_init(&idac_hook_cfg.aime, 3, is_swdc_cvt ? 3 : 2, idac_hook_mod); if (FAILED(hr)) { goto fail; diff --git a/tokyohook/dllmain.c b/tokyohook/dllmain.c index 5f46615..9c3a262 100644 --- a/tokyohook/dllmain.c +++ b/tokyohook/dllmain.c @@ -70,6 +70,26 @@ static DWORD CALLBACK tokyo_pre_startup(void) goto fail; } + bool *dipsw = &tokyo_hook_cfg.platform.system.dipsw[0]; + unsigned int cabinet_id = 0; + + if (dipsw[0] == 1 && dipsw[1] == 0 && dipsw[2] == 0) { + cabinet_id = 1; // Server 1 + } else if (dipsw[0] == 0 && dipsw[1] == 1 && dipsw[2] == 0) { + cabinet_id = 2; // Client 2 + } else if (dipsw[0] == 0 && dipsw[1] == 0 && dipsw[2] == 1) { + cabinet_id = 3; // Client 3 + } else if (dipsw[0] == 0 && dipsw[1] == 1 && dipsw[2] == 1) { + cabinet_id = 4; // Client 4 + } else { + dprintf("Error: Invalid dip switch configuration!\n"); + } + + // Print the correct Cabinet ID if valid + if (cabinet_id > 0) { + dprintf("System: Cabinet ID %d\n", cabinet_id); + } + hr = tokyo_dll_init(&tokyo_hook_cfg.dll, tokyo_hook_mod); if (FAILED(hr)) { From 3371f3f437bb668b759cd9a0cd48d0f7413ccb35 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sun, 2 Mar 2025 01:45:23 -0500 Subject: [PATCH 8/9] fix msvc build by removing ntstatus include from platform/system.c --- platform/system.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/system.c b/platform/system.c index 4928e05..5879032 100644 --- a/platform/system.c +++ b/platform/system.c @@ -1,11 +1,10 @@ #include "platform/system.h" +#include #include -#include #include #include #include -#include #include "platform/vfs.h" #include "util/crc.h" From 369fe286871e741cc69f01e15bd5686b2559f02e Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sun, 2 Mar 2025 04:10:35 -0500 Subject: [PATCH 9/9] disable excess logging for carol touchscreen hook --- carolhook/touch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/carolhook/touch.c b/carolhook/touch.c index 70c2e92..cf94355 100644 --- a/carolhook/touch.c +++ b/carolhook/touch.c @@ -196,7 +196,7 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const flg = resp.touches[0].x1 != last_x1 || resp.touches[0].x2 != last_x2 || resp.touches[0].y1 != last_y1 || resp.touches[0].y2 != last_y2; -#if 1 +#if 0 if (flg) dprintf("Touch: Mouse down! x %02X %02X y: %02X %02X\n", resp.touches[0].x1, resp.touches[0].x2, resp.touches[0].y1, resp.touches[0].y2); #endif