From 693e73dbf3ea41730ad9106e343b304c916f1ef2 Mon Sep 17 00:00:00 2001 From: Lord-Nightmare Date: Sun, 20 Sep 2015 06:36:23 -0400 Subject: [PATCH] Significant accuracy improvements, documentation and other updates to the ER-2055 EAROM emulation used for several Atari games, based on schematics and datasheets. It now uses a state machine to keep track of the current EAROM bus state. [Lord Nightmare] --- src/mame/machine/atari_vg.c | 117 +++++++++++++++++++++++++++--------- src/mame/machine/atari_vg.h | 7 ++- 2 files changed, 92 insertions(+), 32 deletions(-) diff --git a/src/mame/machine/atari_vg.c b/src/mame/machine/atari_vg.c index 9f2f043de58..68676150a08 100644 --- a/src/mame/machine/atari_vg.c +++ b/src/mame/machine/atari_vg.c @@ -1,14 +1,38 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders:Aaron Giles, Jonathan Gevaryahu /*************************************************************************** - Atari vector hardware + General Instruments ER-2055 EAROM + 64 word x 8 bit Electrically Alterable Read Only Memory + + Atari often called this part "137161-001" on their technical manuals, + but their schematics usually called it by its proper ER-2055 name. + + Centipede, Millipede, Dig Dug CTRL port wiring: + 7 6 5 4 3 2 1 0 + x x x x | | | \-- EAROM CLK (directly connected) + x x x x | | \---- /EAROM C1 (note this is inverted! the value written here is inverted, then connected to EAROM C1 AND to the /OE of the 'input latch' which drive the earom bus when writing) + x x x x | \------ EAROM C2 (directly connected) + x x x x \-------- EAROM CS1 (postive enable, directly connected) + + Gravitar, Red Baron, Black Widow, Tempest, Liberator, Asteroids Deluxe, Runaway CTRL port wiring: + 7 6 5 4 3 2 1 0 + x x x x | | | \-- EAROM CLK (directly connected) + x x x x | | \---- EAROM C2 (directly connected) + x x x x | \------ /EAROM C1 (note this is inverted! the value written here is inverted, then connected to EAROM C1 AND to the /OE of the 'input latch' which drive the earom bus when writing) + x x x x \-------- EAROM CS1 (postive enable, directly connected) ***************************************************************************/ #include "emu.h" #include "atari_vg.h" +#define ER2055_IDLE (0) +#define ER2055_READ_WAITING_FOR_CLOCK (1) +#define ER2055_READ_DRIVING_BUS (2) +#define ER2055_WRITING_BITS (3) +#define ER2055_ERASING_BITS (4) + // device type definition const device_type ATARIVGEAROM = &device_creator; @@ -23,45 +47,71 @@ atari_vg_earom_device::atari_vg_earom_device(const machine_config &mconfig, cons { } - +// Activate the output buffer (LS244)'s /G1 and /G2 lines to read whatever is on the EAROM's output bus READ8_MEMBER( atari_vg_earom_device::read ) { - logerror("read earom: %02x(%02x):%02x\n", m_offset, offset, m_data); - return (m_data); + logerror("read from earom output: %02x(%02x):%02x\n", m_in_offset, offset, m_out_data); + return (m_out_data); } - +// Write to the address input (LS174) and data input (LS374) latches respectively WRITE8_MEMBER( atari_vg_earom_device::write ) { - logerror("write earom: %02x:%02x\n", offset, data); - m_offset = offset; - m_data = data; + logerror("write to earom buffers: offset:data of %02x:%02x\n", offset, data); + m_in_offset = offset; + m_in_data = data; } - -/* 0,8 and 14 get written to this location, too. - * Don't know what they do exactly +/* CTRL controls the CTRL latch (LS175): +See top of file: there are two possible wirings! */ WRITE8_MEMBER( atari_vg_earom_device::ctrl_w ) { - logerror("earom ctrl: %02x:%02x\n",offset, data); - /* - 0x01 = clock - 0x02 = set data latch? - writes only (not always) - 0x04 = write mode? - writes only - 0x08 = set addr latch? - */ - if (data & 0x01) + static const char *const er2055_State[5] = { "IDLE", "RD_WAIT", "RD_OUTPUT", "WRITE", "ERASE" }; + logerror("EAROM_CTRL written with %02x: ", data); + switch(data&0xe) { - m_data = m_rom[m_offset]; -//printf("Read %02X = %02X\n", m_offset, m_data); + case 0x0: case 0x2: case 0x4: case 0x6: // CS was low, chip is idle + m_state = ER2055_IDLE; + break; + case 0x8: // C1 = 1, C2 = 0: Read, (wait for clock, if clock has arrived, idle). + if ((m_state==ER2055_READ_WAITING_FOR_CLOCK)&&(((m_old_ctrl&1)==0)&&((data&1)==1))) // rising clock edge? + m_state = ER2055_READ_DRIVING_BUS; + else if (m_state!=ER2055_READ_DRIVING_BUS) // if we're already driving the bus, stay driving it. otherwise we're still waiting. + m_state = ER2055_READ_WAITING_FOR_CLOCK; + break; + case 0xA: // C1 = 0, C2 = 0: Write (set gate 0 if the bit is a 0, set gate 1 if the bit is a 1) + m_state = ER2055_WRITING_BITS; + break; + case 0xC: // C1 = 1, C2 = 1: Invalid + logerror("INVALID CTRL STATE!"); + m_state = ER2055_WRITING_BITS; + break; + case 0xE: // C1 = 0, C2 = 1: Erase (zero both gates for all bits of the current byte; byte will read as random garbage after this, different each time!) + m_state = ER2055_ERASING_BITS; + break; } - if ((data & 0x0c) == 0x0c) + logerror("state is now %s\n", er2055_State[m_state]); + + switch(m_state) { - m_rom[m_offset]=m_data; - logerror(" written %02x:%02x\n", m_offset, m_data); -//printf("Write %02X = %02X\n", m_offset, m_data); + case ER2055_IDLE: // idle, do nothing. + case ER2055_READ_WAITING_FOR_CLOCK: // waiting for a clock rising edge which we haven't yet seen, do nothing + m_out_data = 0xFF; + break; + case ER2055_READ_DRIVING_BUS: // bus is being driven with data + m_out_data = m_rom[m_in_offset]; + break; + case ER2055_WRITING_BITS: // write contents of bus to rom + m_rom[m_in_offset] = m_in_data; + m_out_data = m_in_data; + break; + case ER2055_ERASING_BITS: // erase contents of rom + m_rom[m_in_offset] = 0; //TODO: this should actually set the rom contents to an invalid state which reads inconsistently until it is written to by a WRITE command + m_out_data = m_in_data; + break; } + m_old_ctrl = data; } //------------------------------------------------- @@ -100,8 +150,12 @@ void atari_vg_earom_device::nvram_write(emu_file &file) void atari_vg_earom_device::device_start() { /* register for save states */ - save_item(NAME(m_offset)); - save_item(NAME(m_data)); + save_item(NAME(m_state)); + save_item(NAME(m_old_ctrl)); + save_item(NAME(m_in_offset)); + save_item(NAME(m_in_data)); + save_item(NAME(m_out_data)); + save_item(NAME(m_rom)); } //------------------------------------------------- @@ -110,6 +164,9 @@ void atari_vg_earom_device::device_start() void atari_vg_earom_device::device_reset() { - m_data = 0; - m_offset = 0; + m_state = ER2055_READ_WAITING_FOR_CLOCK; // start in read mode + m_old_ctrl = 0; + m_in_offset = 0; + m_in_data = 0; + m_out_data = 0xFF; // the value driven to the bus by the resistors if EAROM is open bus } diff --git a/src/mame/machine/atari_vg.h b/src/mame/machine/atari_vg.h index 7815f20ace9..e85b4a65ed9 100644 --- a/src/mame/machine/atari_vg.h +++ b/src/mame/machine/atari_vg.h @@ -41,8 +41,11 @@ public: DECLARE_WRITE8_MEMBER( write ); DECLARE_WRITE8_MEMBER( ctrl_w ); private: - int m_offset; - int m_data; + int m_old_ctrl; + int m_state; + int m_in_offset; + int m_in_data; + int m_out_data; char m_rom[EAROM_SIZE]; };