Win 8.1/10 support: Fixed crashes, added automatic download feature for the MSVC runtime

This commit is contained in:
Souryo 2016-01-16 19:33:10 -05:00
parent e4fa287e66
commit a56aa15f28
18 changed files with 459 additions and 40 deletions

View file

@ -179,7 +179,7 @@ void AutoRomTest::RecordFromTest(string newTestFilename, string existingTestFile
}
}
int AutoRomTest::Run(string filename)
int32_t AutoRomTest::Run(string filename)
{
ZipReader zipReader;
zipReader.LoadZipArchive(filename);

View file

@ -42,6 +42,6 @@ public:
void Record(string filename, bool reset);
void RecordFromMovie(string testFilename, string movieFilename);
void RecordFromTest(string newTestFilename, string existingTestFilename);
int Run(string filename);
int32_t Run(string filename);
void Stop();
};

View file

@ -169,7 +169,9 @@ void VideoDecoder::StopThread()
void VideoDecoder::RenderThread()
{
_renderer->Reset();
if(_renderer) {
_renderer->Reset();
}
while(!_stopFlag.load()) {
//Wait until a frame is ready, or until 16ms have passed (to allow UI to run at a minimum of 60fps)
_waitForRender.Wait(16);

View file

@ -26,6 +26,8 @@ namespace Mesen.GUI.Config
//Create new config file and save it to disk
_config = new Configuration();
_dirtyConfig = new Configuration();
_config.InitializeDefaults();
_dirtyConfig.InitializeDefaults();
SaveConfig();
}
}

View file

