bus/gameboy: Added partial support for some Chinese multi-game cartridges.

Cartridge RAM features are not implemented yet.

New working software list items
---------------------
gbcolor.xml: New Super Color 145 in 1 (China) [taizou, Vas Crabb]
This commit is contained in:
Vas Crabb 2022-09-18 06:05:43 +10:00
parent 8b4eee0898
commit 33f2b34198
9 changed files with 318 additions and 37 deletions

View File

@ -26287,8 +26287,8 @@ license:CC0
<info name="alt_title" value="2003哈利波特2-消失的密室 ~ 2003 Harry Potter 2 - Xiao Shi De Mi Shi"/> <info name="alt_title" value="2003哈利波特2-消失的密室 ~ 2003 Harry Potter 2 - Xiao Shi De Mi Shi"/>
<part name="cart" interface="gameboy_cart"> <part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_sintax" /> <feature name="slot" value="rom_sintax" />
<dataarea name="rom" size="2097152"> <dataarea name="rom" size="0x200000">
<rom name="2003 ha li bo te 2 - xiao shi de mi shi (unlicensed, chinese) [raw dump].bin" size="2097152" crc="1b3e1243" sha1="0829cbcab3ef5d03c94d5efe769f4f4a93ac47fa"/> <rom name="2003 ha li bo te 2 - xiao shi de mi shi (unlicensed, chinese) [raw dump].bin" size="0x200000" crc="1b3e1243" sha1="0829cbcab3ef5d03c94d5efe769f4f4a93ac47fa"/>
</dataarea> </dataarea>
<dataarea name="nvram" size="8192" /> <dataarea name="nvram" size="8192" />
</part> </part>
@ -26301,8 +26301,8 @@ license:CC0
<info name="alt_title" value="哈利小子IV, 2003哈利小子IV ~ 2003 Ha Li Xiao Zi IV (Cart)"/> <info name="alt_title" value="哈利小子IV, 2003哈利小子IV ~ 2003 Ha Li Xiao Zi IV (Cart)"/>
<part name="cart" interface="gameboy_cart"> <part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_sintax" /> <feature name="slot" value="rom_sintax" />
<dataarea name="rom" size="2097152"> <dataarea name="rom" size="0x200000">
<rom name="2003 ha li xiao zi iv (unlicensed, chinese) [raw dump].bin" size="2097152" crc="db3c8b95" sha1="0d230b20388f4396d6345b8eb59f54fc169ad8ee"/> <rom name="2003 ha li xiao zi iv (unlicensed, chinese) [raw dump].bin" size="0x200000" crc="db3c8b95" sha1="0d230b20388f4396d6345b8eb59f54fc169ad8ee"/>
</dataarea> </dataarea>
<dataarea name="nvram" size="8192"> <dataarea name="nvram" size="8192">
</dataarea> </dataarea>
@ -26316,8 +26316,8 @@ license:CC0
<info name="alt_title" value="女王格鬥2000"/> <!-- translates to "Queen Fight 2000" --> <info name="alt_title" value="女王格鬥2000"/> <!-- translates to "Queen Fight 2000" -->
<part name="cart" interface="gameboy_cart"> <part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_vf001" /> <feature name="slot" value="rom_vf001" />
<dataarea name="rom" size="2097152"> <dataarea name="rom" size="0x200000">
<rom name="Nv Wang Ge Dou 2000 (Unl) [C] [Raw].gbc" size="2097152" crc="e1668b49" sha1="37516139aa317a16440379c1dc00bdfc4c1e607a"/> <rom name="nuwang gedou.gbc" size="0x200000" crc="e1668b49" sha1="37516139aa317a16440379c1dc00bdfc4c1e607a"/>
</dataarea> </dataarea>
</part> </part>
</software> </software>
@ -26329,8 +26329,8 @@ license:CC0
<info name="alt_title" value="超級格鬥2001α"/> <!-- translates to "Super Fight 2001 Alpha" --> <info name="alt_title" value="超級格鬥2001α"/> <!-- translates to "Super Fight 2001 Alpha" -->
<part name="cart" interface="gameboy_cart"> <part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_vf001" /> <feature name="slot" value="rom_vf001" />
<dataarea name="rom" size="2097152"> <dataarea name="rom" size="0x200000">
<rom name="Chao Ji Ge Dou 2001 Alpha (Unl) [C] [Raw].gbc" size="2097152" crc="afd7a0cc" sha1="f44f629687ec91aade40ff52014587003f728ec9"/> <rom name="chaoju gedou 2001 alpha.gbc" size="0x200000" crc="afd7a0cc" sha1="f44f629687ec91aade40ff52014587003f728ec9"/>
</dataarea> </dataarea>
</part> </part>
</software> </software>
@ -26345,8 +26345,8 @@ license:CC0
<part name="cart" interface="gameboy_cart"> <part name="cart" interface="gameboy_cart">
<feature name="pcb" value="HK0819" /> <feature name="pcb" value="HK0819" />
<feature name="slot" value="rom_newgbchk" /> <feature name="slot" value="rom_newgbchk" />
<dataarea name="rom" size="1048576"> <dataarea name="rom" size="0x100000">
<rom name="koudai guaishou dongzuo pian.gbc" size="1048576" crc="14355371" sha1="f398086d1f8cb435a632e5ea45fb19e980b0568d" /> <rom name="koudai guaishou dongzuo pian.gbc" size="0x100000" crc="14355371" sha1="f398086d1f8cb435a632e5ea45fb19e980b0568d" />
</dataarea> </dataarea>
</part> </part>
</software> </software>
@ -26360,13 +26360,27 @@ license:CC0
<part name="cart" interface="gameboy_cart"> <part name="cart" interface="gameboy_cart">
<feature name="pcb" value="HK0701" /> <feature name="pcb" value="HK0701" />
<feature name="slot" value="rom_newgbchk" /> <feature name="slot" value="rom_newgbchk" />
<dataarea name="rom" size="1048576"> <dataarea name="rom" size="0x100000">
<rom name="guaishou go go ii.gbc" size="1048576" crc="b0237467" sha1="8ed6f39a9973d634266806455ef845b6bdb5ab95" /> <rom name="guaishou go go ii.gbc" size="0x100000" crc="b0237467" sha1="8ed6f39a9973d634266806455ef845b6bdb5ab95" />
</dataarea> </dataarea>
<dataarea name="nvram" size="8192" /> <dataarea name="nvram" size="8192" />
</part> </part>
</software> </software>
<!-- some games don't work on gbcolor (e.g. 02. KOF98 works on gameboy but not gbcolor) -->
<software name="145in1" supported="partial">
<description>New Super Color 145 in 1 (China)</description>
<year>200?</year>
<publisher>J.Y. Company</publisher>
<info name="usage" value="Use hard reset to return to game selection menu." />
<part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_slmulti" />
<dataarea name="rom" size="0x1000000">
<rom name="new super color 145 in 1.gbc" size="0x1000000" crc="12345678" sha1="cbeb1745d68163978a422a8d7260a6a0f2693b85" />
</dataarea>
</part>
</software>
<software name="emodao"> <software name="emodao">
<description>E Mo Dao (China, ripped from 8 in 1 multicart)</description> <description>E Mo Dao (China, ripped from 8 in 1 multicart)</description>
<year>200?</year> <year>200?</year>
@ -27601,7 +27615,7 @@ license:CC0
used here repeated twice. we need to redump the standalone cart to confirm the size used here repeated twice. we need to redump the standalone cart to confirm the size
but the 256KB version is definitely underdumped and misses sprite data but the 256KB version is definitely underdumped and misses sprite data
--> -->
<description>Super Mario 3 Special (China)</description> <description>Super Mario 3 Special (China)</description>
<year>2000</year> <year>2000</year>
<publisher>Yong Yong</publisher> <publisher>Yong Yong</publisher>
<part name="cart" interface="gameboy_cart"> <part name="cart" interface="gameboy_cart">

