move QR and USIO to board folder, try to actually emulate the USIO properly

This commit is contained in:
Hay1tsme 2023-07-10 23:21:36 -04:00
parent 16b1678bdb
commit 69d7b74d95
32 changed files with 800 additions and 255 deletions

View File

@ -26,7 +26,10 @@ static size_t build_bpreader_response(
uint8_t *response,
const size_t resp_size);
static HRESULT bpreader_poll_card();
static HRESULT bpreader_generic_cmd(uint32_t resp_code);
static HRESULT bpreader_poll_card_cmd();
static HRESULT bpreader_init_cmd();
static HRESULT bpreader_set_output_cmd();
static struct bpreader_config *config;
static struct uart bp_uart;
@ -42,7 +45,7 @@ HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port)
if (!config->enable) {
return S_OK;
}
if (cfg->port < 0) {
if (cfg->port > 0) {
port = cfg->port;
}
@ -57,39 +60,6 @@ HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port)
return iohook_push_handler(bp_handle_irp);
}
void bpreader_congif_load(struct bpreader_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"reader", L"enable", 1, filename);
cfg->port = GetPrivateProfileIntW(L"reader", L"port", 0, filename);
GetPrivateProfileStringW(
L"reader",
L"access_code",
L"00000000000000000000",
cfg->access_code,
_countof(cfg->access_code),
filename);
GetPrivateProfileStringW(
L"reader",
L"chip_id",
L"00000000000000000000000000000000",
cfg->chip_id,
_countof(cfg->chip_id),
filename);
HRESULT hr = wstr_to_bytes(cfg->access_code, 20, cfg->access_code_bytes, sizeof(cfg->access_code_bytes));
if (FAILED(hr)) {
dprintf("Reader: wstr_to_bytes 1 failed! 0x%lX", hr);
}
hr = wstr_to_bytes(cfg->chip_id, 32, cfg->chip_id_bytes, sizeof(cfg->chip_id_bytes));
if (FAILED(hr)) {
dprintf("Reader: wstr_to_bytes 2 failed! 0x%lX", hr);
}
}
static HRESULT bp_handle_irp(struct irp *irp)
{
HRESULT hr;
@ -143,6 +113,10 @@ static HRESULT bp_handle_irp_locked(struct irp *irp)
if (!read_ct) {
//dump_iobuf(&bp_uart.written);
hr = crack_bpreader_request();
if (!FAILED(hr)) {
bp_uart.written.pos = 0;
return hr;
}
}
switch (bp_uart.written.bytes[3]) {
case 0x02:
@ -296,6 +270,7 @@ static HRESULT crack_bpreader_request() {
case 0x18:
dprintf("Reader: Initialize\n");
// return bpreader_init_cmd(); FIXME
break;
case 0x0C:
@ -304,10 +279,12 @@ static HRESULT crack_bpreader_request() {
case 0x0E:
dprintf("Reader: Set Output\n");
return bpreader_generic_cmd(0x0F);
break;
case 0x32:
dprintf("Reader: Cmd 0x32\n");
//return bpreader_generic_cmd(0x33);
break;
case 0x40:
@ -316,7 +293,7 @@ static HRESULT crack_bpreader_request() {
case 0x4A:
dprintf("Reader: Poll Card\n");
return bpreader_poll_card();
return bpreader_poll_card_cmd();
case 0xA0:
dprintf("Reader: Read Felica\n");
@ -326,7 +303,7 @@ static HRESULT crack_bpreader_request() {
dprintf("Reader: Unknown command 0x%02x\n", header.cmd);
}
return S_OK;
return (HRESULT)-1;
}
static size_t build_bpreader_response(
@ -349,7 +326,9 @@ static size_t build_bpreader_response(
resp_header->header_checksum = 0xFF - ((0xFF + len_data + 2) & 0xFF);
memcpy_s(response, resp_size, resp_header, sizeof(*resp_header)); // Copy header
memcpy_s(&response[7], resp_size - 7, data, len_data); // copy data
if (len_data > 0) {
memcpy_s(&response[7], resp_size - 7, data, len_data); // copy data if there's any
}
for (int i = 0; i < full_resp_len; i++) {
final_checksum = (final_checksum + response[i]) & 0xFF; // Calculate checksum
@ -359,7 +338,67 @@ static size_t build_bpreader_response(
return full_resp_len;
}
static HRESULT bpreader_poll_card()
static HRESULT bpreader_generic_cmd(uint32_t resp_code)
{
//uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x19, 0x12, 0x00 };
uint8_t buff[9] = { 0x00 };
struct bpreader_cmd_header header = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, resp_code };
size_t resp_len = 0;
resp_len = build_bpreader_response((uint8_t *){0}, 0, &header, buff, sizeof(buff));
if (resp_len > 0) {
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
//dump_iobuf(&bp_uart.readable);
return hr;
} else {
dprintf("Reader: No data to return in bpreader_generic_cmd (0x%2X response code)!\n", resp_code);
return E_FAIL;
}
}
static HRESULT bpreader_init_cmd()
{
//uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x19, 0x12, 0x00 };
uint8_t buff[9] = { 0x00 };
struct bpreader_cmd_header header = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x19 };
size_t resp_len = 0;
resp_len = build_bpreader_response((uint8_t *){0}, 0, &header, buff, sizeof(buff));
if (resp_len > 0) {
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
dump_iobuf(&bp_uart.readable);
return hr;
} else {
dprintf("Reader: No data to return in bpreader_init_cmd!\n");
return E_FAIL;
}
}
static HRESULT bpreader_set_output_cmd()
{
//uint8_t buff[] = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x0F, 0x1C, 0x00 };
uint8_t buff[9] = { 0x00 };
struct bpreader_cmd_header header = { 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD5, 0x0F };
size_t resp_len = 0;
resp_len = build_bpreader_response((uint8_t *){0}, 0, &header, buff, sizeof(buff));
if (resp_len > 0) {
HRESULT hr = iobuf_write(&bp_uart.readable, buff, resp_len);
dump_iobuf(&bp_uart.readable);
return hr;
} else {
dprintf("Reader: No data to return in bpreader_set_output_cmd!\n");
return E_FAIL;
}
}
static HRESULT bpreader_poll_card_cmd()
{
struct bpreader_cmd_header header = { 0x00, 0x00, 0xFF, 0x03, 0xFD, 0xD5, 0x4B };
struct bpreader_poll_banapass_data data = { 0x00 };
@ -388,7 +427,7 @@ static HRESULT bpreader_poll_card()
return hr;
} else {
dprintf("Reader: No data to return in bpreader_poll_card!\n");
dprintf("Reader: No data to return in bpreader_poll_card_cmd!\n");
return E_FAIL;
}
}

View File

@ -13,7 +13,6 @@ struct bpreader_config {
};
HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port);
void bpreader_congif_load(struct bpreader_config *cfg, const wchar_t *filename);
/*
bpreader packet format WIP

61
board/config.c Normal file
View File

@ -0,0 +1,61 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "board/config.h"
#include "board/bpreader.h"
#include "util/dprintf.h"
#include "util/hexstr.h"
void bpreader_config_load(struct bpreader_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"reader", L"enable", 1, filename);
cfg->port = GetPrivateProfileIntW(L"reader", L"port", 0, filename);
GetPrivateProfileStringW(
L"reader",
L"access_code",
L"00000000000000000000",
cfg->access_code,
_countof(cfg->access_code),
filename);
GetPrivateProfileStringW(
L"reader",
L"chip_id",
L"00000000000000000000000000000000",
cfg->chip_id,
_countof(cfg->chip_id),
filename);
HRESULT hr = wstr_to_bytes(cfg->access_code, 20, cfg->access_code_bytes, sizeof(cfg->access_code_bytes));
if (FAILED(hr)) {
dprintf("Reader: wstr_to_bytes 1 failed! 0x%lX", hr);
}
hr = wstr_to_bytes(cfg->chip_id, 32, cfg->chip_id_bytes, sizeof(cfg->chip_id_bytes));
if (FAILED(hr)) {
dprintf("Reader: wstr_to_bytes 2 failed! 0x%lX", hr);
}
}
void usio_config_load(struct usio_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"usio", L"enable", 1, filename);
}
void qr_config_load(struct qr_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"qr", L"enable", 1, filename);
cfg->port = GetPrivateProfileIntW(L"qr", L"port", 0, filename);
}

12
board/config.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include "board/usio.h"
#include "board/bpreader.h"
#include "board/qr.h"
void bpreader_config_load(struct bpreader_config *cfg, const wchar_t *filename);
void usio_config_load(struct usio_config *cfg, const wchar_t *filename);
void qr_config_load(struct qr_config *cfg, const wchar_t *filename);

3
board/guid.c Normal file
View File

@ -0,0 +1,3 @@
#include <initguid.h>
#include "board/guid.h"

10
board/guid.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <windows.h>
DEFINE_GUID(
usio_guid,
0xE54BF304L,
0x66A3,
0x476F,
0xA4, 0x56, 0xC6, 0xDD, 0xAB, 0x8C, 0x70, 0x78);

View File

@ -1,5 +1,5 @@
board_lib = static_library(
'gfxhook',
'board',
include_directories : inc,
implicit_include_directories : false,
c_pch : '../precompiled.h',
@ -15,6 +15,14 @@ board_lib = static_library(
'bpreader.c',
'bpreader.h',
'najv4.c',
'najv4.h'
'najv4.h',
'config.c',
'config.h',
'guid.c',
'guid.h',
'usio.c',
'usio.h',
'qr.c',
'qr.h',
],
)

View File

@ -72,6 +72,11 @@ static HRESULT najv4_cmd_read_analogs(
struct const_iobuf *req_buf,
struct iobuf *resp_buf);
static HRESULT najv4_cmd_analog_out(
struct najv4 *najv4,
struct const_iobuf *req_buf,
struct iobuf *resp_buf);
static HRESULT najv4_cmd_write_gpio(
struct najv4 *najv4,
struct const_iobuf *req_buf,
@ -264,6 +269,9 @@ static HRESULT najv4_cmd(
case JVS_CMD_READ_ANALOGS:
return najv4_cmd_read_analogs(najv4, req, resp);
case JVS_CMD_ANALOG_OUT:
return najv4_cmd_analog_out(najv4, req, resp);
case JVS_CMD_WRITE_GPIO:
return najv4_cmd_write_gpio(najv4, req, resp);
@ -589,6 +597,37 @@ static HRESULT najv4_cmd_read_analogs(
}
static HRESULT najv4_cmd_analog_out(
struct najv4 *najv4,
struct const_iobuf *req_buf,
struct iobuf *resp_buf)
{
uint8_t cmd;
uint8_t channel_ct;
uint16_t bytes[MAX_PATH];
HRESULT hr;
hr = iobuf_read_8(req_buf, &cmd);
if (FAILED(hr)) {
return hr;
}
hr = iobuf_read_8(req_buf, &channel_ct);
if (FAILED(hr)) {
return hr;
}
for (int i = 0; i < channel_ct; i++) {
iobuf_read_be16(req_buf, &bytes[i]);
}
//dprintf("JVS I/O: Write Analog Out to %d channels\n", channel_ct);
return iobuf_write_8(resp_buf, 0x01);
}
static HRESULT najv4_cmd_write_gpio(
struct najv4 *najv4,
struct const_iobuf *req_buf,
@ -748,6 +787,7 @@ static HRESULT najv4_cmd_namco_extend_noop_cmd(
return iobuf_write_8(resp_buf, 1);
case 0x14B4:
case 0x143c: // Run it back??
hr = iobuf_read_8(req_buf, &cmd); // cmd (0x70)
hr = iobuf_read_8(req_buf, &subcmd); // subcmd (0x18)
@ -759,7 +799,7 @@ static HRESULT najv4_cmd_namco_extend_noop_cmd(
return iobuf_write_8(resp_buf, 1);
default:
dprintf("\nJVS I/O: Namco Extended Command 0x18 param unknown!\n");
dprintf("\nJVS I/O: Namco Extended Command 0x18 param unknown! %04X\n", param);
dump_const_iobuf(req_buf);
return iobuf_write_8(resp_buf, 1);

91
board/qr.c Normal file
View File

@ -0,0 +1,91 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "board/qr.h"
#include "hook/table.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "hooklib/fdshark.h"
#include "util/dprintf.h"
#include "util/dump.h"
/*
* Scans QR Codes that the Taiko twitter sometimes
* puts out to unlock songs and other things. Pretty
* sure that it's COM1...
*/
static HRESULT qr_handle_irp_locked(struct irp *irp);
static HRESULT qr_handle_irp(struct irp *irp);
static struct uart qr_uart;
static CRITICAL_SECTION qr_lock;
static uint8_t qr_written_bytes[520];
static uint8_t qr_readable_bytes[520];
HRESULT qr_hook_init(const struct qr_config *cfg, unsigned int port)
{
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
if (cfg->port > 0) {
port = cfg->port;
}
dprintf("QR: Init\n");
uart_init(&qr_uart, port);
qr_uart.written.bytes = qr_written_bytes;
qr_uart.written.nbytes = sizeof(qr_written_bytes);
qr_uart.readable.bytes = qr_readable_bytes;
qr_uart.readable.nbytes = sizeof(qr_readable_bytes);
InitializeCriticalSection(&qr_lock);
return iohook_push_handler(qr_handle_irp);
return S_OK;
}
static HRESULT qr_handle_irp(struct irp *irp)
{
HRESULT hr;
assert(irp != NULL);
if (uart_match_irp(&qr_uart, irp)) {
EnterCriticalSection(&qr_lock);
hr = qr_handle_irp_locked(irp);
LeaveCriticalSection(&qr_lock);
}
else {
return iohook_invoke_next(irp);
}
return hr;
}
static HRESULT qr_handle_irp_locked(struct irp *irp)
{
HRESULT hr;
if (irp->op == IRP_OP_OPEN) {
dprintf("QR: Starting backend\n");
}
hr = uart_handle_irp(&qr_uart, irp);
if (FAILED(hr)) {
return hr;
}
#if 1
dprintf("QR: IRP_OP %d Written\n", irp->op);
dump_iobuf(&qr_uart.written);
#endif
return S_OK;
}

View File

@ -5,7 +5,7 @@
struct qr_config {
bool enable;
unsigned int port;
};
HRESULT qr_hook_init(const struct qr_config *cfg);
void qr_insert_hooks(HMODULE target);
HRESULT qr_hook_init(const struct qr_config *cfg, unsigned int port);

176
board/usio.c Normal file
View File

@ -0,0 +1,176 @@
#include <windows.h>
#include <devioctl.h>
#include <hidclass.h>
#include <winusb.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "board/config.h"
#include "board/guid.h"
#include "board/usio.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/setupapi.h"
#include "util/dprintf.h"
#include "util/dump.h"
#pragma pack(push, 1)
enum {
USIO_CMD_SET_COMM_TIMEOUT = 0x01,
USIO_CMD_SET_SAMPLING_COUNT = 0x02,
USIO_CMD_CLEAR_BOARD_STATUS = 0x03,
USIO_CMD_SET_GENERAL_OUTPUT = 0x04,
USIO_CMD_SET_PWM_OUTPUT = 0x05,
USIO_CMD_UNIMPLEMENTED = 0x41,
USIO_CMD_UPDATE_FIRMWARE = 0x85,
};
#pragma pack(pop)
static HRESULT usio_handle_irp(struct irp *irp);
static HRESULT usio_handle_open(struct irp *irp);
static HRESULT usio_handle_close(struct irp *irp);
static HRESULT usio_handle_read(struct irp *irp);
static HRESULT usio_handle_write(struct irp *irp);
static HRESULT usio_handle_ioctl(struct irp *irp);
static HRESULT usio_ioctl_get_manufacturer_string(struct irp *irp);
static HRESULT usio_ioctl_get_product_string(struct irp *irp);
static const wchar_t usio_path[] = L"$usio";
//static const wchar_t usio_path[] = L"USBIO_Device0";
static HANDLE usio_fd;
static const struct usio_ops *usio_ops;
static void *usio_ops_ctx;
HRESULT usio_hook_init(
const struct usio_config *cfg,
const struct usio_ops *ops,
void *ctx)
{
HRESULT hr;
assert(cfg != NULL);
assert(ops != NULL);
if (!cfg->enable) {
return S_FALSE;
}
hr = iohook_open_nul_fd(&usio_fd);
if (FAILED(hr)) {
return hr;
}
usio_ops = ops;
usio_ops_ctx = ctx;
iohook_push_handler(usio_handle_irp);
hr = setupapi_add_phantom_dev(&usio_guid, usio_path);
if (FAILED(hr)) {
return hr;
}
dprintf("USIO: Init\n");
return S_OK;
}
static HRESULT usio_handle_irp(struct irp *irp)
{
assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != usio_fd) {
return iohook_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN: return usio_handle_open(irp);
case IRP_OP_CLOSE: return usio_handle_close(irp);
case IRP_OP_READ: return usio_handle_read(irp);
case IRP_OP_WRITE: return usio_handle_write(irp);
case IRP_OP_IOCTL: return usio_handle_ioctl(irp);
default: return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
}
}
static HRESULT usio_handle_open(struct irp *irp)
{
if (wcscmp(irp->open_filename, usio_path) != 0) {
return iohook_invoke_next(irp);
}
dprintf("USIO: Device opened\n");
irp->fd = usio_fd;
return S_OK;
}
static HRESULT usio_handle_close(struct irp *irp)
{
dprintf("USIO: Device closed\n");
return S_OK;
}
static HRESULT usio_handle_read(struct irp *irp)
{
dprintf("USIO: Read\n");
dump_iobuf(&irp->read);
return S_OK;
}
static HRESULT usio_handle_write(struct irp *irp)
{
dprintf("USIO: Write\n");
dump_const_iobuf(&irp->write);
return S_OK;
}
static HRESULT usio_handle_ioctl(struct irp *irp)
{
switch (irp->ioctl) {
case IOCTL_HID_GET_MANUFACTURER_STRING:
dprintf("USIO: Get Manufacturer String\n");
//return usio_ioctl_get_manufacturer_string(irp);
case IOCTL_HID_GET_PRODUCT_STRING:
dprintf("USIO: Get Product String\n");
//return usio_ioctl_get_product_string(irp);
case IOCTL_HID_GET_INPUT_REPORT:
dprintf("USIO: Control IN (untested!!)\n");
//return usio_handle_read(irp);
case IOCTL_HID_SET_OUTPUT_REPORT:
dprintf("USIO: Control OUT (untested!!)\n");
//return usio_handle_write(irp);
default:
dprintf("USIO: Unknown ioctl %#08x, write %i read %i\n",
irp->ioctl,
(int) irp->write.nbytes,
(int) irp->read.nbytes);
#if 1
dprintf("USIO: Written\n");
dump_const_iobuf(&irp->write);
dprintf("USIO: Read\n");
dump_iobuf(&irp->read);
#endif
return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
}
}

32
board/usio.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <windows.h>
#include <stdint.h>
enum {
/* System buttons in button[0] */
USIO_BUTTON_TEST = 1 << 9,
USIO_BUTTON_SERVICE = 1 << 6,
};
struct usio_config {
bool enable;
};
struct usio_state {
uint16_t adcs[8];
uint16_t spinners[4];
uint16_t chutes[2];
uint16_t buttons[2];
};
struct usio_ops {
HRESULT (*poll)(void *ctx, struct usio_state *state);
};
HRESULT usio_hook_init(
const struct usio_config *cfg,
const struct usio_ops *ops,
void *ctx);

View File

@ -43,5 +43,5 @@ void ferrum_hook_config_load(
ferrum_dll_config_load(&cfg->dll, filename);
ferrum_xinput_config_load(&cfg->xinput, filename);
gfx_config_load(&cfg->gfx, filename);
bpreader_congif_load(&cfg->reader, filename);
bpreader_config_load(&cfg->reader, filename);
}

View File

@ -5,7 +5,7 @@
#include "ferrumhook/ferrum-dll.h"
#include "ferrumhook/xinput.h"
#include "ferrumhook/jvs.h"
#include "board/bpreader.h"
#include "board/config.h"
#include "platform/config.h"
#include "gfxhook/config.h"

View File

@ -23,6 +23,12 @@ static void setupapi_hook_init(void);
/* API hooks */
static HDEVINFO WINAPI my_SetupDiGetClassDevsA(
const GUID *ClassGuid,
char *Enumerator,
HWND hwndParent,
DWORD Flags);
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
const GUID *ClassGuid,
wchar_t *Enumerator,
@ -44,10 +50,24 @@ static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailW(
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailA(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
/* Links */
static HDEVINFO (WINAPI *next_SetupDiGetClassDevsA)(
const GUID *ClassGuid,
char *Enumerator,
HWND hwndParent,
DWORD Flags);
static HDEVINFO (WINAPI *next_SetupDiGetClassDevsW)(
const GUID *ClassGuid,
wchar_t *Enumerator,
@ -69,12 +89,24 @@ static BOOL (WINAPI *next_SetupDiGetDeviceInterfaceDetailW)(
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL (WINAPI *next_SetupDiGetDeviceInterfaceDetailA)(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL (WINAPI *next_SetupDiDestroyDeviceInfoList)(HDEVINFO DeviceInfoSet);
/* Hook tbl */
static const struct hook_symbol setupapi_syms[] = {
{
.name = "SetupDiGetClassDevsA",
.patch = my_SetupDiGetClassDevsA,
.link = (void *) &next_SetupDiGetClassDevsA,
}, {
.name = "SetupDiGetClassDevsW",
.patch = my_SetupDiGetClassDevsW,
.link = (void *) &next_SetupDiGetClassDevsW,
@ -86,6 +118,10 @@ static const struct hook_symbol setupapi_syms[] = {
.name = "SetupDiGetDeviceInterfaceDetailW",
.patch = my_SetupDiGetDeviceInterfaceDetailW,
.link = (void *) &next_SetupDiGetDeviceInterfaceDetailW,
}, {
.name = "SetupDiGetDeviceInterfaceDetailA",
.patch = my_SetupDiGetDeviceInterfaceDetailA,
.link = (void *) &next_SetupDiGetDeviceInterfaceDetailA,
}, {
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
@ -155,6 +191,40 @@ void setupapi_hook_insert_hooks(HMODULE target)
_countof(setupapi_syms));
}
static HDEVINFO WINAPI my_SetupDiGetClassDevsA(
const GUID *ClassGuid,
char *Enumerator,
HWND hwndParent,
DWORD Flags)
{
struct setupapi_class *class_;
HDEVINFO result;
size_t i;
result = next_SetupDiGetClassDevsA(
ClassGuid,
Enumerator,
hwndParent,
Flags);
if (result == INVALID_HANDLE_VALUE || ClassGuid == NULL) {
return result;
}
EnterCriticalSection(&setupapi_lock);
for (i = 0 ; i < setupapi_nclasses ; i++) {
class_ = &setupapi_classes[i];
if (memcmp(ClassGuid, class_->guid, sizeof(*ClassGuid)) == 0) {
class_->cur_handle = result;
}
}
LeaveCriticalSection(&setupapi_lock);
return result;
}
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
const GUID *ClassGuid,
wchar_t *Enumerator,
@ -322,6 +392,83 @@ pass:
DeviceInfoData);
}
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailA(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData)
{
const wchar_t *wstr;
char path_ch[MAX_PATH];
size_t nbytes_wstr;
size_t nbytes_str;
size_t nbytes_total;
size_t i;
bool match;
if (DeviceInfoSet == INVALID_HANDLE_VALUE || DeviceInterfaceData == NULL) {
goto pass;
}
EnterCriticalSection(&setupapi_lock);
for ( i = 0, match = false ;
i < setupapi_nclasses && !match ;
i++) {
if ( DeviceInfoSet == setupapi_classes[i].cur_handle &&
DeviceInterfaceData->Reserved == (ULONG_PTR) setupapi_classes[i].path) {
match = true;
}
}
LeaveCriticalSection(&setupapi_lock);
if (!match) {
goto pass;
}
wstr = (const wchar_t *) DeviceInterfaceData->Reserved;
nbytes_wstr = (wcslen(wstr) + 1) * sizeof(wchar_t);
wcstombs(path_ch, (wchar_t *) DeviceInterfaceData->Reserved, MAX_PATH);
nbytes_str = strlen(path_ch) * sizeof(char);
nbytes_total = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
nbytes_total += nbytes_str;
if (RequiredSize != NULL) {
*RequiredSize = (DWORD) nbytes_total;
}
if ( DeviceInterfaceDetailData == NULL &&
DeviceInterfaceDetailDataSize < nbytes_total) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
if (DeviceInterfaceDetailData->cbSize!=sizeof(*DeviceInterfaceDetailData)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memcpy(DeviceInterfaceDetailData->DevicePath, path_ch, nbytes_str);
SetLastError(ERROR_SUCCESS);
return TRUE;
pass:
return next_SetupDiGetDeviceInterfaceDetailA(
DeviceInfoSet,
DeviceInterfaceData,
DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize,
RequiredSize,
DeviceInfoData);
}
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet)
{
size_t i;

View File

@ -11,6 +11,7 @@ enum {
JVS_CMD_READ_COIN = 0x21,
JVS_CMD_READ_ANALOGS = 0x22,
JVS_CMD_WRITE_GPIO = 0x32,
JVS_CMD_ANALOG_OUT = 0x33,
JVS_CMD_RESET = 0xF0,
JVS_CMD_ASSIGN_ADDR = 0xF1,
JVS_CMD_NAMCO_EXTEND = 0x70,

View File

@ -1,7 +1,4 @@
#include <windows.h>
#include "taikohook/bnusio.h"
#include "taikohook/qr.h"
#include "taikohook/config.h"
#include "hook/table.h"
@ -17,28 +14,6 @@
* to reinvent the wheel for the most part, we can just hook the functions
* that AMFW uses and let it talk to the game for us.
*/
void amfw_dongle_insert_hooks(HMODULE target);
static int my_nbamUsbFinderInitialize();
static int my_nbamUsbFinderGetSerialNumber(int a1, char serial[32]);
static int my_nbamUsbFinder_GetInformation(int a1, int a2, uint64_t a3, uint16_t a4, void *a5);
static const struct hook_symbol dongle_hooks[] = {
{
.name = "nbamUsbFinderInitialize",
.patch = my_nbamUsbFinderInitialize
},
{
.name = "nbamUsbFinderGetSerialNumber",
.patch = my_nbamUsbFinderGetSerialNumber
},
{
.name = "nbamUsbFinder_GetInformation",
.patch = my_nbamUsbFinder_GetInformation
},
};
char g_serial[13] = {0};
HRESULT amfw_hook_init(wchar_t serial[13])
{
@ -55,40 +30,7 @@ HRESULT amfw_hook_init(wchar_t serial[13])
dprintf("AMFW: Found AMFrameWork Handle\n");
bnusio_insert_hooks(hMod);
amfw_dongle_insert_hooks(hMod);
path_hook_insert_hooks(hMod);
qr_insert_hooks(hMod);
wcstombs_s(NULL, g_serial, sizeof(g_serial), serial, 26);
return S_OK;
}
void amfw_dongle_insert_hooks(HMODULE target) {
hook_table_apply(
target,
"nbamUsbFinder.dll",
dongle_hooks,
_countof(dongle_hooks));
}
static int my_nbamUsbFinderInitialize()
{
dprintf("AMFW: nbamUsbFinderInitialize\n");
return 0;
}
static int my_nbamUsbFinderGetSerialNumber(int a1, char serial[32])
{
dprintf("AMFW: nbamUsbFinderGetSerialNumber %d serial %s\n", a1, g_serial);
strcpy_s(serial, 32, g_serial);
return 0;
}
static int my_nbamUsbFinder_GetInformation(int a1, int a2, uint64_t a3, uint16_t a4, void *a5)
{
dprintf("AMFW: nbamUsbFinder_GetInformation %d\n", a1);
memset(a5, 0x00, 0x628);
//memcpy(a5 + 0x428, L"123456789012\0", 26);
return 0;
}

View File

View File

View File

@ -21,28 +21,8 @@ void taiko_dll_config_load(
filename);
}
void bnusio_config_load(
struct bnusio_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"bnusio", L"enable", 1, filename);
}
void qr_config_load(
struct qr_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"qr", L"enable", 1, filename);
}
void network_config_load(
struct ferrum_network_config *cfg,
struct taiko_network_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
@ -60,9 +40,10 @@ void taiko_hook_config_load(
platform_config_load(&cfg->platform, filename);
taiko_dll_config_load(&cfg->dll, filename);
bnusio_config_load(&cfg->bnusio, filename);
gfx_config_load(&cfg->gfx, filename);
qr_config_load(&cfg->qr, filename);
network_config_load(&cfg->network, filename);
bpreader_congif_load(&cfg->reader, filename);
bpreader_config_load(&cfg->reader, filename);
usio_config_load(&cfg->usio, filename);
}

View File

@ -3,40 +3,34 @@
#include <stddef.h>
#include "taikohook/taiko-dll.h"
#include "taikohook/bnusio.h"
#include "taikohook/qr.h"
#include "taikohook/network.h"
#include "platform/config.h"
#include "gfxhook/config.h"
#include "amcus/config.h"
#include "board/bpreader.h"
#include "board/config.h"
struct taiko_hook_config {
struct platform_config platform;
struct taiko_dll_config dll;
struct bnusio_config bnusio;
struct gfx_config gfx;
struct amcus_config amcus;
struct qr_config qr;
struct ferrum_network_config network;
struct taiko_network_config network;
struct bpreader_config reader;
struct usio_config usio;
};
void taiko_dll_config_load(
struct taiko_dll_config *cfg,
const wchar_t *filename);
void bnusio_config_load(
struct bnusio_config *cfg,
const wchar_t *filename);
void qr_config_load(
struct qr_config *cfg,
const wchar_t *filename);
void network_config_load(
struct ferrum_network_config *cfg,
struct taiko_network_config *cfg,
const wchar_t *filename);
void taiko_hook_config_load(

View File

@ -3,10 +3,12 @@
#include "taikohook/config.h"
#include "taikohook/taiko-dll.h"
#include "taikohook/bnusio.h"
#include "taikohook/amfw.h"
#include "taikohook/network.h"
#include "taikohook/qr.h"
#include "taikohook/usio.h"
#include "board/bpreader.h"
#include "board/qr.h"
#include "amcus/amcus.h"
@ -36,8 +38,8 @@ static DWORD CALLBACK taiko_pre_startup(void)
serial_hook_init();
struct dongle_info dinfo;
dinfo.pid = 0;
dinfo.vid = 0;
dinfo.pid = 0x0C00;
dinfo.vid = 0x0B9A;
hr = platform_hook_init(&taiko_hook_cfg.platform, PLATFORM_BNA1, NULL, taiko_hook_mod, dinfo);
@ -51,13 +53,19 @@ static DWORD CALLBACK taiko_pre_startup(void)
ExitProcess(EXIT_FAILURE);
}
hr = bnusio_hook_init(&taiko_hook_cfg.bnusio);
hr = taiko_usio_hook_init(&taiko_hook_cfg.usio);
if (FAILED(hr)) {
ExitProcess(EXIT_FAILURE);
}
hr = qr_hook_init(&taiko_hook_cfg.qr);
hr = qr_hook_init(&taiko_hook_cfg.qr, 1);
if (FAILED(hr)) {
ExitProcess(EXIT_FAILURE);
}
hr = bpreader_init(&taiko_hook_cfg.reader, 3);
if (FAILED(hr)) {
ExitProcess(EXIT_FAILURE);

View File

@ -26,15 +26,11 @@ shared_library(
'config.h',
'taiko-dll.c',
'taiko-dll.h',
'bnusio.c',
'bnusio.h',
'amfw.c',
'amfw.h',
'qr.c',
'qr.h',
'network.c',
'network.h',
'bngrw.c',
'bngrw.h',
'usio.c',
'usio.h',
],
)

View File

@ -6,6 +6,13 @@
#include "util/dprintf.h"
/*
* Forces Taiko to use TLS v1.2 instead of 1.0
* This was made to solve a niche issue with
* the server stack I was using. Recomend
* leaving it disabled.
*/
void network_insert_hooks(HMODULE target);
static uint64_t my_TLSv1_method(uint64_t a1, uint64_t flag);
@ -24,7 +31,7 @@ static const struct hook_symbol nethook_syms[] = {
},
};
HRESULT network_hook_init(const struct ferrum_network_config *cfg)
HRESULT network_hook_init(const struct taiko_network_config *cfg)
{
if (!cfg->enable) {
return S_FALSE;

View File

@ -3,8 +3,8 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct ferrum_network_config {
struct taiko_network_config {
bool enable;
};
HRESULT network_hook_init(const struct ferrum_network_config *cfg);
HRESULT network_hook_init(const struct taiko_network_config *cfg);

View File

@ -1,80 +0,0 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "taikohook/qr.h"
#include "hook/table.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "hooklib/fdshark.h"
#include "util/dprintf.h"
#include "util/dump.h"
static int my_nbamQrInitialize(void *qr);
static int my_nbamQrEncode(void *qr, void *info);
static int my_nbamQrGetQrImageSize(void *qr, void *info);
static const struct hook_symbol qr_hooks[] = {
{
.name = "nbamQrInitialize(void * *)",
.patch = my_nbamQrInitialize,
.ordinal = 6
},
{
.name = "nbamQrEncode(void *,nbamQr_encode_info_t *)",
.patch = my_nbamQrInitialize,
.ordinal = 3
},
{
.name = "nbamQrGetQrImageSize(void *,nbamQr_encode_info_t *)",
.patch = my_nbamQrInitialize,
.ordinal = 5
},
};
HRESULT qr_hook_init(const struct qr_config *cfg)
{
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
dprintf("QR: Init\n");
// Hook the DLL the game loads
qr_insert_hooks(NULL);
return S_OK;
}
void qr_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"Nbam_QR_Code.dll",
qr_hooks,
_countof(qr_hooks));
}
static int my_nbamQrInitialize(void *qr)
{
dprintf("QR: nbamQrInitialize\n");
return 0;
}
static int my_nbamQrEncode(void *qr, void *info)
{
dprintf("QR: nbamQrEncode\n");
return 0;
}
static int my_nbamQrGetQrImageSize(void *qr, void *info)
{
dprintf("QR: nbamQrGetQrImageSize\n");
return 0;
}

43
taikohook/usio.c Normal file
View File

@ -0,0 +1,43 @@
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "board/usio.h"
#include "taikohook/taiko-dll.h"
#include "util/dprintf.h"
bool taiko_io_coin = false;
uint16_t taiko_io_coins = 0;
static HRESULT taiko_usio_poll(void *ctx, struct usio_state *state);
static const struct usio_ops taiko_usio_ops = {
.poll = taiko_usio_poll,
};
HRESULT taiko_usio_hook_init(const struct usio_config *cfg)
{
HRESULT hr;
assert(taiko_dll.init != NULL);
hr = usio_hook_init(cfg, &taiko_usio_ops, NULL);
if (FAILED(hr)) {
return hr;
}
dprintf("Taiko USIO: Init\n");
return taiko_dll.init();
}
static HRESULT taiko_usio_poll(void *ctx, struct usio_state *state)
{
return S_OK;
}

7
taikohook/usio.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <windows.h>
#include "board/usio.h"
HRESULT taiko_usio_hook_init(const struct usio_config *cfg);

View File

@ -6,12 +6,22 @@
#include "taikoio/config.h"
void taiko_io_config_load(struct taiko_input_config *cfg, const char *filename)
void taiko_io_config_load(struct taiko_input_config *cfg, const wchar_t *filename)
{
cfg->test = GetPrivateProfileIntW(L"input", L"test", VK_HOME, filename);
cfg->service = GetPrivateProfileIntW(L"input", L"service", VK_DELETE, filename);
cfg->coin = GetPrivateProfileIntW(L"input", L"coin", VK_INSERT, filename);
cfg->up = GetPrivateProfileIntW(L"input", L"up", VK_UP, filename);
cfg->down = GetPrivateProfileIntW(L"input", L"down", VK_DOWN, filename);
cfg->enter = GetPrivateProfileIntW(L"input", L"enter", VK_RETURN, filename);
cfg->test = GetPrivateProfileIntW(L"usio", L"test", VK_HOME, filename);
cfg->service = GetPrivateProfileIntW(L"usio", L"service", VK_DELETE, filename);
cfg->coin = GetPrivateProfileIntW(L"usio", L"coin", VK_INSERT, filename);
cfg->up = GetPrivateProfileIntW(L"usio", L"up", VK_UP, filename);
cfg->down = GetPrivateProfileIntW(L"usio", L"down", VK_DOWN, filename);
cfg->enter = GetPrivateProfileIntW(L"usio", L"enter", VK_RETURN, filename);
cfg->p1_rim_l = GetPrivateProfileIntW(L"drum", L"p1_rim_l", 'Z', filename);
cfg->p1_center_l = GetPrivateProfileIntW(L"usio", L"p1_center_l", 'X', filename);
cfg->p1_center_r = GetPrivateProfileIntW(L"usio", L"p1_center_r", 'C', filename);
cfg->p1_rim_r = GetPrivateProfileIntW(L"usio", L"p1_rim_r", 'V', filename);
cfg->p2_rim_l = GetPrivateProfileIntW(L"drum", L"p2_rim_l", 'U', filename);
cfg->p2_center_l = GetPrivateProfileIntW(L"usio", L"p2_center_l", 'I', filename);
cfg->p2_center_r = GetPrivateProfileIntW(L"usio", L"p2_center_r", 'O', filename);
cfg->p2_rim_r = GetPrivateProfileIntW(L"usio", L"p2_rim_r", 'P', filename);
}

View File

@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
#pragma pack(push, 1)
struct taiko_input_config {
uint8_t test;
uint8_t service;
@ -10,4 +11,16 @@ struct taiko_input_config {
uint8_t down;
uint8_t enter;
uint8_t coin;
};
uint8_t p1_rim_l;
uint8_t p1_center_l;
uint8_t p1_center_r;
uint8_t p1_rim_r;
uint8_t p2_rim_l;
uint8_t p2_center_l;
uint8_t p2_center_r;
uint8_t p2_rim_r;
};
#pragma pack(pop)
void taiko_io_config_load(struct taiko_input_config *cfg, const wchar_t *filename);

View File

@ -10,5 +10,7 @@ taikoio_lib = static_library(
sources : [
'taikoio.c',
'taikoio.h',
'config.c',
'config.h',
],
)

View File

@ -6,6 +6,7 @@
#include <stdbool.h>
#include "taikoio/taikoio.h"
#include "taikoio/config.h"
#include "util/dprintf.h"
@ -16,6 +17,7 @@ static uint8_t taiko_opbtn = 0;
static uint16_t taiko_gamebtn = 0;
static uint16_t taiko_coin_ct = 0;
static uint16_t taiko_service_ct = 0;
static struct taiko_input_config cfg;
uint16_t taiko_io_get_api_version(void)
{
@ -25,6 +27,7 @@ uint16_t taiko_io_get_api_version(void)
HRESULT taiko_io_init(void)
{
dprintf("Taiko IO: Init\n");
taiko_io_config_load(&cfg, L".\\bananatools.ini");
return S_OK;
}
@ -33,55 +36,55 @@ HRESULT taiko_io_poll(void)
taiko_opbtn = 0;
taiko_gamebtn = 0;
if ((GetAsyncKeyState(VK_HOME) & 0x8000)) {
if ((GetAsyncKeyState(cfg.test) & 0x8000)) {
taiko_opbtn |= TAIKO_IO_OPBTN_TEST;
}
if (GetAsyncKeyState(VK_DELETE) & 0x8000) {
if (GetAsyncKeyState(cfg.service) & 0x8000) {
taiko_opbtn |= TAIKO_IO_OPBTN_SERVICE;
}
if (GetAsyncKeyState(VK_UP) & 0x8000) {
if (GetAsyncKeyState(cfg.up) & 0x8000) {
taiko_opbtn |= TAIKO_IO_OPBTN_UP;
}
if (GetAsyncKeyState(VK_DOWN) & 0x8000) {
if (GetAsyncKeyState(cfg.down) & 0x8000) {
taiko_opbtn |= TAIKO_IO_OPBTN_DOWN;
}
if (GetAsyncKeyState(VK_RETURN) & 0x8000) {
if (GetAsyncKeyState(cfg.enter) & 0x8000) {
taiko_opbtn |= TAIKO_IO_OPBTN_ENTER;
}
if (GetAsyncKeyState('Z') & 0x8000) {
if (GetAsyncKeyState(cfg.p1_rim_l) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P1_RIM_L;
}
if (GetAsyncKeyState('X') & 0x8000) {
if (GetAsyncKeyState(cfg.p1_center_l) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P1_CENTER_L;
}
if (GetAsyncKeyState('C') & 0x8000) {
if (GetAsyncKeyState(cfg.p1_center_r) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P1_CENTER_R;
}
if (GetAsyncKeyState('V') & 0x8000) {
if (GetAsyncKeyState(cfg.p1_rim_r) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P1_RIM_R;
}
if (GetAsyncKeyState('U') & 0x8000) {
if (GetAsyncKeyState(cfg.p2_rim_l) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P2_RIM_L;
}
if (GetAsyncKeyState('I') & 0x8000) {
if (GetAsyncKeyState(cfg.p2_center_l) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P2_CENTER_L;
}
if (GetAsyncKeyState('O') & 0x8000) {
if (GetAsyncKeyState(cfg.p2_center_r) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P2_CENTER_R;
}
if (GetAsyncKeyState('P') & 0x8000) {
if (GetAsyncKeyState(cfg.p2_rim_r) & 0x8000) {
taiko_gamebtn |= TAIKO_IO_P2_RIM_R;
}