diff --git a/src/mame/machine/m2comm.c b/src/mame/machine/m2comm.c new file mode 100644 index 00000000000..835d59f0acd --- /dev/null +++ b/src/mame/machine/m2comm.c @@ -0,0 +1,597 @@ +// license:BSD-3-Clause +// copyright-holders:Ariane Fugmann + +/* +Sega MODEL2 COMMUNICATION BOARD 837-10537 +( http://images.arianchen.de/sega-comm/daytona_comm.jpg ) +|-----------------------------------------------------------------------------| +| |-------------------| |-------------------| | +| |-------------------| |-------------------| | +| CN5 CN4 -- | +| LED Z80 LH5268A 16726.7 JP6 JP5 JP4 JP1 || | +| C|| | +| 315-5751 315-5752 uPD72103 N|| | +| JP7 8|| | +| LH5268A LH5268A JP8 || | +| JP9 -- | +| LH5268A LH5268A 315-5753A 315-5547 | +| | +| CN6 | +| CN9 | +| CN7 | +| CN3 CN2 CN1 | +| |-------------------| |-------------------| |-------------------| | +| |-------------------| |-------------------| |-------------------| | +|-----------------------------------------------------------------------------| + + Setup: + Z80 Zilog Z0840008PSC Z80 CPU (DIP40) + LH5268A SHARP LH5268AD-10LL 8k x8 SRAM (DIP28) + uPD72103 NEC uPD72103 HDLC/Frame Relay Controller (QFP80) + 16726.7 M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-16726') + 315-5751 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5752 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5753A AMI 18CV8PC-15 PAL (DIP20) + 315-5547 AMI 18CV8PC-25 PAL (DIP20) + + Board: + 837-10537 Daytona USA + + EEPROM: + 16726.7 Daytona USA + + +Sega PC BD MODEL2 A-CRX COMMUNICATION 837-11525 +( http://images.arianchen.de/sega-comm/srally_comm.jpg ) +|-------------------------------------------------------------------------------------------| +| |-------------------| |-------------------| |---------| | +| |-------------------| |-------------------| |---------| | +| CN5 CN4 CN10 | +| LED Z80 LH5268A 16726.7 JP6 JP5 JP4 JP1 | +| | +| 315-5751 315-5752 uPD72103 | +| | +| LH5268A LH5268A | +| -- | +| LH5268A LH5268A 315-5753A 315-5547 || | +| C|| | +| N|| | +| CN9 8|| | +| JP7 || | +| CN3 CN2 CN1 JP8 -- | +| |-------------------| |-------------------| |-------------------| JP9 | +| |-------------------| |-------------------| |-------------------| | +|-------------------------------------------------------------------------------------------| + + Setup: + Z80 Zilog Z0840008PSC Z80 CPU (DIP40) + LH5268A SHARP LH5268AD-10LL 8k x8 SRAM (DIP28) + uPD72103 NEC uPD72103 HDLC/Frame Relay Controller (QFP80) + 16726.7 M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-16726') + 315-5751 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5752 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5753A AMI 18CV8PC-15 PAL (DIP20) + 315-5547 AMI 18CV8PC-25 PAL (DIP20) + + Board: + 837-11525 + 837-11572 Sega Rally Championship + + EEPROM: + 16726.7 Sega Rally Championship + 18643A.7 ManxTT + + +Sega PC BD MODEL2 B-CRX COMMUNICATION 837-11615 +( http://images.arianchen.de/sega-comm/model2b-com_top.jpg ) +|-------------------------------------------------------------------------------------------| +| | +| -- | +| || 18643A.7 MB84256A Z80 | +| C|| MB84256A | +| N|| JP9 uPD72103A 315-5751 | +| 8|| JP8 MB84256A | +| || JP7 315-5752 | +| -- MB84256A | +| | +| MB84256A | +| 315-5753A | +| LED | +| 315-5547A | +| | +| CN1 | +| |-------------------| | +| CN3 |-------------------| | +|-------------------------------------------------------------------------------------------| + + Setup: + Z80 Zilog Z0840008PSC Z80 CPU (DIP40) + MB84256A Fujitsu MB84256A-70LL 32k x8 SRAM (SDIP28) + uPD72103A NEC uPD72103 HDLC/Frame Relay Controller (QFP80) + 18643A.7 M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-18643A') + 315-5751 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5752 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5753A ICT PEEL18CV8P-15 PAL (DIP20) + 315-5547A AMI 18CV8PC-25 PAL (DIP20) + + Board: + 837-11615 Virtua On + 837-11615-02 Virtua On + + EEPROM: + 18643.7 Virtua On + 18643A.7 Virtua On + + + + +Sega PC BD MODEL2 C-CRX COMMUNICATION 837-12839 +|-------------------------------------------------------------------------------------------| +| | +| -- | +| || 18643A.7 MB84256A Z80 | +| C|| MB84256A | +| N|| JP9 uPD72103A 315-5751 | +| 8|| JP8 MB84256A | +| || JP7 315-5752 | +| -- MB84256A | +| | +| MB84256A | +| 315-5753A | +| LED | +| 315-5547A | +| | +| CN1 | +| |-------------------| | +| CN3 |-------------------| | +|-------------------------------------------------------------------------------------------| + + Setup: + Z80 Zilog Z0840008PSC Z80 CPU (DIP40) + MB84256A Fujitsu MB84256A-70LL 32k x8 SRAM (SDIP28) + uPD72103A NEC uPD72103 HDLC/Frame Relay Controller (QFP80) + 18643A.7 M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-18643A') + 315-5751 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5752 Lattice GAL16V8B-25LP PAL (DIP20) + 315-5753A ICT PEEL18CV8P-15 PAL (DIP20) + 315-5547A AMI 18CV8PC-25 PAL (DIP20) + + Board: + 837-12839 Sega Touring Car Championship + + EEPROM: + 18643A.7 Sega Touring Car Championship +*/ + +#include "machine/m2comm.h" + +//#define __M2COMM_VERBOSE__ + +MACHINE_CONFIG_FRAGMENT( m2comm ) +MACHINE_CONFIG_END + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type M2COMM = &device_creator; + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor m2comm_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( m2comm ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// m2comm_device - constructor +//------------------------------------------------- + +m2comm_device::m2comm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, M2COMM, "MODEL2 COMMUNICATION BD", tag, owner, clock, "m2comm", __FILE__), + m_line_rx(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE ), + m_line_tx(OPEN_FLAG_READ) +{ + // prepare localhost "filename" + m_localhost[0] = 0; + strcat(m_localhost, "socket."); + strcat(m_localhost, mconfig.options().comm_localhost()); + strcat(m_localhost, ":"); + strcat(m_localhost, mconfig.options().comm_localport()); + + // prepare remotehost "filename" + m_remotehost[0] = 0; + strcat(m_remotehost, "socket."); + strcat(m_remotehost, mconfig.options().comm_remotehost()); + strcat(m_remotehost, ":"); + strcat(m_remotehost, mconfig.options().comm_remoteport()); +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void m2comm_device::device_start() +{ +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void m2comm_device::device_reset() +{ + set_linktype(16726); + m_zfg = 0; + m_cn = 0; + m_fg = 0; +} + +READ8_MEMBER(m2comm_device::zfg_r) +{ + UINT8 result = m_zfg | 0xFE; +#ifdef __M2COMM_VERBOSE__ + printf("m2comm-zfg_r: read register %02x for value %02x\n", offset, result); +#endif + return result; +} + +WRITE8_MEMBER(m2comm_device::zfg_w) +{ +#ifdef __M2COMM_VERBOSE__ + printf("m2comm-zfg_w: %02x\n", data); +#endif + m_zfg = data & 0x01; +} + +READ8_MEMBER(m2comm_device::share_r) +{ + UINT8 result = m_shared[offset]; +#ifdef __M2COMM_VERBOSE__ + printf("m2comm-share_r: read shared memory %02x for value %02x\n", offset, result); +#endif + return result; +} + +WRITE8_MEMBER(m2comm_device::share_w) +{ +#ifdef __M2COMM_VERBOSE__ + printf("m2comm-share_w: %02x %02x\n", offset, data); +#endif + m_shared[offset] = data; +} + +READ8_MEMBER(m2comm_device::cn_r) +{ + return m_cn; +} + +WRITE8_MEMBER(m2comm_device::cn_w) +{ + m_cn = data & 0x01; + +#ifndef __M2COMM_SIMULATION__ + if (!m_cn) + device_reset(); +#else + if (!m_cn) + { + // reset command + printf("M2COMM: board disabled\n"); + m_linkenable = 0x00; + } + else + { + // init command + printf("M2COMM: board enabled\n"); + m_linkenable = 0x01; + m_linkid = 0x00; + m_linkalive = 0x00; + m_linkcount = 0x00; + m_linktimer = 0x04; //0x00E8; // 58 fps * 4s + + comm_tick(); + } +#endif +} + +READ8_MEMBER(m2comm_device::fg_r) +{ + return m_fg | (~m_zfg << 7); +} + +WRITE8_MEMBER(m2comm_device::fg_w) +{ + m_fg = data & 0x01; +} + +void m2comm_device::check_vint_irq() +{ +#ifndef __M2COMM_SIMULATION__ +#else + comm_tick(); +#endif +} + +#ifdef __M2COMM_SIMULATION__ +void m2comm_device::set_linktype(UINT16 linktype) +{ + m_linktype = linktype; + + switch (m_linktype) + { + case 16726: + // Daytona USA / Sega Rally Championship + printf("M2COMM: set mode 'EPR-16726 - Daytona USA'\n"); + break; + } +} + +void m2comm_device::comm_tick() +{ + switch (m_linktype) + { + case 16726: + // Daytona USA / Sega Rally Championship + comm_tick_16726(); + break; + } +} + +void m2comm_device::comm_tick_16726() +{ + if (m_linkenable == 0x01) + { + m_zfg ^= 1; + + int frameStart = 0x2000; + int frameOffset = 0x0000; + int frameSize = 0x01c0; + int dataSize = frameSize + 1; + int togo = 0; + int recv = 0; + int idx = 0; + + bool isMaster = (m_fg == 0x01); + bool isSlave = (m_fg == 0x00); + + // if link not yet established... + if (m_linkalive == 0x00) + { + // waiting... + m_shared[0] = 0x00; + m_shared[2] = 0xff; + m_shared[3] = 0xff; + + // check rx socket + if (!m_line_rx.is_open()) + { + printf("M2COMM: listen on %s\n", m_localhost); + m_line_rx.open(m_localhost); + } + + // check tx socket + if (!m_line_tx.is_open()) + { + printf("M2COMM: 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) + { + m_buffer[1]++; + m_linkid = m_buffer[1]; + + // forward message + m_line_tx.write(m_buffer, dataSize); + } + } + + // 0xFE - link size + else if (idx == 0xfe) + { + if (isSlave) + { + m_linkcount = m_buffer[1]; + + // forward message + m_line_tx.write(m_buffer, dataSize); + } + + // consider it done + printf("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; + } + } + 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; + } + printf("M2COMM: droped 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 + printf("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; + } + + 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) { + int slotFrom = m_linkid - idx; + int slotDest = slotFrom + m_linkcount; + while (slotDest < 9) { + slotDest += m_linkcount; + } + while (slotDest - m_linkcount > 0) { + slotFrom = slotDest - m_linkcount; + if (slotDest < 9) { + int frameOffset1 = frameStart + slotFrom * frameSize; + int frameOffset2 = frameStart + slotDest * frameSize; + for (int j = 0x00 ; j < frameSize ; j++) + { + m_shared[frameOffset2 + j] = m_shared[frameOffset1 + j]; + } + } + slotDest -= m_linkcount; + } + if (slotDest > 0) { + // save message to "ring buffer" + frameOffset = frameStart + (slotDest * frameSize); + for (int j = 0x00 ; j < frameSize ; j++) + { + m_shared[frameOffset + j] = m_buffer[1 + j]; + } + } + if (idx != m_linkid) + { + // 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; + } + printf("M2COMM: droped a message...\n"); + } + recv = m_line_rx.read(m_buffer, dataSize); + } + + // push message to other nodes + m_buffer[0] = m_linkid; + for (int j = 0x00 ; j < frameSize ; j++) + { + m_buffer[1 + j] = m_shared[frameStart + j]; + } + 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 + //TODO:m_shared[3] = 0x00; + } +} +#endif diff --git a/src/mame/machine/m2comm.h b/src/mame/machine/m2comm.h new file mode 100644 index 00000000000..0c717e1c2ed --- /dev/null +++ b/src/mame/machine/m2comm.h @@ -0,0 +1,89 @@ +// license:BSD-3-Clause +// copyright-holders:Ariane Fugmann +#pragma once + +#ifndef __M2COMM_H__ +#define __M2COMM_H__ + +#define __M2COMM_SIMULATION__ + +#include "emu.h" + +#define MCFG_M2COMM_ADD(_tag ) \ + MCFG_DEVICE_ADD(_tag, M2COMM, 0) + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class m2comm_device : public device_t +{ +public: + // construction/destruction + m2comm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual machine_config_constructor device_mconfig_additions() const; + + // single bit registers (74LS74) + DECLARE_READ8_MEMBER(zfg_r); + DECLARE_WRITE8_MEMBER(zfg_w); + // shared memory 2k + DECLARE_READ8_MEMBER(share_r); + DECLARE_WRITE8_MEMBER(share_w); + + // public API - stuff that gets called from host + // shared memory 16k + // reads/writes at I/O 0x01a10000-0x01a13fff + // - share_r + // - share_w + // single bit registers (74LS74) + // reads/writes at I/O 0x01a14000 + DECLARE_READ8_MEMBER(cn_r); + DECLARE_WRITE8_MEMBER(cn_w); + // reads/writes at I/O 0x01a14002 + DECLARE_READ8_MEMBER(fg_r); + DECLARE_WRITE8_MEMBER(fg_w); + + // IRQ logic - 5 = VINT, 7 = DLC + void check_vint_irq(); +#ifdef __M2COMM_SIMULATION__ + void set_linktype(UINT16 linktype); +#endif + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + +private: + UINT8 m_shared[0x4000]; // 16k shared memory + UINT8 m_zfg; // z80 flip gate? purpose unknown, bit0 is stored + UINT8 m_cn; // bit0 is used to enable/disable the comm board + UINT8 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 + char m_localhost[256]; + char m_remotehost[256]; + UINT8 m_buffer[0x4000]; + +#ifdef __M2COMM_SIMULATION__ + UINT8 m_linkenable; + UINT16 m_linktimer; + UINT8 m_linkalive; + UINT8 m_linkid; + UINT8 m_linkcount; + + UINT16 m_linktype; + + void comm_tick(); + + void comm_tick_16726(); +#endif +}; + +// device type definition +extern const device_type M2COMM; + +#endif /* __M2COMM_H__ */