1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-29 00:29:34 +00:00

Secondary slot selections are per primary slot.

This commit is contained in:
Thomas Harte 2023-01-11 13:15:00 -05:00
parent fee82d3baa
commit 0d8c014099

View File

@ -420,18 +420,16 @@ class ConcreteMachine:
// MARK: Memory paging. // MARK: Memory paging.
void page_primary(uint8_t value) { void page_primary(uint8_t value) {
paging_.primary = value; primary_slots_ = value;
update_paging();
}
void page_secondary(uint8_t value) {
paging_.secondary = value;
update_paging(); update_paging();
} }
void update_paging() { void update_paging() {
uint8_t primary = paging_.primary; uint8_t primary = primary_slots_;
final_slot_ = &memory_slots_[primary >> 6];
// TODO: factor in secondary slot selection below.
for(std::size_t c = 0; c < 8; c += 2) { for(std::size_t c = 0; c < 8; c += 2) {
const MemorySlot &slot = memory_slots_[primary & 3]; const MemorySlot &slot = memory_slots_[primary & 3];
primary >>= 2; primary >>= 2;
@ -444,11 +442,6 @@ class ConcreteMachine:
set_use_fast_tape(); set_use_fast_tape();
} }
// For now: support secondary paging on the MSX 2 only.
constexpr static bool supports_secondary_paging() {
return model == Target::Model::MSX2;
}
// MARK: Z80::BusHandler // MARK: Z80::BusHandler
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
// Per the best information I currently have, the MSX inserts an extra cycle into each opcode read, // Per the best information I currently have, the MSX inserts an extra cycle into each opcode read,
@ -533,38 +526,34 @@ class ConcreteMachine:
[[fallthrough]]; [[fallthrough]];
case CPU::Z80::PartialMachineCycle::Read: case CPU::Z80::PartialMachineCycle::Read:
if constexpr (supports_secondary_paging()) { if(address == 0xffff && final_slot_->supports_secondary_paging) {
if(address == 0xffff) { *cycle.value = final_slot_->secondary_paging ^ 0xff;
*cycle.value = paging_.secondary ^ 0xff;; break;
break;
}
} }
if(read_pointers_[address >> 13]) { if(read_pointers_[address >> 13]) {
*cycle.value = read_pointers_[address >> 13][address & 8191]; *cycle.value = read_pointers_[address >> 13][address & 8191];
} else { } else {
int slot_hit = (paging_.primary >> ((address >> 14) * 2)) & 3; const int slot_hit = (primary_slots_ >> ((address >> 14) * 2)) & 3;
memory_slots_[slot_hit].handler->run_for(memory_slots_[slot_hit].cycles_since_update.template flush<HalfCycles>()); memory_slots_[slot_hit].handler->run_for(memory_slots_[slot_hit].cycles_since_update.template flush<HalfCycles>());
*cycle.value = memory_slots_[slot_hit].handler->read(address); *cycle.value = memory_slots_[slot_hit].handler->read(address);
} }
break; break;
case CPU::Z80::PartialMachineCycle::Write: { case CPU::Z80::PartialMachineCycle::Write: {
if constexpr (supports_secondary_paging()) { if(address == 0xffff && final_slot_->supports_secondary_paging) {
if(address == 0xffff) { final_slot_->secondary_paging = *cycle.value;
paging_.secondary = *cycle.value; update_paging();
update_paging(); break;
break;
}
} }
write_pointers_[address >> 13][address & 8191] = *cycle.value; const int slot_hit = (primary_slots_ >> ((address >> 14) * 2)) & 3;
int slot_hit = (paging_.primary >> ((address >> 14) * 2)) & 3;
if(memory_slots_[slot_hit].handler) { if(memory_slots_[slot_hit].handler) {
update_audio(); update_audio();
memory_slots_[slot_hit].handler->run_for(memory_slots_[slot_hit].cycles_since_update.template flush<HalfCycles>()); memory_slots_[slot_hit].handler->run_for(memory_slots_[slot_hit].cycles_since_update.template flush<HalfCycles>());
memory_slots_[slot_hit].handler->write(address, *cycle.value, read_pointers_[pc_address_ >> 13] != memory_slots_[0].read_pointers[pc_address_ >> 13]); memory_slots_[slot_hit].handler->write(address, *cycle.value, read_pointers_[pc_address_ >> 13] != memory_slots_[0].read_pointers[pc_address_ >> 13]);
} else {
write_pointers_[address >> 13][address & 8191] = *cycle.value;
} }
} break; } break;
@ -804,18 +793,20 @@ class ConcreteMachine:
bool allow_fast_tape_ = false; bool allow_fast_tape_ = false;
bool use_fast_tape_ = false; bool use_fast_tape_ = false;
void set_use_fast_tape() { void set_use_fast_tape() {
use_fast_tape_ = !tape_player_is_sleeping_ && allow_fast_tape_ && tape_player_.has_tape() && !(paging_.primary&3) && !(paging_.secondary&3); use_fast_tape_ =
!tape_player_is_sleeping_ &&
allow_fast_tape_ &&
tape_player_.has_tape() &&
!(primary_slots_ & 3) &&
!(memory_slots_[0].secondary_paging & 3);
} }
i8255PortHandler i8255_port_handler_; i8255PortHandler i8255_port_handler_;
AYPortHandler ay_port_handler_; AYPortHandler ay_port_handler_;
/// The current primary and secondary slot selections; the former retains whatever was written /// The current primary and secondary slot selections; the former retains whatever was written
/// last to the 8255 PPI via port A8 and the latter — if enabled — captures 0xffff. /// last to the 8255 PPI via port A8 and the latter — if enabled — captures 0xffff on a per-slot basis.
struct { uint8_t primary_slots_ = 0;
uint8_t primary = 0;
uint8_t secondary = 0;
} paging_;
// Divides the current 64kb address space into 8kb chunks. // Divides the current 64kb address space into 8kb chunks.
// 8kb resolution is used by some cartride titles. // 8kb resolution is used by some cartride titles.
@ -852,12 +843,17 @@ class ConcreteMachine:
HalfCycles cycles_since_update; HalfCycles cycles_since_update;
std::unique_ptr<ROMSlotHandler> handler; std::unique_ptr<ROMSlotHandler> handler;
ROMSlotHandler::WrappingStrategy wrapping_strategy = ROMSlotHandler::WrappingStrategy::Repeat; ROMSlotHandler::WrappingStrategy wrapping_strategy = ROMSlotHandler::WrappingStrategy::Repeat;
bool supports_secondary_paging = false;
uint8_t secondary_paging = 0x00;
/// Per-slot storage, as a convenience. /// Per-slot storage, as a convenience.
std::vector<uint8_t> source; std::vector<uint8_t> source;
}; };
MemorySlot memory_slots_[4]; MemorySlot memory_slots_[4];
MemorySlot *final_slot_ = nullptr;
/// Base RAM. /// Base RAM.
uint8_t ram_[65536]; uint8_t ram_[65536];