Added overscan config

This commit is contained in:
Souryo 2015-07-23 23:16:31 -04:00
parent fb17e7b154
commit 068fa72e87
16 changed files with 606 additions and 299 deletions

View file

@ -361,6 +361,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release x64|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release x64|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release x64|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release x64|x64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="VideoDecoder.cpp" />
<ClCompile Include="VirtualController.cpp" /> <ClCompile Include="VirtualController.cpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -301,5 +301,8 @@
<ClCompile Include="ApuLengthCounter.cpp"> <ClCompile Include="ApuLengthCounter.cpp">
<Filter>Source Files\APU</Filter> <Filter>Source Files\APU</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="VideoDecoder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -4,4 +4,5 @@
uint32_t EmulationSettings::Flags = 0; uint32_t EmulationSettings::Flags = 0;
uint32_t EmulationSettings::AudioLatency = 20000; uint32_t EmulationSettings::AudioLatency = 20000;
double EmulationSettings::ChannelVolume[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; double EmulationSettings::ChannelVolume[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
NesModel EmulationSettings::Model; NesModel EmulationSettings::Model;
OverscanDimensions EmulationSettings::Overscan;

View file

@ -25,6 +25,29 @@ enum class NesModel
PAL = 2, 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 class EmulationSettings
{ {
private: private:
@ -32,6 +55,7 @@ private:
static uint32_t AudioLatency; static uint32_t AudioLatency;
static double ChannelVolume[5]; static double ChannelVolume[5];
static NesModel Model; static NesModel Model;
static OverscanDimensions Overscan;
public: public:
static void SetFlags(uint32_t flags) static void SetFlags(uint32_t flags)
@ -70,6 +94,19 @@ public:
AudioLatency = msLatency; 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) static double GetChannelVolume(AudioChannel channel)
{ {
return ChannelVolume[(int)channel]; return ChannelVolume[(int)channel];

View file

@ -182,6 +182,11 @@ class PPU : public IMemoryHandler, public Snapshotable
void StreamState(bool saving); void StreamState(bool saving);
public: 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(MemoryManager *memoryManager);
~PPU(); ~PPU();

143
Core/VideoDecoder.cpp Normal file
View file

@ -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> 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));
}

View file

@ -1,67 +1,24 @@
#pragma once #pragma once
#include "stdafx.h" #include "stdafx.h"
#include <algorithm> #include "../Utilities/SimpleLock.h"
#include "EmulationSettings.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,
};
class VideoDecoder class VideoDecoder
{ {
private: private:
static uint32_t ProcessIntensifyBits(uint16_t ppuPixel) static unique_ptr<VideoDecoder> Instance;
{
uint32_t pixelOutput = PPU_PALETTE_ARGB[ppuPixel & 0x3F];
//Incorrect emphasis bit implementation, but will do for now. OverscanDimensions _overscan;
float redChannel = (float)((pixelOutput & 0xFF0000) >> 16); uint32_t* _frameBuffer = nullptr;
float greenChannel = (float)((pixelOutput & 0xFF00) >> 8); SimpleLock _frameLock;
float blueChannel = (float)(pixelOutput & 0xFF);
if(ppuPixel & 0x40) { uint32_t ProcessIntensifyBits(uint16_t ppuPixel);
//Intensify red void UpdateBufferSize();
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;
}
public: public:
static void DecodeFrame(uint16_t* inputBuffer, uint32_t* outputBuffer) static VideoDecoder* GetInstance();
{ ~VideoDecoder();
for(uint32_t i = 0; i < 256*240; i++) {
((uint32_t*)outputBuffer)[i] = ProcessIntensifyBits(inputBuffer[i]); uint32_t* DecodeFrame(uint16_t* inputBuffer);
} void TakeScreenshot(string romFilename);
}
}; };

View file

@ -13,6 +13,10 @@ namespace Mesen.GUI.Config
{ {
public bool LimitFPS = true; public bool LimitFPS = true;
public bool ShowFPS = false; public bool ShowFPS = false;
public UInt32 OverscanLeft = 0;
public UInt32 OverscanRight = 0;
public UInt32 OverscanTop = 8;
public UInt32 OverscanBottom = 8;
public VideoInfo() public VideoInfo()
{ {
@ -20,6 +24,7 @@ namespace Mesen.GUI.Config
static public void ApplyConfig() static public void ApplyConfig()
{ {
VideoInfo videoInfo = ConfigManager.Config.VideoInfo;
if(ConfigManager.Config.VideoInfo.LimitFPS) { if(ConfigManager.Config.VideoInfo.LimitFPS) {
InteropEmu.SetFlags((UInt32)EmulationFlags.LimitFPS); InteropEmu.SetFlags((UInt32)EmulationFlags.LimitFPS);
} else { } else {
@ -31,6 +36,14 @@ namespace Mesen.GUI.Config
} else { } else {
InteropEmu.ClearFlags((UInt32)EmulationFlags.ShowFPS); 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);
} }
} }
} }

View file

@ -27,107 +27,291 @@
/// </summary> /// </summary>
private void InitializeComponent() 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.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.txtPort = new System.Windows.Forms.TextBox(); this.picOverscan = new System.Windows.Forms.PictureBox();
this.lblHost = new System.Windows.Forms.Label(); this.flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel();
this.lblPort = new System.Windows.Forms.Label(); this.lblLeft = new System.Windows.Forms.Label();
this.txtHost = new System.Windows.Forms.TextBox(); this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel();
this.chkSpectator = new System.Windows.Forms.CheckBox(); 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(); 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(); 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 // 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());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); 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.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.lblHost, 0, 0); this.tableLayoutPanel1.Controls.Add(this.picOverscan, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.lblPort, 0, 1); this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel3, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.txtHost, 1, 0); this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel4, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.chkSpectator, 0, 2); this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel5, 1, 2);
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 2, 1);
this.tableLayoutPanel1.Location = new System.Drawing.Point(9, 19);
this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 4; this.tableLayoutPanel1.RowCount = 3;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); 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(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(284, 175); this.tableLayoutPanel1.Size = new System.Drawing.Size(277, 234);
this.tableLayoutPanel1.TabIndex = 1; this.tableLayoutPanel1.TabIndex = 0;
// //
// txtPort // picOverscan
// //
this.txtPort.Dock = System.Windows.Forms.DockStyle.Fill; this.picOverscan.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtPort.Location = new System.Drawing.Point(41, 29); this.picOverscan.Location = new System.Drawing.Point(56, 43);
this.txtPort.Name = "txtPort"; this.picOverscan.Name = "picOverscan";
this.txtPort.Size = new System.Drawing.Size(240, 20); this.picOverscan.Size = new System.Drawing.Size(165, 148);
this.txtPort.TabIndex = 6; this.picOverscan.TabIndex = 1;
this.txtPort.Text = "8888"; this.picOverscan.TabStop = false;
// //
// lblHost // flowLayoutPanel3
// //
this.lblHost.Anchor = System.Windows.Forms.AnchorStyles.Left; this.flowLayoutPanel3.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.lblHost.AutoSize = true; this.flowLayoutPanel3.Controls.Add(this.lblLeft);
this.lblHost.Location = new System.Drawing.Point(3, 6); this.flowLayoutPanel3.Controls.Add(this.nudOverscanLeft);
this.lblHost.Name = "lblHost"; this.flowLayoutPanel3.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.lblHost.Size = new System.Drawing.Size(32, 13); this.flowLayoutPanel3.Location = new System.Drawing.Point(0, 97);
this.lblHost.TabIndex = 3; this.flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
this.lblHost.Text = "Host:"; 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.lblLeft.AutoSize = true;
this.lblPort.AutoSize = true; this.lblLeft.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblPort.Location = new System.Drawing.Point(3, 32); this.lblLeft.Location = new System.Drawing.Point(3, 0);
this.lblPort.Name = "lblPort"; this.lblLeft.Name = "lblLeft";
this.lblPort.Size = new System.Drawing.Size(29, 13); this.lblLeft.Size = new System.Drawing.Size(50, 13);
this.lblPort.TabIndex = 4; this.lblLeft.TabIndex = 0;
this.lblPort.Text = "Port:"; this.lblLeft.Text = "Left";
this.lblLeft.TextAlign = System.Drawing.ContentAlignment.TopCenter;
// //
// txtHost // flowLayoutPanel4
// //
this.txtHost.Dock = System.Windows.Forms.DockStyle.Fill; this.flowLayoutPanel4.Anchor = System.Windows.Forms.AnchorStyles.None;
this.txtHost.Location = new System.Drawing.Point(41, 3); this.flowLayoutPanel4.Controls.Add(this.lblTop);
this.txtHost.Name = "txtHost"; this.flowLayoutPanel4.Controls.Add(this.nudOverscanTop);
this.txtHost.Size = new System.Drawing.Size(240, 20); this.flowLayoutPanel4.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.txtHost.TabIndex = 5; this.flowLayoutPanel4.Location = new System.Drawing.Point(112, 0);
this.txtHost.Text = "127.0.0.1"; 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.lblTop.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.chkSpectator, 2); this.lblTop.Dock = System.Windows.Forms.DockStyle.Fill;
this.chkSpectator.Enabled = false; this.lblTop.Location = new System.Drawing.Point(3, 0);
this.chkSpectator.Location = new System.Drawing.Point(3, 55); this.lblTop.Name = "lblTop";
this.chkSpectator.Name = "chkSpectator"; this.lblTop.Size = new System.Drawing.Size(50, 13);
this.chkSpectator.Size = new System.Drawing.Size(106, 17); this.lblTop.TabIndex = 0;
this.chkSpectator.TabIndex = 7; this.lblTop.Text = "Top";
this.chkSpectator.Text = "Join as spectator"; this.lblTop.TextAlign = System.Drawing.ContentAlignment.TopCenter;
this.chkSpectator.UseVisualStyleBackColor = true; //
// 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 // frmVideoConfig
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262); this.ClientSize = new System.Drawing.Size(362, 337);
this.Controls.Add(this.tableLayoutPanel1); this.Controls.Add(this.tlpMain);
this.Name = "frmVideoConfig"; this.Name = "frmVideoConfig";
this.Text = "Video Options"; 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.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); this.ResumeLayout(false);
} }
#endregion #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.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.TextBox txtPort; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3;
private System.Windows.Forms.Label lblHost; private System.Windows.Forms.Label lblLeft;
private System.Windows.Forms.Label lblPort; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel4;
private System.Windows.Forms.TextBox txtHost; private System.Windows.Forms.Label lblTop;
private System.Windows.Forms.CheckBox chkSpectator; 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;
} }
} }

