(MESS) sms: added backward compatibility to SG-1000 Mark III, for SG-1000 games. [Fabio Priuli]

Only supported from fullpath for the moment
This commit is contained in:
Fabio Priuli 2013-05-24 09:45:28 +00:00
parent 5ed2398162
commit 5b3ba478c9
6 changed files with 586 additions and 126 deletions

View File

@ -540,6 +540,17 @@ static const sn76496_config psg_intf =
static SLOT_INTERFACE_START(sms_cart)
SLOT_INTERFACE_INTERNAL("rom", SEGA8_ROM_STD)
SLOT_INTERFACE_INTERNAL("codemasters", SEGA8_ROM_CODEMASTERS)
SLOT_INTERFACE_INTERNAL("4pak", SEGA8_ROM_4PAK)
SLOT_INTERFACE_INTERNAL("zemina", SEGA8_ROM_ZEMINA)
SLOT_INTERFACE_INTERNAL("nemesis", SEGA8_ROM_NEMESIS)
SLOT_INTERFACE_INTERNAL("janggun", SEGA8_ROM_JANGGUN)
SLOT_INTERFACE_INTERNAL("korean", SEGA8_ROM_KOREAN)
SLOT_INTERFACE_INTERNAL("korean_nb", SEGA8_ROM_KOREAN_NB)
SLOT_INTERFACE_END
static SLOT_INTERFACE_START(sg1000mk3_cart)
SLOT_INTERFACE_INTERNAL("rom", SEGA8_ROM_STD)
SLOT_INTERFACE_INTERNAL("terebi", SEGA8_ROM_TEREBI)
SLOT_INTERFACE_INTERNAL("codemasters", SEGA8_ROM_CODEMASTERS)
@ -549,6 +560,12 @@ static SLOT_INTERFACE_START(sms_cart)
SLOT_INTERFACE_INTERNAL("janggun", SEGA8_ROM_JANGGUN)
SLOT_INTERFACE_INTERNAL("korean", SEGA8_ROM_KOREAN)
SLOT_INTERFACE_INTERNAL("korean_nb", SEGA8_ROM_KOREAN_NB)
SLOT_INTERFACE_INTERNAL("castle", SEGA8_ROM_CASTLE)
SLOT_INTERFACE_INTERNAL("dahjee_typea", SEGA8_ROM_DAHJEE_TYPEA)
SLOT_INTERFACE_INTERNAL("dahjee_typeb", SEGA8_ROM_DAHJEE_TYPEB)
// are these SC-3000 carts below actually compatible or not? remove if not!
SLOT_INTERFACE_INTERNAL("level3", SEGA8_ROM_BASIC_L3)
SLOT_INTERFACE_INTERNAL("music_editor", SEGA8_ROM_MUSIC_EDITOR)
SLOT_INTERFACE_END
static SLOT_INTERFACE_START(gg_cart)
@ -793,7 +810,7 @@ static MACHINE_CONFIG_DERIVED( sg1000m3, sms_fm )
MCFG_CPU_IO_MAP(sms_no3e3f_io)
MCFG_DEVICE_REMOVE("slot")
MCFG_SG1000MK3_CARTRIDGE_ADD("slot", sms_cart, NULL, NULL)
MCFG_SG1000MK3_CARTRIDGE_ADD("slot", sg1000mk3_cart, NULL, NULL)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms2_fm, sms2_ntsc )

View File