View File

@ -3719,6 +3719,8 @@ if (BUSES["GAMEBOY"]~=null) then
MAME_DIR .. "src/devices/bus/gameboy/mmm01.h", MAME_DIR .. "src/devices/bus/gameboy/mmm01.h",
MAME_DIR .. "src/devices/bus/gameboy/rom.cpp", MAME_DIR .. "src/devices/bus/gameboy/rom.cpp",
MAME_DIR .. "src/devices/bus/gameboy/rom.h", MAME_DIR .. "src/devices/bus/gameboy/rom.h",
MAME_DIR .. "src/devices/bus/gameboy/slmulti.cpp",
MAME_DIR .. "src/devices/bus/gameboy/slmulti.h",
MAME_DIR .. "src/devices/bus/gameboy/slot.cpp", MAME_DIR .. "src/devices/bus/gameboy/slot.cpp",
MAME_DIR .. "src/devices/bus/gameboy/slot.h", MAME_DIR .. "src/devices/bus/gameboy/slot.h",
MAME_DIR .. "src/devices/bus/gameboy/tama5.cpp", MAME_DIR .. "src/devices/bus/gameboy/tama5.cpp",

View File

@ -18,6 +18,7 @@
#include "mbc7.h" #include "mbc7.h"
#include "mmm01.h" #include "mmm01.h"
#include "rom.h" #include "rom.h"
#include "slmulti.h"
#include "tama5.h" #include "tama5.h"
@ -53,6 +54,7 @@ char const *const GB_LICHENG = "rom_licheng";
char const *const GB_NEWGBCHK = "rom_newgbchk"; char const *const GB_NEWGBCHK = "rom_newgbchk";
char const *const GB_VF001 = "rom_vf001"; char const *const GB_VF001 = "rom_vf001";
char const *const GB_DIGIMON = "rom_digimon"; char const *const GB_DIGIMON = "rom_digimon";
char const *const GB_SLMULTI = "rom_slmulti";
char const *const MEGADUCK_STD = "rom"; char const *const MEGADUCK_STD = "rom";
char const *const MEGADUCK_BANKED = "rom_banked"; char const *const MEGADUCK_BANKED = "rom_banked";
@ -95,6 +97,7 @@ void gameboy_cartridges(device_slot_interface &device)
device.option_add_internal(slotoptions::GB_NEWGBCHK, GB_ROM_NEWGBCHK); device.option_add_internal(slotoptions::GB_NEWGBCHK, GB_ROM_NEWGBCHK);
device.option_add_internal(slotoptions::GB_VF001, GB_ROM_VF001); device.option_add_internal(slotoptions::GB_VF001, GB_ROM_VF001);
device.option_add_internal(slotoptions::GB_DIGIMON, GB_ROM_DIGIMON); device.option_add_internal(slotoptions::GB_DIGIMON, GB_ROM_DIGIMON);
device.option_add_internal(slotoptions::GB_SLMULTI, GB_ROM_SLMULTI);
} }