View file

@ -7,6 +7,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Mesen.GUI.Config;
namespace Mesen.GUI.Forms.Config namespace Mesen.GUI.Forms.Config
{ {
@ -15,6 +16,21 @@ namespace Mesen.GUI.Forms.Config
public frmVideoConfig() public frmVideoConfig()
{ {
InitializeComponent(); 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();
} }
} }
} }

View file

@ -51,9 +51,13 @@
this.mnuLimitFPS = new System.Windows.Forms.ToolStripMenuItem(); this.mnuLimitFPS = new System.Windows.Forms.ToolStripMenuItem();
this.mnuShowFPS = new System.Windows.Forms.ToolStripMenuItem(); this.mnuShowFPS = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); 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.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.mnuTools = new System.Windows.Forms.ToolStripMenuItem();
this.mnuNetPlay = new System.Windows.Forms.ToolStripMenuItem(); this.mnuNetPlay = new System.Windows.Forms.ToolStripMenuItem();
this.mnuStartServer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuStartServer = new System.Windows.Forms.ToolStripMenuItem();
@ -78,10 +82,6 @@
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem(); this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
this.dxViewer = new Mesen.GUI.Controls.DXViewer(); 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.menuStrip.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
@ -218,7 +218,7 @@
this.mnuLimitFPS.CheckOnClick = true; this.mnuLimitFPS.CheckOnClick = true;
this.mnuLimitFPS.Name = "mnuLimitFPS"; this.mnuLimitFPS.Name = "mnuLimitFPS";
this.mnuLimitFPS.ShortcutKeys = System.Windows.Forms.Keys.F9; 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.Text = "Limit FPS";
this.mnuLimitFPS.Click += new System.EventHandler(this.mnuLimitFPS_Click); this.mnuLimitFPS.Click += new System.EventHandler(this.mnuLimitFPS_Click);
// //
@ -227,37 +227,67 @@
this.mnuShowFPS.CheckOnClick = true; this.mnuShowFPS.CheckOnClick = true;
this.mnuShowFPS.Name = "mnuShowFPS"; this.mnuShowFPS.Name = "mnuShowFPS";
this.mnuShowFPS.ShortcutKeys = System.Windows.Forms.Keys.F10; 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.Text = "Show FPS";
this.mnuShowFPS.Click += new System.EventHandler(this.mnuShowFPS_Click); this.mnuShowFPS.Click += new System.EventHandler(this.mnuShowFPS_Click);
// //
// toolStripMenuItem1 // toolStripMenuItem1
// //
this.toolStripMenuItem1.Name = "toolStripMenuItem1"; this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(149, 6); this.toolStripMenuItem1.Size = new System.Drawing.Size(147, 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);
// //
// mnuAudioConfig // mnuAudioConfig
// //
this.mnuAudioConfig.Name = "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.Text = "Audio";
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click); 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 // mnuTools
// //
this.mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -441,45 +471,15 @@
this.dxViewer.Location = new System.Drawing.Point(0, 24); this.dxViewer.Location = new System.Drawing.Point(0, 24);
this.dxViewer.Margin = new System.Windows.Forms.Padding(0); this.dxViewer.Margin = new System.Windows.Forms.Padding(0);
this.dxViewer.Name = "dxViewer"; 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; 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 // frmMain
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true; this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ClientSize = new System.Drawing.Size(365, 272); this.ClientSize = new System.Drawing.Size(365, 272);
this.Controls.Add(this.dxViewer); this.Controls.Add(this.dxViewer);
this.Controls.Add(this.menuStrip); this.Controls.Add(this.menuStrip);

