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"/>
<part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_sintax" />
<dataarea name="rom" size="2097152">
<rom name="2003 ha li bo te 2 - xiao shi de mi shi (unlicensed, chinese) [raw dump].bin" size="2097152" crc="1b3e1243" sha1="0829cbcab3ef5d03c94d5efe769f4f4a93ac47fa"/>
<dataarea name="rom" size="0x200000">
<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 name="nvram" size="8192" />
</part>
@ -26301,8 +26301,8 @@ license:CC0
<info name="alt_title" value="哈利小子IV, 2003哈利小子IV ~ 2003 Ha Li Xiao Zi IV (Cart)"/>
<part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_sintax" />
<dataarea name="rom" size="2097152">
<rom name="2003 ha li xiao zi iv (unlicensed, chinese) [raw dump].bin" size="2097152" crc="db3c8b95" sha1="0d230b20388f4396d6345b8eb59f54fc169ad8ee"/>
<dataarea name="rom" size="0x200000">
<rom name="2003 ha li xiao zi iv (unlicensed, chinese) [raw dump].bin" size="0x200000" crc="db3c8b95" sha1="0d230b20388f4396d6345b8eb59f54fc169ad8ee"/>
</dataarea>
<dataarea name="nvram" size="8192">
</dataarea>
@ -26316,8 +26316,8 @@ license:CC0
<info name="alt_title" value="女王格鬥2000"/> <!-- translates to "Queen Fight 2000" -->
<part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_vf001" />
<dataarea name="rom" size="2097152">
<rom name="Nv Wang Ge Dou 2000 (Unl) [C] [Raw].gbc" size="2097152" crc="e1668b49" sha1="37516139aa317a16440379c1dc00bdfc4c1e607a"/>
<dataarea name="rom" size="0x200000">
<rom name="nuwang gedou.gbc" size="0x200000" crc="e1668b49" sha1="37516139aa317a16440379c1dc00bdfc4c1e607a"/>
</dataarea>
</part>
</software>
@ -26329,8 +26329,8 @@ license:CC0
<info name="alt_title" value="超級格鬥2001α"/> <!-- translates to "Super Fight 2001 Alpha" -->
<part name="cart" interface="gameboy_cart">
<feature name="slot" value="rom_vf001" />
<dataarea name="rom" size="2097152">
<rom name="Chao Ji Ge Dou 2001 Alpha (Unl) [C] [Raw].gbc" size="2097152" crc="afd7a0cc" sha1="f44f629687ec91aade40ff52014587003f728ec9"/>
<dataarea name="rom" size="0x200000">
<rom name="chaoju gedou 2001 alpha.gbc" size="0x200000" crc="afd7a0cc" sha1="f44f629687ec91aade40ff52014587003f728ec9"/>
</dataarea>
</part>
</software>
@ -26345,8 +26345,8 @@ license:CC0
<part name="cart" interface="gameboy_cart">
<feature name="pcb" value="HK0819" />
<feature name="slot" value="rom_newgbchk" />
<dataarea name="rom" size="1048576">
<rom name="koudai guaishou dongzuo pian.gbc" size="1048576" crc="14355371" sha1="f398086d1f8cb435a632e5ea45fb19e980b0568d" />
<dataarea name="rom" size="0x100000">
<rom name="koudai guaishou dongzuo pian.gbc" size="0x100000" crc="14355371" sha1="f398086d1f8cb435a632e5ea45fb19e980b0568d" />
</dataarea>
</part>
</software>
@ -26360,13 +26360,27 @@ license:CC0
<part name="cart" interface="gameboy_cart">
<feature name="pcb" value="HK0701" />
<feature name="slot" value="rom_newgbchk" />
<dataarea name="rom" size="1048576">
<rom name="guaishou go go ii.gbc" size="1048576" crc="b0237467" sha1="8ed6f39a9973d634266806455ef845b6bdb5ab95" />
<dataarea name="rom" size="0x100000">
<rom name="guaishou go go ii.gbc" size="0x100000" crc="b0237467" sha1="8ed6f39a9973d634266806455ef845b6bdb5ab95" />
</dataarea>
<dataarea name="nvram" size="8192" />
</part>
</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">
<description>E Mo Dao (China, ripped from 8 in 1 multicart)</description>
<year>200?</year>
@ -27601,7 +27615,7 @@ license:CC0
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
-->
<description>Super Mario 3 Special (China)</description>
<description>Super Mario 3 Special (China)</description>
<year>2000</year>
<publisher>Yong Yong</publisher>
<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/rom.cpp",
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.h",
MAME_DIR .. "src/devices/bus/gameboy/tama5.cpp",

