mirror of
https://github.com/holub/mame
synced 2025-04-26 18:23:08 +03:00
(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:
parent
5ed2398162
commit
5b3ba478c9
@ -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 )
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user