mame/src/mess/drivers/ie15.c
2014-03-15 13:00:23 +00:00

671 lines
18 KiB
C

/***************************************************************************
15IE-00-013 Terminal
board images : http://asvcorp.ru/darch/hardware/pdp/fryazin-display/index.html
29/06/2012 Skeleton driver.
A serial (RS232 or current loop) green-screen terminal, mostly VT52 compatible
(no Hold Screen mode and no graphics character set, but has Cyrillic characters).
The top line is a status line.
****************************************************************************/
#include "emu.h"
#include "cpu/ie15/ie15.h"
#include "imagedev/bitbngr.h"
#include "machine/keyboard.h"
#include "sound/beep.h"
#define SCREEN_PAGE (80*48)
#define IE_1 0x80
#define IE_KB_ACK 1
#define IE15_TOTAL_HORZ 1000
#define IE15_TOTAL_VERT 28*11
#define IE15_DISP_HORZ 800
#define IE15_DISP_VERT 25*11
#define IE15_HORZ_START 100
#define IE15_VERT_START 2*11
#define VERBOSE_DBG 1 /* general debug messages */
#define DBG_LOG(N,M,A) \
do { \
if(VERBOSE_DBG>=N) \
{ \
if( M ) \
logerror("%11.6f at %s: %-24s",machine().time().as_double(),machine().describe_context(),(char*)M ); \
logerror A; \
} \
} while (0)
#if VERBOSE_DBG > 0
#define LOOPBACK (m_io_keyboard->read() & 0x20)
#else
#define LOOPBACK (0)
#endif
#define BITBANGER_TAG "bitbanger"
#define KEYBOARD_TAG "keyboard"
class ie15_state : public driver_device
{
public:
ie15_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_beeper(*this, "beeper"),
m_bitbanger(*this, BITBANGER_TAG),
m_io_keyboard(*this, KEYBOARD_TAG)
{ }
virtual void machine_reset();
virtual void video_start();
DECLARE_PALETTE_INIT(ie15);
UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
UINT32 screen_update_hle(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_DEVICE_CALLBACK_MEMBER(scanline_callback);
DECLARE_WRITE8_MEMBER(kbd_put);
static const bitbanger_config ie15_bitbanger_config;
TIMER_CALLBACK_MEMBER(serial_tx_callback);
emu_timer *m_serial_tx_timer;
DECLARE_WRITE8_MEMBER( mem_w );
DECLARE_READ8_MEMBER( mem_r );
DECLARE_WRITE8_MEMBER( mem_addr_lo_w );
DECLARE_WRITE8_MEMBER( mem_addr_hi_w );
DECLARE_WRITE8_MEMBER( mem_addr_inc_w );
DECLARE_WRITE8_MEMBER( mem_addr_dec_w );
DECLARE_READ8_MEMBER( flag_r );
DECLARE_WRITE8_MEMBER( flag_w );
DECLARE_WRITE8_MEMBER( beep_w );
DECLARE_READ8_MEMBER( kb_r );
DECLARE_READ8_MEMBER( kb_ready_r );
DECLARE_READ8_MEMBER( kb_s_red_r );
DECLARE_READ8_MEMBER( kb_s_sdv_r );
DECLARE_READ8_MEMBER( kb_s_dk_r );
DECLARE_READ8_MEMBER( kb_s_dupl_r );
DECLARE_READ8_MEMBER( kb_s_lin_r );
DECLARE_WRITE8_MEMBER( kb_ready_w );
DECLARE_READ8_MEMBER( serial_tx_ready_r );
DECLARE_WRITE8_MEMBER( serial_w );
DECLARE_READ8_MEMBER( serial_rx_ready_r );
DECLARE_READ8_MEMBER( serial_r );
#if 0
DECLARE_WRITE8_MEMBER( serial_speed_w );
#endif
private:
TIMER_CALLBACK_MEMBER(ie15_beepoff);
UINT32 draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline, UINT8 y);
bitmap_ind16 m_tmpbmp;
const UINT8 *m_p_chargen;
UINT8 *m_p_videoram;
UINT8 m_beep;
UINT8 m_cursor;
UINT8 m_kb_data;
UINT8 m_kb_flag;
UINT8 m_kb_flag0;
UINT8 m_latch;
UINT8 m_ruslat;
UINT8 m_serial_rx_bits;
UINT8 m_serial_rx_buffer;
UINT8 m_serial_rx_data;
UINT8 m_serial_tx_bits;
UINT8 m_serial_tx_data;
UINT8 m_statusline;
UINT8 m_video;
UINT32 m_videoptr;
UINT32 m_videoptr_2;
static void bitbanger_callback(running_machine &machine, UINT8 bit);
DECLARE_WRITE_LINE_MEMBER( serial_rx_callback );
protected:
required_device<cpu_device> m_maincpu;
required_device<beep_device> m_beeper;
required_device<bitbanger_device> m_bitbanger;
required_ioport m_io_keyboard;
};
READ8_MEMBER( ie15_state::mem_r ) {
UINT8 ret;
ret = m_p_videoram[m_videoptr];
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_videoptr >= SCREEN_PAGE)
{
DBG_LOG(2,"memory",("R @ %03x == %02x\n", m_videoptr, ret));
}
m_videoptr++;
m_videoptr &= 0xfff;
m_latch = 0;
return ret;
}
WRITE8_MEMBER( ie15_state::mem_w ) {
if ((m_latch ^= 1) == 0) {
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_videoptr >= SCREEN_PAGE)
{
DBG_LOG(2,"memory",("W @ %03x <- %02x\n", m_videoptr, data));
}
m_p_videoram[m_videoptr++] = data;
m_videoptr &= 0xfff;
}
}
WRITE8_MEMBER( ie15_state::mem_addr_inc_w ) {
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
DBG_LOG(2,"memory",("++ %03x\n", m_videoptr));
}
m_videoptr++;
m_videoptr &= 0xfff;
if (m_video)
m_videoptr_2 = m_videoptr;
}
WRITE8_MEMBER( ie15_state::mem_addr_dec_w ) {
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
DBG_LOG(2,"memory",("-- %03x\n", m_videoptr));
}
m_videoptr--;
m_videoptr &= 0xfff;
if (m_video)
m_videoptr_2 = m_videoptr;
}
WRITE8_MEMBER( ie15_state::mem_addr_lo_w ) {
UINT16 tmp = m_videoptr;
tmp &= 0xff0;
tmp |= ((data >> 4) & 0xf);
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
DBG_LOG(2,"memory",("lo %03x <- %02x = %03x\n", m_videoptr, data, tmp));
}
m_videoptr = tmp;
if (m_video)
m_videoptr_2 = tmp;
}
WRITE8_MEMBER( ie15_state::mem_addr_hi_w ) {
UINT16 tmp = m_videoptr;
tmp &= 0xf;
tmp |= (data << 4);
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
DBG_LOG(2,"memory",("hi %03x <- %02x = %03x\n", m_videoptr, data, tmp));
}
m_videoptr = tmp;
if (m_video)
m_videoptr_2 = tmp;
}
TIMER_CALLBACK_MEMBER(ie15_state::ie15_beepoff)
{
machine().device<beep_device>("beeper")->set_state(0);
}
WRITE8_MEMBER( ie15_state::beep_w ) {
UINT16 length = (m_beep&128)?150:400;
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
DBG_LOG(1,"beep",("(%s)\n", m_beep?"short":"long"));
}
machine().scheduler().timer_set(attotime::from_msec(length), timer_expired_delegate(FUNC(ie15_state::ie15_beepoff),this));
machine().device<beep_device>("beeper")->set_state(1);
}
// active high
READ8_MEMBER( ie15_state::kb_r ) {
DBG_LOG(2,"keyboard",("R %02X '%c'\n", m_kb_data, m_kb_data < 0x20?' ':m_kb_data));
return m_kb_data;
}
// active low
READ8_MEMBER( ie15_state::kb_ready_r ) {
m_kb_flag &= IE_1;
if (m_kb_flag != m_kb_flag0) {
DBG_LOG(2,"keyboard",("? %c\n", m_kb_flag?'n':'y'));
m_kb_flag0 = m_kb_flag;
}
return m_kb_flag;
}
// active low
WRITE8_MEMBER( ie15_state::kb_ready_w ) {
DBG_LOG(2,"keyboard",("clear ready\n"));
m_kb_flag = IE_1 | IE_KB_ACK;
}
// active high; active = interpret controls, inactive = display controls
READ8_MEMBER( ie15_state::kb_s_red_r ) {
return m_io_keyboard->read() & 0x01 ? IE_1 : 0;
}
// active high; active = setup mode
READ8_MEMBER( ie15_state::kb_s_sdv_r ) {
return m_io_keyboard->read() & 0x02 ? IE_1 : 0;
}
// active high, XXX stub
READ8_MEMBER( ie15_state::kb_s_dk_r ) {
return 0;
}
// active low; active = full duplex, inactive = half duplex
READ8_MEMBER( ie15_state::kb_s_dupl_r ) {
return m_io_keyboard->read() & 0x08 ? IE_1 : 0;
}
// active high; active = on-line, inactive = local editing
READ8_MEMBER( ie15_state::kb_s_lin_r ) {
return m_io_keyboard->read() & 0x10 ? IE_1 : 0;
}
// active low
READ8_MEMBER( ie15_state::serial_rx_ready_r ) {
if (LOOPBACK)
return m_serial_tx_data ? 0 : IE_1;
else
return m_serial_rx_data ? 0 : IE_1;
}
// not called unless data is ready
READ8_MEMBER( ie15_state::serial_r ) {
UINT8 tmp;
if (LOOPBACK) {
tmp = m_serial_tx_data;
m_serial_tx_data = 0;
} else {
tmp = m_serial_rx_data;
m_serial_rx_data = 0;
}
DBG_LOG(2,"serial",("R %02X '%c'\n", tmp, tmp < 0x20?' ':tmp));
return tmp;
}
/*
m_serial_rx_buffer incoming bits.
m_serial_rx_bits number of bits in _buffer.
m_serial_rx_data complete byte, ready to be read by host, or 0 if no data.
*/
WRITE_LINE_MEMBER( ie15_state::serial_rx_callback )
{
UINT8 tmp = m_serial_rx_bits;
switch (m_serial_rx_bits) {
// wait for start bit (0)
case 10:
m_serial_rx_bits = 0;
case 0:
if (!state) {
m_serial_rx_bits++;
m_serial_rx_buffer = 0;
}
break;
// stuff incoming bits into byte buffer
case 1: case 2: case 3: case 4:
case 5: case 6: case 7: case 8:
m_serial_rx_buffer |= state << (m_serial_rx_bits-1);
m_serial_rx_bits++;
break;
// expecting stop bit (1)
case 9:
if (state && !m_serial_rx_data) {
m_serial_rx_data = m_serial_rx_buffer;
m_serial_rx_bits++;
} else
m_serial_rx_bits = 0;
break;
default:
// overflow
break;
}
DBG_LOG(2,"serial",("r %d bits %02d->%02d buffer %02X data %02X\n",
state, tmp, m_serial_rx_bits, m_serial_rx_buffer, m_serial_rx_data));
}
const bitbanger_config ie15_state::ie15_bitbanger_config =
{
DEVCB_DRIVER_LINE_MEMBER(ie15_state, serial_rx_callback), /* callback */
BITBANGER_PRINTER, /* default mode */
BITBANGER_9600, /* default output baud */
BITBANGER_0PERCENT /* default fine tune adjustment */
};
// active high
READ8_MEMBER( ie15_state::serial_tx_ready_r ) {
return m_serial_tx_data ? 0 : IE_1;
}
WRITE8_MEMBER( ie15_state::serial_w ) {
DBG_LOG(2,"serial",("W %02X '%c'\n", data, data < 0x20?' ':data));
if (LOOPBACK) {
if (!m_serial_tx_data)
m_serial_tx_data = data;
} else {
/* 1 start bit */
m_bitbanger->output(0);
/* 8 data bits, 1 stop bit, no parity */
m_serial_tx_bits = 8;
m_serial_tx_data = data;
m_serial_tx_timer->adjust(attotime::from_hz(9600));
}
}
TIMER_CALLBACK_MEMBER(ie15_state::serial_tx_callback) {
if (!m_serial_tx_bits) {
m_bitbanger->output(1);
m_serial_tx_data = 0;
} else {
m_bitbanger->output(BIT(m_serial_tx_data, 8-(m_serial_tx_bits--)));
m_serial_tx_timer->adjust(attotime::from_hz(9600));
}
}
READ8_MEMBER( ie15_state::flag_r ) {
UINT8 ret = 0;
switch (offset)
{
case 0: // hsync pulse (not hblank)
ret = machine().first_screen()->hpos() < IE15_HORZ_START;
break;
case 1: // marker scanline
ret = (machine().first_screen()->vpos() % 11) > 7;
break;
case 2: // vblank
ret = !machine().first_screen()->vblank();
break;
case 4:
ret = m_ruslat;
break;
default:
break;
}
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && ret)
{
DBG_LOG(2,"flag",("read %d: %d\n", offset, ret));
}
return ret;
}
WRITE8_MEMBER( ie15_state::flag_w ) {
switch (offset)
{
case 0:
m_video = data;
break;
case 1:
m_cursor = data;
break;
case 2:
m_beep = data;
break;
case 3:
m_statusline = data;
break;
case 4:
m_ruslat = data;
break;
default:
break;
}
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
DBG_LOG(2,"flag",("%sset %d\n", data?"":"re", offset));
}
}
static ADDRESS_MAP_START(ie15_mem, AS_PROGRAM, 8, ie15_state)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE( 0x0000, 0x0fff ) AM_ROM
ADDRESS_MAP_END
static ADDRESS_MAP_START(ie15_io, AS_IO, 8, ie15_state)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(000, 000) AM_READ(mem_r) AM_WRITE(mem_w) // 00h W: memory request, R: memory data [6.1.2.2]
AM_RANGE(001, 001) AM_READ(serial_rx_ready_r) AM_WRITENOP // 01h W: memory latch [6.1.2.2]
AM_RANGE(002, 002) AM_WRITE(mem_addr_hi_w) // 02h W: memory address high [6.1.2.2]
AM_RANGE(003, 003) AM_WRITE(mem_addr_lo_w) // 03h W: memory address low [6.1.2.2]
AM_RANGE(004, 004) AM_WRITE(mem_addr_inc_w) // 04h W: memory address counter + [6.1.2.2]
AM_RANGE(005, 005) AM_WRITE(mem_addr_dec_w) // 05h W: memory address counter - [6.1.2.2]
AM_RANGE(006, 006) AM_READ(serial_r) AM_WRITE(serial_w) // 06h W: serial port data [6.1.5.4]
// port 7 is handled in cpu core
AM_RANGE(010, 010) AM_READ(serial_tx_ready_r) AM_WRITE(beep_w) // 08h W: speaker control [6.1.5.4]
AM_RANGE(011, 011) AM_READ(kb_r) // 09h R: keyboard data [6.1.5.2]
AM_RANGE(012, 012) AM_READ(kb_s_red_r) // 0Ah I: keyboard mode "RED" [6.1.5.2]
AM_RANGE(013, 013) AM_READ(kb_ready_r) // 0Bh R: keyboard data ready [6.1.5.2]
AM_RANGE(014, 014) AM_READ(kb_s_sdv_r) AM_WRITENOP // 0Ch W: serial port speed [6.1.3.1], R: keyboard mode "SDV" [6.1.5.2]
AM_RANGE(015, 015) AM_READ(kb_s_dk_r) AM_WRITE(kb_ready_w) // 0Dh I: keyboard mode "DK" [6.1.5.2]
AM_RANGE(016, 016) AM_READ(kb_s_dupl_r) // 0Eh I: keyboard mode "DUPL" [6.1.5.2]
AM_RANGE(017, 017) AM_READ(kb_s_lin_r) // 0Fh I: keyboard mode "LIN" [6.1.5.2]
// simulation of flag registers
AM_RANGE(020, 027) AM_READ(flag_r) AM_WRITE(flag_w)
ADDRESS_MAP_END
/* Input ports */
static INPUT_PORTS_START( ie15 )
PORT_START("keyboard")
PORT_DIPNAME(0x01, 0x00, "RED mode")
PORT_DIPSETTING(0x00, "Off" )
PORT_DIPSETTING(0x01, "On" )
PORT_DIPNAME(0x02, 0x00, "SDV mode (Setup)")
PORT_DIPSETTING(0x00, "Off" )
PORT_DIPSETTING(0x02, "On" )
PORT_DIPNAME(0x08, 0x00, "DUPL mode")
PORT_DIPSETTING(0x00, "Off" )
PORT_DIPSETTING(0x08, "On" )
PORT_DIPNAME(0x10, 0x00, "LIN mode")
PORT_DIPSETTING(0x00, "Off" )
PORT_DIPSETTING(0x10, "On" )
PORT_DIPNAME(0x20, 0x00, "digital loopback")
PORT_DIPSETTING(0x00, "Off" )
PORT_DIPSETTING(0x20, "On" )
INPUT_PORTS_END
WRITE8_MEMBER( ie15_state::kbd_put )
{
DBG_LOG(2,"keyboard",("W %02X<-%02X '%c' %c\n", m_kb_data, data, data < 0x20?' ':data, m_kb_flag?'n':'y'));
if (m_kb_flag == IE_1) {
m_kb_data = data;
m_kb_flag = 0;
}
}
static ASCII_KEYBOARD_INTERFACE( keyboard_intf )
{
DEVCB_DRIVER_MEMBER(ie15_state, kbd_put)
};
void ie15_state::machine_reset()
{
m_ruslat = m_beep = m_statusline = m_cursor = m_video = m_kb_data = m_kb_flag0 = 0;
m_serial_tx_data = m_serial_tx_bits = m_serial_rx_buffer = m_serial_rx_data = m_serial_rx_bits = 0;
m_kb_flag = IE_1;
machine().device<beep_device>("beeper")->set_frequency(2400);
machine().device<beep_device>("beeper")->set_state(0);
m_serial_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ie15_state::serial_tx_callback),this));
}
void ie15_state::video_start()
{
m_p_chargen = machine().root_device().memregion("chargen")->base();
m_p_videoram = memregion("video")->base();
m_videoptr = m_videoptr_2 = m_latch = 0;
m_tmpbmp.allocate(IE15_DISP_HORZ, IE15_DISP_VERT);
}
UINT32 ie15_state::draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline, UINT8 y)
{
UINT8 gfx,fg,bg,ra,blink,red;
UINT16 x,chr;
bg = 0; fg = 1; ra = scanline % 8;
blink = (machine().first_screen()->frame_number() % 10) >= 5;
red = m_io_keyboard->read() & 0x01;
DBG_LOG(2,"draw_scanline",
("addr %03x row %d-%d video %d\n", offset, y, scanline, m_video));
for (x = offset; x < offset + 80; x++)
{
if (m_video) {
chr = m_p_videoram[x] << 3;
gfx = m_p_chargen[chr | ra];
/*
Cursor is a character with only 3 scan lines, and is
not shown if flag 1 is not active on this scan line.
It always blinks if shown.
Control characters blink if RED mode is on and they
are not on status line; else they are blanked out.
*/
if (scanline > 7 && (!m_cursor || blink))
gfx = 0;
if (chr < (0x20<<3)) {
if (!y || !red || blink)
gfx = 0;
else
gfx = m_p_chargen[chr | 0x200 | ra];
}
/* Display a scanline of a character */
*p++ = BIT(gfx, 7) ? fg : bg;
*p++ = BIT(gfx, 6) ? fg : bg;
*p++ = BIT(gfx, 5) ? fg : bg;
*p++ = BIT(gfx, 4) ? fg : bg;
*p++ = BIT(gfx, 3) ? fg : bg;
*p++ = BIT(gfx, 2) ? fg : bg;
*p++ = BIT(gfx, 1) ? fg : bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
} else {
*p++ = bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
*p++ = bg;
}
}
return 0;
}
TIMER_DEVICE_CALLBACK_MEMBER(ie15_state::scanline_callback)
{
UINT16 y = machine().first_screen()->vpos();
// DBG_LOG(2,"scanline",
// ("addr %03x frame %lld x %04d y %03d\n", m_videoptr_2, machine().first_screen()->frame_number(), machine().first_screen()->hpos(), y));
if (y>=IE15_VERT_START) {
y -= IE15_VERT_START;
if (y < IE15_DISP_VERT) {
draw_scanline(&m_tmpbmp.pix16(y), m_videoptr_2, y%11, y/11);
}
}
}
UINT32 ie15_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
copybitmap( bitmap, m_tmpbmp, 0, 0, IE15_HORZ_START, IE15_VERT_START, cliprect );
return 0;
}
/* F4 Character Displayer */
static const gfx_layout ie15_charlayout =
{
7, 8, /* 7x8 pixels in 10x11 cell */
256, /* 256 characters */
1, /* 1 bits per pixel */
{ 0 }, /* no bitplanes */
/* x offsets */
{ 0, 1, 2, 3, 4, 5, 6 },
/* y offsets */
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 bytes */
};
static GFXDECODE_START( ie15 )
GFXDECODE_ENTRY( "chargen", 0x0000, ie15_charlayout, 0, 1 )
GFXDECODE_END
PALETTE_INIT_MEMBER(ie15_state, ie15)
{
palette.set_pen_color(0, rgb_t::black); // black
palette.set_pen_color(1, 0x00, 0xc0, 0x00); // green
}
static MACHINE_CONFIG_START( ie15, ie15_state )
/* Basic machine hardware */
MCFG_CPU_ADD("maincpu", IE15, XTAL_30_8MHz / 10)
MCFG_CPU_PROGRAM_MAP(ie15_mem)
MCFG_CPU_IO_MAP(ie15_io)
MCFG_TIMER_DRIVER_ADD_PERIODIC("scantimer", ie15_state, scanline_callback, attotime::from_hz(50*28*11))
MCFG_TIMER_START_DELAY(attotime::from_hz(XTAL_30_8MHz/(2*IE15_HORZ_START)))
/* Video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_UPDATE_DRIVER(ie15_state, screen_update)
MCFG_SCREEN_RAW_PARAMS(XTAL_30_8MHz/2,IE15_TOTAL_HORZ,IE15_HORZ_START,
IE15_HORZ_START+IE15_DISP_HORZ,IE15_TOTAL_VERT,IE15_VERT_START,
IE15_VERT_START+IE15_DISP_VERT);
MCFG_SCREEN_PALETTE("palette")
MCFG_GFXDECODE_ADD("gfxdecode", "palette", ie15)
MCFG_PALETTE_ADD("palette", 2)
MCFG_PALETTE_INIT_OWNER(ie15_state, ie15)
/* Devices */
MCFG_ASCII_KEYBOARD_ADD(KEYBOARD_TAG, keyboard_intf)
MCFG_BITBANGER_ADD(BITBANGER_TAG, ie15_state::ie15_bitbanger_config)
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("beeper", BEEP, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS,"mono",0.15)
MACHINE_CONFIG_END
/* ROM definition */
ROM_START( ie15 )
ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASE00 )
ROM_DEFAULT_BIOS("5chip")
ROM_SYSTEM_BIOS(0, "5chip", "5-chip firmware (newer)")
ROMX_LOAD( "dump1.bin", 0x0000, 0x1000, CRC(14b82284) SHA1(5ac4159fbb1c3b81445605e26cd97a713ae12b5f),ROM_BIOS(1) )
ROM_SYSTEM_BIOS(1, "6chip", "6-chip firmware (older)")
ROMX_LOAD( "dump5.bin", 0x0000, 0x1000, CRC(01f2e065) SHA1(2b72dc0594e38a528400cd25aed0c47e0c432895),ROM_BIOS(2) )
ROM_REGION( 0x1000, "video", ROMREGION_ERASE00 )
ROM_REGION( 0x0800, "chargen", ROMREGION_ERASE00 )
ROM_LOAD( "chargen-15ie.bin", 0x0000, 0x0800, CRC(ed16bf6b) SHA1(6af9fb75f5375943d5c0ce9ed408e0fb4621b17e) )
ROM_END
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
COMP( 1980, ie15, 0, 0, ie15, ie15, driver_device, 0, "USSR", "15IE-00-013", 0)