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