diff options
Diffstat (limited to 'src/emu/bus/gameboy/mbc.c')
-rw-r--r-- | src/emu/bus/gameboy/mbc.c | 1274 |
1 files changed, 0 insertions, 1274 deletions
diff --git a/src/emu/bus/gameboy/mbc.c b/src/emu/bus/gameboy/mbc.c deleted file mode 100644 index 4c0a81459b6..00000000000 --- a/src/emu/bus/gameboy/mbc.c +++ /dev/null @@ -1,1274 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Fabio Priuli, Wilbert Pol -/*********************************************************************************************************** - - Game Boy carts with MBC (Memory Bank Controller) - - - TODO: add proper RTC and Rumble support - - ***********************************************************************************************************/ - - -#include "emu.h" -#include "mbc.h" - - -//------------------------------------------------- -// gb_rom_mbc*_device - constructor -//------------------------------------------------- - -const device_type GB_ROM_MBC1 = &device_creator<gb_rom_mbc1_device>; -const device_type GB_ROM_MBC2 = &device_creator<gb_rom_mbc2_device>; -const device_type GB_ROM_MBC3 = &device_creator<gb_rom_mbc3_device>; -const device_type GB_ROM_MBC5 = &device_creator<gb_rom_mbc5_device>; -const device_type GB_ROM_MBC6 = &device_creator<gb_rom_mbc6_device>; -const device_type GB_ROM_MBC7 = &device_creator<gb_rom_mbc7_device>; -const device_type GB_ROM_M161_M12 = &device_creator<gb_rom_m161_device>; -const device_type GB_ROM_MMM01 = &device_creator<gb_rom_mmm01_device>; -const device_type GB_ROM_SACHEN1 = &device_creator<gb_rom_sachen_mmc1_device>; -const device_type GB_ROM_SACHEN2 = &device_creator<gb_rom_sachen_mmc2_device>; -const device_type GB_ROM_188IN1 = &device_creator<gb_rom_188in1_device>; -const device_type GB_ROM_SINTAX = &device_creator<gb_rom_sintax_device>; -const device_type GB_ROM_CHONGWU = &device_creator<gb_rom_chongwu_device>; -const device_type GB_ROM_LICHENG = &device_creator<gb_rom_licheng_device>; -const device_type GB_ROM_DIGIMON = &device_creator<gb_rom_digimon_device>; -const device_type GB_ROM_ROCKMAN8 = &device_creator<gb_rom_rockman8_device>; -const device_type GB_ROM_SM3SP = &device_creator<gb_rom_sm3sp_device>; - - -gb_rom_mbc_device::gb_rom_mbc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : device_t(mconfig, type, name, tag, owner, clock, shortname, source), - device_gb_cart_interface( mconfig, *this ) -{ -} - -gb_rom_mbc1_device::gb_rom_mbc1_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : gb_rom_mbc_device(mconfig, type, name, tag, owner, clock, shortname, source), - m_mask(0x1f), - m_shift(0) -{ -} - -gb_rom_mbc1_device::gb_rom_mbc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_MBC1, "GB MBC1 Carts", tag, owner, clock, "gb_rom_mbc1", __FILE__), - m_mask(0x1f), - m_shift(0) -{ -} - -gb_rom_mbc2_device::gb_rom_mbc2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_MBC2, "GB MBC2 Carts", tag, owner, clock, "gb_rom_mbc2", __FILE__) -{ -} - -gb_rom_mbc3_device::gb_rom_mbc3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_MBC3, "GB MBC3 Carts", tag, owner, clock, "gb_rom_mbc3", __FILE__) -{ -} - -gb_rom_mbc5_device::gb_rom_mbc5_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : gb_rom_mbc_device(mconfig, type, name, tag, owner, clock, shortname, source) -{ -} - -gb_rom_mbc5_device::gb_rom_mbc5_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_MBC5, "GB MBC5 Carts", tag, owner, clock, "gb_rom_mbc5", __FILE__) -{ -} - -gb_rom_mbc6_device::gb_rom_mbc6_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_MBC6, "GB MBC6 Carts", tag, owner, clock, "gb_rom_mbc6", __FILE__) -{ -} - -gb_rom_mbc7_device::gb_rom_mbc7_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_MBC7, "GB MBC7 Carts", tag, owner, clock, "gb_rom_mbc7", __FILE__) -{ -} - -gb_rom_m161_device::gb_rom_m161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_M161_M12, "GB M161-M12 Carts", tag, owner, clock, "gb_rom_m161m12", __FILE__) -{ -} - -gb_rom_mmm01_device::gb_rom_mmm01_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_MMM01, "GB MMM01 Carts", tag, owner, clock, "gb_rom_mmm01", __FILE__) -{ -} - -gb_rom_sachen_mmc1_device::gb_rom_sachen_mmc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_SACHEN1, "GB Sachen MMC1 Carts", tag, owner, clock, "gb_rom_sachen1", __FILE__) -{ -} - -gb_rom_sachen_mmc1_device::gb_rom_sachen_mmc1_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : gb_rom_mbc_device(mconfig, type, name, tag, owner, clock, shortname, source) -{ -} - -gb_rom_sachen_mmc2_device::gb_rom_sachen_mmc2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_sachen_mmc1_device(mconfig, GB_ROM_SACHEN2, "GB Sachen MMC2 Carts", tag, owner, clock, "gb_rom_sachen2", __FILE__) -{ -} - -gb_rom_188in1_device::gb_rom_188in1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc1_device(mconfig, GB_ROM_188IN1, "GB 188in1", tag, owner, clock, "gb_rom_188in1", __FILE__) -{ -} - -gb_rom_sintax_device::gb_rom_sintax_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_SINTAX, "GB MBC5 Sintax Carts", tag, owner, clock, "gb_rom_sintax", __FILE__) -{ -} - -gb_rom_chongwu_device::gb_rom_chongwu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc5_device(mconfig, GB_ROM_CHONGWU, "GB Chong Wu Xiao Jing Ling", tag, owner, clock, "gb_rom_chongwu", __FILE__) -{ -} - -gb_rom_licheng_device::gb_rom_licheng_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc5_device(mconfig, GB_ROM_LICHENG, "GB MBC5 Li Cheng Carts", tag, owner, clock, "gb_rom_licheng", __FILE__) -{ -} - -gb_rom_digimon_device::gb_rom_digimon_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc5_device(mconfig, GB_ROM_DIGIMON, "GB Digimon", tag, owner, clock, "gb_rom_digimon", __FILE__) -{ -} - -gb_rom_rockman8_device::gb_rom_rockman8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_ROCKMAN8, "GB MBC1 Rockman 8", tag, owner, clock, "gb_rom_rockman8", __FILE__) -{ -} - -gb_rom_sm3sp_device::gb_rom_sm3sp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : gb_rom_mbc_device(mconfig, GB_ROM_SM3SP, "GB MBC1 Super Mario 3 Special", tag, owner, clock, "gb_rom_sm3sp", __FILE__) -{ -} - - -//------------------------------------------------- -// shared_start -//------------------------------------------------- - -void gb_rom_mbc_device::shared_start() -{ - save_item(NAME(m_latch_bank)); - save_item(NAME(m_latch_bank2)); - save_item(NAME(m_ram_bank)); - save_item(NAME(m_ram_enable)); -} - -//------------------------------------------------- -// shared_reset -//------------------------------------------------- - -void gb_rom_mbc_device::shared_reset() -{ - m_latch_bank = 0; - m_latch_bank2 = 1; - m_ram_bank = 0; - m_ram_enable = 0; -} - -//------------------------------------------------- -// mapper specific start/reset -//------------------------------------------------- - -void gb_rom_mbc3_device::device_start() -{ - shared_start(); - save_item(NAME(m_rtc_map)); -} - -void gb_rom_mbc3_device::device_reset() -{ - shared_reset(); - memset(m_rtc_map, 0, sizeof(m_rtc_map)); -} - -void gb_rom_mbc6_device::device_start() -{ - save_item(NAME(m_bank_4000)); - save_item(NAME(m_bank_6000)); - save_item(NAME(m_latch1)); - save_item(NAME(m_latch2)); - save_item(NAME(m_latch_bank)); - save_item(NAME(m_latch_bank2)); - save_item(NAME(m_ram_bank)); - save_item(NAME(m_ram_enable)); -} - -void gb_rom_mbc6_device::device_reset() -{ - m_bank_4000 = 2; // correct default? - m_bank_6000 = 3; // correct default? - m_latch1 = 0; // correct default? - m_latch2 = 0; // correct default? - - m_latch_bank = 2; // correct default? - m_latch_bank2 = 3; // correct default? - m_ram_bank = 0; - m_ram_enable = 0; -} - -void gb_rom_m161_device::device_start() -{ - shared_start(); - save_item(NAME(m_base_bank)); -} - -void gb_rom_m161_device::device_reset() -{ - shared_reset(); - m_base_bank = 0; -} - -void gb_rom_mmm01_device::device_start() -{ - shared_start(); - save_item(NAME(m_bank_mask)); - save_item(NAME(m_bank)); - save_item(NAME(m_reg)); -} - -void gb_rom_mmm01_device::device_reset() -{ - m_latch_bank = 0x200 - 2; - m_latch_bank2 = 0x200 - 1; - m_ram_bank = 0; - m_bank_mask = 0xff; - m_bank = 0; - m_reg = 0; -} - -void gb_rom_sachen_mmc1_device::device_start() -{ - shared_start(); - save_item(NAME(m_base_bank)); - save_item(NAME(m_mask)); - save_item(NAME(m_mode)); - save_item(NAME(m_unlock_cnt)); -} - -void gb_rom_sachen_mmc1_device::device_reset() -{ - shared_reset(); - m_base_bank = 0x00; - m_mask = 0x00; - m_mode = MODE_LOCKED; - m_unlock_cnt = 0x00; -} - -void gb_rom_sachen_mmc2_device::device_start() -{ - shared_start(); - save_item(NAME(m_base_bank)); - save_item(NAME(m_mask)); - save_item(NAME(m_mode)); - save_item(NAME(m_unlock_cnt)); -} - -void gb_rom_sachen_mmc2_device::device_reset() -{ - shared_reset(); - m_base_bank = 0x00; - m_mask = 0x00; - m_mode = MODE_LOCKED_DMG; - m_unlock_cnt = 0x00; -} - -void gb_rom_sintax_device::device_start() -{ - shared_start(); - save_item(NAME(m_sintax_mode)); - save_item(NAME(m_currentxor)); - save_item(NAME(m_xor2)); - save_item(NAME(m_xor3)); - save_item(NAME(m_xor4)); - save_item(NAME(m_xor5)); -} - -void gb_rom_sintax_device::device_reset() -{ - shared_reset(); - m_sintax_mode = 0; - m_currentxor = 0; - m_xor2 = 0; - m_xor3 = 0; - m_xor4 = 0; - m_xor5 = 0; -} - -void gb_rom_chongwu_device::device_start() -{ - shared_start(); - save_item(NAME(m_protection_checked)); -} - -void gb_rom_chongwu_device::device_reset() -{ - shared_reset(); - m_protection_checked = 0; -} - - -/*------------------------------------------------- - mapper specific handlers - -------------------------------------------------*/ - -READ8_MEMBER(gb_rom_mbc_device::read_rom) -{ - return m_rom[rom_bank_map[m_latch_bank] + offset]; -} - -READ8_MEMBER(gb_rom_mbc_device::read_ram) -{ - if (!m_ram.empty()) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + offset]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_mbc_device::write_ram) -{ - if (!m_ram.empty()) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + offset] = data; -} - - -// MBC1 - -READ8_MEMBER(gb_rom_mbc1_device::read_rom) -{ - if (offset & 0x4000) /* RB1 */ - return m_rom[rom_bank_map[(m_ram_bank << (5 + m_shift)) | m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; - else - { /* RB0 */ - int bank = (m_mode == MODE_4M_256k) ? (m_ram_bank << (5 + m_shift)) : 0; - return m_rom[rom_bank_map[bank] * 0x4000 + (offset & 0x3fff)]; - } -} - -WRITE8_MEMBER(gb_rom_mbc1_device::write_bank) -{ - // the mapper only uses inputs A15..A13 - switch (offset & 0xe000) - { - case 0x0000: // RAM Enable Register - m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0; - break; - case 0x2000: // ROM Bank Register - data &= 0x1f; - m_latch_bank2 = data ? data : 1; - m_latch_bank2 &= m_mask; - break; - case 0x4000: // RAM Bank Register - m_ram_bank = data & 0x3; - break; - case 0x6000: // MBC1 Mode Register - m_mode = (data & 0x1) ? MODE_4M_256k : MODE_16M_64k; - break; - } -} - -READ8_MEMBER(gb_rom_mbc1_device::read_ram) -{ - if (!m_ram.empty() && m_ram_enable) - { - int bank = (m_mode == MODE_4M_256k) ? m_ram_bank : 0; - return m_ram[ram_bank_map[bank] * 0x2000 + offset]; - } - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_mbc1_device::write_ram) -{ - if (!m_ram.empty() && m_ram_enable) - { - int bank = (m_mode == MODE_4M_256k) ? m_ram_bank : 0; - m_ram[ram_bank_map[bank] * 0x2000 + offset] = data; - } -} - - -// MBC2 - -READ8_MEMBER(gb_rom_mbc2_device::read_rom) -{ - if (offset & 0x4000) /* RB1 */ - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; - else /* RB0 */ - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_mbc2_device::write_bank) -{ - // the mapper only has data lines D3..D0 - data &= 0x0f; - - // the mapper only uses inputs A15..A14, A8 for register accesses - switch (offset & 0xc100) - { - case 0x0000: // RAM Enable Register - m_ram_enable = (data == 0x0a) ? 1 : 0; - break; - case 0x0100: // ROM Bank Register - m_latch_bank2 = (data == 0x00) ? 0x01 : data; - break; - } -} - -READ8_MEMBER(gb_rom_mbc2_device::read_ram) -{ - if (!m_ram.empty() && m_ram_enable) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x01ff)] | 0xF0; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_mbc2_device::write_ram) -{ - if (!m_ram.empty() && m_ram_enable) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x01ff)] = data & 0x0F; -} - - -// MBC3 - -READ8_MEMBER(gb_rom_mbc3_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_mbc3_device::write_bank) -{ - if (offset < 0x2000) - m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0; - else if (offset < 0x4000) - { - // 7bits - data &= 0x7f; - /* Selecting bank 0 == selecting bank 1 */ - if (data == 0) - data = 1; - - m_latch_bank2 = data; - } - else if (offset < 0x6000) - { - m_ram_bank = data; - } - else - { - if (has_timer) - { - /* FIXME: RTC Latch goes here */ - m_rtc_map[0] = 50; /* Seconds */ - m_rtc_map[1] = 40; /* Minutes */ - m_rtc_map[2] = 15; /* Hours */ - m_rtc_map[3] = 25; /* Day counter lowest 8 bits */ - m_rtc_map[4] = 0x01; /* Day counter upper bit, timer off, no day overflow occurred (bit7) */ - } - } -} - -READ8_MEMBER(gb_rom_mbc3_device::read_ram) -{ - if (m_ram_bank < 4 && m_ram_enable) - { // RAM - if (!m_ram.empty()) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)]; - } - if (m_ram_bank >= 0x8 && m_ram_bank <= 0xc) - { // RAM - if (has_timer) - return m_rtc_map[m_ram_bank - 8]; - } - return 0xff; -} - -WRITE8_MEMBER(gb_rom_mbc3_device::write_ram) -{ - if (m_ram_bank < 4 && m_ram_enable) - { // RAM - if (!m_ram.empty()) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data; - } - if (m_ram_bank >= 0x8 && m_ram_bank <= 0xc) - { // RAM - if (has_timer) - { - // what to do here? - } - } -} - -// MBC5 - -READ8_MEMBER(gb_rom_mbc5_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_mbc5_device::write_bank) -{ - if (offset < 0x2000) - m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0; - else if (offset < 0x3000) - { - // MBC5 has a 9 bit bank select - // Writing into 2000-2fff sets the lower 8 bits - m_latch_bank2 = (m_latch_bank2 & 0x100) | data; - } - else if (offset < 0x4000) - { - // MBC5 has a 9 bit bank select - // Writing into 3000-3fff sets the 9th bit - m_latch_bank2 = (m_latch_bank2 & 0xff) | ((data & 0x01) << 8); - } - else if (offset < 0x6000) - { - data &= 0x0f; - if (has_rumble) - data &= 0x7; - m_ram_bank = data; - } -} - -READ8_MEMBER(gb_rom_mbc5_device::read_ram) -{ - if (!m_ram.empty() && m_ram_enable) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_mbc5_device::write_ram) -{ - if (!m_ram.empty() && m_ram_enable) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data; -} - -// MBC6 - -READ8_MEMBER(gb_rom_mbc6_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else if (offset < 0x6000) - return m_rom[rom_bank_map[m_bank_4000 >> 1] * 0x4000 + (m_bank_4000 & 0x01) * 0x2000 + (offset & 0x1fff)]; - else - return m_rom[rom_bank_map[m_bank_6000 >> 1] * 0x4000 + (m_bank_6000 & 0x01) * 0x2000 + (offset & 0x1fff)]; -} - -WRITE8_MEMBER(gb_rom_mbc6_device::write_bank) -{ - if (offset < 0x2000) - { - logerror( "0x%04X: write to mbc6 ram enable area: %04X <- 0x%02X\n", space.device().safe_pc(), offset, data ); - } - else if (offset < 0x3000) - { - if (!(offset & 0x0800)) - m_latch1 = data; - else if (data == 0x00) - m_bank_4000 = m_latch1; - } - else if (offset < 0x4000) - { - if (!(offset & 0x0800)) - m_latch2 = data; - else if (data == 0x00) - m_bank_6000 = m_latch2; - } -} - -READ8_MEMBER(gb_rom_mbc6_device::read_ram) -{ - if (!m_ram.empty()) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_mbc6_device::write_ram) -{ - if (!m_ram.empty()) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data; -} - -// MBC7 - -READ8_MEMBER(gb_rom_mbc7_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_mbc7_device::write_bank) -{ - if (offset < 0x2000) - { - // FIXME: Add RAM enable support - logerror("0x%04X: Write to ram enable register 0x%04X <- 0x%02X\n", space.device().safe_pc( ), offset, data); - } - else if (offset < 0x3000) - { - logerror( "0x%04X: write to mbc7 rom select register: 0x%04X <- 0x%02X\n", space.device() .safe_pc( ), 0x2000 + offset, data ); - /* Bit 12 must be set for writing to the mbc register */ - if (offset & 0x0100) - m_latch_bank2 = data; - } - else - { - logerror( "0x%04X: write to mbc7 rom area: 0x%04X <- 0x%02X\n", space.device() .safe_pc( ), 0x3000 + offset, data ); - /* Bit 12 must be set for writing to the mbc register */ - if (offset & 0x0100) - { - switch (offset & 0x7000) - { - case 0x3000: /* 0x3000-0x3fff */ - case 0x4000: /* 0x4000-0x4fff */ - case 0x5000: /* 0x5000-0x5fff */ - case 0x6000: /* 0x6000-0x6fff */ - case 0x7000: /* 0x7000-0x7fff */ - break; - } - } - } -} - -READ8_MEMBER(gb_rom_mbc7_device::read_ram) -{ - if (!m_ram.empty()) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_mbc7_device::write_ram) -{ - if (!m_ram.empty()) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data; -} - - -// M161-M12 - -READ8_MEMBER(gb_rom_m161_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_base_bank] * 0x4000 + offset]; - else - return m_rom[rom_bank_map[m_base_bank] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_m161_device::write_bank) -{ - switch (offset & 0xe000) - { - case 0x4000: // Base Bank Register - m_base_bank = data << 1; - break; - case 0x2000: // Tetris writes 1 here when selected... - default: - break; - } -} - - -// MMM01 -// This mmm01 implementation is mostly guess work, no clue how correct it all is -/* TODO: This implementation is wrong. Tauwasser - * - * Register 0: Map Latch, AA Mask, RAM Enable - * Register 1: EA1..EA0, RA18..RA14 - * Register 2: ??, AA18..AA15, AA14..AA13 - * Register 3: AA Multiplex, RA Mask, ???, MBC1 Mode - * - */ - -READ8_MEMBER(gb_rom_mmm01_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + offset]; - else - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_mmm01_device::write_bank) -{ - if (offset < 0x2000) - { - if (data & 0x40) - { - m_latch_bank = m_reg; - m_latch_bank2 = m_latch_bank + m_bank; - } - } - else if (offset < 0x4000) - { - m_reg = data & ((m_rom_size / 0x4000) - 1); - m_bank = m_reg & m_bank_mask; - if (m_bank == 0) - m_bank = 1; - m_latch_bank2 = m_latch_bank + m_bank; - } - else if (offset < 0x6000) - logerror("0x%04X: write 0x%02X to 0x%04X\n", space.device().safe_pc(), data, offset); - else - { - logerror("0x%04X: write 0x%02X to 0x%04X\n", space.device().safe_pc(), data, offset); - /* Not sure if this is correct, Taito Variety Pack sets these values */ - /* Momotarou Collection 2 writes 01 and 21 here */ - switch (data) - { - case 0x30: m_bank_mask = 0x07; break; - case 0x38: m_bank_mask = 0x03; break; - default: m_bank_mask = 0xff; break; - } - } -} - -// Sachen MMC1 - -READ8_MEMBER(gb_rom_sachen_mmc1_device::read_rom) -{ - UINT16 off_edit = offset; - - /* Wait for 0x31 transitions of A15 (hi -> lo), i.e. ROM accesses; A15 = HI while in bootstrap */ - /* This is 0x31 transitions, because we increment counter _after_ checking it */ - if (m_unlock_cnt == 0x30) - m_mode = MODE_UNLOCKED; - else - m_unlock_cnt++; - - /* Logo Switch */ - if (m_mode == MODE_LOCKED) - off_edit |= 0x80; - - /* Header Un-Scramble */ - if ((off_edit & 0xFF00) == 0x0100) { - off_edit &= 0xFFAC; - off_edit |= ((offset >> 6) & 0x01) << 0; - off_edit |= ((offset >> 4) & 0x01) << 1; - off_edit |= ((offset >> 1) & 0x01) << 4; - off_edit |= ((offset >> 0) & 0x01) << 6; - } - //logerror("read from %04X (%04X)\n", offset, off_edit); - - if (offset & 0x4000) /* RB1 */ - return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)] * 0x4000 + (offset & 0x3fff)]; - else /* RB0 */ - return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank & ~m_mask)] * 0x4000 + (off_edit & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_sachen_mmc1_device::write_bank) -{ - /* Only A15..A6, A4, A1..A0 are connected */ - /* We only decode upper three bits */ - switch ((offset & 0xFFD3) & 0xE000) - { - case 0x0000: /* Base ROM Bank Register */ - - if ((m_latch_bank2 & 0x30) == 0x30) - m_base_bank = data; - //logerror("write to base bank %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)); - break; - - case 0x2000: /* ROM Bank Register */ - - m_latch_bank2 = data ? data : 0x01; - //logerror("write to latch %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)); - break; - - case 0x4000: /* ROM Bank Mask Register */ - - if ((m_latch_bank2 & 0x30) == 0x30) - m_mask = data; - //logerror("write to mask %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)); - break; - - case 0x6000: - - /* nothing happens when writing to 0x6000-0x7fff, as verified by Tauwasser */ - break; - - default: - - //logerror("write to unknown/unmapped area %04X <= %02X\n", offset, data); - /* did not extensively test other unlikely ranges */ - break; - } -} - -// Sachen MMC2 - -READ8_MEMBER(gb_rom_sachen_mmc2_device::read_rom) -{ - UINT16 off_edit = offset; - - /* Wait for 0x30 transitions of A15 (lo -> hi), i.e. ROM accesses; A15 = HI while in bootstrap */ - /* This is 0x30 transitions, because we increment counter _after_ checking it, but A15 lo -> hi*/ - /* transition means first read (hi -> lo transition) must not count */ - - if (m_unlock_cnt == 0x30 && m_mode == MODE_LOCKED_DMG) { - m_mode = MODE_LOCKED_CGB; - m_unlock_cnt = 0x00; - } else if (m_unlock_cnt == 0x30 && m_mode == MODE_LOCKED_CGB) { - m_mode = MODE_UNLOCKED; - } - - if (m_unlock_cnt != 0x30) - m_unlock_cnt++; - - /* Logo Switch */ - if (m_mode == MODE_LOCKED_CGB) - off_edit |= 0x80; - - /* Header Un-Scramble */ - if ((off_edit & 0xFF00) == 0x0100) { - off_edit &= 0xFFAC; - off_edit |= ((offset >> 6) & 0x01) << 0; - off_edit |= ((offset >> 4) & 0x01) << 1; - off_edit |= ((offset >> 1) & 0x01) << 4; - off_edit |= ((offset >> 0) & 0x01) << 6; - } - //logerror("read from %04X (%04X) cnt: %02X\n", offset, off_edit, m_unlock_cnt); - - if (offset & 0x4000) /* RB1 */ - return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)] * 0x4000 + (offset & 0x3fff)]; - else /* RB0 */ - return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank & ~m_mask)] * 0x4000 + (off_edit & 0x3fff)]; -} - -READ8_MEMBER(gb_rom_sachen_mmc2_device::read_ram) -{ - if (m_mode == MODE_LOCKED_DMG) { - m_unlock_cnt = 0x00; - m_mode = MODE_LOCKED_CGB; - } - return 0xFF; - -} - -WRITE8_MEMBER(gb_rom_sachen_mmc2_device::write_ram) -{ - if (m_mode == MODE_LOCKED_DMG) { - m_unlock_cnt = 0x00; - m_mode = MODE_LOCKED_CGB; - } - -} - - -// 188 in 1 pirate (only preliminary) - -READ8_MEMBER(gb_rom_188in1_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[m_game_base + rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[m_game_base + rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_188in1_device::write_bank) -{ - if (offset == 0x7b00) - { - if (data < 0x80) - logerror("write to 0x%X data 0x%X\n", offset, data); - else - { - data -= 0x80; - m_game_base = 0x400000 + (data * 0x8000); - //logerror("offset 0x%X\n", m_game_base); - } - } - else if (offset == 0x7b01 || offset == 0x7b02) - { - // what do these writes do? - printf("write to 0x%X data 0x%X\n", offset, data); - } - else - gb_rom_mbc1_device::write_bank(space, offset, data); -} - - -// MBC5 variant used by Li Cheng / Niutoude games - -WRITE8_MEMBER(gb_rom_licheng_device::write_bank) -{ - if (offset > 0x2100 && offset < 0x3000) - return; - - gb_rom_mbc5_device::write_bank(space, offset, data); -} - -// MBC5 variant used by Chong Wu Xiao Jing Ling (this appears to be a re-release of a Li Cheng / Niutoude game, -// given that it contains the Niutoude logo, with most protection checks patched out) - -READ8_MEMBER(gb_rom_chongwu_device::read_rom) -{ - // protection check at the first read here... - if (offset == 0x41c3 && !m_protection_checked) - { - m_protection_checked = 1; - return 0x5d; - } - - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; -} - -// MBC5 variant used by Sintax games - -void gb_rom_sintax_device::set_xor_for_bank(UINT8 bank) -{ - switch (bank & 0x0f) - { - case 0x00: case 0x04: case 0x08: case 0x0c: - m_currentxor = m_xor2; - break; - case 0x01: case 0x05: case 0x09: case 0x0d: - m_currentxor = m_xor3; - break; - case 0x02: case 0x06: case 0x0a: case 0x0e: - m_currentxor = m_xor4; - break; - case 0x03: case 0x07: case 0x0b: case 0x0f: - m_currentxor = m_xor5; - break; - } -} - -READ8_MEMBER(gb_rom_sintax_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)] ^ m_currentxor; -} - -WRITE8_MEMBER(gb_rom_sintax_device::write_bank) -{ - if (offset < 0x2000) - m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0; - else if (offset < 0x3000) - { - set_xor_for_bank(data); - - switch (m_sintax_mode & 0x0f) - { - case 0x0d: - data = BITSWAP8(data, 1,0,7,6,5,4,3,2); - break; - case 0x09: - //data = BITSWAP8(data, 3,2,5,4,0,1,6,7); // Monkey..no - data = BITSWAP8(data, 4,5,2,3,0,1,6,7); - break; - case 0x00: // 0x10=lion 0x00 hmmmmm // 1 and 0 unconfirmed - data = BITSWAP8(data, 7,0,5,6,3,4,1,2); - break; - case 0x01: - data = BITSWAP8(data, 0,1,6,7,4,5,2,3); - break; - case 0x05: - data = BITSWAP8(data, 7,6,1,0,3,2,5,4); // Not 100% on this one - break; - case 0x07: - data = BITSWAP8(data, 2,0,3,1,5,4,7,6); // 5 and 7 unconfirmed - break; - case 0x0b: - data = BITSWAP8(data, 2,3,0,1,6,7,4,5); // 5 and 6 unconfirmed - break; - } - m_latch_bank2 = (m_latch_bank2 & 0x100) | data; - } - else if (offset < 0x4000) - { - m_latch_bank2 = (m_latch_bank2 & 0xff) | ((data & 0x01) << 8); - } - else if (offset < 0x5000) - { - data &= 0x0f; - if (has_rumble) - data &= 0x7; - m_ram_bank = data; - } - else if (offset < 0x6000) - { - if (!m_sintax_mode) - { - m_sintax_mode = data; - write_bank(space, 0x2000, 1); //force a fake bank switch - } -// printf("sintax mode %x\n", m_sintax_mode & 0xf); - } - else if (offset >= 0x7000) - { - switch ((offset & 0x00f0) >> 4) - { - case 2: - m_xor2 = data; - break; - case 3: - m_xor3 = data; - break; - case 4: - m_xor4 = data; - break; - case 5: - m_xor5 = data; - break; - } - - if (m_currentxor == 0) - set_xor_for_bank(4); - } - -} - -READ8_MEMBER(gb_rom_sintax_device::read_ram) -{ - if (!m_ram.empty() && m_ram_enable) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_sintax_device::write_ram) -{ - if (!m_ram.empty() && m_ram_enable) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data; -} - -/* - - Further MBC5 variants to emulate: - - Digimon 2 & Digimon 4 (Yong Yong) - - Digimon 2 writes at $2000 to select latch2 (data must be divided by 2, and 0 becomes 1), - then writes to $2400 a series of values that the patched version does not write... - Digimon 4 seems to share part of the $2000 behavior, but does not write to $2400... - - */ - -// MBC5 variant used by Digimon 2 (and maybe 4?) - -READ8_MEMBER(gb_rom_digimon_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_digimon_device::write_bank) -{ - if (offset < 0x2000) - m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0; - else if (offset == 0x2000) - { -// printf("written $02 %X at %X\n", data, offset); - if (!data) - data++; - m_latch_bank2 = data/2; - } - else if (offset < 0x3000) - { -// printf("written $03 %X at %X\n", data, offset); - } - else if (offset < 0x4000) - { -// printf("written $04 %X at %X\n", data, offset); - } - else if (offset < 0x6000) - { -// printf("written $05-$06 %X at %X\n", data, offset); - data &= 0x0f; - if (has_rumble) - data &= 0x7; - m_ram_bank = data; - } -// else -// printf("written $07 %X at %X\n", data, offset); -} - -READ8_MEMBER(gb_rom_digimon_device::read_ram) -{ - if (!m_ram.empty() && m_ram_enable) - return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_digimon_device::write_ram) -{ - if (!m_ram.empty() && m_ram_enable) - m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data; -} - - -// MBC1 variant used by Yong Yong for Rockman 8 - -READ8_MEMBER(gb_rom_rockman8_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[m_latch_bank * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[m_latch_bank2 * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_rockman8_device::write_bank) -{ - if (offset < 0x2000) - return; - else if (offset < 0x4000) - { - // 5bits only - data &= 0x1f; - if (data == 0) - data = 1; - if (data > 0xf) - data -= 8; - - m_latch_bank2 = data; - } -} - -READ8_MEMBER(gb_rom_rockman8_device::read_ram) -{ - if (!m_ram.empty()) - return m_ram[offset]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_rockman8_device::write_ram) -{ - if (!m_ram.empty()) - m_ram[offset] = data; -} - -// MBC1 variant used by Yong Yong for Super Mario 3 Special - -// Mario special seems to be 512k image (mirrored up to 1m or 2m [redump needed to establish this]) -// it consists of 13 unique 16k chunks layed out as follows -// unique chunk --> bank in bin -// 1st to 7th --> 0x00 to 0x06 -// 8th --> 0x08 -// 9th --> 0x0b -// 10th --> 0x0c -// 11th --> 0x0d -// 12th --> 0x0f -// 13th --> 0x13 - -// writing data to 0x2000-0x2fff switches bank according to the table below -// (the value values corresponding to table[0x0f] is not confirmed, choices -// 0,1,2,3,8,c,f freeze the game, while 4,5,6,7,b,d,0x13 work with glitches) -static UINT8 smb3_table1[0x20] = -{ - 0x00,0x04,0x01,0x05, 0x02,0x06,0x03,0x05, 0x08,0x0c,0x03,0x0d, 0x03,0x0b,0x0b,0x08 /* original doc here put 0x0f (i.e. 11th unique bank) */, - 0x05,0x06,0x0b,0x0d, 0x08,0x06,0x13,0x0b, 0x08,0x05,0x05,0x08, 0x0b,0x0d,0x06,0x05 -}; - -// according to old doc from Brian Provinciano, writing bit5 in 0x5000-0x5fff should -// change the bank layout, in the sense that writing to bankswitch acts like if -// the original rom has a different layout (as if unique chunks were under permutations -// (24), (365) and (8a9) with 0,1,7,b,c fixed) and the same table above is used -// however, no such a write ever happen (only bit4 is written, but changing mode with -// bit4 breaks the gfx...) - -READ8_MEMBER(gb_rom_sm3sp_device::read_rom) -{ - if (offset < 0x4000) - return m_rom[rom_bank_map[0] * 0x4000 + (offset & 0x3fff)]; - else - return m_rom[m_latch_bank2 * 0x4000 + (offset & 0x3fff)]; -} - -WRITE8_MEMBER(gb_rom_sm3sp_device::write_bank) -{ -// printf("write 0x%x at %x\n", data, offset); - if (offset < 0x2000) - return; - else if (offset < 0x3000) - { - // Table 1 confirmed... - // 0->0, 4->2, 6->3 - // 1e -> 6 (level 1 bg gfx) - // 19 -> 5 (level 2 bg gfx) - // 1b -> 8 (level 3 bg gfx) - // 1d -> D (level 4 bg gfx) - // 1c -> B (bonus house bg gfx) - // 1 (9 maybe, or 3)? f (5 maybe)? 2->1? - // 16 -> 4-8? b? - - // 5bits only - data &= 0x1f; - - m_latch_bank2 = smb3_table1[data]; - if (m_mode) - { - switch (m_latch_bank2) - { - case 0x02: m_latch_bank2 = 4; break; - case 0x03: m_latch_bank2 = 6; break; - case 0x04: m_latch_bank2 = 2; break; - case 0x05: m_latch_bank2 = 3; break; - case 0x06: m_latch_bank2 = 5; break; - case 0x0b: m_latch_bank2 = 0xd; break; - case 0x0c: m_latch_bank2 = 0xb; break; - case 0x0d: m_latch_bank2 = 0xc; break; - - case 0x00: - case 0x01: - case 0x08: - case 0x0f: - case 0x13: - default: - break; - } - } - } - else if (offset < 0x5000) - { -// printf("write $5 %X at %X\n", data, offset); - //maybe rumble?? - } - else if (offset < 0x6000) - { -// printf("write mode %x\n", data); - m_mode = BIT(data, 5); -// write_bank(space, 0x2000, 1); - } -} - -READ8_MEMBER(gb_rom_sm3sp_device::read_ram) -{ - if (!m_ram.empty()) - return m_ram[offset]; - else - return 0xff; -} - -WRITE8_MEMBER(gb_rom_sm3sp_device::write_ram) -{ - if (!m_ram.empty()) - m_ram[offset] = data; -} |