From 4dcf01f6433fed99e6d6f82e8f1b673fcf021986 Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Mon, 27 Nov 2023 23:23:00 -0500 Subject: [PATCH] carol: somewhat-working touch board?? --- carolhook/dllmain.c | 5 ++++ carolhook/touch.c | 69 +++++++++++++++++++++++++----------------- carolhook/touch.h | 19 ++++++++---- carolio/carolio.c | 52 ++++++++++++++++++++++++++++---- carolio/carolio.h | 2 +- hooklib/cursor.c | 73 +++++++++++++++++++++++++++++++++++++++++++++ hooklib/cursor.h | 3 ++ hooklib/meson.build | 2 ++ 8 files changed, 186 insertions(+), 39 deletions(-) create mode 100644 hooklib/cursor.c create mode 100644 hooklib/cursor.h diff --git a/carolhook/dllmain.c b/carolhook/dllmain.c index eca445b..6ff4c9f 100644 --- a/carolhook/dllmain.c +++ b/carolhook/dllmain.c @@ -20,6 +20,7 @@ #include "hooklib/serial.h" #include "hooklib/spike.h" #include "hooklib/createprocess.h" +#include "hooklib/cursor.h" #include "platform/platform.h" @@ -44,6 +45,8 @@ static DWORD CALLBACK carol_pre_startup(void) HMODULE dbghelp; dprintf("--- Begin carol_pre_startup ---\n"); + if ( !SetProcessDPIAware() ) + dprintf("Failed to set process DPI awareness level!\n"); /* Pin the D3D shader compiler. This makes startup much faster. */ @@ -65,6 +68,8 @@ static DWORD CALLBACK carol_pre_startup(void) dprintf("Failed to load debug helper library!\n"); } + cursor_hook_init(); + /* Config load */ carol_hook_config_load(&carol_hook_cfg, L".\\segatools.ini"); diff --git a/carolhook/touch.c b/carolhook/touch.c index 46527b8..ba61e42 100644 --- a/carolhook/touch.c +++ b/carolhook/touch.c @@ -8,13 +8,15 @@ #include "carolhook/carol-dll.h" #include "carolhook/touch.h" +#include "hook/table.h" + #include "hooklib/uart.h" #include "util/dprintf.h" #include "util/dump.h" /** - * CMDS for M3 EX series + * CMDS for touch thing * CX -> Calibrate Extend, preform callibration * MS -> Mode Stream, enters stream mode * R -> Reset, resets the device @@ -32,7 +34,8 @@ static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf); static HRESULT handle_touch_ack_cmd(const struct touch_req *req); static HRESULT handle_touch_name_cmd(const struct touch_req *req); static HRESULT handle_touch_id_cmd(const struct touch_req *req); -static void touch_scan_auto(const bool is_pressed, const uint32_t mouse_x, const uint32_t mouse_y); +static HRESULT handle_touch_unit_type_cmd(const struct touch_req *req); +static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const uint16_t mouse_y); static CRITICAL_SECTION touch_lock; static struct uart touch_uart; @@ -40,8 +43,10 @@ static uint8_t touch_written_bytes[528]; static uint8_t touch_readable_bytes[528]; static bool should_stream = false; static bool last_pressed; -static uint16_t last_x; -static uint16_t last_y; +static uint8_t last_x1; +static uint8_t last_x2; +static uint8_t last_y1; +static uint8_t last_y2; HRESULT touch_hook_init(const struct touch_config *cfg) @@ -91,6 +96,7 @@ static HRESULT touch_handle_irp_locked(struct irp *irp) if (irp->op == IRP_OP_OPEN) { dprintf("Touchscreen: Starting backend DLL\n"); hr = carol_dll.touch_init(); + carol_dll.touch_start(touch_scan_auto); if (FAILED(hr)) { dprintf("Touchscreen: Backend DLL error: %X\n", (int) hr); @@ -123,7 +129,9 @@ static HRESULT touch_handle_irp_locked(struct irp *irp) } else if (!strcmp("OI", (char *)req.cmd)) { hr = handle_touch_id_cmd(&req); - //carol_dll.touch_start(touch_scan_auto); + } + else if (!strcmp("UT", (char *)req.cmd)) { + hr = handle_touch_unit_type_cmd(&req); } else if (!strcmp("NM", (char *)req.cmd)) { hr = handle_touch_name_cmd(&req); @@ -150,16 +158,22 @@ static HRESULT handle_touch_ack_cmd(const struct touch_req *req) static HRESULT handle_touch_name_cmd(const struct touch_req *req) { dprintf("Touch: Get Name\n"); - return iobuf_write(&touch_uart.readable, "\001EX1234 EX1234\015", 15); + return iobuf_write(&touch_uart.readable, "\001AD1000\015", 15); } static HRESULT handle_touch_id_cmd(const struct touch_req *req) { dprintf("Touch: Get ID\n"); - return iobuf_write(&touch_uart.readable, "\001EX1234\015", 8); + return iobuf_write(&touch_uart.readable, "\001AD1000\015", 8); } -static void touch_scan_auto(const bool is_pressed, const uint32_t mouse_x, const uint32_t mouse_y) +static HRESULT handle_touch_unit_type_cmd(const struct touch_req *req) +{ + dprintf("Touch: Get Unit Type\n"); + return iobuf_write(&touch_uart.readable, "\001AD****00\015", 8); +} + +static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const uint16_t mouse_y) { struct touch_auto_resp resp; uint16_t tmp_x; @@ -167,34 +181,37 @@ static void touch_scan_auto(const bool is_pressed, const uint32_t mouse_x, const bool flg = false; memset(&resp, 0, sizeof(resp)); - resp.rep_id = 0x17; - resp.touches[0].status = 0x04; - resp.count = 1; + resp.touches[0].status |= 1 << 7; if (is_pressed) { - resp.touches[0].status = 0x07; + resp.touches[0].status |= (1 << 7) | (1 << 6); resp.touches[0].touch_id = 1; tmp_x = mouse_x & 0x7FFF; tmp_y = mouse_y & 0x7FFF; - // flip - resp.touches[0].x = (tmp_x << 8) | (tmp_x >> 8); - resp.touches[0].y = (tmp_y << 8) | (tmp_y >> 8); + resp.touches[0].x1 = tmp_x & 0x7F; + resp.touches[0].x2 = (tmp_x >> 7) & 0x7F; + resp.touches[0].y1 = tmp_y & 0x7F; + resp.touches[0].y2 = (tmp_y >> 7) & 0x7F; - flg = resp.touches[0].x != last_x || resp.touches[0].y != last_y; + 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 (flg) - dprintf("Touch: Mouse down! x %04X y: %04X\n", resp.touches[0].x, resp.touches[0].y); + 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 - last_x = resp.touches[0].x; - last_y = resp.touches[0].y; + last_x1 = resp.touches[0].x1; + last_x2 = resp.touches[0].x2; + last_y1 = resp.touches[0].y1; + last_y2 = resp.touches[0].y2; } else if (last_pressed) { - resp.touches[0].x = last_x; - resp.touches[0].y = last_y; + resp.touches[0].x1 = last_x1; + resp.touches[0].x2 = last_x2; + resp.touches[0].y1 = last_y1; + resp.touches[0].y2 = last_y2; } last_pressed = is_pressed; @@ -203,11 +220,9 @@ static void touch_scan_auto(const bool is_pressed, const uint32_t mouse_x, const iobuf_write(&touch_uart.readable, &resp, sizeof(resp)); LeaveCriticalSection(&touch_lock); -#if 1 - //if (flg) { - dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos); - dump_iobuf(&touch_uart.readable); - //} +#if 0 + dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos); + dump_iobuf(&touch_uart.readable); #endif } @@ -235,4 +250,4 @@ static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf) } return S_OK; -} \ No newline at end of file +} diff --git a/carolhook/touch.h b/carolhook/touch.h index a815cd1..bc621d6 100644 --- a/carolhook/touch.h +++ b/carolhook/touch.h @@ -8,6 +8,9 @@ struct touch_config { bool enable; + unsigned int port_no; + char board_id[7]; + char unit_type[9]; }; // Always starts with 0x01, always ends with 0x0D @@ -20,17 +23,21 @@ struct touch_req { struct touch_report { uint8_t status; + uint8_t x1; + uint8_t x2; + uint8_t y1; + uint8_t y2; uint8_t touch_id; - uint16_t x; - uint16_t y; }; struct touch_auto_resp { - uint8_t rep_id; struct touch_report touches[10]; - uint8_t count; - uint16_t scan_time; - //uint8_t padding[456]; +}; + +enum { + TOUCH_MODE_STREAM = 0x01, + TOUCH_MODE_DOWN_UP = 0x02, + TOUCH_MODE_INACTIVE = 0x03, }; #pragma pack(pop) diff --git a/carolio/carolio.c b/carolio/carolio.c index 3f4339b..5368da6 100644 --- a/carolio/carolio.c +++ b/carolio/carolio.c @@ -7,6 +7,7 @@ #include "carolio/carolio.h" #include "carolio/config.h" +#include "util/dprintf.h" static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx); @@ -15,6 +16,7 @@ static uint16_t carol_io_coins; static struct carol_io_config carol_io_cfg; static bool carol_io_touch_stop_flag; static HANDLE carol_io_touch_thread; +static bool carol_io_window_focus = false; uint16_t carol_io_get_api_version(void) { @@ -110,22 +112,62 @@ void carol_io_touch_stop() carol_io_touch_stop_flag = true; } +void check_fg_wind(void) +{ + HWND hwnd = GetForegroundWindow(); + wchar_t window_class[MAX_PATH]; + + /* Unlike every other game, we can't use GetWindowText here. Why? + + From MSDN: + + "If the window does not have a caption, the return value is a null + string. This behavior is by design. It allows applications to call + GetWindowText without becoming unresponsive if the process that owns + the target window is not responding. However, if the target window + is not responding and it belongs to the calling application, + GetWindowText will cause the calling application to become + unresponsive." + + Great, thanks Microsoft, very cool. Luckily Carol sets its class + name to the window title too so we can use that. */ + + GetClassNameW(hwnd, window_class, MAX_PATH); + + if (wcscmp(window_class, L"WONDER Master")) { + if (carol_io_window_focus) { + dprintf("Carol IO: Window focus lost\n"); + carol_io_window_focus = false; + } + } else if (!carol_io_window_focus) { + dprintf("Carol IO: Window focus regained\n"); + carol_io_window_focus = true; + } +} + static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx) { carol_io_touch_callback_t callback; bool mouse_is_down = false; - uint32_t mX = 0; - uint32_t mY = 0; + uint16_t mX = 0; + uint16_t mY = 0; POINT lpPoint; + HWND hwnd; callback = ctx; while (!carol_io_touch_stop_flag) { + check_fg_wind(); if (GetAsyncKeyState(VK_LBUTTON) & 0x8000) { mouse_is_down = true; - if (GetCursorPos(&lpPoint)) { - mX = lpPoint.x; - mY = lpPoint.y; + if (GetCursorPos(&lpPoint)) { + hwnd = GetForegroundWindow(); + if (ScreenToClient(hwnd, &lpPoint)) { + if (lpPoint.x < 0) lpPoint.x = 0; + if (lpPoint.y < 0) lpPoint.y = 0; + mX = (uint16_t)lpPoint.x; + mY = (uint16_t)lpPoint.y; + } } } else { mouse_is_down = false; diff --git a/carolio/carolio.h b/carolio/carolio.h index 6c85e3d..8b2b308 100644 --- a/carolio/carolio.h +++ b/carolio/carolio.h @@ -5,7 +5,7 @@ #include #include -typedef void (*carol_io_touch_callback_t)(const bool is_pressed, const uint32_t mouse_x, const uint32_t mouse_y); +typedef void (*carol_io_touch_callback_t)(const bool is_pressed, const uint16_t mouse_x, const uint16_t mouse_y); /* Get the version of the Project carol IO API that this DLL supports. This function should return a positive 16-bit integer, where the high byte is diff --git a/hooklib/cursor.c b/hooklib/cursor.c new file mode 100644 index 0000000..8c66412 --- /dev/null +++ b/hooklib/cursor.c @@ -0,0 +1,73 @@ +#include + +#include +#include +#include +#include + +#include "hook/table.h" +#include "util/dprintf.h" + +static HCURSOR my_SetCursor(HCURSOR hCursor); +static HCURSOR (*next_SetCursor)(HCURSOR hCursor); +static BOOL my_SetCursorPos(int x, int y); +static BOOL my_SetPhysicalCursorPos(int x, int y); +static int my_ShowCursor(BOOL bShow); + +static const struct hook_symbol cursor_syms[] = { + { + .name = "SetCursor", + .patch = my_SetCursor, + .link = (void **) &next_SetCursor + },/*{ + .name = "SetCursorPos", + .patch = my_SetCursorPos, + },*/ { + .name = "SetPhysicalCursorPos", + .patch = my_SetPhysicalCursorPos + }, /*{ + .name = "ShowCursor", + .patch = my_ShowCursor + }*/ +}; + +void cursor_hook_init() +{ + hook_table_apply( + NULL, + "user32.dll", + cursor_syms, + _countof(cursor_syms)); + + dprintf("Cursor: Init\n"); +} + +static BOOL my_SetCursorPos(int x, int y) +{ + dprintf("my_SetCursorPos Hit! x %d y %d\n", x, y); + return true; +} + +static BOOL my_SetPhysicalCursorPos(int x, int y) +{ + dprintf("my_SetPhysicalCursorPos Hit! x %d y %d\n", x, y); + return true; +} + +static int my_ShowCursor(BOOL bShow) +{ + dprintf("my_ShowCursor Hit!\n"); + return 0; +} + +static HCURSOR my_SetCursor(HCURSOR hCursor) +{ + dprintf("my_SetCursor Hit!\n"); + HCURSOR fake_cursor; + + if ( hCursor ) + return next_SetCursor(hCursor); + fake_cursor = LoadCursorA(0, (LPCSTR)0x7F00); + next_SetCursor(fake_cursor); + return 0; +} diff --git a/hooklib/cursor.h b/hooklib/cursor.h new file mode 100644 index 0000000..de0461a --- /dev/null +++ b/hooklib/cursor.h @@ -0,0 +1,3 @@ +#pragma once + +void cursor_hook_init(); \ No newline at end of file diff --git a/hooklib/meson.build b/hooklib/meson.build index 4a381b4..4ff4734 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -7,6 +7,8 @@ hooklib_lib = static_library( capnhook.get_variable('hook_dep'), ], sources : [ + 'cursor.c', + 'cursor.h', 'config.c', 'config.h', 'createprocess.c',