summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2022-09-19 03:22:19 +1000
committer Vas Crabb <vas@vastheman.com>2022-09-19 03:26:16 +1000
commit796d8d672081bcc3bcc9036bdcfbb990b24bba80 (patch)
treebdeb85094c960d62d1dc90888a9044d23a6b704e /src
parentee4095f2f0e67cd788349e726c1c84aa923c7b27 (diff)
bus/gameboy: Fixes for multi-game cartridges.
* Reset the system from a timer callback for the Vast Fame/SL/J.Y. Company multi-game cartridges. This fixes games on gbcolor. * Reset system when leaving configuration mode for GBCK003. Fixes most issues with games. * Moved GBCK003 to its own source file, and added notes for both multi-game cartridge types.
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/gameboy/carts.cpp5
-rw-r--r--src/devices/bus/gameboy/carts.h2
-rw-r--r--src/devices/bus/gameboy/gbck003.cpp259
-rw-r--r--src/devices/bus/gameboy/gbck003.h18
-rw-r--r--src/devices/bus/gameboy/gbslot.cpp4
-rw-r--r--src/devices/bus/gameboy/rom.cpp164
-rw-r--r--src/devices/bus/gameboy/rom.h1
-rw-r--r--src/devices/bus/gameboy/slmulti.cpp80
8 files changed, 361 insertions, 172 deletions
diff --git a/src/devices/bus/gameboy/carts.cpp b/src/devices/bus/gameboy/carts.cpp
index 94ffa62cec9..8bb63cf3cbd 100644
--- a/src/devices/bus/gameboy/carts.cpp
+++ b/src/devices/bus/gameboy/carts.cpp
@@ -10,6 +10,7 @@
#include "carts.h"
#include "camera.h"
+#include "gbck003.h"
#include "huc1.h"
#include "huc3.h"
#include "mbc.h"
@@ -34,7 +35,6 @@ char const *const GB_SACHEN1 = "rom_sachen1";
char const *const GB_SACHEN2 = "rom_sachen2";
char const *const GB_ROCKET = "rom_rocket";
char const *const GB_LASAMA = "rom_lasama";
-char const *const GB_GBCK003 = "rom_gbck003";
char const *const GB_MBC1 = "rom_mbc1";
char const *const GB_MBC2 = "rom_mbc2";
char const *const GB_MBC3 = "rom_mbc3";
@@ -55,6 +55,7 @@ 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 GB_GBCK003 = "rom_gbck003";
char const *const MEGADUCK_STD = "rom";
char const *const MEGADUCK_BANKED = "rom_banked";
@@ -76,7 +77,6 @@ void gameboy_cartridges(device_slot_interface &device)
device.option_add_internal(slotoptions::GB_SACHEN2, GB_ROM_SACHEN2);
device.option_add_internal(slotoptions::GB_ROCKET, GB_ROM_ROCKET);
device.option_add_internal(slotoptions::GB_LASAMA, GB_ROM_LASAMA);
- device.option_add_internal(slotoptions::GB_GBCK003, GB_ROM_GBCK003);
device.option_add_internal(slotoptions::GB_MBC1, GB_ROM_MBC1);
device.option_add_internal(slotoptions::GB_MBC2, GB_ROM_MBC2);
device.option_add_internal(slotoptions::GB_MBC3, GB_ROM_MBC3);
@@ -98,6 +98,7 @@ void gameboy_cartridges(device_slot_interface &device)
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);
+ device.option_add_internal(slotoptions::GB_GBCK003, GB_ROM_GBCK003);
}
diff --git a/src/devices/bus/gameboy/carts.h b/src/devices/bus/gameboy/carts.h
index 47c8e8b7568..e0227401a76 100644
--- a/src/devices/bus/gameboy/carts.h
+++ b/src/devices/bus/gameboy/carts.h
@@ -26,7 +26,6 @@ extern char const *const GB_SACHEN1;
extern char const *const GB_SACHEN2;
extern char const *const GB_ROCKET;
extern char const *const GB_LASAMA;
-extern char const *const GB_GBCK003;
extern char const *const GB_MBC1;
extern char const *const GB_MBC2;
extern char const *const GB_MBC3;
@@ -48,6 +47,7 @@ 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 GB_GBCK003;
extern char const *const MEGADUCK_STD;
extern char const *const MEGADUCK_BANKED;
diff --git a/src/devices/bus/gameboy/gbck003.cpp b/src/devices/bus/gameboy/gbck003.cpp
new file mode 100644
index 00000000000..f7db29f8484
--- /dev/null
+++ b/src/devices/bus/gameboy/gbck003.cpp
@@ -0,0 +1,259 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ GBCK003 multi-game board soldered inside some units
+
+ Used with a menu program for selecting between multiple games designed for
+ MBC1 cartridges. Supports up to 8 MiB ROM (512 16 KiB pages). Included
+ games can use up to 4 MiB ROM (256 16 KiB pages).
+
+ The menu program sets up code in WRAM to switch to the selected game's ROM
+ and exit configuration mode. The configuration values are read directly
+ from ROM, so the configuration is presumably applied when exiting
+ configuration mode.
+
+ The write to 0x7B02 that presumably exits configuration mode is followed by
+ code to do the following (SP contains 0xFFFE at this point):
+ * Set HL to 0x000D
+ * Set DE to 0xFF56
+ * Set AF to 0x1180 (Znhc)
+ * Set BC to 0x0000
+ * Jump to 0x0100
+
+ This doesn't match the state set up by any official Nintendo bootstrap
+ programs. Leaving configuration mode presumably asserts the rest line on
+ the cartridge edge connector to get out of CGB mode for games that expect
+ DMG mode.
+
+ 0x0000-3FFF R - Low ROM bank.
+ 0x4000-7FFF R - High ROM bank.
+
+ 0x2000-2FFF W - Set ROM A21-A14 for 0x4000-7FFF as allowed by mask.
+ 0x7B00 * W - Set ROM A22-A15 as allowed by mask.
+ 0x7B01 * W - Set mask for A22-A15 - high for bits controlled by
+ 0x7B00, low for bits controlled by 0x2000-2FFF.
+ 0x7B02 * W - Software writes 0xF0 to exit configuration mode.
+
+ * Registers only writable in configuration mode.
+
+ TODO:
+ * Are large games that require coarse ROM banking supported?
+ * Is static RAM supported? If so, is it banked?
+ * What actual ranges are the configuration registers accessible in?
+ * This isn't really a cartridge - does it belong elsewhere?
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "gbck003.h"
+
+#include "cartbase.ipp"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class gbck003_device : public flat_ram_device_base<mbc_dual_uniform_device_base>
+{
+public:
+ gbck003_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_inner(u8 data);
+ void bank_switch_outer(u8 data);
+ void bank_set_mux(u8 data);
+ void exit_config_mode(u8 data);
+
+ TIMER_CALLBACK_MEMBER(do_reset);
+
+ u16 bank_rom_entry_low() const noexcept
+ {
+ // TODO: is this affected by the multiplexer?
+ return u16(m_bank_setting[0]) << 1;
+ }
+
+ u16 bank_rom_entry_high() const noexcept
+ {
+ return (u16(m_bank_setting[0] & m_bank_mux_rom) << 1) | (m_bank_setting[1] & ~(u16(m_bank_mux_rom) << 1));
+ }
+
+ u8 m_bank_setting[2];
+ u8 m_bank_mux_rom;
+ u8 m_config_mode;
+};
+
+
+gbck003_device::gbck003_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ flat_ram_device_base<mbc_dual_uniform_device_base>(mconfig, GB_ROM_GBCK003, tag, owner, clock),
+ m_bank_setting{ 0U, 0U },
+ m_bank_mux_rom(0U),
+ m_config_mode(0U)
+{
+}
+
+
+image_init_result gbck003_device::load(std::string &message)
+{
+ // set up ROM/RAM
+ set_bank_bits_rom(9);
+ if (!check_rom(message))
+ return image_init_result::FAIL;
+ install_rom();
+ install_ram();
+
+ // install bank switch handlers
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ write8smo_delegate(*this, FUNC(gbck003_device::bank_switch_inner)));
+ cart_space()->install_write_handler(
+ 0x7b00, 0x7b00,
+ write8smo_delegate(*this, FUNC(gbck003_device::bank_switch_outer)));
+ cart_space()->install_write_handler(
+ 0x7b01, 0x7b01,
+ write8smo_delegate(*this, FUNC(gbck003_device::bank_set_mux)));
+ cart_space()->install_write_handler(
+ 0x7b02, 0x7b02,
+ write8smo_delegate(*this, FUNC(gbck003_device::exit_config_mode)));
+
+ // set initial power-on state
+ set_bank_rom_low(0);
+ set_bank_rom_high(1);
+
+ // all good
+ return image_init_result::PASS;
+}
+
+
+void gbck003_device::device_start()
+{
+ flat_ram_device_base<mbc_dual_uniform_device_base>::device_start();
+
+ // this stuff must survive reset for getting out of CGB mode
+ m_bank_setting[0] = 0U;
+ m_bank_mux_rom = 0xff;
+ m_config_mode = 1U;
+
+ save_item(NAME(m_bank_setting));
+ save_item(NAME(m_bank_mux_rom));
+ save_item(NAME(m_config_mode));
+}
+
+
+void gbck003_device::device_reset()
+{
+ flat_ram_device_base<mbc_dual_uniform_device_base>::device_reset();
+
+ // TODO: proper reset state
+ m_bank_setting[1] = 1U;
+}
+
+
+void gbck003_device::bank_switch_inner(u8 data)
+{
+ data &= 0x1f;
+ m_bank_setting[1] = data ? data : 1;
+ set_bank_rom_high(bank_rom_entry_high());
+}
+
+
+void gbck003_device::bank_switch_outer(u8 data)
+{
+ if (m_config_mode)
+ {
+ LOG(
+ "%s: Set base page = 0x%03X (0x%06X)\n",
+ machine().describe_context(),
+ u16(data) << 1,
+ u32(data) << 15);
+ m_bank_setting[0] = data;
+ set_bank_rom_low(bank_rom_entry_low());
+ set_bank_rom_high(bank_rom_entry_high());
+ }
+ else
+ {
+ logerror(
+ "%s: Write 0x7B00 = 0x%02X after disabling configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+void gbck003_device::bank_set_mux(u8 data)
+{
+ if (m_config_mode)
+ {
+ LOG(
+ "%s: Set bank multiplexer = 0x%03X\n",
+ machine().describe_context(),
+ u16(data) << 1);
+ m_bank_mux_rom = data;
+ set_bank_rom_high(bank_rom_entry_high());
+ }
+ else
+ {
+ logerror(
+ "%s: Write 0x7B01 = 0x%02X after disabling configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+void gbck003_device::exit_config_mode(u8 data)
+{
+ if (m_config_mode)
+ {
+ if (0xf0 == data)
+ {
+ LOG("%s: Configuration mode disabled, resetting system\n", machine().describe_context());
+ m_config_mode = 0U;
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(gbck003_device::do_reset), this));
+ }
+ else
+ {
+ logerror(
+ "%s: Unknown write 0x7B02 = 0x%02X in configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+ }
+ else
+ {
+ logerror(
+ "%s: Write 0x7B02 = 0x%02X after disabling configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+TIMER_CALLBACK_MEMBER(gbck003_device::do_reset)
+{
+ machine().root_device().reset(); // TODO: expose reset line on cartridge interface
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_GBCK003, device_gb_cart_interface, bus::gameboy::gbck003_device, "gb_rom_gbck003", "Game Boy GBCK003 Multi-Game Board")
diff --git a/src/devices/bus/gameboy/gbck003.h b/src/devices/bus/gameboy/gbck003.h
new file mode 100644
index 00000000000..04aa19f2c44
--- /dev/null
+++ b/src/devices/bus/gameboy/gbck003.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ GBCK003 multi-game board soldered inside some units
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_GBCK003_H
+#define MAME_BUS_GAMEBOY_GBCK003_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_GBCK003, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_GBCK003_H
diff --git a/src/devices/bus/gameboy/gbslot.cpp b/src/devices/bus/gameboy/gbslot.cpp
index 0e69f0cb972..e7e22ec4bd5 100644
--- a/src/devices/bus/gameboy/gbslot.cpp
+++ b/src/devices/bus/gameboy/gbslot.cpp
@@ -292,7 +292,7 @@ std::string cart_licensee_description(u8 const *header)
{
// TODO: fill in and correct lists, distinguish duplicates
static constexpr std::pair<u8, char const *> BASE[] = {
- { 0x01, "Nintendo" },
+ { 0x01, "Nintendo" },
{ 0x08, "Capcom" }, { 0x09, "Hot-B" }, { 0x0a, "Jaleco" }, { 0x0b, "Coconuts Japan" },
{ 0x0c, "Elite Systems" },
{ 0x13, "Electronic Arts" },
@@ -407,7 +407,7 @@ std::string cart_licensee_description(u8 const *header)
{ 0x3932, "Video System" },
{ 0x3933, "Ocean/Acclaim" },
{ 0x3935, "Varie Corporation" },
- { 0x3936, "Yonezawa/s’pal" },
+ { 0x3936, "Yonezawa/s'pal" },
{ 0x3937, "Kaneko" },
{ 0x3939, "Pack-In-Video Co." },
{ 0x4134, "Konami (Yu-Gi-Oh!)" } };
diff --git a/src/devices/bus/gameboy/rom.cpp b/src/devices/bus/gameboy/rom.cpp
index b2d53ff0291..cf593b95c8a 100644
--- a/src/devices/bus/gameboy/rom.cpp
+++ b/src/devices/bus/gameboy/rom.cpp
@@ -18,10 +18,6 @@
- ATV Racing/Rocket Games:
- Does it monitor the address to detect RAM writes for logo spoofing, or just /CS?
- How does RAM banking work? Are over-size RAM chips just inaccessible?
- - GBCK003:
- - Are large games that require coarse ROM banking supported?
- - Is static RAM supported? If so, is it banked?
- - This isn't really a cartridge - does it belong elsewhere?
***********************************************************************************************************/
@@ -1128,165 +1124,6 @@ private:
}
};
-
-
-//**************************************************************************
-// GBCK003 board soldered inside some units
-//**************************************************************************
-/*
- Seems to be a kind of MBC1 emulator, like MMM01 but less sophisticated.
-
- Base page for game right shifted by one bit position is written to 0x7B00.
- Fine bank mask right shifted by one bit position is written to 0x7B01.
- It always seems to write 0xF0 to 0x7B02 before jumping to the game.
- */
-
-class gbck003_device : public flat_ram_device_base<mbc_dual_uniform_device_base>
-{
-public:
- gbck003_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) :
- flat_ram_device_base<mbc_dual_uniform_device_base>(mconfig, GB_ROM_GBCK003, tag, owner, clock),
- m_bank_setting{ 0U, 0U },
- m_bank_mux_rom(0U),
- m_config_mode(0U)
- {
- }
-
- virtual image_init_result load(std::string &message) override ATTR_COLD
- {
- // set up ROM/RAM
- set_bank_bits_rom(9);
- if (!check_rom(message))
- return image_init_result::FAIL;
- install_rom();
- install_ram();
-
- // install bank switch handlers
- cart_space()->install_write_handler(0x2000, 0x3fff, write8smo_delegate(*this, FUNC(gbck003_device::bank_switch_inner)));
- cart_space()->install_write_handler(0x7b00, 0x7b00, write8smo_delegate(*this, FUNC(gbck003_device::bank_switch_outer)));
- cart_space()->install_write_handler(0x7b01, 0x7b01, write8smo_delegate(*this, FUNC(gbck003_device::bank_set_mux)));
- cart_space()->install_write_handler(0x7b02, 0x7b02, write8smo_delegate(*this, FUNC(gbck003_device::exit_config_mode)));
-
- // all good
- return image_init_result::PASS;
- }
-
-protected:
- virtual void device_start() override ATTR_COLD
- {
- flat_ram_device_base<mbc_dual_uniform_device_base>::device_start();
-
- save_item(NAME(m_bank_setting));
- save_item(NAME(m_bank_mux_rom));
- save_item(NAME(m_config_mode));
- }
-
- virtual void device_reset() override ATTR_COLD
- {
- flat_ram_device_base<mbc_dual_uniform_device_base>::device_reset();
-
- // TODO: proper reset state
- m_bank_setting[0] = 0U;
- m_bank_setting[1] = 1U;
- m_bank_mux_rom = 0xff;
- m_config_mode = 1U;
-
- set_bank_rom_low(0);
- set_bank_rom_high(1);
- }
-
-private:
- void bank_switch_inner(u8 data)
- {
- data &= 0x1f;
- m_bank_setting[1] = data ? data : 1;
- set_bank_rom_high(bank_rom_entry_high());
- }
-
- void bank_switch_outer(u8 data)
- {
- if (m_config_mode)
- {
- LOG(
- "%s: Set base page = 0x%03X (0x%06X)\n",
- machine().describe_context(),
- u16(data) << 1,
- u32(data) << 15);
- m_bank_setting[0] = data;
- set_bank_rom_low(bank_rom_entry_low());
- set_bank_rom_high(bank_rom_entry_high());
- }
- else
- {
- logerror(
- "%s: Write 0x7B00 = 0x%02X after disabling configuration mode\n",
- machine().describe_context(),
- data);
- }
- }
-
- void bank_set_mux(u8 data)
- {
- if (m_config_mode)
- {
- LOG(
- "%s: Set bank multiplexer = 0x%03X\n",
- machine().describe_context(),
- u16(data) << 1);
- m_bank_mux_rom = data;
- set_bank_rom_high(bank_rom_entry_high());
- }
- else
- {
- logerror(
- "%s: Write 0x7B01 = 0x%02X after disabling configuration mode\n",
- machine().describe_context(),
- data);
- }
- }
-
- void exit_config_mode(u8 data)
- {
- if (m_config_mode)
- {
- if (0xf0 == data)
- {
- LOG("%s: Configuration mode disabled\n", machine().describe_context());
- m_config_mode = 0U;
- }
- else
- {
- logerror(
- "%s: Unknown write 0x7B02 = 0x%02X in configuration mode\n",
- machine().describe_context(),
- data);
- }
- }
- else
- {
- logerror(
- "%s: Write 0x7B02 = 0x%02X after disabling configuration mode\n",
- machine().describe_context(),
- data);
- }
- }
-
- u16 bank_rom_entry_low() const
- {
- // TODO: is this affected by the multiplexer?
- return u16(m_bank_setting[0]) << 1;
- }
-
- u16 bank_rom_entry_high() const
- {
- return (u16(m_bank_setting[0] & m_bank_mux_rom) << 1) | (m_bank_setting[1] & ~(u16(m_bank_mux_rom) << 1));
- }
-
- u8 m_bank_setting[2];
- u8 m_bank_mux_rom;
- u8 m_config_mode;
-};
-
} // anonymous namespace
} // namespace bus::gameboy
@@ -1306,4 +1143,3 @@ DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SACHEN1, device_gb_cart_interface, bus::g
DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SACHEN2, device_gb_cart_interface, bus::gameboy::sachen_mmc2_device, "gb_rom_sachen2", "Game Boy Sachen MMC2 Cartridge")
DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_ROCKET, device_gb_cart_interface, bus::gameboy::rocket_device, "gb_rom_rocket", "Game Boy Rocket Games Cartridge")
DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_LASAMA, device_gb_cart_interface, bus::gameboy::lasama_device, "gb_rom_lasama", "Game Boy Story of Lasama Cartridge")
-DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_GBCK003, device_gb_cart_interface, bus::gameboy::gbck003_device, "gb_rom_gbck003", "Game Boy GBCK003 188 in 1 Game Board")
diff --git a/src/devices/bus/gameboy/rom.h b/src/devices/bus/gameboy/rom.h
index f523446f72f..e1cc56444cd 100644
--- a/src/devices/bus/gameboy/rom.h
+++ b/src/devices/bus/gameboy/rom.h
@@ -18,6 +18,5 @@ DECLARE_DEVICE_TYPE(GB_ROM_SACHEN1, device_gb_cart_interface)
DECLARE_DEVICE_TYPE(GB_ROM_SACHEN2, device_gb_cart_interface)
DECLARE_DEVICE_TYPE(GB_ROM_ROCKET, device_gb_cart_interface)
DECLARE_DEVICE_TYPE(GB_ROM_LASAMA, device_gb_cart_interface)
-DECLARE_DEVICE_TYPE(GB_ROM_GBCK003, device_gb_cart_interface)
#endif // MAME_BUS_GAMEBOY_ROM_H
diff --git a/src/devices/bus/gameboy/slmulti.cpp b/src/devices/bus/gameboy/slmulti.cpp
index b2b76578df7..d6c0711c37a 100644
--- a/src/devices/bus/gameboy/slmulti.cpp
+++ b/src/devices/bus/gameboy/slmulti.cpp
@@ -5,7 +5,75 @@
Chinese multi-game cartridges by SL and possibly others
Supports collections containing very large numbers of games designed for
- MBC1 and MBC5 cartridges.
+ MBC1 and MBC5 cartridges. Supports ROM sizes up to 16 MiB ROM (1024 16 KiB
+ pages) and 128 KiB static RAM (16 8 KiB pages). Included MBC1 games can
+ use 32 KiB to at least 512 KiB ROM (2 to 32 pages) and 8 KiB or 32 KiB
+ static RAM (1 or 4 pages). Included MBC5 games can use 32 KiB to 4 MiB ROM
+ (2 to 256 pages) and 8 KiB or 32 KiB static RAM (1 or 4 pages). Static RAM
+ can be disabled for games that don't use it to avoid corrupting save data
+ for other games.
+
+ The controller starts in configuration mode. After setting up ROM and
+ static RAM for the selected game, the controller asserts the reset line on
+ the cartridge edge connector to reset the Game Boy CPU and PPU. This is
+ necessary to get out of CGB mode on a Game Boy Color for games that don't
+ have CGB support. The ROM and static RAM configuration settings aren't
+ affected by the soft reset.
+
+ Changes to the base ROM page seem to take effect immediately. The Vast
+ Fame games switch the base page when starting the menu program. Changes to
+ static RAM configuration presumably take effect immediately, although the
+ menu program doesn't use static RAM.
+
+ The menu program sets up the code to switch to the selected game's ROM and
+ static RAM configuration in WRAM. The register write to complete setup,
+ exit configuration mode and reset the system is followed by a nop and a
+ jp $100. This will jump to the game's entry point if the system fails to
+ reset, although many games don't work properly if this happens, as they
+ expect the system state set up by the bootstrap ROM.
+
+ 0x0000-3FFF R - Low ROM bank.
+ 0x4000-7FFF R - High ROM bank.
+ 0xA000-BFFF RW - Static RAM if enabled.
+
+ 0x0000-1FFF W - Enable (0x0A) or disable (not 0x0A) static RAM.
+ 0x2000-2FFF W - Set ROM A21-A14 for 0x4000-7FFF as allowed by mask.
+ 0x3000-3FFF W - Same as 0x2000 in MBC1 mode, ignored in MBC5 mode.
+ 0x4000-5FFF W - Set static RAM A14-A13 0xA000-BFFF as allowed by mask.
+
+ 0x5000-5FFF * W - Set command for next write to 0x7000-7FFF.
+ 0x7000-7FFF * W - Argument for last command written to 0x5000-5FFF.
+
+ * Registers only writable in configuration mode.
+
+ 0x55 - X------- Exit configuration mode and reset system if set?
+ -XX----- Dumped software writes 11 for MBC1 mode, or 00 for MBC5
+ mode.
+ ---X---- Unknown.
+ ----X--- Set ROM base A23.
+ -----XXX Set number of A21-A15 lines controlled by ROM base setting.
+ 0xAA - XXXXXXXX Set ROM base A22-A15 as allowed by mask.
+ 0xBB - XX------ Unknown - dumped software always write 00.
+ --X----- Allow static RAM to be enabled if set.
+ ---X---- Set static RAM base page mask to A16-A13 if set, or A16-A15
+ if clear.
+ ----XXXX Set static RAM A16-A13 as allowed by mask.
+
+ The Vast Fame cartridges write 0x07 to the 0x7000 area after writing the
+ base ROM page for the previous 0xAA command without an intervening write to
+ the 0x5000 area. It isn't clear what this is supposed to do. It seems to
+ be save to ignore.
+
+ TODO:
+ * What is the exact effect of bit 7 of the 0x55 command argument?
+ * Does bit 4 of the 0x55 command argument have a purpose? Does it control
+ an output for ROM A24 to support 32 MiB ROMs?
+ * The two bits used for setting MBC1 mode probably have separate effects
+ that can be controlled independently.
+ * Can MBC1 games larger than 512 KiB be supported? Does 0x6000-7FFF
+ switch between coarse ROM banking and static RAM banking in MBC1 mode?
+ * Do the two most significant bits of the 0xBB command argument have a
+ purpose?
***************************************************************************/
@@ -44,6 +112,8 @@ private:
void set_config_cmd(u8 data);
void do_config_cmd(u8 data);
+ TIMER_CALLBACK_MEMBER(do_reset);
+
void update_bank_rom_high()
{
u16 const page(bank_rom_entry_high());
@@ -288,7 +358,7 @@ void slmulti_device::do_config_cmd(u8 data)
set_bank_rom_low(m_base_page_rom & ~m_page_mask_rom);
update_bank_rom_high();
if (BIT(data, 7))
- machine().root_device().reset(); // TODO: expose reset line on cartridge interface
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(slmulti_device::do_reset), this));
break;
case 0xaa:
@@ -327,6 +397,12 @@ void slmulti_device::do_config_cmd(u8 data)
m_config_cmd = 0x0100;
}
+
+TIMER_CALLBACK_MEMBER(slmulti_device::do_reset)
+{
+ machine().root_device().reset(); // TODO: expose reset line on cartridge interface
+}
+
} // anonymous namespace
} // namespace bus::gameboy