From d75c4cc68e55316538c18fa7d39e262e93d27970 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 12 Nov 2022 06:36:29 +1100 Subject: bus/gameboy: Added support for bootleg Telefang translations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit English and German versions of the Speed Version bootleg, passed off as Pokémon Jade version, have been added to the software list. Chinese and Spanish translations, and translations of Power Version (Pokémon Diamond) also exist. New working software list additions (gbcolor.xml) ----------------------------------- Pokémon Jade Version [taizou] Pokémon Vision Jade [Sanqui, taizou] --- hash/gbcolor.xml | 55 ++++++++++---- src/devices/bus/gameboy/carts.cpp | 2 + src/devices/bus/gameboy/carts.h | 1 + src/devices/bus/gameboy/gbslot.cpp | 3 + src/devices/bus/gameboy/gbxfile.h | 1 + src/devices/bus/gameboy/liebao.cpp | 2 +- src/devices/bus/gameboy/mbc.h | 1 - src/devices/bus/gameboy/mbc3.cpp | 150 +++++++++++++++++++++++++++++++++++-- src/devices/bus/gameboy/mbc3.h | 5 +- src/devices/bus/gameboy/ntnew.cpp | 2 +- 10 files changed, 196 insertions(+), 26 deletions(-) diff --git a/hash/gbcolor.xml b/hash/gbcolor.xml index 1ebfbf1b9e5..40cf7239fa8 100644 --- a/hash/gbcolor.xml +++ b/hash/gbcolor.xml @@ -9993,9 +9993,9 @@ license:CC0 Keitai Denjuu Telefang - Power Version (Japan) 2000 Natsume - - - + + + @@ -10005,11 +10005,10 @@ license:CC0 - - - - + + + @@ -10017,17 +10016,47 @@ license:CC0 Keitai Denjuu Telefang - Speed Version (Japan) 2000 Natsume - - - + + + - - + + - + + + + + + + Pokémon Jade Version + 200? + bootleg + + + + + + + + + + + + + + Pokémon Vision Jade + 200? + bootleg + + + + + + diff --git a/src/devices/bus/gameboy/carts.cpp b/src/devices/bus/gameboy/carts.cpp index a1341314fc6..e43f62c96dc 100644 --- a/src/devices/bus/gameboy/carts.cpp +++ b/src/devices/bus/gameboy/carts.cpp @@ -51,6 +51,7 @@ char const *const GB_HUC1 = "rom_huc1"; char const *const GB_HUC3 = "rom_huc3"; char const *const GB_TAMA5 = "rom_tama5"; char const *const GB_CAMERA = "rom_camera"; +char const *const GB_TFANGBOOT = "rom_tfboot"; char const *const GB_SINTAX = "rom_sintax"; char const *const GB_CHONGWU = "rom_chong"; char const *const GB_LICHENG = "rom_licheng"; @@ -95,6 +96,7 @@ void gameboy_cartridges(device_slot_interface &device) device.option_add_internal(slotoptions::GB_HUC1, GB_ROM_HUC1); device.option_add_internal(slotoptions::GB_HUC3, GB_ROM_HUC3); device.option_add_internal(slotoptions::GB_TAMA5, GB_ROM_TAMA5); + device.option_add_internal(slotoptions::GB_TFANGBOOT, GB_ROM_TFANGBOOT); device.option_add_internal(slotoptions::GB_SINTAX, GB_ROM_SINTAX); device.option_add_internal(slotoptions::GB_CHONGWU, GB_ROM_CHONGWU); device.option_add_internal(slotoptions::GB_LICHENG, GB_ROM_LICHENG); diff --git a/src/devices/bus/gameboy/carts.h b/src/devices/bus/gameboy/carts.h index ddf1d174665..1a33a4d4a22 100644 --- a/src/devices/bus/gameboy/carts.h +++ b/src/devices/bus/gameboy/carts.h @@ -40,6 +40,7 @@ extern char const *const GB_CAMERA; extern char const *const GB_HUC1; extern char const *const GB_HUC3; extern char const *const GB_TAMA5; +extern char const *const GB_TFANGBOOT; extern char const *const GB_SINTAX; extern char const *const GB_CHONGWU; extern char const *const GB_LICHENG; diff --git a/src/devices/bus/gameboy/gbslot.cpp b/src/devices/bus/gameboy/gbslot.cpp index 9cd95a59441..2203e2b94f9 100644 --- a/src/devices/bus/gameboy/gbslot.cpp +++ b/src/devices/bus/gameboy/gbslot.cpp @@ -734,6 +734,9 @@ std::optional probe_gbx_footer(std::string_view tag, util::random_ case gbxfile::TYPE_HUC3: result = slotoptions::GB_HUC3; break; + case gbxfile::TYPE_TFANGBOOT: + result = slotoptions::GB_TFANGBOOT; + break; case gbxfile::TYPE_SINTAX: result = slotoptions::GB_SINTAX; break; diff --git a/src/devices/bus/gameboy/gbxfile.h b/src/devices/bus/gameboy/gbxfile.h index 2be34583ff0..11f0d09bcda 100644 --- a/src/devices/bus/gameboy/gbxfile.h +++ b/src/devices/bus/gameboy/gbxfile.h @@ -67,6 +67,7 @@ enum : u32 TYPE_MMM01 = 0x4d4d4d31, // 'MMM1' TYPE_NEWGBCHK = 0x4e47484b, // 'NGHK' TYPE_NTNEW = 0x4e544e00, // 'NTN\0' + TYPE_TFANGBOOT = 0x504b4a44, // 'PKJD' TYPE_ROCKET = 0x524f434b, // 'ROCK' TYPE_PLAIN = 0x524f4d00, // 'ROM\0' TYPE_SACHEN1 = 0x53414d31, // 'SAM1' diff --git a/src/devices/bus/gameboy/liebao.cpp b/src/devices/bus/gameboy/liebao.cpp index f9bd8cafcc1..df261921546 100644 --- a/src/devices/bus/gameboy/liebao.cpp +++ b/src/devices/bus/gameboy/liebao.cpp @@ -114,7 +114,7 @@ void liebao_device::device_reset() void liebao_device::enable_ram(offs_t offset, u8 data) { // TODO: how many bits are checked? - bool const enable = 0x0a == (data & 0x0f); + bool const enable(0x0a == (data & 0x0f)); LOG( "%s: Cartridge RAM %s\n", machine().describe_context(), diff --git a/src/devices/bus/gameboy/mbc.h b/src/devices/bus/gameboy/mbc.h index 9dfedb31232..4cc03952fea 100644 --- a/src/devices/bus/gameboy/mbc.h +++ b/src/devices/bus/gameboy/mbc.h @@ -10,7 +10,6 @@ DECLARE_DEVICE_TYPE(GB_ROM_MBC1, device_gb_cart_interface) DECLARE_DEVICE_TYPE(GB_ROM_MBC5, device_gb_cart_interface) -DECLARE_DEVICE_TYPE(GB_ROM_MMM01, device_gb_cart_interface) DECLARE_DEVICE_TYPE(GB_ROM_SINTAX, device_gb_cart_interface) DECLARE_DEVICE_TYPE(GB_ROM_CHONGWU, device_gb_cart_interface) DECLARE_DEVICE_TYPE(GB_ROM_LICHENG, device_gb_cart_interface) diff --git a/src/devices/bus/gameboy/mbc3.cpp b/src/devices/bus/gameboy/mbc3.cpp index bfead355999..f1971c749e4 100644 --- a/src/devices/bus/gameboy/mbc3.cpp +++ b/src/devices/bus/gameboy/mbc3.cpp @@ -47,6 +47,17 @@ -X------ Set to halt real-time clock. -------X Bit 8 of days. + Telefang bootlegs have three additional registers: + 0x5 - Low value. + 0x6 - High value. + 0x7 - Command: + 0x11 Decrement low value. + 0x12 Decrement high value. + 0x41 Add high value to low value. + 0x42 Add low value to high value. + 0x51 Increment low value. + 0x52 Increment high value. + TODO: * How are the static RAM bank outputs set when real-time clock registers are selected? @@ -54,6 +65,8 @@ * How do invalid seconds, minutes and hours values roll over? * Does MBC30 really have eight ROM bank outputs? The one game using it only uses seven. + * Does the bootleg Keitai Denjuu Telefang controller actually include a + real-time clock? No oscillator crystal is present. ***************************************************************************/ @@ -100,6 +113,13 @@ protected: bool install_memory(std::string &message, unsigned highbits, unsigned lowbits) ATTR_COLD; +protected: + u8 const rtc_select() const { return BIT(m_rtc_select, 3); } + u8 const rtc_register() const { return m_rtc_select & 0x07; } + + virtual u8 read_rtc(address_space &space); + virtual void write_rtc(u8 data); + private: static inline constexpr u8 RTC_MASK[]{ 0x3f, 0x3f, 0x1f, 0xff, 0xc1 }; static inline constexpr u8 RTC_ROLLOVER[]{ 0x3c, 0x3c, 0x18, 0x00, 0x00 }; @@ -110,8 +130,6 @@ private: void bank_switch_fine(u8 data); void select_ram_rtc(u8 data); void latch_rtc(u8 data); - u8 read_rtc(address_space &space); - void write_rtc(u8 data); u8 rtc_increment(unsigned index) { @@ -153,6 +171,25 @@ public: }; +class tfboot_device : public mbc3_device_base +{ +public: + tfboot_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; + + virtual u8 read_rtc(address_space &space) override; + virtual void write_rtc(u8 data) override; + +private: + u8 m_protection[2]; +}; + + //************************************************************************** // mbc3_device_base @@ -546,12 +583,12 @@ void mbc3_device_base::enable_ram_rtc(u8 data) machine().describe_context()); m_view_ram.disable(); } - else if (BIT(m_rtc_select, 3)) + else if (rtc_select()) { LOG( "%s: RTC register %u enabled\n", machine().describe_context(), - m_rtc_select & 0x07); + rtc_register()); m_view_ram.select(1); } else @@ -611,7 +648,7 @@ void mbc3_device_base::latch_rtc(u8 data) u8 mbc3_device_base::read_rtc(address_space &space) { - u8 const reg(m_rtc_select & 0x07); + u8 const reg(rtc_register()); if (std::size(m_rtc_regs[1]) > reg) { LOG( @@ -634,7 +671,7 @@ u8 mbc3_device_base::read_rtc(address_space &space) void mbc3_device_base::write_rtc(u8 data) { - u8 const reg(m_rtc_select & 0x07); + u8 const reg(rtc_register()); if (std::size(m_rtc_regs[0]) > reg) { LOG( @@ -712,10 +749,107 @@ image_init_result mbc30_device::load(std::string &message) return image_init_result::PASS; } + + +//************************************************************************** +// tfboot_device +//************************************************************************** + +tfboot_device::tfboot_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + u32 clock) : + mbc3_device_base(mconfig, GB_ROM_TFANGBOOT, tag, owner, clock), + m_protection{ 0U, 0U } +{ +} + + +image_init_result tfboot_device::load(std::string &message) +{ + if (!install_memory(message, 2, 7)) + return image_init_result::FAIL; + else + return image_init_result::PASS; +} + + +void tfboot_device::device_start() +{ + mbc3_device_base::device_start(); + + save_item(NAME(m_protection)); +} + + +void tfboot_device::device_reset() +{ + mbc3_device_base::device_reset(); + + m_protection[0] = 0U; + m_protection[1] = 0U; +} + + +u8 tfboot_device::read_rtc(address_space &space) +{ + u8 const reg(rtc_register()); + switch (reg) + { + case 0x05: + case 0x06: + return m_protection[BIT(reg, 0)]; + case 0x07: + return 0U; + default: + return mbc3_device_base::read_rtc(space); + } +} + + +void tfboot_device::write_rtc(u8 data) +{ + u8 const reg(rtc_register()); + switch (reg) + { + case 0x05: + case 0x06: + m_protection[BIT(reg, 0)] = data; + break; + case 0x07: + LOG("%s: Protection command 0x%02X\n", machine().describe_context(), data); + switch (data) + { + case 0x11: + case 0x12: + --m_protection[BIT(data, 0)]; + break; + case 0x41: + case 0x42: + m_protection[BIT(data, 0)] += m_protection[BIT(~data, 0)]; + break; + case 0x51: + case 0x52: + ++m_protection[BIT(data, 0)]; + break; + default: + logerror( + "%s: Unknown protection command 0x%02X\n", + machine().describe_context(), + data); + } + break; + default: + mbc3_device_base::write_rtc(data); + } +} + } // anonymous namespace } // namespace bus::gameboy -DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC3, device_gb_cart_interface, bus::gameboy::mbc3_device, "gb_rom_mbc3", "Game Boy MBC3 Cartridge") -DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC30, device_gb_cart_interface, bus::gameboy::mbc30_device, "gb_rom_mbc30", "Game Boy MBC30 Cartridge") +DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC3, device_gb_cart_interface, bus::gameboy::mbc3_device, "gb_rom_mbc3", "Game Boy MBC3 Cartridge") +DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC30, device_gb_cart_interface, bus::gameboy::mbc30_device, "gb_rom_mbc30", "Game Boy MBC30 Cartridge") +DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_TFANGBOOT, device_gb_cart_interface, bus::gameboy::tfboot_device, "gb_rom_tfboot", "Game Boy Telefang bootleg Cartridge") diff --git a/src/devices/bus/gameboy/mbc3.h b/src/devices/bus/gameboy/mbc3.h index e039262fc3d..ffa35d26a36 100644 --- a/src/devices/bus/gameboy/mbc3.h +++ b/src/devices/bus/gameboy/mbc3.h @@ -13,7 +13,8 @@ #include "slot.h" -DECLARE_DEVICE_TYPE(GB_ROM_MBC3, device_gb_cart_interface) -DECLARE_DEVICE_TYPE(GB_ROM_MBC30, device_gb_cart_interface) +DECLARE_DEVICE_TYPE(GB_ROM_MBC3, device_gb_cart_interface) +DECLARE_DEVICE_TYPE(GB_ROM_MBC30, device_gb_cart_interface) +DECLARE_DEVICE_TYPE(GB_ROM_TFANGBOOT, device_gb_cart_interface) #endif // MAME_BUS_GAMEBOY_MBC3_H diff --git a/src/devices/bus/gameboy/ntnew.cpp b/src/devices/bus/gameboy/ntnew.cpp index 6df635c6ad0..7ea72a2d9f4 100644 --- a/src/devices/bus/gameboy/ntnew.cpp +++ b/src/devices/bus/gameboy/ntnew.cpp @@ -125,7 +125,7 @@ void ntnew_device::enable_ram(offs_t offset, u8 data) } // TODO: how many bits are checked? - bool const enable = 0x0a == (data & 0x0f); + bool const enable(0x0a == (data & 0x0f)); LOG( "%s: Cartridge RAM %s\n", machine().describe_context(), -- cgit v1.2.3