192 lines
4.0 KiB
C
192 lines
4.0 KiB
C
#define LOG_MODULE "jbhook-io"
|
|
|
|
#include <string.h>
|
|
|
|
#include "bemanitools/jbio.h"
|
|
|
|
#include "imports/avs.h"
|
|
|
|
#include "jbhook-util/p4io.h"
|
|
|
|
#include "p4io/cmd.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
static void jbhook_io_jamma2_read(void *resp, uint32_t nbytes);
|
|
static uint32_t jbhook_command_handle(
|
|
uint8_t cmd,
|
|
const void *payload,
|
|
uint32_t payload_len,
|
|
void *resp,
|
|
uint32_t resp_max_len);
|
|
|
|
static const struct p4ioemu_device_msg_hook jbhook_p4io_msg = {
|
|
.jamma2_read = jbhook_io_jamma2_read,
|
|
.command_handle = jbhook_command_handle,
|
|
.roundplug_read_id = NULL,
|
|
.roundplug_read_mem = NULL};
|
|
|
|
/*
|
|
0:0 ???
|
|
0:1 b2
|
|
0:2 b6
|
|
0:3 b10
|
|
0:4 b14
|
|
0:5 b1
|
|
0:6 b5
|
|
0:7 b9
|
|
|
|
1:0 ???
|
|
1:1 b4
|
|
1:2 b8
|
|
1:3 b12
|
|
1:4 b16
|
|
1:5 b3
|
|
1:6 b7
|
|
1:7 b11
|
|
|
|
2:0 b13
|
|
2:1 ???
|
|
2:2 ???
|
|
2:3 ???
|
|
2:4 b15
|
|
2:5 ???
|
|
2:6 ???
|
|
2:7 ???
|
|
|
|
3:0 coin
|
|
3:1 service
|
|
3:2 ???
|
|
3:3 ???
|
|
3:4 test
|
|
3:5 ???
|
|
3:6 ???
|
|
3:7 ???
|
|
*/
|
|
static const uint32_t jbhook_io_panel_mappings[] = {
|
|
(1 << 5),
|
|
(1 << 1),
|
|
(1 << 13),
|
|
(1 << 9),
|
|
(1 << 6),
|
|
(1 << 2),
|
|
(1 << 14),
|
|
(1 << 10),
|
|
(1 << 7),
|
|
(1 << 3),
|
|
(1 << 15),
|
|
(1 << 11),
|
|
(1 << 16),
|
|
(1 << 4),
|
|
(1 << 20),
|
|
(1 << 12),
|
|
};
|
|
|
|
static const uint32_t jbhook_io_sys_button_mappings[] = {
|
|
(1 << 28),
|
|
(1 << 25),
|
|
(1 << 24),
|
|
};
|
|
|
|
static void jbhook_io_jamma2_read(void *resp, uint32_t nbytes)
|
|
{
|
|
uint32_t inputs_out;
|
|
uint16_t panels;
|
|
uint8_t buttons;
|
|
|
|
/* lower three bytes low active, highest byte high active */
|
|
inputs_out = 0x00FFFFFF;
|
|
|
|
if (!jb_io_read_inputs()) {
|
|
log_warning("Reading inputs from jbio failed");
|
|
return;
|
|
}
|
|
|
|
panels = jb_io_get_panel_inputs();
|
|
buttons = jb_io_get_sys_inputs();
|
|
|
|
for (uint8_t i = 0; i < 16; i++) {
|
|
if (panels & (1 << i)) {
|
|
inputs_out &= ~jbhook_io_panel_mappings[i];
|
|
}
|
|
}
|
|
|
|
for (uint8_t i = 0; i < 3; i++) {
|
|
if (buttons & (1 << i)) {
|
|
inputs_out |= jbhook_io_sys_button_mappings[i];
|
|
}
|
|
}
|
|
|
|
// Single write to external/game managed buffer to reduce risk for
|
|
// inconsistent state/random input misfiring
|
|
*((uint32_t *) resp) = inputs_out;
|
|
}
|
|
|
|
static uint32_t jbhook_command_handle(
|
|
uint8_t cmd,
|
|
const void *payload,
|
|
uint32_t payload_len,
|
|
void *resp,
|
|
uint32_t resp_max_len)
|
|
{
|
|
switch (cmd) {
|
|
case P4IO_CMD_COINSTOCK: {
|
|
// on is 0x00, off is either 0x10 or 0x20 depending on whether it's
|
|
// during gameplay (0x10) or test menu (0x20). Both seem to have the
|
|
// same effect
|
|
jb_io_set_coin_blocker(*(uint8_t *) payload == 0x00);
|
|
|
|
// this actually returns the coinstock, don't care for it
|
|
memset(resp, 0, 4);
|
|
|
|
return 4;
|
|
}
|
|
|
|
case P4IO_CMD_SET_PORTOUT: {
|
|
const struct p4io_req_panel_mode *req =
|
|
(const struct p4io_req_panel_mode *) payload;
|
|
|
|
// always fallback to ALL if input is unknown
|
|
enum jb_io_panel_mode mode = JB_IO_PANEL_MODE_ALL;
|
|
|
|
if (req->is_single) {
|
|
switch (req->mode) {
|
|
case 0x0001:
|
|
mode = JB_IO_PANEL_MODE_TOP_LEFT;
|
|
break;
|
|
|
|
case 0x0000:
|
|
mode = JB_IO_PANEL_MODE_TOP_RIGHT;
|
|
break;
|
|
|
|
case 0x0101:
|
|
mode = JB_IO_PANEL_MODE_BOTTOM_LEFT;
|
|
break;
|
|
|
|
case 0x0100:
|
|
mode = JB_IO_PANEL_MODE_BOTTOM_RIGHT;
|
|
break;
|
|
|
|
default:
|
|
mode = JB_IO_PANEL_MODE_ALL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
jb_io_set_panel_mode(mode);
|
|
|
|
memset(resp, 0, 1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
default:
|
|
return 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
const struct p4ioemu_device_msg_hook *jbhook_p4io_init(void)
|
|
{
|
|
return &jbhook_p4io_msg;
|
|
}
|