UI: Added recent game selection screen

This commit is contained in:
Sour 2019-03-14 18:07:25 -04:00
parent fe7a1add99
commit 0836db643f
15 changed files with 761 additions and 95 deletions

View file

@ -54,7 +54,7 @@ void Console::Initialize()
void Console::Release()
{
Stop();
Stop(true);
_videoDecoder->StopThread();
_videoRenderer->StopThread();
@ -130,7 +130,7 @@ void Console::Run()
PlatformUtilities::RestoreTimerResolution();
}
void Console::Stop()
void Console::Stop(bool sendNotification)
{
_stopFlag = true;
@ -141,6 +141,11 @@ void Console::Stop()
_runLock.WaitForRelease();
if(_cart) {
//TODO IPS/BPS patch support
_saveStateManager->SaveRecentGame(GetRomInfo().RomFile.GetFileName(), _cart->GetRomInfo().RomFile, "");
}
//Make sure we release both pointers to destroy the debugger before everything else
_debugger.reset();
debugger.reset();
@ -158,21 +163,25 @@ void Console::Stop()
_dmaController.reset();
_soundMixer->StopAudio();
if(sendNotification) {
_notificationManager->SendNotification(ConsoleNotificationType::EmulationStopped);
}
}
void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
bool Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
{
Stop();
shared_ptr<BaseCartridge> cart = BaseCartridge::CreateCartridge(romFile, patchFile);
if(cart) {
Stop(false);
vector<uint8_t> spcRomData;
VirtualFile spcBios(FolderUtilities::CombinePath(FolderUtilities::GetHomeFolder(), "spc700.rom"));
if(spcBios.IsValid()) {
spcBios.ReadFile(spcRomData);
} else {
MessageManager::Log("[SPC] spc700.rom not found, cannot launch game.");
return;
return false;
}
_internalRegisters.reset(new InternalRegisters(shared_from_this()));
@ -204,7 +213,11 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
_paused = false;
_notificationManager->SendNotification(ConsoleNotificationType::GameLoaded);
return true;
}
return false;
}
RomInfo Console::GetRomInfo()

View file

@ -74,13 +74,13 @@ public:
void Release();
void Run();
void Stop();
void Stop(bool sendNotification);
void Pause();
void Resume();
bool IsPaused();
void LoadRom(VirtualFile romFile, VirtualFile patchFile);
bool LoadRom(VirtualFile romFile, VirtualFile patchFile);
RomInfo GetRomInfo();
uint32_t GetMasterClockRate();
ConsoleRegion GetRegion();

View file

@ -195,12 +195,9 @@ bool SaveStateManager::LoadState(int stateIndex)
return false;
}
//TODO
/*
void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath)
{
if(!_console->GetSettings()->CheckFlag(EmulationFlags::ConsoleMode) && !_console->GetSettings()->CheckFlag(EmulationFlags::DisableGameSelectionScreen) && _console->GetRomInfo().Format != RomFormat::Nsf) {
string filename = FolderUtilities::GetFilename(_console->GetRomInfo().RomName, false) + ".rgd";
string filename = FolderUtilities::GetFilename(_console->GetRomInfo().RomFile.GetFileName(), false) + ".rgd";
ZipWriter writer;
writer.Initialize(FolderUtilities::CombinePath(FolderUtilities::GetRecentGamesFolder(), filename));
@ -219,7 +216,6 @@ void SaveStateManager::SaveRecentGame(string romName, string romPath, string pat
writer.AddFile(romInfoStream, "RomInfo.txt");
writer.Save();
}
}
void SaveStateManager::LoadRecentGame(string filename, bool resetGame)
{
@ -237,14 +233,13 @@ void SaveStateManager::LoadRecentGame(string filename, bool resetGame)
_console->Pause();
try {
if(_console->Initialize(romPath, patchPath)) {
if(_console->LoadRom(romPath, patchPath)) {
if(!resetGame) {
SaveStateManager::LoadState(stateStream, false);
}
}
} catch(std::exception ex) {
_console->Stop();
_console->Stop(true);
}
_console->Resume();
}
*/

View file

@ -32,8 +32,8 @@ public:
bool LoadState(string filepath, bool hashCheckRequired = true);
bool LoadState(int stateIndex);
//void SaveRecentGame(string romName, string romPath, string patchPath);
//void LoadRecentGame(string filename, bool resetGame);
void SaveRecentGame(string romName, string romPath, string patchPath);
void LoadRecentGame(string filename, bool resetGame);
void MoveToNextSlot();
void MoveToPreviousSlot();

