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:
parent
529f61caa1
commit
33c06baffa
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user