mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +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.
|
// 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];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user