mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 03:32:01 +00:00
Factors out auxiliary memory switches and related decisions.
This commit is contained in:
parent
410c99de54
commit
9371a8993f
@ -19,9 +19,10 @@
|
|||||||
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
||||||
#include "../../../Outputs/Log.hpp"
|
#include "../../../Outputs/Log.hpp"
|
||||||
|
|
||||||
|
#include "AuxiliaryMemorySwitches.hpp"
|
||||||
#include "Card.hpp"
|
#include "Card.hpp"
|
||||||
#include "DiskIICard.hpp"
|
#include "DiskIICard.hpp"
|
||||||
#include "LanguageCard.hpp"
|
#include "LanguageCardSwitches.hpp"
|
||||||
#include "Video.hpp"
|
#include "Video.hpp"
|
||||||
|
|
||||||
#include "../../../Analyser/Static/AppleII/Target.hpp"
|
#include "../../../Analyser/Static/AppleII/Target.hpp"
|
||||||
@ -188,42 +189,39 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - The language card.
|
// MARK: The language card.
|
||||||
LanguageCard<ConcreteMachine> language_card_;
|
LanguageCardSwitches<ConcreteMachine> language_card_;
|
||||||
friend LanguageCard<ConcreteMachine>;
|
AuxiliaryMemorySwitches<ConcreteMachine> auxiliary_switches_;
|
||||||
|
friend LanguageCardSwitches<ConcreteMachine>;
|
||||||
|
friend AuxiliaryMemorySwitches<ConcreteMachine>;
|
||||||
|
|
||||||
void set_language_card_paging() {
|
void set_language_card_paging() {
|
||||||
uint8_t *const ram = alternative_zero_page_ ? aux_ram_ : ram_;
|
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();
|
uint8_t *const rom = is_iie() ? &rom_[3840] : rom_.data();
|
||||||
|
|
||||||
const auto state = language_card_.state();
|
|
||||||
page(0xd0, 0xe0,
|
page(0xd0, 0xe0,
|
||||||
state.read ? &ram[state.bank1 ? 0xd000 : 0xc000] : rom,
|
language_state.read ? &ram[language_state.bank1 ? 0xd000 : 0xc000] : rom,
|
||||||
state.write ? nullptr : &ram[state.bank1 ? 0xd000 : 0xc000]);
|
language_state.write ? nullptr : &ram[language_state.bank1 ? 0xd000 : 0xc000]);
|
||||||
|
|
||||||
page(0xe0, 0x100,
|
page(0xe0, 0x100,
|
||||||
state.read ? &ram[0xe000] : &rom[0x1000],
|
language_state.read ? &ram[0xe000] : &rom[0x1000],
|
||||||
state.write ? nullptr : &ram[0xe000]);
|
language_state.write ? nullptr : &ram[0xe000]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK - The IIe's ROM controls.
|
// MARK: Auxiliary memory and the other IIe improvements.
|
||||||
bool internal_CX_rom_ = false;
|
|
||||||
bool slot_C3_rom_ = false;
|
|
||||||
bool internal_c8_rom_ = false;
|
|
||||||
|
|
||||||
void set_card_paging() {
|
void set_card_paging() {
|
||||||
page(0xc1, 0xc8, internal_CX_rom_ ? rom_.data() : nullptr, nullptr);
|
const auto state = auxiliary_switches_.card_state();
|
||||||
|
|
||||||
if(!internal_CX_rom_) {
|
page(0xc1, 0xc4, state.region_C1_C3 ? &rom_[0xc100 - 0xc100] : nullptr, nullptr);
|
||||||
if(!slot_C3_rom_) read_pages_[0xc3] = &rom_[0xc300 - 0xc100];
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
page(0xc8, 0xd0, (internal_CX_rom_ || internal_c8_rom_) ? &rom_[0xc800 - 0xc100] : nullptr, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK - The IIe's auxiliary RAM controls.
|
|
||||||
bool alternative_zero_page_ = false;
|
|
||||||
void set_zero_page_paging() {
|
void set_zero_page_paging() {
|
||||||
if(alternative_zero_page_) {
|
if(auxiliary_switches_.zero_state()) {
|
||||||
write_pages_[0] = aux_ram_;
|
write_pages_[0] = aux_ram_;
|
||||||
} else {
|
} else {
|
||||||
write_pages_[0] = ram_;
|
write_pages_[0] = ram_;
|
||||||
@ -231,27 +229,30 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
write_pages_[1] = write_pages_[0] + 256;
|
write_pages_[1] = write_pages_[0] + 256;
|
||||||
read_pages_[0] = write_pages_[0];
|
read_pages_[0] = write_pages_[0];
|
||||||
read_pages_[1] = write_pages_[1];
|
read_pages_[1] = write_pages_[1];
|
||||||
}
|
|
||||||
|
|
||||||
bool read_auxiliary_memory_ = false;
|
// Zero page banking also affects interpretation of the language card's switches.
|
||||||
bool write_auxiliary_memory_ = false;
|
set_language_card_paging();
|
||||||
|
}
|
||||||
void set_main_paging() {
|
void set_main_paging() {
|
||||||
page(0x02, 0xc0,
|
const auto state = auxiliary_switches_.main_state();
|
||||||
read_auxiliary_memory_ ? &aux_ram_[0x0200] : &ram_[0x0200],
|
|
||||||
write_auxiliary_memory_ ? &aux_ram_[0x0200] : &ram_[0x0200]);
|
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]);
|
||||||
|
|
||||||
if(video_.get_80_store()) {
|
|
||||||
bool use_aux_ram = video_.get_page2();
|
|
||||||
page(0x04, 0x08,
|
page(0x04, 0x08,
|
||||||
use_aux_ram ? &aux_ram_[0x0400] : &ram_[0x0400],
|
state.region_04_08.read ? &aux_ram_[0x0400] : &ram_[0x0400],
|
||||||
use_aux_ram ? &aux_ram_[0x0400] : &ram_[0x0400]);
|
state.region_04_08.write ? &aux_ram_[0x0400] : &ram_[0x0400]);
|
||||||
|
|
||||||
if(video_.get_high_resolution()) {
|
|
||||||
page(0x20, 0x40,
|
page(0x20, 0x40,
|
||||||
use_aux_ram ? &aux_ram_[0x2000] : &ram_[0x2000],
|
state.region_20_40.read ? &aux_ram_[0x2000] : &ram_[0x2000],
|
||||||
use_aux_ram ? &aux_ram_[0x2000] : &ram_[0x2000]);
|
state.region_20_40.write ? &aux_ram_[0x2000] : &ram_[0x2000]);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK - typing
|
// MARK - typing
|
||||||
@ -318,7 +319,8 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
video_(video_bus_handler_),
|
video_(video_bus_handler_),
|
||||||
audio_toggle_(audio_queue_),
|
audio_toggle_(audio_queue_),
|
||||||
speaker_(audio_toggle_),
|
speaker_(audio_toggle_),
|
||||||
language_card_(*this) {
|
language_card_(*this),
|
||||||
|
auxiliary_switches_(*this) {
|
||||||
// The system's master clock rate.
|
// The system's master clock rate.
|
||||||
constexpr float master_clock = 14318180.0;
|
constexpr float master_clock = 14318180.0;
|
||||||
|
|
||||||
@ -398,9 +400,6 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
// Set the whole card area to initially backed by nothing.
|
// Set the whole card area to initially backed by nothing.
|
||||||
page(0xc0, 0xd0, nullptr, nullptr);
|
page(0xc0, 0xd0, nullptr, nullptr);
|
||||||
|
|
||||||
// Set proper values for the language card/ROM area.
|
|
||||||
set_language_card_paging();
|
|
||||||
|
|
||||||
insert_media(target.media);
|
insert_media(target.media);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,14 +454,8 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
if(write_pages_[address >> 8]) write_pages_[address >> 8][address & 0xff] = *value;
|
if(write_pages_[address >> 8]) write_pages_[address >> 8][address & 0xff] = *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_iie() && address >= 0xc300 && address < 0xd000) {
|
if(is_iie()) {
|
||||||
bool internal_c8_rom = internal_c8_rom_;
|
auxiliary_switches_.access(address, isReadOperation(operation));
|
||||||
internal_c8_rom |= ((address >> 8) == 0xc3) && !slot_C3_rom_;
|
|
||||||
internal_c8_rom &= (address != 0xcfff);
|
|
||||||
if(internal_c8_rom != internal_c8_rom_) {
|
|
||||||
internal_c8_rom_ = internal_c8_rom;
|
|
||||||
set_card_paging();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Assume a vapour read unless it turns out otherwise; this is a little
|
// Assume a vapour read unless it turns out otherwise; this is a little
|
||||||
@ -534,11 +527,11 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
#define IIeSwitchRead(s) *value = get_keyboard_input(); if(is_iie()) *value = (*value & 0x7f) | (s ? 0x80 : 0x00);
|
#define IIeSwitchRead(s) *value = get_keyboard_input(); if(is_iie()) *value = (*value & 0x7f) | (s ? 0x80 : 0x00);
|
||||||
case 0xc011: IIeSwitchRead(language_card_.state().bank1); break;
|
case 0xc011: IIeSwitchRead(language_card_.state().bank1); break;
|
||||||
case 0xc012: IIeSwitchRead(language_card_.state().read); break;
|
case 0xc012: IIeSwitchRead(language_card_.state().read); break;
|
||||||
case 0xc013: IIeSwitchRead(read_auxiliary_memory_); break;
|
case 0xc013: IIeSwitchRead(auxiliary_switches_.switches().read_auxiliary_memory); break;
|
||||||
case 0xc014: IIeSwitchRead(write_auxiliary_memory_); break;
|
case 0xc014: IIeSwitchRead(auxiliary_switches_.switches().write_auxiliary_memory); break;
|
||||||
case 0xc015: IIeSwitchRead(internal_CX_rom_); break;
|
case 0xc015: IIeSwitchRead(auxiliary_switches_.switches().internal_CX_rom); break;
|
||||||
case 0xc016: IIeSwitchRead(alternative_zero_page_); break;
|
case 0xc016: IIeSwitchRead(auxiliary_switches_.switches().alternative_zero_page); break;
|
||||||
case 0xc017: IIeSwitchRead(slot_C3_rom_); break;
|
case 0xc017: IIeSwitchRead(auxiliary_switches_.switches().slot_C3_rom); break;
|
||||||
case 0xc018: IIeSwitchRead(video_.get_80_store()); break;
|
case 0xc018: IIeSwitchRead(video_.get_80_store()); break;
|
||||||
case 0xc019: IIeSwitchRead(video_.get_is_vertical_blank(cycles_since_video_update_)); break;
|
case 0xc019: IIeSwitchRead(video_.get_is_vertical_blank(cycles_since_video_update_)); break;
|
||||||
case 0xc01a: IIeSwitchRead(video_.get_text()); break;
|
case 0xc01a: IIeSwitchRead(video_.get_text()); break;
|
||||||
@ -556,6 +549,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
} else {
|
} else {
|
||||||
// Write-only switches. All IIe as currently implemented.
|
// Write-only switches. All IIe as currently implemented.
|
||||||
if(is_iie()) {
|
if(is_iie()) {
|
||||||
|
auxiliary_switches_.access(address, false);
|
||||||
switch(address) {
|
switch(address) {
|
||||||
default: break;
|
default: break;
|
||||||
|
|
||||||
@ -563,40 +557,6 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
case 0xc001:
|
case 0xc001:
|
||||||
update_video();
|
update_video();
|
||||||
video_.set_80_store(!!(address&1));
|
video_.set_80_store(!!(address&1));
|
||||||
set_main_paging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc002:
|
|
||||||
case 0xc003:
|
|
||||||
read_auxiliary_memory_ = !!(address&1);
|
|
||||||
set_main_paging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc004:
|
|
||||||
case 0xc005:
|
|
||||||
write_auxiliary_memory_ = !!(address&1);
|
|
||||||
set_main_paging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc006:
|
|
||||||
case 0xc007:
|
|
||||||
internal_CX_rom_ = !!(address&1);
|
|
||||||
set_card_paging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc008:
|
|
||||||
case 0xc009:
|
|
||||||
// The alternative zero page setting affects both bank 0 and any RAM
|
|
||||||
// that's paged as though it were on a language card.
|
|
||||||
alternative_zero_page_ = !!(address&1);
|
|
||||||
set_zero_page_paging();
|
|
||||||
set_language_card_paging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc00a:
|
|
||||||
case 0xc00b:
|
|
||||||
slot_C3_rom_ = !!(address&1);
|
|
||||||
set_card_paging();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc00c:
|
case 0xc00c:
|
||||||
@ -639,13 +599,13 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
case 0xc055:
|
case 0xc055:
|
||||||
update_video();
|
update_video();
|
||||||
video_.set_page2(!!(address&1));
|
video_.set_page2(!!(address&1));
|
||||||
set_main_paging();
|
auxiliary_switches_.access(address, isReadOperation(operation));
|
||||||
break;
|
break;
|
||||||
case 0xc056:
|
case 0xc056:
|
||||||
case 0xc057:
|
case 0xc057:
|
||||||
update_video();
|
update_video();
|
||||||
video_.set_high_resolution(!!(address&1));
|
video_.set_high_resolution(!!(address&1));
|
||||||
set_main_paging();
|
auxiliary_switches_.access(address, isReadOperation(operation));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc05e:
|
case 0xc05e:
|
||||||
|
225
Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp
Normal file
225
Machines/Apple/AppleII/AuxiliaryMemorySwitches.hpp
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
//
|
||||||
|
// AuxiliaryMemorySwitches.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 22/10/2020.
|
||||||
|
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AuxiliaryMemorySwitches_h
|
||||||
|
#define AuxiliaryMemorySwitches_h
|
||||||
|
|
||||||
|
namespace Apple {
|
||||||
|
namespace II {
|
||||||
|
|
||||||
|
template <typename Machine> class AuxiliaryMemorySwitches {
|
||||||
|
public:
|
||||||
|
static constexpr bool Auxiliary = true;
|
||||||
|
static constexpr bool Main = false;
|
||||||
|
static constexpr bool ROM = true;
|
||||||
|
static constexpr bool Card = false;
|
||||||
|
|
||||||
|
/// Describes banking state between $0200 and $BFFF.
|
||||||
|
struct MainState {
|
||||||
|
struct Region {
|
||||||
|
/// @c true indicates auxiliary memory should be read from in this region; @c false indicates that main memory should be used.
|
||||||
|
bool read = false;
|
||||||
|
/// @c true indicates auxiliary memory should be written to in this region; @c false indicates that main memory should be used.
|
||||||
|
bool write = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Describes banking state in the ranges $0200–$3FFF, $0800–$1FFF and $4000–$BFFF.
|
||||||
|
Region base;
|
||||||
|
/// Describes banking state in the range $0400–$7FFF.
|
||||||
|
Region region_04_08;
|
||||||
|
/// Describes banking state in the range $2000–$3FFF.
|
||||||
|
Region region_20_40;
|
||||||
|
|
||||||
|
bool operator != (const MainState &rhs) {
|
||||||
|
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 ||
|
||||||
|
region_20_40.read != rhs.region_20_40.read || region_20_40.write != rhs.region_20_40.write;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Describes banking state between $C100 and $Cfff.
|
||||||
|
struct CardState {
|
||||||
|
/// @c true indicates that the built-in ROM should appear from $C100 to $C2FF @c false indicates that cards should service those accesses.
|
||||||
|
bool region_C1_C3 = false;
|
||||||
|
/// @c true indicates that the built-in ROM should appear from $C300 to $C3FF; @c false indicates that cards should service those accesses.
|
||||||
|
bool region_C3 = false;
|
||||||
|
/// @c true indicates that the built-in ROM should appear from $C400 to $C7FF; @c false indicates that cards should service those accesses.
|
||||||
|
bool region_C4_C8 = false;
|
||||||
|
/// @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) {
|
||||||
|
return
|
||||||
|
region_C1_C3 != rhs.region_C1_C3 ||
|
||||||
|
region_C3 != rhs.region_C3 ||
|
||||||
|
region_C4_C8 != rhs.region_C4_C8 ||
|
||||||
|
region_C8_D0 != rhs.region_C8_D0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descibes banking state between $0000 and $01ff; @c true indicates that auxiliary memory should be used; @c false indicates main memory.
|
||||||
|
using ZeroState = bool;
|
||||||
|
|
||||||
|
/// Returns raw switch state for all switches that affect banking, even if they're logically video switches.
|
||||||
|
struct SwitchState {
|
||||||
|
bool read_auxiliary_memory = false;
|
||||||
|
bool write_auxiliary_memory = false;
|
||||||
|
|
||||||
|
bool internal_CX_rom = false;
|
||||||
|
bool slot_C3_rom = false;
|
||||||
|
bool internal_C8_rom = false;
|
||||||
|
|
||||||
|
bool store_80 = false;
|
||||||
|
bool alternative_zero_page = false;
|
||||||
|
bool video_page_2 = false;
|
||||||
|
bool high_resolution = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
AuxiliaryMemorySwitches(Machine &machine) : machine_(machine) {}
|
||||||
|
|
||||||
|
/// Used by an owner to forward, at least, any access in the range $C000 to $C00B,
|
||||||
|
/// in $C054 to $C058, or in the range $C300 to $CFFF. Safe to call for any [16-bit] address.
|
||||||
|
void access(uint16_t address, bool is_read) {
|
||||||
|
if(address >= 0xc300 && address < 0xd000) {
|
||||||
|
switches_.internal_C8_rom |= ((address >> 8) == 0xc3) && !switches_.slot_C3_rom;
|
||||||
|
switches_.internal_C8_rom &= (address != 0xcfff);
|
||||||
|
set_card_paging();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_read) return;
|
||||||
|
|
||||||
|
switch(address) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case 0xc000: case 0xc001:
|
||||||
|
switches_.store_80 = address & 1;
|
||||||
|
set_main_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc002: case 0xc003:
|
||||||
|
switches_.read_auxiliary_memory = address & 1;
|
||||||
|
set_main_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc004: case 0xc005:
|
||||||
|
switches_.write_auxiliary_memory = address & 1;
|
||||||
|
set_main_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc006: case 0xc007:
|
||||||
|
switches_.internal_CX_rom = address & 1;
|
||||||
|
set_card_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc008: case 0xc009:
|
||||||
|
if(switches_.alternative_zero_page != bool(address & 1)) {
|
||||||
|
switches_.alternative_zero_page = address & 1;
|
||||||
|
set_zero_page_paging();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc00a: case 0xc00b:
|
||||||
|
switches_.slot_C3_rom = address & 1;
|
||||||
|
set_card_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc054: case 0xc055:
|
||||||
|
switches_.video_page_2 = address & 1;
|
||||||
|
set_main_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc056: case 0xc057:
|
||||||
|
switches_.high_resolution = address & 1;
|
||||||
|
set_main_paging();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MainState &main_state() {
|
||||||
|
return main_state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CardState &card_state() {
|
||||||
|
return card_state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ZeroState zero_state() {
|
||||||
|
return switches_.alternative_zero_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SwitchState switches() {
|
||||||
|
return switches_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Machine &machine_;
|
||||||
|
SwitchState switches_;
|
||||||
|
|
||||||
|
MainState main_state_;
|
||||||
|
void set_main_paging() {
|
||||||
|
MainState previous_state = main_state_;
|
||||||
|
|
||||||
|
// The two appropriately named switches provide the base case.
|
||||||
|
main_state_.base.read = switches_.read_auxiliary_memory;
|
||||||
|
main_state_.base.write = switches_.write_auxiliary_memory;
|
||||||
|
|
||||||
|
if(switches_.store_80) {
|
||||||
|
// If store 80 is set, use the page 2 flag for the lower carve out;
|
||||||
|
// if both store 80 and high resolution are set, use the page 2 flag for both carve outs.
|
||||||
|
main_state_.region_04_08.read = main_state_.region_04_08.write = switches_.video_page_2;
|
||||||
|
|
||||||
|
if(switches_.high_resolution) {
|
||||||
|
main_state_.region_20_40.read = main_state_.region_20_40.write = switches_.video_page_2;
|
||||||
|
} else {
|
||||||
|
main_state_.region_20_40 = main_state_.base;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
main_state_.region_04_08 = main_state_.region_20_40 = main_state_.base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(previous_state != main_state_) {
|
||||||
|
machine_.set_main_paging();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CardState card_state_;
|
||||||
|
void set_card_paging() {
|
||||||
|
CardState 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;
|
||||||
|
|
||||||
|
// Allow the C3 region to be switched to internal ROM in isolation even if the rest of the
|
||||||
|
// first half of the CX region is diabled, if its specific switch is also disabled.
|
||||||
|
if(!switches_.internal_CX_rom && !switches_.slot_C3_rom) {
|
||||||
|
card_state_.region_C3 = true;
|
||||||
|
} else {
|
||||||
|
card_state_.region_C3 = card_state_.region_C1_C3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the CX switch to $C800+, but also allow the C8 switch to select that region in isolation.
|
||||||
|
card_state_.region_C8_D0 = switches_.internal_CX_rom || switches_.internal_C8_rom;
|
||||||
|
|
||||||
|
if(previous_state != card_state_) {
|
||||||
|
machine_.set_card_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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* AuxiliaryMemorySwitches_h */
|
@ -1,18 +1,18 @@
|
|||||||
//
|
//
|
||||||
// LanguageCard.hpp
|
// LanguageCardSwitches.hpp
|
||||||
// Clock Signal
|
// Clock Signal
|
||||||
//
|
//
|
||||||
// Created by Thomas Harte on 22/10/2020.
|
// Created by Thomas Harte on 22/10/2020.
|
||||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef LanguageCard_h
|
#ifndef LanguageCardSwitches_h
|
||||||
#define LanguageCard_h
|
#define LanguageCardSwitches_h
|
||||||
|
|
||||||
namespace Apple {
|
namespace Apple {
|
||||||
namespace II {
|
namespace II {
|
||||||
|
|
||||||
template <typename Machine> class LanguageCard {
|
template <typename Machine> class LanguageCardSwitches {
|
||||||
public:
|
public:
|
||||||
struct State {
|
struct State {
|
||||||
/// Indicates which 4kb chunk of RAM should be visible at $Dxxx if RAM is visible at all.
|
/// Indicates which 4kb chunk of RAM should be visible at $Dxxx if RAM is visible at all.
|
||||||
@ -30,9 +30,9 @@ template <typename Machine> class LanguageCard {
|
|||||||
bool pre_write = false;
|
bool pre_write = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
LanguageCard(Machine &machine) : machine_(machine) {}
|
LanguageCardSwitches(Machine &machine) : machine_(machine) {}
|
||||||
|
|
||||||
/// Should be used by an owner to forward any access to $c08x.
|
/// Used by an owner to forward any access to $c08x.
|
||||||
void access(uint16_t address, bool is_read) {
|
void access(uint16_t address, bool is_read) {
|
||||||
// Quotes below taken from Understanding the Apple II, p. 5-28 and 5-29.
|
// Quotes below taken from Understanding the Apple II, p. 5-28 and 5-29.
|
||||||
|
|
@ -1809,7 +1809,8 @@
|
|||||||
4BEF6AA81D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DigitalPhaseLockedLoopBridge.h; sourceTree = "<group>"; };
|
4BEF6AA81D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DigitalPhaseLockedLoopBridge.h; sourceTree = "<group>"; };
|
||||||
4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DigitalPhaseLockedLoopBridge.mm; sourceTree = "<group>"; };
|
4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DigitalPhaseLockedLoopBridge.mm; sourceTree = "<group>"; };
|
||||||
4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DPLLTests.swift; sourceTree = "<group>"; };
|
4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DPLLTests.swift; sourceTree = "<group>"; };
|
||||||
4BF40A5525424C770033EA39 /* LanguageCard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LanguageCard.hpp; sourceTree = "<group>"; };
|
4BF40A5525424C770033EA39 /* LanguageCardSwitches.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LanguageCardSwitches.hpp; sourceTree = "<group>"; };
|
||||||
|
4BF40A5A254263140033EA39 /* AuxiliaryMemorySwitches.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AuxiliaryMemorySwitches.hpp; sourceTree = "<group>"; };
|
||||||
4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentParser.cpp; sourceTree = "<group>"; };
|
4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentParser.cpp; sourceTree = "<group>"; };
|
||||||
4BF437ED209D0F7E008CBD6B /* SegmentParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SegmentParser.hpp; sourceTree = "<group>"; };
|
4BF437ED209D0F7E008CBD6B /* SegmentParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SegmentParser.hpp; sourceTree = "<group>"; };
|
||||||
4BF437F0209D112F008CBD6B /* Sector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sector.hpp; sourceTree = "<group>"; };
|
4BF437F0209D112F008CBD6B /* Sector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sector.hpp; sourceTree = "<group>"; };
|
||||||
@ -3744,10 +3745,11 @@
|
|||||||
4BCE004E227CE8CA000CA200 /* DiskIICard.cpp */,
|
4BCE004E227CE8CA000CA200 /* DiskIICard.cpp */,
|
||||||
4BCE004D227CE8CA000CA200 /* Video.cpp */,
|
4BCE004D227CE8CA000CA200 /* Video.cpp */,
|
||||||
4BCE004A227CE8CA000CA200 /* AppleII.hpp */,
|
4BCE004A227CE8CA000CA200 /* AppleII.hpp */,
|
||||||
|
4BF40A5A254263140033EA39 /* AuxiliaryMemorySwitches.hpp */,
|
||||||
4BCE004B227CE8CA000CA200 /* Card.hpp */,
|
4BCE004B227CE8CA000CA200 /* Card.hpp */,
|
||||||
4BCE004C227CE8CA000CA200 /* DiskIICard.hpp */,
|
4BCE004C227CE8CA000CA200 /* DiskIICard.hpp */,
|
||||||
|
4BF40A5525424C770033EA39 /* LanguageCardSwitches.hpp */,
|
||||||
4BCE004F227CE8CA000CA200 /* Video.hpp */,
|
4BCE004F227CE8CA000CA200 /* Video.hpp */,
|
||||||
4BF40A5525424C770033EA39 /* LanguageCard.hpp */,
|
|
||||||
);
|
);
|
||||||
path = AppleII;
|
path = AppleII;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
Loading…
Reference in New Issue
Block a user