From a62c7f5c56a19d92d77009d2ecb1f6feb42ab1cd Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 18 Aug 2015 22:22:47 -0400 Subject: [PATCH] At last! Discovered CRT scanning bug; was always moving by the full proposed run length along the scan, not the time until the next event. Using this, have implemented proper vertical sync at last (I think). Have disabled scanline banding too, as now everything meets up it's more helpful to be able to see with clarity. --- OSBindings/Mac/Clock Signal/CSAtari2600.mm | 32 +++++++------------ .../Mac/Clock Signal/CSCathodeRayView.m | 2 +- Outputs/CRT.cpp | 22 ++++++------- 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/CSAtari2600.mm b/OSBindings/Mac/Clock Signal/CSAtari2600.mm index b20b1f040..98edbed40 100644 --- a/OSBindings/Mac/Clock Signal/CSAtari2600.mm +++ b/OSBindings/Mac/Clock Signal/CSAtari2600.mm @@ -30,7 +30,7 @@ typedef NS_ENUM(NSInteger, CSAtari2600RunningState) { dispatch_queue_t _serialDispatchQueue; int _frameCount; - NSTimeInterval _startTimeInterval; + int _hitCount; BOOL _didDecideRegion; NSConditionLock *_runningLock; @@ -40,28 +40,20 @@ typedef NS_ENUM(NSInteger, CSAtari2600RunningState) { if(!_didDecideRegion) { - if(_startTimeInterval < 1.0) - { - _startTimeInterval = [NSDate timeIntervalSinceReferenceDate]; - } - else - { - _frameCount++; + _frameCount++; + _hitCount += didDetectVSync ? 1 : 0; - if(_frameCount > 30) + if(_frameCount > 30) + { + if(_hitCount < _frameCount >> 1) { - float fps = (float)_frameCount / (float)([NSDate timeIntervalSinceReferenceDate] - _startTimeInterval); + _atari2600.switch_region(); + _didDecideRegion = YES; + } - if(fabsf(fps - 50.0f) < 5.0f) - { - _atari2600.switch_region(); - _didDecideRegion = YES; - } - - if(fabsf(fps - 60.0f) < 5.0f) - { - _didDecideRegion = YES; - } + if(_hitCount > (_frameCount * 7) >> 3) + { + _didDecideRegion = YES; } } } diff --git a/OSBindings/Mac/Clock Signal/CSCathodeRayView.m b/OSBindings/Mac/Clock Signal/CSCathodeRayView.m index ce0ebc03e..331324511 100644 --- a/OSBindings/Mac/Clock Signal/CSCathodeRayView.m +++ b/OSBindings/Mac/Clock Signal/CSCathodeRayView.m @@ -204,7 +204,7 @@ const char *fragmentShader = "\n" "void main(void)\n" "{\n" - "fragColour = texture(texID, srcCoordinatesVarying) * vec4(1.0, 1.0, 1.0, sin(lateralVarying));\n" // + "fragColour = texture(texID, srcCoordinatesVarying) * vec4(1.0, 1.0, 1.0, 1.0);\n" // .a = sin(lateralVarying) "}\n"; #if defined(DEBUG) diff --git a/Outputs/CRT.cpp b/Outputs/CRT.cpp index 9bd2a50fd..e327d6a49 100644 --- a/Outputs/CRT.cpp +++ b/Outputs/CRT.cpp @@ -28,7 +28,7 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di height_of_display += (height_of_display / 20); // this is the overrun area we'll use to // store fundamental display configuration properties - _height_of_display = height_of_display; + _height_of_display = height_of_display + 5; _cycles_per_line = cycles_per_line * _time_multiplier; // generate timing values implied by the given arbuments @@ -37,7 +37,7 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di _sync_capacitor_charge_threshold = ((syncCapacityLineChargeThreshold * _cycles_per_line) * 50) >> 7; _horizontal_retrace_time = (millisecondsHorizontalRetraceTime * _cycles_per_line) >> 6; const unsigned int vertical_retrace_time = scanlinesVerticalRetraceTime * _cycles_per_line; - const float halfLineWidth = (float)_height_of_display * 1.85f; + const float halfLineWidth = (float)_height_of_display * 2.0f; for(int c = 0; c < 4; c++) { @@ -103,7 +103,7 @@ CRT::SyncEvent CRT::get_next_vertical_sync_event(bool vsync_is_requested, unsign // will an acceptable vertical sync be triggered? if (vsync_is_requested && !_is_in_vsync) { - if (_sync_capacitor_charge_level >= _sync_capacitor_charge_threshold && _rasterPosition.y >= (kCRTFixedPointRange >> 1)) { + if (_sync_capacitor_charge_level >= _sync_capacitor_charge_threshold && _rasterPosition.y >= 3*(kCRTFixedPointRange >> 2)) { proposedSyncTime = 0; proposedEvent = SyncEvent::StartVSync; _did_detect_vsync = true; @@ -112,12 +112,12 @@ CRT::SyncEvent CRT::get_next_vertical_sync_event(bool vsync_is_requested, unsign // have we overrun the maximum permitted number of horizontal syncs for this frame? if (!_is_in_vsync) { -// unsigned int time_until_end_of_frame = (kCRTFixedPointRange - _rasterPosition.y) / _scanSpeed[0].y; -// -// if(time_until_end_of_frame < proposedSyncTime) { -// proposedSyncTime = time_until_end_of_frame; -// proposedEvent = SyncEvent::StartVSync; -// } + unsigned int time_until_end_of_frame = (kCRTFixedPointRange - _rasterPosition.y) / _scanSpeed[0].y; + + if(time_until_end_of_frame < proposedSyncTime) { + proposedSyncTime = time_until_end_of_frame; + proposedEvent = SyncEvent::StartVSync; + } } else { unsigned int time_until_start_of_frame = _rasterPosition.y / (uint32_t)(-_scanSpeed[kRetraceYMask].y); @@ -217,8 +217,8 @@ void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bo // advance the raster position as dictated by current sync status int64_t end_position[2]; - end_position[0] = (int64_t)_rasterPosition.x + (int64_t)number_of_cycles * (int32_t)_scanSpeed[lengthMask].x; - end_position[1] = (int64_t)_rasterPosition.y + (int64_t)number_of_cycles * (int32_t)_scanSpeed[lengthMask].y; + end_position[0] = (int64_t)_rasterPosition.x + (int64_t)next_run_length * (int32_t)_scanSpeed[lengthMask].x; + end_position[1] = (int64_t)_rasterPosition.y + (int64_t)next_run_length * (int32_t)_scanSpeed[lengthMask].y; if (_is_in_hsync) _rasterPosition.x = (uint32_t)std::max((int64_t)0, end_position[0]);