2014-06-29 03:03:27 +00:00
|
|
|
|
using BizHawk.Emulation.Common;
|
2013-12-07 16:31:04 +00:00
|
|
|
|
|
2013-10-25 00:59:34 +00:00
|
|
|
|
namespace BizHawk.Client.Common
|
|
|
|
|
{
|
2014-06-13 00:15:55 +00:00
|
|
|
|
public partial class BkmMovie : IMovie
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-08 22:12:15 +00:00
|
|
|
|
private bool _makeBackup = true;
|
2014-04-06 19:01:00 +00:00
|
|
|
|
private bool _changes;
|
|
|
|
|
private int? _loopOffset;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
|
2014-06-14 20:17:07 +00:00
|
|
|
|
public BkmMovie(string filename)
|
|
|
|
|
: this()
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-11 01:41:41 +00:00
|
|
|
|
Rerecords = 0;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
Filename = filename;
|
2014-04-06 19:01:00 +00:00
|
|
|
|
Loaded = !string.IsNullOrWhiteSpace(filename);
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-14 20:17:07 +00:00
|
|
|
|
public BkmMovie()
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-13 00:43:55 +00:00
|
|
|
|
Header = new BkmHeader();
|
2014-06-12 20:42:46 +00:00
|
|
|
|
Header[HeaderKeys.MOVIEVERSION] = "BizHawk v0.0.1";
|
2014-04-06 19:01:00 +00:00
|
|
|
|
Filename = string.Empty;
|
2013-11-16 21:05:59 +00:00
|
|
|
|
_preloadFramecount = 0;
|
2014-06-12 23:57:23 +00:00
|
|
|
|
|
2013-10-25 00:59:34 +00:00
|
|
|
|
IsCountingRerecords = true;
|
2013-11-16 21:05:59 +00:00
|
|
|
|
_mode = Moviemode.Inactive;
|
2014-06-08 22:12:15 +00:00
|
|
|
|
_makeBackup = true;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Properties
|
2013-11-30 03:23:19 +00:00
|
|
|
|
|
2014-06-14 22:36:32 +00:00
|
|
|
|
public ILogEntryGenerator LogGeneratorInstance()
|
|
|
|
|
{
|
|
|
|
|
return new BkmLogEntryGenerator();
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-17 01:24:44 +00:00
|
|
|
|
public string PreferredExtension { get { return Extension; } }
|
|
|
|
|
public const string Extension = "bkm";
|
|
|
|
|
|
2014-06-13 00:43:55 +00:00
|
|
|
|
public BkmHeader Header { get; private set; }
|
2013-10-27 22:13:08 +00:00
|
|
|
|
public string Filename { get; set; }
|
|
|
|
|
public bool IsCountingRerecords { get; set; }
|
2013-10-25 00:59:34 +00:00
|
|
|
|
public bool Loaded { get; private set; }
|
2014-06-12 23:57:23 +00:00
|
|
|
|
|
2013-11-30 03:10:05 +00:00
|
|
|
|
public int InputLogLength
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-14 21:37:51 +00:00
|
|
|
|
get { return _log.Count; }
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-30 03:10:05 +00:00
|
|
|
|
public double FrameCount
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2013-11-30 03:10:05 +00:00
|
|
|
|
if (_loopOffset.HasValue)
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2013-11-30 03:10:05 +00:00
|
|
|
|
return double.PositiveInfinity;
|
|
|
|
|
}
|
2014-04-06 19:01:00 +00:00
|
|
|
|
|
|
|
|
|
if (Loaded)
|
2013-11-30 03:10:05 +00:00
|
|
|
|
{
|
2014-06-14 21:37:51 +00:00
|
|
|
|
return _log.Count;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
2014-04-06 19:01:00 +00:00
|
|
|
|
|
|
|
|
|
return _preloadFramecount;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-23 18:18:58 +00:00
|
|
|
|
public bool Changes
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2013-10-27 22:13:08 +00:00
|
|
|
|
get { return _changes; }
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Public Log Editing
|
|
|
|
|
|
2014-06-18 02:26:22 +00:00
|
|
|
|
public IController GetInputState(int frame)
|
|
|
|
|
{
|
|
|
|
|
if (frame < FrameCount && frame >= 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
int getframe;
|
|
|
|
|
|
|
|
|
|
if (_loopOffset.HasValue)
|
|
|
|
|
{
|
|
|
|
|
if (frame < _log.Count)
|
|
|
|
|
{
|
|
|
|
|
getframe = frame;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
getframe = ((frame - _loopOffset.Value) % (_log.Count - _loopOffset.Value)) + _loopOffset.Value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
getframe = frame;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-29 03:03:27 +00:00
|
|
|
|
var adapter = new BkmControllerAdapter
|
|
|
|
|
{
|
|
|
|
|
Type = Global.MovieSession.MovieControllerAdapter.Type
|
|
|
|
|
};
|
2014-06-18 02:26:22 +00:00
|
|
|
|
adapter.SetControllersAsMnemonic(_log[getframe]);
|
|
|
|
|
return adapter;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-29 03:03:27 +00:00
|
|
|
|
return null;
|
2014-06-18 02:26:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-25 00:59:34 +00:00
|
|
|
|
public void ClearFrame(int frame)
|
|
|
|
|
{
|
2014-06-14 22:36:32 +00:00
|
|
|
|
var lg = LogGeneratorInstance();
|
2014-06-15 02:23:28 +00:00
|
|
|
|
SetFrameAt(frame, lg.EmptyEntry);
|
2013-10-27 22:13:08 +00:00
|
|
|
|
_changes = true;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-07 16:31:04 +00:00
|
|
|
|
public void AppendFrame(IController source)
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-14 22:36:32 +00:00
|
|
|
|
var lg = LogGeneratorInstance();
|
|
|
|
|
lg.SetSource(source);
|
|
|
|
|
_log.Add(lg.GenerateLogEntry());
|
2013-10-27 22:13:08 +00:00
|
|
|
|
_changes = true;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-03 01:43:02 +00:00
|
|
|
|
public void Truncate(int frame)
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-15 02:23:28 +00:00
|
|
|
|
if (frame < _log.Count)
|
|
|
|
|
{
|
|
|
|
|
_log.RemoveRange(frame, _log.Count - frame);
|
|
|
|
|
_changes = true;
|
|
|
|
|
}
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-07 16:31:04 +00:00
|
|
|
|
public void PokeFrame(int frame, IController source)
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-14 22:36:32 +00:00
|
|
|
|
var lg = LogGeneratorInstance();
|
|
|
|
|
lg.SetSource(source);
|
2013-12-07 16:31:04 +00:00
|
|
|
|
|
2013-10-27 22:13:08 +00:00
|
|
|
|
_changes = true;
|
2014-06-15 02:23:28 +00:00
|
|
|
|
SetFrameAt(frame, lg.GenerateLogEntry());
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-07 16:31:04 +00:00
|
|
|
|
public void RecordFrame(int frame, IController source)
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2013-11-30 02:20:34 +00:00
|
|
|
|
// Note: Truncation here instead of loadstate will make VBA style loadstates
|
|
|
|
|
// (Where an entire movie is loaded then truncated on the next frame
|
|
|
|
|
// this allows users to restore a movie with any savestate from that "timeline"
|
2013-10-25 00:59:34 +00:00
|
|
|
|
if (Global.Config.VBAStyleMovieLoadState)
|
|
|
|
|
{
|
2014-06-14 21:37:51 +00:00
|
|
|
|
if (Global.Emulator.Frame < _log.Count)
|
2013-10-25 00:59:34 +00:00
|
|
|
|
{
|
2014-06-15 02:23:28 +00:00
|
|
|
|
Truncate(Global.Emulator.Frame);
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-11-30 02:20:34 +00:00
|
|
|
|
|
2014-06-14 22:36:32 +00:00
|
|
|
|
var lg = LogGeneratorInstance();
|
|
|
|
|
lg.SetSource(source);
|
2014-06-15 02:23:28 +00:00
|
|
|
|
SetFrameAt(frame, lg.GenerateLogEntry());
|
2013-12-07 16:31:04 +00:00
|
|
|
|
|
2013-10-27 22:13:08 +00:00
|
|
|
|
_changes = true;
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2014-06-15 02:23:28 +00:00
|
|
|
|
private void SetFrameAt(int frameNum, string frame)
|
|
|
|
|
{
|
|
|
|
|
if (_log.Count > frameNum)
|
|
|
|
|
{
|
|
|
|
|
_log[frameNum] = frame;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_log.Add(frame);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-25 00:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|