View file

@ -202,14 +202,12 @@ void VideoDecoder::StopThread()
//TODO
//_hud.reset();
/*UpdateVideoFilter();
/*UpdateVideoFilter();*/
if(_ppuOutputBuffer != nullptr) {
//Clear whole screen
for(uint32_t i = 0; i < PPU::PixelCount; i++) {
_ppuOutputBuffer[i] = 14; //Black
}
memset(_ppuOutputBuffer, 0, 512 * 478 * 2);
DecodeFrame();
}*/
}
_ppuOutputBuffer = nullptr;
}
#endif

View file

@ -114,7 +114,7 @@ extern "C" {
DllExport void __stdcall Stop()
{
_console->Stop();
_console->Stop(true);
}
DllExport void __stdcall Pause()
@ -134,7 +134,7 @@ extern "C" {
DllExport void __stdcall Release()
{
_console->Stop();
_console->Stop(true);
_renderer.reset();
_soundManager.reset();
@ -175,6 +175,7 @@ extern "C" {
DllExport void __stdcall SaveStateFile(char* filepath) { _console->GetSaveStateManager()->SaveState(filepath); }
DllExport void __stdcall LoadStateFile(char* filepath) { _console->GetSaveStateManager()->LoadState(filepath); }
DllExport int64_t __stdcall GetStateInfo(uint32_t stateIndex) { return _console->GetSaveStateManager()->GetStateInfo(stateIndex); }
DllExport void __stdcall LoadRecentGame(char* filepath, bool resetGame) { _console->GetSaveStateManager()->LoadRecentGame(filepath, resetGame); }
DllExport void __stdcall PgoRunTest(vector<string> testRoms, bool enableDebugger)
{
@ -191,7 +192,7 @@ extern "C" {
_console->Run();
});
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(5000));
_console->Stop();
_console->Stop(false);
testThread.join();
_console->Release();
}

View file

@ -57,14 +57,10 @@ namespace Mesen.GUI.Config
public override string ToString()
{
string path = RomFile.ReadablePath.Replace("&", "&&");
string file = Path.GetFileName(path);
string folder = Path.GetDirectoryName(path);
string text = file;
string text = Path.GetFileName(path);
if(PatchFile.HasValue) {
text += " [" + Path.GetFileName(PatchFile.Value) + "]";
}
text += " (" + folder + ")";
return text;
}
}

View file

@ -0,0 +1,306 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Mesen.GUI.Config;
using System.Drawing.Text;
using System.IO.Compression;
using Mesen.GUI.Forms;
using Mesen.GUI.Controls;
using Mesen.GUI.Emulation;
namespace Mesen.GUI.Controls
{
public partial class ctrlRecentGames : BaseControl
{
public delegate void RecentGameLoadedHandler(RecentGameInfo gameInfo);
public event RecentGameLoadedHandler OnRecentGameLoaded;
public new event MouseEventHandler MouseMove
{
add { this.tlpPreviousState.MouseMove += value; }
remove { this.tlpPreviousState.MouseMove -= value; }
}
public new event EventHandler DoubleClick
{
add { this.tlpPreviousState.DoubleClick += value; }
remove { this.tlpPreviousState.DoubleClick -= value; }
}
private bool _initialized = false;
private int _currentIndex = 0;
private List<RecentGameInfo> _recentGames = new List<RecentGameInfo>();
private PrivateFontCollection _fonts = new PrivateFontCollection();
public ctrlRecentGames()
{
InitializeComponent();
if(IsDesignMode) {
return;
}
DoubleBuffered = true;
_fonts.AddFontFile(Path.Combine(ConfigManager.HomeFolder, "Resources", "PixelFont.ttf"));
lblGameName.Font = new Font(_fonts.Families[0], 10);
lblSaveDate.Font = new Font(_fonts.Families[0], 10);
picPrevGame.Image.RotateFlip(RotateFlipType.RotateNoneFlipX);
}
public new bool Visible
{
get { return base.Visible; }
set
{
if(value && ((_initialized && _recentGames.Count == 0) /* TODO || ConfigManager.Config.Preferences.DisableGameSelectionScreen*/)) {
value = false;
}
if(value != base.Visible) {
if(value && !_initialized) {
//We just re-enabled the screen, initialize it
Initialize();
}
base.Visible = value;
tmrInput.Enabled = value;
}
}
}
public int GameCount
{
get { return _recentGames.Count; }
}
public void Initialize()
{
_initialized = true;
_recentGames = new List<RecentGameInfo>();
_currentIndex = 0;
foreach(string file in Directory.GetFiles(ConfigManager.RecentGamesFolder, "*.rgd")) {
try {
RecentGameInfo info = new RecentGameInfo();
ZipArchive zip = new ZipArchive(new MemoryStream(File.ReadAllBytes(file)));
using(StreamReader sr = new StreamReader(zip.GetEntry("RomInfo.txt").Open())) {
info.RomName = sr.ReadLine();
info.RomPath = sr.ReadLine();
}
info.Timestamp = new FileInfo(file).LastWriteTime;
info.FileName = file;
if(info.RomPath.Exists) {
_recentGames.Add(info);
}
} catch { }
}
_recentGames = _recentGames.OrderBy((info) => info.Timestamp).Reverse().ToList();
if(_recentGames.Count > 5) {
_recentGames.RemoveRange(5, _recentGames.Count - 5);
}
picPrevGame.Visible = _recentGames.Count > 1;
picNextGame.Visible = _recentGames.Count > 1;
if(_recentGames.Count == 0) {
this.Visible = false;
tmrInput.Enabled = false;
} else {
UpdateGameInfo();
tmrInput.Enabled = true;
}
}
public void UpdateGameInfo()
{
if(_currentIndex < _recentGames.Count) {
lblGameName.Text = Path.GetFileNameWithoutExtension(_recentGames[_currentIndex].RomName);
lblSaveDate.Text = _recentGames[_currentIndex].Timestamp.ToString();
try {
ZipArchive zip = new ZipArchive(new MemoryStream(File.ReadAllBytes(_recentGames[_currentIndex].FileName)));
ZipArchiveEntry entry = zip.GetEntry("Screenshot.png");
if(entry != null) {
using(Stream stream = entry.Open()) {
picPreviousState.Image = Image.FromStream(stream);
}
} else {
picPreviousState.Image = null;
}
} catch {
picPreviousState.Image = null;
}
UpdateSize();
}
}
float _xFactor = 1;
float _yFactor = 1;
protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
_xFactor = factor.Width;
_yFactor = factor.Height;
base.ScaleControl(factor, specified);
}
private void UpdateSize()
{
tlpPreviousState.Visible = false;
Size maxSize = new Size(this.Size.Width - (int)(120 * _xFactor), this.Size.Height - (int)(50 * _yFactor));
if(picPreviousState.Image != null) {
double xRatio = (double)picPreviousState.Image.Width / maxSize.Width;
double yRatio = (double)picPreviousState.Image.Height / maxSize.Height;
double ratio = Math.Max(xRatio, yRatio);
Size newSize = new Size((int)(picPreviousState.Image.Width / ratio), (int)(picPreviousState.Image.Height / ratio));
picPreviousState.Size = newSize;
pnlPreviousState.Size = new Size(newSize.Width+4, newSize.Height+4);
}
tlpPreviousState.Visible = true;
}
protected override void OnResize(EventArgs e)
{
if(Program.IsMono) {
//Fix resize issues
picNextGame.Dock = DockStyle.None;
picPrevGame.Dock = DockStyle.None;
picNextGame.Dock = DockStyle.Fill;
picPrevGame.Dock = DockStyle.Fill;
}
if(picPreviousState.Image != null) {
UpdateSize();
}
base.OnResize(e);
}
private void picPreviousState_MouseEnter(object sender, EventArgs e)
{
pnlPreviousState.BackColor = Color.LightBlue;
}
private void picPreviousState_MouseLeave(object sender, EventArgs e)
{
pnlPreviousState.BackColor = Color.Gray;
}
private void picPreviousState_Click(object sender, EventArgs e)
{
LoadSelectedGame();
}
private void picNextGame_MouseDown(object sender, MouseEventArgs e)
{
GoToNextGame();
}
private void picPrevGame_MouseDown(object sender, MouseEventArgs e)
{
GoToPreviousGame();
}
private void GoToPreviousGame()
{
if(_currentIndex == 0) {
_currentIndex = _recentGames.Count - 1;
} else {
_currentIndex--;
}
UpdateGameInfo();
}
private void GoToNextGame()
{
_currentIndex = (_currentIndex + 1) % _recentGames.Count;
UpdateGameInfo();
}
private void LoadSelectedGame()
{
EmuRunner.LoadRecentGame(_recentGames[_currentIndex].FileName);
}
private bool _waitForRelease = false;
private void tmrInput_Tick(object sender, EventArgs e)
{
//Use player 1's controls to navigate the recent game selection screen
if(Application.OpenForms.Count > 0 && Application.OpenForms[0].ContainsFocus && !EmuRunner.IsRunning()) {
List<uint> keyCodes = InputApi.GetPressedKeys();
uint keyCode = keyCodes.Count > 0 ? keyCodes[0] : 0;
if(keyCode > 0) {
if(!_waitForRelease) {
List<KeyMapping> mappings = new List<KeyMapping>() {
ConfigManager.Config.Input.Controllers[0].Keys.Mapping1,
ConfigManager.Config.Input.Controllers[0].Keys.Mapping2,
ConfigManager.Config.Input.Controllers[0].Keys.Mapping3,
ConfigManager.Config.Input.Controllers[0].Keys.Mapping4
};
foreach(KeyMapping mapping in mappings) {
if(mapping.Left == keyCode) {
_waitForRelease = true;
GoToPreviousGame();
} else if(mapping.Right == keyCode) {
_waitForRelease = true;
GoToNextGame();
} else if(mapping.A == keyCode || mapping.B == keyCode) {
_waitForRelease = true;
LoadSelectedGame();
}
}
}
} else {
_waitForRelease = false;
}
}
}
}
public class DBTableLayoutPanel : TableLayoutPanel
{
public DBTableLayoutPanel()
{
DoubleBuffered = true;
}
}
public class GamePreviewBox : PictureBox
{
public System.Drawing.Drawing2D.InterpolationMode InterpolationMode { get; set; }
public GamePreviewBox()
{
DoubleBuffered = true;
InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.InterpolationMode = InterpolationMode;
base.OnPaint(pe);
}
}
public class RecentGameInfo
{
public string FileName { get; set; }
public string RomName { get; set; }
public ResourcePath RomPath { get; set; }
public DateTime Timestamp { get; set; }
}
}

