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(),