View file

@ -37,8 +37,7 @@ namespace Mesen.GUI.Forms
_notifListener = new InteropEmu.NotificationListener(); _notifListener = new InteropEmu.NotificationListener();
_notifListener.OnNotification += _notifListener_OnNotification; _notifListener.OnNotification += _notifListener_OnNotification;
mnuShowFPS.Checked = ConfigManager.Config.VideoInfo.ShowFPS; UpdateVideoSettings();
mnuLimitFPS.Checked = ConfigManager.Config.VideoInfo.LimitFPS;
InitializeEmu(); InitializeEmu();
@ -72,6 +71,13 @@ namespace Mesen.GUI.Forms
VideoInfo.ApplyConfig(); 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) void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{ {
MessageBox.Show(e.Exception.ToString(), "Unexpected Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 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) private void mnuVideoConfig_Click(object sender, EventArgs e)
{ {
new frmVideoConfig().ShowDialog();
UpdateVideoSettings();
} }
private void mnuDebugger_Click(object sender, EventArgs e) private void mnuDebugger_Click(object sender, EventArgs e)
@ -397,14 +404,12 @@ namespace Mesen.GUI.Forms
private void mnuInput_Click(object sender, EventArgs e) private void mnuInput_Click(object sender, EventArgs e)
{ {
frmInputConfig frm = new frmInputConfig(); new frmInputConfig().ShowDialog();
frm.ShowDialog();
} }
private void mnuAudioConfig_Click(object sender, EventArgs e) private void mnuAudioConfig_Click(object sender, EventArgs e)
{ {
frmAudioConfig frm = new frmAudioConfig(); new frmAudioConfig().ShowDialog();
frm.ShowDialog();
} }
private void mnuRegion_Click(object sender, EventArgs e) private void mnuRegion_Click(object sender, EventArgs e)

View file

@ -66,6 +66,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void SetChannelVolume(UInt32 channel, double volume); [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 SetAudioLatency(UInt32 msLatency);
[DllImport(DLLPath)] public static extern void SetNesModel(NesModel model); [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 DebugInitialize();
[DllImport(DLLPath)] public static extern void DebugRelease(); [DllImport(DLLPath)] public static extern void DebugRelease();

View file

@ -12,6 +12,7 @@
#include "../Core/CheatManager.h" #include "../Core/CheatManager.h"
#include "../Core/StandardController.h" #include "../Core/StandardController.h"
#include "../Core/EmulationSettings.h" #include "../Core/EmulationSettings.h"
#include "../Core/VideoDecoder.h"
static NES::Renderer *_renderer = nullptr; static NES::Renderer *_renderer = nullptr;
static SoundManager *_soundManager = nullptr; static SoundManager *_soundManager = nullptr;
@ -131,7 +132,7 @@ namespace InteropEmu {
} }
DllExport void __stdcall Render() { _renderer->Render(); } 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) 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 SetChannelVolume(uint32_t channel, double volume) { EmulationSettings::SetChannelVolume((AudioChannel)channel, volume); }
DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { EmulationSettings::SetAudioLatency(msLatency); } DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { EmulationSettings::SetAudioLatency(msLatency); }
DllExport void __stdcall SetNesModel(uint32_t model) { EmulationSettings::SetNesModel((NesModel)model); } 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); }
} }
} }