@ -15,9 +15,20 @@
// constructors
//-------------------------------------------------
// Base cart type shared across SG-1000, SG-1000 Mark II, SG-1000 Mark III, SMS, GG
// even if in sg1000 rom banks are never changed and ram is never enabled
const device_type SEGA8_ROM_STD = &device_creator<sega8_rom_device>;
const device_type SEGA8_ROM_EEPROM = &device_creator<sega8_eeprom_device>;
// Specific SG-1000 MkI - MkII cart types
const device_type SEGA8_ROM_CASTLE = &device_creator<sega8_castle_device>;
const device_type SEGA8_ROM_BASIC_L3 = &device_creator<sega8_basic_l3_device>;
const device_type SEGA8_ROM_MUSIC_EDITOR = &device_creator<sega8_music_editor_device>;
const device_type SEGA8_ROM_TEREBI = &device_creator<sega8_terebi_device>;
const device_type SEGA8_ROM_DAHJEE_TYPEA = &device_creator<sega8_dahjee_typea_device>;
const device_type SEGA8_ROM_DAHJEE_TYPEB = &device_creator<sega8_dahjee_typeb_device>;
// Specific SG-1000 MkIII - SMS - GG cart types
const device_type SEGA8_ROM_EEPROM = &device_creator<sega8_eeprom_device>;
const device_type SEGA8_ROM_CODEMASTERS = &device_creator<sega8_codemasters_device>;
const device_type SEGA8_ROM_4PAK = &device_creator<sega8_4pak_device>;
const device_type SEGA8_ROM_ZEMINA = &device_creator<sega8_zemina_device>;
@ -27,6 +38,7 @@ const device_type SEGA8_ROM_KOREAN = &device_creator<sega8_korean_device>;
const device_type SEGA8_ROM_KOREAN_NB = &device_creator<sega8_korean_nb_device>;
sega8_rom_device::sega8_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_sega8_cart_interface( mconfig, *this )
@ -34,22 +46,34 @@ sega8_rom_device::sega8_rom_device(const machine_config &mconfig, device_type ty
}
sega8_rom_device::sega8_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SEGA8_ROM_STD, "SMS Carts", tag, owner, clock, "sega8_rom", __FILE__),
: device_t(mconfig, SEGA8_ROM_STD, "Mark III, SMS & GG Carts", tag, owner, clock, "sega8_rom", __FILE__),
device_sega8_cart_interface( mconfig, *this )
{
}
sega8_eeprom_device::sega8_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SEGA8_ROM_EEPROM, "SMS EEPROM Carts", tag, owner, clock, "sega8_eeprom", __FILE__),
device_sega8_cart_interface( mconfig, *this ),
m_eeprom(*this, "eeprom")
sega8_castle_device::sega8_castle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: sega8_rom_device(mconfig, SEGA8_ROM_CASTLE, "SG-1000 The Castle Cart", tag, owner, clock, "sega8_castle", __FILE__)
{
}
sega8_basic_l3_device::sega8_basic_l3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: sega8_rom_device(mconfig, SEGA8_ROM_BASIC_L3, "SC-3000 BASIC Level III Cart", tag, owner, clock, "sega8_basicl3", __FILE__)
{
}
sega8_music_editor_device::sega8_music_editor_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: sega8_rom_device(mconfig, SEGA8_ROM_MUSIC_EDITOR, "SC-3000 Music Editor Cart", tag, owner, clock, "sega8_music", __FILE__)
{
}
sega8_terebi_device::sega8_terebi_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: sega8_rom_device(mconfig, SEGA8_ROM_TEREBI, "SMS Terebi Oekaki Cart", tag, owner, clock, "sega8_terebi", __FILE__),
: sega8_rom_device(mconfig, SEGA8_ROM_TEREBI, "SG-1000 Terebi Oekaki Cart", tag, owner, clock, "sega8_terebi", __FILE__),
m_tvdraw_x(*this, "TVDRAW_X"),
m_tvdraw_y(*this, "TVDRAW_Y"),
m_tvdraw_pen(*this, "TVDRAW_PEN")
@ -57,8 +81,30 @@ sega8_terebi_device::sega8_terebi_device(const machine_config &mconfig, const ch
}
sega8_dahjee_typea_device::sega8_dahjee_typea_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: sega8_rom_device(mconfig, SEGA8_ROM_DAHJEE_TYPEA, "SG-1000 Dahjee RAM expansion + Cart (Type A)", tag, owner, clock, "sega8_dahjeea", __FILE__)
{
}
sega8_dahjee_typeb_device::sega8_dahjee_typeb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: sega8_rom_device(mconfig, SEGA8_ROM_DAHJEE_TYPEB, "SG-1000 Dahjee RAM expansion + Cart (Type B)", tag, owner, clock, "sega8_dahjeeb", __FILE__)
{
}
sega8_eeprom_device::sega8_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SEGA8_ROM_EEPROM, "GG Carts + EEPROM", tag, owner, clock, "sega8_eeprom", __FILE__),
device_sega8_cart_interface( mconfig, *this ),
m_eeprom(*this, "eeprom")
{
}
sega8_codemasters_device::sega8_codemasters_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SEGA8_ROM_CODEMASTERS, "SMS Codemasters Carts", tag, owner, clock, "sega8_codemasters", __FILE__),
: device_t(mconfig, SEGA8_ROM_CODEMASTERS, "Mark III, SMS & GG Codemasters Carts", tag, owner, clock, "sega8_codemasters", __FILE__),
device_sega8_cart_interface( mconfig, *this )
{
}
@ -122,6 +168,21 @@ void sega8_rom_device::device_reset()
}
void sega8_terebi_device::device_start()
{
save_item(NAME(m_rom_bank_base));
save_item(NAME(m_tvdraw_data));
}
void sega8_terebi_device::device_reset()
{
m_tvdraw_data = 0;
}
void sega8_eeprom_device::device_start()
{
save_item(NAME(m_rom_bank_base));
@ -136,17 +197,6 @@ void sega8_eeprom_device::device_reset()
}
void sega8_terebi_device::device_start()
{
save_item(NAME(m_rom_bank_base));
save_item(NAME(m_tvdraw_data));
}
void sega8_terebi_device::device_reset()
{
m_tvdraw_data = 0;
}
void sega8_codemasters_device::device_start()
{
save_item(NAME(m_rom_bank_base));
@ -186,12 +236,6 @@ void sega8_zemina_device::device_reset()
}
void sega8_janggun_device::device_start()
{
save_item(NAME(m_rom_bank_base));
}
// initial bank setup needs to know how many 16K banks are available, so it needs to be called during cart loading...
void sega8_rom_device::late_bank_setup()
@ -254,7 +298,6 @@ void sega8_korean_device::late_bank_setup()
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
@ -262,6 +305,7 @@ void sega8_korean_device::late_bank_setup()
/*-------------------------------------------------
Base Sega 8bit carts, possibly with bankswitch
(only used by Mark III, SMS and GG games)
-------------------------------------------------*/
@ -312,6 +356,242 @@ WRITE8_MEMBER(sega8_rom_device::write_mapper)
}
}
/*-------------------------------------------------
The Castle is a SG-1000 game featuring 8K of
oncart RAM, mapped at 0x8000-0x9fff
-------------------------------------------------*/
READ8_MEMBER(sega8_castle_device::read_cart)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
return m_ram[offset & 0x1fff];
return m_rom[offset % m_rom_size];
}
WRITE8_MEMBER(sega8_castle_device::write_cart)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
m_ram[offset & 0x1fff] = data;
}
/*-------------------------------------------------
BASIC Level III cart featured 32K of
oncart RAM, mapped at 0x8000-0xffff?
-------------------------------------------------*/
READ8_MEMBER(sega8_basic_l3_device::read_cart)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000)
return m_ram[offset & 0x3fff];
return m_rom[offset % m_rom_size];
}
WRITE8_MEMBER(sega8_basic_l3_device::write_cart)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000)
m_ram[offset & 0x3fff] = data;
}
READ8_MEMBER(sega8_basic_l3_device::read_ram)
{
return m_ram[0x4000 + (offset & 0x3fff)];
}
WRITE8_MEMBER(sega8_basic_l3_device::write_ram)
{
m_ram[0x4000 + (offset & 0x3fff)] = data;
}
/*-------------------------------------------------
Music Editor cart featured 10K of oncart RAM, mapped
in 0x8000-0x9fff and 0xc000-0xffff
-------------------------------------------------*/
READ8_MEMBER(sega8_music_editor_device::read_cart)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
return m_ram[offset & 0x1fff];
return m_rom[offset % m_rom_size];
}
WRITE8_MEMBER(sega8_music_editor_device::write_cart)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
m_ram[offset & 0x1fff] = data;
}
READ8_MEMBER(sega8_music_editor_device::read_ram)
{
// 2K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff)
// or should it simply go to the 2K of SC3000 RAM???
return m_ram[0x2000 + (offset & 0x7ff)];
}
WRITE8_MEMBER(sega8_music_editor_device::write_ram)
{
// 2K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff)
// or should it simply go to the 2K of SC3000 RAM???
m_ram[0x2000 + (offset & 0x7ff)] = data;
}
/*-------------------------------------------------
SG-1000 Terebi Oekaki using a Tablet input device
-------------------------------------------------*/
/*
Terebi Oekaki (TV Draw)
Address Access Bits
7 6 5 4 3 2 1 0
$6000 W - - - - - - - AXIS
$8000 R BUSY - - - - - - PRESS
$A000 R/W DATA
AXIS: write 0 to select X axis, 1 to select Y axis.
BUSY: reads 1 when graphic board is busy sampling position, else 0.
PRESS: reads 0 when pen is touching graphic board, else 1.
DATA: when pen is touching graphic board, return 8-bit sample position for currently selected axis (X is in the 0-255 range, Y in the 0-191 range). Else, return 0.
*/
READ8_MEMBER(sega8_terebi_device::read_cart)
{
int bank = offset / 0x4000;
if (offset == 0x8000)
return m_tvdraw_pen->read();
if (offset == 0xa000)
return m_tvdraw_data;
return m_rom[m_rom_bank_base[bank] * 0x4000 + (offset & 0x3fff)];
}
WRITE8_MEMBER(sega8_terebi_device::write_cart)
{
switch (offset)
{
case 0x6000:
if (data & 0x01)
{
m_tvdraw_data = m_tvdraw_x->read();
if (m_tvdraw_data < 4) m_tvdraw_data = 4;
if (m_tvdraw_data > 251) m_tvdraw_data = 251;
}
else
m_tvdraw_data = m_tvdraw_y->read() + 0x20;
break;
case 0xa000:
// effect unknown
break;
}
}
static INPUT_PORTS_START( tvdraw )
PORT_START("TVDRAW_X")
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Tablet - X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1)
PORT_START("TVDRAW_Y")
PORT_BIT( 0xff, 0x60, IPT_LIGHTGUN_Y ) PORT_NAME("Tablet - Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0, 191) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1)
PORT_START("TVDRAW_PEN")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Tablet - Pen")
INPUT_PORTS_END
ioport_constructor sega8_terebi_device::device_input_ports() const
{
return INPUT_PORTS_NAME( tvdraw );
}
/*-------------------------------------------------
Dahjee carts were sold with a RAM expansion pass-through
cart (which we don't emulate separately for the
moment) which allowed to play on old SG1000 machines
some MSX conversions requiring more RAM than available
Two kind of expansion existed (for different games),
one with 9K of RAM (Type A) and one with 8K of
RAM (Type B).
-------------------------------------------------*/
// TYPE A
READ8_MEMBER(sega8_dahjee_typea_device::read_cart)
{
// 8K of RAM sits in 0x2000-0x3fff
if (offset >= 0x2000 && offset < 0x4000)
return m_ram[offset & 0x1fff];
return m_rom[offset % m_rom_size];
}
WRITE8_MEMBER(sega8_dahjee_typea_device::write_cart)
{
// 8K of RAM sits in 0x2000-0x3fff
if (offset >= 0x2000 && offset < 0x4000)
m_ram[offset & 0x1fff] = data;
}
READ8_MEMBER(sega8_dahjee_typea_device::read_ram)
{
// 1K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff
// or should it simply go to the 1K of SG1000 RAM???
return m_ram[0x2000 + (offset & 0x3ff)];
}
WRITE8_MEMBER(sega8_dahjee_typea_device::write_ram)
{
// 1K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff
// or should it simply go to the 1K of SG1000 RAM???
m_ram[0x2000 + (offset & 0x3ff)] = data;
}
// TYPE B
READ8_MEMBER(sega8_dahjee_typeb_device::read_cart)
{
return m_rom[offset % m_rom_size];
}
READ8_MEMBER(sega8_dahjee_typeb_device::read_ram)
{
// 8K more of RAM sits in 0xc000-0xffff
return m_ram[offset & 0x1fff];
}
WRITE8_MEMBER(sega8_dahjee_typeb_device::write_ram)
{
// 8K more of RAM sits in 0xc000-0xffff
m_ram[offset & 0x1fff] = data;
}
/*-------------------------------------------------
Sega carts + EEPROM, used for some GameGear baseball
@ -381,63 +661,6 @@ machine_config_constructor sega8_eeprom_device::device_mconfig_additions() const
}
/*-------------------------------------------------
Sega 8-bit cart + Tablet input device, used for
SG-1000 Terebi Oekaki (compatible with Mark III)
-------------------------------------------------*/
READ8_MEMBER(sega8_terebi_device::read_cart)
{
int bank = offset / 0x4000;
if (offset == 0x8000)
return m_tvdraw_pen->read();
if (offset == 0xa000)
return m_tvdraw_data;
return m_rom[m_rom_bank_base[bank] * 0x4000 + (offset & 0x3fff)];
}
WRITE8_MEMBER(sega8_terebi_device::write_cart)
{
switch (offset)
{
case 0x6000:
if (data & 0x01)
{
m_tvdraw_data = m_tvdraw_x->read();
if (m_tvdraw_data < 4) m_tvdraw_data = 4;
if (m_tvdraw_data > 251) m_tvdraw_data = 251;
}
else
m_tvdraw_data = m_tvdraw_y->read() + 0x20;
break;
case 0xa000:
// effect unknown
break;
}
}
static INPUT_PORTS_START( tvdraw )
PORT_START("TVDRAW_X")
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Tablet - X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1)
PORT_START("TVDRAW_Y")
PORT_BIT( 0xff, 0x60, IPT_LIGHTGUN_Y ) PORT_NAME("Tablet - Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0, 191) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1)
PORT_START("TVDRAW_PEN")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Tablet - Pen")
INPUT_PORTS_END
ioport_constructor sega8_terebi_device::device_input_ports() const
{
return INPUT_PORTS_NAME( tvdraw );
}
/*-------------------------------------------------
Codemasters carts, possibly having on cart RAM
@ -639,3 +862,4 @@ WRITE8_MEMBER(sega8_korean_device::write_cart)
if (offset == 0xa000)
m_rom_bank_base[2] = data % m_rom_page_count;
}

View File

@ -32,6 +32,128 @@ protected:
};
// ======================> sega8_castle_device
class sega8_castle_device : public sega8_rom_device
{
public:
// construction/destruction
sega8_castle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
virtual DECLARE_WRITE8_MEMBER(write_mapper) {}
};
// ======================> sega8_basic_l3_device
class sega8_basic_l3_device : public sega8_rom_device
{
public:
// construction/destruction
sega8_basic_l3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
virtual DECLARE_WRITE8_MEMBER(write_mapper) {}
// has internal RAM which overwrites the system one!
virtual DECLARE_READ8_MEMBER(read_ram);
virtual DECLARE_WRITE8_MEMBER(write_ram);
};
// ======================> sega8_music_editor_device
class sega8_music_editor_device : public sega8_rom_device
{
public:
// construction/destruction
sega8_music_editor_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
virtual DECLARE_WRITE8_MEMBER(write_mapper) {}
// has internal RAM which overwrites the system one!
virtual DECLARE_READ8_MEMBER(read_ram);
virtual DECLARE_WRITE8_MEMBER(write_ram);
};
// ======================> sega8_terebi_device
class sega8_terebi_device : public sega8_rom_device
{
public:
// construction/destruction
sega8_terebi_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual ioport_constructor device_input_ports() const;
virtual void device_reset();
required_ioport m_tvdraw_x;
required_ioport m_tvdraw_y;
required_ioport m_tvdraw_pen;
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
virtual DECLARE_WRITE8_MEMBER(write_mapper) {}
protected:
UINT8 m_tvdraw_data;
};
// ======================> sega8_dahjee_typea_device
class sega8_dahjee_typea_device : public sega8_rom_device
{
public:
// construction/destruction
sega8_dahjee_typea_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
virtual DECLARE_WRITE8_MEMBER(write_mapper) {}
// has internal RAM which overwrites the system one!
virtual DECLARE_READ8_MEMBER(read_ram);
virtual DECLARE_WRITE8_MEMBER(write_ram);
};
// ======================> sega8_dahjee_typeb_device
class sega8_dahjee_typeb_device : public sega8_rom_device
{
public:
// construction/destruction
sega8_dahjee_typeb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart) {}
virtual DECLARE_WRITE8_MEMBER(write_mapper) {}
// has internal RAM which overwrites the system one!
virtual DECLARE_READ8_MEMBER(read_ram);
virtual DECLARE_WRITE8_MEMBER(write_ram);
};
// ======================> sega8_eeprom_device
class sega8_eeprom_device : public device_t,
@ -62,32 +184,6 @@ protected:
};
// ======================> sega8_terebi_device
class sega8_terebi_device : public sega8_rom_device
{
public:
// construction/destruction
sega8_terebi_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual ioport_constructor device_input_ports() const;
virtual void device_reset();
required_ioport m_tvdraw_x;
required_ioport m_tvdraw_y;
required_ioport m_tvdraw_pen;
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
protected:
UINT8 m_tvdraw_data;
};
// ======================> sega8_codemasters_device
class sega8_codemasters_device : public device_t,
@ -183,9 +279,9 @@ class sega8_janggun_device : public device_t,
public:
// construction/destruction
sega8_janggun_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_start() { save_item(NAME(m_rom_bank_base)); }
virtual void late_bank_setup();
@ -228,8 +324,14 @@ public:
};
// device type definition
extern const device_type SEGA8_ROM_STD;
extern const device_type SEGA8_ROM_CASTLE;
extern const device_type SEGA8_ROM_BASIC_L3;
extern const device_type SEGA8_ROM_MUSIC_EDITOR;
extern const device_type SEGA8_ROM_DAHJEE_TYPEA;
extern const device_type SEGA8_ROM_DAHJEE_TYPEB;
extern const device_type SEGA8_ROM_EEPROM;
extern const device_type SEGA8_ROM_TEREBI;
extern const device_type SEGA8_ROM_CODEMASTERS;

View File

@ -182,7 +182,12 @@ static const sega8_slot slot_list[] =
{ SEGA8_NEMESIS, "nemesis" },
{ SEGA8_JANGGUN, "janggun" },
{ SEGA8_KOREAN, "korean" },
{ SEGA8_KOREAN_NOBANK, "korean_nobank" }
{ SEGA8_KOREAN_NOBANK, "korean_nb" },
{ SEGA8_CASTLE, "castle" },
{ SEGA8_BASIC_L3, "level3" },
{ SEGA8_MUSIC_EDITOR, "music_editor" },
{ SEGA8_DAHJEE_TYPEA, "dahjee_typea" },
{ SEGA8_DAHJEE_TYPEB, "dahjee_typeb" }
};
static int sega8_get_pcb_id(const char *slot)
@ -272,20 +277,45 @@ void sega8_cart_slot_device::setup_ram()
{
if (software_entry() == NULL)
{
// from fullpath we have no way to know exactly if there was RAM, how much RAM was in the cart and if there was a battery
// so we always alloc 32KB and we save its content only if the game enable the RAM (unless it's Codemasters mapper...)
if (m_type != SEGA8_CODEMASTERS)
if (m_type == SEGA8_CASTLE)
{
m_cart->set_late_battery(TRUE);
m_cart->ram_alloc(machine(), 0x08000);
m_cart->ram_alloc(machine(), 0x2000);
m_cart->set_has_battery(FALSE);
}
else
else if (m_type == SEGA8_BASIC_L3)
{
// Codemasters cart can have 64KB of RAM (Ernie Els Golf) and no battery
m_cart->ram_alloc(machine(), 0x8000);
m_cart->set_has_battery(FALSE);
}
else if (m_type == SEGA8_MUSIC_EDITOR)
{
m_cart->ram_alloc(machine(), 0x2800);
m_cart->set_has_battery(FALSE);
}
else if (m_type == SEGA8_DAHJEE_TYPEA)
{
m_cart->ram_alloc(machine(), 0x2400);
m_cart->set_has_battery(FALSE);
}
else if (m_type == SEGA8_DAHJEE_TYPEB)
{
m_cart->ram_alloc(machine(), 0x2000);
m_cart->set_has_battery(FALSE);
}
else if (m_type == SEGA8_CODEMASTERS)
{
// Codemasters cart can have 64KB of RAM (Ernie Els Golf? or 8KB?) and no battery
m_cart->ram_alloc(machine(), 0x10000);
m_cart->set_has_battery(FALSE);
}
else
{
// for generic carts loaded from fullpath we have no way to know exactly if there was RAM,
// how much RAM was in the cart and if there was a battery so we always alloc 32KB and
// we save its content only if the game enable the RAM
m_cart->set_late_battery(TRUE);
m_cart->ram_alloc(machine(), 0x08000);
}
}
else
{
@ -456,9 +486,8 @@ int sms_state::detect_korean_mapper( UINT8 *rom )
int sega8_cart_slot_device::get_cart_type(UINT8 *ROM, UINT32 len)
{
int type = SEGA8_BASE_ROM;
static const UINT8 terebi_oekaki[7] = { 0x61, 0x6e, 0x6e, 0x61, 0x6b, 0x6d, 0x6e }; // "annakmn"
/* Check for special cartridge features (new routine, courtesy of Omar Cornut, from MEKA) */
// Check for special cartridge features (new routine, courtesy of Omar Cornut, from MEKA)
if (len >= 0x8000)
{
int _0002 = 0, _8000 = 0, _a000 = 0, _ffff = 0, _3ffe = 0, _4000 = 0, _6000 = 0;
@ -506,9 +535,64 @@ int sega8_cart_slot_device::get_cart_type(UINT8 *ROM, UINT32 len)
type = SEGA8_JANGGUN;
}
// Terebi Oekaki (TV Draw) is a SG1000 game with special input device which is compatible with SG1000 Mark III
if (!memcmp(&ROM[0x13b3], terebi_oekaki, 7))
// Try to detect Dahjee RAM Expansions
if (len >= 0x8000)
{
int x2000_3000 = 0, xd000_e000_f000 = 0, x2000_ff = 0;
for (int i = 0; i < 0x8000; i++)
{
if (ROM[i] == 0x32)
{
UINT16 addr = ROM[i + 1] | (ROM[i + 2] << 8);
switch (addr & 0xf000)
{
case 0x2000:
case 0x3000:
i += 2;
x2000_3000++;
break;
case 0xd000:
case 0xe000:
case 0xf000:
i += 2;
xd000_e000_f000++;
break;
}
}
}
for (int i = 0x2000; i < 0x4000; i++)
{
if (ROM[i] == 0xff)
x2000_ff++;
}
if (x2000_ff == 0x2000 && (xd000_e000_f000 > 10 || x2000_3000 > 10))
{
if (xd000_e000_f000 > x2000_3000)
type = SEGA8_DAHJEE_TYPEB;
else
type = SEGA8_DAHJEE_TYPEA;
}
}
// Terebi Oekaki (TV Draw)
if (!strncmp((const char *)&ROM[0x13b3], "annakmn", 7))
type = SEGA8_TEREBIOEKAKI;
// The Castle (ROM+RAM)
if (!strncmp((const char *)&ROM[0x1cc3], "ASCII 1986", 10))
type = SEGA8_CASTLE;
// BASIC Level 3
if (!strncmp((const char *)&ROM[0x6a20], "SC-3000 BASIC Level 3 ver 1.0", 29))
type = SEGA8_BASIC_L3;
// Music Editor
if (!strncmp((const char *)&ROM[0x0841], "PIANO", 5))
type = SEGA8_MUSIC_EDITOR;
return type;
}
@ -557,6 +641,14 @@ READ8_MEMBER(sega8_cart_slot_device::read_cart)
return 0xff;
}
READ8_MEMBER(sega8_cart_slot_device::read_ram)
{
if (m_cart)
return m_cart->read_ram(space, offset);
else
return 0xff;
}
/*-------------------------------------------------
write
@ -574,6 +666,12 @@ WRITE8_MEMBER(sega8_cart_slot_device::write_cart)
m_cart->write_cart(space, offset, data);
}
WRITE8_MEMBER(sega8_cart_slot_device::write_ram)
{
if (m_cart)
m_cart->write_ram(space, offset, data);
}
/*-------------------------------------------------
Internal header logging

View File

@ -18,7 +18,12 @@ enum
SEGA8_NEMESIS,
SEGA8_JANGGUN,
SEGA8_KOREAN,
SEGA8_KOREAN_NOBANK
SEGA8_KOREAN_NOBANK,
SEGA8_CASTLE,
SEGA8_BASIC_L3,
SEGA8_MUSIC_EDITOR,
SEGA8_DAHJEE_TYPEA,
SEGA8_DAHJEE_TYPEB
};
@ -39,6 +44,9 @@ public:
virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
virtual DECLARE_WRITE8_MEMBER(write_cart) {}
virtual DECLARE_WRITE8_MEMBER(write_mapper) {}
// a few carts (for SG1000) acts as a RAM expansion, taking control of the system RAM in 0xc000-0xffff
virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; }
virtual DECLARE_WRITE8_MEMBER(write_ram) {}
void rom_alloc(running_machine &machine, UINT32 size);
void ram_alloc(running_machine &machine, UINT32 size);
@ -132,6 +140,8 @@ public:
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
virtual DECLARE_WRITE8_MEMBER(write_mapper);
virtual DECLARE_READ8_MEMBER(read_ram);
virtual DECLARE_WRITE8_MEMBER(write_ram);
//protected:

View File

@ -1108,6 +1108,15 @@ MACHINE_START_MEMBER(sms_state,sms)
m_cards[i] = machine().device<sega8_card_slot_device>(str);
}
}
// a bunch of SG1000 carts (compatible with SG1000 Mark III) can access directly system RAM... let's install here the necessary handlers
// TODO: are BASIC and Music actually compatible with Mark III??
if (m_cartslot->get_type() == SEGA8_BASIC_L3 || m_cartslot->get_type() == SEGA8_MUSIC_EDITOR
|| m_cartslot->get_type() == SEGA8_DAHJEE_TYPEA || m_cartslot->get_type() == SEGA8_DAHJEE_TYPEB)
{
m_maincpu->space(AS_PROGRAM).install_read_handler(0xc000, 0xffff, 0, 0, read8_delegate(FUNC(sega8_cart_slot_device::read_ram),(sega8_cart_slot_device*)m_cartslot));
m_maincpu->space(AS_PROGRAM).install_write_handler(0xc000, 0xffff, 0, 0, write8_delegate(FUNC(sega8_cart_slot_device::write_ram),(sega8_cart_slot_device*)m_cartslot));
}
}
MACHINE_RESET_MEMBER(sms_state,sms)