diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index 14d68d279..c1f88e26f 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -183,72 +183,72 @@ template class ConcreteMachine: } } - // MARK: The language card. + // MARK: - The language card, auxiliary memory, and IIe-specific improvements. LanguageCardSwitches language_card_; AuxiliaryMemorySwitches auxiliary_switches_; friend LanguageCardSwitches; friend AuxiliaryMemorySwitches; - void set_language_card_paging() { - const auto language_state = language_card_.state(); - const auto zero_state = auxiliary_switches_.zero_state(); - - uint8_t *const ram = zero_state ? aux_ram_ : ram_; - uint8_t *const rom = is_iie() ? &rom_[3840] : rom_.data(); - - // Which way the region here is mapped to be banks 1 and 2 is - // arbitrary. - page(0xd0, 0xe0, - language_state.read ? &ram[language_state.bank2 ? 0xd000 : 0xc000] : rom, - language_state.write ? nullptr : &ram[language_state.bank2 ? 0xd000 : 0xc000]); - - page(0xe0, 0x100, - language_state.read ? &ram[0xe000] : &rom[0x1000], - language_state.write ? nullptr : &ram[0xe000]); - } - - // MARK: Auxiliary memory and the other IIe improvements. - void set_card_paging() { - const auto state = auxiliary_switches_.card_state(); - - page(0xc1, 0xc4, state.region_C1_C3 ? &rom_[0xc100 - 0xc100] : nullptr, nullptr); - read_pages_[0xc3] = state.region_C3 ? &rom_[0xc300 - 0xc100] : nullptr; - page(0xc4, 0xc8, state.region_C4_C8 ? &rom_[0xc400 - 0xc100] : nullptr, nullptr); - page(0xc8, 0xd0, state.region_C8_D0 ? &rom_[0xc800 - 0xc100] : nullptr, nullptr); - } - void set_zero_page_paging() { - if(auxiliary_switches_.zero_state()) { - write_pages_[0] = aux_ram_; - } else { - write_pages_[0] = ram_; + template void set_paging() { + if constexpr (bool(type & PagingType::ZeroPage)) { + if(auxiliary_switches_.zero_state()) { + write_pages_[0] = aux_ram_; + } else { + write_pages_[0] = ram_; + } + write_pages_[1] = write_pages_[0] + 256; + read_pages_[0] = write_pages_[0]; + read_pages_[1] = write_pages_[1]; } - write_pages_[1] = write_pages_[0] + 256; - read_pages_[0] = write_pages_[0]; - read_pages_[1] = write_pages_[1]; - // Zero page banking also affects interpretation of the language card's switches. - set_language_card_paging(); - } - void set_main_paging() { - const auto state = auxiliary_switches_.main_state(); + if constexpr (bool(type & (PagingType::LanguageCard | PagingType::ZeroPage))) { + const auto language_state = language_card_.state(); + const auto zero_state = auxiliary_switches_.zero_state(); - page(0x02, 0x04, - state.base.read ? &aux_ram_[0x0200] : &ram_[0x0200], - state.base.write ? &aux_ram_[0x0200] : &ram_[0x0200]); - page(0x08, 0x20, - state.base.read ? &aux_ram_[0x0800] : &ram_[0x0800], - state.base.write ? &aux_ram_[0x0800] : &ram_[0x0800]); - page(0x40, 0xc0, - state.base.read ? &aux_ram_[0x4000] : &ram_[0x4000], - state.base.write ? &aux_ram_[0x4000] : &ram_[0x4000]); + uint8_t *const ram = zero_state ? aux_ram_ : ram_; + uint8_t *const rom = is_iie() ? &rom_[3840] : rom_.data(); - page(0x04, 0x08, - state.region_04_08.read ? &aux_ram_[0x0400] : &ram_[0x0400], - state.region_04_08.write ? &aux_ram_[0x0400] : &ram_[0x0400]); + // Which way the region here is mapped to be banks 1 and 2 is + // arbitrary. + page(0xd0, 0xe0, + language_state.read ? &ram[language_state.bank2 ? 0xd000 : 0xc000] : rom, + language_state.write ? nullptr : &ram[language_state.bank2 ? 0xd000 : 0xc000]); - page(0x20, 0x40, - state.region_20_40.read ? &aux_ram_[0x2000] : &ram_[0x2000], - state.region_20_40.write ? &aux_ram_[0x2000] : &ram_[0x2000]); + page(0xe0, 0x100, + language_state.read ? &ram[0xe000] : &rom[0x1000], + language_state.write ? nullptr : &ram[0xe000]); + } + + if constexpr (bool(type & PagingType::CardArea)) { + const auto state = auxiliary_switches_.card_state(); + + page(0xc1, 0xc4, state.region_C1_C3 ? &rom_[0xc100 - 0xc100] : nullptr, nullptr); + read_pages_[0xc3] = state.region_C3 ? &rom_[0xc300 - 0xc100] : nullptr; + page(0xc4, 0xc8, state.region_C4_C8 ? &rom_[0xc400 - 0xc100] : nullptr, nullptr); + page(0xc8, 0xd0, state.region_C8_D0 ? &rom_[0xc800 - 0xc100] : nullptr, nullptr); + } + + if constexpr (bool(type & PagingType::Main)) { + const auto state = auxiliary_switches_.main_state(); + + page(0x02, 0x04, + state.base.read ? &aux_ram_[0x0200] : &ram_[0x0200], + state.base.write ? &aux_ram_[0x0200] : &ram_[0x0200]); + page(0x08, 0x20, + state.base.read ? &aux_ram_[0x0800] : &ram_[0x0800], + state.base.write ? &aux_ram_[0x0800] : &ram_[0x0800]); + page(0x40, 0xc0, + state.base.read ? &aux_ram_[0x4000] : &ram_[0x4000], + state.base.write ? &aux_ram_[0x4000] : &ram_[0x4000]); + + page(0x04, 0x08, + state.region_04_08.read ? &aux_ram_[0x0400] : &ram_[0x0400], + state.region_04_08.write ? &aux_ram_[0x0400] : &ram_[0x0400]); + + page(0x20, 0x40, + state.region_20_40.read ? &aux_ram_[0x2000] : &ram_[0x2000], + state.region_20_40.write ? &aux_ram_[0x2000] : &ram_[0x2000]); + } } // MARK: - Keyboard and typing. @@ -485,8 +485,7 @@ template class ConcreteMachine: // Set up the default memory blocks. On a II or II+ these values will never change. // On a IIe they'll be affected by selection of auxiliary RAM. - set_main_paging(); - set_zero_page_paging(); + set_paging(); // Set the whole card area to initially backed by nothing. page(0xc0, 0xd0, nullptr, nullptr); diff --git a/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp b/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp index 9dc5b56fb..389083b95 100644 --- a/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp +++ b/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp @@ -9,6 +9,8 @@ #ifndef AuxiliaryMemorySwitches_h #define AuxiliaryMemorySwitches_h +#include "MemorySwitches.hpp" + namespace Apple { namespace II { @@ -235,7 +237,7 @@ template class AuxiliaryMemorySwitches { } if(previous_state != main_state_) { - machine_.set_main_paging(); + machine_.template set_paging(); } } @@ -258,14 +260,14 @@ template class AuxiliaryMemorySwitches { card_state_.region_C8_D0 = switches_.internal_CX_rom || switches_.internal_C8_rom; if(previous_state != card_state_) { - machine_.set_card_paging(); + machine_.template set_paging(); } } void set_zero_page_paging() { // Believe it or not, the zero page is just set or cleared by a single flag. // As though life were rational. - machine_.set_zero_page_paging(); + machine_.template set_paging(); } }; diff --git a/Machines/Apple/AppleII/LanguageCardSwitches.hpp b/Machines/Apple/AppleII/LanguageCardSwitches.hpp index 1c52d21aa..873260a36 100644 --- a/Machines/Apple/AppleII/LanguageCardSwitches.hpp +++ b/Machines/Apple/AppleII/LanguageCardSwitches.hpp @@ -9,6 +9,8 @@ #ifndef LanguageCardSwitches_h #define LanguageCardSwitches_h +#include "MemorySwitches.hpp" + namespace Apple { namespace II { @@ -70,7 +72,7 @@ template class LanguageCardSwitches { // Apply whatever the net effect of all that is to the memory map. if(previous_state != state_) { - machine_.set_language_card_paging(); + machine_.template set_paging(); } } @@ -90,7 +92,7 @@ template class LanguageCardSwitches { state_.bank2 = value & 0x04; if(previous_state != state_) { - machine_.set_language_card_paging(); + machine_.template set_paging(); } } diff --git a/Machines/Apple/AppleII/MemorySwitches.hpp b/Machines/Apple/AppleII/MemorySwitches.hpp new file mode 100644 index 000000000..c71bd4c1e --- /dev/null +++ b/Machines/Apple/AppleII/MemorySwitches.hpp @@ -0,0 +1,25 @@ +// +// MemorySwitches.hpp +// Clock Signal +// +// Created by Thomas Harte on 27/06/2022. +// Copyright © 2022 Thomas Harte. All rights reserved. +// + +#ifndef MemorySwitches_h +#define MemorySwitches_h + +namespace Apple { +namespace II { + +enum PagingType: int { + Main = 1 << 0, + ZeroPage = 1 << 1, + CardArea = 1 << 2, + LanguageCard = 1 << 3, +}; + +} +} + +#endif /* MemorySwitches_h */ diff --git a/Machines/Apple/AppleIIgs/MemoryMap.hpp b/Machines/Apple/AppleIIgs/MemoryMap.hpp index 63a3b8eb7..a72b16b94 100644 --- a/Machines/Apple/AppleIIgs/MemoryMap.hpp +++ b/Machines/Apple/AppleIIgs/MemoryMap.hpp @@ -20,6 +20,9 @@ namespace Apple { namespace IIgs { class MemoryMap { + private: + using PagingType = Apple::II::PagingType; + public: // MARK: - Initial construction and configuration. @@ -179,7 +182,7 @@ class MemoryMap { // TODO: set 1Mhz flags. // Apply initial language/auxiliary state. - set_all_paging(); + set_paging<~0>(); } // MARK: - Live bus access notifications and register access. @@ -189,8 +192,7 @@ class MemoryMap { shadow_register_ = value; if(diff & 0x40) { // IO/language-card inhibit. - set_language_card_paging(); - set_card_paging(); + set_paging(); } if(diff & 0x3f) { @@ -251,150 +253,178 @@ class MemoryMap { assert(region_map[end-1] == region_map[start]); \ assert(region_map[end] == region_map[end-1]+1); - // Cf. LanguageCardSwitches; this function should update the region from - // $D000 onwards as per the state of the language card flags — there may - // end up being ROM or RAM (or auxiliary RAM), and the first 4kb of it - // may be drawn from either of two pools. - void set_language_card_paging() { - const auto language_state = language_card_.state(); - const auto zero_state = auxiliary_switches_.zero_state(); - const bool inhibit_banks0001 = shadow_register_ & 0x40; + template void set_paging() { + // Update the region from + // $D000 onwards as per the state of the language card flags — there may + // end up being ROM or RAM (or auxiliary RAM), and the first 4kb of it + // may be drawn from either of two pools. + if constexpr (bool(type & (PagingType::LanguageCard | PagingType::ZeroPage))) { + const auto language_state = language_card_.state(); + const auto zero_state = auxiliary_switches_.zero_state(); + const bool inhibit_banks0001 = shadow_register_ & 0x40; - auto apply = [&language_state, this](uint32_t bank_base, uint8_t *ram) { - // This assumes bank 1 is the one before bank 2 when RAM is linear. - uint8_t *const d0_ram_bank = ram - (language_state.bank2 ? 0x0000 : 0x1000); + auto apply = [&language_state, this](uint32_t bank_base, uint8_t *ram) { + // This assumes bank 1 is the one before bank 2 when RAM is linear. + uint8_t *const d0_ram_bank = ram - (language_state.bank2 ? 0x0000 : 0x1000); - // Crib the ROM pointer from a page it's always visible on. - const uint8_t *const rom = ®ions[region_map[0xffd0]].read[0xff'd000] - ((bank_base << 8) + 0xd000); + // Crib the ROM pointer from a page it's always visible on. + const uint8_t *const rom = ®ions[region_map[0xffd0]].read[0xff'd000] - ((bank_base << 8) + 0xd000); - auto &d0_region = regions[region_map[bank_base | 0xd0]]; - d0_region.read = language_state.read ? d0_ram_bank : rom; - d0_region.write = language_state.write ? nullptr : d0_ram_bank; + auto &d0_region = regions[region_map[bank_base | 0xd0]]; + d0_region.read = language_state.read ? d0_ram_bank : rom; + d0_region.write = language_state.write ? nullptr : d0_ram_bank; - auto &e0_region = regions[region_map[bank_base | 0xe0]]; - e0_region.read = language_state.read ? ram : rom; - e0_region.write = language_state.write ? nullptr : ram; + auto &e0_region = regions[region_map[bank_base | 0xe0]]; + e0_region.read = language_state.read ? ram : rom; + e0_region.write = language_state.write ? nullptr : ram; - // Assert assumptions made above re: memory layout. - assert(region_map[bank_base | 0xd0] + 1 == region_map[bank_base | 0xe0]); - assert(region_map[bank_base | 0xe0] == region_map[bank_base | 0xff]); - }; - auto set_no_card = [this](uint32_t bank_base, uint8_t *ram) { - auto &d0_region = regions[region_map[bank_base | 0xd0]]; - d0_region.read = ram; - d0_region.write = ram; + // Assert assumptions made above re: memory layout. + assert(region_map[bank_base | 0xd0] + 1 == region_map[bank_base | 0xe0]); + assert(region_map[bank_base | 0xe0] == region_map[bank_base | 0xff]); + }; + auto set_no_card = [this](uint32_t bank_base, uint8_t *ram) { + auto &d0_region = regions[region_map[bank_base | 0xd0]]; + d0_region.read = ram; + d0_region.write = ram; - auto &e0_region = regions[region_map[bank_base | 0xe0]]; - e0_region.read = ram; - e0_region.write = ram; + auto &e0_region = regions[region_map[bank_base | 0xe0]]; + e0_region.read = ram; + e0_region.write = ram; - // Assert assumptions made above re: memory layout. - assert(region_map[bank_base | 0xd0] + 1 == region_map[bank_base | 0xe0]); - assert(region_map[bank_base | 0xe0] == region_map[bank_base | 0xff]); - }; + // Assert assumptions made above re: memory layout. + assert(region_map[bank_base | 0xd0] + 1 == region_map[bank_base | 0xe0]); + assert(region_map[bank_base | 0xe0] == region_map[bank_base | 0xff]); + }; - if(inhibit_banks0001) { - set_no_card(0x0000, zero_state ? &ram_base[0x01'0000] : ram_base); - set_no_card(0x0100, ram_base); - } else { - apply(0x0000, zero_state ? &ram_base[0x01'0000] : ram_base); - apply(0x0100, ram_base); - } - - // The pointer stored in region_map[0xe000] has already been adjusted for - // the 0xe0'0000 addressing offset. - uint8_t *const e0_ram = regions[region_map[0xe000]].write; - apply(0xe000, e0_ram); - apply(0xe100, e0_ram); - } - - // Cf. AuxiliarySwitches; this should establish whether ROM or card switches - // are exposed in the distinct regions C100–C2FF, C300–C3FF, C400–C7FF and - // C800–CFFF. - // - // On the IIgs it intersects with the current shadow register. - // - // TODO: so... shouldn't the card mask be incorporated here? I've got it implemented - // distinctly at present, but does that create any invalid state interactions? - void set_card_paging() { - const bool inhibit_banks0001 = shadow_register_ & 0x40; - const auto state = auxiliary_switches_.card_state(); - - auto apply = [&state, this](uint32_t bank_base) { - auto &c0_region = regions[region_map[bank_base | 0xc0]]; - auto &c1_region = regions[region_map[bank_base | 0xc1]]; - auto &c3_region = regions[region_map[bank_base | 0xc3]]; - auto &c4_region = regions[region_map[bank_base | 0xc4]]; - auto &c8_region = regions[region_map[bank_base | 0xc8]]; - - const uint8_t *const rom = ®ions[region_map[0xffd0]].read[0xffc100] - ((bank_base << 8) + 0xc100); - - // This is applied dynamically as it may be added or lost in banks $00 and $01. - c0_region.flags |= Region::IsIO; - -#define apply_region(flag, region) \ - if(flag) { \ - region.read = rom; \ - region.flags &= ~Region::IsIO; \ - } else { \ - region.flags |= Region::IsIO; \ + if(inhibit_banks0001) { + set_no_card(0x0000, zero_state ? &ram_base[0x01'0000] : ram_base); + set_no_card(0x0100, ram_base); + } else { + apply(0x0000, zero_state ? &ram_base[0x01'0000] : ram_base); + apply(0x0100, ram_base); } - apply_region(state.region_C1_C3, c1_region); - apply_region(state.region_C3, c3_region); - apply_region(state.region_C4_C8, c4_region); - apply_region(state.region_C8_D0, c8_region); + // The pointer stored in region_map[0xe000] has already been adjusted for + // the 0xe0'0000 addressing offset. + uint8_t *const e0_ram = regions[region_map[0xe000]].write; + apply(0xe000, e0_ram); + apply(0xe100, e0_ram); + + } + + // Establish whether main or auxiliary RAM + // is exposed in bank $00 for a bunch of regions. + if constexpr (type & PagingType::Main) { + const auto state = auxiliary_switches_.main_state(); + +#define set(page, flags) {\ + auto ®ion = regions[region_map[page]]; \ + region.read = flags.read ? &ram_base[0x01'0000] : ram_base; \ + region.write = flags.write ? &ram_base[0x01'0000] : ram_base; \ + } + + // Base: $0200–$03FF. + set(0x02, state.base); + assert_is_region(0x02, 0x04); + + // Region $0400–$07ff. + set(0x04, state.region_04_08); + assert_is_region(0x04, 0x08); + + // Base: $0800–$1FFF. + set(0x08, state.base); + assert_is_region(0x08, 0x20); + + // Region $2000–$3FFF. + set(0x20, state.region_20_40); + assert_is_region(0x20, 0x40); + + // Base: $4000–$BFFF. + set(0x40, state.base); + assert_is_region(0x40, 0xc0); + +#undef set + } + + // Update whether base or auxiliary RAM is visible in: (i) the zero + // and stack pages; and (ii) anywhere that the language card is exposing RAM instead of ROM. + if constexpr (bool(type & PagingType::ZeroPage)) { + // Affects bank $00 only, and should be a single region. + auto ®ion = regions[region_map[0]]; + region.read = region.write = auxiliary_switches_.zero_state() ? &ram_base[0x01'0000] : ram_base; + assert(region_map[0x0000] == region_map[0x0001]); + assert(region_map[0x0001]+1 == region_map[0x0002]); + } + + // Establish whether ROM or card switches are exposed in the distinct + // regions C100–C2FF, C300–C3FF, C400–C7FF and C800–CFFF. + // + // On the IIgs it intersects with the current shadow register. + if constexpr (bool(type & (PagingType::CardArea | PagingType::Main))) { + const bool inhibit_banks0001 = shadow_register_ & 0x40; + const auto state = auxiliary_switches_.card_state(); + + auto apply = [&state, this](uint32_t bank_base) { + auto &c0_region = regions[region_map[bank_base | 0xc0]]; + auto &c1_region = regions[region_map[bank_base | 0xc1]]; + auto &c3_region = regions[region_map[bank_base | 0xc3]]; + auto &c4_region = regions[region_map[bank_base | 0xc4]]; + auto &c8_region = regions[region_map[bank_base | 0xc8]]; + + const uint8_t *const rom = ®ions[region_map[0xffd0]].read[0xffc100] - ((bank_base << 8) + 0xc100); + + // This is applied dynamically as it may be added or lost in banks $00 and $01. + c0_region.flags |= Region::IsIO; + +#define apply_region(flag, region) \ + if(flag) { \ + region.read = rom; \ + region.flags &= ~Region::IsIO; \ + } else { \ + region.flags |= Region::IsIO; \ + } + + apply_region(state.region_C1_C3, c1_region); + apply_region(state.region_C3, c3_region); + apply_region(state.region_C4_C8, c4_region); + apply_region(state.region_C8_D0, c8_region); #undef apply_region - // Sanity checks. - assert(region_map[bank_base | 0xc1] == region_map[bank_base | 0xc0]+1); - assert(region_map[bank_base | 0xc2] == region_map[bank_base | 0xc1]); - assert(region_map[bank_base | 0xc3] == region_map[bank_base | 0xc2]+1); - assert(region_map[bank_base | 0xc4] == region_map[bank_base | 0xc3]+1); - assert(region_map[bank_base | 0xc7] == region_map[bank_base | 0xc4]); - assert(region_map[bank_base | 0xc8] == region_map[bank_base | 0xc7]+1); - assert(region_map[bank_base | 0xcf] == region_map[bank_base | 0xc8]); - assert(region_map[bank_base | 0xd0] == region_map[bank_base | 0xcf]+1); - }; + // Sanity checks. + assert(region_map[bank_base | 0xc1] == region_map[bank_base | 0xc0]+1); + assert(region_map[bank_base | 0xc2] == region_map[bank_base | 0xc1]); + assert(region_map[bank_base | 0xc3] == region_map[bank_base | 0xc2]+1); + assert(region_map[bank_base | 0xc4] == region_map[bank_base | 0xc3]+1); + assert(region_map[bank_base | 0xc7] == region_map[bank_base | 0xc4]); + assert(region_map[bank_base | 0xc8] == region_map[bank_base | 0xc7]+1); + assert(region_map[bank_base | 0xcf] == region_map[bank_base | 0xc8]); + assert(region_map[bank_base | 0xd0] == region_map[bank_base | 0xcf]+1); + }; - if(inhibit_banks0001) { - // Set no IO in the Cx00 range for banks $00 and $01, just - // regular RAM (or possibly auxiliary). - const auto auxiliary_state = auxiliary_switches_.main_state(); - for(uint8_t region = region_map[0x00c0]; region < region_map[0x00d0]; region++) { - regions[region].read = auxiliary_state.base.read ? &ram_base[0x01'0000] : ram_base; - regions[region].write = auxiliary_state.base.write ? &ram_base[0x01'0000] : ram_base; - regions[region].flags &= ~Region::IsIO; + if(inhibit_banks0001) { + // Set no IO in the Cx00 range for banks $00 and $01, just + // regular RAM (or possibly auxiliary). + const auto auxiliary_state = auxiliary_switches_.main_state(); + for(uint8_t region = region_map[0x00c0]; region < region_map[0x00d0]; region++) { + regions[region].read = auxiliary_state.base.read ? &ram_base[0x01'0000] : ram_base; + regions[region].write = auxiliary_state.base.write ? &ram_base[0x01'0000] : ram_base; + regions[region].flags &= ~Region::IsIO; + } + for(uint8_t region = region_map[0x01c0]; region < region_map[0x01d0]; region++) { + regions[region].read = regions[region].write = ram_base; + regions[region].flags &= ~Region::IsIO; + } + } else { + // Obey the card state for banks $00 and $01. + apply(0x0000); + apply(0x0100); } - for(uint8_t region = region_map[0x01c0]; region < region_map[0x01d0]; region++) { - regions[region].read = regions[region].write = ram_base; - regions[region].flags &= ~Region::IsIO; - } - } else { - // Obey the card state for banks $00 and $01. - apply(0x0000); - apply(0x0100); + + // Obey the card state for banks $e0 and $e1. + apply(0xe000); + apply(0xe100); } - - // Obey the card state for banks $e0 and $e1. - apply(0xe000); - apply(0xe100); - } - - // Cf. LanguageCardSwitches; this should update whether base or auxiliary RAM is - // visible in: (i) the zero and stack pages; and (ii) anywhere that the language - // card is exposing RAM instead of ROM. - void set_zero_page_paging() { - // Affects bank $00 only, and should be a single region. - auto ®ion = regions[region_map[0]]; - region.read = region.write = auxiliary_switches_.zero_state() ? &ram_base[0x01'0000] : ram_base; - assert(region_map[0x0000] == region_map[0x0001]); - assert(region_map[0x0001]+1 == region_map[0x0002]); - - // Switching to or from auxiliary RAM potentially affects the - // language card area. - set_language_card_paging(); } // IIgs specific: sets or resets the ::IsShadowed flag across affected banks as @@ -466,52 +496,6 @@ class MemoryMap { } } - // Cf. the AuxiliarySwitches; establishes whether main or auxiliary RAM - // is exposed in bank $00 for a bunch of regions. - void set_main_paging() { - const auto state = auxiliary_switches_.main_state(); - -#define set(page, flags) {\ - auto ®ion = regions[region_map[page]]; \ - region.read = flags.read ? &ram_base[0x01'0000] : ram_base; \ - region.write = flags.write ? &ram_base[0x01'0000] : ram_base; \ - } - - // Base: $0200–$03FF. - set(0x02, state.base); - assert_is_region(0x02, 0x04); - - // Region $0400–$07ff. - set(0x04, state.region_04_08); - assert_is_region(0x04, 0x08); - - // Base: $0800–$1FFF. - set(0x08, state.base); - assert_is_region(0x08, 0x20); - - // Region $2000–$3FFF. - set(0x20, state.region_20_40); - assert_is_region(0x20, 0x40); - - // Base: $4000–$BFFF. - set(0x40, state.base); - assert_is_region(0x40, 0xc0); - -#undef set - - // This also affects shadowing flags, if shadowing is enabled at all, - // and might affect RAM in the IO area of bank $00 because the language - // card can be inhibited on a IIgs. - set_card_paging(); - } - - void set_all_paging() { - set_card_paging(); - set_zero_page_paging(); // ... which calls set_language_card_paging(). - set_main_paging(); - set_shadowing(); - } - void print_state() { uint8_t region = region_map[0]; uint32_t start = 0; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 65b123b00..3311a4686 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -2137,6 +2137,7 @@ 4BDB3D8522833321002D3CEE /* Keyboard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = ""; }; 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = ""; }; 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = ""; }; + 4BE0151C286A8C8E00EA42E9 /* MemorySwitches.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MemorySwitches.hpp; sourceTree = ""; }; 4BE0A3EC237BB170002AB46F /* ST.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ST.cpp; sourceTree = ""; }; 4BE0A3ED237BB170002AB46F /* ST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ST.hpp; sourceTree = ""; }; 4BE211DD253E4E4800435408 /* 65C02_no_Rockwell_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 65C02_no_Rockwell_test.bin; path = "Klaus Dormann/65C02_no_Rockwell_test.bin"; sourceTree = ""; }; @@ -4628,6 +4629,7 @@ 4BCE004C227CE8CA000CA200 /* DiskIICard.hpp */, 4B2E86E125DC95150024F1E9 /* Joystick.hpp */, 4BF40A5525424C770033EA39 /* LanguageCardSwitches.hpp */, + 4BE0151C286A8C8E00EA42E9 /* MemorySwitches.hpp */, 4BCE004F227CE8CA000CA200 /* Video.hpp */, 4B8DF4F2254E141700F3433C /* VideoSwitches.hpp */, );