Example #1
0
 public TasMovieRecord this[int index] => new TasMovieRecord
 {
     HasState  = TasStateManager.HasState(index),
     LogEntry  = GetInputLogEntry(index),
     Lagged    = TasLagLog[index + 1],
     WasLagged = TasLagLog.History(index + 1)
 };
Example #2
0
        public TasLagLog Clone()
        {
            var log = new TasLagLog();

            log.LagLog = LagLog.ToList();
            log.WasLag = WasLag.ToList();

            return(log);
        }
Example #3
0
        /// <summary>
        /// Removes lag log and greenzone after this frame
        /// </summary>
        /// <param name="frame">The last frame that can be valid.</param>
        private void InvalidateAfter(int frame)
        {
            var anyInvalidated = TasLagLog.RemoveFrom(frame);

            TasStateManager.Invalidate(frame + 1);
            Changes         = anyInvalidated;
            LastEditedFrame = frame;

            if (anyInvalidated && Global.MovieSession.Movie.IsCountingRerecords)
            {
                Rerecords++;
            }
        }
        public override void RecordFrame(int frame, IController source)
        {
            if (frame != 0)
            {
                ChangeLog.AddGeneralUndo(frame - 1, frame - 1, $"Record Frame: {frame}");
            }

            base.RecordFrame(frame, source);

            TasLagLog.RemoveFrom(frame);
            TasLagLog[frame] = Global.Emulator.AsInputPollable().IsLagFrame;

            if (this.IsRecording())
            {
                TasStateManager.Invalidate(frame + 1);
            }

            if (frame != 0)
            {
                ChangeLog.SetGeneralRedo();
            }
        }
        public override void Truncate(int frame)
        {
            bool endBatch = ChangeLog.BeginNewBatch($"Truncate Movie: {frame}", true);

            ChangeLog.AddGeneralUndo(frame, InputLogLength - 1);

            if (frame < Log.Count - 1)
            {
                Changes = true;
            }

            base.Truncate(frame);

            TasLagLog.RemoveFrom(frame);
            TasStateManager.Invalidate(frame);
            Markers.TruncateAt(frame);

            ChangeLog.SetGeneralRedo();
            if (endBatch)
            {
                ChangeLog.EndBatch();
            }
        }
