diff --git a/Machines/Atari2600/Atari2600.cpp b/Machines/Atari2600/Atari2600.cpp index 2450d9889..3cd0d00be 100644 --- a/Machines/Atari2600/Atari2600.cpp +++ b/Machines/Atari2600/Atari2600.cpp @@ -24,7 +24,7 @@ Machine::Machine() : _piaDataValue{0xff, 0xff}, _tiaInputValue{0xff, 0xff} { - _crt = new Outputs::CRT(228, 262, 1, 2); + _crt = new Outputs::CRT(228, Outputs::CRT::DisplayType::NTSC60, 1, 2); memset(_collisions, 0xff, sizeof(_collisions)); set_reset_line(true); } @@ -37,7 +37,7 @@ Machine::~Machine() void Machine::switch_region() { - _crt->set_new_timing(228, 312); + _crt->set_new_display_type(228, Outputs::CRT::DisplayType::PAL50); } void Machine::get_output_pixel(uint8_t *pixel, int offset) diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 41089bcac..59bffe30d 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -26,7 +26,7 @@ Machine::Machine() : _audioOutputPosition(0), _audioOutputPositionError(0), _currentOutputLine(0), - _crt(Outputs::CRT(crt_cycles_per_line, 312, 1, 1)) + _crt(Outputs::CRT(crt_cycles_per_line, Outputs::CRT::DisplayType::PAL50, 1, 1)) { memset(_keyStates, 0, sizeof(_keyStates)); memset(_palette, 0xf, sizeof(_palette)); diff --git a/Outputs/CRT.cpp b/Outputs/CRT.cpp index 80558c48b..7a4bd9dc5 100644 --- a/Outputs/CRT.cpp +++ b/Outputs/CRT.cpp @@ -25,7 +25,7 @@ static const uint32_t kCRTFixedPointOffset = 0x04000000; #define kRetraceXMask 0x01 #define kRetraceYMask 0x02 -void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_display) +void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator) { const unsigned int syncCapacityLineChargeThreshold = 3; const unsigned int millisecondsHorizontalRetraceTime = 7; // source: Dictionary of Video and Television Technology, p. 234 @@ -62,9 +62,42 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di _beamWidth[c].x = (uint32_t)((sinf(angle) / halfLineWidth) * kCRTFixedPointRange); _beamWidth[c].y = (uint32_t)((cosf(angle) / halfLineWidth) * kCRTFixedPointRange); } + + // reset flywheel sync + _expected_next_hsync = _cycles_per_line; } -CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int number_of_buffers, ...) : +void CRT::set_new_display_type(unsigned int cycles_per_line, DisplayType displayType) +{ + switch(displayType) + { + case DisplayType::PAL50: + set_new_timing(cycles_per_line, 312, 1135, 4); + break; + + case DisplayType::NTSC60: + set_new_timing(cycles_per_line, 262, 545, 2); + break; + } +} + +void CRT::allocate_buffers(unsigned int number, va_list sizes) +{ + // generate buffers for signal storage as requested — format is + // number of buffers, size of buffer 1, size of buffer 2... + const uint16_t bufferWidth = 2048; + const uint16_t bufferHeight = 2048; + for(int frame = 0; frame < sizeof(_frame_builders) / sizeof(*_frame_builders); frame++) + { + va_list va; + va_copy(va, sizes); + _frame_builders[frame] = new CRTFrameBuilder(bufferWidth, bufferHeight, number, va); + va_end(va); + } + _current_frame_builder = _frame_builders[0]; +} + +CRT::CRT() : _next_scan(0), _frames_with_delegate(0), _frame_read_pointer(0), @@ -74,24 +107,26 @@ CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned _is_in_hsync(false), _is_in_vsync(false), _rasterPosition({.x = 0, .y = 0}) +{} + +CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator, unsigned int number_of_buffers, ...) : CRT() { - set_new_timing(cycles_per_line, height_of_display); + set_new_timing(cycles_per_line, height_of_display, colour_cycle_numerator, colour_cycle_denominator); - // generate buffers for signal storage as requested — format is - // number of buffers, size of buffer 1, size of buffer 2... - const uint16_t bufferWidth = 2048; - const uint16_t bufferHeight = 2048; - for(int frame = 0; frame < sizeof(_frame_builders) / sizeof(*_frame_builders); frame++) - { - va_list va; - va_start(va, number_of_buffers); - _frame_builders[frame] = new CRTFrameBuilder(bufferWidth, bufferHeight, number_of_buffers, va); - va_end(va); - } - _current_frame_builder = _frame_builders[0]; + va_list buffer_sizes; + va_start(buffer_sizes, number_of_buffers); + allocate_buffers(number_of_buffers, buffer_sizes); + va_end(buffer_sizes); +} - // reset flywheel sync - _expected_next_hsync = _cycles_per_line; +CRT::CRT(unsigned int cycles_per_line, DisplayType displayType, unsigned int number_of_buffers, ...) : CRT() +{ + set_new_display_type(cycles_per_line, displayType); + + va_list buffer_sizes; + va_start(buffer_sizes, number_of_buffers); + allocate_buffers(number_of_buffers, buffer_sizes); + va_end(buffer_sizes); } CRT::~CRT() diff --git a/Outputs/CRT.hpp b/Outputs/CRT.hpp index dd17d6b28..7b39c68fc 100644 --- a/Outputs/CRT.hpp +++ b/Outputs/CRT.hpp @@ -48,10 +48,17 @@ static const int kCRTNumberOfFrames = 4; class CRT { public: - CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int number_of_buffers, ...); + enum DisplayType { + PAL50, + NTSC60 + }; + + CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator, unsigned int number_of_buffers, ...); + CRT(unsigned int cycles_per_line, DisplayType displayType, unsigned int number_of_buffers, ...); ~CRT(); - void set_new_timing(unsigned int cycles_per_line, unsigned int height_of_display); + void set_new_timing(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator); + void set_new_display_type(unsigned int cycles_per_line, DisplayType displayType); /*! Output at the sync level. @@ -105,6 +112,9 @@ class CRT { uint8_t *get_write_target_for_buffer(int buffer); private: + CRT(); + void allocate_buffers(unsigned int number, va_list sizes); + // the incoming clock lengths will be multiplied by something to give at least 1000 // sample points per line unsigned int _time_multiplier;