195 lines
4.7 KiB
C#
195 lines
4.7 KiB
C#
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 int Frames; // number of frames successfully run
|
|
public int LaggedFrames; // number of those that were lagged
|
|
|
|
public void DumpToTW(System.IO.TextWriter tw)
|
|
{
|
|
tw.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", Filename, Fullname, CoreType, Status, Frames, LaggedFrames);
|
|
}
|
|
}
|
|
|
|
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, 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);
|
|
|
|
current.Frames = 0;
|
|
current.LaggedFrames = 0;
|
|
|
|
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);
|
|
current.Frames++;
|
|
if (emu.IsLagFrame)
|
|
current.LaggedFrames++;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|