1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 05:29:23 +00:00

Adjust names of the newly-private.

This commit is contained in:
Thomas Harte 2024-01-04 10:36:33 -05:00
parent bfbaebb661
commit dae80217bc
2 changed files with 92 additions and 91 deletions

View File

@ -13,15 +13,15 @@ using PagingType = Apple::II::PagingType;
void MemoryMap::set_storage(std::vector<uint8_t> &ram, std::vector<uint8_t> &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<uint8_t> &ram, std::vector<uint8_t> &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<uint8_t> &ram, std::vector<uint8_t> &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 &region = regions[region_map[address >> 8]];
auto &region = 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<uint8_t> &ram, std::vector<uint8_t> &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 0x020x80.
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 <int type> void MemoryMap::set_paging() {
@ -219,9 +219,9 @@ template <int type> 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 &region = 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 &region = 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 <int type> 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 &region = 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 &region = 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 <int type> 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 = &regions[region_map[0xffd0]].read[0xffc100] - ((bank_base << 8) + 0xc100);
const uint8_t *const rom = &regions_[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 <int type> 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 <int type> 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 = &regions[region_map[0xffd0]].read[0xff'd000] - ((bank_base << 8) + 0xd000);
const uint8_t *const rom = &regions_[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;
}
}

View File

@ -64,14 +64,14 @@ class MemoryMap {
};
};
const Region &region(uint32_t address) const { return regions[region_map[address >> 8]]; }
const Region &region(uint32_t address) const { return regions_[region_map_[address >> 8]]; }
uint8_t read(const Region &region, uint32_t address) const {
return region.read ? region.read[address] : 0xff;
}
bool is_shadowed(const Region &region, 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 &region, 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 <int type> 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<uint8_t, 65536> region_map{};
uint8_t *ram_base = nullptr;
std::array<Region, 40> 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<uint8_t, 65536> region_map_{};
std::array<Region, 40> 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 &region, uint32_t address) const {
return std::size_t(&region.write[address] - ram_base);
return std::size_t(&region.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_{};
};
}