diff --git a/Core/BisqwitNtscFilter.cpp b/Core/BisqwitNtscFilter.cpp index a343c599d..e1846b218 100644 --- a/Core/BisqwitNtscFilter.cpp +++ b/Core/BisqwitNtscFilter.cpp @@ -8,11 +8,12 @@ #include "EmulationSettings.h" #include "Console.h" -BisqwitNtscFilter::BisqwitNtscFilter(shared_ptr console, int resDivider) : BaseVideoFilter(console) +BisqwitNtscFilter::BisqwitNtscFilter(shared_ptr console, int resDivider, bool SMPTE_C) : BaseVideoFilter(console) { _resDivider = resDivider; _stopThread = false; _workDone = false; + _SMPTE_C = SMPTE_C; const int8_t signalLumaLow[4] = { -29, -15, 22, 71 }; const int8_t signalLumaHigh[4] = { 32, 66, 105, 105 }; @@ -49,7 +50,7 @@ BisqwitNtscFilter::BisqwitNtscFilter(shared_ptr console, int resDivider outputBuffer += GetOverscan().GetScreenWidth() * 64 / _resDivider / _resDivider * (120 - GetOverscan().Top); } - DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer, (IsOddFrame() ? 8 : 0) + 327360); + DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer, (IsOddFrame() ? 8 : 0) + 327360, SMPTE_C); _workDone = true; } @@ -69,7 +70,7 @@ void BisqwitNtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer) _workDone = false; _waitWork.Signal(); - DecodeFrame(GetOverscan().Top, 120, ppuOutputBuffer, GetOutputBuffer(), (IsOddFrame() ? 8 : 0) + GetOverscan().Top*341*8); + DecodeFrame(GetOverscan().Top, 120, ppuOutputBuffer, GetOutputBuffer(), (IsOddFrame() ? 8 : 0) + GetOverscan().Top*341*8, _SMPTE_C); while(!_workDone) {} } @@ -89,7 +90,6 @@ void BisqwitNtscFilter::OnBeforeApplyFilter() NtscFilterSettings ntscSettings = _console->GetSettings()->GetNtscFilterSettings(); _keepVerticalRes = ntscSettings.KeepVerticalResolution; - //_SMPTE_C = ntscSettings.NtscSmpteC; const double pi = std::atan(1.0) * 4; int contrast = (int)((pictureSettings.Contrast + 1.0) * (pictureSettings.Contrast + 1.0) * 167941); @@ -209,7 +209,7 @@ void BisqwitNtscFilter::GenerateNtscSignal(int8_t *ntscSignal, int &phase, int r phase += (341 - 256 - _paddingSize * 2) * _signalsPerPixel; } -void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, int startPhase) +void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, int startPhase, bool SMPTE_C) { int pixelsPerCycle = 8 / _resDivider; int phase = startPhase; @@ -229,7 +229,7 @@ void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutpu GenerateNtscSignal(rowSignal, phase, y); //Convert the NTSC signal to RGB - NtscDecodeLine(lineWidth * _signalsPerPixel, rowSignal, outputBuffer, (startCycle + 7) % 12); + NtscDecodeLine(lineWidth * _signalsPerPixel, rowSignal, outputBuffer, (startCycle + 7) % 12, SMPTE_C); outputBuffer += rowPixelGap; } @@ -281,7 +281,7 @@ void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutpu * In essence it conveys in one integer the same information that real NTSC signal * would convey in the colorburst period in the beginning of each scanline. */ -void BisqwitNtscFilter::NtscDecodeLine(int width, const int8_t* signal, uint32_t* target, int phase0) +void BisqwitNtscFilter::NtscDecodeLine(int width, const int8_t* signal, uint32_t* target, int phase0, bool SMPTE_C) { auto Read = [=](int pos) -> char { return pos >= 0 ? signal[pos] : 0; }; auto Cos = [=](int pos) -> char { return _sinetable[(pos + 36) % 12 + phase0]; }; @@ -299,9 +299,9 @@ void BisqwitNtscFilter::NtscDecodeLine(int width, const int8_t* signal, uint32_t qsum += Read(s) * Sin(s) - Read(s - _qWidth) * Sin(s - _qWidth); if(!(s % _resDivider) && s >= leftOverscan) { - int r = std::min(255, std::max(0, (ysum*_y + isum*_irC + qsum*_qrC) / 65536)); - int g = std::min(255, std::max(0, (ysum*_y + isum*_igC + qsum*_qgC) / 65536)); - int b = std::min(255, std::max(0, (ysum*_y + isum*_ibC + qsum*_qbC) / 65536)); + int r = std::min(255, std::max(0, (ysum*_y + isum*(SMPTE_C ? _irC : _ir) + qsum*(SMPTE_C ? _qrC : _qr)) / 65536)); + int g = std::min(255, std::max(0, (ysum*_y + isum*(SMPTE_C ? _igC : _ig) + qsum*(SMPTE_C ? _qgC : _qg)) / 65536)); + int b = std::min(255, std::max(0, (ysum*_y + isum*(SMPTE_C ? _ibC : _ib) + qsum*(SMPTE_C ? _qbC : _qb)) / 65536)); *target = 0xFF000000 | (r << 16) | (g << 8) | b; target++; diff --git a/Core/BisqwitNtscFilter.h b/Core/BisqwitNtscFilter.h index 15c54a854..3890fa9e6 100644 --- a/Core/BisqwitNtscFilter.h +++ b/Core/BisqwitNtscFilter.h @@ -44,14 +44,14 @@ class BisqwitNtscFilter : public BaseVideoFilter void RecursiveBlend(int iterationCount, uint64_t *output, uint64_t *currentLine, uint64_t *nextLine, int pixelsPerCycle, bool verticalBlend); - void NtscDecodeLine(int width, const int8_t* signal, uint32_t* target, int phase0); + void NtscDecodeLine(int width, const int8_t* signal, uint32_t* target, int phase0, bool SMPTE_C); void GenerateNtscSignal(int8_t *ntscSignal, int &phase, int rowNumber); - void DecodeFrame(int startRow, int endRow, uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, int startPhase); + void DecodeFrame(int startRow, int endRow, uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, int startPhase, bool SMPTE_C); void OnBeforeApplyFilter(); public: - BisqwitNtscFilter(shared_ptr console, int resDivider); + BisqwitNtscFilter(shared_ptr console, int resDivider, bool SMPTE_C); virtual ~BisqwitNtscFilter(); virtual void ApplyFilter(uint16_t *ppuOutputBuffer); diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index e7075c225..e23f399f8 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -171,6 +171,9 @@ enum class VideoFilterType Prescale8x = 23, Prescale10x = 24, Raw = 25, + BisqwitNtscSMPTECQuarterRes = 26, + BisqwitNtscSMPTECHalfRes = 27, + BisqwitNtscSMPTEC = 28, HdPack = 999 }; diff --git a/Core/ScaleFilter.cpp b/Core/ScaleFilter.cpp index 70230cbdd..5ff76ccb2 100644 --- a/Core/ScaleFilter.cpp +++ b/Core/ScaleFilter.cpp @@ -107,6 +107,9 @@ shared_ptr ScaleFilter::GetScaleFilter(VideoFilterType filter) case VideoFilterType::BisqwitNtsc: case VideoFilterType::BisqwitNtscHalfRes: case VideoFilterType::BisqwitNtscQuarterRes: + case VideoFilterType::BisqwitNtscSMPTEC: + case VideoFilterType::BisqwitNtscSMPTECHalfRes: + case VideoFilterType::BisqwitNtscSMPTECQuarterRes: case VideoFilterType::NTSC: case VideoFilterType::HdPack: case VideoFilterType::Raw: diff --git a/Core/VideoDecoder.cpp b/Core/VideoDecoder.cpp index ee4a94cb2..de0f5e734 100644 --- a/Core/VideoDecoder.cpp +++ b/Core/VideoDecoder.cpp @@ -70,9 +70,12 @@ void VideoDecoder::UpdateVideoFilter() switch(_videoFilterType) { case VideoFilterType::None: break; case VideoFilterType::NTSC: _videoFilter.reset(new NtscFilter(_console)); break; - case VideoFilterType::BisqwitNtsc: _videoFilter.reset(new BisqwitNtscFilter(_console, 1)); break; - case VideoFilterType::BisqwitNtscHalfRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 2)); break; - case VideoFilterType::BisqwitNtscQuarterRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 4)); break; + case VideoFilterType::BisqwitNtsc: _videoFilter.reset(new BisqwitNtscFilter(_console, 1, false)); break; + case VideoFilterType::BisqwitNtscHalfRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 2, false)); break; + case VideoFilterType::BisqwitNtscQuarterRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 4, false)); break; + case VideoFilterType::BisqwitNtscSMPTEC: _videoFilter.reset(new BisqwitNtscFilter(_console, 1, true)); break; + case VideoFilterType::BisqwitNtscSMPTECHalfRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 2, true)); break; + case VideoFilterType::BisqwitNtscSMPTECQuarterRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 4, true)); break; case VideoFilterType::Raw: _videoFilter.reset(new RawVideoFilter(_console)); break; default: _scaleFilter = ScaleFilter::GetScaleFilter(_videoFilterType); break; } diff --git a/GUI.NET/Forms/Config/frmVideoConfig.cs b/GUI.NET/Forms/Config/frmVideoConfig.cs index f893e3b20..5ececd30d 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.cs +++ b/GUI.NET/Forms/Config/frmVideoConfig.cs @@ -165,7 +165,12 @@ protected override bool ValidateInput() tlpNtscFilter2.Visible = false; chkMergeFields.Visible = true; grpNtscFilter.Visible = true; - } else if(filter == VideoFilterType.BisqwitNtsc || filter == VideoFilterType.BisqwitNtscHalfRes || filter == VideoFilterType.BisqwitNtscQuarterRes) { + } else if(filter == VideoFilterType.BisqwitNtsc || + filter == VideoFilterType.BisqwitNtscHalfRes || + filter == VideoFilterType.BisqwitNtscQuarterRes || + filter == VideoFilterType.BisqwitNtscSMPTEC || + filter == VideoFilterType.BisqwitNtscSMPTECHalfRes || + filter == VideoFilterType.BisqwitNtscSMPTECQuarterRes) { tlpNtscFilter1.Visible = true; tlpNtscFilter2.Visible = true; chkMergeFields.Visible = false; diff --git a/GUI.NET/Forms/frmMain.Designer.cs b/GUI.NET/Forms/frmMain.Designer.cs index f810490f0..0651ddece 100644 --- a/GUI.NET/Forms/frmMain.Designer.cs +++ b/GUI.NET/Forms/frmMain.Designer.cs @@ -106,6 +106,9 @@ private void InitializeComponent() this.mnuNtscBisqwitQuarterFilter = new System.Windows.Forms.ToolStripMenuItem(); this.mnuNtscBisqwitHalfFilter = new System.Windows.Forms.ToolStripMenuItem(); this.mnuNtscBisqwitFullFilter = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuNtscSMPTECBisqwitQuarterFilter = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuNtscSMPTECBisqwitHalfFilter = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuNtscSMPTECBisqwitFullFilter = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripSeparator(); this.mnuXBRZ2xFilter = new System.Windows.Forms.ToolStripMenuItem(); this.mnuXBRZ3xFilter = new System.Windows.Forms.ToolStripMenuItem(); @@ -831,6 +834,9 @@ private void InitializeComponent() this.mnuNtscBisqwitQuarterFilter, this.mnuNtscBisqwitHalfFilter, this.mnuNtscBisqwitFullFilter, + this.mnuNtscSMPTECBisqwitQuarterFilter, + this.mnuNtscSMPTECBisqwitHalfFilter, + this.mnuNtscSMPTECBisqwitFullFilter, this.toolStripMenuItem15, this.mnuXBRZ2xFilter, this.mnuXBRZ3xFilter, @@ -903,6 +909,27 @@ private void InitializeComponent() this.mnuNtscBisqwitFullFilter.Text = "NTSC 8x (Bisqwit)"; this.mnuNtscBisqwitFullFilter.Click += new System.EventHandler(this.mnuNtscBisqwitFullFilter_Click); // + // mnuNtscSMPTECBisqwitQuarterFilter + // + this.mnuNtscSMPTECBisqwitQuarterFilter.Name = "mnuNtscSMPTECBisqwitQuarterFilter"; + this.mnuNtscSMPTECBisqwitQuarterFilter.Size = new System.Drawing.Size(206, 22); + this.mnuNtscSMPTECBisqwitQuarterFilter.Text = "NTSC SMPTE C 2x (Bisqwit)"; + this.mnuNtscSMPTECBisqwitQuarterFilter.Click += new System.EventHandler(this.mnuNtscSMPTECBisqwitQuarterFilter_Click); + // + // mnuNtscSMPTECBisqwitHalfFilter + // + this.mnuNtscSMPTECBisqwitHalfFilter.Name = "mnuNtscSMPTECBisqwitHalfFilter"; + this.mnuNtscSMPTECBisqwitHalfFilter.Size = new System.Drawing.Size(206, 22); + this.mnuNtscSMPTECBisqwitHalfFilter.Text = "NTSC SMPTE C 4x (Bisqwit)"; + this.mnuNtscSMPTECBisqwitHalfFilter.Click += new System.EventHandler(this.mnuNtscSMPTECBisqwitHalfFilter_Click); + // + // mnuNtscSMPTECBisqwitFullFilter + // + this.mnuNtscSMPTECBisqwitFullFilter.Name = "mnuNtscSMPTECBisqwitFullFilter"; + this.mnuNtscSMPTECBisqwitFullFilter.Size = new System.Drawing.Size(206, 22); + this.mnuNtscSMPTECBisqwitFullFilter.Text = "NTSC SMPTE C 8x (Bisqwit)"; + this.mnuNtscSMPTECBisqwitFullFilter.Click += new System.EventHandler(this.mnuNtscSMPTECBisqwitFullFilter_Click); + // // toolStripMenuItem15 // this.toolStripMenuItem15.Name = "toolStripMenuItem15"; @@ -1977,6 +2004,9 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem mnuNtscBisqwitHalfFilter; private System.Windows.Forms.ToolStripMenuItem mnuNtscBisqwitFullFilter; private System.Windows.Forms.ToolStripMenuItem mnuNtscBisqwitQuarterFilter; + private System.Windows.Forms.ToolStripMenuItem mnuNtscSMPTECBisqwitHalfFilter; + private System.Windows.Forms.ToolStripMenuItem mnuNtscSMPTECBisqwitFullFilter; + private System.Windows.Forms.ToolStripMenuItem mnuNtscSMPTECBisqwitQuarterFilter; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem22; private System.Windows.Forms.ToolStripMenuItem mnuVideoRecorder; private System.Windows.Forms.ToolStripMenuItem mnuAviRecord; diff --git a/GUI.NET/Forms/frmMain.Options.cs b/GUI.NET/Forms/frmMain.Options.cs index 54bac9194..d9e50843b 100644 --- a/GUI.NET/Forms/frmMain.Options.cs +++ b/GUI.NET/Forms/frmMain.Options.cs @@ -52,6 +52,9 @@ private void UpdateFilterMenu(VideoFilterType filterType) mnuNtscBisqwitFullFilter.Checked = (filterType == VideoFilterType.BisqwitNtsc); mnuNtscBisqwitHalfFilter.Checked = (filterType == VideoFilterType.BisqwitNtscHalfRes); mnuNtscBisqwitQuarterFilter.Checked = (filterType == VideoFilterType.BisqwitNtscQuarterRes); + mnuNtscSMPTECBisqwitFullFilter.Checked = (filterType == VideoFilterType.BisqwitNtscSMPTEC); + mnuNtscSMPTECBisqwitHalfFilter.Checked = (filterType == VideoFilterType.BisqwitNtscSMPTECHalfRes); + mnuNtscSMPTECBisqwitQuarterFilter.Checked = (filterType == VideoFilterType.BisqwitNtscSMPTECQuarterRes); mnuXBRZ2xFilter.Checked = (filterType == VideoFilterType.xBRZ2x); mnuXBRZ3xFilter.Checked = (filterType == VideoFilterType.xBRZ3x); @@ -370,5 +373,20 @@ private void mnuNtscBisqwitQuarterFilter_Click(object sender, EventArgs e) { SetVideoFilter(VideoFilterType.BisqwitNtscQuarterRes); } + + private void mnuNtscSMPTECBisqwitFullFilter_Click(object sender, EventArgs e) + { + SetVideoFilter(VideoFilterType.BisqwitNtscSMPTEC); + } + + private void mnuNtscSMPTECBisqwitHalfFilter_Click(object sender, EventArgs e) + { + SetVideoFilter(VideoFilterType.BisqwitNtscSMPTECHalfRes); + } + + private void mnuNtscSMPTECBisqwitQuarterFilter_Click(object sender, EventArgs e) + { + SetVideoFilter(VideoFilterType.BisqwitNtscSMPTECQuarterRes); + } } } diff --git a/GUI.NET/Forms/frmMain.cs b/GUI.NET/Forms/frmMain.cs index cd19dbf78..785651079 100644 --- a/GUI.NET/Forms/frmMain.cs +++ b/GUI.NET/Forms/frmMain.cs @@ -1363,6 +1363,9 @@ private void UpdateMenus() mnuNtscBisqwitQuarterFilter.Enabled = !isHdPackLoader; mnuNtscBisqwitHalfFilter.Enabled = !isHdPackLoader; mnuNtscBisqwitFullFilter.Enabled = !isHdPackLoader; + mnuNtscSMPTECBisqwitQuarterFilter.Enabled = !isHdPackLoader; + mnuNtscSMPTECBisqwitHalfFilter.Enabled = !isHdPackLoader; + mnuNtscSMPTECBisqwitFullFilter.Enabled = !isHdPackLoader; } } catch { } } diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 97ee7a012..7044583b9 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -2362,6 +2362,9 @@ public enum VideoFilterType Prescale6x = 22, Prescale8x = 23, Prescale10x = 24, + BisqwitNtscSMPTECQuarterRes = 26, + BisqwitNtscSMPTECHalfRes = 27, + BisqwitNtscSMPTEC = 28, } public enum HDPackOuputTileType