summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/odyssey2/homecomp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/odyssey2/homecomp.cpp')
-rw-r--r--src/devices/bus/odyssey2/homecomp.cpp153
1 files changed, 118 insertions, 35 deletions
diff --git a/src/devices/bus/odyssey2/homecomp.cpp b/src/devices/bus/odyssey2/homecomp.cpp
index 23c6f6c31f7..345d9270ca9 100644
--- a/src/devices/bus/odyssey2/homecomp.cpp
+++ b/src/devices/bus/odyssey2/homecomp.cpp
@@ -9,9 +9,12 @@ be inserted into the Odyssey 2/G7000.
Hardware notes:
- Z80 @ 3.547MHz
-- 2*8KB ROM, 16KB RAM(2*TMS4416, 2 unpopulated sockets)
+- 2*8KB ROM, 16KB RAM(2*TMS4416, 2 unpopulated locations)
- optional data recorder
+The RAM can be expanded to 32KB by simply adding two more TMS4416. To enable it,
+enter command CLEAR 50,-2
+
TODO:
- lots of unacknowledged writes to latch 1, probably harmless
- cassette data saved from MAME can be loaded fine, but other WAVs can't, even
@@ -21,15 +24,57 @@ TODO:
#include "emu.h"
#include "homecomp.h"
-#include "speaker.h"
-DEFINE_DEVICE_TYPE(O2_ROM_HOMECOMP, o2_homecomp_device, "o2_homecomp", "Odyssey 2 Videopac+ C7420")
+#include "cpu/z80/z80.h"
+#include "imagedev/cassette.h"
+#include "machine/gen_latch.h"
+
+#include "speaker.h"
+namespace {
//-------------------------------------------------
-// o2_homecomp_device - constructor
+// initialization
//-------------------------------------------------
+class o2_homecomp_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_homecomp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override { return m_rom[offset]; }
+ virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0x400]; }
+
+ virtual void write_p1(u8 data) override;
+ virtual void io_write(offs_t offset, u8 data) override;
+ virtual u8 io_read(offs_t offset) override;
+ virtual int t0_read() override { return m_latch[0]->pending_r(); }
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device_array<generic_latch_8_device, 2> m_latch;
+ required_device<cassette_image_device> m_cass;
+
+ std::unique_ptr<u8[]> m_ram;
+ u8 m_control = 0;
+ bool m_installed = false;
+
+ void internal_io_w(offs_t offset, u8 data);
+ u8 internal_io_r(offs_t offset);
+ u8 internal_rom_r(offs_t offset) { return m_exrom[offset]; }
+
+ void homecomp_io(address_map &map);
+ void homecomp_mem(address_map &map);
+};
+
o2_homecomp_device::o2_homecomp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_HOMECOMP, tag, owner, clock),
device_o2_cart_interface(mconfig, *this),
@@ -41,16 +86,64 @@ o2_homecomp_device::o2_homecomp_device(const machine_config &mconfig, const char
void o2_homecomp_device::device_start()
{
save_item(NAME(m_control));
+ save_item(NAME(m_installed));
+
+ // allocate maximum RAM beforehand
+ m_ram = std::make_unique<u8[]>(0x8000);
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+void o2_homecomp_device::device_reset()
+{
+ if (!m_installed)
+ {
+ // install RAM
+ u32 ramsize = ioport("RAM")->read() ? 0x8000 : 0x4000;
+ m_maincpu->space(AS_PROGRAM).install_ram(0x8000, ramsize - 1 + 0x8000, m_ram.get());
+
+ m_installed = true;
+ }
}
void o2_homecomp_device::cart_init()
{
- if (m_rom.bytes() != 0x800 || !m_exrom || m_exrom.bytes() != 0x4000)
+ if (m_rom_size != 0x800 || m_exrom_size != 0x4000)
fatalerror("o2_homecomp_device: Wrong ROM region size\n");
}
//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+void o2_homecomp_device::write_p1(u8 data)
+{
+ // P10: Z80 INT pin
+ // P10+P11: Z80 RESET pin
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 3) ? CLEAR_LINE : ASSERT_LINE);
+
+ // P11: must be low to access latch 0
+ // P14: must be low to access latch 1
+ m_control = data;
+}
+
+u8 o2_homecomp_device::io_read(offs_t offset)
+{
+ if ((offset & 0xa0) == 0xa0 && ~m_control & 2)
+ return m_latch[0]->read();
+ else
+ return 0xff;
+}
+
+void o2_homecomp_device::io_write(offs_t offset, u8 data)
+{
+ if (offset & 0x80 && ~m_control & 0x10)
+ m_latch[1]->write(data);
+}
+
+
+//-------------------------------------------------
// internal i/o
//-------------------------------------------------
@@ -107,7 +200,6 @@ void o2_homecomp_device::internal_io_w(offs_t offset, u8 data)
void o2_homecomp_device::homecomp_mem(address_map &map)
{
map(0x0000, 0x3fff).r(FUNC(o2_homecomp_device::internal_rom_r));
- map(0x8000, 0xbfff).ram();
}
void o2_homecomp_device::homecomp_io(address_map &map)
@@ -118,6 +210,23 @@ void o2_homecomp_device::homecomp_io(address_map &map)
//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( homecomp )
+ PORT_START("RAM")
+ PORT_CONFNAME( 0x01, 0x00, "RAM Size" )
+ PORT_CONFSETTING( 0x00, "16KB" )
+ PORT_CONFSETTING( 0x01, "32KB" ) // unofficial
+INPUT_PORTS_END
+
+ioport_constructor o2_homecomp_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(homecomp);
+}
+
+
+//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -133,38 +242,12 @@ void o2_homecomp_device::device_add_mconfig(machine_config &config)
// cassette
CASSETTE(config, m_cass);
- m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_DISABLED);
+ m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_MUTED | CASSETTE_MOTOR_DISABLED);
SPEAKER(config, "cass_output").front_center(); // on data recorder
m_cass->add_route(ALL_OUTPUTS, "cass_output", 0.05);
}
+} // anonymous namespace
-//-------------------------------------------------
-// mapper specific handlers
-//-------------------------------------------------
-
-void o2_homecomp_device::write_p1(u8 data)
-{
- // P10: Z80 INT pin
- // P10+P11: Z80 RESET pin
- m_maincpu->set_input_line(INPUT_LINE_IRQ0, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
- m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 3) ? CLEAR_LINE : ASSERT_LINE);
-
- // P11: must be low to access latch 0
- // P14: must be low to access latch 1
- m_control = data;
-}
-
-u8 o2_homecomp_device::io_read(offs_t offset)
-{
- if ((offset & 0xa0) == 0xa0 && ~m_control & 2)
- return m_latch[0]->read();
- else
- return 0xff;
-}
-void o2_homecomp_device::io_write(offs_t offset, u8 data)
-{
- if (offset & 0x80 && ~m_control & 0x10)
- m_latch[1]->write(data);
-}
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_HOMECOMP, device_o2_cart_interface, o2_homecomp_device, "o2_homecomp", "Videopac+ C7420 Cartridge")