From 547f4b1ac1ac8f09b9a5c4d1ee7c053ee838c81f Mon Sep 17 00:00:00 2001 From: tim lindner Date: Tue, 26 May 2020 08:42:15 -0700 Subject: [PATCH] New clones marked as WORKING mcx128 MC-10 with MCX-128 expanion [tim lindner] alice128 Alice with MCX-28 expansion [tim lindner] --- src/mame/drivers/mc10.cpp | 331 ++++++++++++++++++++++++++++++-------- src/mame/mame.lst | 2 + 2 files changed, 263 insertions(+), 70 deletions(-) diff --git a/src/mame/drivers/mc10.cpp b/src/mame/drivers/mc10.cpp index e0135aa56c3..5ac5ff873f5 100644 --- a/src/mame/drivers/mc10.cpp +++ b/src/mame/drivers/mc10.cpp @@ -1,9 +1,11 @@ // license:BSD-3-Clause -// copyright-holders:Nathan Woods, Dirk Best +// copyright-holders:Nathan Woods, Dirk Best, tim lindner /*************************************************************************** TRS-80 Radio Shack MicroColor Computer + May 2020: Added emulation for Darren Atkinson's MCX 128. + ***************************************************************************/ @@ -12,6 +14,7 @@ #include "cpu/m6800/m6801.h" #include "imagedev/cassette.h" #include "imagedev/printer.h" +#include "bus/rs232/rs232.h" #include "machine/ram.h" #include "machine/timer.h" #include "sound/dac.h" @@ -41,9 +44,12 @@ public: void alice32(machine_config &config); void mc10(machine_config &config); -private: DECLARE_READ8_MEMBER(mc10_bfff_r); DECLARE_WRITE8_MEMBER(mc10_bfff_w); + +protected: + required_device m_maincpu; + uint8_t mc10_port1_r(); void mc10_port1_w(uint8_t data); uint8_t mc10_port2_r(); @@ -54,29 +60,11 @@ private: uint8_t mc6847_videoram_r(offs_t offset); TIMER_DEVICE_CALLBACK_MEMBER(alice32_scanline); - void alice32_mem(address_map &map); - void alice90_mem(address_map &map); - void mc10_mem(address_map &map); - // device-level overrides virtual void driver_start() override; + virtual void driver_reset() override; - //printer state - enum class printer_state : uint8_t - { - WAIT, - REC, - DONE - }; - - required_device m_maincpu; - optional_device m_mc6847; - optional_device m_ef9345; - required_device m_dac; required_device m_ram; - required_device m_cassette; - required_device m_printer; - required_ioport_array<8> m_pb; required_memory_bank m_bank1; optional_memory_bank m_bank2; @@ -85,14 +73,54 @@ private: uint8_t m_keyboard_strobe; uint8_t m_port2; - // printer - uint8_t m_pr_buffer; - uint8_t m_pr_counter; - printer_state m_pr_state; - uint8_t read_keyboard_strobe(bool single_line); + +private: + void alice32_mem(address_map &map); + void alice90_mem(address_map &map); + void mc10_mem(address_map &map); + + optional_device m_mc6847; + optional_device m_ef9345; + required_device m_dac; + required_device m_cassette; + required_device m_rs232; + required_ioport_array<8> m_pb; }; +class mcx128_state : public mc10_state +{ +public: + mcx128_state(const machine_config &mconfig, device_type type, const char *tag); + void mcx128(machine_config &config); + +private: + DECLARE_READ8_MEMBER(mcx128_bf00_r); + DECLARE_WRITE8_MEMBER(mcx128_bf00_w); + + void mcx128_mem(address_map &map); + void update_mcx128_banking(); + + // device-level overrides + virtual void driver_start() override; + virtual void driver_reset() override; + + required_device m_mcx_ram; + required_memory_bank m_bank3; + required_memory_bank m_bank4r; + required_memory_bank m_bank4w; + required_memory_bank m_bank5r; + required_memory_bank m_bank5w; + required_memory_bank m_bank6r; + required_memory_bank m_bank6w; + + uint8_t *m_mcx_cart_rom_base; + uint8_t *m_mcx_int_rom_base; + uint8_t *m_mcx_ram_base; + + uint8_t m_bank_control; + uint8_t m_map_control; +}; /*************************************************************************** MEMORY MAPPED I/O @@ -145,6 +173,97 @@ WRITE8_MEMBER( mc10_state::alice32_bfff_w ) m_dac->write(BIT(data, 7)); } +/*************************************************************************** + $bf00: RAM Bank Control Register + 7 6 5 4 3 2 1 0 + | | | | | | | | + | | | | | | | +- Bank Selection for Page 0 + | | | | | | +--- Bank Selection for Page 1 + +-+-+-+-+-+----- N/C + $bf01: ROM Map Control Register + 7 6 5 4 3 2 1 0 | reading | writing | + | | | | | | | | 0 0 - 16K External ROM 16K RAM + | | | | | | | +-\_ 0 1 - 8K RAM / 8K External ROM 16K RAM + | | | | | | +---/ 1 0 - 8K RAM / 8K Internal ROM 16K RAM + | | | | | | 1 1 - 16K RAM 16K RAM + +-+-+-+-+-+--------N/C +***************************************************************************/ + +void mcx128_state::update_mcx128_banking() +{ + int32_t bank_offset_page_0 = 0x10000 * BIT(m_bank_control,0); + int32_t bank_offset_page_1 = 0x10000 * BIT(m_bank_control,1); + + // 0x0000 - 0x3fff + m_bank1->set_base(m_mcx_ram_base + bank_offset_page_0 + 0); + + // 0x4000 - 0x4fff + if( bank_offset_page_1 == 0) + m_bank2->set_base(m_ram_base); /* internal 4K when page is 0 */ + else + m_bank2->set_base(m_mcx_ram_base + bank_offset_page_1 + 0x8000); + + // 0x5000 - 0xbeff + m_bank3->set_base(m_mcx_ram_base + bank_offset_page_1 + 0x8000 + 0x1000); + + // 0xc000 - 0xdfff + m_bank4w->set_base(m_mcx_ram_base + bank_offset_page_0 + 0x4000); + + // 0xe000 - 0xfeff + m_bank5w->set_base(m_mcx_ram_base + bank_offset_page_0 + 0x6000); + + // 0xff00 - 0xffff + m_bank6w->set_base(m_mcx_ram_base + 0 + 0x7f00); /* always bank 0 */ + + switch( m_map_control ) + { + case 0: + m_bank4r->set_base(m_mcx_cart_rom_base); + m_bank5r->set_base(m_mcx_cart_rom_base + 0x2000); + m_bank6r->set_base(m_mcx_cart_rom_base + 0x3f00); + break; + + case 1: + m_bank4r->set_base(m_mcx_ram_base + bank_offset_page_0 + 0x4000); + m_bank5r->set_base(m_mcx_cart_rom_base + 0x2000 + 0x2000); + m_bank6r->set_base(m_mcx_cart_rom_base + 0x3f00 + 0x2000); + break; + + case 2: + m_bank4r->set_base(m_mcx_ram_base + bank_offset_page_0 + 0x4000); + m_bank5r->set_base(m_mcx_int_rom_base); + m_bank6r->set_base(m_mcx_int_rom_base + 0x1f00); + break; + + case 3: + m_bank4r->set_base(m_mcx_ram_base + bank_offset_page_0 + 0x4000); + m_bank5r->set_base(m_mcx_ram_base + bank_offset_page_0 + 0x6000); + m_bank6r->set_base(m_mcx_ram_base + 0 + 0x7f00); /* always bank 0 */ + break; + + default: + // can't get here + break; + } +} + +READ8_MEMBER( mcx128_state::mcx128_bf00_r ) +{ + if( (offset & 1) == 0 ) return m_bank_control; + + return m_map_control; +} + +WRITE8_MEMBER( mcx128_state::mcx128_bf00_w ) +{ + if( (offset & 1) == 0 ) + m_bank_control = data & 3; + else + m_map_control = data & 3; + + update_mcx128_banking(); +} + /*************************************************************************** MC6803 I/O @@ -171,10 +290,11 @@ uint8_t mc10_state::mc10_port2_r() if (!BIT(m_keyboard_strobe, 2)) result &= m_pb[2]->read() >> 5; if (!BIT(m_keyboard_strobe, 7)) result &= m_pb[7]->read() >> 5; - // bit 2, printer ots input - result |= (m_printer->is_ready() ? 1 : 0) << 2; + // bit 2, rs232 input + result |= (m_rs232->rxd_r() ? 1 : 0) << 2; - // bit 3, rs232 input + // bit 3, printer ots input + result |= (m_rs232->cts_r() ? 1 : 0) << 3; // bit 4, cassette input result |= (m_cassette->input() >= 0 ? 1 : 0) << 4; @@ -187,28 +307,7 @@ void mc10_state::mc10_port2_w(uint8_t data) // bit 0, cassette & printer output m_cassette->output( BIT(data, 0) ? +1.0 : -1.0); - switch (m_pr_state) - { - case printer_state::WAIT: - if (BIT(m_port2, 0) && !BIT(data, 0)) - { - m_pr_state = printer_state::REC; - m_pr_counter = 8; - m_pr_buffer = 0; - } - break; - case printer_state::REC: - if (m_pr_counter--) - m_pr_buffer |= (BIT(data,0)<<(7-m_pr_counter)); - else - m_pr_state = printer_state::DONE; - break; - case printer_state::DONE: - if (BIT(data,0)) - m_printer->output(m_pr_buffer); - m_pr_state = printer_state::WAIT; - break; - } + m_rs232->write_txd(BIT(data, 0) ? 1 : 0); m_port2 = data; } @@ -239,18 +338,36 @@ TIMER_DEVICE_CALLBACK_MEMBER(mc10_state::alice32_scanline) mc10_state::mc10_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") + , m_ram(*this, RAM_TAG) + , m_bank1(*this, "bank1") + , m_bank2(*this, "bank2") , m_mc6847(*this, "mc6847") , m_ef9345(*this, "ef9345") , m_dac(*this, "dac") - , m_ram(*this, RAM_TAG) , m_cassette(*this, "cassette") - , m_printer(*this, "printer") + , m_rs232(*this, "rs232") , m_pb(*this, "pb%u", 0) - , m_bank1(*this, "bank1") - , m_bank2(*this, "bank2") { } +mcx128_state::mcx128_state(const machine_config &mconfig, device_type type, const char *tag) + : mc10_state(mconfig, type, tag) + , m_mcx_ram(*this, "mcx_ram") + , m_bank3(*this, "bank3") + , m_bank4r(*this, "bank4r") + , m_bank4w(*this, "bank4w") + , m_bank5r(*this, "bank5r") + , m_bank5w(*this, "bank5w") + , m_bank6r(*this, "bank6r") + , m_bank6w(*this, "bank6w") +{ +} + +void mc10_state::driver_reset() +{ + /* initialize keyboard strobe */ + m_keyboard_strobe = 0x00; +} void mc10_state::driver_start() { @@ -259,14 +376,9 @@ void mc10_state::driver_start() address_space &prg = m_maincpu->space(AS_PROGRAM); - /* initialize keyboard strobe */ - m_keyboard_strobe = 0x00; - /* initialize memory */ m_ram_base = m_ram->pointer(); m_ram_size = m_ram->size(); - m_pr_state = printer_state::WAIT; - m_bank1->set_base(m_ram_base); /* initialize memory expansion */ @@ -282,14 +394,39 @@ void mc10_state::driver_start() /* register for state saving */ save_item(NAME(m_keyboard_strobe)); - save_item(NAME(m_pr_state)); - save_item(NAME(m_pr_counter)); //for alice32 force port4 DDR to 0xff at startup //if (!strcmp(machine().system().name, "alice32") || !strcmp(machine().system().name, "alice90")) //m_maincpu->m6801_io_w(prg, 0x05, 0xff); } +void mcx128_state::driver_start() +{ + // call base device_start + driver_device::driver_start(); + + /* initialize memory */ + m_ram_base = m_ram->pointer(); + m_ram_size = m_ram->size(); + + m_mcx_ram_base = m_mcx_ram->pointer(); + m_mcx_cart_rom_base = memregion("cart")->base(); + m_mcx_int_rom_base = memregion("maincpu")->base(); + + save_item(NAME(m_bank_control)); + save_item(NAME(m_map_control)); +} + +void mcx128_state::driver_reset() +{ + // call base device_start + mc10_state::driver_reset(); + + m_bank_control = 0; + m_map_control = 0; + + update_mcx128_banking(); +} /*************************************************************************** ADDRESS MAPS @@ -325,6 +462,23 @@ void mc10_state::alice90_mem(address_map &map) map(0xc000, 0xffff).rom().region("maincpu", 0x0000); /* ROM */ } +void mcx128_state::mcx128_mem(address_map &map) +{ + map(0x0000, 0x3fff).bankrw("bank1"); + map(0x4000, 0x4fff).bankrw("bank2"); + map(0x5000, 0xbeff).bankrw("bank3"); + map(0xbf00, 0xbf01).rw(FUNC(mcx128_state::mcx128_bf00_r), FUNC(mcx128_state::mcx128_bf00_w)); + map(0xbf02, 0xbf7f).noprw(); /* unused */ + map(0xbf80, 0xbffe).noprw(); /* unused */ + map(0xbfff, 0xbfff).rw(FUNC(mc10_state::mc10_bfff_r), FUNC(mc10_state::mc10_bfff_w)); + map(0xc000, 0xdfff).bankr("bank4r"); + map(0xc000, 0xdfff).bankw("bank4w"); + map(0xe000, 0xfeff).bankr("bank5r"); + map(0xe000, 0xfeff).bankw("bank5w"); + map(0xff00, 0xffff).bankr("bank6r"); + map(0xff00, 0xffff).bankw("bank6w"); +} + /*************************************************************************** INPUT PORTS ***************************************************************************/ @@ -498,6 +652,14 @@ INPUT_PORTS_START( alice ) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) INPUT_PORTS_END +static DEVICE_INPUT_DEFAULTS_START( printer ) + DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_600 ) + DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 ) + DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 ) + DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE ) + DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 ) +DEVICE_INPUT_DEFAULTS_END + /*************************************************************************** MACHINE DRIVERS ***************************************************************************/ @@ -532,7 +694,8 @@ void mc10_state::mc10(machine_config &config) m_cassette->set_interface("mc10_cass"); /* printer */ - PRINTER(config, m_printer, 0); + rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "printer")); + rs232.set_option_device_input_defaults("printer", DEVICE_INPUT_DEFAULTS_NAME(printer)); /* internal ram */ RAM(config, m_ram).set_default_size("20K").set_extra_options("4K"); @@ -575,7 +738,8 @@ void mc10_state::alice32(machine_config &config) m_cassette->set_interface("mc10_cass"); /* printer */ - PRINTER(config, m_printer, 0); + rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "printer")); + rs232.set_option_device_input_defaults("printer", DEVICE_INPUT_DEFAULTS_NAME(printer)); /* internal ram */ RAM(config, m_ram).set_default_size("24K").set_extra_options("8K"); @@ -598,6 +762,17 @@ void mc10_state::alice90(machine_config &config) config.device_remove("mc10_cass"); } +void mcx128_state::mcx128(machine_config &config) +{ + mc10(config); + m_maincpu->set_addrmap(AS_PROGRAM, &mcx128_state::mcx128_mem); + + /* internal ram */ + m_ram->set_default_size("4K"); + RAM(config, m_mcx_ram).set_default_size("128K"); + + /* Software lists */ + /* to do */ } @@ -631,14 +806,30 @@ ROM_START( alice90 ) ROM_LOAD( "charset.rom", 0x0000, 0x2000, BAD_DUMP CRC(b2f49eb3) SHA1(d0ef530be33bfc296314e7152302d95fdf9520fc) ) // from dcvg5k ROM_END -ALLOW_SAVE_TYPE(mc10_state::printer_state); +ROM_START( mcx128 ) + ROM_REGION(0x2000, "maincpu", 0) + ROM_LOAD("mc10.rom", 0x0000, 0x2000, CRC(11fda97e) SHA1(4afff2b4c120334481aab7b02c3552bf76f1bc43)) + ROM_REGION(0x4000, "cart", 0) + ROM_LOAD("mcx128bas.rom", 0x0000, 0x4000, CRC(11202e4b) SHA1(36c30d0f198a1bffee88ef29d92f2401447a91f4)) +ROM_END + +ROM_START( alice128 ) + ROM_REGION(0x2000, "maincpu", 0) + ROM_LOAD("alice.rom", 0x0000, 0x2000, CRC(f876abe9) SHA1(c2166b91e6396a311f486832012aa43e0d2b19f8)) + ROM_REGION(0x4000, "cart", 0) + ROM_LOAD("alice128bas.rom", 0x0000, 0x4000, CRC(a737544a) SHA1(c8fd92705fc42deb6a0ffac6274e27fd61ecd4cc)) +ROM_END + +} /*************************************************************************** GAME DRIVERS ***************************************************************************/ -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1983, mc10, 0, 0, mc10, mc10, mc10_state, empty_init, "Tandy Radio Shack", "MC-10", MACHINE_SUPPORTS_SAVE ) -COMP( 1983, alice, mc10, 0, mc10, alice, mc10_state, empty_init, "Matra & Hachette", "Alice", MACHINE_SUPPORTS_SAVE ) -COMP( 1984, alice32, 0, 0, alice32, alice, mc10_state, empty_init, "Matra & Hachette", "Alice 32", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) -COMP( 1985, alice90, alice32, 0, alice90, alice, mc10_state, empty_init, "Matra & Hachette", "Alice 90", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1983, mc10, 0, 0, mc10, mc10, mc10_state, empty_init, "Tandy Radio Shack", "MC-10", MACHINE_SUPPORTS_SAVE ) +COMP( 1983, alice, mc10, 0, mc10, alice, mc10_state, empty_init, "Matra & Hachette", "Alice", MACHINE_SUPPORTS_SAVE ) +COMP( 1984, alice32, 0, 0, alice32, alice, mc10_state, empty_init, "Matra & Hachette", "Alice 32", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) +COMP( 1985, alice90, alice32, 0, alice90, alice, mc10_state, empty_init, "Matra & Hachette", "Alice 90", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) +COMP( 2011, mcx128, mc10, 0, mcx128, mc10, mcx128_state, empty_init, "Tandy Radio Shack", "MCX-128", MACHINE_SUPPORTS_SAVE | MACHINE_UNOFFICIAL ) +COMP( 2011, alice128,mc10, 0, mcx128, alice, mcx128_state, empty_init, "Matra & Hachette", "Alice with MCX-128", MACHINE_SUPPORTS_SAVE | MACHINE_UNOFFICIAL ) \ No newline at end of file diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 01a861e6cdc..5b9c9918df2 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -21865,6 +21865,8 @@ alice // Matra & Hachette Ordinateur Alice alice32 // Matra & Hachette Alice 32 alice90 // Matra & Hachette Alice 90 mc10 // MC-10 +mcx128 // MCX-128 +alice128 // Alice with a MCX-128 @source:mc1000.cpp mc1000 //