diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 10dac16f38f..c5a3f346b6f 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -2426,6 +2426,7 @@ files { MAME_DIR .. "src/mame/drivers/model1.c", MAME_DIR .. "src/mame/machine/model1.c", MAME_DIR .. "src/mame/video/model1.c", + MAME_DIR .. "src/mame/machine/s32comm.c", MAME_DIR .. "src/mame/machine/m1comm.c", MAME_DIR .. "src/mame/audio/dsbz80.c", MAME_DIR .. "src/mame/drivers/model2.c", diff --git a/src/mame/drivers/segas32.c b/src/mame/drivers/segas32.c index bfcf36dd938..73fa882fe4d 100644 --- a/src/mame/drivers/segas32.c +++ b/src/mame/drivers/segas32.c @@ -524,7 +524,8 @@ segas32_state::segas32_state(const machine_config &mconfig, const char *tag, dev m_screen(*this, "screen"), m_palette(*this, "palette"), m_irq_timer_0(*this, "v60_irq0"), - m_irq_timer_1(*this, "v60_irq1") + m_irq_timer_1(*this, "v60_irq1"), + m_s32comm(*this, "s32comm") { } @@ -761,6 +762,8 @@ INTERRUPT_GEN_MEMBER(segas32_state::start_of_vblank_int) machine().scheduler().timer_set(m_screen->time_until_pos(0), timer_expired_delegate(FUNC(segas32_state::end_of_vblank_int),this)); if (m_system32_prot_vblank) (this->*m_system32_prot_vblank)(); + if (m_s32comm != NULL) + m_s32comm->check_vint_irq(); } @@ -1363,6 +1366,9 @@ static ADDRESS_MAP_START( system32_map, AS_PROGRAM, 16, segas32_state ) AM_RANGE(0x600000, 0x60ffff) AM_MIRROR(0x0e0000) AM_READWRITE(system32_paletteram_r, system32_paletteram_w) AM_SHARE("paletteram.0") AM_RANGE(0x610000, 0x61007f) AM_MIRROR(0x0eff80) AM_READWRITE(system32_mixer_r, system32_mixer_w) AM_RANGE(0x700000, 0x701fff) AM_MIRROR(0x0fe000) AM_READWRITE(shared_ram_16_r, shared_ram_16_w) + AM_RANGE(0x800000, 0x800fff) AM_DEVREADWRITE8("s32comm", s32comm_device, share_r, share_w, 0x00ff) + AM_RANGE(0x801000, 0x801001) AM_DEVREADWRITE8("s32comm", s32comm_device, cn_r, cn_w, 0x00ff) + AM_RANGE(0x801002, 0x801003) AM_DEVREADWRITE8("s32comm", s32comm_device, fg_r, fg_w, 0x00ff) AM_RANGE(0xc00000, 0xc0001f) AM_MIRROR(0x0fff80) AM_READWRITE(io_chip_r, io_chip_w) AM_RANGE(0xc00040, 0xc0007f) AM_MIRROR(0x0fff80) AM_READWRITE(io_expansion_r, io_expansion_w) AM_RANGE(0xd00000, 0xd0000f) AM_MIRROR(0x07fff0) AM_READWRITE(interrupt_control_16_r, interrupt_control_16_w) @@ -1384,6 +1390,9 @@ static ADDRESS_MAP_START( multi32_map, AS_PROGRAM, 32, segas32_state ) AM_RANGE(0x680000, 0x68ffff) AM_MIRROR(0x060000) AM_READWRITE(multi32_paletteram_1_r, multi32_paletteram_1_w) AM_SHARE("paletteram.1") AM_RANGE(0x690000, 0x69007f) AM_MIRROR(0x06ff80) AM_WRITE(multi32_mixer_1_w) AM_RANGE(0x700000, 0x701fff) AM_MIRROR(0x0fe000) AM_READWRITE(shared_ram_32_r, shared_ram_32_w) + AM_RANGE(0x800000, 0x800fff) AM_DEVREADWRITE8("s32comm", s32comm_device, share_r, share_w, 0x00ff00ff) + AM_RANGE(0x801000, 0x801003) AM_DEVREADWRITE8("s32comm", s32comm_device, cn_r, cn_w, 0x000000ff) + AM_RANGE(0x801000, 0x801003) AM_DEVREADWRITE8("s32comm", s32comm_device, fg_r, fg_w, 0x00ff0000) AM_RANGE(0xc00000, 0xc0001f) AM_MIRROR(0x07ff80) AM_READWRITE(io_chip_0_r, io_chip_0_w) AM_RANGE(0xc00040, 0xc0007f) AM_MIRROR(0x07ff80) AM_READWRITE(io_expansion_0_r, io_expansion_0_w) AM_RANGE(0xc80000, 0xc8001f) AM_MIRROR(0x07ff80) AM_READWRITE(io_chip_1_r, io_chip_1_w) @@ -2477,6 +2486,8 @@ static MACHINE_CONFIG_FRAGMENT( system32 ) MCFG_RF5C68_ADD("rfsnd", RFC_CLOCK/4) MCFG_SOUND_ROUTE(0, "lspeaker", 0.55) MCFG_SOUND_ROUTE(1, "rspeaker", 0.55) + + MCFG_S32COMM_ADD("s32comm") MACHINE_CONFIG_END const device_type SEGA_S32_REGULAR_DEVICE = &device_creator; @@ -2561,6 +2572,8 @@ static MACHINE_CONFIG_FRAGMENT( multi32 ) MCFG_SOUND_ADD("sega", MULTIPCM, MASTER_CLOCK/4) MCFG_SOUND_ROUTE(1, "lspeaker", 1.0) MCFG_SOUND_ROUTE(0, "rspeaker", 1.0) + + MCFG_S32COMM_ADD("s32comm") MACHINE_CONFIG_END @@ -5148,9 +5161,6 @@ DRIVER_INIT_MEMBER(segas32_new_state,f1en) { DRIVER_INIT_MEMBER(segas32_new_state,f1lap) { m_mainpcb->init_f1lap(); - m_dual_pcb_comms = auto_alloc_array(machine(), UINT16, 0x1000/2); - m_mainpcb->m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x800000, 0x800fff, read16_delegate(FUNC(segas32_new_state::dual_pcb_comms_r),this), write16_delegate(FUNC(segas32_new_state::dual_pcb_comms_w),this)); - m_mainpcb->m_maincpu->space(AS_PROGRAM).install_read_handler(0x801000, 0x801003, read16_delegate(FUNC(segas32_new_state::dual_pcb_masterslave),this)); } @@ -5228,6 +5238,8 @@ void segas32_state::init_f1lap(void) m_system32_prot_vblank = &segas32_state::f1lap_fd1149_vblank; m_sw1_output = &segas32_state::f1lap_sw1_output; + + m_s32comm->set_linktype(15612); // EPR-15612 } @@ -5290,6 +5302,8 @@ void segas32_state::init_radr(void) segas32_common_init(read16_delegate(FUNC(segas32_state::analog_custom_io_r),this), write16_delegate(FUNC(segas32_state::analog_custom_io_w),this)); m_sw1_output = &segas32_state::radm_sw1_output; m_sw2_output = &segas32_state::radr_sw2_output; + + m_s32comm->set_linktype(14084); // EPR-14084 } diff --git a/src/mame/includes/segas32.h b/src/mame/includes/segas32.h index 9ea0727ad3a..07bc22714ba 100644 --- a/src/mame/includes/segas32.h +++ b/src/mame/includes/segas32.h @@ -8,6 +8,7 @@ #include "machine/eepromser.h" #include "sound/multipcm.h" +#include "machine/s32comm.h" @@ -34,6 +35,7 @@ public: required_device m_irq_timer_0; required_device m_irq_timer_1; + optional_device m_s32comm; typedef void (segas32_state::*sys32_output_callback)(int which, UINT16 data); diff --git a/src/mame/machine/s32comm.c b/src/mame/machine/s32comm.c new file mode 100644 index 00000000000..bf8367fcbb1 --- /dev/null +++ b/src/mame/machine/s32comm.c @@ -0,0 +1,456 @@ +// license:BSD-3-Clause +// copyright-holders:Ariane Fugmann + +/* +System32/Multi32 Comm PCB +*/ + +#include "machine/s32comm.h" + +//#define __S32COMM_VERBOSE__ + +MACHINE_CONFIG_FRAGMENT( s32comm ) +MACHINE_CONFIG_END + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type S32COMM = &device_creator; + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor s32comm_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( s32comm ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// s32comm_device - constructor +//------------------------------------------------- + +s32comm_device::s32comm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, S32COMM, "SYSTEM32 COMMUNICATION BD", tag, owner, clock, "s32comm", __FILE__), + m_line_rx(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE ), + m_line_tx(OPEN_FLAG_READ) +{ + // prepare localhost "filename" + if (strlen(m_localhost) == 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" + if (strlen(m_remotehost) == 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 s32comm_device::device_start() +{ +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void s32comm_device::device_reset() +{ + m_zfg = 0; + m_cn = 0; + m_fg = 0; +} + +READ8_MEMBER(s32comm_device::zfg_r) +{ + UINT8 result = m_zfg | 0xFE; +#ifdef __S32COMM_VERBOSE__ + printf("s32comm-zfg_r: read register %02x for value %02x\n", offset, result); +#endif + return result; +} + +WRITE8_MEMBER(s32comm_device::zfg_w) +{ +#ifdef __S32COMM_VERBOSE__ + printf("s32comm-zfg_w: %02x\n", data); +#endif + m_zfg = data & 0x01; +} + +READ8_MEMBER(s32comm_device::share_r) +{ + UINT8 result = m_shared[offset]; +#ifdef __S32COMM_VERBOSE__ + printf("s32comm-share_r: read shared memory %02x for value %02x\n", offset, result); +#endif + return result; +} + +WRITE8_MEMBER(s32comm_device::share_w) +{ +#ifdef __S32COMM_VERBOSE__ + printf("s32comm-share_w: %02x %02x\n", offset, data); +#endif + m_shared[offset] = data; +} + +READ8_MEMBER(s32comm_device::cn_r) +{ + return m_cn | 0xFE; +} + +WRITE8_MEMBER(s32comm_device::cn_w) +{ + m_cn = data & 0x01; + +#ifndef __S32COMM_SIMULATION__ + if (!m_cn) + device_reset(); +#else + if (!m_cn) + { + // reset command + printf("S32COMM: board disabled\n"); + m_linkenable = 0x00; + } + else + { + // init command + printf("S32COMM: board enabled\n"); + m_linkenable = 0x01; + m_linkid = 0x00; + m_linkalive = 0x00; + m_linkcount = 0x00; + m_linktimer = 0x04; //0x00E8; // 58 fps * 4s + } +#endif +} + +READ8_MEMBER(s32comm_device::fg_r) +{ + return m_fg | (~m_zfg << 7) | 0x7E; +} + +WRITE8_MEMBER(s32comm_device::fg_w) +{ + if (!m_cn) + return; + + m_fg = data & 0x01; +} + +void s32comm_device::check_vint_irq() +{ +#ifndef __S32COMM_SIMULATION__ +#else + comm_tick(); +#endif +} + +#ifdef __S32COMM_SIMULATION__ +void s32comm_device::set_linktype(UINT16 linktype) +{ + m_linktype = linktype; + + switch (m_linktype) + { + case 1: + // F1 Super Lap + printf("S32COMM: set mode 'EPR-15612 - F1 Super Lap'\n"); + break; + case 2: + // Rad Rally + printf("S32COMM: set mode 'EPR-14084 - Rad Rally'\n"); + break; + case 3: + // OutRunners + printf("S32COMM: set mode 'EPR-????? - OutRunners'\n"); + break; + } +} + +void s32comm_device::comm_tick() +{ + switch (m_linktype) + { + case 14084: + // Rad Rally + comm_tick_14084(); + break; + case 15612: + // F1 Super Lap + comm_tick_15612(); + break; + case 3: + // OutRunners + comm_tick3(); + break; + } +} + +void s32comm_device::comm_tick_14084() +{ +} + +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()) + { + printf("S32COMM: listen on %s\n", m_localhost); + m_line_rx.open(m_localhost); + } + + // check tx socket + if (!m_line_tx.is_open()) + { + printf("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 + printf("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; + } + printf("S32COMM: 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("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 > 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 = frameStart + (idx * 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 = 0x06 ; 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("S32COMM: droped 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[4] != 0x00) + { + m_buffer[0] = m_linkid; + frameOffset = frameStart + (m_linkid * frameSize); + for (int j = 0x00 ; j < frameSize ; j++) + { + // 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); + + // 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 = 0x06 ; j < 0x10 ; j++) + { + m_buffer[1 + j] = m_shared[frameStart + j]; + } + // push message to other nodes + m_line_tx.write(m_buffer, dataSize); + } + } + // clear 04 + m_shared[4] = 0x00; + } + } +} + +void s32comm_device::comm_tick3() +{ +} +#endif diff --git a/src/mame/machine/s32comm.h b/src/mame/machine/s32comm.h new file mode 100644 index 00000000000..c349740d4ef --- /dev/null +++ b/src/mame/machine/s32comm.h @@ -0,0 +1,91 @@ +// license:BSD-3-Clause +// copyright-holders:Ariane Fugmann +#pragma once + +#ifndef __S32COMM_H__ +#define __S32COMM_H__ + +#define __S32COMM_SIMULATION__ + +#include "emu.h" + +#define MCFG_S32COMM_ADD(_tag ) \ + MCFG_DEVICE_ADD(_tag, S32COMM, 0) + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class s32comm_device : public device_t +{ +public: + // construction/destruction + s32comm_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 2k + // reads/writes at I/O 0x800xxx + // - share_r + // - share_w + // single bit registers (74LS74) + // reads/writes at I/O 0x801000 + DECLARE_READ8_MEMBER(cn_r); + DECLARE_WRITE8_MEMBER(cn_w); + // reads/writes at I/O 0x801002 + DECLARE_READ8_MEMBER(fg_r); + DECLARE_WRITE8_MEMBER(fg_w); + + // IRQ logic - 5 = VINT, 7 = DLC + void check_vint_irq(); +#ifdef __S32COMM_SIMULATION__ + void set_linktype(UINT16 linktype); +#endif + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + +private: + UINT8 m_shared[0x800]; // 2k 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[0x800]; + +#ifdef __S32COMM_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_14084(); + void comm_tick_15612(); + void comm_tick3(); +#endif +}; + +// device type definition +extern const device_type S32COMM; + +#endif /* __S32COMM_H__ */