183
UI/Controls/ctrlRecentGames.designer.cs generated Normal file
View file

@ -0,0 +1,183 @@
namespace Mesen.GUI.Controls
{
partial class ctrlRecentGames
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tlpPreviousState = new Mesen.GUI.Controls.DBTableLayoutPanel();
this.pnlPreviousState = new System.Windows.Forms.Panel();
this.picPreviousState = new Mesen.GUI.Controls.GamePreviewBox();
this.lblGameName = new System.Windows.Forms.Label();
this.lblSaveDate = new System.Windows.Forms.Label();
this.picNextGame = new System.Windows.Forms.PictureBox();
this.picPrevGame = new System.Windows.Forms.PictureBox();
this.tmrInput = new System.Windows.Forms.Timer(this.components);
this.tlpPreviousState.SuspendLayout();
this.pnlPreviousState.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picPreviousState)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picNextGame)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picPrevGame)).BeginInit();
this.SuspendLayout();
//
// tlpPreviousState
//
this.tlpPreviousState.BackColor = System.Drawing.Color.Black;
this.tlpPreviousState.ColumnCount = 3;
this.tlpPreviousState.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpPreviousState.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpPreviousState.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpPreviousState.Controls.Add(this.pnlPreviousState, 1, 1);
this.tlpPreviousState.Controls.Add(this.lblGameName, 1, 2);
this.tlpPreviousState.Controls.Add(this.lblSaveDate, 1, 3);
this.tlpPreviousState.Controls.Add(this.picNextGame, 2, 1);
this.tlpPreviousState.Controls.Add(this.picPrevGame, 0, 1);
this.tlpPreviousState.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpPreviousState.Location = new System.Drawing.Point(0, 0);
this.tlpPreviousState.Name = "tlpPreviousState";
this.tlpPreviousState.RowCount = 6;
this.tlpPreviousState.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F));
this.tlpPreviousState.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpPreviousState.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpPreviousState.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpPreviousState.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5F));
this.tlpPreviousState.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpPreviousState.Size = new System.Drawing.Size(272, 107);
this.tlpPreviousState.TabIndex = 9;
//
// pnlPreviousState
//
this.pnlPreviousState.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.pnlPreviousState.BackColor = System.Drawing.Color.Gray;
this.pnlPreviousState.Controls.Add(this.picPreviousState);
this.pnlPreviousState.Location = new System.Drawing.Point(113, 13);
this.pnlPreviousState.Name = "pnlPreviousState";
this.pnlPreviousState.Padding = new System.Windows.Forms.Padding(2);
this.pnlPreviousState.Size = new System.Drawing.Size(46, 46);
this.pnlPreviousState.TabIndex = 8;
//
// picPreviousState
//
this.picPreviousState.BackColor = System.Drawing.Color.Black;
this.picPreviousState.Cursor = System.Windows.Forms.Cursors.Hand;
this.picPreviousState.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
this.picPreviousState.Location = new System.Drawing.Point(2, 2);
this.picPreviousState.Margin = new System.Windows.Forms.Padding(0);
this.picPreviousState.Name = "picPreviousState";
this.picPreviousState.Size = new System.Drawing.Size(42, 42);
this.picPreviousState.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.picPreviousState.TabIndex = 7;
this.picPreviousState.TabStop = false;
this.picPreviousState.Click += new System.EventHandler(this.picPreviousState_Click);
this.picPreviousState.MouseEnter += new System.EventHandler(this.picPreviousState_MouseEnter);
this.picPreviousState.MouseLeave += new System.EventHandler(this.picPreviousState_MouseLeave);
//
// lblGameName
//
this.lblGameName.AutoEllipsis = true;
this.lblGameName.BackColor = System.Drawing.Color.Transparent;
this.lblGameName.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblGameName.ForeColor = System.Drawing.Color.White;
this.lblGameName.Location = new System.Drawing.Point(36, 62);
this.lblGameName.Name = "lblGameName";
this.lblGameName.Size = new System.Drawing.Size(200, 16);
this.lblGameName.TabIndex = 9;
this.lblGameName.Text = "Game Name";
this.lblGameName.TextAlign = System.Drawing.ContentAlignment.TopCenter;
//
// lblSaveDate
//
this.lblSaveDate.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.lblSaveDate.AutoSize = true;
this.lblSaveDate.BackColor = System.Drawing.Color.Transparent;
this.lblSaveDate.ForeColor = System.Drawing.Color.White;
this.lblSaveDate.Location = new System.Drawing.Point(121, 78);
this.lblSaveDate.Name = "lblSaveDate";
this.lblSaveDate.Size = new System.Drawing.Size(30, 13);
this.lblSaveDate.TabIndex = 10;
this.lblSaveDate.Text = "Date";
//
// picNextGame
//
this.picNextGame.Cursor = System.Windows.Forms.Cursors.Hand;
this.picNextGame.Dock = System.Windows.Forms.DockStyle.Right;
this.picNextGame.Image = global::Mesen.GUI.Properties.Resources.MediaPlay;
this.picNextGame.Location = new System.Drawing.Point(242, 13);
this.picNextGame.Name = "picNextGame";
this.picNextGame.Size = new System.Drawing.Size(27, 46);
this.picNextGame.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picNextGame.TabIndex = 11;
this.picNextGame.TabStop = false;
this.picNextGame.MouseDown += new System.Windows.Forms.MouseEventHandler(this.picNextGame_MouseDown);
//
// picPrevGame
//
this.picPrevGame.Cursor = System.Windows.Forms.Cursors.Hand;
this.picPrevGame.Dock = System.Windows.Forms.DockStyle.Left;
this.picPrevGame.Image = global::Mesen.GUI.Properties.Resources.MediaPlay;
this.picPrevGame.Location = new System.Drawing.Point(3, 13);
this.picPrevGame.Name = "picPrevGame";
this.picPrevGame.Size = new System.Drawing.Size(27, 46);
this.picPrevGame.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picPrevGame.TabIndex = 12;
this.picPrevGame.TabStop = false;
this.picPrevGame.MouseDown += new System.Windows.Forms.MouseEventHandler(this.picPrevGame_MouseDown);
//
// tmrInput
//
this.tmrInput.Interval = 50;
this.tmrInput.Tick += new System.EventHandler(this.tmrInput_Tick);
//
// ctrlRecentGames
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Transparent;
this.Controls.Add(this.tlpPreviousState);
this.Name = "ctrlRecentGames";
this.Size = new System.Drawing.Size(272, 107);
this.tlpPreviousState.ResumeLayout(false);
this.tlpPreviousState.PerformLayout();
this.pnlPreviousState.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.picPreviousState)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picNextGame)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picPrevGame)).EndInit();
this.ResumeLayout(false);
}
#endregion
private DBTableLayoutPanel tlpPreviousState;
private System.Windows.Forms.Panel pnlPreviousState;
private GamePreviewBox picPreviousState;
private System.Windows.Forms.Label lblGameName;
private System.Windows.Forms.Label lblSaveDate;
private System.Windows.Forms.PictureBox picNextGame;
private System.Windows.Forms.PictureBox picPrevGame;
private System.Windows.Forms.Timer tmrInput;
}
}

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="tmrInput.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -21,11 +21,21 @@ namespace Mesen.GUI.Emulation
}
EmuApi.LoadRom(romPath, patchPath);
ConfigManager.Config.RecentFiles.AddRecentFile(romPath, patchPath);
StartEmulation();
}
public static void LoadRecentGame(string recentGameArchivePath)
{
EmuApi.LoadRecentGame(recentGameArchivePath, false /* TODO , ConfigManager.Config.Preferences.GameSelectionScreenResetGame */);
StartEmulation();
}
private static void StartEmulation()
{
_emuThread = new Thread(() => {
EmuApi.Run();
_emuThread = null;
});
_emuThread.Start();
}

