1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-11 08:30:55 +00:00

Adds notes to self; implements get_next_sequence_point for video, allowing per-line interrupts.

This commit is contained in:
Thomas Harte 2020-11-16 14:42:50 -05:00
parent 7e39550fc0
commit 9206ab5dc3
4 changed files with 26 additions and 2 deletions

View File

@ -50,11 +50,13 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
/// Flushes all accumulated time and returns a pointer to the included object.
forceinline T *operator->() {
flush();
// TODO: I actually need to update time_until_event_ after the access occurring here has ended.
// So I guess I need to supply some sort of proxy object and jump on its destructor?
return &object_;
}
/// Acts exactly as per the standard ->, but preserves constness.
forceinline const T *operator->() const {
forceinline const T *operator -> () const {
auto non_const_this = const_cast<JustInTimeActor<T, multiplier, divider, LocalTimeScale, TargetTimeScale> *>(this);
non_const_this->flush();
return &object_;
@ -78,6 +80,7 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
object_.run_for(duration);
}
// TODO: this probably shouldn't be per-flush(), merely per-operator-> and when a previous point is passed.
if constexpr (has_sequence_points<T>::value) {
time_until_event_ = object_.get_next_sequence_point();
assert(time_until_event_ > LocalTimeScale(0));

View File

@ -685,6 +685,8 @@ class ConcreteMachine:
while(ticks--) {
clock_.update();
video_.last_valid()->notify_clock_tick(); // The video controller marshalls the one-second interrupt.
// TODO: I think I may have made a false assumption here; does
// the VGC have an independent 1-second interrupt?
update_interrupts();
}

View File

@ -104,6 +104,21 @@ void VideoBase::advance(Cycles cycles) {
}
}
Cycles VideoBase::get_next_sequence_point() const {
const int cycles_into_row = cycles_into_frame_ % CyclesPerLine;
const int row = cycles_into_frame_ / CyclesPerLine;
constexpr int sequence_point_offset = (5 + 8) * CyclesPerTick;
// Handle every case that doesn't involve wrapping to the next row 0.
if(row <= 200) {
if(cycles_into_row < sequence_point_offset) return Cycles(sequence_point_offset - cycles_into_row);
if(row < 200) return Cycles(CyclesPerLine + sequence_point_offset - cycles_into_row);
}
return Cycles(CyclesPerLine + sequence_point_offset - cycles_into_row + (Lines - row - 1)*CyclesPerLine);
}
void VideoBase::output_row(int row, int start, int end) {
// Reasoned guesswork ahoy!
//
@ -192,7 +207,8 @@ void VideoBase::output_row(int row, int start, int end) {
palette_[c] = PaletteConvulve(entry);
}
// TODO: obey line_control_ & 0x40 interrupt control bit.
// Post an interrupt if requested.
if(line_control_ & 0x40) set_interrupts(0x20);
}
if(next_pixel_) {

View File

@ -56,6 +56,9 @@ class VideoBase: public Apple::II::VideoSwitches<Cycles> {
/// Gets the type of output.
Outputs::Display::DisplayType get_display_type() const;
/// Determines the period until video might autonomously update its interrupt lines.
Cycles get_next_sequence_point() const;
private:
Outputs::CRT::CRT crt_;