summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/eti660.c
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/mame/drivers/eti660.c
parent565b835ee137ef29e0650a3416d62719c858a07a (diff)
eti660: fixed various issues, marked as Working [Robbbert]
Diffstat (limited to 'src/mame/drivers/eti660.c')
-rw-r--r--src/mame/drivers/eti660.c210
1 files changed, 158 insertions, 52 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 )