private void AddTasProjLumps(ZipStateSaver bs, bool isBackup = false) { var settings = JsonConvert.SerializeObject(TasStateManager.Settings); bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(settings)); bs.PutLump(BinaryStateLump.LagLog, tw => LagLog.Save(tw)); bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString())); 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(VerificationLog.ToInputLog())); } if (Branches.Any()) { Branches.Save(bs); } bs.PutLump(BinaryStateLump.Session, tw => tw.WriteLine(JsonConvert.SerializeObject(TasSession))); if (TasStateManager.Settings.SaveStateHistory && !isBackup) { bs.PutLump(BinaryStateLump.StateHistory, bw => TasStateManager.Save(bw)); } }
public override void RecordFrame(int frame, IController source) { // RetroEdit: This check is questionable; recording at frame 0 is valid and should be reversible. // Also, frame - 1, why? // Is the precondition compensating for frame - 1 reindexing? if (frame != 0) { ChangeLog.AddGeneralUndo(frame - 1, frame - 1, $"Record Frame: {frame}"); } var lg = LogGeneratorInstance(source); SetFrameAt(frame, lg.GenerateLogEntry()); Changes = true; LagLog.RemoveFrom(frame); LagLog[frame] = _inputPollable.IsLagFrame; if (this.IsRecording()) { TasStateManager.InvalidateAfter(frame); GreenzoneInvalidated(frame + 1); } if (frame != 0) { ChangeLog.SetGeneralRedo(); } }
public void UpdateBranch(TasBranch old, TasBranch newBranch) { int index = Branches.IndexOf(old); Branches[index] = newBranch; TasStateManager.UpdateBranch(index); }
public override void RecordFrame(int frame, IController source) { if (frame != 0) { ChangeLog.AddGeneralUndo(frame - 1, frame - 1, $"Record Frame: {frame}"); } var lg = LogGeneratorInstance(source); SetFrameAt(frame, lg.GenerateLogEntry()); Changes = true; LagLog.RemoveFrom(frame); LagLog[frame] = _inputPollable.IsLagFrame; if (this.IsRecording()) { TasStateManager.Invalidate(frame + 1); } if (frame != 0) { ChangeLog.SetGeneralRedo(); } }
private void ClearTasprojExtras() { LagLog.Clear(); TasStateManager.Clear(); Markers.Clear(); ChangeLog.Clear(); }
public override void Attach(IEmulator emulator) { if (!emulator.HasSavestates()) { throw new InvalidOperationException($"A core must be able to provide an {nameof(IStatable)} service"); } if (!emulator.CanPollInput()) { throw new InvalidOperationException($"A core must be able to provide an {nameof(IInputPollable)} service"); } _inputPollable = emulator.AsInputPollable(); if (StartsFromSavestate) { TasStateManager.Engage(BinarySavestate); } else { var ms = new MemoryStream(); emulator.AsStatable().SaveStateBinary(new BinaryWriter(ms)); TasStateManager.Engage(ms.ToArray()); } base.Attach(emulator); foreach (var button in emulator.ControllerDefinition.BoolButtons) { _mnemonicCache[button] = Bk2MnemonicLookup.Lookup(button, emulator.SystemId); } }
public static StateManagerState Read(BinaryReader r, TasStateManager m) { int frame = r.ReadInt32(); byte[] data = r.ReadBytes(r.ReadInt32()); return(new StateManagerState(m, data, frame)); }
public TasMovie() : base() { StateManager = new TasStateManager(this); Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.Add(0, StartsFromSavestate ? "Savestate" : "Power on"); }
public TasMovie() : base() { StateManager = new TasStateManager(this); Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.Add(0, StartsFromSavestate ? "Savestate" : "Power on"); }
public void UpdateBranch(TasBranch old, TasBranch newBranch) { int index = Branches.IndexOf(old); newBranch.UniqueIdentifier = old.UniqueIdentifier; Branches[index] = newBranch; TasStateManager.UpdateBranch(index); Changes = true; }
public tsmState(TasStateManager manager, byte[] state, int frame) { _manager = manager; _state = state; Frame = frame; if (state_id > long.MaxValue - 100) throw new InvalidOperationException(); ID = System.Threading.Interlocked.Increment(ref state_id); }
/// <exception cref="InvalidOperationException">loaded core does not implement <see cref="IStatable"/></exception> internal TasMovie(string path, bool startsFromSavestate) : base(path) { Branches = new TasBranchCollection(this); ChangeLog = new TasMovieChangeLog(this); TasStateManager = new TasStateManager(this, Global.Config.DefaultTasStateManagerSettings); Header[HeaderKeys.MovieVersion] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.CollectionChanged += Markers_CollectionChanged; Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); }
/// <exception cref="InvalidOperationException">loaded core does not implement <see cref="IStatable"/></exception> internal TasMovie(IMovieSession session, string path) : base(session, path) { Branches = new TasBranchCollection(this); ChangeLog = new TasMovieChangeLog(this); TasStateManager = new TasStateManager(this, session.Settings.DefaultTasStateManagerSettings); Header[HeaderKeys.MovieVersion] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.CollectionChanged += Markers_CollectionChanged; Markers.Add(0, "Power on"); }
public tsmState(TasStateManager manager, byte[] state, int frame) { _manager = manager; _state = state; Frame = frame; if (state_id > long.MaxValue - 100) { throw new InvalidOperationException(); } ID = System.Threading.Interlocked.Increment(ref state_id); }
/// <exception cref="InvalidOperationException">loaded core does not implement <see cref="IStatable"/></exception> public TasMovie(string path = null, bool startsFromSavestate = false) : base(path) { if (!Global.Emulator.HasSavestates()) { throw new InvalidOperationException($"Cannot create a {nameof(TasMovie)} against a core that does not implement {nameof(IStatable)}"); } Branches = new TasBranchCollection(this); ChangeLog = new TasMovieChangeLog(this); TasStateManager = new TasStateManager(this, Global.Config.DefaultTasStateManagerSettings); Header[HeaderKeys.MovieVersion] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.CollectionChanged += Markers_CollectionChanged; Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); }
public override void Attach(IEmulator emulator) { if (!emulator.HasSavestates()) { throw new InvalidOperationException($"A core must be able to provide an {nameof(IStatable)} service"); } if (!emulator.CanPollInput()) { throw new InvalidOperationException($"A core must be able to provide an {nameof(IInputPollable)} service"); } _inputPollable = emulator.AsInputPollable(); TasStateManager.Attach(emulator); base.Attach(emulator); }
public TasMovie(bool startsFromSavestate = false, BackgroundWorker progressReportWorker = null) { _progressReportWorker = progressReportWorker; if (!Global.Emulator.HasSavestates()) { throw new InvalidOperationException($"Cannot create a {nameof(TasMovie)} against a core that does not implement {nameof(IStatable)}"); } ChangeLog = new TasMovieChangeLog(this); _stateManager = new TasStateManager(this); Session = new TasSession(this); Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.CollectionChanged += Markers_CollectionChanged; Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); BindMarkersToInput = false; CurrentBranch = -1; }
public TasMovie(bool startsFromSavestate = false, BackgroundWorker progressReportWorker = null) : base() { _progressReportWorker = progressReportWorker; if (!Global.Emulator.HasSavestates()) { throw new InvalidOperationException("Cannot create a TasMovie against a core that does not implement IStatable"); } ChangeLog = new TasMovieChangeLog(this); StateManager = new TasStateManager(this); Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.CollectionChanged += Markers_CollectionChanged; Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); BindMarkersToInput = true; }
public TasMovie(string path, bool startsFromSavestate = false, BackgroundWorker progressReportWorker = null) : base(path) { // TODO: how to call the default constructor AND the base(path) constructor? And is base(path) calling base() ? _progressReportWorker = progressReportWorker; if (!Global.Emulator.HasSavestates()) { throw new InvalidOperationException("Cannot create a TasMovie against a core that does not implement IStatable"); } ChangeLog = new TasMovieChangeLog(this); _stateManager = new TasStateManager(this); Session = new TasSession(this); Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.CollectionChanged += Markers_CollectionChanged; Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); BindMarkersToInput = true; CurrentBranch = -1; }
public override void RecordFrame(int frame, IController source) { if (frame != 0) { ChangeLog.AddGeneralUndo(frame - 1, frame - 1, $"Record Frame: {frame}"); } base.RecordFrame(frame, source); LagLog.RemoveFrom(frame); LagLog[frame] = Global.Emulator.AsInputPollable().IsLagFrame; if (this.IsRecording()) { TasStateManager.Invalidate(frame + 1); } if (frame != 0) { ChangeLog.SetGeneralRedo(); } }
public TasMovie(string path, bool startsFromSavestate = false, BackgroundWorker progressReportWorker = null) : base(path) { // TODO: how to call the default constructor AND the base(path) constructor? And is base(path) calling base() ? _progressReportWorker = progressReportWorker; if (!Global.Emulator.HasSavestates()) { throw new InvalidOperationException("Cannot create a TasMovie against a core that does not implement IStatable"); } ChangeLog = new TasMovieChangeLog(this); StateManager = new TasStateManager(this); Session = new TasSession(this); Header[HeaderKeys.MOVIEVERSION] = "BizHawk v2.0 Tasproj v1.0"; Markers = new TasMovieMarkerList(this); Markers.CollectionChanged += Markers_CollectionChanged; Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); BindMarkersToInput = true; CurrentBranch = -1; }
public override void Attach(IEmulator emulator) { if (!emulator.HasSavestates()) { throw new InvalidOperationException($"A core must be able to provide an {nameof(IStatable)} service"); } if (!emulator.CanPollInput()) { throw new InvalidOperationException($"A core must be able to provide an {nameof(IInputPollable)} service"); } _inputPollable = emulator.AsInputPollable(); TasStateManager.Attach(emulator); base.Attach(emulator); foreach (var button in emulator.ControllerDefinition.BoolButtons) { _mnemonicCache[button] = Bk2MnemonicLookup.Lookup(button, emulator.SystemId); } }
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); LagLog.RemoveFrom(frame); TasStateManager.Invalidate(frame); Markers.TruncateAt(frame); ChangeLog.SetGeneralRedo(); if (endBatch) { ChangeLog.EndBatch(); } }
public void AddBranch(TasBranch branch) { Branches.Add(branch); TasStateManager.AddBranch(); }
public static StateManagerState Read(BinaryReader r, TasStateManager m) { int frame = r.ReadInt32(); byte[] data = r.ReadBytes(r.ReadInt32()); return new StateManagerState(m, data, frame); }
private bool _align; // extra care about fine alignment. TODO: do we want it? public StateManagerDecay(ITasMovie movie, TasStateManager tsm) { _movie = movie; _tsm = tsm; _align = false; }
private void LoadTasprojExtras(ZipStateLoader bl, bool preload) { bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr) { LagLog.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 { TasSession = 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); }); } } }
private void LoadTasprojExtras(ZipStateLoader bl) { bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr) { LagLog.Load(tr); }); 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 { TasSession = JsonConvert.DeserializeObject <TasSession>(json); } catch { // Do nothing, and use default settings instead } }); ZwinderStateManagerSettings settings = new ZwinderStateManagerSettings(); bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr) { var json = tr.ReadToEnd(); try { settings = JsonConvert.DeserializeObject <ZwinderStateManagerSettings>(json); } catch { // Do nothing, and use default settings instead } }); bl.GetLump(BinaryStateLump.StateHistory, false, delegate(BinaryReader br, long length) { try { TasStateManager?.Dispose(); TasStateManager = ZwinderStateManager.Create(br, settings, IsReserved); } catch { // Continue with a fresh manager. If state history got corrupted, the file is still very much useable // and we would want the user to be able to load, and regenerate their state history // however, we still have an issue of how state history got corrupted TasStateManager = new ZwinderStateManager( Session.Settings.DefaultTasStateManagerSettings, IsReserved); Session.PopupMessage("State history was corrupted, clearing and working with a fresh history."); } }); }
public GreenzoneSettings(TasStateManager.ManagerSettings settings) { Settings = settings; InitializeComponent(); }
// 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.Count != 0) { 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 && 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 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); }
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) { LagLog.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); }); } } } Changes = false; return(true); }
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 => LagLog.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(VerificationLog.ToInputLog())); } 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 AddBranch(TasBranch branch) { Branches.Add(branch); TasStateManager.AddBranch(); Changes = true; }
public void RemoveBranch(TasBranch branch) { TasStateManager.RemoveBranch(Branches.IndexOf(branch)); Branches.Remove(branch); Changes = true; }
private bool _align; // extra care about fine alignment. TODO: do we want it? public StateManagerDecay(TasStateManager tsm) { _tsm = tsm; _align = false; }
protected override void Write(string fn, bool isBackup = false) { if (Emulator is Emulation.Cores.Nintendo.SubNESHawk.SubNESHawk subNes) { Header[HeaderKeys.VBlankCount] = subNes.VblankCount.ToString(); } else if (Emulator is Emulation.Cores.Nintendo.Gameboy.Gameboy gameboy) { Header[HeaderKeys.CycleCount] = gameboy.CycleCount.ToString(); } else if (Emulator is Emulation.Cores.Nintendo.SubGBHawk.SubGBHawk subGb) { Header[HeaderKeys.CycleCount] = subGb.CycleCount.ToString(); } var file = new FileInfo(fn); if (file.Directory != null && !file.Directory.Exists) { Directory.CreateDirectory(file.Directory.ToString()); } using var bs = new ZipStateSaver(fn, Global.Config.Savestates.MovieCompressionLevel); 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 => LagLog.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(VerificationLog.ToInputLog())); } if (Branches.Any()) { Branches.Save(bs); } bs.PutLump(BinaryStateLump.Session, tw => tw.WriteLine(JsonConvert.SerializeObject(TasSession))); if (TasStateManager.Settings.SaveStateHistory && !isBackup) { bs.PutLump(BinaryStateLump.StateHistory, bw => TasStateManager.Save(bw)); } if (!isBackup) { Changes = false; } }