From c32176f2bb336ccfdff7ca8b305a68b8470557bd Mon Sep 17 00:00:00 2001 From: Ariane Fugmann Date: Wed, 21 Mar 2018 18:34:39 +0100 Subject: [PATCH] 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 --- src/emu/emuopts.cpp | 1 + src/emu/emuopts.h | 2 + src/mame/machine/m1comm.cpp | 377 +++++++----- src/mame/machine/m1comm.h | 12 +- src/mame/machine/m2comm.cpp | 389 ++++++++---- src/mame/machine/m2comm.h | 14 +- src/mame/machine/s32comm.cpp | 1102 ++++++++++++++++++---------------- src/mame/machine/s32comm.h | 22 +- 8 files changed, 1137 insertions(+), 782 deletions(-) diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp index e9009e92dd4..06c816a2ff5 100644 --- a/src/emu/emuopts.cpp +++ b/src/emu/emuopts.cpp @@ -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" }, diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index ab220e99bba..b1869c82c16 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -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); } diff --git a/src/mame/machine/m1comm.cpp b/src/mame/machine/m1comm.cpp index 3688e3f617d..4b76be4351f 100644 --- a/src/mame/machine/m1comm.cpp +++ b/src/mame/machine/m1comm.cpp @@ -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 diff --git a/src/mame/machine/m1comm.h b/src/mame/machine/m1comm.h index f7bf91e5e57..dd657bc71cc 100644 --- a/src/mame/machine/m1comm.h +++ b/src/mame/machine/m1comm.h @@ -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 }; diff --git a/src/mame/machine/m2comm.cpp b/src/mame/machine/m2comm.cpp index f7bd43a6efd..6b43ecdf428 100644 --- a/src/mame/machine/m2comm.cpp +++ b/src/mame/machine/m2comm.cpp @@ -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 diff --git a/src/mame/machine/m2comm.h b/src/mame/machine/m2comm.h index ff11efb90ba..93b6145ac9d 100644 --- a/src/mame/machine/m2comm.h +++ b/src/mame/machine/m2comm.h @@ -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 }; diff --git a/src/mame/machine/s32comm.cpp b/src/mame/machine/s32comm.cpp index 5512c9f24ff..761e0a14981 100644 --- a/src/mame/machine/s32comm.cpp +++ b/src/mame/machine/s32comm.cpp @@ -96,9 +96,7 @@ MACHINE_CONFIG_END //------------------------------------------------- s32comm_device::s32comm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, S32COMM, tag, owner, clock), - m_line_rx(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE ), - m_line_tx(OPEN_FLAG_READ) + device_t(mconfig, S32COMM, tag, owner, clock) { // prepare localhost "filename" m_localhost[0] = 0; @@ -113,6 +111,8 @@ s32comm_device::s32comm_device(const machine_config &mconfig, const char *tag, d 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; } //------------------------------------------------- @@ -187,7 +187,7 @@ WRITE8_MEMBER(s32comm_device::cn_w) m_linkid = 0x00; m_linkalive = 0x00; m_linkcount = 0x00; - m_linktimer = 0x04; //0x00E8; // 58 fps * 4s + m_linktimer = 0x00e8; // 58 fps * 4s comm_tick(); } @@ -256,15 +256,97 @@ void s32comm_device::comm_tick() } } +int s32comm_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("S32COMM: rx connection lost\n"); + m_linkalive = 0x02; + m_linktimer = 0x00; + m_line_rx.reset(); + } + } + return recv; +} + +void s32comm_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]; + } + // forward message to next node + send_frame(dataSize); +} + +void s32comm_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("S32COMM: tx connection lost\n"); + m_linkalive = 0x02; + m_linktimer = 0x00; + m_line_tx.reset(); + } + } +} void s32comm_device::comm_tick_14084() { + // m_shared[0] = node count + // m_shared[1] = node id + // m_shared[2] = node mode (0 = slave, 1 = master, ff = relay) + // m_shared[3] = node ready-to-send + // m_shared[4] = node link status (0 = offline, 1 = online) if (m_linkenable == 0x01) { int frameStart = 0x0480; int frameOffset = 0x0000; int frameSize = 0x0080; int dataSize = frameSize + 1; - int togo = 0; int recv = 0; int idx = 0; @@ -272,119 +354,77 @@ void s32comm_device::comm_tick_14084() bool isSlave = (m_shared[2] == 0x00); bool isRelay = (m_shared[2] == 0xFF); - // if link not yet established... - if (m_linkalive == 0x00) + if (m_linkalive == 0x02) { - // waiting... + // link failed... + m_shared[4] = 0xff; + return; + } + else if (m_linkalive == 0x00) + { + // link not yet established... m_shared[4] = 0x00; // check rx socket - if (!m_line_rx.is_open()) + if (!m_line_rx) { osd_printf_verbose("S32COMM: 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("S32COMM: 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 if 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) { - if (isSlave || isRelay) + // slave gets own id + 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("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); - m_linkalive = 0x01; - - // write to shared mem - m_shared[4] = 0x01; - m_shared[1] = m_linkid; - m_shared[0] = m_linkcount; + // slave and relay forward message + 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]; + + // slave and relay forward message + send_frame(dataSize); } - osd_printf_verbose("S32COMM: 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("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); @@ -396,12 +436,44 @@ void s32comm_device::comm_tick_14084() m_shared[0] = 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("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); + m_linkalive = 0x01; + + // write to shared mem + m_shared[4] = 0x01; + m_shared[1] = m_linkid; + m_shared[0] = m_linkcount; + } + + else if (m_linktimer > 0x01) { // decrease delay timer m_linktimer--; - if (m_linktimer == 0x02) - m_linktimer = 0x00; } } } @@ -410,85 +482,93 @@ void s32comm_device::comm_tick_14084() // 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) + do { - // check if complete message - if (recv == dataSize) + // try to read one 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 = 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 = 0x05 ; 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 = 0x05; + for (int j = 0x00 ; j < 0x0b ; 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("S32COMM: 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[3] != 0x00) + if (m_linkid != 0x00) { - m_buffer[0] = m_linkid; - frameOffset = m_linkid * frameSize; - for (int j = 0x00 ; j < frameSize ; j++) + // check ready-to-send flag + if (m_shared[3] != 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 = 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 = 0x05 ; 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 some additional status bytes + send_data(0xfd, 0x05, 0x0b, dataSize); + + // send vsync + m_buffer0[0] = 0xfc; + m_buffer0[1] = 0x01; + send_frame(dataSize); } } @@ -500,6 +580,11 @@ void s32comm_device::comm_tick_14084() void s32comm_device::comm_tick_15033() { + // m_shared[0] = node count + // m_shared[1] = node id + // m_shared[2] = node mode (0 = slave, 1 = master, ff = relay) + // m_shared[3] = node ready-to-send + // m_shared[4] = node link status (0 = offline, 1 = online) if (m_linkenable == 0x01) { int frameStartTX = 0x0710; @@ -507,7 +592,6 @@ void s32comm_device::comm_tick_15033() int frameOffset = 0x0000; int frameSize = 0x00E0; int dataSize = frameSize + 1; - int togo = 0; int recv = 0; int idx = 0; @@ -515,129 +599,89 @@ void s32comm_device::comm_tick_15033() bool isSlave = (m_shared[2] == 0x00); bool isRelay = (m_shared[2] == 0x02); - // if link not yet established - Z80 reply check? - if (m_linkalive == 0x00 && m_shared[0] == 0x56 && m_shared[1] == 0x37 && m_shared[2] == 0x30) + if (m_linkalive == 0x02) { - for (int j = 0x003 ; j < 0x0800 ; j++) - { - m_shared[j] = 0; - } - m_shared[0x08] = 0x5A; - m_shared[0x09] = 0x38; - m_shared[0x0A] = 0x30; + // link failed... + m_shared[0] = 0xff; + return; } else if (m_linkalive == 0x00) { + // link not yet established... + if (m_shared[0] == 0x56 && m_shared[1] == 0x37 && m_shared[2] == 0x30) + { + for (int j = 0x003 ; j < 0x0800 ; j++) + { + m_shared[j] = 0; + } + m_shared[0x08] = 0x5A; + m_shared[0x09] = 0x38; + m_shared[0x0A] = 0x30; + } + // waiting... m_shared[4] = 0x00; // check rx socket - if (!m_line_rx.is_open()) + if (!m_line_rx) { osd_printf_verbose("S32COMM: 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("S32COMM: 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) + recv = read_frame(dataSize); + while (recv > 0) { - // check if complete message - if (recv == dataSize) - { - // check if message id - idx = m_buffer[0]; + // check if 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) { - if (isSlave || isRelay) + // slave gets own id + 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("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); - m_linkalive = 0x01; - - // write to shared mem - m_shared[4] = 0x01; - m_shared[1] = m_linkid; - m_shared[0] = m_linkcount; + // slave and relay forward message + 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]; + + // slave and relay forward message + send_frame(dataSize); } - osd_printf_verbose("S32COMM: 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("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); @@ -649,215 +693,8 @@ void s32comm_device::comm_tick_15033() m_shared[0] = m_linkcount; } - else if (m_linktimer > 0x02) - { - // 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) - { - // check if complete message - if (recv == dataSize) - { - // check if valid id - int idx = m_buffer[0]; - if (idx > 0 && idx <= m_linkcount) { - // if not our own message - if (idx != m_linkid) - { - // save message to "ring buffer" - frameOffset = frameStartRX + ((idx - 1) * frameSize); - for (int j = 0x00 ; j < frameSize ; j++) - { - m_shared[frameOffset + j] = m_buffer[1 + j]; - } - - // forward message to other nodes - m_line_tx.write(m_buffer, dataSize); - } - } else { - if (!isMaster && idx == 0xF0){ - // 0xF0 - master addional bytes - for (int j = 0x05 ; j < 0x10 ; j++) - { - m_shared[j] = m_buffer[1 + j]; - } - - // forward message to other nodes - m_line_tx.write(m_buffer, 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("S32COMM: dropped a message...\n"); - } - recv = m_line_rx.read(m_buffer, dataSize); - } - - // update "ring buffer" if link established - // live relay does not send data - if (m_linkid != 0x00 && m_shared[3] != 0x00) - { - m_buffer[0] = m_linkid; - frameOffset = frameStartRX + ((m_linkid - 1) * frameSize); - for (int j = 0x00 ; j < frameSize ; j++) - { - // push message to "ring buffer" - m_shared[frameOffset + j] = m_shared[frameStartTX + j]; - m_buffer[1 + j] = m_shared[frameStartTX + j]; - } - // push message to other nodes - m_line_tx.write(m_buffer, dataSize); - - // master sends some additional status bytes - if (isMaster){ - m_buffer[0] = 0xF0; - for (int j = 0x00 ; j < frameSize ; j++) - { - m_buffer[1 + j] = 0x00; - } - for (int j = 0x05 ; j < 0x10 ; j++) - { - m_buffer[1 + j] = m_shared[j]; - } - // push message to other nodes - m_line_tx.write(m_buffer, dataSize); - } - } - // clear 03 - m_shared[3] = 0x00; - } - } -} - -void s32comm_device::comm_tick_15612() -{ - if (m_linkenable == 0x01) - { - int frameStart = 0x0010; - int frameOffset = 0x0000; - int frameSize = 0x00E0; - int dataSize = frameSize + 1; - int togo = 0; - int recv = 0; - int idx = 0; - - bool isMaster = (m_shared[1] == 0x01); - bool isSlave = (m_shared[1] == 0x02); - bool isRelay = (m_shared[1] == 0x00); - - // if link not yet established... - if (m_linkalive == 0x00) - { - // waiting... - m_shared[0] = 0x05; - - // check rx socket - if (!m_line_rx.is_open()) - { - osd_printf_verbose("S32COMM: listen on %s\n", m_localhost); - m_line_rx.open(m_localhost); - } - - // check tx socket - if (!m_line_tx.is_open()) - { - osd_printf_verbose("S32COMM: connect to %s\n", m_remotehost); - m_line_tx.open(m_remotehost); - } - - // if both sockets are there check ring - if ((m_line_rx.is_open()) && (m_line_tx.is_open())) - { - // try to read one messages - recv = m_line_rx.read(m_buffer, dataSize); - while (recv != 0) - { - // check if complete message - if (recv == dataSize) - { - // check if message id - idx = m_buffer[0]; - - // 0xFF - link id - if (idx == 0xFF) - { - 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); - } - } - - // 0xFE - link size - else if (idx == 0xFE) - { - if (isSlave || isRelay) - { - m_linkcount = m_buffer[1]; - - // slave and relay forward message - m_line_tx.write(m_buffer, dataSize); - } - - // consider it done - osd_printf_verbose("S32COMM: 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; - } - } - 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("S32COMM: dropped a message...\n"); - } - if (m_linkalive == 0x00) - recv = m_line_rx.read(m_buffer, dataSize); + recv = read_frame(dataSize); else recv = 0; } @@ -866,19 +703,228 @@ void s32comm_device::comm_tick_15612() 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_line_tx.write(m_buffer, dataSize); + m_buffer0[0] = 0xff; + m_buffer0[1] = 0x01; + 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_line_tx.write(m_buffer, dataSize); + m_buffer0[0] = 0xfe; + m_buffer0[1] = m_linkcount; + send_frame(dataSize); + + // consider it done + osd_printf_verbose("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); + m_linkalive = 0x01; + + // write to shared mem + m_shared[4] = 0x01; + m_shared[1] = m_linkid; + m_shared[0] = m_linkcount; + } + + else if (m_linktimer > 0x01) + { + // decrease delay timer + m_linktimer--; + } + } + } + } + + // if link established + if (m_linkalive == 0x01) + { + 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) + { + // if not own message + if (idx != m_linkid) + { + // save message to "ring buffer" + frameOffset = frameStartRX + ((idx - 1) * frameSize); + for (int j = 0x00 ; j < frameSize ; j++) + { + m_shared[frameOffset + j] = m_buffer0[1 + j]; + } + + // forward message to other nodes + send_frame(dataSize); + } + } + 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) + { + // save message to "ring buffer" + frameOffset = 0x05; + for (int j = 0x00 ; j < 0x0b ; j++) + { + m_shared[frameOffset + j] = m_buffer0[1 + j]; + } + + // 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; + + // update "ring buffer" if link established + // live relay does not send data + if (m_linkid != 0x00) + { + // check ready-to-send flag + if (m_shared[3] != 0x00) + { + send_data(m_linkid, frameStartTX, frameSize, dataSize); + + // save message to "ring buffer" + frameOffset = frameStartRX + ((m_linkid - 1) * frameSize); + for (int j = 0x00 ; j < frameSize ; j++) + { + m_shared[frameOffset + j] = m_buffer0[1 + j]; + } + } + + if (isMaster){ + // master sends some additional status bytes + send_data(0xfd, 0x05, 0x0b, dataSize); + + // send vsync + m_buffer0[0] = 0xfc; + m_buffer0[1] = 0x01; + send_frame(dataSize); + } + } + + // clear 03 + m_shared[3] = 0x00; + } + } +} + +void s32comm_device::comm_tick_15612() +{ + // m_shared[0] = node link status (5 = linking, 1 = online) + // m_shared[1] = node mode (0 = relay, 1 = master, 2 = slave) + // m_shared[2] = node id + // m_shared[3] = node count + // m_shared[4] = ready-to-send + if (m_linkenable == 0x01) + { + int frameStart = 0x0010; + int frameOffset = 0x0000; + int frameSize = 0x00E0; + int dataSize = frameSize + 1; + int recv = 0; + int idx = 0; + + bool isMaster = (m_shared[1] == 0x01); + bool isSlave = (m_shared[1] == 0x02); + bool isRelay = (m_shared[1] == 0x00); + + if (m_linkalive == 0x02) + { + // 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) + { + osd_printf_verbose("S32COMM: listen on %s\n", 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) + { + osd_printf_verbose("S32COMM: connect to %s\n", 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 && m_line_tx) + { + // try to read one message + recv = read_frame(dataSize); + while (recv > 0) + { + // check if message id + idx = m_buffer0[0]; + + // 0xFF - link id + if (idx == 0xff) + { + if (isMaster) + { + // master gets first id and starts next state + m_linkid = 0x01; + m_linkcount = m_buffer0[1]; + m_linktimer = 0x00; + } + else if (isSlave || isRelay) + { + // slave gets own id + if (isSlave) + { + m_buffer0[1]++; + m_linkid = m_buffer0[1]; + } + + // slave and relay forward message + send_frame(dataSize); + } + } + + // 0xFE - link size + else if (idx == 0xfe) + { + if (isSlave || isRelay) + { + m_linkcount = m_buffer0[1]; + + // slave and relay forward message + send_frame(dataSize); + } // consider it done osd_printf_verbose("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); @@ -890,12 +936,44 @@ void s32comm_device::comm_tick_15612() 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("S32COMM: 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; + } + + else if (m_linktimer > 0x01) { // decrease delay timer m_linktimer--; - if (m_linktimer == 0x02) - m_linktimer = 0x00; } } } @@ -904,87 +982,97 @@ void s32comm_device::comm_tick_15612() // 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) + 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 = 0x05 ; 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 = 0x05; + for (int j = 0x00 ; j < 0x0b ; 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("S32COMM: 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 = 0x05 ; 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 some additional status bytes + // master sends additional status bytes + send_data(0xfd, 0x05, 0x0b, dataSize); + + // send vsync + m_buffer0[0] = 0xfc; + m_buffer0[1] = 0x01; + send_frame(dataSize); } } + // clear 04 m_shared[4] = 0x00; } diff --git a/src/mame/machine/s32comm.h b/src/mame/machine/s32comm.h index 658e2e9fcdd..8f0f9536a60 100644 --- a/src/mame/machine/s32comm.h +++ b/src/mame/machine/s32comm.h @@ -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();