Compare commits
No commits in common. "master" and "master" have entirely different histories.
|
@ -1,17 +1,6 @@
|
|||
.*.swp
|
||||
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
.vscode/
|
||||
|
||||
# Suggested names for build dirs
|
||||
build/
|
||||
|
|
|
@ -1,19 +1,3 @@
|
|||
{
|
||||
"editor.formatOnSave": false,
|
||||
"mesonbuild.configureOnOpen": false,
|
||||
"files.associations": {
|
||||
"string.h": "c",
|
||||
"stdbool.h": "c",
|
||||
"windows.h": "c",
|
||||
"dprintf.h": "c",
|
||||
"touch.h": "c",
|
||||
"mai2-dll.h": "c",
|
||||
"led.h": "c",
|
||||
"path.h": "c",
|
||||
"reg.h": "c",
|
||||
"platform.h": "c",
|
||||
"procaddr.h": "c",
|
||||
"table.h": "c",
|
||||
"serial.h": "c"
|
||||
},
|
||||
}
|
||||
|
|
16
Package.mk
16
Package.mk
|
@ -104,21 +104,6 @@ $(BUILD_DIR_ZIP)/mu3.zip:
|
|||
$(V)strip $(BUILD_DIR_ZIP)/mu3/*.{exe,dll}
|
||||
$(V)cd $(BUILD_DIR_ZIP)/mu3 ; zip -r ../mu3.zip *
|
||||
|
||||
$(BUILD_DIR_ZIP)/mai2.zip:
|
||||
$(V)echo ... $@
|
||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/mai2
|
||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/mai2/DEVICE
|
||||
$(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 \
|
||||
$(BUILD_DIR_ZIP)/mai2
|
||||
$(V)cp pki/billing.pub \
|
||||
pki/ca.crt \
|
||||
$(BUILD_DIR_ZIP)/mai2/DEVICE
|
||||
$(V)strip $(BUILD_DIR_ZIP)/mai2/*.{exe,dll}
|
||||
$(V)cd $(BUILD_DIR_ZIP)/mai2 ; zip -r ../mai2.zip *
|
||||
|
||||
$(BUILD_DIR_ZIP)/doc.zip: \
|
||||
$(DOC_DIR)/config \
|
||||
$(DOC_DIR)/chunihook.md \
|
||||
|
@ -136,7 +121,6 @@ $(BUILD_DIR_ZIP)/segatools.zip: \
|
|||
$(BUILD_DIR_ZIP)/idz.zip \
|
||||
$(BUILD_DIR_ZIP)/mercury.zip \
|
||||
$(BUILD_DIR_ZIP)/mu3.zip \
|
||||
$(BUILD_DIR_ZIP)/mai2.zip \
|
||||
CHANGELOG.md \
|
||||
README.md \
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "hook/iobuf.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "carolhook/carol-dll.h"
|
||||
#include "carolhook/controlbd.h"
|
||||
|
||||
|
@ -36,6 +38,39 @@ static struct uart controlbd_uart;
|
|||
static uint8_t controlbd_written_bytes[520];
|
||||
static uint8_t controlbd_readable_bytes[520];
|
||||
|
||||
static BOOL WINAPI my_CreateProcessA(
|
||||
LPCSTR lpApplicationName,
|
||||
LPSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
);
|
||||
static BOOL (WINAPI *next_CreateProcessA)(
|
||||
LPCSTR lpApplicationName,
|
||||
LPSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
);
|
||||
|
||||
static const struct hook_symbol win32_hooks[] = {
|
||||
{
|
||||
.name = "CreateProcessA",
|
||||
.patch = my_CreateProcessA,
|
||||
.link = (void **) &next_CreateProcessA
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT controlbd_hook_init(const struct controlbd_config *cfg)
|
||||
{
|
||||
if (!cfg->enable) {
|
||||
|
@ -50,6 +85,12 @@ HRESULT controlbd_hook_init(const struct controlbd_config *cfg)
|
|||
controlbd_uart.readable.bytes = controlbd_readable_bytes;
|
||||
controlbd_uart.readable.nbytes = sizeof(controlbd_readable_bytes);
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"kernel32.dll",
|
||||
win32_hooks,
|
||||
_countof(win32_hooks));
|
||||
|
||||
dprintf("Control Board: Init\n");
|
||||
|
||||
return iohook_push_handler(controlbd_handle_irp);
|
||||
|
@ -337,3 +378,50 @@ static HRESULT controlbd_req_ack_any(uint8_t cmd)
|
|||
|
||||
return iobuf_write(&controlbd_uart.readable, &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
static BOOL WINAPI my_CreateProcessA(
|
||||
LPCSTR lpApplicationName,
|
||||
LPSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
)
|
||||
{
|
||||
dprintf("Control Board: my_CreateProcessA Hit! %s\n", lpCommandLine);
|
||||
if (strncmp(".\\15312firm\\firmupdate_1113.exe", lpCommandLine, 31)) {
|
||||
return next_CreateProcessA(
|
||||
lpApplicationName,
|
||||
lpCommandLine,
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
lpCurrentDirectory,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation
|
||||
);
|
||||
}
|
||||
|
||||
dprintf("Control Board: Hooking child process\n");
|
||||
char new_cmd[MAX_PATH] = "inject -d -k carolhook.dll ";
|
||||
strcat_s(new_cmd, MAX_PATH, lpCommandLine);
|
||||
|
||||
return next_CreateProcessA(
|
||||
lpApplicationName,
|
||||
new_cmd,
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
lpCurrentDirectory,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation
|
||||
);
|
||||
}
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
#include "hooklib/serial.h"
|
||||
#include "hooklib/spike.h"
|
||||
#include "hooklib/createprocess.h"
|
||||
#include "hooklib/cursor.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
|
||||
|
@ -45,8 +43,6 @@ 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. */
|
||||
|
||||
|
@ -68,8 +64,6 @@ 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");
|
||||
|
@ -128,12 +122,7 @@ static DWORD CALLBACK carol_pre_startup(void)
|
|||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = createprocess_push_hook_a(".\\15312firm\\firmupdate_1113.exe", "inject -d -k carolhook.dll ", NULL, false);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Initialize debug helpers */
|
||||
|
||||
spike_hook_init(L".\\segatools.ini");
|
||||
|
|
|
@ -8,15 +8,13 @@
|
|||
#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 touch thing
|
||||
* CMDS for M3 EX series
|
||||
* CX -> Calibrate Extend, preform callibration
|
||||
* MS -> Mode Stream, enters stream mode
|
||||
* R -> Reset, resets the device
|
||||
|
@ -34,8 +32,7 @@ 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 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 void touch_scan_auto(const bool is_pressed, const uint32_t mouse_x, const uint32_t mouse_y);
|
||||
|
||||
static CRITICAL_SECTION touch_lock;
|
||||
static struct uart touch_uart;
|
||||
|
@ -43,10 +40,8 @@ static uint8_t touch_written_bytes[528];
|
|||
static uint8_t touch_readable_bytes[528];
|
||||
static bool should_stream = false;
|
||||
static bool last_pressed;
|
||||
static uint8_t last_x1;
|
||||
static uint8_t last_x2;
|
||||
static uint8_t last_y1;
|
||||
static uint8_t last_y2;
|
||||
static uint16_t last_x;
|
||||
static uint16_t last_y;
|
||||
|
||||
|
||||
HRESULT touch_hook_init(const struct touch_config *cfg)
|
||||
|
@ -96,7 +91,6 @@ 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);
|
||||
|
@ -129,9 +123,7 @@ static HRESULT touch_handle_irp_locked(struct irp *irp)
|
|||
}
|
||||
else if (!strcmp("OI", (char *)req.cmd)) {
|
||||
hr = handle_touch_id_cmd(&req);
|
||||
}
|
||||
else if (!strcmp("UT", (char *)req.cmd)) {
|
||||
hr = handle_touch_unit_type_cmd(&req);
|
||||
//carol_dll.touch_start(touch_scan_auto);
|
||||
}
|
||||
else if (!strcmp("NM", (char *)req.cmd)) {
|
||||
hr = handle_touch_name_cmd(&req);
|
||||
|
@ -158,22 +150,16 @@ 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, "\001AD1000\015", 15);
|
||||
return iobuf_write(&touch_uart.readable, "\001EX1234 EX1234\015", 15);
|
||||
}
|
||||
|
||||
static HRESULT handle_touch_id_cmd(const struct touch_req *req)
|
||||
{
|
||||
dprintf("Touch: Get ID\n");
|
||||
return iobuf_write(&touch_uart.readable, "\001AD1000\015", 8);
|
||||
return iobuf_write(&touch_uart.readable, "\001EX1234\015", 8);
|
||||
}
|
||||
|
||||
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)
|
||||
static void touch_scan_auto(const bool is_pressed, const uint32_t mouse_x, const uint32_t mouse_y)
|
||||
{
|
||||
struct touch_auto_resp resp;
|
||||
uint16_t tmp_x;
|
||||
|
@ -181,37 +167,34 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
|
|||
bool flg = false;
|
||||
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
resp.touches[0].status |= 1 << 7;
|
||||
resp.rep_id = 0x17;
|
||||
resp.touches[0].status = 0x04;
|
||||
resp.count = 1;
|
||||
|
||||
if (is_pressed) {
|
||||
resp.touches[0].status |= (1 << 7) | (1 << 6);
|
||||
resp.touches[0].status = 0x07;
|
||||
resp.touches[0].touch_id = 1;
|
||||
tmp_x = mouse_x & 0x7FFF;
|
||||
tmp_y = mouse_y & 0x7FFF;
|
||||
|
||||
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;
|
||||
// flip
|
||||
resp.touches[0].x = (tmp_x << 8) | (tmp_x >> 8);
|
||||
resp.touches[0].y = (tmp_y << 8) | (tmp_y >> 8);
|
||||
|
||||
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;
|
||||
flg = resp.touches[0].x != last_x || resp.touches[0].y != last_y;
|
||||
|
||||
#if 1
|
||||
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);
|
||||
dprintf("Touch: Mouse down! x %04X y: %04X\n", resp.touches[0].x, resp.touches[0].y);
|
||||
#endif
|
||||
|
||||
|
||||
last_x1 = resp.touches[0].x1;
|
||||
last_x2 = resp.touches[0].x2;
|
||||
last_y1 = resp.touches[0].y1;
|
||||
last_y2 = resp.touches[0].y2;
|
||||
last_x = resp.touches[0].x;
|
||||
last_y = resp.touches[0].y;
|
||||
|
||||
} else if (last_pressed) {
|
||||
resp.touches[0].x1 = last_x1;
|
||||
resp.touches[0].x2 = last_x2;
|
||||
resp.touches[0].y1 = last_y1;
|
||||
resp.touches[0].y2 = last_y2;
|
||||
resp.touches[0].x = last_x;
|
||||
resp.touches[0].y = last_y;
|
||||
}
|
||||
|
||||
last_pressed = is_pressed;
|
||||
|
@ -220,9 +203,11 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
|
|||
iobuf_write(&touch_uart.readable, &resp, sizeof(resp));
|
||||
LeaveCriticalSection(&touch_lock);
|
||||
|
||||
#if 0
|
||||
dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos);
|
||||
dump_iobuf(&touch_uart.readable);
|
||||
#if 1
|
||||
//if (flg) {
|
||||
dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos);
|
||||
dump_iobuf(&touch_uart.readable);
|
||||
//}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -250,4 +235,4 @@ static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf)
|
|||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
}
|
|
@ -8,9 +8,6 @@
|
|||
|
||||
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
|
||||
|
@ -23,21 +20,17 @@ 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];
|
||||
};
|
||||
|
||||
enum {
|
||||
TOUCH_MODE_STREAM = 0x01,
|
||||
TOUCH_MODE_DOWN_UP = 0x02,
|
||||
TOUCH_MODE_INACTIVE = 0x03,
|
||||
uint8_t count;
|
||||
uint16_t scan_time;
|
||||
//uint8_t padding[456];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include "carolio/carolio.h"
|
||||
#include "carolio/config.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static unsigned int __stdcall carol_io_touch_thread_proc(void *ctx);
|
||||
|
||||
|
@ -16,7 +15,6 @@ 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)
|
||||
{
|
||||
|
@ -112,62 +110,22 @@ 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;
|
||||
uint16_t mX = 0;
|
||||
uint16_t mY = 0;
|
||||
uint32_t mX = 0;
|
||||
uint32_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)) {
|
||||
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;
|
||||
}
|
||||
if (GetCursorPos(&lpPoint)) {
|
||||
mX = lpPoint.x;
|
||||
mY = lpPoint.y;
|
||||
}
|
||||
} else {
|
||||
mouse_is_down = false;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*carol_io_touch_callback_t)(const bool is_pressed, const uint16_t mouse_x, const uint16_t mouse_y);
|
||||
typedef void (*carol_io_touch_callback_t)(const bool is_pressed, const uint32_t mouse_x, const uint32_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
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "cxbhook/led.h"
|
||||
#include "cxbhook/cxb-dll.h"
|
||||
|
||||
#include "hook/procaddr.h"
|
||||
#include "hooklib/procaddr.h"
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
|
@ -50,7 +50,7 @@ static struct hook_symbol lamp_syms[] = {
|
|||
HRESULT led_hook_init(struct led_config *cfg)
|
||||
{
|
||||
dprintf("LED: Init\n");
|
||||
return proc_addr_table_push(NULL, "CommLamp.dll", lamp_syms, _countof(lamp_syms));
|
||||
return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms));
|
||||
}
|
||||
|
||||
static int my_cCommLamp_Open(char *port)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "cxbhook/revio.h"
|
||||
#include "cxbhook/cxb-dll.h"
|
||||
|
||||
#include "hook/procaddr.h"
|
||||
#include "hooklib/procaddr.h"
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
|
@ -83,7 +83,7 @@ static struct hook_symbol revio_syms[] = {
|
|||
HRESULT revio_hook_init(struct revio_config *cfg)
|
||||
{
|
||||
dprintf("Revio: Init\n");
|
||||
return proc_addr_table_push(NULL, "CommIo.dll", revio_syms, _countof(revio_syms));
|
||||
return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms));
|
||||
}
|
||||
|
||||
static int my_cCommIo_Open(char *port)
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
[vfs]
|
||||
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
||||
amfs=amfs
|
||||
; Create an empty directory somewhere and insert the path here.
|
||||
; This directory may be shared between multiple SEGA games.
|
||||
; NOTE: This has nothing to do with Windows %APPDATA%.
|
||||
appdata=appdata
|
||||
option=option
|
||||
|
||||
[dns]
|
||||
; Insert the hostname or IP address of the server you wish to use here.
|
||||
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
||||
default=127.0.0.1
|
||||
|
||||
[ds]
|
||||
; Region code on the emulated AMEX board DS EEPROM.
|
||||
; 1: Japan
|
||||
; 4: Export (some UI elements in English)
|
||||
;
|
||||
; NOTE: Changing this setting causes a factory reset.
|
||||
region=1
|
||||
|
||||
[netenv]
|
||||
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
|
||||
; SEGA games are somewhat picky about their LAN environment, so leaving this
|
||||
; setting enabled is recommended.
|
||||
enable=1
|
||||
|
||||
[keychip]
|
||||
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
||||
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
||||
; that subnet must start with 192.168.
|
||||
subnet=192.168.172.0
|
||||
|
||||
[gfx]
|
||||
enable=1
|
||||
|
||||
[io4]
|
||||
; Delete
|
||||
test=0x2E
|
||||
; End
|
||||
service=0x23
|
||||
; Insert
|
||||
coin=0x2D
|
|
@ -1,11 +0,0 @@
|
|||
@echo off
|
||||
pushd %~dp0
|
||||
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
start inject -d -k mai2hook.dll amdaemon.exe -f -c config_client.json config_common.json config_server.json
|
||||
inject.exe -d -k mai2hook.dll Sinmai.exe -screen-fullscreen 0 -screen-width 2160 -screen-height 1920
|
||||
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
echo Game processes have terminated
|
|
@ -30,7 +30,7 @@ enable=1
|
|||
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
||||
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
||||
; that subnet must start with 192.168.
|
||||
subnet=192.168.162.0
|
||||
subnet=192.168.250.0
|
||||
|
||||
[gfx]
|
||||
enable=1
|
||||
|
@ -57,4 +57,4 @@ RIGHT_SIDE=0x55
|
|||
SLIDER_LEFT=0x54
|
||||
SLIDER_RIGHT=0x59
|
||||
;Change move speed of slider when use dinput
|
||||
SLIDER_SPEED=1000
|
||||
SLIDER_SPEED=1000
|
|
@ -3,8 +3,12 @@ pushd %~dp0
|
|||
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
start inject -d -k mu3hook.dll amdaemon.exe -f -c config_client.json config_common.json config_server.json
|
||||
inject -d -k mu3hook.dll mu3.exe
|
||||
REM USA
|
||||
REM start 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 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
|
||||
inject -d -k mercuryhook.dll ../WindowsNoEditor/Mercury/Binaries/Win64/Mercury-Win64-Shipping.exe
|
||||
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
|
|
|
@ -1,257 +0,0 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/createprocess.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
void createprocess_hook_init();
|
||||
static BOOL WINAPI my_CreateProcessA(
|
||||
LPCSTR lpApplicationName,
|
||||
LPSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
);
|
||||
BOOL my_CreateProcessW(
|
||||
LPCWSTR lpApplicationName,
|
||||
LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCWSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
);
|
||||
|
||||
static BOOL (WINAPI *next_CreateProcessA)(
|
||||
LPCSTR lpApplicationName,
|
||||
LPSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
);
|
||||
|
||||
static BOOL (WINAPI *next_CreateProcessW)(
|
||||
LPCWSTR lpApplicationName,
|
||||
LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCWSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
);
|
||||
|
||||
static const struct hook_symbol win32_hooks[] = {
|
||||
{
|
||||
.name = "CreateProcessA",
|
||||
.patch = my_CreateProcessA,
|
||||
.link = (void **) &next_CreateProcessA
|
||||
},
|
||||
{
|
||||
.name = "CreateProcessW",
|
||||
.patch = my_CreateProcessW,
|
||||
.link = (void **) &next_CreateProcessW
|
||||
},
|
||||
};
|
||||
|
||||
static bool did_init = false;
|
||||
|
||||
static struct process_hook_sym_w *process_syms_w;
|
||||
static struct process_hook_sym_a *process_syms_a;
|
||||
|
||||
static size_t process_nsyms_a = 0;
|
||||
static size_t process_nsyms_w = 0;
|
||||
|
||||
static CRITICAL_SECTION createproc_lock;
|
||||
|
||||
HRESULT createprocess_push_hook_w(const wchar_t *name, const wchar_t *head, const wchar_t *tail, bool replace_all) {
|
||||
struct process_hook_sym_w *new_mem;
|
||||
struct process_hook_sym_w *new_proc;
|
||||
HRESULT hr;
|
||||
|
||||
assert(name != NULL);
|
||||
assert(head != NULL);
|
||||
|
||||
createprocess_hook_init();
|
||||
EnterCriticalSection(&createproc_lock);
|
||||
|
||||
new_mem = realloc(
|
||||
process_syms_w,
|
||||
(process_nsyms_w + 1) * sizeof(struct process_hook_sym_w));
|
||||
|
||||
if (new_mem == NULL) {
|
||||
|
||||
LeaveCriticalSection(&createproc_lock);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
new_proc = &new_mem[process_nsyms_w];
|
||||
memset(new_proc, 0, sizeof(*new_proc));
|
||||
new_proc->name = name;
|
||||
new_proc->head = head;
|
||||
new_proc->tail = tail;
|
||||
new_proc->replace_all = replace_all;
|
||||
|
||||
process_syms_w = new_mem;
|
||||
process_nsyms_w++;
|
||||
|
||||
LeaveCriticalSection(&createproc_lock);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT createprocess_push_hook_a(const char *name, const char *head, const char *tail, bool replace_all) {
|
||||
struct process_hook_sym_a *new_mem;
|
||||
struct process_hook_sym_a *new_proc;
|
||||
|
||||
assert(name != NULL);
|
||||
assert(head != NULL);
|
||||
|
||||
createprocess_hook_init();
|
||||
|
||||
EnterCriticalSection(&createproc_lock);
|
||||
|
||||
new_mem = realloc(
|
||||
process_syms_a,
|
||||
(process_nsyms_a + 1) * sizeof(struct process_hook_sym_a));
|
||||
|
||||
if (new_mem == NULL) {
|
||||
|
||||
LeaveCriticalSection(&createproc_lock);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
new_proc = &new_mem[process_nsyms_a];
|
||||
memset(new_proc, 0, sizeof(*new_proc));
|
||||
new_proc->name = name;
|
||||
new_proc->head = head;
|
||||
new_proc->tail = tail;
|
||||
new_proc->replace_all = replace_all;
|
||||
|
||||
process_syms_a = new_mem;
|
||||
process_nsyms_a++;
|
||||
|
||||
LeaveCriticalSection(&createproc_lock);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void createprocess_hook_init() {
|
||||
if (did_init) {
|
||||
return;
|
||||
}
|
||||
did_init = true;
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"kernel32.dll",
|
||||
win32_hooks,
|
||||
_countof(win32_hooks));
|
||||
InitializeCriticalSection(&createproc_lock);
|
||||
dprintf("CreateProcess: Init\n");
|
||||
}
|
||||
|
||||
|
||||
static BOOL WINAPI my_CreateProcessA(
|
||||
LPCSTR lpApplicationName,
|
||||
LPSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
)
|
||||
{
|
||||
for (int i = 0; i < process_nsyms_a; i++) {
|
||||
if (strncmp(process_syms_a[i].name, lpCommandLine, strlen(process_syms_a[i].name))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dprintf("CreateProcess: Hooking child process %s %s\n", lpApplicationName, lpCommandLine);
|
||||
char new_cmd[MAX_PATH] = {0};
|
||||
strcat_s(new_cmd, MAX_PATH, process_syms_a[i].head);
|
||||
|
||||
if (!process_syms_a[i].replace_all) {
|
||||
strcat_s(new_cmd, MAX_PATH, lpCommandLine);
|
||||
}
|
||||
|
||||
if (process_syms_a[i].tail != NULL) {
|
||||
strcat_s(new_cmd, MAX_PATH, process_syms_a[i].tail);
|
||||
}
|
||||
|
||||
dprintf("CreateProcess: Replaced CreateProcessA %s\n", new_cmd);
|
||||
return next_CreateProcessA(
|
||||
lpApplicationName,
|
||||
new_cmd,
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
lpCurrentDirectory,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation
|
||||
);
|
||||
}
|
||||
return next_CreateProcessA(
|
||||
lpApplicationName,
|
||||
lpCommandLine,
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
lpCurrentDirectory,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation
|
||||
);
|
||||
}
|
||||
|
||||
BOOL my_CreateProcessW(
|
||||
LPCWSTR lpApplicationName,
|
||||
LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment,
|
||||
LPCWSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation)
|
||||
{
|
||||
return next_CreateProcessW(
|
||||
lpApplicationName,
|
||||
lpCommandLine,
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
lpCurrentDirectory,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation
|
||||
);
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
HRESULT createprocess_push_hook_w(const wchar_t *name, const wchar_t *head, const wchar_t *tail, bool replace_all);
|
||||
HRESULT createprocess_push_hook_a(const char *name, const char *head, const char *tail, bool replace_all);
|
||||
|
||||
struct process_hook_sym_w {
|
||||
const wchar_t *name;
|
||||
const wchar_t *head;
|
||||
const wchar_t *tail;
|
||||
bool replace_all;
|
||||
};
|
||||
|
||||
struct process_hook_sym_a {
|
||||
const char *name;
|
||||
const char *head;
|
||||
const char *tail;
|
||||
bool replace_all;
|
||||
};
|
|
@ -1,71 +0,0 @@
|
|||
#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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HCURSOR my_SetCursor(HCURSOR hCursor)
|
||||
{
|
||||
HCURSOR fake_cursor;
|
||||
|
||||
if ( hCursor )
|
||||
return next_SetCursor(hCursor);
|
||||
fake_cursor = LoadCursorA(0, (LPCSTR)0x7F00);
|
||||
next_SetCursor(fake_cursor);
|
||||
return 0;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
void cursor_hook_init();
|
|
@ -7,12 +7,8 @@ hooklib_lib = static_library(
|
|||
capnhook.get_variable('hook_dep'),
|
||||
],
|
||||
sources : [
|
||||
'cursor.c',
|
||||
'cursor.h',
|
||||
'config.c',
|
||||
'config.h',
|
||||
'createprocess.c',
|
||||
'createprocess.h',
|
||||
'dll.c',
|
||||
'dll.h',
|
||||
'dns.c',
|
||||
|
@ -23,6 +19,8 @@ hooklib_lib = static_library(
|
|||
'fdshark.h',
|
||||
'path.c',
|
||||
'path.h',
|
||||
'procaddr.c',
|
||||
'procaddr.h',
|
||||
'reg.c',
|
||||
'reg.h',
|
||||
'setupapi.c',
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "hooklib/procaddr.h"
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static struct proc_addr_table *proc_addr_hook_list;
|
||||
static size_t proc_addr_hook_count;
|
||||
static CRITICAL_SECTION proc_addr_hook_lock;
|
||||
static bool proc_addr_hook_initted;
|
||||
|
||||
static FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name);
|
||||
static FARPROC (WINAPI *next_GetProcAddress)(HMODULE hModule, const char *name);
|
||||
static void proc_addr_hook_init(void);
|
||||
|
||||
static const struct hook_symbol win32_hooks[] = {
|
||||
{
|
||||
.name = "GetProcAddress",
|
||||
.patch = my_GetProcAddress,
|
||||
.link = (void **) &next_GetProcAddress
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT proc_addr_table_push(
|
||||
const char *target,
|
||||
struct hook_symbol *syms,
|
||||
size_t nsyms
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
struct proc_addr_table *new_item;
|
||||
struct proc_addr_table *new_mem;
|
||||
|
||||
proc_addr_hook_init();
|
||||
|
||||
EnterCriticalSection(&proc_addr_hook_lock);
|
||||
|
||||
new_mem = realloc(
|
||||
proc_addr_hook_list,
|
||||
(proc_addr_hook_count + 1) * sizeof(struct proc_addr_table));
|
||||
|
||||
if (new_mem == NULL) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
|
||||
LeaveCriticalSection(&proc_addr_hook_lock);
|
||||
return hr;
|
||||
}
|
||||
|
||||
new_item = &new_mem[proc_addr_hook_count];
|
||||
new_item->name = target;
|
||||
new_item->nsyms = nsyms;
|
||||
new_item->syms = syms;
|
||||
|
||||
proc_addr_hook_list = new_mem;
|
||||
proc_addr_hook_count++;
|
||||
hr = S_OK;
|
||||
|
||||
LeaveCriticalSection(&proc_addr_hook_lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void proc_addr_hook_init(void)
|
||||
{
|
||||
if (proc_addr_hook_initted) {
|
||||
return;
|
||||
}
|
||||
|
||||
dprintf("ProcAddr: Hook init\n");
|
||||
proc_addr_hook_initted = true;
|
||||
|
||||
InitializeCriticalSection(&proc_addr_hook_lock);
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"kernel32.dll",
|
||||
win32_hooks,
|
||||
_countof(win32_hooks));
|
||||
}
|
||||
|
||||
FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name)
|
||||
{
|
||||
uintptr_t ordinal = (uintptr_t) name;
|
||||
char mod_path[PATH_MAX];
|
||||
char *mod_name;
|
||||
const struct hook_symbol *sym;
|
||||
FARPROC result = next_GetProcAddress(hModule, name);
|
||||
|
||||
GetModuleFileNameA(hModule, mod_path, PATH_MAX);
|
||||
mod_name = basename(mod_path);
|
||||
|
||||
for (int i = 0; i < proc_addr_hook_count; i++) {
|
||||
|
||||
if (strcmp(proc_addr_hook_list[i].name, mod_name) == 0) {
|
||||
|
||||
for (int j = 0; j < proc_addr_hook_list[i].nsyms; j++) {
|
||||
sym = &proc_addr_hook_list[i].syms[j];
|
||||
|
||||
if (ordinal > 0xFFFF) {
|
||||
|
||||
if (strcmp(sym->name, name) == 0) {
|
||||
|
||||
dprintf("ProcAddr: Hooking %s from %s\n", name, mod_name);
|
||||
result = (FARPROC) sym->patch;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if (sym->ordinal == ordinal) {
|
||||
|
||||
dprintf("ProcAddr: Hooking Ord %p from %s\n", (void *)ordinal, mod_name);
|
||||
result = (FARPROC) sym->patch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
struct proc_addr_table {
|
||||
const char *name;
|
||||
size_t nsyms;
|
||||
struct hook_symbol *syms;
|
||||
};
|
||||
|
||||
HRESULT proc_addr_table_push(
|
||||
const char *target,
|
||||
struct hook_symbol *syms,
|
||||
size_t nsyms
|
||||
);
|
165
hooklib/reg.c
165
hooklib/reg.c
|
@ -7,7 +7,6 @@
|
|||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/reg.h"
|
||||
#include "hook/procaddr.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
#include "util/str.h"
|
||||
|
@ -100,29 +99,6 @@ static LSTATUS WINAPI hook_RegGetValueW(
|
|||
uint32_t *numData
|
||||
);
|
||||
|
||||
static LSTATUS WINAPI hook_RegQueryInfoKeyW(
|
||||
HKEY hKey,
|
||||
LPWSTR lpClass,
|
||||
LPDWORD lpcchClass,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpcSubKeys,
|
||||
LPDWORD lpcbMaxSubKeyLen,
|
||||
LPDWORD lpcbMaxClassLen,
|
||||
LPDWORD lpcValues,
|
||||
LPDWORD lpcbMaxValueNameLen,
|
||||
LPDWORD lpcbMaxValueLen,
|
||||
LPDWORD lpcbSecurityDescriptor,
|
||||
PFILETIME lpftLastWriteTime);
|
||||
|
||||
static LSTATUS WINAPI hook_RegEnumValueW(
|
||||
HKEY hkey,
|
||||
DWORD dwIndex,
|
||||
LPWSTR lpValueName,
|
||||
LPDWORD lpcchValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData);
|
||||
/* Link pointers */
|
||||
|
||||
static LSTATUS (WINAPI *next_RegOpenKeyExW)(
|
||||
|
@ -179,30 +155,6 @@ static LSTATUS (WINAPI *next_RegGetValueW)(
|
|||
uint32_t *numData
|
||||
);
|
||||
|
||||
static LSTATUS (WINAPI *next_RegQueryInfoKeyW)(
|
||||
HKEY hKey,
|
||||
LPWSTR lpClass,
|
||||
LPDWORD lpcchClass,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpcSubKeys,
|
||||
LPDWORD lpcbMaxSubKeyLen,
|
||||
LPDWORD lpcbMaxClassLen,
|
||||
LPDWORD lpcValues,
|
||||
LPDWORD lpcbMaxValueNameLen,
|
||||
LPDWORD lpcbMaxValueLen,
|
||||
LPDWORD lpcbSecurityDescriptor,
|
||||
PFILETIME lpftLastWriteTime);
|
||||
|
||||
static LSTATUS (WINAPI *next_RegEnumValueW)(
|
||||
HKEY hkey,
|
||||
DWORD dwIndex,
|
||||
LPWSTR lpValueName,
|
||||
LPDWORD lpcchValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData);
|
||||
|
||||
static const struct hook_symbol reg_hook_syms[] = {
|
||||
{
|
||||
.name = "RegOpenKeyExW",
|
||||
|
@ -232,14 +184,6 @@ static const struct hook_symbol reg_hook_syms[] = {
|
|||
.name = "RegGetValueW",
|
||||
.patch = hook_RegGetValueW,
|
||||
.link = (void **) &next_RegGetValueW,
|
||||
}, {
|
||||
.name = "RegQueryInfoKeyW",
|
||||
.patch = hook_RegQueryInfoKeyW,
|
||||
.link = (void **) &next_RegQueryInfoKeyW,
|
||||
}, {
|
||||
.name = "RegEnumValueW",
|
||||
.patch = hook_RegEnumValueW,
|
||||
.link = (void **) &next_RegEnumValueW,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -310,24 +254,11 @@ static void reg_hook_init(void)
|
|||
InitializeCriticalSection(®_hook_lock);
|
||||
dprintf("Reg hook init\n");
|
||||
|
||||
reg_hook_insert_hooks(NULL);
|
||||
|
||||
proc_addr_table_push(
|
||||
NULL,
|
||||
"ADVAPI32.dll",
|
||||
(struct hook_symbol *) reg_hook_syms,
|
||||
_countof(reg_hook_syms));
|
||||
|
||||
}
|
||||
|
||||
void reg_hook_insert_hooks(HMODULE target)
|
||||
{
|
||||
hook_table_apply(
|
||||
target,
|
||||
NULL,
|
||||
"advapi32.dll",
|
||||
reg_hook_syms,
|
||||
_countof(reg_hook_syms));
|
||||
|
||||
}
|
||||
|
||||
static LRESULT reg_hook_propagate_hr(HRESULT hr)
|
||||
|
@ -400,7 +331,6 @@ static LSTATUS reg_hook_open_locked(
|
|||
/* Assume reg keys are referenced from a root key and not from some
|
||||
intermediary key */
|
||||
key = ®_hook_keys[i];
|
||||
//dprintf("Reg: %ls vs %ls\n", name, key->name);
|
||||
|
||||
if (key->root == parent && wstr_ieq(key->name, name)) {
|
||||
break;
|
||||
|
@ -891,99 +821,6 @@ static LSTATUS WINAPI hook_RegGetValueW(
|
|||
return err;
|
||||
}
|
||||
|
||||
static LSTATUS WINAPI hook_RegQueryInfoKeyW(
|
||||
HKEY hKey,
|
||||
LPWSTR lpClass,
|
||||
LPDWORD lpcchClass,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpcSubKeys,
|
||||
LPDWORD lpcbMaxSubKeyLen,
|
||||
LPDWORD lpcbMaxClassLen,
|
||||
LPDWORD lpcValues,
|
||||
LPDWORD lpcbMaxValueNameLen,
|
||||
LPDWORD lpcbMaxValueLen,
|
||||
LPDWORD lpcbSecurityDescriptor,
|
||||
PFILETIME lpftLastWriteTime)
|
||||
{
|
||||
struct reg_hook_key *key;
|
||||
LSTATUS err;
|
||||
|
||||
EnterCriticalSection(®_hook_lock);
|
||||
|
||||
key = reg_hook_match_key_locked(hKey);
|
||||
|
||||
/* Check if this is a virtualized registry key */
|
||||
|
||||
if (key == NULL) {
|
||||
LeaveCriticalSection(®_hook_lock);
|
||||
|
||||
return next_RegQueryInfoKeyW(
|
||||
hKey,
|
||||
lpClass,
|
||||
lpcchClass,
|
||||
lpReserved,
|
||||
lpcSubKeys,
|
||||
lpcbMaxSubKeyLen,
|
||||
lpcbMaxClassLen,
|
||||
lpcValues,
|
||||
lpcbMaxValueNameLen,
|
||||
lpcbMaxValueLen,
|
||||
lpcbSecurityDescriptor,
|
||||
lpftLastWriteTime);
|
||||
}
|
||||
|
||||
// This is the only one I've seen even be changed, so it's all I'm doing
|
||||
// until I see otherwise.
|
||||
*lpcValues = key->nvals;
|
||||
LeaveCriticalSection(®_hook_lock);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static LSTATUS WINAPI hook_RegEnumValueW(
|
||||
HKEY hkey,
|
||||
DWORD dwIndex,
|
||||
LPWSTR lpValueName,
|
||||
LPDWORD lpcchValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData)
|
||||
{
|
||||
struct reg_hook_key *key;
|
||||
HRESULT hr;
|
||||
LSTATUS err;
|
||||
|
||||
EnterCriticalSection(®_hook_lock);
|
||||
|
||||
key = reg_hook_match_key_locked(hkey);
|
||||
|
||||
/* Check if this is a virtualized registry key */
|
||||
|
||||
if (key == NULL) {
|
||||
LeaveCriticalSection(®_hook_lock);
|
||||
|
||||
return next_RegEnumValueW(
|
||||
hkey,
|
||||
dwIndex,
|
||||
lpValueName,
|
||||
lpcchValueName,
|
||||
lpReserved,
|
||||
lpType,
|
||||
lpData,
|
||||
lpcbData);
|
||||
}
|
||||
|
||||
if (dwIndex >= key->nvals) {
|
||||
LeaveCriticalSection(®_hook_lock);
|
||||
return ERROR_NO_MORE_ITEMS; // Pretty sure this is what it actually returns here?
|
||||
}
|
||||
|
||||
wcscpy_s(lpValueName, *lpcchValueName, key->vals[dwIndex].name);
|
||||
*lpcchValueName = wcslen(key->vals[dwIndex].name);
|
||||
LeaveCriticalSection(®_hook_lock);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
HRESULT reg_hook_read_bin(
|
||||
void *bytes,
|
||||
uint32_t *nbytes,
|
||||
|
|
|
@ -12,8 +12,6 @@ struct reg_hook_val {
|
|||
uint32_t type;
|
||||
};
|
||||
|
||||
void reg_hook_insert_hooks(HMODULE target);
|
||||
|
||||
HRESULT reg_hook_push_key(
|
||||
HKEY root,
|
||||
const wchar_t *name,
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "board/config.h"
|
||||
|
||||
#include "gfxhook/config.h"
|
||||
|
||||
#include "hooklib/config.h"
|
||||
#include "hooklib/dvd.h"
|
||||
|
||||
#include "mai2hook/config.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
|
||||
void mai2_dll_config_load(
|
||||
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);
|
||||
}
|
||||
|
||||
void touch_config_load(
|
||||
struct touch_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"touch", L"enable", 1, filename);
|
||||
}
|
||||
|
||||
void led_config_load(
|
||||
struct led_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"led", L"enable", 1, filename);
|
||||
}
|
||||
|
||||
void mai2_hook_config_load(
|
||||
struct mai2_hook_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
platform_config_load(&cfg->platform, filename);
|
||||
aime_config_load(&cfg->aime, filename);
|
||||
dvd_config_load(&cfg->dvd, filename);
|
||||
io4_config_load(&cfg->io4, filename);
|
||||
gfx_config_load(&cfg->gfx, filename);
|
||||
mai2_dll_config_load(&cfg->dll, filename);
|
||||
touch_config_load(&cfg->touch, filename);
|
||||
led_config_load(&cfg->led, filename);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "board/config.h"
|
||||
|
||||
#include "gfxhook/gfx.h"
|
||||
|
||||
#include "hooklib/dvd.h"
|
||||
|
||||
#include "mai2hook/mai2-dll.h"
|
||||
#include "mai2hook/touch.h"
|
||||
#include "mai2hook/led.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
|
||||
struct mai2_hook_config {
|
||||
struct platform_config platform;
|
||||
struct aime_config aime;
|
||||
struct dvd_config dvd;
|
||||
struct io4_config io4;
|
||||
struct gfx_config gfx;
|
||||
struct mai2_dll_config dll;
|
||||
struct touch_config touch;
|
||||
struct led_config led;
|
||||
};
|
||||
|
||||
void mai2_dll_config_load(
|
||||
struct mai2_dll_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
void mai2_hook_config_load(
|
||||
struct mai2_hook_config *cfg,
|
||||
const wchar_t *filename);
|
|
@ -1,148 +0,0 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
#include "board/sg-reader.h"
|
||||
#include "board/vfd.h"
|
||||
|
||||
#include "gfxhook/d3d9.h"
|
||||
#include "gfxhook/d3d11.h"
|
||||
#include "gfxhook/dxgi.h"
|
||||
#include "gfxhook/gfx.h"
|
||||
|
||||
#include "hook/process.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/dvd.h"
|
||||
#include "hooklib/spike.h"
|
||||
#include "hooklib/path.h"
|
||||
#include "hooklib/reg.h"
|
||||
#include "hook/procaddr.h"
|
||||
#include "hooklib/serial.h"
|
||||
|
||||
#include "mai2hook/config.h"
|
||||
#include "mai2hook/io4.h"
|
||||
#include "mai2hook/mai2-dll.h"
|
||||
#include "mai2hook/unity.h"
|
||||
#include "mai2hook/touch.h"
|
||||
#include "mai2hook/led.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static HMODULE mai2_hook_mod;
|
||||
static process_entry_t mai2_startup;
|
||||
static struct mai2_hook_config mai2_hook_cfg;
|
||||
|
||||
static DWORD CALLBACK mai2_pre_startup(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
dprintf("--- Begin mai2_pre_startup ---\n");
|
||||
|
||||
/* Load config */
|
||||
|
||||
mai2_hook_config_load(&mai2_hook_cfg, L".\\segatools.ini");
|
||||
|
||||
/* Hook Win32 APIs */
|
||||
|
||||
dvd_hook_init(&mai2_hook_cfg.dvd, mai2_hook_mod);
|
||||
gfx_hook_init(&mai2_hook_cfg.gfx);
|
||||
gfx_d3d9_hook_init(&mai2_hook_cfg.gfx, mai2_hook_mod);
|
||||
gfx_d3d11_hook_init(&mai2_hook_cfg.gfx, mai2_hook_mod);
|
||||
gfx_dxgi_hook_init(&mai2_hook_cfg.gfx, mai2_hook_mod);
|
||||
serial_hook_init();
|
||||
|
||||
/* Initialize emulation hooks */
|
||||
|
||||
hr = platform_hook_init(
|
||||
&mai2_hook_cfg.platform,
|
||||
"SDEZ",
|
||||
"ACA1",
|
||||
mai2_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = sg_reader_hook_init(&mai2_hook_cfg.aime, 1, mai2_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = vfd_hook_init(2);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
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)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// TODO: The handling of the fake registry COM values is extraordinarly lazy
|
||||
// and I need to make a better method for tacking fake values onto common keys
|
||||
// that multiple modules may try to use.
|
||||
hr = led_hook_init(&mai2_hook_cfg.led);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = touch_hook_init(&mai2_hook_cfg.touch);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize Unity native plugin DLL hooks
|
||||
|
||||
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
||||
hooked earlier in the `mai2hook` initialization. */
|
||||
|
||||
unity_hook_init();
|
||||
|
||||
/* Initialize debug helpers */
|
||||
|
||||
spike_hook_init(L".\\segatools.ini");
|
||||
|
||||
dprintf("--- End mai2_pre_startup ---\n");
|
||||
|
||||
/* Jump to EXE start address */
|
||||
|
||||
return mai2_startup();
|
||||
|
||||
fail:
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (cause != DLL_PROCESS_ATTACH) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
mai2_hook_mod = mod;
|
||||
|
||||
hr = process_hijack_startup(mai2_pre_startup, &mai2_startup);
|
||||
|
||||
if (!SUCCEEDED(hr)) {
|
||||
dprintf("Failed to hijack process startup: %x\n", (int) hr);
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
147
mai2hook/io4.c
147
mai2hook/io4.c
|
@ -1,147 +0,0 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
|
||||
#include "mai2hook/mai2-dll.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
bool mai2_io_coin = false;
|
||||
uint16_t mai2_io_coins = 0;
|
||||
|
||||
static HRESULT mai2_io4_poll(void *ctx, struct io4_state *state);
|
||||
|
||||
static const struct io4_ops mai2_io4_ops = {
|
||||
.poll = mai2_io4_poll,
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return mai2_dll.init();
|
||||
}
|
||||
|
||||
static HRESULT mai2_io4_poll(void *ctx, struct io4_state *state)
|
||||
{
|
||||
uint8_t opbtn = 0;
|
||||
uint8_t player1 = 0;
|
||||
uint8_t player2 = 0;
|
||||
HRESULT hr;
|
||||
|
||||
assert(mai2_dll.poll != NULL);
|
||||
|
||||
hr = mai2_dll.poll(&opbtn, &player1, &player2);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (opbtn & MAI2_IO_OPBTN_TEST) {
|
||||
state->buttons[0] |= IO4_BUTTON_TEST;
|
||||
}
|
||||
|
||||
if (opbtn & MAI2_IO_OPBTN_SERVICE) {
|
||||
state->buttons[0] |= IO4_BUTTON_SERVICE;
|
||||
}
|
||||
|
||||
if (opbtn & MAI2_IO_P1_START) {
|
||||
state->buttons[0] |= 1 << 1;
|
||||
}
|
||||
|
||||
if (opbtn & MAI2_IO_P2_START) {
|
||||
state->buttons[1] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_1)) {
|
||||
state->buttons[0] |= 1 << 2;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_2)) {
|
||||
state->buttons[0] |= 1 << 3;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_3)) {
|
||||
state->buttons[0] |= 1 << 0;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_4)) {
|
||||
state->buttons[0] |= 1 << 15;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_5)) {
|
||||
state->buttons[0] |= 1 << 14;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_6)) {
|
||||
state->buttons[0] |= 1 << 13;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_7)) {
|
||||
state->buttons[0] |= 1 << 12;
|
||||
}
|
||||
|
||||
if (!(player1 & MAI2_IO_GAMEBTN_8)) {
|
||||
state->buttons[0] |= 1 << 11;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_1)) {
|
||||
state->buttons[1] |= 1 << 2;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_2)) {
|
||||
state->buttons[1] |= 1 << 3;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_3)) {
|
||||
state->buttons[1] |= 1 << 0;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_4)) {
|
||||
state->buttons[1] |= 1 << 15;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_5)) {
|
||||
state->buttons[1] |= 1 << 14;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_6)) {
|
||||
state->buttons[1] |= 1 << 13;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_7)) {
|
||||
state->buttons[1] |= 1 << 12;
|
||||
}
|
||||
|
||||
if (!(player2 & MAI2_IO_GAMEBTN_8)) {
|
||||
state->buttons[1] |= 1 << 11;
|
||||
}
|
||||
|
||||
|
||||
if (opbtn & MAI2_IO_OPBTN_COIN) {
|
||||
if (!mai2_io_coin) {
|
||||
mai2_io_coin = true;
|
||||
mai2_io_coins++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mai2_io_coin = false;
|
||||
}
|
||||
|
||||
state->chutes[0] = 128 + 256 * mai2_io_coins;
|
||||
|
||||
return S_OK;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
|
||||
HRESULT mai2_io4_hook_init(const struct io4_config *cfg);
|
210
mai2hook/led.c
210
mai2hook/led.c
|
@ -1,210 +0,0 @@
|
|||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hooklib/reg.h"
|
||||
#include "hooklib/uart.h"
|
||||
#include "hooklib/fdshark.h"
|
||||
|
||||
#include "mai2hook/led.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static HRESULT read_fake_com0(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT read_fake_com1(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT read_fake_com2(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT led_handle_irp(struct irp *irp);
|
||||
static HRESULT led0_handle_irp_locked(struct irp *irp);
|
||||
static HRESULT led1_handle_irp_locked(struct irp *irp);
|
||||
|
||||
static CRITICAL_SECTION led0_lock;
|
||||
static struct uart led0_uart;
|
||||
static uint8_t led0_written_bytes[520];
|
||||
static uint8_t led0_readable_bytes[520];
|
||||
|
||||
static CRITICAL_SECTION led1_lock;
|
||||
static struct uart led1_uart;
|
||||
static uint8_t led1_written_bytes[520];
|
||||
static uint8_t led1_readable_bytes[520];
|
||||
|
||||
static const struct reg_hook_val fake_com_keys[] = {
|
||||
{
|
||||
.name = L"\\Device\\RealTouchBoard0",
|
||||
.read = read_fake_com0,
|
||||
.type = REG_SZ,
|
||||
},{
|
||||
.name = L"\\Device\\RealTouchBoard1",
|
||||
.read = read_fake_com1,
|
||||
.type = REG_SZ,
|
||||
},{
|
||||
.name = L"\\Device\\RealLedBoard0",
|
||||
.read = read_fake_com2,
|
||||
.type = REG_SZ,
|
||||
},
|
||||
};
|
||||
|
||||
HRESULT led_hook_init(const struct led_config *cfg)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (!cfg->enable) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
dprintf("Mai2 LED: Init\n");
|
||||
InitializeCriticalSection(&led0_lock);
|
||||
InitializeCriticalSection(&led1_lock);
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"HARDWARE\\DEVICEMAP\\SERIALCOMM",
|
||||
fake_com_keys,
|
||||
_countof(fake_com_keys));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
uart_init(&led0_uart, 21);
|
||||
led0_uart.written.bytes = led0_written_bytes;
|
||||
led0_uart.written.nbytes = sizeof(led0_written_bytes);
|
||||
led0_uart.readable.bytes = led0_readable_bytes;
|
||||
led0_uart.readable.nbytes = sizeof(led0_readable_bytes);
|
||||
|
||||
uart_init(&led1_uart, 23);
|
||||
led1_uart.written.bytes = led1_written_bytes;
|
||||
led1_uart.written.nbytes = sizeof(led1_written_bytes);
|
||||
led1_uart.readable.bytes = led1_readable_bytes;
|
||||
led1_uart.readable.nbytes = sizeof(led1_readable_bytes);
|
||||
|
||||
return iohook_push_handler(led_handle_irp);
|
||||
}
|
||||
|
||||
static HRESULT read_fake_com0(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
//dprintf("Mai2 Touch: Read COM3 reg val\n");
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"COM3");
|
||||
}
|
||||
|
||||
static HRESULT read_fake_com1(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
//dprintf("Mai2 Touch: Read COM4 reg val\n");
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"COM4");
|
||||
}
|
||||
|
||||
static HRESULT read_fake_com2(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
//dprintf("Mai2 LED: Read COM20 reg val\n");
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"COM20");
|
||||
}
|
||||
|
||||
static HRESULT led_handle_irp(struct irp *irp)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
assert(irp != NULL);
|
||||
|
||||
if (uart_match_irp(&led0_uart, irp)) {
|
||||
EnterCriticalSection(&led0_lock);
|
||||
hr = led0_handle_irp_locked(irp);
|
||||
LeaveCriticalSection(&led0_lock);
|
||||
}
|
||||
else if (uart_match_irp(&led1_uart, irp)) {
|
||||
EnterCriticalSection(&led1_lock);
|
||||
hr = led1_handle_irp_locked(irp);
|
||||
LeaveCriticalSection(&led1_lock);
|
||||
}
|
||||
else {
|
||||
return iohook_invoke_next(irp);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
static HRESULT led0_handle_irp_locked(struct irp *irp)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (irp->op == IRP_OP_OPEN) {
|
||||
dprintf("Mai2 led0: Starting backend\n");
|
||||
//hr = mai2_dll.led_init();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 led: Backend error: %x\n", (int) hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = uart_handle_irp(&led0_uart, irp);
|
||||
|
||||
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
#if 0
|
||||
dprintf("TX0 Buffer:\n");
|
||||
dump_iobuf(&led0_uart.written);
|
||||
#endif
|
||||
//hr = led_frame_decode(&req, &led0_uart.written, 0);
|
||||
|
||||
if (hr != S_OK) {
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 led: Deframe error: %x\n", (int) hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//hr = led_req_dispatch(&req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 led: Processing error: %x\n", (int) hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT led1_handle_irp_locked(struct irp *irp)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (irp->op == IRP_OP_OPEN) {
|
||||
dprintf("Mai2 led1: Starting backend\n");
|
||||
//hr = mai2_dll.led_init();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 led: Backend error: %x\n", (int) hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = uart_handle_irp(&led0_uart, irp);
|
||||
|
||||
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
#if 0
|
||||
dprintf("TX0 Buffer:\n");
|
||||
dump_iobuf(&led0_uart.written);
|
||||
#endif
|
||||
//hr = led_frame_decode(&req, &led0_uart.written, 0);
|
||||
|
||||
if (hr != S_OK) {
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 led: Deframe error: %x\n", (int) hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//hr = led_req_dispatch(&req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 led: Processing error: %x\n", (int) hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct led_config {
|
||||
bool enable;
|
||||
};
|
||||
|
||||
HRESULT led_hook_init(const struct led_config *cfg);
|
|
@ -1,103 +0,0 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mai2hook/mai2-dll.h"
|
||||
|
||||
#include "util/dll-bind.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
const struct dll_bind_sym mai2_dll_syms[] = {
|
||||
{
|
||||
.sym = "mai2_io_init",
|
||||
.off = offsetof(struct mai2_dll, init),
|
||||
}, {
|
||||
.sym = "mai2_io_poll",
|
||||
.off = offsetof(struct mai2_dll, poll),
|
||||
},
|
||||
};
|
||||
|
||||
struct mai2_dll mai2_dll;
|
||||
|
||||
// Copypasta DLL binding and diagnostic message boilerplate.
|
||||
// Not much of this lends itself to being easily factored out. Also there
|
||||
// will be a lot of API-specific branching code here eventually as new API
|
||||
// versions get defined, so even though these functions all look the same
|
||||
// now this won't remain the case forever.
|
||||
|
||||
HRESULT mai2_dll_init(const struct mai2_dll_config *cfg, HINSTANCE self)
|
||||
{
|
||||
uint16_t (*get_api_version)(void);
|
||||
const struct dll_bind_sym *sym;
|
||||
HINSTANCE owned;
|
||||
HINSTANCE src;
|
||||
HRESULT hr;
|
||||
|
||||
assert(cfg != NULL);
|
||||
assert(self != NULL);
|
||||
|
||||
if (cfg->path[0] != L'\0') {
|
||||
owned = LoadLibraryW(cfg->path);
|
||||
|
||||
if (owned == NULL) {
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
dprintf("Mai2 IO: Failed to load IO DLL: %lx: %S\n",
|
||||
hr,
|
||||
cfg->path);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
dprintf("Mai2 IO: Using custom IO DLL: %S\n", cfg->path);
|
||||
src = owned;
|
||||
} else {
|
||||
owned = NULL;
|
||||
src = self;
|
||||
}
|
||||
|
||||
get_api_version = (void *) GetProcAddress(src, "mai2_io_get_api_version");
|
||||
|
||||
if (get_api_version != NULL) {
|
||||
mai2_dll.api_version = get_api_version();
|
||||
} else {
|
||||
mai2_dll.api_version = 0x0100;
|
||||
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");
|
||||
}
|
||||
|
||||
if (mai2_dll.api_version >= 0x0200) {
|
||||
hr = E_NOTIMPL;
|
||||
dprintf("Mai2 IO: Custom IO DLL implements an unsupported "
|
||||
"API version (%#04x). Please update Segatools.\n",
|
||||
mai2_dll.api_version);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
sym = mai2_dll_syms;
|
||||
hr = dll_bind(&mai2_dll, src, &sym, _countof(mai2_dll_syms));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (src != self) {
|
||||
dprintf("Mai2 IO: Custom IO DLL does not provide function "
|
||||
"\"%s\". Please contact your IO DLL's developer for "
|
||||
"further assistance.\n",
|
||||
sym->sym);
|
||||
|
||||
goto end;
|
||||
} else {
|
||||
dprintf("Internal error: could not reflect \"%s\"\n", sym->sym);
|
||||
}
|
||||
}
|
||||
|
||||
owned = NULL;
|
||||
|
||||
end:
|
||||
if (owned != NULL) {
|
||||
FreeLibrary(owned);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "mai2io/mai2io.h"
|
||||
|
||||
struct mai2_dll {
|
||||
uint16_t api_version;
|
||||
HRESULT (*init)(void);
|
||||
HRESULT (*poll)(uint8_t *opbtn, uint8_t *p1, uint8_t *p2);
|
||||
};
|
||||
|
||||
struct mai2_dll_config {
|
||||
wchar_t path[MAX_PATH];
|
||||
};
|
||||
|
||||
extern struct mai2_dll mai2_dll;
|
||||
|
||||
HRESULT mai2_dll_init(const struct mai2_dll_config *cfg, HINSTANCE self);
|
|
@ -1,22 +0,0 @@
|
|||
LIBRARY mai2hook
|
||||
|
||||
EXPORTS
|
||||
CreateDXGIFactory
|
||||
CreateDXGIFactory1
|
||||
CreateDXGIFactory2
|
||||
D3D11CreateDevice
|
||||
D3D11CreateDeviceAndSwapChain
|
||||
Direct3DCreate9
|
||||
aime_io_get_api_version
|
||||
aime_io_init
|
||||
aime_io_led_set_color
|
||||
aime_io_nfc_get_aime_id
|
||||
aime_io_nfc_get_felica_id
|
||||
aime_io_nfc_poll
|
||||
amDllVideoClose @2
|
||||
amDllVideoGetVBiosVersion @4
|
||||
amDllVideoOpen @1
|
||||
amDllVideoSetResolution @3
|
||||
mai2_io_get_api_version
|
||||
mai2_io_init
|
||||
mai2_io_poll
|
|
@ -1,37 +0,0 @@
|
|||
shared_library(
|
||||
'mai2hook',
|
||||
name_prefix : '',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
vs_module_defs : 'mai2hook.def',
|
||||
c_pch : '../precompiled.h',
|
||||
dependencies : [
|
||||
capnhook.get_variable('hook_dep'),
|
||||
capnhook.get_variable('hooklib_dep'),
|
||||
xinput_lib,
|
||||
],
|
||||
link_with : [
|
||||
aimeio_lib,
|
||||
board_lib,
|
||||
gfxhook_lib,
|
||||
hooklib_lib,
|
||||
mai2io_lib,
|
||||
platform_lib,
|
||||
util_lib,
|
||||
],
|
||||
sources : [
|
||||
'config.c',
|
||||
'config.h',
|
||||
'dllmain.c',
|
||||
'led.c',
|
||||
'led.h',
|
||||
'io4.c',
|
||||
'io4.h',
|
||||
'mai2-dll.c',
|
||||
'mai2-dll.h',
|
||||
'touch.c',
|
||||
'touch.h',
|
||||
'unity.h',
|
||||
'unity.c',
|
||||
],
|
||||
)
|
237
mai2hook/touch.c
237
mai2hook/touch.c
|
@ -1,237 +0,0 @@
|
|||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hooklib/reg.h"
|
||||
#include "hooklib/uart.h"
|
||||
#include "hooklib/fdshark.h"
|
||||
|
||||
#include "mai2hook/touch.h"
|
||||
#include "mai2hook/mai2-dll.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
#include "util/dump.h"
|
||||
|
||||
const char CMD_START = '{';
|
||||
const char CMD_END = '}';
|
||||
const char RESP_START = '(';
|
||||
const char RESP_END = ')';
|
||||
const char BLANK = '@';
|
||||
|
||||
// Commands with parameters
|
||||
const char CMD_RATIO[1] = "r";
|
||||
const char CMD_SENS[1] = "k";
|
||||
const char CMD_SENS_CHECK[2] = "th";
|
||||
|
||||
// Commands that never change
|
||||
const char CMD_RESET[7] = "{RSET}"; // Reset board to default state
|
||||
const char CMD_STAT[7] = "{STAT}"; // Start sending touch state
|
||||
const char CMD_HALT[7] = "{HALT}"; // Stop sending touch state
|
||||
const char RSP_ANY[6] = "(0000)"; // Stop sending touch state
|
||||
|
||||
static HRESULT read_fake_com0(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT read_fake_com1(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT read_fake_com2(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT touch_handle_irp(struct irp *irp);
|
||||
static HRESULT touch0_handle_irp_locked(struct irp *irp);
|
||||
static HRESULT touch1_handle_irp_locked(struct irp *irp);
|
||||
static HRESULT touch_cmd_dispatch(char* cmd, struct iobuf *dest, uint8_t side);
|
||||
|
||||
bool touch0_auto = false;
|
||||
bool touch1_auto = false;
|
||||
|
||||
static CRITICAL_SECTION touch0_lock;
|
||||
static struct uart touch0_uart;
|
||||
static uint8_t touch0_written_bytes[520];
|
||||
static uint8_t touch0_readable_bytes[520];
|
||||
|
||||
static CRITICAL_SECTION touch1_lock;
|
||||
static struct uart touch1_uart;
|
||||
static uint8_t touch1_written_bytes[520];
|
||||
static uint8_t touch1_readable_bytes[520];
|
||||
|
||||
static const struct reg_hook_val fake_com_keys[] = {
|
||||
{
|
||||
.name = L"\\Device\\RealTouchBoard0",
|
||||
.read = read_fake_com0,
|
||||
.type = REG_SZ,
|
||||
},{
|
||||
.name = L"\\Device\\RealTouchBoard1",
|
||||
.read = read_fake_com1,
|
||||
.type = REG_SZ,
|
||||
},{
|
||||
.name = L"\\Device\\RealLedBoard0",
|
||||
.read = read_fake_com2,
|
||||
.type = REG_SZ,
|
||||
},
|
||||
};
|
||||
|
||||
HRESULT touch_hook_init(const struct touch_config *cfg)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (!cfg->enable) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
dprintf("Mai2 touch: Init\n");
|
||||
InitializeCriticalSection(&touch0_lock);
|
||||
InitializeCriticalSection(&touch1_lock);
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"HARDWARE\\DEVICEMAP\\SERIALCOMM",
|
||||
fake_com_keys,
|
||||
_countof(fake_com_keys));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
uart_init(&touch0_uart, 3);
|
||||
touch0_uart.written.bytes = touch0_written_bytes;
|
||||
touch0_uart.written.nbytes = sizeof(touch0_written_bytes);
|
||||
touch0_uart.readable.bytes = touch0_readable_bytes;
|
||||
touch0_uart.readable.nbytes = sizeof(touch0_readable_bytes);
|
||||
|
||||
uart_init(&touch1_uart, 4);
|
||||
touch1_uart.written.bytes = touch1_written_bytes;
|
||||
touch1_uart.written.nbytes = sizeof(touch1_written_bytes);
|
||||
touch1_uart.readable.bytes = touch1_readable_bytes;
|
||||
touch1_uart.readable.nbytes = sizeof(touch1_readable_bytes);
|
||||
|
||||
return iohook_push_handler(touch_handle_irp);
|
||||
}
|
||||
|
||||
static HRESULT read_fake_com0(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
// dprintf("Mai2 Touch: Read COM3 reg val\n");
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"COM3");
|
||||
}
|
||||
|
||||
static HRESULT read_fake_com1(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
// dprintf("Mai2 Touch: Read COM4 reg val\n");
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"COM4");
|
||||
}
|
||||
|
||||
static HRESULT read_fake_com2(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
// dprintf("Mai2 LED: Read COM20 reg val\n");
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"COM20");
|
||||
}
|
||||
|
||||
static HRESULT touch_handle_irp(struct irp *irp)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
assert(irp != NULL);
|
||||
|
||||
if (uart_match_irp(&touch0_uart, irp)) {
|
||||
EnterCriticalSection(&touch0_lock);
|
||||
hr = touch0_handle_irp_locked(irp);
|
||||
LeaveCriticalSection(&touch0_lock);
|
||||
}
|
||||
else if (uart_match_irp(&touch1_uart, irp)) {
|
||||
EnterCriticalSection(&touch1_lock);
|
||||
hr = touch1_handle_irp_locked(irp);
|
||||
LeaveCriticalSection(&touch1_lock);
|
||||
}
|
||||
else {
|
||||
return iohook_invoke_next(irp);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT touch0_handle_irp_locked(struct irp *irp)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (irp->op == IRP_OP_OPEN) {
|
||||
dprintf("Mai2 touch0: Starting backend\n");
|
||||
//hr = mai2_dll.touch_init();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 touch0: Backend error: %x\n", (int) hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = uart_handle_irp(&touch0_uart, irp);
|
||||
|
||||
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
#if 0
|
||||
dprintf("touch0 Buffer:\n");
|
||||
dump_iobuf(&touch0_uart.written);
|
||||
#endif
|
||||
hr = touch_cmd_dispatch((char*)touch0_uart.written.bytes, &touch0_uart.readable, 0);
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 touch0: Dispatch failed %08lX\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
touch0_uart.written.pos = 0;
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT touch1_handle_irp_locked(struct irp *irp)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (irp->op == IRP_OP_OPEN) {
|
||||
dprintf("Mai2 touch1: Starting backend\n");
|
||||
//hr = mai2_dll.touch_init();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 touch1: Backend error: %x\n", (int) hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = uart_handle_irp(&touch1_uart, irp);
|
||||
|
||||
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
#if 0
|
||||
dprintf("touch1 Buffer:\n");
|
||||
dump_iobuf(&touch0_uart.written);
|
||||
#endif
|
||||
|
||||
hr = touch_cmd_dispatch((char*)touch1_uart.written.bytes, &touch1_uart.readable, 1);
|
||||
if (FAILED(hr)) {
|
||||
dprintf("Mai2 touch1: Dispatch failed %08lX\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
touch1_uart.written.pos = 0;
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT touch_cmd_dispatch(char* cmd, struct iobuf *dest, uint8_t side)
|
||||
{
|
||||
if (!strcmp(cmd, CMD_RESET)) {
|
||||
dprintf("Mai2 touch%d: Reset\n", side);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, CMD_HALT)) {
|
||||
dprintf("Mai2 touch%d: Halt\n", side);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
dprintf("Mai2 touch%d: Unknow %s\n", side, cmd);
|
||||
return S_OK;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct touch_config {
|
||||
bool enable;
|
||||
};
|
||||
|
||||
HRESULT touch_hook_init(const struct touch_config *cfg);
|
116
mai2hook/unity.c
116
mai2hook/unity.c
|
@ -1,116 +0,0 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "hooklib/dll.h"
|
||||
#include "hooklib/path.h"
|
||||
#include "hooklib/reg.h"
|
||||
#include "hook/procaddr.h"
|
||||
#include "hooklib/serial.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void dll_hook_insert_hooks(HMODULE target);
|
||||
|
||||
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name);
|
||||
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
|
||||
static HMODULE WINAPI my_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags);
|
||||
static HMODULE (WINAPI *next_LoadLibraryExW)(const wchar_t *name, HANDLE hFile, DWORD dwFlags);
|
||||
|
||||
static const struct hook_symbol unity_kernel32_syms[] = {
|
||||
{
|
||||
.name = "LoadLibraryW",
|
||||
.patch = my_LoadLibraryW,
|
||||
.link = (void **) &next_LoadLibraryW,
|
||||
},{
|
||||
.name = "LoadLibraryExW",
|
||||
.patch = my_LoadLibraryExW,
|
||||
.link = (void **) &next_LoadLibraryExW,
|
||||
}
|
||||
};
|
||||
|
||||
static const wchar_t *target_modules[] = {
|
||||
L"mono-2.0-bdwgc.dll",
|
||||
L"cri_ware_unity.dll",
|
||||
};
|
||||
|
||||
static const size_t target_modules_len = _countof(target_modules);
|
||||
|
||||
void unity_hook_init(void)
|
||||
{
|
||||
dll_hook_insert_hooks(NULL);
|
||||
}
|
||||
|
||||
static void dll_hook_insert_hooks(HMODULE target)
|
||||
{
|
||||
hook_table_apply(
|
||||
target,
|
||||
"kernel32.dll",
|
||||
unity_kernel32_syms,
|
||||
_countof(unity_kernel32_syms));
|
||||
}
|
||||
|
||||
static HMODULE WINAPI my_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags)
|
||||
{
|
||||
//dprintf("Unity: LoadLibraryExW %ls\n", name);
|
||||
return my_LoadLibraryW(name);
|
||||
}
|
||||
|
||||
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name)
|
||||
{
|
||||
const wchar_t *name_end;
|
||||
const wchar_t *target_module;
|
||||
bool already_loaded;
|
||||
HMODULE result;
|
||||
size_t name_len;
|
||||
size_t target_module_len;
|
||||
|
||||
if (name == NULL) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if the module is already loaded
|
||||
already_loaded = GetModuleHandleW(name) != NULL;
|
||||
|
||||
// Must call the next handler so the DLL reference count is incremented
|
||||
result = next_LoadLibraryW(name);
|
||||
|
||||
if (!already_loaded && result != NULL) {
|
||||
name_len = wcslen(name);
|
||||
|
||||
for (size_t i = 0; i < target_modules_len; i++) {
|
||||
target_module = target_modules[i];
|
||||
target_module_len = wcslen(target_module);
|
||||
|
||||
// Check if the newly loaded library is at least the length of
|
||||
// the name of the target module
|
||||
if (name_len < target_module_len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
name_end = &name[name_len - target_module_len];
|
||||
|
||||
// Check if the name of the newly loaded library is one of the
|
||||
// modules the path hooks should be injected into
|
||||
if (_wcsicmp(name_end, target_module) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dprintf("Unity: Loaded %S\n", target_module);
|
||||
|
||||
dll_hook_insert_hooks(result);
|
||||
path_hook_insert_hooks(result);
|
||||
reg_hook_insert_hooks(result);
|
||||
proc_addr_insert_hooks(result);
|
||||
serial_hook_apply_hooks(result);
|
||||
iohook_apply_hooks(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
void unity_hook_init(void);
|
|
@ -1,46 +0,0 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mai2io/config.h"
|
||||
|
||||
static const int mai2_io_1p_default[] = {'W', 'E', 'D', 'C', 'X', 'Z', 'A', 'Q'};
|
||||
static const int mai2_io_2p_default[] = {0x68, 0x69, 0x66, 0x63, 0x62, 0x61, 0x64, 0x67};
|
||||
|
||||
void mai2_io_config_load(
|
||||
struct mai2_io_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
wchar_t key[240];
|
||||
int i;
|
||||
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", VK_DELETE, filename);
|
||||
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", VK_END, filename);
|
||||
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", VK_INSERT, filename);
|
||||
cfg->vk_p1_start = GetPrivateProfileIntW(L"io4", L"p1_start", '1', filename);
|
||||
cfg->vk_p2_start = GetPrivateProfileIntW(L"io4", L"p2_start", '2', filename);
|
||||
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
swprintf_s(key, _countof(key), L"1p_btn%i", i + 1);
|
||||
cfg->vk_p1_btn[i] = GetPrivateProfileIntW(
|
||||
L"button",
|
||||
key,
|
||||
mai2_io_1p_default[i],
|
||||
filename);
|
||||
}
|
||||
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
swprintf_s(key, _countof(key), L"2p_btn%i", i + 1);
|
||||
cfg->vk_p2_btn[i] = GetPrivateProfileIntW(
|
||||
L"button",
|
||||
key,
|
||||
mai2_io_2p_default[i],
|
||||
filename);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct mai2_io_config {
|
||||
uint8_t vk_test;
|
||||
uint8_t vk_service;
|
||||
uint8_t vk_coin;
|
||||
uint8_t vk_p1_start;
|
||||
uint8_t vk_p2_start;
|
||||
uint8_t vk_p1_btn[8];
|
||||
uint8_t vk_p2_btn[8];
|
||||
};
|
||||
|
||||
void mai2_io_config_load(
|
||||
struct mai2_io_config *cfg,
|
||||
const wchar_t *filename);
|
|
@ -1,83 +0,0 @@
|
|||
#include <windows.h>
|
||||
#include <xinput.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mai2io/mai2io.h"
|
||||
#include "mai2io/config.h"
|
||||
|
||||
static struct mai2_io_config mai2_io_cfg;
|
||||
|
||||
uint16_t mai2_io_get_api_version(void)
|
||||
{
|
||||
return 0x0100;
|
||||
}
|
||||
|
||||
HRESULT mai2_io_init(void)
|
||||
{
|
||||
mai2_io_config_load(&mai2_io_cfg, L".\\segatools.ini");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT mai2_io_poll(uint8_t *opbtn, uint8_t *player1, uint8_t *player2)
|
||||
{
|
||||
uint8_t opts = 0;
|
||||
uint8_t p1 = 0;
|
||||
uint8_t p2 = 0;
|
||||
|
||||
if (GetAsyncKeyState(mai2_io_cfg.vk_test) & 0x8000) {
|
||||
opts |= MAI2_IO_OPBTN_TEST;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_service) & 0x8000) {
|
||||
opts |= MAI2_IO_OPBTN_SERVICE;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_coin) & 0x8000) {
|
||||
opts |= MAI2_IO_OPBTN_COIN;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_start) & 0x8000) {
|
||||
opts |= MAI2_IO_P1_START;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_start) & 0x8000) {
|
||||
opts |= MAI2_IO_P2_START;
|
||||
}
|
||||
|
||||
*opbtn = opts;
|
||||
|
||||
if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[0]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_1;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[1]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_2;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[2]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_3;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[3]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_4;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[4]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_5;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[5]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_6;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[6]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_7;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p1_btn[7]) & 0x8000) {
|
||||
p1 |= MAI2_IO_GAMEBTN_8;
|
||||
}
|
||||
|
||||
*player1 = p1;
|
||||
|
||||
if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[0]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_1;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[1]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_2;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[2]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_3;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[3]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_4;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[4]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_5;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[5]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_6;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[6]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_7;
|
||||
}if (GetAsyncKeyState(mai2_io_cfg.vk_p2_btn[7]) & 0x8000) {
|
||||
p2 |= MAI2_IO_GAMEBTN_8;
|
||||
}
|
||||
|
||||
*player2 = p2;
|
||||
return S_OK;
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
MAI2_IO_OPBTN_TEST = 0x01,
|
||||
MAI2_IO_OPBTN_SERVICE = 0x02,
|
||||
MAI2_IO_OPBTN_COIN = 0x04,
|
||||
MAI2_IO_P1_START = 0x08,
|
||||
MAI2_IO_P2_START = 0x10,
|
||||
};
|
||||
|
||||
enum {
|
||||
MAI2_IO_GAMEBTN_1 = 0x01,
|
||||
MAI2_IO_GAMEBTN_2 = 0x02,
|
||||
MAI2_IO_GAMEBTN_3 = 0x04,
|
||||
MAI2_IO_GAMEBTN_4 = 0x08,
|
||||
MAI2_IO_GAMEBTN_5 = 0x10,
|
||||
MAI2_IO_GAMEBTN_6 = 0x20,
|
||||
MAI2_IO_GAMEBTN_7 = 0x40,
|
||||
MAI2_IO_GAMEBTN_8 = 0x80,
|
||||
};
|
||||
|
||||
/* Get the version of the Mai2 IO API that this DLL supports. This
|
||||
function should return a positive 16-bit integer, where the high byte is
|
||||
the major version and the low byte is the minor version (as defined by the
|
||||
Semantic Versioning standard).
|
||||
|
||||
The latest API version as of this writing is 0x0100. */
|
||||
|
||||
uint16_t mai2_io_get_api_version(void);
|
||||
|
||||
/* Initialize the IO DLL. This is the second function that will be called on
|
||||
your DLL, after mai2_io_get_api_version.
|
||||
|
||||
All subsequent calls to this API may originate from arbitrary threads.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
HRESULT mai2_io_init(void);
|
||||
|
||||
/* Send any queued outputs (of which there are currently none, though this may
|
||||
change in subsequent API versions) and retrieve any new inputs.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
HRESULT mai2_io_poll(uint8_t *opbtn, uint8_t *player1, uint8_t *player2);
|
|
@ -1,16 +0,0 @@
|
|||
mai2io_lib = static_library(
|
||||
'mai2io',
|
||||
name_prefix : '',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
c_pch : '../precompiled.h',
|
||||
dependencies : [
|
||||
xinput_lib,
|
||||
],
|
||||
sources : [
|
||||
'mai2io.c',
|
||||
'mai2io.h',
|
||||
'config.c',
|
||||
'config.h',
|
||||
],
|
||||
)
|
|
@ -61,7 +61,6 @@ subdir('idzio')
|
|||
subdir('mu3io')
|
||||
subdir('mercuryio')
|
||||
subdir('cxbio')
|
||||
subdir('mai2io')
|
||||
|
||||
subdir('chunihook')
|
||||
subdir('divahook')
|
||||
|
@ -71,4 +70,3 @@ subdir('minihook')
|
|||
subdir('mu3hook')
|
||||
subdir('mercuryhook')
|
||||
subdir('cxbhook')
|
||||
subdir('mai2hook')
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "platform/clock.h"
|
||||
#include "platform/config.h"
|
||||
#include "platform/dns.h"
|
||||
#include "platform/epay.h"
|
||||
#include "platform/hwmon.h"
|
||||
#include "platform/hwreset.h"
|
||||
#include "platform/misc.h"
|
||||
|
@ -31,7 +30,6 @@ void platform_config_load(struct platform_config *cfg, const wchar_t *filename)
|
|||
amvideo_config_load(&cfg->amvideo, filename);
|
||||
clock_config_load(&cfg->clock, filename);
|
||||
dns_config_load(&cfg->dns, filename);
|
||||
epay_config_load(&cfg->epay, filename);
|
||||
hwmon_config_load(&cfg->hwmon, filename);
|
||||
hwreset_config_load(&cfg->hwreset, filename);
|
||||
misc_config_load(&cfg->misc, filename);
|
||||
|
@ -319,10 +317,3 @@ void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename)
|
|||
filename);
|
||||
}
|
||||
|
||||
void epay_config_load(struct epay_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"epay", L"enable", 1, filename);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "platform/amvideo.h"
|
||||
#include "platform/clock.h"
|
||||
#include "platform/dns.h"
|
||||
#include "platform/epay.h"
|
||||
#include "platform/hwmon.h"
|
||||
#include "platform/hwreset.h"
|
||||
#include "platform/misc.h"
|
||||
|
@ -26,7 +25,6 @@ void platform_config_load(
|
|||
void amvideo_config_load(struct amvideo_config *cfg, const wchar_t *filename);
|
||||
void clock_config_load(struct clock_config *cfg, const wchar_t *filename);
|
||||
void dns_config_load(struct dns_config *cfg, const wchar_t *filename);
|
||||
void epay_config_load(struct epay_config *cfg, const wchar_t *filename);
|
||||
void hwmon_config_load(struct hwmon_config *cfg, const wchar_t *filename);
|
||||
void hwreset_config_load(struct hwreset_config *cfg, const wchar_t *filename);
|
||||
void misc_config_load(struct misc_config *cfg, const wchar_t *filename);
|
||||
|
|
|
@ -64,19 +64,6 @@ HRESULT dns_platform_hook_init(const struct dns_config *cfg)
|
|||
return hr;
|
||||
}
|
||||
|
||||
// Epay urls
|
||||
hr = dns_hook_push(L"api-aime.am-all.net", cfg->startup);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = dns_hook_push(L"tasms-api-basis.thincacloud.com", cfg->startup);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// if your ISP resolves bad domains, it will kill the network. These 2
|
||||
// *cannot* resolve
|
||||
|
||||
|
|
335
platform/epay.c
335
platform/epay.c
|
@ -1,335 +0,0 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/reg.h"
|
||||
|
||||
#include "platform/epay.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static HRESULT misc_read_thinca_adapter(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_ca_loc(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_ca_client_loc(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_network_timeout(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_pattern0(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_network_timeout0(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_pattern1(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_network_timeout1(void *bytes, uint32_t *nbytes);
|
||||
|
||||
static uint64_t thinca_initialize(struct thinca_impl * self, uint64_t val);
|
||||
static uint64_t thinca_dispose(struct thinca_impl * self);
|
||||
static uint64_t thinca_set_resource(struct thinca_impl * self, char * res);
|
||||
static uint64_t thinca_set_pay_log(struct thinca_impl * self, uint64_t val, char * log, uint64_t val2, const char * size_lim);
|
||||
static uint64_t thinca_set_client_log(struct thinca_impl * self, uint64_t val, char * log);
|
||||
static uint64_t thinca_set_client_cfg(struct thinca_impl * self, char * log, uint64_t val);
|
||||
static uint64_t thinca_set_goods_code(struct thinca_impl * self, char * code);
|
||||
static uint64_t thinca_set_evt_handler(struct thinca_impl * self, void* handler);
|
||||
static uint64_t thinca_set_cert(struct thinca_impl * self, char * cert, uint64_t val);
|
||||
static uint64_t thinca_set_serial(struct thinca_impl * self, char * cert);
|
||||
static uint64_t thinca_check_deal(struct thinca_impl * self, void* deal);
|
||||
static uint64_t thinca_cancel(struct thinca_impl * self);
|
||||
static uint64_t thinca_select(struct thinca_impl * self);
|
||||
static uint64_t thinca_unk(struct thinca_impl * self, uint64_t val);
|
||||
static void thinca_unk8(struct thinca_impl * self);
|
||||
|
||||
static uint64_t my_ThincaPaymentGetVersion();
|
||||
static uint64_t (*next_ThincaPaymentGetVersion)();
|
||||
|
||||
static struct thinca_main* my_ThincaPaymentGetInstance(uint64_t ver);
|
||||
static struct thinca_main* (*next_ThincaPaymentGetInstance)(uint64_t ver);
|
||||
|
||||
static struct thinca_main* thinca_stub;
|
||||
|
||||
static const struct reg_hook_val epay_adapter_keys[] = {
|
||||
{
|
||||
.name = L"TfpsAimeRwAdapter",
|
||||
.read = misc_read_thinca_adapter,
|
||||
.type = REG_SZ,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct reg_hook_val epay_tcap_keys[] = {
|
||||
{
|
||||
.name = L"CaLocation",
|
||||
.read = misc_read_ca_loc,
|
||||
.type = REG_SZ,
|
||||
},
|
||||
{
|
||||
.name = L"ThincaTcapClientPath",
|
||||
.read = misc_read_ca_client_loc,
|
||||
.type = REG_SZ,
|
||||
},
|
||||
{
|
||||
.name = L"ClientNetworkTimeout",
|
||||
.read = misc_read_network_timeout,
|
||||
.type = REG_DWORD,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct reg_hook_val epay_tcap_url0_keys[] = {
|
||||
{
|
||||
.name = L"Pattern",
|
||||
.read = misc_read_pattern0,
|
||||
.type = REG_SZ,
|
||||
},
|
||||
{
|
||||
.name = L"ClientNetworkTimeout",
|
||||
.read = misc_read_network_timeout0,
|
||||
.type = REG_DWORD,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct reg_hook_val epay_tcap_url1_keys[] = {
|
||||
{
|
||||
.name = L"Pattern",
|
||||
.read = misc_read_pattern1,
|
||||
.type = REG_SZ,
|
||||
},
|
||||
{
|
||||
.name = L"ClientNetworkTimeout",
|
||||
.read = misc_read_network_timeout1,
|
||||
.type = REG_DWORD,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hook_symbol epay_syms[] = {
|
||||
{
|
||||
.name = "ThincaPaymentGetVersion",
|
||||
.patch = my_ThincaPaymentGetVersion,
|
||||
.link = (void **) &next_ThincaPaymentGetVersion,
|
||||
.ordinal = 1,
|
||||
},
|
||||
{
|
||||
.name = "__imp_ThincaPaymentGetInstance",
|
||||
.patch = my_ThincaPaymentGetInstance,
|
||||
.link = (void **) &next_ThincaPaymentGetInstance,
|
||||
.ordinal = 2,
|
||||
},
|
||||
{
|
||||
.name = "ThincaPaymentGetInstance",
|
||||
.patch = my_ThincaPaymentGetInstance,
|
||||
.link = (void **) &next_ThincaPaymentGetInstance,
|
||||
.ordinal = 2,
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT epay_hook_init(const struct epay_config *cfg) {
|
||||
HRESULT hr;
|
||||
assert(cfg != NULL);
|
||||
|
||||
if (!cfg->enable) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\TFPaymentService\\ThincaRwAdapter",
|
||||
epay_adapter_keys,
|
||||
_countof(epay_adapter_keys));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\TFPaymentService\\ThincaTcapClient",
|
||||
epay_tcap_keys,
|
||||
_countof(epay_tcap_keys));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\TFPaymentService\\ThincaTcapClient\\URL0",
|
||||
epay_tcap_url0_keys,
|
||||
_countof(epay_tcap_url0_keys));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\TFPaymentService\\ThincaTcapClient\\URL1",
|
||||
epay_tcap_url1_keys,
|
||||
_countof(epay_tcap_url1_keys));
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"ThincaPayment.dll",
|
||||
epay_syms,
|
||||
_countof(epay_syms));
|
||||
|
||||
thinca_stub = (struct thinca_main *)malloc(sizeof(struct thinca_main));
|
||||
thinca_stub->impl1 = (struct thinca_impl *)malloc(sizeof(struct thinca_impl));
|
||||
|
||||
thinca_stub->impl1->unk8 = thinca_unk8;
|
||||
thinca_stub->impl1->initialize = thinca_initialize;
|
||||
thinca_stub->impl1->dispose = thinca_dispose;
|
||||
thinca_stub->impl1->setResource = thinca_set_resource;
|
||||
thinca_stub->impl1->setThincaPaymentLog = thinca_set_pay_log;
|
||||
thinca_stub->impl1->setThincaEventInterface = thinca_set_evt_handler;
|
||||
thinca_stub->impl1->setIcasClientLog = thinca_set_client_log;
|
||||
thinca_stub->impl1->setIcasClientConfig = thinca_set_client_cfg;
|
||||
thinca_stub->impl1->setGoodsCode = thinca_set_goods_code;
|
||||
thinca_stub->impl1->setTerminalSerial = thinca_set_serial;
|
||||
thinca_stub->impl1->setClientCertificate = thinca_set_cert;
|
||||
thinca_stub->impl1->checkDeal = thinca_check_deal;
|
||||
thinca_stub->impl1->cancelRequest = thinca_cancel;
|
||||
thinca_stub->impl1->selectButton = thinca_select;
|
||||
thinca_stub->impl1->unk220 = thinca_unk;
|
||||
thinca_stub->impl1->unk228 = thinca_unk;
|
||||
|
||||
dprintf("Epay: Init\n");
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT misc_read_thinca_adapter(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"aime_rw_adapterMD.dll");
|
||||
}
|
||||
|
||||
static HRESULT misc_read_ca_loc(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"ca.pem");
|
||||
}
|
||||
|
||||
static HRESULT misc_read_ca_client_loc(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"thincatcapclient.dll");
|
||||
}
|
||||
|
||||
static HRESULT misc_read_network_timeout(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_u32(bytes, nbytes, 20000);
|
||||
}
|
||||
|
||||
static HRESULT misc_read_pattern0(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L".*\\.jsp");
|
||||
}
|
||||
|
||||
static HRESULT misc_read_network_timeout0(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_u32(bytes, nbytes, 5000);
|
||||
}
|
||||
|
||||
static HRESULT misc_read_pattern1(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L".*(closing|remove).*");
|
||||
}
|
||||
|
||||
static HRESULT misc_read_network_timeout1(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_u32(bytes, nbytes, 60000);
|
||||
}
|
||||
|
||||
static uint64_t thinca_initialize(struct thinca_impl * self, uint64_t val)
|
||||
{
|
||||
dprintf("Epay: Thinca Initialize v%I64X\n", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_dispose(struct thinca_impl * self)
|
||||
{
|
||||
dprintf("Epay: Thinca Dispose\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_resource(struct thinca_impl * self, char * res)
|
||||
{
|
||||
dprintf("Epay: Thinca Set Resource %s\n", res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_pay_log(struct thinca_impl * self, uint64_t val, char * log, uint64_t val2, const char * size_lim)
|
||||
{
|
||||
dprintf("Epay: Thinca Set Paylog %lld | %s | %lld | %s\n", val, log, val2, size_lim);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_client_log(struct thinca_impl * self, uint64_t val, char * log)
|
||||
{
|
||||
dprintf("Epay: Thinca Set ICAS Client log %lld | %s\n", val, log);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_client_cfg(struct thinca_impl * self, char * log, uint64_t val)
|
||||
{
|
||||
dprintf("Epay: Thinca Set ICAS Client Config %s | %lld\n", log, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_goods_code(struct thinca_impl * self, char * code)
|
||||
{
|
||||
dprintf("Epay: Thinca Set Goods Code %s\n", code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_evt_handler(struct thinca_impl * self, void* handler)
|
||||
{
|
||||
dprintf("Epay: Thinca Set Event Handler %p\n", handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_cert(struct thinca_impl * self, char * cert, uint64_t val)
|
||||
{
|
||||
dprintf("Epay: Thinca Set Client Cert %s | %lld\n", cert, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_set_serial(struct thinca_impl * self, char * cert)
|
||||
{
|
||||
dprintf("Epay: Thinca Set Terminal Serial %s\n", cert);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_check_deal(struct thinca_impl * self, void* deal)
|
||||
{
|
||||
dprintf("Epay: Thinca Check Deal %p\n", deal);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_cancel(struct thinca_impl * self)
|
||||
{
|
||||
dprintf("Epay: Thinca Cancel\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_select(struct thinca_impl * self)
|
||||
{
|
||||
dprintf("Epay: Thinca Select\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t thinca_unk(struct thinca_impl * self, uint64_t val)
|
||||
{
|
||||
dprintf("Epay: Thinca Unknown 220/228 %lld\n", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void thinca_unk8(struct thinca_impl * self)
|
||||
{
|
||||
dprintf("Epay: Thinca Unknown 8\n");
|
||||
}
|
||||
|
||||
static uint64_t my_ThincaPaymentGetVersion()
|
||||
{
|
||||
return 0x1040B00;
|
||||
}
|
||||
|
||||
static struct thinca_main* my_ThincaPaymentGetInstance(uint64_t ver)
|
||||
{
|
||||
dprintf("Epay: my_ThincaPaymentGetInstance hit!\n");
|
||||
return thinca_stub;
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct epay_config {
|
||||
bool enable;
|
||||
};
|
||||
|
||||
/* The functions in these structs are how clients like amdaemon interface
|
||||
* with thinca. We can simply replace these functions with our own stubs
|
||||
* to bypass errors and such. Currently this DOES NOT allow for epay, and
|
||||
* trying to do so will most likely just lead to misery. My goal isn't to
|
||||
* reimplement epay, just to give amdaemon SOMETHING so we can boot properly.
|
||||
*/
|
||||
struct thinca_impl {
|
||||
uint64_t* unk0;
|
||||
void (*unk8)(struct thinca_impl *);
|
||||
uint64_t (*initialize)(struct thinca_impl *, uint64_t);
|
||||
uint64_t (*dispose)(struct thinca_impl *);
|
||||
uint64_t (*setResource)(struct thinca_impl *, char *);
|
||||
uint64_t (*setThincaPaymentLog)(struct thinca_impl *, uint64_t, char *, uint64_t, const char *);
|
||||
uint64_t (*setIcasClientLog)(struct thinca_impl *, uint64_t, char *);
|
||||
uint64_t (*setIcasClientConfig)(struct thinca_impl *, char *, uint64_t);
|
||||
uint64_t* unk40;
|
||||
uint64_t* unk48;
|
||||
uint64_t (*setClientCertificate)(struct thinca_impl *, char *, uint64_t);
|
||||
uint64_t (*setTerminalSerial)(struct thinca_impl *, char *);
|
||||
uint64_t (*setGoodsCode)(struct thinca_impl *, char *);
|
||||
uint64_t unk68;
|
||||
uint64_t (*setThincaEventInterface)(struct thinca_impl *, void*); // probably a struct
|
||||
uint64_t unkGap78[7];
|
||||
uint64_t (*checkDeal)(struct thinca_impl *, void *); // probably a struct
|
||||
uint64_t unkGapB8[41];
|
||||
uint64_t (*cancelRequest)(struct thinca_impl *);
|
||||
uint64_t (*selectButton)(struct thinca_impl *);
|
||||
uint64_t unkGap210[2];
|
||||
uint64_t (*unk220)(struct thinca_impl *, uint64_t);
|
||||
uint64_t (*unk228)(struct thinca_impl *, uint64_t);
|
||||
};
|
||||
|
||||
/* I believe the actual struct is 0x310 bytes, so for now I'm just
|
||||
* implementing what I need and hoping the rest don't cause issues
|
||||
* later. AMDaemon seems to only care about impl1 and deal_thing,
|
||||
* at least from what I can tell
|
||||
*/
|
||||
struct thinca_main {
|
||||
struct thinca_impl* impl1;
|
||||
struct thinca_impl* impl2;
|
||||
HANDLE* mutex1;
|
||||
HANDLE* mutex2;
|
||||
HANDLE* mutex3;
|
||||
uint64_t* unk28;
|
||||
uint64_t* unk30;
|
||||
uint64_t* unk38;
|
||||
uint64_t* unk40;
|
||||
uint64_t* deal_thing;
|
||||
uint64_t filler[88];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
HRESULT epay_hook_init(const struct epay_config *cfg);
|
|
@ -16,8 +16,6 @@ platform_lib = static_library(
|
|||
'config.h',
|
||||
'dns.c',
|
||||
'dns.h',
|
||||
'epay.c',
|
||||
'epay.h',
|
||||
'hwmon.c',
|
||||
'hwmon.h',
|
||||
'hwreset.c',
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#include "util/dprintf.h"
|
||||
|
||||
static BOOL WINAPI misc_ExitWindowsEx(unsigned int flags, uint32_t reason);
|
||||
static int my_vsprintf(char *const buffer, const char *const format, va_list args);
|
||||
static int (*next_vsprintf)(char *const buffer, const char *const format, va_list args);
|
||||
|
||||
static HRESULT misc_read_os_version(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_app_loader_count(void *bytes, uint32_t *nbytes);
|
||||
|
@ -31,14 +29,6 @@ static const struct hook_symbol misc_syms[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static const struct hook_symbol logging_sym[] = {
|
||||
{
|
||||
.name = "vsprintf",
|
||||
.patch = my_vsprintf,
|
||||
.link = (void **) &next_vsprintf,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct reg_hook_val misc_root_keys[] = {
|
||||
{
|
||||
.name = L"OSVersion",
|
||||
|
@ -140,7 +130,6 @@ HRESULT misc_hook_init(const struct misc_config *cfg, const char *platform_id)
|
|||
/* Apply function hooks */
|
||||
|
||||
hook_table_apply(NULL, "user32.dll", misc_syms, _countof(misc_syms));
|
||||
hook_table_apply(NULL, "msvcr110.dll", logging_sym, _countof(logging_sym));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -181,10 +170,3 @@ static HRESULT misc_read_platform_name(void *bytes, uint32_t *nbytes)
|
|||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"ALLS MX2.1"); // TODO: Dynamic
|
||||
}
|
||||
|
||||
static int my_vsprintf(char *const buffer, const char *const format, va_list args)
|
||||
{
|
||||
int ret = next_vsprintf(buffer, format, args);
|
||||
dprintf("%s\n", buffer);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -14,22 +14,21 @@
|
|||
#include "util/str.h"
|
||||
|
||||
enum {
|
||||
NUSEC_IOCTL_PING = CTL_CODE(0x22, 0x845, METHOD_BUFFERED, FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_PLAY_COUNT = CTL_CODE(0x22, 0x854, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_ADD_PLAY_COUNT = CTL_CODE(0x22, 0x855, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_ERASE_TRACE_LOG = CTL_CODE(0x22, 0x862, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_TD_ERASE_USED = CTL_CODE(0x22, 0x863, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_PUT_TRACE_LOG_DATA = CTL_CODE(0x22, 0x864, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_TRACE_LOG_DATA = CTL_CODE(0x22, 0x865, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_TRACE_LOG_STATE = CTL_CODE(0x22, 0x866, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_NVRAM_AVAILABLE = CTL_CODE(0x22, 0x867, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_BILLING_CA_CERT = CTL_CODE(0x22, 0x871, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_BILLING_PUBKEY = CTL_CODE(0x22, 0x872, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_PLAY_LIMIT = CTL_CODE(0x22, 0x881, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_PUT_PLAY_LIMIT = CTL_CODE(0x22, 0x882, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_NEARFULL = CTL_CODE(0x22, 0x883, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_PUT_NEARFULL = CTL_CODE(0x22, 0x884, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_GET_NVRAM_GEOMETRY = CTL_CODE(0x22, 0x893, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
NUSEC_IOCTL_PING = 0x22A114,
|
||||
NUSEC_IOCTL_ERASE_TRACE_LOG = 0x22E188,
|
||||
NUSEC_IOCTL_ADD_PLAY_COUNT = 0x22E154,
|
||||
NUSEC_IOCTL_GET_BILLING_CA_CERT = 0x22E1C4,
|
||||
NUSEC_IOCTL_GET_BILLING_PUBKEY = 0x22E1C8,
|
||||
NUSEC_IOCTL_GET_NEARFULL = 0x22E20C,
|
||||
NUSEC_IOCTL_GET_NVRAM_AVAILABLE = 0x22E19C,
|
||||
NUSEC_IOCTL_GET_NVRAM_GEOMETRY = 0x22E24C,
|
||||
NUSEC_IOCTL_GET_PLAY_COUNT = 0x22E150,
|
||||
NUSEC_IOCTL_GET_PLAY_LIMIT = 0x22E204,
|
||||
NUSEC_IOCTL_GET_TRACE_LOG_DATA = 0x22E194,
|
||||
NUSEC_IOCTL_GET_TRACE_LOG_STATE = 0x22E198,
|
||||
NUSEC_IOCTL_PUT_NEARFULL = 0x22E210,
|
||||
NUSEC_IOCTL_PUT_PLAY_LIMIT = 0x22E208,
|
||||
NUSEC_IOCTL_PUT_TRACE_LOG_DATA = 0x22E190,
|
||||
};
|
||||
|
||||
struct nusec_log_record {
|
||||
|
@ -43,7 +42,6 @@ static HRESULT nusec_handle_ioctl(struct irp *irp);
|
|||
|
||||
static HRESULT nusec_ioctl_ping(struct irp *irp);
|
||||
static HRESULT nusec_ioctl_erase_trace_log(struct irp *irp);
|
||||
static HRESULT nusec_ioctl_td_erase_used(struct irp *irp);
|
||||
static HRESULT nusec_ioctl_add_play_count(struct irp *irp);
|
||||
static HRESULT nusec_ioctl_get_billing_ca_cert(struct irp *irp);
|
||||
static HRESULT nusec_ioctl_get_billing_pubkey(struct irp *irp);
|
||||
|
@ -211,9 +209,6 @@ static HRESULT nusec_handle_ioctl(struct irp *irp)
|
|||
case NUSEC_IOCTL_ERASE_TRACE_LOG:
|
||||
return nusec_ioctl_erase_trace_log(irp);
|
||||
|
||||
case NUSEC_IOCTL_TD_ERASE_USED:
|
||||
return nusec_ioctl_td_erase_used(irp);
|
||||
|
||||
case NUSEC_IOCTL_ADD_PLAY_COUNT:
|
||||
return nusec_ioctl_add_play_count(irp);
|
||||
|
||||
|
@ -293,13 +288,6 @@ static HRESULT nusec_ioctl_erase_trace_log(struct irp *irp)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT nusec_ioctl_td_erase_used(struct irp *irp)
|
||||
{
|
||||
dprintf("Security: %s\n", __func__);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT nusec_ioctl_add_play_count(struct irp *irp)
|
||||
{
|
||||
uint32_t delta;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "platform/amvideo.h"
|
||||
#include "platform/clock.h"
|
||||
#include "platform/dns.h"
|
||||
#include "platform/epay.h"
|
||||
#include "platform/hwmon.h"
|
||||
#include "platform/misc.h"
|
||||
#include "platform/netenv.h"
|
||||
|
@ -75,13 +74,7 @@ HRESULT platform_hook_init(
|
|||
return hr;
|
||||
}
|
||||
|
||||
hr = vfs_hook_init(&cfg->vfs, game_id);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = epay_hook_init(&cfg->epay);
|
||||
hr = vfs_hook_init(&cfg->vfs);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "platform/amvideo.h"
|
||||
#include "platform/clock.h"
|
||||
#include "platform/dns.h"
|
||||
#include "platform/epay.h"
|
||||
#include "platform/hwmon.h"
|
||||
#include "platform/hwreset.h"
|
||||
#include "platform/misc.h"
|
||||
|
@ -18,7 +17,6 @@ struct platform_config {
|
|||
struct amvideo_config amvideo;
|
||||
struct clock_config clock;
|
||||
struct dns_config dns;
|
||||
struct epay_config epay;
|
||||
struct hwmon_config hwmon;
|
||||
struct hwreset_config hwreset;
|
||||
struct misc_config misc;
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
#include "hooklib/path.h"
|
||||
#include "hooklib/reg.h"
|
||||
#include "hook/procaddr.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "platform/vfs.h"
|
||||
|
||||
|
@ -22,10 +20,6 @@ static HRESULT vfs_path_hook_nthome(
|
|||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
size_t *count);
|
||||
static HRESULT vfs_path_hook_w10home(
|
||||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
size_t *count);
|
||||
static HRESULT vfs_path_hook_option(
|
||||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
|
@ -33,25 +27,10 @@ static HRESULT vfs_path_hook_option(
|
|||
static HRESULT vfs_reg_read_amfs(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes);
|
||||
|
||||
static wchar_t* my_System_getAppRootPath();
|
||||
static wchar_t* (*next_System_getAppRootPath)();
|
||||
|
||||
static const struct hook_symbol amdaemon_syms[] = {
|
||||
{
|
||||
.name = "System_getAppRootPath",
|
||||
.patch = my_System_getAppRootPath,
|
||||
.link = (void **) &next_System_getAppRootPath,
|
||||
},
|
||||
};
|
||||
|
||||
static wchar_t game[5] = {0};
|
||||
static wchar_t vfs_nthome_real[MAX_PATH];
|
||||
static const wchar_t vfs_nthome[] = L"C:\\Documents and Settings\\AppUser";
|
||||
static const size_t vfs_nthome_len = _countof(vfs_nthome) - 1;
|
||||
|
||||
static const wchar_t vfs_w10home[] = L"C:\\Users\\AppUser";
|
||||
static const size_t vfs_w10home_len = _countof(vfs_w10home) - 1;
|
||||
|
||||
static const wchar_t vfs_option[] = L"C:\\Mount\\Option";
|
||||
static const size_t vfs_option_len = _countof(vfs_option) - 1;
|
||||
|
||||
|
@ -69,7 +48,7 @@ static const struct reg_hook_val vfs_reg_vals[] = {
|
|||
|
||||
static struct vfs_config vfs_config;
|
||||
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id)
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config)
|
||||
{
|
||||
wchar_t temp[MAX_PATH];
|
||||
size_t nthome_len;
|
||||
|
@ -82,8 +61,6 @@ HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id)
|
|||
return S_FALSE;
|
||||
}
|
||||
|
||||
mbstowcs(game, game_id, 4);
|
||||
|
||||
if (config->amfs[0] == L'\0') {
|
||||
dprintf("Vfs: FATAL: AMFS path not specified in INI file\n");
|
||||
|
||||
|
@ -167,12 +144,6 @@ HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id)
|
|||
return hr;
|
||||
}
|
||||
|
||||
hr = path_hook_push(vfs_path_hook_w10home);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (vfs_config.option[0] != L'\0') {
|
||||
hr = path_hook_push(vfs_path_hook_option);
|
||||
|
||||
|
@ -191,13 +162,6 @@ HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id)
|
|||
return hr;
|
||||
}
|
||||
|
||||
proc_addr_table_push(
|
||||
NULL,
|
||||
"amdaemon_api.dll",
|
||||
amdaemon_syms,
|
||||
_countof(amdaemon_syms)
|
||||
);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -393,53 +357,6 @@ static HRESULT vfs_path_hook_nthome(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT vfs_path_hook_w10home(
|
||||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
size_t *count)
|
||||
{
|
||||
size_t required;
|
||||
size_t redir_len;
|
||||
size_t shift;
|
||||
|
||||
assert(src != NULL);
|
||||
assert(count != NULL);
|
||||
|
||||
/* Case-insensitive check to see if src starts with vfs_w10home */
|
||||
|
||||
if (path_compare_w(src, vfs_w10home, vfs_w10home_len) != 0) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/* Check if the character after vfs_w10home is a separator or the end of
|
||||
the string */
|
||||
|
||||
if (!path_is_separator_w(src[vfs_w10home_len]) &&
|
||||
src[vfs_w10home_len] != L'\0')
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/* Cut off the matched <prefix>\, add the replaced prefix, count NUL */
|
||||
|
||||
shift = path_is_separator_w(src[vfs_w10home_len]) ? 1 : 0;
|
||||
redir_len = wcslen(vfs_nthome_real);
|
||||
required = wcslen(src) - vfs_w10home_len - shift + redir_len + 1;
|
||||
|
||||
if (dest != NULL) {
|
||||
if (required > *count) {
|
||||
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
wcscpy_s(dest, *count, vfs_nthome_real);
|
||||
wcscpy_s(dest + redir_len, *count - redir_len, src + vfs_w10home_len + shift);
|
||||
}
|
||||
|
||||
*count = required;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT vfs_path_hook_option(
|
||||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
|
@ -496,12 +413,3 @@ static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes)
|
|||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, vfs_config.appdata);
|
||||
}
|
||||
|
||||
static wchar_t* my_System_getAppRootPath()
|
||||
{
|
||||
wchar_t *path = malloc(sizeof(wchar_t) * MAX_PATH);
|
||||
wcscpy_s(path, MAX_PATH, vfs_config.appdata);
|
||||
wcscat_s(path, MAX_PATH, game);
|
||||
wcscat_s(path, MAX_PATH, L"\\");
|
||||
return path;
|
||||
}
|
||||
|
|
|
@ -12,4 +12,4 @@ struct vfs_config {
|
|||
wchar_t option[MAX_PATH];
|
||||
};
|
||||
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id);
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[wrap-git]
|
||||
directory = capnhook
|
||||
url = https://github.com/Hay1tsme/capnhook
|
||||
revision = dbdcd61b3a3043b08f86f959bd45df4967503a77
|
||||
url = https://github.com/decafcode/capnhook
|
||||
revision = 69f7e3b48c2e0ff5be1d7a83cdcc2597a458357b
|
||||
|
|
Loading…
Reference in New Issue