PPU: Always output a 239-line picture (+ UI refactoring for scaling/resizing logic)
This commit is contained in:
parent
a8d388043e
commit
61c1b58051
6 changed files with 129 additions and 80 deletions
17
Core/Ppu.cpp
17
Core/Ppu.cpp
|
@ -22,8 +22,8 @@ Ppu::Ppu(shared_ptr<Console> console)
|
||||||
|
|
||||||
_outputBuffers[0] = new uint16_t[512 * 478];
|
_outputBuffers[0] = new uint16_t[512 * 478];
|
||||||
_outputBuffers[1] = new uint16_t[512 * 478];
|
_outputBuffers[1] = new uint16_t[512 * 478];
|
||||||
memset(_outputBuffers[0], 0, 512 * 478);
|
memset(_outputBuffers[0], 0, 512 * 478 * sizeof(uint16_t));
|
||||||
memset(_outputBuffers[1], 0, 512 * 478);
|
memset(_outputBuffers[1], 0, 512 * 478 * sizeof(uint16_t));
|
||||||
|
|
||||||
_currentBuffer = _outputBuffers[0];
|
_currentBuffer = _outputBuffers[0];
|
||||||
|
|
||||||
|
@ -1016,7 +1016,8 @@ void Ppu::ApplyBrightness()
|
||||||
|
|
||||||
void Ppu::ApplyHiResMode()
|
void Ppu::ApplyHiResMode()
|
||||||
{
|
{
|
||||||
uint16_t scanline = _scanline - 1;
|
//When overscan mode is off, center the 224-line picture in the center of the 239-line output buffer
|
||||||
|
uint16_t scanline = _overscanMode ? (_scanline - 1) : (_scanline + 7);
|
||||||
uint32_t screenY = IsDoubleHeight() ? ((_frameCount & 0x01) ? ((scanline << 1) + 1) : (scanline << 1)) : (scanline << 1);
|
uint32_t screenY = IsDoubleHeight() ? ((_frameCount & 0x01) ? ((scanline << 1) + 1) : (scanline << 1)) : (scanline << 1);
|
||||||
uint32_t baseAddr = (screenY << 9);
|
uint32_t baseAddr = (screenY << 9);
|
||||||
|
|
||||||
|
@ -1073,10 +1074,16 @@ void Ppu::ProcessWindowMaskSettings(uint8_t value, uint8_t offset)
|
||||||
|
|
||||||
void Ppu::SendFrame()
|
void Ppu::SendFrame()
|
||||||
{
|
{
|
||||||
|
constexpr uint16_t width = 512;
|
||||||
|
constexpr uint16_t height = 478;
|
||||||
|
|
||||||
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
|
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
|
||||||
|
|
||||||
uint16_t width = 512;
|
if(!_overscanMode) {
|
||||||
uint16_t height = _overscanMode ? 478 : 448;
|
//Clear the top 7 and bottom 8 rows
|
||||||
|
memset(_currentBuffer, 0, width * 14 * sizeof(uint16_t));
|
||||||
|
memset(_currentBuffer + width * 462, 0, width * 16 * sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
|
||||||
bool isRewinding = _console->GetRewindManager()->IsRewinding();
|
bool isRewinding = _console->GetRewindManager()->IsRewinding();
|
||||||
if(isRewinding || _screenInterlace) {
|
if(isRewinding || _screenInterlace) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ private:
|
||||||
atomic<bool> _stopFlag;
|
atomic<bool> _stopFlag;
|
||||||
uint32_t _frameCount = 0;
|
uint32_t _frameCount = 0;
|
||||||
|
|
||||||
FrameInfo _baseFrameInfo = { 256, 224 };
|
FrameInfo _baseFrameInfo = { 512, 478 };
|
||||||
ScreenSize _previousScreenSize = {};
|
ScreenSize _previousScreenSize = {};
|
||||||
double _previousScale = 0;
|
double _previousScale = 0;
|
||||||
FrameInfo _lastFrameInfo;
|
FrameInfo _lastFrameInfo;
|
||||||
|
|
87
UI/Emulation/DisplayManager.cs
Normal file
87
UI/Emulation/DisplayManager.cs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
using Mesen.GUI.Config;
|
||||||
|
using Mesen.GUI.Controls;
|
||||||
|
using Mesen.GUI.Forms;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Mesen.GUI.Emulation
|
||||||
|
{
|
||||||
|
public class DisplayManager
|
||||||
|
{
|
||||||
|
private frmMain _frm;
|
||||||
|
private ctrlRenderer _renderer;
|
||||||
|
private Panel _panel;
|
||||||
|
|
||||||
|
public DisplayManager(frmMain frm, ctrlRenderer renderer, Panel panel)
|
||||||
|
{
|
||||||
|
_frm = frm;
|
||||||
|
_renderer = renderer;
|
||||||
|
_panel = panel;
|
||||||
|
_frm.Resize += frmMain_Resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void frmMain_Resize(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
SetScaleBasedOnWindowSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateViewerSize(bool resizeForm)
|
||||||
|
{
|
||||||
|
ScreenSize screenSize = EmuApi.GetScreenSize(false);
|
||||||
|
|
||||||
|
if(resizeForm && _frm.WindowState != FormWindowState.Maximized) {
|
||||||
|
_frm.Resize -= frmMain_Resize;
|
||||||
|
Size newSize = new Size(screenSize.Width, screenSize.Height);
|
||||||
|
_frm.ClientSize = new Size(newSize.Width, newSize.Height + _panel.Top);
|
||||||
|
_frm.Resize += frmMain_Resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderer.Size = new Size(screenSize.Width, screenSize.Height);
|
||||||
|
_renderer.Top = (_panel.Height - _renderer.Height) / 2;
|
||||||
|
_renderer.Left = (_panel.Width - _renderer.Width) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetScaleBasedOnDimensions(Size dimensions)
|
||||||
|
{
|
||||||
|
ScreenSize size = EmuApi.GetScreenSize(true);
|
||||||
|
|
||||||
|
double verticalScale = (double)dimensions.Height / size.Height;
|
||||||
|
double horizontalScale = (double)dimensions.Width / size.Width;
|
||||||
|
double scale = Math.Min(verticalScale, horizontalScale);
|
||||||
|
/*if(_fullscreenMode && ConfigManager.Config.Video.FullscreenForceIntegerScale) {
|
||||||
|
scale = Math.Floor(scale);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
SetScale(scale, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetScaleBasedOnWindowSize()
|
||||||
|
{
|
||||||
|
SetScaleBasedOnDimensions(_panel.ClientSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetScaleBasedOnScreenSize()
|
||||||
|
{
|
||||||
|
SetScaleBasedOnDimensions(Screen.FromControl(_frm).Bounds.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetScale(double scale, bool resizeForm)
|
||||||
|
{
|
||||||
|
ConfigManager.Config.Video.VideoScale = scale;
|
||||||
|
ConfigManager.Config.Video.ApplyConfig();
|
||||||
|
ConfigManager.ApplyChanges();
|
||||||
|
|
||||||
|
UpdateViewerSize(resizeForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleFullscreen()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,10 +13,14 @@ namespace Mesen.GUI.Emulation
|
||||||
{
|
{
|
||||||
public class ShortcutHandler
|
public class ShortcutHandler
|
||||||
{
|
{
|
||||||
|
private DisplayManager _displayManager;
|
||||||
private Dictionary<EmulatorShortcut, Func<bool>> _actionEnabledFuncs = new Dictionary<EmulatorShortcut, Func<bool>>();
|
private Dictionary<EmulatorShortcut, Func<bool>> _actionEnabledFuncs = new Dictionary<EmulatorShortcut, Func<bool>>();
|
||||||
private List<uint> _speedValues = new List<uint> { 1, 3, 6, 12, 25, 50, 75, 100, 150, 200, 250, 300, 350, 400, 450, 500, 750, 1000, 2000, 4000 };
|
private List<uint> _speedValues = new List<uint> { 1, 3, 6, 12, 25, 50, 75, 100, 150, 200, 250, 300, 350, 400, 450, 500, 750, 1000, 2000, 4000 };
|
||||||
|
|
||||||
public bool AutoResizeForm { get; internal set; }
|
public ShortcutHandler(DisplayManager displayManager)
|
||||||
|
{
|
||||||
|
_displayManager = displayManager;
|
||||||
|
}
|
||||||
|
|
||||||
public void BindShortcut(ToolStripMenuItem item, EmulatorShortcut shortcut, Func<bool> isActionEnabled = null)
|
public void BindShortcut(ToolStripMenuItem item, EmulatorShortcut shortcut, Func<bool> isActionEnabled = null)
|
||||||
{
|
{
|
||||||
|
@ -80,18 +84,18 @@ namespace Mesen.GUI.Emulation
|
||||||
case EmulatorShortcut.ToggleAlwaysOnTop: ToggleAlwaysOnTop(); break;
|
case EmulatorShortcut.ToggleAlwaysOnTop: ToggleAlwaysOnTop(); break;
|
||||||
case EmulatorShortcut.ToggleDebugInfo: ToggleDebugInfo(); break;
|
case EmulatorShortcut.ToggleDebugInfo: ToggleDebugInfo(); break;
|
||||||
case EmulatorShortcut.MaxSpeed: ToggleMaxSpeed(); break;
|
case EmulatorShortcut.MaxSpeed: ToggleMaxSpeed(); break;
|
||||||
//case EmulatorShortcut.ToggleFullscreen: ToggleFullscreen(); restoreFullscreen = false; break;
|
case EmulatorShortcut.ToggleFullscreen: _displayManager.ToggleFullscreen(); break;
|
||||||
|
|
||||||
case EmulatorShortcut.OpenFile: OpenFile(); break;
|
case EmulatorShortcut.OpenFile: OpenFile(); break;
|
||||||
case EmulatorShortcut.IncreaseSpeed: IncreaseEmulationSpeed(); break;
|
case EmulatorShortcut.IncreaseSpeed: IncreaseEmulationSpeed(); break;
|
||||||
case EmulatorShortcut.DecreaseSpeed: DecreaseEmulationSpeed(); break;
|
case EmulatorShortcut.DecreaseSpeed: DecreaseEmulationSpeed(); break;
|
||||||
|
|
||||||
case EmulatorShortcut.SetScale1x: SetScale(1); break;
|
case EmulatorShortcut.SetScale1x: _displayManager.SetScale(1, true); break;
|
||||||
case EmulatorShortcut.SetScale2x: SetScale(2); break;
|
case EmulatorShortcut.SetScale2x: _displayManager.SetScale(2, true); break;
|
||||||
case EmulatorShortcut.SetScale3x: SetScale(3); break;
|
case EmulatorShortcut.SetScale3x: _displayManager.SetScale(3, true); break;
|
||||||
case EmulatorShortcut.SetScale4x: SetScale(4); break;
|
case EmulatorShortcut.SetScale4x: _displayManager.SetScale(4, true); break;
|
||||||
case EmulatorShortcut.SetScale5x: SetScale(5); break;
|
case EmulatorShortcut.SetScale5x: _displayManager.SetScale(5, true); break;
|
||||||
case EmulatorShortcut.SetScale6x: SetScale(6); break;
|
case EmulatorShortcut.SetScale6x: _displayManager.SetScale(6, true); break;
|
||||||
|
|
||||||
case EmulatorShortcut.TakeScreenshot: EmuApi.TakeScreenshot(); break;
|
case EmulatorShortcut.TakeScreenshot: EmuApi.TakeScreenshot(); break;
|
||||||
|
|
||||||
|
@ -160,14 +164,6 @@ namespace Mesen.GUI.Emulation
|
||||||
ConfigManager.ApplyChanges();
|
ConfigManager.ApplyChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetScale(double scale, bool autoResize = true)
|
|
||||||
{
|
|
||||||
this.AutoResizeForm = autoResize;
|
|
||||||
ConfigManager.Config.Video.VideoScale = scale;
|
|
||||||
ConfigManager.Config.Video.ApplyConfig();
|
|
||||||
ConfigManager.ApplyChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ToggleBilinearInterpolation()
|
public void ToggleBilinearInterpolation()
|
||||||
{
|
{
|
||||||
ConfigManager.Config.Video.UseBilinearInterpolation = !ConfigManager.Config.Video.UseBilinearInterpolation;
|
ConfigManager.Config.Video.UseBilinearInterpolation = !ConfigManager.Config.Video.UseBilinearInterpolation;
|
||||||
|
@ -229,7 +225,9 @@ namespace Mesen.GUI.Emulation
|
||||||
|
|
||||||
private void ToggleOsd()
|
private void ToggleOsd()
|
||||||
{
|
{
|
||||||
//TODO
|
ConfigManager.Config.Preferences.DisableOsd = !ConfigManager.Config.Preferences.DisableOsd;
|
||||||
|
ConfigManager.Config.Preferences.ApplyConfig();
|
||||||
|
ConfigManager.ApplyChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleFps()
|
private void ToggleFps()
|
||||||
|
|
|
@ -22,10 +22,15 @@ namespace Mesen.GUI.Forms
|
||||||
{
|
{
|
||||||
private NotificationListener _notifListener;
|
private NotificationListener _notifListener;
|
||||||
private ShortcutHandler _shortcuts;
|
private ShortcutHandler _shortcuts;
|
||||||
|
private DisplayManager _displayManager;
|
||||||
|
|
||||||
public frmMain(string[] args)
|
public frmMain(string[] args)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
if(DesignMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ResourceHelper.LoadResources(Language.English);
|
ResourceHelper.LoadResources(Language.English);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +49,6 @@ namespace Mesen.GUI.Forms
|
||||||
{
|
{
|
||||||
base.OnShown(e);
|
base.OnShown(e);
|
||||||
|
|
||||||
_shortcuts = new ShortcutHandler();
|
|
||||||
|
|
||||||
EmuApi.InitDll();
|
EmuApi.InitDll();
|
||||||
ConfigManager.Config.Video.ApplyConfig();
|
ConfigManager.Config.Video.ApplyConfig();
|
||||||
EmuApi.InitializeEmu(ConfigManager.HomeFolder, Handle, ctrlRenderer.Handle, false, false, false);
|
EmuApi.InitializeEmu(ConfigManager.HomeFolder, Handle, ctrlRenderer.Handle, false, false, false);
|
||||||
|
@ -53,6 +56,10 @@ namespace Mesen.GUI.Forms
|
||||||
ConfigManager.Config.InitializeDefaults();
|
ConfigManager.Config.InitializeDefaults();
|
||||||
ConfigManager.Config.ApplyConfig();
|
ConfigManager.Config.ApplyConfig();
|
||||||
|
|
||||||
|
_displayManager = new DisplayManager(this, ctrlRenderer, pnlRenderer);
|
||||||
|
_displayManager.UpdateViewerSize(false);
|
||||||
|
_shortcuts = new ShortcutHandler(_displayManager);
|
||||||
|
|
||||||
_notifListener = new NotificationListener();
|
_notifListener = new NotificationListener();
|
||||||
_notifListener.OnNotification += OnNotificationReceived;
|
_notifListener.OnNotification += OnNotificationReceived;
|
||||||
|
|
||||||
|
@ -63,9 +70,9 @@ namespace Mesen.GUI.Forms
|
||||||
|
|
||||||
ctrlRecentGames.Initialize();
|
ctrlRecentGames.Initialize();
|
||||||
ctrlRecentGames.Visible = true;
|
ctrlRecentGames.Visible = true;
|
||||||
|
ResizeRecentGames();
|
||||||
|
|
||||||
this.Resize += frmMain_Resize;
|
this.Resize += frmMain_Resize;
|
||||||
ResizeRecentGames();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||||
|
@ -105,13 +112,6 @@ namespace Mesen.GUI.Forms
|
||||||
}));
|
}));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConsoleNotificationType.ResolutionChanged:
|
|
||||||
ScreenSize size = EmuApi.GetScreenSize(false);
|
|
||||||
this.BeginInvoke((Action)(() => {
|
|
||||||
UpdateViewerSize(size);
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ConsoleNotificationType.ExecuteShortcut:
|
case ConsoleNotificationType.ExecuteShortcut:
|
||||||
this.BeginInvoke((Action)(() => {
|
this.BeginInvoke((Action)(() => {
|
||||||
_shortcuts.ExecuteShortcut((EmulatorShortcut)e.Parameter);
|
_shortcuts.ExecuteShortcut((EmulatorShortcut)e.Parameter);
|
||||||
|
@ -191,58 +191,14 @@ namespace Mesen.GUI.Forms
|
||||||
mnuRegionPal.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Pal); };
|
mnuRegionPal.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Pal); };
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateViewerSize(ScreenSize screenSize)
|
|
||||||
{
|
|
||||||
if(_shortcuts.AutoResizeForm && this.WindowState != FormWindowState.Maximized) {
|
|
||||||
this.Resize -= frmMain_Resize;
|
|
||||||
Size newSize = new Size(screenSize.Width, screenSize.Height);
|
|
||||||
this.ClientSize = new Size(newSize.Width, newSize.Height + pnlRenderer.Top);
|
|
||||||
this.Resize += frmMain_Resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrlRenderer.Size = new Size(screenSize.Width, screenSize.Height);
|
|
||||||
ctrlRenderer.Top = (pnlRenderer.Height - ctrlRenderer.Height) / 2;
|
|
||||||
ctrlRenderer.Left = (pnlRenderer.Width - ctrlRenderer.Width) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetScaleBasedOnDimensions(Size dimensions)
|
|
||||||
{
|
|
||||||
ScreenSize size = EmuApi.GetScreenSize(true);
|
|
||||||
|
|
||||||
double verticalScale = (double)dimensions.Height / size.Height;
|
|
||||||
double horizontalScale = (double)dimensions.Width / size.Width;
|
|
||||||
double scale = Math.Min(verticalScale, horizontalScale);
|
|
||||||
/*if(_fullscreenMode && ConfigManager.Config.Video.FullscreenForceIntegerScale) {
|
|
||||||
scale = Math.Floor(scale);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
_shortcuts.SetScale(scale, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetScaleBasedOnWindowSize()
|
|
||||||
{
|
|
||||||
SetScaleBasedOnDimensions(pnlRenderer.ClientSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetScaleBasedOnScreenSize()
|
|
||||||
{
|
|
||||||
SetScaleBasedOnDimensions(Screen.FromControl(this).Bounds.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResizeRecentGames()
|
private void ResizeRecentGames()
|
||||||
{
|
{
|
||||||
ctrlRecentGames.Height = this.ClientSize.Height - ctrlRecentGames.Top - 80;
|
ctrlRecentGames.Height = this.ClientSize.Height - ctrlRecentGames.Top - 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessResize()
|
|
||||||
{
|
|
||||||
ResizeRecentGames();
|
|
||||||
SetScaleBasedOnWindowSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void frmMain_Resize(object sender, EventArgs e)
|
private void frmMain_Resize(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
ProcessResize();
|
ResizeRecentGames();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mnuVideoConfig_Click(object sender, EventArgs e)
|
private void mnuVideoConfig_Click(object sender, EventArgs e)
|
||||||
|
|
|
@ -467,6 +467,7 @@
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Debugger\WatchManager.cs" />
|
<Compile Include="Debugger\WatchManager.cs" />
|
||||||
|
<Compile Include="Emulation\DisplayManager.cs" />
|
||||||
<Compile Include="Emulation\SaveStateManager.cs" />
|
<Compile Include="Emulation\SaveStateManager.cs" />
|
||||||
<Compile Include="Forms\BaseConfigForm.Designer.cs">
|
<Compile Include="Forms\BaseConfigForm.Designer.cs">
|
||||||
<DependentUpon>BaseConfigForm.cs</DependentUpon>
|
<DependentUpon>BaseConfigForm.cs</DependentUpon>
|
||||||
|
|
Loading…
Add table
Reference in a new issue