View File

@ -47,6 +47,7 @@ extern char const *const GB_LICHENG;
extern char const *const GB_NEWGBCHK; extern char const *const GB_NEWGBCHK;
extern char const *const GB_VF001; extern char const *const GB_VF001;
extern char const *const GB_DIGIMON; extern char const *const GB_DIGIMON;
extern char const *const GB_SLMULTI;
extern char const *const MEGADUCK_STD; extern char const *const MEGADUCK_STD;
extern char const *const MEGADUCK_BANKED; extern char const *const MEGADUCK_BANKED;

View File

@ -743,6 +743,9 @@ std::optional<char const *> probe_gbx_footer(std::string_view tag, util::random_
case gbxfile::TYPE_VF001: case gbxfile::TYPE_VF001:
result = slotoptions::GB_VF001; result = slotoptions::GB_VF001;
break; break;
case gbxfile::TYPE_SLMULTI:
result = slotoptions::GB_SLMULTI;
break;
} }
if (result) if (result)
{ {

View File

@ -53,6 +53,7 @@ enum : u32
TYPE_CAMERA = 0x43414d52, // 'CAMR' TYPE_CAMERA = 0x43414d52, // 'CAMR'
TYPE_HUC1 = 0x48554331, // 'HUC1' TYPE_HUC1 = 0x48554331, // 'HUC1'
TYPE_HUC3 = 0x48554333, // 'HUC3' TYPE_HUC3 = 0x48554333, // 'HUC3'
TYPE_SLMULTI = 0x4c424d43, // 'LBMC'
TYPE_LICHENG = 0x4c494348, // 'LICH' TYPE_LICHENG = 0x4c494348, // 'LICH'
TYPE_M161 = 0x4d313631, // 'M161' TYPE_M161 = 0x4d313631, // 'M161'
TYPE_MBC1_COLL = 0x4d42314d, // 'MB1M' TYPE_MBC1_COLL = 0x4d42314d, // 'MB1M'

View File

@ -103,7 +103,8 @@ private:
void install_ram() ATTR_COLD; void install_ram() ATTR_COLD;
required_device<intelfsh8_device> m_flash; required_device<intelfsh8_device> m_flash;
memory_view m_view_rom[2]; memory_view m_view_rom_low;
memory_view m_view_rom_high;
memory_view m_view_ram; memory_view m_view_ram;
memory_bank_array_creator<2> m_bank_rom; memory_bank_array_creator<2> m_bank_rom;
memory_bank_array_creator<2> m_bank_ram; memory_bank_array_creator<2> m_bank_ram;
@ -126,7 +127,8 @@ mbc6_device::mbc6_device(
device_t(mconfig, GB_ROM_MBC6, tag, owner, clock), device_t(mconfig, GB_ROM_MBC6, tag, owner, clock),
device_gb_cart_interface(mconfig, *this), device_gb_cart_interface(mconfig, *this),
m_flash(*this, "flash"), m_flash(*this, "flash"),
m_view_rom{ { *this, "romlow" }, { *this, "romhigh" } }, m_view_rom_low(*this, "romlow"),
m_view_rom_high(*this, "romhigh" ),
m_view_ram(*this, "ram"), m_view_ram(*this, "ram"),
m_bank_rom(*this, { "romlow", "romhigh" }), m_bank_rom(*this, { "romlow", "romhigh" }),
m_bank_ram(*this, { "ramlow", "ramhigh" }), m_bank_ram(*this, { "ramlow", "ramhigh" }),
@ -148,8 +150,8 @@ image_init_result mbc6_device::load(std::string &message)
return image_init_result::FAIL; return image_init_result::FAIL;
// install views for ROM/flash and RAM // install views for ROM/flash and RAM
cart_space()->install_view(0x4000, 0x5fff, m_view_rom[0]); cart_space()->install_view(0x4000, 0x5fff, m_view_rom_low);
cart_space()->install_view(0x6000, 0x7fff, m_view_rom[1]); cart_space()->install_view(0x6000, 0x7fff, m_view_rom_high);
cart_space()->install_view(0xa000, 0xbfff, m_view_ram); cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
// set up ROM and RAM as appropriate // set up ROM and RAM as appropriate
@ -180,11 +182,11 @@ image_init_result mbc6_device::load(std::string &message)
write8sm_delegate(*this, FUNC(mbc6_device::select_flash))); write8sm_delegate(*this, FUNC(mbc6_device::select_flash)));
// install Flash handlers // install Flash handlers
m_view_rom[0][1].install_readwrite_handler( m_view_rom_low[1].install_readwrite_handler(
0x4000, 0x5fff, 0x4000, 0x5fff,
read8sm_delegate(*this, FUNC(mbc6_device::read_flash<0>)), read8sm_delegate(*this, FUNC(mbc6_device::read_flash<0>)),
write8sm_delegate(*this, FUNC(mbc6_device::write_flash<0>))); write8sm_delegate(*this, FUNC(mbc6_device::write_flash<0>)));
m_view_rom[1][1].install_readwrite_handler( m_view_rom_high[1].install_readwrite_handler(
0x6000, 0x7fff, 0x6000, 0x7fff,
read8sm_delegate(*this, FUNC(mbc6_device::read_flash<1>)), read8sm_delegate(*this, FUNC(mbc6_device::read_flash<1>)),
write8sm_delegate(*this, FUNC(mbc6_device::write_flash<1>))); write8sm_delegate(*this, FUNC(mbc6_device::write_flash<1>)));
@ -227,8 +229,8 @@ void mbc6_device::device_reset()
m_flash_enable = 0U; m_flash_enable = 0U;
m_flash_writable = 0U; m_flash_writable = 0U;
m_view_rom[0].select(0); m_view_rom_low.select(0);
m_view_rom[1].select(0); m_view_rom_high.select(0);
m_view_ram.disable(); m_view_ram.disable();
if (m_bank_mask_rom) if (m_bank_mask_rom)
@ -270,6 +272,7 @@ void mbc6_device::write_flash(offs_t offset, u8 data)
void mbc6_device::bank_switch_rom(offs_t offset, u8 data) void mbc6_device::bank_switch_rom(offs_t offset, u8 data)
{ {
auto const bank(BIT(offset, 12)); auto const bank(BIT(offset, 12));
memory_view &view(bank ? m_view_rom_high : m_view_rom_low);
m_bank_sel_rom[bank] = data; m_bank_sel_rom[bank] = data;
if (!m_flash_select[bank]) if (!m_flash_select[bank])
@ -280,11 +283,11 @@ void mbc6_device::bank_switch_rom(offs_t offset, u8 data)
"%s: ROM bank %s unmapped\n", "%s: ROM bank %s unmapped\n",
machine().describe_context(), machine().describe_context(),
bank ? "high" : "low"); bank ? "high" : "low");
m_view_rom[bank].disable(); // is there a chip select for a second program ROM? view.disable(); // is there a chip select for a second program ROM?
} }
else else
{ {
m_view_rom[bank].select(0); view.select(0);
} }
} }
@ -304,6 +307,7 @@ void mbc6_device::bank_switch_rom(offs_t offset, u8 data)
void mbc6_device::select_flash(offs_t offset, u8 data) void mbc6_device::select_flash(offs_t offset, u8 data)
{ {
auto const bank(BIT(offset, 12)); auto const bank(BIT(offset, 12));
memory_view &view(bank ? m_view_rom_high : m_view_rom_low);
m_flash_select[bank] = BIT(data, 3); m_flash_select[bank] = BIT(data, 3);
if (m_flash_select[bank]) if (m_flash_select[bank])
{ {
@ -313,9 +317,9 @@ void mbc6_device::select_flash(offs_t offset, u8 data)
bank ? "high" : "low", bank ? "high" : "low",
m_flash_enable ? "enabled" : "disabled"); m_flash_enable ? "enabled" : "disabled");
if (m_flash_enable) if (m_flash_enable)
m_view_rom[bank].select(1); view.select(1);
else else
m_view_rom[bank].disable(); view.disable();
} }
else if (BIT(m_bank_sel_rom[bank], 7)) else if (BIT(m_bank_sel_rom[bank], 7))
{ {
@ -323,7 +327,7 @@ void mbc6_device::select_flash(offs_t offset, u8 data)
"%s: ROM bank %s unmapped\n", "%s: ROM bank %s unmapped\n",
machine().describe_context(), machine().describe_context(),
bank ? "high" : "low"); bank ? "high" : "low");
m_view_rom[bank].disable(); // is there a chip select for a second program ROM? view.disable(); // is there a chip select for a second program ROM?
} }
else else
{ {
@ -331,7 +335,7 @@ void mbc6_device::select_flash(offs_t offset, u8 data)
"%s: ROM bank %s selected\n", "%s: ROM bank %s selected\n",
machine().describe_context(), machine().describe_context(),
bank ? "high" : "low"); bank ? "high" : "low");
m_view_rom[bank].select(0); view.select(0);
} }
// game writes 0xc6 when selecting ROM during boot - what do the other bits do? // game writes 0xc6 when selecting ROM during boot - what do the other bits do?
@ -372,17 +376,17 @@ void mbc6_device::enable_flash(u8 data)
{ {
LOG("%s: Flash enabled\n", machine().describe_context()); LOG("%s: Flash enabled\n", machine().describe_context());
if (m_flash_select[0]) if (m_flash_select[0])
m_view_rom[0].select(1); m_view_rom_low.select(1);
if (m_flash_select[1]) if (m_flash_select[1])
m_view_rom[1].select(1); m_view_rom_high.select(1);
} }
else else
{ {
LOG("%s: Flash disabled\n", machine().describe_context()); LOG("%s: Flash disabled\n", machine().describe_context());
if (m_flash_select[0]) if (m_flash_select[0])
m_view_rom[0].disable(); m_view_rom_low.disable();
if (m_flash_select[1]) if (m_flash_select[1])
m_view_rom[1].disable(); m_view_rom_high.disable();
} }
if (data & ~0x01) if (data & ~0x01)
@ -484,8 +488,8 @@ void mbc6_device::install_rom()
if (!rombytes) if (!rombytes)
{ {
// just avoid fatal errors // just avoid fatal errors
m_view_rom[0][0]; m_view_rom_low[0];
m_view_rom[1][0]; m_view_rom_high[0];
m_bank_mask_rom = 0U; m_bank_mask_rom = 0U;
} }
else if (PAGE_ROM_SIZE >= rombytes) else if (PAGE_ROM_SIZE >= rombytes)
@ -507,8 +511,8 @@ void mbc6_device::install_rom()
end, end,
mirror); mirror);
cart_space()->install_rom(begin, end, 0x2000 | mirror, &base[src]); cart_space()->install_rom(begin, end, 0x2000 | mirror, &base[src]);
m_view_rom[0][0].install_rom(0x4000 | begin, 0x4000 | end, mirror, &base[src]); m_view_rom_low[0].install_rom(0x4000 | begin, 0x4000 | end, mirror, &base[src]);
m_view_rom[1][0].install_rom(0x6000 | begin, 0x6000 | end, mirror, &base[src]); m_view_rom_high[0].install_rom(0x6000 | begin, 0x6000 | end, mirror, &base[src]);
}); });
m_bank_mask_rom = 0U; m_bank_mask_rom = 0U;
} }
@ -533,8 +537,8 @@ void mbc6_device::install_rom()
m_bank_rom[0]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]); m_bank_rom[0]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
m_bank_rom[1]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]); m_bank_rom[1]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
}); });
m_view_rom[0][0].install_read_bank(0x4000, 0x5fff, m_bank_rom[0]); m_view_rom_low[0].install_read_bank(0x4000, 0x5fff, m_bank_rom[0]);
m_view_rom[1][0].install_read_bank(0x6000, 0x7fff, m_bank_rom[1]); m_view_rom_high[0].install_read_bank(0x6000, 0x7fff, m_bank_rom[1]);
} }
} }

