diff --git a/board/bpreader.c b/board/bpreader.c index a7c4483..9f57fb8 100644 --- a/board/bpreader.c +++ b/board/bpreader.c @@ -77,7 +77,7 @@ HRESULT bpreader_init(struct bpreader_config *cfg, uint16_t port) return hr; } - dprintf("Reader: Init\n"); + dprintf("Reader: Init on COM%d\n", port); return iohook_push_handler(bp_handle_irp); } diff --git a/board/qr.c b/board/qr.c index f8cf4f9..72fbc3d 100644 --- a/board/qr.c +++ b/board/qr.c @@ -16,8 +16,8 @@ /* * Scans QR Codes that the Taiko twitter sometimes - * puts out to unlock songs and other things. Pretty - * sure that it's COM1... + * puts out to unlock songs and other things. Huge + * thanks to mon for writing most of this! */ static HRESULT qr_handle_irp_locked(struct irp *irp); static HRESULT qr_handle_irp(struct irp *irp); @@ -26,6 +26,7 @@ static struct uart qr_uart; static CRITICAL_SECTION qr_lock; static uint8_t qr_written_bytes[520]; static uint8_t qr_readable_bytes[520]; +static bool reader_active; HRESULT qr_hook_init(const struct qr_config *cfg, unsigned int port) { @@ -38,7 +39,7 @@ HRESULT qr_hook_init(const struct qr_config *cfg, unsigned int port) port = cfg->port; } - dprintf("QR: Init\n"); + dprintf("QR: Init on COM%d\n", port); uart_init(&qr_uart, port); qr_uart.written.bytes = qr_written_bytes; @@ -52,40 +53,145 @@ HRESULT qr_hook_init(const struct qr_config *cfg, unsigned int port) return S_OK; } +/* +QR port opened -static HRESULT qr_handle_irp(struct irp *irp) +all requests and responses end with 0x55 0x00 +all requests appear to start with 0x57 0x00 followed by a command code + +Requests: +Lamp on: 57 00 17 52 00 02 00 01 00 55 00 +Lamp off: 57 00 17 52 00 01 00 01 00 55 00 +Scan off: 57 00 19 00 55 00 +Scan on : 57 00 18 00 55 00 + +Responses: +Bit index 2 appears to be used as a status code +"OK" : 31 00 00 00 55 00 + +example QR code (thx tung) +[83,49,50,0,0,255,255,17,1,0,67,79,76,76,65,66,79,95,84,79,72,79,95,50,48,50,48,238,255] + +WRITE: + 00000000: W..R.....U. +*/ + +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 { + // dprintf("QR: IRP request to %ls\n", irp->open_filename); + + if (!uart_match_irp(&qr_uart, irp)) { return iohook_invoke_next(irp); } + EnterCriticalSection(&qr_lock); + hr = qr_handle_irp_locked(irp); + LeaveCriticalSection(&qr_lock); + return hr; } -static HRESULT qr_handle_irp_locked(struct irp *irp) +static HRESULT qr_handle_irp_locked(struct irp* irp) { HRESULT hr; - if (irp->op == IRP_OP_OPEN) { - dprintf("QR: Starting backend\n"); + +#if 0 + if (irp->op == IRP_OP_WRITE) { + dprintf("WRITE:\n"); + dump_const_iobuf(&irp->write); } - - hr = uart_handle_irp(&qr_uart, irp); - if (FAILED(hr)) { +#endif + +#if 0 + if (irp->op == IRP_OP_READ) { + dprintf("READ:\n"); + dump_iobuf(&qr_uart.readable); + } +#endif + + if (irp->op == IRP_OP_OPEN) { + dprintf("QR: port opened\n"); + ///* Unfortunately the card reader UART gets opened and closed + // repeatedly */ + + //if (!qr_started) { + // dprintf("NFC Assembly: Starting backend DLL\n"); + // hr = aime_io_init(); + + // qr_started = true; + // qr_start_hr = hr; + + // if (FAILED(hr)) { + // dprintf("NFC Assembly: Backend error: %x\n", (int)hr); + + // return hr; + // } + //} + //else { + // hr = qr_start_hr; + + // if (FAILED(hr)) { + // return hr; + // } + //} + } + + if (irp->op == IRP_OP_READ) { + // page up key + if (reader_active && GetAsyncKeyState(VK_PRIOR) & 0x8000) { + dprintf("QR: Scanning\n"); + // data from scans is literally just sent as raw bytes, nothing fancy lol + // https://twitter.com/taiko_team/status/1377425481855799299 + unsigned char taiko_aprilfools_2021[] = { + 0x53, 0x31, 0x32, 0x00, 0x01, 0xC3, 0x93, 0xC3, 0xA1, 0xC2, 0x92, 0xC3, + 0x87, 0xC4, 0xA0, 0x44, 0x16, 0xC3, 0xB8, 0x4B, 0xC2, 0xA0, 0x44, 0xC3, + 0xBD, 0xC3, 0xBA, 0x29, 0xC5, 0xB6, 0xC3, 0xA5, 0x06, 0xE1, 0xB8, 0x9F, + 0x2A, 0x43, 0x6F, 0x25, 0x79, 0xC2, 0x84, 0x2B, 0xC2, 0x90, 0x29, 0xC2, + 0xAE, 0xC3, 0xAD, 0x54, 0x3E, 0xC3, 0xAB, 0x0A + }; + /*const uint8_t scan_response[] = { + 83,49,50,0,0,255,255,17,1,0,67,79,76,76,65,66,79,95,84,79,72,79,95,50,48,50,48,238,255 + };*/ + iobuf_write(&qr_uart.readable, taiko_aprilfools_2021, sizeof(taiko_aprilfools_2021)); + } + } + + hr = uart_handle_irp(&qr_uart, irp); + + if (FAILED(hr) || irp->op != IRP_OP_WRITE) { return hr; } -#if 1 - dprintf("QR: IRP_OP %d Written\n", irp->op); - dump_iobuf(&qr_uart.written); -#endif - return S_OK; + const uint8_t scan_on[] = { + 0x57, 0x00, 0x18, 0x00, 0x55, 0x00, + }; + const uint8_t scan_off[] = { + 0x57, 0x00, 0x19, 0x00, 0x55, 0x00, + }; + + const uint8_t qr_response[6] = { + 0x31, 0x00, 0x00, 0x00, 0x55, 0x00 + }; + + if (qr_uart.written.pos == sizeof(scan_on) && memcmp(qr_uart.written.bytes, scan_on, sizeof(scan_on)) == 0) { + if (!reader_active) { + dprintf("QR: Scanning enabled\n"); + } + reader_active = true; + } else if (qr_uart.written.pos == sizeof(scan_off) && memcmp(qr_uart.written.bytes, scan_off, sizeof(scan_off)) == 0) { + if (reader_active) { + dprintf("QR: Scanning disabled\n"); + } + reader_active = false; + } + + iobuf_write(&qr_uart.readable, qr_response, sizeof(qr_response)); + + qr_uart.written.pos = 0; + + return hr; } \ No newline at end of file diff --git a/platform/config.c b/platform/config.c index 5bbceea..cef5717 100644 --- a/platform/config.c +++ b/platform/config.c @@ -57,7 +57,7 @@ void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename) if (cfg->path[0] == L'\0') { dprintf("No vfs folder specified, using default 'vfs' at CWD\n"); GetCurrentDirectoryW(_countof(cfg->path), cfg->path); - wcscat_s(cfg->path, _countof(cfg->path), L"vfs"); + wcscat_s(cfg->path, _countof(cfg->path), L"\\vfs"); } if (cfg->path[len - 2] != '\\' && cfg->path[len - 2] != '/') { // -2 for null terminator diff --git a/taikohook/dllmain.c b/taikohook/dllmain.c index c526a98..ae5767d 100644 --- a/taikohook/dllmain.c +++ b/taikohook/dllmain.c @@ -9,6 +9,7 @@ #include "board/bpreader.h" #include "board/qr.h" +#include "board/vfd.h" #include "amcus/amcus.h" @@ -59,13 +60,19 @@ static DWORD CALLBACK taiko_pre_startup(void) ExitProcess(EXIT_FAILURE); } - hr = qr_hook_init(&taiko_hook_cfg.qr, 1); + hr = qr_hook_init(&taiko_hook_cfg.qr, 5); + + if (FAILED(hr)) { + ExitProcess(EXIT_FAILURE); + } + + hr = vfd_hook_init(2); if (FAILED(hr)) { ExitProcess(EXIT_FAILURE); } - hr = bpreader_init(&taiko_hook_cfg.reader, 3); + hr = bpreader_init(&taiko_hook_cfg.reader, 1); if (FAILED(hr)) { ExitProcess(EXIT_FAILURE);