diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index fb83d6d8..13b2caa5 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -361,6 +361,7 @@
Create
Create
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index 6b9178ba..0d581125 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -301,5 +301,8 @@
Source Files\APU
+
+ Source Files
+
\ No newline at end of file
diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp
index 75c0511e..6f7e9520 100644
--- a/Core/EmulationSettings.cpp
+++ b/Core/EmulationSettings.cpp
@@ -4,4 +4,5 @@
uint32_t EmulationSettings::Flags = 0;
uint32_t EmulationSettings::AudioLatency = 20000;
double EmulationSettings::ChannelVolume[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
-NesModel EmulationSettings::Model;
\ No newline at end of file
+NesModel EmulationSettings::Model;
+OverscanDimensions EmulationSettings::Overscan;
\ No newline at end of file
diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h
index 58b14523..03921515 100644
--- a/Core/EmulationSettings.h
+++ b/Core/EmulationSettings.h
@@ -25,6 +25,29 @@ enum class NesModel
PAL = 2,
};
+struct OverscanDimensions
+{
+ uint32_t Left = 0;
+ uint32_t Right = 0;
+ uint32_t Top = 0;
+ uint32_t Bottom = 0;
+
+ uint32_t GetPixelCount()
+ {
+ return GetScreenWidth() * GetScreenHeight();
+ }
+
+ uint32_t GetScreenWidth()
+ {
+ return 256 - Left - Right;
+ }
+
+ uint32_t GetScreenHeight()
+ {
+ return 240 - Top - Bottom;
+ }
+};
+
class EmulationSettings
{
private:
@@ -32,6 +55,7 @@ private:
static uint32_t AudioLatency;
static double ChannelVolume[5];
static NesModel Model;
+ static OverscanDimensions Overscan;
public:
static void SetFlags(uint32_t flags)
@@ -70,6 +94,19 @@ public:
AudioLatency = msLatency;
}
+ static void SetOverscanDimensions(uint8_t left, uint8_t right, uint8_t top, uint8_t bottom)
+ {
+ Overscan.Left = left;
+ Overscan.Right = right;
+ Overscan.Top = top;
+ Overscan.Bottom = bottom;
+ }
+
+ static OverscanDimensions GetOverscanDimensions()
+ {
+ return Overscan;
+ }
+
static double GetChannelVolume(AudioChannel channel)
{
return ChannelVolume[(int)channel];
diff --git a/Core/PPU.h b/Core/PPU.h
index c4aadebc..553b2b13 100644
--- a/Core/PPU.h
+++ b/Core/PPU.h
@@ -182,6 +182,11 @@ class PPU : public IMemoryHandler, public Snapshotable
void StreamState(bool saving);
public:
+ static const uint32_t ScreenWidth = 256;
+ static const uint32_t ScreenHeight = 240;
+ static const uint32_t PixelCount = 256*240;
+ static const uint32_t OutputBufferSize = 256*240*2;
+
PPU(MemoryManager *memoryManager);
~PPU();
diff --git a/Core/VideoDecoder.cpp b/Core/VideoDecoder.cpp
new file mode 100644
index 00000000..9589aa63
--- /dev/null
+++ b/Core/VideoDecoder.cpp
@@ -0,0 +1,143 @@
+#pragma once
+#include "stdafx.h"
+#include "VideoDecoder.h"
+#include "EmulationSettings.h"
+#include "MessageManager.h"
+#include "../Utilities/PNGWriter.h"
+#include "../Utilities/FolderUtilities.h"
+
+const uint32_t PPU_PALETTE_ARGB[] = {
+ 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()
+{
+ if(!Instance) {
+ Instance.reset(new VideoDecoder());
+ }
+ return Instance.get();
+}
+
+VideoDecoder::~VideoDecoder()
+{
+ if(_frameBuffer) {
+ delete[] _frameBuffer;
+ }
+}
+
+uint32_t VideoDecoder::ProcessIntensifyBits(uint16_t ppuPixel)
+{
+ uint32_t pixelOutput = PPU_PALETTE_ARGB[ppuPixel & 0x3F];
+
+ //Incorrect emphasis bit implementation, but will do for now.
+ float redChannel = (float)((pixelOutput & 0xFF0000) >> 16);
+ float greenChannel = (float)((pixelOutput & 0xFF00) >> 8);
+ float blueChannel = (float)(pixelOutput & 0xFF);
+
+ if(ppuPixel & 0x40) {
+ //Intensify red
+ redChannel *= 1.1f;
+ greenChannel *= 0.9f;
+ blueChannel *= 0.9f;
+ }
+ if(ppuPixel & 0x80) {
+ //Intensify green
+ greenChannel *= 1.1f;
+ redChannel *= 0.9f;
+ blueChannel *= 0.9f;
+ }
+ if(ppuPixel & 0x100) {
+ //Intensify blue
+ blueChannel *= 1.1f;
+ redChannel *= 0.9f;
+ greenChannel *= 0.9f;
+ }
+
+ uint8_t r, g, b;
+ r = (uint8_t)fmin(redChannel, 255);
+ g = (uint8_t)fmin(greenChannel, 255);
+ b = (uint8_t)fmin(blueChannel, 255);
+
+ return 0xFF000000 | (r << 16) | (g << 8) | b;
+}
+
+void VideoDecoder::UpdateBufferSize()
+{
+ OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
+
+ if(!_frameBuffer || _overscan.GetPixelCount() != overscan.GetPixelCount()) {
+ _overscan = overscan;
+ if(_frameBuffer) {
+ delete[] _frameBuffer;
+ }
+ _frameBuffer = new uint32_t[_overscan.GetPixelCount()];
+ }
+}
+
+uint32_t* VideoDecoder::DecodeFrame(uint16_t* inputBuffer)
+{
+ _frameLock.Acquire();
+ UpdateBufferSize();
+ uint32_t* outputBuffer = _frameBuffer;
+ 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(inputBuffer[i*256+j]);
+ outputBuffer++;
+ }
+ }
+ _frameLock.Release();
+
+ return _frameBuffer;
+}
+
+void VideoDecoder::TakeScreenshot(string romFilename)
+{
+ uint32_t bufferSize = _overscan.GetPixelCount() * 4;
+ uint32_t* frameBuffer = new uint32_t[bufferSize];
+
+ _frameLock.Acquire();
+ memcpy(frameBuffer, _frameBuffer, bufferSize);
+ _frameLock.Release();
+
+ //ARGB -> ABGR
+ for(uint32_t i = 0; i < bufferSize; i++) {
+ frameBuffer[i] = (frameBuffer[i] & 0xFF00FF00) | ((frameBuffer[i] & 0xFF0000) >> 16) | ((frameBuffer[i] & 0xFF) << 16);
+ }
+
+ int counter = 0;
+ string baseFilename = FolderUtilities::GetScreenshotFolder() + romFilename;
+ string ssFilename;
+ while(true) {
+ string counterStr = std::to_string(counter);
+ while(counterStr.length() < 3) {
+ counterStr = "0" + counterStr;
+ }
+ ssFilename = baseFilename + "_" + counterStr + ".png";
+ ifstream file(ssFilename, ios::in);
+ if(file) {
+ file.close();
+ } else {
+ break;
+ }
+ counter++;
+ }
+
+ PNGWriter::WritePNG(ssFilename, (uint8_t*)frameBuffer, _overscan.GetScreenWidth(), _overscan.GetScreenHeight());
+ delete[] frameBuffer;
+
+ MessageManager::DisplayMessage("Screenshot saved", FolderUtilities::GetFilename(ssFilename, true));
+}
\ No newline at end of file
diff --git a/Core/VideoDecoder.h b/Core/VideoDecoder.h
index 8fbc7a1f..b068f317 100644
--- a/Core/VideoDecoder.h
+++ b/Core/VideoDecoder.h
@@ -1,67 +1,24 @@
#pragma once
#include "stdafx.h"
-#include
-
-const uint32_t PPU_PALETTE_ARGB[] = {
- 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,
-};
+#include "../Utilities/SimpleLock.h"
+#include "EmulationSettings.h"
class VideoDecoder
{
private:
- static uint32_t ProcessIntensifyBits(uint16_t ppuPixel)
- {
- uint32_t pixelOutput = PPU_PALETTE_ARGB[ppuPixel & 0x3F];
+ static unique_ptr Instance;
- //Incorrect emphasis bit implementation, but will do for now.
- float redChannel = (float)((pixelOutput & 0xFF0000) >> 16);
- float greenChannel = (float)((pixelOutput & 0xFF00) >> 8);
- float blueChannel = (float)(pixelOutput & 0xFF);
+ OverscanDimensions _overscan;
+ uint32_t* _frameBuffer = nullptr;
+ SimpleLock _frameLock;
- if(ppuPixel & 0x40) {
- //Intensify red
- redChannel *= 1.1f;
- greenChannel *= 0.9f;
- blueChannel *= 0.9f;
- }
- if(ppuPixel & 0x80) {
- //Intensify green
- greenChannel *= 1.1f;
- redChannel *= 0.9f;
- blueChannel *= 0.9f;
- }
- if(ppuPixel & 0x100) {
- //Intensify blue
- blueChannel *= 1.1f;
- redChannel *= 0.9f;
- greenChannel *= 0.9f;
- }
-
- uint8_t r, g, b;
- r = (uint8_t)fmin(redChannel, 255);
- g = (uint8_t)fmin(greenChannel, 255);
- b = (uint8_t)fmin(blueChannel, 255);
-
- return 0xFF000000 | (r << 16) | (g << 8) | b;
- }
+ uint32_t ProcessIntensifyBits(uint16_t ppuPixel);
+ void UpdateBufferSize();
public:
- static void DecodeFrame(uint16_t* inputBuffer, uint32_t* outputBuffer)
- {
- for(uint32_t i = 0; i < 256*240; i++) {
- ((uint32_t*)outputBuffer)[i] = ProcessIntensifyBits(inputBuffer[i]);
- }
- }
+ static VideoDecoder* GetInstance();
+ ~VideoDecoder();
+
+ uint32_t* DecodeFrame(uint16_t* inputBuffer);
+ void TakeScreenshot(string romFilename);
};
\ No newline at end of file
diff --git a/GUI.NET/Config/VideoInfo.cs b/GUI.NET/Config/VideoInfo.cs
index 4093b5ad..69acd598 100644
--- a/GUI.NET/Config/VideoInfo.cs
+++ b/GUI.NET/Config/VideoInfo.cs
@@ -13,6 +13,10 @@ namespace Mesen.GUI.Config
{
public bool LimitFPS = true;
public bool ShowFPS = false;
+ public UInt32 OverscanLeft = 0;
+ public UInt32 OverscanRight = 0;
+ public UInt32 OverscanTop = 8;
+ public UInt32 OverscanBottom = 8;
public VideoInfo()
{
@@ -20,6 +24,7 @@ namespace Mesen.GUI.Config
static public void ApplyConfig()
{
+ VideoInfo videoInfo = ConfigManager.Config.VideoInfo;
if(ConfigManager.Config.VideoInfo.LimitFPS) {
InteropEmu.SetFlags((UInt32)EmulationFlags.LimitFPS);
} else {
@@ -31,6 +36,14 @@ namespace Mesen.GUI.Config
} else {
InteropEmu.ClearFlags((UInt32)EmulationFlags.ShowFPS);
}
+
+ InteropEmu.SetOverscanDimensions(videoInfo.OverscanLeft, videoInfo.OverscanRight, videoInfo.OverscanTop, videoInfo.OverscanBottom);
+ }
+
+ static public Size GetViewerSize()
+ {
+ VideoInfo videoInfo = ConfigManager.Config.VideoInfo;
+ return new Size((int)(256-videoInfo.OverscanLeft-videoInfo.OverscanRight)*4, (int)(240-videoInfo.OverscanTop-videoInfo.OverscanBottom)*4);
}
}
}
diff --git a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs
index d7d7ea32..e64f7c38 100644
--- a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs
+++ b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs
@@ -27,107 +27,291 @@
///
private void InitializeComponent()
{
+ this.tlpMain = new System.Windows.Forms.TableLayoutPanel();
+ this.grpCropping = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
- this.txtPort = new System.Windows.Forms.TextBox();
- this.lblHost = new System.Windows.Forms.Label();
- this.lblPort = new System.Windows.Forms.Label();
- this.txtHost = new System.Windows.Forms.TextBox();
- this.chkSpectator = new System.Windows.Forms.CheckBox();
+ this.picOverscan = new System.Windows.Forms.PictureBox();
+ this.flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel();
+ this.lblLeft = new System.Windows.Forms.Label();
+ this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel();
+ this.lblTop = new System.Windows.Forms.Label();
+ this.flowLayoutPanel5 = new System.Windows.Forms.FlowLayoutPanel();
+ this.lblBottom = new System.Windows.Forms.Label();
+ this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
+ this.lblRight = new System.Windows.Forms.Label();
+ this.chkLimitFps = new System.Windows.Forms.CheckBox();
+ this.chkShowFps = new System.Windows.Forms.CheckBox();
+ this.nudOverscanRight = new System.Windows.Forms.NumericUpDown();
+ this.nudOverscanBottom = new System.Windows.Forms.NumericUpDown();
+ this.nudOverscanLeft = new System.Windows.Forms.NumericUpDown();
+ this.nudOverscanTop = new System.Windows.Forms.NumericUpDown();
+ this.tlpMain.SuspendLayout();
+ this.grpCropping.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.picOverscan)).BeginInit();
+ this.flowLayoutPanel3.SuspendLayout();
+ this.flowLayoutPanel4.SuspendLayout();
+ this.flowLayoutPanel5.SuspendLayout();
+ this.flowLayoutPanel2.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanRight)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanBottom)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanLeft)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanTop)).BeginInit();
this.SuspendLayout();
//
+ // baseConfigPanel
+ //
+ this.baseConfigPanel.Location = new System.Drawing.Point(0, 308);
+ this.baseConfigPanel.Size = new System.Drawing.Size(362, 29);
+ //
+ // tlpMain
+ //
+ this.tlpMain.ColumnCount = 1;
+ this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.tlpMain.Controls.Add(this.grpCropping, 0, 2);
+ this.tlpMain.Controls.Add(this.chkLimitFps, 0, 0);
+ this.tlpMain.Controls.Add(this.chkShowFps, 0, 1);
+ this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tlpMain.Location = new System.Drawing.Point(0, 0);
+ this.tlpMain.Name = "tlpMain";
+ this.tlpMain.RowCount = 3;
+ 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(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tlpMain.Size = new System.Drawing.Size(362, 308);
+ this.tlpMain.TabIndex = 1;
+ //
+ // grpCropping
+ //
+ this.grpCropping.Controls.Add(this.tableLayoutPanel1);
+ this.grpCropping.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.grpCropping.Location = new System.Drawing.Point(3, 49);
+ this.grpCropping.Name = "grpCropping";
+ this.grpCropping.Size = new System.Drawing.Size(356, 256);
+ this.grpCropping.TabIndex = 7;
+ this.grpCropping.TabStop = false;
+ this.grpCropping.Text = "Video Cropping";
+ //
// tableLayoutPanel1
//
- this.tableLayoutPanel1.ColumnCount = 2;
+ this.tableLayoutPanel1.ColumnCount = 3;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayoutPanel1.Controls.Add(this.txtPort, 1, 1);
- this.tableLayoutPanel1.Controls.Add(this.lblHost, 0, 0);
- this.tableLayoutPanel1.Controls.Add(this.lblPort, 0, 1);
- this.tableLayoutPanel1.Controls.Add(this.txtHost, 1, 0);
- this.tableLayoutPanel1.Controls.Add(this.chkSpectator, 0, 2);
- this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.tableLayoutPanel1.Controls.Add(this.picOverscan, 1, 1);
+ this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel3, 0, 1);
+ 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(9, 19);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
- this.tableLayoutPanel1.RowCount = 4;
- this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel1.RowCount = 3;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel1.Size = new System.Drawing.Size(284, 175);
- this.tableLayoutPanel1.TabIndex = 1;
+ this.tableLayoutPanel1.Size = new System.Drawing.Size(277, 234);
+ this.tableLayoutPanel1.TabIndex = 0;
//
- // txtPort
+ // picOverscan
//
- this.txtPort.Dock = System.Windows.Forms.DockStyle.Fill;
- this.txtPort.Location = new System.Drawing.Point(41, 29);
- this.txtPort.Name = "txtPort";
- this.txtPort.Size = new System.Drawing.Size(240, 20);
- this.txtPort.TabIndex = 6;
- this.txtPort.Text = "8888";
+ this.picOverscan.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.picOverscan.Location = new System.Drawing.Point(56, 43);
+ this.picOverscan.Name = "picOverscan";
+ this.picOverscan.Size = new System.Drawing.Size(165, 148);
+ this.picOverscan.TabIndex = 1;
+ this.picOverscan.TabStop = false;
//
- // lblHost
+ // flowLayoutPanel3
//
- this.lblHost.Anchor = System.Windows.Forms.AnchorStyles.Left;
- this.lblHost.AutoSize = true;
- this.lblHost.Location = new System.Drawing.Point(3, 6);
- this.lblHost.Name = "lblHost";
- this.lblHost.Size = new System.Drawing.Size(32, 13);
- this.lblHost.TabIndex = 3;
- this.lblHost.Text = "Host:";
+ this.flowLayoutPanel3.Anchor = System.Windows.Forms.AnchorStyles.Right;
+ this.flowLayoutPanel3.Controls.Add(this.lblLeft);
+ this.flowLayoutPanel3.Controls.Add(this.nudOverscanLeft);
+ this.flowLayoutPanel3.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
+ this.flowLayoutPanel3.Location = new System.Drawing.Point(0, 97);
+ this.flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
+ this.flowLayoutPanel3.Name = "flowLayoutPanel3";
+ this.flowLayoutPanel3.Size = new System.Drawing.Size(53, 40);
+ this.flowLayoutPanel3.TabIndex = 1;
//
- // lblPort
+ // lblLeft
//
- this.lblPort.Anchor = System.Windows.Forms.AnchorStyles.Left;
- this.lblPort.AutoSize = true;
- this.lblPort.Location = new System.Drawing.Point(3, 32);
- this.lblPort.Name = "lblPort";
- this.lblPort.Size = new System.Drawing.Size(29, 13);
- this.lblPort.TabIndex = 4;
- this.lblPort.Text = "Port:";
+ this.lblLeft.AutoSize = true;
+ this.lblLeft.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lblLeft.Location = new System.Drawing.Point(3, 0);
+ this.lblLeft.Name = "lblLeft";
+ this.lblLeft.Size = new System.Drawing.Size(50, 13);
+ this.lblLeft.TabIndex = 0;
+ this.lblLeft.Text = "Left";
+ this.lblLeft.TextAlign = System.Drawing.ContentAlignment.TopCenter;
//
- // txtHost
+ // flowLayoutPanel4
//
- this.txtHost.Dock = System.Windows.Forms.DockStyle.Fill;
- this.txtHost.Location = new System.Drawing.Point(41, 3);
- this.txtHost.Name = "txtHost";
- this.txtHost.Size = new System.Drawing.Size(240, 20);
- this.txtHost.TabIndex = 5;
- this.txtHost.Text = "127.0.0.1";
+ this.flowLayoutPanel4.Anchor = System.Windows.Forms.AnchorStyles.None;
+ this.flowLayoutPanel4.Controls.Add(this.lblTop);
+ this.flowLayoutPanel4.Controls.Add(this.nudOverscanTop);
+ this.flowLayoutPanel4.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
+ this.flowLayoutPanel4.Location = new System.Drawing.Point(112, 0);
+ this.flowLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
+ this.flowLayoutPanel4.Name = "flowLayoutPanel4";
+ this.flowLayoutPanel4.Size = new System.Drawing.Size(53, 40);
+ this.flowLayoutPanel4.TabIndex = 2;
//
- // chkSpectator
+ // lblTop
//
- this.chkSpectator.AutoSize = true;
- this.tableLayoutPanel1.SetColumnSpan(this.chkSpectator, 2);
- this.chkSpectator.Enabled = false;
- this.chkSpectator.Location = new System.Drawing.Point(3, 55);
- this.chkSpectator.Name = "chkSpectator";
- this.chkSpectator.Size = new System.Drawing.Size(106, 17);
- this.chkSpectator.TabIndex = 7;
- this.chkSpectator.Text = "Join as spectator";
- this.chkSpectator.UseVisualStyleBackColor = true;
+ this.lblTop.AutoSize = true;
+ this.lblTop.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lblTop.Location = new System.Drawing.Point(3, 0);
+ this.lblTop.Name = "lblTop";
+ this.lblTop.Size = new System.Drawing.Size(50, 13);
+ this.lblTop.TabIndex = 0;
+ this.lblTop.Text = "Top";
+ this.lblTop.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ //
+ // flowLayoutPanel5
+ //
+ this.flowLayoutPanel5.Anchor = System.Windows.Forms.AnchorStyles.None;
+ this.flowLayoutPanel5.Controls.Add(this.lblBottom);
+ this.flowLayoutPanel5.Controls.Add(this.nudOverscanBottom);
+ this.flowLayoutPanel5.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
+ this.flowLayoutPanel5.Location = new System.Drawing.Point(112, 194);
+ this.flowLayoutPanel5.Margin = new System.Windows.Forms.Padding(0);
+ this.flowLayoutPanel5.Name = "flowLayoutPanel5";
+ this.flowLayoutPanel5.Size = new System.Drawing.Size(53, 40);
+ this.flowLayoutPanel5.TabIndex = 3;
+ //
+ // lblBottom
+ //
+ this.lblBottom.AutoSize = true;
+ this.lblBottom.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lblBottom.Location = new System.Drawing.Point(3, 0);
+ this.lblBottom.Name = "lblBottom";
+ this.lblBottom.Size = new System.Drawing.Size(50, 13);
+ this.lblBottom.TabIndex = 0;
+ this.lblBottom.Text = "Bottom";
+ this.lblBottom.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ //
+ // flowLayoutPanel2
+ //
+ this.flowLayoutPanel2.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.flowLayoutPanel2.Controls.Add(this.lblRight);
+ this.flowLayoutPanel2.Controls.Add(this.nudOverscanRight);
+ this.flowLayoutPanel2.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
+ this.flowLayoutPanel2.Location = new System.Drawing.Point(224, 97);
+ this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
+ this.flowLayoutPanel2.Name = "flowLayoutPanel2";
+ this.flowLayoutPanel2.Size = new System.Drawing.Size(53, 40);
+ this.flowLayoutPanel2.TabIndex = 0;
+ //
+ // lblRight
+ //
+ this.lblRight.AutoSize = true;
+ this.lblRight.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lblRight.Location = new System.Drawing.Point(3, 0);
+ this.lblRight.Name = "lblRight";
+ this.lblRight.Size = new System.Drawing.Size(50, 13);
+ this.lblRight.TabIndex = 0;
+ this.lblRight.Text = "Right";
+ this.lblRight.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ //
+ // chkLimitFps
+ //
+ this.chkLimitFps.AutoSize = true;
+ this.chkLimitFps.Location = new System.Drawing.Point(3, 3);
+ this.chkLimitFps.Name = "chkLimitFps";
+ this.chkLimitFps.Size = new System.Drawing.Size(70, 17);
+ this.chkLimitFps.TabIndex = 8;
+ this.chkLimitFps.Text = "Limit FPS";
+ this.chkLimitFps.UseVisualStyleBackColor = true;
+ //
+ // chkShowFps
+ //
+ this.chkShowFps.AutoSize = true;
+ this.chkShowFps.Location = new System.Drawing.Point(3, 26);
+ this.chkShowFps.Name = "chkShowFps";
+ this.chkShowFps.Size = new System.Drawing.Size(76, 17);
+ this.chkShowFps.TabIndex = 9;
+ this.chkShowFps.Text = "Show FPS";
+ this.chkShowFps.UseVisualStyleBackColor = true;
+ //
+ // nudRight
+ //
+ this.nudOverscanRight.Location = new System.Drawing.Point(3, 16);
+ this.nudOverscanRight.Name = "nudRight";
+ this.nudOverscanRight.Size = new System.Drawing.Size(50, 20);
+ this.nudOverscanRight.TabIndex = 1;
+ //
+ // nudBottom
+ //
+ this.nudOverscanBottom.Location = new System.Drawing.Point(3, 16);
+ this.nudOverscanBottom.Name = "nudBottom";
+ this.nudOverscanBottom.Size = new System.Drawing.Size(50, 20);
+ this.nudOverscanBottom.TabIndex = 2;
+ //
+ // nudLeft
+ //
+ this.nudOverscanLeft.Location = new System.Drawing.Point(3, 16);
+ this.nudOverscanLeft.Name = "nudLeft";
+ this.nudOverscanLeft.Size = new System.Drawing.Size(50, 20);
+ this.nudOverscanLeft.TabIndex = 2;
+ //
+ // nudTop
+ //
+ this.nudOverscanTop.Location = new System.Drawing.Point(3, 16);
+ this.nudOverscanTop.Name = "nudTop";
+ this.nudOverscanTop.Size = new System.Drawing.Size(50, 20);
+ this.nudOverscanTop.TabIndex = 2;
//
// frmVideoConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(284, 262);
- this.Controls.Add(this.tableLayoutPanel1);
+ this.ClientSize = new System.Drawing.Size(362, 337);
+ this.Controls.Add(this.tlpMain);
this.Name = "frmVideoConfig";
this.Text = "Video Options";
- this.Controls.SetChildIndex(this.tableLayoutPanel1, 0);
+ this.Controls.SetChildIndex(this.baseConfigPanel, 0);
+ this.Controls.SetChildIndex(this.tlpMain, 0);
+ this.tlpMain.ResumeLayout(false);
+ this.tlpMain.PerformLayout();
+ this.grpCropping.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
- this.tableLayoutPanel1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.picOverscan)).EndInit();
+ this.flowLayoutPanel3.ResumeLayout(false);
+ this.flowLayoutPanel3.PerformLayout();
+ this.flowLayoutPanel4.ResumeLayout(false);
+ this.flowLayoutPanel4.PerformLayout();
+ this.flowLayoutPanel5.ResumeLayout(false);
+ this.flowLayoutPanel5.PerformLayout();
+ this.flowLayoutPanel2.ResumeLayout(false);
+ this.flowLayoutPanel2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanRight)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanBottom)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanLeft)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.nudOverscanTop)).EndInit();
this.ResumeLayout(false);
}
#endregion
+ private System.Windows.Forms.TableLayoutPanel tlpMain;
+ private System.Windows.Forms.GroupBox grpCropping;
+ private System.Windows.Forms.CheckBox chkLimitFps;
+ private System.Windows.Forms.CheckBox chkShowFps;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
- private System.Windows.Forms.TextBox txtPort;
- private System.Windows.Forms.Label lblHost;
- private System.Windows.Forms.Label lblPort;
- private System.Windows.Forms.TextBox txtHost;
- private System.Windows.Forms.CheckBox chkSpectator;
+ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3;
+ private System.Windows.Forms.Label lblLeft;
+ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel4;
+ private System.Windows.Forms.Label lblTop;
+ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel5;
+ private System.Windows.Forms.Label lblBottom;
+ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;
+ private System.Windows.Forms.Label lblRight;
+ private System.Windows.Forms.PictureBox picOverscan;
+ private System.Windows.Forms.NumericUpDown nudOverscanLeft;
+ private System.Windows.Forms.NumericUpDown nudOverscanTop;
+ private System.Windows.Forms.NumericUpDown nudOverscanBottom;
+ private System.Windows.Forms.NumericUpDown nudOverscanRight;
}
}
\ No newline at end of file
diff --git a/GUI.NET/Forms/Config/frmVideoConfig.cs b/GUI.NET/Forms/Config/frmVideoConfig.cs
index c1f7f20a..3ba7684a 100644
--- a/GUI.NET/Forms/Config/frmVideoConfig.cs
+++ b/GUI.NET/Forms/Config/frmVideoConfig.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
+using Mesen.GUI.Config;
namespace Mesen.GUI.Forms.Config
{
@@ -15,6 +16,21 @@ namespace Mesen.GUI.Forms.Config
public frmVideoConfig()
{
InitializeComponent();
+
+ Entity = ConfigManager.Config.VideoInfo;
+
+ AddBinding("ShowFPS", chkShowFps);
+ AddBinding("LimitFPS", chkLimitFps);
+ AddBinding("OverscanLeft", nudOverscanLeft);
+ AddBinding("OverscanRight", nudOverscanRight);
+ AddBinding("OverscanTop", nudOverscanTop);
+ AddBinding("OverscanBottom", nudOverscanBottom);
+ }
+
+ protected override void OnFormClosed(FormClosedEventArgs e)
+ {
+ base.OnFormClosed(e);
+ VideoInfo.ApplyConfig();
}
}
}
diff --git a/GUI.NET/Forms/frmMain.Designer.cs b/GUI.NET/Forms/frmMain.Designer.cs
index d6e79ce9..cda20401 100644
--- a/GUI.NET/Forms/frmMain.Designer.cs
+++ b/GUI.NET/Forms/frmMain.Designer.cs
@@ -51,9 +51,13 @@
this.mnuLimitFPS = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowFPS = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
- this.mnuInput = new System.Windows.Forms.ToolStripMenuItem();
- this.mnuVideoConfig = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAudioConfig = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuInput = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuRegion = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuRegionAuto = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuRegionNtsc = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuRegionPal = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuVideoConfig = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTools = new System.Windows.Forms.ToolStripMenuItem();
this.mnuNetPlay = new System.Windows.Forms.ToolStripMenuItem();
this.mnuStartServer = new System.Windows.Forms.ToolStripMenuItem();
@@ -78,10 +82,6 @@
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
this.dxViewer = new Mesen.GUI.Controls.DXViewer();
- this.mnuRegion = new System.Windows.Forms.ToolStripMenuItem();
- this.mnuRegionAuto = new System.Windows.Forms.ToolStripMenuItem();
- this.mnuRegionNtsc = new System.Windows.Forms.ToolStripMenuItem();
- this.mnuRegionPal = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip.SuspendLayout();
this.SuspendLayout();
//
@@ -218,7 +218,7 @@
this.mnuLimitFPS.CheckOnClick = true;
this.mnuLimitFPS.Name = "mnuLimitFPS";
this.mnuLimitFPS.ShortcutKeys = System.Windows.Forms.Keys.F9;
- this.mnuLimitFPS.Size = new System.Drawing.Size(152, 22);
+ this.mnuLimitFPS.Size = new System.Drawing.Size(150, 22);
this.mnuLimitFPS.Text = "Limit FPS";
this.mnuLimitFPS.Click += new System.EventHandler(this.mnuLimitFPS_Click);
//
@@ -227,37 +227,67 @@
this.mnuShowFPS.CheckOnClick = true;
this.mnuShowFPS.Name = "mnuShowFPS";
this.mnuShowFPS.ShortcutKeys = System.Windows.Forms.Keys.F10;
- this.mnuShowFPS.Size = new System.Drawing.Size(152, 22);
+ this.mnuShowFPS.Size = new System.Drawing.Size(150, 22);
this.mnuShowFPS.Text = "Show FPS";
this.mnuShowFPS.Click += new System.EventHandler(this.mnuShowFPS_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
- this.toolStripMenuItem1.Size = new System.Drawing.Size(149, 6);
- //
- // mnuInput
- //
- this.mnuInput.Name = "mnuInput";
- this.mnuInput.Size = new System.Drawing.Size(152, 22);
- this.mnuInput.Text = "Input";
- this.mnuInput.Click += new System.EventHandler(this.mnuInput_Click);
- //
- // mnuVideoConfig
- //
- this.mnuVideoConfig.Enabled = false;
- this.mnuVideoConfig.Name = "mnuVideoConfig";
- this.mnuVideoConfig.Size = new System.Drawing.Size(152, 22);
- this.mnuVideoConfig.Text = "Video";
- this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
+ this.toolStripMenuItem1.Size = new System.Drawing.Size(147, 6);
//
// mnuAudioConfig
//
this.mnuAudioConfig.Name = "mnuAudioConfig";
- this.mnuAudioConfig.Size = new System.Drawing.Size(152, 22);
+ this.mnuAudioConfig.Size = new System.Drawing.Size(150, 22);
this.mnuAudioConfig.Text = "Audio";
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click);
//
+ // mnuInput
+ //
+ this.mnuInput.Name = "mnuInput";
+ this.mnuInput.Size = new System.Drawing.Size(150, 22);
+ this.mnuInput.Text = "Input";
+ this.mnuInput.Click += new System.EventHandler(this.mnuInput_Click);
+ //
+ // mnuRegion
+ //
+ this.mnuRegion.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.mnuRegionAuto,
+ this.mnuRegionNtsc,
+ this.mnuRegionPal});
+ this.mnuRegion.Name = "mnuRegion";
+ this.mnuRegion.Size = new System.Drawing.Size(150, 22);
+ this.mnuRegion.Text = "Region";
+ //
+ // mnuRegionAuto
+ //
+ this.mnuRegionAuto.Name = "mnuRegionAuto";
+ this.mnuRegionAuto.Size = new System.Drawing.Size(104, 22);
+ this.mnuRegionAuto.Text = "Auto";
+ this.mnuRegionAuto.Click += new System.EventHandler(this.mnuRegion_Click);
+ //
+ // mnuRegionNtsc
+ //
+ this.mnuRegionNtsc.Name = "mnuRegionNtsc";
+ this.mnuRegionNtsc.Size = new System.Drawing.Size(104, 22);
+ this.mnuRegionNtsc.Text = "NTSC";
+ this.mnuRegionNtsc.Click += new System.EventHandler(this.mnuRegion_Click);
+ //
+ // mnuRegionPal
+ //
+ this.mnuRegionPal.Name = "mnuRegionPal";
+ this.mnuRegionPal.Size = new System.Drawing.Size(104, 22);
+ this.mnuRegionPal.Text = "PAL";
+ this.mnuRegionPal.Click += new System.EventHandler(this.mnuRegion_Click);
+ //
+ // mnuVideoConfig
+ //
+ this.mnuVideoConfig.Name = "mnuVideoConfig";
+ this.mnuVideoConfig.Size = new System.Drawing.Size(150, 22);
+ this.mnuVideoConfig.Text = "Video";
+ this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
+ //
// mnuTools
//
this.mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -441,45 +471,15 @@
this.dxViewer.Location = new System.Drawing.Point(0, 24);
this.dxViewer.Margin = new System.Windows.Forms.Padding(0);
this.dxViewer.Name = "dxViewer";
- this.dxViewer.Size = new System.Drawing.Size(1024, 896);
+ this.dxViewer.Size = new System.Drawing.Size(1024, 960);
this.dxViewer.TabIndex = 1;
//
- // mnuRegion
- //
- this.mnuRegion.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.mnuRegionAuto,
- this.mnuRegionNtsc,
- this.mnuRegionPal});
- this.mnuRegion.Name = "mnuRegion";
- this.mnuRegion.Size = new System.Drawing.Size(152, 22);
- this.mnuRegion.Text = "Region";
- //
- // mnuRegionAuto
- //
- this.mnuRegionAuto.Name = "mnuRegionAuto";
- this.mnuRegionAuto.Size = new System.Drawing.Size(152, 22);
- this.mnuRegionAuto.Text = "Auto";
- this.mnuRegionAuto.Click += new System.EventHandler(this.mnuRegion_Click);
- //
- // mnuRegionNtsc
- //
- this.mnuRegionNtsc.Name = "mnuRegionNtsc";
- this.mnuRegionNtsc.Size = new System.Drawing.Size(152, 22);
- this.mnuRegionNtsc.Text = "NTSC";
- this.mnuRegionNtsc.Click += new System.EventHandler(this.mnuRegion_Click);
- //
- // mnuRegionPal
- //
- this.mnuRegionPal.Name = "mnuRegionPal";
- this.mnuRegionPal.Size = new System.Drawing.Size(152, 22);
- this.mnuRegionPal.Text = "PAL";
- this.mnuRegionPal.Click += new System.EventHandler(this.mnuRegion_Click);
- //
// frmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
+ this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ClientSize = new System.Drawing.Size(365, 272);
this.Controls.Add(this.dxViewer);
this.Controls.Add(this.menuStrip);
diff --git a/GUI.NET/Forms/frmMain.cs b/GUI.NET/Forms/frmMain.cs
index 69ca3ff9..2ab19a1a 100644
--- a/GUI.NET/Forms/frmMain.cs
+++ b/GUI.NET/Forms/frmMain.cs
@@ -37,8 +37,7 @@ namespace Mesen.GUI.Forms
_notifListener = new InteropEmu.NotificationListener();
_notifListener.OnNotification += _notifListener_OnNotification;
- mnuShowFPS.Checked = ConfigManager.Config.VideoInfo.ShowFPS;
- mnuLimitFPS.Checked = ConfigManager.Config.VideoInfo.LimitFPS;
+ UpdateVideoSettings();
InitializeEmu();
@@ -72,6 +71,13 @@ namespace Mesen.GUI.Forms
VideoInfo.ApplyConfig();
}
+ void UpdateVideoSettings()
+ {
+ mnuShowFPS.Checked = ConfigManager.Config.VideoInfo.ShowFPS;
+ mnuLimitFPS.Checked = ConfigManager.Config.VideoInfo.LimitFPS;
+ dxViewer.Size = VideoInfo.GetViewerSize();
+ }
+
void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.ToString(), "Unexpected Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
@@ -317,7 +323,8 @@ namespace Mesen.GUI.Forms
private void mnuVideoConfig_Click(object sender, EventArgs e)
{
-
+ new frmVideoConfig().ShowDialog();
+ UpdateVideoSettings();
}
private void mnuDebugger_Click(object sender, EventArgs e)
@@ -397,14 +404,12 @@ namespace Mesen.GUI.Forms
private void mnuInput_Click(object sender, EventArgs e)
{
- frmInputConfig frm = new frmInputConfig();
- frm.ShowDialog();
+ new frmInputConfig().ShowDialog();
}
private void mnuAudioConfig_Click(object sender, EventArgs e)
{
- frmAudioConfig frm = new frmAudioConfig();
- frm.ShowDialog();
+ new frmAudioConfig().ShowDialog();
}
private void mnuRegion_Click(object sender, EventArgs e)
diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs
index 1608a502..5d19b855 100644
--- a/GUI.NET/InteropEmu.cs
+++ b/GUI.NET/InteropEmu.cs
@@ -66,6 +66,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void SetChannelVolume(UInt32 channel, double volume);
[DllImport(DLLPath)] public static extern void SetAudioLatency(UInt32 msLatency);
[DllImport(DLLPath)] public static extern void SetNesModel(NesModel model);
+ [DllImport(DLLPath)] public static extern void SetOverscanDimensions(UInt32 left, UInt32 right, UInt32 top, UInt32 bottom);
[DllImport(DLLPath)] public static extern void DebugInitialize();
[DllImport(DLLPath)] public static extern void DebugRelease();
diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp
index 7c725c92..27c82013 100644
--- a/InteropDLL/ConsoleWrapper.cpp
+++ b/InteropDLL/ConsoleWrapper.cpp
@@ -12,6 +12,7 @@
#include "../Core/CheatManager.h"
#include "../Core/StandardController.h"
#include "../Core/EmulationSettings.h"
+#include "../Core/VideoDecoder.h"
static NES::Renderer *_renderer = nullptr;
static SoundManager *_soundManager = nullptr;
@@ -131,7 +132,7 @@ namespace InteropEmu {
}
DllExport void __stdcall Render() { _renderer->Render(); }
- DllExport void __stdcall TakeScreenshot() { _renderer->TakeScreenshot(Console::GetROMPath()); }
+ DllExport void __stdcall TakeScreenshot() { VideoDecoder::GetInstance()->TakeScreenshot(FolderUtilities::GetFilename(Console::GetROMPath(), false)); }
DllExport INotificationListener* __stdcall RegisterNotificationCallback(NotificationListenerCallback callback)
{
@@ -163,6 +164,7 @@ namespace InteropEmu {
DllExport void __stdcall SetChannelVolume(uint32_t channel, double volume) { EmulationSettings::SetChannelVolume((AudioChannel)channel, volume); }
DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { EmulationSettings::SetAudioLatency(msLatency); }
DllExport void __stdcall SetNesModel(uint32_t model) { EmulationSettings::SetNesModel((NesModel)model); }
+ DllExport void __stdcall SetOverscanDimensions(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) { EmulationSettings::SetOverscanDimensions(left, right, top, bottom); }
}
}
\ No newline at end of file
diff --git a/Windows/Renderer.cpp b/Windows/Renderer.cpp
index caa1cd70..facff700 100644
--- a/Windows/Renderer.cpp
+++ b/Windows/Renderer.cpp
@@ -16,16 +16,12 @@ namespace NES
{
Renderer::Renderer(HWND hWnd)
{
- SetScreenSize(256, 240);
-
_hWnd = hWnd;
- if(FAILED(InitDevice())) {
- CleanupDevice();
- } else {
- PPU::RegisterVideoDevice(this);
- MessageManager::RegisterMessageManager(this);
- }
+ SetScreenSize();
+
+ PPU::RegisterVideoDevice(this);
+ MessageManager::RegisterMessageManager(this);
}
Renderer::~Renderer()
@@ -33,17 +29,25 @@ namespace NES
CleanupDevice();
}
- void Renderer::SetScreenSize(uint32_t screenWidth, uint32_t screenHeight)
+ void Renderer::SetScreenSize()
{
- _screenWidth = screenWidth;
- _screenHeight = screenHeight;
- _bytesPerPixel = 4;
+ OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
- _hdScreenWidth = _screenWidth * 4;
- _hdScreenHeight = (_screenHeight - 16) * 4;
-
- _screenBufferSize = _screenWidth * _screenHeight * _bytesPerPixel;
- _hdScreenBufferSize = _hdScreenWidth * _hdScreenHeight * _bytesPerPixel;
+ if(_hdScreenBufferSize == 0 || _hdScreenBufferSize != overscan.GetPixelCount() * 64) {
+ uint32_t screenWidth = overscan.GetScreenWidth();
+ uint32_t screenHeight = overscan.GetScreenHeight();
+
+ _hdScreenWidth = screenWidth * 4;
+ _hdScreenHeight = screenHeight * 4;
+ _hdScreenBufferSize = _hdScreenWidth * _hdScreenHeight * _bytesPerPixel;
+
+ _frameLock.Acquire();
+ CleanupDevice();
+ if(FAILED(InitDevice())) {
+ CleanupDevice();
+ }
+ _frameLock.Release();
+ }
}
void Renderer::CleanupDevice()
@@ -67,11 +71,6 @@ namespace NES
_videoRAM = nullptr;
}
- if(_nextFrameBuffer) {
- delete[] _nextFrameBuffer;
- _nextFrameBuffer = nullptr;
- }
-
if(_overlayBuffer) {
delete[] _overlayBuffer;
_overlayBuffer = nullptr;
@@ -79,10 +78,12 @@ namespace NES
if(_ppuOutputBuffer) {
delete[] _ppuOutputBuffer;
+ _ppuOutputBuffer = nullptr;
}
if(_ppuOutputSecondaryBuffer) {
delete[] _ppuOutputSecondaryBuffer;
+ _ppuOutputSecondaryBuffer = nullptr;
}
}
@@ -228,16 +229,14 @@ namespace NES
vp.TopLeftY = 0;
_pDeviceContext->RSSetViewports(1, &vp);
- _videoRAM = new uint8_t[_screenBufferSize];
- _nextFrameBuffer = new uint8_t[_screenBufferSize];
- _ppuOutputBuffer = new uint16_t[_screenWidth * _screenHeight];
- _ppuOutputSecondaryBuffer = new uint16_t[_screenWidth * _screenHeight];
- memset(_videoRAM, 0x00, _screenBufferSize);
- memset(_nextFrameBuffer, 0x00, _screenBufferSize);
- memset(_ppuOutputBuffer, 0x00, _screenWidth * _screenHeight * sizeof(uint16_t));
- memset(_ppuOutputSecondaryBuffer, 0x00, _screenWidth * _screenHeight * sizeof(uint16_t));
+ _videoRAM = new uint32_t[PPU::PixelCount];
+ _ppuOutputBuffer = new uint16_t[PPU::PixelCount];
+ _ppuOutputSecondaryBuffer = new uint16_t[PPU::PixelCount];
+ memset(_videoRAM, 0x00, PPU::PixelCount * sizeof(uint32_t));
+ memset(_ppuOutputBuffer, 0x00, PPU::OutputBufferSize);
+ memset(_ppuOutputSecondaryBuffer, 0x00, PPU::OutputBufferSize);
- _pTexture = CreateTexture(_screenWidth, _screenHeight);
+ _pTexture = CreateTexture(_hdScreenWidth/4, _hdScreenHeight/4);
if(!_pTexture) {
return 0;
}
@@ -380,32 +379,31 @@ namespace NES
memcpy(_ppuOutputSecondaryBuffer, _ppuOutputBuffer, 256 * 240 * sizeof(uint16_t));
_frameLock.Release();
- VideoDecoder::DecodeFrame(_ppuOutputSecondaryBuffer, (uint32_t*)_nextFrameBuffer);
+ uint32_t* outputBuffer = VideoDecoder::GetInstance()->DecodeFrame(_ppuOutputSecondaryBuffer);
- RECT sourceRect;
- sourceRect.left = 0;
- sourceRect.right = _screenWidth;
- sourceRect.top = 8;
- sourceRect.bottom = _screenHeight - 8;
+ OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
RECT destRect;
destRect.left = 0;
destRect.top = 0;
- destRect.right = _screenWidth * 4;
- destRect.bottom = (_screenHeight - 16) * 4;
+ destRect.right = overscan.GetScreenWidth() * 4;
+ destRect.bottom = overscan.GetScreenHeight() * 4;
XMVECTOR position{ { 0, 0 } };
D3D11_MAPPED_SUBRESOURCE dd;
dd.pData = (void *)_videoRAM;
- dd.RowPitch = _screenWidth * _bytesPerPixel;
- dd.DepthPitch = _screenBufferSize;
+ dd.RowPitch = overscan.GetScreenWidth() * _bytesPerPixel;
+ dd.DepthPitch = overscan.GetPixelCount() * _bytesPerPixel;
_pDeviceContext->Map(_pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &dd);
- memcpy(dd.pData, _nextFrameBuffer, _screenBufferSize);
+ memset(dd.pData, 0, dd.DepthPitch);
+ for(uint32_t i = 0; i < overscan.GetScreenHeight(); i++) {
+ memcpy((uint8_t*)dd.pData+i*dd.RowPitch, outputBuffer+i*overscan.GetScreenWidth(), overscan.GetScreenWidth() * _bytesPerPixel);
+ }
_pDeviceContext->Unmap(_pTexture, 0);
ID3D11ShaderResourceView *nesOutputBuffer = GetShaderResourceView(_pTexture);
- _spriteBatch->Draw(nesOutputBuffer, destRect, &sourceRect);
+ _spriteBatch->Draw(nesOutputBuffer, destRect);
nesOutputBuffer->Release();
}
@@ -441,6 +439,8 @@ namespace NES
void Renderer::Render()
{
if(_frameChanged || EmulationSettings::CheckFlag(EmulationFlags::Paused) || !_toasts.empty()) {
+ SetScreenSize();
+
_frameChanged = false;
// Clear the back buffer
_pDeviceContext->ClearRenderTargetView(_pRenderTargetView, Colors::Black);
@@ -473,7 +473,7 @@ namespace NES
}
string fpsString = string("FPS: ") + std::to_string(_currentFPS);
- DrawOutlinedString(fpsString, 256 * 4 - 80, 13, Colors::AntiqueWhite, 1.0f);
+ DrawOutlinedString(fpsString, (float)(_hdScreenWidth - 80), 13, Colors::AntiqueWhite, 1.0f);
}
}
@@ -591,40 +591,4 @@ namespace NES
_frameChanged = true;
_frameCount++;
}
-
- void Renderer::TakeScreenshot(string romFilename)
- {
- uint32_t* frameBuffer = new uint32_t[256 * 240];
-
- _frameLock.Acquire();
- memcpy(frameBuffer, _nextFrameBuffer, 256 * 240 * 4);
- _frameLock.Release();
-
- //ARGB -> ABGR
- for(uint32_t i = 0; i < 256 * 240; i++) {
- frameBuffer[i] = (frameBuffer[i] & 0xFF00FF00) | ((frameBuffer[i] & 0xFF0000) >> 16) | ((frameBuffer[i] & 0xFF) << 16);
- }
-
- int counter = 0;
- string baseFilename = FolderUtilities::GetScreenshotFolder() + FolderUtilities::GetFilename(romFilename, false);
- string ssFilename;
- while(true) {
- string counterStr = std::to_string(counter);
- while(counterStr.length() < 3) {
- counterStr = "0" + counterStr;
- }
- ssFilename = baseFilename + "_" + counterStr + ".png";
- ifstream file(ssFilename, ios::in);
- if(file) {
- file.close();
- } else {
- break;
- }
- counter++;
- }
-
- PNGWriter::WritePNG(ssFilename, (uint8_t*)frameBuffer, 256, 240);
- MessageManager::DisplayMessage("Screenshot saved", FolderUtilities::GetFilename(ssFilename, true));
- }
-
}
\ No newline at end of file
diff --git a/Windows/Renderer.h b/Windows/Renderer.h
index 3f6c4fe6..5e65ebe6 100644
--- a/Windows/Renderer.h
+++ b/Windows/Renderer.h
@@ -36,10 +36,9 @@ namespace NES {
ID3D11SamplerState* _samplerState = nullptr;
ID3D11Texture2D* _pTexture = nullptr;
- byte* _videoRAM = nullptr;
+ uint32_t* _videoRAM = nullptr;
bool _frameChanged = true;
- uint8_t* _nextFrameBuffer = nullptr;
uint16_t* _ppuOutputBuffer = nullptr;
uint16_t* _ppuOutputSecondaryBuffer = nullptr;
SimpleLock _frameLock;
@@ -57,23 +56,18 @@ namespace NES {
unique_ptr _spriteBatch;
//ID3D11PixelShader* _pixelShader = nullptr;
- uint32_t _screenWidth;
- uint32_t _screenHeight;
- uint32_t _bytesPerPixel;
- uint32_t _hdScreenWidth;
- uint32_t _hdScreenHeight;
- uint32_t _screenBufferSize;
- uint32_t _hdScreenBufferSize;
-
- uint32_t _flags = 0;
+ const uint32_t _bytesPerPixel = 4;
+ uint32_t _hdScreenWidth = 0;
+ uint32_t _hdScreenHeight = 0;
+ uint32_t _hdScreenBufferSize = 0;
list> _toasts;
- ID3D11ShaderResourceView* _toastTexture;
+ ID3D11ShaderResourceView* _toastTexture = nullptr;
HRESULT InitDevice();
void CleanupDevice();
- void SetScreenSize(uint32_t screenWidth, uint32_t screenHeight);
+ void SetScreenSize();
ID3D11Texture2D* CreateTexture(uint32_t width, uint32_t height);
ID3D11ShaderResourceView* GetShaderResourceView(ID3D11Texture2D* texture);
@@ -92,27 +86,8 @@ namespace NES {
~Renderer();
void Render();
-
void DisplayMessage(string title, string message);
-
- void SetFlags(uint32_t flags)
- {
- _flags |= flags;
- }
-
- void ClearFlags(uint32_t flags)
- {
- _flags &= ~flags;
- }
-
- bool CheckFlag(uint32_t flag)
- {
- return (_flags & flag) == flag;
- }
-
void UpdateFrame(void* frameBuffer);
void DisplayToast(shared_ptr toast);
-
- void TakeScreenshot(string romFilename);
};
}
\ No newline at end of file