From 8aa49632187e4ae201aacd8316343d9f0f62d4db Mon Sep 17 00:00:00 2001 From: hap Date: Mon, 3 Aug 2020 02:51:42 +0200 Subject: odyssey2: add support for 4in1 cartridge --- hash/odyssey2.xml | 12 +++---- scripts/src/bus.lua | 2 ++ src/devices/bus/odyssey2/4in1.cpp | 53 ++++++++++++++++++++++++++++ src/devices/bus/odyssey2/4in1.h | 47 +++++++++++++++++++++++++ src/devices/bus/odyssey2/chess.cpp | 14 ++++---- src/devices/bus/odyssey2/chess.h | 2 +- src/devices/bus/odyssey2/rom.cpp | 5 --- src/devices/bus/odyssey2/rom.h | 2 +- src/devices/bus/odyssey2/slot.cpp | 3 ++ src/devices/bus/odyssey2/slot.h | 7 ++-- src/devices/bus/odyssey2/voice.cpp | 4 ++- src/devices/bus/odyssey2/voice.h | 4 ++- src/mame/drivers/odyssey2.cpp | 71 +++++++++++--------------------------- 13 files changed, 152 insertions(+), 74 deletions(-) create mode 100644 src/devices/bus/odyssey2/4in1.cpp create mode 100644 src/devices/bus/odyssey2/4in1.h diff --git a/hash/odyssey2.xml b/hash/odyssey2.xml index 2cf4de54b96..fc15a63d59a 100644 --- a/hash/odyssey2.xml +++ b/hash/odyssey2.xml @@ -107,13 +107,13 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM. - + Musician (Euro) 1981 Philips - + @@ -271,25 +271,25 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM. - + 4 in 1 Row (Euro) 1982 Philips - + - + 4 en 1 Ligne (Fra) 1982 Radiola - + diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 60dbdcaed71..caee6d08d12 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1692,6 +1692,8 @@ if (BUSES["O2"]~=null) then MAME_DIR .. "src/devices/bus/odyssey2/slot.h", MAME_DIR .. "src/devices/bus/odyssey2/rom.cpp", MAME_DIR .. "src/devices/bus/odyssey2/rom.h", + MAME_DIR .. "src/devices/bus/odyssey2/4in1.cpp", + MAME_DIR .. "src/devices/bus/odyssey2/4in1.h", MAME_DIR .. "src/devices/bus/odyssey2/chess.cpp", MAME_DIR .. "src/devices/bus/odyssey2/chess.h", MAME_DIR .. "src/devices/bus/odyssey2/voice.cpp", diff --git a/src/devices/bus/odyssey2/4in1.cpp b/src/devices/bus/odyssey2/4in1.cpp new file mode 100644 index 00000000000..e1c382e7fe9 --- /dev/null +++ b/src/devices/bus/odyssey2/4in1.cpp @@ -0,0 +1,53 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/****************************************************************************** + +Videopac 40 cartridge emulation + +3KB program ROM + 1KB bankswitched data ROM + +Used in: +- #31: Musician +- #40: 4 in 1 Row + +******************************************************************************/ + +#include "emu.h" +#include "4in1.h" + + +//------------------------------------------------- +// o2_4in1_device - constructor +//------------------------------------------------- + +DEFINE_DEVICE_TYPE(O2_ROM_4IN1, o2_4in1_device, "o2_4in1", "Odyssey 2 Videopac 40") + + +o2_4in1_device::o2_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + o2_rom_device(mconfig, O2_ROM_4IN1, tag, owner, clock) +{ } + +void o2_4in1_device::device_start() +{ + save_item(NAME(m_control)); + save_item(NAME(m_bank)); +} + +void o2_4in1_device::cart_init() +{ + if (m_rom_size != 0x1000) + fatalerror("o2_4in1_device: Wrong ROM region size\n"); +} + + +//------------------------------------------------- +// mapper specific handlers +//------------------------------------------------- + +u8 o2_4in1_device::io_read(offs_t offset) +{ + if (m_control & 2) + return m_rom[m_bank << 8 | offset]; + else + return 0xff; +} diff --git a/src/devices/bus/odyssey2/4in1.h b/src/devices/bus/odyssey2/4in1.h new file mode 100644 index 00000000000..825eeb3108a --- /dev/null +++ b/src/devices/bus/odyssey2/4in1.h @@ -0,0 +1,47 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/********************************************************************** + + Videopac 40 cartridge emulation + +**********************************************************************/ + +#ifndef MAME_BUS_ODYSSEY2_4IN1_H +#define MAME_BUS_ODYSSEY2_4IN1_H + +#pragma once + +#include "slot.h" +#include "rom.h" + + +// ======================> o2_4in1_device + +class o2_4in1_device : public o2_rom_device +{ +public: + // construction/destruction + o2_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override; + + virtual void cart_init() override; + + virtual u8 read_rom04(offs_t offset) override { return m_rom[offset + 0x400]; } + virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0xc00]; } + + virtual void write_p1(u8 data) override { m_control = data; } + virtual void write_p2(u8 data) override { m_bank = data & 3; } + virtual u8 io_read(offs_t offset) override; + +private: + u8 m_control = 0; + u8 m_bank = 0; +}; + +// device type definition +DECLARE_DEVICE_TYPE(O2_ROM_4IN1, o2_4in1_device) + +#endif // MAME_BUS_ODYSSEY2_4IN1_H diff --git a/src/devices/bus/odyssey2/chess.cpp b/src/devices/bus/odyssey2/chess.cpp index 6dd254c62d1..068050a7dcd 100644 --- a/src/devices/bus/odyssey2/chess.cpp +++ b/src/devices/bus/odyssey2/chess.cpp @@ -21,7 +21,7 @@ Service manual with schematics is available. // o2_chess_device - constructor //------------------------------------------------- -DEFINE_DEVICE_TYPE(O2_ROM_CHESS, o2_chess_device, "o2_chess", "Odyssey 2 Videopac Chess Module") +DEFINE_DEVICE_TYPE(O2_ROM_CHESS, o2_chess_device, "o2_chess", "Odyssey 2 Videopac C7010") o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : @@ -78,18 +78,18 @@ void o2_chess_device::device_add_mconfig(machine_config &config) // mapper specific handlers //------------------------------------------------- -void o2_chess_device::write_bank(int bank) +void o2_chess_device::write_p1(u8 data) { - // P10: must be low to access latches + // P10,P14: must be low to access latches // P11: reset - m_cpu->set_input_line(INPUT_LINE_RESET, (bank & 2) ? CLEAR_LINE : ASSERT_LINE); + m_cpu->set_input_line(INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE); - m_control = bank; + m_control = data; } u8 o2_chess_device::io_read(offs_t offset) { - if (offset & 0x80 && offset & 0x20 && ~m_control & 1) + if ((offset & 0xa0) == 0xa0 && (m_control & 0x11) == 0) return m_latch[0]->read(); else return 0xff; @@ -97,6 +97,6 @@ u8 o2_chess_device::io_read(offs_t offset) void o2_chess_device::io_write(offs_t offset, u8 data) { - if (offset & 0x80 && ~m_control & 1) + if (offset & 0x80 && (m_control & 0x11) == 0) m_latch[1]->write(data); } diff --git a/src/devices/bus/odyssey2/chess.h b/src/devices/bus/odyssey2/chess.h index d1f6ecbfc9f..291f97e9b9d 100644 --- a/src/devices/bus/odyssey2/chess.h +++ b/src/devices/bus/odyssey2/chess.h @@ -35,7 +35,7 @@ protected: virtual u8 read_rom04(offs_t offset) override { return m_rom[offset + 0x2000]; } virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0x2000]; } - virtual void write_bank(int bank) override; + 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; diff --git a/src/devices/bus/odyssey2/rom.cpp b/src/devices/bus/odyssey2/rom.cpp index c76759c5cc5..c09969540db 100644 --- a/src/devices/bus/odyssey2/rom.cpp +++ b/src/devices/bus/odyssey2/rom.cpp @@ -63,11 +63,6 @@ void o2_rom_device::device_reset() mapper specific handlers -------------------------------------------------*/ -void o2_rom_device::write_bank(int bank) -{ - m_bank_base = bank; -} - uint8_t o2_rom_device::read_rom04(offs_t offset) { return m_rom[(offset + (m_bank_base & 0x03) * 0x800) & (m_rom_size - 1)]; diff --git a/src/devices/bus/odyssey2/rom.h b/src/devices/bus/odyssey2/rom.h index 68c63dc8e40..356b8d39b59 100644 --- a/src/devices/bus/odyssey2/rom.h +++ b/src/devices/bus/odyssey2/rom.h @@ -21,7 +21,7 @@ public: virtual uint8_t read_rom04(offs_t offset) override; virtual uint8_t read_rom0c(offs_t offset) override; - virtual void write_bank(int bank) override; + virtual void write_p1(uint8_t data) override { m_bank_base = data & 3; } protected: o2_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/devices/bus/odyssey2/slot.cpp b/src/devices/bus/odyssey2/slot.cpp index b5a2f71be67..ee814e3cc26 100644 --- a/src/devices/bus/odyssey2/slot.cpp +++ b/src/devices/bus/odyssey2/slot.cpp @@ -116,6 +116,7 @@ static const o2_slot slot_list[] = { O2_STD, "o2_rom" }, { O2_ROM12, "o2_rom12" }, { O2_ROM16, "o2_rom16" }, + { O2_4IN1, "o2_4in1" }, { O2_CHESS, "o2_chess" }, { O2_VOICE, "o2_voice" } }; @@ -250,6 +251,7 @@ uint8_t o2_cart_slot_device::io_read(offs_t offset) #include "bus/odyssey2/rom.h" +#include "bus/odyssey2/4in1.h" #include "bus/odyssey2/chess.h" #include "bus/odyssey2/voice.h" @@ -258,6 +260,7 @@ void o2_cart(device_slot_interface &device) device.option_add_internal("o2_rom", O2_ROM_STD); device.option_add_internal("o2_rom12", O2_ROM_12K); device.option_add_internal("o2_rom16", O2_ROM_16K); + device.option_add_internal("o2_4in1", O2_ROM_4IN1); device.option_add_internal("o2_chess", O2_ROM_CHESS); device.option_add_internal("o2_voice", O2_ROM_VOICE); } diff --git a/src/devices/bus/odyssey2/slot.h b/src/devices/bus/odyssey2/slot.h index cec7e2b8eb5..60151303cb8 100644 --- a/src/devices/bus/odyssey2/slot.h +++ b/src/devices/bus/odyssey2/slot.h @@ -19,6 +19,7 @@ enum O2_STD = 0, O2_ROM12, O2_ROM16, + O2_4IN1, O2_CHESS, O2_VOICE }; @@ -35,7 +36,8 @@ public: // reading and writing virtual uint8_t read_rom04(offs_t offset) { return 0xff; } virtual uint8_t read_rom0c(offs_t offset) { return 0xff; } - virtual void write_bank(int bank) { } + virtual void write_p1(uint8_t data) { } + virtual void write_p2(uint8_t data) { } virtual void io_write(offs_t offset, uint8_t data) { } virtual uint8_t io_read(offs_t offset) { return 0xff; } @@ -106,7 +108,8 @@ public: uint8_t io_read(offs_t offset); DECLARE_READ_LINE_MEMBER(t0_read) { if (m_cart) return m_cart->t0_read(); else return 0; } - void write_bank(int bank) { if (m_cart) m_cart->write_bank(bank); } + void write_p1(uint8_t data) { if (m_cart) m_cart->write_p1(data); } + void write_p2(uint8_t data) { if (m_cart) m_cart->write_p2(data); } protected: // device-level overrides diff --git a/src/devices/bus/odyssey2/voice.cpp b/src/devices/bus/odyssey2/voice.cpp index b0c93670b78..5a89e7a6160 100644 --- a/src/devices/bus/odyssey2/voice.cpp +++ b/src/devices/bus/odyssey2/voice.cpp @@ -29,6 +29,7 @@ o2_voice_device::o2_voice_device(const machine_config &mconfig, const char *tag, , m_speech(*this, "sp0256_speech") , m_subslot(*this, "subslot") , m_lrq_state(0) + , m_control(0) { } @@ -36,6 +37,7 @@ o2_voice_device::o2_voice_device(const machine_config &mconfig, const char *tag, void o2_voice_device::device_start() { save_item(NAME(m_lrq_state)); + save_item(NAME(m_control)); } @@ -88,7 +90,7 @@ WRITE_LINE_MEMBER(o2_voice_device::lrq_callback) void o2_voice_device::io_write(offs_t offset, uint8_t data) { - if (offset & 0x80) + if (offset & 0x80 && ~m_control & 0x10) { if (data & 0x20) m_speech->ald_w(offset & 0x7f); diff --git a/src/devices/bus/odyssey2/voice.h b/src/devices/bus/odyssey2/voice.h index 37ac35dcdcb..139dc7d9a78 100644 --- a/src/devices/bus/odyssey2/voice.h +++ b/src/devices/bus/odyssey2/voice.h @@ -22,7 +22,8 @@ public: virtual uint8_t read_rom04(offs_t offset) override { if (m_subslot->exists()) return m_subslot->read_rom04(offset); else return 0xff; } virtual uint8_t read_rom0c(offs_t offset) override { if (m_subslot->exists()) return m_subslot->read_rom0c(offset); else return 0xff; } - virtual void write_bank(int bank) override { if (m_subslot->exists()) m_subslot->write_bank(bank); } + virtual void write_p1(uint8_t data) override { m_control = data; if (m_subslot->exists()) m_subslot->write_p1(data); } + virtual void write_p2(uint8_t data) override { if (m_subslot->exists()) m_subslot->write_p2(data); } virtual void io_write(offs_t offset, uint8_t data) override; virtual DECLARE_READ_LINE_MEMBER(t0_read) override { return m_speech->lrq_r() ? 0 : 1; } @@ -42,6 +43,7 @@ private: required_device m_subslot; int m_lrq_state; + uint8_t m_control; }; diff --git a/src/mame/drivers/odyssey2.cpp b/src/mame/drivers/odyssey2.cpp index 798fd564d4d..bf779a38092 100644 --- a/src/mame/drivers/odyssey2.cpp +++ b/src/mame/drivers/odyssey2.cpp @@ -6,14 +6,13 @@ Driver file to handle emulation of the Odyssey2. TODO: - odyssey3 cpu/video should have different clocks -- 4in1(4 in a row)/musician needs a new mappertype to work: 3KB program ROM - and 1KB bankswitched data ROM -- backgam does not work, it only shows the background graphics +- backgamm does not work, it only shows the background graphics - chess has graphics issues near the screen borders: missing A-H at bottom, rightmost column is not erased properly, wrongly places chars at top - qbert has major graphics problems, similar to chess? - missing questionmark graphics in turtles - homecomp does not work, needs new slot device +- g7400 EF9341 R/W is connected to CPU A2, what happens if it is disobeyed? - a lot more issues, probably, this TODO list was written by someone with no knowledge on odyssey2 @@ -322,7 +321,7 @@ void odyssey2_state::machine_reset() /* jump to "last" bank, will work for all sizes due to being mirrored */ m_p1 = 0xff; m_p2 = 0xff; - m_cart->write_bank(m_p1); + m_cart->write_p1(m_p1 & 0x13); } @@ -350,18 +349,12 @@ void g7400_state::machine_reset() uint8_t odyssey2_state::io_read(offs_t offset) { - u8 data = 0; + u8 data = m_cart->io_read(offset); + if (!(m_p1 & P1_EXT_RAM_ENABLE) && ~offset & 0x80) + data &= m_ram[offset]; if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0) - { - data = m_i8244->read(offset); - } - else if (!(m_p1 & P1_EXT_RAM_ENABLE)) - { - data = m_cart->io_read(offset); - if (~offset & 0x80) - data &= m_ram[offset]; - } + data &= m_i8244->read(offset); return data; } @@ -369,37 +362,24 @@ uint8_t odyssey2_state::io_read(offs_t offset) void odyssey2_state::io_write(offs_t offset, uint8_t data) { - if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00) + if (!(m_p1 & P1_VDC_COPY_MODE_ENABLE)) { - if (~offset & 0x80) - m_ram[offset] = data; m_cart->io_write(offset, data); + if (!(m_p1 & P1_EXT_RAM_ENABLE) && ~offset & 0x80) + m_ram[offset] = data; } - else if (!(m_p1 & P1_VDC_ENABLE)) - { + + if (!(m_p1 & P1_VDC_ENABLE)) m_i8244->write(offset, data); - } } uint8_t g7400_state::io_read(offs_t offset) { - u8 data = 0; + u8 data = odyssey2_state::io_read(offset); - if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0) - { - data = m_i8244->read(offset); - } - else if (!(m_p1 & P1_EXT_RAM_ENABLE)) - { - data = m_cart->io_read(offset); - if (~offset & 0x80) - data &= m_ram[offset]; - } - else if (!(m_p1 & P1_VPP_ENABLE)) - { - data = m_ef9340_1->ef9341_read( offset & 0x02, offset & 0x01 ); - } + if (!(m_p1 & P1_VPP_ENABLE) && offset & 4) + data &= m_ef9340_1->ef9341_read( offset & 0x02, offset & 0x01 ); return data; } @@ -407,20 +387,10 @@ uint8_t g7400_state::io_read(offs_t offset) void g7400_state::io_write(offs_t offset, uint8_t data) { - if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00) - { - if (~offset & 0x80) - m_ram[offset] = data; - m_cart->io_write(offset, data); - } - else if (!(m_p1 & P1_VDC_ENABLE)) - { - m_i8244->write(offset, data); - } - else if (!(m_p1 & P1_VPP_ENABLE)) - { + odyssey2_state::io_write(offset, data); + + if (!(m_p1 & P1_VPP_ENABLE) && ~offset & 4) m_ef9340_1->ef9341_write( offset & 0x02, offset & 0x01, data ); - } } @@ -509,7 +479,7 @@ void odyssey2_state::p1_write(uint8_t data) { m_p1 = data; m_lum = ( data & 0x80 ) >> 4; - m_cart->write_bank(m_p1); + m_cart->write_p1(m_p1 & 0x13); } @@ -553,12 +523,13 @@ uint8_t odyssey2_state::p2_read() void odyssey2_state::p2_write(uint8_t data) { m_p2 = data; + m_cart->write_p2(m_p2 & 0x0f); } void g7400_state::p2_write(uint8_t data) { - m_p2 = data; + odyssey2_state::p2_write(data); m_i8243->p2_w(m_p2 & 0x0f); } -- cgit v1.2.3