From 117a4b073d2007277be387b0dc54ec74f164f6f2 Mon Sep 17 00:00:00 2001 From: Souryo Date: Sun, 17 Jan 2016 14:21:31 -0500 Subject: [PATCH] Video: Added customizable RGB palette --- Core/DefaultVideoFilter.cpp | 4 +- Core/EmulationSettings.cpp | 16 ++ Core/EmulationSettings.h | 16 ++ Core/HdNesPack.h | 4 +- Core/HdVideoFilter.cpp | 4 +- Core/VideoDecoder.cpp | 18 +- GUI.NET/Config/Configuration.cs | 8 +- GUI.NET/Config/VideoInfo.cs | 5 + .../Forms/Config/frmVideoConfig.Designer.cs | 175 +++++++++++++----- GUI.NET/Forms/Config/frmVideoConfig.cs | 86 ++++++++- GUI.NET/Forms/Config/frmVideoConfig.resx | 6 + GUI.NET/InteropEmu.cs | 18 +- InteropDLL/ConsoleWrapper.cpp | 4 +- 13 files changed, 288 insertions(+), 76 deletions(-) diff --git a/Core/DefaultVideoFilter.cpp b/Core/DefaultVideoFilter.cpp index d64eb405..9174f486 100644 --- a/Core/DefaultVideoFilter.cpp +++ b/Core/DefaultVideoFilter.cpp @@ -2,8 +2,6 @@ #include "DefaultVideoFilter.h" #include "EmulationSettings.h" -extern const uint32_t PPU_PALETTE_ARGB[]; - FrameInfo DefaultVideoFilter::GetFrameInfo() { OverscanDimensions overscan = GetOverscan(); @@ -25,7 +23,7 @@ void DefaultVideoFilter::ApplyFilter(uint16_t *ppuOutputBuffer) uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel) { - uint32_t pixelOutput = PPU_PALETTE_ARGB[ppuPixel & 0x3F]; + uint32_t pixelOutput = EmulationSettings::GetRgbPalette()[ppuPixel & 0x3F]; //Incorrect emphasis bit implementation, but will do for now. float redChannel = (float)((pixelOutput & 0xFF0000) >> 16); diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp index 606e9a33..1838069f 100644 --- a/Core/EmulationSettings.cpp +++ b/Core/EmulationSettings.cpp @@ -1,6 +1,22 @@ #include "stdafx.h" #include "EmulationSettings.h" +uint32_t EmulationSettings::PpuPaletteArgb[64] = { + 0xFF666666, 0xFF002A88, 0xFF1412A7, 0xFF3B00A4, 0xFF5C007E, + 0xFF6E0040, 0xFF6C0600, 0xFF561D00, 0xFF333500, 0xFF0B4800, + 0xFF005200, 0xFF004F08, 0xFF00404D, 0xFF000000, 0xFF000000, + 0xFF000000, 0xFFADADAD, 0xFF155FD9, 0xFF4240FF, 0xFF7527FE, + 0xFFA01ACC, 0xFFB71E7B, 0xFFB53120, 0xFF994E00, 0xFF6B6D00, + 0xFF388700, 0xFF0C9300, 0xFF008F32, 0xFF007C8D, 0xFF000000, + 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFF64B0FF, 0xFF9290FF, + 0xFFC676FF, 0xFFF36AFF, 0xFFFE6ECC, 0xFFFE8170, 0xFFEA9E22, + 0xFFBCBE00, 0xFF88D800, 0xFF5CE430, 0xFF45E082, 0xFF48CDDE, + 0xFF4F4F4F, 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFFC0DFFF, + 0xFFD3D2FF, 0xFFE8C8FF, 0xFFFBC2FF, 0xFFFEC4EA, 0xFFFECCC5, + 0xFFF7D8A5, 0xFFE4E594, 0xFFCFEF96, 0xFFBDF4AB, 0xFFB3F3CC, + 0xFFB5EBF2, 0xFFB8B8B8, 0xFF000000, 0xFF000000, +}; + uint32_t EmulationSettings::_flags = 0; uint32_t EmulationSettings::_audioLatency = 20000; diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index 811caa2b..e7b21236 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -64,6 +64,7 @@ struct OverscanDimensions class EmulationSettings { private: + static uint32_t PpuPaletteArgb[64]; static uint32_t _flags; static uint32_t _audioLatency; @@ -201,4 +202,19 @@ public: { return _videoScale; } + + static uint32_t* GetRgbPalette() + { + return PpuPaletteArgb; + } + + static void GetRgbPalette(uint32_t* paletteBuffer) + { + memcpy(paletteBuffer, PpuPaletteArgb, sizeof(PpuPaletteArgb)); + } + + static void SetRgbPalette(uint32_t* paletteBuffer) + { + memcpy(PpuPaletteArgb, paletteBuffer, sizeof(PpuPaletteArgb)); + } }; diff --git a/Core/HdNesPack.h b/Core/HdNesPack.h index 54d3f234..fbffd133 100644 --- a/Core/HdNesPack.h +++ b/Core/HdNesPack.h @@ -7,8 +7,6 @@ #include "../Utilities/FolderUtilities.h" #include "../Utilities/PNGHelper.h" -extern const uint32_t PPU_PALETTE_ARGB[]; - struct HdPpuTileInfo { static const uint32_t NoTile = -1; @@ -184,7 +182,7 @@ public: for(uint32_t y = 0; y < _hdScale; y++) { for(uint32_t x = 0; x < _hdScale; x++) { if(drawBackground) { - *outputBuffer = PPU_PALETTE_ARGB[tileInfo.BgColor]; + *outputBuffer = EmulationSettings::GetRgbPalette()[tileInfo.BgColor]; } if(!tileInfo.BackgroundPriority || tileInfo.BgColorIndex == 0) { if((bitmapData[bitmapOffset] & 0xFF000000) == 0xFF000000) { diff --git a/Core/HdVideoFilter.cpp b/Core/HdVideoFilter.cpp index 42c74d43..f849d9ee 100644 --- a/Core/HdVideoFilter.cpp +++ b/Core/HdVideoFilter.cpp @@ -2,8 +2,6 @@ #include "HdNesPack.h" #include "HdVideoFilter.h" -extern const uint32_t PPU_PALETTE_ARGB[]; - HdVideoFilter::HdVideoFilter() { _hdNesPack.reset(new HdNesPack()); @@ -31,7 +29,7 @@ void HdVideoFilter::ApplyFilter(uint16_t *ppuOutputBuffer) 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++) { - uint32_t sdPixel = PPU_PALETTE_ARGB[ppuOutputBuffer[i * 256 + j] & 0x3F]; //ProcessIntensifyBits(inputBuffer[i * 256 + j]); + uint32_t sdPixel = EmulationSettings::GetRgbPalette()[ppuOutputBuffer[i * 256 + j] & 0x3F]; //ProcessIntensifyBits(inputBuffer[i * 256 + j]); uint32_t bufferIndex = (i - overscan.Top) * screenWidth * hdScale + (j - overscan.Left) * hdScale; _hdNesPack->GetPixels(_hdScreenTiles[i * 256 + j], sdPixel, (uint32_t*)GetOutputBuffer() + bufferIndex, screenWidth); } diff --git a/Core/VideoDecoder.cpp b/Core/VideoDecoder.cpp index e2808bff..617a1b23 100644 --- a/Core/VideoDecoder.cpp +++ b/Core/VideoDecoder.cpp @@ -6,22 +6,6 @@ #include "NtscFilter.h" #include "HdVideoFilter.h" -const uint32_t PPU_PALETTE_ARGB[64] = { - 0xFF666666, 0xFF002A88, 0xFF1412A7, 0xFF3B00A4, 0xFF5C007E, - 0xFF6E0040, 0xFF6C0600, 0xFF561D00, 0xFF333500, 0xFF0B4800, - 0xFF005200, 0xFF004F08, 0xFF00404D, 0xFF000000, 0xFF000000, - 0xFF000000, 0xFFADADAD, 0xFF155FD9, 0xFF4240FF, 0xFF7527FE, - 0xFFA01ACC, 0xFFB71E7B, 0xFFB53120, 0xFF994E00, 0xFF6B6D00, - 0xFF388700, 0xFF0C9300, 0xFF008F32, 0xFF007C8D, 0xFF000000, - 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFF64B0FF, 0xFF9290FF, - 0xFFC676FF, 0xFFF36AFF, 0xFFFE6ECC, 0xFFFE8170, 0xFFEA9E22, - 0xFFBCBE00, 0xFF88D800, 0xFF5CE430, 0xFF45E082, 0xFF48CDDE, - 0xFF4F4F4F, 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFFC0DFFF, - 0xFFD3D2FF, 0xFFE8C8FF, 0xFFFBC2FF, 0xFFFEC4EA, 0xFFFECCC5, - 0xFFF7D8A5, 0xFFE4E594, 0xFFCFEF96, 0xFFBDF4AB, 0xFFB3F3CC, - 0xFFB5EBF2, 0xFFB8B8B8, 0xFF000000, 0xFF000000, -}; - unique_ptr VideoDecoder::Instance; VideoDecoder* VideoDecoder::GetInstance() @@ -87,7 +71,7 @@ void VideoDecoder::DecodeFrame() void VideoDecoder::DebugDecodeFrame(uint16_t* inputBuffer, uint32_t* outputBuffer, uint32_t length) { for(uint32_t i = 0; i < length; i++) { - outputBuffer[i] = PPU_PALETTE_ARGB[inputBuffer[i] & 0x3F]; + outputBuffer[i] = EmulationSettings::GetRgbPalette()[inputBuffer[i] & 0x3F]; } } diff --git a/GUI.NET/Config/Configuration.cs b/GUI.NET/Config/Configuration.cs index 18f02fa6..0a7c4e85 100644 --- a/GUI.NET/Config/Configuration.cs +++ b/GUI.NET/Config/Configuration.cs @@ -12,18 +12,18 @@ namespace Mesen.GUI.Config { private const int MaxRecentFiles = 10; - public PlayerProfile Profile; - public ClientConnectionInfo ClientConnectionInfo; - public ServerInfo ServerInfo; + public PreferenceInfo PreferenceInfo; public AudioInfo AudioInfo; public VideoInfo VideoInfo; - public PreferenceInfo PreferenceInfo; public List RecentFiles; public List Cheats; public List Controllers; public bool ShowOnlyCheatsForCurrentGame; public bool AutoLoadIpsPatches; public NesModel Region; + public ClientConnectionInfo ClientConnectionInfo; + public ServerInfo ServerInfo; + public PlayerProfile Profile; public Configuration() { diff --git a/GUI.NET/Config/VideoInfo.cs b/GUI.NET/Config/VideoInfo.cs index 280becb9..7a624738 100644 --- a/GUI.NET/Config/VideoInfo.cs +++ b/GUI.NET/Config/VideoInfo.cs @@ -23,6 +23,7 @@ namespace Mesen.GUI.Config public bool VerticalSync = true; public bool FullscreenMode = false; public bool UseHdPacks = false; + public Int32[] Palette = new Int32[0]; public VideoInfo() { @@ -42,6 +43,10 @@ namespace Mesen.GUI.Config InteropEmu.SetVideoFilter(videoInfo.VideoFilter); InteropEmu.SetVideoScale(videoInfo.VideoScale); + + if(videoInfo.Palette.Length == 64) { + InteropEmu.SetRgbPalette(videoInfo.Palette); + } } } } diff --git a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs index f813a29d..c75f0b4c 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs +++ b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs @@ -41,6 +41,9 @@ this.lblEmuSpeedHint = new System.Windows.Forms.Label(); this.lblEmulationSpeed = new System.Windows.Forms.Label(); this.chkShowFps = new System.Windows.Forms.CheckBox(); + this.flowLayoutPanel7 = new System.Windows.Forms.FlowLayoutPanel(); + this.chkUseHdPacks = new System.Windows.Forms.CheckBox(); + this.picHdNesTooltip = new System.Windows.Forms.PictureBox(); this.tabMain = new System.Windows.Forms.TabControl(); this.tpgGeneral = new System.Windows.Forms.TabPage(); this.tpgOverscan = new System.Windows.Forms.TabPage(); @@ -60,12 +63,17 @@ this.lblRight = new System.Windows.Forms.Label(); this.nudOverscanRight = new System.Windows.Forms.NumericUpDown(); this.tpgPalette = new System.Windows.Forms.TabPage(); - this.chkUseHdPacks = new System.Windows.Forms.CheckBox(); - this.flowLayoutPanel7 = new System.Windows.Forms.FlowLayoutPanel(); - this.picHdNesTooltip = new System.Windows.Forms.PictureBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.picPalette = new System.Windows.Forms.PictureBox(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.btnResetPalette = new System.Windows.Forms.Button(); + this.btnLoadPalFile = new System.Windows.Forms.Button(); + this.colorDialog = new System.Windows.Forms.ColorDialog(); this.tlpMain.SuspendLayout(); this.flowLayoutPanel6.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudEmulationSpeed)).BeginInit(); + this.flowLayoutPanel7.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picHdNesTooltip)).BeginInit(); this.tabMain.SuspendLayout(); this.tpgGeneral.SuspendLayout(); this.tpgOverscan.SuspendLayout(); @@ -80,14 +88,16 @@ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanBottom)).BeginInit(); this.flowLayoutPanel2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudOverscanRight)).BeginInit(); - this.flowLayoutPanel7.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.picHdNesTooltip)).BeginInit(); + this.tpgPalette.SuspendLayout(); + this.tableLayoutPanel3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picPalette)).BeginInit(); + this.tableLayoutPanel2.SuspendLayout(); this.SuspendLayout(); // // baseConfigPanel // - this.baseConfigPanel.Location = new System.Drawing.Point(0, 308); - this.baseConfigPanel.Size = new System.Drawing.Size(362, 29); + this.baseConfigPanel.Location = new System.Drawing.Point(0, 288); + this.baseConfigPanel.Size = new System.Drawing.Size(515, 29); // // tlpMain // @@ -120,7 +130,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(348, 276); + this.tlpMain.Size = new System.Drawing.Size(501, 256); this.tlpMain.TabIndex = 1; // // chkFullscreenMode @@ -227,7 +237,7 @@ this.flowLayoutPanel6.Location = new System.Drawing.Point(96, 173); this.flowLayoutPanel6.Margin = new System.Windows.Forms.Padding(0); this.flowLayoutPanel6.Name = "flowLayoutPanel6"; - this.flowLayoutPanel6.Size = new System.Drawing.Size(252, 26); + this.flowLayoutPanel6.Size = new System.Drawing.Size(405, 26); this.flowLayoutPanel6.TabIndex = 10; // // nudEmulationSpeed @@ -274,6 +284,37 @@ this.chkShowFps.Text = "Show FPS"; this.chkShowFps.UseVisualStyleBackColor = true; // + // flowLayoutPanel7 + // + this.tlpMain.SetColumnSpan(this.flowLayoutPanel7, 2); + this.flowLayoutPanel7.Controls.Add(this.chkUseHdPacks); + this.flowLayoutPanel7.Controls.Add(this.picHdNesTooltip); + this.flowLayoutPanel7.Location = new System.Drawing.Point(0, 81); + this.flowLayoutPanel7.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel7.Name = "flowLayoutPanel7"; + this.flowLayoutPanel7.Size = new System.Drawing.Size(166, 23); + this.flowLayoutPanel7.TabIndex = 20; + // + // chkUseHdPacks + // + this.chkUseHdPacks.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.chkUseHdPacks.AutoSize = true; + this.chkUseHdPacks.Location = new System.Drawing.Point(3, 3); + this.chkUseHdPacks.Name = "chkUseHdPacks"; + this.chkUseHdPacks.Size = new System.Drawing.Size(134, 17); + this.chkUseHdPacks.TabIndex = 19; + this.chkUseHdPacks.Text = "Use HDNes HD packs"; + this.chkUseHdPacks.UseVisualStyleBackColor = true; + // + // picHdNesTooltip + // + this.picHdNesTooltip.Image = global::Mesen.GUI.Properties.Resources.help; + this.picHdNesTooltip.Location = new System.Drawing.Point(143, 3); + this.picHdNesTooltip.Name = "picHdNesTooltip"; + this.picHdNesTooltip.Size = new System.Drawing.Size(17, 17); + this.picHdNesTooltip.TabIndex = 21; + this.picHdNesTooltip.TabStop = false; + // // tabMain // this.tabMain.Controls.Add(this.tpgGeneral); @@ -283,7 +324,7 @@ this.tabMain.Location = new System.Drawing.Point(0, 0); this.tabMain.Name = "tabMain"; this.tabMain.SelectedIndex = 0; - this.tabMain.Size = new System.Drawing.Size(362, 308); + this.tabMain.Size = new System.Drawing.Size(515, 288); this.tabMain.TabIndex = 2; // // tpgGeneral @@ -292,7 +333,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(354, 282); + this.tpgGeneral.Size = new System.Drawing.Size(507, 262); this.tpgGeneral.TabIndex = 0; this.tpgGeneral.Text = "General"; this.tpgGeneral.UseVisualStyleBackColor = true; @@ -303,7 +344,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(354, 282); + this.tpgOverscan.Size = new System.Drawing.Size(507, 262); this.tpgOverscan.TabIndex = 1; this.tpgOverscan.Text = "Overscan"; this.tpgOverscan.UseVisualStyleBackColor = true; @@ -314,7 +355,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(348, 276); + this.grpCropping.Size = new System.Drawing.Size(501, 256); this.grpCropping.TabIndex = 8; this.grpCropping.TabStop = false; this.grpCropping.Text = "Video Cropping"; @@ -470,50 +511,88 @@ // // 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(354, 282); + this.tpgPalette.Size = new System.Drawing.Size(507, 262); this.tpgPalette.TabIndex = 2; this.tpgPalette.Text = "Palette"; this.tpgPalette.UseVisualStyleBackColor = true; // - // chkUseHdPacks + // tableLayoutPanel3 // - this.chkUseHdPacks.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.chkUseHdPacks.AutoSize = true; - this.chkUseHdPacks.Location = new System.Drawing.Point(3, 3); - this.chkUseHdPacks.Name = "chkUseHdPacks"; - this.chkUseHdPacks.Size = new System.Drawing.Size(134, 17); - this.chkUseHdPacks.TabIndex = 19; - this.chkUseHdPacks.Text = "Use HDNes HD packs"; - this.chkUseHdPacks.UseVisualStyleBackColor = true; + this.tableLayoutPanel3.ColumnCount = 2; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.Controls.Add(this.picPalette, 0, 1); + this.tableLayoutPanel3.Controls.Add(this.tableLayoutPanel2, 1, 1); + this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + 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, 256); + this.tableLayoutPanel3.TabIndex = 4; // - // flowLayoutPanel7 + // picPalette // - this.tlpMain.SetColumnSpan(this.flowLayoutPanel7, 2); - this.flowLayoutPanel7.Controls.Add(this.chkUseHdPacks); - this.flowLayoutPanel7.Controls.Add(this.picHdNesTooltip); - this.flowLayoutPanel7.Location = new System.Drawing.Point(0, 81); - this.flowLayoutPanel7.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.flowLayoutPanel7.Name = "flowLayoutPanel7"; - this.flowLayoutPanel7.Size = new System.Drawing.Size(166, 23); - this.flowLayoutPanel7.TabIndex = 20; + this.picPalette.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picPalette.Cursor = System.Windows.Forms.Cursors.Hand; + this.picPalette.Location = new System.Drawing.Point(1, 1); + this.picPalette.Margin = new System.Windows.Forms.Padding(1); + this.picPalette.Name = "picPalette"; + this.picPalette.Size = new System.Drawing.Size(386, 98); + this.picPalette.TabIndex = 0; + this.picPalette.TabStop = false; + this.picPalette.MouseDown += new System.Windows.Forms.MouseEventHandler(this.picPalette_MouseDown); // - // picHdNesTooltip + // tableLayoutPanel2 // - this.picHdNesTooltip.Image = global::Mesen.GUI.Properties.Resources.help; - this.picHdNesTooltip.Location = new System.Drawing.Point(143, 3); - this.picHdNesTooltip.Name = "picHdNesTooltip"; - this.picHdNesTooltip.Size = new System.Drawing.Size(17, 17); - this.picHdNesTooltip.TabIndex = 21; - this.picHdNesTooltip.TabStop = false; + this.tableLayoutPanel2.ColumnCount = 1; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Controls.Add(this.btnResetPalette, 0, 1); + this.tableLayoutPanel2.Controls.Add(this.btnLoadPalFile, 0, 0); + this.tableLayoutPanel2.Location = new System.Drawing.Point(388, 0); + this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 3; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(113, 73); + this.tableLayoutPanel2.TabIndex = 1; + // + // btnResetPalette + // + this.btnResetPalette.Location = new System.Drawing.Point(3, 31); + this.btnResetPalette.Name = "btnResetPalette"; + this.btnResetPalette.Size = new System.Drawing.Size(106, 22); + this.btnResetPalette.TabIndex = 1; + this.btnResetPalette.Text = "Reset to Defaults"; + this.btnResetPalette.UseVisualStyleBackColor = true; + this.btnResetPalette.Click += new System.EventHandler(this.btnResetPalette_Click); + // + // btnLoadPalFile + // + this.btnLoadPalFile.Location = new System.Drawing.Point(3, 3); + this.btnLoadPalFile.Name = "btnLoadPalFile"; + this.btnLoadPalFile.Size = new System.Drawing.Size(106, 22); + this.btnLoadPalFile.TabIndex = 0; + this.btnLoadPalFile.Text = "Load Palette File"; + this.btnLoadPalFile.UseVisualStyleBackColor = true; + this.btnLoadPalFile.Click += new System.EventHandler(this.btnLoadPalFile_Click); // // frmVideoConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(362, 337); + this.ClientSize = new System.Drawing.Size(515, 317); this.Controls.Add(this.tabMain); this.Name = "frmVideoConfig"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; @@ -525,6 +604,9 @@ this.flowLayoutPanel6.ResumeLayout(false); this.flowLayoutPanel6.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudEmulationSpeed)).EndInit(); + this.flowLayoutPanel7.ResumeLayout(false); + this.flowLayoutPanel7.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picHdNesTooltip)).EndInit(); this.tabMain.ResumeLayout(false); this.tpgGeneral.ResumeLayout(false); this.tpgOverscan.ResumeLayout(false); @@ -543,9 +625,10 @@ this.flowLayoutPanel2.ResumeLayout(false); this.flowLayoutPanel2.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudOverscanRight)).EndInit(); - this.flowLayoutPanel7.ResumeLayout(false); - this.flowLayoutPanel7.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.picHdNesTooltip)).EndInit(); + this.tpgPalette.ResumeLayout(false); + this.tableLayoutPanel3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.picPalette)).EndInit(); + this.tableLayoutPanel2.ResumeLayout(false); this.ResumeLayout(false); } @@ -588,5 +671,11 @@ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel7; private System.Windows.Forms.CheckBox chkUseHdPacks; private System.Windows.Forms.PictureBox picHdNesTooltip; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.PictureBox picPalette; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.Button btnResetPalette; + private System.Windows.Forms.Button btnLoadPalFile; + private System.Windows.Forms.ColorDialog colorDialog; } } \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmVideoConfig.cs b/GUI.NET/Forms/Config/frmVideoConfig.cs index d448f28b..cd596b50 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.cs +++ b/GUI.NET/Forms/Config/frmVideoConfig.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; +using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; @@ -13,6 +15,8 @@ namespace Mesen.GUI.Forms.Config { public partial class frmVideoConfig : BaseConfigForm { + private Int32[] _paletteData; + public frmVideoConfig() { InitializeComponent(); @@ -34,13 +38,93 @@ namespace Mesen.GUI.Forms.Config AddBinding("OverscanTop", nudOverscanTop); AddBinding("OverscanBottom", nudOverscanBottom); + _paletteData = InteropEmu.GetRgbPalette(); + RefreshPalette(); + toolTip.SetToolTip(picHdNesTooltip, "This option allows Mesen to load HDNes-format HD packs if they are found." + Environment.NewLine + Environment.NewLine + "HD Packs should be placed in the \"HdPacks\" folder in a subfolder matching the name of the ROM." + Environment.NewLine + "e.g: MyRom.nes should have their HD Pack in \"HdPacks\\MyRom\\hires.txt\"." + Environment.NewLine + Environment.NewLine + "Note: Support for HD Packs is a work in progress and some limitations remain."); } - + protected override void OnFormClosed(FormClosedEventArgs e) { + if(DialogResult == System.Windows.Forms.DialogResult.OK) { + ((VideoInfo)Entity).Palette = _paletteData; + } base.OnFormClosed(e); VideoInfo.ApplyConfig(); } + + private void RefreshPalette() + { + GCHandle handle = GCHandle.Alloc(_paletteData, GCHandleType.Pinned); + try { + Bitmap source = new Bitmap(16, 4, 16*4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()); + Bitmap target = new Bitmap(384, 96); + + using(Graphics g = Graphics.FromImage(target)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(source, new Rectangle(0, 0, 384, 96), new Rectangle(0, 0, 16, 4), GraphicsUnit.Pixel); + } + this.picPalette.Image = target; + } finally { + handle.Free(); + } + } + + private void picPalette_MouseDown(object sender, MouseEventArgs e) + { + int offset = (e.X / 24) + (e.Y / 24 * 16); + + colorDialog.SolidColorOnly = true; + colorDialog.AllowFullOpen = true; + colorDialog.FullOpen = true; + colorDialog.Color = Color.FromArgb(_paletteData[offset]); + if(colorDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { + _paletteData[offset] = colorDialog.Color.ToArgb(); + } + + RefreshPalette(); + } + + private void btnResetPalette_Click(object sender, EventArgs e) + { + _paletteData = (Int32[])((object)(new UInt32[] { + 0xFF666666, 0xFF002A88, 0xFF1412A7, 0xFF3B00A4, 0xFF5C007E, + 0xFF6E0040, 0xFF6C0600, 0xFF561D00, 0xFF333500, 0xFF0B4800, + 0xFF005200, 0xFF004F08, 0xFF00404D, 0xFF000000, 0xFF000000, + 0xFF000000, 0xFFADADAD, 0xFF155FD9, 0xFF4240FF, 0xFF7527FE, + 0xFFA01ACC, 0xFFB71E7B, 0xFFB53120, 0xFF994E00, 0xFF6B6D00, + 0xFF388700, 0xFF0C9300, 0xFF008F32, 0xFF007C8D, 0xFF000000, + 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFF64B0FF, 0xFF9290FF, + 0xFFC676FF, 0xFFF36AFF, 0xFFFE6ECC, 0xFFFE8170, 0xFFEA9E22, + 0xFFBCBE00, 0xFF88D800, 0xFF5CE430, 0xFF45E082, 0xFF48CDDE, + 0xFF4F4F4F, 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFFC0DFFF, + 0xFFD3D2FF, 0xFFE8C8FF, 0xFFFBC2FF, 0xFFFEC4EA, 0xFFFECCC5, + 0xFFF7D8A5, 0xFFE4E594, 0xFFCFEF96, 0xFFBDF4AB, 0xFFB3F3CC, + 0xFFB5EBF2, 0xFFB8B8B8, 0xFF000000, 0xFF000000 + })); + + RefreshPalette(); + } + + private void btnLoadPalFile_Click(object sender, EventArgs e) + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Filter = "Palette Files (*.pal)|*.pal|All Files (*.*)|*.*"; + if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { + using(FileStream paletteFile = File.OpenRead(ofd.FileName)) { + byte[] paletteFileData = new byte[64*3]; + if(paletteFile.Read(paletteFileData, 0, 64*3) == 64*3) { + for(int i = 0; i < 64; i++) { + int fileOffset = i * 3; + _paletteData[i] = (Int32)((UInt32)0xFF000000 | (UInt32)paletteFileData[fileOffset+2] | (UInt32)(paletteFileData[fileOffset+1] << 8) | (UInt32)(paletteFileData[fileOffset] << 16)); + } + RefreshPalette(); + } + paletteFile.Close(); + } + } + } } } diff --git a/GUI.NET/Forms/Config/frmVideoConfig.resx b/GUI.NET/Forms/Config/frmVideoConfig.resx index 1af7de15..aeccf29f 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.resx +++ b/GUI.NET/Forms/Config/frmVideoConfig.resx @@ -117,4 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + + + 107, 17 + \ No newline at end of file diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 503df04a..7d039d86 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -82,7 +82,9 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void SetOverscanDimensions(UInt32 left, UInt32 right, UInt32 top, UInt32 bottom); [DllImport(DLLPath)] public static extern void SetVideoScale(UInt32 scale); [DllImport(DLLPath)] public static extern void SetVideoFilter(VideoFilterType filter); - + [DllImport(DLLPath)] public static extern void SetRgbPalette(Int32[] palette); + [DllImport(DLLPath, EntryPoint="GetRgbPalette")] private static extern void GetRgbPaletteWrapper(IntPtr paletteBuffer); + [DllImport(DLLPath, EntryPoint="GetScreenSize")] private static extern void GetScreenSizeWrapper(out ScreenSize size); [DllImport(DLLPath)] public static extern void DebugInitialize(); @@ -219,6 +221,20 @@ namespace Mesen.GUI } } + public static Int32[] GetRgbPalette() + { + Int32[] paleteData = new Int32[64]; + + GCHandle hPaletteData = GCHandle.Alloc(paleteData, GCHandleType.Pinned); + try { + InteropEmu.GetRgbPaletteWrapper(hPaletteData.AddrOfPinnedObject()); + } finally { + hPaletteData.Free(); + } + + return paleteData; + } + public static string GetROMPath() { return PtrToStringUtf8(InteropEmu.GetROMPathWrapper()); } public static string GetKeyName(UInt32 key) { return PtrToStringUtf8(InteropEmu.GetKeyNameWrapper(key)); } diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 04355038..1fd4332f 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -217,7 +217,9 @@ namespace InteropEmu { DllExport void __stdcall SetEmulationSpeed(uint32_t emulationSpeed) { EmulationSettings::SetEmulationSpeed(emulationSpeed); } DllExport void __stdcall SetVideoScale(uint32_t scale) { EmulationSettings::SetVideoScale(scale); } DllExport void __stdcall SetVideoFilter(VideoFilterType filter) { EmulationSettings::SetVideoFilterType(filter); } - DllExport void __stdcall GetScreenSize(ScreenSize &size) { VideoDecoder::GetInstance()->GetScreenSize(size); } + DllExport void __stdcall GetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::GetRgbPalette(paletteBuffer); } + DllExport void __stdcall SetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::SetRgbPalette(paletteBuffer); } + DllExport void __stdcall GetScreenSize(ScreenSize &size) { VideoDecoder::GetInstance()->GetScreenSize(size); } } } \ No newline at end of file