diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index ea0b78ea6..4aa54eb86 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -66,9 +66,9 @@ void CRT::allocate_buffers(unsigned int number, va_list sizes) _run_builders = new CRTRunBuilder *[kCRTNumberOfFields]; for(int builder = 0; builder < kCRTNumberOfFields; builder++) { - _run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize, 6); + _run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize); } - _composite_src_runs = std::unique_ptr(new CRTRunBuilder(kCRTInputVertexSize, 2)); + _composite_src_runs = std::unique_ptr(new CRTRunBuilder(kCRTInputVertexSize)); va_list va; va_copy(va, sizes); @@ -84,7 +84,8 @@ CRT::CRT(unsigned int common_output_divisor) : _visible_area(Rect(0, 0, 1, 1)), _sync_period(0), _common_output_divisor(common_output_divisor), - _composite_src_output_y(0) + _composite_src_output_y(0), + _is_writing_composite_run(false) { construct_openGL(); } @@ -170,28 +171,28 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi if(is_output_segment) { _output_mutex->lock(); - next_run = (_output_device == CRT::Monitor) ? _run_builders[_run_write_pointer]->get_next_run() : _composite_src_runs->get_next_run(); + next_run = (_output_device == CRT::Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2); } - // Vertex output is arranged as: + // Vertex output is arranged for triangle strips, as: // - // [0/4] 3 + // 2 [4/5] // - // 1 [2/5] + // [0/1] 3 if(next_run) { if(_output_device == CRT::Monitor) { // set the type, initial raster position and type of this run - output_position_x(0) = output_position_x(1) = output_position_x(4) = (uint16_t)_horizontal_flywheel->get_current_output_position(); - output_position_y(0) = output_position_y(1) = output_position_y(4) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider); - output_timestamp(0) = output_timestamp(1) = output_timestamp(4) = _run_builders[_run_write_pointer]->duration; - output_tex_x(0) = output_tex_x(1) = output_tex_x(4) = tex_x; + output_position_x(0) = output_position_x(1) = output_position_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position(); + output_position_y(0) = output_position_y(1) = output_position_y(2) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider); + output_timestamp(0) = output_timestamp(1) = output_timestamp(2) = _run_builders[_run_write_pointer]->duration; + output_tex_x(0) = output_tex_x(1) = output_tex_x(2) = tex_x; // these things are constants across the line so just throw them out now - output_tex_y(0) = output_tex_y(4) = output_tex_y(1) = output_tex_y(2) = output_tex_y(3) = output_tex_y(5) = tex_y; - output_lateral(0) = output_lateral(4) = output_lateral(5) = 0; - output_lateral(1) = output_lateral(2) = output_lateral(3) = 1; + output_tex_y(0) = output_tex_y(1) = output_tex_y(2) = output_tex_y(3) = output_tex_y(4) = output_tex_y(5) = tex_y; + output_lateral(0) = output_lateral(1) = output_lateral(3) = 0; + output_lateral(2) = output_lateral(4) = output_lateral(5) = 1; } else { @@ -228,10 +229,10 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi if(_output_device == CRT::Monitor) { // store the final raster position - output_position_x(2) = output_position_x(3) = output_position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position(); - output_position_y(2) = output_position_y(3) = output_position_y(5) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider); - output_timestamp(2) = output_timestamp(3) = output_timestamp(5) = _run_builders[_run_write_pointer]->duration; - output_tex_x(2) = output_tex_x(3) = output_tex_x(5) = tex_x; + output_position_x(3) = output_position_x(4) = output_position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position(); + output_position_y(3) = output_position_y(4) = output_position_y(5) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider); + output_timestamp(3) = output_timestamp(4) = output_timestamp(5) = _run_builders[_run_write_pointer]->duration; + output_tex_x(3) = output_tex_x(4) = output_tex_x(5) = tex_x; } else { @@ -291,6 +292,19 @@ void CRT::output_scan(Scan *scan) bool vsync_requested = is_trailing_edge && (_sync_capacitor_charge_level >= _sync_capacitor_charge_threshold); _is_receiving_sync = this_is_sync; + // simplified colour burst logic: if it's within the back porch we'll take it + if(scan->type == Type::ColourBurst) + { + if(_horizontal_flywheel->get_current_time() < (_horizontal_flywheel->get_standard_period() * 12) >> 6) + { + _colour_burst_time = (uint16_t)_colour_burst_time; + _colour_burst_phase = scan->phase; + _colour_burst_amplitude = scan->amplitude; + } + } + + // TODO: inspect raw data for potential colour burst if required + _sync_period = _is_receiving_sync ? (_sync_period + scan->number_of_cycles) : 0; advance_cycles(scan->number_of_cycles, scan->source_divider, hsync_requested, vsync_requested, this_is_sync, scan->type, scan->tex_x, scan->tex_y); } @@ -327,13 +341,13 @@ void CRT::output_level(unsigned int number_of_cycles) output_scan(&scan); } -void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t magnitude) +void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude) { Scan scan { .type = Type::ColourBurst, .number_of_cycles = number_of_cycles, .phase = phase, - .magnitude = magnitude + .amplitude = amplitude }; output_scan(&scan); } diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index 971eef0e1..4a40fe82d 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -141,10 +141,10 @@ class CRT { @param phase The initial phase of the colour burst in a measuring system with 256 units per circle, e.g. 0 = 0 degrees, 128 = 180 degrees, 256 = 360 degree. - @param magnitude The magnitude of the colour burst in 1/256ths of the magnitude of the + @param amplitude The amplitude of the colour burst in 1/256ths of the amplitude of the positive portion of the wave. */ - void output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t magnitude); + void output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude); /*! Ensures that the given number of output samples are allocated for writing. @@ -289,14 +289,14 @@ class CRT { uint16_t tex_x, tex_y; }; struct { - uint8_t phase, magnitude; + uint8_t phase, amplitude; }; }; }; void output_scan(Scan *scan); struct CRTRunBuilder { - CRTRunBuilder(size_t vertex_size, int vertices_per_run) : _vertex_size(vertex_size), _vertices_per_run(vertices_per_run) { reset(); } + CRTRunBuilder(size_t vertex_size) : _vertex_size(vertex_size) { reset(); } // Resets the run builder. void reset(); @@ -305,7 +305,7 @@ class CRT { // from the input buffer to the screen. In composite mode input runs will map from the // input buffer to the processing buffer, and output runs will map from the processing // buffer to the screen. - uint8_t *get_next_run(); + uint8_t *get_next_run(size_t number_of_vertices); std::vector _runs; // Container for total length in cycles of all contained runs. @@ -318,7 +318,6 @@ class CRT { private: size_t _vertex_size; - int _vertices_per_run; }; struct CRTInputBufferBuilder { @@ -358,6 +357,7 @@ class CRT { uint16_t _composite_src_output_y; uint8_t _colour_burst_phase, _colour_burst_amplitude; uint16_t _colour_burst_time; + bool _is_writing_composite_run; // OpenGL state, kept behind an opaque pointer to avoid inclusion of the GL headers here. struct OpenGLState; diff --git a/Outputs/CRT/CRTBuilders.cpp b/Outputs/CRT/CRTBuilders.cpp index d065b2095..bf4eee8bc 100644 --- a/Outputs/CRT/CRTBuilders.cpp +++ b/Outputs/CRT/CRTBuilders.cpp @@ -86,16 +86,16 @@ void CRT::CRTRunBuilder::reset() duration = 0; } -uint8_t *CRT::CRTRunBuilder::get_next_run() +uint8_t *CRT::CRTRunBuilder::get_next_run(size_t number_of_vertices_in_run) { // get a run from the allocated list, allocating more if we're about to overrun - if((number_of_vertices + (size_t)_vertices_per_run) * _vertex_size >= _runs.size()) + if((number_of_vertices + number_of_vertices_in_run) * _vertex_size >= _runs.size()) { - _runs.resize(_runs.size() + _vertex_size * (size_t)_vertices_per_run * 100); + _runs.resize(_runs.size() + _vertex_size * 100); } uint8_t *next_run = &_runs[number_of_vertices * _vertex_size]; - number_of_vertices += (size_t)_vertices_per_run; + number_of_vertices += number_of_vertices_in_run; return next_run; } diff --git a/Outputs/CRT/CRTOpenGL.cpp b/Outputs/CRT/CRTOpenGL.cpp index 2b7026231..c99846ea8 100644 --- a/Outputs/CRT/CRTOpenGL.cpp +++ b/Outputs/CRT/CRTOpenGL.cpp @@ -172,7 +172,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool } // draw this frame - glDrawArrays(GL_TRIANGLES, (GLint)(run * _openGL_state->verticesPerSlice), (GLsizei)_run_builders[run]->number_of_vertices); + glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(run * _openGL_state->verticesPerSlice), (GLsizei)_run_builders[run]->number_of_vertices); } // advance back in time