summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Robbbert <pac0446@bigpond.net.au>2015-10-09 19:10:52 +1100
committer Robbbert <pac0446@bigpond.net.au>2015-10-09 19:10:52 +1100
commitbc6aa6be4b31305d054f60a491808f3797ecde40 (patch)
tree52d08df68e91efdd6ba13b1a9ffec3c39731af0e /src
parent565b835ee137ef29e0650a3416d62719c858a07a (diff)
eti660: fixed various issues, marked as Working [Robbbert]
Diffstat (limited to 'src')
-rw-r--r--src/mame/drivers/eti660.c210
-rw-r--r--src/mame/includes/eti660.h46
2 files changed, 183 insertions, 73 deletions
diff --git a/src/mame/drivers/eti660.c b/src/mame/drivers/eti660.c
index 80b490eff0f..238ec6d9b6f 100644
--- a/src/mame/drivers/eti660.c
+++ b/src/mame/drivers/eti660.c
@@ -1,21 +1,40 @@
// license:BSD-3-Clause
-// copyright-holders:Curt Coder
-/*
+// copyright-holders:Curt Coder, Robbbert
+/*****************************************************************************************
- TODO:
+ ETI project 660, featured in the Australian magazine Electronics Today International.
+
+ Commands:
+ R - Reset (use this before any other instruction)
+ S - Step
+ 0 - Enter modify memory mode
+ 2 - Save memory to cassette
+ 4 - Load memory from cassette
+ 6 - start binary program
+ 8 - start chip-8 program.
+
+ To modify memory, press R, 0, enter 4-digit address, S, enter data, S, continue on.
+ R to escape.
- - does not boot!
- - reset key
- - allocate color ram
- - quickload
- - color on
+ To save a tape, enter the start address into 0400,0401 (big endian), and the end
+ address into 0402,0403. Press R. Press record on the tape, press 2.
- - keyboard not working
- - foreground is black, according to the construction article it should be white.
- - it is supposed to reset itself at boot, but that isn't working. You must press R.
- - Pressing F3 causes it to jump into the weeds.
+ To load a tape, enter the start and end addresses as above. Press R, 4. Screen goes
+ black. Press play on tape. If the screen is still black after the tape ends, press R.
+
+ All chip-8 programs start at 0600. The manual says the max end address is 7FF (gives
+ 512 bytes), but you can fill up all of memory (gives 2560 bytes).
+
+ TODO:
+ - sometimes there's no sound when started. You may need to hard reset until it beeps.
+ - don't know why, but the expected behaviour of our 6821 pia isn't what this machine
+ expects, so had to add a couple of hacks.
+ - doesn't run programs for other chip-8 computers (this might be normal?)
+ - we support BIN files, but have none to test with.
+ - in Invaders, can't shoot them
+ - in Maze, the result is rubbish (works in Emma02 emulator)
-*/
+**************************************************************************************************/
#include "includes/eti660.h"
@@ -23,25 +42,37 @@
READ8_MEMBER( eti660_state::pia_r )
{
- int pia_offset = m_maincpu->get_memory_address() & 0x03;
+ UINT8 pia_offset = m_maincpu->get_memory_address() & 0x03;
return m_pia->read(space, pia_offset);
}
WRITE8_MEMBER( eti660_state::pia_w )
{
- int pia_offset = m_maincpu->get_memory_address() & 0x03;
+ UINT8 pia_offset = m_maincpu->get_memory_address() & 0x03;
+
+ // Some PIA hacks here, as mentioned in the ToDo.
+ if (pia_offset == 1)
+ {
+ // switch color on when requested (test with Wipeout game)
+ if (data == 0x2c)
+ m_color_on = 1;
+ // enable keyboard
+ if (data == 0x20)
+ data = 0x24;
+ }
m_pia->write(space, pia_offset, data);
}
WRITE8_MEMBER( eti660_state::colorram_w )
{
- int colorram_offset = m_maincpu->get_memory_address() & 0xff;
+ offset = m_maincpu->get_memory_address() - 0xc80;
- colorram_offset = ((colorram_offset & 0xf8) >> 1) || (colorram_offset & 0x03);
+ UINT8 colorram_offset = (((offset & 0x1f0) >> 1) | (offset & 0x07));
- m_color_ram[colorram_offset] = data;
+ if (colorram_offset < 0xc0)
+ m_color_ram[colorram_offset] = data;
}
/* Memory Maps */
@@ -49,7 +80,9 @@ WRITE8_MEMBER( eti660_state::colorram_w )
static ADDRESS_MAP_START( eti660_map, AS_PROGRAM, 8, eti660_state )
ADDRESS_MAP_GLOBAL_MASK(0xfff)
AM_RANGE(0x0000, 0x03ff) AM_ROM
- AM_RANGE(0x0400, 0x0fff) AM_RAM
+ AM_RANGE(0x0400, 0x047f) AM_RAM
+ AM_RANGE(0x0480, 0x05ff) AM_RAM AM_SHARE("videoram")
+ AM_RANGE(0x0600, 0x0fff) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START( eti660_io_map, AS_IO, 8, eti660_state )
@@ -60,31 +93,34 @@ static ADDRESS_MAP_START( eti660_io_map, AS_IO, 8, eti660_state )
ADDRESS_MAP_END
/* Input Ports */
-
static INPUT_PORTS_START( eti660 )
- PORT_START("PA0")
+ PORT_START("KEY.0")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3')
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+ PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("KEY.1")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4')
+ PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_START("PA1")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2')
+ PORT_START("KEY.2")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8')
+ PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_START("PA2")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1')
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9')
+ PORT_START("KEY.3")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5')
-
- PORT_START("PA3")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8')
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("SPECIAL")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_R)
@@ -112,7 +148,13 @@ READ_LINE_MEMBER( eti660_state::gdata_r )
READ_LINE_MEMBER( eti660_state::clear_r )
{
- return BIT(m_special->read(), 0);
+ // A hack to make the machine reset itself on
+ // boot, like the real one does.
+ if (m_resetcnt < 0xffff)
+ m_resetcnt++;
+ if (m_resetcnt == 0xff00)
+ return 0;
+ return BIT(m_special->read(), 0); // R key
}
READ_LINE_MEMBER( eti660_state::ef2_r )
@@ -122,7 +164,7 @@ READ_LINE_MEMBER( eti660_state::ef2_r )
READ_LINE_MEMBER( eti660_state::ef4_r )
{
- return BIT(m_special->read(), 1);
+ return BIT(m_special->read(), 1); // S key
}
WRITE_LINE_MEMBER( eti660_state::q_w )
@@ -139,9 +181,19 @@ WRITE_LINE_MEMBER( eti660_state::q_w )
WRITE8_MEMBER( eti660_state::dma_w )
{
- UINT8 colorram_offset = ((offset & 0xf8) >> 1) | (offset & 0x03);
+ offset -= 0x480;
+
+ m_color = 7;
+
+ if (m_color_on)
+ {
+ UINT8 colorram_offset = ((offset & 0x1f0) >> 1) | (offset & 0x07);
- m_color = m_color_ram[colorram_offset];
+ if (colorram_offset < 0xc0)
+ m_color = m_color_ram[colorram_offset];
+ }
+ else
+ m_color = m_p_videoram[offset] ? 7 : 0;
m_cti->con_w(0); // HACK
m_cti->dma_w(space, offset, data);
@@ -166,14 +218,13 @@ READ8_MEMBER( eti660_state::pia_pa_r )
*/
- UINT8 data = 0xf0;
+ UINT8 i, data = 0xff;
+
+ for (i = 0; i < 4; i++)
+ if BIT(m_keylatch, i)
+ return m_io_keyboard[i]->read();
- if (!BIT(m_keylatch, 0)) data &= m_pa0->read();
- if (!BIT(m_keylatch, 1)) data &= m_pa1->read();
- if (!BIT(m_keylatch, 2)) data &= m_pa2->read();
- if (!BIT(m_keylatch, 3)) data &= m_pa3->read();
-
- return data | m_keylatch;
+ return data;
}
WRITE8_MEMBER( eti660_state::pia_pa_w )
@@ -193,7 +244,57 @@ WRITE8_MEMBER( eti660_state::pia_pa_w )
*/
- m_keylatch = data & 0x0f;
+ m_keylatch = data ^ 0xff;
+}
+
+void eti660_state::machine_reset()
+{
+ m_resetcnt = 0;
+ m_color_on = 0;
+ // fix for F3 soft reboot
+ m_maincpu->set_state_int(COSMAC_R0, 0); // set R0 to start of rom
+ m_maincpu->set_state_int(COSMAC_P, 0); // set R0 as the PC register
+}
+
+void eti660_state::machine_start()
+{
+ save_item(NAME(m_color_ram));
+}
+
+QUICKLOAD_LOAD_MEMBER( eti660_state, eti660 )
+{
+ address_space &space = m_maincpu->space(AS_PROGRAM);
+ int i;
+ int quick_addr = 0x600;
+ int quick_length;
+ dynamic_buffer quick_data;
+ int read_;
+ int result = IMAGE_INIT_FAIL;
+
+ quick_length = image.length();
+ quick_data.resize(quick_length);
+ read_ = image.fread( &quick_data[0], quick_length);
+ if (read_ != quick_length)
+ {
+ image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file");
+ image.message(" Cannot read the file");
+ }
+ else
+ {
+ for (i = 0; i < quick_length; i++)
+ if ((quick_addr + i) < 0x1000)
+ space.write_byte(i + quick_addr, quick_data[i]);
+
+ /* display a message about the loaded quickload */
+ if (strcmp(image.filetype(), "bin") == 0)
+ image.message(" Quickload: size=%04X : start=%04X : end=%04X : Press 6 to start",quick_length,quick_addr,quick_addr+quick_length);
+ else
+ image.message(" Quickload: size=%04X : start=%04X : end=%04X : Press 8 to start",quick_length,quick_addr,quick_addr+quick_length);
+
+ result = IMAGE_INIT_PASS;
+ }
+
+ return result;
}
/* Machine Drivers */
@@ -224,6 +325,8 @@ static MACHINE_CONFIG_START( eti660, eti660_state )
MCFG_DEVICE_ADD(MC6821_TAG, PIA6821, 0)
MCFG_PIA_READPA_HANDLER(READ8(eti660_state, pia_pa_r))
MCFG_PIA_WRITEPA_HANDLER(WRITE8(eti660_state, pia_pa_w))
+ MCFG_PIA_IRQA_HANDLER(DEVWRITELINE(CDP1802_TAG, cosmac_device, int_w)) MCFG_DEVCB_INVERT
+ MCFG_PIA_IRQB_HANDLER(DEVWRITELINE(CDP1802_TAG, cosmac_device, int_w)) MCFG_DEVCB_INVERT
MCFG_CASSETTE_ADD("cassette")
MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_MUTED)
@@ -231,6 +334,9 @@ static MACHINE_CONFIG_START( eti660, eti660_state )
/* internal ram */
MCFG_RAM_ADD(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("3K")
+
+ /* quickload */
+ MCFG_QUICKLOAD_ADD("quickload", eti660_state, eti660, "bin,c8,ch8", 2)
MACHINE_CONFIG_END
/* ROMs */
@@ -240,5 +346,5 @@ ROM_START( eti660 )
ROM_LOAD( "eti660.bin", 0x0000, 0x0400, CRC(811dfa62) SHA1(c0c4951e02f873f15560bdc3f35cdf3f99653922) )
ROM_END
-/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
-COMP( 1981, eti660, 0, 0, eti660, eti660, driver_device, 0, "Electronics Today International", "ETI-660", MACHINE_NOT_WORKING )
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+COMP( 1981, eti660, 0, 0, eti660, eti660, driver_device, 0, "Electronics Today International", "ETI-660", 0 )
diff --git a/src/mame/includes/eti660.h b/src/mame/includes/eti660.h
index 6298475d66a..0502bcd0cbd 100644
--- a/src/mame/includes/eti660.h
+++ b/src/mame/includes/eti660.h
@@ -8,6 +8,7 @@
#include "emu.h"
#include "cpu/cosmac/cosmac.h"
#include "imagedev/cassette.h"
+#include "imagedev/snapquik.h"
#include "machine/ram.h"
#include "machine/6821pia.h"
#include "machine/rescap.h"
@@ -28,28 +29,16 @@ class eti660_state : public driver_device
{
public:
eti660_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag),
- m_maincpu(*this, CDP1802_TAG),
- m_cti(*this, CDP1864_TAG),
- m_pia(*this, MC6821_TAG),
- m_cassette(*this, "cassette"),
- m_pa0(*this, "PA0"),
- m_pa1(*this, "PA1"),
- m_pa2(*this, "PA2"),
- m_pa3(*this, "PA3"),
- m_special(*this, "SPECIAL")
+ : driver_device(mconfig, type, tag)
+ , m_p_videoram(*this, "videoram")
+ , m_maincpu(*this, CDP1802_TAG)
+ , m_cti(*this, CDP1864_TAG)
+ , m_pia(*this, MC6821_TAG)
+ , m_cassette(*this, "cassette")
+ , m_io_keyboard(*this, "KEY")
+ , m_special(*this, "SPECIAL")
{ }
- required_device<cosmac_device> m_maincpu;
- required_device<cdp1864_device> m_cti;
- required_device<pia6821_device> m_pia;
- required_device<cassette_image_device> m_cassette;
- required_ioport m_pa0;
- required_ioport m_pa1;
- required_ioport m_pa2;
- required_ioport m_pa3;
- required_ioport m_special;
-
DECLARE_READ8_MEMBER( pia_r );
DECLARE_WRITE8_MEMBER( pia_w );
DECLARE_WRITE8_MEMBER( colorram_w );
@@ -63,13 +52,28 @@ public:
DECLARE_WRITE8_MEMBER( dma_w );
DECLARE_READ8_MEMBER( pia_pa_r );
DECLARE_WRITE8_MEMBER( pia_pa_w );
+ DECLARE_QUICKLOAD_LOAD_MEMBER( eti660 );
+ required_shared_ptr<UINT8> m_p_videoram;
+
+private:
+ required_device<cosmac_device> m_maincpu;
+ required_device<cdp1864_device> m_cti;
+ required_device<pia6821_device> m_pia;
+ required_device<cassette_image_device> m_cassette;
+ required_ioport_array<4> m_io_keyboard;
+ required_ioport m_special;
+
+ virtual void machine_start();
+ virtual void machine_reset();
+ UINT16 m_resetcnt;
/* keyboard state */
UINT8 m_keylatch;
/* video state */
- UINT8 m_color_ram[0x100];
+ UINT8 m_color_ram[0xc0];
UINT8 m_color;
+ bool m_color_on;
};
#endif