diff --git a/Core/BaseVideoFilter.cpp b/Core/BaseVideoFilter.cpp index dd16affe..ebf946d4 100644 --- a/Core/BaseVideoFilter.cpp +++ b/Core/BaseVideoFilter.cpp @@ -36,11 +36,16 @@ OverscanDimensions BaseVideoFilter::GetOverscan() return _overscan; } +void BaseVideoFilter::OnBeforeApplyFilter() +{ +} + void BaseVideoFilter::SendFrame(uint16_t *ppuOutputBuffer) { _frameLock.Acquire(); _overscan = EmulationSettings::GetOverscanDimensions(); UpdateBufferSize(); + OnBeforeApplyFilter(); ApplyFilter(ppuOutputBuffer); _frameLock.Release(); } diff --git a/Core/BaseVideoFilter.h b/Core/BaseVideoFilter.h index 2aa26356..a43315e2 100644 --- a/Core/BaseVideoFilter.h +++ b/Core/BaseVideoFilter.h @@ -23,6 +23,7 @@ private: protected: OverscanDimensions GetOverscan(); virtual void ApplyFilter(uint16_t *ppuOutputBuffer) = 0; + virtual void OnBeforeApplyFilter(); public: BaseVideoFilter(); diff --git a/Core/DefaultVideoFilter.cpp b/Core/DefaultVideoFilter.cpp index 6a89cfa4..972878cf 100644 --- a/Core/DefaultVideoFilter.cpp +++ b/Core/DefaultVideoFilter.cpp @@ -1,6 +1,37 @@ #include "stdafx.h" #include "DefaultVideoFilter.h" #include "EmulationSettings.h" +#define _USE_MATH_DEFINES +#include +#include + +DefaultVideoFilter::DefaultVideoFilter() +{ + InitConversionMatrix(_pictureSettings.Hue, _pictureSettings.Saturation); +} + +void DefaultVideoFilter::InitConversionMatrix(double hueShift, double saturationShift) +{ + _pictureSettings.Hue = hueShift; + _pictureSettings.Saturation = saturationShift; + + double hue = hueShift * M_PI - 15 * M_PI / 180; + double sat = saturationShift + 1; + + double baseValues[6] = { 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f }; + + double s = sin(hue) * sat; + double c = cos(hue) * sat; + + double *output = _yiqToRgbMatrix; + double *input = baseValues; + for(int n = 0; n < 3; n++) { + double i = *input++; + double q = *input++; + *output++ = i * c - q * s; + *output++ = i * s + q * c; + } +} FrameInfo DefaultVideoFilter::GetFrameInfo() { @@ -8,20 +39,55 @@ FrameInfo DefaultVideoFilter::GetFrameInfo() return { overscan.GetScreenWidth(), overscan.GetScreenHeight(), 4 }; } -void DefaultVideoFilter::ApplyFilter(uint16_t *ppuOutputBuffer) +void DefaultVideoFilter::OnBeforeApplyFilter() +{ + PictureSettings currentSettings = EmulationSettings::GetPictureSettings(); + if(_pictureSettings.Hue != currentSettings.Hue || _pictureSettings.Saturation != currentSettings.Saturation) { + InitConversionMatrix(currentSettings.Hue, currentSettings.Saturation); + } + _pictureSettings = currentSettings; + _needToProcess = _pictureSettings.Hue != 0 || _pictureSettings.Saturation != 0 || _pictureSettings.Brightness || _pictureSettings.Contrast; +} + +void DefaultVideoFilter::DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines) { OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions(); - - uint32_t* outputBuffer = (uint32_t*)GetOutputBuffer(); + double scanlineIntensity = 1.0 - EmulationSettings::GetPictureSettings().ScanlineIntensity; for(uint32_t i = overscan.Top, iMax = 240 - overscan.Bottom; i < iMax; i++) { - for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) { - *outputBuffer = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j]); - outputBuffer++; + if(displayScanlines && (i + overscan.Top) % 2 == 0) { + for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) { + *outputBuffer = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j], scanlineIntensity); + outputBuffer++; + } + } else { + for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) { + *outputBuffer = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j]); + outputBuffer++; + } } } } -uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel) +void DefaultVideoFilter::ApplyFilter(uint16_t *ppuOutputBuffer) +{ + DecodePpuBuffer(ppuOutputBuffer, (uint32_t*)GetOutputBuffer(), true); +} + +void DefaultVideoFilter::RgbToYiq(double r, double g, double b, double &y, double &i, double &q) +{ + y = r * 0.299f + g * 0.587f + b * 0.114f; + i = r * 0.596f - g * 0.275f - b * 0.321f; + q = r * 0.212f - g * 0.523f + b * 0.311f; +} + +void DefaultVideoFilter::YiqToRgb(double y, double i, double q, double &r, double &g, double &b) +{ + r = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[0] * i + _yiqToRgbMatrix[1] * q))); + g = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[2] * i + _yiqToRgbMatrix[3] * q))); + b = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[4] * i + _yiqToRgbMatrix[5] * q))); +} + +uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity) { uint32_t pixelOutput = EmulationSettings::GetRgbPalette()[ppuPixel & 0x3F]; @@ -49,10 +115,28 @@ uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel) greenChannel *= 0.9; } - uint8_t r, g, b; - r = (uint8_t)(redChannel > 255 ? 255 : redChannel); - g = (uint8_t)(greenChannel > 255 ? 255 : greenChannel); - b = (uint8_t)(blueChannel > 255 ? 255 : blueChannel); + redChannel = (float)(redChannel > 255 ? 255 : redChannel) / 255.0; + greenChannel = (float)(greenChannel > 255 ? 255 : greenChannel) / 255.0; + blueChannel = (float)(blueChannel > 255 ? 255 : blueChannel) / 255.0; + + //Apply brightness, contrast, hue & saturation + if(_needToProcess) { + double y, i, q; + RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q); + y *= _pictureSettings.Contrast * 0.5f + 1; + y += _pictureSettings.Brightness * 0.5f; + YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel); + } + + if(scanlineIntensity < 1.0) { + redChannel *= scanlineIntensity; + greenChannel *= scanlineIntensity; + blueChannel *= scanlineIntensity; + } + + int r = std::min(255, (int)(redChannel * 255)); + int g = std::min(255, (int)(greenChannel * 255)); + int b = std::min(255, (int)(blueChannel * 255)); return 0xFF000000 | (r << 16) | (g << 8) | b; } \ No newline at end of file diff --git a/Core/DefaultVideoFilter.h b/Core/DefaultVideoFilter.h index b44fec69..d7e1dc28 100644 --- a/Core/DefaultVideoFilter.h +++ b/Core/DefaultVideoFilter.h @@ -5,10 +5,23 @@ class DefaultVideoFilter : public BaseVideoFilter { +private: + double _yiqToRgbMatrix[6]; + PictureSettings _pictureSettings; + bool _needToProcess = false; + + void InitConversionMatrix(double hueShift, double saturationShift); + + void RgbToYiq(double r, double g, double b, double &y, double &i, double &q); + void YiqToRgb(double y, double i, double q, double &r, double &g, double &b); + protected: - uint32_t ProcessIntensifyBits(uint16_t ppuPixel); + void DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines); + uint32_t ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity = 1.0); + void OnBeforeApplyFilter(); public: + DefaultVideoFilter(); void ApplyFilter(uint16_t *ppuOutputBuffer); FrameInfo GetFrameInfo(); }; \ No newline at end of file diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp index 6bceabad..b95f5037 100644 --- a/Core/EmulationSettings.cpp +++ b/Core/EmulationSettings.cpp @@ -31,6 +31,8 @@ VideoFilterType EmulationSettings::_videoFilterType = VideoFilterType::None; VideoResizeFilter EmulationSettings::_resizeFilter = VideoResizeFilter::NearestNeighbor; double EmulationSettings::_videoScale = 1; VideoAspectRatio EmulationSettings::_aspectRatio = VideoAspectRatio::Auto; +PictureSettings EmulationSettings::_pictureSettings; +NtscFilterSettings EmulationSettings::_ntscFilterSettings; ConsoleType EmulationSettings::_consoleType = ConsoleType::Nes; ExpansionPortDevice EmulationSettings::_expansionDevice = ExpansionPortDevice::None; diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index 9ac9627e..193457b2 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -111,6 +111,26 @@ struct OverscanDimensions } }; +struct PictureSettings +{ + double Brightness = 0; + double Contrast = 0; + double Saturation = 0; + double Hue = 0; + double ScanlineIntensity = 0; +}; + +struct NtscFilterSettings +{ + double Sharpness = 0; + double Gamma = 0; + double Resolution = 0; + double Artifacts = 0; + double Fringing = 0; + double Bleed = 0; + bool MergeFields = false; +}; + enum class ConsoleType { Nes = 0, @@ -226,6 +246,8 @@ private: static double _videoScale; static VideoAspectRatio _aspectRatio; static VideoResizeFilter _resizeFilter; + static PictureSettings _pictureSettings; + static NtscFilterSettings _ntscFilterSettings; static ConsoleType _consoleType; static ExpansionPortDevice _expansionDevice; @@ -441,6 +463,37 @@ public: return _aspectRatio; } + static void SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity) + { + _pictureSettings.Brightness = brightness; + _pictureSettings.Contrast = contrast; + _pictureSettings.Saturation = saturation; + _pictureSettings.Hue = hue; + _pictureSettings.ScanlineIntensity = scanlineIntensity; + } + + static PictureSettings GetPictureSettings() + { + return _pictureSettings; + } + + static void SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, bool mergeFields) + { + _ntscFilterSettings.Artifacts = artifacts; + _ntscFilterSettings.Bleed = bleed; + _ntscFilterSettings.Fringing = fringing; + _ntscFilterSettings.Gamma = gamma; + _ntscFilterSettings.Resolution = resolution; + _ntscFilterSettings.Sharpness = sharpness; + + _ntscFilterSettings.MergeFields = mergeFields; + } + + static NtscFilterSettings GetNtscFilterSettings() + { + return _ntscFilterSettings; + } + static double GetAspectRatio() { switch(_aspectRatio) { diff --git a/Core/NtscFilter.cpp b/Core/NtscFilter.cpp index fdb1863c..92a74106 100644 --- a/Core/NtscFilter.cpp +++ b/Core/NtscFilter.cpp @@ -18,6 +18,32 @@ FrameInfo NtscFilter::GetFrameInfo() return { NES_NTSC_OUT_WIDTH(PPU::ScreenWidth) - overscanLeft - overscanRight, (PPU::ScreenHeight - overscan.Top - overscan.Bottom) * 2, 4 }; } +void NtscFilter::OnBeforeApplyFilter() +{ + PictureSettings pictureSettings = EmulationSettings::GetPictureSettings(); + NtscFilterSettings ntscSettings = EmulationSettings::GetNtscFilterSettings(); + if(_ntscSetup.hue != pictureSettings.Hue || _ntscSetup.saturation != pictureSettings.Saturation || _ntscSetup.brightness != pictureSettings.Brightness || _ntscSetup.contrast != pictureSettings.Contrast || + _ntscSetup.artifacts != ntscSettings.Artifacts || _ntscSetup.bleed != ntscSettings.Bleed || _ntscSetup.fringing != ntscSettings.Fringing || _ntscSetup.gamma != ntscSettings.Gamma || + (_ntscSetup.merge_fields == 1) != ntscSettings.MergeFields || _ntscSetup.resolution != ntscSettings.Resolution || _ntscSetup.sharpness != ntscSettings.Sharpness) { + + _ntscData = new nes_ntsc_t(); + _ntscSetup.hue = pictureSettings.Hue; + _ntscSetup.saturation = pictureSettings.Saturation; + _ntscSetup.brightness = pictureSettings.Brightness; + _ntscSetup.contrast = pictureSettings.Contrast; + + _ntscSetup.artifacts = ntscSettings.Artifacts; + _ntscSetup.bleed = ntscSettings.Bleed; + _ntscSetup.fringing = ntscSettings.Fringing; + _ntscSetup.gamma = ntscSettings.Gamma; + _ntscSetup.merge_fields = (int)ntscSettings.MergeFields; + _ntscSetup.resolution = ntscSettings.Resolution; + _ntscSetup.sharpness = ntscSettings.Sharpness; + + nes_ntsc_init(_ntscData, &_ntscSetup); + } +} + void NtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer) { static bool oddFrame = false; @@ -38,6 +64,8 @@ void NtscFilter::DoubleOutputHeight(uint32_t *ntscBuffer) int rowWidth = NES_NTSC_OUT_WIDTH(PPU::ScreenWidth); int rowWidthOverscan = rowWidth - overscanLeft - overscanRight; + double scanlineIntensity = 1.0 - EmulationSettings::GetPictureSettings().ScanlineIntensity; + for(int y = PPU::ScreenHeight - 1 - overscan.Bottom; y >= (int)overscan.Top; y--) { uint32_t const* in = ntscBuffer + y * rowWidth; uint32_t* out = outputBuffer + (y - overscan.Top) * 2 * rowWidthOverscan; @@ -46,11 +74,20 @@ void NtscFilter::DoubleOutputHeight(uint32_t *ntscBuffer) uint32_t prev = in[overscanLeft]; uint32_t next = y < 239 ? in[overscanLeft + rowWidth] : 0; - /* mix 24-bit rgb without losing low bits */ - uint64_t mixed = prev + next + ((prev ^ next) & 0x030303); - /* darken color */ *out = prev; - *(out + rowWidthOverscan) = (uint32_t)((mixed >> 1) - (mixed >> 4 & 0x0F0F0F)); + + /* mix 24-bit rgb without losing low bits */ + uint32_t mixed = (prev + next + ((prev ^ next) & 0x030303)) >> 1; + + if(scanlineIntensity < 1.0) { + uint8_t r = (mixed >> 16) & 0xFF, g = (mixed >> 8) & 0xFF, b = mixed & 0xFF; + r = (uint8_t)(r * scanlineIntensity); + g = (uint8_t)(g * scanlineIntensity); + b = (uint8_t)(b * scanlineIntensity); + *(out + rowWidthOverscan) = (r << 16) | (g << 8) | b; + } else { + *(out + rowWidthOverscan) = mixed; + } in++; out++; } diff --git a/Core/NtscFilter.h b/Core/NtscFilter.h index 0c88e287..fb6e0d7d 100644 --- a/Core/NtscFilter.h +++ b/Core/NtscFilter.h @@ -11,6 +11,9 @@ private: void DoubleOutputHeight(uint32_t *outputBuffer); +protected: + void OnBeforeApplyFilter(); + public: NtscFilter(); virtual ~NtscFilter(); diff --git a/Core/ScaleFilter.cpp b/Core/ScaleFilter.cpp index 519da72b..a1fbcd87 100644 --- a/Core/ScaleFilter.cpp +++ b/Core/ScaleFilter.cpp @@ -33,34 +33,42 @@ FrameInfo ScaleFilter::GetFrameInfo() void ScaleFilter::ApplyFilter(uint16_t *ppuOutputBuffer) { + DecodePpuBuffer(ppuOutputBuffer, _decodedPpuBuffer, false); + OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions(); - - uint32_t* outputBuffer = _decodedPpuBuffer; - for(uint32_t i = overscan.Top, iMax = 240 - overscan.Bottom; i < iMax; i++) { - for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) { - *outputBuffer = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j]); - outputBuffer++; - } - } - uint32_t height = overscan.GetScreenHeight(); uint32_t width = overscan.GetScreenWidth(); + uint32_t* outputBuffer = (uint32_t*)GetOutputBuffer(); if(_scaleFilterType == ScaleFilterType::xBRZ) { - xbrz::scale(_filterScale, _decodedPpuBuffer, (uint32_t*)GetOutputBuffer(), width, height, xbrz::ColorFormat::ARGB); + xbrz::scale(_filterScale, _decodedPpuBuffer, outputBuffer, width, height, xbrz::ColorFormat::ARGB); } else if(_scaleFilterType == ScaleFilterType::HQX) { switch(_filterScale) { - case 2: hq2x_32(_decodedPpuBuffer, (uint32_t*)GetOutputBuffer(), width, height); break; - case 3: hq3x_32(_decodedPpuBuffer, (uint32_t*)GetOutputBuffer(), width, height); break; - case 4: hq4x_32(_decodedPpuBuffer, (uint32_t*)GetOutputBuffer(), width, height); break; + case 2: hq2x_32(_decodedPpuBuffer, outputBuffer, width, height); break; + case 3: hq3x_32(_decodedPpuBuffer, outputBuffer, width, height); break; + case 4: hq4x_32(_decodedPpuBuffer, outputBuffer, width, height); break; } } else if(_scaleFilterType == ScaleFilterType::Scale2x) { - scale(_filterScale, GetOutputBuffer(), width*sizeof(uint32_t)*_filterScale, _decodedPpuBuffer, width*sizeof(uint32_t), 4, width, height); + scale(_filterScale, outputBuffer, width*sizeof(uint32_t)*_filterScale, _decodedPpuBuffer, width*sizeof(uint32_t), 4, width, height); } else if(_scaleFilterType == ScaleFilterType::_2xSai) { - twoxsai_generic_xrgb8888(width, height, _decodedPpuBuffer, width, (uint32_t*)GetOutputBuffer(), width * _filterScale); + twoxsai_generic_xrgb8888(width, height, _decodedPpuBuffer, width, outputBuffer, width * _filterScale); } else if(_scaleFilterType == ScaleFilterType::Super2xSai) { - supertwoxsai_generic_xrgb8888(width, height, _decodedPpuBuffer, width, (uint32_t*)GetOutputBuffer(), width * _filterScale); + supertwoxsai_generic_xrgb8888(width, height, _decodedPpuBuffer, width, outputBuffer, width * _filterScale); } else if(_scaleFilterType == ScaleFilterType::SuperEagle) { - supereagle_generic_xrgb8888(width, height, _decodedPpuBuffer, width, (uint32_t*)GetOutputBuffer(), width * _filterScale); + supereagle_generic_xrgb8888(width, height, _decodedPpuBuffer, width, outputBuffer, width * _filterScale); + } + + double scanlineIntensity = 1.0 - EmulationSettings::GetPictureSettings().ScanlineIntensity; + if(scanlineIntensity < 1.0) { + for(int y = 1, yMax = height * _filterScale; y < yMax; y += 2) { + for(int x = 0, xMax = width * _filterScale; x < xMax; x++) { + uint32_t &color = outputBuffer[y*xMax + x]; + uint8_t r = (color >> 16) & 0xFF, g = (color >> 8) & 0xFF, b = color & 0xFF; + r = (uint8_t)(r * scanlineIntensity); + g = (uint8_t)(g * scanlineIntensity); + b = (uint8_t)(b * scanlineIntensity); + color = (r << 16) | (g << 8) | b; + } + } } } \ No newline at end of file diff --git a/GUI.NET/Config/VideoInfo.cs b/GUI.NET/Config/VideoInfo.cs index 80e5194b..c0295dfc 100644 --- a/GUI.NET/Config/VideoInfo.cs +++ b/GUI.NET/Config/VideoInfo.cs @@ -25,6 +25,20 @@ namespace Mesen.GUI.Config public bool UseHdPacks = false; public Int32[] Palette = new Int32[0]; + public Int32 Brightness = 0; + public Int32 Contrast = 0; + public Int32 Hue = 0; + public Int32 Saturation = 0; + public Int32 ScanlineIntensity = 0; + + public Int32 NtscArtifacts = 0; + public Int32 NtscBleed = 0; + public Int32 NtscFringing = 0; + public Int32 NtscGamma = 0; + public Int32 NtscResolution = 0; + public Int32 NtscSharpness = 0; + public bool NtscMergeFields = false; + public VideoInfo() { } @@ -46,6 +60,9 @@ namespace Mesen.GUI.Config InteropEmu.SetVideoScale(videoInfo.VideoScale); InteropEmu.SetVideoAspectRatio(videoInfo.AspectRatio); + InteropEmu.SetPictureSettings(videoInfo.Brightness / 100.0, videoInfo.Contrast / 100.0, videoInfo.Saturation / 100.0, videoInfo.Hue / 100.0, videoInfo.ScanlineIntensity / 100.0); + InteropEmu.SetNtscFilterSettings(videoInfo.NtscArtifacts / 100.0, videoInfo.NtscBleed / 100.0, videoInfo.NtscFringing / 100.0, videoInfo.NtscGamma / 100.0, videoInfo.NtscResolution / 100.0, videoInfo.NtscSharpness / 100.0, videoInfo.NtscMergeFields); + if(videoInfo.Palette.Length == 64) { InteropEmu.SetRgbPalette(videoInfo.Palette); } diff --git a/GUI.NET/Controls/ctrlHorizontalTrackbar.Designer.cs b/GUI.NET/Controls/ctrlHorizontalTrackbar.Designer.cs new file mode 100644 index 00000000..e145057d --- /dev/null +++ b/GUI.NET/Controls/ctrlHorizontalTrackbar.Designer.cs @@ -0,0 +1,121 @@ +namespace Mesen.GUI.Controls +{ + partial class ctrlHorizontalTrackbar + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.trackBar = new System.Windows.Forms.TrackBar(); + this.txtValue = new System.Windows.Forms.TextBox(); + this.lblText = new System.Windows.Forms.Label(); + this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBar)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.trackBar, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.txtValue, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.lblText, 0, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(206, 55); + this.tableLayoutPanel1.TabIndex = 0; + // + // trackBar + // + this.trackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.trackBar.Dock = System.Windows.Forms.DockStyle.Fill; + this.trackBar.Location = new System.Drawing.Point(0, 20); + this.trackBar.Margin = new System.Windows.Forms.Padding(0); + this.trackBar.Maximum = 100; + this.trackBar.Minimum = -100; + this.trackBar.Name = "trackBar"; + this.trackBar.Size = new System.Drawing.Size(172, 35); + this.trackBar.TabIndex = 13; + this.trackBar.TickFrequency = 10; + this.trackBar.Value = 50; + this.trackBar.ValueChanged += new System.EventHandler(this.trackBar_ValueChanged); + // + // txtValue + // + this.txtValue.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.txtValue.BackColor = System.Drawing.Color.White; + this.txtValue.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtValue.Location = new System.Drawing.Point(175, 23); + this.txtValue.Multiline = true; + this.txtValue.Name = "txtValue"; + this.txtValue.ReadOnly = true; + this.txtValue.Size = new System.Drawing.Size(28, 17); + this.txtValue.TabIndex = 17; + this.txtValue.TabStop = false; + this.txtValue.Text = "100"; + this.txtValue.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // lblText + // + this.lblText.AutoSize = true; + this.lblText.Dock = System.Windows.Forms.DockStyle.Fill; + this.lblText.Location = new System.Drawing.Point(3, 0); + this.lblText.Name = "lblText"; + this.lblText.Size = new System.Drawing.Size(166, 20); + this.lblText.TabIndex = 18; + this.lblText.Text = "Text"; + this.lblText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // ctrlHorizontalTrackbar + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel1); + this.Margin = new System.Windows.Forms.Padding(0); + this.MaximumSize = new System.Drawing.Size(400, 55); + this.MinimumSize = new System.Drawing.Size(206, 55); + this.Name = "ctrlHorizontalTrackbar"; + this.Size = new System.Drawing.Size(206, 55); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBar)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.TrackBar trackBar; + private System.Windows.Forms.TextBox txtValue; + private System.Windows.Forms.Label lblText; + } +} diff --git a/GUI.NET/Controls/ctrlHorizontalTrackbar.cs b/GUI.NET/Controls/ctrlHorizontalTrackbar.cs new file mode 100644 index 00000000..62389074 --- /dev/null +++ b/GUI.NET/Controls/ctrlHorizontalTrackbar.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Mesen.GUI.Controls +{ + public partial class ctrlHorizontalTrackbar : UserControl + { + public event EventHandler ValueChanged + { + add { trackBar.ValueChanged += value; } + remove { trackBar.ValueChanged -= value; } + } + + public ctrlHorizontalTrackbar() + { + InitializeComponent(); + } + + public int Maximum + { + get { return trackBar.Maximum; } + set { trackBar.Maximum = value; } + } + + public int Minimum + { + get { return trackBar.Minimum; } + set { trackBar.Minimum = value; } + } + + [Bindable(true)] + [Browsable(true)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] + [EditorBrowsable(EditorBrowsableState.Always)] + public override string Text + { + get { return lblText.Text; } + set { lblText.Text = value; } + } + + public int Value + { + get { return trackBar.Value; } + set + { + trackBar.Value = value; + txtValue.Text = trackBar.Value.ToString(); + } + } + + private void trackBar_ValueChanged(object sender, EventArgs e) + { + txtValue.Text = trackBar.Value.ToString(); + } + } +} diff --git a/GUI.NET/Controls/ctrlHorizontalTrackbar.resx b/GUI.NET/Controls/ctrlHorizontalTrackbar.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Controls/ctrlHorizontalTrackbar.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Dependencies/resources.fr.xml b/GUI.NET/Dependencies/resources.fr.xml index 4078ff60..287196b4 100644 --- a/GUI.NET/Dependencies/resources.fr.xml +++ b/GUI.NET/Dependencies/resources.fr.xml @@ -173,6 +173,23 @@ Palette Réinitialiser Charger fichier .pal + Image + Paramètres communs + Luminosité + Contraste + Teinte + Saturation + Paramètres du filtre NTSC + Artefact + Dispersion des couleurs + Franges de distorsion + Gamma + Résolution + Piqué + Combiner les images alternées + Lignes de balayage + Lignes de balayage + Réinitialiser OK Annuler diff --git a/GUI.NET/Dependencies/resources.ja.xml b/GUI.NET/Dependencies/resources.ja.xml index 408bbd42..bd0bcc11 100644 --- a/GUI.NET/Dependencies/resources.ja.xml +++ b/GUI.NET/Dependencies/resources.ja.xml @@ -173,6 +173,23 @@ パレット リセット .palファイルをロードする + 画像 + 共通設定 + 明るさ + コントラスト + 色相 + 彩度 + NTSCエフェクトの設定 + アーティファクト + 色にじみ + フリンジ + ガンマ + 解像度 + シャープネス + 画像をマージする + 走査線 + 走査線 + リセット OK キャンセル diff --git a/GUI.NET/Forms/BaseConfigForm.cs b/GUI.NET/Forms/BaseConfigForm.cs index 3a88b24e..ddd38fed 100644 --- a/GUI.NET/Forms/BaseConfigForm.cs +++ b/GUI.NET/Forms/BaseConfigForm.cs @@ -175,8 +175,14 @@ namespace Mesen.GUI.Forms } } else if(kvp.Value is ctrlTrackbar) { ((ctrlTrackbar)kvp.Value).Value = (int)(uint)value; + } else if(kvp.Value is ctrlHorizontalTrackbar) { + ((ctrlHorizontalTrackbar)kvp.Value).Value = (int)value; } else if(kvp.Value is TrackBar) { - ((TrackBar)kvp.Value).Value = (int)(uint)value; + if(field.FieldType == typeof(Int32)) { + ((TrackBar)kvp.Value).Value = (int)value; + } else { + ((TrackBar)kvp.Value).Value = (int)(uint)value; + } } else if(kvp.Value is NumericUpDown) { NumericUpDown nud = kvp.Value as NumericUpDown; decimal val; @@ -248,8 +254,14 @@ namespace Mesen.GUI.Forms field.SetValue(Entity, kvp.Value.Controls.OfType().FirstOrDefault(r => r.Checked).Tag); } else if(kvp.Value is ctrlTrackbar) { field.SetValue(Entity, (UInt32)((ctrlTrackbar)kvp.Value).Value); + } else if(kvp.Value is ctrlHorizontalTrackbar) { + field.SetValue(Entity, (Int32)((ctrlHorizontalTrackbar)kvp.Value).Value); } else if(kvp.Value is TrackBar) { - field.SetValue(Entity, (UInt32)((TrackBar)kvp.Value).Value); + if(field.FieldType == typeof(Int32)) { + field.SetValue(Entity, ((TrackBar)kvp.Value).Value); + } else { + field.SetValue(Entity, (UInt32)((TrackBar)kvp.Value).Value); + } } else if(kvp.Value is NumericUpDown) { if(field.FieldType == typeof(UInt32)) { field.SetValue(Entity, (UInt32)((NumericUpDown)kvp.Value).Value); diff --git a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs index 19efaeb8..625ffc88 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs +++ b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs @@ -43,6 +43,7 @@ this.picHdNesTooltip = new System.Windows.Forms.PictureBox(); this.nudScale = new System.Windows.Forms.NumericUpDown(); this.cboFilter = new System.Windows.Forms.ComboBox(); + this.chkBilinearInterpolation = new System.Windows.Forms.CheckBox(); this.tabMain = new System.Windows.Forms.TabControl(); this.tpgGeneral = new System.Windows.Forms.TabPage(); this.tpgOverscan = new System.Windows.Forms.TabPage(); @@ -61,6 +62,26 @@ this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); this.lblRight = new System.Windows.Forms.Label(); this.nudOverscanRight = new System.Windows.Forms.NumericUpDown(); + this.tpgPicture = new System.Windows.Forms.TabPage(); + this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel(); + this.btnResetPictureSettings = new System.Windows.Forms.Button(); + this.grpNtscFilter = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel(); + this.trkArtifacts = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkBleed = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkFringing = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkGamma = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkResolution = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkSharpness = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.chkMergeFields = new System.Windows.Forms.CheckBox(); + this.grpCommon = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.trkBrightness = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkContrast = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkHue = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.trkSaturation = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); + this.grpScanlines = new System.Windows.Forms.GroupBox(); + this.trkScanlines = new Mesen.GUI.Controls.ctrlHorizontalTrackbar(); this.tpgPalette = new System.Windows.Forms.TabPage(); this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); this.picPalette = new System.Windows.Forms.PictureBox(); @@ -68,7 +89,6 @@ this.btnResetPalette = new System.Windows.Forms.Button(); this.btnLoadPalFile = new System.Windows.Forms.Button(); this.colorDialog = new System.Windows.Forms.ColorDialog(); - this.chkBilinearInterpolation = new System.Windows.Forms.CheckBox(); this.tlpMain.SuspendLayout(); this.flowLayoutPanel6.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudEmulationSpeed)).BeginInit(); @@ -89,6 +109,13 @@ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanBottom)).BeginInit(); this.flowLayoutPanel2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudOverscanRight)).BeginInit(); + this.tpgPicture.SuspendLayout(); + this.tableLayoutPanel5.SuspendLayout(); + this.grpNtscFilter.SuspendLayout(); + this.tableLayoutPanel6.SuspendLayout(); + this.grpCommon.SuspendLayout(); + this.tableLayoutPanel4.SuspendLayout(); + this.grpScanlines.SuspendLayout(); this.tpgPalette.SuspendLayout(); this.tableLayoutPanel3.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.picPalette)).BeginInit(); @@ -97,7 +124,7 @@ // // baseConfigPanel // - this.baseConfigPanel.Location = new System.Drawing.Point(0, 368); + this.baseConfigPanel.Location = new System.Drawing.Point(0, 376); this.baseConfigPanel.Size = new System.Drawing.Size(515, 29); // // tlpMain @@ -131,7 +158,7 @@ this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpMain.Size = new System.Drawing.Size(501, 336); + this.tlpMain.Size = new System.Drawing.Size(501, 344); this.tlpMain.TabIndex = 1; // // lblVideoScale @@ -304,16 +331,29 @@ this.cboFilter.Size = new System.Drawing.Size(76, 21); this.cboFilter.TabIndex = 14; // + // chkBilinearInterpolation + // + this.chkBilinearInterpolation.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.chkBilinearInterpolation.AutoSize = true; + this.tlpMain.SetColumnSpan(this.chkBilinearInterpolation, 2); + this.chkBilinearInterpolation.Location = new System.Drawing.Point(3, 83); + this.chkBilinearInterpolation.Name = "chkBilinearInterpolation"; + this.chkBilinearInterpolation.Size = new System.Drawing.Size(206, 17); + this.chkBilinearInterpolation.TabIndex = 22; + this.chkBilinearInterpolation.Text = "Use bilinear interpolation when scaling"; + this.chkBilinearInterpolation.UseVisualStyleBackColor = true; + // // tabMain // this.tabMain.Controls.Add(this.tpgGeneral); this.tabMain.Controls.Add(this.tpgOverscan); + this.tabMain.Controls.Add(this.tpgPicture); this.tabMain.Controls.Add(this.tpgPalette); this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; this.tabMain.Location = new System.Drawing.Point(0, 0); this.tabMain.Name = "tabMain"; this.tabMain.SelectedIndex = 0; - this.tabMain.Size = new System.Drawing.Size(515, 368); + this.tabMain.Size = new System.Drawing.Size(515, 376); this.tabMain.TabIndex = 2; // // tpgGeneral @@ -322,7 +362,7 @@ this.tpgGeneral.Location = new System.Drawing.Point(4, 22); this.tpgGeneral.Name = "tpgGeneral"; this.tpgGeneral.Padding = new System.Windows.Forms.Padding(3); - this.tpgGeneral.Size = new System.Drawing.Size(507, 342); + this.tpgGeneral.Size = new System.Drawing.Size(507, 350); this.tpgGeneral.TabIndex = 0; this.tpgGeneral.Text = "General"; this.tpgGeneral.UseVisualStyleBackColor = true; @@ -333,7 +373,7 @@ this.tpgOverscan.Location = new System.Drawing.Point(4, 22); this.tpgOverscan.Name = "tpgOverscan"; this.tpgOverscan.Padding = new System.Windows.Forms.Padding(3); - this.tpgOverscan.Size = new System.Drawing.Size(507, 342); + this.tpgOverscan.Size = new System.Drawing.Size(507, 350); this.tpgOverscan.TabIndex = 1; this.tpgOverscan.Text = "Overscan"; this.tpgOverscan.UseVisualStyleBackColor = true; @@ -344,7 +384,7 @@ this.grpCropping.Dock = System.Windows.Forms.DockStyle.Fill; this.grpCropping.Location = new System.Drawing.Point(3, 3); this.grpCropping.Name = "grpCropping"; - this.grpCropping.Size = new System.Drawing.Size(501, 336); + this.grpCropping.Size = new System.Drawing.Size(501, 344); this.grpCropping.TabIndex = 8; this.grpCropping.TabStop = false; this.grpCropping.Text = "Video Cropping"; @@ -361,7 +401,7 @@ this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel4, 1, 0); this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel5, 1, 2); this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 2, 1); - this.tableLayoutPanel1.Location = new System.Drawing.Point(65, 8); + this.tableLayoutPanel1.Location = new System.Drawing.Point(65, 12); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 3; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -504,13 +544,315 @@ this.nudOverscanRight.TabIndex = 1; this.nudOverscanRight.ValueChanged += new System.EventHandler(this.nudOverscan_ValueChanged); // + // tpgPicture + // + this.tpgPicture.Controls.Add(this.tableLayoutPanel5); + this.tpgPicture.Location = new System.Drawing.Point(4, 22); + this.tpgPicture.Name = "tpgPicture"; + this.tpgPicture.Padding = new System.Windows.Forms.Padding(3); + this.tpgPicture.Size = new System.Drawing.Size(507, 350); + this.tpgPicture.TabIndex = 3; + this.tpgPicture.Text = "Picture"; + this.tpgPicture.UseVisualStyleBackColor = true; + // + // tableLayoutPanel5 + // + this.tableLayoutPanel5.ColumnCount = 2; + this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel5.Controls.Add(this.btnResetPictureSettings, 0, 2); + this.tableLayoutPanel5.Controls.Add(this.grpNtscFilter, 1, 0); + this.tableLayoutPanel5.Controls.Add(this.grpCommon, 0, 0); + this.tableLayoutPanel5.Controls.Add(this.grpScanlines, 0, 1); + this.tableLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel5.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel5.Name = "tableLayoutPanel5"; + this.tableLayoutPanel5.RowCount = 3; + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel5.Size = new System.Drawing.Size(501, 344); + this.tableLayoutPanel5.TabIndex = 5; + // + // btnResetPictureSettings + // + this.btnResetPictureSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnResetPictureSettings.AutoSize = true; + this.btnResetPictureSettings.Location = new System.Drawing.Point(3, 318); + this.btnResetPictureSettings.Name = "btnResetPictureSettings"; + this.btnResetPictureSettings.Size = new System.Drawing.Size(75, 23); + this.btnResetPictureSettings.TabIndex = 3; + this.btnResetPictureSettings.Text = "Reset"; + this.btnResetPictureSettings.UseVisualStyleBackColor = true; + this.btnResetPictureSettings.Click += new System.EventHandler(this.btnResetPictureSettings_Click); + // + // grpNtscFilter + // + this.grpNtscFilter.Controls.Add(this.tableLayoutPanel6); + this.grpNtscFilter.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpNtscFilter.Location = new System.Drawing.Point(252, 0); + this.grpNtscFilter.Margin = new System.Windows.Forms.Padding(2, 0, 0, 0); + this.grpNtscFilter.Name = "grpNtscFilter"; + this.tableLayoutPanel5.SetRowSpan(this.grpNtscFilter, 3); + this.grpNtscFilter.Size = new System.Drawing.Size(249, 344); + this.grpNtscFilter.TabIndex = 4; + this.grpNtscFilter.TabStop = false; + this.grpNtscFilter.Text = "NTSC Filter"; + // + // tableLayoutPanel6 + // + this.tableLayoutPanel6.ColumnCount = 1; + this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel6.Controls.Add(this.trkArtifacts, 0, 0); + this.tableLayoutPanel6.Controls.Add(this.trkBleed, 0, 1); + this.tableLayoutPanel6.Controls.Add(this.trkFringing, 0, 2); + this.tableLayoutPanel6.Controls.Add(this.trkGamma, 0, 3); + this.tableLayoutPanel6.Controls.Add(this.trkResolution, 0, 4); + this.tableLayoutPanel6.Controls.Add(this.trkSharpness, 0, 5); + this.tableLayoutPanel6.Controls.Add(this.chkMergeFields, 0, 6); + this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel6.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel6.Name = "tableLayoutPanel6"; + this.tableLayoutPanel6.RowCount = 7; + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel6.Size = new System.Drawing.Size(243, 325); + this.tableLayoutPanel6.TabIndex = 5; + // + // trkArtifacts + // + this.trkArtifacts.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkArtifacts.Location = new System.Drawing.Point(0, 0); + this.trkArtifacts.Margin = new System.Windows.Forms.Padding(0); + this.trkArtifacts.Maximum = 100; + this.trkArtifacts.MaximumSize = new System.Drawing.Size(0, 60); + this.trkArtifacts.Minimum = -100; + this.trkArtifacts.MinimumSize = new System.Drawing.Size(206, 50); + this.trkArtifacts.Name = "trkArtifacts"; + this.trkArtifacts.Size = new System.Drawing.Size(243, 50); + this.trkArtifacts.TabIndex = 24; + this.trkArtifacts.Text = "Artifacts"; + this.trkArtifacts.Value = 0; + // + // trkBleed + // + this.trkBleed.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBleed.Location = new System.Drawing.Point(0, 50); + this.trkBleed.Margin = new System.Windows.Forms.Padding(0); + this.trkBleed.Maximum = 100; + this.trkBleed.MaximumSize = new System.Drawing.Size(400, 55); + this.trkBleed.Minimum = -100; + this.trkBleed.MinimumSize = new System.Drawing.Size(206, 50); + this.trkBleed.Name = "trkBleed"; + this.trkBleed.Size = new System.Drawing.Size(243, 50); + this.trkBleed.TabIndex = 25; + this.trkBleed.Text = "Bleed"; + this.trkBleed.Value = 0; + // + // trkFringing + // + this.trkFringing.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkFringing.Location = new System.Drawing.Point(0, 100); + this.trkFringing.Margin = new System.Windows.Forms.Padding(0); + this.trkFringing.Maximum = 100; + this.trkFringing.MaximumSize = new System.Drawing.Size(0, 41); + this.trkFringing.Minimum = -100; + this.trkFringing.MinimumSize = new System.Drawing.Size(206, 50); + this.trkFringing.Name = "trkFringing"; + this.trkFringing.Size = new System.Drawing.Size(243, 50); + this.trkFringing.TabIndex = 26; + this.trkFringing.Text = "Fringing"; + this.trkFringing.Value = 0; + // + // trkGamma + // + this.trkGamma.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkGamma.Location = new System.Drawing.Point(0, 150); + this.trkGamma.Margin = new System.Windows.Forms.Padding(0); + this.trkGamma.Maximum = 100; + this.trkGamma.MaximumSize = new System.Drawing.Size(0, 41); + this.trkGamma.Minimum = -100; + this.trkGamma.MinimumSize = new System.Drawing.Size(206, 50); + this.trkGamma.Name = "trkGamma"; + this.trkGamma.Size = new System.Drawing.Size(243, 50); + this.trkGamma.TabIndex = 27; + this.trkGamma.Text = "Gamma"; + this.trkGamma.Value = 0; + // + // trkResolution + // + this.trkResolution.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkResolution.Location = new System.Drawing.Point(0, 200); + this.trkResolution.Margin = new System.Windows.Forms.Padding(0); + this.trkResolution.Maximum = 100; + this.trkResolution.MaximumSize = new System.Drawing.Size(0, 41); + this.trkResolution.Minimum = -100; + this.trkResolution.MinimumSize = new System.Drawing.Size(206, 50); + this.trkResolution.Name = "trkResolution"; + this.trkResolution.Size = new System.Drawing.Size(243, 50); + this.trkResolution.TabIndex = 28; + this.trkResolution.Text = "Resolution"; + this.trkResolution.Value = 0; + // + // trkSharpness + // + this.trkSharpness.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkSharpness.Location = new System.Drawing.Point(0, 250); + this.trkSharpness.Margin = new System.Windows.Forms.Padding(0); + this.trkSharpness.Maximum = 100; + this.trkSharpness.MaximumSize = new System.Drawing.Size(0, 41); + this.trkSharpness.Minimum = -100; + this.trkSharpness.MinimumSize = new System.Drawing.Size(206, 50); + this.trkSharpness.Name = "trkSharpness"; + this.trkSharpness.Size = new System.Drawing.Size(243, 50); + this.trkSharpness.TabIndex = 29; + this.trkSharpness.Text = "Sharpness"; + this.trkSharpness.Value = 0; + // + // chkMergeFields + // + this.chkMergeFields.AutoSize = true; + this.chkMergeFields.Location = new System.Drawing.Point(3, 303); + this.chkMergeFields.Name = "chkMergeFields"; + this.chkMergeFields.Size = new System.Drawing.Size(86, 17); + this.chkMergeFields.TabIndex = 30; + this.chkMergeFields.Text = "Merge Fields"; + this.chkMergeFields.UseVisualStyleBackColor = true; + // + // grpCommon + // + this.grpCommon.Controls.Add(this.tableLayoutPanel4); + this.grpCommon.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpCommon.Location = new System.Drawing.Point(0, 0); + this.grpCommon.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); + this.grpCommon.Name = "grpCommon"; + this.grpCommon.Size = new System.Drawing.Size(248, 217); + this.grpCommon.TabIndex = 3; + this.grpCommon.TabStop = false; + this.grpCommon.Text = "Common Settings"; + // + // tableLayoutPanel4 + // + this.tableLayoutPanel4.ColumnCount = 1; + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel4.Controls.Add(this.trkBrightness, 0, 0); + this.tableLayoutPanel4.Controls.Add(this.trkContrast, 0, 1); + this.tableLayoutPanel4.Controls.Add(this.trkHue, 0, 2); + this.tableLayoutPanel4.Controls.Add(this.trkSaturation, 0, 3); + this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel4.Name = "tableLayoutPanel4"; + this.tableLayoutPanel4.RowCount = 5; + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.Size = new System.Drawing.Size(242, 198); + this.tableLayoutPanel4.TabIndex = 4; + // + // trkBrightness + // + this.trkBrightness.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkBrightness.Location = new System.Drawing.Point(0, 0); + this.trkBrightness.Margin = new System.Windows.Forms.Padding(0); + this.trkBrightness.Maximum = 100; + this.trkBrightness.MaximumSize = new System.Drawing.Size(0, 60); + this.trkBrightness.Minimum = -100; + this.trkBrightness.MinimumSize = new System.Drawing.Size(206, 50); + this.trkBrightness.Name = "trkBrightness"; + this.trkBrightness.Size = new System.Drawing.Size(242, 50); + this.trkBrightness.TabIndex = 24; + this.trkBrightness.Text = "Brightness"; + this.trkBrightness.Value = 0; + // + // trkContrast + // + this.trkContrast.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkContrast.Location = new System.Drawing.Point(0, 50); + this.trkContrast.Margin = new System.Windows.Forms.Padding(0); + this.trkContrast.Maximum = 100; + this.trkContrast.MaximumSize = new System.Drawing.Size(400, 55); + this.trkContrast.Minimum = -100; + this.trkContrast.MinimumSize = new System.Drawing.Size(206, 50); + this.trkContrast.Name = "trkContrast"; + this.trkContrast.Size = new System.Drawing.Size(242, 50); + this.trkContrast.TabIndex = 25; + this.trkContrast.Text = "Contrast"; + this.trkContrast.Value = 0; + // + // trkHue + // + this.trkHue.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkHue.Location = new System.Drawing.Point(0, 100); + this.trkHue.Margin = new System.Windows.Forms.Padding(0); + this.trkHue.Maximum = 100; + this.trkHue.MaximumSize = new System.Drawing.Size(0, 41); + this.trkHue.Minimum = -100; + this.trkHue.MinimumSize = new System.Drawing.Size(206, 50); + this.trkHue.Name = "trkHue"; + this.trkHue.Size = new System.Drawing.Size(242, 50); + this.trkHue.TabIndex = 26; + this.trkHue.Text = "Hue"; + this.trkHue.Value = 0; + // + // trkSaturation + // + this.trkSaturation.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkSaturation.Location = new System.Drawing.Point(0, 150); + this.trkSaturation.Margin = new System.Windows.Forms.Padding(0); + this.trkSaturation.Maximum = 100; + this.trkSaturation.MaximumSize = new System.Drawing.Size(0, 41); + this.trkSaturation.Minimum = -100; + this.trkSaturation.MinimumSize = new System.Drawing.Size(206, 50); + this.trkSaturation.Name = "trkSaturation"; + this.trkSaturation.Size = new System.Drawing.Size(242, 50); + this.trkSaturation.TabIndex = 27; + this.trkSaturation.Text = "Saturation"; + this.trkSaturation.Value = 0; + // + // grpScanlines + // + this.grpScanlines.Controls.Add(this.trkScanlines); + this.grpScanlines.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpScanlines.Location = new System.Drawing.Point(3, 220); + this.grpScanlines.Name = "grpScanlines"; + this.grpScanlines.Size = new System.Drawing.Size(244, 72); + this.grpScanlines.TabIndex = 5; + this.grpScanlines.TabStop = false; + this.grpScanlines.Text = "Scanlines"; + // + // trkScanlines + // + this.trkScanlines.Dock = System.Windows.Forms.DockStyle.Fill; + this.trkScanlines.Location = new System.Drawing.Point(3, 16); + this.trkScanlines.Margin = new System.Windows.Forms.Padding(0); + this.trkScanlines.Maximum = 100; + this.trkScanlines.MaximumSize = new System.Drawing.Size(0, 41); + this.trkScanlines.Minimum = 0; + this.trkScanlines.MinimumSize = new System.Drawing.Size(206, 50); + this.trkScanlines.Name = "trkScanlines"; + this.trkScanlines.Size = new System.Drawing.Size(238, 50); + this.trkScanlines.TabIndex = 28; + this.trkScanlines.Text = "Scanlines"; + this.trkScanlines.Value = 0; + // // tpgPalette // this.tpgPalette.Controls.Add(this.tableLayoutPanel3); this.tpgPalette.Location = new System.Drawing.Point(4, 22); this.tpgPalette.Name = "tpgPalette"; this.tpgPalette.Padding = new System.Windows.Forms.Padding(3); - this.tpgPalette.Size = new System.Drawing.Size(507, 342); + this.tpgPalette.Size = new System.Drawing.Size(507, 350); this.tpgPalette.TabIndex = 2; this.tpgPalette.Text = "Palette"; this.tpgPalette.UseVisualStyleBackColor = true; @@ -529,7 +871,7 @@ this.tableLayoutPanel3.RowCount = 2; this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.Size = new System.Drawing.Size(501, 336); + this.tableLayoutPanel3.Size = new System.Drawing.Size(501, 344); this.tableLayoutPanel3.TabIndex = 4; // // picPalette @@ -584,23 +926,11 @@ this.btnLoadPalFile.UseVisualStyleBackColor = true; this.btnLoadPalFile.Click += new System.EventHandler(this.btnLoadPalFile_Click); // - // chkBilinearInterpolation - // - this.chkBilinearInterpolation.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.chkBilinearInterpolation.AutoSize = true; - this.tlpMain.SetColumnSpan(this.chkBilinearInterpolation, 2); - this.chkBilinearInterpolation.Location = new System.Drawing.Point(3, 83); - this.chkBilinearInterpolation.Name = "chkBilinearInterpolation"; - this.chkBilinearInterpolation.Size = new System.Drawing.Size(206, 17); - this.chkBilinearInterpolation.TabIndex = 22; - this.chkBilinearInterpolation.Text = "Use bilinear interpolation when scaling"; - this.chkBilinearInterpolation.UseVisualStyleBackColor = true; - // // frmVideoConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(515, 397); + this.ClientSize = new System.Drawing.Size(515, 405); this.Controls.Add(this.tabMain); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MaximizeBox = false; @@ -637,6 +967,15 @@ this.flowLayoutPanel2.ResumeLayout(false); this.flowLayoutPanel2.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudOverscanRight)).EndInit(); + this.tpgPicture.ResumeLayout(false); + this.tableLayoutPanel5.ResumeLayout(false); + this.tableLayoutPanel5.PerformLayout(); + this.grpNtscFilter.ResumeLayout(false); + this.tableLayoutPanel6.ResumeLayout(false); + this.tableLayoutPanel6.PerformLayout(); + this.grpCommon.ResumeLayout(false); + this.tableLayoutPanel4.ResumeLayout(false); + this.grpScanlines.ResumeLayout(false); this.tpgPalette.ResumeLayout(false); this.tableLayoutPanel3.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.picPalette)).EndInit(); @@ -690,5 +1029,25 @@ private System.Windows.Forms.ColorDialog colorDialog; private System.Windows.Forms.NumericUpDown nudScale; private System.Windows.Forms.CheckBox chkBilinearInterpolation; + private System.Windows.Forms.TabPage tpgPicture; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; + private Controls.ctrlHorizontalTrackbar trkBrightness; + private Controls.ctrlHorizontalTrackbar trkContrast; + private Controls.ctrlHorizontalTrackbar trkHue; + private Controls.ctrlHorizontalTrackbar trkSaturation; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; + private System.Windows.Forms.GroupBox grpNtscFilter; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; + private Controls.ctrlHorizontalTrackbar trkArtifacts; + private Controls.ctrlHorizontalTrackbar trkBleed; + private Controls.ctrlHorizontalTrackbar trkFringing; + private Controls.ctrlHorizontalTrackbar trkGamma; + private Controls.ctrlHorizontalTrackbar trkResolution; + private Controls.ctrlHorizontalTrackbar trkSharpness; + private System.Windows.Forms.GroupBox grpCommon; + private System.Windows.Forms.CheckBox chkMergeFields; + private System.Windows.Forms.Button btnResetPictureSettings; + private System.Windows.Forms.GroupBox grpScanlines; + private Controls.ctrlHorizontalTrackbar trkScanlines; } } \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmVideoConfig.cs b/GUI.NET/Forms/Config/frmVideoConfig.cs index 8b386b5b..3e750887 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.cs +++ b/GUI.NET/Forms/Config/frmVideoConfig.cs @@ -38,6 +38,20 @@ namespace Mesen.GUI.Forms.Config AddBinding("OverscanTop", nudOverscanTop); AddBinding("OverscanBottom", nudOverscanBottom); + AddBinding("Brightness", trkBrightness); + AddBinding("Contrast", trkContrast); + AddBinding("Hue", trkHue); + AddBinding("Saturation", trkSaturation); + AddBinding("ScanlineIntensity", trkScanlines); + + AddBinding("NtscArtifacts", trkArtifacts); + AddBinding("NtscBleed", trkBleed); + AddBinding("NtscFringing", trkFringing); + AddBinding("NtscGamma", trkGamma); + AddBinding("NtscResolution", trkResolution); + AddBinding("NtscSharpness", trkSharpness); + AddBinding("NtscMergeFields", chkMergeFields); + _paletteData = InteropEmu.GetRgbPalette(); RefreshPalette(); @@ -45,7 +59,14 @@ namespace Mesen.GUI.Forms.Config UpdateOverscanImage(); } - + + protected override bool ValidateInput() + { + UpdateObject(); + VideoInfo.ApplyConfig(); + return true; + } + protected override void OnFormClosed(FormClosedEventArgs e) { if(DialogResult == System.Windows.Forms.DialogResult.OK) { @@ -147,5 +168,23 @@ namespace Mesen.GUI.Forms.Config { UpdateOverscanImage(); } + + private void btnResetPictureSettings_Click(object sender, EventArgs e) + { + trkBrightness.Value = 0; + trkContrast.Value = 0; + trkHue.Value = 0; + trkSaturation.Value = 0; + + trkScanlines.Value = 0; + + trkArtifacts.Value = 0; + trkBleed.Value = 0; + trkFringing.Value = 0; + trkGamma.Value = 0; + trkResolution.Value = 0; + trkSharpness.Value = 0; + chkMergeFields.Checked = false; + } } } diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index ca0a2e47..a494e27f 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -219,6 +219,12 @@ + + UserControl + + + ctrlHorizontalTrackbar.cs + UserControl @@ -479,6 +485,9 @@ + + ctrlHorizontalTrackbar.cs + ctrlTrackbar.cs diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 1e276dfa..78aec94e 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -118,6 +118,9 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void SetVideoFilter(VideoFilterType filter); [DllImport(DLLPath)] public static extern void SetVideoResizeFilter(VideoResizeFilter filter); [DllImport(DLLPath)] public static extern void SetRgbPalette(Int32[] palette); + [DllImport(DLLPath)] public static extern void SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity); + [DllImport(DLLPath)] public static extern void SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, [MarshalAs(UnmanagedType.I1)]bool mergeFields); + [DllImport(DLLPath, EntryPoint="GetRgbPalette")] private static extern void GetRgbPaletteWrapper(IntPtr paletteBuffer); [DllImport(DLLPath, EntryPoint="GetScreenSize")] private static extern void GetScreenSizeWrapper(out ScreenSize size, [MarshalAs(UnmanagedType.I1)]bool ignoreScale); diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 707b8c30..3251ebb3 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -269,6 +269,8 @@ namespace InteropEmu { DllExport void __stdcall SetVideoResizeFilter(VideoResizeFilter filter) { EmulationSettings::SetVideoResizeFilter(filter); } DllExport void __stdcall GetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::GetRgbPalette(paletteBuffer); } DllExport void __stdcall SetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::SetRgbPalette(paletteBuffer); } + DllExport void __stdcall SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity) { EmulationSettings::SetPictureSettings(brightness, contrast, saturation, hue, scanlineIntensity); } + DllExport void __stdcall SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, bool mergeFields) { EmulationSettings::SetNtscFilterSettings(artifacts, bleed, fringing, gamma, resolution, sharpness, mergeFields); } DllExport const char* __stdcall GetAudioDevices() {