summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatarGravatar hap <happppp@users.noreply.github.com>2020-08-03 02:51:42 +0200
committerGravatarGravatar hap <happppp@users.noreply.github.com>2020-08-03 02:51:42 +0200
commit8aa49632187e4ae201aacd8316343d9f0f62d4db (patch)
treea14c926ba960a135cf20ce91f3a0cee25146711c
parenta4e8aeb12f2cd2a4b3070bff55b23a5db4eb0f70 (diff)
odyssey2: add support for 4in1 cartridge
-rw-r--r--hash/odyssey2.xml12
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--src/devices/bus/odyssey2/4in1.cpp53
-rw-r--r--src/devices/bus/odyssey2/4in1.h47
-rw-r--r--src/devices/bus/odyssey2/chess.cpp14
-rw-r--r--src/devices/bus/odyssey2/chess.h2
-rw-r--r--src/devices/bus/odyssey2/rom.cpp5
-rw-r--r--src/devices/bus/odyssey2/rom.h2
-rw-r--r--src/devices/bus/odyssey2/slot.cpp3
-rw-r--r--src/devices/bus/odyssey2/slot.h7
-rw-r--r--src/devices/bus/odyssey2/voice.cpp4
-rw-r--r--src/devices/bus/odyssey2/voice.h4
-rw-r--r--src/mame/drivers/odyssey2.cpp71
13 files changed, 152 insertions, 74 deletions
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.
</part>
</software>
- <software name="musician" supported="no">
+ <software name="musician">
<description>Musician (Euro)</description>
<year>1981</year>
<publisher>Philips</publisher>
<info name="serial" value="31"/>
<part name="cart" interface="odyssey_cart">
- <feature name="slot" value="o2_rom" />
+ <feature name="slot" value="o2_4in1" />
<dataarea name="rom" size="4096">
<rom name="musician (europe).bin" size="4096" crc="afb23f89" sha1="7445f4df9017c4d2ea94542d0db335dc18c9d7ed" offset="0" />
</dataarea>
@@ -271,25 +271,25 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM.
<!-- Games -->
- <software name="4in1" supported="no">
+ <software name="4in1">
<description>4 in 1 Row (Euro)</description>
<year>1982</year>
<publisher>Philips</publisher>
<info name="serial" value="40"/>
<part name="cart" interface="odyssey_cart">
- <feature name="slot" value="o2_rom" />
+ <feature name="slot" value="o2_4in1" />
<dataarea name="rom" size="4096">
<rom name="4 in 1 row (europe).bin" size="4096" crc="3bfef56b" sha1="e9a8996c4fb87120d8620ab8876b90ddb48335db" offset="0" />
</dataarea>
</part>
</software>
- <software name="4en1" cloneof="4in1" supported="no">
+ <software name="4en1" cloneof="4in1">
<description>4 en 1 Ligne (Fra)</description>
<year>1982</year>
<publisher>Radiola</publisher>
<part name="cart" interface="odyssey_cart">
- <feature name="slot" value="o2_rom" />
+ <feature name="slot" value="o2_4in1" />
<dataarea name="rom" size="4096">
<rom name="4 en 1 ligne (france).bin" size="4096" crc="9b5e9356" sha1="0831c3212a9e0a588a242dcd2b136e350aaceac9" offset="0" />
</dataarea>
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<o2_cart_slot_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);
}