mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-15 11:32:29 +00:00
Begins addition of interrupt feedback from Nick.
Also fixes clock rate. Though clearly get_next_sequence_point isn't quite right yet.
This commit is contained in:
parent
0c3e9dca28
commit
2fd8a8aa66
@ -94,13 +94,26 @@ class ConcreteMachine:
|
||||
page<3>(0x00);
|
||||
}
|
||||
|
||||
int halves = 0;
|
||||
|
||||
// MARK: - Z80::BusHandler.
|
||||
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
||||
using PartialMachineCycle = CPU::Z80::PartialMachineCycle;
|
||||
const uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||
|
||||
// TODO: possibly apply an access penalty.
|
||||
nick_ += cycle.length;
|
||||
|
||||
|
||||
halves += cycle.length.as<int>();
|
||||
if(nick_ += cycle.length) {
|
||||
const auto nick = nick_.last_valid();
|
||||
const bool nick_interrupt_line = nick->get_interrupt_line();
|
||||
if(nick_interrupt_line && !previous_nick_interrupt_line_) {
|
||||
printf("Interrupt after %d\n", halves + nick_.last_sequence_point_overrun().as<int>());
|
||||
halves = - nick_.last_sequence_point_overrun().as<int>();
|
||||
}
|
||||
previous_nick_interrupt_line_ = nick_interrupt_line;
|
||||
}
|
||||
|
||||
switch(cycle.operation) {
|
||||
default: break;
|
||||
@ -270,6 +283,7 @@ class ConcreteMachine:
|
||||
// MARK: - Chips.
|
||||
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
|
||||
JustInTimeActor<Nick, HalfCycles, 444923, 125000> nick_;
|
||||
bool previous_nick_interrupt_line_ = false;
|
||||
// Cf. timing guesses above.
|
||||
};
|
||||
|
||||
|
@ -82,7 +82,7 @@ uint8_t Nick::read([[maybe_unused]] uint16_t address) {
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void Nick::run_for(HalfCycles duration) {
|
||||
void Nick::run_for(Cycles duration) {
|
||||
constexpr int line_length = 912;
|
||||
|
||||
int clocks_remaining = duration.as<int>();
|
||||
@ -112,8 +112,13 @@ void Nick::run_for(HalfCycles duration) {
|
||||
++fetch_spot;
|
||||
}
|
||||
|
||||
// TODO: when exactly does the interrupt output change? Am I a window too late? Or two too early?
|
||||
|
||||
// Special: set mode as soon as it's known. It'll be needed at the end of HSYNC.
|
||||
if(window < 2 && fetch_spot >= 2) {
|
||||
// Set the new interrupt line output.
|
||||
interrupt_line_ = line_parameters_[1] & 0x80;
|
||||
|
||||
// Determine the margins.
|
||||
left_margin_ = line_parameters_[2] & 0x3f;
|
||||
right_margin_ = line_parameters_[3] & 0x3f;
|
||||
@ -326,6 +331,22 @@ void Nick::flush_pixels() {
|
||||
allocated_pointer_ = nullptr;
|
||||
}
|
||||
|
||||
// MARK: - Sequence points.
|
||||
|
||||
Cycles Nick::get_next_sequence_point() {
|
||||
// TODO: the below is incorrect; unit test and correct.
|
||||
// Changing to e.g. Cycles(1) reveals the relevant discrepancy.
|
||||
// return Cycles(1);
|
||||
|
||||
// Any mode line may cause a change in the interrupt output, so as a first blush
|
||||
// just always report the time until the end of the mode line.
|
||||
if(lines_remaining_ || horizontal_counter_ >= 2) {
|
||||
return Cycles(2 + (912 - horizontal_counter_) + (0xff - lines_remaining_) * 912);
|
||||
} else {
|
||||
return Cycles(2 - horizontal_counter_);
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CRT passthroughs.
|
||||
|
||||
void Nick::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
|
||||
|
@ -22,11 +22,21 @@ class Nick {
|
||||
void write(uint16_t address, uint8_t value);
|
||||
uint8_t read(uint16_t address);
|
||||
|
||||
void run_for(HalfCycles);
|
||||
void run_for(Cycles);
|
||||
|
||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
|
||||
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
||||
|
||||
Cycles get_next_sequence_point();
|
||||
|
||||
/*!
|
||||
@returns The current state of the interrupt line — @c true for active;
|
||||
@c false for inactive.
|
||||
*/
|
||||
inline bool get_interrupt_line() {
|
||||
return interrupt_line_;
|
||||
}
|
||||
|
||||
private:
|
||||
Outputs::CRT::CRT crt_;
|
||||
const uint8_t *const ram_;
|
||||
@ -64,6 +74,7 @@ class Nick {
|
||||
} state_ = State::Sync;
|
||||
int bpp_ = 0;
|
||||
int column_size_ = 0;
|
||||
bool interrupt_line_ = true;
|
||||
|
||||
// An accumulator for border output regions.
|
||||
int border_duration_ = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user