diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp index 4bd44dbb4..fbcacb390 100644 --- a/Components/6560/6560.hpp +++ b/Components/6560/6560.hpp @@ -69,7 +69,7 @@ template class MOS6560 { speaker_(audio_generator_) { crt_->set_svideo_sampling_function( - "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase)" + "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)" "{" "vec2 yc = texture(texID, coordinate).rg / vec2(255.0);" @@ -125,10 +125,10 @@ template class MOS6560 { 19, 86, 123, 59, }; const uint8_t ntsc_chrominances[16] = { - 255, 255, 7, 71, - 25, 86, 48, 112, - 0, 119, 7, 71, - 25, 86, 48, 112, + 255, 255, 121, 57, + 103, 42, 80, 16, + 0, 9, 121, 57, + 103, 42, 80, 16, }; const uint8_t *chrominances; Outputs::CRT::DisplayType display_type; diff --git a/Machines/Atari2600/TIA.cpp b/Machines/Atari2600/TIA.cpp index 29f294fb0..af37c49f9 100644 --- a/Machines/Atari2600/TIA.cpp +++ b/Machines/Atari2600/TIA.cpp @@ -124,19 +124,19 @@ void TIA::set_output_mode(Atari2600::TIA::OutputMode output_mode) { if(output_mode == OutputMode::NTSC) { crt_->set_svideo_sampling_function( - "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase)" + "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)" "{" "uint c = texture(texID, coordinate).r;" "uint y = c & 14u;" "uint iPhase = (c >> 4);" "float phaseOffset = 6.283185308 * float(iPhase) / 13.0 + 5.074880441076923;" - "return vec2(float(y) / 14.0, step(1, iPhase) * cos(phase + phaseOffset));" + "return vec2(float(y) / 14.0, step(1, iPhase) * cos(phase - phaseOffset));" "}"); display_type = Outputs::CRT::DisplayType::NTSC60; } else { crt_->set_svideo_sampling_function( - "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase)" + "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)" "{" "uint c = texture(texID, coordinate).r;" "uint y = c & 14u;" diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 86a74b69b..7f0f4f20b 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -170,7 +170,9 @@ void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bo // outside of the locked region source_output_position_x1() = static_cast(horizontal_flywheel_->get_current_output_position()); source_phase() = colour_burst_phase_; - source_amplitude() = colour_burst_amplitude_; + + // TODO: determine what the PAL phase-shift machines actually do re: the swinging burst. + source_amplitude() = phase_alternates_ ? 128 - colour_burst_amplitude_ : 128 + colour_burst_amplitude_; } // decrement the number of cycles left to run for and increment the @@ -368,7 +370,7 @@ void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint scan.type = Scan::Type::ColourBurst; scan.number_of_cycles = number_of_cycles; scan.phase = phase; - scan.amplitude = amplitude; + scan.amplitude = amplitude >> 1; output_scan(&scan); } diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index 335a2710e..c27fa86e5 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -332,10 +332,10 @@ class CRT { output mode will be applied. @param shader A GLSL fragment including a function with the signature - `vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase)` + `vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)` that evaluates to the s-video signal level, luminance as the first component and chrominance as the second, as a function of a source buffer, sampling location and colour - carrier phase. + carrier phase; amplitude is supplied for its sign. */ inline void set_svideo_sampling_function(const std::string &shader) { enqueue_openGL_function([shader, this] { diff --git a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp index 36c614659..630d09ce1 100644 --- a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp +++ b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp @@ -96,10 +96,10 @@ std::unique_ptr IntermediateShader::make_shader(const std::s // setup phaseAndAmplitudeVarying.x as colour burst subcarrier phase, in radians; // setup phaseAndAmplitudeVarying.y as colour burst amplitude; - // setup phaseAndAmplitudeVarying.z as 1 / (colour burst amplitude), or 0.0 if amplitude is 0.0; + // setup phaseAndAmplitudeVarying.z as 1 / abs(colour burst amplitude), or 0.0 if amplitude is 0.0; "phaseAndAmplitudeVarying.x = (extendedOutputPosition.x + (phaseTimeAndAmplitude.x / 64.0)) * 0.5 * 3.141592654;" - "phaseAndAmplitudeVarying.y = phaseTimeAndAmplitude.y / 255.0;" - "phaseAndAmplitudeVarying.z = (phaseAndAmplitudeVarying.y > 0.0) ? 1.0 / phaseAndAmplitudeVarying.y : 0.0;" + "phaseAndAmplitudeVarying.y = (phaseTimeAndAmplitude.y - 128) / 127.0;" + "phaseAndAmplitudeVarying.z = (abs(phaseAndAmplitudeVarying.y) > 0.05) ? 1.0 / abs(phaseAndAmplitudeVarying.y) : 0.0;" // determine output position by scaling the output position according to the texture size "vec2 eyePosition = 2.0*(extendedOutputPosition / outputTextureSize) - vec2(1.0);" @@ -134,8 +134,8 @@ std::unique_ptr IntermediateShader::make_composite_source_sh svideo_shader << "float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)" "{" - "vec2 svideoColour = svideo_sample(texID, coordinate, iCoordinate, phase);" - "return mix(svideoColour.x, svideoColour.y, amplitude);" + "vec2 svideoColour = svideo_sample(texID, coordinate, iCoordinate, phase, amplitude);" + "return mix(svideoColour.x, svideoColour.y, abs(amplitude));" "}"; } else { fragment_shader << @@ -145,7 +145,7 @@ std::unique_ptr IntermediateShader::make_composite_source_sh "{" "vec3 rgbColour = clamp(rgb_sample(texID, coordinate, iCoordinate), vec3(0.0), vec3(1.0));" "vec3 lumaChromaColour = rgbToLumaChroma * rgbColour;" - "vec2 quadrature = vec2(cos(phase), -sin(phase)) * amplitude;" + "vec2 quadrature = vec2(cos(phase), sin(phase)) * vec2(abs(amplitude), amplitude);" "return dot(lumaChromaColour, vec3(1.0 - amplitude, quadrature));" "}"; } @@ -178,11 +178,11 @@ std::unique_ptr IntermediateShader::make_svideo_source_shade fragment_shader << rgb_shader << "uniform mat3 rgbToLumaChroma;" - "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase)" + "vec2 svideo_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)" "{" "vec3 rgbColour = clamp(rgb_sample(texID, coordinate, iCoordinate), vec3(0.0), vec3(1.0));" "vec3 lumaChromaColour = rgbToLumaChroma * rgbColour;" - "vec2 quadrature = vec2(cos(phase), -sin(phase));" + "vec2 quadrature = vec2(cos(phase), sin(phase)) * vec2(1.0, sign(amplitude));" "return vec2(lumaChromaColour.x, 0.5 + dot(quadrature, lumaChromaColour.yz) * 0.5);" "}"; } @@ -190,8 +190,8 @@ std::unique_ptr IntermediateShader::make_svideo_source_shade fragment_shader << "void main(void)" "{" - "vec2 sample = svideo_sample(texID, inputPositionsVarying[5], iInputPositionVarying, phaseAndAmplitudeVarying.x);" - "vec2 quadrature = vec2(cos(phaseAndAmplitudeVarying.x), -sin(phaseAndAmplitudeVarying.x)) * 0.5 * phaseAndAmplitudeVarying.z;" + "vec2 sample = svideo_sample(texID, inputPositionsVarying[5], iInputPositionVarying, phaseAndAmplitudeVarying.x, phaseAndAmplitudeVarying.y);" + "vec2 quadrature = vec2(cos(phaseAndAmplitudeVarying.x), sin(phaseAndAmplitudeVarying.x)) * vec2(1.0, sign(phaseAndAmplitudeVarying.y)) * 0.5 * phaseAndAmplitudeVarying.z;" "fragColour = vec3(sample.x, vec2(0.5) + (sample.y * quadrature));" "}"; @@ -244,11 +244,11 @@ std::unique_ptr IntermediateShader::make_chroma_luma_separat // define chroma to be whatever was here, minus luma "float chrominance = 0.5 * (samples.z - luminance) * phaseAndAmplitudeVarying.z;" - "luminance /= (1.0 - phaseAndAmplitudeVarying.y);" + "luminance /= (1.0 - abs(phaseAndAmplitudeVarying.y));" // split choma colours here, as the most direct place, writing out // RGB = (luma, chroma.x, chroma.y) - "vec2 quadrature = vec2(cos(phaseAndAmplitudeVarying.x), -sin(phaseAndAmplitudeVarying.x));" + "vec2 quadrature = vec2(cos(phaseAndAmplitudeVarying.x), sin(phaseAndAmplitudeVarying.x)) * vec2(1.0, sign(phaseAndAmplitudeVarying.y));" "fragColour = vec3(luminance, vec2(0.5) + (chrominance * quadrature));" "}",false, false); }