88#include " EmulationSettings.h"
99#include " Console.h"
1010
11- BisqwitNtscFilter::BisqwitNtscFilter (shared_ptr<Console> console, int resDivider, bool SMPTE_C ) : BaseVideoFilter(console)
11+ BisqwitNtscFilter::BisqwitNtscFilter (shared_ptr<Console> console, int resDivider) : BaseVideoFilter(console)
1212{
1313 _resDivider = resDivider;
1414 _stopThread = false ;
1515 _workDone = false ;
16- _SMPTE_C = SMPTE_C;
1716
1817 const int8_t signalLumaLow[4 ] = { -29 , -15 , 22 , 71 };
1918 const int8_t signalLumaHigh[4 ] = { 32 , 66 , 105 , 105 };
@@ -50,7 +49,7 @@ BisqwitNtscFilter::BisqwitNtscFilter(shared_ptr<Console> console, int resDivider
5049 outputBuffer += GetOverscan ().GetScreenWidth () * 64 / _resDivider / _resDivider * (120 - GetOverscan ().Top );
5150 }
5251
53- DecodeFrame (120 , 239 - GetOverscan ().Bottom , _ppuOutputBuffer, outputBuffer, (IsOddFrame () ? 8 : 0 ) + 327360 , SMPTE_C);
52+ DecodeFrame (120 , 239 - GetOverscan ().Bottom , _ppuOutputBuffer, outputBuffer, (IsOddFrame () ? 8 : 0 ) + 327360 );
5453
5554 _workDone = true ;
5655 }
@@ -70,7 +69,7 @@ void BisqwitNtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
7069
7170 _workDone = false ;
7271 _waitWork.Signal ();
73- DecodeFrame (GetOverscan ().Top , 120 , ppuOutputBuffer, GetOutputBuffer (), (IsOddFrame () ? 8 : 0 ) + GetOverscan ().Top *341 *8 , _SMPTE_C );
72+ DecodeFrame (GetOverscan ().Top , 120 , ppuOutputBuffer, GetOutputBuffer (), (IsOddFrame () ? 8 : 0 ) + GetOverscan ().Top *341 *8 );
7473 while (!_workDone) {}
7574}
7675
@@ -94,6 +93,11 @@ void BisqwitNtscFilter::OnBeforeApplyFilter()
9493 const double pi = std::atan (1.0 ) * 4 ;
9594 int contrast = (int )((pictureSettings.Contrast + 1.0 ) * (pictureSettings.Contrast + 1.0 ) * 167941 );
9695 int saturation = (int )((pictureSettings.Saturation + 1.0 ) * (pictureSettings.Saturation + 1.0 ) * 144044 );
96+ bool colorimetryCorrection = _console->GetSettings ()->GetNtscFilterSettings ().ColorimetryCorrection ;
97+
98+ // [saturation at 0] * 100 / [I or Q width at 0]
99+ double SatFactor = 144044 * 100 / 12 ;
100+
97101 for (int i = 0 ; i < 27 ; i++) {
98102 _sinetable[i] = (int8_t )(8 * std::sin (i * 2 * pi / 12 + pictureSettings.Hue * pi));
99103 }
@@ -104,30 +108,14 @@ void BisqwitNtscFilter::OnBeforeApplyFilter()
104108
105109 _y = contrast / _yWidth;
106110
107- // magic numbers is corresponding values from the YIQ to RGB formula
108- // but divided by 13,995 * [arbitrary value]
109- /*
110- _ir = (int)(( 0.95599 / (13995 * 34.2457747)) * contrast * saturation / _iWidth);
111- _ig = (int)((-0.27201 / (13995 * 212.3864250)) * contrast * saturation / _iWidth);
112- _ib = (int)((-1.10674 / (13995 * 78.0674723)) * contrast * saturation / _iWidth);
113- _qr = (int)(( 0.62082 / (13995 * 44.7370743)) * contrast * saturation / _qWidth);
114- _qg = (int)((-0.64720 / (13995 * 73.0015960)) * contrast * saturation / _qWidth);
115- _qb = (int)(( 1.70423 / (13995 * 73.0404051)) * contrast * saturation / _qWidth);
116- */
117- _ir = (int )(contrast * 1.994681e-6 * saturation / _iWidth);
118- _ig = (int )(contrast * 9.151351e-8 * saturation / _iWidth);
119- _ib = (int )(contrast * -1.012984e-6 * saturation / _iWidth);
120- _qr = (int )(contrast * 9.915742e-7 * saturation / _qWidth);
121- _qg = (int )(contrast * -6.334805e-7 * saturation / _qWidth);
122- _qb = (int )(contrast * 1.667217e-6 * saturation / _qWidth);
123-
124- // alternate values based on the SMPTE C color primaries
125- _irC = (int )((0.95599 / (13995 * 80 )) * contrast * saturation / _iWidth);
126- _igC = (int )((-0.27201 / (13995 * 80 )) * contrast * saturation / _iWidth);
127- _ibC = (int )((-1.10674 / (13995 * 80 )) * contrast * saturation / _iWidth);
128- _qrC = (int )((0.62082 / (13995 * 80 )) * contrast * saturation / _qWidth);
129- _qgC = (int )((-0.64720 / (13995 * 80 )) * contrast * saturation / _qWidth);
130- _qbC = (int )((1.70423 / (13995 * 80 )) * contrast * saturation / _qWidth);
111+ _ir = colorimetryCorrection ? (int )(contrast * 1.994681e-6 * saturation / _iWidth) : (int )(contrast * (0.95599 / SatFactor) * saturation / _iWidth);
112+ _qr = colorimetryCorrection ? (int )(contrast * 9.915742e-7 * saturation / _qWidth) : (int )(contrast * (0.62082 / SatFactor) * saturation / _qWidth);
113+
114+ _ig = colorimetryCorrection ? (int )(contrast * 9.151351e-8 * saturation / _iWidth) : (int )(contrast * (-0.27201 / SatFactor) * saturation / _iWidth);
115+ _qg = colorimetryCorrection ? (int )(contrast * -6.334805e-7 * saturation / _qWidth) : (int )(contrast * (-0.64720 / SatFactor) * saturation / _qWidth);
116+
117+ _ib = colorimetryCorrection ? (int )(contrast * -1.012984e-6 * saturation / _iWidth) : (int )(contrast * (-1.10674 / SatFactor) * saturation / _iWidth);
118+ _qb = colorimetryCorrection ? (int )(contrast * 1.667217e-6 * saturation / _qWidth) : (int )(contrast * (1.70423 / SatFactor) * saturation / _qWidth);
131119}
132120
133121void BisqwitNtscFilter::RecursiveBlend (int iterationCount, uint64_t *output, uint64_t *currentLine, uint64_t *nextLine, int pixelsPerCycle, bool verticalBlend)
@@ -209,7 +197,7 @@ void BisqwitNtscFilter::GenerateNtscSignal(int8_t *ntscSignal, int &phase, int r
209197 phase += (341 - 256 - _paddingSize * 2 ) * _signalsPerPixel;
210198}
211199
212- void BisqwitNtscFilter::DecodeFrame (int startRow, int endRow, uint16_t *ppuOutputBuffer, uint32_t * outputBuffer, int startPhase, bool SMPTE_C )
200+ void BisqwitNtscFilter::DecodeFrame (int startRow, int endRow, uint16_t *ppuOutputBuffer, uint32_t * outputBuffer, int startPhase)
213201{
214202 int pixelsPerCycle = 8 / _resDivider;
215203 int phase = startPhase;
@@ -229,7 +217,7 @@ void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutpu
229217 GenerateNtscSignal (rowSignal, phase, y);
230218
231219 // Convert the NTSC signal to RGB
232- NtscDecodeLine (lineWidth * _signalsPerPixel, rowSignal, outputBuffer, (startCycle + 7 ) % 12 , SMPTE_C );
220+ NtscDecodeLine (lineWidth * _signalsPerPixel, rowSignal, outputBuffer, (startCycle + 7 ) % 12 );
233221
234222 outputBuffer += rowPixelGap;
235223 }
@@ -281,7 +269,7 @@ void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutpu
281269* In essence it conveys in one integer the same information that real NTSC signal
282270* would convey in the colorburst period in the beginning of each scanline.
283271*/
284- void BisqwitNtscFilter::NtscDecodeLine (int width, const int8_t * signal, uint32_t * target, int phase0, bool SMPTE_C )
272+ void BisqwitNtscFilter::NtscDecodeLine (int width, const int8_t * signal, uint32_t * target, int phase0)
285273{
286274 auto Read = [=](int pos) -> char { return pos >= 0 ? signal[pos] : 0 ; };
287275 auto Cos = [=](int pos) -> char { return _sinetable[(pos + 36 ) % 12 + phase0]; };
@@ -299,9 +287,9 @@ void BisqwitNtscFilter::NtscDecodeLine(int width, const int8_t* signal, uint32_t
299287 qsum += Read (s) * Sin (s) - Read (s - _qWidth) * Sin (s - _qWidth);
300288
301289 if (!(s % _resDivider) && s >= leftOverscan) {
302- int r = std::min (255 , std::max (0 , (ysum*_y + isum*(SMPTE_C ? _irC : _ir) + qsum*(SMPTE_C ? _qrC : _qr) ) / 65536 ));
303- int g = std::min (255 , std::max (0 , (ysum*_y + isum*(SMPTE_C ? _igC : _ig) + qsum*(SMPTE_C ? _qgC : _qg) ) / 65536 ));
304- int b = std::min (255 , std::max (0 , (ysum*_y + isum*(SMPTE_C ? _ibC : _ib) + qsum*(SMPTE_C ? _qbC : _qb) ) / 65536 ));
290+ int r = std::min (255 , std::max (0 , (ysum*_y + isum*_ir + qsum*_qr) / 65536 ));
291+ int g = std::min (255 , std::max (0 , (ysum*_y + isum*_ig + qsum*_qg) / 65536 ));
292+ int b = std::min (255 , std::max (0 , (ysum*_y + isum*_ib + qsum*_qb) / 65536 ));
305293
306294 *target = 0xFF000000 | (r << 16 ) | (g << 8 ) | b;
307295 target++;
0 commit comments