diff options
Diffstat (limited to 'src/mess/drivers/elf.c')
-rw-r--r-- | src/mess/drivers/elf.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/mess/drivers/elf.c b/src/mess/drivers/elf.c new file mode 100644 index 00000000000..abb9660f85f --- /dev/null +++ b/src/mess/drivers/elf.c @@ -0,0 +1,336 @@ +/*************************************************************************** + + Netronics Elf II + +****************************************************************************/ + +/* + + TODO: + + - proper layout + +*/ + +#include "includes/elf.h" +#include "elf2.lh" + +#define RUN \ + BIT(ioport("SPECIAL")->read(), 0) + +#define LOAD \ + BIT(ioport("SPECIAL")->read(), 1) + +#define MEMORY_PROTECT \ + BIT(ioport("SPECIAL")->read(), 2) + +#define INPUT \ + BIT(ioport("SPECIAL")->read(), 3) + +/* Read/Write Handlers */ + +READ8_MEMBER( elf2_state::dispon_r ) +{ + m_vdc->disp_on_w(1); + m_vdc->disp_on_w(0); + + return 0xff; +} + +READ8_MEMBER( elf2_state::data_r ) +{ + return m_data; +} + +WRITE8_MEMBER( elf2_state::data_w ) +{ + m_led_l->a_w(data & 0x0f); + m_led_h->a_w(data >> 4); +} + +WRITE8_MEMBER( elf2_state::memory_w ) +{ + if (LOAD) + { + if (MEMORY_PROTECT) + { + /* latch data from memory */ + data = m_ram->pointer()[offset]; + } + else + { + /* write latched data to memory */ + m_ram->pointer()[offset] = data; + } + + /* write data to 7 segment displays */ + m_led_l->a_w(data & 0x0f); + m_led_h->a_w(data >> 4); + } +} + +/* Memory Maps */ + +static ADDRESS_MAP_START( elf2_mem, AS_PROGRAM, 8, elf2_state ) + ADDRESS_MAP_UNMAP_HIGH + ADDRESS_MAP_GLOBAL_MASK(0xff) + AM_RANGE(0x0000, 0x00ff) AM_RAMBANK("bank1") +ADDRESS_MAP_END + +static ADDRESS_MAP_START( elf2_io, AS_IO, 8, elf2_state ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x01, 0x01) AM_READ(dispon_r) + AM_RANGE(0x04, 0x04) AM_READWRITE(data_r, data_w) +ADDRESS_MAP_END + +/* Input Ports */ + +INPUT_CHANGED_MEMBER( elf2_state::input_w ) +{ + if (newval) + { + /* assert DMAIN */ + m_maincpu->set_input_line(COSMAC_INPUT_LINE_DMAIN, ASSERT_LINE); + } +} + +static INPUT_PORTS_START( elf2 ) + PORT_START("X1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("X2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("X3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("X4") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("SPECIAL") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("RUN") PORT_CODE(KEYCODE_R) PORT_TOGGLE + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LOAD") PORT_CODE(KEYCODE_L) PORT_TOGGLE + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("M/P") PORT_CODE(KEYCODE_M) PORT_TOGGLE + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("INPUT") PORT_CODE(KEYCODE_ENTER) PORT_CHANGED_MEMBER(DEVICE_SELF, elf2_state, input_w, 0) +INPUT_PORTS_END + +/* CDP1802 Configuration */ + +READ_LINE_MEMBER( elf2_state::wait_r ) +{ + return LOAD; +} + +READ_LINE_MEMBER( elf2_state::clear_r ) +{ + return RUN; +} + +READ_LINE_MEMBER( elf2_state::ef4_r ) +{ + return INPUT; +} + +static COSMAC_SC_WRITE( elf2_sc_w ) +{ + elf2_state *state = device->machine().driver_data<elf2_state>(); + + switch (sc) + { + case COSMAC_STATE_CODE_S2_DMA: + case COSMAC_STATE_CODE_S3_INTERRUPT: + /* clear DMAIN */ + state->m_maincpu->set_input_line(COSMAC_INPUT_LINE_DMAIN, CLEAR_LINE); + break; + + default: + break; + } +} + +WRITE_LINE_MEMBER( elf2_state::q_w ) +{ + output_set_led_value(0, state); +} + +READ8_MEMBER( elf2_state::dma_r ) +{ + return m_data; +} + +static COSMAC_INTERFACE( elf2_config ) +{ + DEVCB_DRIVER_LINE_MEMBER(elf2_state, wait_r), + DEVCB_DRIVER_LINE_MEMBER(elf2_state, clear_r), + DEVCB_NULL, + DEVCB_NULL, + DEVCB_NULL, + DEVCB_DRIVER_LINE_MEMBER(elf2_state, ef4_r), + DEVCB_DRIVER_LINE_MEMBER(elf2_state, q_w), + DEVCB_DRIVER_MEMBER(elf2_state, dma_r), + DEVCB_DEVICE_MEMBER(CDP1861_TAG, cdp1861_device, dma_w), + elf2_sc_w, + DEVCB_NULL, + DEVCB_NULL +}; + +/* MM74C923 Interface */ + +WRITE_LINE_MEMBER( elf2_state::da_w ) +{ + if (state) + { + /* shift keyboard data to latch */ + m_data <<= 4; + m_data |= m_kb->data_out_r() & 0x0f; + + if (LOAD) + { + /* write data to 7 segment displays */ + m_led_l->a_w(m_data & 0x0f); + m_led_h->a_w(m_data >> 4); + } + } +} + +static MM74C923_INTERFACE( keyboard_intf ) +{ + CAP_U(0.15), + CAP_U(1), + DEVCB_DRIVER_LINE_MEMBER(elf2_state, da_w), + DEVCB_INPUT_PORT("X1"), + DEVCB_INPUT_PORT("X2"), + DEVCB_INPUT_PORT("X3"), + DEVCB_INPUT_PORT("X4"), + DEVCB_NULL +}; + +/* CDP1861 Interface */ + +static CDP1861_INTERFACE( elf2_cdp1861_intf ) +{ + CDP1802_TAG, + SCREEN_TAG, + DEVCB_CPU_INPUT_LINE(CDP1802_TAG, COSMAC_INPUT_LINE_INT), + DEVCB_CPU_INPUT_LINE(CDP1802_TAG, COSMAC_INPUT_LINE_DMAOUT), + DEVCB_CPU_INPUT_LINE(CDP1802_TAG, COSMAC_INPUT_LINE_EF1) +}; + +/* Machine Initialization */ + +void elf2_state::machine_start() +{ + address_space *program = m_maincpu->memory().space(AS_PROGRAM); + + /* initialize LED displays */ + m_led_l->rbi_w(1); + m_led_h->rbi_w(1); + + /* setup memory banking */ + program->install_read_bank(0x0000, 0x00ff, "bank1"); + program->install_write_handler(0x0000, 0x00ff, write8_delegate(FUNC(elf2_state::memory_w), this)); + membank("bank1")->configure_entry(0, m_ram->pointer()); + membank("bank1")->set_entry(0); + + /* register for state saving */ + save_item(NAME(m_data)); +} + +/* Machine Driver */ + +static const cassette_interface elf_cassette_interface = +{ + cassette_default_formats, + NULL, + (cassette_state)(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_MUTED), + NULL, + NULL +}; + +static DM9368_INTERFACE( led_h_intf ) +{ + 0, + DEVCB_NULL, + DEVCB_NULL +}; + +static DM9368_INTERFACE( led_l_intf ) +{ + 1, + DEVCB_NULL, + DEVCB_NULL +}; + +static QUICKLOAD_LOAD( elf ) +{ + elf2_state *state = image.device().machine().driver_data<elf2_state>(); + + int size = image.length(); + + if (size > state->m_ram->size()) + { + return IMAGE_INIT_FAIL; + } + + image.fread(state->m_ram->pointer(), size); + + return IMAGE_INIT_PASS; +} + +static MACHINE_CONFIG_START( elf2, elf2_state ) + /* basic machine hardware */ + MCFG_CPU_ADD(CDP1802_TAG, COSMAC, XTAL_3_579545MHz/2) + MCFG_CPU_PROGRAM_MAP(elf2_mem) + MCFG_CPU_IO_MAP(elf2_io) + MCFG_CPU_CONFIG(elf2_config) + + /* video hardware */ + MCFG_DEFAULT_LAYOUT( layout_elf2 ) + + MCFG_SCREEN_ADD(SCREEN_TAG, RASTER) + MCFG_SCREEN_UPDATE_DEVICE(CDP1861_TAG, cdp1861_device, screen_update) + MCFG_SCREEN_RAW_PARAMS(XTAL_3_579545MHz/2, CDP1861_SCREEN_WIDTH, CDP1861_HBLANK_END, CDP1861_HBLANK_START, CDP1861_TOTAL_SCANLINES, CDP1861_SCANLINE_VBLANK_END, CDP1861_SCANLINE_VBLANK_START) + + MCFG_PALETTE_LENGTH(2) + MCFG_PALETTE_INIT(black_and_white) + + MCFG_MM74C923_ADD(MM74C923_TAG, keyboard_intf) + MCFG_DM9368_ADD(DM9368_H_TAG, led_h_intf) + MCFG_DM9368_ADD(DM9368_L_TAG, led_l_intf) + MCFG_CDP1861_ADD(CDP1861_TAG, XTAL_3_579545MHz/2, elf2_cdp1861_intf) + + /* devices */ + MCFG_CASSETTE_ADD(CASSETTE_TAG, elf_cassette_interface) + MCFG_QUICKLOAD_ADD("quickload", elf, "bin", 0) + + /* internal ram */ + MCFG_RAM_ADD(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("256") +MACHINE_CONFIG_END + +/* ROMs */ + +ROM_START( elf2 ) + ROM_REGION( 0x10000, CDP1802_TAG, ROMREGION_ERASE00 ) +ROM_END + +/* System Drivers */ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ +COMP( 1978, elf2, 0, 0, elf2, elf2, driver_device, 0, "Netronics", "Elf II", GAME_SUPPORTS_SAVE | GAME_NO_SOUND) |