From bc42af0fa6c8b4596e8b477e3cdcd688b7189e80 Mon Sep 17 00:00:00 2001 From: adelikat Date: Wed, 19 Apr 2017 10:36:08 -0500 Subject: [PATCH] Libsnescore - Break off IEmulator implementation into a separate file --- .../Interfaces/IEmulator.cs | 16 +- .../BizHawk.Emulation.Cores.csproj | 3 + .../Nintendo/SNES/LibsnesCore.IEmulator.cs | 140 ++++++++++++++++++ .../Consoles/Nintendo/SNES/LibsnesCore.cs | 134 +---------------- 4 files changed, 157 insertions(+), 136 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs diff --git a/BizHawk.Emulation.Common/Interfaces/IEmulator.cs b/BizHawk.Emulation.Common/Interfaces/IEmulator.cs index 21f48d5f11..80bb782845 100644 --- a/BizHawk.Emulation.Common/Interfaces/IEmulator.cs +++ b/BizHawk.Emulation.Common/Interfaces/IEmulator.cs @@ -10,14 +10,15 @@ namespace BizHawk.Emulation.Common public interface IEmulator : IEmulatorService, IDisposable { /// - /// The intended mechanism to get services from a core + /// Gets the service provider. + /// This is the intended mechanism to get services from a core /// Retrieves an IEmulatorService from the core, /// if the core does not have the type specified, it will return null /// IEmulatorServiceProvider ServiceProvider { get; } /// - /// Defines all the possible inputs and types that the core can receive + /// Gets the definition that defines all the possible inputs and types that the core can receive /// By design this should not change during the lifetime of the instance of the core /// To change the definition, a new instance should be created /// @@ -39,17 +40,18 @@ namespace BizHawk.Emulation.Common void FrameAdvance(bool render, bool rendersound = true); /// - /// The frame count + /// Gets the current frame count /// int Frame { get; } /// - /// The unique Id of the platform currently being emulated, for instance "NES" + /// Gets the unique Id of the platform currently being emulated, for instance "NES" /// string SystemId { get; } /// - /// This flag is a contract with the client. + /// Gets a value indicating whether the core is in deterministic mode. + /// This flag is a contract with the client. /// If true, the core agrees to behave in a completely deterministic manner, /// Features like movie recording depend on this. /// It is the client's responsibility to manage this flag. @@ -59,7 +61,7 @@ namespace BizHawk.Emulation.Common bool DeterministicEmulation { get; } /// - /// identifying information about a "mapper" or similar capability. null if no such useful distinction can be drawn + /// Gets the identifying information about a "mapper" or similar capability. null if no such useful distinction can be drawn /// string BoardName { get; } @@ -69,7 +71,7 @@ namespace BizHawk.Emulation.Common void ResetCounters(); /// - /// the corecomm module in use by this core. + /// Gets the core communications module in use by this core. /// /// CoreComm CoreComm { get; } diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 127d3adb1a..2306ec5157 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -905,6 +905,9 @@ LibsnesCore.cs + LibsnesCore.cs + + LibsnesCore.cs diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs new file mode 100644 index 0000000000..2420722c61 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IEmulator.cs @@ -0,0 +1,140 @@ +using System.IO; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SNES +{ + public partial class LibsnesCore : IEmulator + { + public IEmulatorServiceProvider ServiceProvider { get; } + + public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; + + public IController Controller { get; set; } + + public void FrameAdvance(bool render, bool rendersound) + { + /* if the input poll callback is called, it will set this to false + * this has to be done before we save the per-frame state in deterministic + * mode, because in there, the core actually advances, and might advance + * through the point in time where IsLagFrame gets set to false. makes sense? + */ + + IsLagFrame = true; + + if (!nocallbacks && Tracer.Enabled) + { + api.QUERY_set_trace_callback(tracecb); + } + else + { + api.QUERY_set_trace_callback(null); + } + + // for deterministic emulation, save the state we're going to use before frame advance + // don't do this during nocallbacks though, since it's already been done + if (!nocallbacks && DeterministicEmulation) + { + var ms = new MemoryStream(); + var bw = new BinaryWriter(ms); + bw.Write(CoreSaveState()); + bw.Write(false); // not framezero + var ssc = new SnesSaveController(); + ssc.CopyFrom(Controller); + ssc.Serialize(bw); + bw.Close(); + _savestatebuff = ms.ToArray(); + } + + // speedup when sound rendering is not needed + api.QUERY_set_audio_sample(rendersound ? soundcb : null); + + bool resetSignal = Controller.IsPressed("Reset"); + if (resetSignal) + { + api.CMD_reset(); + } + + bool powerSignal = Controller.IsPressed("Power"); + if (powerSignal) + { + api.CMD_power(); + } + + var enables = new LibsnesApi.LayerEnables + { + BG1_Prio0 = _settings.ShowBG1_0, + BG1_Prio1 = _settings.ShowBG1_1, + BG2_Prio0 = _settings.ShowBG2_0, + BG2_Prio1 = _settings.ShowBG2_1, + BG3_Prio0 = _settings.ShowBG3_0, + BG3_Prio1 = _settings.ShowBG3_1, + BG4_Prio0 = _settings.ShowBG4_0, + BG4_Prio1 = _settings.ShowBG4_1, + Obj_Prio0 = _settings.ShowOBJ_0, + Obj_Prio1 = _settings.ShowOBJ_1, + Obj_Prio2 = _settings.ShowOBJ_2, + Obj_Prio3 = _settings.ShowOBJ_3 + }; + + api.SetLayerEnables(ref enables); + + RefreshMemoryCallbacks(false); + + // apparently this is one frame? + _timeFrameCounter++; + api.CMD_run(); + + // once upon a time we forwarded messages frmo bsnes here, by checking for queued text messages, but I don't think it's needed any longer + if (IsLagFrame) + { + LagCount++; + } + } + + public int Frame + { + get { return _timeFrameCounter; } + private set { _timeFrameCounter = value; } + } + + public string SystemId { get; } + + // adelikat: Nasty hack to force new business logic. Compatibility (and Accuracy when fully supported) will ALWAYS be in deterministic mode, + // a consequence is a permanent performance hit to the compatibility core + // Perormance will NEVER be in deterministic mode (and the client side logic will prohibit movie recording on it) + // feos: Nasty hack to a nasty hack. Allow user disable it with a strong warning. + public bool DeterministicEmulation => + _settings.ForceDeterminism + && (CurrentProfile == "Compatibility" || CurrentProfile == "Accuracy"); + + public string BoardName { get; } + + public void ResetCounters() + { + _timeFrameCounter = 0; + LagCount = 0; + IsLagFrame = false; + } + + public CoreComm CoreComm { get; } + + public void Dispose() + { + if (_disposed) + { + return; + } + + _disposed = true; + + api.CMD_unload_cartridge(); + api.CMD_term(); + + resampler.Dispose(); + api.Dispose(); + + _currCdl?.Unpin(); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs index 9433b0bd0f..23b0c0b5b5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -160,7 +160,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES SetupMemoryDomains(romData, sgbRomData); - DeterministicEmulation = deterministicEmulation; + // DeterministicEmulation = deterministicEmulation; // Note we don't respect the value coming in and force it instead if (DeterministicEmulation) // save frame-0 savestate now { MemoryStream ms = new MemoryStream(); @@ -174,8 +174,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES } } - public IEmulatorServiceProvider ServiceProvider { get; private set; } - private GameInfo _game; public string CurrentProfile @@ -199,21 +197,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES /// disable all external callbacks. the front end should not even know the core is frame advancing bool nocallbacks = false; - bool disposed = false; - public void Dispose() - { - if (disposed) return; - disposed = true; - - api.CMD_unload_cartridge(); - api.CMD_term(); - - resampler.Dispose(); - api.Dispose(); - - if (_currCdl != null) _currCdl.Unpin(); - } - public ITraceable Tracer { get; private set; } public class MyScanlineHookManager : ScanlineHookManager @@ -230,10 +213,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES } } + bool _disposed = false; + public MyScanlineHookManager ScanlineHookManager; void OnScanlineHooksChanged() { - if (disposed) return; + if (_disposed) return; if (ScanlineHookManager.HookCount == 0) api.QUERY_set_scanlineStart(null); else api.QUERY_set_scanlineStart(scanlineStart_cb); } @@ -507,75 +492,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES } } - public void FrameAdvance(bool render, bool rendersound) - { - /* if the input poll callback is called, it will set this to false - * this has to be done before we save the per-frame state in deterministic - * mode, because in there, the core actually advances, and might advance - * through the point in time where IsLagFrame gets set to false. makes sense? - */ - - IsLagFrame = true; - - if (!nocallbacks && Tracer.Enabled) - api.QUERY_set_trace_callback(tracecb); - else - api.QUERY_set_trace_callback(null); - - // for deterministic emulation, save the state we're going to use before frame advance - // don't do this during nocallbacks though, since it's already been done - if (!nocallbacks && DeterministicEmulation) - { - MemoryStream ms = new MemoryStream(); - BinaryWriter bw = new BinaryWriter(ms); - bw.Write(CoreSaveState()); - bw.Write(false); // not framezero - SnesSaveController ssc = new SnesSaveController(); - ssc.CopyFrom(Controller); - ssc.Serialize(bw); - bw.Close(); - _savestatebuff = ms.ToArray(); - } - - // speedup when sound rendering is not needed - if (!rendersound) - api.QUERY_set_audio_sample(null); - else - api.QUERY_set_audio_sample(soundcb); - - bool resetSignal = Controller.IsPressed("Reset"); - if (resetSignal) api.CMD_reset(); - - bool powerSignal = Controller.IsPressed("Power"); - if (powerSignal) api.CMD_power(); - - var enables = new LibsnesApi.LayerEnables(); - enables.BG1_Prio0 = _settings.ShowBG1_0; - enables.BG1_Prio1 = _settings.ShowBG1_1; - enables.BG2_Prio0 = _settings.ShowBG2_0; - enables.BG2_Prio1 = _settings.ShowBG2_1; - enables.BG3_Prio0 = _settings.ShowBG3_0; - enables.BG3_Prio1 = _settings.ShowBG3_1; - enables.BG4_Prio0 = _settings.ShowBG4_0; - enables.BG4_Prio1 = _settings.ShowBG4_1; - enables.Obj_Prio0 = _settings.ShowOBJ_0; - enables.Obj_Prio1 = _settings.ShowOBJ_1; - enables.Obj_Prio2 = _settings.ShowOBJ_2; - enables.Obj_Prio3 = _settings.ShowOBJ_3; - api.SetLayerEnables(ref enables); - - RefreshMemoryCallbacks(false); - - //apparently this is one frame? - timeFrameCounter++; - api.CMD_run(); - - //once upon a time we forwarded messages frmo bsnes here, by checking for queued text messages, but I don't think it's needed any longer - - if (IsLagFrame) - LagCount++; - } - void RefreshMemoryCallbacks(bool suppress) { var mcs = MemoryCallbacks; @@ -584,34 +500,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES api.QUERY_set_state_hook_write(!suppress && mcs.HasWrites); } - public ControllerDefinition ControllerDefinition { get { return _controllerDeck.Definition; } } - IController controller; - public IController Controller - { - get { return controller; } - set { controller = value; } - } - - int timeFrameCounter; - public int Frame { get { return timeFrameCounter; } set { timeFrameCounter = value; } } - - public string SystemId { get; private set; } - - public string BoardName { get; private set; } - - // adelikat: Nasty hack to force new business logic. Compatibility (and Accuracy when fully supported) will ALWAYS be in deterministic mode, - // a consequence is a permanent performance hit to the compatibility core - // Perormance will NEVER be in deterministic mode (and the client side logic will prohibit movie recording on it) - // feos: Nasty hack to a nasty hack. Allow user disable it with a strong warning. - public bool DeterministicEmulation - { - get - { - return _settings.ForceDeterminism && - (CurrentProfile == "Compatibility" || CurrentProfile == "Accuracy"); - } - private set { /* Do nothing */ } - } + private int _timeFrameCounter; //public byte[] snes_get_memory_data_read(LibsnesApi.SNES_MEMORY id) //{ @@ -621,13 +510,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES // return ret; //} - public void ResetCounters() - { - timeFrameCounter = 0; - LagCount = 0; - IsLagFrame = false; - } - #region savestates /// @@ -729,14 +611,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES } } - - - - #endregion - public CoreComm CoreComm { get; private set; } - // works for WRAM, garbage for anything else static int? FakeBusMap(int addr) {