mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +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;
|
||||
}
|
||||
|
||||
int access_delay() const {
|
||||
int access_delay(HalfCycles offset) const {
|
||||
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;
|
||||
if(lines >= 192) return 0;
|
||||
|
||||
|
@ -107,27 +107,36 @@ template<Model model> class ConcreteMachine:
|
||||
// MARK: - BusHandler
|
||||
|
||||
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.
|
||||
// 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;
|
||||
using PartialMachineCycle = CPU::Z80::PartialMachineCycle;
|
||||
switch(cycle.operation) {
|
||||
default: break;
|
||||
case PartialMachineCycle::ReadOpcode:
|
||||
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];
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
@ -211,9 +220,22 @@ template<Model model> class ConcreteMachine:
|
||||
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
|
||||
// HalfCycles get_typer_delay(const std::string &) const final {
|
||||
// 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_;
|
||||
const uint8_t *read_pointers_[4];
|
||||
uint8_t *write_pointers_[4];
|
||||
bool is_contended_[4];
|
||||
|
||||
uint8_t port1ffd_ = 0;
|
||||
uint8_t port7ffd_ = 0;
|
||||
@ -267,31 +290,31 @@ template<Model model> class ConcreteMachine:
|
||||
switch(port1ffd_ & 0x6) {
|
||||
default:
|
||||
case 0x00:
|
||||
set_memory(0, &ram_[0 * 16384], &ram_[0 * 16384]);
|
||||
set_memory(1, &ram_[1 * 16384], &ram_[1 * 16384]);
|
||||
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
|
||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
|
||||
set_memory(0, &ram_[0 * 16384], &ram_[0 * 16384], false);
|
||||
set_memory(1, &ram_[1 * 16384], &ram_[1 * 16384], false);
|
||||
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384], false);
|
||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
|
||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
|
||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
|
||||
set_memory(3, &ram_[7 * 16384], &ram_[7 * 16384]);
|
||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
||||
set_memory(3, &ram_[7 * 16384], &ram_[7 * 16384], true);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
|
||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
|
||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
|
||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
|
||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
|
||||
set_memory(1, &ram_[7 * 16384], &ram_[7 * 16384]);
|
||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
|
||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
|
||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
||||
set_memory(1, &ram_[7 * 16384], &ram_[7 * 16384], true);
|
||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -300,16 +323,17 @@ template<Model model> class ConcreteMachine:
|
||||
|
||||
// Apply standard 128kb-esque mapping (albeit with extra ROM to pick from).
|
||||
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(2, &ram_[2 * 16384], &ram_[2 * 16384]);
|
||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
||||
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384], false);
|
||||
|
||||
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;
|
||||
write_pointers_[bank] = (write ? write : scratch_.data()) - bank*16384;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user