mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Makes a genuine attempt at real line counting.
No output yet though.
This commit is contained in:
parent
90b8163d54
commit
60cf8486bb
@ -36,8 +36,13 @@ void Nick::write(uint16_t address, uint8_t value) {
|
||||
// Still a mystery to me: the exact meaning of the top two bits here. For now
|
||||
// just treat a 0 -> 1 transition of the MSB as a forced frame restart.
|
||||
if((value^line_parameter_control_) & value & 0x80) {
|
||||
// TODO: restart frame.
|
||||
printf("Should restart frame from %04x\n", line_parameter_base_);
|
||||
|
||||
// For now: just force this to be the final line of this mode block.
|
||||
// I'm unclear whether I should also reset the horizontal counter
|
||||
// (i.e. completely abandon current video phase).
|
||||
lines_remaining_ = 0xff;
|
||||
line_parameters_[1] |= 1;
|
||||
}
|
||||
line_parameter_control_ = value & 0xc0;
|
||||
break;
|
||||
@ -48,7 +53,58 @@ uint8_t Nick::read([[maybe_unused]] uint16_t address) {
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void Nick::run_for(HalfCycles) {
|
||||
void Nick::run_for(HalfCycles duration) {
|
||||
constexpr int line_length = 912;
|
||||
|
||||
int clocks_remaining = duration.as<int>();
|
||||
while(clocks_remaining) {
|
||||
// Determine how many cycles are left this line.
|
||||
const int clocks_this_line = std::min(clocks_remaining, line_length - horizontal_counter_);
|
||||
|
||||
// Convert that into a [start/current] and end window.
|
||||
int window = horizontal_counter_ >> 4;
|
||||
const int end_window = (horizontal_counter_ + clocks_this_line) >> 4;
|
||||
|
||||
// Advance the line counters.
|
||||
clocks_remaining -= clocks_this_line;
|
||||
horizontal_counter_ = (horizontal_counter_ + clocks_this_line) % line_length;
|
||||
|
||||
// Do nothing if a window boundary isn't crossed.
|
||||
if(window == end_window) continue;
|
||||
|
||||
// If this is within the first 8 cycles of the line, [possibly] fetch
|
||||
// the relevant part of the line parameters.
|
||||
if(should_reload_line_parameters_ && window < 8) {
|
||||
int fetch_spot = window;
|
||||
while(fetch_spot < end_window && fetch_spot < 8) {
|
||||
line_parameters_[(fetch_spot << 1)] = ram_[line_parameter_pointer_];
|
||||
line_parameters_[(fetch_spot << 1) + 1] = ram_[line_parameter_pointer_ + 1];
|
||||
line_parameter_pointer_ += 2;
|
||||
++fetch_spot;
|
||||
}
|
||||
|
||||
// If all parameters have been loaded, set appropriate fields.
|
||||
if(fetch_spot == 8) {
|
||||
should_reload_line_parameters_ = false;
|
||||
|
||||
// Set length of mode line.
|
||||
lines_remaining_ = line_parameters_[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Check for end of line.
|
||||
if(!horizontal_counter_) {
|
||||
++lines_remaining_;
|
||||
if(!lines_remaining_) {
|
||||
should_reload_line_parameters_ = true;
|
||||
|
||||
// Check for end-of-frame.
|
||||
if(line_parameters_[1] & 1) {
|
||||
line_parameter_pointer_ = line_parameter_base_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CRT passthroughs.
|
||||
|
@ -31,9 +31,18 @@ class Nick {
|
||||
Outputs::CRT::CRT crt_;
|
||||
const uint8_t *const ram_;
|
||||
|
||||
// CPU-provided state.
|
||||
uint8_t line_parameter_control_ = 0xc0;
|
||||
uint16_t line_parameter_base_ = 0x0000;
|
||||
|
||||
// Ephemerals, related to current video position.
|
||||
int horizontal_counter_ = 0;
|
||||
uint16_t line_parameter_pointer_ = 0x0000;
|
||||
uint8_t line_parameters_[16];
|
||||
bool should_reload_line_parameters_ = false;
|
||||
|
||||
// Current mode line parameters.
|
||||
uint8_t lines_remaining_ = 0x00;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user