mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Takes a run at contended timings.
This commit is contained in:
parent
f8c9ef2950
commit
93b9ea67e6
@ -225,11 +225,13 @@ template <VideoTiming timing> class Video {
|
|||||||
return time_since_interrupt_ < interrupt_duration;
|
return time_since_interrupt_ < interrupt_duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
int access_delay() const {
|
int access_delay(HalfCycles offset) const {
|
||||||
constexpr auto timings = get_timings();
|
constexpr auto timings = get_timings();
|
||||||
if(time_since_interrupt_ < timings.first_delay) return 0;
|
const int delay_time = (time_since_interrupt_ + offset.as<int>()) % (timings.cycles_per_line * timings.lines_per_frame);
|
||||||
|
|
||||||
const int time_since = time_since_interrupt_ - timings.first_delay;
|
if(delay_time < timings.first_delay) return 0;
|
||||||
|
|
||||||
|
const int time_since = delay_time - timings.first_delay;
|
||||||
const int lines = time_since / timings.cycles_per_line;
|
const int lines = time_since / timings.cycles_per_line;
|
||||||
if(lines >= 192) return 0;
|
if(lines >= 192) return 0;
|
||||||
|
|
||||||
|
@ -107,27 +107,36 @@ template<Model model> class ConcreteMachine:
|
|||||||
// MARK: - BusHandler
|
// MARK: - BusHandler
|
||||||
|
|
||||||
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
||||||
time_since_audio_update_ += cycle.length;
|
|
||||||
|
|
||||||
video_ += cycle.length;
|
|
||||||
if(video_.did_flush()) {
|
|
||||||
z80_.set_interrupt_line(video_.last_valid()->get_interrupt_line());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore all but terminal cycles.
|
// Ignore all but terminal cycles.
|
||||||
// TODO: I doubt this is correct for timing.
|
// TODO: I doubt this is correct for timing.
|
||||||
if(!cycle.is_terminal()) return HalfCycles(0);
|
if(!cycle.is_terminal()) {
|
||||||
|
advance(cycle.length);
|
||||||
|
return HalfCycles(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
HalfCycles delay(0);
|
||||||
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||||
using PartialMachineCycle = CPU::Z80::PartialMachineCycle;
|
using PartialMachineCycle = CPU::Z80::PartialMachineCycle;
|
||||||
switch(cycle.operation) {
|
switch(cycle.operation) {
|
||||||
default: break;
|
default: break;
|
||||||
case PartialMachineCycle::ReadOpcode:
|
case PartialMachineCycle::ReadOpcode:
|
||||||
case PartialMachineCycle::Read:
|
case PartialMachineCycle::Read:
|
||||||
|
// Apply contention if necessary.
|
||||||
|
if(is_contended_[address >> 14]) {
|
||||||
|
delay = video_.last_valid()->access_delay(video_.time_since_flush());
|
||||||
|
}
|
||||||
|
|
||||||
*cycle.value = read_pointers_[address >> 14][address];
|
*cycle.value = read_pointers_[address >> 14][address];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PartialMachineCycle::Write:
|
case PartialMachineCycle::Write:
|
||||||
|
// Apply contention if necessary.
|
||||||
|
// For now this causes a video sync up every time any contended area is written to.
|
||||||
|
// TODO: flush only upon a video-area write.
|
||||||
|
if(is_contended_[address >> 14]) {
|
||||||
|
delay = video_->access_delay(HalfCycles(0));
|
||||||
|
}
|
||||||
|
|
||||||
write_pointers_[address >> 14][address] = *cycle.value;
|
write_pointers_[address >> 14][address] = *cycle.value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -211,9 +220,22 @@ template<Model model> class ConcreteMachine:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return HalfCycles(0);
|
advance(cycle.length + delay);
|
||||||
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void advance(HalfCycles duration) {
|
||||||
|
time_since_audio_update_ += duration;
|
||||||
|
|
||||||
|
video_ += duration;
|
||||||
|
if(video_.did_flush()) {
|
||||||
|
z80_.set_interrupt_line(video_.last_valid()->get_interrupt_line());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
// MARK: - Typer
|
// MARK: - Typer
|
||||||
// HalfCycles get_typer_delay(const std::string &) const final {
|
// HalfCycles get_typer_delay(const std::string &) const final {
|
||||||
// return z80_.get_is_resetting() ? Cycles(7'000'000) : Cycles(0);
|
// return z80_.get_is_resetting() ? Cycles(7'000'000) : Cycles(0);
|
||||||
@ -246,6 +268,7 @@ template<Model model> class ConcreteMachine:
|
|||||||
std::array<uint8_t, 16*1024> scratch_;
|
std::array<uint8_t, 16*1024> scratch_;
|
||||||
const uint8_t *read_pointers_[4];
|
const uint8_t *read_pointers_[4];
|
||||||
uint8_t *write_pointers_[4];
|
uint8_t *write_pointers_[4];
|
||||||
|
bool is_contended_[4];
|
||||||
|
|
||||||
uint8_t port1ffd_ = 0;
|
uint8_t port1ffd_ = 0;
|
||||||
uint8_t port7ffd_ = 0;
|
uint8_t port7ffd_ = 0;
|
||||||
@ -267,31 +290,31 @@ template<Model model> class ConcreteMachine:
|
|||||||
switch(port1ffd_ & 0x6) {
|
switch(port1ffd_ & 0x6) {
|
||||||
default:
|
default:
|
||||||
case 0x00:
|
case 0x00:
|
||||||
set_memory(0, &ram_[0 * 16384], &ram_[0 * 16384]);
|
set_memory(0, &ram_[0 * 16384], &ram_[0 * 16384], false);
|
||||||
set_memory(1, &ram_[1 * 16384], &ram_[1 * 16384]);
|
set_memory(1, &ram_[1 * 16384], &ram_[1 * 16384], false);
|
||||||
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
|
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384], false);
|
||||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
|
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
|
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
||||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
|
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
||||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
|
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
||||||
set_memory(3, &ram_[7 * 16384], &ram_[7 * 16384]);
|
set_memory(3, &ram_[7 * 16384], &ram_[7 * 16384], true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04:
|
case 0x04:
|
||||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
|
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
||||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
|
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
||||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
|
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
||||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
|
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x06:
|
case 0x06:
|
||||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
|
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
||||||
set_memory(1, &ram_[7 * 16384], &ram_[7 * 16384]);
|
set_memory(1, &ram_[7 * 16384], &ram_[7 * 16384], true);
|
||||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
|
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
||||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
|
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,16 +323,17 @@ template<Model model> class ConcreteMachine:
|
|||||||
|
|
||||||
// Apply standard 128kb-esque mapping (albeit with extra ROM to pick from).
|
// Apply standard 128kb-esque mapping (albeit with extra ROM to pick from).
|
||||||
const auto rom = &rom_[ (((port1ffd_ >> 1) & 2) | ((port7ffd_ >> 4) & 1)) * 16384];
|
const auto rom = &rom_[ (((port1ffd_ >> 1) & 2) | ((port7ffd_ >> 4) & 1)) * 16384];
|
||||||
set_memory(0, rom, nullptr);
|
set_memory(0, rom, nullptr, false);
|
||||||
|
|
||||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
|
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
||||||
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
|
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384], false);
|
||||||
|
|
||||||
const auto high_ram = &ram_[(port7ffd_ & 7) * 16384];
|
const auto high_ram = &ram_[(port7ffd_ & 7) * 16384];
|
||||||
set_memory(3, high_ram, high_ram);
|
set_memory(3, high_ram, high_ram, (port7ffd_ & 7) >= 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_memory(int bank, const uint8_t *read, uint8_t *write) {
|
void set_memory(int bank, const uint8_t *read, uint8_t *write, bool is_contended) {
|
||||||
|
is_contended_[bank] = is_contended;
|
||||||
read_pointers_[bank] = read - bank*16384;
|
read_pointers_[bank] = read - bank*16384;
|
||||||
write_pointers_[bank] = (write ? write : scratch_.data()) - bank*16384;
|
write_pointers_[bank] = (write ? write : scratch_.data()) - bank*16384;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user