mirror of
https://github.com/holub/mame
synced 2025-10-06 17:08:28 +03:00
eti660: fixed various issues, marked as Working [Robbbert]
This commit is contained in:
parent
565b835ee1
commit
bc6aa6be4b
@ -1,21 +1,40 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Curt Coder
|
||||
/*
|
||||
// copyright-holders:Curt Coder, Robbbert
|
||||
/*****************************************************************************************
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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)
|
||||
|
||||
- does not boot!
|
||||
- reset key
|
||||
- allocate color ram
|
||||
- quickload
|
||||
- color on
|
||||
|
||||
- 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.
|
||||
|
||||
*/
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "includes/eti660.h"
|
||||
|
||||
@ -23,24 +42,36 @@
|
||||
|
||||
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));
|
||||
|
||||
if (colorram_offset < 0xc0)
|
||||
m_color_ram[colorram_offset] = data;
|
||||
}
|
||||
|
||||
@ -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("PA1")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2')
|
||||
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_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_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_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("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_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("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_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);
|
||||
|
||||
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;
|
||||
|
||||
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();
|
||||
for (i = 0; i < 4; i++)
|
||||
if BIT(m_keylatch, i)
|
||||
return m_io_keyboard[i]->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 )
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user