1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-28 21:49:27 +00:00

This field is counted in half-cycles.

This commit is contained in:
Thomas Harte 2021-04-26 21:20:32 -04:00
parent 7fb3048257
commit 708c24cc57
2 changed files with 17 additions and 19 deletions

View File

@ -54,7 +54,7 @@ template <Timing timing> class Video {
private: private:
struct Timings { struct Timings {
// Number of cycles per line. Will be 224 or 228. // Number of cycles per line. Will be 224 or 228.
int cycles_per_line; int half_cycles_per_line;
// Number of lines comprising a whole frame. Will be 311 or 312. // Number of lines comprising a whole frame. Will be 311 or 312.
int lines_per_frame; int lines_per_frame;
@ -71,7 +71,7 @@ template <Timing timing> class Video {
int delays[8]; int delays[8];
constexpr Timings(int cycles_per_line, int lines_per_frame, int contention_leadin, int contention_duration, int interrupt_offset, const int *delays) noexcept : constexpr Timings(int cycles_per_line, int lines_per_frame, int contention_leadin, int contention_duration, int interrupt_offset, const int *delays) noexcept :
cycles_per_line(cycles_per_line * 2), half_cycles_per_line(cycles_per_line * 2),
lines_per_frame(lines_per_frame), lines_per_frame(lines_per_frame),
contention_leadin(contention_leadin * 2), contention_leadin(contention_leadin * 2),
contention_duration(contention_duration * 2), contention_duration(contention_duration * 2),
@ -104,7 +104,7 @@ template <Timing timing> class Video {
void run_for(HalfCycles duration) { void run_for(HalfCycles duration) {
constexpr auto timings = get_timings(); constexpr auto timings = get_timings();
constexpr int sync_line = (timings.interrupt_time / timings.cycles_per_line) + 1; constexpr int sync_line = (timings.interrupt_time / timings.half_cycles_per_line) + 1;
constexpr int sync_position = (timing == Timing::FortyEightK) ? 164 * 2 : 166 * 2; constexpr int sync_position = (timing == Timing::FortyEightK) ? 164 * 2 : 166 * 2;
constexpr int sync_length = 17 * 2; constexpr int sync_length = 17 * 2;
@ -113,9 +113,9 @@ template <Timing timing> class Video {
int cycles_remaining = duration.as<int>(); int cycles_remaining = duration.as<int>();
while(cycles_remaining) { while(cycles_remaining) {
int line = time_into_frame_ / timings.cycles_per_line; int line = time_into_frame_ / timings.half_cycles_per_line;
int offset = time_into_frame_ % timings.cycles_per_line; int offset = time_into_frame_ % timings.half_cycles_per_line;
const int cycles_this_line = std::min(cycles_remaining, timings.cycles_per_line - offset); const int cycles_this_line = std::min(cycles_remaining, timings.half_cycles_per_line - offset);
const int end_offset = offset + cycles_this_line; const int end_offset = offset + cycles_this_line;
if(!offset) { if(!offset) {
@ -239,7 +239,7 @@ template <Timing timing> class Video {
} }
cycles_remaining -= cycles_this_line; cycles_remaining -= cycles_this_line;
time_into_frame_ = (time_into_frame_ + cycles_this_line) % (timings.cycles_per_line * timings.lines_per_frame); time_into_frame_ = (time_into_frame_ + cycles_this_line) % (timings.half_cycles_per_line * timings.lines_per_frame);
} }
} }
@ -264,7 +264,7 @@ template <Timing timing> class Video {
static constexpr HalfCycles frame_duration() { static constexpr HalfCycles frame_duration() {
const auto timings = get_timings(); const auto timings = get_timings();
return HalfCycles(timings.cycles_per_line * timings.lines_per_frame); return HalfCycles(timings.half_cycles_per_line * timings.lines_per_frame);
} }
HalfCycles time_since_interrupt() { HalfCycles time_since_interrupt() {
@ -307,7 +307,7 @@ template <Timing timing> class Video {
// //
// TODO: this is coupled to an assumption about the initial CRT. Fix. // TODO: this is coupled to an assumption about the initial CRT. Fix.
const auto timings = get_timings(); const auto timings = get_timings();
crt_.output_blank(timings.lines_per_frame*timings.cycles_per_line - timings.interrupt_time); crt_.output_blank(timings.lines_per_frame*timings.half_cycles_per_line - timings.interrupt_time);
} }
void set_video_source(const uint8_t *source) { void set_video_source(const uint8_t *source) {
@ -331,7 +331,7 @@ template <Timing timing> class Video {
} }
// If not, it'll be in the next batch. // If not, it'll be in the next batch.
return timings.interrupt_time + timings.cycles_per_line * timings.lines_per_frame - time_into_frame_; return timings.interrupt_time + timings.half_cycles_per_line * timings.lines_per_frame - time_into_frame_;
} }
/*! /*!
@ -348,15 +348,15 @@ template <Timing timing> class Video {
*/ */
HalfCycles access_delay(HalfCycles offset) const { HalfCycles access_delay(HalfCycles offset) const {
constexpr auto timings = get_timings(); constexpr auto timings = get_timings();
const int delay_time = (time_into_frame_ + offset.as<int>() + timings.contention_leadin) % (timings.cycles_per_line * timings.lines_per_frame); const int delay_time = (time_into_frame_ + offset.as<int>() + timings.contention_leadin) % (timings.half_cycles_per_line * timings.lines_per_frame);
assert(!(delay_time&1)); assert(!(delay_time&1));
// Check for a time within the no-contention window. // Check for a time within the no-contention window.
if(delay_time >= (191*timings.cycles_per_line + timings.contention_duration)) { if(delay_time >= (191*timings.half_cycles_per_line + timings.contention_duration)) {
return 0; return 0;
} }
const int time_into_line = delay_time % timings.cycles_per_line; const int time_into_line = delay_time % timings.half_cycles_per_line;
if(time_into_line >= timings.contention_duration) { if(time_into_line >= timings.contention_duration) {
return 0; return 0;
} }
@ -371,12 +371,12 @@ template <Timing timing> class Video {
constexpr auto timings = get_timings(); constexpr auto timings = get_timings();
const uint8_t out_of_bounds = (timing == Timing::Plus3) ? last_contended_access_ : 0xff; const uint8_t out_of_bounds = (timing == Timing::Plus3) ? last_contended_access_ : 0xff;
const int line = time_into_frame_ / timings.cycles_per_line; const int line = time_into_frame_ / timings.half_cycles_per_line;
if(line >= 192) { if(line >= 192) {
return out_of_bounds; return out_of_bounds;
} }
const int time_into_line = time_into_frame_ % timings.cycles_per_line; const int time_into_line = time_into_frame_ % timings.half_cycles_per_line;
if(time_into_line >= 256 || (time_into_line&8)) { if(time_into_line >= 256 || (time_into_line&8)) {
return out_of_bounds; return out_of_bounds;
} }

View File

@ -148,18 +148,16 @@ std::unique_ptr<Analyser::Static::Target> Z80::load(const std::string &file_name
// More Z80, the emulator, lack of encapsulation to deal with here. // More Z80, the emulator, lack of encapsulation to deal with here.
const uint16_t low_t_state = file.get16le(); const uint16_t low_t_state = file.get16le();
const uint16_t high_t_state = file.get8(); const uint16_t high_t_state = file.get8();
int time_since_interrupt;
switch(result->model) { switch(result->model) {
case Target::Model::SixteenK: case Target::Model::SixteenK:
case Target::Model::FortyEightK: case Target::Model::FortyEightK:
time_since_interrupt = (17471 - low_t_state) + (high_t_state * 17472); state->video.half_cycles_since_interrupt = ((17471 - low_t_state) + (high_t_state * 17472)) * 2;
break; break;
default: default:
time_since_interrupt = (17726 - low_t_state) + (high_t_state * 17727); state->video.half_cycles_since_interrupt = ((17726 - low_t_state) + (high_t_state * 17727)) * 2;
break; break;
} }
// TODO: map time_since_interrupt to time_into_frame, somehow.
// Skip: Spectator flag, MGT, Multiface and other ROM flags. // Skip: Spectator flag, MGT, Multiface and other ROM flags.
file.seek(5, SEEK_CUR); file.seek(5, SEEK_CUR);