diff --git a/Machines/Apple/AppleIIgs/MemoryMap.cpp b/Machines/Apple/AppleIIgs/MemoryMap.cpp index a853db3a6..04a33caaa 100644 --- a/Machines/Apple/AppleIIgs/MemoryMap.cpp +++ b/Machines/Apple/AppleIIgs/MemoryMap.cpp @@ -13,15 +13,15 @@ using PagingType = Apple::II::PagingType; void MemoryMap::set_storage(std::vector &ram, std::vector &rom) { // Keep a pointer for later; also note the proper RAM offset. - ram_base = ram.data(); - shadow_base[0] = ram_base; // i.e. all unshadowed writes go to where they've already gone (to make a no-op). - shadow_base[1] = &ram[ram.size() - 0x02'0000]; // i.e. all shadowed writes go somewhere in the last + ram_base_ = ram.data(); + shadow_base_[0] = ram_base_; // i.e. all unshadowed writes go to where they've already gone (to make a no-op). + shadow_base_[1] = &ram[ram.size() - 0x02'0000]; // i.e. all shadowed writes go somewhere in the last // 128bk of RAM. // Establish bank mapping. uint8_t next_region = 0; auto region = [&]() -> uint8_t { - assert(next_region != this->regions.size()); + assert(next_region != this->regions_.size()); return next_region++; }; auto set_region = [this](uint8_t bank, uint16_t start, uint16_t end, uint8_t region) { @@ -31,7 +31,7 @@ void MemoryMap::set_storage(std::vector &ram, std::vector &rom // Fill in memory map. size_t target = size_t((bank << 8) | (start >> 8)); for(int c = start; c < end; c += 0x100) { - region_map[target] = region; + region_map_[target] = region; ++target; } }; @@ -130,10 +130,10 @@ void MemoryMap::set_storage(std::vector &ram, std::vector &rom // Apply proper storage to those banks. auto set_storage = [this](uint32_t address, const uint8_t *read, uint8_t *write) { // Don't allow the reserved null region to be modified. - assert(region_map[address >> 8]); + assert(region_map_[address >> 8]); // Either set or apply a quick bit of testing as to the logic at play. - auto ®ion = regions[region_map[address >> 8]]; + auto ®ion = regions_[region_map_[address >> 8]]; if(read) read -= address; if(write) write -= address; if(!region.read) { @@ -160,7 +160,7 @@ void MemoryMap::set_storage(std::vector &ram, std::vector &rom } // Set shadowing as working from banks 0 and 1 (forever). - shadow_banks[0] = true; + shadow_banks_[0] = true; // TODO: set 1Mhz flags. @@ -190,7 +190,7 @@ void MemoryMap::set_speed_register(uint8_t value) { // Enable or disable shadowing from banks 0x02–0x80. for(size_t c = 0x01; c < 0x40; c++) { - shadow_banks[c] = speed_register_ & 0x10; + shadow_banks_[c] = speed_register_ & 0x10; } } @@ -209,9 +209,9 @@ void MemoryMap::access(uint16_t address, bool is_read) { } void MemoryMap::assert_is_region(uint8_t start, uint8_t end) { - assert(region_map[start] == region_map[start-1]+1); - assert(region_map[end-1] == region_map[start]); - assert(region_map[end] == region_map[end-1]+1); + assert(region_map_[start] == region_map_[start-1]+1); + assert(region_map_[end-1] == region_map_[start]); + assert(region_map_[end] == region_map_[end-1]+1); } template void MemoryMap::set_paging() { @@ -219,9 +219,9 @@ template void MemoryMap::set_paging() { // is exposed in bank $00 for a bunch of regions. if constexpr (type & PagingType::Main) { const auto set = [&](std::size_t page, const auto &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; + 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_; }; const auto state = auxiliary_switches_.main_state(); @@ -250,10 +250,10 @@ template void MemoryMap::set_paging() { // 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]); + 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 @@ -265,13 +265,13 @@ template void MemoryMap::set_paging() { 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]]; + 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); + 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; @@ -292,28 +292,28 @@ template void MemoryMap::set_paging() { apply_region(state.region_C8_D0, c8_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); + 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; + 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; + 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. @@ -341,47 +341,47 @@ template void MemoryMap::set_paging() { 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); + 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]]; + 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]]; + 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]); + 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 *read, uint8_t *write) { - auto &d0_region = regions[region_map[bank_base | 0xd0]]; + auto &d0_region = regions_[region_map_[bank_base | 0xd0]]; d0_region.read = read; d0_region.write = write; - auto &e0_region = regions[region_map[bank_base | 0xe0]]; + auto &e0_region = regions_[region_map_[bank_base | 0xe0]]; e0_region.read = read; e0_region.write = write; // 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(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, - main.base.read ? &ram_base[0x01'0000] : ram_base, - main.base.write ? &ram_base[0x01'0000] : ram_base); - set_no_card(0x0100, ram_base, ram_base); + main.base.read ? &ram_base_[0x01'0000] : ram_base_, + main.base.write ? &ram_base_[0x01'0000] : ram_base_); + set_no_card(0x0100, ram_base_, ram_base_); } else { - apply(0x0000, zero_state ? &ram_base[0x01'0000] : ram_base); - apply(0x0100, ram_base); + 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 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; + uint8_t *const e0_ram = regions_[region_map_[0xe000]].write; apply(0xe000, e0_ram); apply(0xe100, e0_ram); } @@ -423,13 +423,13 @@ void MemoryMap::set_shadowing() { }; // Clear all shadowing. - shadow_pages.reset(); + shadow_pages_.reset(); // Text Page 1, main and auxiliary — $0400–$0800. { const bool should_shadow_text1 = !(shadow_register_ & Inhibit::TextPage1); if(should_shadow_text1) { - shadow_pages |= shadow_text1; + shadow_pages_ |= shadow_text1_; } } @@ -439,7 +439,7 @@ void MemoryMap::set_shadowing() { { const bool should_shadow_text2 = !(shadow_register_ & Inhibit::TextPage2); if(should_shadow_text2) { - shadow_pages |= shadow_text2; + shadow_pages_ |= shadow_text2_; } } @@ -456,7 +456,7 @@ void MemoryMap::set_shadowing() { { const bool should_shadow_highres1 = !(shadow_register_ & Inhibit::HighRes1); if(should_shadow_highres1) { - shadow_pages |= shadow_highres1; + shadow_pages_ |= shadow_highres1_; } const bool should_shadow_aux_highres1 = !( @@ -464,7 +464,7 @@ void MemoryMap::set_shadowing() { shadow_register_ & Inhibit::SuperHighRes ); if(should_shadow_aux_highres1) { - shadow_pages |= shadow_highres1_aux; + shadow_pages_ |= shadow_highres1_aux_; } } @@ -475,7 +475,7 @@ void MemoryMap::set_shadowing() { { const bool should_shadow_highres2 = !(shadow_register_ & Inhibit::HighRes2); if(should_shadow_highres2) { - shadow_pages |= shadow_highres2; + shadow_pages_ |= shadow_highres2_; } const bool should_shadow_aux_highres2 = !( @@ -483,7 +483,7 @@ void MemoryMap::set_shadowing() { shadow_register_ & Inhibit::SuperHighRes ); if(should_shadow_aux_highres2) { - shadow_pages |= shadow_highres2_aux; + shadow_pages_ |= shadow_highres2_aux_; } } @@ -497,7 +497,7 @@ void MemoryMap::set_shadowing() { shadow_register_ & Inhibit::AuxiliaryHighRes ); if(should_shadow_superhighres) { - shadow_pages |= shadow_superhighres; + shadow_pages_ |= shadow_superhighres_; } } } @@ -507,27 +507,27 @@ void MemoryMap::setup_shadow_maps(bool is_rom03) { static constexpr int auxiliary_offset = 0x1'0000 >> shadow_shift; for(size_t c = 0x0400 >> shadow_shift; c < 0x0800 >> shadow_shift; c++) { - shadow_text1[c] = shadow_text1[c+auxiliary_offset] = true; + shadow_text1_[c] = shadow_text1_[c+auxiliary_offset] = true; } // Shadowing of text page 2 was added only with the ROM03 machine. if(is_rom03) { for(size_t c = 0x0800 >> shadow_shift; c < 0x0c00 >> shadow_shift; c++) { - shadow_text2[c] = shadow_text2[c+auxiliary_offset] = true; + shadow_text2_[c] = shadow_text2_[c+auxiliary_offset] = true; } } for(size_t c = 0x2000 >> shadow_shift; c < 0x4000 >> shadow_shift; c++) { - shadow_highres1[c] = true; - shadow_highres1_aux[c+auxiliary_offset] = true; + shadow_highres1_[c] = true; + shadow_highres1_aux_[c+auxiliary_offset] = true; } for(size_t c = 0x4000 >> shadow_shift; c < 0x6000 >> shadow_shift; c++) { - shadow_highres2[c] = true; - shadow_highres2_aux[c+auxiliary_offset] = true; + shadow_highres2_[c] = true; + shadow_highres2_aux_[c+auxiliary_offset] = true; } for(size_t c = 0x6000 >> shadow_shift; c < 0xa000 >> shadow_shift; c++) { - shadow_superhighres[c+auxiliary_offset] = true; + shadow_superhighres_[c+auxiliary_offset] = true; } } diff --git a/Machines/Apple/AppleIIgs/MemoryMap.hpp b/Machines/Apple/AppleIIgs/MemoryMap.hpp index 9614202f2..866952d7c 100644 --- a/Machines/Apple/AppleIIgs/MemoryMap.hpp +++ b/Machines/Apple/AppleIIgs/MemoryMap.hpp @@ -64,14 +64,14 @@ class MemoryMap { }; }; - const Region ®ion(uint32_t address) const { return regions[region_map[address >> 8]]; } + const Region ®ion(uint32_t address) const { return regions_[region_map_[address >> 8]]; } uint8_t read(const Region ®ion, uint32_t address) const { return region.read ? region.read[address] : 0xff; } bool is_shadowed(const Region ®ion, uint32_t address) const { const auto physical = physical_address(region, address); - return shadow_pages[(physical >> 10) & 127] & shadow_banks[physical >> 17]; + return shadow_pages_[(physical >> 10) & 127] & shadow_banks_[physical >> 17]; } void write(const Region ®ion, uint32_t address, uint8_t value) { if(!region.write) { @@ -84,7 +84,7 @@ class MemoryMap { // Write again, either to the same place (if unshadowed) or to the shadow destination. static constexpr std::size_t shadow_mask[2] = {0xff'ffff, 0x01'ffff}; const bool shadowed = is_shadowed(region, address); - shadow_base[shadowed][physical_address(region, address) & shadow_mask[shadowed]] = value; + shadow_base_[shadowed][physical_address(region, address) & shadow_mask[shadowed]] = value; } // The objective is to support shadowing: @@ -113,43 +113,44 @@ class MemoryMap { void assert_is_region(uint8_t start, uint8_t end); template void set_paging(); + uint8_t *ram_base_ = nullptr; + // Memory layout here is done via double indirection; the main loop should: // (i) use the top two bytes of the address to get an index from region_map; and // (ii) use that to index the memory_regions table. // // Pointers are eight bytes at the time of writing, so the extra level of indirection // reduces what would otherwise be a 1.25mb table down to not a great deal more than 64kb. - std::array region_map{}; - uint8_t *ram_base = nullptr; - - std::array regions; // An assert above ensures that this is large enough; there's no - // doctrinal reason for it to be whatever size it is now, just - // adjust as required. + std::array region_map_{}; + std::array regions_; // An assert above ensures that this is large enough; there's no + // doctrinal reason for it to be whatever size it is now, just + // adjust as required. std::size_t physical_address(const Region ®ion, uint32_t address) const { - return std::size_t(®ion.write[address] - ram_base); + return std::size_t(®ion.write[address] - ram_base_); } // MARK: - Shadowing // Various precomputed bitsets describing key regions; std::bitset doesn't support constexpr instantiation // beyond the first 64 bits at the time of writing, alas, so these are generated at runtime. - std::bitset<128> shadow_text1; - std::bitset<128> shadow_text2; - std::bitset<128> shadow_highres1, shadow_highres1_aux; - std::bitset<128> shadow_highres2, shadow_highres2_aux; - std::bitset<128> shadow_superhighres; + std::bitset<128> shadow_text1_; + std::bitset<128> shadow_text2_; + std::bitset<128> shadow_highres1_, shadow_highres1_aux_; + std::bitset<128> shadow_highres2_, shadow_highres2_aux_; + std::bitset<128> shadow_superhighres_; void setup_shadow_maps(bool is_rom03); void set_shadowing(); - uint8_t *shadow_base[2] = {nullptr, nullptr}; + uint8_t *shadow_base_[2] = {nullptr, nullptr}; - // Shadow_pages: divides the final 128kb of memory into 1kb chunks and includes a flag to indicate whether + // Divide the final 128kb of memory into 1kb chunks and flag to indicate whether // each is a potential destination for shadowing. - // - // Shadow_banks: divides the whole 16mb of memory into 128kb chunks and includes a flag to indicate whether + std::bitset<128> shadow_pages_{}; + + // Divide the whole 16mb of memory into 128kb chunks and flag to indicate whether // each is a potential source of shadowing. - std::bitset<128> shadow_pages{}, shadow_banks{}; + std::bitset<128> shadow_banks_{}; }; }