diff --git a/src/BizHawk.Client.Common/inputAdapters/CopyController.cs b/src/BizHawk.Client.Common/inputAdapters/CopyController.cs index c852a6cb18..8ce44963c0 100644 --- a/src/BizHawk.Client.Common/inputAdapters/CopyController.cs +++ b/src/BizHawk.Client.Common/inputAdapters/CopyController.cs @@ -5,7 +5,7 @@ namespace BizHawk.Client.Common /// /// Just copies source to sink, or returns whatever a NullController would if it is disconnected. useful for immovable hard-points. /// - public class CopyControllerAdapter : IController + public class CopyControllerAdapter : IInputAdapter { public ControllerDefinition Definition => Curr.Definition; diff --git a/src/BizHawk.Client.Common/inputAdapters/IInputAdapter.cs b/src/BizHawk.Client.Common/inputAdapters/IInputAdapter.cs new file mode 100644 index 0000000000..45e977bd77 --- /dev/null +++ b/src/BizHawk.Client.Common/inputAdapters/IInputAdapter.cs @@ -0,0 +1,13 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Client.Common +{ + /// + /// Represents an input adapter, that can take in a source, manipulate it as needed + /// and then represent the resulting state as an + /// + public interface IInputAdapter : IController + { + IController Source { get; set; } + } +} diff --git a/src/BizHawk.Client.Common/inputAdapters/InputManager.cs b/src/BizHawk.Client.Common/inputAdapters/InputManager.cs index 00ca5347e0..8ae53744c7 100644 --- a/src/BizHawk.Client.Common/inputAdapters/InputManager.cs +++ b/src/BizHawk.Client.Common/inputAdapters/InputManager.cs @@ -12,11 +12,6 @@ namespace BizHawk.Client.Common // (1)->Input Display public class InputManager { - // the movie will be spliced in between these if it is present - public CopyControllerAdapter MovieInputSourceAdapter { get; } = new CopyControllerAdapter(); - public CopyControllerAdapter MovieOutputHardpoint { get; } = new CopyControllerAdapter(); - public MultitrackRewiringControllerAdapter MultitrackRewiringAdapter { get; } = new MultitrackRewiringControllerAdapter(); - // the original source controller, bound to the user, sort of the "input" port for the chain, i think public Controller ActiveController { get; set; } // TODO: private setter, add a method that takes both controllers in @@ -26,7 +21,7 @@ namespace BizHawk.Client.Common // the "output" port for the controller chain. public CopyControllerAdapter ControllerOutput { get; } = new CopyControllerAdapter(); - public UdlrControllerAdapter UdLRControllerAdapter { get; } = new UdlrControllerAdapter(); + private UdlrControllerAdapter UdLRControllerAdapter { get; } = new UdlrControllerAdapter(); public AutoFireStickyXorAdapter AutofireStickyXorAdapter { get; } = new AutoFireStickyXorAdapter(); @@ -51,7 +46,7 @@ namespace BizHawk.Client.Common public Controller ClientControls { get; set; } - public void SyncControls(IEmulator emulator, Config config) + public void SyncControls(IEmulator emulator, IMovieSession session, Config config) { var def = emulator.ControllerDefinition; @@ -73,14 +68,8 @@ namespace BizHawk.Client.Common StickyXorAdapter.Source = UdLRControllerAdapter; AutofireStickyXorAdapter.Source = StickyXorAdapter; - MultitrackRewiringAdapter.Source = AutofireStickyXorAdapter; - MovieInputSourceAdapter.Source = MultitrackRewiringAdapter; - ControllerOutput.Source = MovieOutputHardpoint; - - Global.MovieSession.RecreateMovieController(MovieInputSourceAdapter.Definition); - - // connect the movie session before MovieOutputHardpoint - MovieOutputHardpoint.Source = Global.MovieSession.MovieController; + session.MovieIn.Source = AutofireStickyXorAdapter; + ControllerOutput.Source = session.MovieOut; } private static Controller BindToDefinition(ControllerDefinition def, IDictionary> allBinds, IDictionary> analogBinds) diff --git a/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs b/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs index 26ee7c0d38..0a970ef7ce 100644 --- a/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs +++ b/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs @@ -107,7 +107,7 @@ namespace BizHawk.Client.Common } } - public class AutoFireStickyXorAdapter : IStickyController + public class AutoFireStickyXorAdapter : IStickyController, IInputAdapter { public ControllerDefinition Definition => Source.Definition; diff --git a/src/BizHawk.Client.Common/movie/MovieSession.cs b/src/BizHawk.Client.Common/movie/MovieSession.cs index 720f3701ac..941076dfcf 100644 --- a/src/BizHawk.Client.Common/movie/MovieSession.cs +++ b/src/BizHawk.Client.Common/movie/MovieSession.cs @@ -39,6 +39,8 @@ namespace BizHawk.Client.Common ?? throw new ArgumentNullException($"{nameof(pauseCallback)} cannot be null."); _modeChangedCallback = modeChangedCallback ?? throw new ArgumentNullException($"{nameof(modeChangedCallback)} CannotUnloadAppDomainException be null."); + + MultiTrack.RewiringAdapter.Source = MovieIn; } public IMovieConfig Settings { get; } @@ -50,15 +52,13 @@ namespace BizHawk.Client.Common public bool NewMovieQueued => _queuedMovie != null; public string QueuedSyncSettings => _queuedMovie.SyncSettingsJson; + public IInputAdapter MovieIn { get; } = new CopyControllerAdapter(); + public IInputAdapter MovieOut { get; } = new CopyControllerAdapter(); + public IMovieController MovieController { get; private set; } = new Bk2Controller("", NullController.Instance.Definition); public MultitrackRecorder MultiTrack { get; } = new MultitrackRecorder(); - public void RecreateMovieController(ControllerDefinition definition) - { - MovieController = new Bk2Controller(definition); - } - public IMovieController GenerateMovieController(ControllerDefinition definition = null) { // TODO: expose Movie.LogKey and pass in here @@ -233,6 +233,7 @@ namespace BizHawk.Client.Common public void RunQueuedMovie(bool recordMode, IEmulator emulator, IDictionary preferredCores) { + MovieController = new Bk2Controller(emulator.ControllerDefinition); _queuedMovie.Attach(emulator); foreach (var previousPref in _preferredCores) { @@ -255,8 +256,6 @@ namespace BizHawk.Client.Common { Movie.StartNewPlayback(); } - - MultiTrack.Restart(emulator.ControllerDefinition.PlayerCount); } public void ToggleMultitrack() @@ -350,9 +349,9 @@ namespace BizHawk.Client.Common private void LatchInputToMultitrackUser() { - var rewiredSource = Global.InputManager.MultitrackRewiringAdapter; if (MultiTrack.IsActive) { + var rewiredSource = MultiTrack.RewiringAdapter; rewiredSource.PlayerSource = 1; rewiredSource.PlayerTargetMask = 1 << MultiTrack.CurrentPlayer; if (MultiTrack.RecordAll) @@ -372,7 +371,8 @@ namespace BizHawk.Client.Common private void LatchInputToUser() { - MovieController.SetFrom(Global.InputManager.MovieInputSourceAdapter); + MovieOut.Source = MovieIn; + MovieController.SetFrom(MovieIn); // TODO: this shouldn't be necessary anymore } // Latch input from the input log, if available @@ -393,10 +393,7 @@ namespace BizHawk.Client.Common } MovieController.SetFrom(input); - if (MultiTrack.IsActive) - { - Global.InputManager.MultitrackRewiringAdapter.Source = MovieController; - } + MovieOut.Source = MovieController; } private void HandlePlaybackEnd() @@ -438,6 +435,7 @@ namespace BizHawk.Client.Common // we don't want TasMovie to latch user input outside its internal recording mode, so limit it to autohold if (Movie is ITasMovie && Movie.IsPlayingOrFinished()) { + // TODO: same as MovieIn, since autofiresitcky is the last in the chain before movie MovieController.SetFromSticky(Global.InputManager.AutofireStickyXorAdapter); } else @@ -452,9 +450,7 @@ namespace BizHawk.Client.Common } } - // the movie session makes sure that the correct input has been read and merged to its MovieControllerAdapter; - // this has been wired to Global.MovieOutputHardpoint in RewireInputChain - Movie.RecordFrame(Movie.Emulator.Frame, Global.InputManager.MovieOutputHardpoint); + Movie.RecordFrame(Movie.Emulator.Frame, MovieController); } } } \ No newline at end of file diff --git a/src/BizHawk.Client.Common/movie/MultitrackRecording.cs b/src/BizHawk.Client.Common/movie/MultitrackRecording.cs index f832b30c98..1de5d236e7 100644 --- a/src/BizHawk.Client.Common/movie/MultitrackRecording.cs +++ b/src/BizHawk.Client.Common/movie/MultitrackRecording.cs @@ -9,6 +9,8 @@ namespace BizHawk.Client.Common Restart(1); } + internal MultitrackRewiringControllerAdapter RewiringAdapter { get; } = new MultitrackRewiringControllerAdapter(); + public bool IsActive { get; set; } public int CurrentPlayer { get; private set; } public int PlayerCount { get; private set; } @@ -84,10 +86,10 @@ namespace BizHawk.Client.Common /// /// rewires player1 controls to playerN /// - public class MultitrackRewiringControllerAdapter : IController + public class MultitrackRewiringControllerAdapter : IInputAdapter { public IController Source { get; set; } - public int PlayerSource { get; set; } = 1; + public int PlayerSource { get; set; } = -1; public int PlayerTargetMask { get; set; } public ControllerDefinition Definition => Source.Definition; diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs index 9db064c7f1..9b9a38966e 100644 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs @@ -14,7 +14,7 @@ namespace BizHawk.Client.Common { writer.WriteLine("[Input]"); - var lg = new Bk2LogEntryGenerator(LogKey, Global.InputManager.MovieOutputHardpoint); + var lg = new Bk2LogEntryGenerator(LogKey, Session.MovieController); writer.WriteLine(lg.GenerateLogKey()); foreach (var record in Log) diff --git a/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs b/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs index 6f9445572b..f1a4847518 100644 --- a/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs +++ b/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs @@ -24,10 +24,18 @@ namespace BizHawk.Client.Common MultitrackRecorder MultiTrack { get; } /// - /// Recreates MovieController with the given controller definition - /// with an empty controller state + /// Represents the input source that is fed to + /// the movie for the purpsoe of recording, if active, + /// or to simply pass through if inactive /// - void RecreateMovieController(ControllerDefinition definition); + IInputAdapter MovieIn { get; } + + /// + /// Represents the movie input in the input chain + /// Is a pass through when movies are not active, + /// otherwise they handle necessary movie logic + /// + IInputAdapter MovieOut { get; } /// /// Creates a instance based on the diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs index a54effbf30..0c4cbd5d70 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs @@ -275,10 +275,11 @@ namespace BizHawk.Client.Common int oldLength = InputLogLength; ChangeLog.AddGeneralUndo(oldLength, oldLength + numFrames - 1); + // TODO: same as MovieIn, since autofiresitcky is the last in the chain before movie Session.MovieController.SetFromSticky(Global.InputManager.AutofireStickyXorAdapter); // account for autohold. needs autohold pattern to be already recorded in the current frame - var lg = LogGeneratorInstance(Global.InputManager.MovieOutputHardpoint); + var lg = LogGeneratorInstance(Session.MovieController); for (int i = 0; i < numFrames; i++) { diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs index f48f82ee9f..4ce4047638 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -932,7 +932,7 @@ namespace BizHawk.Client.EmuHawk { AddOnScreenMessage("Controller settings saved"); InitControls(); - InputManager.SyncControls(Emulator, Config); + InputManager.SyncControls(Emulator, MovieSession, Config); } else { @@ -947,7 +947,7 @@ namespace BizHawk.Client.EmuHawk { AddOnScreenMessage("Hotkey settings saved"); InitControls(); - InputManager.SyncControls(Emulator, Config); + InputManager.SyncControls(Emulator, MovieSession, Config); } else { diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index f983bfa6b0..a8e2544c09 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -413,7 +413,7 @@ namespace BizHawk.Client.EmuHawk } Sound.StartSound(); - InputManager.SyncControls(Emulator, Config); + InputManager.SyncControls(Emulator, MovieSession, Config); GlobalWin.CheatList = new CheatCollection(Config.Cheats); CheatList.Changed += Tools.UpdateCheatRelatedTools; RewireSound(); @@ -2845,7 +2845,7 @@ namespace BizHawk.Client.EmuHawk Config = ConfigService.Load(iniPath); Config.ResolveDefaults(); InitControls(); // rebind hotkeys - InputManager.SyncControls(Emulator, Config); + InputManager.SyncControls(Emulator, MovieSession, Config); AddOnScreenMessage($"Config file loaded: {iniPath}"); } @@ -3706,7 +3706,7 @@ namespace BizHawk.Client.EmuHawk { string openAdvancedArgs = $"*{OpenAdvancedSerializer.Serialize(ioa)}"; Emulator = loader.LoadedEmulator; - InputManager.SyncControls(Emulator, Config); + InputManager.SyncControls(Emulator, MovieSession, Config); if (oaOpenrom != null && Path.GetExtension(oaOpenrom.Path.Replace("|", "")).ToLowerInvariant() == ".xml" && !(Emulator is LibsnesCore)) {