mirror of
https://github.com/holub/mame
synced 2025-04-16 05:24:54 +03:00
Merge pull request #205 from SailorSat/master
Model1 Communication Board [Ariane Fugmann] - add emulator options required for comm boards - add the model 1 communication board as a device - add an optional simulation for the model 1 communication (enabled atm.) - allows to play Virtua Racing, Virtua Formula and WingWar in "link mode".
This commit is contained in:
commit
ed05af5bff
@ -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/m1comm.c",
|
||||
MAME_DIR .. "src/mame/audio/dsbz80.c",
|
||||
MAME_DIR .. "src/mame/drivers/model2.c",
|
||||
MAME_DIR .. "src/mame/video/model2.c",
|
||||
|
@ -160,6 +160,13 @@ const options_entry emu_options::s_option_entries[] =
|
||||
{ OPTION_UPDATEINPAUSE, "0", OPTION_BOOLEAN, "keep calling video updates while in pause" },
|
||||
{ OPTION_DEBUGSCRIPT, NULL, OPTION_STRING, "script for debugger" },
|
||||
|
||||
// comm options
|
||||
{ NULL, NULL, OPTION_HEADER, "CORE COMM OPTIONS" },
|
||||
{ OPTION_COMM_LOCAL_HOST, "0.0.0.0", OPTION_STRING, "local address to bind to" },
|
||||
{ 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" },
|
||||
|
||||
// misc options
|
||||
{ NULL, NULL, OPTION_HEADER, "CORE MISC OPTIONS" },
|
||||
{ OPTION_DRC, "1", OPTION_BOOLEAN, "enable DRC cpu core if available" },
|
||||
|
@ -174,6 +174,12 @@ enum
|
||||
#define OPTION_UI_FONT "uifont"
|
||||
#define OPTION_RAMSIZE "ramsize"
|
||||
|
||||
// core comm options
|
||||
#define OPTION_COMM_LOCAL_HOST "comm_localhost"
|
||||
#define OPTION_COMM_LOCAL_PORT "comm_localport"
|
||||
#define OPTION_COMM_REMOTE_HOST "comm_remotehost"
|
||||
#define OPTION_COMM_REMOTE_PORT "comm_remoteport"
|
||||
|
||||
#define OPTION_CONFIRM_QUIT "confirm_quit"
|
||||
#define OPTION_UI_MOUSE "ui_mouse"
|
||||
|
||||
@ -343,6 +349,12 @@ public:
|
||||
const char *ui_font() const { return value(OPTION_UI_FONT); }
|
||||
const char *ram_size() const { return value(OPTION_RAMSIZE); }
|
||||
|
||||
// core comm options
|
||||
const char *comm_localhost() const { return value(OPTION_COMM_LOCAL_HOST); }
|
||||
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 confirm_quit() const { return bool_value(OPTION_CONFIRM_QUIT); }
|
||||
bool ui_mouse() const { return bool_value(OPTION_UI_MOUSE); }
|
||||
|
||||
|
@ -742,6 +742,9 @@ TIMER_DEVICE_CALLBACK_MEMBER(model1_state::model1_interrupt)
|
||||
irq_raise(m_sound_irq);
|
||||
|
||||
m_m1audio->check_fifo_irq();
|
||||
|
||||
if (m_m1comm != NULL)
|
||||
m_m1comm->check_vint_irq();
|
||||
}
|
||||
}
|
||||
|
||||
@ -902,6 +905,10 @@ static ADDRESS_MAP_START( model1_mem, AS_PROGRAM, 16, model1_state )
|
||||
AM_RANGE(0x900000, 0x903fff) AM_RAM_WRITE(p_w) AM_SHARE("palette")
|
||||
AM_RANGE(0x910000, 0x91bfff) AM_RAM AM_SHARE("color_xlat")
|
||||
|
||||
AM_RANGE(0xb00000, 0xb00fff) AM_DEVREADWRITE8("m1comm", m1comm_device, share_r, share_w, 0xffff)
|
||||
AM_RANGE(0xb01000, 0xb01001) AM_DEVREADWRITE8("m1comm", m1comm_device, cn_r, cn_w, 0x00ff)
|
||||
AM_RANGE(0xb01002, 0xb01003) AM_DEVREADWRITE8("m1comm", m1comm_device, fg_r, fg_w, 0x00ff)
|
||||
|
||||
AM_RANGE(0xc00000, 0xc0003f) AM_READWRITE(io_r, io_w)
|
||||
|
||||
AM_RANGE(0xc00040, 0xc00043) AM_READWRITE(network_ctl_r, network_ctl_w)
|
||||
@ -950,6 +957,10 @@ static ADDRESS_MAP_START( model1_vr_mem, AS_PROGRAM, 16, model1_state )
|
||||
AM_RANGE(0x900000, 0x903fff) AM_RAM_WRITE(p_w) AM_SHARE("palette")
|
||||
AM_RANGE(0x910000, 0x91bfff) AM_RAM AM_SHARE("color_xlat")
|
||||
|
||||
AM_RANGE(0xb00000, 0xb00fff) AM_DEVREADWRITE8("m1comm", m1comm_device, share_r, share_w, 0xffff)
|
||||
AM_RANGE(0xb01000, 0xb01001) AM_DEVREADWRITE8("m1comm", m1comm_device, cn_r, cn_w, 0x00ff)
|
||||
AM_RANGE(0xb01002, 0xb01003) AM_DEVREADWRITE8("m1comm", m1comm_device, fg_r, fg_w, 0x00ff)
|
||||
|
||||
AM_RANGE(0xc00000, 0xc0003f) AM_READWRITE(io_r, io_w)
|
||||
|
||||
AM_RANGE(0xc00040, 0xc00043) AM_READWRITE(network_ctl_r, network_ctl_w)
|
||||
@ -1541,6 +1552,8 @@ static MACHINE_CONFIG_START( model1, model1_state )
|
||||
MCFG_VIDEO_START_OVERRIDE(model1_state,model1)
|
||||
|
||||
MCFG_SEGAM1AUDIO_ADD("m1audio")
|
||||
|
||||
MCFG_M1COMM_ADD("m1comm")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED(swa, model1)
|
||||
@ -1586,6 +1599,8 @@ static MACHINE_CONFIG_START( model1_vr, model1_state )
|
||||
MCFG_VIDEO_START_OVERRIDE(model1_state,model1)
|
||||
|
||||
MCFG_SEGAM1AUDIO_ADD("m1audio")
|
||||
|
||||
MCFG_M1COMM_ADD("m1comm")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
GAME( 1993, vf, 0, model1, vf, driver_device, 0, ROT0, "Sega", "Virtua Fighter", GAME_IMPERFECT_GRAPHICS )
|
||||
|
@ -2,6 +2,7 @@
|
||||
// copyright-holders:Olivier Galibert
|
||||
#include "audio/dsbz80.h"
|
||||
#include "audio/segam1audio.h"
|
||||
#include "machine/m1comm.h"
|
||||
#include "cpu/v60/v60.h"
|
||||
|
||||
#define DECLARE_TGP_FUNCTION(name) void name()
|
||||
@ -16,6 +17,7 @@ public:
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_m1audio(*this, "m1audio"),
|
||||
m_m1comm(*this, "m1comm"),
|
||||
m_dsbz80(*this, DSBZ80_TAG),
|
||||
m_tgp(*this, "tgp"),
|
||||
m_screen(*this, "screen"),
|
||||
@ -29,6 +31,7 @@ public:
|
||||
|
||||
required_device<v60_device> m_maincpu; // V60
|
||||
required_device<segam1audio_device> m_m1audio; // Model 1 standard sound board
|
||||
optional_device<m1comm_device> m_m1comm; // Model 1 communication board
|
||||
optional_device<dsbz80_device> m_dsbz80; // Digital Sound Board
|
||||
optional_device<mb86233_cpu_device> m_tgp;
|
||||
required_device<screen_device> m_screen;
|
||||
|
565
src/mame/machine/m1comm.c
Normal file
565
src/mame/machine/m1comm.c
Normal file
@ -0,0 +1,565 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ariane Fugmann
|
||||
|
||||
/*
|
||||
Comm PCB
|
||||
--------
|
||||
|
||||
MODEL-1 COMMUNICATION BD 837-8842 171-6293B (C) SEGA 1992
|
||||
|--------------------------------------------------------------------------------|
|
||||
| |
|
||||
| MB89237A MB89374 |
|
||||
| JP4 LED1 |
|
||||
| 15112.17 Z80 |
|
||||
| JP2 JP3 75179 |
|
||||
| MB8464 315-5624 JP6 |
|
||||
| 315-5547 |
|
||||
| 315-5611 SW1 PC910 CN4|
|
||||
| |
|
||||
| PC910 CN5|
|
||||
| MB8421 MB8431 JP7 |
|
||||
| JP5 |
|
||||
| JP8 CN7|
|
||||
| CN1 CN2 |
|
||||
| |---------------------------------| |---------------------------------| CN6|
|
||||
| |---------------------------------| |---------------------------------| |
|
||||
|--------------------------------------------------------------------------------|
|
||||
Notes:
|
||||
15112.17 - AMD AM27C100 128k x8 EPROM (DIP32, labelled 'EPR-15112')
|
||||
Z80 - Zilog Z0840004PSC Z80 CPU, running at 4.000MHz (DIP40)
|
||||
MB8464 - Fujitsu MB8464 8k x8 SRAM (DIP28)
|
||||
MB8421 - Fujitsu MB8421-12LP 2k x8 SRAM (SDIP52)
|
||||
MB8431 - Fujitsu MB8431-90LP 2k x8 SRAM (SDIP52)
|
||||
MB89237A - Fujitsu MB89237A DMA-Controller (DIP20) [most likely i8237A clone]
|
||||
MB89374 - Fujitsu MB89374 Data Link Controller (SDIP42)
|
||||
75179 - Texas Instruments SN75179 Differential Driver and Receiver Pair (DIP8)
|
||||
315-5547 - AMI 18CV8PC-25 PAL (DIP20)
|
||||
315-5624 - MMI PAL16L8BCN PAL (DIP20)
|
||||
315-5611 - Lattice GAL16V8A PAL (DIP20)
|
||||
PC910 - Sharp PC910 opto-isolator (x2, DIP8)
|
||||
SW1 - Push Button Switch (enables board)
|
||||
CN1, CN2 - Connectors to join Comm board to Video board
|
||||
CN4 - 8 pin connector (DIFFERENTIAL port)
|
||||
CN5 - 6 pin connector (SERIAL port)
|
||||
CN6, CN7 - TOSLINK-Connectors for network optical cable link
|
||||
JP2 - Jumper, set to 2-3 (connected to EPROM A15)
|
||||
JP3 - Jumper, set to 1-2 (connected to EPROM A16)
|
||||
JP4 - Jumper, set to 1-2
|
||||
JP5 - Jumper, shorted (enables TOSLINK RX channel)
|
||||
JP6 - Jumper, not shorted (enables DIFFERERENTIAL RX channel)
|
||||
JP7 - Jumper, not shorted (enables SERIAL RX channel)
|
||||
JP8 - Jumper, set to 1-2 (selects CLOCK SOURCE)
|
||||
*/
|
||||
|
||||
#include "machine/m1comm.h"
|
||||
|
||||
#define Z80_TAG "m1commcpu"
|
||||
|
||||
//#define __M1COMM_VERBOSE__
|
||||
|
||||
/*************************************
|
||||
* M1COMM Memory Map
|
||||
*************************************/
|
||||
static ADDRESS_MAP_START( m1comm_mem, AS_PROGRAM, 8, m1comm_device )
|
||||
AM_RANGE(0x0000, 0x7fff) AM_ROM
|
||||
AM_RANGE(0x8000, 0x9fff) AM_RAM
|
||||
AM_RANGE(0xC000, 0xffff) AM_READWRITE(share_r, share_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
/*************************************
|
||||
* M1COMM I/O Map
|
||||
*************************************/
|
||||
static ADDRESS_MAP_START( m1comm_io, AS_IO, 8, m1comm_device )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
||||
AM_RANGE(0x00, 0x1F) AM_READWRITE(dlc_reg_r, dlc_reg_w)
|
||||
AM_RANGE(0x20, 0x2F) AM_READWRITE(dma_reg_r, dma_reg_w)
|
||||
AM_RANGE(0x40, 0x40) AM_READWRITE(syn_r, syn_w)
|
||||
AM_RANGE(0x60, 0x60) AM_READWRITE(zfg_r, zfg_w)
|
||||
AM_RANGE(0xFFFF, 0xFFFF) AM_RAM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
MACHINE_CONFIG_FRAGMENT( m1comm )
|
||||
MCFG_CPU_ADD(Z80_TAG, Z80, 4000000) /* 32 MHz / 8 */
|
||||
MCFG_CPU_PROGRAM_MAP(m1comm_mem)
|
||||
MCFG_CPU_IO_MAP(m1comm_io)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START( m1comm )
|
||||
ROM_REGION( 0x20000, Z80_TAG, ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "epr-15112.17", 0x0000, 0x20000, CRC(4950E771) )
|
||||
ROM_END
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
const device_type M1COMM = &device_creator<m1comm_device>;
|
||||
|
||||
//-------------------------------------------------
|
||||
// machine_config_additions - device-specific
|
||||
// machine configurations
|
||||
//-------------------------------------------------
|
||||
|
||||
machine_config_constructor m1comm_device::device_mconfig_additions() const
|
||||
{
|
||||
return MACHINE_CONFIG_NAME( m1comm );
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rom_region - device-specific ROM region
|
||||
//-------------------------------------------------
|
||||
|
||||
const rom_entry *m1comm_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( m1comm );
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// m1comm_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
m1comm_device::m1comm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, M1COMM, "MODEL-1 COMMUNICATION BD", tag, owner, clock, "m1comm", __FILE__),
|
||||
m_commcpu(*this, Z80_TAG),
|
||||
m_line_rx(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE ),
|
||||
m_line_tx(OPEN_FLAG_READ)
|
||||
{
|
||||
// prepare localhost "filename"
|
||||
strcat(m_localhost, "socket.");
|
||||
strcat(m_localhost, mconfig.options().comm_localhost());
|
||||
strcat(m_localhost, ":");
|
||||
strcat(m_localhost, mconfig.options().comm_localport());
|
||||
|
||||
// prepare remotehost "filename"
|
||||
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 m1comm_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void m1comm_device::device_reset()
|
||||
{
|
||||
m_syn = 0;
|
||||
m_zfg = 0;
|
||||
m_cn = 0;
|
||||
m_fg = 0;
|
||||
|
||||
m_commcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
||||
}
|
||||
|
||||
READ8_MEMBER(m1comm_device::dlc_reg_r)
|
||||
{
|
||||
// dirty hack to keep Z80 in RESET state
|
||||
if (!m_cn)
|
||||
{
|
||||
device_reset();
|
||||
return 0xFF;
|
||||
}
|
||||
// dirty hack to keep Z80 in RESET state
|
||||
|
||||
UINT8 result = m_dlc_reg[offset];
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-dlc_reg_r: read register %02x for value %02x\n", offset, result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m1comm_device::dlc_reg_w)
|
||||
{
|
||||
m_dlc_reg[offset] = data;
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-dlc_reg_w: write register %02x for value %02x\n", offset, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
READ8_MEMBER(m1comm_device::dma_reg_r)
|
||||
{
|
||||
UINT8 result = m_dma_reg[offset];
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-dma_reg_r: read register %02x for value %02x\n", offset, result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m1comm_device::dma_reg_w)
|
||||
{
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-dma_reg_w: %02x %02x\n", offset, data);
|
||||
#endif
|
||||
m_dma_reg[offset] = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m1comm_device::syn_r)
|
||||
{
|
||||
UINT8 result = m_syn | 0xFC;
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-syn_r: read register %02x for value %02x\n", offset, result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m1comm_device::syn_w)
|
||||
{
|
||||
m_syn = data & 0x03;
|
||||
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
switch (data & 0x02)
|
||||
{
|
||||
case 0x00:
|
||||
printf("m1comm-syn_w: VINT disabled\n");
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
printf("m1comm-syn_w: VINT enabled\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("m1comm-syn_w: %02x\n", data);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
READ8_MEMBER(m1comm_device::zfg_r)
|
||||
{
|
||||
UINT8 result = m_zfg | 0xFE;
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-zfg_r: read register %02x for value %02x\n", offset, result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m1comm_device::zfg_w)
|
||||
{
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-zfg_w: %02x\n", data);
|
||||
#endif
|
||||
m_zfg = data & 0x01;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m1comm_device::share_r)
|
||||
{
|
||||
return m_shared[offset];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m1comm_device::share_w)
|
||||
{
|
||||
m_shared[offset] = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(m1comm_device::cn_r)
|
||||
{
|
||||
return m_cn | 0xFE;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m1comm_device::cn_w)
|
||||
{
|
||||
m_cn = data & 0x01;
|
||||
|
||||
#ifndef __M1COMM_SIMULATION__
|
||||
if (!m_cn)
|
||||
device_reset();
|
||||
else
|
||||
m_commcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
||||
#else
|
||||
if (!m_cn)
|
||||
{
|
||||
// reset command
|
||||
printf("M1COMM: board disabled\n");
|
||||
m_linkenable = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
// init command
|
||||
printf("M1COMM: board enabled\n");
|
||||
m_linkenable = 0x01;
|
||||
m_linkid = 0x00;
|
||||
m_linkalive = 0x00;
|
||||
m_linkcount = 0x00;
|
||||
m_linktimer = 0x00E8; // 58 fps * 4s
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
READ8_MEMBER(m1comm_device::fg_r)
|
||||
{
|
||||
return m_fg | (~m_zfg << 7) | 0x7E;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(m1comm_device::fg_w)
|
||||
{
|
||||
if (!m_cn)
|
||||
return;
|
||||
|
||||
m_fg = data & 0x01;
|
||||
}
|
||||
|
||||
void m1comm_device::check_vint_irq()
|
||||
{
|
||||
#ifndef __M1COMM_SIMULATION__
|
||||
if (m_syn & 0x02)
|
||||
{
|
||||
m_commcpu->set_input_line_and_vector(0, HOLD_LINE, 0xEF);
|
||||
#ifdef __M1COMM_VERBOSE__
|
||||
printf("m1comm-INT5\n");
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
comm_tick();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __M1COMM_SIMULATION__
|
||||
void m1comm_device::comm_tick(){
|
||||
if (m_linkenable == 0x01)
|
||||
{
|
||||
int frameStart = 0x0010;
|
||||
int frameOffset = 0x0000;
|
||||
int frameSize = 0x01C4;
|
||||
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)
|
||||
{
|
||||
// check rx socket
|
||||
if (!m_line_rx.is_open())
|
||||
{
|
||||
printf("M1COMM: listen on %s\n", m_localhost);
|
||||
m_line_rx.open(m_localhost);
|
||||
}
|
||||
|
||||
// check tx socket
|
||||
if (!m_line_tx.is_open())
|
||||
{
|
||||
printf("M1COMM: 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("M1COMM: 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("M1COMM: 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("M1COMM: 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("M1COMM: 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[5] == 0x01)
|
||||
{
|
||||
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 05
|
||||
m_shared[5] = 0x00;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
98
src/mame/machine/m1comm.h
Normal file
98
src/mame/machine/m1comm.h
Normal file
@ -0,0 +1,98 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ariane Fugmann
|
||||
#pragma once
|
||||
|
||||
#ifndef __M1COMM_H__
|
||||
#define __M1COMM_H__
|
||||
|
||||
#define __M1COMM_SIMULATION__
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
|
||||
#define MCFG_M1COMM_ADD(_tag ) \
|
||||
MCFG_DEVICE_ADD(_tag, M1COMM, 0)
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
class m1comm_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
m1comm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
|
||||
required_device<z80_device> m_commcpu;
|
||||
|
||||
// internal API - stuff that happens on the comm board
|
||||
// MB89374 registers
|
||||
DECLARE_READ8_MEMBER(dlc_reg_r);
|
||||
DECLARE_WRITE8_MEMBER(dlc_reg_w);
|
||||
// MB89237A registers
|
||||
DECLARE_READ8_MEMBER(dma_reg_r);
|
||||
DECLARE_WRITE8_MEMBER(dma_reg_w);
|
||||
// single bit registers (74LS74)
|
||||
DECLARE_READ8_MEMBER(syn_r);
|
||||
DECLARE_WRITE8_MEMBER(syn_w);
|
||||
DECLARE_READ8_MEMBER(zfg_r);
|
||||
DECLARE_WRITE8_MEMBER(zfg_w);
|
||||
// shared memory 4k
|
||||
DECLARE_READ8_MEMBER(share_r);
|
||||
DECLARE_WRITE8_MEMBER(share_w);
|
||||
|
||||
// public API - stuff that gets called from the model1
|
||||
// shared memory 4k
|
||||
// reads/writes at I/O 0xB00xxx
|
||||
// - share_r
|
||||
// - share_w
|
||||
// single bit registers (74LS74)
|
||||
// reads/writes at I/O 0xB01000
|
||||
DECLARE_READ8_MEMBER(cn_r);
|
||||
DECLARE_WRITE8_MEMBER(cn_w);
|
||||
// reads/writes at I/O 0xB01002
|
||||
DECLARE_READ8_MEMBER(fg_r);
|
||||
DECLARE_WRITE8_MEMBER(fg_w);
|
||||
|
||||
// IRQ logic - 5 = VINT, 7 = DLC
|
||||
void check_vint_irq();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual const rom_entry *device_rom_region() const;
|
||||
|
||||
private:
|
||||
UINT8 m_shared[0x1000]; // 2x 2k = 4k; model1 accesses this with 16bit data and 11bit address (A0 to A10)
|
||||
UINT8 m_dlc_reg[0x20]; // MB89374 registers
|
||||
UINT8 m_dma_reg[0x20]; // MB89237A registers
|
||||
UINT8 m_syn; // bit0 is stored; purpose unknown, bit1 is used to enable/disable VINT/IRQ5
|
||||
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[0x1000];
|
||||
|
||||
#ifdef __M1COMM_SIMULATION__
|
||||
UINT8 m_linkenable;
|
||||
UINT16 m_linktimer;
|
||||
UINT8 m_linkalive;
|
||||
UINT8 m_linkid;
|
||||
UINT8 m_linkcount;
|
||||
|
||||
void comm_tick();
|
||||
#endif
|
||||
};
|
||||
|
||||
// device type definition
|
||||
extern const device_type M1COMM;
|
||||
|
||||
#endif /* __M1COMM_H__ */
|
Loading…
Reference in New Issue
Block a user