mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Adds documentation, ensures the language card signals less noisily.
This commit is contained in:
parent
9371a8993f
commit
966241b4cc
@ -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 <typename Machine> class AuxiliaryMemorySwitches {
|
||||
public:
|
||||
static constexpr bool Auxiliary = true;
|
||||
@ -35,7 +46,7 @@ template <typename Machine> 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 <typename Machine> 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 <typename Machine> 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 <typename Machine> 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;
|
||||
|
@ -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 <typename Machine> class LanguageCardSwitches {
|
||||
public:
|
||||
struct State {
|
||||
@ -26,14 +32,20 @@ template <typename Machine> 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 <typename Machine> 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 <typename Machine> 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 <typename Machine> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user