add a new tool to mainform, the batch runner. it's only enabled in INTERIM. it allows you to mass instantiate a bunch of emu cores and look for failure to load or exceptions on frame advance. it doesn't do all that much, but can easily be extended if any other devs are interested in it
This commit is contained in:
parent
a54119db03
commit
7668b15052
|
@ -157,6 +157,9 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
|
||||
// set this here so we can see what file we tried to load even if an error occurs
|
||||
CanonicalFullPath = file.CanonicalFullPath;
|
||||
|
||||
IEmulator nextEmulator = null;
|
||||
RomGame rom = null;
|
||||
GameInfo game = null;
|
||||
|
@ -234,18 +237,21 @@ namespace BizHawk.Client.Common
|
|||
"The PCE-CD System Card you have selected is known to be a bad dump. This may cause problems playing PCE-CD games.\n\n"
|
||||
+ "It is recommended that you find a good dump of the system card. Sorry to be the bearer of bad news!",
|
||||
game.System);
|
||||
return false;
|
||||
}
|
||||
else if (rom.GameInfo.NotInDatabase)
|
||||
{
|
||||
ThrowLoadError(
|
||||
"The PCE-CD System Card you have selected is not recognized in our database. That might mean it's a bad dump, or isn't the correct rom.",
|
||||
game.System);
|
||||
return false;
|
||||
}
|
||||
else if (rom.GameInfo["BIOS"] == false)
|
||||
{
|
||||
ThrowLoadError(
|
||||
"The PCE-CD System Card you have selected is not a BIOS image. You may have selected the wrong rom.",
|
||||
game.System);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rom.GameInfo["SuperSysCard"])
|
||||
|
@ -258,6 +264,7 @@ namespace BizHawk.Client.Common
|
|||
ThrowLoadError(
|
||||
"This game requires a version 3.0 System card and won't run with the system card you've selected. Try selecting a 3.0 System Card in Config->Paths->PC Engine.",
|
||||
game.System);
|
||||
return false;
|
||||
}
|
||||
|
||||
game.FirmwareHash = Util.Hash_SHA1(rom.RomData);
|
||||
|
@ -295,6 +302,7 @@ namespace BizHawk.Client.Common
|
|||
catch (Exception ex)
|
||||
{
|
||||
ThrowLoadError(ex.ToString(), "XMLGame Load Error"); // TODO: don't pass in XMLGame Load Error as a system ID
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else // most extensions
|
||||
|
@ -449,7 +457,6 @@ namespace BizHawk.Client.Common
|
|||
Rom = rom;
|
||||
LoadedEmulator = nextEmulator;
|
||||
Game = game;
|
||||
CanonicalFullPath = file.CanonicalFullPath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -453,6 +453,13 @@
|
|||
<DependentUpon>ScanlineSlider.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Throttle.cs" />
|
||||
<Compile Include="tools\BatchRun.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="tools\BatchRun.Designer.cs">
|
||||
<DependentUpon>BatchRun.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="tools\BatchRunner.cs" />
|
||||
<Compile Include="tools\Cheats\CheatEdit.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
|
@ -966,6 +973,9 @@
|
|||
<EmbeddedResource Include="ScanlineSlider.resx">
|
||||
<DependentUpon>ScanlineSlider.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="tools\BatchRun.resx">
|
||||
<DependentUpon>BatchRun.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="tools\Cheats\CheatEdit.resx">
|
||||
<DependentUpon>CheatEdit.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1107,6 +1107,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
TAStudioMenuItem.Enabled =
|
||||
VirtualPadMenuItem.Enabled =
|
||||
!(Global.Emulator is NullEmulator);
|
||||
batchRunnerToolStripMenuItem.Visible = VersionInfo.INTERIM;
|
||||
}
|
||||
|
||||
private void ToolBoxMenuItem_Click(object sender, EventArgs e)
|
||||
|
|
|
@ -3242,5 +3242,10 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
Global.Config.NES_InQuickNES ^= true;
|
||||
}
|
||||
|
||||
private void batchRunnerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
new BatchRun().ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
partial class BatchRun
|
||||
{
|
||||
/// <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.label1 = new System.Windows.Forms.Label();
|
||||
this.listBox1 = new System.Windows.Forms.ListBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.buttonClear = new System.Windows.Forms.Button();
|
||||
this.buttonGo = new System.Windows.Forms.Button();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.numericUpDownFrames = new System.Windows.Forms.NumericUpDown();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.progressBar1 = new System.Windows.Forms.ProgressBar();
|
||||
this.buttonDump = new System.Windows.Forms.Button();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDownFrames)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(12, 9);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(83, 13);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Drag Files Here:";
|
||||
//
|
||||
// listBox1
|
||||
//
|
||||
this.listBox1.AllowDrop = true;
|
||||
this.listBox1.FormattingEnabled = true;
|
||||
this.listBox1.Location = new System.Drawing.Point(12, 25);
|
||||
this.listBox1.Name = "listBox1";
|
||||
this.listBox1.Size = new System.Drawing.Size(268, 147);
|
||||
this.listBox1.TabIndex = 2;
|
||||
this.listBox1.DragDrop += new System.Windows.Forms.DragEventHandler(this.listBox1_DragDrop);
|
||||
this.listBox1.DragEnter += new System.Windows.Forms.DragEventHandler(this.listBox1_DragEnter);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(12, 175);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(92, 13);
|
||||
this.label2.TabIndex = 3;
|
||||
this.label2.Text = "Number of Files: 0";
|
||||
//
|
||||
// buttonClear
|
||||
//
|
||||
this.buttonClear.Location = new System.Drawing.Point(12, 191);
|
||||
this.buttonClear.Name = "buttonClear";
|
||||
this.buttonClear.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonClear.TabIndex = 4;
|
||||
this.buttonClear.Text = "Clear!";
|
||||
this.buttonClear.UseVisualStyleBackColor = true;
|
||||
this.buttonClear.Click += new System.EventHandler(this.buttonClear_Click);
|
||||
//
|
||||
// buttonGo
|
||||
//
|
||||
this.buttonGo.Location = new System.Drawing.Point(12, 220);
|
||||
this.buttonGo.Name = "buttonGo";
|
||||
this.buttonGo.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonGo.TabIndex = 5;
|
||||
this.buttonGo.Text = "Go!";
|
||||
this.buttonGo.UseVisualStyleBackColor = true;
|
||||
this.buttonGo.Click += new System.EventHandler(this.buttonGo_Click);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(12, 246);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(40, 13);
|
||||
this.label3.TabIndex = 6;
|
||||
this.label3.Text = "Status:";
|
||||
//
|
||||
// numericUpDownFrames
|
||||
//
|
||||
this.numericUpDownFrames.Location = new System.Drawing.Point(160, 194);
|
||||
this.numericUpDownFrames.Maximum = new decimal(new int[] {
|
||||
1000,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numericUpDownFrames.Name = "numericUpDownFrames";
|
||||
this.numericUpDownFrames.Size = new System.Drawing.Size(120, 20);
|
||||
this.numericUpDownFrames.TabIndex = 7;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(157, 175);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(74, 13);
|
||||
this.label4.TabIndex = 8;
|
||||
this.label4.Text = "Frames to run:";
|
||||
//
|
||||
// progressBar1
|
||||
//
|
||||
this.progressBar1.Location = new System.Drawing.Point(12, 262);
|
||||
this.progressBar1.Name = "progressBar1";
|
||||
this.progressBar1.Size = new System.Drawing.Size(268, 23);
|
||||
this.progressBar1.TabIndex = 9;
|
||||
//
|
||||
// buttonDump
|
||||
//
|
||||
this.buttonDump.Location = new System.Drawing.Point(93, 220);
|
||||
this.buttonDump.Name = "buttonDump";
|
||||
this.buttonDump.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonDump.TabIndex = 10;
|
||||
this.buttonDump.Text = "Dump...";
|
||||
this.buttonDump.UseVisualStyleBackColor = true;
|
||||
this.buttonDump.Click += new System.EventHandler(this.buttonDump_Click);
|
||||
//
|
||||
// BatchRun
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(292, 327);
|
||||
this.Controls.Add(this.buttonDump);
|
||||
this.Controls.Add(this.progressBar1);
|
||||
this.Controls.Add(this.label4);
|
||||
this.Controls.Add(this.numericUpDownFrames);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.buttonGo);
|
||||
this.Controls.Add(this.buttonClear);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.listBox1);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Name = "BatchRun";
|
||||
this.Text = "BatchRun";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BatchRun_FormClosing);
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDownFrames)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.ListBox listBox1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Button buttonClear;
|
||||
private System.Windows.Forms.Button buttonGo;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.NumericUpDown numericUpDownFrames;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.ProgressBar progressBar1;
|
||||
private System.Windows.Forms.Button buttonDump;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class BatchRun : Form
|
||||
{
|
||||
Thread thread = null;
|
||||
List<BatchRunner.Result> MostRecentResults = null;
|
||||
|
||||
public BatchRun()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void listBox1_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
e.Effect = DragDropEffects.Link;
|
||||
else
|
||||
e.Effect = DragDropEffects.None;
|
||||
}
|
||||
|
||||
private void SetCount()
|
||||
{
|
||||
label2.Text = string.Format("Number of files: {0}", listBox1.Items.Count);
|
||||
}
|
||||
|
||||
private void listBox1_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
{
|
||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
listBox1.Items.AddRange(files);
|
||||
SetCount();
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonClear_Click(object sender, EventArgs e)
|
||||
{
|
||||
listBox1.Items.Clear();
|
||||
SetCount();
|
||||
}
|
||||
|
||||
private void buttonGo_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (thread != null)
|
||||
{
|
||||
MessageBox.Show("Old one still running!");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (listBox1.Items.Count == 0)
|
||||
{
|
||||
MessageBox.Show("No files!");
|
||||
}
|
||||
else
|
||||
{
|
||||
label3.Text = "Status: Running...";
|
||||
int nframes = (int)numericUpDownFrames.Value;
|
||||
List<string> files = new List<string>(listBox1.Items.Count);
|
||||
foreach (string s in listBox1.Items)
|
||||
files.Add(s);
|
||||
thread = new Thread(ThreadProc);
|
||||
thread.Start(new Tuple<int, List<string>>(nframes, files));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressUpdate(int curr, int max)
|
||||
{
|
||||
progressBar1.Maximum = max;
|
||||
progressBar1.Value = curr;
|
||||
}
|
||||
|
||||
void ThreadProc(object o)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pp = (Tuple<int, List<string>>)o;
|
||||
BatchRunner br = new BatchRunner(pp.Item2, pp.Item1);
|
||||
br.OnProgress += br_OnProgress;
|
||||
var results = br.Run();
|
||||
this.Invoke(() => { label3.Text = "Status: Finished!"; MostRecentResults = results; });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(e.ToString(), "The Whole Thing Died!");
|
||||
this.Invoke(() => label3.Text = "Deaded!");
|
||||
}
|
||||
this.Invoke(() => thread = null);
|
||||
}
|
||||
|
||||
void br_OnProgress(object sender, BatchRunner.ProgressEventArgs e)
|
||||
{
|
||||
this.Invoke(() => ProgressUpdate(e.Completed, e.Total));
|
||||
e.ShouldCancel = false;
|
||||
}
|
||||
|
||||
private void BatchRun_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (thread != null)
|
||||
{
|
||||
MessageBox.Show("Can't close while task is running!");
|
||||
e.Cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonDump_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (MostRecentResults != null)
|
||||
{
|
||||
using (var sfd = new SaveFileDialog())
|
||||
{
|
||||
var result = sfd.ShowDialog(this);
|
||||
if (result == System.Windows.Forms.DialogResult.OK)
|
||||
{
|
||||
using (TextWriter tw = new StreamWriter(sfd.FileName))
|
||||
{
|
||||
foreach (var r in MostRecentResults)
|
||||
r.DumpToTW(tw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("No results to save!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
<?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>
|
||||
</root>
|
|
@ -0,0 +1,185 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public class BatchRunner
|
||||
{
|
||||
public class ProgressEventArgs
|
||||
{
|
||||
public int Completed { get; private set; }
|
||||
public int Total { get; private set; }
|
||||
public bool ShouldCancel { get; set; }
|
||||
public ProgressEventArgs(int Completed, int Total)
|
||||
{
|
||||
this.Completed = Completed;
|
||||
this.Total = Total;
|
||||
}
|
||||
}
|
||||
public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);
|
||||
public event ProgressEventHandler OnProgress;
|
||||
|
||||
List<string> files;
|
||||
RomLoader ldr;
|
||||
CoreComm Comm;
|
||||
int numframes = 0;
|
||||
int multiindex = 0;
|
||||
bool multihasnext = false;
|
||||
|
||||
List<Result> Results = new List<Result>();
|
||||
Result current;
|
||||
|
||||
public class Result
|
||||
{
|
||||
public string Filename; // name of file
|
||||
public string Fullname; // filename + subfilename
|
||||
public GameInfo GI;
|
||||
|
||||
public Type CoreType; // actual type of the core that was returned
|
||||
public enum EStatus
|
||||
{
|
||||
ExceptOnLoad, // exception thrown on load
|
||||
ErrorOnLoad, // error method thrown on load
|
||||
FalseOnLoad, // romloader returned false with no other information
|
||||
ExceptOnAdv, // exception thrown on frame advance
|
||||
Success, // load fully complete
|
||||
};
|
||||
public EStatus Status; // what happened
|
||||
public List<string> Messages = new List<string>();
|
||||
|
||||
public void DumpToTW(System.IO.TextWriter tw)
|
||||
{
|
||||
tw.WriteLine("{0}\t{1}\t{2}\t{3}\n", Filename, Fullname, CoreType, Status);
|
||||
}
|
||||
}
|
||||
|
||||
public BatchRunner(IEnumerable<string> files, int numframes)
|
||||
{
|
||||
this.files = new List<string>(files);
|
||||
this.numframes = numframes;
|
||||
|
||||
ldr = new RomLoader();
|
||||
ldr.OnLoadError += OnLoadError;
|
||||
ldr.ChooseArchive = ChooseArchive;
|
||||
Comm = new CoreComm(CommMessage);
|
||||
CoreFileProvider.SyncCoreCommInputSignals(Comm);
|
||||
}
|
||||
|
||||
void OnLoadError(object sender, RomLoader.RomErrorArgs e)
|
||||
{
|
||||
current.Status = Result.EStatus.ErrorOnLoad;
|
||||
current.Messages.Add(string.Format("OnLoadError: {0}, {1}", e.AttemptedCoreLoad, e.Message));
|
||||
}
|
||||
|
||||
void CommMessage(string msg)
|
||||
{
|
||||
current.Messages.Add(string.Format("CommMessage: {0}", msg));
|
||||
}
|
||||
|
||||
int? ChooseArchive(HawkFile hf)
|
||||
{
|
||||
int ret = multiindex;
|
||||
multiindex++;
|
||||
multihasnext = multiindex < hf.ArchiveItems.Count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<Result> Run()
|
||||
{
|
||||
Results.Clear();
|
||||
current = null;
|
||||
RunInternal();
|
||||
return new List<Result>(Results);
|
||||
}
|
||||
|
||||
void RunInternal()
|
||||
{
|
||||
for (int i = 0; i < files.Count; i++)
|
||||
{
|
||||
string f = files[i];
|
||||
multihasnext = false;
|
||||
multiindex = 0;
|
||||
do
|
||||
{
|
||||
LoadOne(f);
|
||||
} while (multihasnext);
|
||||
if (OnProgress != null)
|
||||
{
|
||||
var e = new ProgressEventArgs(i + 1, files.Count);
|
||||
OnProgress(this, e);
|
||||
if (e.ShouldCancel)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoadOne(string f)
|
||||
{
|
||||
current = new Result { Filename = f };
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
result = ldr.LoadRom(f, Comm);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
current.Status = Result.EStatus.ExceptOnLoad;
|
||||
current.Messages.Add(e.ToString());
|
||||
Results.Add(current);
|
||||
current = null;
|
||||
return;
|
||||
}
|
||||
current.Fullname = ldr.CanonicalFullPath;
|
||||
if (current.Status == Result.EStatus.ErrorOnLoad)
|
||||
{
|
||||
Results.Add(current);
|
||||
current = null;
|
||||
return;
|
||||
}
|
||||
if (result == false)
|
||||
{
|
||||
current.Status = Result.EStatus.FalseOnLoad;
|
||||
Results.Add(current);
|
||||
current = null;
|
||||
return;
|
||||
}
|
||||
|
||||
using (IEmulator emu = ldr.LoadedEmulator)
|
||||
{
|
||||
current.GI = ldr.Game;
|
||||
current.CoreType = emu.GetType();
|
||||
emu.Controller = new Controller(emu.ControllerDefinition);
|
||||
|
||||
for (int i = 0; i < numframes; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
int nsamp;
|
||||
short[] samp;
|
||||
emu.FrameAdvance(true, true);
|
||||
// some cores really really really like it if you drain their audio every frame
|
||||
emu.SyncSoundProvider.GetSamples(out samp, out nsamp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
current.Messages.Add(e.ToString());
|
||||
current.Status = Result.EStatus.ExceptOnAdv;
|
||||
Results.Add(current);
|
||||
current = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
current.Status = Result.EStatus.Success;
|
||||
Results.Add(current);
|
||||
current = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue