Files
djhackersdev_bemanitools/src/main/jbhook-util/p4io.c
T

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;
}