PPU: Always output a 239-line picture (+ UI refactoring for scaling/resizing logic)

This commit is contained in:
Sour 2019-03-14 23:30:47 -04:00
parent a8d388043e
commit 61c1b58051
6 changed files with 129 additions and 80 deletions

View file

@ -22,8 +22,8 @@ Ppu::Ppu(shared_ptr<Console> console)
_outputBuffers[0] = new uint16_t[512 * 478];
_outputBuffers[1] = new uint16_t[512 * 478];
memset(_outputBuffers[0], 0, 512 * 478);
memset(_outputBuffers[1], 0, 512 * 478);
memset(_outputBuffers[0], 0, 512 * 478 * sizeof(uint16_t));
memset(_outputBuffers[1], 0, 512 * 478 * sizeof(uint16_t));
_currentBuffer = _outputBuffers[0];
@ -1016,7 +1016,8 @@ void Ppu::ApplyBrightness()
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 baseAddr = (screenY << 9);
@ -1073,10 +1074,16 @@ void Ppu::ProcessWindowMaskSettings(uint8_t value, uint8_t offset)
void Ppu::SendFrame()
{
constexpr uint16_t width = 512;
constexpr uint16_t height = 478;
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
uint16_t width = 512;
uint16_t height = _overscanMode ? 478 : 448;
if(!_overscanMode) {
//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();
if(isRewinding || _screenInterlace) {

View file

@ -28,7 +28,7 @@ private:
atomic<bool> _stopFlag;
uint32_t _frameCount = 0;
FrameInfo _baseFrameInfo = { 256, 224 };
FrameInfo _baseFrameInfo = { 512, 478 };
ScreenSize _previousScreenSize = {};
double _previousScale = 0;
FrameInfo _lastFrameInfo;

View 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()
{
}
}
}

View file

@ -13,10 +13,14 @@ namespace Mesen.GUI.Emulation
{
public class ShortcutHandler
{
private DisplayManager _displayManager;
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 };
public bool AutoResizeForm { get; internal set; }
public ShortcutHandler(DisplayManager displayManager)
{
_displayManager = displayManager;
}
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.ToggleDebugInfo: ToggleDebugInfo(); 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.IncreaseSpeed: IncreaseEmulationSpeed(); break;
case EmulatorShortcut.DecreaseSpeed: DecreaseEmulationSpeed(); break;
case EmulatorShortcut.SetScale1x: SetScale(1); break;
case EmulatorShortcut.SetScale2x: SetScale(2); break;
case EmulatorShortcut.SetScale3x: SetScale(3); break;
case EmulatorShortcut.SetScale4x: SetScale(4); break;
case EmulatorShortcut.SetScale5x: SetScale(5); break;
case EmulatorShortcut.SetScale6x: SetScale(6); break;
case EmulatorShortcut.SetScale1x: _displayManager.SetScale(1, true); break;
case EmulatorShortcut.SetScale2x: _displayManager.SetScale(2, true); break;
case EmulatorShortcut.SetScale3x: _displayManager.SetScale(3, true); break;
case EmulatorShortcut.SetScale4x: _displayManager.SetScale(4, true); break;
case EmulatorShortcut.SetScale5x: _displayManager.SetScale(5, true); break;
case EmulatorShortcut.SetScale6x: _displayManager.SetScale(6, true); break;
case EmulatorShortcut.TakeScreenshot: EmuApi.TakeScreenshot(); break;
@ -145,7 +149,7 @@ namespace Mesen.GUI.Emulation
}
}
}
public void SetRegion(ConsoleRegion region)
{
ConfigManager.Config.Emulation.Region = region;
@ -160,14 +164,6 @@ namespace Mesen.GUI.Emulation
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()
{
ConfigManager.Config.Video.UseBilinearInterpolation = !ConfigManager.Config.Video.UseBilinearInterpolation;
@ -229,7 +225,9 @@ namespace Mesen.GUI.Emulation
private void ToggleOsd()
{
//TODO
ConfigManager.Config.Preferences.DisableOsd = !ConfigManager.Config.Preferences.DisableOsd;
ConfigManager.Config.Preferences.ApplyConfig();
ConfigManager.ApplyChanges();
}
private void ToggleFps()

View file

@ -22,10 +22,15 @@ namespace Mesen.GUI.Forms
{
private NotificationListener _notifListener;
private ShortcutHandler _shortcuts;
private DisplayManager _displayManager;
public frmMain(string[] args)
{
InitializeComponent();
if(DesignMode) {
return;
}
ResourceHelper.LoadResources(Language.English);
}
@ -44,8 +49,6 @@ namespace Mesen.GUI.Forms
{
base.OnShown(e);
_shortcuts = new ShortcutHandler();
EmuApi.InitDll();
ConfigManager.Config.Video.ApplyConfig();
EmuApi.InitializeEmu(ConfigManager.HomeFolder, Handle, ctrlRenderer.Handle, false, false, false);
@ -53,9 +56,13 @@ namespace Mesen.GUI.Forms
ConfigManager.Config.InitializeDefaults();
ConfigManager.Config.ApplyConfig();
_displayManager = new DisplayManager(this, ctrlRenderer, pnlRenderer);
_displayManager.UpdateViewerSize(false);
_shortcuts = new ShortcutHandler(_displayManager);
_notifListener = new NotificationListener();
_notifListener.OnNotification += OnNotificationReceived;
SaveStateManager.InitializeStateMenu(mnuSaveState, true, _shortcuts);
SaveStateManager.InitializeStateMenu(mnuLoadState, false, _shortcuts);
@ -63,9 +70,9 @@ namespace Mesen.GUI.Forms
ctrlRecentGames.Initialize();
ctrlRecentGames.Visible = true;
ResizeRecentGames();
this.Resize += frmMain_Resize;
ResizeRecentGames();
}
protected override void OnFormClosing(FormClosingEventArgs e)
@ -105,13 +112,6 @@ namespace Mesen.GUI.Forms
}));
break;
case ConsoleNotificationType.ResolutionChanged:
ScreenSize size = EmuApi.GetScreenSize(false);
this.BeginInvoke((Action)(() => {
UpdateViewerSize(size);
}));
break;
case ConsoleNotificationType.ExecuteShortcut:
this.BeginInvoke((Action)(() => {
_shortcuts.ExecuteShortcut((EmulatorShortcut)e.Parameter);
@ -191,58 +191,14 @@ namespace Mesen.GUI.Forms
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()
{
ctrlRecentGames.Height = this.ClientSize.Height - ctrlRecentGames.Top - 80;
}
private void ProcessResize()
{
ResizeRecentGames();
SetScaleBasedOnWindowSize();
}
private void frmMain_Resize(object sender, EventArgs e)
{
ProcessResize();
ResizeRecentGames();
}
private void mnuVideoConfig_Click(object sender, EventArgs e)

View file

@ -467,6 +467,7 @@
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\WatchManager.cs" />
<Compile Include="Emulation\DisplayManager.cs" />
<Compile Include="Emulation\SaveStateManager.cs" />
<Compile Include="Forms\BaseConfigForm.Designer.cs">
<DependentUpon>BaseConfigForm.cs</DependentUpon>