From d27df7816d7873fe13249a6b61fa4bee74153cbe Mon Sep 17 00:00:00 2001 From: adelikat Date: Sat, 14 Jun 2014 21:09:14 +0000 Subject: [PATCH] Rip out a bunch of stuff from my previous attempt at a mnemonics overhaul and from TasMovie --- .../BooleanControllerMnemonicGenerator.cs | 103 --- .../MnemonicGenerators/IMnemonicGenerator.cs | 40 -- .../MnemonicGenerators/IMnemonicPorts.cs | 44 -- .../MnemonicGeneratorFactory.cs | 23 - .../NesMnemonicGenerator.cs | 225 ------- .../movie/bk2/Bk2Movie.HeaderApi.cs | 2 +- BizHawk.Client.Common/movie/bk2/Bk2Movie.cs | 2 +- .../movie/tasproj/TasMovie.cs | 616 +----------------- 8 files changed, 25 insertions(+), 1030 deletions(-) delete mode 100644 BizHawk.Client.Common/movie/MnemonicGenerators/BooleanControllerMnemonicGenerator.cs delete mode 100644 BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicGenerator.cs delete mode 100644 BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicPorts.cs delete mode 100644 BizHawk.Client.Common/movie/MnemonicGenerators/MnemonicGeneratorFactory.cs delete mode 100644 BizHawk.Client.Common/movie/MnemonicGenerators/NesMnemonicGenerator.cs diff --git a/BizHawk.Client.Common/movie/MnemonicGenerators/BooleanControllerMnemonicGenerator.cs b/BizHawk.Client.Common/movie/MnemonicGenerators/BooleanControllerMnemonicGenerator.cs deleted file mode 100644 index b12033b7f7..0000000000 --- a/BizHawk.Client.Common/movie/MnemonicGenerators/BooleanControllerMnemonicGenerator.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using BizHawk.Common; -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - public class BooleanControllerMnemonicGenerator : IMnemonicGenerator - { - private readonly NamedDictionary _controllerMnemonics; - - public BooleanControllerMnemonicGenerator(string name, IEnumerable> mnemonics) - { - _controllerMnemonics = new NamedDictionary(name); - foreach (var kvp in mnemonics) - { - _controllerMnemonics.Add(kvp.Key, kvp.Value); - } - } - - public bool IsFloat { get { return true; } } - - public void Add(string key, char value) - { - _controllerMnemonics.Add(key, value); - } - - public Dictionary AvailableMnemonics - { - get - { - return _controllerMnemonics.ToDictionary(kvp => ControllerPrefix + " " + kvp.Key, kvp => kvp.Value); - } - } - - public IController Source { get; set; } - public string ControllerPrefix { get; set; } - public string Name - { - get { return _controllerMnemonics.Name; } - } - - public char this[string key] - { - get - { - return _controllerMnemonics[ControllerPrefix + " " + key]; - } - } - - public bool IsEmpty - { - get - { - return _controllerMnemonics.All(kvp => !this.Source.IsPressed(kvp.Key)); - } - } - - public string MnemonicString - { - get - { - var sb = new StringBuilder(_controllerMnemonics.Count); - foreach (var kvp in _controllerMnemonics) - { - sb.Append(Source.IsPressed(kvp.Key) ? kvp.Value : '.'); - } - - return sb.ToString(); - } - } - - public string EmptyMnemonicString - { - get - { - var sb = new StringBuilder(_controllerMnemonics.Count); - foreach (var kvp in _controllerMnemonics) - { - sb.Append('.'); - } - - return sb.ToString(); - } - } - - public IDictionary ParseMnemonicSegment(string mnemonicSegment) - { - var buttons = new Dictionary(); - var keys = _controllerMnemonics.Select(kvp => kvp.Key).ToList(); - - for (var i = 0; i < mnemonicSegment.Length; i++) - { - buttons.Add(keys[i], mnemonicSegment[i] != '.'); - } - - return buttons; - } - } -} diff --git a/BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicGenerator.cs b/BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicGenerator.cs deleted file mode 100644 index 52aa6c461c..0000000000 --- a/BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicGenerator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Generic; -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - public interface IMnemonicGenerator - { - IController Source { get; set; } - - string Name { get; } - - /// - /// Gets or sets the prefix that will be prepended to all button names - /// Example: "P1" would combine with "Up" to make "P1 Up" - /// - string ControllerPrefix { get; set; } - - void Add(string key, char value); - - char this[string key] { get; } - bool IsEmpty { get; } - string MnemonicString { get; } - - bool IsFloat { get; } // Float or Boolean - - /// - /// Gets a string that represents an empty or default mnemonic - /// - string EmptyMnemonicString { get; } - - // Analog TODO: this assumes the Generator is boolean, pass an object structure that contains both the boolean and float dictionaries - /// - /// Parses a segment of a full mnemonic string (the content between pipes) - /// Note: this assume the pipes are not being passed in! - /// - IDictionary ParseMnemonicSegment(string mnemonicSegment); - - Dictionary AvailableMnemonics { get; } - } -} diff --git a/BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicPorts.cs b/BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicPorts.cs deleted file mode 100644 index 1101e39e2c..0000000000 --- a/BizHawk.Client.Common/movie/MnemonicGenerators/IMnemonicPorts.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - /// - /// A console specific collection of Mnemonic generators - /// This handles includes all the "business" logic specific to the console - /// - public interface IMnemonicPorts - { - /// - /// Gets the total number of available controller ports (this does not include the console controls - /// - int Count { get; } - - /// - /// Gets or sets the Source controller to read the input state from - /// - IController Source { get; set; } - - /// - /// Gets or sets the given port with an IMnemonicGenerator implementation - /// Ports are zero based - /// Set will throw an InvalidOperationException if a particular implementation is not allowed, this is platform specific logic such as NES doesn't allow a zapper in port 0, etc - /// Both will throw an ArgumentOutOfRangeException exception if portNum is not less than Count - /// - IMnemonicGenerator this[int portNum] { get; set; } - - /// - /// Gets an IMnemonicGenerator implementation that represents the buttons and controls on the console itself (Reset, Power, etc) - /// - IMnemonicGenerator ConsoleControls { get; } - - Dictionary ParseMnemonicString(string mnemonicStr); - - Dictionary GetBoolButtons(); - Dictionary GetFloatButtons(); - - string EmptyMnemonic { get; } - - Dictionary AvailableMnemonics { get; } - } -} diff --git a/BizHawk.Client.Common/movie/MnemonicGenerators/MnemonicGeneratorFactory.cs b/BizHawk.Client.Common/movie/MnemonicGenerators/MnemonicGeneratorFactory.cs deleted file mode 100644 index 04d4783522..0000000000 --- a/BizHawk.Client.Common/movie/MnemonicGenerators/MnemonicGeneratorFactory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - // Lot's of todos here - public static class MnemonicGeneratorFactory - { - public static IMnemonicPorts Generate() - { - switch (Global.Emulator.SystemId) - { - default: - case "NES": - return new NesMnemonicGenerator(Global.MovieOutputHardpoint, false, false); - } - } - } -} diff --git a/BizHawk.Client.Common/movie/MnemonicGenerators/NesMnemonicGenerator.cs b/BizHawk.Client.Common/movie/MnemonicGenerators/NesMnemonicGenerator.cs deleted file mode 100644 index 3801662705..0000000000 --- a/BizHawk.Client.Common/movie/MnemonicGenerators/NesMnemonicGenerator.cs +++ /dev/null @@ -1,225 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - public class NesMnemonicGenerator : IMnemonicPorts - { - private bool _isFds; - private bool _isFourscore; - - public NesMnemonicGenerator(IController source, bool fds = false, bool isFourscore = false) - { - Source = source; - _isFds = fds; - _isFourscore = isFourscore; - - _nesConsoleControls.Source = source; - _fdsConsoleControls.Source = source; - _controllerPorts.ForEach(x => x.Source = source); - } - - public bool FourScoreEnabled - { - get { return _isFourscore; } - set { _isFourscore = value; } - } - - public bool IsFDS - { - get { return _isFds; } - set { _isFds = value; } - } - - #region IMnemonicPorts Implementation - - public string EmptyMnemonic - { - get - { - var blah = AvailableGenerators.Select(x => x.EmptyMnemonicString); - return "|" + string.Join("|", blah) + "|"; - } - } - - public int Count - { - get { return _isFourscore ? 4 : 2; } - } - - public IController Source { get; set; } - - // This is probably not necessary, but let's see how things go - public IEnumerable AvailableGenerators - { - get - { - yield return ConsoleControls; - - for (var i = 0; i < Count; i++) - { - yield return _controllerPorts[i]; - } - } - } - - public IMnemonicGenerator ConsoleControls - { - get { return _isFds ? _fdsConsoleControls : _nesConsoleControls; } - } - - public IMnemonicGenerator this[int portNum] - { - get - { - if (portNum < Count) - { - return _controllerPorts[portNum]; - } - else - { - throw new ArgumentOutOfRangeException("portNum"); - } - } - - set - { - if (portNum < Count) - { - // Eventually this will support zappers and FDS controllers, Arkanoid paddle, etc - if (value is BooleanControllerMnemonicGenerator) - { - _controllerPorts[portNum] = value; - } - else - { - throw new InvalidOperationException("Invalid Mnemonic Generator for the given port"); - } - } - else - { - throw new ArgumentOutOfRangeException("portNum"); - } - } - } - - #region TODO: nothing specific to this object here, this could be done in a base class - - public Dictionary ParseMnemonicString(string mnemonicStr) - { - var segments = mnemonicStr.Split('|'); - var kvps = new List>(); - var generators = AvailableGenerators.ToList(); - for (var i = 0; i < mnemonicStr.Length; i++) - { - kvps.AddRange(generators[i].ParseMnemonicSegment(segments[i])); - } - - return kvps.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - } - - public Dictionary GetBoolButtons() - { - return AvailableGenerators - .Where(g => g.IsFloat) - .SelectMany(mc => mc.AvailableMnemonics) - .ToDictionary(kvp => kvp.Key, kvp => Source.IsPressed(kvp.Key)); - } - - public Dictionary GetFloatButtons() - { - return AvailableGenerators - .Where(g => !g.IsFloat) - .SelectMany(mc => mc.AvailableMnemonics) - .ToDictionary(kvp => kvp.Key, kvp => Source.GetFloat(kvp.Key)); - } - - // TODO: refactor me! - public Dictionary AvailableMnemonics - { - get - { - var dictionary = new Dictionary(); - foreach (var generator in AvailableGenerators) - { - foreach (var mnemonic in generator.AvailableMnemonics) - { - dictionary.Add(mnemonic.Key, mnemonic.Value); - } - } - - return dictionary; - } - } - #endregion - - #endregion - - #region Privates - - private static readonly Dictionary _basicController = new Dictionary - { - { "Up", 'U' }, - { "Down", 'D' }, - { "Left", 'L' }, - { "Right", 'R' }, - { "Select", 's' }, - { "Start", 'S' }, - { "B", 'B' }, - { "A", 'A' } - }; - - private readonly BooleanControllerMnemonicGenerator _nesConsoleControls = new BooleanControllerMnemonicGenerator( - "Console", - new Dictionary - { - { "Reset", 'r' }, - { "Power", 'P' }, - } - ) - { - ControllerPrefix = string.Empty - }; - - private readonly BooleanControllerMnemonicGenerator _fdsConsoleControls = new BooleanControllerMnemonicGenerator( - "Console", - new Dictionary - { - { "Reset", 'r' }, - { "Power", 'P' }, - { "FDS Eject", 'E' }, - { "FDS Insert 0", '0' }, - { "FDS Insert 1", '1' }, - } - ) - { - ControllerPrefix = string.Empty - }; - - private readonly List _controllerPorts = - new List - { - new BooleanControllerMnemonicGenerator("Player 1", _basicController) - { - ControllerPrefix = "P1" - }, - new BooleanControllerMnemonicGenerator("Player 2", _basicController) - { - ControllerPrefix = "P2" - }, - new BooleanControllerMnemonicGenerator("Player 3", _basicController) - { - ControllerPrefix = "P3" - }, - new BooleanControllerMnemonicGenerator("Player 4", _basicController) - { - ControllerPrefix = "P4" - } - }; - - #endregion - } -} diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs index 53c556a868..1337251b3f 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs @@ -7,7 +7,7 @@ namespace BizHawk.Client.Common { public partial class Bk2Movie : IMovie { - private readonly Bk2Header Header = new Bk2Header(); + protected readonly Bk2Header Header = new Bk2Header(); private string _syncSettingsJson = string.Empty; private string _savestateBlob = string.Empty; diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs index 30f925fe10..4a990ff495 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs @@ -36,7 +36,7 @@ namespace BizHawk.Client.Common public string Filename { get; set; } - public string PreferredExtension { get { return "bk2"; } } + public virtual string PreferredExtension { get { return "bk2"; } } public bool Changes { get; private set; } public bool IsCountingRerecords { get; set; } diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs index 7dc1db6f06..0428dd793d 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs @@ -9,625 +9,55 @@ using BizHawk.Emulation.Common; namespace BizHawk.Client.Common { - public class TasMovie : IMovie + public class TasMovie : Bk2Movie { - // TODO: pass source into - // TODO: preloading, or benchmark and see how much of a performaance gain it really is - // TODO: support loop Offset - // TODO: consider the fileformat of binary and lagged data - private readonly IMnemonicPorts _mg; - private readonly IController _source = Global.MovieOutputHardpoint; - - public MovieRecord this[int index] + public TasMovie(string path) + : base(path) { - get { return _records[index]; } - } - public List ActivePlayers { get; set; } - - public Dictionary AvailableMnemonics - { - get - { - return _mg.AvailableMnemonics; - } - } - - public string PreferredExtension { get { return Extension; } } - - public const string Extension = "tasproj"; - - public void ToggleButton(int frame, string buttonName) - { - InvalidateGreenzone(frame); - /*Serialize todo - _records[frame].SetButton(buttonName, !_records[frame].Buttons[buttonName]); - */ - - } - - public void SetButton(int frame, string buttonName, bool value) - { - InvalidateGreenzone(frame); - /*Serialize TODO - _records[frame].SetButton(buttonName, value); - */ - } - - public bool IsPressed(int frame, string buttonName) - { - return true; //Serialize TODO - _records[frame].Buttons[buttonName]; - } - - /// - /// Removes the greenzone content after the given frame - /// - /// - private void InvalidateGreenzone(int frame) - { - for (int i = frame + 1; i < _records.Count; i++) - { - _records[i].ClearState(); - } - } - - #region IMovie Implementation - - public TasMovie(string filename) - : this() - { - Filename = filename; } public TasMovie() + : base() { - _mg = MnemonicGeneratorFactory.Generate(); - Filename = string.Empty; - Header = new BkmHeader(); - Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0"; - _records = new MovieRecordList(); - _mode = Moviemode.Inactive; - IsCountingRerecords = true; + Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0 Tasproj v1.0"; } - public SubtitleList Subtitles - { - get { return Header.Subtitles; } - } - - public IList Comments - { - get { return Header.Comments; } - } - - public string SyncSettingsJson + public override string PreferredExtension { get { - return Header[HeaderKeys.SYNCSETTINGS]; - } - - set - { - Header[HeaderKeys.SYNCSETTINGS] = value; + return Extension; } } - public string SavestateBinaryBase64Blob + public const string Extension = "tasproj"; + + public MovieRecord this[int index] { get { - return Header.SavestateBinaryBase64Blob; + // TODO + return new MovieRecord("", false); } + } - set - { - Header.SavestateBinaryBase64Blob = value; - } - } + public void SetBoolButton(int index, string button, bool value) + { + // TODO + } - public ulong Rerecords + public Dictionary ColumnNames { get { - return Header.Rerecords; - } - - set - { - Header.Rerecords = value; - } - } - - public bool StartsFromSavestate - { - get - { - return Header.StartsFromSavestate; - } - - set - { - Header.StartsFromSavestate = value; - } - } - - public string GameName - { - get - { - return Header.GameName; - } - - set - { - Header.GameName = value; - } - } - - public string SystemID - { - get - { - return Header.SystemID; - } - - set - { - Header.SystemID = value; - } - } - - public string Hash - { - get - { - return Header[HeaderKeys.SHA1]; - } - - set - { - Header[HeaderKeys.SHA1] = value; - } - } - - public string Author - { - get - { - return Header[HeaderKeys.AUTHOR]; - } - - set - { - Header[HeaderKeys.AUTHOR] = value; - } - } - - public string Core - { - get - { - return Header[HeaderKeys.CORE]; - } - - set - { - Header[HeaderKeys.CORE] = value; - } - } - - public string Platform - { - get - { - return Header[HeaderKeys.PLATFORM]; - } - - set - { - Header[HeaderKeys.PLATFORM] = value; - } - } - - public string FirmwareHash - { - get - { - return Header[HeaderKeys.FIRMWARESHA1]; - } - - set - { - Header[HeaderKeys.FIRMWARESHA1] = value; - } - } - - public string EmulatorVersion - { - get - { - return Header[HeaderKeys.EMULATIONVERSION]; - } - - set - { - Header[HeaderKeys.EMULATIONVERSION] = value; - } - } - - public string BoardName - { - get - { - return Header[HeaderKeys.BOARDNAME]; - } - - set - { - Header[HeaderKeys.BOARDNAME] = value; - } - } - - public bool PreLoadHeaderAndLength(HawkFile hawkFile) - { - throw new NotImplementedException(); - } - - public IDictionary HeaderEntries - { - get - { - return Header; - } - } - - public void SaveBackup() - { - throw new NotImplementedException(); - } - - public string Filename { get; set; } - - public BkmHeader Header { get; private set; } - - public bool IsActive - { - get { return _mode != Moviemode.Inactive; } - } - - public bool IsPlaying - { - get { return _mode == Moviemode.Play; } - } - - public bool IsRecording - { - get { return _mode == Moviemode.Record; } - } - - public bool IsFinished - { - get { return false; } //a TasMovie is never in this mode. - } - - public bool IsCountingRerecords { get; set; } - - public bool Changes { get; set; } - - public TimeSpan Time - { - get - { - double dblseconds = GetSeconds(_records.Count); - int seconds = (int)(dblseconds % 60); - int days = seconds / 86400; - int hours = seconds / 3600; - int minutes = (seconds / 60) % 60; - int milliseconds = (int)((dblseconds - seconds) * 1000); - return new TimeSpan(days, hours, minutes, seconds, milliseconds); - } - } - - public double FrameCount - { - get { return _records.Count; } - } - - public int InputLogLength - { - get { return _records.Count; } - } - - public string GetInput(int frame) - { - if (frame < _records.Count) - { - if (frame >= 0) + // TODO + return new Dictionary() { - if (!_records[frame].HasState) - { - _records[frame].CaptureSate(); - } - - return string.Empty; //Serialize TODO _mg.GenerateMnemonicString(_records[frame].Buttons); - } - else - { - return string.Empty; - } - } - else - { - _mode = Moviemode.Record; - - /* Serialize TODO - var buttons = _mg.ParseMnemonicString(_mg.EmptyMnemonic); - _records.Add(new MovieRecord(buttons, true)); - */ - - return string.Empty; + { "A", "A" }, + { "B", "B" } + }; } } - - public string GetInputLog() - { - StringBuilder sb = new StringBuilder(); - foreach (var record in _records) - { - sb.AppendLine(record.SerializedInput); - } - - return sb.ToString(); - } - - public void SwitchToRecord() - { - _mode = Moviemode.Record; - } - - public void SwitchToPlay() - { - _mode = Moviemode.Play; - } - - public void StartNewPlayback() - { - _mode = Moviemode.Play; - Global.Emulator.ClearSaveRam(); // should this exist?? - } - - public void Stop(bool saveChanges = true) - { - // adelikat: I think Tastudio should be in charge of saving, and so we should not attempt to manage any logic like that here - // EmuHawk client UI assumes someone has already picked a filename ahead of time and that it is in charge of movies - _mode = Moviemode.Inactive; - } - - public void Truncate(int frame) - { - _records.Truncate(frame); - } - - public void ClearFrame(int frame) - { - if (frame < _records.Count) - { - Changes = true; - _records[frame].ClearInput(); - } - } - - public void AppendFrame(IController source) - { - Changes = true; - /* Serialize TODO - _mg.Source = source; - var record = new MovieRecord(_mg.GetBoolButtons(), true); - _records.Add(record); - */ - } - - public void RecordFrame(int frame, IController source) - { - if (_mode == Moviemode.Record) - { - Changes = true; - if (Global.Config.VBAStyleMovieLoadState) - { - if (Global.Emulator.Frame < _records.Count) - { - _records.Truncate(Global.Emulator.Frame); - } - } - - if (frame < _records.Count) - { - PokeFrame(frame, source); - } - else - { - AppendFrame(source); - } - } - } - - public void PokeFrame(int frame, IController source) - { - InvalidateGreenzone(frame); - if (frame < _records.Count) - { - Changes = true; - _mg.Source = source; - /* Serialize TODO - _records[frame].SetInput(_mg.GetBoolButtons()); - */ - } - } - - public double Fps - { - get - { - var system = Header[HeaderKeys.PLATFORM]; - var pal = Header.ContainsKey(HeaderKeys.PAL) && - Header[HeaderKeys.PAL] == "1"; - - return _frameRates[system, pal]; - } - } - - public void StartNewRecording() - { - SwitchToRecord(); - - // TODO: MakeBackup logic - Tastudio logic should be to always make backups before saving! - - if (Changes && !String.IsNullOrWhiteSpace(Filename)) - { - Save(); - } - - _records.Clear(); - Header.Clear(); - } - - public bool Load() - { - var file = new FileInfo(Filename); - if (!file.Exists) - { - return false; - } - // there's a lot of common code here with SavestateManager. refactor? - using (BinaryStateLoader bl = BinaryStateLoader.LoadAndDetect(Filename)) - { - if (bl == null) - return false; - - Header.Clear(); - _records.Clear(); - - bl.GetLump(BinaryStateLump.Movieheader, true, - delegate(TextReader tr) - { - string line; - while ((line = tr.ReadLine()) != null) - if (!Header.ParseLineFromFile(line)) - Header.Comments.Add(line); - }); - bl.GetLump(BinaryStateLump.Input, true, - delegate(TextReader tr) - { - string line = string.Empty; - while (true) - { - line = tr.ReadLine(); - if (line == null) - { - break; - } - else if (line.StartsWith("|")) - { - /* Serialize TODO - var parsedButtons = _mg.ParseMnemonicString(line); - _records.Add(new MovieRecord(parsedButtons, captureState: false)); - */ - } - } - }); - - if (StartsFromSavestate) - { - // should we raise some sort of error if there's a savestate in the archive but Header.StartsFromSavestate is false? - bl.GetCoreState( - delegate(Stream s) - { - BinaryReader br = new BinaryReader(s); - Global.Emulator.LoadStateBinary(br); - }, - delegate(Stream s) - { - StreamReader sr = new StreamReader(s); - Global.Emulator.LoadStateText(sr); - }); - } - bl.GetLump(BinaryStateLump.Framebuffer, false, - delegate(BinaryReader br) - { - int i; - var buff = Global.Emulator.VideoProvider.GetVideoBuffer(); - try - { - for (i = 0; i < buff.Length; i++) - { - int j = br.ReadInt32(); - buff[i] = j; - } - } - catch (EndOfStreamException) { } - }); - } - - _mode = Moviemode.Play; - return true; - } - - public void Save() - { - // there's a lot of common code here with SavestateManager. refactor? - - using (FileStream fs = new FileStream(Filename, FileMode.Create, FileAccess.Write)) - using (BinaryStateSaver bs = new BinaryStateSaver(fs)) - { - bs.PutLump(BinaryStateLump.Movieheader, (tw) => tw.WriteLine(Header.ToString())); - bs.PutLump(BinaryStateLump.Input, (tw) => tw.WriteLine(GetInputLog())); - if (StartsFromSavestate) - { -#if true - bs.PutLump(BinaryStateLump.CorestateText, (tw) => Global.Emulator.SaveStateText(tw)); -#else - bs.PutLump(BinaryStateLump.Corestate, (bw) => Global.Emulator.SaveStateBinary(bw)); -#endif - } - } - Changes = false; - } - - public bool CheckTimeLines(TextReader reader, out string errorMessage) - { - throw new NotImplementedException(); - } - - public bool ExtractInputLog(TextReader reader, out string errorMessage) - { - throw new NotImplementedException(); - } - - #endregion - - #region Private - - private enum Moviemode { Inactive, Play, Record, Finished } - private readonly MovieRecordList _records; - private Moviemode _mode; - private readonly PlatformFrameRates _frameRates = new PlatformFrameRates(); - - private double GetSeconds(int frameCount) - { - double frames = frameCount; - - if (frames < 1) - { - return 0; - } - - var system = Header[HeaderKeys.PLATFORM]; - var pal = Header.ContainsKey(HeaderKeys.PAL) && Header[HeaderKeys.PAL] == "1"; - - return frames / _frameRates[system, pal]; - } - - #endregion } }