BizHawk/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs

323 lines
7.0 KiB
C#
Raw Normal View History

2014-06-29 03:03:27 +00:00
using System.Collections.Generic;
2014-06-14 14:04:54 +00:00
using System.Globalization;
2014-06-13 00:15:55 +00:00
using System.IO;
namespace BizHawk.Client.Common
{
2014-06-29 03:03:27 +00:00
public partial class Bk2Movie
2014-06-13 00:15:55 +00:00
{
2017-05-19 18:17:07 +00:00
protected IStringLog Log { get; set; }
protected string LogKey { get; set; } = "";
2014-06-13 00:43:55 +00:00
public void WriteInputLog(TextWriter writer)
{
writer.WriteLine("[Input]");
WriteRawInputLog(writer);
writer.WriteLine("[/Input]");
}
2015-03-22 16:55:34 +00:00
public string GetInputLogEntry(int frame)
{
if (frame < FrameCount && frame >= 0)
{
int getframe;
if (LoopOffset.HasValue)
{
2017-05-19 18:17:07 +00:00
if (frame < Log.Count)
2015-03-22 16:55:34 +00:00
{
getframe = frame;
}
else
{
2017-05-19 18:17:07 +00:00
getframe = ((frame - LoopOffset.Value) % (Log.Count - LoopOffset.Value)) + LoopOffset.Value;
2015-03-22 16:55:34 +00:00
}
}
else
{
getframe = frame;
}
2017-05-19 18:17:07 +00:00
return Log[getframe];
2015-03-22 16:55:34 +00:00
}
2017-05-10 11:45:23 +00:00
return "";
2015-03-22 16:55:34 +00:00
}
public virtual bool ExtractInputLog(TextReader reader, out string errorMessage)
2014-06-13 00:15:55 +00:00
{
2017-05-10 11:45:23 +00:00
errorMessage = "";
2014-06-14 14:04:54 +00:00
int? stateFrame = null;
// We are in record mode so replace the movie log with the one from the savestate
if (!Global.MovieSession.MultiTrack.IsActive)
{
2017-05-19 18:17:07 +00:00
if (Global.Config.EnableBackupMovies && MakeBackup && Log.Count != 0)
2014-06-14 14:04:54 +00:00
{
SaveBackup();
MakeBackup = false;
2014-06-14 14:04:54 +00:00
}
2017-05-19 18:17:07 +00:00
Log.Clear();
2014-06-14 14:04:54 +00:00
while (true)
{
var line = reader.ReadLine();
if (string.IsNullOrEmpty(line))
2014-06-14 14:04:54 +00:00
{
break;
}
// in BK2, this is part of the input log, and not involved with the core state at all
// accordingly, this case (for special neshawk format frame numbers) is irrelevant
// probably
else if (line.Contains("Frame 0x")) // NES stores frame count in hex, yay
2014-06-14 14:04:54 +00:00
{
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:", "");
}
2014-06-14 14:04:54 +00:00
else if (line[0] == '|')
{
2017-05-19 18:17:07 +00:00
Log.Add(line);
2014-06-14 14:04:54 +00:00
}
}
}
else
{
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:", "");
}
2014-06-14 14:04:54 +00:00
else if (line.StartsWith("|"))
{
SetFrameAt(i, line);
2014-06-14 14:04:54 +00:00
i++;
}
}
}
if (!stateFrame.HasValue)
{
errorMessage = "Savestate Frame number failed to parse";
}
var stateFramei = stateFrame ?? 0;
2017-05-19 18:17:07 +00:00
if (stateFramei > 0 && stateFramei < Log.Count)
2014-06-14 14:04:54 +00:00
{
if (!Global.Config.VBAStyleMovieLoadState)
{
2014-06-15 02:23:28 +00:00
Truncate(stateFramei);
2014-06-14 14:04:54 +00:00
}
}
2017-05-19 18:17:07 +00:00
else if (stateFramei > Log.Count) // Post movie savestate
2014-06-14 14:04:54 +00:00
{
if (!Global.Config.VBAStyleMovieLoadState)
{
2017-05-19 18:17:07 +00:00
Truncate(Log.Count);
2014-06-14 14:04:54 +00:00
}
2017-05-19 18:17:07 +00:00
Mode = Moviemode.Finished;
2014-06-14 14:04:54 +00:00
}
if (IsCountingRerecords)
{
Rerecords++;
}
return true;
2014-06-13 00:15:55 +00:00
}
public bool CheckTimeLines(TextReader reader, out string errorMessage)
{
2014-06-14 14:04:54 +00:00
// This function will compare the movie data to the savestate movie data to see if they match
2017-05-10 11:45:23 +00:00
errorMessage = "";
2014-06-15 02:23:28 +00:00
var newLog = new List<string>();
2014-06-14 14:04:54 +00:00
var stateFrame = 0;
while (true)
{
var line = reader.ReadLine();
if (line == null)
{
break;
2014-06-14 14:04:54 +00:00
}
2017-05-10 11:45:23 +00:00
if (line.Trim() == "")
2014-06-14 14:04:54 +00:00
{
continue;
}
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[0] == '|')
{
newLog.Add(line);
2014-06-14 14:04:54 +00:00
}
}
if (stateFrame == 0)
{
stateFrame = newLog.Count; // In case the frame count failed to parse, revert to using the entire state input log
2014-06-14 14:04:54 +00:00
}
2017-05-19 18:17:07 +00:00
if (Log.Count < stateFrame)
2014-06-14 14:04:54 +00:00
{
if (IsFinished)
{
return true;
}
errorMessage = "The savestate is from frame "
+ newLog.Count
2014-06-14 14:04:54 +00:00
+ " which is greater than the current movie length of "
2017-05-19 18:17:07 +00:00
+ Log.Count;
2014-06-14 14:04:54 +00:00
return false;
}
for (var i = 0; i < stateFrame; i++)
{
2017-05-19 18:17:07 +00:00
if (Log[i] != newLog[i])
2014-06-14 14:04:54 +00:00
{
errorMessage = "The savestate input does not match the movie input at frame "
+ (i + 1)
+ ".";
return false;
}
}
if (stateFrame > newLog.Count) // stateFrame is greater than state input log, so movie finished mode
2014-06-14 14:04:54 +00:00
{
2017-05-19 18:17:07 +00:00
if (Mode == Moviemode.Play || Mode == Moviemode.Finished)
2014-06-14 14:04:54 +00:00
{
2017-05-19 18:17:07 +00:00
Mode = Moviemode.Finished;
2014-06-14 14:04:54 +00:00
return true;
}
return false;
}
2017-05-19 18:17:07 +00:00
if (Mode == Moviemode.Finished)
2014-06-14 14:04:54 +00:00
{
2017-05-19 18:17:07 +00:00
Mode = Moviemode.Play;
2014-06-14 14:04:54 +00:00
}
return true;
2014-06-13 00:15:55 +00:00
}
2014-06-13 11:30:25 +00:00
protected void WriteRawInputLog(TextWriter writer)
2014-06-13 11:30:25 +00:00
{
var lg = new Bk2LogEntryGenerator(LogKey);
lg.SetSource(Global.MovieOutputHardpoint);
writer.WriteLine(lg.GenerateLogKey());
2017-05-19 18:17:07 +00:00
foreach (var record in Log)
2014-06-13 11:30:25 +00:00
{
writer.WriteLine(record);
2014-06-13 11:30:25 +00:00
}
}
/// <summary>
/// Takes a log entry from a line in an input log,
/// If the log key differs from the system's, it will be converted
/// </summary>
/// <param name="line">a log entry line of text from the input log</param>
/// <param name="logKey">a key used to describe the mnemonic values and positions in the log</param>
private string ConvertLogEntryFromFile(string line, string logKey)
{
var adapter = new Bk2LogEntryGenerator(logKey).MovieControllerAdapter;
adapter.Definition = Global.MovieSession.MovieControllerAdapter.Definition;
adapter.SetControllersAsMnemonic(line);
var lg = LogGeneratorInstance();
lg.SetSource(adapter);
return lg.GenerateLogEntry();
}
2014-06-13 00:15:55 +00:00
}
}