M1COMM: Add preliminary MB89374 emulation (#3378)

* M1COMM: Add preliminary MB89374 emulation (nw)

* M1COMM: moved knowns roms to device. (nw)

* MB89374: arrays and savestates (nw)
This commit is contained in:
Ariane Fugmann 2018-03-24 13:40:45 +01:00 committed by R. Belmont
parent 8cc881837a
commit 2ad88fd875
8 changed files with 949 additions and 111 deletions

View File

@ -1658,6 +1658,18 @@ if (MACHINES["MB89371"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/mb89374.h,MACHINES["MB89374"] = true
---------------------------------------------------
if (MACHINES["MB89374"]~=null) then
files {
MAME_DIR .. "src/devices/machine/mb89374.cpp",
MAME_DIR .. "src/devices/machine/mb89374.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/mc146818.h,MACHINES["MC146818"] = true

View File

@ -480,6 +480,7 @@ MACHINES["MB87078"] = true
--MACHINES["MB8795"] = true
MACHINES["MB89352"] = true
MACHINES["MB89371"] = true
MACHINES["MB89374"] = true
--MACHINES["MC14411"] = true
MACHINES["MC146818"] = true
MACHINES["MC2661"] = true

View File

@ -0,0 +1,617 @@
// license:BSD-3-Clause
// copyright-holders:Ariane Fugmann
/**
MB89374
Fujitsu
Data Link Controller
**/
#include "emu.h"
#include "mb89374.h"
#include "emuopts.h"
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
// device type definition
DEFINE_DEVICE_TYPE(MB89374, mb89374_device, "mb89374", "MB89374 Data Link Controller")
enum
{
REGISTER_SMR0 = 0x00,
REGISTER_SMR1,
REGISTER_SMR2,
REGISTER_CHRR0,
REGISTER_CHRR1,
REGISTER_MSR = 0x06,
REGISTER_MCR,
REGISTER_RXSR0,
REGISTER_RXSR1,
REGISTER_RXCR,
REGISTER_RXIER,
REGISTER_TXSR,
REGISTER_TXCR,
REGISTER_TXIER,
REGISTER_SDR,
REGISTER_TXBCR0,
REGISTER_TXBCR1,
REGISTER_TXFR0,
REGISTER_TXFR1,
REGISTER_SMR3,
REGISTER_PORTR,
REGISTER_REQR,
REGISTER_MASKR,
REGISTER_B1PSR,
REGISTER_B1PCR,
REGISTER_BG1DR,
REGISTER_B2SR = 0x1c,
REGISTER_B2CR,
REGISTER_BG2DR
};
#define SMR0_MASK 0xf0
#define SMR1_MASK 0xe3
#define MSR_MASK 0x80
#define MCR_MASK 0x14
#define RXSR1_MASK 0x08
#define RXCR_MASK 0x7c
#define RXCR_HUNT BIT(m_rxcr, 1)
#define RXCR_RXE BIT(m_rxcr, 7)
#define RXIER_RXDI BIT(m_rxier, 7)
#define TXSR_MASK 0x60
#define TXSR_TXRDY BIT(m_txsr, 0)
#define TXSR_TXEND BIT(m_txsr, 4)
#define TXCR_TXRST BIT(m_txcr, 3)
#define TXCR_TXE BIT(m_txcr, 7)
#define TXIER_MASK 0x60
#define TXIER_TXDI BIT(m_txier, 7)
#define TXFR1_MASK 0x70
#define SMR3_MASK 0x80
#define REQR_MASK 0x38
#define MASKR_MASK 0x38
#define MASKR_MRXDRQ BIT(m_maskr, 6)
#define MASKR_MTXDRQ BIT(m_maskr, 7)
#define B1PSR_MASK 0xfc
#define B2SR_MASK 0xfe
//-------------------------------------------------
// mb89374_device - constructor
//-------------------------------------------------
mb89374_device::mb89374_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
: device_t(mconfig, MB89374, tag, owner, clock),
device_execute_interface(mconfig, *this),
m_icount(0),
m_out_irq_cb(*this),
m_out_po_cb{ { *this }, { *this }, { *this }, { *this } }
{
// 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 mb89374_device::device_start()
{
// set our instruction counter
m_icountptr = &m_icount;
// resolve callbacks
m_out_irq_cb.resolve_safe();
for(auto &cb : m_out_po_cb)
cb.resolve_safe();
// state saving
save_item(NAME(m_irq));
save_item(NAME(m_po));
save_item(NAME(m_pi));
save_item(NAME(m_ci));
save_item(NAME(m_smr0));
save_item(NAME(m_smr1));
save_item(NAME(m_smr2));
save_item(NAME(m_chrr0));
save_item(NAME(m_chrr1));
save_item(NAME(m_msr));
save_item(NAME(m_mcr));
save_item(NAME(m_rxsr0));
save_item(NAME(m_rxsr1));
save_item(NAME(m_rxcr));
save_item(NAME(m_rxier));
save_item(NAME(m_txsr));
save_item(NAME(m_txcr));
save_item(NAME(m_txier));
save_item(NAME(m_sdr));
save_item(NAME(m_txbcr0));
save_item(NAME(m_txbcr1));
save_item(NAME(m_txfr0));
save_item(NAME(m_txfr1));
save_item(NAME(m_smr3));
save_item(NAME(m_portr));
save_item(NAME(m_reqr));
save_item(NAME(m_maskr));
save_item(NAME(m_b1psr));
save_item(NAME(m_b1pcr));
save_item(NAME(m_bg1dr));
save_item(NAME(m_b2sr));
save_item(NAME(m_b2cr));
save_item(NAME(m_bg2dr));
save_item(NAME(m_intr_delay));
save_item(NAME(m_sock_delay));
save_item(NAME(m_rx_buffer));
save_item(NAME(m_rx_offset));
save_item(NAME(m_rx_length));
save_item(NAME(m_tx_buffer));
save_item(NAME(m_tx_offset));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mb89374_device::device_reset()
{
m_smr0 = SMR0_MASK;
m_smr1 = SMR1_MASK;
m_smr2 = 0x00;
m_chrr0 = 0x00;
m_chrr1 = 0x00;
m_msr = MSR_MASK;
m_mcr = MCR_MASK;
m_rxsr0 = 0x00;
m_rxsr1 = RXSR1_MASK;
m_rxcr = RXCR_MASK;
m_rxier = 0x00;
m_txsr = TXSR_MASK;
m_txcr = 0x00;
m_txier = TXIER_MASK;
m_sdr = 0x00;
m_txbcr0 = 0x00;
m_txbcr1 = 0x00;
m_txfr0 = 0x00;
m_txfr1 = TXFR1_MASK;
m_smr3 = SMR3_MASK;
m_portr = 0x00;
m_reqr = REQR_MASK;
m_maskr = MASKR_MASK;
m_b1psr = B1PSR_MASK;
m_b1pcr = 0x00;
m_bg1dr = 0x00;
m_b2sr = B2SR_MASK;
m_b2cr = 0x00;
m_bg2dr = 0x00;
set_irq(0);
set_po0(0);
set_po1(0);
set_po2(0);
set_po3(0);
m_intr_delay = 0;
m_sock_delay = 0x20;
m_rx_length = 0x0000;
m_rx_offset = 0x0000;
m_tx_offset = 0x0000;
}
//-------------------------------------------------
// execute_run -
//-------------------------------------------------
void mb89374_device::execute_run()
{
while (m_icount > 0)
{
// TODO waste some cycles before triggering ints
if (m_intr_delay > 0)
{
m_intr_delay--;
if (m_intr_delay == 0)
{
}
}
if (m_sock_delay > 0)
{
m_sock_delay--;
if (m_sock_delay == 0)
{
m_sock_delay = 0x20;
checkSockets();
}
}
m_icount--;
}
}
//-------------------------------------------------
// read - handler for register reading
//-------------------------------------------------
READ8_MEMBER(mb89374_device::read)
{
uint8_t data = 0xff;
switch (offset & 0x1f)
{
case REGISTER_RXSR0:
data = m_rxsr0;
break;
case REGISTER_RXSR1:
data = m_rxsr1;
break;
case REGISTER_TXSR:
data = m_txsr;
break;
case REGISTER_SDR:
m_sdr = rxRead();
data = m_sdr;
break;
case REGISTER_PORTR:
data = m_portr;
break;
default:
logerror("MB89374 unimplemented register read @%02X\n", offset);
}
return data;
}
//-------------------------------------------------
// write - handler for register writing
//-------------------------------------------------
WRITE8_MEMBER(mb89374_device::write)
{
switch (offset & 0x1f)
{
case REGISTER_SMR2:
m_smr2 = data;
break;
case REGISTER_MCR:
m_mcr = data | MCR_MASK;
break;
case REGISTER_RXCR:
m_rxcr = data | RXCR_MASK;
if (RXCR_HUNT)
rxReset();
break;
case REGISTER_RXIER:
m_rxier = data;
case REGISTER_TXSR:
m_txsr = data | TXSR_MASK;
txReset();
break;
case REGISTER_TXCR:
m_txcr = data;
if (TXCR_TXRST)
txReset();
break;
case REGISTER_TXIER:
m_txier = data | TXIER_MASK;
break;
case REGISTER_SMR3:
m_smr3 = data | SMR3_MASK;
break;
case REGISTER_PORTR:
m_portr = data;
break;
case REGISTER_MASKR:
m_maskr = data | MASKR_MASK;
set_po2((!MASKR_MTXDRQ && TXCR_TXE && TXIER_TXDI) ? 1 : 0);
break;
default:
logerror("MB89374 unimplemented register write @%02X = %02X\n", offset, data);
}
}
//-------------------------------------------------
// pi0_w - handler for RxCI#/PI0
//-------------------------------------------------
WRITE_LINE_MEMBER(mb89374_device::pi0_w)
{
m_pi[0] = state;
}
//-------------------------------------------------
// pi1_w - handler for TxCI#/PI1
//-------------------------------------------------
WRITE_LINE_MEMBER(mb89374_device::pi1_w)
{
m_pi[1] = state;
}
//-------------------------------------------------
// pi2_w - handler for TxDACK#/PI2
//-------------------------------------------------
WRITE_LINE_MEMBER(mb89374_device::pi2_w)
{
m_pi[2] = state;
}
//-------------------------------------------------
// pi3_w - handler for RxDACK#/PI3
//-------------------------------------------------
WRITE_LINE_MEMBER(mb89374_device::pi3_w)
{
m_pi[3] = state;
}
//-------------------------------------------------
// ci_w - handler for TxLAST#/CI#
//-------------------------------------------------
WRITE_LINE_MEMBER(mb89374_device::ci_w)
{
m_ci = state;
if (m_ci == 1 && m_pi[2] == 0)
{
txComplete();
}
}
//-------------------------------------------------
// read - handler for dma reading (rx buffer)
//-------------------------------------------------
READ8_MEMBER(mb89374_device::dma_r)
{
uint8_t data = rxRead();
if (m_rx_offset == m_rx_length)
set_po3(0); // transfer finished; release dma
return data;
}
//-------------------------------------------------
// write - handler for dma writing (tx buffer)
//-------------------------------------------------
WRITE8_MEMBER(mb89374_device::dma_w)
{
txWrite(data);
}
//**************************************************************************
// buffer logic
//**************************************************************************
void mb89374_device::rxReset()
{
m_rx_length = 0;
m_rx_offset = 0;
m_rxsr0 = 0x06; // RXIDL | DIDL
}
uint8_t mb89374_device::rxRead()
{
uint8_t data = m_rx_buffer[m_rx_offset];
m_rx_offset++;
if (m_rx_offset == m_rx_length)
m_rxsr0 |= 0x40; // EOF
if (m_rx_offset >= m_rx_length)
rxReset();
return data;
}
void mb89374_device::txReset()
{
m_tx_offset = 0;
m_txsr |= 0x05;
}
void mb89374_device::txWrite(uint8_t data)
{
m_tx_buffer[m_tx_offset] = data;
m_tx_offset++;
m_txsr = 0x6b;
// prevent overflow
if (m_tx_offset >= 0x0f00)
m_tx_offset = 0x0eff;
}
void mb89374_device::txComplete()
{
if (m_tx_offset > 0)
{
if (m_line_rx && m_line_tx)
{
m_socket_buffer[0x00] = m_tx_offset & 0xff;
m_socket_buffer[0x01] = (m_tx_offset >> 8) & 0xff;
for (int i = 0x00 ; i < m_tx_offset ; i++)
{
m_socket_buffer[i + 2] = m_tx_buffer[i];
}
std::uint32_t dataSize = m_tx_offset + 2;
std::uint32_t written;
m_line_tx->write(&m_socket_buffer, 0, dataSize, written);
}
}
m_txsr = 0x6f;
txReset();
}
void mb89374_device::checkSockets()
{
// check rx socket
if (!m_line_rx)
{
osd_printf_verbose("MB89374 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("MB89374 connect to %s\n", m_remotehost);
uint64_t filesize; // unused
osd_file::open(m_remotehost, 0, m_line_tx, filesize);
}
if (m_line_rx && m_line_tx)
{
if (RXCR_RXE)
{
if (m_rx_length == 0)
{
std::uint32_t recv = 0;
m_line_rx->read(m_socket_buffer, 0, 2, recv);
if (recv > 0)
{
if (recv == 2)
m_rx_length = m_socket_buffer[0x01] << 8 | m_socket_buffer[0x00];
else
{
m_rx_length = m_socket_buffer[0x00];
m_line_rx->read(m_socket_buffer, 0, 1, recv);
while (recv == 0) {}
m_rx_length |= m_socket_buffer[0x00] << 8;
}
int offset = 0;
int togo = m_rx_length;
while (togo > 0)
{
m_line_rx->read(m_socket_buffer, 0, togo, recv);
for (int i = 0x00 ; i < recv ; i++)
{
m_rx_buffer[offset] = m_socket_buffer[i];
offset++;
}
togo -= recv;
}
m_rx_offset = 0;
m_rxsr0 = 0x01; // RXRDY
if (m_rx_offset + 1 == m_rx_length)
m_rxsr0 |= 0x40; // EOF
m_rxsr1 = 0xc8;
set_po3(!MASKR_MRXDRQ && RXIER_RXDI ? 1 : 0);
}
}
}
}
}
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
inline void mb89374_device::set_irq(int state)
{
if (m_irq != state)
{
m_out_irq_cb(state);
m_irq = state;
}
}
inline void mb89374_device::set_po0(int state)
{
if (m_po[0] != state)
{
m_out_po_cb[0](state);
m_po[0] = state;
}
}
inline void mb89374_device::set_po1(int state)
{
if (m_po[1] != state)
{
m_out_po_cb[1](state);
m_po[1] = state;
}
}
inline void mb89374_device::set_po2(int state)
{
if (m_po[2] != state)
{
m_out_po_cb[2](state);
m_po[2] = state;
}
}
inline void mb89374_device::set_po3(int state)
{
if (m_po[3] != state)
{
m_out_po_cb[3](state);
m_po[3] = state;
}
}

View File

@ -0,0 +1,170 @@
// license:BSD-3-Clause
// copyright-holders:Ariane Fugmann
/*
MB89374
Fujitsu
Data Link Controller
_____ _____
CLK 1 |* \_/ | 42 Vcc
FORMAT# 2 | | 41 RxDACK#/PI3
RESET# 3 | | 40 TxDACK#/PI2
RD#/DS# 4 | | 39 RxDRQ/PO3
WR#/R/W# 5 | | 38 TxDRQ/PO2
CS# 6 | | 37 IRQT
A4 7 | | 36 Vss
A3 8 | | 35 IRQ
A2 9 | | 34 FD#/DTR#
A1 10 | MB89374 | 33 SCLK/DSR#
A0 11 | | 32 TxLAST#/CI#
Vss 12 | | 31 TxCI#/PI1
D7 13 | | 30 TxCO#/PO1
D6 14 | | 29 TxD
D5 15 | | 28 RxD
D4 16 | | 27 RxCI#/PI0
D3 17 | | 26 RxCO#/PO0
D2 18 | | 25 DCD#
D1 19 | | 24 CTS#
D0 20 | | 23 TCLK
Vss 21 |_____________| 22 LOC#/RTS#
*/
#ifndef MAME_MACHINE_MB89374_H
#define MAME_MACHINE_MB89374_H
#pragma once
#include "osdcore.h"
//**************************************************************************
// DEVICE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_MB89374_IRQ_CB(_devcb) \
devcb = &downcast<mb89374_device &>(*device).set_out_irq_callback(DEVCB_##_devcb);
#define MCFG_MB89374_PO0_CB(_devcb) \
devcb = &downcast<mb89374_device &>(*device).set_out_po_callback<0>(DEVCB_##_devcb);
#define MCFG_MB89374_PO1_CB(_devcb) \
devcb = &downcast<mb89374_device &>(*device).set_out_po_callback<1>(DEVCB_##_devcb);
#define MCFG_MB89374_PO2_CB(_devcb) \
devcb = &downcast<mb89374_device &>(*device).set_out_po_callback<2>(DEVCB_##_devcb);
#define MCFG_MB89374_PO3_CB(_devcb) \
devcb = &downcast<mb89374_device &>(*device).set_out_po_callback<3>(DEVCB_##_devcb);
class mb89374_device : public device_t,
public device_execute_interface
{
public:
// construction/destruction
mb89374_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <class Object> devcb_base &set_out_irq_callback(Object &&cb) { return m_out_irq_cb.set_callback(std::forward<Object>(cb)); }
template <unsigned N, class Object> devcb_base &set_out_po_callback(Object &&cb) { return m_out_po_cb[N].set_callback(std::forward<Object>(cb)); }
// read/write handlers
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
DECLARE_WRITE_LINE_MEMBER( pi0_w );
DECLARE_WRITE_LINE_MEMBER( pi1_w );
DECLARE_WRITE_LINE_MEMBER( pi2_w );
DECLARE_WRITE_LINE_MEMBER( pi3_w );
DECLARE_WRITE_LINE_MEMBER( ci_w );
DECLARE_READ8_MEMBER( dma_r );
DECLARE_WRITE8_MEMBER( dma_w );
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void execute_run() override;
int m_icount;
private:
// internal state
inline void set_irq(int state);
inline void set_po0(int state);
inline void set_po1(int state);
inline void set_po2(int state);
inline void set_po3(int state);
devcb_write_line m_out_irq_cb;
devcb_write_line m_out_po_cb[4];
// pins
int m_irq;
int m_po[4];
int m_pi[4];
int m_ci;
// registers
uint8_t m_smr0;
uint8_t m_smr1;
uint8_t m_smr2;
uint8_t m_chrr0;
uint8_t m_chrr1;
uint8_t m_msr;
uint8_t m_mcr;
uint8_t m_rxsr0;
uint8_t m_rxsr1;
uint8_t m_rxcr;
uint8_t m_rxier;
uint8_t m_txsr;
uint8_t m_txcr;
uint8_t m_txier;
uint8_t m_sdr;
uint8_t m_txbcr0;
uint8_t m_txbcr1;
uint8_t m_txfr0;
uint8_t m_txfr1;
uint8_t m_smr3;
uint8_t m_portr;
uint8_t m_reqr;
uint8_t m_maskr;
uint8_t m_b1psr;
uint8_t m_b1pcr;
uint8_t m_bg1dr;
uint8_t m_b2sr;
uint8_t m_b2cr;
uint8_t m_bg2dr;
uint16_t m_intr_delay;
uint16_t m_sock_delay;
// 512 byte fifos (not in hardware)
uint8_t m_rx_buffer[0x200];
uint16_t m_rx_offset;
uint16_t m_rx_length;
uint8_t m_tx_buffer[0x200];
uint16_t m_tx_offset;
void rxReset();
uint8_t rxRead();
void txReset();
void txWrite(uint8_t data);
void txComplete();
osd_file::ptr m_line_rx;
osd_file::ptr m_line_tx;
char m_localhost[256];
char m_remotehost[256];
uint8_t m_socket_buffer[0x200];
void checkSockets();
};
// device type definition
DECLARE_DEVICE_TYPE(MB89374, mb89374_device)
#endif // MAME_MACHINE_MB89374_H

View File

@ -885,10 +885,6 @@ void model1_state::model1_mem(address_map &map)
map(0x900000, 0x903fff).ram().w(this, FUNC(model1_state::p_w)).share("palette");
map(0x910000, 0x91bfff).ram().share("color_xlat");
map(0xb00000, 0xb00fff).rw(m_m1comm, FUNC(m1comm_device::share_r), FUNC(m1comm_device::share_w));
map(0xb01000, 0xb01000).rw(m_m1comm, FUNC(m1comm_device::cn_r), FUNC(m1comm_device::cn_w));
map(0xb01002, 0xb01002).rw(m_m1comm, FUNC(m1comm_device::fg_r), FUNC(m1comm_device::fg_w));
map(0xc00000, 0xc0003f).rw(this, FUNC(model1_state::io_r), FUNC(model1_state::io_w));
map(0xc00040, 0xc00043).rw(this, FUNC(model1_state::network_ctl_r), FUNC(model1_state::network_ctl_w));
@ -916,6 +912,15 @@ void model1_state::model1_io(address_map &map)
map(0xd80000, 0xd80003).r(this, FUNC(model1_state::model1_tgp_copro_r));
}
void model1_state::model1_comm_mem(address_map &map)
{
model1_mem(map);
map(0xb00000, 0xb00fff).rw(m_m1comm, FUNC(m1comm_device::share_r), FUNC(m1comm_device::share_w));
map(0xb01000, 0xb01000).rw(m_m1comm, FUNC(m1comm_device::cn_r), FUNC(m1comm_device::cn_w));
map(0xb01002, 0xb01002).rw(m_m1comm, FUNC(m1comm_device::fg_r), FUNC(m1comm_device::fg_w));
}
void model1_state::model1_vr_mem(address_map &map)
{
map(0x000000, 0x0fffff).rom();
@ -1286,9 +1291,6 @@ ROM_START( vformula )
ROM_LOAD32_BYTE( "mpr-14900.41", 0x000002, 0x80000, CRC(aa7c017d) SHA1(0fa2b59a8bb5f5907b2b2567e69d11c73b398dc1) )
ROM_LOAD32_BYTE( "mpr-14901.42", 0x000003, 0x80000, CRC(175b7a9a) SHA1(c86602e771cd49bab425b4ba7926d2f44858bd39) )
ROM_REGION( 0x20000, "commboard", 0 ) /* Comms Board */
ROM_LOAD( "epr-15624.17", 0x00000, 0x20000, CRC(9b3ba315) SHA1(0cd0983cc8b2f2d6b41617d0d0a24cc6c188e62a) )
ROM_REGION( 0x2000, "tgp", 0 ) /* TGP program rom */
// The real internal TGP rom
ROM_LOAD("315-5573.bin", 0, 0x2000, CRC(ec913af2) SHA1(a18bf6c9d7b35f8b9e513a7d279f13a30b32a961) )
@ -1561,9 +1563,6 @@ ROM_START( wingwar360 )
ROM_REGION( 0x10000, "ioboard", 0 )
ROM_LOAD("epr-16891.6", 0x00000, 0x10000, CRC(a33f84d1) SHA1(3079397c7241c1a6f494fa310faff0989dfa04a0) )
ROM_REGION( 0x20000, "commboard", 0 )
ROM_LOAD("epr-15112.17", 0x00000, 0x20000, CRC(4950e771) SHA1(99014124e0324dd114cb22f55159d18b597a155a) )
// Dumper's note: Video & Drive is the control board in the attendants' tower, same hardware as G-Loc R360 with the two program roms being the only difference.
ROM_REGION( 0x400000, "controlboard", 0 )
ROM_LOAD("ic22_18851.bin", 0x00000, 0x20000, CRC(85f75bd7) SHA1(43cc8f8c81631d71b661e55e15f3fe8803a8a7e9) )
@ -1652,8 +1651,16 @@ MACHINE_CONFIG_START(model1_state::model1)
MCFG_CLOCK_ADD("m1uart_clock", 500000) // 16 times 31.25MHz (standard Sega/MIDI sound data rate)
MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("m1uart", i8251_device, write_txc))
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("m1uart", i8251_device, write_rxc))
MACHINE_CONFIG_END
MCFG_M1COMM_ADD("m1comm")
MACHINE_CONFIG_START(model1_state::wingwar)
model1(config);
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(model1_comm_mem)
MCFG_M1COMM_ADD(M1COMM_TAG)
// use EPR-15112
MACHINE_CONFIG_END
MACHINE_CONFIG_START(model1_state::swa)
@ -1725,8 +1732,20 @@ MACHINE_CONFIG_START(model1_state::model1_vr)
MCFG_CLOCK_ADD("m1uart_clock", 500000) // 16 times 31.25MHz (standard Sega/MIDI sound data rate)
MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("m1uart", i8251_device, write_txc))
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("m1uart", i8251_device, write_rxc))
MACHINE_CONFIG_END
MCFG_M1COMM_ADD("m1comm")
MACHINE_CONFIG_START(model1_state::vr)
model1_vr(config);
MCFG_M1COMM_ADD(M1COMM_TAG)
// use EPR-15112
MACHINE_CONFIG_END
MACHINE_CONFIG_START(model1_state::vformula)
model1_vr(config);
MCFG_M1COMM_ADD(M1COMM_TAG)
// use EPR-15624
MACHINE_CONFIG_END
DRIVER_INIT_MEMBER(model1_state,wingwar360)
@ -1793,12 +1812,12 @@ WRITE16_MEMBER(model1_state::r360_w)
}
}
GAME( 1993, vf, 0, model1, vf, model1_state, 0, ROT0, "Sega", "Virtua Fighter", MACHINE_IMPERFECT_GRAPHICS )
GAMEL(1992, vr, 0, model1_vr, vr, model1_state, 0, ROT0, "Sega", "Virtua Racing", MACHINE_IMPERFECT_GRAPHICS, layout_vr )
GAME( 1993, vformula, vr, model1_vr, vr, model1_state, 0, ROT0, "Sega", "Virtua Formula", MACHINE_IMPERFECT_GRAPHICS )
GAME( 1993, swa, 0, swa, swa, model1_state, 0, ROT0, "Sega", "Star Wars Arcade", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
GAME( 1994, wingwar, 0, model1, wingwar, model1_state, 0, ROT0, "Sega", "Wing War (World)", MACHINE_NOT_WORKING )
GAME( 1994, wingwaru, wingwar, model1, wingwar, model1_state, 0, ROT0, "Sega", "Wing War (US)", MACHINE_NOT_WORKING )
GAME( 1994, wingwarj, wingwar, model1, wingwar, model1_state, 0, ROT0, "Sega", "Wing War (Japan)", MACHINE_NOT_WORKING )
GAME( 1994, wingwar360, wingwar, model1, wingwar, model1_state, wingwar360, ROT0, "Sega", "Wing War R360 (US)", MACHINE_NOT_WORKING )
GAME( 1993, netmerc, 0, netmerc, vf, model1_state, 0, ROT0, "Sega", "Sega NetMerc", MACHINE_NOT_WORKING )
GAME( 1993, vf, 0, model1, vf, model1_state, 0, ROT0, "Sega", "Virtua Fighter", MACHINE_IMPERFECT_GRAPHICS )
GAMEL(1992, vr, 0, vr, vr, model1_state, 0, ROT0, "Sega", "Virtua Racing", MACHINE_IMPERFECT_GRAPHICS, layout_vr )
GAME( 1993, vformula, vr, vformula, vr, model1_state, 0, ROT0, "Sega", "Virtua Formula", MACHINE_IMPERFECT_GRAPHICS )
GAME( 1993, swa, 0, swa, swa, model1_state, 0, ROT0, "Sega", "Star Wars Arcade", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
GAME( 1994, wingwar, 0, wingwar, wingwar, model1_state, 0, ROT0, "Sega", "Wing War (World)", MACHINE_NOT_WORKING )
GAME( 1994, wingwaru, wingwar, wingwar, wingwar, model1_state, 0, ROT0, "Sega", "Wing War (US)", MACHINE_NOT_WORKING )
GAME( 1994, wingwarj, wingwar, wingwar, wingwar, model1_state, 0, ROT0, "Sega", "Wing War (Japan)", MACHINE_NOT_WORKING )
GAME( 1994, wingwar360, wingwar, wingwar, wingwar, model1_state, wingwar360, ROT0, "Sega", "Wing War R360 (US)", MACHINE_NOT_WORKING )
GAME( 1993, netmerc, 0, netmerc, vf, model1_state, 0, ROT0, "Sega", "Sega NetMerc", MACHINE_NOT_WORKING )

View File

@ -186,11 +186,15 @@ public:
};
void model1(machine_config &config);
void wingwar(machine_config &config);
void swa(machine_config &config);
void netmerc(machine_config &config);
void model1_vr(machine_config &config);
void vr(machine_config &config);
void vformula(machine_config &config);
void model1_io(address_map &map);
void model1_mem(address_map &map);
void model1_comm_mem(address_map &map);
void model1_vr_io(address_map &map);
void model1_vr_mem(address_map &map);
void model1_vr_tgp_map(address_map &map);

View File

@ -52,13 +52,12 @@ Notes:
*/
#include "emu.h"
#include "emuopts.h"
#include "machine/m1comm.h"
#include "emuopts.h"
#define Z80_TAG "m1commcpu"
#define VERBOSE 0
#include "logmacro.h"
#define Z80_TAG "commcpu"
#define DMA_TAG "commdma"
#define DLC_TAG "commdlc"
/*************************************
* M1COMM Memory Map
@ -76,23 +75,30 @@ void m1comm_device::m1comm_mem(address_map &map)
void m1comm_device::m1comm_io(address_map &map)
{
map.global_mask(0x7f);
map(0x00, 0x1f).rw(this, FUNC(m1comm_device::dlc_reg_r), FUNC(m1comm_device::dlc_reg_w));
map(0x20, 0x2f).rw(this, FUNC(m1comm_device::dma_reg_r), FUNC(m1comm_device::dma_reg_w));
map(0x00, 0x1f).rw(m_dlc, FUNC(mb89374_device::read), FUNC(mb89374_device::write));
map(0x20, 0x2f).rw(m_dma, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
map(0x40, 0x5f).mask(0x01).rw(this, FUNC(m1comm_device::syn_r), FUNC(m1comm_device::syn_w));
map(0x60, 0x7f).mask(0x01).rw(this, FUNC(m1comm_device::zfg_r), FUNC(m1comm_device::zfg_w));
}
ROM_START( m1comm )
ROM_REGION( 0x20000, Z80_TAG, ROMREGION_ERASEFF )
ROM_LOAD( "epr-15112.17", 0x0000, 0x20000, CRC(4950e771) SHA1(99014124e0324dd114cb22f55159d18b597a155a) )
ROM_DEFAULT_BIOS("epr-15112")
// found on Virtua Racing and WingWar
ROM_SYSTEM_BIOS( 0, "epr-15112", "EPR-15112" )
ROMX_LOAD( "epr-15112.17", 0x0000, 0x20000, CRC(4950e771) SHA1(99014124e0324dd114cb22f55159d18b597a155a), ROM_BIOS(1) )
// found on Virtua Formula
ROM_SYSTEM_BIOS( 1, "epr-15624", "EPR-15624" )
ROMX_LOAD( "epr-15624.17", 0x0000, 0x20000, CRC(9b3ba315) SHA1(0cd0983cc8b2f2d6b41617d0d0a24cc6c188e62a), ROM_BIOS(2) )
ROM_END
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
DEFINE_DEVICE_TYPE(M1COMM, m1comm_device, "m1comm", "Model 1 Communication Board")
DEFINE_DEVICE_TYPE(M1COMM, m1comm_device, "m1comm", "Model-1 Communication Board")
//-------------------------------------------------
// device_add_mconfig - add device configuration
@ -102,16 +108,30 @@ MACHINE_CONFIG_START(m1comm_device::device_add_mconfig)
MCFG_CPU_ADD(Z80_TAG, Z80, 8000000) /* 32 MHz / 4 */
MCFG_CPU_PROGRAM_MAP(m1comm_mem)
MCFG_CPU_IO_MAP(m1comm_io)
MCFG_DEVICE_ADD(DMA_TAG, AM9517A, 8000000) /* 32 MHz / 4 */
MCFG_I8237_OUT_HREQ_CB(WRITELINE(m1comm_device, dma_hreq_w))
MCFG_I8237_IN_MEMR_CB(READ8(m1comm_device, dma_mem_r))
MCFG_I8237_OUT_MEMW_CB(WRITE8(m1comm_device, dma_mem_w))
MCFG_I8237_OUT_DACK_2_CB(DEVWRITELINE(DLC_TAG, mb89374_device, pi3_w))
MCFG_I8237_OUT_DACK_3_CB(DEVWRITELINE(DLC_TAG, mb89374_device, pi2_w))
MCFG_I8237_OUT_EOP_CB(DEVWRITELINE(DLC_TAG, mb89374_device, ci_w))
MCFG_I8237_IN_IOR_2_CB(DEVREAD8(DLC_TAG, mb89374_device, dma_r))
MCFG_I8237_OUT_IOW_3_CB(DEVWRITE8(DLC_TAG, mb89374_device, dma_w))
MCFG_DEVICE_ADD(DLC_TAG, MB89374, 8000000) /* 32 MHz / 4 */
MCFG_MB89374_PO2_CB(DEVWRITELINE(DMA_TAG, am9517a_device, dreq3_w))
MCFG_MB89374_PO3_CB(DEVWRITELINE(DMA_TAG, am9517a_device, dreq2_w))
MCFG_MB89374_IRQ_CB(WRITELINE(m1comm_device, dlc_int7_w))
MACHINE_CONFIG_END
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const tiny_rom_entry *m1comm_device::device_rom_region() const
{
return ROM_NAME( m1comm );
}
const tiny_rom_entry *m1comm_device::device_rom_region() const
{
return ROM_NAME( m1comm );
}
//**************************************************************************
// LIVE DEVICE
@ -123,8 +143,11 @@ 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_cpu(*this, Z80_TAG),
m_dma(*this, DMA_TAG),
m_dlc(*this, DLC_TAG)
{
#ifdef M1COMM_SIMULATION
// prepare localhost "filename"
m_localhost[0] = 0;
strcat(m_localhost, "socket.");
@ -140,6 +163,7 @@ m1comm_device::m1comm_device(const machine_config &mconfig, const char *tag, dev
strcat(m_remotehost, mconfig.options().comm_remoteport());
m_framesync = mconfig.options().comm_framesync() ? 0x01 : 0x00;
#endif
}
//-------------------------------------------------
@ -160,81 +184,53 @@ void m1comm_device::device_reset()
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)
void m1comm_device::device_reset_after_children()
{
// dirty hack to keep Z80 in RESET state
if (!m_cn)
{
device_reset();
return 0xff;
}
// dirty hack to keep Z80 in RESET state
uint8_t result = m_dlc_reg[offset];
LOG("m1comm-dlc_reg_r: read register %02x for value %02x\n", offset, result);
return result;
m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_dma->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_dlc->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
}
WRITE8_MEMBER(m1comm_device::dlc_reg_w)
WRITE_LINE_MEMBER(m1comm_device::dma_hreq_w)
{
m_dlc_reg[offset] = data;
LOG("m1comm-dlc_reg_w: write register %02x for value %02x\n", offset, data);
m_cpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
m_dma->hack_w(state);
}
READ8_MEMBER(m1comm_device::dma_reg_r)
READ8_MEMBER(m1comm_device::dma_mem_r)
{
uint8_t result = m_dma_reg[offset];
LOG("m1comm-dma_reg_r: read register %02x for value %02x\n", offset, result);
return result;
return m_cpu->space(AS_PROGRAM).read_byte(offset);
}
WRITE8_MEMBER(m1comm_device::dma_reg_w)
WRITE8_MEMBER(m1comm_device::dma_mem_w)
{
LOG("m1comm-dma_reg_w: %02x %02x\n", offset, data);
m_dma_reg[offset] = data;
m_cpu->space(AS_PROGRAM).write_byte(offset, data);
}
WRITE_LINE_MEMBER(m1comm_device::dlc_int7_w)
{
m_cpu->set_input_line_and_vector(0, state ? ASSERT_LINE : CLEAR_LINE, 0xff);
}
READ8_MEMBER(m1comm_device::syn_r)
{
uint8_t result = m_syn | 0xfc;
LOG("m1comm-syn_r: read register %02x for value %02x\n", offset, result);
return result;
return m_syn | 0xfc;
}
WRITE8_MEMBER(m1comm_device::syn_w)
{
m_syn = data & 0x03;
switch (data & 0x02)
{
case 0x00:
LOG("m1comm-syn_w: VINT disabled\n");
break;
case 0x02:
LOG("m1comm-syn_w: VINT enabled\n");
break;
default:
LOG("m1comm-syn_w: %02x\n", data);
break;
}
}
READ8_MEMBER(m1comm_device::zfg_r)
{
uint8_t result = m_zfg | (~m_fg << 7) | 0x7e;
LOG("m1comm-zfg_r: read register %02x for value %02x\n", offset, result);
return result;
return m_zfg | (~m_fg << 7) | 0x7e;
}
WRITE8_MEMBER(m1comm_device::zfg_w)
{
LOG("m1comm-zfg_w: %02x\n", data);
m_zfg = data & 0x01;
}
@ -259,9 +255,16 @@ WRITE8_MEMBER(m1comm_device::cn_w)
#ifndef M1COMM_SIMULATION
if (!m_cn)
{
device_reset();
device_reset_after_children();
}
else
m_commcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
{
m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
m_dma->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
m_dlc->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
}
#else
if (!m_cn)
{
@ -301,8 +304,7 @@ void m1comm_device::check_vint_irq()
#ifndef M1COMM_SIMULATION
if (m_syn & 0x02)
{
m_commcpu->set_input_line_and_vector(0, HOLD_LINE, 0xef);
LOG("m1comm-INT5\n");
m_cpu->set_input_line_and_vector(0, HOLD_LINE, 0xef);
}
#else
comm_tick();

View File

@ -9,6 +9,11 @@
#include "osdcore.h"
#include "cpu/z80/z80.h"
#include "machine/am9517a.h"
#include "machine/mb89374.h"
#define M1COMM_TAG "m1comm"
#define M1COMM_CPU_REGION "m1comm:commcpu"
#define MCFG_M1COMM_ADD(_tag ) \
MCFG_DEVICE_ADD(_tag, M1COMM, 0)
@ -23,31 +28,17 @@ public:
// construction/destruction
m1comm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// 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
DECLARE_READ8_MEMBER(share_r);
DECLARE_WRITE8_MEMBER(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);
@ -61,21 +52,44 @@ protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_reset_after_children() override;
virtual const tiny_rom_entry *device_rom_region() const override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
private:
required_device<z80_device> m_commcpu;
required_device<z80_device> m_cpu;
required_device<am9517a_device> m_dma;
required_device<mb89374_device> m_dlc;
// MB89374 handler
DECLARE_WRITE_LINE_MEMBER(dlc_int7_w);
// MB89237A handler
DECLARE_WRITE_LINE_MEMBER(dma_hreq_w);
DECLARE_READ8_MEMBER(dma_mem_r);
DECLARE_WRITE8_MEMBER(dma_mem_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
// reads/writes at 0xC000-FFFF
// - share_r
// - share_w
uint8_t m_shared[0x1000]; // 2x 2k = 4k; model1 accesses this with 16bit data and 11bit address (A0 to A10)
uint8_t m_dlc_reg[0x20]; // MB89374 registers
uint8_t m_dma_reg[0x20]; // MB89237A registers
uint8_t m_syn; // bit0 is stored; purpose unknown, bit1 is used to enable/disable VINT/IRQ5
uint8_t m_zfg; // z80 flip gate? purpose unknown, bit0 is stored
uint8_t m_syn; // bit0 is used to trigger DOP line on VINT, bit1 is used to enable/disable VINT/IRQ5
uint8_t m_zfg; // z80 flip gate, 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_fg; // flip gate, bit0 is stored, bit7 is connected to ZFG bit 0
#ifdef M1COMM_SIMULATION
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];
@ -84,7 +98,6 @@ private:
uint8_t m_buffer1[0x200];
uint8_t m_framesync;
#ifdef M1COMM_SIMULATION
uint8_t m_linkenable;
uint16_t m_linktimer;
uint8_t m_linkalive;