#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 "hook/table.h" #include "hook/iohook.h" #include "hooklib/setupapi.h" #include "util/dprintf.h" #include "util/dump.h" static const wchar_t usio_path[] = L"$usio"; //static const wchar_t usio_path[] = L"USBIO_Device0"; static int my_bnusio_Open(); static int my_bnusio_Close(); static int my_bnusio_GetFirmwareVersion(); static int my_bnusio_SetSystemError(uint16_t err); static int my_bnusio_ClearSram(); static BOOL my_bnusio_ResetIoBoard(); static int my_bnusio_Communication(uint64_t com); static int my_bnusio_GetSystemError(); static void my_bnusio_SetPLCounter(uint16_t pl_ct); static int my_bnusio_SetGout(uint8_t id, uint8_t value); static int my_bnusio_GetAnalogIn(uint8_t id); static int my_bnusio_GetSwIn(); static int my_bnusio_SetCoinLock(uint8_t id, char value); static int my_bnusio_GetCoin(uint8_t id); static int my_bnusio_GetCoinError(uint8_t id); static int my_bnusio_GetService(uint8_t id); static int my_bnusio_GetServiceError(uint8_t id); static const struct hook_symbol winusb_syms[] = { { .name = "bnusio_Open", .patch = my_bnusio_Open }, { .name = "bnusio_GetFirmwareVersion", .patch = my_bnusio_GetFirmwareVersion }, { .name = "bnusio_Close", .patch = my_bnusio_Close }, { .name = "bnusio_SetSystemError", .patch = my_bnusio_SetSystemError }, { .name = "bnusio_ClearSram", .patch = my_bnusio_ClearSram }, { .name = "bnusio_ResetIoBoard", .patch = my_bnusio_ResetIoBoard }, { .name = "bnusio_Communication", .patch = my_bnusio_Communication }, { .name = "bnusio_GetSystemError", .patch = my_bnusio_GetSystemError }, { .name = "bnusio_SetPLCounter", .patch = my_bnusio_SetPLCounter }, { .name = "bnusio_SetGout", .patch = my_bnusio_SetGout }, { .name = "bnusio_GetAnalogIn", .patch = my_bnusio_GetAnalogIn }, { .name = "bnusio_GetSwIn", .patch = my_bnusio_GetSwIn }, { .name = "bnusio_SetCoinLock", .patch = my_bnusio_SetCoinLock }, { .name = "bnusio_GetCoin", .patch = my_bnusio_GetCoin }, { .name = "bnusio_GetCoinError", .patch = my_bnusio_GetCoinError }, { .name = "bnusio_GetService", .patch = my_bnusio_GetService }, { .name = "bnusio_GetServiceError", .patch = my_bnusio_GetServiceError } }; static HANDLE usio_fd; static const struct usio_ops *usio_ops; static void *usio_ops_ctx; static struct usio_state state; HRESULT usio_hook_init( const struct usio_config *cfg, const struct usio_ops *ops, void *ctx, HMODULE target) { HRESULT hr; assert(cfg != NULL); assert(ops != NULL); if (!cfg->enable) { return S_FALSE; } usio_ops = ops; usio_ops_ctx = ctx; hook_table_apply(target, "bnusio.dll", winusb_syms, _countof(winusb_syms)); memset(&state, 0, sizeof(state)); dprintf("USIO: Init\n"); return S_OK; } static int my_bnusio_Open() { dprintf("USIO: Open\n"); return 0; } static int my_bnusio_GetFirmwareVersion() { dprintf("USIO: GetFirmwareVersion\n"); return 126; } static int my_bnusio_Close() { dprintf("USIO: Close\n"); return 0; } static int my_bnusio_SetSystemError(uint16_t err) { dprintf("USIO: SetSystemError %d\n", err); state.err = err; return 0; } static int my_bnusio_ClearSram() { dprintf("USIO: ClearSram\n"); return 0; } static BOOL my_bnusio_ResetIoBoard() { dprintf("USIO: ResetIoBoard\n"); return false; } static int my_bnusio_Communication(uint64_t com) { //dprintf("USIO: Communication\n"); return 0; } static int my_bnusio_GetSystemError() { dprintf("USIO: GetSystemError\n"); return state.err; } static void my_bnusio_SetPLCounter(uint16_t pl_ct) { //dprintf("USIO: SetPLCounter\n"); state.pl_count = pl_ct; } static int my_bnusio_SetGout(uint8_t id, uint8_t value) { //dprintf("USIO: SetGout ID %d Val %d\n", id, value); if (id <= 32) { state.gpio[id - 1] = value; return 0; } return 0xFFFFFFEA; } static int my_bnusio_SetCoinLock(uint8_t id, char value) { dprintf("USIO: SetCoinLock %d %x\n", id, value); state.coins[id].is_lock = value; return 0; } static int my_bnusio_GetCoin(uint8_t id) { //dprintf("USIO: GetCoin ID %d\n", id); usio_ops->poll(usio_ops_ctx, &state); if (id < 2) { return state.coins[id].current_coin_count; } return 0; } static int my_bnusio_GetCoinError(uint8_t id) { //dprintf("USIO: GetCoinErrorID %d\n", id); if (id >= _countof(state.coins)) { return 0; } return state.coins[id].err; } static int my_bnusio_GetService(uint8_t id) { //dprintf("USIO: GetService ID %d\n", id); usio_ops->poll(usio_ops_ctx, &state); if (id < 1) { return state.service.current_coin_count; } return 0; } static int my_bnusio_GetServiceError(uint8_t id) { // TODO: multiple service switches? //dprintf("USIO: GetServiceError ID %d\n", id); if (id < 1) { return state.service.err; } return 0; } static int my_bnusio_GetAnalogIn(uint8_t id) { //dprintf("USIO: GetAnalogIn ID %d\n", id); uint8_t gamebtns = 0; usio_ops->poll(usio_ops_ctx, &state); if (id < 8) { return state.analog[id]; } return 0; } static int my_bnusio_GetSwIn() { //dprintf("USIO: GetSwitchIn\n"); uint32_t opbtn_out = 0; usio_ops->poll(usio_ops_ctx, &state); opbtn_out = (state.p2_btns << 16) | (state.p1_btns << 8) | state.op_btns; return opbtn_out; }