mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
M1COMM, M2COMM, S32COMM: Updates to simulation (#3369)
* M1COMM: update simulation based on real firmware (nw) - read partial frames correctly now - added VSYNC packets (framesync currently disabled as this can cause MAME to freeze and we have no way to tell if the socket is still open) * M2COMM: update simulation (nw) - read partial frames correctly now - added VSYNC packets (framesync currently disabled as this can cause MAME to freeze and we have no way to tell if the socket is still open) * M1COMM, M2COMM: add config option to sync frames over network (nw) * M2COMM: another update to the simulation. - added relay mode (used by stcc) - added "connection loss" * M1COMM: update to simulation (nw) - better sync - detect lost connection * M2COMM: use osd_file rather than emu_file for better control (nw) * M2COMM: handle connection loss in a a more elegant way (nw) * M1COMM: use osd_file rather than emu_file for better control (nw) * S32COMM: updated simulation (nw) - handle connection loss - use osd_file rather than emu_file for better control
This commit is contained in:
parent
0883f01e66
commit
c32176f2bb
@ -187,6 +187,7 @@ const options_entry emu_options::s_option_entries[] =
|
||||
{ OPTION_COMM_LOCAL_PORT, "15112", OPTION_STRING, "local port to bind to" },
|
||||
{ OPTION_COMM_REMOTE_HOST, "127.0.0.1", OPTION_STRING, "remote address to connect to" },
|
||||
{ OPTION_COMM_REMOTE_PORT, "15112", OPTION_STRING, "remote port to connect to" },
|
||||
{ OPTION_COMM_FRAME_SYNC, "0", OPTION_BOOLEAN, "sync frames" },
|
||||
|
||||
// misc options
|
||||
{ nullptr, nullptr, OPTION_HEADER, "CORE MISC OPTIONS" },
|
||||
|
@ -177,6 +177,7 @@
|
||||
#define OPTION_COMM_LOCAL_PORT "comm_localport"
|
||||
#define OPTION_COMM_REMOTE_HOST "comm_remotehost"
|
||||
#define OPTION_COMM_REMOTE_PORT "comm_remoteport"
|
||||
#define OPTION_COMM_FRAME_SYNC "comm_framesync"
|
||||
|
||||
#define OPTION_CONFIRM_QUIT "confirm_quit"
|
||||
#define OPTION_UI_MOUSE "ui_mouse"
|
||||
@ -456,6 +457,7 @@ public:
|
||||
const char *comm_localport() const { return value(OPTION_COMM_LOCAL_PORT); }
|
||||
const char *comm_remotehost() const { return value(OPTION_COMM_REMOTE_HOST); }
|
||||
const char *comm_remoteport() const { return value(OPTION_COMM_REMOTE_PORT); }
|
||||
bool comm_framesync() const { return bool_value(OPTION_COMM_FRAME_SYNC); }
|
||||
|
||||
|
||||
bool confirm_quit() const { return bool_value(OPTION_CONFIRM_QUIT); }
|
||||
|
@ -123,9 +123,7 @@ const tiny_rom_entry *m1comm_device::device_rom_region() const
|
||||
|
||||
m1comm_device::m1comm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, M1COMM, tag, owner, clock),
|
||||
m_commcpu(*this, Z80_TAG),
|
||||
m_line_rx(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE ),
|
||||
m_line_tx(OPEN_FLAG_READ)
|
||||
m_commcpu(*this, Z80_TAG)
|
||||
{
|
||||
// prepare localhost "filename"
|
||||
m_localhost[0] = 0;
|
||||
@ -140,6 +138,8 @@ m1comm_device::m1comm_device(const machine_config &mconfig, const char *tag, dev
|
||||
strcat(m_remotehost, mconfig.options().comm_remotehost());
|
||||
strcat(m_remotehost, ":");
|
||||
strcat(m_remotehost, mconfig.options().comm_remoteport());
|
||||
|
||||
m_framesync = mconfig.options().comm_framesync() ? 0x01 : 0x00;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -318,7 +318,6 @@ void m1comm_device::comm_tick()
|
||||
int frameOffset = 0x0000;
|
||||
int frameSize = 0x01c4;
|
||||
int dataSize = frameSize + 1;
|
||||
int togo = 0;
|
||||
int recv = 0;
|
||||
int idx = 0;
|
||||
|
||||
@ -326,120 +325,77 @@ void m1comm_device::comm_tick()
|
||||
bool isSlave = (m_shared[1] == 0x02);
|
||||
bool isRelay = (m_shared[1] == 0x00);
|
||||
|
||||
// if link not yet established...
|
||||
if (m_linkalive == 0x00)
|
||||
if (m_linkalive == 0x02)
|
||||
{
|
||||
// waiting...
|
||||
// link failed...
|
||||
m_shared[0] = 0xff;
|
||||
return;
|
||||
}
|
||||
else if (m_linkalive == 0x00)
|
||||
{
|
||||
// link not yet established...
|
||||
m_shared[0] = 0x05;
|
||||
|
||||
// check rx socket
|
||||
if (!m_line_rx.is_open())
|
||||
if (!m_line_rx)
|
||||
{
|
||||
osd_printf_verbose("M1COMM: listen on %s\n", m_localhost);
|
||||
m_line_rx.open(m_localhost);
|
||||
uint64_t filesize; // unused
|
||||
osd_file::open(m_localhost, OPEN_FLAG_CREATE, m_line_rx, filesize);
|
||||
}
|
||||
|
||||
// check tx socket
|
||||
if (!m_line_tx.is_open())
|
||||
if (!m_line_tx)
|
||||
{
|
||||
osd_printf_verbose("M1COMM: connect to %s\n", m_remotehost);
|
||||
m_line_tx.open(m_remotehost);
|
||||
uint64_t filesize; // unused
|
||||
osd_file::open(m_remotehost, 0, m_line_tx, filesize);
|
||||
}
|
||||
|
||||
// if both sockets are there check ring
|
||||
if ((m_line_rx.is_open()) && (m_line_tx.is_open()))
|
||||
if (m_line_rx && m_line_tx)
|
||||
{
|
||||
// try to read one messages
|
||||
recv = m_line_rx.read(m_buffer, dataSize);
|
||||
while (recv != 0)
|
||||
// try to read one message
|
||||
recv = read_frame(dataSize);
|
||||
while (recv > 0)
|
||||
{
|
||||
// check if complete message
|
||||
if (recv == dataSize)
|
||||
{
|
||||
// check if message id
|
||||
idx = m_buffer[0];
|
||||
// check message id
|
||||
idx = m_buffer0[0];
|
||||
|
||||
// 0xFF - link id
|
||||
if (idx == 0xff)
|
||||
// 0xFF - link id
|
||||
if (idx == 0xff)
|
||||
{
|
||||
if (isMaster)
|
||||
{
|
||||
if (isMaster)
|
||||
{
|
||||
// master gets first id and starts next state
|
||||
m_linkid = 0x01;
|
||||
m_linkcount = m_buffer[1];
|
||||
m_linktimer = 0x01;
|
||||
}
|
||||
else if (isSlave || isRelay)
|
||||
{
|
||||
// slave gets own id
|
||||
if (isSlave)
|
||||
{
|
||||
m_buffer[1]++;
|
||||
m_linkid = m_buffer[1];
|
||||
}
|
||||
|
||||
// slave and relay forward message
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
}
|
||||
// master gets first id and starts next state
|
||||
m_linkid = 0x01;
|
||||
m_linkcount = m_buffer0[1];
|
||||
m_linktimer = 0x00;
|
||||
}
|
||||
|
||||
// 0xFE - link size
|
||||
else if (idx == 0xfe)
|
||||
else
|
||||
{
|
||||
if (isSlave || isRelay)
|
||||
// slave get own id, relay does nothing
|
||||
if (isSlave)
|
||||
{
|
||||
m_linkcount = m_buffer[1];
|
||||
|
||||
// slave and relay forward message
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
m_buffer0[1]++;
|
||||
m_linkid = m_buffer0[1];
|
||||
}
|
||||
|
||||
// consider it done
|
||||
osd_printf_verbose("M1COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
|
||||
m_linkalive = 0x01;
|
||||
m_zfg = 0x01;
|
||||
|
||||
// write to shared mem
|
||||
m_shared[0] = 0x01;
|
||||
m_shared[2] = m_linkid;
|
||||
m_shared[3] = m_linkcount;
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// 0xFE - link size
|
||||
else if (idx == 0xfe)
|
||||
{
|
||||
// got only part of a message - read the rest (and drop it)
|
||||
// TODO: combine parts and push to "ring buffer"
|
||||
togo = dataSize - recv;
|
||||
while (togo > 0){
|
||||
recv = m_line_rx.read(m_buffer, togo);
|
||||
togo -= recv;
|
||||
if (isSlave || isRelay)
|
||||
{
|
||||
m_linkcount = m_buffer0[1];
|
||||
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
osd_printf_verbose("M1COMM: dropped a message...\n");
|
||||
}
|
||||
|
||||
if (m_linkalive == 0x00)
|
||||
recv = m_line_rx.read(m_buffer, dataSize);
|
||||
else
|
||||
recv = 0;
|
||||
}
|
||||
|
||||
// if we are master and link is not yet established
|
||||
if (isMaster && (m_linkalive == 0x00))
|
||||
{
|
||||
// send first packet
|
||||
if (m_linktimer == 0x00)
|
||||
{
|
||||
m_buffer[0] = 0xff;
|
||||
m_buffer[1] = 0x01;
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
}
|
||||
|
||||
// send second packet
|
||||
else if (m_linktimer == 0x01)
|
||||
{
|
||||
m_buffer[0] = 0xfe;
|
||||
m_buffer[1] = m_linkcount;
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
|
||||
// consider it done
|
||||
osd_printf_verbose("M1COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
|
||||
@ -452,104 +408,233 @@ void m1comm_device::comm_tick()
|
||||
m_shared[3] = m_linkcount;
|
||||
}
|
||||
|
||||
else if (m_linktimer > 0x02)
|
||||
|
||||
if (m_linkalive == 0x00)
|
||||
recv = read_frame(dataSize);
|
||||
else
|
||||
recv = 0;
|
||||
}
|
||||
|
||||
// if we are master and link is not yet established
|
||||
if (isMaster && (m_linkalive == 0x00))
|
||||
{
|
||||
// send first packet
|
||||
if (m_linktimer == 0x01)
|
||||
{
|
||||
m_buffer0[0] = 0xff;
|
||||
m_buffer0[1] = 0x01;
|
||||
send_frame(dataSize);
|
||||
}
|
||||
|
||||
// send second packet
|
||||
else if (m_linktimer == 0x00)
|
||||
{
|
||||
m_buffer0[0] = 0xfe;
|
||||
m_buffer0[1] = m_linkcount;
|
||||
send_frame(dataSize);
|
||||
|
||||
// consider it done
|
||||
osd_printf_verbose("M1COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
|
||||
m_linkalive = 0x01;
|
||||
m_zfg = 0x01;
|
||||
|
||||
// write to shared mem
|
||||
m_shared[0] = 0x01;
|
||||
m_shared[2] = m_linkid;
|
||||
m_shared[3] = m_linkcount;
|
||||
}
|
||||
|
||||
else if (m_linktimer > 0x01)
|
||||
{
|
||||
// decrease delay timer
|
||||
m_linktimer--;
|
||||
if (m_linktimer == 0x02)
|
||||
m_linktimer = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update "ring buffer" if link established
|
||||
if (m_linkalive == 0x01)
|
||||
{
|
||||
int togo = 0;
|
||||
// try to read one messages
|
||||
int recv = m_line_rx.read(m_buffer, dataSize);
|
||||
while (recv != 0)
|
||||
// link established
|
||||
do
|
||||
{
|
||||
// check if complete message
|
||||
if (recv == dataSize)
|
||||
// try to read a message
|
||||
recv = read_frame(dataSize);
|
||||
while (recv > 0)
|
||||
{
|
||||
// check if valid id
|
||||
int idx = m_buffer[0];
|
||||
if (idx > 0 && idx <= m_linkcount) {
|
||||
// if not our own message
|
||||
idx = m_buffer0[0];
|
||||
if (idx > 0 && idx <= m_linkcount)
|
||||
{
|
||||
// if not own message
|
||||
if (idx != m_linkid)
|
||||
{
|
||||
// save message to "ring buffer"
|
||||
frameOffset = frameStart + (idx * frameSize);
|
||||
for (int j = 0x00 ; j < frameSize ; j++)
|
||||
{
|
||||
m_shared[frameOffset + j] = m_buffer[1 + j];
|
||||
m_shared[frameOffset + j] = m_buffer0[1 + j];
|
||||
}
|
||||
|
||||
// forward message to other nodes
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
send_frame(dataSize);
|
||||
}
|
||||
} else {
|
||||
if (!isMaster && idx == 0xf0){
|
||||
// 0xF0 - master addional bytes
|
||||
for (int j = 0x06 ; j < 0x10 ; j++)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idx == 0xfc)
|
||||
{
|
||||
// 0xFC - VSYNC
|
||||
m_linktimer = 0x00;
|
||||
if (!isMaster)
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
if (idx == 0xfd)
|
||||
{
|
||||
// 0xFD - master addional bytes
|
||||
if (!isMaster)
|
||||
{
|
||||
m_shared[j] = m_buffer[1 + j];
|
||||
}
|
||||
// save message to "ring buffer"
|
||||
frameOffset = 0x06;
|
||||
for (int j = 0x00 ; j < 0x0a ; j++)
|
||||
{
|
||||
m_shared[frameOffset + j] = m_buffer0[1 + j];
|
||||
}
|
||||
|
||||
// forward message to other nodes
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try to read another message
|
||||
recv = read_frame(dataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// got only part of a message - read the rest (and drop it)
|
||||
// TODO: combine parts and push to "ring buffer"
|
||||
togo = dataSize - recv;
|
||||
while (togo > 0){
|
||||
recv = m_line_rx.read(m_buffer, togo);
|
||||
togo -= recv;
|
||||
}
|
||||
osd_printf_verbose("M1COMM: dropped a message...\n");
|
||||
}
|
||||
recv = m_line_rx.read(m_buffer, dataSize);
|
||||
}
|
||||
while (m_linktimer == 0x01);
|
||||
|
||||
// enable wait for vsync
|
||||
m_linktimer = m_framesync;
|
||||
|
||||
// update "ring buffer" if link established
|
||||
// live relay does not send data
|
||||
if (m_linkid != 0x00 && m_shared[4] != 0x00)
|
||||
if (m_linkid != 0x00)
|
||||
{
|
||||
m_buffer[0] = m_linkid;
|
||||
frameOffset = frameStart + (m_linkid * frameSize);
|
||||
for (int j = 0x00 ; j < frameSize ; j++)
|
||||
// check ready-to-send flag
|
||||
if (m_shared[4] != 0x00)
|
||||
{
|
||||
// push message to "ring buffer"
|
||||
m_shared[frameOffset + j] = m_shared[frameStart + j];
|
||||
m_buffer[1 + j] = m_shared[frameStart + j];
|
||||
}
|
||||
// push message to other nodes
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
send_data(m_linkid, frameStart, frameSize, dataSize);
|
||||
|
||||
// master sends some additional status bytes
|
||||
if (isMaster){
|
||||
m_buffer[0] = 0xf0;
|
||||
// save message to "ring buffer"
|
||||
frameOffset = frameStart + (m_linkid * frameSize);
|
||||
for (int j = 0x00 ; j < frameSize ; j++)
|
||||
{
|
||||
m_buffer[1 + j] = 0x00;
|
||||
m_shared[frameOffset + j] = m_buffer0[1 + j];
|
||||
}
|
||||
for (int j = 0x06 ; j < 0x10 ; j++)
|
||||
{
|
||||
m_buffer[1 + j] = m_shared[j];
|
||||
}
|
||||
// push message to other nodes
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
}
|
||||
|
||||
if (isMaster)
|
||||
{
|
||||
// master sends additional status bytes
|
||||
send_data(0xfd, 0x06, 0x0a, dataSize);
|
||||
|
||||
// send vsync
|
||||
m_buffer0[0] = 0xfc;
|
||||
m_buffer0[1] = 0x01;
|
||||
send_frame(dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
// clear 05
|
||||
m_shared[5] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int m1comm_device::read_frame(int dataSize)
|
||||
{
|
||||
if (!m_line_rx)
|
||||
return 0;
|
||||
|
||||
// try to read a message
|
||||
std::uint32_t recv = 0;
|
||||
osd_file::error filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv);
|
||||
if (recv > 0)
|
||||
{
|
||||
// check if message complete
|
||||
if (recv != dataSize)
|
||||
{
|
||||
// only part of a message - read on
|
||||
std::uint32_t togo = dataSize - recv;
|
||||
int offset = recv;
|
||||
while (togo > 0)
|
||||
{
|
||||
filerr = m_line_rx->read(m_buffer1, 0, togo, recv);
|
||||
if (recv > 0)
|
||||
{
|
||||
for (int i = 0 ; i < recv ; i++)
|
||||
{
|
||||
m_buffer0[offset + i] = m_buffer1[i];
|
||||
}
|
||||
togo -= recv;
|
||||
offset += recv;
|
||||
}
|
||||
else if (filerr == osd_file::error::NONE && recv == 0)
|
||||
{
|
||||
togo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (filerr == osd_file::error::NONE && recv == 0)
|
||||
{
|
||||
if (m_linkalive == 0x01)
|
||||
{
|
||||
osd_printf_verbose("M1COMM: rx connection lost\n");
|
||||
m_linkalive = 0x02;
|
||||
m_linktimer = 0x00;
|
||||
|
||||
m_shared[0] = 0xff;
|
||||
|
||||
m_line_rx.reset();
|
||||
m_line_tx.reset();
|
||||
}
|
||||
}
|
||||
return recv;
|
||||
}
|
||||
|
||||
void m1comm_device::send_data(uint8_t frameType, int frameStart, int frameSize, int dataSize)
|
||||
{
|
||||
m_buffer0[0] = frameType;
|
||||
for (int i = 0x00 ; i < frameSize ; i++)
|
||||
{
|
||||
m_buffer0[1 + i] = m_shared[frameStart + i];
|
||||
}
|
||||
send_frame(dataSize);
|
||||
}
|
||||
|
||||
void m1comm_device::send_frame(int dataSize){
|
||||
if (!m_line_tx)
|
||||
return;
|
||||
|
||||
osd_file::error filerr;
|
||||
std::uint32_t written;
|
||||
|
||||
filerr = m_line_tx->write(&m_buffer0, 0, dataSize, written);
|
||||
if (filerr != osd_file::error::NONE)
|
||||
{
|
||||
if (m_linkalive == 0x01)
|
||||
{
|
||||
osd_printf_verbose("M1COMM: tx connection lost\n");
|
||||
m_linkalive = 0x02;
|
||||
m_linktimer = 0x00;
|
||||
|
||||
m_shared[0] = 0xff;
|
||||
|
||||
m_line_rx.reset();
|
||||
m_line_tx.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#define M1COMM_SIMULATION
|
||||
|
||||
#include "osdcore.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
|
||||
#define MCFG_M1COMM_ADD(_tag ) \
|
||||
@ -75,11 +76,13 @@ private:
|
||||
uint8_t m_cn; // bit0 is used to enable/disable the comm board
|
||||
uint8_t m_fg; // flip gate? purpose unknown, bit0 is stored, bit7 is connected to ZFG bit 0
|
||||
|
||||
emu_file m_line_rx; // rx line - can be either differential, simple serial or toslink
|
||||
emu_file m_line_tx; // tx line - is differential, simple serial and toslink
|
||||
osd_file::ptr m_line_rx; // rx line - can be either differential, simple serial or toslink
|
||||
osd_file::ptr m_line_tx; // tx line - is differential, simple serial and toslink
|
||||
char m_localhost[256];
|
||||
char m_remotehost[256];
|
||||
uint8_t m_buffer[0x1000];
|
||||
uint8_t m_buffer0[0x200];
|
||||
uint8_t m_buffer1[0x200];
|
||||
uint8_t m_framesync;
|
||||
|
||||
#ifdef M1COMM_SIMULATION
|
||||
uint8_t m_linkenable;
|
||||
@ -89,6 +92,9 @@ private:
|
||||
uint8_t m_linkcount;
|
||||
|
||||
void comm_tick();
|
||||
int read_frame(int dataSize);
|
||||
void send_data(uint8_t frameType, int frameStart, int frameSize, int dataSize);
|
||||
void send_frame(int dataSize);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -194,9 +194,7 @@ MACHINE_CONFIG_END
|
||||
//-------------------------------------------------
|
||||
|
||||
m2comm_device::m2comm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, M2COMM, tag, owner, clock),
|
||||
m_line_rx(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE ),
|
||||
m_line_tx(OPEN_FLAG_READ)
|
||||
device_t(mconfig, M2COMM, tag, owner, clock)
|
||||
{
|
||||
// prepare localhost "filename"
|
||||
m_localhost[0] = 0;
|
||||
@ -211,6 +209,8 @@ m2comm_device::m2comm_device(const machine_config &mconfig, const char *tag, dev
|
||||
strcat(m_remotehost, mconfig.options().comm_remotehost());
|
||||
strcat(m_remotehost, ":");
|
||||
strcat(m_remotehost, mconfig.options().comm_remoteport());
|
||||
|
||||
m_framesync = mconfig.options().comm_framesync() ? 0x01 : 0x00;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -296,6 +296,7 @@ WRITE8_MEMBER(m2comm_device::cn_w)
|
||||
m_shared[i] = 0x00;
|
||||
}
|
||||
|
||||
m_shared[0x01] = 0x02;
|
||||
// TODO - check EPR-16726 on Daytona USA and Sega Rally Championship
|
||||
// EPR-18643(A) - these are accessed by VirtuaON and Sega Touring Car Championship
|
||||
|
||||
@ -314,6 +315,9 @@ WRITE8_MEMBER(m2comm_device::cn_w)
|
||||
|
||||
READ8_MEMBER(m2comm_device::fg_r)
|
||||
{
|
||||
#ifdef M2COMM_SIMULATION
|
||||
read_fg();
|
||||
#endif
|
||||
return m_fg | (~m_zfg << 7) | 0x7e;
|
||||
}
|
||||
|
||||
@ -335,115 +339,119 @@ void m2comm_device::comm_tick()
|
||||
{
|
||||
if (m_linkenable == 0x01)
|
||||
{
|
||||
m_zfg ^= 1;
|
||||
|
||||
int frameStart = 0x2000;
|
||||
int frameSize = m_shared[0x13] << 8 | m_shared[0x12];
|
||||
int frameOffset = m_shared[0x15] << 8 | m_shared[0x14];
|
||||
int frameOffset = frameStart | m_shared[0x15] << 8 | m_shared[0x14];
|
||||
|
||||
int dataSize = frameSize + 1;
|
||||
int togo = 0;
|
||||
int recv = 0;
|
||||
int idx = 0;
|
||||
|
||||
// EPR-16726 uses m_fg for Master/Slave
|
||||
// EPR-18643(A) seems to check m_shared[1], with a fallback to m_fg
|
||||
bool isMaster = (m_fg == 0x01 || m_shared[1] == 0x01);
|
||||
bool isSlave = !isMaster && (m_fg == 0x00);
|
||||
bool isSlave = (m_fg == 0x00 && m_shared[1] == 0x02);
|
||||
bool isRelay = (m_fg == 0x00 && m_shared[1] == 0x00);
|
||||
|
||||
// if link not yet established...
|
||||
if (m_linkalive == 0x00)
|
||||
if (m_linkalive == 0x02)
|
||||
{
|
||||
// waiting...
|
||||
// link failed...
|
||||
m_shared[0] = 0xff;
|
||||
return;
|
||||
}
|
||||
else if (m_linkalive == 0x00)
|
||||
{
|
||||
// link not yet established...
|
||||
m_shared[0] = 0x00;
|
||||
m_shared[2] = 0xff;
|
||||
m_shared[3] = 0xff;
|
||||
|
||||
// check rx socket
|
||||
if (!m_line_rx.is_open())
|
||||
if (!m_line_rx)
|
||||
{
|
||||
osd_printf_verbose("M2COMM: listen on %s\n", m_localhost);
|
||||
m_line_rx.open(m_localhost);
|
||||
uint64_t filesize; // unused
|
||||
osd_file::open(m_localhost, OPEN_FLAG_CREATE, m_line_rx, filesize);
|
||||
}
|
||||
|
||||
// check tx socket
|
||||
if (!m_line_tx.is_open())
|
||||
if (!m_line_tx)
|
||||
{
|
||||
osd_printf_verbose("M2COMM: connect to %s\n", m_remotehost);
|
||||
m_line_tx.open(m_remotehost);
|
||||
uint64_t filesize; // unused
|
||||
osd_file::open(m_remotehost, 0, m_line_tx, filesize);
|
||||
}
|
||||
|
||||
// if both sockets are there check ring
|
||||
if ((m_line_rx.is_open()) && (m_line_tx.is_open()))
|
||||
if (m_line_rx && m_line_tx)
|
||||
{
|
||||
// try to read one messages
|
||||
recv = m_line_rx.read(m_buffer, dataSize);
|
||||
while (recv != 0)
|
||||
m_zfg ^= 0x01;
|
||||
|
||||
// try to read one message
|
||||
recv = read_frame(dataSize);
|
||||
while (recv > 0)
|
||||
{
|
||||
// check if complete message
|
||||
if (recv == dataSize)
|
||||
// check if message id
|
||||
idx = m_buffer0[0];
|
||||
|
||||
// 0xFF - link id
|
||||
if (idx == 0xff)
|
||||
{
|
||||
// check if message id
|
||||
idx = m_buffer[0];
|
||||
|
||||
// 0xFF - link id
|
||||
if (idx == 0xff)
|
||||
if (isMaster)
|
||||
{
|
||||
if (isMaster)
|
||||
{
|
||||
// master gets first id and starts next state
|
||||
m_linkid = 0x01;
|
||||
m_linkcount = m_buffer[1];
|
||||
m_linktimer = 0x01;
|
||||
}
|
||||
else if (isSlave)
|
||||
{
|
||||
// increase linkcount
|
||||
m_buffer[1]++;
|
||||
|
||||
// forward message
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
}
|
||||
// master gets first id and starts next state
|
||||
m_linkid = 0x01;
|
||||
m_linkcount = m_buffer0[1];
|
||||
m_linktimer = 0x00;
|
||||
}
|
||||
|
||||
// 0xFE - link size
|
||||
else if (idx == 0xfe)
|
||||
else
|
||||
{
|
||||
// slave get own id, relay does nothing
|
||||
if (isSlave)
|
||||
{
|
||||
// fetch linkcount and linkid, then decrease linkid
|
||||
m_linkcount = m_buffer[1];
|
||||
m_linkid = m_buffer[2];
|
||||
m_buffer[2]--;
|
||||
|
||||
// forward message
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
m_buffer0[1]++;
|
||||
}
|
||||
|
||||
// consider it done
|
||||
osd_printf_verbose("M2COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
|
||||
m_linkalive = 0x01;
|
||||
m_linktimer = 0x01;
|
||||
|
||||
// write to shared mem
|
||||
m_shared[0] = 0x01;
|
||||
m_shared[2] = m_linkid;
|
||||
m_shared[3] = m_linkcount;
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// 0xFE - link size
|
||||
else if (idx == 0xfe)
|
||||
{
|
||||
// got only part of a message - read the rest (and drop it)
|
||||
// TODO: combine parts and push to "ring buffer"
|
||||
togo = dataSize - recv;
|
||||
while (togo > 0){
|
||||
recv = m_line_rx.read(m_buffer, togo);
|
||||
togo -= recv;
|
||||
if (isSlave)
|
||||
{
|
||||
// fetch linkid and linkcount, then decrease linkid
|
||||
m_linkid = m_buffer0[1];
|
||||
m_linkcount = m_buffer0[2];
|
||||
m_buffer0[1]--;
|
||||
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
osd_printf_verbose("M2COMM: dropped a message...\n");
|
||||
else if (isRelay)
|
||||
{
|
||||
// fetch linkid and linkcount, then decrease linkid
|
||||
m_linkid = 0x00;
|
||||
m_linkcount = m_buffer0[2];
|
||||
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
|
||||
// consider it done
|
||||
osd_printf_verbose("M2COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
|
||||
m_linkalive = 0x01;
|
||||
|
||||
// write to shared mem
|
||||
m_shared[0] = 0x01;
|
||||
m_shared[2] = m_linkid;
|
||||
m_shared[3] = m_linkcount;
|
||||
}
|
||||
|
||||
if (m_linkalive == 0x00)
|
||||
recv = m_line_rx.read(m_buffer, dataSize);
|
||||
recv = read_frame(dataSize);
|
||||
else
|
||||
recv = 0;
|
||||
}
|
||||
@ -452,27 +460,25 @@ void m2comm_device::comm_tick()
|
||||
if (isMaster && (m_linkalive == 0x00))
|
||||
{
|
||||
// send first packet
|
||||
if (m_linktimer == 0x00)
|
||||
if (m_linktimer == 0x01)
|
||||
{
|
||||
m_buffer[0] = 0xff;
|
||||
m_buffer[1] = 0x01;
|
||||
m_buffer[2] = 0x00;
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
m_linktimer = 0x00e8; // 58 fps * 4s
|
||||
m_buffer0[0] = 0xff;
|
||||
m_buffer0[1] = 0x01;
|
||||
m_buffer0[2] = 0x00;
|
||||
send_frame(dataSize);
|
||||
}
|
||||
|
||||
// send second packet
|
||||
else if (m_linktimer == 0x01)
|
||||
else if (m_linktimer == 0x00)
|
||||
{
|
||||
m_buffer[0] = 0xfe;
|
||||
m_buffer[1] = m_linkcount;
|
||||
m_buffer[2] = m_linkcount;
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
m_buffer0[0] = 0xfe;
|
||||
m_buffer0[1] = m_linkcount;
|
||||
m_buffer0[2] = m_linkcount;
|
||||
send_frame(dataSize);
|
||||
|
||||
// consider it done
|
||||
osd_printf_verbose("M2COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
|
||||
m_linkalive = 0x01;
|
||||
m_linktimer = 0x00;
|
||||
|
||||
// write to shared mem
|
||||
m_shared[0] = 0x01;
|
||||
@ -480,64 +486,217 @@ void m2comm_device::comm_tick()
|
||||
m_shared[3] = m_linkcount;
|
||||
}
|
||||
|
||||
else if (m_linktimer > 0x02)
|
||||
else if (m_linktimer > 0x01)
|
||||
{
|
||||
// decrease delay timer
|
||||
m_linktimer--;
|
||||
if (m_linktimer == 0x02)
|
||||
m_linktimer = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update "ring buffer" if link established
|
||||
// if link established
|
||||
if (m_linkalive == 0x01)
|
||||
{
|
||||
int togo = 0;
|
||||
// try to read one messages
|
||||
int recv = m_line_rx.read(m_buffer, dataSize);
|
||||
while (recv != 0)
|
||||
do
|
||||
{
|
||||
m_linktimer = 0x00;
|
||||
// check if complete message
|
||||
if (recv == dataSize)
|
||||
// try to read a message
|
||||
recv = read_frame(dataSize);
|
||||
while (recv > 0)
|
||||
{
|
||||
// check if valid id
|
||||
int idx = m_buffer[0];
|
||||
if (idx >= 0 && idx <= m_linkcount) {
|
||||
idx = m_buffer0[0];
|
||||
if (idx >= 0 && idx <= m_linkcount)
|
||||
{
|
||||
// save message to "ring buffer"
|
||||
for (int j = 0x00 ; j < frameSize ; j++)
|
||||
{
|
||||
m_shared[0x2000 + frameOffset + j] = m_buffer[1 + j];
|
||||
m_shared[frameOffset + j] = m_buffer0[1 + j];
|
||||
}
|
||||
m_zfg ^= 0x01;
|
||||
if (isSlave)
|
||||
send_data(m_linkid, frameStart, frameSize, dataSize);
|
||||
else if (isRelay)
|
||||
send_frame(dataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idx == 0xfc)
|
||||
{
|
||||
// 0xFC - VSYNC
|
||||
m_linktimer = 0x00;
|
||||
|
||||
if (!isMaster)
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
// try to read another message
|
||||
recv = read_frame(dataSize);
|
||||
}
|
||||
}
|
||||
while (m_linktimer == 0x01);
|
||||
|
||||
// enable wait for vsync
|
||||
m_linktimer = m_framesync;
|
||||
|
||||
if (isMaster)
|
||||
{
|
||||
// update "ring buffer" if link established
|
||||
send_data(m_linkid, frameStart, frameSize, dataSize);
|
||||
|
||||
// send vsync
|
||||
m_buffer0[0] = 0xfc;
|
||||
m_buffer0[1] = 0x01;
|
||||
send_frame(dataSize);
|
||||
}
|
||||
|
||||
m_zfg_delay = 0x02;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void m2comm_device::read_fg()
|
||||
{
|
||||
if (m_zfg_delay > 0x00)
|
||||
{
|
||||
m_zfg_delay--;
|
||||
return;
|
||||
}
|
||||
if (m_linkalive == 0x01)
|
||||
{
|
||||
int frameStart = 0x2000;
|
||||
int frameSize = m_shared[0x13] << 8 | m_shared[0x12];
|
||||
int frameOffset = frameStart | m_shared[0x15] << 8 | m_shared[0x14];
|
||||
|
||||
int dataSize = frameSize + 1;
|
||||
int recv = 0;
|
||||
int idx = 0;
|
||||
|
||||
// EPR-16726 uses m_fg for Master/Slave
|
||||
// EPR-18643(A) seems to check m_shared[1], with a fallback to m_fg
|
||||
bool isMaster = (m_fg == 0x01 || m_shared[1] == 0x01);
|
||||
bool isSlave = (m_fg == 0x00 && m_shared[1] == 0x02);
|
||||
bool isRelay = (m_fg == 0x00 && m_shared[1] == 0x00);
|
||||
|
||||
do
|
||||
{
|
||||
// try to read a message
|
||||
recv = read_frame(dataSize);
|
||||
while (recv > 0)
|
||||
{
|
||||
// check if valid id
|
||||
idx = m_buffer0[0];
|
||||
if (idx >= 0 && idx <= m_linkcount)
|
||||
{
|
||||
// save message to "ring buffer"
|
||||
for (int j = 0x00 ; j < frameSize ; j++)
|
||||
{
|
||||
m_shared[frameOffset + j] = m_buffer0[1 + j];
|
||||
}
|
||||
m_zfg ^= 0x01;
|
||||
if (isSlave)
|
||||
send_data(m_linkid, frameStart, frameSize, dataSize);
|
||||
else if (isRelay)
|
||||
send_frame(dataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// got only part of a message - read the rest (and drop it)
|
||||
// TODO: combine parts and push to "ring buffer"
|
||||
togo = dataSize - recv;
|
||||
while (togo > 0){
|
||||
recv = m_line_rx.read(m_buffer, togo);
|
||||
togo -= recv;
|
||||
}
|
||||
osd_printf_verbose("M2COMM: dropped a message...\n");
|
||||
}
|
||||
recv = m_line_rx.read(m_buffer, dataSize);
|
||||
}
|
||||
if (idx == 0xfc)
|
||||
{
|
||||
// 0xFC - VSYNC
|
||||
m_linktimer = 0x00;
|
||||
|
||||
if (m_linktimer == 0x00)
|
||||
{
|
||||
// push message to other nodes
|
||||
m_buffer[0] = m_linkid;
|
||||
for (int j = 0x00 ; j < frameSize ; j++)
|
||||
{
|
||||
m_buffer[1 + j] = m_shared[0x2000 + j];
|
||||
if (!isMaster)
|
||||
// forward message to other nodes
|
||||
send_frame(dataSize);
|
||||
}
|
||||
}
|
||||
m_line_tx.write(m_buffer, dataSize);
|
||||
m_linktimer = 0x01;
|
||||
|
||||
// try to read another message
|
||||
recv = read_frame(dataSize);
|
||||
}
|
||||
}
|
||||
while (m_linktimer == 0x01);
|
||||
}
|
||||
}
|
||||
|
||||
int m2comm_device::read_frame(int dataSize)
|
||||
{
|
||||
if (!m_line_rx)
|
||||
return 0;
|
||||
|
||||
// try to read a message
|
||||
std::uint32_t recv = 0;
|
||||
osd_file::error filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv);
|
||||
if (recv > 0)
|
||||
{
|
||||
// check if message complete
|
||||
if (recv != dataSize)
|
||||
{
|
||||
// only part of a message - read on
|
||||
std::uint32_t togo = dataSize - recv;
|
||||
int offset = recv;
|
||||
while (togo > 0)
|
||||
{
|
||||
filerr = m_line_rx->read(m_buffer1, 0, togo, recv);
|
||||
if (recv > 0)
|
||||
{
|
||||
for (int i = 0 ; i < recv ; i++)
|
||||
{
|
||||
m_buffer0[offset + i] = m_buffer1[i];
|
||||
}
|
||||
togo -= recv;
|
||||
offset += recv;
|
||||
}
|
||||
else if (filerr == osd_file::error::NONE && recv == 0)
|
||||
{
|
||||
togo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (filerr == osd_file::error::NONE && recv == 0)
|
||||
{
|
||||
if (m_linkalive == 0x01)
|
||||
{
|
||||
osd_printf_verbose("M2COMM: rx connection lost\n");
|
||||
m_linkalive = 0x02;
|
||||
m_linktimer = 0x00;
|
||||
m_line_rx.reset();
|
||||
}
|
||||
}
|
||||
return recv;
|
||||
}
|
||||
|
||||
void m2comm_device::send_data(uint8_t frameType, int frameStart, int frameSize, int dataSize)
|
||||
{
|
||||
m_buffer0[0] = frameType;
|
||||
for (int i = 0x0000 ; i < frameSize ; i++)
|
||||
{
|
||||
m_buffer0[1 + i] = m_shared[frameStart + i];
|
||||
}
|
||||
send_frame(dataSize);
|
||||
}
|
||||
|
||||
void m2comm_device::send_frame(int dataSize){
|
||||
if (!m_line_tx)
|
||||
return;
|
||||
|
||||
osd_file::error filerr;
|
||||
std::uint32_t written;
|
||||
|
||||
filerr = m_line_tx->write(&m_buffer0, 0, dataSize, written);
|
||||
if (filerr != osd_file::error::NONE)
|
||||
{
|
||||
if (m_linkalive == 0x01)
|
||||
{
|
||||
osd_printf_verbose("M2COMM: tx connection lost\n");
|
||||
m_linkalive = 0x02;
|
||||
m_linktimer = 0x00;
|
||||
m_line_tx.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#define M2COMM_SIMULATION
|
||||
|
||||
#include "osdcore.h"
|
||||
|
||||
#define MCFG_M2COMM_ADD(_tag ) \
|
||||
MCFG_DEVICE_ADD(_tag, M2COMM, 0)
|
||||
@ -56,11 +57,13 @@ private:
|
||||
uint8_t m_cn; // bit0 is used to enable/disable the comm board
|
||||
uint8_t m_fg; // i960 flip gate - bit0 is stored, bit7 is connected to ZFG bit 0
|
||||
|
||||
emu_file m_line_rx; // rx line - can be either differential, simple serial or toslink
|
||||
emu_file m_line_tx; // tx line - is differential, simple serial and toslink
|
||||
osd_file::ptr m_line_rx; // rx line - can be either differential, simple serial or toslink
|
||||
osd_file::ptr m_line_tx; // tx line - is differential, simple serial and toslink
|
||||
char m_localhost[256];
|
||||
char m_remotehost[256];
|
||||
uint8_t m_buffer[0x4000];
|
||||
uint8_t m_buffer0[0x1000];
|
||||
uint8_t m_buffer1[0x1000];
|
||||
uint8_t m_framesync;
|
||||
|
||||
#ifdef M2COMM_SIMULATION
|
||||
uint8_t m_linkenable;
|
||||
@ -68,8 +71,13 @@ private:
|
||||
uint8_t m_linkalive;
|
||||
uint8_t m_linkid;
|
||||
uint8_t m_linkcount;
|
||||
uint8_t m_zfg_delay;
|
||||
|
||||
void comm_tick();
|
||||
void read_fg();
|
||||
int read_frame(int dataSize);
|
||||
void send_data(uint8_t frameType, int frameStart, int frameSize, int dataSize);
|
||||
void send_frame(int dataSize);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,8 @@
|
||||
|
||||
#define S32COMM_SIMULATION
|
||||
|
||||
#include "osdcore.h"
|
||||
|
||||
#define MCFG_S32COMM_ADD(_tag ) \
|
||||
MCFG_DEVICE_ADD(_tag, S32COMM, 0)
|
||||
|
||||
@ -54,16 +56,18 @@ protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
private:
|
||||
uint8_t m_shared[0x800]; // 2k shared memory
|
||||
uint8_t m_zfg; // z80 flip gate? purpose unknown, bit0 is stored
|
||||
uint8_t m_cn; // bit0 is used to enable/disable the comm board
|
||||
uint8_t m_fg; // flip gate? purpose unknown, bit0 is stored, bit7 is connected to ZFG bit 0
|
||||
uint8_t m_shared[0x800]; // 2k shared memory
|
||||
uint8_t m_zfg; // z80 flip gate? purpose unknown, bit0 is stored
|
||||
uint8_t m_cn; // bit0 is used to enable/disable the comm board
|
||||
uint8_t m_fg; // flip gate? purpose unknown, bit0 is stored, bit7 is connected to ZFG bit 0
|
||||
|
||||
emu_file m_line_rx; // rx line - can be either differential, simple serial or toslink
|
||||
emu_file m_line_tx; // tx line - is differential, simple serial and toslink
|
||||
osd_file::ptr m_line_rx; // rx line - can be either differential, simple serial or toslink
|
||||
osd_file::ptr m_line_tx; // tx line - is differential, simple serial and toslink
|
||||
char m_localhost[256];
|
||||
char m_remotehost[256];
|
||||
uint8_t m_buffer[0x800];
|
||||
uint8_t m_buffer0[0x100];
|
||||
uint8_t m_buffer1[0x100];
|
||||
uint8_t m_framesync;
|
||||
|
||||
#ifdef S32COMM_SIMULATION
|
||||
uint8_t m_linkenable;
|
||||
@ -71,10 +75,12 @@ private:
|
||||
uint8_t m_linkalive;
|
||||
uint8_t m_linkid;
|
||||
uint8_t m_linkcount;
|
||||
|
||||
uint16_t m_linktype;
|
||||
|
||||
void comm_tick();
|
||||
int read_frame(int dataSize);
|
||||
void send_data(uint8_t frameType, int frameStart, int frameSize, int dataSize);
|
||||
void send_frame(int dataSize);
|
||||
|
||||
void comm_tick_14084();
|
||||
void comm_tick_15033();
|
||||
|
Loading…
Reference in New Issue
Block a user