Tastudio - support "out of order savestating" using saveslot states. Experiemental, could have bugs particularly off by one issues

This commit is contained in:
adelikat 2014-11-15 21:49:58 +00:00
parent eb292eddcc
commit 5349affbc4
5 changed files with 175 additions and 14 deletions

View File

@ -9,7 +9,7 @@ namespace BizHawk.Client.Common
public partial class Bk2Movie
{
protected List<string> _log = new List<string>();
private string _logKey = string.Empty;
protected string LogKey = string.Empty;
public string GetInputLog()
{
@ -22,7 +22,7 @@ namespace BizHawk.Client.Common
return sb.ToString();
}
public bool ExtractInputLog(TextReader reader, out string errorMessage)
public virtual bool ExtractInputLog(TextReader reader, out string errorMessage)
{
errorMessage = string.Empty;
int? stateFrame = null;
@ -30,10 +30,10 @@ namespace BizHawk.Client.Common
// We are in record mode so replace the movie log with the one from the savestate
if (!Global.MovieSession.MultiTrack.IsActive)
{
if (Global.Config.EnableBackupMovies && _makeBackup && _log.Any())
if (Global.Config.EnableBackupMovies && MakeBackup && _log.Any())
{
SaveBackup();
_makeBackup = false;
MakeBackup = false;
}
_log.Clear();
@ -72,7 +72,7 @@ namespace BizHawk.Client.Common
}
else if (line.StartsWith("LogKey:"))
{
_logKey = line.Replace("LogKey:", "");
LogKey = line.Replace("LogKey:", "");
}
else if (line[0] == '|')
{
@ -119,7 +119,7 @@ namespace BizHawk.Client.Common
}
else if (line.StartsWith("LogKey:"))
{
_logKey = line.Replace("LogKey:", "");
LogKey = line.Replace("LogKey:", "");
}
else if (line.StartsWith("|"))
{
@ -265,7 +265,7 @@ namespace BizHawk.Client.Common
protected StringBuilder RawInputLog()
{
var lg = new Bk2LogEntryGenerator(_logKey);
var lg = new Bk2LogEntryGenerator(LogKey);
lg.SetSource(Global.MovieOutputHardpoint);
var sb = new StringBuilder();

View File

@ -30,10 +30,10 @@ namespace BizHawk.Client.Common
public virtual void StartNewRecording()
{
_mode = Moviemode.Record;
if (Global.Config.EnableBackupMovies && _makeBackup && _log.Any())
if (Global.Config.EnableBackupMovies && MakeBackup && _log.Any())
{
SaveBackup();
_makeBackup = false;
MakeBackup = false;
}
_log.Clear();

View File

@ -7,7 +7,7 @@ namespace BizHawk.Client.Common
{
public partial class Bk2Movie : IMovie
{
private bool _makeBackup = true;
protected bool MakeBackup = true;
public Bk2Movie(string filename)
: this()
@ -24,7 +24,7 @@ namespace BizHawk.Client.Common
Filename = string.Empty;
IsCountingRerecords = true;
_mode = Moviemode.Inactive;
_makeBackup = true;
MakeBackup = true;
Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0.0";
}
@ -52,7 +52,7 @@ namespace BizHawk.Client.Common
public ILogEntryGenerator LogGeneratorInstance()
{
return new Bk2LogEntryGenerator(_logKey);
return new Bk2LogEntryGenerator(LogKey);
}
public double FrameCount
@ -168,7 +168,7 @@ namespace BizHawk.Client.Common
#endregion
private void SetFrameAt(int frameNum, string frame)
protected void SetFrameAt(int frameNum, string frame)
{
if (_log.Count > frameNum)
{

View File

@ -141,7 +141,7 @@ namespace BizHawk.Client.Common
}
});
bl.GetLump(BinaryStateLump.Input, true, delegate(TextReader tr)
bl.GetLump(BinaryStateLump.Input, true, delegate(TextReader tr) // Note: ExtractInputLog will clear Lag and State data potentially, this must come before loading those
{
var errorMessage = string.Empty;
IsCountingRerecords = false;

View File

@ -7,6 +7,7 @@ using System.Text;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using System.ComponentModel;
using System.Globalization;
namespace BizHawk.Client.Common
{
@ -335,5 +336,165 @@ namespace BizHawk.Client.Common
{
return _log;
}
private int? TimelineBranchFrame = null;
// TODO: this is 99% copy pasting of bad code
public override bool ExtractInputLog(TextReader reader, out string errorMessage)
{
errorMessage = string.Empty;
int? stateFrame = null;
var newLog = new List<string>();
// We are in record mode so replace the movie log with the one from the savestate
if (!Global.MovieSession.MultiTrack.IsActive)
{
TimelineBranchFrame = null;
if (Global.Config.EnableBackupMovies && MakeBackup && _log.Any())
{
SaveBackup();
MakeBackup = false;
}
int counter = 0;
while (true)
{
var line = reader.ReadLine();
if (string.IsNullOrEmpty(line))
{
break;
}
else if (line.Contains("Frame 0x")) // NES stores frame count in hex, yay
{
var strs = line.Split('x');
try
{
stateFrame = int.Parse(strs[1], NumberStyles.HexNumber);
}
catch
{
errorMessage = "Savestate Frame number failed to parse";
return false;
}
}
else if (line.Contains("Frame "))
{
var strs = line.Split(' ');
try
{
stateFrame = int.Parse(strs[1]);
}
catch
{
errorMessage = "Savestate Frame number failed to parse";
return false;
}
}
else if (line.StartsWith("LogKey:"))
{
LogKey = line.Replace("LogKey:", "");
}
else if (line[0] == '|')
{
newLog.Add(line);
if (!TimelineBranchFrame.HasValue && line != _log[counter])
{
TimelineBranchFrame = counter;
}
counter++;
}
}
_log.Clear();
_log.AddRange(newLog);
}
else //Multitrack mode
{
// TODO: consider TimelineBranchFrame here, my thinking is that there's never a scenario to invalidate state/lag data during multitrack
var i = 0;
while (true)
{
var line = reader.ReadLine();
if (line == null)
{
break;
}
if (line.Contains("Frame 0x")) // NES stores frame count in hex, yay
{
var strs = line.Split('x');
try
{
stateFrame = int.Parse(strs[1], NumberStyles.HexNumber);
}
catch
{
errorMessage = "Savestate Frame number failed to parse";
return false;
}
}
else if (line.Contains("Frame "))
{
var strs = line.Split(' ');
try
{
stateFrame = int.Parse(strs[1]);
}
catch
{
errorMessage = "Savestate Frame number failed to parse";
return false;
}
}
else if (line.StartsWith("LogKey:"))
{
LogKey = line.Replace("LogKey:", "");
}
else if (line.StartsWith("|"))
{
SetFrameAt(i, line);
i++;
}
}
}
if (!stateFrame.HasValue)
{
errorMessage = "Savestate Frame number failed to parse";
}
var stateFramei = stateFrame ?? 0;
if (stateFramei > 0 && stateFramei < _log.Count)
{
if (!Global.Config.VBAStyleMovieLoadState)
{
Truncate(stateFramei);
}
}
else if (stateFramei > _log.Count) // Post movie savestate
{
if (!Global.Config.VBAStyleMovieLoadState)
{
Truncate(_log.Count);
}
_mode = Moviemode.Finished;
}
if (IsCountingRerecords)
{
Rerecords++;
}
if (TimelineBranchFrame.HasValue)
{
LagLog.RemoveFrom(TimelineBranchFrame.Value);
TasStateManager.Invalidate(TimelineBranchFrame.Value);
}
return true;
}
}
}