View file

@ -16,16 +16,12 @@ namespace NES
{ {
Renderer::Renderer(HWND hWnd) Renderer::Renderer(HWND hWnd)
{ {
SetScreenSize(256, 240);
_hWnd = hWnd; _hWnd = hWnd;
if(FAILED(InitDevice())) { SetScreenSize();
CleanupDevice();
} else { PPU::RegisterVideoDevice(this);
PPU::RegisterVideoDevice(this); MessageManager::RegisterMessageManager(this);
MessageManager::RegisterMessageManager(this);
}
} }
Renderer::~Renderer() Renderer::~Renderer()
@ -33,17 +29,25 @@ namespace NES
CleanupDevice(); CleanupDevice();
} }
void Renderer::SetScreenSize(uint32_t screenWidth, uint32_t screenHeight) void Renderer::SetScreenSize()
{ {
_screenWidth = screenWidth; OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
_screenHeight = screenHeight;
_bytesPerPixel = 4;
_hdScreenWidth = _screenWidth * 4; if(_hdScreenBufferSize == 0 || _hdScreenBufferSize != overscan.GetPixelCount() * 64) {
_hdScreenHeight = (_screenHeight - 16) * 4; uint32_t screenWidth = overscan.GetScreenWidth();
uint32_t screenHeight = overscan.GetScreenHeight();
_screenBufferSize = _screenWidth * _screenHeight * _bytesPerPixel;
_hdScreenBufferSize = _hdScreenWidth * _hdScreenHeight * _bytesPerPixel; _hdScreenWidth = screenWidth * 4;
_hdScreenHeight = screenHeight * 4;
_hdScreenBufferSize = _hdScreenWidth * _hdScreenHeight * _bytesPerPixel;
_frameLock.Acquire();
CleanupDevice();
if(FAILED(InitDevice())) {
CleanupDevice();
}
_frameLock.Release();
}
} }
void Renderer::CleanupDevice() void Renderer::CleanupDevice()
@ -67,11 +71,6 @@ namespace NES
_videoRAM = nullptr; _videoRAM = nullptr;
} }
if(_nextFrameBuffer) {
delete[] _nextFrameBuffer;
_nextFrameBuffer = nullptr;
}
if(_overlayBuffer) { if(_overlayBuffer) {
delete[] _overlayBuffer; delete[] _overlayBuffer;
_overlayBuffer = nullptr; _overlayBuffer = nullptr;
@ -79,10 +78,12 @@ namespace NES
if(_ppuOutputBuffer) { if(_ppuOutputBuffer) {
delete[] _ppuOutputBuffer; delete[] _ppuOutputBuffer;
_ppuOutputBuffer = nullptr;
} }
if(_ppuOutputSecondaryBuffer) { if(_ppuOutputSecondaryBuffer) {
delete[] _ppuOutputSecondaryBuffer; delete[] _ppuOutputSecondaryBuffer;
_ppuOutputSecondaryBuffer = nullptr;
} }
} }
@ -228,16 +229,14 @@ namespace NES
vp.TopLeftY = 0; vp.TopLeftY = 0;
_pDeviceContext->RSSetViewports(1, &vp); _pDeviceContext->RSSetViewports(1, &vp);
_videoRAM = new uint8_t[_screenBufferSize]; _videoRAM = new uint32_t[PPU::PixelCount];
_nextFrameBuffer = new uint8_t[_screenBufferSize]; _ppuOutputBuffer = new uint16_t[PPU::PixelCount];
_ppuOutputBuffer = new uint16_t[_screenWidth * _screenHeight]; _ppuOutputSecondaryBuffer = new uint16_t[PPU::PixelCount];
_ppuOutputSecondaryBuffer = new uint16_t[_screenWidth * _screenHeight]; memset(_videoRAM, 0x00, PPU::PixelCount * sizeof(uint32_t));
memset(_videoRAM, 0x00, _screenBufferSize); memset(_ppuOutputBuffer, 0x00, PPU::OutputBufferSize);
memset(_nextFrameBuffer, 0x00, _screenBufferSize); memset(_ppuOutputSecondaryBuffer, 0x00, PPU::OutputBufferSize);
memset(_ppuOutputBuffer, 0x00, _screenWidth * _screenHeight * sizeof(uint16_t));
memset(_ppuOutputSecondaryBuffer, 0x00, _screenWidth * _screenHeight * sizeof(uint16_t));
_pTexture = CreateTexture(_screenWidth, _screenHeight); _pTexture = CreateTexture(_hdScreenWidth/4, _hdScreenHeight/4);
if(!_pTexture) { if(!_pTexture) {
return 0; return 0;
} }
@ -380,32 +379,31 @@ namespace NES
memcpy(_ppuOutputSecondaryBuffer, _ppuOutputBuffer, 256 * 240 * sizeof(uint16_t)); memcpy(_ppuOutputSecondaryBuffer, _ppuOutputBuffer, 256 * 240 * sizeof(uint16_t));
_frameLock.Release(); _frameLock.Release();
VideoDecoder::DecodeFrame(_ppuOutputSecondaryBuffer, (uint32_t*)_nextFrameBuffer); uint32_t* outputBuffer = VideoDecoder::GetInstance()->DecodeFrame(_ppuOutputSecondaryBuffer);
RECT sourceRect; OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
sourceRect.left = 0;
sourceRect.right = _screenWidth;
sourceRect.top = 8;
sourceRect.bottom = _screenHeight - 8;
RECT destRect; RECT destRect;
destRect.left = 0; destRect.left = 0;
destRect.top = 0; destRect.top = 0;
destRect.right = _screenWidth * 4; destRect.right = overscan.GetScreenWidth() * 4;
destRect.bottom = (_screenHeight - 16) * 4; destRect.bottom = overscan.GetScreenHeight() * 4;
XMVECTOR position{ { 0, 0 } }; XMVECTOR position{ { 0, 0 } };
D3D11_MAPPED_SUBRESOURCE dd; D3D11_MAPPED_SUBRESOURCE dd;
dd.pData = (void *)_videoRAM; dd.pData = (void *)_videoRAM;
dd.RowPitch = _screenWidth * _bytesPerPixel; dd.RowPitch = overscan.GetScreenWidth() * _bytesPerPixel;
dd.DepthPitch = _screenBufferSize; dd.DepthPitch = overscan.GetPixelCount() * _bytesPerPixel;
_pDeviceContext->Map(_pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &dd); _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); _pDeviceContext->Unmap(_pTexture, 0);
ID3D11ShaderResourceView *nesOutputBuffer = GetShaderResourceView(_pTexture); ID3D11ShaderResourceView *nesOutputBuffer = GetShaderResourceView(_pTexture);
_spriteBatch->Draw(nesOutputBuffer, destRect, &sourceRect); _spriteBatch->Draw(nesOutputBuffer, destRect);
nesOutputBuffer->Release(); nesOutputBuffer->Release();
} }
@ -441,6 +439,8 @@ namespace NES
void Renderer::Render() void Renderer::Render()
{ {
if(_frameChanged || EmulationSettings::CheckFlag(EmulationFlags::Paused) || !_toasts.empty()) { if(_frameChanged || EmulationSettings::CheckFlag(EmulationFlags::Paused) || !_toasts.empty()) {
SetScreenSize();
_frameChanged = false; _frameChanged = false;
// Clear the back buffer // Clear the back buffer
_pDeviceContext->ClearRenderTargetView(_pRenderTargetView, Colors::Black); _pDeviceContext->ClearRenderTargetView(_pRenderTargetView, Colors::Black);
@ -473,7 +473,7 @@ namespace NES
} }
string fpsString = string("FPS: ") + std::to_string(_currentFPS); 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; _frameChanged = true;
_frameCount++; _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));
}
} }