View File

@ -0,0 +1,235 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************
Chinese multi-game cartridges by SL and possibly others
Supports collections containing very large numbers of games designed for
MBC1 and MBC5 cartridges.
***************************************************************************/
#include "emu.h"
#include "slmulti.h"
#include "cartbase.h"
#include <string>
//#define VERBOSE 1
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
namespace bus::gameboy {
namespace {
class slmulti_device : public mbc_dual_uniform_device_base
{
public:
slmulti_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
virtual image_init_result load(std::string &message) override ATTR_COLD;
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
private:
void bank_switch_rom_fine(u8 data);
void bank_switch_rom_coarse(u8 data);
void set_config_cmd(u8 data);
void do_config_cmd(u8 data);
void update_bank_rom_high()
{
u16 const page(bank_rom_entry_high());
LOG(
"%s: Set high ROM page 0x%03X (0x%06X)\n",
machine().describe_context(),
page,
u32(page) << 14);
set_bank_rom_high(page);
}
u16 bank_rom_entry_high() const noexcept
{
u16 const hi(m_high_page & m_page_mask);
return (m_base_page & ~m_page_mask) | (hi ? hi : (m_zero_remap & m_page_mask));
}
memory_view m_view_ctrl;
u16 m_base_page;
u16 m_high_page;
u16 m_page_mask;
u16 m_zero_remap;
u8 m_config_cmd;
};
slmulti_device::slmulti_device(
machine_config const &mconfig,
char const *tag,
device_t *owner,
u32 clock) :
mbc_dual_uniform_device_base(mconfig, GB_ROM_SLMULTI, tag, owner, clock),
m_view_ctrl(*this, "ctrl"),
m_base_page(0U),
m_high_page(0U),
m_page_mask(0U),
m_zero_remap(0U),
m_config_cmd(0U)
{
}
image_init_result slmulti_device::load(std::string &message)
{
// set up ROM
set_bank_bits_rom(10);
if (!check_rom(message))
return image_init_result::FAIL;
install_rom();
// install memory mapping control handlers
cart_space()->install_view(
0x2000, 0x7fff,
m_view_ctrl);
cart_space()->install_write_handler(
0x2000, 0x3fff,
write8smo_delegate(*this, FUNC(slmulti_device::bank_switch_rom_fine)));
// this is for MBC5 games
m_view_ctrl[0].install_write_handler(
0x3000, 0x3fff,
write8smo_delegate(*this, FUNC(slmulti_device::bank_switch_rom_coarse)));
// install configuration handlers over the top
m_view_ctrl[1].install_write_handler(
0x5000, 0x5fff,
write8smo_delegate(*this, FUNC(slmulti_device::set_config_cmd)));
m_view_ctrl[1].install_write_handler(
0x7000, 0x7fff,
write8smo_delegate(*this, FUNC(slmulti_device::do_config_cmd)));
// do this here - the menu program apparently does a system reset to get into DMG mode
m_view_ctrl.select(1);
// all good
return image_init_result::PASS;
}
void slmulti_device::device_start()
{
mbc_dual_uniform_device_base::device_start();
m_base_page = 0U;
m_high_page = 0U;
m_page_mask = 1U;
m_zero_remap = 0U;
m_config_cmd = 0U;
save_item(NAME(m_base_page));
save_item(NAME(m_high_page));
save_item(NAME(m_page_mask));
save_item(NAME(m_zero_remap));
save_item(NAME(m_config_cmd));
}
void slmulti_device::device_reset()
{
mbc_dual_uniform_device_base::device_reset();
set_bank_rom_low(m_base_page & ~m_page_mask);
update_bank_rom_high();
}
void slmulti_device::bank_switch_rom_fine(u8 data)
{
m_high_page = data;
update_bank_rom_high();
}
void slmulti_device::bank_switch_rom_coarse(u8 data)
{
// there's no way to specify a 9-bit page mask, so MBC5 games larger than 4 MiB can't be supported
LOG("%s Set coarse ROM bank 0x%02X\n", machine().describe_context(), data);
}
void slmulti_device::set_config_cmd(u8 data)
{
LOG("%s: Set configuration command 0x%02X\n", machine().describe_context(), data);
m_config_cmd = data;
}
void slmulti_device::do_config_cmd(u8 data)
{
switch (m_config_cmd)
{
case 0x55:
// bit 4 unknown
m_base_page = (m_base_page & ~0x0200) | (u16(BIT(data, 3)) << 9);
m_page_mask = (2U << BIT(~data, 0, 3)) - 1;
switch (BIT(data, 5, 2))
{
case 0x0: // used for MBC5 games
m_zero_remap = 0U;
m_view_ctrl.select(0);
break;
case 0x3: // used for MBC1 games
m_zero_remap = 1U;
m_view_ctrl.disable();
break;
default:
logerror(
"%s: Unknown memory mapping mode 0x%X\n",
machine().describe_context(),
BIT(data, 5, 2));
m_view_ctrl.disable();
}
LOG(
"%s: Set base page = 0x%03X (0x%06X), page mask = 0x%03X, zero remap = 0x%03X%s\n",
machine().describe_context(),
m_base_page,
u32(m_base_page) << 14,
m_page_mask,
m_zero_remap,
BIT(data, 7) ? ", reset" : "");
set_bank_rom_low(m_base_page & ~m_page_mask);
update_bank_rom_high();
if (BIT(data, 7))
machine().root_device().reset(); // TODO: expose reset line on cartridge interface
break;
case 0xaa:
m_base_page = (m_base_page & ~0x01fe) | (u16(data) << 1);
LOG(
"%s: Set base page = 0x%03X (0x%06X)\n",
machine().describe_context(),
m_base_page,
u32(m_base_page) << 14);
break;
default:
LOG(
"%s: Unknown configuration command 0x%02X with argument 0x%02X\n",
machine().describe_context(),
m_config_cmd,
data);
}
}
} // anonymous namespace
} // namespace bus::gameboy
DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SLMULTI, device_gb_cart_interface, bus::gameboy::slmulti_device, "gb_rom_slmulti", "Game Boy SL Multi-Game Cartridge")

View File

@ -0,0 +1,18 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************
Chinese multi-game cartridges by SL and possibly others
***************************************************************************/
#ifndef MAME_BUS_GAMEBOY_SLMULTI_H
#define MAME_BUS_GAMEBOY_SLMULTI_H
#pragma once
#include "slot.h"
DECLARE_DEVICE_TYPE(GB_ROM_SLMULTI, device_gb_cart_interface)
#endif // MAME_BUS_GAMEBOY_SLMULTI_H