JVS reader OK, fastio progress

This commit is contained in:
Hay1tsme
2025-01-31 06:07:46 -05:00
parent c2bed706f8
commit 112348ce38
16 changed files with 726 additions and 76 deletions
+485
View File
@@ -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);
}
+25
View File
@@ -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);
+2
View File
@@ -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',
+29
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+1
View File
@@ -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
View File
@@ -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)
+15
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
{
}
+1
View File
@@ -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
View File
@@ -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);