From 958e912777148c72fab7cd84e3e8db7354cbd072 Mon Sep 17 00:00:00 2001 From: arbee Date: Thu, 8 Jun 2023 20:37:09 -0400 Subject: apple/apple2.cpp: added Apple ROM/Firmware card with 3 options: Applesoft, Integer, and User-Defined. [R. Belmont] * Use "-rom file.bin" with the user-defined ROM card to make your own custom Apple. File must be 12KiB and goes in D0/D8/E0/E8/F0/F8 order. a2bus: wire up a method to assert the reset line on the slots. This is important for the ROM card. [R. Belmont] apple/apple2.cpp,apple2e.cpp,apple2gs.cpp,apple3.cpp: Reset the a2bus when the 6502/65816 is reset. [R. Belmont] apple/apple2gs.cpp: Reset the softswitches like a IIe on Control-Reset. [R. Belmont] apple/apple3.cpp: Now has the same Control-Reset behavior improvements as the Apple IIs. [R. Belmont] --- scripts/src/bus.lua | 2 + src/devices/bus/a2bus/a2bus.cpp | 12 ++ src/devices/bus/a2bus/a2bus.h | 2 + src/devices/bus/a2bus/cards.cpp | 26 ++-- src/devices/bus/a2bus/romcard.cpp | 273 ++++++++++++++++++++++++++++++++++++++ src/devices/bus/a2bus/romcard.h | 23 ++++ src/mame/apple/apple2.cpp | 70 +++++----- src/mame/apple/apple2e.cpp | 2 + src/mame/apple/apple2gs.cpp | 21 +++ src/mame/apple/apple3_m.cpp | 16 ++- 10 files changed, 401 insertions(+), 46 deletions(-) create mode 100644 src/devices/bus/a2bus/romcard.cpp create mode 100644 src/devices/bus/a2bus/romcard.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 0f8ada2b828..59d5daa9e5d 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2856,6 +2856,8 @@ if (BUSES["A2BUS"]~=null) then MAME_DIR .. "src/devices/bus/a2bus/ramcard128k.h", MAME_DIR .. "src/devices/bus/a2bus/ramcard16k.cpp", MAME_DIR .. "src/devices/bus/a2bus/ramcard16k.h", + MAME_DIR .. "src/devices/bus/a2bus/romcard.cpp", + MAME_DIR .. "src/devices/bus/a2bus/romcard.h", MAME_DIR .. "src/devices/bus/a2bus/sider.cpp", MAME_DIR .. "src/devices/bus/a2bus/sider.h", MAME_DIR .. "src/devices/bus/a2bus/softcard3.cpp", diff --git a/src/devices/bus/a2bus/a2bus.cpp b/src/devices/bus/a2bus/a2bus.cpp index 026e0060445..e8e8a973e99 100644 --- a/src/devices/bus/a2bus/a2bus.cpp +++ b/src/devices/bus/a2bus/a2bus.cpp @@ -197,6 +197,18 @@ void a2bus_device::add_a2bus_card(int slot, device_a2bus_card_interface *card) m_device_list[slot] = card; } +void a2bus_device::reset_bus() +{ + for (int slot = 0; slot <= 7; slot++) + { + auto card = get_a2bus_card(slot); + if (card != nullptr) + { + card->bus_reset(); + } + } +} + uint8_t a2bus_device::get_a2bus_irq_mask() { return m_slot_irq_mask; diff --git a/src/devices/bus/a2bus/a2bus.h b/src/devices/bus/a2bus/a2bus.h index 2d4b523fa2a..f838d865073 100644 --- a/src/devices/bus/a2bus/a2bus.h +++ b/src/devices/bus/a2bus/a2bus.h @@ -98,6 +98,7 @@ public: void recalc_inh(int slot); uint8_t dma_r(uint16_t offset); void dma_w(uint16_t offset, uint8_t data); + void reset_bus(); void irq_w(int state); void nmi_w(int state); @@ -151,6 +152,7 @@ public: virtual uint16_t inh_end() { return INH_END_INVALID; } virtual bool inh_check(uint16_t offset, bool bIsWrite) { return false; } virtual int inh_type() { return INH_NONE; } + virtual void bus_reset() { } device_a2bus_card_interface *next() const { return m_next; } diff --git a/src/devices/bus/a2bus/cards.cpp b/src/devices/bus/a2bus/cards.cpp index 40668bb9882..10357935263 100644 --- a/src/devices/bus/a2bus/cards.cpp +++ b/src/devices/bus/a2bus/cards.cpp @@ -21,6 +21,7 @@ #include "a2diskiing.h" #include "a2dx1.h" #include "a2echoii.h" +#include "a2hsscsi.h" #include "a2iwm.h" #include "a2mcms.h" #include "a2memexp.h" @@ -30,6 +31,7 @@ #include "a2pic.h" #include "a2sam.h" #include "a2scsi.h" +#include "a2sd.h" #include "a2softcard.h" #include "a2ssc.h" #include "a2superdrive.h" @@ -38,43 +40,45 @@ #include "a2thunderclock.h" #include "a2ultraterm.h" #include "a2videoterm.h" +#include "a2vulcan.h" #include "a2zipdrive.h" +#include "booti.h" #include "byte8251.h" #include "computereyes2.h" #include "ccs7710.h" +#include "cmsscsi.h" #include "excel9.h" #include "ezcgi.h" #include "grafex.h" #include "grappler.h" +#include "lancegs.h" #include "laser128.h" #include "mouse.h" +#include "pc_xporter.h" #include "prodosromdrive.h" #include "ramcard128k.h" #include "ramcard16k.h" +#include "romcard.h" +#include "sider.h" +#include "softcard3.h" #include "ssbapple.h" #include "ssprite.h" #include "suprterminal.h" #include "timemasterho.h" +#include "titan3plus2.h" #include "transwarp.h" #include "uniprint.h" -#include "booti.h" -#include "q68.h" -#include "pc_xporter.h" -#include "cmsscsi.h" -#include "a2vulcan.h" #include "uthernet.h" -#include "a2hsscsi.h" -#include "a2sd.h" -#include "sider.h" -#include "lancegs.h" -#include "titan3plus2.h" -#include "softcard3.h" +#include "q68.h" void apple2_slot0_cards(device_slot_interface &device) { device.option_add("lang", A2BUS_RAMCARD16K); // Apple II RAM Language Card device.option_add("ssram", A2BUS_RAMCARD128K); // Saturn Systems 128K extended language card + device.option_add("romcard", A2BUS_ROMCARDUSER); // Apple II ROM Card that loads a custom ROM image + device.option_add("romcardfp", A2BUS_ROMCARDFP); // Apple II ROM Card with Autostart Monitor + Applesoft BASIC + device.option_add("romcardint", A2BUS_ROMCARDINT); // Apple II ROM Card with Autostart Monitor + Integer BASIC } void apple2_cards(device_slot_interface &device) diff --git a/src/devices/bus/a2bus/romcard.cpp b/src/devices/bus/a2bus/romcard.cpp new file mode 100644 index 00000000000..66137234077 --- /dev/null +++ b/src/devices/bus/a2bus/romcard.cpp @@ -0,0 +1,273 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************* + + romcard.cpp + + Implemention of the Apple II ROM card. This is like a language + card, but with 12K instead of 16K, and ROM instead of RAM. + + Apple at various points called it both "ROM Card" and + "Firmware Card", + +*********************************************************************/ + +#include "a2bus.h" +#include "romcard.h" +#include + +namespace { + +class a2bus_romcard_device: + public device_t, + public device_a2bus_card_interface +{ +public: + a2bus_romcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void bus_reset() override; + virtual ioport_constructor device_input_ports() const override; + + // overrides of standard a2bus slot functions + virtual uint8_t read_c0nx(uint8_t offset) override; + virtual void write_c0nx(uint8_t offset, uint8_t data) override; + virtual uint8_t read_inh_rom(uint16_t offset) override; + virtual void write_inh_rom(uint16_t offset, uint8_t data) override; + virtual uint16_t inh_start() override { return 0xd000; } + virtual uint16_t inh_end() override { return 0xffff; } + virtual int inh_type() override; + +protected: + u8 *m_rom; + required_ioport m_config; + +private: + void do_io(int offset); + + int m_inh_state; +}; + +class a2bus_romcardfp_device: public a2bus_romcard_device +{ +public: + a2bus_romcardfp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; +}; + +class a2bus_romcardint_device: public a2bus_romcard_device +{ +public: + a2bus_romcardint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; +}; + +class a2bus_romcarduser_device: public a2bus_romcard_device, public device_image_interface +{ +public: + a2bus_romcarduser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_image_interface overrides + virtual std::pair call_load() override; + + virtual bool is_readable() const noexcept override { return true; } + virtual bool is_writeable() const noexcept override { return false; } + virtual bool is_creatable() const noexcept override { return false; } + virtual bool is_reset_on_load() const noexcept override { return false; } + virtual const char *file_extensions() const noexcept override { return "bin,rom"; } + virtual const char *image_type_name() const noexcept override { return "romimage"; } + virtual const char *image_brief_type_name() const noexcept override { return "rom"; } + +protected: +}; + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +ROM_START( romcardfp ) + ROM_REGION(0x3000, "romcard", 0) + ROM_LOAD ( "341-0011.d0", 0x0000, 0x0800, CRC(6f05f949) SHA1(0287ebcef2c1ce11dc71be15a99d2d7e0e128b1e)) + ROM_LOAD ( "341-0012.d8", 0x0800, 0x0800, CRC(1f08087c) SHA1(a75ce5aab6401355bf1ab01b04e4946a424879b5)) + ROM_LOAD ( "341-0013.e0", 0x1000, 0x0800, CRC(2b8d9a89) SHA1(8d82a1da63224859bd619005fab62c4714b25dd7)) + ROM_LOAD ( "341-0014.e8", 0x1800, 0x0800, CRC(5719871a) SHA1(37501be96d36d041667c15d63e0c1eff2f7dd4e9)) + ROM_LOAD ( "341-0015.f0", 0x2000, 0x0800, CRC(9a04eecf) SHA1(e6bf91ed28464f42b807f798fc6422e5948bf581)) + ROM_LOAD ( "341-0020-00.f8", 0x2800, 0x0800, CRC(079589c4) SHA1(a28852ff997b4790e53d8d0352112c4b1a395098)) +ROM_END + +ROM_START( romcardint ) + ROM_REGION(0x3000, "romcard", 0) + ROM_LOAD ( "341-0001-00.e0", 0x1000, 0x0800, CRC(c0a4ad3b) SHA1(bf32195efcb34b694c893c2d342321ec3a24b98f)) + ROM_LOAD ( "341-0002-00.e8", 0x1800, 0x0800, CRC(a99c2cf6) SHA1(9767d92d04fc65c626223f25564cca31f5248980)) + ROM_LOAD ( "341-0003-00.f0", 0x2000, 0x0800, CRC(62230d38) SHA1(f268022da555e4c809ca1ae9e5d2f00b388ff61c)) + ROM_LOAD ( "341-0020-00.f8", 0x2800, 0x0800, CRC(079589c4) SHA1(a28852ff997b4790e53d8d0352112c4b1a395098)) +ROM_END + +static INPUT_PORTS_START( romcard ) + PORT_START("CONFIG") + PORT_CONFNAME(0x01, 0x00, "Enable at boot") + PORT_CONFSETTING(0x00, DEF_STR(No)) + PORT_CONFSETTING(0x01, DEF_STR(Yes)) +INPUT_PORTS_END + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +a2bus_romcard_device::a2bus_romcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_a2bus_card_interface(mconfig, *this), + m_rom(nullptr), + m_config(*this, "CONFIG"), + m_inh_state(0) +{ +} + +a2bus_romcardfp_device::a2bus_romcardfp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + a2bus_romcard_device(mconfig, A2BUS_ROMCARDFP, tag, owner, clock) +{ +} + +a2bus_romcardint_device::a2bus_romcardint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + a2bus_romcard_device(mconfig, A2BUS_ROMCARDINT, tag, owner, clock) +{ +} + +a2bus_romcarduser_device::a2bus_romcarduser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + a2bus_romcard_device(mconfig, A2BUS_ROMCARDUSER, tag, owner, clock), + device_image_interface(mconfig, *this) +{ +} + +const tiny_rom_entry *a2bus_romcardfp_device::device_rom_region() const +{ + return ROM_NAME( romcardfp ); +} + +const tiny_rom_entry *a2bus_romcardint_device::device_rom_region() const +{ + return ROM_NAME( romcardint ); +} + +ioport_constructor a2bus_romcard_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( romcard ); +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void a2bus_romcard_device::device_start() +{ + save_item(NAME(m_inh_state)); +} + +void a2bus_romcardfp_device::device_start() +{ + m_rom = device().machine().root_device().memregion(this->subtag("romcard"))->base(); + a2bus_romcard_device::device_start(); +} + +void a2bus_romcardint_device::device_start() +{ + m_rom = device().machine().root_device().memregion(this->subtag("romcard"))->base(); + a2bus_romcard_device::device_start(); +} + +void a2bus_romcard_device::bus_reset() +{ + if ((m_config->read() == 1) && (m_rom != nullptr)) + { + m_inh_state = INH_READ; + } + else + { + m_inh_state = 0; + } + recalc_slot_inh(); +} + +void a2bus_romcard_device::do_io(int offset) +{ + int old_inh_state = m_inh_state; + + // any even access enables ROM reading + if (((offset & 1) == 1) && (m_rom != nullptr)) + { + m_inh_state |= INH_READ; + } + else + { + m_inh_state &= ~INH_READ; + } + + if (m_inh_state != old_inh_state) + { + recalc_slot_inh(); + } +} + + +/*------------------------------------------------- + read_c0nx - called for reads from this card's c0nx space +-------------------------------------------------*/ + +uint8_t a2bus_romcard_device::read_c0nx(uint8_t offset) +{ + do_io(offset & 0xf); + return 0xff; +} + + +/*------------------------------------------------- + write_c0nx - called for writes to this card's c0nx space +-------------------------------------------------*/ + +void a2bus_romcard_device::write_c0nx(uint8_t offset, uint8_t data) +{ + do_io(offset & 0xf); +} + +uint8_t a2bus_romcard_device::read_inh_rom(uint16_t offset) +{ + assert(m_inh_state & INH_READ); // this should never happen + return m_rom[offset-0xd000]; +} + +void a2bus_romcard_device::write_inh_rom(uint16_t offset, uint8_t data) +{ +} + +int a2bus_romcard_device::inh_type() +{ + return m_inh_state; +} + +std::pair a2bus_romcarduser_device::call_load() +{ + if (is_open()) + { + m_rom = (u8 *)malloc(12*1024*1024); + fread(m_rom, 12*1024*1024); + } + else + { + return std::make_pair(std::error_condition(ENOENT, std::generic_category()), std::string()); + } + return std::make_pair(std::error_condition(), std::string()); +} + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ROMCARDUSER, device_a2bus_card_interface, a2bus_romcarduser_device, "a2romusr", "Apple II ROM Card (Custom)") +DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ROMCARDFP, device_a2bus_card_interface, a2bus_romcardfp_device, "a2romfp", "Apple II ROM Card (Applesoft BASIC)") +DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ROMCARDINT, device_a2bus_card_interface, a2bus_romcardint_device, "a2romint", "Apple II ROM Card (Integer BASIC))") diff --git a/src/devices/bus/a2bus/romcard.h b/src/devices/bus/a2bus/romcard.h new file mode 100644 index 00000000000..8ff831d13e2 --- /dev/null +++ b/src/devices/bus/a2bus/romcard.h @@ -0,0 +1,23 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************* + + romcard.h + + Implemention of the Apple II ROM card/firmware card + +*********************************************************************/ + +#ifndef MAME_BUS_A2BUS_ROMCARD_H +#define MAME_BUS_A2BUS_ROMCARD_H + +#pragma once + +#include "a2bus.h" + +// device type definition +DECLARE_DEVICE_TYPE(A2BUS_ROMCARDUSER, device_a2bus_card_interface) +DECLARE_DEVICE_TYPE(A2BUS_ROMCARDFP, device_a2bus_card_interface) +DECLARE_DEVICE_TYPE(A2BUS_ROMCARDINT, device_a2bus_card_interface) + +#endif // MAME_BUS_A2BUS_ROMCARD_H diff --git a/src/mame/apple/apple2.cpp b/src/mame/apple/apple2.cpp index 4cb076c027d..0888ba3019d 100644 --- a/src/mame/apple/apple2.cpp +++ b/src/mame/apple/apple2.cpp @@ -322,6 +322,13 @@ void apple2_state::machine_reset() m_inh_slot = 0; m_cnxx_slot = -1; m_anykeydown = false; + + // reset the cards + m_a2bus->reset_bus(); + // reset the 6502 now as a card may have pulled /INH on the reset vector + printf("machine_reset\n"); + m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); } /*************************************************************************** @@ -335,52 +342,47 @@ TIMER_DEVICE_CALLBACK_MEMBER(apple2_state::apple2_interrupt) if (scanline == 192) { // check reset - if (m_resetdip.found()) // if reset DIP is present, use it + if ((m_resetdip.found()) && (m_resetdip->read() & 1)) // if reset DIP is present, use it { - if (m_resetdip->read() & 1) - { // CTRL-RESET - if ((m_kbspecial->read() & 0x88) == 0x88) - { - if (!m_reset_latch) - { - m_reset_latch = true; - m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - } - } - else + // CTRL-RESET + if ((m_kbspecial->read() & 0x88) == 0x88) + { + if (!m_reset_latch) { - if (m_reset_latch) - { - m_reset_latch = false; - m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - } + m_reset_latch = true; + m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); } } - else // plain RESET + else { - if (m_kbspecial->read() & 0x80) - { - if (!m_reset_latch) - { - m_reset_latch = true; - m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - } - } - else + if (m_reset_latch) { - if (m_reset_latch) - { - m_reset_latch = false; - m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - } + m_reset_latch = false; + // allow cards to see reset + m_a2bus->reset_bus(); + m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); } } } - else // no DIP, so always plain RESET + else // plain RESET { if (m_kbspecial->read() & 0x80) { - m_maincpu->reset(); + if (!m_reset_latch) + { + m_reset_latch = true; + m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + } + } + else + { + if (m_reset_latch) + { + m_reset_latch = false; + // allow cards to see reset + m_a2bus->reset_bus(); + m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + } } } } diff --git a/src/mame/apple/apple2e.cpp b/src/mame/apple/apple2e.cpp index f9431c88471..7394681e6b8 100644 --- a/src/mame/apple/apple2e.cpp +++ b/src/mame/apple/apple2e.cpp @@ -1346,6 +1346,8 @@ TIMER_DEVICE_CALLBACK_MEMBER(apple2e_state::apple2_interrupt) if (m_reset_latch) { m_reset_latch = false; + // allow cards to see reset + m_a2bus->reset_bus(); m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); } } diff --git a/src/mame/apple/apple2gs.cpp b/src/mame/apple/apple2gs.cpp index d0d0fdd47ad..272dea42b08 100644 --- a/src/mame/apple/apple2gs.cpp +++ b/src/mame/apple/apple2gs.cpp @@ -893,6 +893,9 @@ void apple2gs_state::machine_reset() auxbank_update(); update_slotrom_banks(); + // reset the slots + m_a2bus->reset_bus(); + // with all the banking reset, now reset the CPU m_maincpu->reset(); @@ -3385,8 +3388,26 @@ void apple2gs_state::adbmicro_p2_out(u8 data) if (!BIT(data, 5) && BIT(m_adb_p2_last, 5)) { m_adb_reset_freeze = 2; + m_a2bus->reset_bus(); m_maincpu->reset(); m_video->set_newvideo(0x41); + + m_lcram = false; + m_lcram2 = true; + m_lcprewrite = false; + m_lcwriteenable = true; + m_intcxrom = false; + m_slotc3rom = false; + m_video->a80store_w(false); + m_altzp = false; + m_ramrd = false; + m_ramwrt = false; + m_altzp = false; + m_video->page2_w(false); + m_video->res_w(0); + + auxbank_update(); + update_slotrom_banks(); } if (!(data & 0x10)) diff --git a/src/mame/apple/apple3_m.cpp b/src/mame/apple/apple3_m.cpp index 99f92f879a6..98aaddf8df2 100644 --- a/src/mame/apple/apple3_m.cpp +++ b/src/mame/apple/apple3_m.cpp @@ -1127,7 +1127,21 @@ TIMER_CALLBACK_MEMBER(apple3_state::scanend_cb) // check for ctrl-reset if ((m_kbspecial->read() & 0x88) == 0x88) { - m_maincpu->reset(); + if (!m_reset_latch) + { + m_reset_latch = true; + m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + } + } + else + { + if (m_reset_latch) + { + m_reset_latch = false; + // allow cards to see reset + m_a2bus->reset_bus(); + m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + } } } -- cgit v1.2.3