mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 03:32:01 +00:00
Corrects NTSC quadrature phase.
This commit is contained in:
parent
8dd7c6ef23
commit
35e84ff1a8
@ -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;
|
||||
|
@ -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;"
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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] {
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user