mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-21 21:33:54 +00:00
Breaks up loop for arithmetic simplicity.
This commit is contained in:
parent
402eab10f8
commit
82205d71cc
@ -127,6 +127,8 @@ bool Chipset::Copper::advance(uint16_t position) {
|
||||
}
|
||||
|
||||
template <int cycle> void Chipset::output() {
|
||||
// Notes to self on guesses below:
|
||||
//
|
||||
// Hardware stop is at 0x18;
|
||||
// 12/64 * 227 = 42.5625
|
||||
//
|
||||
@ -242,6 +244,41 @@ template <int cycle, bool stop_if_cpu> bool Chipset::perform_cycle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <bool stop_on_cpu> int Chipset::advance_slots(int first_slot, int last_slot) {
|
||||
if(first_slot == last_slot) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define C(x) \
|
||||
case x: \
|
||||
if constexpr(stop_on_cpu) {\
|
||||
if(perform_cycle<x, stop_on_cpu>()) {\
|
||||
return x - first_slot;\
|
||||
}\
|
||||
} else {\
|
||||
perform_cycle<x, stop_on_cpu>(); \
|
||||
} \
|
||||
output<x>(); \
|
||||
if((x + 1) == last_slot) break; \
|
||||
[[fallthrough]]
|
||||
|
||||
#define C10(x) C(x); C(x+1); C(x+2); C(x+3); C(x+4); C(x+5); C(x+6); C(x+7); C(x+8); C(x+9);
|
||||
switch(first_slot) {
|
||||
C10(0); C10(10); C10(20); C10(30); C10(40);
|
||||
C10(50); C10(60); C10(70); C10(80); C10(90);
|
||||
C10(100); C10(110); C10(120); C10(130); C10(140);
|
||||
C10(150); C10(160); C10(170); C10(180); C10(190);
|
||||
C10(200); C10(210);
|
||||
C(220); C(221); C(222); C(223); C(224);
|
||||
C(225); C(226); C(227); C(228);
|
||||
|
||||
default: assert(false);
|
||||
}
|
||||
#undef C
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) {
|
||||
Changes changes;
|
||||
|
||||
@ -252,54 +289,19 @@ template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) {
|
||||
// Update raster position, spooling out graphics.
|
||||
while(pixels_remaining) {
|
||||
// Determine number of pixels left on this line.
|
||||
int line_pixels = std::min(pixels_remaining, (line_length_ * 4) - line_cycle_);
|
||||
const int line_pixels = std::min(pixels_remaining, (line_length_ * 4) - line_cycle_);
|
||||
|
||||
//
|
||||
// Run DMA scheduler.
|
||||
//
|
||||
const int start_slot = line_cycle_ >> 2;
|
||||
const int end_slot = (line_cycle_ + line_pixels) >> 2;
|
||||
const int actual_slots = advance_slots<stop_on_cpu>(start_slot, end_slot);
|
||||
|
||||
int final_slot = (line_cycle_ + line_pixels) >> 2;
|
||||
|
||||
if((line_cycle_ >> 2) == final_slot) {
|
||||
// Not enough pixels left to fill any whole slots, just stop.
|
||||
line_cycle_ += line_pixels;
|
||||
break;
|
||||
if(actual_slots >= 0) {
|
||||
// TODO: abbreviate run, prior to adding to totals below.
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// Advance to window boundary.
|
||||
const int distance_to_boundary = ((line_cycle_ - 1) & 3) ^ 3;
|
||||
line_pixels -= distance_to_boundary;
|
||||
pixels_remaining -= distance_to_boundary;
|
||||
line_cycle_ += distance_to_boundary;
|
||||
|
||||
#define C(x) \
|
||||
case x: \
|
||||
assert(!(line_cycle_&3)); \
|
||||
if constexpr(stop_on_cpu) {\
|
||||
if(perform_cycle<x, stop_on_cpu>()) {\
|
||||
break;\
|
||||
}\
|
||||
} else {\
|
||||
perform_cycle<x, stop_on_cpu>(); \
|
||||
} \
|
||||
output<x>(); \
|
||||
if((line_cycle_ >> 2) == final_slot) break; \
|
||||
line_cycle_ += 4; \
|
||||
pixels_remaining -= 4;
|
||||
|
||||
#define C10(x) C(x); C(x+1); C(x+2); C(x+3); C(x+4); C(x+5); C(x+6); C(x+7); C(x+8); C(x+9);
|
||||
switch(line_cycle_ >> 2) {
|
||||
C10(0); C10(10); C10(20); C10(30); C10(40);
|
||||
C10(50); C10(60); C10(70); C10(80); C10(90);
|
||||
C10(100); C10(110); C10(120); C10(130); C10(140);
|
||||
C10(150); C10(160); C10(170); C10(180); C10(190);
|
||||
C10(200); C10(210);
|
||||
C(220); C(221); C(222); C(223); C(224);
|
||||
C(225); C(226); C(227); C(228);
|
||||
|
||||
default: assert(false);
|
||||
}
|
||||
#undef C
|
||||
line_cycle_ += line_pixels;
|
||||
pixels_remaining -= line_pixels;
|
||||
|
||||
// Advance intraline counter and possibly ripple upwards into
|
||||
// lines and fields.
|
||||
@ -320,6 +322,7 @@ template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) {
|
||||
copper_.reload(0);
|
||||
}
|
||||
}
|
||||
assert(line_cycle_ < line_length_ * 4);
|
||||
}
|
||||
|
||||
changes.interrupt_level = interrupt_level_;
|
||||
|
@ -66,6 +66,7 @@ class Chipset {
|
||||
// MARK: - Scheduler.
|
||||
|
||||
template <bool stop_on_cpu> Changes run(HalfCycles duration = HalfCycles());
|
||||
template <bool stop_on_cpu> int advance_slots(int, int);
|
||||
template <int cycle, bool stop_if_cpu> bool perform_cycle();
|
||||
template <int cycle> void output();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user