Libsnescore - Break off IEmulator implementation into a separate file
This commit is contained in:
parent
8e3c3dab5d
commit
bc42af0fa6
|
@ -10,14 +10,15 @@ namespace BizHawk.Emulation.Common
|
|||
public interface IEmulator : IEmulatorService, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
IEmulatorServiceProvider ServiceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
|
@ -39,17 +40,18 @@ namespace BizHawk.Emulation.Common
|
|||
void FrameAdvance(bool render, bool rendersound = true);
|
||||
|
||||
/// <summary>
|
||||
/// The frame count
|
||||
/// Gets the current frame count
|
||||
/// </summary>
|
||||
int Frame { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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"
|
||||
/// </summary>
|
||||
string SystemId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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; }
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
string BoardName { get; }
|
||||
|
||||
|
@ -69,7 +71,7 @@ namespace BizHawk.Emulation.Common
|
|||
void ResetCounters();
|
||||
|
||||
/// <summary>
|
||||
/// the corecomm module in use by this core.
|
||||
/// Gets the core communications module in use by this core.
|
||||
/// </summary>
|
||||
/// <seealso cref="BizHawk.Emulation.Common.CoreComm" />
|
||||
CoreComm CoreComm { get; }
|
||||
|
|
|
@ -905,6 +905,9 @@
|
|||
<DependentUpon>LibsnesCore.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\SNES\LibsnesCore.IDebuggable.cs">
|
||||
<DependentUpon>LibsnesCore.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\SNES\LibsnesCore.IEmulator.cs">
|
||||
<DependentUpon>LibsnesCore.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\SNES\LibsnesCore.IInputPollable.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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|||
/// <summary>disable all external callbacks. the front end should not even know the core is frame advancing</summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue