1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Restores just-in-time processing of video.

This commit is contained in:
Thomas Harte 2019-07-09 18:08:07 -04:00
parent ab14433151
commit b4a3f66773

View File

@ -137,13 +137,36 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
using Microcycle = CPU::MC68000::Microcycle; using Microcycle = CPU::MC68000::Microcycle;
HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) { HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
// time_since_video_update_ += cycle.length; time_since_video_update_ += cycle.length;
iwm_.time_since_update += cycle.length; iwm_.time_since_update += cycle.length;
// The VIA runs at one-tenth of the 68000's clock speed, in sync with the E clock. // The VIA runs at one-tenth of the 68000's clock speed, in sync with the E clock.
// See: Guide to the Macintosh Hardware Family p149 (PDF p188). // See: Guide to the Macintosh Hardware Family p149 (PDF p188). Some extra division
via_clock_ += cycle.length; // may occur here in order to provide VSYNC at a proper moment.
via_.run_for(via_clock_.divide(HalfCycles(10))); // Possibly route vsync.
if(time_until_video_event_ >= cycle.length) {
via_clock_ += cycle.length;
via_.run_for(via_clock_.divide(HalfCycles(10)));
time_until_video_event_ -= cycle.length;
} else {
auto cycles_to_progress = cycle.length;
while(time_until_video_event_ < cycles_to_progress) {
cycles_to_progress -= time_until_video_event_;
via_clock_ += time_until_video_event_;
via_.run_for(via_clock_.divide(HalfCycles(10)));
video_.run_for(time_until_video_event_);
time_since_video_update_ -= time_until_video_event_;
time_until_video_event_ = video_.get_next_sequence_point();
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !video_.vsync());
}
via_clock_ += cycles_to_progress;
via_.run_for(via_clock_.divide(HalfCycles(10)));
time_until_video_event_ -= cycles_to_progress;
}
// The keyboard also has a clock, albeit a very slow one — 100,000 cycles/second. // The keyboard also has a clock, albeit a very slow one — 100,000 cycles/second.
// Its clock and data lines are connected to the VIA. // Its clock and data lines are connected to the VIA.
@ -177,10 +200,6 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two, false); via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two, false);
} }
// Update the video. TODO: only on demand.
video_.run_for(cycle.length);
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !video_.vsync());
// Update interrupt input. TODO: move this into a VIA/etc delegate callback? // Update interrupt input. TODO: move this into a VIA/etc delegate callback?
// Double TODO: does this really cascade like this? // Double TODO: does this really cascade like this?
if(scc_.get_interrupt_line()) { if(scc_.get_interrupt_line()) {
@ -292,6 +311,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
) { ) {
memory_base = ram_; memory_base = ram_;
word_address &= ram_mask_; word_address &= ram_mask_;
update_video();
} else { } else {
memory_base = rom_; memory_base = rom_;
word_address &= rom_mask_; word_address &= rom_mask_;
@ -371,7 +391,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// video is responsible for providing part of the // video is responsible for providing part of the
// audio signal, so the two aren't as distinct as in // audio signal, so the two aren't as distinct as in
// most machines. // most machines.
// video_.run_for(time_since_video_update_.flush()); update_video();
// As above: flush audio after video. // As above: flush audio after video.
via_.flush(); via_.flush();
@ -385,6 +405,10 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
ROM_is_overlay_ = rom_is_overlay; ROM_is_overlay_ = rom_is_overlay;
} }
bool video_is_outputting() {
return video_.is_outputting(time_since_video_update_);
}
void set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer) { void set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer) {
video_.set_use_alternate_buffers(use_alternate_screen_buffer, use_alternate_audio_buffer); video_.set_use_alternate_buffers(use_alternate_screen_buffer, use_alternate_audio_buffer);
} }
@ -414,6 +438,11 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// TODO: clear all keys. // TODO: clear all keys.
private: private:
void update_video() {
video_.run_for(time_since_video_update_.flush());
time_until_video_event_ = video_.get_next_sequence_point();
}
Inputs::Mouse &get_mouse() override { Inputs::Mouse &get_mouse() override {
return mouse_; return mouse_;
} }
@ -496,7 +525,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
((mouse_.get_channel(0) & 2) << 3) | ((mouse_.get_channel(0) & 2) << 3) |
((mouse_.get_channel(1) & 2) << 4) | ((mouse_.get_channel(1) & 2) << 4) |
(clock_.get_data() ? 0x02 : 0x00) | (clock_.get_data() ? 0x02 : 0x00) |
(video_.is_outputting() ? 0x00 : 0x40) (machine_.video_is_outputting() ? 0x00 : 0x40)
); );
} }
@ -556,8 +585,8 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
HalfCycles via_clock_; HalfCycles via_clock_;
HalfCycles real_time_clock_; HalfCycles real_time_clock_;
HalfCycles keyboard_clock_; HalfCycles keyboard_clock_;
HalfCycles video_clock_; HalfCycles time_since_video_update_;
// HalfCycles time_since_video_update_; HalfCycles time_until_video_event_;
HalfCycles time_since_iwm_update_; HalfCycles time_since_iwm_update_;
HalfCycles time_since_mouse_update_; HalfCycles time_since_mouse_update_;