diff options
Diffstat (limited to 'src/devices/bus/vcs/rom.cpp')
-rw-r--r-- | src/devices/bus/vcs/rom.cpp | 1171 |
1 files changed, 482 insertions, 689 deletions
diff --git a/src/devices/bus/vcs/rom.cpp b/src/devices/bus/vcs/rom.cpp index 9650bc29661..f40591e1173 100644 --- a/src/devices/bus/vcs/rom.cpp +++ b/src/devices/bus/vcs/rom.cpp @@ -21,8 +21,7 @@ // a26_rom_*k_device - constructor //------------------------------------------------- -DEFINE_DEVICE_TYPE(A26_ROM_2K, a26_rom_2k_device, "vcs_2k", "Atari VCS 2600 2K ROM Carts") -DEFINE_DEVICE_TYPE(A26_ROM_4K, a26_rom_4k_device, "vcs_4k", "Atari VCS 2600 4K ROM Carts") +DEFINE_DEVICE_TYPE(A26_ROM_2K_4K, a26_rom_2k_4k_device, "vcs_2k_4k", "Atari VCS 2600 2K/4K ROM Carts") DEFINE_DEVICE_TYPE(A26_ROM_F4, a26_rom_f4_device, "vcs_f4", "Atari VCS 2600 ROM Carts w/F4 bankswitch") DEFINE_DEVICE_TYPE(A26_ROM_F6, a26_rom_f6_device, "vcs_f6", "Atari VCS 2600 ROM Carts w/F6 bankswitch") DEFINE_DEVICE_TYPE(A26_ROM_F8, a26_rom_f8_device, "vcs_f8", "Atari VCS 2600 ROM Carts w/F8 bankswitch") @@ -44,301 +43,95 @@ DEFINE_DEVICE_TYPE(A26_ROM_32IN1, a26_rom_32in1_device, "vcs_32in1", "Atari VCS DEFINE_DEVICE_TYPE(A26_ROM_X07, a26_rom_x07_device, "vcs_x07", "Atari VCS 2600 ROM Carts w/X07 bankswitch") -a26_rom_2k_device::a26_rom_2k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock), device_vcs_cart_interface(mconfig, *this) -{ -} - -a26_rom_2k_device::a26_rom_2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_2k_device(mconfig, A26_ROM_2K, tag, owner, clock) -{ -} - -a26_rom_4k_device::a26_rom_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_2k_device(mconfig, A26_ROM_4K, tag, owner, clock) -{ -} - - -a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_2k_device(mconfig, type, tag, owner, clock) - , m_base_bank(-1) // set to -1 to help the Xin1 multicart... -{ -} - -a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_F6, tag, owner, clock) +bool a26_rom_base_device::is_ram_present(size_t minimum_size) { + return m_ram.size() >= minimum_size; } - -a26_rom_f4_device::a26_rom_f4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_F4, tag, owner, clock) +uint8_t a26_rom_base_device::read_ram(offs_t offset) { + return m_ram[offset]; } - -a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, type, tag, owner, clock) +void a26_rom_base_device::write_ram(offs_t offset, uint8_t data) { + m_ram[offset] = data; } -a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f8_device(mconfig, A26_ROM_F8, tag, owner, clock) -{ -} -a26_rom_f8_sw_device::a26_rom_f8_sw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f8_device(mconfig, A26_ROM_F8_SW, tag, owner, clock) -{ -} - -a26_rom_fa_device::a26_rom_fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_FA, tag, owner, clock) -{ -} - - -a26_rom_fe_device::a26_rom_fe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_2k_device(mconfig, A26_ROM_FE, tag, owner, clock), m_base_bank(0), m_trigger_on_next_access(0) -{ -} - - -a26_rom_3e_device::a26_rom_3e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_3E, tag, owner, clock), m_num_bank(0), m_ram_bank(0), m_ram_enable(0) -{ -} - - -a26_rom_3f_device::a26_rom_3f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_3F, tag, owner, clock), m_num_bank(0) -{ -} - - -a26_rom_e0_device::a26_rom_e0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_E0, tag, owner, clock) -{ -} - - -a26_rom_e7_device::a26_rom_e7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_E7, tag, owner, clock), m_ram_bank(0) -{ -} - - -a26_rom_ua_device::a26_rom_ua_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_UA, tag, owner, clock) -{ -} - - -a26_rom_cv_device::a26_rom_cv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_2k_device(mconfig, A26_ROM_CV, tag, owner, clock) -{ -} - - -a26_rom_dc_device::a26_rom_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_DC, tag, owner, clock) -{ -} - - -a26_rom_fv_device::a26_rom_fv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_FV, tag, owner, clock), m_locked(0) -{ -} - - -a26_rom_jvp_device::a26_rom_jvp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_JVP, tag, owner, clock) -{ -} +/*------------------------------------------------- + BASE 2K & 4K Carts: + no bankswitch + GAMES: a large majority + -------------------------------------------------*/ -a26_rom_4in1_device::a26_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_4IN1, tag, owner, clock) +a26_rom_2k_4k_device::a26_rom_2k_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_2K_4K, tag, owner, clock) { } - -a26_rom_8in1_device::a26_rom_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f8_device(mconfig, A26_ROM_8IN1, tag, owner, clock), m_reset_bank(0) +void a26_rom_2k_4k_device::install_memory_handlers(address_space *space) { + if (m_rom_size < 0x1000) + space->install_rom(0x1000, 0x17ff, 0x800, get_rom_base()); + else + space->install_rom(0x1000, 0x1fff, get_rom_base()); } -a26_rom_32in1_device::a26_rom_32in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_32IN1, tag, owner, clock) -{ -} -a26_rom_x07_device::a26_rom_x07_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a26_rom_f6_device(mconfig, A26_ROM_X07, tag, owner, clock) -{ -} +/*------------------------------------------------- + "F6 Bankswitch" Carts: + read/write access to 0x1ff6-0x1ff9 determines the + 4K ROM bank to be read + GAMES: Atari 16K games, like Crossbow, Crystal + Castles and the 2-in-1 carts -void a26_rom_2k_device::device_start() -{ -} + -------------------------------------------------*/ -void a26_rom_2k_device::device_reset() +a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, type, tag, owner, clock) + , m_bank(*this, "bank") { } -void a26_rom_f6_device::device_start() +a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_f6_device(mconfig, A26_ROM_F6, tag, owner, clock) { - save_item(NAME(m_base_bank)); } void a26_rom_f6_device::device_reset() { - m_base_bank = 0; -} - -void a26_rom_f4_device::device_reset() -{ - m_base_bank = 7; -} - -void a26_rom_f8_sw_device::device_reset() -{ - // Snow White proto starts from bank 1!!! - m_base_bank = 1; -} - -void a26_rom_fe_device::device_start() -{ - save_item(NAME(m_base_bank)); - save_item(NAME(m_trigger_on_next_access)); -} - -void a26_rom_fe_device::device_reset() -{ - m_base_bank = 0; - m_trigger_on_next_access = 0; -} - -void a26_rom_3e_device::device_start() -{ - save_item(NAME(m_base_bank)); - save_item(NAME(m_ram_bank)); - save_item(NAME(m_ram_enable)); -} - -void a26_rom_3e_device::device_reset() -{ - m_num_bank = m_rom_size / 0x800; - m_base_bank = m_num_bank - 1; - m_ram_bank = 0; - m_ram_enable = 0; -} - -void a26_rom_3f_device::device_reset() -{ - m_num_bank = m_rom_size / 0x800; - m_base_bank = m_num_bank - 1; + m_bank->set_entry(get_start_bank()); } -void a26_rom_e0_device::device_start() +void a26_rom_f6_device::install_super_chip_handlers(address_space *space) { - save_item(NAME(m_base_banks)); -} - -void a26_rom_e0_device::device_reset() -{ - m_base_banks[0] = 4; - m_base_banks[1] = 5; - m_base_banks[2] = 6; - m_base_banks[3] = 7; -} - -void a26_rom_e7_device::device_start() -{ - save_item(NAME(m_base_bank)); - save_item(NAME(m_ram_bank)); -} - -void a26_rom_e7_device::device_reset() -{ - m_base_bank = 0; - m_ram_bank = 0; -} - -void a26_rom_ua_device::device_reset() -{ - m_base_bank = 0; -} - -void a26_rom_fv_device::device_start() -{ - save_item(NAME(m_base_bank)); - save_item(NAME(m_locked)); -} - -void a26_rom_fv_device::device_reset() -{ - m_base_bank = 0; - m_locked = 0; -} - - -void a26_rom_4in1_device::device_reset() -{ - m_base_bank++; - m_base_bank &= 3; -} - - -void a26_rom_8in1_device::device_start() -{ - save_item(NAME(m_base_bank)); - save_item(NAME(m_reset_bank)); + if (is_ram_present(0x80)) { + space->install_read_handler(0x1080, 0x10ff, read8sm_delegate(*this, FUNC(a26_rom_f6_device::read_ram))); + space->install_write_handler(0x1000, 0x107f, write8sm_delegate(*this, FUNC(a26_rom_f6_device::write_ram))); + } } -void a26_rom_8in1_device::device_reset() +void a26_rom_f6_device::install_memory_handlers(address_space *space) { - // we use here two different bank counter: the main one for the 8x8K chunks, - // and the usual one (m_base_bank) for the 4K bank of the current game - m_reset_bank++; - m_reset_bank &= 7; - m_base_bank = 0; + m_bank->configure_entries(0, 4, get_rom_base(), 0x1000); + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_write_handler(0x1ff6, 0x1ff9, write8sm_delegate(*this, FUNC(a26_rom_f6_device::switch_bank))); + install_super_chip_handlers(space); + space->install_read_tap(0x1ff6, 0x1ff9, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff6, 0); }); } - -void a26_rom_32in1_device::device_reset() +void a26_rom_f6_device::switch_bank(offs_t offset, uint8_t data) { - m_base_bank++; - m_base_bank &= 0x1f; + m_bank->set_entry(offset); } -/*------------------------------------------------- - mapper specific handlers - -------------------------------------------------*/ - -/*------------------------------------------------- - BASE 2K & 4K Carts: - no bankswitch - - GAMES: a large majority - -------------------------------------------------*/ - -READ8_MEMBER(a26_rom_2k_device::read_rom) -{ - // Super Chip RAM reads are mapped in 0x1080-0x10ff - if (!m_ram.empty() && offset >= 0x80 && offset < 0x100) - { - return m_ram[offset & (m_ram.size() - 1)]; - } - - return m_rom[offset & (m_rom_size - 1)]; -} /*------------------------------------------------- "F4 Bankswitch" Carts: @@ -348,119 +141,21 @@ READ8_MEMBER(a26_rom_2k_device::read_rom) GAMES: Fatal Run -------------------------------------------------*/ -READ8_MEMBER(a26_rom_f4_device::read_rom) -{ - // Super Chip RAM reads are mapped in 0x1080-0x10ff - if (!m_ram.empty() && offset >= 0x80 && offset < 0x100) - { - return m_ram[offset & (m_ram.size() - 1)]; - } - - // update banks - if (!machine().side_effects_disabled()) - { - switch (offset) - { - case 0x0ff4: - case 0x0ff5: - case 0x0ff6: - case 0x0ff7: - case 0x0ff8: - case 0x0ff9: - case 0x0ffa: - case 0x0ffb: - m_base_bank = offset - 0x0ff4; - break; - } - } - - return m_rom[offset + (m_base_bank * 0x1000)]; -} - -WRITE8_MEMBER(a26_rom_f4_device::write_bank) +a26_rom_f4_device::a26_rom_f4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_f6_device(mconfig, A26_ROM_F4, tag, owner, clock) { - // Super Chip RAM writes are mapped in 0x1000-0x107f - if (!m_ram.empty() && offset < 0x80) - { - m_ram[offset & (m_ram.size() - 1)] = data; - return; - } - - switch (offset) - { - case 0x0ff4: - case 0x0ff5: - case 0x0ff6: - case 0x0ff7: - case 0x0ff8: - case 0x0ff9: - case 0x0ffa: - case 0x0ffb: - m_base_bank = offset - 0x0ff4; - break; - default: - logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000); - break; - } } -/*------------------------------------------------- - "F6 Bankswitch" Carts: - read/write access to 0x1ff6-0x1ff9 determines the - 4K ROM bank to be read - - GAMES: Atari 16K games, like Crossbow, Crystal - Castles and the 2-in-1 carts - - -------------------------------------------------*/ - -READ8_MEMBER(a26_rom_f6_device::read_rom) +void a26_rom_f4_device::install_memory_handlers(address_space *space) { - // Super Chip RAM reads are mapped in 0x1080-0x10ff - if (!m_ram.empty() && offset >= 0x80 && offset < 0x100) - { - return m_ram[offset & (m_ram.size() - 1)]; - } - - // update banks - if (!machine().side_effects_disabled()) - { - switch (offset) - { - case 0x0ff6: - case 0x0ff7: - case 0x0ff8: - case 0x0ff9: - m_base_bank = offset - 0x0ff6; - break; - } - } - - return m_rom[offset + (m_base_bank * 0x1000)]; + m_bank->configure_entries(0, 8, get_rom_base(), 0x1000); + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_write_handler(0x1ff4, 0x1ffb, write8sm_delegate(*this, FUNC(a26_rom_f4_device::switch_bank))); + install_super_chip_handlers(space); + space->install_read_tap(0x1ff4, 0x1ffb, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff4, 0); }); } -WRITE8_MEMBER(a26_rom_f6_device::write_bank) -{ - // Super Chip RAM writes are mapped in 0x1000-0x107f - if (!m_ram.empty() && offset < 0x80) - { - m_ram[offset & (m_ram.size() - 1)] = data; - return; - } - - switch (offset) - { - case 0x0ff6: - case 0x0ff7: - case 0x0ff8: - case 0x0ff9: - m_base_bank = offset - 0x0ff6; - break; - default: - logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000); - break; - } -} /*------------------------------------------------- "F8 Bankswitch" Carts: @@ -472,50 +167,33 @@ WRITE8_MEMBER(a26_rom_f6_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_f8_device::read_rom) +a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_f6_device(mconfig, type, tag, owner, clock) { - // Super Chip RAM reads are mapped in 0x1080-0x10ff - if (!m_ram.empty() && offset >= 0x80 && offset < 0x100) - { - return m_ram[offset & (m_ram.size() - 1)]; - } - - // update banks - if (!machine().side_effects_disabled()) - { - switch (offset) - { - case 0x0ff8: - case 0x0ff9: - m_base_bank = offset - 0x0ff8; - break; - } - } +} - return m_rom[offset + (m_base_bank * 0x1000)]; +a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_f8_device(mconfig, A26_ROM_F8, tag, owner, clock) +{ } -WRITE8_MEMBER(a26_rom_f8_device::write_bank) +void a26_rom_f8_device::install_memory_handlers(address_space *space) { - // Super Chip RAM writes are mapped in 0x1000-0x107f - if (!m_ram.empty() && offset < 0x80) - { - m_ram[offset & (m_ram.size() - 1)] = data; - return; - } + m_bank->configure_entries(0, 2, get_rom_base(), 0x1000); + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_write_handler(0x1ff8, 0x1ff9, write8sm_delegate(*this, FUNC(a26_rom_f8_device::switch_bank))); + install_super_chip_handlers(space); + space->install_read_tap(0x1ff8, 0x1ff9, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff8, 0); }); +} - switch (offset) - { - case 0x0ff8: - case 0x0ff9: - m_base_bank = offset - 0x0ff8; - break; - default: - logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000); - break; - } + +a26_rom_f8_sw_device::a26_rom_f8_sw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_f8_device(mconfig, A26_ROM_F8_SW, tag, owner, clock) +{ } + /*------------------------------------------------- "FA Bankswitch" Carts: read/write access to 0x1ff8-0x1ffa determines the @@ -528,51 +206,24 @@ WRITE8_MEMBER(a26_rom_f8_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_fa_device::read_rom) +a26_rom_fa_device::a26_rom_fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_f6_device(mconfig, A26_ROM_FA, tag, owner, clock) { - // CBS RAM+ reads are mapped in 0x1100-0x11ff - if (!m_ram.empty() && offset >= 0x100 && offset < 0x200) - { - return m_ram[offset & (m_ram.size() - 1)]; - } - - // update banks - if (!machine().side_effects_disabled()) - { - switch (offset) - { - case 0x0ff8: - case 0x0ff9: - case 0x0ffa: - m_base_bank = offset - 0x0ff8; - break; - } - } - - return m_rom[offset + (m_base_bank * 0x1000)]; } -WRITE8_MEMBER(a26_rom_fa_device::write_bank) +void a26_rom_fa_device::install_memory_handlers(address_space *space) { - // CBS RAM+ writes are mapped in 0x1000-0x10ff - if (!m_ram.empty() && offset < 0x100) - { - m_ram[offset & (m_ram.size() - 1)] = data; - } - - switch (offset) - { - case 0x0ff8: - case 0x0ff9: - case 0x0ffa: - m_base_bank = offset - 0x0ff8; - break; - default: - logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000); - break; - } + m_bank->configure_entries(0, 3, get_rom_base(), 0x1000); + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_write_handler(0x1ff8, 0x1ffa, write8sm_delegate(*this, FUNC(a26_rom_fa_device::switch_bank))); + space->install_read_tap(0x1ff8, 0x1ffa, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff8, 0); }); + space->install_read_handler(0x1100, 0x11ff, read8sm_delegate(*this, FUNC(a26_rom_fa_device::read_ram))); + space->install_write_handler(0x1000, 0x10ff, write8sm_delegate(*this, FUNC(a26_rom_fa_device::write_ram))); } + + /*------------------------------------------------- "FE Bankswitch" Carts: read/write access to 0x01fe-0x1ff determines the @@ -581,6 +232,43 @@ WRITE8_MEMBER(a26_rom_fa_device::write_bank) GAMES: Activision 8K games like Decathlon -------------------------------------------------*/ + +a26_rom_fe_device::a26_rom_fe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_FE, tag, owner, clock) + , m_bank(*this, "bank") + , m_trigger_on_next_access(false) + , m_ignore_first_read(true) +{ +} + +void a26_rom_fe_device::device_start() +{ + save_item(NAME(m_trigger_on_next_access)); + save_item(NAME(m_ignore_first_read)); +} + +void a26_rom_fe_device::device_reset() +{ + m_bank->set_entry(0); + m_trigger_on_next_access = false; + // During cpu startup, before reading the boot vector a read from $01fe occurs + m_ignore_first_read = true; +} + +void a26_rom_fe_device::install_memory_handlers(address_space *space) +{ + m_bank->configure_entries(0, 8, get_rom_base(), 0x1000); + + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_readwrite_tap(0x1fe, 0x1fe, "trigger_bank", + [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) trigger_bank(); }, + [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) trigger_bank(); }); + space->install_read_tap(0x1ff, 0x1ff, "switch_bank1", + [this] (offs_t, u8 &data, u8) { if (!machine().side_effects_disabled()) switch_bank(data); }); + space->install_read_tap(0x1000, 0x1fff, "switch_bank2", + [this] (offs_t, u8 &data, u8) { if (!machine().side_effects_disabled()) switch_bank(data); }); +} + /* There seems to be a kind of lag between the writing to address 0x1FE and the @@ -593,73 +281,25 @@ WRITE8_MEMBER(a26_rom_fa_device::write_bank) */ -READ8_MEMBER(a26_rom_fe_device::read_rom) +void a26_rom_fe_device::switch_bank(uint8_t data) { - uint8_t data; - - // Super Chip RAM reads are mapped in 0x1080-0x10ff - if (!m_ram.empty() && offset >= 0x80 && offset < 0x100) - { - return m_ram[offset & (m_ram.size() - 1)]; - } - - data = m_rom[offset + (m_base_bank * 0x1000)]; - - if (!machine().side_effects_disabled()) + if (m_trigger_on_next_access) { - if (m_trigger_on_next_access) - { - m_base_bank = BIT(data, 5) ? 0 : 1; - m_trigger_on_next_access = 0; - } + m_bank->set_entry(BIT(data, 5) ? 0 : 1); + m_trigger_on_next_access = false; } - - return data; } -WRITE8_MEMBER(a26_rom_fe_device::write_ram) +void a26_rom_fe_device::trigger_bank() { - // Super Chip RAM writes are mapped in 0x1000-0x107f - if (!m_ram.empty() && offset < 0x80) - { - m_ram[offset & (m_ram.size() - 1)] = data; - } + if (m_ignore_first_read) + m_ignore_first_read = false; + else + // The next byte on the data bus determines which bank to switch to + m_trigger_on_next_access = true; } -READ8_MEMBER(a26_rom_fe_device::read_bank) -{ - uint8_t data = space.read_byte(0xfe + offset); - if (!machine().side_effects_disabled()) - { - switch (offset & 1) - { - case 0: - // The next byte on the data bus determines which bank to switch to - m_trigger_on_next_access = 1; - break; - - case 1: - if (m_trigger_on_next_access) - { - m_base_bank = BIT(data, 5) ? 0 : 1; - m_trigger_on_next_access = 0; - } - break; - } - } - return data; -} - -WRITE8_MEMBER(a26_rom_fe_device::write_bank) -{ - space.write_byte(0xfe, data); - if (!machine().side_effects_disabled()) - { - // The next byte on the data bus determines which bank to switch to - m_trigger_on_next_access = 1; - } -} /*------------------------------------------------- "3E Bankswitch" Carts: @@ -671,38 +311,58 @@ WRITE8_MEMBER(a26_rom_fe_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_3e_device::read_rom) +a26_rom_3e_device::a26_rom_3e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_3E, tag, owner, clock) + , m_rom_bank(*this, "rom_bank") + , m_ram_bank(*this, "ram_bank") + , m_view(*this, "view") + , m_rom_bank_mask(0) + , m_ram_bank_mask(0) { - if (!m_ram.empty() && m_ram_enable && offset < 0x400) - return m_ram[offset + (m_ram_bank * 0x400)]; +} - if (offset >= 0x800) - return m_rom[(offset & 0x7ff) + (m_num_bank - 1) * 0x800]; - else - return m_rom[offset + m_base_bank * 0x800]; +void a26_rom_3e_device::device_reset() +{ + m_rom_bank->set_entry(m_rom_bank_mask); + m_view.select(0); } -WRITE8_MEMBER(a26_rom_3e_device::write_bank) +void a26_rom_3e_device::install_memory_handlers(address_space *space) { - if (offset == 0x3f) - { - m_base_bank = data & (m_num_bank - 1); - m_ram_enable = 0; - } - else if (offset == 0x3e) - { - m_ram_bank = data & 0x1f; - m_ram_enable = 1; - } + m_rom_bank_mask = (get_rom_size() / 0x800) - 1; + m_ram_bank_mask = (get_ram_size() / 0x400) - 1; + m_rom_bank->configure_entries(0, m_rom_bank_mask + 1, get_rom_base(), 0x800); + m_ram_bank->configure_entries(0, m_ram_bank_mask + 1, get_ram_base(), 0x400); + + space->install_view(0x1000, 0x17ff, m_view); + // RAM disabled + m_view[0].install_read_bank(0x1000, 0x17ff, m_rom_bank); + // RAM enabled + m_view[1].install_read_bank(0x1000, 0x17ff, m_rom_bank); + m_view[1].install_read_bank(0x1000, 0x13ff, m_ram_bank); + m_view[1].install_write_bank(0x1400, 0x17ff, m_ram_bank); + + space->install_rom(0x1800, 0x1fff, get_rom_base() + m_rom_bank_mask * 0x800); + space->install_write_tap(0x3e, 0x3e, "ram_bank", + [this] (offs_t address, u8 &data, u8) { if (!machine().side_effects_disabled()) select_ram_bank(address, data); }); + space->install_write_tap(0x3f, 0x3f, "rom_bank", + [this] (offs_t address, u8 &data, u8) { if (!machine().side_effects_disabled()) select_rom_bank(address, data); }); +} + +void a26_rom_3e_device::select_ram_bank(offs_t address, uint8_t data) +{ + m_ram_bank->set_entry(data & m_ram_bank_mask); + m_view.select(1); } -WRITE8_MEMBER(a26_rom_3e_device::write_ram) +void a26_rom_3e_device::select_rom_bank(offs_t address, uint8_t data) { - if (!m_ram.empty() && m_ram_enable && offset >= 0x400 && offset < 0x800) - m_ram[(offset & 0x3ff) + (m_ram_bank * 0x400)] = data; + m_rom_bank->set_entry(data & m_rom_bank_mask); + m_view.select(0); } + /*------------------------------------------------- "3F Bankswitch" Carts: write access to 0x00-0x3f determines the 2K ROM bank @@ -714,22 +374,40 @@ WRITE8_MEMBER(a26_rom_3e_device::write_ram) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_3f_device::read_rom) +a26_rom_3f_device::a26_rom_3f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_3F, tag, owner, clock) + , m_bank(*this, "bank") + , m_bank_mask(0) { - if (offset >= 0x800) - return m_rom[(offset & 0x7ff) + (m_num_bank - 1) * 0x800]; - else - return m_rom[offset + m_base_bank * 0x800]; } -WRITE8_MEMBER(a26_rom_3f_device::write_bank) +void a26_rom_3f_device::device_reset() +{ + m_bank->set_entry(m_bank_mask); +} + +void a26_rom_3f_device::install_memory_handlers(address_space *space) +{ + m_bank_mask = (get_rom_size() / 0x800) - 1; + m_bank->configure_entries(0, get_rom_size() / 0x800, get_rom_base(), 0x800); + + space->install_read_bank(0x1000, 0x17ff, m_bank); + // last bank + space->install_rom(0x1800, 0x1fff, get_rom_base() + m_bank_mask * 0x800); + space->install_write_tap(0x00, 0x3f, "bank", + [this] (offs_t offset, u8 &data, u8) { if (!machine().side_effects_disabled()) select_bank(offset, data); }); +} + +void a26_rom_3f_device::select_bank(offs_t offset, uint8_t data) { - m_base_bank = data & (m_num_bank - 1); + m_bank->set_entry(data & m_bank_mask); } + + /*------------------------------------------------- "E0 Bankswitch" Carts: - read/write access to 0x1fe0-0x1ff8 determines the + read/write access to 0x1fe0-0x1ff7 determines the 1K ROM bank to be read in each 1K chunk (0x1c00-0x1fff always points to the last 1K of the ROM) @@ -737,25 +415,48 @@ WRITE8_MEMBER(a26_rom_3f_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_e0_device::read_rom) +a26_rom_e0_device::a26_rom_e0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_E0, tag, owner, clock) + , m_bank(*this, "bank%u", 0U) { - // update banks - if (!machine().side_effects_disabled()) - { - if (offset >= 0xfe0 && offset <= 0xff8) - m_base_banks[(offset >> 3) & 3] = offset & 7; - } +} - return m_rom[(offset & 0x3ff) + (m_base_banks[(offset >> 10) & 3] * 0x400)]; +void a26_rom_e0_device::device_reset() +{ + m_bank[0]->set_entry(4); + m_bank[1]->set_entry(5); + m_bank[2]->set_entry(6); } -WRITE8_MEMBER(a26_rom_e0_device::write_bank) +void a26_rom_e0_device::install_memory_handlers(address_space *space) { - if (offset >= 0xfe0 && offset <= 0xff8) - m_base_banks[(offset >> 3) & 3] = offset & 7; + m_bank[0]->configure_entries(0, 8, get_rom_base(), 0x400); + m_bank[1]->configure_entries(0, 8, get_rom_base(), 0x400); + m_bank[2]->configure_entries(0, 8, get_rom_base(), 0x400); + + space->install_read_bank(0x1000, 0x13ff, m_bank[0]); + space->install_read_bank(0x1400, 0x17ff, m_bank[1]); + space->install_read_bank(0x1800, 0x1bff, m_bank[2]); + space->install_rom(0x1c00, 0x1fff, get_rom_base() + 7 * 0x400); + space->install_write_handler(0x1fe0, 0x1fe7, write8sm_delegate(*this, FUNC(a26_rom_e0_device::switch_bank<0>))); + space->install_write_handler(0x1fe8, 0x1fef, write8sm_delegate(*this, FUNC(a26_rom_e0_device::switch_bank<1>))); + space->install_write_handler(0x1ff0, 0x1ff7, write8sm_delegate(*this, FUNC(a26_rom_e0_device::switch_bank<2>))); + space->install_read_tap(0x1fe0, 0x1fe7, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank<0>(address, 0); }); + space->install_read_tap(0x1fe8, 0x1fef, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank<1>(address, 0); }); + space->install_read_tap(0x1ff0, 0x1ff7, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank<2>(address, 0); }); +} + +template <uint8_t Bank> +void a26_rom_e0_device::switch_bank(offs_t offset, uint8_t data) +{ + m_bank[Bank]->set_entry(offset & 7); } + /*------------------------------------------------- "E7 Bankswitch" Carts: this PCB can handle up to 16K of ROM and 2K of RAM, @@ -776,57 +477,59 @@ WRITE8_MEMBER(a26_rom_e0_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_e7_device::read_rom) +a26_rom_e7_device::a26_rom_e7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_E7, tag, owner, clock) + , m_rom_bank(*this, "rom_bank") + , m_lo_ram_bank(*this, "low_ram") + , m_hi_ram_bank(*this, "high_ram") + , m_view(*this, "view") { - // update banks - if (!machine().side_effects_disabled()) - { - if (offset >= 0xfe0 && offset <= 0xfe7) - m_base_bank = offset - 0xfe0; - if (offset >= 0xfe8 && offset <= 0xfeb) - m_ram_bank = offset - 0xfe8; - } +} - if (!m_ram.empty()) - { - // 1K of RAM - if (m_base_bank == 0x07 && offset >= 0x400 && offset < 0x800) - return m_ram[0x400 + (offset & 0x3ff)]; - // the other 1K of RAM - if (offset >= 0x900 && offset < 0xa00) - { - offset -= 0x900; - return m_ram[offset + (m_ram_bank * 0x100)]; - } - } +void a26_rom_e7_device::device_reset() +{ + m_rom_bank->set_entry(0); + m_hi_ram_bank->set_entry(0); +} - if (offset > 0x800) - return m_rom[(offset & 0x7ff) + 0x3800]; - else - return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)]; +void a26_rom_e7_device::install_memory_handlers(address_space *space) +{ + m_rom_bank->configure_entries(0, 8, get_rom_base(), 0x800); + m_lo_ram_bank->configure_entry(0, get_ram_base() + 0x400); + m_hi_ram_bank->configure_entries(0, 4, get_ram_base(), 0x100); + + space->install_view(0x1000, 0x17ff, m_view); + // RAM disabled + m_view[0].install_read_bank(0x1000, 0x17ff, m_rom_bank); + // RAM enabled + m_view[1].install_read_bank(0x1000, 0x17ff, m_rom_bank); + m_view[1].install_write_bank(0x1000, 0x13ff, m_lo_ram_bank); + m_view[1].install_read_bank(0x1400, 0x17ff, m_lo_ram_bank); + + space->install_rom(0x1800, 0x1fff, get_rom_base() + 7 * 0x800); + space->install_write_bank(0x1800, 0x18ff, m_hi_ram_bank); + space->install_read_bank(0x1900, 0x19ff, m_hi_ram_bank); + space->install_write_handler(0x1fe0, 0x1fe7, write8sm_delegate(*this, FUNC(a26_rom_e7_device::switch_rom_bank))); + space->install_read_tap(0x1fe0, 0x1fe7, "rom_bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_rom_bank(address - 0x1fe0, 0); }); + space->install_write_handler(0x1fe8, 0x1feb, write8sm_delegate(*this, FUNC(a26_rom_e7_device::switch_ram_bank))); + space->install_read_tap(0x1fe8, 0x1feb, "ram_bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_ram_bank(address - 0x1fe8, 0); }); } -WRITE8_MEMBER(a26_rom_e7_device::write_bank) +void a26_rom_e7_device::switch_rom_bank(offs_t offset, uint8_t data) { - if (offset >= 0xfe0 && offset <= 0xfe7) - m_base_bank = offset - 0xfe0; - if (offset >= 0xfe8 && offset <= 0xfeb) - m_ram_bank = offset - 0xfe8; + m_view.select(offset == 0x07 ? 1 : 0); + m_rom_bank->set_entry(offset); +} - if (!m_ram.empty()) - { - // 1K of RAM - if (m_base_bank == 0x07 && offset < 0x400) - m_ram[0x400 + (offset & 0x3ff)] = data; - // the other 1K of RAM - if (offset >= 0x800 && offset < 0x900) - { - offset -= 0x800; - m_ram[offset + (m_ram_bank * 0x100)] = data; - } - } +void a26_rom_e7_device::switch_ram_bank(offs_t offset, uint8_t data) +{ + m_hi_ram_bank->set_entry(offset); } + + /*------------------------------------------------- "UA Bankswitch" Carts: read/write access to 0x200-0x27f determines the @@ -838,25 +541,34 @@ WRITE8_MEMBER(a26_rom_e7_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_ua_device::read_rom) +a26_rom_ua_device::a26_rom_ua_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_UA, tag, owner, clock) + , m_bank(*this, "bank") { - return m_rom[(offset + (m_base_bank * 0x1000)) & (m_rom_size - 1)]; } -READ8_MEMBER(a26_rom_ua_device::read_bank) +void a26_rom_ua_device::device_reset() { - if (!machine().side_effects_disabled()) - m_base_bank = offset >> 6; + m_bank->set_entry(0); +} - return 0; +void a26_rom_ua_device::install_memory_handlers(address_space *space) +{ + m_bank->configure_entries(0, 2, get_rom_base(), 0x1000); + + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_readwrite_tap(0x200, 0x27f, "bank", + [this] (offs_t offset, u8 &data, u8) { if (!machine().side_effects_disabled()) change_bank(offset); }, + [this] (offs_t offset, u8 &data, u8) { if (!machine().side_effects_disabled()) change_bank(offset); }); } -WRITE8_MEMBER(a26_rom_ua_device::write_bank) +void a26_rom_ua_device::change_bank(offs_t offset) { - m_base_bank = offset >> 6; + m_bank->set_entry((offset >> 6) & 1); } + /*------------------------------------------------- Commavid Carts: It allows for both ROM and RAM on the cartridge, @@ -867,27 +579,20 @@ WRITE8_MEMBER(a26_rom_ua_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_cv_device::read_rom) +a26_rom_cv_device::a26_rom_cv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_CV, tag, owner, clock) { - if (!m_ram.empty() && offset < 0x400) - { - return m_ram[offset & (m_ram.size() - 1)]; - } - - // games shall not read from 0x1400-0x17ff (RAM write) - // but we fall back to ROM just in case... - return m_rom[offset & 0x7ff]; } -WRITE8_MEMBER(a26_rom_cv_device::write_bank) +void a26_rom_cv_device::install_memory_handlers(address_space *space) { - if (!m_ram.empty() && offset >= 0x400 && offset < 0x800) - { - m_ram[offset & (m_ram.size() - 1)] = data; - } + space->install_rom(0x1000, 0x17ff, 0x800, get_rom_base()); + space->install_read_handler(0x1000, 0x13ff, read8sm_delegate(*this, FUNC(a26_rom_cv_device::read_ram))); + space->install_write_handler(0x1400, 0x17ff, write8sm_delegate(*this, FUNC(a26_rom_cv_device::write_ram))); } + /*------------------------------------------------- Dynacom Megaboy Carts (aka "F0 Banswitch"): read/write access to 0x1ff0 determines the 4K ROM @@ -898,96 +603,115 @@ WRITE8_MEMBER(a26_rom_cv_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_dc_device::read_rom) +a26_rom_dc_device::a26_rom_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_DC, tag, owner, clock) + , m_bank(*this, "bank") +{ +} + +void a26_rom_dc_device::device_reset() { - if (!machine().side_effects_disabled()) - { - if (offset == 0xff0) - m_base_bank = (m_base_bank + 1) & 0x0f; - } + m_bank->set_entry(0); +} + +void a26_rom_dc_device::install_memory_handlers(address_space *space) +{ + m_bank->configure_entries(0, 16, get_rom_base(), 0x1000); - if (offset == 0xfec) - return m_base_bank; + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_read_handler(0x1fec, 0x1fec, read8sm_delegate(*this, FUNC(a26_rom_dc_device::read_current_bank))); + space->install_write_handler(0x1ff0, 0x1ff0, write8sm_delegate(*this, FUNC(a26_rom_dc_device::switch_bank))); + space->install_read_tap(0x1ff0, 0x1ff0, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(0, 0); }); +} - return m_rom[offset + (m_base_bank * 0x1000)]; +uint8_t a26_rom_dc_device::read_current_bank(offs_t offset) +{ + return m_bank->entry(); } -WRITE8_MEMBER(a26_rom_dc_device::write_bank) +void a26_rom_dc_device::switch_bank(offs_t offset, uint8_t data) { - if (offset == 0xff0) - m_base_bank = (m_base_bank + 1) & 0x0f; + m_bank->set_entry((m_bank->entry() + 1) & 0x0f); } + /*------------------------------------------------- "FV Bankswitch" Carts: - The first access to 0x1fd0 switch the bank, but - only if pc() & 0x1f00 == 0x1f00! + The first access to 0x1fd0 switch the bank. GAMES: Challenge by HES -------------------------------------------------*/ -READ8_MEMBER(a26_rom_fv_device::read_rom) +a26_rom_fv_device::a26_rom_fv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_FV, tag, owner, clock) + , m_bank(*this, "bank") { - if (!machine().side_effects_disabled()) - { - if (offset == 0xfd0) - { - if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00) - { - m_locked = 1; - m_base_bank = m_base_bank ^ 0x01; - } - } - } +} - return m_rom[offset + (m_base_bank * 0x1000)]; +void a26_rom_fv_device::device_reset() +{ + m_bank->set_entry(0); } -WRITE8_MEMBER(a26_rom_fv_device::write_bank) +void a26_rom_fv_device::install_memory_handlers(address_space *space) { - if (offset == 0xfd0) - { - if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00) - { - m_locked = 1; - m_base_bank = m_base_bank ^ 0x01; - } - } + m_bank->configure_entries(0, 2, get_rom_base(), 0x1000); + + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_write_handler(0x1fd0, 0x1fd0, write8sm_delegate(*this, FUNC(a26_rom_fv_device::switch_bank))); + space->install_read_tap(0x1fd0, 0x1fd0, "bank", + [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(0, 0); }); } +void a26_rom_fv_device::switch_bank(offs_t offset, uint8_t data) +{ + m_bank->set_entry(1); +} + + /*------------------------------------------------- "JVP Bankswitch" Carts: read/write access to 0x0fa0-0x0fc0 determines the - 4K ROM bank to be read (notice that this overlaps - the RIOT, currently handled in the main driver until - I can better investigate the behavior) + 4K ROM bank to be read. GAMES: No test case!?! -------------------------------------------------*/ -READ8_MEMBER(a26_rom_jvp_device::read_rom) +a26_rom_jvp_device::a26_rom_jvp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_JVP, tag, owner, clock) + , m_bank(*this, "bank") { - return m_rom[offset + (m_base_bank * 0x1000)]; } -WRITE8_MEMBER(a26_rom_jvp_device::write_bank) +void a26_rom_jvp_device::device_reset() { - switch (offset) - { - case 0x00: - case 0x20: - m_base_bank ^= 1; - break; - default: - //printf("%04X: write to unknown mapper address %02X\n", m_maincpu->pc(), 0xfa0 + offset); - break; - } + m_bank->set_entry(0); +} + +void a26_rom_jvp_device::install_memory_handlers(address_space *space) +{ + m_bank->configure_entries(0, 2, get_rom_base(), 0x1000); + + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_readwrite_tap(0xfa0, 0xfa0, "bank_fa0", + [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); }, + [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); }); + space->install_readwrite_tap(0xfc0, 0xfc0, "bank_fc0", + [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); }, + [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); }); } +void a26_rom_jvp_device::change_bank() +{ + m_bank->set_entry(m_bank->entry() ^ 1); +} + + /*------------------------------------------------- 4 in 1 Carts (Reset based): @@ -997,11 +721,33 @@ WRITE8_MEMBER(a26_rom_jvp_device::write_bank) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_4in1_device::read_rom) +a26_rom_4in1_device::a26_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_4IN1, tag, owner, clock) + , m_bank(*this, "bank") + , m_current_game(0) +{ +} + +void a26_rom_4in1_device::device_start() +{ + save_item(NAME(m_current_game)); + m_current_game = 0; +} + +void a26_rom_4in1_device::device_reset() { - return m_rom[offset + (m_base_bank * 0x1000)]; + m_bank->set_entry(m_current_game); + m_current_game = (m_current_game + 1) & 3; } +void a26_rom_4in1_device::install_memory_handlers(address_space *space) +{ + m_bank->configure_entries(0, 4, get_rom_base(), 0x1000); + + space->install_read_bank(0x1000, 0x1fff, m_bank); +} + + /*------------------------------------------------- 8 in 1 Carts (Reset based): @@ -1012,23 +758,43 @@ READ8_MEMBER(a26_rom_4in1_device::read_rom) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_8in1_device::read_rom) +a26_rom_8in1_device::a26_rom_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_8IN1, tag, owner, clock) + , m_bank(*this, "bank") { - if (!machine().side_effects_disabled()) - { - switch (offset) - { - case 0x0ff8: - case 0x0ff9: - m_base_bank = offset - 0x0ff8; - break; - } - } +} + +void a26_rom_8in1_device::device_start() +{ + save_item(NAME(m_game_bank)); + + // starting from last game so first reset will get us to game #0 + m_game_bank = 14; +} + +void a26_rom_8in1_device::device_reset() +{ + m_game_bank = (m_game_bank + 2) & 15; + m_bank->set_entry(m_game_bank); +} + +void a26_rom_8in1_device::install_memory_handlers(address_space *space) +{ + m_bank->configure_entries(0, 16, get_rom_base(), 0x1000); + + space->install_read_bank(0x1000, 0x1fff, m_bank); + space->install_write_handler(0x1ff8, 0x1ff9, write8sm_delegate(*this, FUNC(a26_rom_8in1_device::switch_bank))); + space->install_read_tap(0x1ff8, 0x1ff9, "bank", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff8, 0); }); +} - return m_rom[offset + (m_base_bank * 0x1000) + (m_reset_bank * 0x2000)]; +void a26_rom_8in1_device::switch_bank(offs_t offset, uint8_t data) +{ + m_bank->set_entry(m_game_bank + offset); } + /*------------------------------------------------- 32 in 1 Carts (Reset based): the 2K banks change at each reset @@ -1037,11 +803,33 @@ READ8_MEMBER(a26_rom_8in1_device::read_rom) -------------------------------------------------*/ -READ8_MEMBER(a26_rom_32in1_device::read_rom) +a26_rom_32in1_device::a26_rom_32in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_32IN1, tag, owner, clock) + , m_bank(*this, "bank") + , m_current_game(0) +{ +} + +void a26_rom_32in1_device::device_start() { - return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)]; + save_item(NAME(m_current_game)); + m_current_game = 0; } +void a26_rom_32in1_device::device_reset() +{ + m_bank->set_entry(m_current_game); + m_current_game = (m_current_game + 1) & 0x1f; +} + +void a26_rom_32in1_device::install_memory_handlers(address_space *space) +{ + m_bank->configure_entries(0, 32, get_rom_base(), 0x800); + + space->install_read_bank(0x1000, 0x17ff, 0x800, m_bank); +} + + /*------------------------------------------------- "X07 Bankswitch" Carts: @@ -1050,43 +838,48 @@ READ8_MEMBER(a26_rom_32in1_device::read_rom) http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt --------------------------------------------------*/ -READ8_MEMBER(a26_rom_x07_device::read_rom) +a26_rom_x07_device::a26_rom_x07_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a26_rom_base_device(mconfig, A26_ROM_X07, tag, owner, clock) + , m_bank(*this, "bank") { - return m_rom[offset + (m_base_bank * 0x1000)]; } -WRITE8_MEMBER(a26_rom_x07_device::write_bank) +void a26_rom_x07_device::install_memory_handlers(address_space *space) { + m_bank->configure_entries(0, 16, get_rom_base(), 0x1000); + + space->install_read_bank(0x1000, 0x1fff, m_bank); /* A13 A0 ---------------- - 0 1xxx nnnn 1101 + 0 0xxx 0nxx xxxx */ - - if ((offset & 0x180f) == 0x080d) - { - m_base_bank = (offset & 0x00f0) >> 4; - } + space->install_readwrite_tap(0x0000, 0x0000, 0x077f, "bank1", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank1(address); }, + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank1(address); }); /* A13 A0 ---------------- - 0 0xxx 0nxx xxxx + 0 1xxx nnnn 1101 */ + space->install_readwrite_tap(0x080d, 0x080d, 0x07f0, "bank2", + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank2(address); }, + [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank2(address); }); +} - if ((offset & 0x1880) == 0x0000) +void a26_rom_x07_device::change_bank1(offs_t address) +{ + // only has an effect if bank is already 14 or 15 + if (m_bank->entry() >= 14) { - // only has an effect if bank is already 14 or 15 - if (m_base_bank == 14 || m_base_bank == 15) - { - if (offset & 0x0040) - { - m_base_bank = 15; - } - else - { - m_base_bank = 14; - } - - } + if (address & 0x0040) + m_bank->set_entry(15); + else + m_bank->set_entry(14); } } + +void a26_rom_x07_device::change_bank2(offs_t address) +{ + m_bank->set_entry((address >> 4) & 0x0f); +} |