odyssey2: add preliminary Videopac+ C7420 Home Computer Module emulation

This commit is contained in:
hap 2020-08-12 14:41:42 +02:00
parent bcb1d091c2
commit 138a281c6c
12 changed files with 243 additions and 27 deletions

View File

@ -32,8 +32,7 @@ Robot City (USA)
Interpol (USA)
NOTE:
The C7420 Home Computer Module, which contains a Z80 microprocessor running at 3.5468 MHz,
adds 16K RAM and 16K ROM, that plugs into the G7000.
The C7420 Home Computer Module contains a Z80, 16K RAM and 16K ROM.
-->
<softwarelist name="g7400" description="Philips Videopac Plus G7400 cartridges">
@ -202,16 +201,16 @@ adds 16K RAM and 16K ROM, that plugs into the G7000.
</part>
</software>
<software name="homecomp" supported="no"><!-- needs home computer module emulation, wrong romtype right now -->
<software name="homecomp" supported="no">
<description>Home Computer Module (Euro)</description><!-- aka Basic -->
<year>1983</year>
<publisher>Philips</publisher>
<info name="serial" value="C7420"/>
<part name="cart" interface="odyssey_cart">
<feature name="slot" value="o2_rom" />
<feature name="slot" value="o2_homecomp" />
<dataarea name="rom" size="0x4800">
<rom name="z80_c7420.bin" size="0x4000" crc="939f0e4c" sha1="24c334ba4321f3dd30ac659d35e43f74283ad93b" offset="0" />
<rom name="vp_c7420.bin" size="0x800" crc="8e824b98" sha1="60dfc1eea93c25f30d25e549f32f837e22735224" offset="0x4000" />
<rom name="z80_c7420.bin" offset="0x0000" size="0x4000" crc="939f0e4c" sha1="24c334ba4321f3dd30ac659d35e43f74283ad93b" />
<rom name="vp_c7420.bin" offset="0x4000" size="0x0800" crc="8e824b98" sha1="60dfc1eea93c25f30d25e549f32f837e22735224" />
</dataarea>
</part>
</software>

View File

@ -551,8 +551,8 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM.
<part name="cart" interface="odyssey_cart">
<feature name="slot" value="o2_chess" />
<dataarea name="rom" size="0x2800">
<rom name="z80_c7010.bin" size="0x2000" crc="45080245" sha1="fff3e6449a0e82e8e4ff45e5830c98fc38a8848e" offset="0" />
<rom name="vp_c7010.bin" size="0x800" crc="77066338" sha1="7162359313f66fe759bdd8a34755a5f62f3cadfb" offset="0x2000" />
<rom name="z80_c7010.bin" offset="0x0000" size="0x2000" crc="45080245" sha1="fff3e6449a0e82e8e4ff45e5830c98fc38a8848e" />
<rom name="vp_c7010.bin" offset="0x2000" size="0x0800" crc="77066338" sha1="7162359313f66fe759bdd8a34755a5f62f3cadfb" />
</dataarea>
</part>
</software>

View File

@ -1696,6 +1696,8 @@ if (BUSES["O2"]~=null) then
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/homecomp.cpp",
MAME_DIR .. "src/devices/bus/odyssey2/homecomp.h",
MAME_DIR .. "src/devices/bus/odyssey2/ktaa.cpp",
MAME_DIR .. "src/devices/bus/odyssey2/ktaa.h",
MAME_DIR .. "src/devices/bus/odyssey2/rally.cpp",

View File

