mirror of
https://gitea.tendokyu.moe/TeamTofuShop/taitools.git
synced 2026-09-29 02:08:06 +03:00
JVS reader OK, fastio progress
This commit is contained in:
@@ -0,0 +1,485 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "board/j9100628a.h"
|
||||
|
||||
#include "jvs/jvs-bus.h"
|
||||
#include "jvs/jvs-cmd.h"
|
||||
#include "jvs/jvs-util.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
#include "util/dump.h"
|
||||
|
||||
static const uint8_t j9100628a_ident[] = "taito;JVS-Reader;Ver1.00;JPN,Multipurpose";
|
||||
|
||||
static uint8_t j9100628a_features[] = {
|
||||
/* Feature : 0x01 : Players and switches
|
||||
Param1 : 1 : Number of players
|
||||
Param2 : 18 : Number of switches per player
|
||||
Param3 : 0 : N/A */
|
||||
|
||||
0x01,
|
||||
0x01,
|
||||
0x18,
|
||||
0x00,
|
||||
|
||||
/* Feature : 0x02 : Coin slots
|
||||
Param1 : 2 : Number of coin slots
|
||||
Param2 : 0 : N/A
|
||||
Param3 : 0 : N/A */
|
||||
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
|
||||
/* Feature : 0x03 : Analog inputs
|
||||
Param1 : 8 : Number of ADC channels
|
||||
Param2 : 10 : Effective bits of resolution per ADC
|
||||
Param3 : 0 : N/A */
|
||||
|
||||
0x03,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
|
||||
/* Feature : 0x04 : Rotary Input
|
||||
Param1 : 4 : Number of Rotary channels
|
||||
Param2 : 0 : N/A
|
||||
Param3 : 0 : N/A */
|
||||
|
||||
0x04,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
|
||||
/* Feature : 0x12 : GPIO outputs
|
||||
Param1 : 3 : Number of ports (8 bits per port)
|
||||
Param2 : 0 : N/A
|
||||
Param3 : 0 : N/A
|
||||
*/
|
||||
|
||||
0x12,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
|
||||
/* Feature : 0x13 : Analog outputs
|
||||
Param1 : 2 : Number of channels
|
||||
Param2 : 0 : N/A
|
||||
Param3 : 0 : N/A
|
||||
*/
|
||||
|
||||
0x13,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
|
||||
/* Feature : 0x14 : Character Output
|
||||
Param1 : 0x50 : Width
|
||||
Param2 : 0x19 : Height
|
||||
Param3 : 0 : Type
|
||||
*/
|
||||
0x14,
|
||||
0x50,
|
||||
0x19,
|
||||
0x00,
|
||||
|
||||
/* Feature : 0x00 : End of capabilities */
|
||||
|
||||
0x00,
|
||||
};
|
||||
|
||||
static void j9100628a_transact(
|
||||
struct jvs_node *node,
|
||||
const void *bytes,
|
||||
size_t nbytes,
|
||||
struct iobuf *resp);
|
||||
|
||||
static bool j9100628a_sense(struct jvs_node *node);
|
||||
|
||||
static HRESULT j9100628a_cmd(
|
||||
void *ctx,
|
||||
struct const_iobuf *req,
|
||||
struct iobuf *resp);
|
||||
|
||||
static HRESULT j9100628a_cmd_reset(struct j9100628a *j9100628a, struct const_iobuf *req_buf);
|
||||
static HRESULT j9100628a_cmd_assign_addr(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_read_id(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_get_cmd_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_get_jvs_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_get_comm_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_get_features(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_read_misc_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_read_dip_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
static HRESULT j9100628a_cmd_write_gpio(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf);
|
||||
|
||||
void j9100628a_init(
|
||||
struct j9100628a *j9100628a,
|
||||
struct jvs_node *next,
|
||||
const struct j9100628a_ops *ops,
|
||||
void *ops_ctx)
|
||||
{
|
||||
assert(j9100628a != NULL);
|
||||
assert(ops != NULL);
|
||||
|
||||
j9100628a->jvs.next = next;
|
||||
j9100628a->jvs.transact = j9100628a_transact;
|
||||
j9100628a->jvs.sense = j9100628a_sense;
|
||||
j9100628a->jvs.sense_out = true;
|
||||
j9100628a->addr = 0xFF;
|
||||
j9100628a->ops = ops;
|
||||
j9100628a->ops_ctx = ops_ctx;
|
||||
}
|
||||
|
||||
struct jvs_node *j9100628a_to_jvs_node(struct j9100628a *j9100628a)
|
||||
{
|
||||
assert(j9100628a != NULL);
|
||||
|
||||
return &j9100628a->jvs;
|
||||
}
|
||||
|
||||
static void j9100628a_transact(
|
||||
struct jvs_node *node,
|
||||
const void *bytes,
|
||||
size_t nbytes,
|
||||
struct iobuf *resp)
|
||||
{
|
||||
struct j9100628a *j9100628a;
|
||||
|
||||
assert(node != NULL);
|
||||
assert(bytes != NULL);
|
||||
assert(resp != NULL);
|
||||
|
||||
j9100628a = CONTAINING_RECORD(node, struct j9100628a, jvs);
|
||||
|
||||
jvs_crack_request(bytes, nbytes, resp, j9100628a->addr, j9100628a_cmd, j9100628a);
|
||||
}
|
||||
|
||||
static bool j9100628a_sense(struct jvs_node *node)
|
||||
{
|
||||
struct j9100628a *j9100628a;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
j9100628a = CONTAINING_RECORD(node, struct j9100628a, jvs);
|
||||
|
||||
return j9100628a->addr == 0xFF;
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd(
|
||||
void *ctx,
|
||||
struct const_iobuf *req,
|
||||
struct iobuf *resp)
|
||||
{
|
||||
struct j9100628a *j9100628a;
|
||||
|
||||
j9100628a = ctx;
|
||||
|
||||
switch (req->bytes[req->pos]) {
|
||||
case JVS_CMD_RESET:
|
||||
return j9100628a_cmd_reset(j9100628a, req);
|
||||
|
||||
case JVS_CMD_ASSIGN_ADDR:
|
||||
return j9100628a_cmd_assign_addr(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_READ_ID:
|
||||
return j9100628a_cmd_read_id(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_GET_CMD_VERSION:
|
||||
return j9100628a_cmd_get_cmd_version(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_GET_JVS_VERSION:
|
||||
return j9100628a_cmd_get_jvs_version(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_GET_COMM_VERSION:
|
||||
return j9100628a_cmd_get_comm_version(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_GET_FEATURES:
|
||||
return j9100628a_cmd_get_features(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_READ_MISC_SWITCHES:
|
||||
return j9100628a_cmd_read_misc_switches(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_TYPEX_READ_DIPSW:
|
||||
return j9100628a_cmd_read_dip_switches(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_TYPEX_POLL_AMIC:
|
||||
// FIXME: seperate func
|
||||
return j9100628a_cmd_read_dip_switches(j9100628a, req, resp);
|
||||
|
||||
case JVS_CMD_WRITE_GPIO:
|
||||
return j9100628a_cmd_write_gpio(j9100628a, req, resp);
|
||||
|
||||
default:
|
||||
dprintf("J9100628A: Node %02x: Unhandled command byte %02x\n",
|
||||
j9100628a->addr,
|
||||
req->bytes[req->pos]);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_reset(struct j9100628a *j9100628a, struct const_iobuf *req_buf)
|
||||
{
|
||||
struct jvs_req_reset req;
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read(req_buf, &req, sizeof(req));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
dprintf("J9100628A: Reset (param %02x)\n", req.unknown);
|
||||
j9100628a->addr = 0xFF;
|
||||
j9100628a->jvs.sense_out = false; // ?
|
||||
|
||||
if (j9100628a->ops->reset != NULL) {
|
||||
j9100628a->ops->reset(j9100628a->ops_ctx);
|
||||
}
|
||||
|
||||
/* No ack for this since it really is addressed to everybody */
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_assign_addr(
|
||||
struct j9100628a *j9100628a,
|
||||
struct const_iobuf *req_buf,
|
||||
struct iobuf *resp_buf)
|
||||
{
|
||||
struct jvs_req_assign_addr req;
|
||||
bool sense;
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read(req_buf, &req, sizeof(req));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
sense = jvs_node_sense(j9100628a->jvs.next);
|
||||
dprintf("J9100628A: Assign addr %02x sense %i\n", req.addr, sense);
|
||||
|
||||
if (sense) {
|
||||
/* That address is for somebody else */
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
j9100628a->addr = req.addr;
|
||||
j9100628a->jvs.sense_out = true;
|
||||
|
||||
return iobuf_write_8(resp_buf, 0x01);
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_read_id(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t req;
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read_8(req_buf, &req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
dprintf("JVS I/O: Read ID\n");
|
||||
|
||||
/* Write report byte */
|
||||
|
||||
hr = iobuf_write_8(resp_buf, 0x01);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Write the identification string. The NUL terminator at the end of this C
|
||||
string is also sent, and it naturally terminates the response chunk. */
|
||||
|
||||
return iobuf_write(resp_buf, j9100628a_ident, sizeof(j9100628a_ident));
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_get_cmd_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t req;
|
||||
uint8_t resp[2];
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read_8(req_buf, &req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
dprintf("JVS I/O: Get command format version\n");
|
||||
resp[0] = 0x01; /* Report byte */
|
||||
resp[1] = 0x13; /* Command format version BCD */
|
||||
|
||||
return iobuf_write(resp_buf, resp, sizeof(resp));
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_get_jvs_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t req;
|
||||
uint8_t resp[2];
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read_8(req_buf, &req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
dprintf("JVS I/O: Get JVS format version\n");
|
||||
resp[0] = 0x01; /* Report byte */
|
||||
resp[1] = 0x30; /* JVS format version BCD */
|
||||
|
||||
return iobuf_write(resp_buf, resp, sizeof(resp));
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_get_comm_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t req;
|
||||
uint8_t resp[2];
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read_8(req_buf, &req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
dprintf("JVS I/O: Get COMM format version\n");
|
||||
resp[0] = 0x01; /* Report byte */
|
||||
resp[1] = 0x10; /* COMM format version BCD */
|
||||
|
||||
return iobuf_write(resp_buf, resp, sizeof(resp));
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_get_features(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t req;
|
||||
uint8_t resp[2];
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read_8(req_buf, &req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
dprintf("JVS I/O: Get reader features\n");
|
||||
|
||||
hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return iobuf_write(resp_buf, j9100628a_features, sizeof(j9100628a_features));
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_read_misc_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t req;
|
||||
uint8_t resp[2];
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read_8(req_buf, &req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return iobuf_write_8(resp_buf, 0x00); /* Write switch byte */
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_read_dip_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t req;
|
||||
uint8_t resp[2];
|
||||
HRESULT hr;
|
||||
|
||||
hr = iobuf_read_8(req_buf, &req);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return iobuf_write_8(resp_buf, 0x00); /* Write switch byte */
|
||||
}
|
||||
|
||||
static HRESULT j9100628a_cmd_write_gpio(
|
||||
struct j9100628a *j9100628a,
|
||||
struct const_iobuf *req_buf,
|
||||
struct iobuf *resp_buf)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint8_t nbytes;
|
||||
uint8_t bytes[3];
|
||||
HRESULT hr;
|
||||
|
||||
/* Read request header */
|
||||
|
||||
hr = iobuf_read_8(req_buf, &cmd);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = iobuf_read_8(req_buf, &nbytes);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (nbytes > 3) {
|
||||
dprintf("J9100628A: Invalid GPIO write size %i\n", nbytes);
|
||||
hr = iobuf_write_8(resp_buf, 0x02);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
/* Read payload */
|
||||
|
||||
memset(bytes, 0, sizeof(bytes));
|
||||
hr = iobuf_read(req_buf, bytes, nbytes);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (j9100628a->ops->write_led != NULL) {
|
||||
j9100628a->ops->write_led(
|
||||
j9100628a->ops_ctx,
|
||||
bytes[0] | (bytes[1] << 8) | (bytes[2] << 16));
|
||||
}
|
||||
|
||||
/* Write report byte */
|
||||
|
||||
return iobuf_write_8(resp_buf, 0x01);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
|
||||
#include "jvs/jvs-bus.h"
|
||||
|
||||
struct j9100628a_ops {
|
||||
void (*reset)(void *ctx);
|
||||
void (*write_led)(void *ctx, uint32_t state);
|
||||
void (*poll_card)(void *ctx, char *serial);
|
||||
};
|
||||
|
||||
struct j9100628a {
|
||||
struct jvs_node jvs;
|
||||
uint8_t addr;
|
||||
const struct j9100628a_ops *ops;
|
||||
void *ops_ctx;
|
||||
};
|
||||
|
||||
void j9100628a_init(
|
||||
struct j9100628a *j9100628a,
|
||||
struct jvs_node *next,
|
||||
const struct j9100628a_ops *ops,
|
||||
void *ops_ctx);
|
||||
|
||||
struct jvs_node *j9100628a_to_jvs_node(struct j9100628a *j9100628a);
|
||||
@@ -15,6 +15,8 @@ board_lib = static_library(
|
||||
'guid.h',
|
||||
'io3.c',
|
||||
'io3.h',
|
||||
'j9100628a.c',
|
||||
'j9100628a.h',
|
||||
'io4.c',
|
||||
'io4.h',
|
||||
'sg-cmd.c',
|
||||
|
||||
@@ -231,3 +231,32 @@ If 1, hook the iDmacDrvxx.dll functions, otherwise create a fake device. Set to
|
||||
1 if you're using the stub included with this hook as a substitute for the real
|
||||
DLL. Both hooking methods lead to the same place, so it doesn't matter too much
|
||||
what you use.
|
||||
|
||||
## `[cert]`
|
||||
### `enable`
|
||||
|
||||
Default: 1
|
||||
|
||||
If 1, hooks functions related to server and client certificate processing.
|
||||
|
||||
### `server_cert`
|
||||
|
||||
Default: `cert/Server.pfx`
|
||||
|
||||
Location of the PKCS #12 file containing the certificates used to verify the server
|
||||
|
||||
### `client_cert`
|
||||
|
||||
Default: ``
|
||||
|
||||
Location of the PKCS #12 containing the certificates used by the client to do mTLS. If
|
||||
your data already came with a cert and the server you're connecting to doesn't use mTLS
|
||||
you can leave this blank to let the game use it's own (TODO verify)
|
||||
|
||||
### `insecure`
|
||||
|
||||
Default: 0
|
||||
|
||||
If 1, overrides `WinHttpSetOption`s `WINHTTP_OPTION_SECURITY_FLAGS` behavior to ignore almost all SSL errors.
|
||||
Useful for testing or if your server sysadmin is lazy. Should be disabled otherwise.
|
||||
|
||||
+59
-2
@@ -1,6 +1,63 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "idmac/fastio.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static struct fastio_node fio_main;
|
||||
static struct fastio_node fio_sub;
|
||||
|
||||
HRESULT fastio_hook_init(fastio_provider_t main, fastio_provider_t sub)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
struct fastio_node fio;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
dprintf("FastIO: Init main %p sub %p\n", main, sub);
|
||||
|
||||
if (main != NULL) {
|
||||
fio_main.board_no = 0; // Maybe 0 should be the PCB itself and connected IO boards start at 1?
|
||||
hr = main(&fio_main);
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (sub != NULL) {
|
||||
// TODO: Unsure if "sub" is treated as input from another box, or just a 2nd link in the chain
|
||||
//fio.next = (struct fastio_node *) malloc(sizeof(struct fastio_node));
|
||||
hr = sub(&fio_sub);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
/// Itterate over the chain of connected boards and return a pointer to the board with the requested number
|
||||
void fastio_match_board_number(uint8_t board_no, struct fastio_node root, struct fastio_node *board)
|
||||
{
|
||||
assert(&root != NULL);
|
||||
|
||||
board = &root;
|
||||
while (board->next != NULL && board->next->board_no != board_no) {
|
||||
board = board->next;
|
||||
}
|
||||
|
||||
if (board->board_no != board_no) {
|
||||
// We've exhausted our boards, give a warning and set boards to NULL
|
||||
dprintf("FastIO: Could not find board number %d\n", board_no);
|
||||
board = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void fastio_digital_read(void* ctx, uint8_t board_no, uint32_t *out)
|
||||
{
|
||||
struct fastio_node *req_board = NULL;
|
||||
fastio_match_board_number(board_no, fio_main, req_board);
|
||||
|
||||
// If we fail to find, or the board we found doesn't have the handler we need,
|
||||
// quietly return with out unmodified
|
||||
if (req_board != NULL && req_board->digital_in != NULL) {
|
||||
fio_main.digital_in(ctx, out);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-7
@@ -2,19 +2,23 @@
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct fastio_node {
|
||||
struct fastio_node *next;
|
||||
uint8_t board_no;
|
||||
// Unlike JVS, FastIO comms are done on the game side through
|
||||
// DMA register reads and writes, meaning we need to have
|
||||
// indivitual functions here instead of just "transact"
|
||||
void (*digital_in)(uint16_t *out); // Digital button inputs
|
||||
void (*analog_in)(uint16_t *out); // Analog stick inputs (WIP)
|
||||
void (*coins_in)(uint8_t slot, uint16_t *out); // Number of unprocessed coins
|
||||
void (*digital_out)(uint16_t channel, uint16_t val); // Digital outputs
|
||||
void (*analog_out)(uint16_t channel, uint16_t val); // Analog outputs (WIP)
|
||||
void (*coins_out)(uint8_t slot, uint16_t removed); // Remove coins from the count
|
||||
void (*digital_in)(void* ctx, uint32_t *out); // Digital button inputs
|
||||
void (*analog_in)(void* ctx, uint16_t *out); // Analog stick inputs (WIP)
|
||||
void (*coins_in)(void* ctx, uint8_t slot, uint32_t *out); // Number of unprocessed coins
|
||||
void (*digital_out)(void* ctx, uint16_t channel, uint16_t val); // Digital outputs
|
||||
void (*analog_out)(void* ctx, uint16_t channel, uint16_t val); // Analog outputs (WIP)
|
||||
void (*coins_out)(void* ctx, uint8_t slot, uint16_t removed); // Remove coins from the count
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef HRESULT (*fastio_provider_t)(struct fastio_node **root);
|
||||
typedef HRESULT (*fastio_provider_t)(struct fastio_node *root);
|
||||
|
||||
HRESULT fastio_hook_init(fastio_provider_t main, fastio_provider_t sub);
|
||||
void fastio_digital_read(void* ctx, uint8_t board_no, uint32_t *out);
|
||||
|
||||
+8
-3
@@ -172,7 +172,11 @@ HRESULT idmac_hook_init(const struct idmac_config *cfg, struct idmac_hardware *h
|
||||
return hr;
|
||||
}
|
||||
|
||||
fastio_hook_init(hardware->fastio_main, hardware->fastio_sub);
|
||||
hr = fastio_hook_init(hardware->fastio_main, hardware->fastio_sub);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
idmac_hook_table_apply(NULL);
|
||||
|
||||
@@ -312,9 +316,10 @@ static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* regist
|
||||
case 0x4004: *register_val = -2; break; // Status
|
||||
|
||||
case 0x4120: // JVS Buttons
|
||||
if (GetAsyncKeyState(VK_DELETE) & 0x8000) {
|
||||
/*if (GetAsyncKeyState(VK_DELETE) & 0x8000) {
|
||||
*register_val = 0x40; // Test
|
||||
}
|
||||
}*/
|
||||
fastio_digital_read(NULL, 0, (uint32_t *)register_val);
|
||||
break;
|
||||
|
||||
case 0x4124: break; // Analog 1
|
||||
|
||||
+36
-23
@@ -35,8 +35,16 @@ static CRITICAL_SECTION jvs_lock;
|
||||
static struct uart jvs_uart;
|
||||
static uint8_t jvs_written_bytes[516];
|
||||
static uint8_t jvs_readable_bytes[516];
|
||||
static uint8_t temp_bytes[516];
|
||||
static struct jvs_node *jvs_root;
|
||||
static jvs_provider_t jvs_provider;
|
||||
static struct iobuf tmp = {
|
||||
.nbytes = 516,
|
||||
.pos = 0,
|
||||
.bytes = temp_bytes
|
||||
};
|
||||
static bool last = false;
|
||||
static uint8_t num_cts = 0;
|
||||
|
||||
HRESULT jvs_hook_init(const struct jvs_config *cfg, jvs_provider_t provider)
|
||||
{
|
||||
@@ -100,35 +108,40 @@ static HRESULT jvs_handle_irp_locked(struct irp *irp)
|
||||
}
|
||||
}
|
||||
|
||||
if (irp->op == IRP_OP_IOCTL) {
|
||||
switch (irp->ioctl) {
|
||||
case IOCTL_SERIAL_GET_MODEMSTATUS:
|
||||
//jvs_uart.cts_on = jvs_root->sense_out;
|
||||
//dprintf("JVS: Set CTS to %X\n", jvs_root->sense_out);
|
||||
jvs_uart.cts_on = jvs_root->sense_out;
|
||||
break;
|
||||
case IOCTL_SERIAL_GET_COMMSTATUS:
|
||||
//dprintf("JVS: Set cbInQue to %d\n", (int)tmp.pos);
|
||||
jvs_uart.readable.pos = tmp.pos;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (irp->op == IRP_OP_READ) {
|
||||
if (irp->read.nbytes > 1) {
|
||||
//dprintf("JVS: Readable buffer is %d / %d\n", (int)irp->read.nbytes, (int)tmp.pos);
|
||||
iobuf_write(&irp->read, tmp.bytes, tmp.pos);
|
||||
tmp.pos = 0;
|
||||
} else {
|
||||
dprintf("JVS: Readable buffer is 1!\n");
|
||||
}
|
||||
}
|
||||
|
||||
hr = uart_handle_irp(&jvs_uart, irp);
|
||||
|
||||
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &irp->read);
|
||||
//jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &irp->read);
|
||||
jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &tmp);
|
||||
|
||||
#if 1
|
||||
dprintf("JVS Port: Inbound frame:\n");
|
||||
dump_iobuf(&irp->read);
|
||||
dprintf("\n");
|
||||
#endif
|
||||
jvs_uart.written.pos = 0;
|
||||
|
||||
if (irp->read.pos == 0) {
|
||||
/* The un-acked JVS reset command must return ERROR_NO_DATA_DETECTED,
|
||||
and this error must always be returned asynchronously. And since
|
||||
async I/O comes from the NT kernel, we have to return that win32
|
||||
error as the equivalent NTSTATUS. */
|
||||
|
||||
if (irp->ovl == NULL || irp->ovl->hEvent == NULL) {
|
||||
return HRESULT_FROM_WIN32(ERROR_NO_DATA_DETECTED);
|
||||
}
|
||||
|
||||
irp->ovl->Internal = STATUS_NO_DATA_DETECTED;
|
||||
SetEvent(irp->ovl->hEvent);
|
||||
|
||||
return HRESULT_FROM_WIN32(ERROR_IO_PENDING);
|
||||
} else {
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ struct jvs_node {
|
||||
size_t nbytes,
|
||||
struct iobuf *resp);
|
||||
bool (*sense)(struct jvs_node *node);
|
||||
bool sense_out;
|
||||
};
|
||||
|
||||
void jvs_bus_transact(
|
||||
|
||||
+15
-11
@@ -1,17 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
enum {
|
||||
JVS_CMD_READ_ID = 0x10,
|
||||
JVS_CMD_GET_CMD_VERSION = 0x11,
|
||||
JVS_CMD_GET_JVS_VERSION = 0x12,
|
||||
JVS_CMD_GET_COMM_VERSION = 0x13,
|
||||
JVS_CMD_GET_FEATURES = 0x14,
|
||||
JVS_CMD_READ_SWITCHES = 0x20,
|
||||
JVS_CMD_READ_COIN = 0x21,
|
||||
JVS_CMD_READ_ANALOGS = 0x22,
|
||||
JVS_CMD_WRITE_GPIO = 0x32,
|
||||
JVS_CMD_RESET = 0xF0,
|
||||
JVS_CMD_ASSIGN_ADDR = 0xF1,
|
||||
JVS_CMD_TYPEX_READ_DIPSW = 0x01,
|
||||
JVS_CMD_READ_ID = 0x10,
|
||||
JVS_CMD_GET_CMD_VERSION = 0x11,
|
||||
JVS_CMD_GET_JVS_VERSION = 0x12,
|
||||
JVS_CMD_GET_COMM_VERSION = 0x13,
|
||||
JVS_CMD_GET_FEATURES = 0x14,
|
||||
JVS_CMD_READ_SWITCHES = 0x20,
|
||||
JVS_CMD_READ_COIN = 0x21,
|
||||
JVS_CMD_READ_ANALOGS = 0x22,
|
||||
JVS_CMD_READ_MISC_SWITCHES = 0x26,
|
||||
JVS_CMD_WRITE_GPIO = 0x32,
|
||||
JVS_CMD_TYPEX_POLL_AMIC = 0x61,
|
||||
JVS_CMD_TYPEX_POLL_CARD = 0x66,
|
||||
JVS_CMD_RESET = 0xF0,
|
||||
JVS_CMD_ASSIGN_ADDR = 0xF1,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
@@ -14,6 +14,21 @@
|
||||
#include "util/dprintf.h"
|
||||
#include "util/str.h"
|
||||
|
||||
/*
|
||||
* There are 2 certs we care about within this hook, the client cert,
|
||||
* and server cert. The client cert is usually stored in a p12 file and
|
||||
* identifies the game cabinet, and what nesica plan the game should use
|
||||
* for billing. It's used in mTLS so the server can verify the client.
|
||||
* The server cert is used for SSL cert pinning so the client can verify
|
||||
* the server. Unless the server you're connecting to requires a proper
|
||||
* mTLS setup, you can pretty safely disregard the client cert as long as
|
||||
* it exists and the game can find it. The server cert is traditionally
|
||||
* gotten around by adding the server's CA cert to the PCs root store, but
|
||||
* that sucks for UX and is generally not a good idea, so this hook aims
|
||||
* to replace (or disable the need for, if able) the server cert without
|
||||
* having to mess with CA stores.
|
||||
*/
|
||||
|
||||
static CRITICAL_SECTION cert_lock;
|
||||
static wchar_t path[MAX_PATH];
|
||||
|
||||
|
||||
+19
-10
@@ -10,18 +10,21 @@
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void fastio_digital_read(void *ctx, struct io3_switch_state *out);
|
||||
static void fastio_coin_read(
|
||||
static void siva_fastio_digital_read(void *ctx, uint32_t *out);
|
||||
static void siva_fastio_coin_read(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out);
|
||||
uint32_t *out);
|
||||
|
||||
HRESULT siva_fastio_init(struct fastio_node **out)
|
||||
HRESULT siva_fastio_init(struct fastio_node *out)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
assert(out != NULL);
|
||||
|
||||
out->digital_in = siva_fastio_digital_read;
|
||||
out->coins_in = siva_fastio_coin_read;
|
||||
|
||||
dprintf("Siva Nesica Fastio: Init\n");
|
||||
|
||||
siva_dll.init();
|
||||
@@ -29,9 +32,15 @@ HRESULT siva_fastio_init(struct fastio_node **out)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void fastio_digital_read(void *ctx, struct io3_switch_state *out) {}
|
||||
static void fastio_coin_read(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out)
|
||||
{}
|
||||
static void siva_fastio_digital_read(void *ctx, uint32_t *out)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void siva_fastio_coin_read(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint32_t *out)
|
||||
{
|
||||
|
||||
}
|
||||
+1
-1
@@ -22,4 +22,4 @@ enum SIVA_SWITCH {
|
||||
SYS_COIN = 0x000001,
|
||||
};
|
||||
|
||||
HRESULT siva_fastio_init(struct fastio_node **out);
|
||||
HRESULT siva_fastio_init(struct fastio_node *out);
|
||||
|
||||
+18
-18
@@ -3,25 +3,22 @@
|
||||
|
||||
#include "jvs/jvs-bus.h"
|
||||
#include "idmac/jvs.h"
|
||||
#include "board/io3.h"
|
||||
#include "board/j9100628a.h"
|
||||
|
||||
#include "sivahook/reader.h"
|
||||
#include "sivahook/siva-dll.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void reader_jvs_read_switches(void *ctx, struct io3_switch_state *out);
|
||||
static void reader_jvs_read_coin_counter(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out);
|
||||
static void reader_jvs_write_led(void *ctx, uint32_t state);
|
||||
static void reader_jvs_poll_card(void *ctx, char *serial);
|
||||
|
||||
static const struct io3_ops siva_jvs_reader_ops = {
|
||||
.read_switches = reader_jvs_read_switches,
|
||||
.read_coin_counter = reader_jvs_read_coin_counter,
|
||||
static const struct j9100628a_ops siva_jvs_reader_ops = {
|
||||
.write_led = reader_jvs_write_led,
|
||||
.poll_card = reader_jvs_poll_card,
|
||||
};
|
||||
|
||||
static struct io3 siva_jvs_reader;
|
||||
static struct j9100628a siva_jvs_reader;
|
||||
|
||||
HRESULT siva_reader_init(struct jvs_node **out)
|
||||
{
|
||||
@@ -31,15 +28,18 @@ HRESULT siva_reader_init(struct jvs_node **out)
|
||||
|
||||
dprintf("Siva Nesica Reader: Init\n");
|
||||
|
||||
io3_init(&siva_jvs_reader, NULL, &siva_jvs_reader_ops, NULL);
|
||||
*out = io3_to_jvs_node(&siva_jvs_reader);
|
||||
j9100628a_init(&siva_jvs_reader, NULL, &siva_jvs_reader_ops, NULL);
|
||||
*out = j9100628a_to_jvs_node(&siva_jvs_reader);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void reader_jvs_read_switches(void *ctx, struct io3_switch_state *out) {}
|
||||
static void reader_jvs_read_coin_counter(
|
||||
void *ctx,
|
||||
uint8_t slot_no,
|
||||
uint16_t *out)
|
||||
{}
|
||||
static void reader_jvs_write_led(void *ctx, uint32_t state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void reader_jvs_poll_card(void *ctx, char *serial)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name)
|
||||
dns_hook_apply_hooks(result);
|
||||
netenv_hook_apply(result);
|
||||
idmac_hook_table_apply(result);
|
||||
iohook_apply_hooks(result);
|
||||
serial_hook_apply_hooks(result);
|
||||
clock_hook_insert_hooks(result);
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ void siva_io_config_load(struct siva_input_config *cfg, const wchar_t *filename)
|
||||
cfg->service = GetPrivateProfileIntW(L"jvs", L"service", VK_DELETE, filename);
|
||||
cfg->coin = GetPrivateProfileIntW(L"jvs", L"coin", VK_INSERT, filename);
|
||||
|
||||
cfg->is_xinput = GetPrivateProfileIntW(L"deck", L"deck", 0, filename);
|
||||
cfg->is_xinput = GetPrivateProfileIntW(L"deck", L"controller_type", 0, filename);
|
||||
cfg->xinput_player = GetPrivateProfileIntW(L"deck", L"controller_num", 0, filename);
|
||||
|
||||
cfg->btn_l = GetPrivateProfileIntW(L"deck", L"left_button", 'C', filename);
|
||||
|
||||
Reference in New Issue
Block a user