Example #6
0
        // TODO: this is 99% copy pasting of bad code
        public override bool ExtractInputLog(TextReader reader, out string errorMessage)
        {
            errorMessage = "";
            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.Count != 0)
                {
                    SaveBackup();
                    MakeBackup = false;
                }

                int counter = 0;
                while (true)
                {
                    var line = reader.ReadLine();
                    if (string.IsNullOrEmpty(line))
                    {
                        break;
                    }

                    if (line.Contains("Frame 0x"))                     // NES stores frame count in hex, yay
                    {
                        var split = line.Split('x');
                        try
                        {
                            stateFrame = int.Parse(split[1], NumberStyles.HexNumber);
                        }
                        catch
                        {
                            errorMessage = "Savestate Frame number failed to parse";
                            return(false);
                        }
                    }
                    else if (line.Contains("Frame "))
                    {
                        var split = line.Split(' ');
                        try
                        {
                            stateFrame = int.Parse(split[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 && counter < Log.Count && 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("|"))
                    {
                        SetFrame(i, line);
                        i++;
                    }
                }
            }

            if (!stateFrame.HasValue)
            {
                errorMessage = "Savestate Frame number failed to parse";
            }

            var stateFrameValue = stateFrame ?? 0;

            if (stateFrameValue > 0 && stateFrameValue < Log.Count)
            {
                if (!Global.Config.VBAStyleMovieLoadState)
                {
                    Truncate(stateFrameValue);
                }
            }
            else if (stateFrameValue > Log.Count)             // Post movie savestate
            {
                if (!Global.Config.VBAStyleMovieLoadState)
                {
                    Truncate(Log.Count);
                }

                Mode = MovieMode.Finished;
            }

            if (IsCountingRerecords)
            {
                Rerecords++;
            }

            if (_timelineBranchFrame.HasValue)
            {
                TasLagLog.RemoveFrom(_timelineBranchFrame.Value);
                TasStateManager.Invalidate(_timelineBranchFrame.Value);
            }

            return(true);
        }
Example #7
0
 public void ClearLagLog()
 {
     TasLagLog.Clear();
 }
Example #8
0
 public void FromLagLog(TasLagLog log)
 {
     _lagLog = log._lagLog.ToList();
     _wasLag = log._wasLag.ToList();
 }
Example #9
0
 public void FromLagLog(TasLagLog log)
 {
     _lagLog = log._lagLog.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
     _wasLag = log._wasLag.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
 }
Example #10
0
 public void FromLagLog(TasLagLog log)
 {
     LagLog = log.LagLog.ToList();
     WasLag = log.WasLag.ToList();
 }
Example #11
0
		public void FromLagLog(TasLagLog log)
		{
			LagLog = log.LagLog.ToList();
			WasLag = log.WasLag.ToList();
		}
Example #12
0
		public TasLagLog Clone()
		{
			var log = new TasLagLog();
			log.LagLog = LagLog.ToList();
			log.WasLag = WasLag.ToList();

			return log;
		}
Example #13
0
        public override bool Load(bool preload)
        {
            var file = new FileInfo(Filename);

            if (!file.Exists)
            {
                return(false);
            }

            using (var bl = BinaryStateLoader.LoadAndDetect(Filename, true))
            {
                if (bl == null)
                {
                    return(false);
                }

                ClearBeforeLoad();
                ClearTasprojExtras();

                bl.GetLump(BinaryStateLump.Movieheader, true, delegate(TextReader tr)
                {
                    string line;
                    while ((line = tr.ReadLine()) != null)
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            var pair = line.Split(new[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);

                            if (pair.Length > 1)
                            {
                                Header.Add(pair[0], pair[1]);
                            }
                        }
                    }
                });

                bl.GetLump(BinaryStateLump.Comments, true, delegate(TextReader tr)
                {
                    string line;
                    while ((line = tr.ReadLine()) != null)
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            Comments.Add(line);
                        }
                    }
                });

                bl.GetLump(BinaryStateLump.Subtitles, true, delegate(TextReader tr)
                {
                    string line;
                    while ((line = tr.ReadLine()) != null)
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            Subtitles.AddFromString(line);
                        }
                    }
                });

                bl.GetLump(BinaryStateLump.SyncSettings, true, delegate(TextReader tr)
                {
                    string line;
                    while ((line = tr.ReadLine()) != null)
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            SyncSettingsJson = line;
                        }
                    }
                });

                bl.GetLump(BinaryStateLump.Input, true, delegate(TextReader tr)                 // Note: ExtractInputLog will clear Lag and State data potentially, this must come before loading those
                {
                    IsCountingRerecords = false;
                    ExtractInputLog(tr, out _);
                    IsCountingRerecords = true;
                });

                if (StartsFromSavestate)
                {
                    bl.GetCoreState(
                        delegate(BinaryReader br, long length)
                    {
                        BinarySavestate = br.ReadBytes((int)length);
                    },
                        delegate(TextReader tr)
                    {
                        TextSavestate = tr.ReadToEnd();
                    });
                }
                else if (StartsFromSaveRam)
                {
                    bl.GetLump(BinaryStateLump.MovieSaveRam, false,
                               delegate(BinaryReader br, long length)
                    {
                        SaveRam = br.ReadBytes((int)length);
                    });
                }

                // TasMovie enhanced information
                bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr)
                {
                    TasLagLog.Load(tr);
                });

                bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr)
                {
                    var json = tr.ReadToEnd();
                    try
                    {
                        TasStateManager.Settings = JsonConvert.DeserializeObject <TasStateManagerSettings>(json);
                    }
                    catch
                    {
                        // Do nothing, and use default settings instead
                    }
                });

                bl.GetLump(BinaryStateLump.Markers, false, delegate(TextReader tr)
                {
                    string line;
                    while ((line = tr.ReadLine()) != null)
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            Markers.Add(new TasMovieMarker(line));
                        }
                    }
                });

                if (GetClientSettingsOnLoad != null)
                {
                    string clientSettings = "";
                    bl.GetLump(BinaryStateLump.ClientSettings, false, delegate(TextReader tr)
                    {
                        string line;
                        while ((line = tr.ReadLine()) != null)
                        {
                            if (!string.IsNullOrWhiteSpace(line))
                            {
                                clientSettings = line;
                            }
                        }
                    });

                    if (!string.IsNullOrWhiteSpace(clientSettings))
                    {
                        GetClientSettingsOnLoad(clientSettings);
                    }
                }

                bl.GetLump(BinaryStateLump.VerificationLog, false, delegate(TextReader tr)
                {
                    VerificationLog.Clear();
                    while (true)
                    {
                        var line = tr.ReadLine();
                        if (string.IsNullOrEmpty(line))
                        {
                            break;
                        }

                        if (line.StartsWith("|"))
                        {
                            VerificationLog.Add(line);
                        }
                    }
                });

                Branches.Load(bl, this);

                bl.GetLump(BinaryStateLump.Session, false, delegate(TextReader tr)
                {
                    var json = tr.ReadToEnd();
                    try
                    {
                        Session = JsonConvert.DeserializeObject <TasSession>(json);
                    }
                    catch
                    {
                        // Do nothing, and use default settings instead
                    }
                });

                if (!preload)
                {
                    if (TasStateManager.Settings.SaveStateHistory)
                    {
                        bl.GetLump(BinaryStateLump.StateHistory, false, delegate(BinaryReader br, long length)
                        {
                            TasStateManager.Load(br);
                        });
                    }

                    // Movie should always have a state at frame 0.
                    if (!StartsFromSavestate && Global.Emulator.Frame == 0)
                    {
                        TasStateManager.Capture();
                    }
                }
            }

            Changes = false;
            return(true);
        }
