S32COMM: initial upload

prepared for multiple simulation modes.
- f1lap works.
This commit is contained in:
Ariane Fugmann 2015-06-18 23:17:06 +02:00
parent be79fd7774
commit 51bc1ff9bf
5 changed files with 568 additions and 4 deletions

View File

@ -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",

View File

@ -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<segas32_regular_state>;
@ -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
}

View File

@ -8,6 +8,7 @@
#include "machine/eepromser.h"
#include "sound/multipcm.h"
#include "machine/s32comm.h"
@ -34,6 +35,7 @@ public:
required_device<timer_device> m_irq_timer_0;
required_device<timer_device> m_irq_timer_1;
optional_device<s32comm_device> m_s32comm;
typedef void (segas32_state::*sys32_output_callback)(int which, UINT16 data);

456
src/mame/machine/s32comm.c Normal file
View File

@ -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<s32comm_device>;
//-------------------------------------------------
// 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

View File

@ -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__ */