View File

@ -18,6 +18,7 @@
#include "mbc7.h"
#include "mmm01.h"
#include "rom.h"
#include "slmulti.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_VF001 = "rom_vf001";
char const *const GB_DIGIMON = "rom_digimon";
char const *const GB_SLMULTI = "rom_slmulti";
char const *const MEGADUCK_STD = "rom";
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_VF001, GB_ROM_VF001);
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_VF001;
extern char const *const GB_DIGIMON;
extern char const *const GB_SLMULTI;
extern char const *const MEGADUCK_STD;
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:
result = slotoptions::GB_VF001;
break;
case gbxfile::TYPE_SLMULTI:
result = slotoptions::GB_SLMULTI;
break;
}
if (result)
{

View File

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

View File

@ -103,7 +103,8 @@ private:
void install_ram() ATTR_COLD;
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_bank_array_creator<2> m_bank_rom;
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_gb_cart_interface(mconfig, *this),
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_bank_rom(*this, { "romlow", "romhigh" }),
m_bank_ram(*this, { "ramlow", "ramhigh" }),
@ -148,8 +150,8 @@ image_init_result mbc6_device::load(std::string &message)
return image_init_result::FAIL;
// install views for ROM/flash and RAM
cart_space()->install_view(0x4000, 0x5fff, m_view_rom[0]);
cart_space()->install_view(0x6000, 0x7fff, m_view_rom[1]);
cart_space()->install_view(0x4000, 0x5fff, m_view_rom_low);
cart_space()->install_view(0x6000, 0x7fff, m_view_rom_high);
cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
// 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)));
// install Flash handlers
m_view_rom[0][1].install_readwrite_handler(
m_view_rom_low[1].install_readwrite_handler(
0x4000, 0x5fff,
read8sm_delegate(*this, FUNC(mbc6_device::read_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,
read8sm_delegate(*this, FUNC(mbc6_device::read_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_writable = 0U;
m_view_rom[0].select(0);
m_view_rom[1].select(0);
m_view_rom_low.select(0);
m_view_rom_high.select(0);
m_view_ram.disable();
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)
{
auto const bank(BIT(offset, 12));
memory_view &view(bank ? m_view_rom_high : m_view_rom_low);
m_bank_sel_rom[bank] = data;
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",
machine().describe_context(),
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
{
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)
{
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);
if (m_flash_select[bank])
{
@ -313,9 +317,9 @@ void mbc6_device::select_flash(offs_t offset, u8 data)
bank ? "high" : "low",
m_flash_enable ? "enabled" : "disabled");
if (m_flash_enable)
m_view_rom[bank].select(1);
view.select(1);
else
m_view_rom[bank].disable();
view.disable();
}
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",
machine().describe_context(),
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
{
@ -331,7 +335,7 @@ void mbc6_device::select_flash(offs_t offset, u8 data)
"%s: ROM bank %s selected\n",
machine().describe_context(),
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?
@ -372,17 +376,17 @@ void mbc6_device::enable_flash(u8 data)
{
LOG("%s: Flash enabled\n", machine().describe_context());
if (m_flash_select[0])
m_view_rom[0].select(1);
m_view_rom_low.select(1);
if (m_flash_select[1])
m_view_rom[1].select(1);
m_view_rom_high.select(1);
}
else
{
LOG("%s: Flash disabled\n", machine().describe_context());
if (m_flash_select[0])
m_view_rom[0].disable();
m_view_rom_low.disable();
if (m_flash_select[1])
m_view_rom[1].disable();
m_view_rom_high.disable();
}
if (data & ~0x01)
@ -484,8 +488,8 @@ void mbc6_device::install_rom()
if (!rombytes)
{
// just avoid fatal errors
m_view_rom[0][0];
m_view_rom[1][0];
m_view_rom_low[0];
m_view_rom_high[0];
m_bank_mask_rom = 0U;
}
else if (PAGE_ROM_SIZE >= rombytes)
@ -507,8 +511,8 @@ void mbc6_device::install_rom()
end,
mirror);
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[1][0].install_rom(0x6000 | begin, 0x6000 | end, mirror, &base[src]);
m_view_rom_low[0].install_rom(0x4000 | begin, 0x4000 | end, mirror, &base[src]);
m_view_rom_high[0].install_rom(0x6000 | begin, 0x6000 | end, mirror, &base[src]);
});
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[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[1][0].install_read_bank(0x6000, 0x7fff, m_bank_rom[1]);
m_view_rom_low[0].install_read_bank(0x4000, 0x5fff, m_bank_rom[0]);
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