1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-29 15:29:36 +00:00

Explicitly separated vertical and horizontal sync event tracking, so as explicitly to be able to handle a coincidental simultaneous occurrence of both. Also for clarity.

This commit is contained in:
Thomas Harte 2015-07-23 18:53:18 -04:00
parent 529f61caa1
commit 33c06baffa
2 changed files with 93 additions and 70 deletions

View File

@ -75,17 +75,8 @@ CRT::~CRT()
#pragma mark - Sync loop #pragma mark - Sync loop
CRT::SyncEvent CRT::advance_to_next_sync_event(bool hsync_is_requested, bool vsync_is_charging, int cycles_to_run_for, int *cycles_advanced) CRT::SyncEvent CRT::next_vertical_sync_event(bool vsync_is_charging, int cycles_to_run_for, int *cycles_advanced)
{ {
// do we recognise this hsync, thereby adjusting time expectations?
if ((_horizontal_counter < _hsync_error_window || _horizontal_counter >= _expected_next_hsync - _hsync_error_window) && hsync_is_requested) {
_did_detect_hsync = true;
int time_now = (_horizontal_counter < _hsync_error_window) ? _expected_next_hsync + _horizontal_counter : _horizontal_counter;
_expected_next_hsync = (_expected_next_hsync + time_now) >> 1;
// printf("to %d for %d\n", _expected_next_hsync, time_now);
}
SyncEvent proposedEvent = SyncEvent::None; SyncEvent proposedEvent = SyncEvent::None;
int proposedSyncTime = cycles_to_run_for; int proposedSyncTime = cycles_to_run_for;
@ -99,18 +90,6 @@ CRT::SyncEvent CRT::advance_to_next_sync_event(bool hsync_is_requested, bool vsy
} }
} }
// will we end an ongoing hsync?
if (_horizontal_counter < _horizontal_retrace_time && _horizontal_counter+proposedSyncTime >= _horizontal_retrace_time) {
proposedSyncTime = _horizontal_retrace_time - _horizontal_counter;
proposedEvent = SyncEvent::EndHSync;
}
// will we start an hsync?
if (_horizontal_counter + proposedSyncTime >= _expected_next_hsync) {
proposedSyncTime = _expected_next_hsync - _horizontal_counter;
proposedEvent = SyncEvent::StartHSync;
}
// will an acceptable vertical sync be triggered? // will an acceptable vertical sync be triggered?
if (vsync_is_charging && !_vretrace_counter) { if (vsync_is_charging && !_vretrace_counter) {
if (_sync_capacitor_charge_level < _sync_capacitor_charge_threshold && _sync_capacitor_charge_level + proposedSyncTime >= _sync_capacitor_charge_threshold) { if (_sync_capacitor_charge_level < _sync_capacitor_charge_threshold && _sync_capacitor_charge_level + proposedSyncTime >= _sync_capacitor_charge_threshold) {
@ -131,6 +110,35 @@ CRT::SyncEvent CRT::advance_to_next_sync_event(bool hsync_is_requested, bool vsy
return proposedEvent; return proposedEvent;
} }
CRT::SyncEvent CRT::next_horizontal_sync_event(bool hsync_is_requested, int cycles_to_run_for, int *cycles_advanced)
{
// do we recognise this hsync, thereby adjusting future time expectations?
if ((_horizontal_counter < _hsync_error_window || _horizontal_counter >= _expected_next_hsync - _hsync_error_window) && hsync_is_requested) {
_did_detect_hsync = true;
int time_now = (_horizontal_counter < _hsync_error_window) ? _expected_next_hsync + _horizontal_counter : _horizontal_counter;
_expected_next_hsync = (_expected_next_hsync + time_now) >> 1;
}
SyncEvent proposedEvent = SyncEvent::None;
int proposedSyncTime = cycles_to_run_for;
// will we end an ongoing hsync?
if (_horizontal_counter < _horizontal_retrace_time && _horizontal_counter+proposedSyncTime >= _horizontal_retrace_time) {
proposedSyncTime = _horizontal_retrace_time - _horizontal_counter;
proposedEvent = SyncEvent::EndHSync;
}
// will we start an hsync?
if (_horizontal_counter + proposedSyncTime >= _expected_next_hsync) {
proposedSyncTime = _expected_next_hsync - _horizontal_counter;
proposedEvent = SyncEvent::StartHSync;
}
*cycles_advanced = proposedSyncTime;
return proposedEvent;
}
void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool vsync_charging, const CRTRun::Type type, const char *data_type) void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool vsync_charging, const CRTRun::Type type, const char *data_type)
{ {
// this is safe to keep locally because it accumulates over this run of cycles only // this is safe to keep locally because it accumulates over this run of cycles only
@ -138,16 +146,19 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool
while(number_of_cycles) { while(number_of_cycles) {
// get the next sync event and its timing; hsync request is instantaneous (being edge triggered) so int time_until_vertical_sync_event, time_until_horizontal_sync_event;
// set it to false for the next run through this loop (if any) SyncEvent next_vertical_sync_event = this->next_vertical_sync_event(vsync_charging, number_of_cycles, &time_until_vertical_sync_event);
int next_run_length; SyncEvent next_horizontal_sync_event = this->next_horizontal_sync_event(hsync_requested, time_until_vertical_sync_event, &time_until_horizontal_sync_event);
SyncEvent next_event = advance_to_next_sync_event(hsync_requested, vsync_charging, number_of_cycles, &next_run_length);
hsync_requested = false; hsync_requested = false;
if(_current_frame) // get the next sync event and its timing; hsync request is instantaneous (being edge triggered) so
{ // set it to false for the next run through this loop (if any)
CRTRun *nextRun = _current_frame->get_next_run(); int next_run_length = std::min(time_until_vertical_sync_event, time_until_horizontal_sync_event);
CRTRun *nextRun = (_current_frame && next_run_length) ? _current_frame->get_next_run() : nullptr;
if(nextRun)
{
// set the type, initial raster position and type of this run // set the type, initial raster position and type of this run
nextRun->type = type; nextRun->type = type;
nextRun->start_point.dst_x = _rasterPosition.x; nextRun->start_point.dst_x = _rasterPosition.x;
@ -205,8 +216,10 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool
_vretrace_counter = std::max(_vretrace_counter - next_run_length, 0); _vretrace_counter = std::max(_vretrace_counter - next_run_length, 0);
// react to the incoming event... // react to the incoming event...
switch(next_event) { if(next_run_length == time_until_horizontal_sync_event)
{
switch(next_horizontal_sync_event)
{
// start of hsync: zero the scanline counter, note that we're now in // start of hsync: zero the scanline counter, note that we're now in
// horizontal sync, increment the lines-in-this-frame counter // horizontal sync, increment the lines-in-this-frame counter
case SyncEvent::StartHSync: case SyncEvent::StartHSync:
@ -224,6 +237,14 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool
_is_in_hsync = false; _is_in_hsync = false;
break; break;
default: break;
}
}
if(next_run_length == time_until_vertical_sync_event)
{
switch(next_vertical_sync_event)
{
// start of vertical sync: reset the lines-in-this-frame counter, // start of vertical sync: reset the lines-in-this-frame counter,
// load the retrace counter with the amount of time it'll take to retrace // load the retrace counter with the amount of time it'll take to retrace
case SyncEvent::StartVSync: case SyncEvent::StartVSync:
@ -253,6 +274,7 @@ void CRT::advance_cycles(int number_of_cycles, bool hsync_requested, const bool
default: break; default: break;
} }
} }
}
} }
void CRT::return_frame() void CRT::return_frame()

View File

@ -132,7 +132,8 @@ class CRT {
StartHSync, EndHSync, StartHSync, EndHSync,
StartVSync, EndVSync StartVSync, EndVSync
}; };
SyncEvent advance_to_next_sync_event(bool hsync_is_requested, bool vsync_is_charging, int cycles_to_run_for, int *cycles_advanced); SyncEvent next_vertical_sync_event(bool vsync_is_charging, int cycles_to_run_for, int *cycles_advanced);
SyncEvent next_horizontal_sync_event(bool hsync_is_requested, int cycles_to_run_for, int *cycles_advanced);
}; };
} }