diff --git a/common/amex/config.c b/common/amex/config.c index e138447..3604c08 100644 --- a/common/amex/config.c +++ b/common/amex/config.c @@ -73,6 +73,7 @@ void jvs_config_load(struct jvs_config *cfg, const wchar_t *filename) assert(filename != NULL); cfg->enable = GetPrivateProfileIntW(L"jvs", L"enable", 1, filename); + cfg->foreground = GetPrivateProfileIntW(L"jvs", L"foreground", 0, filename); } void sram_config_load(struct sram_config *cfg, const wchar_t *filename) diff --git a/common/amex/jvs.h b/common/amex/jvs.h index 0bedb0f..ab3ea36 100644 --- a/common/amex/jvs.h +++ b/common/amex/jvs.h @@ -15,6 +15,7 @@ DEFINE_GUID( struct jvs_config { bool enable; + bool foreground; }; typedef HRESULT (*jvs_provider_t)(struct jvs_node **root); diff --git a/common/board/config.c b/common/board/config.c index 96c4146..be98ebe 100644 --- a/common/board/config.c +++ b/common/board/config.c @@ -92,6 +92,7 @@ void io4_config_load(struct io4_config *cfg, const wchar_t *filename) assert(filename != NULL); cfg->enable = GetPrivateProfileIntW(L"io4", L"enable", 1, filename); + cfg->foreground_only = GetPrivateProfileIntW(L"io4", L"foreground", 0, filename); } void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename) diff --git a/common/board/io3.c b/common/board/io3.c index d61cfdc..2a7ca83 100644 --- a/common/board/io3.c +++ b/common/board/io3.c @@ -26,6 +26,7 @@ #include "util/dprintf.h" #include "util/dump.h" +#include "util/fg-detect.h" static void io3_transact( struct jvs_node *node, @@ -146,6 +147,8 @@ static uint8_t io3_features[] = { 0x00, }; +static struct io3_switch_state prev_state = {0}; + void io3_init( struct io3 *io3, struct jvs_node *next, @@ -423,7 +426,13 @@ static HRESULT io3_cmd_read_switches( memset(&state, 0, sizeof(state)); if (io3->ops != NULL) { - io3->ops->read_switches(io3->ops_ctx, &state); + fgdet_poll(); + if (fgdet_in_foreground()) { // returns true if fgdet is not enabled + io3->ops->read_switches(io3->ops_ctx, &state); + memcpy(&prev_state, &state, sizeof(state)); + } else { + state = prev_state; + } } hr = iobuf_write_8(resp_buf, state.system); /* Test, Tilt lines */ diff --git a/common/board/io4.c b/common/board/io4.c index e1def19..8001457 100644 --- a/common/board/io4.c +++ b/common/board/io4.c @@ -20,6 +20,7 @@ #include "util/async.h" #include "util/dprintf.h" +#include "util/fg-detect.h" #pragma pack(push, 1) @@ -99,12 +100,14 @@ static struct async io4_async; static uint8_t io4_system_status; static const struct io4_ops *io4_ops; static void *io4_ops_ctx; +static struct io4_state prev_state; HRESULT io4_hook_init( - const struct io4_config *cfg, - const struct io4_ops *ops, - void *ctx) -{ + const struct io4_config *cfg, + const struct io4_ops *ops, + void *ctx, + const wchar_t* window_name, + const bool window_name_is_partial_match) { HRESULT hr; assert(cfg != NULL); @@ -122,9 +125,14 @@ HRESULT io4_hook_init( return hr; } + if (window_name != NULL && cfg->foreground_only) { + fgdet_init(window_name, window_name_is_partial_match); + } + io4_ops = ops; io4_ops_ctx = ctx; io4_system_status = 0x02; /* idk */ + memset(&prev_state, 0, sizeof(prev_state)); iohook_push_handler(io4_handle_irp); hr = setupapi_add_phantom_dev(&hid_guid, io4_path); @@ -325,11 +333,18 @@ static HRESULT io4_async_poll(void *ctx, struct irp *irp) /* Call into ops to poll the underlying inputs */ - memset(&state, 0, sizeof(state)); - hr = io4_ops->poll(io4_ops_ctx, &state); + fgdet_poll(); + if (fgdet_in_foreground()) { // returns true if fgdet is not enabled + memset(&state, 0, sizeof(state)); + hr = io4_ops->poll(io4_ops_ctx, &state); - if (FAILED(hr)) { - return hr; + if (FAILED(hr)) { + return hr; + } + + memcpy(&prev_state, &state, sizeof(state)); + } else { + state = prev_state; // if we're unfocused, freeze the current input } /* Construct IN report. Values are all little-endian, unlike JVS. */ diff --git a/common/board/io4.h b/common/board/io4.h index 09a921b..1f93cf1 100644 --- a/common/board/io4.h +++ b/common/board/io4.h @@ -10,12 +10,13 @@ enum { /* System buttons in button[0] */ - IO4_BUTTON_TEST = 1 << 9, - IO4_BUTTON_SERVICE = 1 << 6, + IO4_BUTTON_TEST = 1 << 9, + IO4_BUTTON_SERVICE = 1 << 6, }; struct io4_config { bool enable; + bool foreground_only; }; struct io4_state { @@ -26,11 +27,14 @@ struct io4_state { }; struct io4_ops { - HRESULT (*poll)(void *ctx, struct io4_state *state); + HRESULT (*poll)(void* ctx, struct io4_state* state); + HRESULT (*write_gpio)(uint8_t* payload, size_t len); }; HRESULT io4_hook_init( - const struct io4_config *cfg, - const struct io4_ops *ops, - void *ctx); + const struct io4_config* cfg, + const struct io4_ops* ops, + void* ctx, + const wchar_t* window_name, + const bool window_name_is_partial_match); \ No newline at end of file diff --git a/common/util/fg-detect.c b/common/util/fg-detect.c new file mode 100644 index 0000000..e5ed83c --- /dev/null +++ b/common/util/fg-detect.c @@ -0,0 +1,66 @@ +#include +#include + +#include "util/dprintf.h" +#include "util/fg-detect.h" + +#include + +static HWND window_handle; +static const wchar_t* window_title = NULL; +static bool foreground_state = true; +static bool partial_match; +static wchar_t scanned_title[256]; + +static HWND get_window(){ + if (window_handle != NULL){ + return window_handle; + } + + // try detecting the window + HWND hwnd = GetForegroundWindow(); + if (GetWindowTextW(hwnd, scanned_title, sizeof(scanned_title)) == 0) { + return NULL; + } + if (partial_match) { + if (wcsstr(scanned_title, window_title) == NULL) { + return NULL; + } + } else { + if (wcscmp(scanned_title, window_title) != 0) { + return NULL; + } + } + dprintf("FG-Detect: Program window detected\n"); + window_handle = hwnd; + return window_handle; +} + +void fgdet_init(const wchar_t* wnd_title, const bool wnd_partial_match) { + assert(wnd_title != NULL); + + window_handle = NULL; + window_title = wnd_title; + partial_match = wnd_partial_match; + dprintf("FG-Detect: Searching for \"%ls\"\n", window_title); +} + +bool fgdet_in_foreground(){ + return foreground_state; +} + +void fgdet_poll(){ + if (window_title == NULL){ + return; + } else if (GetForegroundWindow() == get_window()){ + if (!foreground_state){ + dprintf("FG-Detect: Got focus\n"); + foreground_state = true; + } + } else { + if (foreground_state){ + dprintf("FG-Detect: Lost focus\n"); + foreground_state = false; + } + } +} diff --git a/common/util/fg-detect.h b/common/util/fg-detect.h new file mode 100644 index 0000000..3961fac --- /dev/null +++ b/common/util/fg-detect.h @@ -0,0 +1,8 @@ +#pragma once +#include + +void fgdet_init(const wchar_t* wnd_title, const bool wnd_partial_match); + +bool fgdet_in_foreground(); + +void fgdet_poll(); \ No newline at end of file diff --git a/common/util/meson.build b/common/util/meson.build index 58782d3..a0150a7 100644 --- a/common/util/meson.build +++ b/common/util/meson.build @@ -17,6 +17,8 @@ util_lib = static_library( 'dprintf.h', 'dump.c', 'dump.h', + 'fg-detect.c', + 'fg-detect.h', 'get_function_ordinal.c', 'get_function_ordinal.h', 'lib.c', diff --git a/doc/config/common.md b/doc/config/common.md index d2eb385..1be9b7c 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -409,6 +409,12 @@ Default `1` Enable JVS port emulation. Disable to use the JVS port on a real AMEX. +### `foreground` + +Default `0` + +Only enables input when the game's main window is focused. This does not work for all games. + ## `[io4]` Configure emulation of the IO4 board. Same settings also apply to `[io3]`. @@ -419,6 +425,13 @@ Default `1` Enable IO4 port emulation. Disable to use the IO4 port on a real ALLS. + +### `foreground` + +Default `0` + +Only enables input when the game's main window is focused. This does not work for all games, notably APMv3, due to the game switching involved. + ### `test` Default `0x31` diff --git a/games/apm3hook/io4.c b/games/apm3hook/io4.c index 4d04f97..596aa80 100644 --- a/games/apm3hook/io4.c +++ b/games/apm3hook/io4.c @@ -23,7 +23,7 @@ HRESULT apm3_io4_hook_init(const struct io4_config *cfg) assert(apm3_dll.init != NULL); - hr = io4_hook_init(cfg, &apm3_io4_ops, NULL); + hr = io4_hook_init(cfg, &apm3_io4_ops, NULL, NULL, false); // can't use fgdet here because the main window closes if (FAILED(hr)) { return hr; diff --git a/games/chunihook/dllmain.c b/games/chunihook/dllmain.c index a3fa8ab..16e663f 100644 --- a/games/chunihook/dllmain.c +++ b/games/chunihook/dllmain.c @@ -37,6 +37,7 @@ #include "util/dprintf.h" #include "util/env.h" +#include "util/fg-detect.h" static HMODULE chuni_hook_mod; static process_entry_t chuni_startup; @@ -129,6 +130,10 @@ static DWORD CALLBACK chuni_pre_startup(void) goto fail; } + if (chuni_hook_cfg.amex.jvs.enable && chuni_hook_cfg.amex.jvs.foreground) { + fgdet_init(L"teaGfx DirectX Release", false); + } + /* Initialize debug helpers */ spike_hook_init(get_config_path()); diff --git a/games/chusanhook/io4.c b/games/chusanhook/io4.c index c7f8265..48234a3 100644 --- a/games/chusanhook/io4.c +++ b/games/chusanhook/io4.c @@ -16,32 +16,32 @@ struct chunithm_jvs_ir_mask { // Incorrect IR beam mappings retained for backward compatibility static const struct chunithm_jvs_ir_mask chunithm_jvs_ir_masks_v1[] = { - { 0, 1 << 13 }, - { 1 << 13, 0 }, - { 0, 1 << 12 }, - { 1 << 12, 0 }, - { 0, 1 << 11 }, - { 1 << 11, 0 }, + {0, 1 << 13}, + {1 << 13, 0}, + {0, 1 << 12}, + {1 << 12, 0}, + {0, 1 << 11}, + {1 << 11, 0}, }; static const struct chunithm_jvs_ir_mask chunithm_jvs_ir_masks[] = { - { 1 << 13, 0 }, - { 0, 1 << 13 }, - { 1 << 12, 0 }, - { 0, 1 << 12 }, - { 1 << 11, 0 }, - { 0, 1 << 11 }, + {1 << 13, 0}, + {0, 1 << 13}, + {1 << 12, 0}, + {0, 1 << 12}, + {1 << 11, 0}, + {0, 1 << 11}, }; static HRESULT chusan_io4_poll(void* ctx, struct io4_state* state); + static uint16_t coins; static const struct io4_ops chusan_io4_ops = { .poll = chusan_io4_poll, }; -HRESULT chusan_io4_hook_init(const struct io4_config* cfg) -{ +HRESULT chusan_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(chuni_dll.jvs_init != NULL); @@ -50,19 +50,18 @@ HRESULT chusan_io4_hook_init(const struct io4_config* cfg) hr = chuni_dll.jvs_init(); if (FAILED(hr)) { - dprintf("USB I/O: Backend error, I/O disconnected: %x\n", (int)hr); + dprintf("USB I/O: Backend error, I/O disconnected: %x\n", (int) hr); return hr; } - io4_hook_init(cfg, &chusan_io4_ops, NULL); + io4_hook_init(cfg, &chusan_io4_ops, NULL, L"teaGfx DirectX Release", false); return S_OK; } -static HRESULT chusan_io4_poll(void* ctx, struct io4_state* state) -{ - const struct chunithm_jvs_ir_mask *masks; +static HRESULT chusan_io4_poll(void* ctx, struct io4_state* state) { + const struct chunithm_jvs_ir_mask* masks; uint8_t opbtn; uint8_t beams; size_t i; @@ -103,4 +102,4 @@ static HRESULT chusan_io4_poll(void* ctx, struct io4_state* state) } return S_OK; -} +} \ No newline at end of file diff --git a/games/cmhook/io4.c b/games/cmhook/io4.c index 073f681..c497b37 100644 --- a/games/cmhook/io4.c +++ b/games/cmhook/io4.c @@ -10,20 +10,20 @@ #include "util/dprintf.h" -static HRESULT cm_io4_poll(void *ctx, struct io4_state *state); +static HRESULT cm_io4_poll(void* ctx, struct io4_state* state); + static uint16_t coins; static const struct io4_ops cm_io4_ops = { .poll = cm_io4_poll, }; -HRESULT cm_io4_hook_init(const struct io4_config *cfg) -{ +HRESULT cm_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(cm_dll.init != NULL); - hr = io4_hook_init(cfg, &cm_io4_ops, NULL); + hr = io4_hook_init(cfg, &cm_io4_ops, NULL, L"MU3CardViewer", false); if (FAILED(hr)) { return hr; @@ -32,8 +32,7 @@ HRESULT cm_io4_hook_init(const struct io4_config *cfg) return cm_dll.init(); } -static HRESULT cm_io4_poll(void *ctx, struct io4_state *state) -{ +static HRESULT cm_io4_poll(void* ctx, struct io4_state* state) { uint8_t opbtn; HRESULT hr; @@ -66,4 +65,4 @@ static HRESULT cm_io4_poll(void *ctx, struct io4_state *state) state->chutes[0] = coins << 8; return S_OK; -} +} \ No newline at end of file diff --git a/games/cxbhook/config.c b/games/cxbhook/config.c index 98d326d..8a2d6fb 100644 --- a/games/cxbhook/config.c +++ b/games/cxbhook/config.c @@ -42,6 +42,7 @@ void revio_config_load(struct revio_config *cfg, const wchar_t *filename) assert(filename != NULL); cfg->enable = GetPrivateProfileIntW(L"revio", L"enable", 1, filename); + cfg->foreground = GetPrivateProfileIntW(L"revio", L"foreground", 0, filename); } void led_config_load(struct led_config *cfg, const wchar_t *filename) diff --git a/games/cxbhook/dllmain.c b/games/cxbhook/dllmain.c index d644b5e..fd6f4e0 100644 --- a/games/cxbhook/dllmain.c +++ b/games/cxbhook/dllmain.c @@ -24,6 +24,7 @@ #include "util/dprintf.h" #include "util/env.h" +#include "util/fg-detect.h" static HMODULE cxb_hook_mod; static process_entry_t cxb_startup; @@ -103,6 +104,10 @@ static DWORD CALLBACK cxb_pre_startup(void) goto fail; } + if (cxb_hook_cfg.revio.enable && cxb_hook_cfg.revio.foreground) { + fgdet_init(L"MT Framework", false); + } + hr = led_hook_init(&cxb_hook_cfg.led); if (FAILED(hr)) { diff --git a/games/cxbhook/revio.c b/games/cxbhook/revio.c index 84ab016..b06a007 100644 --- a/games/cxbhook/revio.c +++ b/games/cxbhook/revio.c @@ -14,6 +14,7 @@ #include "hook/table.h" #include "util/dprintf.h" +#include "util/fg-detect.h" static int my_cCommIo_Open(char *port); static int my_cCommIo_Close(); @@ -31,6 +32,7 @@ static int my_cCommIo_SetAmpMute(int amp_id, int a2); int amp_volume[] = {20, 20, 20}; int last_triggers = 0; int last_is_mouse_down = false; +int prev_out = 0; static struct hook_symbol revio_syms[] = { { @@ -139,26 +141,32 @@ static int my_cCommIo_GetTrigger() uint16_t btns = 0; int out = 0; - cxb_dll.revio_poll(&btns); + fgdet_poll(); + if (fgdet_in_foreground()) { + cxb_dll.revio_poll(&btns); - if (btns & 0x01) { - out |= 1 << 4; // test - } + if (btns & 0x01) { + out |= 1 << 4; // test + } - if (btns & 0x02) { - out |= 1 << 5; // service? - } + if (btns & 0x02) { + out |= 1 << 5; // service? + } - if (btns & 0x04) { - out |= 1 << 1; // up - } + if (btns & 0x04) { + out |= 1 << 1; // up + } - if (btns & 0x08) { - out |= 1 << 3; // down - } + if (btns & 0x08) { + out |= 1 << 3; // down + } - if (btns & 0x0F) { - out |= 1 << 2; // cancel + if (btns & 0x0F) { + out |= 1 << 2; // cancel + } + prev_out = out; + } else { + out = prev_out; } out &= ~last_triggers; diff --git a/games/cxbhook/revio.h b/games/cxbhook/revio.h index 8150c97..c787607 100644 --- a/games/cxbhook/revio.h +++ b/games/cxbhook/revio.h @@ -6,6 +6,7 @@ struct revio_config { bool enable; + bool foreground; uint8_t test; uint8_t service; uint8_t coin; diff --git a/games/divahook/dllmain.c b/games/divahook/dllmain.c index eb6e16f..52789b1 100644 --- a/games/divahook/dllmain.c +++ b/games/divahook/dllmain.c @@ -34,6 +34,7 @@ #include "util/dprintf.h" #include "util/env.h" +#include "util/fg-detect.h" static HMODULE diva_hook_mod; static process_entry_t diva_startup; @@ -104,6 +105,10 @@ static DWORD CALLBACK diva_pre_startup(void) goto fail; } + if (diva_hook_cfg.amex.jvs.enable && diva_hook_cfg.amex.jvs.foreground) { + fgdet_init(L"Hatsune Miku Project DIVA Arcade Future Tone", false); + } + /* Initialize debug helpers */ spike_hook_init(get_config_path()); diff --git a/games/fgohook/io4.c b/games/fgohook/io4.c index 67dfba4..5194fa3 100644 --- a/games/fgohook/io4.c +++ b/games/fgohook/io4.c @@ -10,20 +10,20 @@ #include "util/dprintf.h" -static HRESULT fgo_io4_poll(void *ctx, struct io4_state *state); +static HRESULT fgo_io4_poll(void* ctx, struct io4_state* state); + static uint16_t coins; static const struct io4_ops fgo_io4_ops = { .poll = fgo_io4_poll, }; -HRESULT fgo_io4_hook_init(const struct io4_config *cfg) -{ +HRESULT fgo_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(fgo_dll.init != NULL); - hr = io4_hook_init(cfg, &fgo_io4_ops, NULL); + hr = io4_hook_init(cfg, &fgo_io4_ops, NULL, L"Fate/Grand Order Arcade r", true); if (FAILED(hr)) { return hr; @@ -32,8 +32,7 @@ HRESULT fgo_io4_hook_init(const struct io4_config *cfg) return fgo_dll.init(); } -static HRESULT fgo_io4_poll(void *ctx, struct io4_state *state) -{ +static HRESULT fgo_io4_poll(void* ctx, struct io4_state* state) { uint8_t opbtn; uint8_t gamebtn; int16_t stick_x; @@ -101,4 +100,4 @@ static HRESULT fgo_io4_poll(void *ctx, struct io4_state *state) state->adcs[4] = 0x8000 + stick_y; return S_OK; -} +} \ No newline at end of file diff --git a/games/idachook/io4.c b/games/idachook/io4.c index 3861ef8..fa4f82b 100644 --- a/games/idachook/io4.c +++ b/games/idachook/io4.c @@ -10,12 +10,14 @@ #include "util/dprintf.h" -static HRESULT idac_io4_poll(void *ctx, struct io4_state *state); +static HRESULT idac_io4_poll(void* ctx, struct io4_state* state); + static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len); + static uint16_t coins; static const struct io4_ops idac_io4_ops = { - .poll = idac_io4_poll, + .poll = idac_io4_poll, .write_gpio = idac_io4_write_gpio }; @@ -36,13 +38,12 @@ static const uint16_t idac_gear_signals[] = { 0x0014, }; -HRESULT idac_io4_hook_init(const struct io4_config *cfg) -{ +HRESULT idac_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(idac_dll.init != NULL); - hr = io4_hook_init(cfg, &idac_io4_ops, NULL); + hr = io4_hook_init(cfg, &idac_io4_ops, NULL, L"GameProject", false); if (FAILED(hr)) { return hr; @@ -51,8 +52,7 @@ HRESULT idac_io4_hook_init(const struct io4_config *cfg) return idac_dll.init(); } -static HRESULT idac_io4_poll(void *ctx, struct io4_state *state) -{ +static HRESULT idac_io4_poll(void* ctx, struct io4_state* state) { uint8_t opbtn; uint8_t gamebtn; uint8_t gear; @@ -131,21 +131,20 @@ static HRESULT idac_io4_poll(void *ctx, struct io4_state *state) return S_OK; } -static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len) -{ +static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len) { assert(idac_dll.led_set_leds != NULL); - + // Just fast fail if there aren't enough bytes in the payload - if (len < 3) + if (len < 3) return S_OK; - + // This command is used for lights in IDAC, but it only contains button lights, // and only in the first 3 bytes of the payload; everything else is padding to // make the payload 62 bytes. The rest of the cabinet lights and the side button // lights are handled separately, by the 15070 lights controller. - uint32_t lights_data = (uint32_t) ((uint8_t)(payload[0]) << 24 | - (uint8_t)(payload[1]) << 16 | - (uint8_t)(payload[2]) << 8); + uint32_t lights_data = (uint32_t)((uint8_t)(payload[0]) << 24 | + (uint8_t)(payload[1]) << 16 | + (uint8_t)(payload[2]) << 8); // Since Sega uses an odd ordering for the first part of the bitfield, // let's normalize the data and just send over bytes for the receiver @@ -162,4 +161,4 @@ static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len) idac_dll.led_set_leds(0, rgb_out); return S_OK; -} +} \ No newline at end of file diff --git a/games/idzhook/dllmain.c b/games/idzhook/dllmain.c index 534f4d0..b73a6a4 100644 --- a/games/idzhook/dllmain.c +++ b/games/idzhook/dllmain.c @@ -41,6 +41,7 @@ #include "util/dprintf.h" #include "util/lib.h" #include "util/env.h" +#include "util/fg-detect.h" static HMODULE idz_hook_mod; static process_entry_t idz_startup; @@ -136,6 +137,10 @@ static DWORD CALLBACK idz_pre_startup(void) goto fail; } + if (idz_hook_cfg.amex.jvs.enable && idz_hook_cfg.amex.jvs.foreground) { + fgdet_init(L"Direct3D Window", false); + } + /* Initialize debug helpers */ spike_hook_init(get_config_path()); diff --git a/games/kemonohook/dllmain.c b/games/kemonohook/dllmain.c index 3373489..f429299 100644 --- a/games/kemonohook/dllmain.c +++ b/games/kemonohook/dllmain.c @@ -18,6 +18,7 @@ #include "unityhook/hook.h" #include "util/dprintf.h" #include "util/env.h" +#include "util/fg-detect.h" static HMODULE kemono_hook_mod; static process_entry_t kemono_startup; @@ -103,6 +104,10 @@ static DWORD CALLBACK kemono_pre_startup(void) { goto fail; } + if (kemono_hook_cfg.amex.jvs.enable && kemono_hook_cfg.amex.jvs.foreground) { + fgdet_init(L"Parade", false); + } + kemono_extra_hooks_init(); /* Initialize Unity native plugin DLL hooks diff --git a/games/mai2hook/io4.c b/games/mai2hook/io4.c index 4eb7f6b..cb0b38d 100644 --- a/games/mai2hook/io4.c +++ b/games/mai2hook/io4.c @@ -10,20 +10,20 @@ #include "util/dprintf.h" -static HRESULT mai2_io4_poll(void *ctx, struct io4_state *state); +static HRESULT mai2_io4_poll(void* ctx, struct io4_state* state); + static uint16_t coins; static const struct io4_ops mai2_io4_ops = { .poll = mai2_io4_poll, }; -HRESULT mai2_io4_hook_init(const struct io4_config *cfg) -{ +HRESULT mai2_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(mai2_dll.init != NULL); - hr = io4_hook_init(cfg, &mai2_io4_ops, NULL); + hr = io4_hook_init(cfg, &mai2_io4_ops, NULL, L"Sinmai", false); if (FAILED(hr)) { return hr; @@ -32,8 +32,7 @@ HRESULT mai2_io4_hook_init(const struct io4_config *cfg) return mai2_dll.init(); } -static HRESULT mai2_io4_poll(void *ctx, struct io4_state *state) -{ +static HRESULT mai2_io4_poll(void* ctx, struct io4_state* state) { uint8_t opbtn; uint16_t player1; uint16_t player2; @@ -150,4 +149,4 @@ static HRESULT mai2_io4_poll(void *ctx, struct io4_state *state) } return S_OK; -} +} \ No newline at end of file diff --git a/games/mercuryhook/io4.c b/games/mercuryhook/io4.c index df22656..c34eb6f 100644 --- a/games/mercuryhook/io4.c +++ b/games/mercuryhook/io4.c @@ -14,19 +14,18 @@ bool mercury_io_coin = false; uint16_t mercury_io_coins = 0; -static HRESULT mercury_io4_poll(void *ctx, struct io4_state *state); +static HRESULT mercury_io4_poll(void* ctx, struct io4_state* state); static const struct io4_ops mercury_io4_ops = { .poll = mercury_io4_poll, }; -HRESULT mercury_io4_hook_init(const struct io4_config *cfg) -{ +HRESULT mercury_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(mercury_dll.init != NULL); - hr = io4_hook_init(cfg, &mercury_io4_ops, NULL); + hr = io4_hook_init(cfg, &mercury_io4_ops, NULL, L"Mercury", false); if (FAILED(hr)) { return hr; @@ -35,8 +34,7 @@ HRESULT mercury_io4_hook_init(const struct io4_config *cfg) return mercury_dll.init(); } -static HRESULT mercury_io4_poll(void *ctx, struct io4_state *state) -{ +static HRESULT mercury_io4_poll(void* ctx, struct io4_state* state) { uint8_t opbtn; uint8_t gamebtn; HRESULT hr; @@ -72,8 +70,7 @@ static HRESULT mercury_io4_poll(void *ctx, struct io4_state *state) mercury_io_coin = true; mercury_io_coins++; } - } - else { + } else { mercury_io_coin = false; } @@ -88,4 +85,4 @@ static HRESULT mercury_io4_poll(void *ctx, struct io4_state *state) } return S_OK; -} +} \ No newline at end of file diff --git a/games/mu3hook/io4.c b/games/mu3hook/io4.c index dfa7ad8..430d17a 100644 --- a/games/mu3hook/io4.c +++ b/games/mu3hook/io4.c @@ -10,7 +10,8 @@ #include "util/dprintf.h" -static HRESULT mu3_io4_poll(void *ctx, struct io4_state *state); +static HRESULT mu3_io4_poll(void* ctx, struct io4_state* state); + static HRESULT mu3_io4_write_gpio(uint8_t* payload, size_t len); static uint16_t coins; @@ -20,13 +21,12 @@ static const struct io4_ops mu3_io4_ops = { .write_gpio = mu3_io4_write_gpio, }; -HRESULT mu3_io4_hook_init(const struct io4_config *cfg) -{ +HRESULT mu3_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(mu3_dll.init != NULL); - hr = io4_hook_init(cfg, &mu3_io4_ops, NULL); + hr = io4_hook_init(cfg, &mu3_io4_ops, NULL, L"Otoge", false); if (FAILED(hr)) { return hr; @@ -35,8 +35,7 @@ HRESULT mu3_io4_hook_init(const struct io4_config *cfg) return mu3_dll.init(); } -static HRESULT mu3_io4_poll(void *ctx, struct io4_state *state) -{ +static HRESULT mu3_io4_poll(void* ctx, struct io4_state* state) { uint8_t opbtn; uint8_t left; uint8_t right; @@ -111,11 +110,11 @@ static HRESULT mu3_io4_poll(void *ctx, struct io4_state *state) } if (!(left & MU3_IO_GAMEBTN_SIDE)) { - state->buttons[1] |= 1 << 15; /* L-Side, active-low */ + state->buttons[1] |= 1 << 15; /* L-Side, active-low */ } if (!(right & MU3_IO_GAMEBTN_SIDE)) { - state->buttons[0] |= 1 << 14; /* R-Side, active-low */ + state->buttons[0] |= 1 << 14; /* R-Side, active-low */ } /* Lever increases right-to-left, not left-to-right. @@ -128,19 +127,18 @@ static HRESULT mu3_io4_poll(void *ctx, struct io4_state *state) return S_OK; } -static HRESULT mu3_io4_write_gpio(uint8_t* payload, size_t len) -{ +static HRESULT mu3_io4_write_gpio(uint8_t* payload, size_t len) { // Just fast fail if there aren't enough bytes in the payload - if (len < 3) + if (len < 3) return S_OK; // This command is used for lights in Ongeki, but it only contains button lights, // and only in the first 3 bytes of the payload; everything else is padding to // make the payload 62 bytes. The rest of the cabinet lights and the side button // lights are handled separately, by the 15093 lights controller. - uint32_t lights_data = (uint32_t) ((uint8_t)(payload[0]) << 24 | - (uint8_t)(payload[1]) << 16 | - (uint8_t)(payload[2]) << 8); + uint32_t lights_data = (uint32_t)((uint8_t)(payload[0]) << 24 | + (uint8_t)(payload[1]) << 16 | + (uint8_t)(payload[2]) << 8); // Since Sega uses an odd ordering for the first part of the bitfield, // let's normalize the data and just send over bytes for the receiver @@ -169,4 +167,4 @@ static HRESULT mu3_io4_write_gpio(uint8_t* payload, size_t len) mu3_dll.led_set_leds(1, rgb_out); return S_OK; -} +} \ No newline at end of file diff --git a/games/swdchook/io4.c b/games/swdchook/io4.c index 679a646..1d3ffcf 100644 --- a/games/swdchook/io4.c +++ b/games/swdchook/io4.c @@ -11,24 +11,28 @@ #include "swdchook/swdc-dll.h" static HANDLE mmf; + static HRESULT init_mmf(void); + static void swdc_set_gamebtns(uint16_t value); -static HRESULT swdc_io4_poll(void *ctx, struct io4_state *state); +static HRESULT swdc_io4_poll(void* ctx, struct io4_state* state); + static HRESULT swdc_io4_write_gpio(uint8_t* payload, size_t len); + static uint16_t coins; static const struct io4_ops swdc_io4_ops = { - .poll = swdc_io4_poll, + .poll = swdc_io4_poll, .write_gpio = swdc_io4_write_gpio }; -HRESULT swdc_io4_hook_init(const struct io4_config *cfg) { +HRESULT swdc_io4_hook_init(const struct io4_config* cfg) { HRESULT hr; assert(swdc_dll.init != NULL); - hr = io4_hook_init(cfg, &swdc_io4_ops, NULL); + hr = io4_hook_init(cfg, &swdc_io4_ops, NULL, L"Todoroki", false); if (FAILED(hr)) { return hr; @@ -61,7 +65,7 @@ void swdc_set_gamebtns(uint16_t value) { // Update the memory-mapped file LPVOID mmf_view = MapViewOfFile(mmf, FILE_MAP_ALL_ACCESS, 0, 0, 2); if (mmf_view != NULL) { - uint16_t* ptr = (uint16_t*)mmf_view; + uint16_t* ptr = (uint16_t *) mmf_view; *ptr = value; UnmapViewOfFile(mmf_view); @@ -70,7 +74,7 @@ void swdc_set_gamebtns(uint16_t value) { // ReleaseMutex(mutex); } -static HRESULT swdc_io4_poll(void *ctx, struct io4_state *state) { +static HRESULT swdc_io4_poll(void* ctx, struct io4_state* state) { uint8_t opbtn; uint16_t gamebtn; struct swdc_io_analog_state analog_state; @@ -128,7 +132,7 @@ static HRESULT swdc_io4_poll(void *ctx, struct io4_state *state) { state->buttons[0] |= 1 << 2; } -/* + /* Update steering wheel buttons Those are connected to the SEGA 838-15415 INDICATOR BD MAIN @@ -175,21 +179,20 @@ static HRESULT swdc_io4_poll(void *ctx, struct io4_state *state) { return S_OK; } -static HRESULT swdc_io4_write_gpio(uint8_t* payload, size_t len) -{ +static HRESULT swdc_io4_write_gpio(uint8_t* payload, size_t len) { assert(swdc_dll.led_set_leds != NULL); // Just fast fail if there aren't enough bytes in the payload - if (len < 3) + if (len < 3) return S_OK; - + // This command is used for lights in SWDC, but it only contains button lights, // and only in the first 3 bytes of the payload; everything else is padding to // make the payload 62 bytes. The rest of the cabinet lights and the side button // lights are handled separately, by the 15070 lights controller. - uint32_t lights_data = (uint32_t) ((uint8_t)(payload[0]) << 24 | - (uint8_t)(payload[1]) << 16 | - (uint8_t)(payload[2]) << 8); + uint32_t lights_data = (uint32_t)((uint8_t)(payload[0]) << 24 | + (uint8_t)(payload[1]) << 16 | + (uint8_t)(payload[2]) << 8); // Since Sega uses an odd ordering for the first part of the bitfield, // let's normalize the data and just send over bytes for the receiver @@ -206,4 +209,4 @@ static HRESULT swdc_io4_write_gpio(uint8_t* payload, size_t len) swdc_dll.led_set_leds(0, rgb_out); return S_OK; -} +} \ No newline at end of file diff --git a/games/tokyohook/io4.c b/games/tokyohook/io4.c index b2924c7..e1995eb 100644 --- a/games/tokyohook/io4.c +++ b/games/tokyohook/io4.c @@ -26,7 +26,7 @@ HRESULT tokyo_io4_hook_init(const struct io4_config *cfg) assert(tokyo_dll.init != NULL); - hr = io4_hook_init(cfg, &tokyo_io4_ops, NULL); + hr = io4_hook_init(cfg, &tokyo_io4_ops, NULL, L"STAR", false); if (FAILED(hr)) { return hr;