Example #14
0
        protected override void Write(string fn, bool backup = false)
        {
            var file = new FileInfo(fn);

            if (file.Directory != null && !file.Directory.Exists)
            {
                Directory.CreateDirectory(file.Directory.ToString());
            }

            using (var bs = new BinaryStateSaver(fn, false))
            {
                bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
                bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
                bs.PutLump(BinaryStateLump.Subtitles, tw => tw.WriteLine(Subtitles.ToString()));
                bs.PutLump(BinaryStateLump.SyncSettings, tw => tw.WriteLine(SyncSettingsJson));
                bs.PutLump(BinaryStateLump.Input, WriteInputLog);

                // TasProj extras
                var settings = JsonConvert.SerializeObject(TasStateManager.Settings);
                bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(settings));

                bs.PutLump(BinaryStateLump.LagLog, tw => TasLagLog.Save(tw));
                bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString()));

                if (StartsFromSavestate)
                {
                    if (TextSavestate != null)
                    {
                        bs.PutLump(BinaryStateLump.CorestateText, (TextWriter tw) => tw.Write(TextSavestate));
                    }
                    else
                    {
                        bs.PutLump(BinaryStateLump.Corestate, (BinaryWriter bw) => bw.Write(BinarySavestate));
                    }
                }
                else if (StartsFromSaveRam)
                {
                    bs.PutLump(BinaryStateLump.MovieSaveRam, (BinaryWriter bw) => bw.Write(SaveRam));
                }

                if (ClientSettingsForSave != null)
                {
                    var clientSettingsJson = ClientSettingsForSave();
                    bs.PutLump(BinaryStateLump.ClientSettings, (TextWriter tw) => tw.Write(clientSettingsJson));
                }

                if (VerificationLog.Any())
                {
                    bs.PutLump(BinaryStateLump.VerificationLog, tw => tw.WriteLine(InputLogToString(VerificationLog)));
                }

                if (Branches.Any())
                {
                    Branches.Save(bs);
                }

                bs.PutLump(BinaryStateLump.Session, tw => tw.WriteLine(JsonConvert.SerializeObject(Session)));

                if (TasStateManager.Settings.SaveStateHistory && !backup)
                {
                    bs.PutLump(BinaryStateLump.StateHistory, bw => TasStateManager.Save(bw));
                }
            }

            if (!backup)
            {
                Changes = false;
            }
        }
 public void InsertLagHistory(int frame, bool isLag)
 {
     TasLagLog.InsertHistoryAt(frame, isLag);
 }
 public void RemoveLagHistory(int frame)
 {
     TasLagLog.RemoveHistoryAt(frame);
 }