376 lines
8.0 KiB
C
376 lines
8.0 KiB
C
#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 "hook/table.h"
|
|
#include "hook/iohook.h"
|
|
|
|
#include "hooklib/setupapi.h"
|
|
#include "hooklib/procaddr.h"
|
|
|
|
#include "util/dprintf.h"
|
|
#include "util/dump.h"
|
|
|
|
static const wchar_t usio_path[] = L"$usio";
|
|
static const wchar_t usio_name[] = L"NBGI.REAL_USIO";
|
|
|
|
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 intptr_t my_bnusio_GetIoBoardName();
|
|
|
|
static struct hook_symbol usio_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
|
|
},
|
|
{
|
|
.name = "bnusio_GetIoBoardName",
|
|
.patch = my_bnusio_GetIoBoardName
|
|
},
|
|
{
|
|
.name = "Open",
|
|
.patch = my_bnusio_Open
|
|
},
|
|
{
|
|
.name = "GetFirmwareVersion",
|
|
.patch = my_bnusio_GetFirmwareVersion
|
|
},
|
|
{
|
|
.name = "Close",
|
|
.patch = my_bnusio_Close
|
|
},
|
|
{
|
|
.name = "SetSystemError",
|
|
.patch = my_bnusio_SetSystemError
|
|
},
|
|
{
|
|
.name = "ClearSram",
|
|
.patch = my_bnusio_ClearSram
|
|
},
|
|
{
|
|
.name = "ResetIoBoard",
|
|
.patch = my_bnusio_ResetIoBoard
|
|
},
|
|
{
|
|
.name = "Communication",
|
|
.patch = my_bnusio_Communication
|
|
},
|
|
{
|
|
.name = "GetSystemError",
|
|
.patch = my_bnusio_GetSystemError
|
|
},
|
|
{
|
|
.name = "SetPLCounter",
|
|
.patch = my_bnusio_SetPLCounter
|
|
},
|
|
{
|
|
.name = "SetGout",
|
|
.patch = my_bnusio_SetGout
|
|
},
|
|
{
|
|
.name = "GetAnalogIn",
|
|
.patch = my_bnusio_GetAnalogIn
|
|
},
|
|
{
|
|
.name = "GetSwIn",
|
|
.patch = my_bnusio_GetSwIn
|
|
},
|
|
{
|
|
.name = "SetCoinLock",
|
|
.patch = my_bnusio_SetCoinLock
|
|
},
|
|
{
|
|
.name = "GetCoin",
|
|
.patch = my_bnusio_GetCoin
|
|
},
|
|
{
|
|
.name = "GetCoinError",
|
|
.patch = my_bnusio_GetCoinError
|
|
},
|
|
{
|
|
.name = "GetService",
|
|
.patch = my_bnusio_GetService
|
|
},
|
|
{
|
|
.name = "GetServiceError",
|
|
.patch = my_bnusio_GetServiceError
|
|
},
|
|
{
|
|
.name = "GetIoBoardName",
|
|
.patch = my_bnusio_GetIoBoardName
|
|
}
|
|
};
|
|
|
|
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", usio_syms, _countof(usio_syms));
|
|
memset(&state, 0, sizeof(state));
|
|
|
|
dprintf("USIO: Init\n");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT usio_hook_proc_addr(HMODULE target)
|
|
{
|
|
if (usio_ops != NULL)
|
|
return proc_addr_table_push(target, "bnusio.dll", usio_syms, _countof(usio_syms));
|
|
|
|
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;
|
|
}
|
|
|
|
static intptr_t my_bnusio_GetIoBoardName()
|
|
{
|
|
intptr_t ret = (intptr_t)malloc(sizeof(usio_name) / 2);
|
|
wcstombs((char *)ret, usio_name, sizeof(usio_name) / 2);
|
|
return ret;
|
|
} |