carol: somewhat-working touch board??

This commit is contained in:
Hay1tsme 2023-11-27 23:23:00 -05:00
parent 962e14dc9b
commit 4dcf01f643
8 changed files with 186 additions and 39 deletions

View File

@ -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");

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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;

View File

@ -5,7 +5,7 @@
#include <stdbool.h>
#include <stdint.h>
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

73
hooklib/cursor.c Normal file
View File

@ -0,0 +1,73 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#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;
}

3
hooklib/cursor.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void cursor_hook_init();

View File

@ -7,6 +7,8 @@ hooklib_lib = static_library(
capnhook.get_variable('hook_dep'),
],
sources : [
'cursor.c',
'cursor.h',
'config.c',
'config.h',
'createprocess.c',