1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-22 14:30:29 +00:00

Corrects NTSC quadrature phase.

This commit is contained in:
Thomas Harte 2018-05-31 21:40:46 -04:00
parent 8dd7c6ef23
commit 35e84ff1a8
5 changed files with 26 additions and 24 deletions

View File

@ -69,7 +69,7 @@ template <class BusHandler> 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 BusHandler> 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;

View File

@ -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;"

View File

@ -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<uint16_t>(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);
}

View File

@ -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] {

View File

@ -96,10 +96,10 @@ std::unique_ptr<IntermediateShader> 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> 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> 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> 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> 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> 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);
}