@ -9,8 +9,6 @@ Hardware notes:
- NSC800 (Z80-compatible) @ 4.43MHz
- 8KB ROM, 2KB RAM
Service manual with schematics is available.
******************************************************************************/
#include "emu.h"
@ -26,7 +24,7 @@ DEFINE_DEVICE_TYPE(O2_ROM_CHESS, o2_chess_device, "o2_chess", "Odyssey 2 Videopa
o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, O2_ROM_CHESS, tag, owner, clock),
device_o2_cart_interface(mconfig, *this),
m_cpu(*this, "subcpu"),
m_maincpu(*this, "maincpu"),
m_latch(*this, "latch%u", 0)
{ }
@ -65,9 +63,10 @@ void o2_chess_device::chess_io(address_map &map)
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);
// basic machine hardware
NSC800(config, m_maincpu, 4.433619_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &o2_chess_device::chess_mem);
m_maincpu->set_addrmap(AS_IO, &o2_chess_device::chess_io);
GENERIC_LATCH_8(config, m_latch[0]);
GENERIC_LATCH_8(config, m_latch[1]);
@ -80,10 +79,10 @@ void o2_chess_device::device_add_mconfig(machine_config &config)
void o2_chess_device::write_p1(u8 data)
{
// P10,P14: must be low to access latches
// P11: reset
m_cpu->set_input_line(INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
// P10,P14: must be low to access latches
m_control = data;
}

View File

@ -12,6 +12,7 @@
#pragma once
#include "slot.h"
#include "cpu/z80/z80.h"
#include "machine/gen_latch.h"
@ -33,14 +34,14 @@ protected:
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 u8 read_rom0c(offs_t offset) override { return read_rom04(offset); }
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;
private:
required_device<nsc800_device> m_cpu;
required_device<cpu_device> m_maincpu;
required_device_array<generic_latch_8_device, 2> m_latch;
u8 internal_rom_r(offs_t offset) { return m_rom[offset]; }

View File

@ -0,0 +1,144 @@
// license:BSD-3-Clause
// copyright-holders:hap
/******************************************************************************
Videopac+ C7420 Home Computer Module emulation
This module only works on the Videopac+ G7400, although the cartridge can still
be inserted into the Odyssey 2/G7000.
Hardware notes:
- Z80 @ 3.547MHz
- 2*8KB ROM, 16KB RAM(2*TMS4416, 2 unpopulated sockets)
- optional data recorder
TODO:
- lots of unacknowledged writes to latch 1, probably harmless
- add cassette i/o
******************************************************************************/
#include "emu.h"
#include "homecomp.h"
#include "speaker.h"
DEFINE_DEVICE_TYPE(O2_ROM_HOMECOMP, o2_homecomp_device, "o2_homecomp", "Odyssey 2 Videopac+ C7420")
//-------------------------------------------------
// o2_homecomp_device - constructor
//-------------------------------------------------
o2_homecomp_device::o2_homecomp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, O2_ROM_HOMECOMP, tag, owner, clock),
device_o2_cart_interface(mconfig, *this),
m_maincpu(*this, "maincpu"),
m_latch(*this, "latch%u", 0),
m_cass(*this, "cassette")
{ }
void o2_homecomp_device::device_start()
{
save_item(NAME(m_control));
}
void o2_homecomp_device::cart_init()
{
if (m_rom_size != 0x4800)
fatalerror("o2_homecomp_device: Wrong ROM region size\n");
}
//-------------------------------------------------
// internal i/o
//-------------------------------------------------
u8 o2_homecomp_device::internal_io_r(offs_t offset)
{
u8 data = 0;
// A7: input latch
if (~offset & 0x80)
data |= m_latch[1]->read();
// A6: other i/o
if (~offset & 0x40)
{
// d0: latch 0 status
data |= m_latch[0]->pending_r() ^ 1;
}
return data;
}
void o2_homecomp_device::internal_io_w(offs_t offset, u8 data)
{
// A7: output latch
if (~offset & 0x80)
m_latch[0]->write(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)
{
map.global_mask(0xff);
map(0x00, 0xff).rw(FUNC(o2_homecomp_device::internal_io_r), FUNC(o2_homecomp_device::internal_io_w));
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void o2_homecomp_device::device_add_mconfig(machine_config &config)
{
// basic machine hardware
Z80(config, m_maincpu, 3.547_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &o2_homecomp_device::homecomp_mem);
m_maincpu->set_addrmap(AS_IO, &o2_homecomp_device::homecomp_io);
GENERIC_LATCH_8(config, m_latch[0]);
GENERIC_LATCH_8(config, m_latch[1]);
// cassette
CASSETTE(config, m_cass);
m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED);
SPEAKER(config, "cass_output").front_center(); // on data recorder
m_cass->add_route(ALL_OUTPUTS, "cass_output", 0.05);
}
//-------------------------------------------------
// 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);
}

View File

