forked from Dniel97/segatools
carol: somewhat-working touch board??
This commit is contained in:
parent
962e14dc9b
commit
4dcf01f643
@ -20,6 +20,7 @@
|
|||||||
#include "hooklib/serial.h"
|
#include "hooklib/serial.h"
|
||||||
#include "hooklib/spike.h"
|
#include "hooklib/spike.h"
|
||||||
#include "hooklib/createprocess.h"
|
#include "hooklib/createprocess.h"
|
||||||
|
#include "hooklib/cursor.h"
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
@ -44,6 +45,8 @@ static DWORD CALLBACK carol_pre_startup(void)
|
|||||||
HMODULE dbghelp;
|
HMODULE dbghelp;
|
||||||
|
|
||||||
dprintf("--- Begin carol_pre_startup ---\n");
|
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. */
|
/* 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");
|
dprintf("Failed to load debug helper library!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cursor_hook_init();
|
||||||
|
|
||||||
/* Config load */
|
/* Config load */
|
||||||
|
|
||||||
carol_hook_config_load(&carol_hook_cfg, L".\\segatools.ini");
|
carol_hook_config_load(&carol_hook_cfg, L".\\segatools.ini");
|
||||||
|
@ -8,13 +8,15 @@
|
|||||||
#include "carolhook/carol-dll.h"
|
#include "carolhook/carol-dll.h"
|
||||||
#include "carolhook/touch.h"
|
#include "carolhook/touch.h"
|
||||||
|
|
||||||
|
#include "hook/table.h"
|
||||||
|
|
||||||
#include "hooklib/uart.h"
|
#include "hooklib/uart.h"
|
||||||
|
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/dump.h"
|
#include "util/dump.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CMDS for M3 EX series
|
* CMDS for touch thing
|
||||||
* CX -> Calibrate Extend, preform callibration
|
* CX -> Calibrate Extend, preform callibration
|
||||||
* MS -> Mode Stream, enters stream mode
|
* MS -> Mode Stream, enters stream mode
|
||||||
* R -> Reset, resets the device
|
* 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_ack_cmd(const struct touch_req *req);
|
||||||
static HRESULT handle_touch_name_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 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 CRITICAL_SECTION touch_lock;
|
||||||
static struct uart touch_uart;
|
static struct uart touch_uart;
|
||||||
@ -40,8 +43,10 @@ static uint8_t touch_written_bytes[528];
|
|||||||
static uint8_t touch_readable_bytes[528];
|
static uint8_t touch_readable_bytes[528];
|
||||||
static bool should_stream = false;
|
static bool should_stream = false;
|
||||||
static bool last_pressed;
|
static bool last_pressed;
|
||||||
static uint16_t last_x;
|
static uint8_t last_x1;
|
||||||
static uint16_t last_y;
|
static uint8_t last_x2;
|
||||||
|
static uint8_t last_y1;
|
||||||
|
static uint8_t last_y2;
|
||||||
|
|
||||||
|
|
||||||
HRESULT touch_hook_init(const struct touch_config *cfg)
|
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) {
|
if (irp->op == IRP_OP_OPEN) {
|
||||||
dprintf("Touchscreen: Starting backend DLL\n");
|
dprintf("Touchscreen: Starting backend DLL\n");
|
||||||
hr = carol_dll.touch_init();
|
hr = carol_dll.touch_init();
|
||||||
|
carol_dll.touch_start(touch_scan_auto);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("Touchscreen: Backend DLL error: %X\n", (int) 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)) {
|
else if (!strcmp("OI", (char *)req.cmd)) {
|
||||||
hr = handle_touch_id_cmd(&req);
|
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)) {
|
else if (!strcmp("NM", (char *)req.cmd)) {
|
||||||
hr = handle_touch_name_cmd(&req);
|
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)
|
static HRESULT handle_touch_name_cmd(const struct touch_req *req)
|
||||||
{
|
{
|
||||||
dprintf("Touch: Get Name\n");
|
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)
|
static HRESULT handle_touch_id_cmd(const struct touch_req *req)
|
||||||
{
|
{
|
||||||
dprintf("Touch: Get ID\n");
|
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;
|
struct touch_auto_resp resp;
|
||||||
uint16_t tmp_x;
|
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;
|
bool flg = false;
|
||||||
|
|
||||||
memset(&resp, 0, sizeof(resp));
|
memset(&resp, 0, sizeof(resp));
|
||||||
resp.rep_id = 0x17;
|
resp.touches[0].status |= 1 << 7;
|
||||||
resp.touches[0].status = 0x04;
|
|
||||||
resp.count = 1;
|
|
||||||
|
|
||||||
if (is_pressed) {
|
if (is_pressed) {
|
||||||
resp.touches[0].status = 0x07;
|
resp.touches[0].status |= (1 << 7) | (1 << 6);
|
||||||
resp.touches[0].touch_id = 1;
|
resp.touches[0].touch_id = 1;
|
||||||
tmp_x = mouse_x & 0x7FFF;
|
tmp_x = mouse_x & 0x7FFF;
|
||||||
tmp_y = mouse_y & 0x7FFF;
|
tmp_y = mouse_y & 0x7FFF;
|
||||||
|
|
||||||
// flip
|
resp.touches[0].x1 = tmp_x & 0x7F;
|
||||||
resp.touches[0].x = (tmp_x << 8) | (tmp_x >> 8);
|
resp.touches[0].x2 = (tmp_x >> 7) & 0x7F;
|
||||||
resp.touches[0].y = (tmp_y << 8) | (tmp_y >> 8);
|
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 1
|
||||||
if (flg)
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
last_x = resp.touches[0].x;
|
last_x1 = resp.touches[0].x1;
|
||||||
last_y = resp.touches[0].y;
|
last_x2 = resp.touches[0].x2;
|
||||||
|
last_y1 = resp.touches[0].y1;
|
||||||
|
last_y2 = resp.touches[0].y2;
|
||||||
|
|
||||||
} else if (last_pressed) {
|
} else if (last_pressed) {
|
||||||
resp.touches[0].x = last_x;
|
resp.touches[0].x1 = last_x1;
|
||||||
resp.touches[0].y = last_y;
|
resp.touches[0].x2 = last_x2;
|
||||||
|
resp.touches[0].y1 = last_y1;
|
||||||
|
resp.touches[0].y2 = last_y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_pressed = is_pressed;
|
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));
|
iobuf_write(&touch_uart.readable, &resp, sizeof(resp));
|
||||||
LeaveCriticalSection(&touch_lock);
|
LeaveCriticalSection(&touch_lock);
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
//if (flg) {
|
|
||||||
dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos);
|
dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos);
|
||||||
dump_iobuf(&touch_uart.readable);
|
dump_iobuf(&touch_uart.readable);
|
||||||
//}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
struct touch_config {
|
struct touch_config {
|
||||||
bool enable;
|
bool enable;
|
||||||
|
unsigned int port_no;
|
||||||
|
char board_id[7];
|
||||||
|
char unit_type[9];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Always starts with 0x01, always ends with 0x0D
|
// Always starts with 0x01, always ends with 0x0D
|
||||||
@ -20,17 +23,21 @@ struct touch_req {
|
|||||||
|
|
||||||
struct touch_report {
|
struct touch_report {
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
uint8_t x1;
|
||||||
|
uint8_t x2;
|
||||||
|
uint8_t y1;
|
||||||
|
uint8_t y2;
|
||||||
uint8_t touch_id;
|
uint8_t touch_id;
|
||||||
uint16_t x;
|
|
||||||
uint16_t y;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct touch_auto_resp {
|
struct touch_auto_resp {
|
||||||
uint8_t rep_id;
|
|
||||||
struct touch_report touches[10];
|
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)
|
#pragma pack(pop)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "carolio/carolio.h"
|
#include "carolio/carolio.h"
|
||||||
#include "carolio/config.h"
|
#include "carolio/config.h"
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx);
|
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 struct carol_io_config carol_io_cfg;
|
||||||
static bool carol_io_touch_stop_flag;
|
static bool carol_io_touch_stop_flag;
|
||||||
static HANDLE carol_io_touch_thread;
|
static HANDLE carol_io_touch_thread;
|
||||||
|
static bool carol_io_window_focus = false;
|
||||||
|
|
||||||
uint16_t carol_io_get_api_version(void)
|
uint16_t carol_io_get_api_version(void)
|
||||||
{
|
{
|
||||||
@ -110,22 +112,62 @@ void carol_io_touch_stop()
|
|||||||
carol_io_touch_stop_flag = true;
|
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)
|
static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx)
|
||||||
{
|
{
|
||||||
carol_io_touch_callback_t callback;
|
carol_io_touch_callback_t callback;
|
||||||
bool mouse_is_down = false;
|
bool mouse_is_down = false;
|
||||||
uint32_t mX = 0;
|
uint16_t mX = 0;
|
||||||
uint32_t mY = 0;
|
uint16_t mY = 0;
|
||||||
POINT lpPoint;
|
POINT lpPoint;
|
||||||
|
HWND hwnd;
|
||||||
|
|
||||||
callback = ctx;
|
callback = ctx;
|
||||||
|
|
||||||
while (!carol_io_touch_stop_flag) {
|
while (!carol_io_touch_stop_flag) {
|
||||||
|
check_fg_wind();
|
||||||
if (GetAsyncKeyState(VK_LBUTTON) & 0x8000) {
|
if (GetAsyncKeyState(VK_LBUTTON) & 0x8000) {
|
||||||
mouse_is_down = true;
|
mouse_is_down = true;
|
||||||
if (GetCursorPos(&lpPoint)) {
|
if (GetCursorPos(&lpPoint)) {
|
||||||
mX = lpPoint.x;
|
hwnd = GetForegroundWindow();
|
||||||
mY = lpPoint.y;
|
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 {
|
} else {
|
||||||
mouse_is_down = false;
|
mouse_is_down = false;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.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
|
/* 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
|
function should return a positive 16-bit integer, where the high byte is
|
||||||
|
73
hooklib/cursor.c
Normal file
73
hooklib/cursor.c
Normal 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
3
hooklib/cursor.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void cursor_hook_init();
|
@ -7,6 +7,8 @@ hooklib_lib = static_library(
|
|||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
],
|
],
|
||||||
sources : [
|
sources : [
|
||||||
|
'cursor.c',
|
||||||
|
'cursor.h',
|
||||||
'config.c',
|
'config.c',
|
||||||
'config.h',
|
'config.h',
|
||||||
'createprocess.c',
|
'createprocess.c',
|
||||||
|
Loading…
Reference in New Issue
Block a user