JVS: Fix multiple i/o board problems

Rotary encoders support for Virtua Golf and Shootout Pool
This commit is contained in:
Flyinghead 2018-10-16 15:34:45 +02:00
parent 7156a165e3
commit 2214af734f
2 changed files with 113 additions and 152 deletions

View File

@ -1384,6 +1384,7 @@ static string get_eeprom_file_path()
*/
bool coin_chute;
static int coin_count;
bool naomi_test_button = false;
struct maple_naomi_jamma;
@ -1416,11 +1417,8 @@ struct maple_naomi_jamma : maple_sega_controller
bool crazy_mode = false;
u8 jvs_repeat_request[32][256];
u32 jvs_repeat_length[32] = { 0 };
u8 jvs_receive_buffer[512];
u32 jvs_receive_length = 0;
u8 *jvs_msg_start = NULL;
u8 jvs_receive_buffer[32][258];
u32 jvs_receive_length[32] = { 0 };
maple_naomi_jamma()
{
@ -1434,47 +1432,10 @@ struct maple_naomi_jamma : maple_sega_controller
return MDT_NaomiJamma;
}
void jvs_recv8(u8 b)
u8 sense_line(u32 node_id)
{
if (jvs_receive_length < sizeof(jvs_receive_buffer))
jvs_receive_buffer[jvs_receive_length++] = b;
}
void jvs_recv32(u32 dw)
{
if (jvs_receive_length < sizeof(jvs_receive_buffer) - 3)
{
*((u32 *)&jvs_receive_buffer[jvs_receive_length]) = dw;
jvs_receive_length += 4;
}
}
void make_jvs_reply_buffer(u32 node_id, u32 channel)
{
jvs_msg_start = &jvs_receive_buffer[jvs_receive_length];
jvs_recv8(MDRS_JVSReply);
jvs_recv8(0x00);
jvs_recv8(0x20);
jvs_recv8(0x00); // length in dword
jvs_recv32(0xffffff16);
jvs_recv32(0xfffeff00);
jvs_recv32(0);
jvs_recv32(0);
jvs_recv8(0);
jvs_recv8(channel); // channel id
bool last_node = node_id == io_boards.size();
jvs_recv8(last_node ? 0x8E : 0x8F); // bit 0 is sense line level. If set during F1 <n>, more I/O boards need addressing
jvs_recv8(node_id); // node number
jvs_recv8(0x00); // 0: ok, 2: timeout, 3: dest node !=0, 4: checksum failed
jvs_recv8(0x00); // len of following data
}
void finish_jvs_reply_buffer()
{
u32 total_len = &jvs_receive_buffer[jvs_receive_length] - jvs_msg_start;
jvs_msg_start[25] = total_len - 26;
jvs_receive_length = ((jvs_receive_length - 1) / 4) * 4 + 4;
jvs_msg_start[3] = (&jvs_receive_buffer[jvs_receive_length] - jvs_msg_start) / 4 - 1;
return last_node ? 0x8E : 0x8F;
}
void send_jvs_message(u32 node_id, u32 channel, u32 length, u8 *data)
@ -1485,10 +1446,15 @@ struct maple_naomi_jamma : maple_sega_controller
u32 out_len = io_boards[node_id - 1]->handle_jvs_message(data, length, temp_buffer);
if (out_len > 0)
{
make_jvs_reply_buffer(node_id, channel);
memcpy(&jvs_receive_buffer[jvs_receive_length], temp_buffer, out_len);
jvs_receive_length += out_len;
finish_jvs_reply_buffer();
u8 *pbuf = &jvs_receive_buffer[channel][jvs_receive_length[channel]];
if (jvs_receive_length[channel] + out_len + 3 <= sizeof(jvs_receive_buffer[0]))
{
pbuf[0] = node_id;
pbuf[1] = 0x00; // 0: ok, 2: timeout, 3: dest node !=0, 4: checksum failed
pbuf[2] = out_len;
memcpy(&pbuf[3], temp_buffer, out_len);
jvs_receive_length[channel] += out_len + 3;
}
}
}
}
@ -1500,14 +1466,14 @@ struct maple_naomi_jamma : maple_sega_controller
{
memcpy(temp_buffer, data, length);
}
if (use_repeat && jvs_repeat_length[node_id - 1] > 0)
u32 repeat_len = jvs_repeat_request[node_id - 1][0];
if (use_repeat && repeat_len > 0)
{
memcpy(temp_buffer + length, jvs_repeat_request[node_id - 1], jvs_repeat_length[node_id - 1]);
length += jvs_repeat_length[node_id - 1];
memcpy(temp_buffer + length, &jvs_repeat_request[node_id - 1][1], repeat_len);
length += repeat_len;
}
if (node_id == ALL_NODES)
{
jvs_receive_length = 0;
for (int i = 0; i < io_boards.size(); i++)
send_jvs_message(i + 1, channel, length, temp_buffer);
}
@ -1515,6 +1481,41 @@ struct maple_naomi_jamma : maple_sega_controller
send_jvs_message(node_id, channel, length, temp_buffer);
}
bool receive_jvs_messages(u32 channel)
{
u32 dword_length = (jvs_receive_length[channel] + 0x10 + 3) / 4 + 1;
w8(MDRS_JVSReply);
w8(0x00);
w8(0x20);
if (jvs_receive_length[channel] == 0)
w8(0x05);
else
w8(dword_length);
w32(0xffffff16);
w32(0xffffff00);
w32(0);
w32(0);
if (jvs_receive_length[channel] == 0)
{
w32(0);
return false;
}
w8(0);
w8(channel);
bool last_node = jvs_receive_buffer[channel][0] == io_boards.size();
w8(last_node ? 0x8E : 0x8F); // bit 0 is sense line level. If set during F1 <n>, more I/O boards need addressing
memcpy(dma_buffer_out, jvs_receive_buffer[channel], jvs_receive_length[channel]);
dma_buffer_out += dword_length * 4 - 0x10 - 3;
*dma_count_out += dword_length * 4 - 0x10 - 3;
jvs_receive_length[channel] = 0;
return true;
}
void handle_86_subcommand()
{
if (dma_count_in == 0)
@ -1552,7 +1553,7 @@ struct maple_naomi_jamma : maple_sega_controller
node_id = dma_buffer_in[6];
len = dma_buffer_in[7];
cmd = &dma_buffer_in[8];
channel = dma_buffer_in[5];
channel = dma_buffer_in[5] & 0x1f;
}
else
{
@ -1565,11 +1566,11 @@ struct maple_naomi_jamma : maple_sega_controller
switch (subcode)
{
case 0x13: // Store repeated request
if (len > 0)
if (len > 0 && node_id > 0 && node_id <= 0x1f)
{
printf("JVS node %d: Storing %d cmd bytes\n", node_id, len);
memcpy(jvs_repeat_request[node_id - 1], cmd, len);
jvs_repeat_length[node_id - 1] = len;
jvs_repeat_request[node_id - 1][0] = len;
memcpy(&jvs_repeat_request[node_id - 1][1], cmd, len);
}
w8(MDRS_JVSReply);
w8(0);
@ -1582,76 +1583,53 @@ struct maple_naomi_jamma : maple_sega_controller
break;
case 0x15: // Receive JVS data
if (jvs_receive_length)
{
memcpy(dma_buffer_out, jvs_receive_buffer, jvs_receive_length);
dma_buffer_out += jvs_receive_length;
*dma_count_out += jvs_receive_length;
jvs_receive_length = 0;
}
else
{
w8(MDRS_JVSReply);
w8(0x00);
w8(0x20);
w8(0x00);
}
receive_jvs_messages(dma_buffer_in[1]);
break;
case 0x17: // Transmit without repeat
jvs_receive_length[channel] = 0;
send_jvs_messages(node_id, channel, false, len, cmd);
w8(MDRS_JVSReply);
w8(0);
w8(0x20);
w8(0x01);
w8(dma_buffer_in[0] + 1); // subcommand + 1
w8(0x18); // always
w8(channel);
w8(0x8E); //sense_line(node_id));
w8(0);
break;
case 0x19: // Transmit with repeat
case 0x21:
jvs_receive_length[channel] = 0;
send_jvs_messages(node_id, channel, true, len, cmd);
w8(MDRS_JVSReply);
w8(0);
w8(0x20);
w8(0x01);
w8(dma_buffer_in[0] + 1); // subcommand + 1
w8(0x18); // always
w8(channel);
w8(0);
w8(sense_line(node_id));
w8(0);
break;
case 0x35: // Receive then transmit with repeat (15 then 27)
if (jvs_receive_length)
{
memcpy(dma_buffer_out, jvs_receive_buffer, jvs_receive_length);
dma_buffer_out += jvs_receive_length;
*dma_count_out += jvs_receive_length;
jvs_receive_length = 0;
}
receive_jvs_messages(channel);
// FALLTHROUGH
case 0x27: // Transmit with repeat
{
jvs_receive_length[channel] = 0;
u32 cmd_count = dma_buffer_in[6];
u32 idx = 7;
for (int i = 0; i < cmd_count; i++)
{
node_id = dma_buffer_in[idx];
if (dma_buffer_in[idx + 1] == 0)
{
len = 0;
cmd = NULL;
idx += 2;
}
else
{
len = dma_buffer_in[idx + 2];
verify(len != 0xFF); // Need implementation
cmd = &dma_buffer_in[idx + 3];
idx += len + 3;
}
len = dma_buffer_in[idx + 1];
cmd = &dma_buffer_in[idx + 2];
idx += len + 2;
send_jvs_messages(node_id, channel, true, len, cmd);
}
@ -1661,26 +1639,21 @@ struct maple_naomi_jamma : maple_sega_controller
w8(0x01);
w8(0x26);
w8(channel);
w8(0);
w8(sense_line(node_id));
w8(0);
}
break;
case 0x33: // Receive then transmit with repeat (15 then 21)
if (jvs_receive_length)
{
memcpy(dma_buffer_out, jvs_receive_buffer, jvs_receive_length);
*dma_count_out += jvs_receive_length;
jvs_receive_length = 0;
}
receive_jvs_messages(channel);
send_jvs_messages(node_id, channel, true, len, cmd);
w8(MDRS_JVSReply);
w8(0);
w8(0x20);
w8(0x01);
w8(dma_buffer_in[0] + 1); // subcommand + 1
w8(0x18); // always
w8(channel);
w8(0);
w8(sense_line(node_id));
w8(0);
break;
@ -1781,11 +1754,6 @@ struct maple_naomi_jamma : maple_sega_controller
w8(0x0);
w8(0x0);
w8(0x0);
//CT
// w8(0x0);
// w8(0x0);
// w8(0x0);
// w8(0x0);
break;
default:
@ -1800,12 +1768,12 @@ struct maple_naomi_jamma : maple_sega_controller
virtual u32 RawDma(u32* buffer_in, u32 buffer_in_len, u32* buffer_out)
{
/*
#ifdef DUMP_JVS
printf("JVS IN: ");
u8 *p = (u8*)buffer_in;
for (int i = 0; i < buffer_in_len; i++) printf("%02x ", *p++);
printf("\n");
*/
#endif
u32 out_len = 0;
dma_buffer_out = (u8 *)buffer_out;
@ -1823,35 +1791,22 @@ struct maple_naomi_jamma : maple_sega_controller
case MDC_JVSUploadFirmware:
{
static FILE *fw_dump;
static u8 *ram;
static XXH32_state_t* state;
if (state == NULL)
{
state = XXH32_createState();
XXH32_reset(state, 0);
}
if (ram == NULL)
ram = (u8 *)calloc(0x10000, 1);
if (dma_buffer_in[1] == 0xff)
{
XXH32_hash_t hash = XXH32_digest(state);
u32 hash = XXH32(ram, 0x10000, 0);
LOGJVS("JVS Firmware hash %08x\n", hash);
if (hash == 0xEF29B145)
if (hash == 0xa7c50459)
crazy_mode = true;
else
crazy_mode = false;
XXH32_freeState(state);
state = NULL;
if (fw_dump)
fclose(fw_dump);
fw_dump = NULL;
return MDRS_DeviceReply;
}
#ifdef DUMP_JVS_FW
if (fw_dump == NULL)
{
FILE *fw_dump;
char filename[128];
for (int i = 0; ; i++)
{
@ -1864,22 +1819,24 @@ struct maple_naomi_jamma : maple_sega_controller
break;
}
}
if (fw_dump)
{
fwrite(ram, 1, 0x10000, fw_dump);
fclose(fw_dump);
}
#endif
free(ram);
ram = NULL;
return MDRS_DeviceReply;
}
int xfer_bytes;
if (dma_buffer_in[0] == 0xff)
xfer_bytes = 0x1C;
else
xfer_bytes = 0x18;
u16 addr = (dma_buffer_in[2] << 8) + dma_buffer_in[3];
XXH32_update(state, &dma_buffer_in[4], xfer_bytes);
#ifdef DUMP_JVS_FW
if (fw_dump)
{
fseek(fw_dump, addr, SEEK_SET);
fwrite(&dma_buffer_in[4], 1, xfer_bytes, fw_dump);
}
#endif
memcpy(ram + addr, &dma_buffer_in[4], xfer_bytes);
u8 sum = 0;
for (int i = 0; i < 0x1C; i++)
sum += dma_buffer_in[i];
@ -1922,10 +1879,7 @@ struct maple_naomi_jamma : maple_sega_controller
w8(MDRS_DeviceStatus);
w8(0x00);
w8(0x20);
w8(0x00); // CT
// w8(0x01);
//
// w32(2);
w8(0x00);
break;
@ -1946,12 +1900,13 @@ struct maple_naomi_jamma : maple_sega_controller
break;
}
/*
#ifdef DUMP_JVS
printf("JVS OUT: ");
p = (u8 *)buffer_out;
for (int i = 0; i < out_len; i++) printf("%02x ", p[i]);
printf("\n");
*/
#endif
return out_len;
}
@ -1959,7 +1914,6 @@ struct maple_naomi_jamma : maple_sega_controller
virtual bool maple_serialize(void **data, unsigned int *total_size)
{
REICAST_S(crazy_mode);
REICAST_S(jvs_repeat_length);
REICAST_S(jvs_repeat_request);
REICAST_S(jvs_receive_length);
REICAST_S(jvs_receive_buffer);
@ -1974,7 +1928,6 @@ struct maple_naomi_jamma : maple_sega_controller
virtual bool maple_unserialize(void **data, unsigned int *total_size)
{
REICAST_US(crazy_mode);
REICAST_US(jvs_repeat_length);
REICAST_US(jvs_repeat_request);
REICAST_US(jvs_receive_length);
REICAST_US(jvs_receive_buffer);
@ -2019,8 +1972,11 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
case 0x10: // Read ID data
JVS_STATUS1(); // status
JVS_STATUS1(); // report
static char ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10";
for (char *p = ID; *p != 0; )
const static char ID_837_13551[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10";
const static char ID_837_13938[] = "SEGA ENTERPRISES,LTD.;837-13938 ENCORDER BD ;Ver0.01;99/08"; // Virtua Golf, Outtrigger, Shootout Pool
const static char ID_837_13844[] = "SEGA ENTERPRISES,LTD.;837-13844-01 I/O CNTL BD2 ;Ver1.00;99/07"; // Sega Marine Fishing
for (const char *p = rotary_encoders ? ID_837_13938 : ID_837_13551; *p != 0; )
JVS_OUT(*p++);
JVS_OUT(0);
break;
@ -2082,7 +2038,7 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
// JVS_OUT(1); // 1 channel
JVS_OUT(0x12); // General output driver
JVS_OUT(6); // 6 outputs
JVS_OUT(rotary_encoders ? 8 : 6); // 6 outputs
JVS_OUT(0);
JVS_OUT(0);
@ -2116,7 +2072,7 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
JVS_STATUS1(); // report byte
LOGJVS("btns ");
JVS_OUT((kcode[0] & 1) ? 0 : 0x80); // test, tilt1, tilt2, tilt3, unused, unused, unused, unused
JVS_OUT(naomi_test_button ? 0x80 : 0x00); // test, tilt1, tilt2, tilt3, unused, unused, unused, unused
// FIXME in-lst mapping
u8 buttons[8] = { 0 };
u32 keycode = ~kcode[0];
@ -2238,7 +2194,7 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
static s16 rotx = 0;
static s16 roty = 0;
rotx += mo_x_delta * 5;
roty += mo_y_delta * 5;
roty -= mo_y_delta * 5;
mo_x_delta = 0;
mo_y_delta = 0;
LOGJVS("rotenc ");
@ -2259,8 +2215,8 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
else
{
LOGJVS("%d:%4x ", chan, 0);
JVS_OUT(0x80); // MSB
JVS_OUT(0x80); // LSB
JVS_OUT(0x00); // MSB
JVS_OUT(0x00); // LSB
}
}
cmdi += 2;

View File

@ -42,6 +42,7 @@ Atom wmDeleteMessage;
void* x11_vis;
extern bool dump_frame_switch;
extern bool naomi_test_button;
void dc_stop(void);
bool dc_loadstate(void);
@ -440,6 +441,10 @@ void input_x11_handle()
{
coin_chute = true;
}
else if (e.xkey.keycode == KEY_F7)
{
naomi_test_button = e.type == KeyPress;
}
#endif
else
{