1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-11 04:28:58 +00:00

Implements video position feedback.

At a substantial performance cost for now, but I'll worry about that once things are working.
This commit is contained in:
Thomas Harte 2019-05-08 16:54:19 -04:00
parent 0ad88508f7
commit 41740fb45e
3 changed files with 35 additions and 12 deletions

View File

@ -40,7 +40,7 @@ class ConcreteMachine:
mc68000_(*this), mc68000_(*this),
video_(ram_.data()), video_(ram_.data()),
via_(via_port_handler_), via_(via_port_handler_),
via_port_handler_(*this, clock_, keyboard_), via_port_handler_(*this, clock_, keyboard_, video_),
iwm_(CLOCK_RATE) { iwm_(CLOCK_RATE) {
// Grab a copy of the ROM and convert it into big-endian data. // Grab a copy of the ROM and convert it into big-endian data.
@ -70,7 +70,7 @@ class ConcreteMachine:
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;
time_since_iwm_update_ += cycle.length; time_since_iwm_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.
@ -100,6 +100,10 @@ class ConcreteMachine:
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?
mc68000_.set_interrupt_level( (via_.get_interrupt_line() ? 1 : 0) ); mc68000_.set_interrupt_level( (via_.get_interrupt_line() ? 1 : 0) );
@ -140,7 +144,8 @@ class ConcreteMachine:
default: default:
if(cycle.operation & Microcycle::Read) { if(cycle.operation & Microcycle::Read) {
cycle.value->halves.low = 0xff; printf("Unrecognised read %06x\n", *cycle.address & 0xffffff);
cycle.value->halves.low = 0x00;
if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff; if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
} }
break; break;
@ -211,7 +216,7 @@ class ConcreteMachine:
} }
void flush() { void flush() {
video_.run_for(time_since_video_update_.flush()); // video_.run_for(time_since_video_update_.flush());
} }
void set_rom_is_overlay(bool rom_is_overlay) { void set_rom_is_overlay(bool rom_is_overlay) {
@ -225,8 +230,8 @@ class ConcreteMachine:
private: private:
class VIAPortHandler: public MOS::MOS6522::PortHandler { class VIAPortHandler: public MOS::MOS6522::PortHandler {
public: public:
VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard) : VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, Video &video) :
machine_(machine), clock_(clock), keyboard_(keyboard) {} machine_(machine), clock_(clock), keyboard_(keyboard), video_(video) {}
using Port = MOS::MOS6522::Port; using Port = MOS::MOS6522::Port;
using Line = MOS::MOS6522::Line; using Line = MOS::MOS6522::Line;
@ -275,11 +280,13 @@ class ConcreteMachine:
switch(port) { switch(port) {
case Port::A: case Port::A:
// printf("6522 r A\n"); // printf("6522 r A\n");
return 0xff; return 0x00; // TODO: b7 = SCC wait/request
case Port::B: case Port::B:
// printf("6522 r B\n"); return
return (clock_.get_data() ? 0x02 : 0x00); (clock_.get_data() ? 0x02 : 0x00) |
(video_.is_outputting() ? 0x00 : 0x40);
// TODO: mouse button, y2, x2
} }
} }
@ -299,6 +306,7 @@ class ConcreteMachine:
ConcreteMachine &machine_; ConcreteMachine &machine_;
RealTimeClock &clock_; RealTimeClock &clock_;
Keyboard &keyboard_; Keyboard &keyboard_;
Video &video_;
}; };
std::array<uint16_t, 32*1024> rom_; std::array<uint16_t, 32*1024> rom_;
@ -318,7 +326,8 @@ class ConcreteMachine:
HalfCycles via_clock_; HalfCycles via_clock_;
HalfCycles real_time_clock_; HalfCycles real_time_clock_;
HalfCycles keyboard_clock_; HalfCycles keyboard_clock_;
HalfCycles time_since_video_update_; HalfCycles video_clock_;
// HalfCycles time_since_video_update_;
HalfCycles time_since_iwm_update_; HalfCycles time_since_iwm_update_;
bool ROM_is_overlay_ = true; bool ROM_is_overlay_ = true;

View File

@ -17,6 +17,8 @@ namespace {
const HalfCycles line_length(704); const HalfCycles line_length(704);
const int number_of_lines = 370; const int number_of_lines = 370;
const HalfCycles frame_length(line_length * HalfCycles(number_of_lines)); const HalfCycles frame_length(line_length * HalfCycles(number_of_lines));
const int sync_start = 36;
const int sync_end = 38;
} }
@ -44,8 +46,6 @@ void Video::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
} }
void Video::run_for(HalfCycles duration) { void Video::run_for(HalfCycles duration) {
const int sync_start = 36;
const int sync_end = 38;
// The number of HalfCycles is literally the number of pixel clocks to move through, // The number of HalfCycles is literally the number of pixel clocks to move through,
// since pixel output occurs at twice the processor clock. So divide by 16 to get // since pixel output occurs at twice the processor clock. So divide by 16 to get
@ -145,6 +145,18 @@ void Video::run_for(HalfCycles duration) {
} }
} }
bool Video::vsync() {
const int line = (frame_position_ / line_length).as_int();
return line >= 353 && line < 356;
}
bool Video::is_outputting() {
const int column = (frame_position_ % line_length).as_int() >> 4;
const int line = (frame_position_ / line_length).as_int();
return line < 342 && column < 32;
}
void Video::set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) { void Video::set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) {
use_alternate_screen_buffer_ = use_alternate_screen_buffer; use_alternate_screen_buffer_ = use_alternate_screen_buffer;
} }

View File

@ -23,6 +23,8 @@ class Video {
void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer); void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer);
// TODO: feedback on blanks and syncs. // TODO: feedback on blanks and syncs.
bool vsync();
bool is_outputting();
private: private:
Outputs::CRT::CRT crt_; Outputs::CRT::CRT crt_;