View file

@ -36,10 +36,9 @@ namespace NES {
ID3D11SamplerState* _samplerState = nullptr; ID3D11SamplerState* _samplerState = nullptr;
ID3D11Texture2D* _pTexture = nullptr; ID3D11Texture2D* _pTexture = nullptr;
byte* _videoRAM = nullptr; uint32_t* _videoRAM = nullptr;
bool _frameChanged = true; bool _frameChanged = true;
uint8_t* _nextFrameBuffer = nullptr;
uint16_t* _ppuOutputBuffer = nullptr; uint16_t* _ppuOutputBuffer = nullptr;
uint16_t* _ppuOutputSecondaryBuffer = nullptr; uint16_t* _ppuOutputSecondaryBuffer = nullptr;
SimpleLock _frameLock; SimpleLock _frameLock;
@ -57,23 +56,18 @@ namespace NES {
unique_ptr<SpriteBatch> _spriteBatch; unique_ptr<SpriteBatch> _spriteBatch;
//ID3D11PixelShader* _pixelShader = nullptr; //ID3D11PixelShader* _pixelShader = nullptr;
uint32_t _screenWidth; const uint32_t _bytesPerPixel = 4;
uint32_t _screenHeight; uint32_t _hdScreenWidth = 0;
uint32_t _bytesPerPixel; uint32_t _hdScreenHeight = 0;
uint32_t _hdScreenWidth; uint32_t _hdScreenBufferSize = 0;
uint32_t _hdScreenHeight;
uint32_t _screenBufferSize;
uint32_t _hdScreenBufferSize;
uint32_t _flags = 0;
list<shared_ptr<ToastInfo>> _toasts; list<shared_ptr<ToastInfo>> _toasts;
ID3D11ShaderResourceView* _toastTexture; ID3D11ShaderResourceView* _toastTexture = nullptr;
HRESULT InitDevice(); HRESULT InitDevice();
void CleanupDevice(); void CleanupDevice();
void SetScreenSize(uint32_t screenWidth, uint32_t screenHeight); void SetScreenSize();
ID3D11Texture2D* CreateTexture(uint32_t width, uint32_t height); ID3D11Texture2D* CreateTexture(uint32_t width, uint32_t height);
ID3D11ShaderResourceView* GetShaderResourceView(ID3D11Texture2D* texture); ID3D11ShaderResourceView* GetShaderResourceView(ID3D11Texture2D* texture);
@ -92,27 +86,8 @@ namespace NES {
~Renderer(); ~Renderer();
void Render(); void Render();
void DisplayMessage(string title, string message); 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 UpdateFrame(void* frameBuffer);
void DisplayToast(shared_ptr<ToastInfo> toast); void DisplayToast(shared_ptr<ToastInfo> toast);
void TakeScreenshot(string romFilename);
}; };
} }