@ -0,0 +1,64 @@
// license:BSD-3-Clause
// copyright-holders:hap
/**********************************************************************
Videopac+ C7420 Home Computer Module emulation
**********************************************************************/
#ifndef MAME_BUS_ODYSSEY2_HOMECOMP_H
#define MAME_BUS_ODYSSEY2_HOMECOMP_H
#pragma once
#include "slot.h"
#include "cpu/z80/z80.h"
#include "imagedev/cassette.h"
#include "machine/gen_latch.h"
// ======================> o2_homecomp_device
class o2_homecomp_device : public device_t,
public device_o2_cart_interface
{
public:
// construction/destruction
o2_homecomp_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 void cart_init() override;
virtual u8 read_rom04(offs_t offset) override { return m_rom[offset + 0x4000]; }
virtual u8 read_rom0c(offs_t offset) override { return read_rom04(offset); }
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 DECLARE_READ_LINE_MEMBER(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;
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_rom[offset]; }
void homecomp_io(address_map &map);
void homecomp_mem(address_map &map);
u8 m_control = 0;
u8 m_ioctrl = 0;
};
// device type definition
DECLARE_DEVICE_TYPE(O2_ROM_HOMECOMP, o2_homecomp_device)
#endif // MAME_BUS_ODYSSEY2_HOMECOMP_H

View File

@ -2,7 +2,7 @@
// copyright-holders:hap
/******************************************************************************
Videopac 55/58/59/60 cartridge emulation
Videopac+ 55/58/59/60 cartridge emulation
Bankswitched ROM via latch, either 16KB/2*8KB, or 4KB+8KB.
@ -12,12 +12,14 @@ Used in:
- #59: Helicopter Rescue
- #60: Trans American Rally
#55 and #58 also work on the G7000.
******************************************************************************/
#include "emu.h"
#include "rally.h"
DEFINE_DEVICE_TYPE(O2_ROM_RALLY, o2_rally_device, "o2_rally", "Odyssey 2 Videopac 60")
DEFINE_DEVICE_TYPE(O2_ROM_RALLY, o2_rally_device, "o2_rally", "Odyssey 2 Videopac+ 60")
//-------------------------------------------------

View File

@ -2,7 +2,7 @@
// copyright-holders:hap
/**********************************************************************
Videopac 55/58/59/60 cartridge emulation
Videopac+ 55/58/59/60 cartridge emulation
**********************************************************************/

View File

@ -118,6 +118,7 @@ static const o2_slot slot_list[] =
{ O2_RALLY, "o2_rally" },
{ O2_KTAA, "o2_ktaa" },
{ O2_CHESS, "o2_chess" },
{ O2_HOMECOMP, "o2_homecomp" },
{ O2_VOICE, "o2_voice" }
};
@ -243,14 +244,16 @@ uint8_t o2_cart_slot_device::io_read(offs_t offset)
#include "bus/odyssey2/rally.h"
#include "bus/odyssey2/ktaa.h"
#include "bus/odyssey2/chess.h"
#include "bus/odyssey2/homecomp.h"
#include "bus/odyssey2/voice.h"
void o2_cart(device_slot_interface &device)
{
device.option_add_internal("o2_rom", O2_ROM_STD);
device.option_add_internal("o2_4in1", O2_ROM_4IN1);
device.option_add_internal("o2_rally", O2_ROM_RALLY);
device.option_add_internal("o2_ktaa", O2_ROM_KTAA);
device.option_add_internal("o2_chess", O2_ROM_CHESS);
device.option_add_internal("o2_voice", O2_ROM_VOICE);
device.option_add_internal("o2_rom", O2_ROM_STD);
device.option_add_internal("o2_4in1", O2_ROM_4IN1);
device.option_add_internal("o2_rally", O2_ROM_RALLY);
device.option_add_internal("o2_ktaa", O2_ROM_KTAA);
device.option_add_internal("o2_chess", O2_ROM_CHESS);
device.option_add_internal("o2_homecomp", O2_ROM_HOMECOMP);
device.option_add_internal("o2_voice", O2_ROM_VOICE);
}

View File

@ -21,6 +21,7 @@ enum
O2_RALLY,
O2_KTAA,
O2_CHESS,
O2_HOMECOMP,
O2_VOICE
};

View File

@ -91,6 +91,7 @@ const double XTAL::known_xtals[] = {
3'276'800, /* 3.2768_MHz_XTAL SP0256 clock in Speech Synthesis for Dragon 32 */
3'521'280, /* 3.52128_MHz_XTAL RCA COSMAC VIP */
3'546'800, /* 3.5468_MHz_XTAL Atari 400 PAL, Philips G7200 */
3'547'000, /* 3.547_MHz_XTAL Philips C7240 */
3'570'000, /* 3.57_MHz_XTAL Telmac TMC-600 */
3'578'640, /* 3.57864_MHz_XTAL Atari Portfolio PCD3311T */
3'579'000, /* 3.579_MHz_XTAL BeebOPL */