mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-21 21:33:54 +00:00
Secondary slot selections are per primary slot.
This commit is contained in:
parent
fee82d3baa
commit
0d8c014099
@ -420,18 +420,16 @@ class ConcreteMachine:
|
||||
|
||||
// MARK: Memory paging.
|
||||
void page_primary(uint8_t value) {
|
||||
paging_.primary = value;
|
||||
update_paging();
|
||||
}
|
||||
|
||||
void page_secondary(uint8_t value) {
|
||||
paging_.secondary = value;
|
||||
primary_slots_ = value;
|
||||
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) {
|
||||
const MemorySlot &slot = memory_slots_[primary & 3];
|
||||
primary >>= 2;
|
||||
@ -444,11 +442,6 @@ class ConcreteMachine:
|
||||
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
|
||||
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,
|
||||
@ -533,38 +526,34 @@ class ConcreteMachine:
|
||||
[[fallthrough]];
|
||||
|
||||
case CPU::Z80::PartialMachineCycle::Read:
|
||||
if constexpr (supports_secondary_paging()) {
|
||||
if(address == 0xffff) {
|
||||
*cycle.value = paging_.secondary ^ 0xff;;
|
||||
break;
|
||||
}
|
||||
if(address == 0xffff && final_slot_->supports_secondary_paging) {
|
||||
*cycle.value = final_slot_->secondary_paging ^ 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
if(read_pointers_[address >> 13]) {
|
||||
*cycle.value = read_pointers_[address >> 13][address & 8191];
|
||||
} 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>());
|
||||
*cycle.value = memory_slots_[slot_hit].handler->read(address);
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU::Z80::PartialMachineCycle::Write: {
|
||||
if constexpr (supports_secondary_paging()) {
|
||||
if(address == 0xffff) {
|
||||
paging_.secondary = *cycle.value;
|
||||
update_paging();
|
||||
break;
|
||||
}
|
||||
if(address == 0xffff && final_slot_->supports_secondary_paging) {
|
||||
final_slot_->secondary_paging = *cycle.value;
|
||||
update_paging();
|
||||
break;
|
||||
}
|
||||
|
||||
write_pointers_[address >> 13][address & 8191] = *cycle.value;
|
||||
|
||||
int slot_hit = (paging_.primary >> ((address >> 14) * 2)) & 3;
|
||||
const int slot_hit = (primary_slots_ >> ((address >> 14) * 2)) & 3;
|
||||
if(memory_slots_[slot_hit].handler) {
|
||||
update_audio();
|
||||
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]);
|
||||
} else {
|
||||
write_pointers_[address >> 13][address & 8191] = *cycle.value;
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -804,18 +793,20 @@ class ConcreteMachine:
|
||||
bool allow_fast_tape_ = false;
|
||||
bool use_fast_tape_ = false;
|
||||
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_;
|
||||
AYPortHandler ay_port_handler_;
|
||||
|
||||
/// 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.
|
||||
struct {
|
||||
uint8_t primary = 0;
|
||||
uint8_t secondary = 0;
|
||||
} paging_;
|
||||
/// last to the 8255 PPI via port A8 and the latter — if enabled — captures 0xffff on a per-slot basis.
|
||||
uint8_t primary_slots_ = 0;
|
||||
|
||||
// Divides the current 64kb address space into 8kb chunks.
|
||||
// 8kb resolution is used by some cartride titles.
|
||||
@ -852,12 +843,17 @@ class ConcreteMachine:
|
||||
|
||||
HalfCycles cycles_since_update;
|
||||
std::unique_ptr<ROMSlotHandler> handler;
|
||||
|
||||
ROMSlotHandler::WrappingStrategy wrapping_strategy = ROMSlotHandler::WrappingStrategy::Repeat;
|
||||
|
||||
bool supports_secondary_paging = false;
|
||||
uint8_t secondary_paging = 0x00;
|
||||
|
||||
/// Per-slot storage, as a convenience.
|
||||
std::vector<uint8_t> source;
|
||||
};
|
||||
MemorySlot memory_slots_[4];
|
||||
MemorySlot *final_slot_ = nullptr;
|
||||
|
||||
/// Base RAM.
|
||||
uint8_t ram_[65536];
|
||||
|
Loading…
Reference in New Issue
Block a user