diff --git a/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs b/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs index 8ec5bf7fdf..85330e9081 100644 --- a/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs +++ b/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs @@ -4,17 +4,6 @@ using System.Linq; using BizHawk.Common; using BizHawk.Common.PathExtensions; -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Arcades.MAME; -using BizHawk.Emulation.Cores.Atari.Jaguar; -using BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64; -using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; -using BizHawk.Emulation.Cores.Consoles.Nintendo.NDS; -using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; -using BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive; -using BizHawk.Emulation.Cores.Nintendo.NES; -using BizHawk.Emulation.Cores.Nintendo.SubNESHawk; -using BizHawk.Emulation.Cores.Sega.MasterSystem; namespace BizHawk.Client.Common { @@ -183,127 +172,6 @@ namespace BizHawk.Client.Common return tas; } - // TODO: This doesn't really belong here, but not sure where to put it - public static void PopulateWithDefaultHeaderValues( - this IMovie movie, - IEmulator emulator, - ISettingsAdapter settable, - IGameInfo game, - FirmwareManager firmwareManager, - string author) - { - movie.Author = author; - movie.EmulatorVersion = VersionInfo.GetEmuVersion(); - movie.OriginalEmulatorVersion = VersionInfo.GetEmuVersion(); - movie.SystemID = emulator.SystemId; - - if (settable.HasSyncSettings) - { - movie.SyncSettingsJson = ConfigService.SaveWithType(settable.GetSyncSettings()); - } - - movie.GameName = game.FilesystemSafeName(); - movie.Hash = game.Hash; - if (game.FirmwareHash != null) - { - movie.FirmwareHash = game.FirmwareHash; - } - - if (emulator.HasBoardInfo()) - { - movie.BoardName = emulator.AsBoardInfo().BoardName; - } - - if (emulator.HasRegions()) - { - var region = emulator.AsRegionable().Region; - if (region == DisplayType.PAL) - { - movie.HeaderEntries.Add(HeaderKeys.Pal, "1"); - } - } - - if (firmwareManager.RecentlyServed.Count != 0) - { - foreach (var firmware in firmwareManager.RecentlyServed) - { - var key = firmware.ID.MovieHeaderKey; - if (!movie.HeaderEntries.ContainsKey(key)) - { - movie.HeaderEntries.Add(key, firmware.Hash); - } - } - } - - if (emulator is NDS nds && nds.IsDSi) - { - movie.HeaderEntries.Add("IsDSi", "1"); - - if (nds.IsDSiWare) - { - movie.HeaderEntries.Add("IsDSiWare", "1"); - } - } - - if ((emulator is NES nes && nes.IsVS) - || (emulator is SubNESHawk subnes && subnes.IsVs)) - { - movie.HeaderEntries.Add("IsVS", "1"); - } - - if (emulator is IGameboyCommon gb) - { - //TODO doesn't IsCGBDMGMode imply IsCGBMode? - if (gb.IsCGBMode) movie.HeaderEntries.Add(gb.IsCGBDMGMode ? "IsCGBDMGMode" : "IsCGBMode", "1"); - } - - if (emulator is SMS sms) - { - if (sms.IsSG1000) - { - movie.HeaderEntries.Add("IsSGMode", "1"); - } - - if (sms.IsGameGear) - { - movie.HeaderEntries.Add("IsGGMode", "1"); - } - } - - if (emulator is GPGX gpgx && gpgx.IsMegaCD) - { - movie.HeaderEntries.Add("IsSegaCDMode", "1"); - } - - if (emulator is PicoDrive pico && pico.Is32XActive) - { - movie.HeaderEntries.Add("Is32X", "1"); - } - - if (emulator is VirtualJaguar jag && jag.IsJaguarCD) - { - movie.HeaderEntries.Add("IsJaguarCD", "1"); - } - - if (emulator is Ares64 ares && ares.IsDD) - { - movie.HeaderEntries.Add("IsDD", "1"); - } - - if (emulator is MAME mame) - { - movie.HeaderEntries.Add(HeaderKeys.VsyncAttoseconds, mame.VsyncAttoseconds.ToString()); - } - - if (emulator.HasCycleTiming()) - { - movie.HeaderEntries.Add(HeaderKeys.CycleCount, "0"); - movie.HeaderEntries.Add(HeaderKeys.ClockRate, "0"); - } - - movie.Core = emulator.Attributes().CoreName; - } - internal static string ConvertFileNameToTasMovie(string oldFileName) { if (oldFileName is null) return null; diff --git a/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs b/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs index d2ba2bd5ed..fec81f1e89 100644 --- a/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs +++ b/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs @@ -17,6 +17,7 @@ namespace BizHawk.Client.EmuHawk bool EmulatorPaused { get; } /// only referenced from + // TODO: remove? or does anything ever need access to the FirmwareManager FirmwareManager FirmwareManager { get; } /// only referenced from @@ -81,7 +82,7 @@ namespace BizHawk.Client.EmuHawk void SetMainformMovieInfo(); - bool StartNewMovie(IMovie movie, bool record); + bool StartNewMovie(IMovie movie, bool newMovie); /// only referenced from void Throttle(); diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs index 5fb9121a17..5bea05ba63 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -173,10 +173,6 @@ namespace BizHawk.Client.EmuHawk = RecentMovieSubMenu.Enabled = !Emulator.IsNull() && !Tools.IsLoaded(); - // Record movie dialog should not be opened while in need of a reboot, - // Otherwise the wrong sync settings could be set for the recording movie and cause crashes - RecordMovieMenuItem.Enabled &= !RebootStatusBarIcon.Visible; - PlayFromBeginningMenuItem.Enabled = MovieSession.Movie.IsActive() && !Tools.IsLoaded(); } @@ -368,7 +364,7 @@ namespace BizHawk.Client.EmuHawk // Nag user to user a more accurate core, but let them continue anyway EnsureCoreIsAccurate(); - using var form = new RecordMovie(this, Config, Game, Emulator, MovieSession, FirmwareManager); + using var form = new RecordMovie(this, Config, Game, Emulator, MovieSession); this.ShowDialogWithTempMute(form); } diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs b/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs index a4e8564e7b..e3bbcd687d 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs @@ -2,13 +2,24 @@ using System.Collections.Generic; using System.Windows.Forms; using BizHawk.Client.Common; +using BizHawk.Common; using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Arcades.MAME; +using BizHawk.Emulation.Cores.Atari.Jaguar; +using BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64; +using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; +using BizHawk.Emulation.Cores.Consoles.Nintendo.NDS; +using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; +using BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive; +using BizHawk.Emulation.Cores.Nintendo.NES; +using BizHawk.Emulation.Cores.Nintendo.SubNESHawk; +using BizHawk.Emulation.Cores.Sega.MasterSystem; namespace BizHawk.Client.EmuHawk { public partial class MainForm { - public bool StartNewMovie(IMovie movie, bool record) + public bool StartNewMovie(IMovie movie, bool newMovie) { if (movie is null) throw new ArgumentNullException(paramName: nameof(movie)); @@ -24,6 +35,7 @@ namespace BizHawk.Client.EmuHawk var oldPreferredCores = new Dictionary(Config.PreferredCores); try { + if (newMovie) PrepopulateMovieHeaderValues(movie); try { MovieSession.QueueNewMovie( @@ -48,7 +60,13 @@ namespace BizHawk.Client.EmuHawk Config.RecentMovies.Add(movie.Filename); - MovieSession.RunQueuedMovie(record, Emulator); + MovieSession.RunQueuedMovie(newMovie, Emulator); + if (newMovie) + { + PopulateWithDefaultHeaderValues(movie); + if (movie is ITasMovie tasMovie) + tasMovie.ClearChanges(); + } } finally { @@ -138,5 +156,132 @@ namespace BizHawk.Client.EmuHawk } } } + + /// + /// Sets necessary movie values in order to be able to start this + /// Only required when creating a new movie from scratch. + /// + /// The movie to fill with values + private void PrepopulateMovieHeaderValues(IMovie movie) + { + movie.Core = Emulator.Attributes().CoreName; + movie.SystemID = Emulator.SystemId; // TODO: I feel like setting this shouldn't be necessary, but it is currently + + var settable = GetSettingsAdapterForLoadedCoreUntyped(); + if (settable.HasSyncSettings) + { + movie.SyncSettingsJson = ConfigService.SaveWithType(settable.GetSyncSettings()); + } + } + + /// + /// Sets default header values for the given . Notably needs to be done after loading the core + /// to make sure all values are in the correct state, see https://github.com/TASEmulators/BizHawk/issues/3980 + /// + /// The movie to fill with values + private void PopulateWithDefaultHeaderValues(IMovie movie) + { + movie.EmulatorVersion = VersionInfo.GetEmuVersion(); + movie.OriginalEmulatorVersion = VersionInfo.GetEmuVersion(); + + movie.GameName = Game.FilesystemSafeName(); + movie.Hash = Game.Hash; + if (Game.FirmwareHash != null) + { + movie.FirmwareHash = Game.FirmwareHash; + } + + if (Emulator.HasBoardInfo()) + { + movie.BoardName = Emulator.AsBoardInfo().BoardName; + } + + if (Emulator.HasRegions()) + { + var region = Emulator.AsRegionable().Region; + if (region == DisplayType.PAL) + { + movie.HeaderEntries.Add(HeaderKeys.Pal, "1"); + } + } + + if (FirmwareManager.RecentlyServed.Count != 0) + { + foreach (var firmware in FirmwareManager.RecentlyServed) + { + var key = firmware.ID.MovieHeaderKey; + if (!movie.HeaderEntries.ContainsKey(key)) + { + movie.HeaderEntries.Add(key, firmware.Hash); + } + } + } + + if (Emulator is NDS nds && nds.IsDSi) + { + movie.HeaderEntries.Add("IsDSi", "1"); + + if (nds.IsDSiWare) + { + movie.HeaderEntries.Add("IsDSiWare", "1"); + } + } + + if ((Emulator is NES nes && nes.IsVS) + || (Emulator is SubNESHawk subnes && subnes.IsVs)) + { + movie.HeaderEntries.Add("IsVS", "1"); + } + + if (Emulator is IGameboyCommon gb) + { + //TODO doesn't IsCGBDMGMode imply IsCGBMode? + if (gb.IsCGBMode) movie.HeaderEntries.Add(gb.IsCGBDMGMode ? "IsCGBDMGMode" : "IsCGBMode", "1"); + } + + if (Emulator is SMS sms) + { + if (sms.IsSG1000) + { + movie.HeaderEntries.Add("IsSGMode", "1"); + } + + if (sms.IsGameGear) + { + movie.HeaderEntries.Add("IsGGMode", "1"); + } + } + + if (Emulator is GPGX gpgx && gpgx.IsMegaCD) + { + movie.HeaderEntries.Add("IsSegaCDMode", "1"); + } + + if (Emulator is PicoDrive pico && pico.Is32XActive) + { + movie.HeaderEntries.Add("Is32X", "1"); + } + + if (Emulator is VirtualJaguar jag && jag.IsJaguarCD) + { + movie.HeaderEntries.Add("IsJaguarCD", "1"); + } + + if (Emulator is Ares64 ares && ares.IsDD) + { + movie.HeaderEntries.Add("IsDD", "1"); + } + + if (Emulator is MAME mame) + { + movie.HeaderEntries.Add(HeaderKeys.VsyncAttoseconds, mame.VsyncAttoseconds.ToString()); + } + + if (Emulator.HasCycleTiming()) + { + movie.HeaderEntries.Add(HeaderKeys.CycleCount, "0"); + movie.HeaderEntries.Add(HeaderKeys.ClockRate, "0"); + } + } } } diff --git a/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs b/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs index 439772bb13..6fcf09c699 100644 --- a/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs +++ b/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs @@ -24,7 +24,6 @@ namespace BizHawk.Client.EmuHawk private readonly GameInfo _game; private readonly IEmulator _emulator; private readonly IMovieSession _movieSession; - private readonly FirmwareManager _firmwareManager; private readonly TextBox AuthorBox; @@ -41,8 +40,7 @@ namespace BizHawk.Client.EmuHawk Config config, GameInfo game, IEmulator core, - IMovieSession movieSession, - FirmwareManager firmwareManager) + IMovieSession movieSession) { if (game.IsNullInstance()) throw new InvalidOperationException("how is the traditional Record dialog open with no game loaded? please report this including as much detail as possible"); @@ -51,7 +49,6 @@ namespace BizHawk.Client.EmuHawk _game = game; _emulator = core; _movieSession = movieSession; - _firmwareManager = firmwareManager; SuspendLayout(); @@ -222,6 +219,7 @@ namespace BizHawk.Client.EmuHawk } var movieToRecord = _movieSession.Get(path); + movieToRecord.Author = AuthorBox.Text ?? _config.DefaultAuthor; var fileInfo = new FileInfo(path); if (!fileInfo.Exists) @@ -260,12 +258,6 @@ namespace BizHawk.Client.EmuHawk movieToRecord.SaveRam = core.CloneSaveRam(); } - movieToRecord.PopulateWithDefaultHeaderValues( - _emulator, - ((MainForm) _mainForm).GetSettingsAdapterForLoadedCoreUntyped(), //HACK - _game, - _firmwareManager, - AuthorBox.Text ?? _config.DefaultAuthor); _mainForm.StartNewMovie(movieToRecord, true); _config.UseDefaultAuthor = DefaultAuthorCheckBox.Checked; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs index e9773faee5..684d75d523 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs @@ -580,18 +580,12 @@ namespace BizHawk.Client.EmuHawk var filename = DefaultTasProjName(); // TODO don't do this, take over any mainform actions that can crash without a filename var tasMovie = (ITasMovie)MovieSession.Get(filename); + tasMovie.Author = Config.DefaultAuthor; tasMovie.BindMarkersToInput = Settings.BindMarkersToInput; tasMovie.GreenzoneInvalidated = GreenzoneInvalidated; tasMovie.PropertyChanged += TasMovie_OnPropertyChanged; - tasMovie.PopulateWithDefaultHeaderValues( - Emulator, - ((MainForm) MainForm).GetSettingsAdapterForLoadedCoreUntyped(), //HACK - Game, - MainForm.FirmwareManager, - Config.DefaultAuthor); - _ = StartNewMovieWrapper(tasMovie, isNew: true); // clear all selections