JVS: refactoring to be closer to actual hardware
Returns multiple JVS messages at once Multiple I/O boards correctly handled Jambo Safari playable Virtua Golf boots
This commit is contained in:
parent
82e0fc7f60
commit
2c4e68ff9f
|
@ -1338,9 +1338,6 @@ extern u8 rt[4], lt[4];
|
|||
char EEPROM[0x100];
|
||||
bool EEPROM_loaded = false;
|
||||
|
||||
_NaomiState State;
|
||||
|
||||
|
||||
enum NAOMI_KEYS
|
||||
{
|
||||
NAOMI_SERVICE_KEY_1 = 1 << 0,
|
||||
|
@ -1409,14 +1406,13 @@ struct maple_naomi_jamma;
|
|||
class jvs_io_board
|
||||
{
|
||||
public:
|
||||
jvs_io_board(u8 node_id, bool last_node, maple_naomi_jamma *parent)
|
||||
jvs_io_board(u8 node_id, maple_naomi_jamma *parent)
|
||||
{
|
||||
this->node_id = node_id;
|
||||
this->last_node = last_node;
|
||||
this->parent = parent;
|
||||
}
|
||||
|
||||
MapleDeviceRV handle_jvs_command(u8* data);
|
||||
u32 handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_out);
|
||||
bool maple_serialize(void **data, unsigned int *total_size);
|
||||
bool maple_unserialize(void **data, unsigned int *total_size);
|
||||
|
||||
|
@ -1424,31 +1420,29 @@ public:
|
|||
bool lightgun_as_analog = false;
|
||||
|
||||
private:
|
||||
void make_jvs_reply_buffer(bool empty = false);
|
||||
void finish_jvs_reply_buffer();
|
||||
|
||||
const u8 ALL_NODES = 0xff;
|
||||
u8 node_id = 0;
|
||||
bool last_node;
|
||||
maple_naomi_jamma *parent;
|
||||
|
||||
u8 jvs_repeat_request[256];
|
||||
u32 jvs_repeat_length = 0;
|
||||
u8 jvs_request[256];
|
||||
u32 jvs_length = 0;
|
||||
u8 *dma_out = NULL;
|
||||
};
|
||||
|
||||
struct maple_naomi_jamma : maple_sega_controller
|
||||
{
|
||||
class jvs_io_board *io_boards[1];
|
||||
const u8 ALL_NODES = 0xff;
|
||||
|
||||
std::vector<jvs_io_board *> io_boards;
|
||||
bool crazy_mode = false;
|
||||
|
||||
u8 jvs_repeat_request[256];
|
||||
u32 jvs_repeat_length = 0;
|
||||
u8 jvs_receive_buffer[512];
|
||||
u32 jvs_receive_length = 0;
|
||||
|
||||
u8 *jvs_msg_start = NULL;
|
||||
|
||||
maple_naomi_jamma()
|
||||
{
|
||||
io_boards[0] = new jvs_io_board(1, true, this);
|
||||
// io_boards[1] = new jvs_io_board(2, true, this);
|
||||
// io_boards[0]->rotary_encoders = true;
|
||||
io_boards.push_back(new jvs_io_board(1, this));
|
||||
// io_boards.back()->rotary_encoders = true;
|
||||
// io_boards.push_back(new jvs_io_board(2, this));
|
||||
}
|
||||
|
||||
virtual MapleDeviceType get_device_type()
|
||||
|
@ -1456,49 +1450,217 @@ struct maple_naomi_jamma : maple_sega_controller
|
|||
return MDT_NaomiJamma;
|
||||
}
|
||||
|
||||
virtual u32 RawDma(u32* buffer_in, u32 buffer_in_len, u32* buffer_out)
|
||||
void jvs_recv8(u8 b)
|
||||
{
|
||||
/*
|
||||
printf("JVS IN: ");
|
||||
u8 *p = (u8*)buffer_in;
|
||||
for (int i = 0; i < buffer_in_len; i++) printf("%02x ", *p++);
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
u32 out_len = 0;
|
||||
dma_buffer_out = (u8 *)buffer_out;
|
||||
dma_count_out = &out_len;
|
||||
|
||||
dma_buffer_in = (u8 *)buffer_in + 4;
|
||||
dma_count_in = buffer_in_len - 4;
|
||||
|
||||
u32 cmd = *(u8*)buffer_in;
|
||||
switch (cmd)
|
||||
if (jvs_receive_length < sizeof(jvs_receive_buffer))
|
||||
jvs_receive_buffer[jvs_receive_length++] = b;
|
||||
}
|
||||
void jvs_recv32(u32 dw)
|
||||
{
|
||||
case MDC_JVSCommand:
|
||||
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(0xffffffff);
|
||||
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_length / 4 - 1;
|
||||
}
|
||||
|
||||
void send_jvs_message(u32 node_id, u32 channel, u32 length, u8 *data)
|
||||
{
|
||||
if (node_id - 1 < io_boards.size())
|
||||
{
|
||||
u8 temp_buffer[256];
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_jvs_messages(u32 node_id, u32 channel, bool use_repeat, u32 length, u8 *data)
|
||||
{
|
||||
u8 temp_buffer[256];
|
||||
if (data)
|
||||
{
|
||||
memcpy(temp_buffer, data, length);
|
||||
}
|
||||
if (use_repeat && jvs_repeat_length > 0)
|
||||
{
|
||||
memcpy(temp_buffer + length, jvs_repeat_request, jvs_repeat_length);
|
||||
length += jvs_repeat_length;
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
send_jvs_message(node_id, channel, length, temp_buffer);
|
||||
}
|
||||
|
||||
void handle_86_subcommand()
|
||||
{
|
||||
u32 subcode = dma_buffer_in[0];
|
||||
|
||||
switch (subcode) // Sub-command
|
||||
// CT fw uses 13 as a 17, and 17 as 13 and also uses 19
|
||||
if (crazy_mode)
|
||||
{
|
||||
switch (subcode)
|
||||
{
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
subcode = 0x17;
|
||||
break;
|
||||
case 0x17:
|
||||
case 0x19:
|
||||
case 0x21:
|
||||
case 0x27:
|
||||
case 0x33:
|
||||
{
|
||||
MapleDeviceRV rc;
|
||||
for (int i = 0; i < sizeof(io_boards)/sizeof(void*); i++)
|
||||
{
|
||||
rc = io_boards[i]->handle_jvs_command(dma_buffer_in);
|
||||
if (rc != MDRS_JVSNone)
|
||||
subcode = 0x13;
|
||||
break;
|
||||
}
|
||||
}
|
||||
u8 node_id = 0;
|
||||
u8 *cmd = NULL;
|
||||
u32 len = 0;
|
||||
u8 channel = 0;
|
||||
if (dma_count_in >= 3)
|
||||
{
|
||||
if (dma_buffer_in[1] > 31 && dma_buffer_in[1] != 0xff && dma_count_in >= 8) // TODO what is this?
|
||||
{
|
||||
node_id = dma_buffer_in[6];
|
||||
len = dma_buffer_in[7];
|
||||
cmd = &dma_buffer_in[8];
|
||||
channel = dma_buffer_in[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
node_id = dma_buffer_in[1];
|
||||
len = dma_buffer_in[2];
|
||||
cmd = &dma_buffer_in[3];
|
||||
}
|
||||
}
|
||||
|
||||
switch (subcode)
|
||||
{
|
||||
case 0x13: // Store repeated request
|
||||
if (len > 0)
|
||||
{
|
||||
printf("JVS node %d: Storing %d cmd bytes\n", node_id, len);
|
||||
memcpy(jvs_repeat_request, cmd, len);
|
||||
jvs_repeat_length = len;
|
||||
}
|
||||
w8(MDRS_JVSReply);
|
||||
w8(0);
|
||||
w8(0x20);
|
||||
w8(0x01);
|
||||
w8(dma_buffer_in[0] + 1); // subcommand + 1
|
||||
w8(0);
|
||||
w8(len + 1);
|
||||
w8(0);
|
||||
break;
|
||||
|
||||
case 0x15: // Receive JVS data
|
||||
if (jvs_receive_length)
|
||||
{
|
||||
memcpy(dma_buffer_out, jvs_receive_buffer, jvs_receive_length);
|
||||
*dma_count_out += jvs_receive_length;
|
||||
jvs_receive_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
w8(MDRS_JVSReply);
|
||||
w8(0x00);
|
||||
w8(0x20);
|
||||
w8(0x00);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x17: // Transmit without repeat
|
||||
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(channel);
|
||||
w8(0);
|
||||
w8(0);
|
||||
break;
|
||||
|
||||
case 0x19: // Transmit with repeat
|
||||
case 0x21:
|
||||
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(channel);
|
||||
w8(0);
|
||||
w8(0);
|
||||
break;
|
||||
|
||||
case 0x27: // Transmit with repeat
|
||||
node_id = cmd[-1];
|
||||
len = cmd[0];
|
||||
cmd++;
|
||||
|
||||
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(channel);
|
||||
w8(0);
|
||||
w8(0);
|
||||
break;
|
||||
|
||||
case 0x33: // Receive then transmit with repeat
|
||||
if (jvs_receive_length)
|
||||
{
|
||||
memcpy(dma_buffer_out, jvs_receive_buffer, jvs_receive_length);
|
||||
*dma_count_out += jvs_receive_length;
|
||||
jvs_receive_length = 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(channel);
|
||||
w8(0);
|
||||
w8(0);
|
||||
break;
|
||||
|
||||
case 0x0B: //EEPROM write
|
||||
|
@ -1526,7 +1688,7 @@ struct maple_naomi_jamma : maple_sega_controller
|
|||
w8(0x00);
|
||||
w8(0x01);
|
||||
memcpy(dma_buffer_out, EEPROM, 4);
|
||||
out_len += 4;
|
||||
*dma_buffer_out += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1556,7 +1718,7 @@ struct maple_naomi_jamma : maple_sega_controller
|
|||
w8(0x00);
|
||||
w8(0x20);
|
||||
memcpy(dma_buffer_out, EEPROM + address, 0x80);
|
||||
out_len += 0x80;
|
||||
*dma_buffer_out += 0x80;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1603,8 +1765,29 @@ struct maple_naomi_jamma : maple_sega_controller
|
|||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
virtual u32 RawDma(u32* buffer_in, u32 buffer_in_len, u32* buffer_out)
|
||||
{
|
||||
/*
|
||||
printf("JVS IN: ");
|
||||
u8 *p = (u8*)buffer_in;
|
||||
for (int i = 0; i < buffer_in_len; i++) printf("%02x ", *p++);
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
u32 out_len = 0;
|
||||
dma_buffer_out = (u8 *)buffer_out;
|
||||
dma_count_out = &out_len;
|
||||
|
||||
dma_buffer_in = (u8 *)buffer_in + 4;
|
||||
dma_count_in = buffer_in_len - 4;
|
||||
|
||||
u32 cmd = *(u8*)buffer_in;
|
||||
switch (cmd)
|
||||
{
|
||||
case MDC_JVSCommand:
|
||||
handle_86_subcommand();
|
||||
break;
|
||||
|
||||
case MDC_JVSUploadFirmware:
|
||||
{
|
||||
|
@ -1730,14 +1913,26 @@ struct maple_naomi_jamma : maple_sega_controller
|
|||
|
||||
break;
|
||||
}
|
||||
/*
|
||||
printf("JVS OUT: ");
|
||||
p = (u8 *)buffer_out;
|
||||
for (int i = 0; i < out_len; i++) printf("%02x ", p[i]);
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
return out_len;
|
||||
}
|
||||
|
||||
virtual bool maple_serialize(void **data, unsigned int *total_size)
|
||||
{
|
||||
// FIXME Should serialize count and rebuild dynamically
|
||||
for (int i = 0; i < sizeof(io_boards)/sizeof(void*); i++)
|
||||
REICAST_S(crazy_mode);
|
||||
REICAST_S(jvs_repeat_length);
|
||||
REICAST_SA(jvs_repeat_request, sizeof(jvs_repeat_request));
|
||||
REICAST_S(jvs_receive_length);
|
||||
REICAST_SA(jvs_receive_buffer, sizeof(jvs_receive_buffer));
|
||||
size_t board_count = io_boards.size();
|
||||
REICAST_S(board_count);
|
||||
for (int i = 0; i < io_boards.size(); i++)
|
||||
io_boards[i]->maple_serialize(data, total_size);
|
||||
|
||||
return true ;
|
||||
|
@ -1745,133 +1940,121 @@ struct maple_naomi_jamma : maple_sega_controller
|
|||
|
||||
virtual bool maple_unserialize(void **data, unsigned int *total_size)
|
||||
{
|
||||
for (int i = 0; i < sizeof(io_boards)/sizeof(void*); i++)
|
||||
io_boards[i]->maple_unserialize(data, total_size);
|
||||
REICAST_US(crazy_mode);
|
||||
REICAST_US(jvs_repeat_length);
|
||||
REICAST_USA(jvs_repeat_request, sizeof(jvs_repeat_request));
|
||||
REICAST_US(jvs_receive_length);
|
||||
REICAST_USA(jvs_receive_buffer, sizeof(jvs_receive_buffer));
|
||||
size_t board_count;
|
||||
REICAST_US(board_count);
|
||||
for (int i = 0; i < board_count; i++)
|
||||
{
|
||||
io_boards.push_back(new jvs_io_board(i + 1, this));
|
||||
io_boards.back()->maple_unserialize(data, total_size);
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
};
|
||||
|
||||
#define JVS_OUT(b) buffer_out[length++] = b
|
||||
#define JVS_STATUS1() JVS_OUT(1)
|
||||
|
||||
MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
||||
u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_out)
|
||||
{
|
||||
MapleDeviceRV rc;
|
||||
u8 jvs_cmd = buffer_in[0];
|
||||
if (jvs_cmd == 0xF0) // JVS reset
|
||||
// Nothing to do
|
||||
return 0;
|
||||
if (jvs_cmd == 0xF1 && (length_in < 2 || buffer_in[1] != node_id))
|
||||
// Not for us
|
||||
return 0;
|
||||
|
||||
u8 req = data[0];
|
||||
if (req == 0x15 || req == 0x33) // Receive
|
||||
{
|
||||
if (req == 0x15 && jvs_length == 0)
|
||||
{
|
||||
return MDRS_JVSNone;
|
||||
}
|
||||
u32 length = 0;
|
||||
JVS_OUT(0xE0); // sync
|
||||
JVS_OUT(0); // master node id
|
||||
u8& jvs_length = buffer_out[length++];
|
||||
|
||||
if (jvs_length > 0)
|
||||
switch (jvs_cmd)
|
||||
{
|
||||
switch (jvs_request[0])
|
||||
{
|
||||
case 0xF0: // board reset
|
||||
// We shouln't get there
|
||||
rc = MDRS_JVSNone;
|
||||
break;
|
||||
|
||||
case 0xF1: // set board address
|
||||
if (jvs_request[1] == node_id)
|
||||
{
|
||||
// That's our node number
|
||||
make_jvs_reply_buffer();
|
||||
parent->w8(1); // report byte
|
||||
finish_jvs_reply_buffer();
|
||||
JVS_STATUS1(); // status
|
||||
JVS_STATUS1(); // report
|
||||
LOGJVS("JVS Node %d address assigned\n", node_id);
|
||||
rc = MDRS_JVSReply;
|
||||
}
|
||||
else
|
||||
rc = MDRS_JVSNone;
|
||||
break;
|
||||
|
||||
case 0x10: // Read ID data
|
||||
make_jvs_reply_buffer();
|
||||
parent->w8(1); // report byte
|
||||
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; )
|
||||
parent->w8(*p++);
|
||||
parent->w8(0);
|
||||
finish_jvs_reply_buffer();
|
||||
rc = MDRS_JVSReply;
|
||||
JVS_OUT(*p++);
|
||||
JVS_OUT(0);
|
||||
break;
|
||||
|
||||
case 0x11: // Get command format version
|
||||
make_jvs_reply_buffer();
|
||||
parent->w8(1); // report byte
|
||||
parent->w8(0x13); // 1.3
|
||||
finish_jvs_reply_buffer();
|
||||
rc = MDRS_JVSReply;
|
||||
JVS_STATUS1();
|
||||
JVS_STATUS1();
|
||||
JVS_OUT(0x13); // 1.3
|
||||
break;
|
||||
|
||||
case 0x12: // Get JVS versionjamma
|
||||
make_jvs_reply_buffer();
|
||||
parent->w8(1); // report byte
|
||||
parent->w8(0x30); // 3.0
|
||||
finish_jvs_reply_buffer();
|
||||
rc = MDRS_JVSReply;
|
||||
case 0x12: // Get JAMMA VIDEO version
|
||||
JVS_STATUS1();
|
||||
JVS_STATUS1();
|
||||
JVS_OUT(0x30); // 3.0
|
||||
break;
|
||||
|
||||
case 0x13: // Get communication version
|
||||
make_jvs_reply_buffer();
|
||||
parent->w8(1); // report byte
|
||||
parent->w8(0x10); // 1.0
|
||||
finish_jvs_reply_buffer();
|
||||
rc = MDRS_JVSReply;
|
||||
JVS_STATUS1();
|
||||
JVS_STATUS1();
|
||||
JVS_OUT(0x10); // 1.0
|
||||
break;
|
||||
|
||||
case 0x14: // Get slave features
|
||||
make_jvs_reply_buffer();
|
||||
parent->w8(1); // report byte
|
||||
JVS_STATUS1();
|
||||
JVS_STATUS1();
|
||||
|
||||
parent->w8(1); // Digital inputs
|
||||
parent->w8(2); // 2 players
|
||||
parent->w8(13); // 13 bits
|
||||
parent->w8(0);
|
||||
JVS_OUT(1); // Digital inputs
|
||||
JVS_OUT(2); // 2 players
|
||||
JVS_OUT(13); // 13 bits
|
||||
JVS_OUT(0);
|
||||
|
||||
parent->w8(2); // Coin inputs
|
||||
parent->w8(2); // 2 inputs
|
||||
parent->w8(0);
|
||||
parent->w8(0);
|
||||
JVS_OUT(2); // Coin inputs
|
||||
JVS_OUT(2); // 2 inputs
|
||||
JVS_OUT(0);
|
||||
JVS_OUT(0);
|
||||
|
||||
parent->w8(3); // Analog inputs
|
||||
parent->w8(4); // 4 channels
|
||||
parent->w8(0); // bits per channel, 0: unknown
|
||||
parent->w8(0);
|
||||
JVS_OUT(3); // Analog inputs
|
||||
JVS_OUT(4); // 4 channels
|
||||
JVS_OUT(0); // bits per channel, 0: unknown
|
||||
JVS_OUT(0);
|
||||
|
||||
if (rotary_encoders)
|
||||
{
|
||||
parent->w8(4); // Rotary encoders
|
||||
parent->w8(2); // 2 channels
|
||||
parent->w8(0);
|
||||
parent->w8(0);
|
||||
JVS_OUT(4); // Rotary encoders
|
||||
JVS_OUT(2); // 2 channels
|
||||
JVS_OUT(0);
|
||||
JVS_OUT(0);
|
||||
}
|
||||
|
||||
// parent->w8(6); // Light gun
|
||||
// parent->w8(16); // X bits
|
||||
// parent->w8(16); // Y bits
|
||||
// parent->w8(1); // 1 channel
|
||||
// JVS_OUT(6); // Light gun
|
||||
// JVS_OUT(16); // X bits
|
||||
// JVS_OUT(16); // Y bits
|
||||
// JVS_OUT(1); // 1 channel
|
||||
|
||||
parent->w8(0); // End of list
|
||||
parent->w8(0);
|
||||
parent->w8(0);
|
||||
parent->w8(0);
|
||||
finish_jvs_reply_buffer();
|
||||
rc = MDRS_JVSReply;
|
||||
JVS_OUT(0); // End of list
|
||||
JVS_OUT(0);
|
||||
JVS_OUT(0);
|
||||
JVS_OUT(0);
|
||||
break;
|
||||
|
||||
case 0x15: // Master board ID
|
||||
make_jvs_reply_buffer();
|
||||
parent->w8(1); // report byte
|
||||
finish_jvs_reply_buffer();
|
||||
rc = MDRS_JVSReply;
|
||||
JVS_STATUS1();
|
||||
JVS_STATUS1();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (jvs_request[0] >= 0x20 && jvs_request[0] <= 0x38) // Read inputs and more
|
||||
if (jvs_cmd >= 0x20 && jvs_cmd <= 0x38) // Read inputs and more
|
||||
{
|
||||
LOGJVS("JVS Node %d: ", node_id);
|
||||
PlainJoystickState pjs;
|
||||
|
@ -1879,17 +2062,17 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
u32 keycode = ~kcode[0];
|
||||
u32 keycode2 = ~kcode[1];
|
||||
|
||||
make_jvs_reply_buffer();
|
||||
for (int cmdi = 0; cmdi < jvs_length; )
|
||||
JVS_STATUS1(); // status
|
||||
for (int cmdi = 0; cmdi < length_in; )
|
||||
{
|
||||
switch (jvs_request[cmdi])
|
||||
switch (buffer_in[cmdi])
|
||||
{
|
||||
case 0x20: // Read digital input
|
||||
{
|
||||
parent->w8(1); // report byte
|
||||
JVS_STATUS1(); // report byte
|
||||
|
||||
LOGJVS("btns ");
|
||||
parent->w8((kcode[0] & 1) ? 0 : 0x80); // test, tilt1, tilt2, tilt3, unused, unused, unused, unused
|
||||
JVS_OUT((kcode[0] & 1) ? 0 : 0x80); // test, tilt1, tilt2, tilt3, unused, unused, unused, unused
|
||||
// FIXME in-lst mapping
|
||||
u8 buttons[8] = { 0 };
|
||||
u32 keycode = ~kcode[0];
|
||||
|
@ -1898,24 +2081,24 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
{
|
||||
buttons[Naomi_Mapping.button_mapping_byte[i]] |= Naomi_Mapping.button_mapping_mask[i];
|
||||
}
|
||||
for (int player = 0; player < jvs_request[cmdi + 1]; player++)
|
||||
for (int player = 0; player < buffer_in[cmdi + 1]; player++)
|
||||
{
|
||||
LOGJVS("P%d %02x ", player + 1, buttons[player * 2]);
|
||||
parent->w8(buttons[player * 2]);
|
||||
if (jvs_request[cmdi + 2] == 2)
|
||||
JVS_OUT(buttons[player * 2]);
|
||||
if (buffer_in[cmdi + 2] == 2)
|
||||
{
|
||||
LOGJVS("%02x ", buttons[player * 2 + 1]);
|
||||
parent->w8(buttons[player * 2 + 1]);
|
||||
JVS_OUT(buttons[player * 2 + 1]);
|
||||
}
|
||||
}
|
||||
// for (int player = 0; player < jvs_request[cmdi + 1]; player++)
|
||||
// for (int player = 0; player < jvs_request[channel][cmdi + 1]; player++)
|
||||
// {
|
||||
// u32 keycode = ~kcode[player];
|
||||
// if (keycode & DC_BTN_C)
|
||||
// keycode |= 0xFFff;
|
||||
//
|
||||
// if (jvs_request[cmdi + 2] == 1)
|
||||
// w8(keycode);
|
||||
// if (jvs_request[channel][cmdi + 2] == 1)
|
||||
// JVS_OUT(keycode);
|
||||
// else
|
||||
// w16(keycode);
|
||||
// }
|
||||
|
@ -1930,21 +2113,21 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
coin_chute = false;
|
||||
coin_count++;
|
||||
}
|
||||
parent->w8(1); // report byte
|
||||
JVS_STATUS1(); // report byte
|
||||
LOGJVS("coins ");
|
||||
for (int slot = 0; slot < jvs_request[cmdi + 1]; slot++)
|
||||
for (int slot = 0; slot < buffer_in[cmdi + 1]; slot++)
|
||||
{
|
||||
if (slot == 0)
|
||||
{
|
||||
LOGJVS("0:%d ", coin_count);
|
||||
parent->w8((coin_count >> 8) & 0x3F); // status (2 highest bits, 0: normal), coin count MSB
|
||||
parent->w8(coin_count); // coin count LSB
|
||||
JVS_OUT((coin_count >> 8) & 0x3F); // status (2 highest bits, 0: normal), coin count MSB
|
||||
JVS_OUT(coin_count); // coin count LSB
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGJVS("%d:0 ", slot);
|
||||
parent->w8(0);
|
||||
parent->w8(0);
|
||||
JVS_OUT(0);
|
||||
JVS_OUT(0);
|
||||
}
|
||||
}
|
||||
cmdi += 2;
|
||||
|
@ -1953,7 +2136,7 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
|
||||
case 0x22: // Read analog inputs
|
||||
{
|
||||
parent->w8(1); // report byte
|
||||
JVS_STATUS1(); // report byte
|
||||
int axis = 0;
|
||||
|
||||
LOGJVS("ana ");
|
||||
|
@ -1968,14 +2151,14 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
y = 0xffff;
|
||||
}
|
||||
LOGJVS("x,y:%4x,%4x ", x, y);
|
||||
parent->w8(x >> 8); // X, MSB
|
||||
parent->w8(x); // X, LSB
|
||||
parent->w8(y >> 8); // Y, MSB
|
||||
parent->w8(y); // Y, LSB
|
||||
JVS_OUT(x >> 8); // X, MSB
|
||||
JVS_OUT(x); // X, LSB
|
||||
JVS_OUT(y >> 8); // Y, MSB
|
||||
JVS_OUT(y); // Y, LSB
|
||||
axis = 2;
|
||||
}
|
||||
|
||||
for (; axis < jvs_request[cmdi + 1]; axis++)
|
||||
for (; axis < buffer_in[cmdi + 1]; axis++)
|
||||
{
|
||||
u16 axis_value;
|
||||
if (Naomi_Mapping.axis[axis] != NULL)
|
||||
|
@ -1998,8 +2181,8 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
}
|
||||
}
|
||||
LOGJVS("%d:%4x ", axis, axis_value);
|
||||
parent->w8(axis_value >> 8);
|
||||
parent->w8(axis_value);
|
||||
JVS_OUT(axis_value >> 8);
|
||||
JVS_OUT(axis_value);
|
||||
}
|
||||
cmdi += 2;
|
||||
}
|
||||
|
@ -2007,7 +2190,7 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
|
||||
case 0x23: // Read rotary encoders
|
||||
{
|
||||
parent->w8(1); // report byte
|
||||
JVS_STATUS1(); // report byte
|
||||
static s16 rotx = 0;
|
||||
static s16 roty = 0;
|
||||
rotx += mo_x_delta * 10;
|
||||
|
@ -2015,25 +2198,25 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
mo_x_delta = 0;
|
||||
mo_y_delta = 0;
|
||||
LOGJVS("rotenc ");
|
||||
for (int chan = 0; chan < jvs_request[cmdi + 1]; chan++)
|
||||
for (int chan = 0; chan < buffer_in[cmdi + 1]; chan++)
|
||||
{
|
||||
if (chan == 0)
|
||||
{
|
||||
LOGJVS("%d:%4x ", chan, rotx);
|
||||
parent->w8(rotx >> 8); // MSB
|
||||
parent->w8(rotx); // LSB
|
||||
JVS_OUT(rotx >> 8); // MSB
|
||||
JVS_OUT(rotx); // LSB
|
||||
}
|
||||
else if (chan == 1)
|
||||
{
|
||||
LOGJVS("%d:%4x ", chan, roty);
|
||||
parent->w8(roty >> 8); // MSB
|
||||
parent->w8(roty); // LSB
|
||||
JVS_OUT(roty >> 8); // MSB
|
||||
JVS_OUT(roty); // LSB
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGJVS("%d:%4x ", chan, 0);
|
||||
parent->w8(0x80); // MSB
|
||||
parent->w8(0x80); // LSB
|
||||
JVS_OUT(0x80); // MSB
|
||||
JVS_OUT(0x80); // LSB
|
||||
}
|
||||
}
|
||||
cmdi += 2;
|
||||
|
@ -2042,206 +2225,61 @@ MapleDeviceRV jvs_io_board::handle_jvs_command(u8* data)
|
|||
|
||||
case 0x25: // Read screen pos inputs
|
||||
{
|
||||
parent->w8(1); // report byte
|
||||
// Channel number is jvs_request[cmdi + 1]
|
||||
JVS_STATUS1(); // report byte
|
||||
// Channel number is jvs_request[channel][cmdi + 1]
|
||||
u16 x = mo_x_abs * 0xFFFF / 639;
|
||||
u16 y = (479 - mo_y_abs) * 0xFFFF / 479;
|
||||
LOGJVS("lightgun %4x,%4x ", x, y);
|
||||
parent->w8(x >> 8); // X, MSB
|
||||
parent->w8(x); // X, LSB
|
||||
parent->w8(y >> 8); // Y, MSB
|
||||
parent->w8(y); // Y, LSB
|
||||
JVS_OUT(x >> 8); // X, MSB
|
||||
JVS_OUT(x); // X, LSB
|
||||
JVS_OUT(y >> 8); // Y, MSB
|
||||
JVS_OUT(y); // Y, LSB
|
||||
cmdi += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x32: // switched outputs
|
||||
case 0x33:
|
||||
parent->w8(1); // report byte
|
||||
cmdi += jvs_request[cmdi + 1] + 2;
|
||||
JVS_STATUS1(); // report byte
|
||||
cmdi += buffer_in[cmdi + 1] + 2;
|
||||
break;
|
||||
|
||||
// case 0x30, 0x31: add coin
|
||||
default:
|
||||
printf("JVS: Unknown input type %x\n", jvs_request[cmdi]);
|
||||
parent->w8(2); // report byte: command error
|
||||
cmdi = jvs_length; // Ignore subsequent commands
|
||||
printf("JVS: Unknown input type %x\n", buffer_in[cmdi]);
|
||||
JVS_OUT(2); // report byte: command error
|
||||
cmdi = length_in; // Ignore subsequent commands
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOGJVS("\n");
|
||||
finish_jvs_reply_buffer();
|
||||
rc = MDRS_JVSReply;
|
||||
}
|
||||
else
|
||||
{
|
||||
JVS_OUT(2); // Unknown command
|
||||
}
|
||||
break;
|
||||
}
|
||||
jvs_length = length - 3;
|
||||
|
||||
jvs_length = 0;
|
||||
}
|
||||
}
|
||||
if (req != 0x15) // Send
|
||||
{
|
||||
u8 node;
|
||||
u8 *cmd;
|
||||
u32 len;
|
||||
u8 channel = 0;
|
||||
if (data[1] > 31 && data[1] != 0xff) // TODO what is this?
|
||||
{
|
||||
node = data[6];
|
||||
len = data[7];
|
||||
cmd = &data[8];
|
||||
channel = data[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
node = data[1];
|
||||
len = data[2];
|
||||
cmd = &data[3];
|
||||
}
|
||||
if (node != ALL_NODES && node != node_id)
|
||||
return MDRS_JVSNone;
|
||||
|
||||
if (len > 0 && *cmd == 0xf0) // reset
|
||||
return MDRS_JVSNone;
|
||||
|
||||
if (req == 0x27)
|
||||
{
|
||||
// FIXME hack
|
||||
node = cmd[-1];
|
||||
len = cmd[0];
|
||||
cmd++;
|
||||
}
|
||||
|
||||
// CT fw uses 13 as a 17, and 17 as 13 and also uses 19
|
||||
if (parent->crazy_mode)
|
||||
{
|
||||
switch (req)
|
||||
{
|
||||
case 0x13:
|
||||
req = 0x17;
|
||||
break;
|
||||
case 0x17:
|
||||
req = 0x13;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Store repeat request
|
||||
if (req == 0x13)
|
||||
{
|
||||
if (node == node_id)
|
||||
{
|
||||
if (len > 0)
|
||||
{
|
||||
printf("JVS node %d: Storing %d cmd bytes\n", node_id, len);
|
||||
memcpy(jvs_repeat_request, cmd, len);
|
||||
jvs_repeat_length = len;
|
||||
}
|
||||
parent->w8(MDRS_JVSReply);
|
||||
parent->w8(channel); // node id?
|
||||
parent->w8(0x20);
|
||||
parent->w8(0x01);
|
||||
parent->w8(data[0] + 1); // subcommand + 1
|
||||
parent->w8(0);
|
||||
parent->w8(len + 1);
|
||||
parent->w8(0);
|
||||
|
||||
return MDRS_JVSReply;
|
||||
}
|
||||
else
|
||||
return MDRS_JVSNone;
|
||||
}
|
||||
memcpy(jvs_request, cmd, len);
|
||||
jvs_length = len;
|
||||
|
||||
if (node == node_id && (req == 0x21 || req == 0x27 || req == 0x33 || req == 0x19))
|
||||
{
|
||||
// Use repeat
|
||||
memcpy(jvs_request + jvs_length, jvs_repeat_request, jvs_repeat_length);
|
||||
jvs_length += jvs_repeat_length;
|
||||
}
|
||||
// FIXME this is for 0x17 and 0x21
|
||||
parent->w8(MDRS_JVSReply);
|
||||
parent->w8(channel);
|
||||
parent->w8(0x20);
|
||||
parent->w8(0x01);
|
||||
parent->w8(0x18);
|
||||
parent->w8(0x10); // FIXME bytes received? >0 required for 0x19
|
||||
parent->w8(0); // in(91)
|
||||
parent->w8(0);
|
||||
if (node != ALL_NODES)
|
||||
rc = MDRS_JVSReply;
|
||||
else
|
||||
rc = MDRS_JVSNone; // Allow other boards to respond to the message
|
||||
//printf("JVS send node %x len %d cmd %x repeat_length %d dma_count_out %d\n", node, jvs_length, *cmd, jvs_repeat_length, *(parent->dma_count_out));
|
||||
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void jvs_io_board::make_jvs_reply_buffer(bool empty)
|
||||
{
|
||||
dma_out = parent->dma_buffer_out;
|
||||
parent->w8(MDRS_JVSReply);
|
||||
parent->w8(0x00); // channel id?
|
||||
parent->w8(0x20);
|
||||
parent->w8(0x00); // length in dword
|
||||
parent->w32(0xffffff16);
|
||||
parent->w32(0xffffffff);
|
||||
if (!empty)
|
||||
{
|
||||
*(parent->dma_count_out) += 9;
|
||||
parent->dma_buffer_out += 9;
|
||||
parent->w8(0x00);
|
||||
parent->w8(last_node ? 0x8E : 0x8F); // bit 0 is sense line level. If set during F1 <n>, more I/O boards need addressing
|
||||
parent->w8(node_id); // node number
|
||||
parent->w8(0x00);
|
||||
parent->w8(0x00); // len of following data
|
||||
parent->w8(0xE0); // sync
|
||||
parent->w8(0x00); // master node
|
||||
parent->w8(0x00); // jvs payload len
|
||||
parent->w8(0x01); // status byte
|
||||
}
|
||||
else
|
||||
{
|
||||
*(parent->dma_count_out) += 8;
|
||||
parent->dma_buffer_out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void jvs_io_board::finish_jvs_reply_buffer()
|
||||
{
|
||||
dma_out[25] = parent->dma_buffer_out - dma_out - 26;
|
||||
dma_out[28] = parent->dma_buffer_out - dma_out - 29;
|
||||
while ((*(parent->dma_count_out)) & 3)
|
||||
{
|
||||
*(parent->dma_count_out) += 1;
|
||||
parent->dma_buffer_out++;
|
||||
}
|
||||
dma_out[3] = (parent->dma_buffer_out - dma_out) / 4 - 1;
|
||||
// printf("dma_count_out=%d\n", *(parent->dma_count_out));
|
||||
return length;
|
||||
}
|
||||
|
||||
bool jvs_io_board::maple_serialize(void **data, unsigned int *total_size)
|
||||
{
|
||||
REICAST_S(node_id);
|
||||
REICAST_S(last_node);
|
||||
REICAST_S(rotary_encoders);
|
||||
REICAST_S(jvs_length);
|
||||
REICAST_SA(jvs_request, sizeof(jvs_request));
|
||||
REICAST_S(jvs_repeat_length);
|
||||
REICAST_SA(jvs_repeat_request, sizeof(jvs_repeat_request));
|
||||
REICAST_S(lightgun_as_analog);
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool jvs_io_board::maple_unserialize(void **data, unsigned int *total_size)
|
||||
{
|
||||
REICAST_US(node_id);
|
||||
REICAST_US(last_node);
|
||||
REICAST_US(rotary_encoders);
|
||||
REICAST_US(jvs_length);
|
||||
REICAST_USA(jvs_request, sizeof(jvs_request));
|
||||
REICAST_US(jvs_repeat_length);
|
||||
REICAST_USA(jvs_repeat_request, sizeof(jvs_repeat_request));
|
||||
REICAST_US(lightgun_as_analog);
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
|
|
@ -167,12 +167,6 @@ void maple_DoDma()
|
|||
{
|
||||
u32 outlen = MapleDevices[bus][port]->RawDma(&p_data[0], inlen + 4, &p_out[0]);
|
||||
xfer_count =+ outlen;
|
||||
/*
|
||||
printf("JVS OUT: ");
|
||||
u8 *p = (u8 *)&p_out[0];
|
||||
for (int i = 0; i < outlen + 4; i++) printf("%02x ", p[i]);
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -212,7 +212,6 @@ extern ByteCount_t ByteCount ;
|
|||
//./core/hw/maple/maple_devs.o
|
||||
extern char EEPROM[0x100];
|
||||
extern bool EEPROM_loaded;
|
||||
extern _NaomiState State;
|
||||
|
||||
//./core/hw/maple/maple_if.o
|
||||
//one time set
|
||||
|
@ -916,7 +915,6 @@ bool dc_serialize(void **data, unsigned int *total_size)
|
|||
|
||||
REICAST_SA(EEPROM,0x100);
|
||||
REICAST_S(EEPROM_loaded);
|
||||
REICAST_S(State);
|
||||
|
||||
|
||||
REICAST_S(maple_ddt_pending_reset);
|
||||
|
@ -1277,7 +1275,6 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
|
||||
REICAST_USA(EEPROM,0x100);
|
||||
REICAST_US(EEPROM_loaded);
|
||||
REICAST_US(State);
|
||||
|
||||
|
||||
REICAST_US(maple_ddt_pending_reset);
|
||||
|
|
Loading…
Reference in New Issue