View file

@ -98,6 +98,11 @@
this.mnuPrescale10xFilter = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem19 = new System.Windows.Forms.ToolStripSeparator();
this.mnuBilinearInterpolation = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRegion = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRegionAuto = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRegionNtsc = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRegionPal = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAudioConfig = new System.Windows.Forms.ToolStripMenuItem();
this.mnuInputConfig = new System.Windows.Forms.ToolStripMenuItem();
@ -122,11 +127,7 @@
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
this.pnlRenderer = new System.Windows.Forms.Panel();
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.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.ctrlRecentGames = new Mesen.GUI.Controls.ctrlRecentGames();
this.mnuMain.SuspendLayout();
this.pnlRenderer.SuspendLayout();
this.SuspendLayout();
@ -305,7 +306,7 @@
this.mnuShowFPS});
this.mnuEmulationSpeed.Image = global::Mesen.GUI.Properties.Resources.Speed;
this.mnuEmulationSpeed.Name = "mnuEmulationSpeed";
this.mnuEmulationSpeed.Size = new System.Drawing.Size(152, 22);
this.mnuEmulationSpeed.Size = new System.Drawing.Size(135, 22);
this.mnuEmulationSpeed.Text = "Speed";
this.mnuEmulationSpeed.DropDownOpening += new System.EventHandler(this.mnuEmulationSpeed_DropDownOpening);
//
@ -393,7 +394,7 @@
this.mnuFullscreen});
this.mnuVideoScale.Image = global::Mesen.GUI.Properties.Resources.Fullscreen;
this.mnuVideoScale.Name = "mnuVideoScale";
this.mnuVideoScale.Size = new System.Drawing.Size(152, 22);
this.mnuVideoScale.Size = new System.Drawing.Size(135, 22);
this.mnuVideoScale.Text = "Video Size";
this.mnuVideoScale.DropDownOpening += new System.EventHandler(this.mnuVideoScale_DropDownOpening);
//
@ -479,7 +480,7 @@
this.mnuBilinearInterpolation});
this.mnuVideoFilter.Image = global::Mesen.GUI.Properties.Resources.VideoFilter;
this.mnuVideoFilter.Name = "mnuVideoFilter";
this.mnuVideoFilter.Size = new System.Drawing.Size(152, 22);
this.mnuVideoFilter.Size = new System.Drawing.Size(135, 22);
this.mnuVideoFilter.Text = "Video Filter";
this.mnuVideoFilter.DropDownOpening += new System.EventHandler(this.mnuVideoFilter_DropDownOpening);
//
@ -657,16 +658,52 @@
this.mnuBilinearInterpolation.Size = new System.Drawing.Size(206, 22);
this.mnuBilinearInterpolation.Text = "Use Bilinear Interpolation";
//
// mnuRegion
//
this.mnuRegion.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuRegionAuto,
this.toolStripMenuItem1,
this.mnuRegionNtsc,
this.mnuRegionPal});
this.mnuRegion.Image = global::Mesen.GUI.Properties.Resources.WebBrowser;
this.mnuRegion.Name = "mnuRegion";
this.mnuRegion.Size = new System.Drawing.Size(135, 22);
this.mnuRegion.Text = "Region";
this.mnuRegion.DropDownOpening += new System.EventHandler(this.mnuRegion_DropDownOpening);
//
// mnuRegionAuto
//
this.mnuRegionAuto.Name = "mnuRegionAuto";
this.mnuRegionAuto.Size = new System.Drawing.Size(104, 22);
this.mnuRegionAuto.Text = "Auto";
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(101, 6);
//
// mnuRegionNtsc
//
this.mnuRegionNtsc.Name = "mnuRegionNtsc";
this.mnuRegionNtsc.Size = new System.Drawing.Size(104, 22);
this.mnuRegionNtsc.Text = "NTSC";
//
// mnuRegionPal
//
this.mnuRegionPal.Name = "mnuRegionPal";
this.mnuRegionPal.Size = new System.Drawing.Size(104, 22);
this.mnuRegionPal.Text = "PAL";
//
// toolStripMenuItem4
//
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
this.toolStripMenuItem4.Size = new System.Drawing.Size(149, 6);
this.toolStripMenuItem4.Size = new System.Drawing.Size(132, 6);
//
// mnuAudioConfig
//
this.mnuAudioConfig.Image = global::Mesen.GUI.Properties.Resources.Audio;
this.mnuAudioConfig.Name = "mnuAudioConfig";
this.mnuAudioConfig.Size = new System.Drawing.Size(152, 22);
this.mnuAudioConfig.Size = new System.Drawing.Size(135, 22);
this.mnuAudioConfig.Text = "Audio";
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click);
//
@ -674,7 +711,7 @@
//
this.mnuInputConfig.Image = global::Mesen.GUI.Properties.Resources.Controller;
this.mnuInputConfig.Name = "mnuInputConfig";
this.mnuInputConfig.Size = new System.Drawing.Size(152, 22);
this.mnuInputConfig.Size = new System.Drawing.Size(135, 22);
this.mnuInputConfig.Text = "Input";
this.mnuInputConfig.Click += new System.EventHandler(this.mnuInputConfig_Click);
//
@ -682,7 +719,7 @@
//
this.mnuVideoConfig.Image = global::Mesen.GUI.Properties.Resources.VideoOptions;
this.mnuVideoConfig.Name = "mnuVideoConfig";
this.mnuVideoConfig.Size = new System.Drawing.Size(152, 22);
this.mnuVideoConfig.Size = new System.Drawing.Size(135, 22);
this.mnuVideoConfig.Text = "Video";
this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
//
@ -690,20 +727,20 @@
//
this.mnuEmulationConfig.Image = global::Mesen.GUI.Properties.Resources.DipSwitches;
this.mnuEmulationConfig.Name = "mnuEmulationConfig";
this.mnuEmulationConfig.Size = new System.Drawing.Size(152, 22);
this.mnuEmulationConfig.Size = new System.Drawing.Size(135, 22);
this.mnuEmulationConfig.Text = "Emulation";
this.mnuEmulationConfig.Click += new System.EventHandler(this.mnuEmulationConfig_Click);
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(149, 6);
this.toolStripMenuItem3.Size = new System.Drawing.Size(132, 6);
//
// mnuPreferences
//
this.mnuPreferences.Image = global::Mesen.GUI.Properties.Resources.Settings;
this.mnuPreferences.Name = "mnuPreferences";
this.mnuPreferences.Size = new System.Drawing.Size(152, 22);
this.mnuPreferences.Size = new System.Drawing.Size(135, 22);
this.mnuPreferences.Text = "Preferences";
this.mnuPreferences.Click += new System.EventHandler(this.mnuPreferences_Click);
//
@ -845,41 +882,15 @@
this.pnlRenderer.Size = new System.Drawing.Size(512, 448);
this.pnlRenderer.TabIndex = 2;
//
// mnuRegion
// ctrlRecentGames
//
this.mnuRegion.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuRegionAuto,
this.toolStripMenuItem1,
this.mnuRegionNtsc,
this.mnuRegionPal});
this.mnuRegion.Image = global::Mesen.GUI.Properties.Resources.WebBrowser;
this.mnuRegion.Name = "mnuRegion";
this.mnuRegion.Size = new System.Drawing.Size(152, 22);
this.mnuRegion.Text = "Region";
this.mnuRegion.DropDownOpening += new System.EventHandler(this.mnuRegion_DropDownOpening);
//
// mnuRegionAuto
//
this.mnuRegionAuto.Name = "mnuRegionAuto";
this.mnuRegionAuto.Size = new System.Drawing.Size(152, 22);
this.mnuRegionAuto.Text = "Auto";
//
// mnuRegionNtsc
//
this.mnuRegionNtsc.Name = "mnuRegionNtsc";
this.mnuRegionNtsc.Size = new System.Drawing.Size(152, 22);
this.mnuRegionNtsc.Text = "NTSC";
//
// mnuRegionPal
//
this.mnuRegionPal.Name = "mnuRegionPal";
this.mnuRegionPal.Size = new System.Drawing.Size(152, 22);
this.mnuRegionPal.Text = "PAL";
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(149, 6);
this.ctrlRecentGames.BackColor = System.Drawing.Color.Transparent;
this.ctrlRecentGames.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlRecentGames.Location = new System.Drawing.Point(0, 24);
this.ctrlRecentGames.Name = "ctrlRecentGames";
this.ctrlRecentGames.Size = new System.Drawing.Size(512, 265);
this.ctrlRecentGames.TabIndex = 1;
this.ctrlRecentGames.Visible = false;
//
// frmMain
//
@ -887,6 +898,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(512, 472);
this.Controls.Add(this.ctrlRecentGames);
this.Controls.Add(this.pnlRenderer);
this.Controls.Add(this.mnuMain);
this.MainMenuStrip = this.mnuMain;
@ -1002,5 +1014,6 @@
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem mnuRegionNtsc;
private System.Windows.Forms.ToolStripMenuItem mnuRegionPal;
private Controls.ctrlRecentGames ctrlRecentGames;
}
}

