diff --git a/hash/odyssey2.xml b/hash/odyssey2.xml
index 6ad3ec9995f..c5d3b1203d8 100644
--- a/hash/odyssey2.xml
+++ b/hash/odyssey2.xml
@@ -83,7 +83,7 @@ adds 16K RAM and 16K ROM, that plugs into the G7000.
-
+
Home Computer Module (Euro)
1983
Philips
@@ -92,7 +92,7 @@ adds 16K RAM and 16K ROM, that plugs into the G7000.
-
+
@@ -545,15 +545,16 @@ adds 16K RAM and 16K ROM, that plugs into the G7000.
-
+
Chess Module (Euro)
1982
Philips
-
-
+
+
+
diff --git a/src/devices/bus/odyssey2/chess.cpp b/src/devices/bus/odyssey2/chess.cpp
index e8226a4d3be..f1a871f1000 100644
--- a/src/devices/bus/odyssey2/chess.cpp
+++ b/src/devices/bus/odyssey2/chess.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:hap
/******************************************************************************
Videopac C7010 Chess Module emulation
@@ -11,10 +11,6 @@ Hardware notes:
Service manual with schematics is available.
-TODO:
-- this code is just a stub... hence, almost everything is still to do!
- most importantly, missing 8KB ROM dump
-
******************************************************************************/
#include "emu.h"
@@ -28,22 +24,38 @@ TODO:
DEFINE_DEVICE_TYPE(O2_ROM_CHESS, o2_chess_device, "o2_chess", "Odyssey 2 Videopac Chess Module")
-o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : o2_rom_device(mconfig, O2_ROM_CHESS, tag, owner, clock)
- , m_cpu(*this, "subcpu")
+o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ o2_rom_device(mconfig, O2_ROM_CHESS, tag, owner, clock),
+ m_cpu(*this, "subcpu"),
+ m_latch(*this, "latch%u", 0)
+{ }
+
+void o2_chess_device::device_start()
{
+ save_item(NAME(m_control));
+}
+
+void o2_chess_device::cart_init()
+{
+ if (m_rom_size != 0x2800)
+ fatalerror("o2_chess_device: Wrong ROM region size\n");
}
+//-------------------------------------------------
+// address maps
+//-------------------------------------------------
+
void o2_chess_device::chess_mem(address_map &map)
{
- map(0x0000, 0x07ff).r(FUNC(o2_chess_device::read_rom04));
+ map(0x0000, 0x1fff).r(FUNC(o2_chess_device::internal_rom_r));
+ map(0xe000, 0xe7ff).mirror(0x1800).ram();
}
void o2_chess_device::chess_io(address_map &map)
{
- map.unmap_value_high();
- map.global_mask(0xff);
+ map.global_mask(0x01);
+ map(0x00, 0x01).r(m_latch[1], FUNC(generic_latch_8_device::read)).w(m_latch[0], FUNC(generic_latch_8_device::write));
}
@@ -56,4 +68,35 @@ void o2_chess_device::device_add_mconfig(machine_config &config)
NSC800(config, m_cpu, 4.433619_MHz_XTAL);
m_cpu->set_addrmap(AS_PROGRAM, &o2_chess_device::chess_mem);
m_cpu->set_addrmap(AS_IO, &o2_chess_device::chess_io);
+
+ GENERIC_LATCH_8(config, m_latch[0]);
+ GENERIC_LATCH_8(config, m_latch[1]);
+}
+
+
+//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+void o2_chess_device::write_bank(int bank)
+{
+ // P10: must be low to access latches
+ // P11: reset
+ m_cpu->set_input_line(INPUT_LINE_RESET, (bank & 2) ? CLEAR_LINE : ASSERT_LINE);
+
+ m_control = bank;
+}
+
+u8 o2_chess_device::io_read(offs_t offset)
+{
+ if (offset & 0x80 && offset & 0x20 && ~m_control & 1)
+ return m_latch[0]->read();
+ else
+ return 0xff;
+}
+
+void o2_chess_device::io_write(offs_t offset, u8 data)
+{
+ if (offset & 0x80 && ~m_control & 1)
+ m_latch[1]->write(data);
}
diff --git a/src/devices/bus/odyssey2/chess.h b/src/devices/bus/odyssey2/chess.h
index da8bee54b9d..d1f6ecbfc9f 100644
--- a/src/devices/bus/odyssey2/chess.h
+++ b/src/devices/bus/odyssey2/chess.h
@@ -1,5 +1,11 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:hap
+/**********************************************************************
+
+ Videopac C7010 Chess Module emulation
+
+**********************************************************************/
+
#ifndef MAME_BUS_ODYSSEY2_CHESS_H
#define MAME_BUS_ODYSSEY2_CHESS_H
@@ -8,6 +14,7 @@
#include "slot.h"
#include "rom.h"
#include "cpu/z80/z80.h"
+#include "machine/gen_latch.h"
// ======================> o2_chess_device
@@ -19,14 +26,29 @@ public:
o2_chess_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 device_add_mconfig(machine_config &config) override;
-// virtual const rom_entry *device_rom_region() const;
+
+ virtual void cart_init() override;
+
+ 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 io_write(offs_t offset, u8 data) override;
+ virtual u8 io_read(offs_t offset) override;
private:
required_device m_cpu;
+ required_device_array m_latch;
+
+ u8 internal_rom_r(offs_t offset) { return m_rom[offset]; }
void chess_io(address_map &map);
void chess_mem(address_map &map);
+
+ u8 m_control = 0;
};
// device type definition
diff --git a/src/devices/bus/odyssey2/slot.cpp b/src/devices/bus/odyssey2/slot.cpp
index 3b743b6964b..b5a2f71be67 100644
--- a/src/devices/bus/odyssey2/slot.cpp
+++ b/src/devices/bus/odyssey2/slot.cpp
@@ -174,7 +174,7 @@ image_init_result o2_cart_slot_device::call_load()
m_type = o2_get_pcb_id(pcb_name);
}
- //printf("Type: %s\n", o2_get_slot(m_type));
+ m_cart->cart_init();
return image_init_result::PASS;
}
@@ -231,7 +231,7 @@ uint8_t o2_cart_slot_device::read_rom0c(offs_t offset)
}
/*-------------------------------------------------
- io_write
+ io
-------------------------------------------------*/
void o2_cart_slot_device::io_write(offs_t offset, uint8_t data)
@@ -240,6 +240,14 @@ void o2_cart_slot_device::io_write(offs_t offset, uint8_t data)
m_cart->io_write(offset, data);
}
+uint8_t o2_cart_slot_device::io_read(offs_t offset)
+{
+ if (m_cart)
+ return m_cart->io_read(offset);
+ else
+ return 0xff;
+}
+
#include "bus/odyssey2/rom.h"
#include "bus/odyssey2/chess.h"
diff --git a/src/devices/bus/odyssey2/slot.h b/src/devices/bus/odyssey2/slot.h
index 69e107edc11..cec7e2b8eb5 100644
--- a/src/devices/bus/odyssey2/slot.h
+++ b/src/devices/bus/odyssey2/slot.h
@@ -38,8 +38,11 @@ public:
virtual void write_bank(int bank) { }
virtual void io_write(offs_t offset, uint8_t data) { }
+ virtual uint8_t io_read(offs_t offset) { return 0xff; }
virtual DECLARE_READ_LINE_MEMBER(t0_read) { return 0; }
+ virtual void cart_init() { } // called after loading ROM
+
void rom_alloc(uint32_t size, const char *tag);
void ram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
@@ -100,9 +103,10 @@ public:
uint8_t read_rom04(offs_t offset);
uint8_t read_rom0c(offs_t offset);
void io_write(offs_t offset, uint8_t data);
+ 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_bank(int bank) { if (m_cart) m_cart->write_bank(bank); }
protected:
// device-level overrides
diff --git a/src/devices/bus/odyssey2/voice.cpp b/src/devices/bus/odyssey2/voice.cpp
index 490b9b286ad..b0c93670b78 100644
--- a/src/devices/bus/odyssey2/voice.cpp
+++ b/src/devices/bus/odyssey2/voice.cpp
@@ -88,8 +88,11 @@ WRITE_LINE_MEMBER(o2_voice_device::lrq_callback)
void o2_voice_device::io_write(offs_t offset, uint8_t data)
{
- if (data & 0x20)
- m_speech->ald_w(offset & 0x7f);
- else
- m_speech->reset();
+ if (offset & 0x80)
+ {
+ if (data & 0x20)
+ m_speech->ald_w(offset & 0x7f);
+ else
+ m_speech->reset();
+ }
}
diff --git a/src/mame/drivers/odyssey2.cpp b/src/mame/drivers/odyssey2.cpp
index ad083128ee2..78cd6ee67f0 100644
--- a/src/mame/drivers/odyssey2.cpp
+++ b/src/mame/drivers/odyssey2.cpp
@@ -2,12 +2,14 @@
// copyright-holders:Wilbert Pol
/***************************************************************************
- /drivers/odyssey2.c
+Driver file to handle emulation of the Odyssey2.
- Driver file to handle emulation of the Odyssey2.
-
- Minor update to "the voice" rom names, and add comment about
- the older revision of "the voice" - LN, 10/03/08
+TODO:
+- chess has graphics issues near the screen borders: missing A-H at bottom,
+ rightmost column is not erased properly, wrongly places chars at top
+- homecomp does not work, needs new slot device
+- a lot more issues, probably, this TODO list was written by someone with
+ no knowledge on odyssey2
***************************************************************************/
@@ -52,7 +54,7 @@ protected:
required_device m_i8244;
required_device m_cart;
- uint8_t m_ram[256];
+ uint8_t m_ram[0x80];
uint8_t m_p1;
uint8_t m_p2;
uint8_t m_lum;
@@ -290,19 +292,17 @@ void g7400_state::g7400_palette(palette_device &palette) const
void odyssey2_state::init_odyssey2()
{
- uint8_t *gfx = memregion("gfx1")->base();
+ memset(m_ram, 0, 0x80);
+ uint8_t *gfx = memregion("gfx1")->base();
for (int i = 0; i < 256; i++)
- {
- gfx[i] = i; /* TODO: Why i and not 0? */
- m_ram[i] = 0;
- }
+ gfx[i] = i; /* TODO: Why i and not 0? */
}
void odyssey2_state::machine_start()
{
- save_pointer(NAME(m_ram),256);
+ save_item(NAME(m_ram));
save_item(NAME(m_p1));
save_item(NAME(m_p2));
save_item(NAME(m_lum));
@@ -344,16 +344,20 @@ void g7400_state::machine_reset()
uint8_t odyssey2_state::io_read(offs_t offset)
{
+ u8 data = 0;
+
if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0)
{
- return m_i8244->read(offset);
+ data = m_i8244->read(offset);
}
- if (!(m_p1 & P1_EXT_RAM_ENABLE))
+ else if (!(m_p1 & P1_EXT_RAM_ENABLE))
{
- return m_ram[offset];
+ data = m_cart->io_read(offset);
+ if (~offset & 0x80)
+ data &= m_ram[offset];
}
- return 0;
+ return data;
}
@@ -361,12 +365,9 @@ void odyssey2_state::io_write(offs_t offset, uint8_t data)
{
if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00)
{
- m_ram[offset] = data;
- if (offset & 0x80)
- {
- logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1);
- m_cart->io_write(offset, data);
- }
+ if (~offset & 0x80)
+ m_ram[offset] = data;
+ m_cart->io_write(offset, data);
}
else if (!(m_p1 & P1_VDC_ENABLE))
{
@@ -377,20 +378,24 @@ void odyssey2_state::io_write(offs_t offset, uint8_t data)
uint8_t g7400_state::io_read(offs_t offset)
{
+ u8 data = 0;
+
if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0)
{
- return m_i8244->read(offset);
+ data = m_i8244->read(offset);
}
else if (!(m_p1 & P1_EXT_RAM_ENABLE))
{
- return m_ram[offset];
+ data = m_cart->io_read(offset);
+ if (~offset & 0x80)
+ data &= m_ram[offset];
}
else if (!(m_p1 & P1_VPP_ENABLE))
{
- return m_ef9340_1->ef9341_read( offset & 0x02, offset & 0x01 );
+ data = m_ef9340_1->ef9341_read( offset & 0x02, offset & 0x01 );
}
- return 0;
+ return data;
}
@@ -398,12 +403,9 @@ void g7400_state::io_write(offs_t offset, uint8_t data)
{
if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00)
{
- m_ram[offset] = data;
- if (offset & 0x80)
- {
- logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1);
- m_cart->io_write(offset, data);
- }
+ if (~offset & 0x80)
+ m_ram[offset] = data;
+ m_cart->io_write(offset, data);
}
else if (!(m_p1 & P1_VDC_ENABLE))
{
@@ -892,4 +894,4 @@ COMP( 1978, odyssey2, 0, 0, odyssey2, odyssey2, odyssey2_state, init
COMP( 1979, videopac, odyssey2, 0, videopac, odyssey2, odyssey2_state, init_odyssey2, "Philips", "Videopac G7000/C52", 0 )
COMP( 1983, g7400, odyssey2, 0, g7400, odyssey2, g7400_state, init_odyssey2, "Philips", "Videopac Plus G7400", MACHINE_IMPERFECT_GRAPHICS )
COMP( 1983, jopac, odyssey2, 0, g7400, odyssey2, g7400_state, init_odyssey2, "Brandt", "Jopac JO7400", MACHINE_IMPERFECT_GRAPHICS )
-COMP( 1983, odyssey3, odyssey2, 0, odyssey3, odyssey2, g7400_state, init_odyssey2, "Magnavox", "Odyssey 3 Command Center (prototype)", MACHINE_IMPERFECT_GRAPHICS )
+COMP( 1983, odyssey3, odyssey2, 0, odyssey3, odyssey2, g7400_state, init_odyssey2, "Magnavox", "Odyssey 3 Command Center (prototype)", MACHINE_IMPERFECT_GRAPHICS ) // USA version of G7400