diff --git a/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp b/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp index c60634cc4..c3ccd35ab 100644 --- a/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp +++ b/Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp @@ -12,6 +12,17 @@ namespace Apple { namespace II { +/*! + Models the auxiliary memory soft switches, added as of the Apple IIe, which allow access to the auxiliary 64kb of RAM and to + the additional almost-4kb of ROM. + + Relevant memory accesses should be fed to this class; it'll call: + * machine.set_main_paging() if anything in the 'main' state changes, i.e. the lower 48kb excluding the zero and stack pages; + * machine.set_card_state() if anything changes with where ROM should appear rather than cards in the $Cxxx range; and + * machine.set_zero_page_paging() if the selection of the lowest two pages of RAM changes. + + Implementation observation: as implemented on the IIe, the zero page setting also affects what happens in the language card area. +*/ template class AuxiliaryMemorySwitches { public: static constexpr bool Auxiliary = true; @@ -35,7 +46,7 @@ template class AuxiliaryMemorySwitches { /// Describes banking state in the range $2000–$3FFF. Region region_20_40; - bool operator != (const MainState &rhs) { + bool operator != (const MainState &rhs) const { return base.read != rhs.base.read || base.write != rhs.base.write || region_04_08.read != rhs.region_04_08.read || region_04_08.write != rhs.region_04_08.write || @@ -54,7 +65,7 @@ template class AuxiliaryMemorySwitches { /// @c true indicates that the built-in ROM should appear from $C800 to $CFFF; @c false indicates that cards should service those accesses. bool region_C8_D0 = false; - bool operator != (const CardState &rhs) { + bool operator != (const CardState &rhs) const { return region_C1_C3 != rhs.region_C1_C3 || region_C3 != rhs.region_C3 || @@ -164,7 +175,7 @@ template class AuxiliaryMemorySwitches { MainState main_state_; void set_main_paging() { - MainState previous_state = main_state_; + const auto previous_state = main_state_; // The two appropriately named switches provide the base case. main_state_.base.read = switches_.read_auxiliary_memory; @@ -191,7 +202,7 @@ template class AuxiliaryMemorySwitches { CardState card_state_; void set_card_paging() { - CardState previous_state = card_state_; + const auto previous_state = card_state_; // By default apply the CX switch through to $C7FF. card_state_.region_C1_C3 = card_state_.region_C4_C8 = switches_.internal_CX_rom; diff --git a/Machines/Apple/AppleII/LanguageCardSwitches.hpp b/Machines/Apple/AppleII/LanguageCardSwitches.hpp index e60888e76..49b4a65cd 100644 --- a/Machines/Apple/AppleII/LanguageCardSwitches.hpp +++ b/Machines/Apple/AppleII/LanguageCardSwitches.hpp @@ -12,6 +12,12 @@ namespace Apple { namespace II { +/*! + Models the language card soft switches, present on any Apple II with a language card and provided built-in from the IIe onwards. + + Relevant memory accesses should be fed to this class; it'll call: + * machine.set_language_card_paging() if the proper mapped state changes. +*/ template class LanguageCardSwitches { public: struct State { @@ -26,14 +32,20 @@ template class LanguageCardSwitches { /// @c false indicates that RAM is selected for writing. bool write = false; - /// Contains the state of the internal pre-write flip flop; it does not directly affect the current memory map. - bool pre_write = false; + bool operator != (const State &rhs) const { + return + bank1 != rhs.bank1 || + read != rhs.read || + write != rhs.write; + } }; LanguageCardSwitches(Machine &machine) : machine_(machine) {} /// Used by an owner to forward any access to $c08x. void access(uint16_t address, bool is_read) { + const auto previous_state = state_; + // Quotes below taken from Understanding the Apple II, p. 5-28 and 5-29. // "A3 controls the 4K bank selection" @@ -44,7 +56,7 @@ template class LanguageCardSwitches { state_.read = !(((address&2) >> 1) ^ (address&1)); // "The WRITE ENABLE' flip-flop is reset by an odd read access to the $C08X range when the PRE-WRITE flip-flop is set." - if(state_.pre_write && is_read && (address&1)) state_.write = false; + if(pre_write_ && is_read && (address&1)) state_.write = false; // "[The WRITE ENABLE' flip-flop] is set by an even access in the $C08X range." if(!(address&1)) state_.write = true; @@ -52,10 +64,12 @@ template class LanguageCardSwitches { // ("Any other type of access causes the WRITE ENABLE' flip-flop to hold its current state.") // "The PRE-WRITE flip-flop is set by an odd read access in the $C08X range. It is reset by an even access or a write access." - state_.pre_write = is_read ? (address&1) : false; + pre_write_ = is_read ? (address&1) : false; // Apply whatever the net effect of all that is to the memory map. - machine_.set_language_card_paging(); + if(previous_state != state_) { + machine_.set_language_card_paging(); + } } /// Provides read-only access to the current language card switch state. @@ -66,6 +80,11 @@ template class LanguageCardSwitches { private: Machine &machine_; State state_; + + // This is an additional flip flop contained on the language card, but + // it is one step removed from current banking state, so I've excluded it + // from the State struct. + bool pre_write_ = false; }; }