View file

@ -49,6 +49,9 @@ namespace Mesen.GUI.Forms
SaveStateManager.InitializeStateMenu(mnuLoadState, false, _shortcuts);
BindShortcuts();
ctrlRecentGames.Initialize();
ctrlRecentGames.Visible = true;
}
protected override void OnFormClosing(FormClosingEventArgs e)
@ -72,11 +75,19 @@ namespace Mesen.GUI.Forms
switch(e.NotificationType) {
case ConsoleNotificationType.GameLoaded:
this.BeginInvoke((Action)(() => {
ctrlRecentGames.Visible = false;
SaveStateManager.UpdateStateMenu(mnuLoadState, false);
SaveStateManager.UpdateStateMenu(mnuSaveState, true);
}));
break;
case ConsoleNotificationType.EmulationStopped:
this.BeginInvoke((Action)(() => {
ctrlRecentGames.Initialize();
ctrlRecentGames.Visible = true;
}));
break;
case ConsoleNotificationType.ResolutionChanged:
ScreenSize size = EmuApi.GetScreenSize(false);
this.BeginInvoke((Action)(() => {
@ -181,6 +192,12 @@ namespace Mesen.GUI.Forms
//this.Resize += frmMain_Resize;
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
ctrlRecentGames.Height = this.ClientSize.Height - ctrlRecentGames.Top - 80;
}
private void mnuVideoConfig_Click(object sender, EventArgs e)
{
using(frmVideoConfig frm = new frmVideoConfig()) {

View file

@ -48,6 +48,8 @@ namespace Mesen.GUI
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string patchFile = ""
);
[DllImport(DllPath)] public static extern void LoadRecentGame([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filepath, [MarshalAs(UnmanagedType.I1)]bool resetGame);
[DllImport(DllPath)] public static extern void AddKnownGameFolder([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string folder);
[DllImport(DllPath)] public static extern void SetFolderOverrides(

View file

@ -222,6 +222,12 @@
<Compile Include="Config\Shortcuts\ShortcutKeyInfo.cs" />
<Compile Include="Config\EmulationConfig.cs" />
<Compile Include="Config\VideoConfig.cs" />
<Compile Include="Controls\ctrlRecentGames.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Controls\ctrlRecentGames.designer.cs">
<DependentUpon>ctrlRecentGames.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Breakpoints\Breakpoint.cs" />
<Compile Include="Debugger\Breakpoints\BreakpointManager.cs" />
<Compile Include="Debugger\Breakpoints\ctrlBreakpoints.cs">
@ -605,6 +611,9 @@
<EmbeddedResource Include="Controls\ctrlPathSelection.resx">
<DependentUpon>ctrlPathSelection.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\ctrlRecentGames.resx">
<DependentUpon>ctrlRecentGames.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\MesenNumericUpDown.resx">
<DependentUpon>MesenNumericUpDown.cs</DependentUpon>
</EmbeddedResource>