diff --git a/src/BizHawk.Client.Common/movie/MovieSession.cs b/src/BizHawk.Client.Common/movie/MovieSession.cs index c0750dcdd4..d0f0be34d6 100644 --- a/src/BizHawk.Client.Common/movie/MovieSession.cs +++ b/src/BizHawk.Client.Common/movie/MovieSession.cs @@ -287,7 +287,6 @@ namespace BizHawk.Client.Common public void ConvertToTasProj() { - Movie.Save(); Movie = Movie.ToTasMovie(); Movie.Save(); Movie.SwitchToPlay(); @@ -335,13 +334,21 @@ namespace BizHawk.Client.Common private void HandlePlaybackEnd() { - if (Movie.Core == CoreNames.Gambatte) + if (Movie.IsAtEnd() && Movie.Core == CoreNames.Gambatte) { - var movieCycles = Convert.ToUInt64(Movie.HeaderEntries[HeaderKeys.CycleCount]); - var coreCycles = ((Gameboy)Movie.Emulator).CycleCount; - if (movieCycles != (ulong)coreCycles) + var coreCycles = (ulong) ((Gameboy)Movie.Emulator).CycleCount; + var cyclesSaved = Movie.HeaderEntries.ContainsKey(HeaderKeys.CycleCount); + ulong previousCycles = 0; + if (cyclesSaved) { - PopupMessage($"Cycle count in the movie ({movieCycles}) doesn't match the emulated value ({coreCycles})."); + previousCycles = Convert.ToUInt64(Movie.HeaderEntries[HeaderKeys.CycleCount]); + } + var cyclesMatch = previousCycles == coreCycles; + if (!cyclesSaved || !cyclesMatch) + { + var previousState = !cyclesSaved ? "The saved movie is currently missing a cycle count." : $"The previous cycle count ({previousCycles}) doesn't match."; + // TODO: Ideally, this would be a Yes/No MessageBox that saves when "Yes" is pressed. + PopupMessage($"The end of the movie has been reached.\n\n{previousState}\n\nSave to update to the new cycle count ({coreCycles})."); } } diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs index 9776c629e3..bec0422e4a 100644 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs @@ -52,7 +52,7 @@ namespace BizHawk.Client.Common protected virtual void Write(string fn, bool isBackup = false) { - SetCycleValues(); // We are pretending these only need to be set on save + SetCycleValues(); // EmulatorVersion used to store the unchanging original emulator version. if (!Header.ContainsKey(HeaderKeys.OriginalEmulatorVersion)) { @@ -72,17 +72,26 @@ namespace BizHawk.Client.Common private void SetCycleValues() { - if (Emulator is Emulation.Cores.Nintendo.SubNESHawk.SubNESHawk subNes) - { - Header[HeaderKeys.VBlankCount] = subNes.VblankCount.ToString(); + // The saved cycle value will only be valid if the end of the movie has been emulated. + if (this.IsAtEnd()) + { + 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(); + } } - else if (Emulator is Emulation.Cores.Nintendo.Gameboy.Gameboy gameboy) + else { - Header[HeaderKeys.CycleCount] = gameboy.CycleCount.ToString(); - } - else if (Emulator is Emulation.Cores.Nintendo.SubGBHawk.SubGBHawk subGb) - { - Header[HeaderKeys.CycleCount] = subGb.CycleCount.ToString(); + Header.Remove(HeaderKeys.CycleCount); + Header.Remove(HeaderKeys.VBlankCount); } } diff --git a/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs b/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs index 1f65873238..02f74e8903 100644 --- a/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs +++ b/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs @@ -258,6 +258,11 @@ namespace BizHawk.Client.Common public static bool IsFinished(this IMovie movie) => movie?.Mode == MovieMode.Finished; public static bool IsPlayingOrFinished(this IMovie movie) => movie?.Mode == MovieMode.Play || movie?.Mode == MovieMode.Finished; public static bool IsPlayingOrRecording(this IMovie movie) => movie?.Mode == MovieMode.Play || movie?.Mode == MovieMode.Record; + /// + /// Emulation is currently right after the movie's last input frame, + /// but no further frames have been emulated. + /// + public static bool IsAtEnd(this IMovie movie) => movie != null && movie.Emulator?.Frame == movie.InputLogLength; /// diff --git a/src/BizHawk.Client.EmuHawk/DisplayManager/OSDManager.cs b/src/BizHawk.Client.EmuHawk/DisplayManager/OSDManager.cs index 73df9b8349..df46d359dd 100644 --- a/src/BizHawk.Client.EmuHawk/DisplayManager/OSDManager.cs +++ b/src/BizHawk.Client.EmuHawk/DisplayManager/OSDManager.cs @@ -273,7 +273,7 @@ namespace BizHawk.Client.EmuHawk { var moviePlaying = GlobalWin.MovieSession.Movie.IsPlaying(); // After the last frame of the movie, we want both the last movie input and the current inputs. - var atMovieEnd = (GlobalWin.MovieSession.Movie.IsFinished() && GlobalWin.Emulator.Frame == GlobalWin.MovieSession.Movie.InputLogLength); + var atMovieEnd = GlobalWin.MovieSession.Movie.IsFinished() && GlobalWin.MovieSession.Movie.IsAtEnd(); if (moviePlaying || atMovieEnd) { var input = InputStrMovie(); diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs index 5eb7e2a227..4610856d67 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs @@ -203,17 +203,28 @@ namespace BizHawk.Client.EmuHawk // Start Scenario 1: A regular movie is active if (MovieSession.Movie.IsActive() && !(MovieSession.Movie is ITasMovie)) { - var result = MessageBox.Show("In order to use Tastudio, a new project must be created from the current movie\nThe current movie will be saved and closed, and a new project file will be created\nProceed?", "Convert movie", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); - if (result.IsOk()) + var changesString = "Would you like to save the current movie before closing it?"; + if (MovieSession.Movie.Changes) { - ConvertCurrentMovieToTasproj(); - StartNewMovieWrapper(CurrentTasMovie); - SetUpColumns(); + changesString = "The current movie has unsaved changes. Would you like to save before closing it?"; } - else + var result = MessageBox.Show( + "TAStudio will create a new project file from the current movie.\n\n" + changesString, + "Convert movie", + MessageBoxButtons.YesNoCancel, + MessageBoxIcon.Question); + if (result.Equals(DialogResult.Yes)) + { + MovieSession.Movie.Save(); + } + else if (result.Equals(DialogResult.Cancel)) { return false; } + + ConvertCurrentMovieToTasproj(); + StartNewMovieWrapper(CurrentTasMovie); + SetUpColumns(); } // Start Scenario 2: A tasproj is already active