From 69d7b74d95110c620c42ee72345bd3dad562ef2e Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Mon, 10 Jul 2023 23:21:36 -0400 Subject: [PATCH] move QR and USIO to board folder, try to actually emulate the USIO properly --- board/bpreader.c | 119 +++++++++++++++++--------- board/bpreader.h | 1 - board/config.c | 61 +++++++++++++ board/config.h | 12 +++ board/guid.c | 3 + board/guid.h | 10 +++ board/meson.build | 12 ++- board/najv4.c | 42 ++++++++- board/qr.c | 91 ++++++++++++++++++++ {taikohook => board}/qr.h | 4 +- board/usio.c | 176 ++++++++++++++++++++++++++++++++++++++ board/usio.h | 32 +++++++ ferrumhook/config.c | 2 +- ferrumhook/config.h | 2 +- hooklib/setupapi.c | 147 +++++++++++++++++++++++++++++++ jvs/jvs-cmd.h | 1 + taikohook/amfw.c | 58 ------------- taikohook/bngrw.c | 0 taikohook/bngrw.h | 0 taikohook/config.c | 27 +----- taikohook/config.h | 14 +-- taikohook/dllmain.c | 20 +++-- taikohook/meson.build | 8 +- taikohook/network.c | 9 +- taikohook/network.h | 4 +- taikohook/qr.c | 80 ----------------- taikohook/usio.c | 43 ++++++++++ taikohook/usio.h | 7 ++ taikoio/config.c | 24 ++++-- taikoio/config.h | 15 +++- taikoio/meson.build | 2 + taikoio/taikoio.c | 29 ++++--- 32 files changed, 800 insertions(+), 255 deletions(-) create mode 100644 board/config.c create mode 100644 board/config.h create mode 100644 board/guid.c create mode 100644 board/guid.h create mode 100644 board/qr.c rename {taikohook => board}/qr.h (55%) create mode 100644 board/usio.c create mode 100644 board/usio.h delete mode 100644 taikohook/bngrw.c delete mode 100644 taikohook/bngrw.h delete mode 100644 taikohook/qr.c create mode 100644 taikohook/usio.c create mode 100644 taikohook/usio.h diff --git a/board/bpreader.c b/board/bpreader.c index f555a3d..cfe24c9 100644 --- a/board/bpreader.c +++ b/board/bpreader.c @@ -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; } } \ No newline at end of file diff --git a/board/bpreader.h b/board/bpreader.h index cb6dab2..a2f36ff 100644 --- a/board/bpreader.h +++ b/board/bpreader.h @@ -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 diff --git a/board/config.c b/board/config.c new file mode 100644 index 0000000..61b5f71 --- /dev/null +++ b/board/config.c @@ -0,0 +1,61 @@ +#include + +#include +#include +#include +#include + +#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); +} \ No newline at end of file diff --git a/board/config.h b/board/config.h new file mode 100644 index 0000000..47380e6 --- /dev/null +++ b/board/config.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +#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); \ No newline at end of file diff --git a/board/guid.c b/board/guid.c new file mode 100644 index 0000000..9c1993b --- /dev/null +++ b/board/guid.c @@ -0,0 +1,3 @@ +#include + +#include "board/guid.h" \ No newline at end of file diff --git a/board/guid.h b/board/guid.h new file mode 100644 index 0000000..56ed377 --- /dev/null +++ b/board/guid.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +DEFINE_GUID( + usio_guid, + 0xE54BF304L, + 0x66A3, + 0x476F, + 0xA4, 0x56, 0xC6, 0xDD, 0xAB, 0x8C, 0x70, 0x78); \ No newline at end of file diff --git a/board/meson.build b/board/meson.build index 082bebe..b35c761 100644 --- a/board/meson.build +++ b/board/meson.build @@ -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', ], ) diff --git a/board/najv4.c b/board/najv4.c index eabb764..c341610 100644 --- a/board/najv4.c +++ b/board/najv4.c @@ -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); diff --git a/board/qr.c b/board/qr.c new file mode 100644 index 0000000..f8cf4f9 --- /dev/null +++ b/board/qr.c @@ -0,0 +1,91 @@ +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/taikohook/qr.h b/board/qr.h similarity index 55% rename from taikohook/qr.h rename to board/qr.h index a980882..3fa99c0 100644 --- a/taikohook/qr.h +++ b/board/qr.h @@ -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); \ No newline at end of file +HRESULT qr_hook_init(const struct qr_config *cfg, unsigned int port); diff --git a/board/usio.c b/board/usio.c new file mode 100644 index 0000000..f37f70b --- /dev/null +++ b/board/usio.c @@ -0,0 +1,176 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#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); + } +} \ No newline at end of file diff --git a/board/usio.h b/board/usio.h new file mode 100644 index 0000000..a5466d1 --- /dev/null +++ b/board/usio.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include + +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); \ No newline at end of file diff --git a/ferrumhook/config.c b/ferrumhook/config.c index 37cb16d..7ded244 100644 --- a/ferrumhook/config.c +++ b/ferrumhook/config.c @@ -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); } diff --git a/ferrumhook/config.h b/ferrumhook/config.h index 6b72f83..64dd8a2 100644 --- a/ferrumhook/config.h +++ b/ferrumhook/config.h @@ -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" diff --git a/hooklib/setupapi.c b/hooklib/setupapi.c index edd416a..2c96d38 100644 --- a/hooklib/setupapi.c +++ b/hooklib/setupapi.c @@ -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; diff --git a/jvs/jvs-cmd.h b/jvs/jvs-cmd.h index d6ffabf..745c16a 100644 --- a/jvs/jvs-cmd.h +++ b/jvs/jvs-cmd.h @@ -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, diff --git a/taikohook/amfw.c b/taikohook/amfw.c index 02f7d5b..fa9c601 100644 --- a/taikohook/amfw.c +++ b/taikohook/amfw.c @@ -1,7 +1,4 @@ #include - -#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; -} diff --git a/taikohook/bngrw.c b/taikohook/bngrw.c deleted file mode 100644 index e69de29..0000000 diff --git a/taikohook/bngrw.h b/taikohook/bngrw.h deleted file mode 100644 index e69de29..0000000 diff --git a/taikohook/config.c b/taikohook/config.c index 9dac33c..01bdb59 100644 --- a/taikohook/config.c +++ b/taikohook/config.c @@ -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); + } diff --git a/taikohook/config.h b/taikohook/config.h index 6958e52..d0f94dd 100644 --- a/taikohook/config.h +++ b/taikohook/config.h @@ -3,40 +3,34 @@ #include #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( diff --git a/taikohook/dllmain.c b/taikohook/dllmain.c index c2e9065..c526a98 100644 --- a/taikohook/dllmain.c +++ b/taikohook/dllmain.c @@ -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); diff --git a/taikohook/meson.build b/taikohook/meson.build index b6de754..8e57d00 100644 --- a/taikohook/meson.build +++ b/taikohook/meson.build @@ -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', ], ) diff --git a/taikohook/network.c b/taikohook/network.c index f918d83..8351d13 100644 --- a/taikohook/network.c +++ b/taikohook/network.c @@ -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; diff --git a/taikohook/network.h b/taikohook/network.h index 2924e7f..487e889 100644 --- a/taikohook/network.h +++ b/taikohook/network.h @@ -3,8 +3,8 @@ #include #include #include -struct ferrum_network_config { +struct taiko_network_config { bool enable; }; -HRESULT network_hook_init(const struct ferrum_network_config *cfg); \ No newline at end of file +HRESULT network_hook_init(const struct taiko_network_config *cfg); \ No newline at end of file diff --git a/taikohook/qr.c b/taikohook/qr.c deleted file mode 100644 index de2566e..0000000 --- a/taikohook/qr.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include - -#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; -} \ No newline at end of file diff --git a/taikohook/usio.c b/taikohook/usio.c new file mode 100644 index 0000000..106d77f --- /dev/null +++ b/taikohook/usio.c @@ -0,0 +1,43 @@ +#include + +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/taikohook/usio.h b/taikohook/usio.h new file mode 100644 index 0000000..938eda5 --- /dev/null +++ b/taikohook/usio.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "board/usio.h" + +HRESULT taiko_usio_hook_init(const struct usio_config *cfg); \ No newline at end of file diff --git a/taikoio/config.c b/taikoio/config.c index 23506a3..bcc5fe5 100644 --- a/taikoio/config.c +++ b/taikoio/config.c @@ -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); } \ No newline at end of file diff --git a/taikoio/config.h b/taikoio/config.h index 836ab3d..6399160 100644 --- a/taikoio/config.h +++ b/taikoio/config.h @@ -3,6 +3,7 @@ #include #include +#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; -}; \ No newline at end of file + + 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); \ No newline at end of file diff --git a/taikoio/meson.build b/taikoio/meson.build index cf10247..2cea435 100644 --- a/taikoio/meson.build +++ b/taikoio/meson.build @@ -10,5 +10,7 @@ taikoio_lib = static_library( sources : [ 'taikoio.c', 'taikoio.h', + 'config.c', + 'config.h', ], ) diff --git a/taikoio/taikoio.c b/taikoio/taikoio.c index 09730a8..e399c60 100644 --- a/taikoio/taikoio.c +++ b/taikoio/taikoio.c @@ -6,6 +6,7 @@ #include #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; }