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

Exposes much of the auxiliary and language card stuff to the IIgs bus.

This commit is contained in:
Thomas Harte 2020-10-28 21:58:20 -04:00
parent 885fae1534
commit 94a6da6b7d
4 changed files with 122 additions and 14 deletions

View File

@ -163,19 +163,32 @@ template <typename Machine> class AuxiliaryMemorySwitches {
}
}
const MainState &main_state() {
/// Provides part of the IIgs interface.
void set_state(uint8_t value) {
switches_.alternative_zero_page = value & 0x80;
switches_.video_page_2 = value & 0x40;
switches_.read_auxiliary_memory = value & 0x20;
switches_.write_auxiliary_memory = value & 0x10;
switches_.internal_CX_rom = value & 0x01;
set_main_paging();
set_zero_page_paging();
set_card_paging();
}
const MainState &main_state() const {
return main_state_;
}
const CardState &card_state() {
const CardState &card_state() const {
return card_state_;
}
const ZeroState zero_state() {
const ZeroState zero_state() const {
return switches_.alternative_zero_page;
}
const SwitchState switches() {
const SwitchState switches() const {
return switches_;
}

View File

@ -73,10 +73,22 @@ template <typename Machine> class LanguageCardSwitches {
}
/// Provides read-only access to the current language card switch state.
const State &state() {
const State &state() const {
return state_;
}
/// Provides relevant parts of the IIgs interface.
void set_state(uint8_t value) {
const auto previous_state = state_;
state_.read = value & 0x08;
state_.bank1 = value & 0x04;
if(previous_state != state_) {
machine_.set_language_card_paging();
}
}
private:
Machine &machine_;
State state_;

View File

@ -89,6 +89,9 @@ class ConcreteMachine:
const auto &region = MemoryMapRegion(memory_, address);
if(region.flags & MemoryMap::Region::IsIO) {
// Ensure classic auxiliary and language card accesses have effect.
memory_.access(uint16_t(address), isReadOperation(operation));
switch(address & 0xffff) {
// New video register.
@ -102,6 +105,15 @@ class ConcreteMachine:
}
break;
// Shadow register.
case 0xc035:
if(isReadOperation(operation)) {
*value = memory_.get_shadow_register();
} else {
memory_.set_shadow_register(*value);
}
break;
// Speed register.
case 0xc036:
if(isReadOperation(operation)) {
@ -113,10 +125,48 @@ class ConcreteMachine:
}
break;
// [Memory] State register.
case 0xc068:
if(isReadOperation(operation)) {
*value = memory_.get_state_register();
} else {
memory_.set_state_register(*value);
}
break;
// Various independent memory switch reads [TODO: does the IIe-style keyboard the low seven?].
#define SwitchRead(s) *value = memory_.s ? 0x80 : 0x00
#define LanguageRead(s) SwitchRead(language_card_switches().state().s)
#define AuxiliaryRead(s) SwitchRead(auxiliary_switches().switches().s)
case 0xc011: LanguageRead(bank1); break;
case 0xc012: LanguageRead(read); break;
case 0xc013: AuxiliaryRead(read_auxiliary_memory); break;
case 0xc014: AuxiliaryRead(write_auxiliary_memory); break;
case 0xc015: AuxiliaryRead(internal_CX_rom); break;
case 0xc016: AuxiliaryRead(alternative_zero_page); break;
case 0xc017: AuxiliaryRead(slot_C3_rom); break;
#undef AuxiliaryRead
#undef LanguageRead
#undef SwitchRead
// These were all dealt with by the call to memory_.access.
// TODO: subject to read data? Does vapour lock apply?
case 0xc000: case 0xc001: case 0xc002: case 0xc003: case 0xc004: case 0xc005:
case 0xc006: case 0xc007: case 0xc008: case 0xc009: case 0xc00a: case 0xc00b:
case 0xc054: case 0xc055: case 0xc056: case 0xc057:
break;
default:
if(address < 0xc100) {
// TODO: all other IO accesses.
printf("Unhandled IO: %04x\n", address);
assert(false);
} else {
// Card IO. Not implemented!
if(isReadOperation(operation)) {
*value = 0xff;
}
}
}
} else {
if(isReadOperation(operation)) {

View File

@ -180,7 +180,7 @@ class MemoryMap {
set_shadowing();
}
// MARK: - Live bus access notifications.
// MARK: - Live bus access notifications and register access.
void set_shadow_register(uint8_t value) {
const uint8_t diff = value ^ shadow_register_;
@ -196,6 +196,10 @@ class MemoryMap {
}
}
uint8_t get_shadow_register() const {
return shadow_register_;
}
void set_speed_register(uint8_t value) {
const uint8_t diff = value ^ speed_register_;
speed_register_ = value;
@ -204,16 +208,45 @@ class MemoryMap {
}
}
void set_state_register(uint8_t value) {
auxiliary_switches_.set_state(value);
language_card_.set_state(value);
}
uint8_t get_state_register() const {
const auto auxiliary_switches = auxiliary_switches_.switches();
const auto language_state = language_card_.state();
return
(auxiliary_switches.alternative_zero_page ? 0x80 : 0x00) |
(auxiliary_switches.video_page_2 ? 0x40 : 0x00) |
(auxiliary_switches.read_auxiliary_memory ? 0x20 : 0x00) |
(auxiliary_switches.write_auxiliary_memory ? 0x10 : 0x00) |
(language_state.read ? 0x08 : 0x00) |
(language_state.bank1 ? 0x04 : 0x00) |
(auxiliary_switches.internal_CX_rom ? 0x01 : 0x00);
}
void access(uint16_t address, bool is_read) {
auxiliary_switches_.access(address, is_read);
if(address &0xfff0 == 0xc080) language_card_.access(address, is_read);
if((address & 0xfff0) == 0xc080) language_card_.access(address, is_read);
}
using AuxiliaryMemorySwitches = Apple::II::AuxiliaryMemorySwitches<MemoryMap>;
const AuxiliaryMemorySwitches &auxiliary_switches() const {
return auxiliary_switches_;
}
using LanguageCardSwitches = Apple::II::LanguageCardSwitches<MemoryMap>;
const LanguageCardSwitches &language_card_switches() const {
return language_card_;
}
private:
Apple::II::AuxiliaryMemorySwitches<MemoryMap> auxiliary_switches_;
Apple::II::LanguageCardSwitches<MemoryMap> language_card_;
friend Apple::II::AuxiliaryMemorySwitches<MemoryMap>;
friend Apple::II::LanguageCardSwitches<MemoryMap>;
AuxiliaryMemorySwitches auxiliary_switches_;
LanguageCardSwitches language_card_;
friend AuxiliaryMemorySwitches;
friend LanguageCardSwitches;
uint8_t shadow_register_ = 0x08;
uint8_t speed_register_ = 0x00;