From 8da543b1a5b1b7371365b70a04e0f2ef9bf6e4e3 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sat, 30 Nov 2019 23:31:18 +1000 Subject: [PATCH] Migrate EmulatorLuaLibrary to ApiHawk delegation `emu.setrenderplanes(bool...)` now works when using BSNES or Genplus-gx --- BizHawk.Client.Common/Api/Classes/EmuApi.cs | 29 +- .../lua/EmuLuaLibrary.Emu.cs | 283 ++---------------- 2 files changed, 38 insertions(+), 274 deletions(-) diff --git a/BizHawk.Client.Common/Api/Classes/EmuApi.cs b/BizHawk.Client.Common/Api/Classes/EmuApi.cs index 4e5dbf7029..6c1cc14f5e 100644 --- a/BizHawk.Client.Common/Api/Classes/EmuApi.cs +++ b/BizHawk.Client.Common/Api/Classes/EmuApi.cs @@ -18,6 +18,15 @@ namespace BizHawk.Client.Common [Description("A library for interacting with the currently loaded emulator core")] public sealed class EmuApi : IEmu { + public EmuApi(Action logCallback) + { + LogCallback = logCallback; + } + + public EmuApi() : this(Console.WriteLine) {} + + private readonly Action LogCallback; + private static class EmuStatic { public static void DisplayVsync(bool enabled) @@ -37,8 +46,8 @@ namespace BizHawk.Client.Common { Global.Config.AutoMinimizeSkipping = enabled; } - } + [RequiredService] private IEmulator Emulator { get; set; } @@ -100,7 +109,7 @@ namespace BizHawk.Client.Common } catch (NotImplementedException) { - Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()"); + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()"); return null; } } @@ -121,7 +130,7 @@ namespace BizHawk.Client.Common } catch (NotImplementedException) { - Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); return null; } } @@ -144,7 +153,7 @@ namespace BizHawk.Client.Common } catch (NotImplementedException) { - Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); } return table; @@ -163,7 +172,7 @@ namespace BizHawk.Client.Common } catch (NotImplementedException) { - Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()"); + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()"); } } @@ -180,7 +189,7 @@ namespace BizHawk.Client.Common } catch (NotImplementedException) { - Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()"); + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()"); return 0; } @@ -198,7 +207,7 @@ namespace BizHawk.Client.Common return InputPollableCore.IsLagFrame; } - Console.WriteLine($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); + LogCallback($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); return false; } @@ -210,7 +219,7 @@ namespace BizHawk.Client.Common } else { - Console.WriteLine($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); + LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); } } @@ -221,7 +230,7 @@ namespace BizHawk.Client.Common return InputPollableCore.LagCount; } - Console.WriteLine($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); + LogCallback($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); return 0; } @@ -233,7 +242,7 @@ namespace BizHawk.Client.Common } else { - Console.WriteLine($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); + LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); } } diff --git a/BizHawk.Client.Common/lua/EmuLuaLibrary.Emu.cs b/BizHawk.Client.Common/lua/EmuLuaLibrary.Emu.cs index c723353e7e..724ae492ba 100644 --- a/BizHawk.Client.Common/lua/EmuLuaLibrary.Emu.cs +++ b/BizHawk.Client.Common/lua/EmuLuaLibrary.Emu.cs @@ -1,14 +1,6 @@ using System; using System.ComponentModel; -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Common.IEmulatorExtensions; -using BizHawk.Emulation.Cores.Nintendo.NES; -using BizHawk.Emulation.Cores.PCEngine; -using BizHawk.Emulation.Cores.Sega.MasterSystem; -using BizHawk.Emulation.Cores.WonderSwan; -using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES; - using NLua; // ReSharper disable UnusedMember.Global @@ -16,29 +8,8 @@ using NLua; namespace BizHawk.Client.Common { [Description("A library for interacting with the currently loaded emulator core")] - public sealed class EmulatorLuaLibrary : LuaLibraryBase + public sealed class EmulatorLuaLibrary : DelegatingLuaLibrary { - [RequiredService] - private IEmulator Emulator { get; set; } - - [OptionalService] - private IDebuggable DebuggableCore { get; set; } - - [OptionalService] - private IDisassemblable DisassemblableCore { get; set; } - - [OptionalService] - private IMemoryDomains MemoryDomains { get; set; } - - [OptionalService] - private IInputPollable InputPollableCore { get; set; } - - [OptionalService] - private IRegionable RegionableCore { get; set; } - - [OptionalService] - private IBoardInfo BoardInfo { get; set; } - public Action FrameAdvanceCallback { get; set; } public Action YieldCallback { get; set; } @@ -52,10 +23,7 @@ namespace BizHawk.Client.Common [LuaMethodExample("emu.displayvsync( true );")] [LuaMethod("displayvsync", "Sets the display vsync property of the emulator")] - public static void DisplayVsync(bool enabled) - { - Global.Config.VSync = enabled; - } + public void DisplayVsync(bool enabled) => APIs.Emu.DisplayVsync(enabled); [LuaMethodExample("emu.frameadvance( );")] [LuaMethod("frameadvance", "Signals to the emulator to resume emulation. Necessary for any lua script while loop or else the emulator will freeze!")] @@ -66,269 +34,66 @@ namespace BizHawk.Client.Common [LuaMethodExample("local inemufra = emu.framecount( );")] [LuaMethod("framecount", "Returns the current frame count")] - public int FrameCount() - { - return Emulator.Frame; - } + public int FrameCount() => APIs.Emu.FrameCount(); [LuaMethodExample("local obemudis = emu.disassemble( 0x8000 );")] [LuaMethod("disassemble", "Returns the disassembly object (disasm string and length int) for the given PC address. Uses System Bus domain if no domain name provided")] - public object Disassemble(uint pc, string name = "") - { - try - { - if (DisassemblableCore == null) - { - throw new NotImplementedException(); - } - - int l; - MemoryDomain domain = MemoryDomains.SystemBus; - - if (!string.IsNullOrEmpty(name)) - { - domain = MemoryDomains[name]; - } - - var d = DisassemblableCore.Disassemble(domain, pc, out l); - return new { disasm = d, length = l }; - } - catch (NotImplementedException) - { - Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()"); - return null; - } - } + public object Disassemble(uint pc, string name = "") => APIs.Emu.Disassemble(pc, name); // TODO: what about 64 bit registers? [LuaMethodExample("local inemuget = emu.getregister( emu.getregisters( )[ 0 ] );")] [LuaMethod("getregister", "returns the value of a cpu register or flag specified by name. For a complete list of possible registers or flags for a given core, use getregisters")] - public int GetRegister(string name) - { - try - { - if (DebuggableCore == null) - { - throw new NotImplementedException(); - } - - var registers = DebuggableCore.GetCpuFlagsAndRegisters(); - return registers.ContainsKey(name) - ? (int)registers[name].Value - : 0; - } - catch (NotImplementedException) - { - Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); - return 0; - } - } + public int GetRegister(string name) => (int?) APIs.Emu.GetRegister(name) ?? 0; [LuaMethodExample("local nlemuget = emu.getregisters( );")] [LuaMethod("getregisters", "returns the complete set of available flags and registers for a given core")] public LuaTable GetRegisters() { + var result = APIs.Emu.GetRegisters(); var table = Lua.NewTable(); - - try - { - if (DebuggableCore == null) - { - throw new NotImplementedException(); - } - - foreach (var kvp in DebuggableCore.GetCpuFlagsAndRegisters()) - { - table[kvp.Key] = kvp.Value.Value; - } - } - catch (NotImplementedException) - { - Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); - } - + foreach (var kvp in result) table[kvp.Key] = kvp.Value; return table; } [LuaMethodExample("emu.setregister( emu.getregisters( )[ 0 ], -1000 );")] [LuaMethod("setregister", "sets the given register name to the given value")] - public void SetRegister(string register, int value) - { - try - { - if (DebuggableCore == null) - { - throw new NotImplementedException(); - } - - DebuggableCore.SetCpuRegister(register, value); - } - catch (NotImplementedException) - { - Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()"); - } - } + public void SetRegister(string register, int value) => APIs.Emu.SetRegister(register, value); [LuaMethodExample("local inemutot = emu.totalexecutedcycles( );")] [LuaMethod("totalexecutedcycles", "gets the total number of executed cpu cycles")] - public long TotalExecutedycles() - { - try - { - if (DebuggableCore == null) - { - throw new NotImplementedException(); - } - - return DebuggableCore.TotalExecutedCycles; - } - catch (NotImplementedException) - { - Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()"); - - return 0; - } - } + public long TotalExecutedycles() => APIs.Emu.TotalExecutedCycles(); [LuaMethodExample("local stemuget = emu.getsystemid( );")] [LuaMethod("getsystemid", "Returns the ID string of the current core loaded. Note: No ROM loaded will return the string NULL")] - public static string GetSystemId() - { - return Global.Game.System; - } + public string GetSystemId() => APIs.Emu.GetSystemId(); [LuaMethodExample("if ( emu.islagged( ) ) then\r\n\tconsole.log( \"Returns whether or not the current frame is a lag frame\" );\r\nend;")] [LuaMethod("islagged", "Returns whether or not the current frame is a lag frame")] - public bool IsLagged() - { - if (InputPollableCore != null) - { - return InputPollableCore.IsLagFrame; - } - - Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); - return false; - } + public bool IsLagged() => APIs.Emu.IsLagged(); [LuaMethodExample("emu.setislagged( true );")] [LuaMethod("setislagged", "Sets the lag flag for the current frame. If no value is provided, it will default to true")] - public void SetIsLagged(bool value = true) - { - if (InputPollableCore != null) - { - InputPollableCore.IsLagFrame = value; - } - else - { - Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); - } - } + public void SetIsLagged(bool value = true) => APIs.Emu.SetIsLagged(value); [LuaMethodExample("local inemulag = emu.lagcount( );")] [LuaMethod("lagcount", "Returns the current lag count")] - public int LagCount() - { - if (InputPollableCore != null) - { - return InputPollableCore.LagCount; - } - - Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); - return 0; - } + public int LagCount() => APIs.Emu.LagCount(); [LuaMethodExample("emu.setlagcount( 50 );")] [LuaMethod("setlagcount", "Sets the current lag count")] - public void SetLagCount(int count) - { - if (InputPollableCore != null) - { - InputPollableCore.LagCount = count; - } - else - { - Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); - } - } + public void SetLagCount(int count) => APIs.Emu.SetLagCount(count); [LuaMethodExample("emu.limitframerate( true );")] [LuaMethod("limitframerate", "sets the limit framerate property of the emulator")] - public static void LimitFramerate(bool enabled) - { - Global.Config.ClockThrottle = enabled; - } + public void LimitFramerate(bool enabled) => APIs.Emu.LimitFramerate(enabled); [LuaMethodExample("emu.minimizeframeskip( true );")] [LuaMethod("minimizeframeskip", "Sets the autominimizeframeskip value of the emulator")] - public static void MinimizeFrameskip(bool enabled) - { - Global.Config.AutoMinimizeSkipping = enabled; - } + public void MinimizeFrameskip(bool enabled) => APIs.Emu.MinimizeFrameskip(enabled); [LuaMethodExample("emu.setrenderplanes( true, false );")] [LuaMethod("setrenderplanes", "Toggles the drawing of sprites and background planes. Set to false or nil to disable a pane, anything else will draw them")] - public void SetRenderPlanes(params bool[] luaParam) - { - if (Emulator is NES nes) - { - // in the future, we could do something more arbitrary here. - // but this isn't any worse than the old system - var s = nes.GetSettings(); - s.DispSprites = luaParam[0]; - s.DispBackground = luaParam[1]; - nes.PutSettings(s); - } - else if (Emulator is QuickNES quicknes) - { - var s = quicknes.GetSettings(); - - // this core doesn't support disabling BG - bool showSp = GetSetting(0, luaParam); - if (showSp && s.NumSprites == 0) - { - s.NumSprites = 8; - } - else if (!showSp && s.NumSprites > 0) - { - s.NumSprites = 0; - } - - quicknes.PutSettings(s); - } - else if (Emulator is PCEngine pce) - { - var s = pce.GetSettings(); - s.ShowOBJ1 = GetSetting(0, luaParam); - s.ShowBG1 = GetSetting(1, luaParam); - if (luaParam.Length > 2) - { - s.ShowOBJ2 = GetSetting(2, luaParam); - s.ShowBG2 = GetSetting(3, luaParam); - } - - pce.PutSettings(s); - } - else if (Emulator is SMS sms) - { - var s = sms.GetSettings(); - s.DispOBJ = GetSetting(0, luaParam); - s.DispBG = GetSetting(1, luaParam); - sms.PutSettings(s); - } - else if (Emulator is WonderSwan ws) - { - var s = ws.GetSettings(); - s.EnableSprites = GetSetting(0, luaParam); - s.EnableFG = GetSetting(1, luaParam); - s.EnableBG = GetSetting(2, luaParam); - ws.PutSettings(s); - } - } - - private static bool GetSetting(int index, bool[] settings) - { - return index >= settings.Length || settings[index]; - } + public void SetRenderPlanes(params bool[] luaParam) => APIs.Emu.SetRenderPlanes(luaParam); [LuaMethodExample("emu.yield( );")] [LuaMethod("yield", "allows a script to run while emulation is paused and interact with the gui/main window in realtime ")] @@ -339,21 +104,11 @@ namespace BizHawk.Client.Common [LuaMethodExample("local stemuget = emu.getdisplaytype();")] [LuaMethod("getdisplaytype", "returns the display type (PAL vs NTSC) that the emulator is currently running in")] - public string GetDisplayType() - { - return RegionableCore != null - ? RegionableCore.Region.ToString() - : ""; - } + public string GetDisplayType() => APIs.Emu.GetDisplayType(); [LuaMethodExample("local stemuget = emu.getboardname();")] [LuaMethod("getboardname", "returns (if available) the board name of the loaded ROM")] - public string GetBoardName() - { - return BoardInfo != null - ? BoardInfo.BoardName - : ""; - } + public string GetBoardName() => APIs.Emu.GetBoardName(); [LuaMethod("getluacore", "returns the name of the Lua core currently in use")] public string GetLuaBackend()