From a07263c04e3ed0413cc3d379f0b5f446811bb5ca Mon Sep 17 00:00:00 2001 From: adelikat Date: Thu, 4 Dec 2014 00:43:12 +0000 Subject: [PATCH] Move InputCallbackSystem from CoreComm to IInputPollable, and refactor all cores accordingly. Lua - OnInputPoll() - log to the user when attemping to add a callback of this type to a core that has not implemented input callbacks. Mark all unmanaged cores' implementations of the InputCallbackSystem as FeatureNotImpleented, won't have any effect on functionality, but will help us keep track of the fact that they still have a bit of work to do. Still todo: ActiveChanged event handler on the base implementation of IInputCallbackSystem --- .../lua/EmuLuaLibrary.Events.cs | 25 +++++++++++++++++-- BizHawk.Client.Common/lua/LuaFunctionList.cs | 15 +++++++++-- .../InputCallbackSystem.cs | 24 ++++++++++++++++++ .../BizHawk.Emulation.Common.csproj | 2 ++ BizHawk.Emulation.Common/CoreComms.cs | 24 ------------------ .../Interfaces/IInputCallbackSystem.cs | 19 ++++++++++++++ .../Interfaces/IInputPollable.cs | 2 ++ .../Calculator/TI83.IInputPollable.cs | 2 ++ BizHawk.Emulation.Cores/Calculator/TI83.cs | 3 ++- .../Computers/Commodore64/C64.Input.cs | 2 +- .../Computers/Commodore64/C64.cs | 3 +++ .../Consoles/Atari/2600/Atari2600.Core.cs | 4 +-- .../Atari/2600/Atari2600.IInputPollable.cs | 2 ++ .../Consoles/Atari/2600/Atari2600.cs | 3 ++- .../Atari/7800/Atari7800.IInputPollable.cs | 2 ++ .../Consoles/Atari/7800/Atari7800.cs | 3 ++- .../Consoles/Atari/lynx/Lynx.cs | 8 ++++++ .../Consoles/Coleco/ColecoVision.cs | 3 +++ .../Consoles/Nintendo/GBA/Meteor.cs | 8 +++++- .../Consoles/Nintendo/GBA/VBANext.cs | 9 +++++-- .../Consoles/Nintendo/Gameboy/Gambatte.cs | 7 +++++- .../Consoles/Nintendo/Gameboy/GambatteLink.cs | 12 +++++++-- .../Consoles/Nintendo/N64/N64.cs | 7 +++++- .../Consoles/Nintendo/N64/N64Input.cs | 7 ++++-- .../Consoles/Nintendo/NES/Core.cs | 2 +- .../Consoles/Nintendo/NES/NES.cs | 5 ++-- .../Consoles/Nintendo/QuickNES/QuickNES.cs | 2 ++ .../Consoles/Nintendo/SNES/LibsnesCore.cs | 7 +++++- .../Consoles/PC Engine/Input.cs | 2 +- .../Consoles/PC Engine/PCEngine.cs | 3 +++ .../Consoles/Sega/Genesis/Genesis.cs | 3 +++ .../Consoles/Sega/Genesis/IO.cs | 2 +- .../Consoles/Sega/SMS/Input.cs | 4 +-- .../Consoles/Sega/SMS/SMS.cs | 4 +++ .../Consoles/Sega/Saturn/Yabause.cs | 7 +++++- .../Consoles/Sega/gpgx/GPGX.cs | 7 +++++- .../Consoles/WonderSwan/WonderSwan.cs | 8 ++++-- 37 files changed, 197 insertions(+), 55 deletions(-) create mode 100644 BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs create mode 100644 BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs diff --git a/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs b/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs index ced5e63d01..0d968f100c 100644 --- a/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs +++ b/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs @@ -3,7 +3,8 @@ using System.Linq; using System.ComponentModel; using LuaInterface; - +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Common.IEmulatorExtensions; namespace BizHawk.Client.Common { @@ -155,7 +156,27 @@ namespace BizHawk.Client.Common { var nlf = new NamedLuaFunction(luaf, "OnInputPoll", LogOutputCallback, CurrentThread, name); _luaFunctions.Add(nlf); - Global.Emulator.CoreComm.InputCallback.Add(nlf.Callback); + + if (Global.Emulator.CanPollInput()) + { + try + { + (Global.Emulator as IInputPollable).InputCallbacks.Add(nlf.Callback); + } + catch (NotImplementedException) + { + LogNotImplemented(); + } + } + else + { + LogNotImplemented(); + } + } + + private void LogNotImplemented() + { + Log(string.Format("Error: {0} does not yet implement input polling callbacks")); } [LuaMethodAttributes( diff --git a/BizHawk.Client.Common/lua/LuaFunctionList.cs b/BizHawk.Client.Common/lua/LuaFunctionList.cs index a9959d2d68..d7bce3c587 100644 --- a/BizHawk.Client.Common/lua/LuaFunctionList.cs +++ b/BizHawk.Client.Common/lua/LuaFunctionList.cs @@ -1,6 +1,9 @@ using System.Collections.Generic; using System.Linq; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Common.IEmulatorExtensions; + namespace BizHawk.Client.Common { public class LuaFunctionList : List @@ -15,14 +18,22 @@ namespace BizHawk.Client.Common public new bool Remove(NamedLuaFunction function) { - Global.Emulator.CoreComm.InputCallback.Remove(function.Callback); + if (Global.Emulator.CanPollInput()) + { + (Global.Emulator as IInputPollable).InputCallbacks.Remove(function.Callback); + } + Global.Emulator.CoreComm.MemoryCallbackSystem.Remove(function.Callback); return base.Remove(function); } public void ClearAll() { - Global.Emulator.CoreComm.InputCallback.RemoveAll(this.Select(x => x.Callback)); + if (Global.Emulator.CanPollInput()) + { + (Global.Emulator as IInputPollable).InputCallbacks.RemoveAll(this.Select(x => x.Callback)); + } + Global.Emulator.CoreComm.MemoryCallbackSystem.RemoveAll(this.Select(x => x.Callback)); Clear(); } diff --git a/BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs b/BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs new file mode 100644 index 0000000000..d4bb90aa28 --- /dev/null +++ b/BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace BizHawk.Emulation.Common +{ + public class InputCallbackSystem : List, IInputCallbackSystem + { + public void Call() + { + foreach (var action in this) + { + action(); + } + } + + public void RemoveAll(IEnumerable actions) + { + foreach (var action in actions) + { + this.Remove(action); + } + } + } +} diff --git a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj index 5df5c5e884..0910275921 100644 --- a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj +++ b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj @@ -50,6 +50,7 @@ VersionInfo.cs + @@ -67,6 +68,7 @@ + diff --git a/BizHawk.Emulation.Common/CoreComms.cs b/BizHawk.Emulation.Common/CoreComms.cs index af0ce43dd4..caea890579 100644 --- a/BizHawk.Emulation.Common/CoreComms.cs +++ b/BizHawk.Emulation.Common/CoreComms.cs @@ -14,11 +14,6 @@ namespace BizHawk.Emulation.Common /// public TraceBuffer Tracer = new TraceBuffer(); - /// - /// for emu.on_snoop() - /// - public InputCallbackSystem InputCallback = new InputCallbackSystem(); - public MemoryCallbackSystem MemoryCallbackSystem = new MemoryCallbackSystem(); public double VsyncRate @@ -121,25 +116,6 @@ namespace BizHawk.Emulation.Common private bool logging; } - public class InputCallbackSystem : List - { - public void Call() - { - foreach (var action in this) - { - action(); - } - } - - public void RemoveAll(IEnumerable actions) - { - foreach (var action in actions) - { - this.Remove(action); - } - } - } - public class MemoryCallbackSystem { private readonly List _reads = new List(); diff --git a/BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs b/BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs new file mode 100644 index 0000000000..82204f8ad7 --- /dev/null +++ b/BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; + +namespace BizHawk.Emulation.Common +{ + // TODO: This isn't a CoreService, it is a sub class of a core service, it would be nice to make that clear + public interface IInputCallbackSystem : IList + { + /// + /// Will iterate and call every callback + /// + void Call(); + + /// + /// Will remove the given list of callbacks + /// + void RemoveAll(IEnumerable actions); + } +} diff --git a/BizHawk.Emulation.Common/Interfaces/IInputPollable.cs b/BizHawk.Emulation.Common/Interfaces/IInputPollable.cs index 7fe8495c66..c539206720 100644 --- a/BizHawk.Emulation.Common/Interfaces/IInputPollable.cs +++ b/BizHawk.Emulation.Common/Interfaces/IInputPollable.cs @@ -12,5 +12,7 @@ /// All cores should define it the same, a lag frame is a frame in which input was not polled. /// bool IsLagFrame { get; } + + IInputCallbackSystem InputCallbacks { get; } } } diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IInputPollable.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IInputPollable.cs index 75f3bdf51e..22927c62ee 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IInputPollable.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IInputPollable.cs @@ -14,6 +14,8 @@ namespace BizHawk.Emulation.Cores.Calculators set { _lagCount = value; } } + public IInputCallbackSystem InputCallbacks { get; private set; } + public bool IsLagFrame { get { return _isLag; } diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.cs b/BizHawk.Emulation.Cores/Calculator/TI83.cs index 0a38ac2d0d..21726c2cfa 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.cs @@ -52,6 +52,7 @@ namespace BizHawk.Emulation.Cores.Calculators [CoreConstructor("TI83")] public TI83(CoreComm comm, GameInfo game, byte[] rom, object Settings) { + InputCallbacks = new InputCallbackSystem(); PutSettings((TI83Settings)Settings ?? new TI83Settings()); CoreComm = comm; @@ -186,7 +187,7 @@ namespace BizHawk.Emulation.Cores.Calculators private byte ReadKeyboard() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); //ref TI-9X int ret = 0xFF; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Input.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Input.cs index 4aa9981b1a..096002f352 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Input.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Input.cs @@ -32,7 +32,7 @@ public void PollInput() { - _c64.CoreComm.InputCallback.Call(); + _c64.InputCallbacks.Call(); // scan joysticks pollIndex = 0; for (int j = 0; j < 5; j++) diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs index 4dfd702286..c86e98d02c 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs @@ -186,6 +186,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public bool BinarySaveStatesPreferred { get { return false; } } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } } + private void SetupMemoryDomains() { // chips must be initialized before this code runs! diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs index 85344800cc..784fd0fdd5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs @@ -424,7 +424,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 public byte ReadControls1(bool peek) { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); byte value = 0xFF; if (Controller["P1 Up"]) { value &= 0xEF; } @@ -443,7 +443,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 public byte ReadControls2(bool peek) { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); byte value = 0xFF; if (Controller["P2 Up"]) { value &= 0xEF; } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IInputPollable.cs index ebf520c533..efe6e472c9 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IInputPollable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IInputPollable.cs @@ -15,6 +15,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 get { return _islag; } } + public IInputCallbackSystem InputCallbacks { get; private set; } + private bool _islag = true; private int _lagcount; } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs index 5ec78d6507..8b72367118 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs @@ -24,6 +24,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 [CoreConstructor("A26")] public Atari2600(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { + InputCallbacks = new InputCallbackSystem(); Ram = new byte[128]; CoreComm = comm; Settings = (A2600Settings)settings ?? new A2600Settings(); @@ -137,7 +138,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600 // give the emu a minimal of input\output connections so it doesn't crash var comm = new CoreComm(null, null); - comm.InputCallback = new InputCallbackSystem(); + using (Atari2600 emu = new Atari2600(new CoreComm(null, null), newgame, rom, null, null)) { emu.Controller = new NullController(); diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.IInputPollable.cs index 4ceeceadc3..74937501de 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.IInputPollable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.IInputPollable.cs @@ -15,6 +15,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800 get { return _islag; } } + public IInputCallbackSystem InputCallbacks { get; private set; } + private bool _islag = true; private int _lagcount; } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.cs b/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.cs index 9fc7f5f562..040fe3de51 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/7800/Atari7800.cs @@ -122,6 +122,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800 public Atari7800(CoreComm comm, GameInfo game, byte[] rom, string GameDBfn) { + InputCallbacks = new InputCallbackSystem(); CoreComm = comm; byte[] highscoreBIOS = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS."); byte[] pal_bios = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available."); @@ -186,7 +187,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800 logger); theMachine.Reset(); - theMachine.InputState.InputPollCallback = CoreComm.InputCallback.Call; + theMachine.InputState.InputPollCallback = InputCallbacks.Call; ControlAdapter = new Atari7800Control(theMachine); ControllerDefinition = ControlAdapter.ControlType; diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs index 6c86a7c80d..a405422192 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs @@ -139,6 +139,14 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx public int LagCount { get; set; } public bool IsLagFrame { get; private set; } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks + { + [FeatureNotImplemented]get { return _inputCallbacks; } + } + public string SystemId { get { return "Lynx"; } } public bool DeterministicEmulation { get { return true; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs index bbb0460dbc..85342d7b6a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs @@ -60,6 +60,9 @@ namespace BizHawk.Emulation.Cores.ColecoVision SetupMemoryDomains(); } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } } + public MemoryDomainList MemoryDomains { get { return memoryDomains; } } MemoryDomainList memoryDomains; const ushort RamSizeMask = 0x03FF; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs index 9162d54efb..81a802f3d4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs @@ -87,6 +87,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public int Frame { get; private set; } public int LagCount { get; set; } public bool IsLagFrame { get; private set; } + + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + public string SystemId { get { return "GBA"; } } public bool DeterministicEmulation { get { return true; } } @@ -309,7 +315,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA LibMeteor.Buttons GetInput() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); // libmeteor bitflips everything itself, so 0 == off, 1 == on IsLagFrame = false; LibMeteor.Buttons ret = 0; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs index 8f4a5d251a..b6dd6a530a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs @@ -109,6 +109,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public int LagCount { get; set; } public bool IsLagFrame { get; private set; } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + public string SystemId { get { return "GBA"; } } public bool DeterministicEmulation { get; private set; } @@ -272,7 +277,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA void InitCallbacks() { - padcb = new LibVBANext.StandardCallback(() => CoreComm.InputCallback.Call()); + padcb = new LibVBANext.StandardCallback(() => InputCallbacks.Call()); fetchcb = new LibVBANext.AddressCallback((addr) => CoreComm.MemoryCallbackSystem.CallExecute(addr)); readcb = new LibVBANext.AddressCallback((addr) => CoreComm.MemoryCallbackSystem.CallRead(addr)); writecb = new LibVBANext.AddressCallback((addr) => CoreComm.MemoryCallbackSystem.CallWrite(addr)); @@ -281,7 +286,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA void SyncCallbacks() { - LibVBANext.SetPadCallback(Core, CoreComm.InputCallback.Any() ? padcb : null); + LibVBANext.SetPadCallback(Core, InputCallbacks.Any() ? padcb : null); LibVBANext.SetFetchCallback(Core, CoreComm.MemoryCallbackSystem.HasExecutes ? fetchcb : null); LibVBANext.SetReadCallback(Core, CoreComm.MemoryCallbackSystem.HasReads ? readcb : null); LibVBANext.SetWriteCallback(Core, CoreComm.MemoryCallbackSystem.HasWrites ? writecb : null); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index afd93c46fb..5f70243a26 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -36,6 +36,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy public int LagCount { get; set; } public bool IsLagFrame { get; private set; } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + // all cycle counts are relative to a 2*1024*1024 mhz refclock /// @@ -222,7 +227,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy LibGambatte.Buttons ControllerCallback() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); IsLagFrame = false; return CurrentButtons; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs index 36ba2f5113..956ca4f150 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs @@ -79,10 +79,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy SetMemoryDomains(); - L.CoreComm.InputCallback = CoreComm.InputCallback; - R.CoreComm.InputCallback = CoreComm.InputCallback; + foreach (var callback in InputCallbacks) + { + L.InputCallbacks.Add(callback); + R.InputCallbacks.Add(callback); + } } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + public IVideoProvider VideoProvider { get { return this; } } public ISoundProvider SoundProvider { get { return null; } } public ISyncSoundProvider SyncSoundProvider { get { return this; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs index 2a9cc9fe56..cb856a631a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs @@ -121,7 +121,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64 // Order is important because the register with the mupen core _videoProvider = new N64VideoProvider(api, videosettings); _audioProvider = new N64Audio(api); - _inputProvider = new N64Input(api, comm, this._syncSettings.Controllers); + _inputProvider = new N64Input(this as IInputPollable, api, comm, this._syncSettings.Controllers); string rsp = _syncSettings.Rsp == N64SyncSettings.RspType.Rsp_Hle ? @@ -410,6 +410,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64 api.setWriteCallback(writecb); } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + #endregion } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs index 0a2b2f7c2f..b19f2c5bb0 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs @@ -48,8 +48,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64 } }; - public N64Input(mupen64plusApi core, CoreComm comm, N64SyncSettings.N64ControllerSettings[] controllerSettings) + private readonly IInputPollable _emuCore; + + public N64Input(IInputPollable emuCore, mupen64plusApi core, CoreComm comm, N64SyncSettings.N64ControllerSettings[] controllerSettings) { + _emuCore = emuCore; api = new mupen64plusInputApi(core); CoreComm = comm; @@ -81,7 +84,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64 /// Id of controller to update and shove public int GetControllerInput(int i) { - CoreComm.InputCallback.Call(); + _emuCore.InputCallbacks.Call(); ThisFrameInputPolled = true; // Analog stick right = +X diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs index b7379bb98a..83ecade106 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Core.cs @@ -420,7 +420,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES byte read_joyport(int addr) { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); lagged = false; byte ret = addr == 0x4016 ? ControllerDeck.ReadA(Controller) : ControllerDeck.ReadB(Controller); ret &= 0x1f; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs index c6229ef34a..c29499d30e 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs @@ -322,10 +322,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public int LagCount { get { return _lagcount; } set { _lagcount = value; } } public bool IsLagFrame { get { return islag; } } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } } + public bool DeterministicEmulation { get { return true; } } - - public byte[] CloneSaveRam() { if (board is FDS) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs index ab27154c93..98f9121046 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs @@ -392,6 +392,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES #endregion + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { throw new NotImplementedException(); } } + #region bootgod public RomStatus? BootGodStatus { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs index b20c7620a6..302cc3d41f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -241,6 +241,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES }; } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + [FeatureNotImplemented] public void SetCpuRegister(string register, int value) { @@ -440,7 +445,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES { // as this is implemented right now, only P1 and P2 normal controllers work - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); //Console.WriteLine("{0} {1} {2} {3}", port, device, index, id); string key = "P" + (1 + port) + " "; diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/Input.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/Input.cs index d221ab0479..f50ed0a41f 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/Input.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/Input.cs @@ -64,7 +64,7 @@ namespace BizHawk.Emulation.Cores.PCEngine byte ReadInput() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); byte value = 0x3F; int player = SelectedController + 1; diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs index f4907748e9..b41a00f86b 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs @@ -295,6 +295,9 @@ namespace BizHawk.Emulation.Cores.PCEngine public int LagCount { get { return lagCount; } set { lagCount = value; } } public bool IsLagFrame { get { return isLag; } } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } } + public void ResetCounters() { // this should just be a public setter instead of a new method. diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/Genesis.cs b/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/Genesis.cs index e61ca290ea..3b133c2964 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/Genesis.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/Genesis.cs @@ -45,6 +45,9 @@ namespace BizHawk.Emulation.Cores.Sega.Genesis private SoundMixer SoundMixer; + [FeatureNotImplemented] + public IInputCallbackSystem InputCallbacks { get { throw new NotImplementedException(); } } + public void ResetCounters() { Frame = 0; diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/IO.cs b/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/IO.cs index c7089b3655..b28fcb87f2 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/IO.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/Genesis/IO.cs @@ -108,7 +108,7 @@ namespace BizHawk.Emulation.Cores.Sega.Genesis void ReadController(ref byte data) { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); data &= 0xC0; if ((data & 0x40) != 0) // TH high { diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Input.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Input.cs index a542078f71..5e1f6d0e97 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Input.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Input.cs @@ -42,7 +42,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem byte ReadControls1() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); lagged = false; byte value = 0xFF; @@ -61,7 +61,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem byte ReadControls2() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); lagged = false; byte value = 0xFF; diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs index 5b85649f8d..19af1df9fa 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs @@ -78,6 +78,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem public int Frame { get { return frame; } set { frame = value; } } public int LagCount { get { return lagCount; } set { lagCount = value; } } public bool IsLagFrame { get { return isLag; } } + + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } } + byte Port01 = 0xFF; byte Port02 = 0xFF; byte Port3E = 0xAF; diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Yabause.cs b/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Yabause.cs index a09f015185..1f9460a895 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Yabause.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Yabause.cs @@ -74,7 +74,7 @@ namespace BizHawk.Emulation.Cores.Sega.Saturn ActivateGL(); Init(bios); - InputCallbackH = new LibYabause.InputCallback(() => CoreComm.InputCallback.Call()); + InputCallbackH = new LibYabause.InputCallback(() => InputCallbacks.Call()); LibYabause.libyabause_setinputcallback(InputCallbackH); CoreComm.UsesDriveLed = true; @@ -292,6 +292,11 @@ namespace BizHawk.Emulation.Cores.Sega.Saturn public int LagCount { get; set; } public bool IsLagFrame { get; private set; } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + public string SystemId { get { return "SAT"; } } public bool DeterministicEmulation { get { return true; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs index 052f0abac1..b1e90dbd0c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs @@ -375,10 +375,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx // core callback for input void input_callback() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); IsLagFrame = false; } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } + #endregion // TODO: use render and rendersound diff --git a/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs b/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs index d7d107a76f..689ead4912 100644 --- a/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs +++ b/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs @@ -175,6 +175,10 @@ namespace BizHawk.Emulation.Cores.WonderSwan public int LagCount { get; set; } public bool IsLagFrame { get; private set; } + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + + // TODO: optimize managed to unmanaged using the ActiveChanged event + public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } public string SystemId { get { return "WSWAN"; } } public bool DeterministicEmulation { get; private set; } @@ -351,7 +355,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan } void ButtonCallback() { - CoreComm.InputCallback.Call(); + InputCallbacks.Call(); } void InitDebugCallbacks() @@ -369,7 +373,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan CoreComm.MemoryCallbackSystem.HasWrites ? WriteCallbackD : null, CoreComm.MemoryCallbackSystem.HasExecutes ? ExecCallbackD : null); BizSwan.bizswan_setbuttoncallback(Core, - CoreComm.InputCallback.Any() ? ButtonCallbackD : null); + InputCallbacks.Any() ? ButtonCallbackD : null); } #endregion