@ -35,6 +35,7 @@ namespace Mesen.GUI.Config
PreferenceInfo = new PreferenceInfo();
RecentFiles = new List<string>();
Controllers = new List<ControllerInfo>();
Cheats = new List<CheatInfo>();
}
public void ApplyConfig()
@ -47,7 +48,7 @@ namespace Mesen.GUI.Config
InteropEmu.SetNesModel(Region);
}
private void InitializeDefaults()
public void InitializeDefaults()
{
while(Controllers.Count < 4) {
var controllerInfo = new ControllerInfo();

View file

@ -15,7 +15,7 @@ namespace Mesen.GUI.Config
public class KeyMappings
{
public string A = "A";
public string B = "B";
public string B = "S";
public string Select = "W";
public string Start = "Q";
public string Up = "Up Arrow";

View file

@ -0,0 +1,100 @@
namespace Mesen.GUI.Forms
{
partial class frmDownloadProgress
{
/// <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 Windows Form 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.progressDownload = new System.Windows.Forms.ProgressBar();
this.lblFilename = new System.Windows.Forms.Label();
this.tmrStart = new System.Windows.Forms.Timer(this.components);
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// progressDownload
//
this.progressDownload.Dock = System.Windows.Forms.DockStyle.Top;
this.progressDownload.Location = new System.Drawing.Point(3, 38);
this.progressDownload.Name = "progressDownload";
this.progressDownload.Size = new System.Drawing.Size(328, 23);
this.progressDownload.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
this.progressDownload.TabIndex = 0;
//
// lblFilename
//
this.lblFilename.AutoSize = true;
this.lblFilename.Location = new System.Drawing.Point(3, 5);
this.lblFilename.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.lblFilename.Name = "lblFilename";
this.lblFilename.Size = new System.Drawing.Size(100, 13);
this.lblFilename.TabIndex = 1;
this.lblFilename.Text = "Downloading file: ...";
//
// tmrStart
//
this.tmrStart.Tick += new System.EventHandler(this.tmrStart_Tick);
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.lblFilename, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.progressDownload, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(334, 67);
this.tableLayoutPanel1.TabIndex = 2;
//
// frmDownloadProgress
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(334, 67);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.MaximumSize = new System.Drawing.Size(350, 500);
this.Name = "frmDownloadProgress";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Downloading...";
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ProgressBar progressDownload;
private System.Windows.Forms.Label lblFilename;
private System.Windows.Forms.Timer tmrStart;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
}
}

View file

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Forms
{
public partial class frmDownloadProgress : BaseForm
{
private string _link;
private string _filename;
private bool _cancel = false;
public frmDownloadProgress(string link, string filename)
{
InitializeComponent();
_link = link;
_filename = filename;
try {
File.Delete(_filename);
} catch {}
lblFilename.Text = link;
tmrStart.Start();
}
protected override void OnClosing(CancelEventArgs e)
{
_cancel = true;
base.OnClosing(e);
}
private void tmrStart_Tick(object sender, EventArgs e)
{
tmrStart.Stop();
DialogResult result = System.Windows.Forms.DialogResult.None;
using(var client = new WebClient()) {
client.DownloadProgressChanged += (object s, DownloadProgressChangedEventArgs args) => {
progressDownload.Value = args.ProgressPercentage;
};
client.DownloadFileCompleted += (object s, AsyncCompletedEventArgs args) => {
if(!args.Cancelled && args.Error == null && File.Exists(_filename)) {
result = System.Windows.Forms.DialogResult.OK;
} else if(args.Error != null) {
MessageBox.Show("Unable to download file. Check your internet connection and try again." + Environment.NewLine + Environment.NewLine + "Details:" + Environment.NewLine + args.Error.Message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Error);
result = System.Windows.Forms.DialogResult.Cancel;
}
};
Task downloadTask = null;
try {
downloadTask = client.DownloadFileTaskAsync(_link, _filename);
} catch(Exception ex) {
MessageBox.Show("Unable to download file. Check your internet connection and try again." + Environment.NewLine + Environment.NewLine + "Details:" + Environment.NewLine + ex.Message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Error);
result = System.Windows.Forms.DialogResult.Cancel;
}
if(downloadTask == null) {
result = System.Windows.Forms.DialogResult.Cancel;
} else {
while(!downloadTask.IsCompleted && !_cancel) {
System.Threading.Thread.Sleep(200);
Application.DoEvents();
}
if(_cancel) {
client.CancelAsync();
} else if(result == System.Windows.Forms.DialogResult.None) {
result = System.Windows.Forms.DialogResult.OK;
}
}
}
DialogResult = result;
this.Close();
}
}
}

View file

@ -0,0 +1,126 @@
<?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="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="tmrStart.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
</metadata>
</root>

View file

@ -276,6 +276,12 @@
<Compile Include="Forms\Cheats\frmCheatList.Designer.cs">
<DependentUpon>frmCheatList.cs</DependentUpon>
</Compile>
<Compile Include="Forms\frmDownloadProgress.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\frmDownloadProgress.Designer.cs">
<DependentUpon>frmDownloadProgress.cs</DependentUpon>
</Compile>
<Compile Include="Forms\NetPlay\frmClientConfig.cs">
<SubType>Form</SubType>
</Compile>
@ -303,6 +309,7 @@
<Compile Include="InteropEmu.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RuntimeChecker.cs" />
<Compile Include="SingleInstance.cs" />
<EmbeddedResource Include="Controls\ctrlTrackbar.resx">
<DependentUpon>ctrlTrackbar.cs</DependentUpon>
@ -391,6 +398,9 @@
<EmbeddedResource Include="Forms\Cheats\frmCheatList.resx">
<DependentUpon>frmCheatList.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\frmDownloadProgress.resx">
<DependentUpon>frmDownloadProgress.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\frmMain.resx">
<DependentUpon>frmMain.cs</DependentUpon>
</EmbeddedResource>

View file

@ -6,12 +6,15 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI
{
public class InteropEmu
{
private const string DLLPath = "WinMesen.dll";
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool TestDll();
[DllImport(DLLPath)] public static extern void InitializeEmu([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string homeFolder, IntPtr windowHandle, IntPtr dxViewerHandle);
[DllImport(DLLPath)] public static extern void Release();
@ -28,16 +31,16 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void Run();
[DllImport(DLLPath)] public static extern void Pause();
[DllImport(DLLPath)] public static extern void Resume();
[DllImport(DLLPath)] public static extern bool IsPaused();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsPaused();
[DllImport(DLLPath)] public static extern void Stop();
[DllImport(DLLPath, EntryPoint="GetROMPath")] private static extern IntPtr GetROMPathWrapper();
[DllImport(DLLPath)] public static extern void Reset();
[DllImport(DLLPath)] public static extern void StartServer(UInt16 port);
[DllImport(DLLPath)] public static extern void StopServer();
[DllImport(DLLPath)] public static extern bool IsServerRunning();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsServerRunning();
[DllImport(DLLPath)] public static extern void Connect([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string host, UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string playerName, byte[] avatarData, UInt32 avatarSize);
[DllImport(DLLPath)] public static extern void Disconnect();
[DllImport(DLLPath)] public static extern bool IsConnected();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsConnected();
[DllImport(DLLPath)] public static extern void TakeScreenshot();
@ -49,15 +52,15 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void MoviePlay([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string filename);
[DllImport(DLLPath)] public static extern void MovieRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool reset);
[DllImport(DLLPath)] public static extern void MovieStop();
[DllImport(DLLPath)] public static extern bool MoviePlaying();
[DllImport(DLLPath)] public static extern bool MovieRecording();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool MoviePlaying();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool MovieRecording();
[DllImport(DLLPath)] public static extern Int32 RomTestRun([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string filename);
[DllImport(DLLPath)] public static extern void RomTestRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool reset);
[DllImport(DLLPath)] public static extern void RomTestRecordFromMovie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string testFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string movieFilename);
[DllImport(DLLPath)] public static extern void RomTestRecordFromTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string newTestFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string existingTestFilename);
[DllImport(DLLPath)] public static extern void RomTestStop();
[DllImport(DLLPath)] public static extern bool RomTestRecording();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool RomTestRecording();
[DllImport(DLLPath)] public static extern void SaveState(UInt32 stateIndex);
[DllImport(DLLPath)] public static extern void LoadState(UInt32 stateIndex);
@ -91,7 +94,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void DebugStepOut();
[DllImport(DLLPath)] public static extern void DebugStepOver();
[DllImport(DLLPath)] public static extern void DebugRun();
[DllImport(DLLPath)] public static extern bool DebugIsCodeChanged();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugIsCodeChanged();
[DllImport(DLLPath)] public static extern IntPtr DebugGetCode();
[DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(UInt32 addr);
[DllImport(DLLPath)] public static extern UInt32 DebugGetRelativeAddress(UInt32 addr);

View file

@ -21,6 +21,10 @@ namespace Mesen.GUI
[STAThread]
static void Main(string[] args)
{
if(!RuntimeChecker.TestDll()) {
return;
}
Guid guid = new Guid("{A46606B7-2D1C-4CC5-A52F-43BCAF094AED}");
using(SingleInstance singleInstance = new SingleInstance(guid)) {
if(singleInstance.FirstInstance || !Config.ConfigManager.Config.PreferenceInfo.SingleInstance) {

74
GUI.NET/RuntimeChecker.cs Normal file
View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Forms;
namespace Mesen.GUI
{
class RuntimeChecker
{
public static bool TestDll()
{
try {
return InteropEmu.TestDll();
} catch { }
if(!File.Exists("WinMesen.dll")) {
MessageBox.Show("Mesen was unable to start due to missing files." + Environment.NewLine + Environment.NewLine + "Error: WinMesen.dll is missing.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else {
if(MessageBox.Show("Mesen was unable to start due to missing dependencies." + Environment.NewLine + Environment.NewLine + "Mesen requires the the Visual Studio 2013 runtime. Would you like to download the runtime from Microsoft's website and install it?", "Mesen", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) {
if(!RuntimeChecker.DownloadRuntime()) {
MessageBox.Show("The Visual Studio Runtime could not be installed properly.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else {
Process.Start(Process.GetCurrentProcess().MainModule.FileName);
}
}
}
return false;
}
private static bool DownloadRuntime()
{
string link = string.Empty;
if(IntPtr.Size == 4) {
//x86
link = "https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe";
} else {
//x64
link = "https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe";
}
string tempFilename = Path.GetTempPath() + "Mesen_VsRuntime2013.exe";
try {
frmDownloadProgress frm = new frmDownloadProgress(link, tempFilename);
if(frm.ShowDialog() == DialogResult.OK) {
Process installer = Process.Start(tempFilename, "/passive /norestart");
installer.WaitForExit();
if(installer.ExitCode != 0) {
MessageBox.Show("Unexpected error: " + installer.ExitCode, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
} else {
//Runtime should now be installed, try to launch Mesen again
return true;
}
}
} catch(Exception e) {
MessageBox.Show("Unexpected error: " + Environment.NewLine + e.Message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Error);
} finally {
try {
File.Delete(tempFilename);
} catch { }
}
return false;
}
}
}

View file

@ -42,6 +42,11 @@ namespace InteropEmu {
};
extern "C" {
DllExport bool __stdcall TestDll()
{
return true;
}
DllExport void __stdcall InitializeEmu(const char* homeFolder, HWND windowHandle, HWND dxViewerHandle)
{
FolderUtilities::SetHomeFolder(homeFolder);
@ -84,7 +89,7 @@ namespace InteropEmu {
}
DllExport void __stdcall Resume() { EmulationSettings::ClearFlags(EmulationFlags::Paused); }
DllExport int __stdcall IsPaused() { return EmulationSettings::CheckFlag(EmulationFlags::Paused); }
DllExport bool __stdcall IsPaused() { return EmulationSettings::CheckFlag(EmulationFlags::Paused); }
DllExport void __stdcall Stop()
{
if(Console::GetInstance()) {
@ -101,7 +106,7 @@ namespace InteropEmu {
DllExport void __stdcall StartServer(uint16_t port) { GameServer::StartServer(port); }
DllExport void __stdcall StopServer() { GameServer::StopServer(); }
DllExport int __stdcall IsServerRunning() { return GameServer::Started(); }
DllExport bool __stdcall IsServerRunning() { return GameServer::Started(); }
DllExport void __stdcall Connect(char* host, uint16_t port, char* playerName, uint8_t* avatarData, uint32_t avatarSize)
{
@ -117,7 +122,7 @@ namespace InteropEmu {
}
DllExport void __stdcall Disconnect() { GameClient::Disconnect(); }
DllExport int __stdcall IsConnected() { return GameClient::Connected(); }
DllExport bool __stdcall IsConnected() { return GameClient::Connected(); }
DllExport void __stdcall Pause()
{
@ -155,10 +160,10 @@ namespace InteropEmu {
DllExport void __stdcall MoviePlay(char* filename) { Movie::Play(filename); }
DllExport void __stdcall MovieRecord(char* filename, bool reset) { Movie::Record(filename, reset); }
DllExport void __stdcall MovieStop() { Movie::Stop(); }
DllExport int __stdcall MoviePlaying() { return Movie::Playing(); }
DllExport int __stdcall MovieRecording() { return Movie::Recording(); }
DllExport bool __stdcall MoviePlaying() { return Movie::Playing(); }
DllExport bool __stdcall MovieRecording() { return Movie::Recording(); }
DllExport int __stdcall RomTestRun(char* filename)
DllExport int32_t __stdcall RomTestRun(char* filename)
{
AutoRomTest romTest;
return romTest.Run(filename);
@ -194,7 +199,7 @@ namespace InteropEmu {
}
}
DllExport int __stdcall RomTestRecording() { return _autoRomTest != nullptr; }
DllExport bool __stdcall RomTestRecording() { return _autoRomTest != nullptr; }
DllExport void __stdcall CheatAddCustom(uint32_t address, uint8_t value, int32_t compareValue, bool isRelativeAddress) { CheatManager::AddCustomCode(address, value, compareValue, isRelativeAddress); }
DllExport void __stdcall CheatAddGameGenie(char* code) { CheatManager::AddGameGenieCode(code); }

View file

@ -35,7 +35,7 @@ extern "C"
DllExport void __stdcall DebugStepCycles(uint32_t count) { GetDebugger()->StepCycles(count); }
DllExport void __stdcall DebugStepOver() { GetDebugger()->StepOver(); }
DllExport void __stdcall DebugStepOut() { GetDebugger()->StepOut(); }
DllExport uint32_t __stdcall DebugIsCodeChanged() { return GetDebugger()->IsCodeChanged(); }
DllExport bool __stdcall DebugIsCodeChanged() { return GetDebugger()->IsCodeChanged(); }
DllExport const char* __stdcall DebugGetCode() { return GetDebugger()->GetCode()->c_str(); }
DllExport void __stdcall DebugSetNextStatement(uint16_t addr) { GetDebugger()->SetNextStatement(addr); }

View file

@ -22,7 +22,6 @@ namespace NES
SetScreenSize(256, 240);
VideoDecoder::GetInstance()->RegisterRenderingDevice(this);
MessageManager::RegisterMessageManager(this);
}
@ -55,6 +54,8 @@ namespace NES
CleanupDevice();
if(FAILED(InitDevice())) {
CleanupDevice();
} else {
VideoDecoder::GetInstance()->RegisterRenderingDevice(this);
}
_frameLock.Release();
}
@ -117,15 +118,17 @@ namespace NES
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_1;
for(UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) {
_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain(nullptr, _driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &sd, &_pSwapChain, &_pd3dDevice, &_featureLevel, &_pDeviceContext);
driverType = driverTypes[driverTypeIndex];
featureLevel = D3D_FEATURE_LEVEL_11_1;
hr = D3D11CreateDeviceAndSwapChain(nullptr, driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &sd, &_pSwapChain, &_pd3dDevice, &featureLevel, &_pDeviceContext);
if(hr == E_INVALIDARG) {
// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
hr = D3D11CreateDeviceAndSwapChain(nullptr, _driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
D3D11_SDK_VERSION, &sd, &_pSwapChain, &_pd3dDevice, &_featureLevel, &_pDeviceContext);
featureLevel = D3D_FEATURE_LEVEL_11_0;
hr = D3D11CreateDeviceAndSwapChain(nullptr, driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &sd, &_pSwapChain, &_pd3dDevice, &featureLevel, &_pDeviceContext);
}
if(SUCCEEDED(hr)) {
@ -168,7 +171,7 @@ namespace NES
// Create the state using the device.
if(FAILED(_pd3dDevice->CreateDepthStencilState(&depthDisabledStencilDesc, &_pDepthDisabledStencilState))) {
return false;
return S_FALSE;
}
// Clear the blend state description.
@ -187,7 +190,7 @@ namespace NES
// Create the blend state using the description.
if(FAILED(_pd3dDevice->CreateBlendState(&blendStateDescription, &_pAlphaEnableBlendingState))) {
return false;
return S_FALSE;
}
float blendFactor[4];
@ -212,12 +215,12 @@ namespace NES
_pTexture = CreateTexture(_nesFrameWidth, _nesFrameHeight);
if(!_pTexture) {
return 0;
return S_FALSE;
}
_overlayTexture = CreateTexture(8, 8);
if(!_overlayTexture) {
return 0;
return S_FALSE;
}
////////////////////////////////////////////////////////////////////////////
@ -243,7 +246,7 @@ namespace NES
_pd3dDevice->CreateSamplerState(&samplerDesc, &_samplerState);
if(!FAILED(CreateDDSTextureFromFile(_pd3dDevice, L"Resources\\Toast.dds", nullptr, &_toastTexture))) {
return 0;
return S_FALSE;
}
return S_OK;
@ -253,9 +256,6 @@ namespace NES
{
ID3D11Texture2D* texture;
UINT fred;
_pd3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_B8G8R8A8_UNORM, 16, &fred);
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.ArraySize = 1;
@ -265,13 +265,14 @@ namespace NES
desc.MipLevels = 1;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = fred;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.Width = width;
desc.Height = height;
desc.MiscFlags = 0;
if(FAILED(_pd3dDevice->CreateTexture2D(&desc, nullptr, &texture))) {
HRESULT hr = _pd3dDevice->CreateTexture2D(&desc, nullptr, &texture);
if(FAILED(hr)) {
return nullptr;
}
return texture;

View file

@ -20,8 +20,6 @@ namespace NES {
private:
HWND _hWnd = nullptr;
D3D_DRIVER_TYPE _driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL _featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device* _pd3dDevice = nullptr;
ID3D11DeviceContext* _pDeviceContext = nullptr;
IDXGISwapChain* _pSwapChain = nullptr;

View file

@ -5,12 +5,16 @@
SoundManager::SoundManager(HWND hwnd)
{
SoundMixer::RegisterAudioDevice(this);
_hWnd = hwnd;
_directSound = 0;
_primaryBuffer = 0;
_secondaryBuffer = 0;
if(InitializeDirectSound(44100)) {
SoundMixer::RegisterAudioDevice(this);
} else {
MessageManager::DisplayMessage("Error", "Could not initialize audio system");
}
}
SoundManager::~SoundManager()