diff --git a/BizHawk.Client.Common/Api/Classes/EmuApi.cs b/BizHawk.Client.Common/Api/Classes/EmuApi.cs index 1f40a62691..ed362f8d6c 100644 --- a/BizHawk.Client.Common/Api/Classes/EmuApi.cs +++ b/BizHawk.Client.Common/Api/Classes/EmuApi.cs @@ -1,23 +1,43 @@ using System; -using System.ComponentModel; using System.Collections.Generic; +using System.ComponentModel; -using BizHawk.Client.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.IEmulatorExtensions; +using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES; +using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; using BizHawk.Emulation.Cores.Nintendo.NES; using BizHawk.Emulation.Cores.Nintendo.SNES; using BizHawk.Emulation.Cores.PCEngine; -using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; using BizHawk.Emulation.Cores.Sega.MasterSystem; using BizHawk.Emulation.Cores.WonderSwan; -using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES; namespace BizHawk.Client.Common { [Description("A library for interacting with the currently loaded emulator core")] public sealed class EmuApi : IEmu { + [RequiredService] + private IEmulator Emulator { get; set; } + + [OptionalService] + private IBoardInfo BoardInfo { get; set; } + + [OptionalService] + private IDebuggable DebuggableCore { get; set; } + + [OptionalService] + private IDisassemblable DisassemblableCore { get; set; } + + [OptionalService] + private IInputPollable InputPollableCore { get; set; } + + [OptionalService] + private IMemoryDomains MemoryDomains { get; set; } + + [OptionalService] + private IRegionable RegionableCore { get; set; } + public EmuApi(Action logCallback) { LogCallback = logCallback; @@ -27,415 +47,248 @@ namespace BizHawk.Client.Common private readonly Action LogCallback; - private static class EmuStatic - { - public static void DisplayVsync(bool enabled) - { - Global.Config.VSync = enabled; - } - public static string GetSystemId() - { - return Global.Game.System; - } - public static void LimitFramerate(bool enabled) - { - Global.Config.ClockThrottle = enabled; - } - - public static void MinimizeFrameskip(bool enabled) - { - Global.Config.AutoMinimizeSkipping = enabled; - } - } - - [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; } - public void DisplayVsync(bool enabled) - { - EmuStatic.DisplayVsync(enabled); - } + public void DisplayVsync(bool enabled) => Global.Config.VSync = enabled; - public void FrameAdvance() - { - FrameAdvanceCallback(); - } + public void FrameAdvance() => FrameAdvanceCallback(); - public int FrameCount() - { - return Emulator.Frame; - } + public int FrameCount() => Emulator.Frame; public object Disassemble(uint pc, string name = "") { try { - if (DisassemblableCore == null) + if (DisassemblableCore != null) { - throw new NotImplementedException(); + return new { + disasm = DisassemblableCore.Disassemble( + string.IsNullOrEmpty(name) ? MemoryDomains.SystemBus : MemoryDomains[name], + pc, + out var l + ), + length = l + }; } - - MemoryDomain domain = MemoryDomains.SystemBus; - - if (!string.IsNullOrEmpty(name)) - { - domain = MemoryDomains[name]; - } - - int l; - var d = DisassemblableCore.Disassemble(domain, pc, out l); - return new { disasm = d, length = l }; - } - catch (NotImplementedException) - { - LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()"); - return null; } + catch (NotImplementedException) {} + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()"); + return null; } public ulong? GetRegister(string name) { try { - if (DebuggableCore == null) + if (DebuggableCore != null) { - throw new NotImplementedException(); + var registers = DebuggableCore.GetCpuFlagsAndRegisters(); + return registers.ContainsKey(name) ? registers[name].Value : default; } - - var registers = DebuggableCore.GetCpuFlagsAndRegisters(); - ulong? value = null; - if (registers.ContainsKey(name)) value = registers[name].Value; - return value; - } - catch (NotImplementedException) - { - LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); - return null; } + catch (NotImplementedException) {} + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); + return null; } public Dictionary GetRegisters() { - var table = new Dictionary(); - try { - if (DebuggableCore == null) + if (DebuggableCore != null) { - throw new NotImplementedException(); - } - - foreach (var kvp in DebuggableCore.GetCpuFlagsAndRegisters()) - { - table[kvp.Key] = kvp.Value.Value; + var table = new Dictionary(); + foreach (var kvp in DebuggableCore.GetCpuFlagsAndRegisters()) table[kvp.Key] = kvp.Value.Value; + return table; } } - catch (NotImplementedException) - { - LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); - } - - return table; + catch (NotImplementedException) {} + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()"); + return new Dictionary(); } public void SetRegister(string register, int value) { try { - if (DebuggableCore == null) + if (DebuggableCore != null) { - throw new NotImplementedException(); + DebuggableCore.SetCpuRegister(register, value); + return; } - - DebuggableCore.SetCpuRegister(register, value); - } - catch (NotImplementedException) - { - LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()"); } + catch (NotImplementedException) {} + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()"); } public long TotalExecutedCycles() { try { - if (DebuggableCore == null) - { - throw new NotImplementedException(); - } - - return DebuggableCore.TotalExecutedCycles; - } - catch (NotImplementedException) - { - LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()"); - - return 0; + if (DebuggableCore != null) return DebuggableCore.TotalExecutedCycles; } + catch (NotImplementedException) {} + LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()"); + return default; } - public string GetSystemId() - { - return EmuStatic.GetSystemId(); - } + public string GetSystemId() => Global.Game.System; public bool IsLagged() { - if (InputPollableCore != null) - { - return InputPollableCore.IsLagFrame; - } - + if (InputPollableCore != null) return InputPollableCore.IsLagFrame; LogCallback($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); return false; } public void SetIsLagged(bool value = true) { - if (InputPollableCore != null) - { - InputPollableCore.IsLagFrame = value; - } - else - { - LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); - } + if (InputPollableCore != null) InputPollableCore.IsLagFrame = value; + else LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); } public int LagCount() { - if (InputPollableCore != null) - { - return InputPollableCore.LagCount; - } - + if (InputPollableCore != null) return InputPollableCore.LagCount; LogCallback($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); - return 0; + return default; } public void SetLagCount(int count) { - if (InputPollableCore != null) - { - InputPollableCore.LagCount = count; - } - else - { - LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); - } + if (InputPollableCore != null) InputPollableCore.LagCount = count; + else LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}"); } - public void LimitFramerate(bool enabled) + public void LimitFramerate(bool enabled) => Global.Config.ClockThrottle = enabled; + + public void MinimizeFrameskip(bool enabled) => Global.Config.AutoMinimizeSkipping = enabled; + + public void Yield() => YieldCallback(); + + public string GetDisplayType() => (RegionableCore?.Region)?.ToString() ?? ""; + + public string GetBoardName() => BoardInfo?.BoardName ?? ""; + + public object GetSettings() => Emulator switch { - EmuStatic.LimitFramerate(enabled); - } + GPGX gpgx => gpgx.GetSettings(), + LibsnesCore snes => snes.GetSettings(), + NES nes => nes.GetSettings(), + PCEngine pce => pce.GetSettings(), + QuickNES quickNes => quickNes.GetSettings(), + SMS sms => sms.GetSettings(), + WonderSwan ws => ws.GetSettings(), + _ => (object) null + }; - public void MinimizeFrameskip(bool enabled) + public bool PutSettings(object settings) => Emulator switch { - EmuStatic.MinimizeFrameskip(enabled); - } + GPGX gpgx => gpgx.PutSettings((GPGX.GPGXSettings) settings), + LibsnesCore snes => snes.PutSettings((LibsnesCore.SnesSettings) settings), + NES nes => nes.PutSettings((NES.NESSettings) settings), + PCEngine pce => pce.PutSettings((PCEngine.PCESettings) settings), + QuickNES quickNes => quickNes.PutSettings((QuickNES.QuickNESSettings) settings), + SMS sms => sms.PutSettings((SMS.SMSSettings) settings), + WonderSwan ws => ws.PutSettings((WonderSwan.Settings) settings), + _ => false + }; - public void Yield() - { - YieldCallback(); - } - - public string GetDisplayType() - { - return RegionableCore != null - ? RegionableCore.Region.ToString() - : ""; - } - - public string GetBoardName() - { - return BoardInfo != null - ? BoardInfo.BoardName - : ""; - } - public object GetSettings() - { - if (Emulator is GPGX gpgx) - { - return gpgx.GetSettings(); - } - - if (Emulator is LibsnesCore snes) - { - return snes.GetSettings(); - } - - if (Emulator is NES nes) - { - return nes.GetSettings(); - } - - if (Emulator is QuickNES quickNes) - { - return quickNes.GetSettings(); - } - - if (Emulator is PCEngine pce) - { - return pce.GetSettings(); - } - - if (Emulator is SMS sms) - { - return sms.GetSettings(); - } - - if (Emulator is WonderSwan ws) - { - return ws.GetSettings(); - } - - return null; - } - public bool PutSettings(object settings) - { - if (Emulator is GPGX gpgx) - { - return gpgx.PutSettings(settings as GPGX.GPGXSettings); - } - - if (Emulator is LibsnesCore snes) - { - return snes.PutSettings(settings as LibsnesCore.SnesSettings); - } - - if (Emulator is NES nes) - { - return nes.PutSettings(settings as NES.NESSettings); - } - - if (Emulator is QuickNES quickNes) - { - return quickNes.PutSettings(settings as QuickNES.QuickNESSettings); - } - - if (Emulator is PCEngine pce) - { - return pce.PutSettings(settings as PCEngine.PCESettings); - } - - if (Emulator is SMS sms) - { - return sms.PutSettings(settings as SMS.SMSSettings); - } - - if (Emulator is WonderSwan ws) - { - return ws.PutSettings(settings as WonderSwan.Settings); - } - - return false; - } public void SetRenderPlanes(params bool[] args) { - if (Emulator is GPGX gpgx) + static bool GetSetting(bool[] settings, int index) => index >= settings.Length || settings[index]; + void SetBSNES(LibsnesCore core) { - var s = gpgx.GetSettings(); - s.DrawBGA = args[0]; - s.DrawBGB = args[1]; - s.DrawBGW = args[2]; - s.DrawObj = args[3]; - gpgx.PutSettings(s); - + var s = core.GetSettings(); + s.ShowBG1_0 = s.ShowBG1_1 = GetSetting(args, 0); + s.ShowBG2_0 = s.ShowBG2_1 = GetSetting(args, 1); + s.ShowBG3_0 = s.ShowBG3_1 = GetSetting(args, 2); + s.ShowBG4_0 = s.ShowBG4_1 = GetSetting(args, 3); + s.ShowOBJ_0 = GetSetting(args, 4); + s.ShowOBJ_1 = GetSetting(args, 5); + s.ShowOBJ_2 = GetSetting(args, 6); + s.ShowOBJ_3 = GetSetting(args, 7); + core.PutSettings(s); } - else if (Emulator is LibsnesCore snes) - { - var s = snes.GetSettings(); - s.ShowBG1_0 = s.ShowBG1_1 = args[0]; - s.ShowBG2_0 = s.ShowBG2_1 = args[1]; - s.ShowBG3_0 = s.ShowBG3_1 = args[2]; - s.ShowBG4_0 = s.ShowBG4_1 = args[3]; - s.ShowOBJ_0 = args[4]; - s.ShowOBJ_1 = args[5]; - s.ShowOBJ_2 = args[6]; - s.ShowOBJ_3 = args[7]; - snes.PutSettings(s); - } - else 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 = args[0]; - s.DispBackground = args[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, args); - 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, args); - s.ShowBG1 = GetSetting(1, args); - if (args.Length > 2) - { - s.ShowOBJ2 = GetSetting(2, args); - s.ShowBG2 = GetSetting(3, args); - } - - pce.PutSettings(s); - } - else if (Emulator is SMS sms) - { - var s = sms.GetSettings(); - s.DispOBJ = GetSetting(0, args); - s.DispBG = GetSetting(1, args); - sms.PutSettings(s); - } - else if (Emulator is WonderSwan ws) + void SetCygne(WonderSwan ws) { var s = ws.GetSettings(); - s.EnableSprites = GetSetting(0, args); - s.EnableFG = GetSetting(1, args); - s.EnableBG = GetSetting(2, args); + s.EnableSprites = GetSetting(args, 0); + s.EnableFG = GetSetting(args, 1); + s.EnableBG = GetSetting(args, 2); ws.PutSettings(s); } - } - - private static bool GetSetting(int index, bool[] settings) - { - return index >= settings.Length || settings[index]; + void SetGPGX(GPGX core) + { + var s = core.GetSettings(); + s.DrawBGA = GetSetting(args, 0); + s.DrawBGB = GetSetting(args, 1); + s.DrawBGW = GetSetting(args, 2); + s.DrawObj = GetSetting(args, 3); + core.PutSettings(s); + } + void SetNesHawk(NES core) + { + var s = core.GetSettings(); + // in the future, we could do something more arbitrary here, but this isn't any worse than the old system + s.DispSprites = GetSetting(args, 0); + s.DispBackground = GetSetting(args, 1); + core.PutSettings(s); + } + void SetPCEHawk(PCEngine pce) + { + var s = pce.GetSettings(); + s.ShowOBJ1 = GetSetting(args, 0); + s.ShowBG1 = GetSetting(args, 1); + if (args.Length > 2) + { + s.ShowOBJ2 = GetSetting(args, 2); + s.ShowBG2 = GetSetting(args, 3); + } + pce.PutSettings(s); + } + void SetQuickNES(QuickNES quicknes) + { + var s = quicknes.GetSettings(); + // this core doesn't support disabling BG + var showSp = GetSetting(args, 0); + if (showSp && s.NumSprites == 0) s.NumSprites = 8; + else if (!showSp && s.NumSprites > 0) s.NumSprites = 0; + quicknes.PutSettings(s); + } + void SetSMSHawk(SMS sms) + { + var s = sms.GetSettings(); + s.DispOBJ = GetSetting(args, 0); + s.DispBG = GetSetting(args, 1); + sms.PutSettings(s); + } + switch (Emulator) + { + case GPGX gpgx: + SetGPGX(gpgx); + break; + case LibsnesCore snes: + SetBSNES(snes); + break; + case NES nes: + SetNesHawk(nes); + break; + case PCEngine pce: + SetPCEHawk(pce); + break; + case QuickNES quicknes: + SetQuickNES(quicknes); + break; + case SMS sms: + SetSMSHawk(sms); + break; + case WonderSwan ws: + SetCygne(ws); + break; + } } } } diff --git a/BizHawk.Client.Common/Api/Classes/GameInfoApi.cs b/BizHawk.Client.Common/Api/Classes/GameInfoApi.cs index 52c8b017a5..2107c29999 100644 --- a/BizHawk.Client.Common/Api/Classes/GameInfoApi.cs +++ b/BizHawk.Client.Common/Api/Classes/GameInfoApi.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; -using BizHawk.Client.Common; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -10,53 +9,23 @@ namespace BizHawk.Client.Common [OptionalService] private IBoardInfo BoardInfo { get; set; } - public string GetRomName() - { - return Global.Game?.Name ?? ""; - } + public string GetRomName() => Global.Game?.Name ?? ""; - public string GetRomHash() - { - return Global.Game?.Hash ?? ""; - } + public string GetRomHash() => Global.Game?.Hash ?? ""; - public bool InDatabase() - { - if (Global.Game != null) - { - return !Global.Game.NotInDatabase; - } + public bool InDatabase() => Global.Game?.NotInDatabase == false; - return false; - } + public string GetStatus() => Global.Game?.Status.ToString(); - public string GetStatus() - { - return Global.Game?.Status.ToString(); - } + public bool IsStatusBad() => Global.Game?.IsRomStatusBad() != false; - public bool IsStatusBad() - { - return Global.Game?.IsRomStatusBad() ?? true; - } - - public string GetBoardType() - { - return BoardInfo?.BoardName ?? ""; - } + public string GetBoardType() => BoardInfo?.BoardName ?? ""; public Dictionary GetOptions() { var options = new Dictionary(); - - if (Global.Game != null) - { - foreach (var option in Global.Game.GetOptionsDict()) - { - options[option.Key] = option.Value; - } - } - + if (Global.Game == null) return options; + foreach (var option in Global.Game.GetOptionsDict()) options[option.Key] = option.Value; return options; } } diff --git a/BizHawk.Client.Common/Api/Classes/JoypadApi.cs b/BizHawk.Client.Common/Api/Classes/JoypadApi.cs index d2ca5ec8db..bc08a08c7a 100644 --- a/BizHawk.Client.Common/Api/Classes/JoypadApi.cs +++ b/BizHawk.Client.Common/Api/Classes/JoypadApi.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using BizHawk.Client.Common; - namespace BizHawk.Client.Common { public sealed class JoypadApi : IJoypad @@ -16,195 +14,93 @@ namespace BizHawk.Client.Common private readonly Action LogCallback; - public Dictionary Get(int? controller = null) + public Dictionary Get(int? controller = null) { - var buttons = new Dictionary(); var adapter = Global.AutofireStickyXORAdapter; + var buttons = new Dictionary(); foreach (var button in adapter.Source.Definition.BoolButtons) { - if (!controller.HasValue) + if (controller == null) buttons[button] = adapter.IsPressed(button); + else if (button.Length > 2 && button.Substring(0, 2) == $"P{controller}") { - buttons[button] = adapter.IsPressed(button); - } - else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}") - { - buttons[button.Substring(3)] = adapter.IsPressed($"P{controller} {button.Substring(3)}"); + var sub = button.Substring(3); + buttons[sub] = adapter.IsPressed($"P{controller} {sub}"); } } - foreach (var button in adapter.Source.Definition.FloatControls) { - if (controller == null) + if (controller == null) buttons[button] = adapter.GetFloat(button); + else if (button.Length > 2 && button.Substring(0, 2) == $"P{controller}") { - buttons[button] = adapter.GetFloat(button); - } - else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}") - { - buttons[button.Substring(3)] = adapter.GetFloat($"P{controller} {button.Substring(3)}"); + var sub = button.Substring(3); + buttons[sub] = adapter.GetFloat($"P{controller} {sub}"); } } - return buttons; } public Dictionary GetImmediate() { - var buttons = new Dictionary(); var adapter = Global.ActiveController; - foreach (var button in adapter.Definition.BoolButtons) - { - buttons[button] = adapter.IsPressed(button); - } - - foreach (var button in adapter.Definition.FloatControls) - { - buttons[button] = adapter.GetFloat(button); - } - + var buttons = new Dictionary(); + foreach (var button in adapter.Definition.BoolButtons) buttons[button] = adapter.IsPressed(button); + foreach (var button in adapter.Definition.FloatControls) buttons[button] = adapter.GetFloat(button); return buttons; } public void SetFromMnemonicStr(string inputLogEntry) { + var lg = Global.MovieSession.MovieControllerInstance(); try { - var lg = Global.MovieSession.MovieControllerInstance(); lg.SetControllersAsMnemonic(inputLogEntry); - - foreach (var button in lg.Definition.BoolButtons) - { - Global.ButtonOverrideAdaptor.SetButton(button, lg.IsPressed(button)); - } - - foreach (var floatButton in lg.Definition.FloatControls) - { - Global.ButtonOverrideAdaptor.SetFloat(floatButton, lg.GetFloat(floatButton)); - } } catch (Exception) { LogCallback($"invalid mnemonic string: {inputLogEntry}"); + return; } + foreach (var button in lg.Definition.BoolButtons) Global.ButtonOverrideAdaptor.SetButton(button, lg.IsPressed(button)); + foreach (var floatButton in lg.Definition.FloatControls) Global.ButtonOverrideAdaptor.SetFloat(floatButton, lg.GetFloat(floatButton)); } - public void Set(Dictionary buttons, int? controller = null) + public void Set(Dictionary buttons, int? controller = null) { - try + foreach (var button in Global.ActiveController.Definition.BoolButtons) { - foreach (var button in buttons.Keys) - { - var invert = false; - bool? theValue; - var theValueStr = buttons[button].ToString(); - - if (!string.IsNullOrWhiteSpace(theValueStr)) - { - if (theValueStr.ToLower() == "false") - { - theValue = false; - } - else if (theValueStr.ToLower() == "true") - { - theValue = true; - } - else - { - invert = true; - theValue = null; - } - } - else - { - theValue = null; - } - - var toPress = button; - if (controller.HasValue) - { - toPress = $"P{controller} {button}"; - } - - if (!invert) - { - if (theValue.HasValue) // Force - { - Global.ButtonOverrideAdaptor.SetButton(toPress, theValue.Value); - Global.ActiveController.Overrides(Global.ButtonOverrideAdaptor); - } - else // Unset - { - Global.ButtonOverrideAdaptor.UnSet(toPress); - Global.ActiveController.Overrides(Global.ButtonOverrideAdaptor); - } - } - else // Inverse - { - Global.ButtonOverrideAdaptor.SetInverse(toPress); - Global.ActiveController.Overrides(Global.ButtonOverrideAdaptor); - } - } - } - catch - { - /*Eat it*/ + Set(button, buttons.TryGetValue(button, out var state) ? state : default, controller); } } + public void Set(string button, bool? state = null, int? controller = null) { try { - var toPress = button; - if (controller.HasValue) - { - toPress = $"P{controller} {button}"; - } - if (state.HasValue) - Global.ButtonOverrideAdaptor.SetButton(toPress, state.Value); - else - Global.ButtonOverrideAdaptor.UnSet(toPress); + var buttonToSet = controller == null ? button : $"P{controller} {button}"; + if (state == null) Global.ButtonOverrideAdaptor.UnSet(buttonToSet); + else Global.ButtonOverrideAdaptor.SetButton(buttonToSet, state.Value); Global.ActiveController.Overrides(Global.ButtonOverrideAdaptor); } catch { - /*Eat it*/ + // ignored } } - public void SetAnalog(Dictionary controls, object controller = null) + + public void SetAnalog(Dictionary controls, object controller = null) { - try - { - foreach (var name in controls.Keys) - { - var theValueStr = controls[name].ToString(); - float? theValue = null; - - if (!string.IsNullOrWhiteSpace(theValueStr)) - { - if (float.TryParse(theValueStr, out var f)) - { - theValue = f; - } - } - - Global.StickyXORAdapter.SetFloat(controller == null ? name : $"P{controller} {name}", theValue); - } - } - catch - { - /*Eat it*/ - } + foreach (var kvp in controls) SetAnalog(kvp.Key, kvp.Value, controller); } + public void SetAnalog(string control, float? value = null, object controller = null) { try { - Global.StickyXORAdapter.SetFloat(controller == null - ? control - : $"P{controller} {control}", value); + Global.StickyXORAdapter.SetFloat(controller == null ? control : $"P{controller} {control}", value); } catch { - /*Eat it*/ + // ignored } } } diff --git a/BizHawk.Client.Common/Api/Classes/MemApi.cs b/BizHawk.Client.Common/Api/Classes/MemApi.cs index 6bbc6bc103..8f775bc657 100644 --- a/BizHawk.Client.Common/Api/Classes/MemApi.cs +++ b/BizHawk.Client.Common/Api/Classes/MemApi.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Security.Cryptography; using BizHawk.Common.BufferExtensions; @@ -16,47 +17,6 @@ namespace BizHawk.Client.Common [OptionalService] private IMemoryDomains MemoryDomainCore { get; set; } - private MemoryDomain _currentMemoryDomain; - - private MemoryDomain Domain - { - get - { - if (MemoryDomainCore != null) - { - if (_currentMemoryDomain == null) - { - _currentMemoryDomain = MemoryDomainCore.HasSystemBus - ? MemoryDomainCore.SystemBus - : MemoryDomainCore.MainMemory; - } - - return _currentMemoryDomain; - } - - var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains"; - LogCallback(error); - throw new NotImplementedException(error); - } - } - - private bool _isBigEndian; - - private IMemoryDomains DomainList - { - get - { - if (MemoryDomainCore != null) - { - return MemoryDomainCore; - } - - var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains"; - LogCallback(error); - throw new NotImplementedException(error); - } - } - public MemApi(Action logCallback) { LogCallback = logCallback; @@ -66,64 +26,92 @@ namespace BizHawk.Client.Common private readonly Action LogCallback; - private string VerifyMemoryDomain(string domain) + private bool _isBigEndian; + + private MemoryDomain _currentMemoryDomain; + private MemoryDomain Domain { - try + get { - if (DomainList[domain] == null) + MemoryDomain LazyInit() { - LogCallback($"Unable to find domain: {domain}, falling back to current"); - return Domain.Name; + if (MemoryDomainCore == null) + { + var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains"; + LogCallback(error); + throw new NotImplementedException(error); + } + return MemoryDomainCore.HasSystemBus ? MemoryDomainCore.SystemBus : MemoryDomainCore.MainMemory; } - - return domain; + _currentMemoryDomain ??= LazyInit(); + return _currentMemoryDomain; } - catch // Just in case + set => _currentMemoryDomain = value; + } + + private IMemoryDomains DomainList + { + get { - LogCallback($"Unable to find domain: {domain}, falling back to current"); + if (MemoryDomainCore == null) + { + var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains"; + LogCallback(error); + throw new NotImplementedException(error); + } + return MemoryDomainCore; } + } - return Domain.Name; + private MemoryDomain NamedDomainOrCurrent(string name) + { + if (!string.IsNullOrEmpty(name)) + { + try + { + var found = DomainList[name]; + if (found != null) return found; + } + catch + { + // ignored + } + LogCallback($"Unable to find domain: {name}, falling back to current"); + } + return Domain; } private uint ReadUnsignedByte(long addr, string domain = null) { - var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)]; - if (addr < d.Size) + var d = NamedDomainOrCurrent(domain); + if (addr >= d.Size) { - return d.PeekByte(addr); + LogCallback($"Warning: attempted read of {addr} outside the memory size of {d.Size}"); + return default; } - - LogCallback($"Warning: attempted read of {addr} outside the memory size of {d.Size}"); - return 0; + return d.PeekByte(addr); } private void WriteUnsignedByte(long addr, uint v, string domain = null) { - var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)]; - if (d.CanPoke()) - { - if (addr < d.Size) - { - d.PokeByte(addr, (byte)v); - } - else - { - LogCallback($"Warning: attempted write to {addr} outside the memory size of {d.Size}"); - } - } - else + var d = NamedDomainOrCurrent(domain); + if (!d.CanPoke()) { LogCallback($"Error: the domain {d.Name} is not writable"); + return; } + if (addr >= d.Size) + { + LogCallback($"Warning: attempted write to {addr} outside the memory size of {d.Size}"); + return; + } + d.PokeByte(addr, (byte) v); } private static int U2S(uint u, int size) { - var s = (int)u; - s <<= 8 * (4 - size); - s >>= 8 * (4 - size); - return s; + var sh = 8 * (4 - size); + return ((int) u << sh) >> sh; } #region Endian Handling @@ -131,60 +119,32 @@ namespace BizHawk.Client.Common private uint ReadUnsignedLittle(long addr, int size, string domain = null) { uint v = 0; - for (var i = 0; i < size; ++i) - { - v |= ReadUnsignedByte(addr + i, domain) << (8 * i); - } - + for (var i = 0; i < size; i++) v |= ReadUnsignedByte(addr + i, domain) << (8 * i); return v; } private uint ReadUnsignedBig(long addr, int size, string domain = null) { uint v = 0; - for (var i = 0; i < size; ++i) - { - v |= ReadUnsignedByte(addr + i, domain) << (8 * (size - 1 - i)); - } - + for (var i = 0; i < size; i++) v |= ReadUnsignedByte(addr + i, domain) << (8 * (size - 1 - i)); return v; } private void WriteUnsignedLittle(long addr, uint v, int size, string domain = null) { - for (var i = 0; i < size; ++i) - { - WriteUnsignedByte(addr + i, (v >> (8 * i)) & 0xFF, domain); - } + for (var i = 0; i < size; i++) WriteUnsignedByte(addr + i, (v >> (8 * i)) & 0xFF, domain); } private void WriteUnsignedBig(long addr, uint v, int size, string domain = null) { - for (var i = 0; i < size; ++i) - { - WriteUnsignedByte(addr + i, (v >> (8 * (size - 1 - i))) & 0xFF, domain); - } + for (var i = 0; i < size; i++) WriteUnsignedByte(addr + i, (v >> (8 * (size - 1 - i))) & 0xFF, domain); } - private int ReadSigned(long addr, int size, string domain = null) - { - return _isBigEndian - ? U2S(ReadUnsignedBig(addr, size, domain), size) - : U2S(ReadUnsignedLittle(addr, size, domain), size); - } + private int ReadSigned(long addr, int size, string domain = null) => U2S(ReadUnsigned(addr, size, domain), size); - private uint ReadUnsigned(long addr, int size, string domain = null) - { - return _isBigEndian - ? ReadUnsignedBig(addr, size, domain) - : ReadUnsignedLittle(addr, size, domain); - } + private uint ReadUnsigned(long addr, int size, string domain = null) => _isBigEndian ? ReadUnsignedBig(addr, size, domain) : ReadUnsignedLittle(addr, size, domain); - private void WriteSigned(long addr, int value, int size, string domain = null) - { - if (_isBigEndian) WriteUnsignedBig(addr, (uint)value, size, domain); - else WriteUnsignedLittle(addr, (uint)value, size, domain); - } + private void WriteSigned(long addr, int value, int size, string domain = null) => WriteUnsigned(addr, (uint) value, size, domain); private void WriteUnsigned(long addr, uint value, int size, string domain = null) { @@ -196,88 +156,57 @@ namespace BizHawk.Client.Common #region Unique Library Methods - public void SetBigEndian(bool enabled = true) - { - _isBigEndian = enabled; - } + public void SetBigEndian(bool enabled = true) => _isBigEndian = enabled; public List GetMemoryDomainList() { var list = new List(); - - foreach (var domain in DomainList) - { - list.Add(domain.Name); - } - + foreach (var domain in DomainList) list.Add(domain.Name); return list; } - public uint GetMemoryDomainSize(string name = "") - { - if (string.IsNullOrEmpty(name)) - { - return (uint)Domain.Size; - } + public uint GetMemoryDomainSize(string name = null) => (uint) NamedDomainOrCurrent(name).Size; - return (uint)DomainList[VerifyMemoryDomain(name)].Size; - } + public string GetCurrentMemoryDomain() => Domain.Name; - public string GetCurrentMemoryDomain() - { - return Domain.Name; - } - - public uint GetCurrentMemoryDomainSize() - { - return (uint)Domain.Size; - } + public uint GetCurrentMemoryDomainSize() => (uint) Domain.Size; public bool UseMemoryDomain(string domain) { try { - if (DomainList[domain] != null) + var found = DomainList[domain]; + if (found != null) { - _currentMemoryDomain = DomainList[domain]; + Domain = found; return true; } - - LogCallback($"Unable to find domain: {domain}"); - return false; } - catch // Just in case + catch { - LogCallback($"Unable to find domain: {domain}"); + // ignored } - + LogCallback($"Unable to find domain: {domain}"); return false; } public string HashRegion(long addr, int count, string domain = null) { - var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)]; - - // checks + var d = NamedDomainOrCurrent(domain); if (addr < 0 || addr >= d.Size) { - string error = $"Address {addr} is outside the bounds of domain {d.Name}"; + var error = $"Address {addr} is outside the bounds of domain {d.Name}"; LogCallback(error); throw new ArgumentOutOfRangeException(error); } if (addr + count > d.Size) { - string error = $"Address {addr} + count {count} is outside the bounds of domain {d.Name}"; + var error = $"Address {addr} + count {count} is outside the bounds of domain {d.Name}"; LogCallback(error); throw new ArgumentOutOfRangeException(error); } - - byte[] data = new byte[count]; - for (int i = 0; i < count; i++) - { - data[i] = d.PeekByte(addr + i); - } - + var data = new byte[count]; + for (var i = 0; i < count; i++) data[i] = d.PeekByte(addr + i); using var hasher = SHA256.Create(); return hasher.ComputeHash(data).BytesToHexString(); } @@ -286,188 +215,111 @@ namespace BizHawk.Client.Common #region Common Special and Legacy Methods - public uint ReadByte(long addr, string domain = null) - { - return ReadUnsignedByte(addr, domain); - } + public uint ReadByte(long addr, string domain = null) => ReadUnsignedByte(addr, domain); - public void WriteByte(long addr, uint value, string domain = null) - { - WriteUnsignedByte(addr, value, domain); - } + public void WriteByte(long addr, uint value, string domain = null) => WriteUnsignedByte(addr, value, domain); public List ReadByteRange(long addr, int length, string domain = null) { - var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)]; - var lastAddr = length + addr; - var list = new List(); - for (; addr <= lastAddr; addr++) - { - if (addr < d.Size) - list.Add(d.PeekByte(addr)); - else { - LogCallback($"Warning: Attempted read {addr} outside memory domain size of {d.Size} in {nameof(ReadByteRange)}()"); - list.Add(0); - } - } - - return list; + var d = NamedDomainOrCurrent(domain); + if (addr < 0) LogCallback($"Warning: Attempted reads on addresses {addr}..-1 outside range of domain {d.Name} in {nameof(ReadByteRange)}()"); + var lastReqAddr = addr + length - 1; + var indexAfterLast = Math.Min(lastReqAddr, d.Size - 1) - addr + 1; + var bytes = new byte[length]; + for (var i = addr < 0 ? -addr : 0; i != indexAfterLast; i++) bytes[i] = d.PeekByte(addr + i); + if (lastReqAddr >= d.Size) LogCallback($"Warning: Attempted reads on addresses {d.Size}..{lastReqAddr} outside range of domain {d.Name} in {nameof(ReadByteRange)}()"); + return bytes.ToList(); } public void WriteByteRange(long addr, List memoryblock, string domain = null) { - var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)]; - if (d.CanPoke()) - { - foreach (var m in memoryblock) - { - if (addr < d.Size) - { - d.PokeByte(addr++, m); - } - else - { - LogCallback($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in {nameof(WriteByteRange)}()"); - } - } - } - else + var d = NamedDomainOrCurrent(domain); + if (!d.CanPoke()) { LogCallback($"Error: the domain {d.Name} is not writable"); + return; } + if (addr < 0) LogCallback($"Warning: Attempted reads on addresses {addr}..-1 outside range of domain {d.Name} in {nameof(WriteByteRange)}()"); + var lastReqAddr = addr + memoryblock.Count - 1; + var indexAfterLast = Math.Min(lastReqAddr, d.Size - 1) - addr + 1; + for (var i = addr < 0 ? (int) -addr : 0; i != indexAfterLast; i++) d.PokeByte(addr + i, memoryblock[i]); + if (lastReqAddr >= d.Size) LogCallback($"Warning: Attempted reads on addresses {d.Size}..{lastReqAddr} outside range of domain {d.Name} in {nameof(WriteByteRange)}()"); } public float ReadFloat(long addr, string domain = null) { - var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)]; - if (addr < d.Size) + var d = NamedDomainOrCurrent(domain); + if (addr >= d.Size) { - var val = d.PeekUint(addr, _isBigEndian); - var bytes = BitConverter.GetBytes(val); - return BitConverter.ToSingle(bytes, 0); + LogCallback($"Warning: Attempted read {addr} outside memory size of {d.Size}"); + return default; } - - LogCallback($"Warning: Attempted read {addr} outside memory size of {d.Size}"); - - return 0; + return BitConverter.ToSingle(BitConverter.GetBytes(d.PeekUint(addr, _isBigEndian)), 0); } public void WriteFloat(long addr, double value, string domain = null) { - var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)]; - if (d.CanPoke()) - { - if (addr < d.Size) - { - var dv = (float)value; - var bytes = BitConverter.GetBytes(dv); - var v = BitConverter.ToUInt32(bytes, 0); - d.PokeUint(addr, v, _isBigEndian); - } - else - { - LogCallback($"Warning: Attempted write {addr} outside memory size of {d.Size}"); - } - } - else + var d = NamedDomainOrCurrent(domain); + if (!d.CanPoke()) { LogCallback($"Error: the domain {Domain.Name} is not writable"); + return; } + if (addr >= d.Size) + { + LogCallback($"Warning: Attempted write {addr} outside memory size of {d.Size}"); + return; + } + d.PokeUint(addr, BitConverter.ToUInt32(BitConverter.GetBytes((float) value), 0), _isBigEndian); } #endregion #region 1 Byte - public int ReadS8(long addr, string domain = null) - { - return (sbyte)ReadUnsignedByte(addr, domain); - } + public int ReadS8(long addr, string domain = null) => (sbyte) ReadUnsignedByte(addr, domain); - public uint ReadU8(long addr, string domain = null) - { - return (byte)ReadUnsignedByte(addr, domain); - } + public uint ReadU8(long addr, string domain = null) => (byte) ReadUnsignedByte(addr, domain); - public void WriteS8(long addr, int value, string domain = null) - { - WriteSigned(addr, value, 1, domain); - } + public void WriteS8(long addr, int value, string domain = null) => WriteSigned(addr, value, 1, domain); - public void WriteU8(long addr, uint value, string domain = null) - { - WriteUnsignedByte(addr, value, domain); - } + public void WriteU8(long addr, uint value, string domain = null) => WriteUnsignedByte(addr, value, domain); #endregion #region 2 Byte - public int ReadS16(long addr, string domain = null) - { - return (short)ReadSigned(addr, 2, domain); - } + public int ReadS16(long addr, string domain = null) => (short) ReadSigned(addr, 2, domain); - public void WriteS16(long addr, int value, string domain = null) - { - WriteSigned(addr, value, 2, domain); - } + public uint ReadU16(long addr, string domain = null) => (ushort) ReadUnsigned(addr, 2, domain); - public uint ReadU16(long addr, string domain = null) - { - return (ushort)ReadUnsigned(addr, 2, domain); - } + public void WriteS16(long addr, int value, string domain = null) => WriteSigned(addr, value, 2, domain); + + public void WriteU16(long addr, uint value, string domain = null) => WriteUnsigned(addr, value, 2, domain); - public void WriteU16(long addr, uint value, string domain = null) - { - WriteUnsigned(addr, value, 2, domain); - } #endregion #region 3 Byte - public int ReadS24(long addr, string domain = null) - { - return ReadSigned(addr, 3, domain); - } - public void WriteS24(long addr, int value, string domain = null) - { - WriteSigned(addr, value, 3, domain); - } + public int ReadS24(long addr, string domain = null) => ReadSigned(addr, 3, domain); - public uint ReadU24(long addr, string domain = null) - { - return ReadUnsigned(addr, 3, domain); - } + public uint ReadU24(long addr, string domain = null) => ReadUnsigned(addr, 3, domain); - public void WriteU24(long addr, uint value, string domain = null) - { - WriteUnsigned(addr, value, 3, domain); - } + public void WriteS24(long addr, int value, string domain = null) => WriteSigned(addr, value, 3, domain); + + public void WriteU24(long addr, uint value, string domain = null) => WriteUnsigned(addr, value, 3, domain); #endregion #region 4 Byte - public int ReadS32(long addr, string domain = null) - { - return ReadSigned(addr, 4, domain); - } + public int ReadS32(long addr, string domain = null) => ReadSigned(addr, 4, domain); - public void WriteS32(long addr, int value, string domain = null) - { - WriteSigned(addr, value, 4, domain); - } + public uint ReadU32(long addr, string domain = null) => ReadUnsigned(addr, 4, domain); - public uint ReadU32(long addr, string domain = null) - { - return ReadUnsigned(addr, 4, domain); - } + public void WriteS32(long addr, int value, string domain = null) => WriteSigned(addr, value, 4, domain); - public void WriteU32(long addr, uint value, string domain = null) - { - WriteUnsigned(addr, value, 4, domain); - } + public void WriteU32(long addr, uint value, string domain = null) => WriteUnsigned(addr, value, 4, domain); #endregion } diff --git a/BizHawk.Client.Common/Api/Classes/MemEventsApi.cs b/BizHawk.Client.Common/Api/Classes/MemEventsApi.cs index 03baca4a93..cdf7a410d4 100644 --- a/BizHawk.Client.Common/Api/Classes/MemEventsApi.cs +++ b/BizHawk.Client.Common/Api/Classes/MemEventsApi.cs @@ -1,6 +1,4 @@ -using System; - -using BizHawk.Emulation.Common; +using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.IEmulatorExtensions; namespace BizHawk.Client.Common @@ -10,9 +8,6 @@ namespace BizHawk.Client.Common [RequiredService] private IDebuggable DebuggableCore { get; set; } - public MemEventsApi () : base() - { } - public void AddReadCallback(MemoryCallbackDelegate cb, uint? address, string domain) { if (DebuggableCore.MemoryCallbacksAvailable()) @@ -20,6 +15,7 @@ namespace BizHawk.Client.Common DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Read, "Plugin Hook", cb, address, null)); } } + public void AddWriteCallback(MemoryCallbackDelegate cb, uint? address, string domain) { if (DebuggableCore.MemoryCallbacksAvailable()) @@ -27,6 +23,7 @@ namespace BizHawk.Client.Common DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Write, "Plugin Hook", cb, address, null)); } } + public void AddExecCallback(MemoryCallbackDelegate cb, uint? address, string domain) { if (DebuggableCore.MemoryCallbacksAvailable() && DebuggableCore.MemoryCallbacks.ExecuteCallbacksAvailable) @@ -34,12 +31,10 @@ namespace BizHawk.Client.Common DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Execute, "Plugin Hook", cb, address, null)); } } + public void RemoveMemoryCallback(MemoryCallbackDelegate cb) { - if (DebuggableCore.MemoryCallbacksAvailable()) - { - DebuggableCore.MemoryCallbacks.Remove(cb); - } + if (DebuggableCore.MemoryCallbacksAvailable()) DebuggableCore.MemoryCallbacks.Remove(cb); } } } diff --git a/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs b/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs index bdfb8ca361..5890c96ed4 100644 --- a/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs +++ b/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs @@ -8,6 +8,9 @@ namespace BizHawk.Client.Common { public sealed class MemorySaveStateApi : IMemorySaveState { + [RequiredService] + private IStatable StatableCore { get; set; } + public MemorySaveStateApi(Action logCallback) { LogCallback = logCallback; @@ -17,30 +20,21 @@ namespace BizHawk.Client.Common private readonly Action LogCallback; - [RequiredService] - private IStatable StatableCore { get; set; } - private readonly Dictionary _memorySavestates = new Dictionary(); public string SaveCoreStateToMemory() { var guid = Guid.NewGuid(); - var bytes = (byte[])StatableCore.SaveStateBinary().Clone(); - - _memorySavestates.Add(guid, bytes); - + _memorySavestates.Add(guid, (byte[]) StatableCore.SaveStateBinary().Clone()); return guid.ToString(); } public void LoadCoreStateFromMemory(string identifier) { var guid = new Guid(identifier); - try { - var state = _memorySavestates[guid]; - - using var ms = new MemoryStream(state); + using var ms = new MemoryStream(_memorySavestates[guid]); using var br = new BinaryReader(ms); StatableCore.LoadStateBinary(br); } @@ -50,15 +44,8 @@ namespace BizHawk.Client.Common } } - public void DeleteState(string identifier) - { - var guid = new Guid(identifier); - _memorySavestates.Remove(guid); - } + public void DeleteState(string identifier) => _memorySavestates.Remove(new Guid(identifier)); - public void ClearInMemoryStates() - { - _memorySavestates.Clear(); - } + public void ClearInMemoryStates() => _memorySavestates.Clear(); } } diff --git a/BizHawk.Client.Common/Api/Classes/MovieApi.cs b/BizHawk.Client.Common/Api/Classes/MovieApi.cs index 40cbd87ffe..0a70b83bf1 100644 --- a/BizHawk.Client.Common/Api/Classes/MovieApi.cs +++ b/BizHawk.Client.Common/Api/Classes/MovieApi.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.IO; -using BizHawk.Client.Common; - namespace BizHawk.Client.Common { public sealed class MovieApi : IInputMovie @@ -17,99 +15,9 @@ namespace BizHawk.Client.Common private readonly Action LogCallback; - private static class MoviePluginStatic - { - public static string Filename() - { - return Global.MovieSession.Movie.Filename; - } + public bool StartsFromSavestate() => Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSavestate; - public static bool GetReadOnly() - { - return Global.MovieSession.ReadOnly; - } - - public static ulong GetRerecordCount() - { - return Global.MovieSession.Movie.Rerecords; - } - - public static bool GetRerecordCounting() - { - return Global.MovieSession.Movie.IsCountingRerecords; - } - - public static bool IsLoaded() - { - return Global.MovieSession.Movie.IsActive; - } - - public static double Length() - { - return Global.MovieSession.Movie.FrameCount; - } - - public static string Mode() - { - if (Global.MovieSession.Movie.IsFinished) - { - return "FINISHED"; - } - - if (Global.MovieSession.Movie.IsPlaying) - { - return "PLAY"; - } - - if (Global.MovieSession.Movie.IsRecording) - { - return "RECORD"; - } - - return "INACTIVE"; - } - - public static void SetReadOnly(bool readOnly) - { - Global.MovieSession.ReadOnly = readOnly; - } - - public static void SetRerecordCounting(bool counting) - { - Global.MovieSession.Movie.IsCountingRerecords = counting; - } - - public static void Stop() - { - Global.MovieSession.Movie.Stop(); - } - - public static double GetFps() - { - if (Global.MovieSession.Movie.IsActive) - { - var movie = Global.MovieSession.Movie; - var system = movie.HeaderEntries[HeaderKeys.PLATFORM]; - var pal = movie.HeaderEntries.ContainsKey(HeaderKeys.PAL) - && movie.HeaderEntries[HeaderKeys.PAL] == "1"; - - return new PlatformFrameRates()[system, pal]; - } - - return 0.0; - } - - } - - public bool StartsFromSavestate() - { - return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSavestate; - } - - public bool StartsFromSaveram() - { - return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSaveRam; - } + public bool StartsFromSaveram() => Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSaveRam; public Dictionary GetInput(int frame) { @@ -118,161 +26,102 @@ namespace BizHawk.Client.Common LogCallback("No movie loaded"); return null; } - - var input = new Dictionary(); var adapter = Global.MovieSession.Movie.GetInputState(frame); - if (adapter == null) { LogCallback("Can't get input of the last frame of the movie. Use the previous frame"); return null; } - - foreach (var button in adapter.Definition.BoolButtons) - { - input[button] = adapter.IsPressed(button); - } - - foreach (var button in adapter.Definition.FloatControls) - { - input[button] = adapter.GetFloat(button); - } - + var input = new Dictionary(); + foreach (var button in adapter.Definition.BoolButtons) input[button] = adapter.IsPressed(button); + foreach (var button in adapter.Definition.FloatControls) input[button] = adapter.GetFloat(button); return input; } public string GetInputAsMnemonic(int frame) { - if (Global.MovieSession.Movie.IsActive && frame < Global.MovieSession.Movie.InputLogLength) - { - var lg = Global.MovieSession.LogGeneratorInstance(); - lg.SetSource(Global.MovieSession.Movie.GetInputState(frame)); - return lg.GenerateLogEntry(); - } - - return ""; + if (!Global.MovieSession.Movie.IsActive || frame >= Global.MovieSession.Movie.InputLogLength) return string.Empty; + var lg = Global.MovieSession.LogGeneratorInstance(); + lg.SetSource(Global.MovieSession.Movie.GetInputState(frame)); + return lg.GenerateLogEntry(); } - public void Save(string filename = "") + public void Save(string filename = null) { - if (!Global.MovieSession.Movie.IsActive) - { - return; - } - + if (!Global.MovieSession.Movie.IsActive) return; if (!string.IsNullOrEmpty(filename)) { filename += $".{Global.MovieSession.Movie.PreferredExtension}"; - var test = new FileInfo(filename); - if (test.Exists) + if (new FileInfo(filename).Exists) { LogCallback($"File {filename} already exists, will not overwrite"); return; } - Global.MovieSession.Movie.Filename = filename; } - Global.MovieSession.Movie.Save(); } - public Dictionary GetHeader() + public Dictionary GetHeader() { - var table = new Dictionary(); - if (Global.MovieSession.Movie.IsActive) - { - foreach (var kvp in Global.MovieSession.Movie.HeaderEntries) - { - table[kvp.Key] = kvp.Value; - } - } - + var table = new Dictionary(); + if (!Global.MovieSession.Movie.IsActive) return table; + foreach (var kvp in Global.MovieSession.Movie.HeaderEntries) table[kvp.Key] = kvp.Value; return table; } public List GetComments() { var list = new List(Global.MovieSession.Movie.Comments.Count); - if (Global.MovieSession.Movie.IsActive) - { - for (int i = 0; i < Global.MovieSession.Movie.Comments.Count; i++) - { - list[i] = Global.MovieSession.Movie.Comments[i]; - } - } - + if (!Global.MovieSession.Movie.IsActive) return list; + for (var i = 0; i < Global.MovieSession.Movie.Comments.Count; i++) list[i] = Global.MovieSession.Movie.Comments[i]; return list; } public List GetSubtitles() { var list = new List(Global.MovieSession.Movie.Subtitles.Count); - if (Global.MovieSession.Movie.IsActive) - { - for (int i = 0; i < Global.MovieSession.Movie.Subtitles.Count; i++) - { - list[i] = Global.MovieSession.Movie.Subtitles[i].ToString(); - } - } - + if (!Global.MovieSession.Movie.IsActive) return list; + for (var i = 0; i < Global.MovieSession.Movie.Subtitles.Count; i++) list[i] = Global.MovieSession.Movie.Subtitles[i].ToString(); return list; } - public string Filename() - { - return MoviePluginStatic.Filename(); - } + public string Filename() => Global.MovieSession.Movie.Filename; - public bool GetReadOnly() - { - return MoviePluginStatic.GetReadOnly(); - } + public bool GetReadOnly() => Global.MovieSession.ReadOnly; - public ulong GetRerecordCount() - { - return MoviePluginStatic.GetRerecordCount(); - } + public ulong GetRerecordCount() => Global.MovieSession.Movie.Rerecords; - public bool GetRerecordCounting() - { - return MoviePluginStatic.GetRerecordCounting(); - } + public bool GetRerecordCounting() => Global.MovieSession.Movie.IsCountingRerecords; - public bool IsLoaded() - { - return MoviePluginStatic.IsLoaded(); - } + public bool IsLoaded() => Global.MovieSession.Movie.IsActive; - public double Length() - { - return MoviePluginStatic.Length(); - } + public double Length() => Global.MovieSession.Movie.FrameCount; - public string Mode() - { - return MoviePluginStatic.Mode(); - } + public string Mode() => Global.MovieSession.Movie.IsFinished + ? "FINISHED" + : Global.MovieSession.Movie.IsPlaying + ? "PLAY" + : Global.MovieSession.Movie.IsRecording + ? "RECORD" + : "INACTIVE"; - public void SetReadOnly(bool readOnly) - { - MoviePluginStatic.SetReadOnly(readOnly); - } + public void SetReadOnly(bool readOnly) => Global.MovieSession.ReadOnly = readOnly; public void SetRerecordCount(ulong count) => Global.MovieSession.Movie.Rerecords = count; - public void SetRerecordCounting(bool counting) - { - MoviePluginStatic.SetRerecordCounting(counting); - } + public void SetRerecordCounting(bool counting) => Global.MovieSession.Movie.IsCountingRerecords = counting; - public void Stop() - { - MoviePluginStatic.Stop(); - } + public void Stop() => Global.MovieSession.Movie.Stop(); public double GetFps() { - return MoviePluginStatic.GetFps(); + var movie = Global.MovieSession.Movie; + if (!movie.IsActive) return default; + return new PlatformFrameRates()[ + movie.HeaderEntries[HeaderKeys.PLATFORM], + movie.HeaderEntries.TryGetValue(HeaderKeys.PAL, out var isPal) && isPal == "1" + ]; } } } diff --git a/BizHawk.Client.Common/Api/Classes/SqlApi.cs b/BizHawk.Client.Common/Api/Classes/SqlApi.cs index 0df1e1f18b..129aeb314f 100644 --- a/BizHawk.Client.Common/Api/Classes/SqlApi.cs +++ b/BizHawk.Client.Common/Api/Classes/SqlApi.cs @@ -1,127 +1,103 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Data; using System.Data.SQLite; namespace BizHawk.Client.Common { public sealed class SqlApi : ISql { - SQLiteConnection _dbConnection; + private SQLiteConnection _dbConnection; public string CreateDatabase(string name) { try { SQLiteConnection.CreateFile(name); - return "Database Created Successfully"; } catch (SQLiteException sqlEx) { return sqlEx.Message; } + return "Database Created Successfully"; } public string OpenDatabase(string name) { try { - var connBuilder = new SQLiteConnectionStringBuilder - { - DataSource = name, - Version = 3, - JournalMode = SQLiteJournalModeEnum.Wal, // Allows for reads and writes to happen at the same time - DefaultIsolationLevel = System.Data.IsolationLevel.ReadCommitted, // This only helps make the database lock left. May be pointless now - SyncMode = SynchronizationModes.Off // This shortens the delay for do synchronous calls. - }; - - _dbConnection = new SQLiteConnection(connBuilder.ToString()); + _dbConnection = new SQLiteConnection( + new SQLiteConnectionStringBuilder { + DataSource = name, + Version = 3, + JournalMode = SQLiteJournalModeEnum.Wal, // Allows for reads and writes to happen at the same time + DefaultIsolationLevel = IsolationLevel.ReadCommitted, // This only helps make the database lock left. May be pointless now + SyncMode = SynchronizationModes.Off // This shortens the delay for do synchronous calls. + }.ToString() + ); _dbConnection.Open(); - _dbConnection.Close(); - return "Database Opened Successfully"; } catch (SQLiteException sqlEx) { return sqlEx.Message; } + _dbConnection?.Close(); + return "Database Opened Successfully"; } - public string WriteCommand(string query = "") + public string WriteCommand(string query = null) { - if (string.IsNullOrWhiteSpace(query)) - { - return "query is empty"; - } - + if (string.IsNullOrWhiteSpace(query)) return "query is empty"; + if (_dbConnection == null) return "Database not open."; + string result; try { _dbConnection.Open(); - var command = new SQLiteCommand(query, _dbConnection); - command.ExecuteNonQuery(); - _dbConnection.Close(); - - return "Command ran successfully"; - } - catch (NullReferenceException) - { - return "Database not open."; + new SQLiteCommand(query, _dbConnection).ExecuteNonQuery(); + result = "Command ran successfully"; } catch (SQLiteException sqlEx) { - _dbConnection.Close(); - return sqlEx.Message; + result = sqlEx.Message; } + _dbConnection.Close(); + return result; } - public dynamic ReadCommand(string query = "") + public dynamic ReadCommand(string query = null) { - if (string.IsNullOrWhiteSpace(query)) - { - return "query is empty"; - } - + if (string.IsNullOrWhiteSpace(query)) return "query is empty"; + if (_dbConnection == null) return "Database not open."; + dynamic result; try { - var table = new Dictionary(); _dbConnection.Open(); - string sql = $"PRAGMA read_uncommitted =1;{query}"; - using var command = new SQLiteCommand(sql, _dbConnection); - SQLiteDataReader reader = command.ExecuteReader(); - bool rows = reader.HasRows; - long rowCount = 0; - var columns = new List(); - for (int i = 0; i < reader.FieldCount; ++i) //Add all column names into list + using var command = new SQLiteCommand($"PRAGMA read_uncommitted =1;{query}", _dbConnection); + using var reader = command.ExecuteReader(); + if (reader.HasRows) { - columns.Add(reader.GetName(i)); - } - - while (reader.Read()) - { - for (int i = 0; i < reader.FieldCount; ++i) + var columns = new string[reader.FieldCount]; + for (int i = 0, l = reader.FieldCount; i < l; i++) columns[i] = reader.GetName(i); + long rowCount = 0; + var table = new Dictionary(); + while (reader.Read()) { - table[$"{columns[i]} {rowCount}"] = reader.GetValue(i); + for (int i = 0, l = reader.FieldCount; i < l; i++) table[$"{columns[i]} {rowCount}"] = reader.GetValue(i); + rowCount++; } - - rowCount += 1; + reader.Close(); + result = table; } - - reader.Close(); - _dbConnection.Close(); - if (rows == false) + else { - return "No rows found"; + result = "No rows found"; } - - return table; - } - catch (NullReferenceException) - { - return "Database not opened."; } catch (SQLiteException sqlEx) { - _dbConnection.Close(); - return sqlEx.Message; + result = sqlEx.Message; } + _dbConnection.Close(); + return result; } } } diff --git a/BizHawk.Client.Common/Api/Classes/UserDataApi.cs b/BizHawk.Client.Common/Api/Classes/UserDataApi.cs index a366ff3dc4..9bff930198 100644 --- a/BizHawk.Client.Common/Api/Classes/UserDataApi.cs +++ b/BizHawk.Client.Common/Api/Classes/UserDataApi.cs @@ -1,47 +1,25 @@ using System; -using BizHawk.Client.Common; namespace BizHawk.Client.Common { public sealed class UserDataApi : IUserData { - public UserDataApi() : base() - { } - public void Set(string name, object value) { if (value != null) { var t = value.GetType(); - if (!t.IsPrimitive && t != typeof(string)) - { - throw new InvalidOperationException("Invalid type for userdata"); - } + if (!t.IsPrimitive && t != typeof(string)) throw new InvalidOperationException("Invalid type for userdata"); } - Global.UserBag[name] = value; } - public object Get(string key) - { - return Global.UserBag.ContainsKey(key) - ? Global.UserBag[key] - : null; - } + public object Get(string key) => Global.UserBag.TryGetValue(key, out var value) ? value : null; - public void Clear() - { - Global.UserBag.Clear(); - } + public void Clear() => Global.UserBag.Clear(); - public bool Remove(string key) - { - return Global.UserBag.Remove(key); - } + public bool Remove(string key) => Global.UserBag.Remove(key); - public bool ContainsKey(string key) - { - return Global.UserBag.ContainsKey(key); - } + public bool ContainsKey(string key) => Global.UserBag.ContainsKey(key); } } diff --git a/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs b/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs index 37eaeac9ce..c96ed0bffe 100644 --- a/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs +++ b/BizHawk.Client.EmuHawk/Api/Libraries/CommApi.cs @@ -1,153 +1,69 @@ -using System; -using System.ComponentModel; - -using BizHawk.Emulation.Common; -using BizHawk.Client.ApiHawk; -using System.Text; -using System.Collections.Generic; -using System.Net.Http; -using System.Windows.Forms; +using System.Text; using BizHawk.Client.Common; - namespace BizHawk.Client.EmuHawk { public sealed class CommApi : IComm { - [RequiredService] - private IEmulator Emulator { get; set; } + public string SocketServerScreenShot() => GlobalWin.socketServer.SendScreenshot(); - [RequiredService] - private IVideoProvider VideoProvider { get; set; } + public string SocketServerScreenShotResponse() => GlobalWin.socketServer.SendScreenshot(1000); - public CommApi() : base() - { } + public string SocketServerSend(string SendString) => $"Sent : {GlobalWin.socketServer.SendString(SendString)} bytes"; - public string SocketServerScreenShot() - { - return GlobalWin.socketServer.SendScreenshot(); - } - public string SocketServerScreenShotResponse() - { - return GlobalWin.socketServer.SendScreenshot(1000).ToString(); - } + public string SocketServerResponse() => GlobalWin.socketServer.ReceiveMessage(); - public string SocketServerSend(string SendString) - { - return $"Sent : {GlobalWin.socketServer.SendString(SendString)} bytes"; - } - public string SocketServerResponse() - { - return GlobalWin.socketServer.ReceiveMessage(); - } + public bool SocketServerSuccessful() => GlobalWin.socketServer.Successful(); - public bool SocketServerSuccessful() - { - return GlobalWin.socketServer.Successful(); - } - public void SocketServerSetTimeout(int timeout) - { - GlobalWin.socketServer.SetTimeout(timeout); - } + public void SocketServerSetTimeout(int timeout) => GlobalWin.socketServer.SetTimeout(timeout); - public void SocketServerSetIp(string ip) - { - GlobalWin.socketServer.Ip = ip; - } + public void SocketServerSetIp(string ip) => GlobalWin.socketServer.Ip = ip; - public void SetSocketServerPort(int port) - { - GlobalWin.socketServer.Port = port; - } + public void SetSocketServerPort(int port) => GlobalWin.socketServer.Port = port; - public string SocketServerGetIp() - { - return GlobalWin.socketServer.Ip; - } + public string SocketServerGetIp() => GlobalWin.socketServer.Ip; - public int SocketServerGetPort() - { - return GlobalWin.socketServer.Port; - } + public int SocketServerGetPort() => GlobalWin.socketServer.Port; - public string SocketServerGetInfo() - { - return GlobalWin.socketServer.GetInfo(); - } + public string SocketServerGetInfo() => GlobalWin.socketServer.GetInfo(); - // All MemoryMappedFile related methods - public void MmfSetFilename(string filename) - { - GlobalWin.memoryMappedFiles.Filename = filename; - } + #region MemoryMappedFile - public string MmfGetFilename() - { - return GlobalWin.memoryMappedFiles.Filename; - } + public void MmfSetFilename(string filename) => GlobalWin.memoryMappedFiles.Filename = filename; - public int MmfScreenshot() - { - return GlobalWin.memoryMappedFiles.ScreenShotToFile(); - } + public string MmfGetFilename() => GlobalWin.memoryMappedFiles.Filename; - public int MmfWrite(string mmf_filename, string outputString) - { - return GlobalWin.memoryMappedFiles.WriteToFile(mmf_filename, Encoding.ASCII.GetBytes(outputString)); - } + public int MmfScreenshot() => GlobalWin.memoryMappedFiles.ScreenShotToFile(); - public string MmfRead(string mmf_filename, int expectedSize) - { - return GlobalWin.memoryMappedFiles.ReadFromFile(mmf_filename, expectedSize); - } + public int MmfWrite(string mmf_filename, string outputString) => GlobalWin.memoryMappedFiles.WriteToFile(mmf_filename, Encoding.ASCII.GetBytes(outputString)); + public string MmfRead(string mmf_filename, int expectedSize) => GlobalWin.memoryMappedFiles.ReadFromFile(mmf_filename, expectedSize); - // All HTTP related methods - public string HttpTest() - { - var list = new StringBuilder(); - list.AppendLine(GlobalWin.httpCommunication.TestGet()); - list.AppendLine(GlobalWin.httpCommunication.SendScreenshot()); - list.AppendLine("done testing"); - return list.ToString(); - } - public string HttpTestGet() - { - return GlobalWin.httpCommunication.TestGet(); - } - public string HttpGet(string url) - { - return GlobalWin.httpCommunication.ExecGet(url); - } + #endregion - public string HttpPost(string url, string payload) - { - return GlobalWin.httpCommunication.ExecPost(url, payload); - } - public string HttpPostScreenshot() - { - return GlobalWin.httpCommunication.SendScreenshot(); - } - public void HttpSetTimeout(int timeout) - { - GlobalWin.httpCommunication.SetTimeout(timeout); - } - public void HttpSetPostUrl(string url) - { - GlobalWin.httpCommunication.PostUrl = url; - } - public void HttpSetGetUrl(string url) - { - GlobalWin.httpCommunication.GetUrl = url; - } - public string HttpGetPostUrl() - { - return GlobalWin.httpCommunication.PostUrl; - } - public string HttpGetGetUrl() - { - return GlobalWin.httpCommunication.GetUrl; - } + #region HTTP + + public string HttpTest() => string.Join("\n", GlobalWin.httpCommunication.TestGet(), GlobalWin.httpCommunication.SendScreenshot(), "done testing"); + + public string HttpTestGet() => GlobalWin.httpCommunication.TestGet(); + + public string HttpGet(string url) => GlobalWin.httpCommunication.ExecGet(url); + + public string HttpPost(string url, string payload) => GlobalWin.httpCommunication.ExecPost(url, payload); + + public string HttpPostScreenshot() => GlobalWin.httpCommunication.SendScreenshot(); + + public void HttpSetTimeout(int timeout) => GlobalWin.httpCommunication.SetTimeout(timeout); + + public void HttpSetPostUrl(string url) => GlobalWin.httpCommunication.PostUrl = url; + + public void HttpSetGetUrl(string url) => GlobalWin.httpCommunication.GetUrl = url; + + public string HttpGetPostUrl() => GlobalWin.httpCommunication.PostUrl; + + public string HttpGetGetUrl() => GlobalWin.httpCommunication.GetUrl; + + #endregion } } diff --git a/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs b/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs index bca90ff694..a8faff5cda 100644 --- a/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs +++ b/BizHawk.Client.EmuHawk/Api/Libraries/GuiApi.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Drawing2D; using System.Drawing.Imaging; -using System.Windows.Forms; +using System.Drawing.Text; using System.IO; +using System.Windows.Forms; -using BizHawk.Client.ApiHawk; using BizHawk.Client.Common; using BizHawk.Emulation.Common; @@ -15,13 +16,6 @@ namespace BizHawk.Client.EmuHawk { [RequiredService] private IEmulator Emulator { get; set; } - private Color _defaultForeground = Color.White; - private Color? _defaultBackground; - private Color? _defaultTextBackground = Color.FromArgb(128, 0, 0, 0); - private int _defaultPixelFont = 1; // gens - private Padding _padding = new Padding(0); - private ImageAttributes _attributes = new ImageAttributes(); - private System.Drawing.Drawing2D.CompositingMode _compositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; public GuiApi(Action logCallback) { @@ -32,38 +26,57 @@ namespace BizHawk.Client.EmuHawk private readonly Action LogCallback; - private DisplaySurface _GUISurface = null; + private readonly Dictionary _imageCache = new Dictionary(); + + private readonly Bitmap _nullGraphicsBitmap = new Bitmap(1, 1); + + private readonly Dictionary _pens = new Dictionary(); + + private readonly Dictionary _solidBrushes = new Dictionary(); + + private ImageAttributes _attributes = new ImageAttributes(); + + private CompositingMode _compositingMode = CompositingMode.SourceOver; + + private Color? _defaultBackground; + + private Color _defaultForeground = Color.White; + + private int _defaultPixelFont = 1; // = "gens" + + private Color? _defaultTextBackground = Color.FromArgb(128, 0, 0, 0); + + private DisplaySurface _GUISurface; + + private Padding _padding = new Padding(0); public bool HasGUISurface => _GUISurface != null; - #region Gui API - public void ToggleCompositingMode() - { - _compositingMode = 1 - _compositingMode; - } + private SolidBrush GetBrush(Color color) => _solidBrushes.TryGetValue(color, out var b) ? b : (_solidBrushes[color] = new SolidBrush(color)); - public ImageAttributes GetAttributes() - { - return _attributes; - } - public void SetAttributes(ImageAttributes a) - { - _attributes = a; - } + private Pen GetPen(Color color) => _pens.TryGetValue(color, out var p) ? p : (_pens[color] = new Pen(color)); - public void Dispose() + private Graphics GetGraphics() { - foreach (var brush in _solidBrushes.Values) + var g = _GUISurface?.GetGraphics() ?? Graphics.FromImage(_nullGraphicsBitmap); + // we don't like CoreComm, right? Someone should find a different way to do this then. + var tx = Emulator.CoreComm.ScreenLogicalOffsetX; + var ty = Emulator.CoreComm.ScreenLogicalOffsetY; + if (tx != 0 || ty != 0) { - brush.Dispose(); - } - - foreach (var brush in _pens.Values) - { - brush.Dispose(); + var transform = g.Transform; + transform.Translate(-tx, -ty); + g.Transform = transform; } + return g; } + public void ToggleCompositingMode() => _compositingMode = 1 - _compositingMode; + + public ImageAttributes GetAttributes() => _attributes; + + public void SetAttributes(ImageAttributes a) => _attributes = a; + public void DrawNew(string name, bool clear) { try @@ -79,82 +92,19 @@ namespace BizHawk.Client.EmuHawk public void DrawFinish() { - if (_GUISurface != null) - { - GlobalWin.DisplayManager.UnlockLuaSurface(_GUISurface); - } - + if (_GUISurface != null) GlobalWin.DisplayManager.UnlockLuaSurface(_GUISurface); _GUISurface = null; } - #endregion - #region Helpers - private readonly Dictionary _imageCache = new Dictionary(); - private readonly Dictionary _solidBrushes = new Dictionary(); - private readonly Dictionary _pens = new Dictionary(); - private readonly Bitmap _nullGraphicsBitmap = new Bitmap(1, 1); - private SolidBrush GetBrush(Color color) - { - SolidBrush b; - if (!_solidBrushes.TryGetValue(color, out b)) - { - b = new SolidBrush(color); - _solidBrushes[color] = b; - } + public void SetPadding(int all) => _padding = new Padding(all); - return b; - } + public void SetPadding(int x, int y) => _padding = new Padding(x / 2, y / 2, x / 2 + x & 1, y / 2 + y & 1); - private Pen GetPen(Color color) - { - Pen p; - if (!_pens.TryGetValue(color, out p)) - { - p = new Pen(color); - _pens[color] = p; - } + public void SetPadding(int l, int t, int r, int b) => _padding = new Padding(l, t, r, b); - return p; - } + public Padding GetPadding() => _padding; - private Graphics GetGraphics() - { - var g = _GUISurface == null ? Graphics.FromImage(_nullGraphicsBitmap) : _GUISurface.GetGraphics(); - - // we don't like CoreComm, right? Someone should find a different way to do this then. - var tx = Emulator.CoreComm.ScreenLogicalOffsetX; - var ty = Emulator.CoreComm.ScreenLogicalOffsetY; - if (tx != 0 || ty != 0) - { - var transform = g.Transform; - transform.Translate(-tx, -ty); - g.Transform = transform; - } - - return g; - } - public void SetPadding(int all) - { - _padding = new Padding(all); - } - public void SetPadding(int x, int y) - { - _padding = new Padding(x / 2, y / 2, x / 2 + x & 1, y / 2 + y & 1); - } - public void SetPadding(int l, int t, int r, int b) - { - _padding = new Padding(l, t, r, b); - } - public Padding GetPadding() - { - return _padding; - } - #endregion - - public void AddMessage(string message) - { - GlobalWin.OSD.AddMessage(message); - } + public void AddMessage(string message) => GlobalWin.OSD.AddMessage(message); public void ClearGraphics() { @@ -162,27 +112,15 @@ namespace BizHawk.Client.EmuHawk DrawFinish(); } - public void ClearText() - { - GlobalWin.OSD.ClearGuiText(); - } + public void ClearText() => GlobalWin.OSD.ClearGuiText(); - public void SetDefaultForegroundColor(Color color) - { - _defaultForeground = color; - } + public void SetDefaultForegroundColor(Color color) => _defaultForeground = color; - public void SetDefaultBackgroundColor(Color color) - { - _defaultBackground = color; - } + public void SetDefaultBackgroundColor(Color color) => _defaultBackground = color; public Color? GetDefaultTextBackground() => _defaultTextBackground; - public void SetDefaultTextBackground(Color color) - { - _defaultTextBackground = color; - } + public void SetDefaultTextBackground(Color color) => _defaultTextBackground = color; public void SetDefaultPixelFont(string fontfamily) { @@ -204,135 +142,108 @@ namespace BizHawk.Client.EmuHawk public void DrawBezier(Point p1, Point p2, Point p3, Point p4, Color? color = null) { - using (var g = GetGraphics()) + try { - try - { - g.CompositingMode = _compositingMode; - g.DrawBezier(GetPen(color ?? _defaultForeground), p1, p2, p3, p4); - } - catch (Exception) - { - return; - } + using var g = GetGraphics(); + g.CompositingMode = _compositingMode; + g.DrawBezier(GetPen(color ?? _defaultForeground), p1, p2, p3, p4); + } + catch (Exception) + { + // ignored } } public void DrawBeziers(Point[] points, Color? color = null) { - using (var g = GetGraphics()) + try { - try - { - g.CompositingMode = _compositingMode; - g.DrawBeziers(GetPen(color ?? _defaultForeground), points); - } - catch (Exception) - { - return; - } + using var g = GetGraphics(); + g.CompositingMode = _compositingMode; + g.DrawBeziers(GetPen(color ?? _defaultForeground), points); + } + catch (Exception) + { + // ignored } } + public void DrawBox(int x, int y, int x2, int y2, Color? line = null, Color? background = null) { - using (var g = GetGraphics()) + try { - try + float w; + if (x < x2) { - float w; - float h; - if (x < x2) - { - w = x2 - x; - } - else - { - x2 = x - x2; - x -= x2; - w = Math.Max(x2, 0.1f); - } - - if (y < y2) - { - h = y2 - y; - } - else - { - y2 = y - y2; - y -= y2; - h = Math.Max(y2, 0.1f); - } - - g.CompositingMode = _compositingMode; - g.DrawRectangle(GetPen(line ?? _defaultForeground), x, y, w, h); - - var bg = background ?? _defaultBackground; - if (bg.HasValue) - { - g.FillRectangle(GetBrush(bg.Value), x + 1, y + 1, Math.Max(w - 1, 0), Math.Max(h - 1, 0)); - } + w = x2 - x; } - catch (Exception) + else { - // need to stop the script from here - return; + x2 = x - x2; + x -= x2; + w = Math.Max(x2, 0.1f); } + float h; + if (y < y2) + { + h = y2 - y; + } + else + { + y2 = y - y2; + y -= y2; + h = Math.Max(y2, 0.1f); + } + using var g = GetGraphics(); + g.CompositingMode = _compositingMode; + g.DrawRectangle(GetPen(line ?? _defaultForeground), x, y, w, h); + var bg = background ?? _defaultBackground; + if (bg != null) g.FillRectangle(GetBrush(bg.Value), x + 1, y + 1, Math.Max(w - 1, 0), Math.Max(h - 1, 0)); + } + catch (Exception) + { + // need to stop the script from here } } public void DrawEllipse(int x, int y, int width, int height, Color? line = null, Color? background = null) { - using (var g = GetGraphics()) + try { - try - { - var bg = background ?? _defaultBackground; - if (bg.HasValue) - { - var brush = GetBrush(bg.Value); - g.FillEllipse(brush, x, y, width, height); - } - - g.CompositingMode = _compositingMode; - g.DrawEllipse(GetPen(line ?? _defaultForeground), x, y, width, height); - } - catch (Exception) - { - // need to stop the script from here - return; - } + using var g = GetGraphics(); + var bg = background ?? _defaultBackground; + if (bg != null) g.FillEllipse(GetBrush(bg.Value), x, y, width, height); + g.CompositingMode = _compositingMode; + g.DrawEllipse(GetPen(line ?? _defaultForeground), x, y, width, height); + } + catch (Exception) + { + // need to stop the script from here } } public void DrawIcon(string path, int x, int y, int? width = null, int? height = null) { - using (var g = GetGraphics()) + try { - try - { - if (!File.Exists(path)) - { - AddMessage($"File not found: {path}"); - return; - } - - Icon icon; - if (width.HasValue && height.HasValue) - { - icon = new Icon(path, width.Value, height.Value); - } - else - { - icon = new Icon(path); - } - - g.CompositingMode = _compositingMode; - g.DrawIcon(icon, x, y); - } - catch (Exception) + if (!File.Exists(path)) { + AddMessage($"File not found: {path}"); return; } + using var g = GetGraphics(); + g.CompositingMode = _compositingMode; + g.DrawIcon( + width != null && height != null + ? new Icon(path, width.Value, height.Value) + : new Icon(path), + x, + y + ); + } + catch (Exception) + { + // ignored } } @@ -343,36 +254,26 @@ namespace BizHawk.Client.EmuHawk LogCallback($"File not found: {path}"); return; } - - using (var g = GetGraphics()) - { - Image img; - if (_imageCache.ContainsKey(path)) - { - img = _imageCache[path]; - } - else - { - img = Image.FromFile(path); - if (cache) - { - _imageCache.Add(path, img); - } - } - var destRect = new Rectangle(x, y, width ?? img.Width, height ?? img.Height); - - g.CompositingMode = _compositingMode; - g.DrawImage(img, destRect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, _attributes); - } + using var g = GetGraphics(); + var isCached = _imageCache.ContainsKey(path); + var img = isCached ? _imageCache[path] : Image.FromFile(path); + if (!isCached && cache) _imageCache[path] = img; + g.CompositingMode = _compositingMode; + g.DrawImage( + img, + new Rectangle(x, y, width ?? img.Width, height ?? img.Height), + 0, + 0, + img.Width, + img.Height, + GraphicsUnit.Pixel, + _attributes + ); } public void ClearImageCache() { - foreach (var image in _imageCache) - { - image.Value.Dispose(); - } - + foreach (var image in _imageCache) image.Value.Dispose(); _imageCache.Clear(); } @@ -383,34 +284,25 @@ namespace BizHawk.Client.EmuHawk LogCallback($"File not found: {path}"); return; } - - using (var g = GetGraphics()) - { - Image img; - if (_imageCache.ContainsKey(path)) - { - img = _imageCache[path]; - } - else - { - img = Image.FromFile(path); - _imageCache.Add(path, img); - } - - var destRect = new Rectangle(dest_x, dest_y, dest_width ?? source_width, dest_height ?? source_height); - - g.CompositingMode = _compositingMode; - g.DrawImage(img, destRect, source_x, source_y, source_width, source_height, GraphicsUnit.Pixel, _attributes); - } + using var g = GetGraphics(); + g.CompositingMode = _compositingMode; + g.DrawImage( + _imageCache.TryGetValue(path, out var img) ? img : (_imageCache[path] = Image.FromFile(path)), + new Rectangle(dest_x, dest_y, dest_width ?? source_width, dest_height ?? source_height), + source_x, + source_y, + source_width, + source_height, + GraphicsUnit.Pixel, + _attributes + ); } public void DrawLine(int x1, int y1, int x2, int y2, Color? color = null) { - using (var g = GetGraphics()) - { - g.CompositingMode = _compositingMode; - g.DrawLine(GetPen(color ?? _defaultForeground), x1, y1, x2, y2); - } + using var g = GetGraphics(); + g.CompositingMode = _compositingMode; + g.DrawLine(GetPen(color ?? _defaultForeground), x1, y1, x2, y2); } public void DrawAxis(int x, int y, int size, Color? color = null) @@ -421,246 +313,191 @@ namespace BizHawk.Client.EmuHawk public void DrawPie(int x, int y, int width, int height, int startangle, int sweepangle, Color? line = null, Color? background = null) { - using (var g = GetGraphics()) - { - g.CompositingMode = _compositingMode; - var bg = background ?? _defaultBackground; - if (bg.HasValue) - { - var brush = GetBrush(bg.Value); - g.FillPie(brush, x, y, width, height, startangle, sweepangle); - } - - g.DrawPie(GetPen(line ?? _defaultForeground), x + 1, y + 1, width - 1, height - 1, startangle, sweepangle); - } + using var g = GetGraphics(); + g.CompositingMode = _compositingMode; + var bg = background ?? _defaultBackground; + if (bg != null) g.FillPie(GetBrush(bg.Value), x, y, width, height, startangle, sweepangle); + g.DrawPie(GetPen(line ?? _defaultForeground), x + 1, y + 1, width - 1, height - 1, startangle, sweepangle); } public void DrawPixel(int x, int y, Color? color = null) { - using (var g = GetGraphics()) + try { - try - { - g.DrawLine(GetPen(color ?? _defaultForeground), x, y, x + 0.1F, y); - } - catch (Exception) - { - return; - } + using var g = GetGraphics(); + g.DrawLine(GetPen(color ?? _defaultForeground), x, y, x + 0.1F, y); + } + catch (Exception) + { + // ignored } } public void DrawPolygon(Point[] points, Color? line = null, Color? background = null) { - using (var g = GetGraphics()) + try { - try - { - g.DrawPolygon(GetPen(line ?? _defaultForeground), points); - var bg = background ?? _defaultBackground; - if (bg.HasValue) - { - g.FillPolygon(GetBrush(bg.Value), points); - } - } - catch (Exception) - { - return; - } + using var g = GetGraphics(); + g.DrawPolygon(GetPen(line ?? _defaultForeground), points); + var bg = background ?? _defaultBackground; + if (bg != null) g.FillPolygon(GetBrush(bg.Value), points); + } + catch (Exception) + { + // ignored } } public void DrawRectangle(int x, int y, int width, int height, Color? line = null, Color? background = null) { - using (var g = GetGraphics()) - { - var w = Math.Max(width, 0.1F); - var h = Math.Max(height, 0.1F); - g.DrawRectangle(GetPen(line ?? _defaultForeground), x, y, w, h); - var bg = background ?? _defaultBackground; - if (bg.HasValue) - { - g.FillRectangle(GetBrush(bg.Value), x + 1, y + 1, Math.Max(w - 1, 0), Math.Max(h - 1, 0)); - } - } + using var g = GetGraphics(); + var w = Math.Max(width, 0.1F); + var h = Math.Max(height, 0.1F); + g.DrawRectangle(GetPen(line ?? _defaultForeground), x, y, w, h); + var bg = background ?? _defaultBackground; + if (bg != null) g.FillRectangle(GetBrush(bg.Value), x + 1, y + 1, Math.Max(w - 1, 0), Math.Max(h - 1, 0)); } - public void DrawString(int x, int y, string message, Color? forecolor = null, Color? backcolor = null, int? fontsize = null, - string fontfamily = null, string fontstyle = null, string horizalign = null, string vertalign = null) + public void DrawString(int x, int y, string message, Color? forecolor = null, Color? backcolor = null, int? fontsize = null, string fontfamily = null, string fontstyle = null, string horizalign = null, string vertalign = null) { - using (var g = GetGraphics()) + try { - try + var family = fontfamily != null ? new FontFamily(fontfamily) : FontFamily.GenericMonospace; + + var fstyle = fontstyle?.ToLower() switch { - var family = FontFamily.GenericMonospace; - if (fontfamily != null) - { - family = new FontFamily(fontfamily); - } + "bold" => FontStyle.Bold, + "italic" => FontStyle.Italic, + "strikethrough" => FontStyle.Strikeout, + "underline" => FontStyle.Underline, + _ => FontStyle.Regular + }; - var fstyle = FontStyle.Regular; - if (fontstyle != null) - { - switch (fontstyle.ToLower()) - { - default: - case "regular": - break; - case "bold": - fstyle = FontStyle.Bold; - break; - case "italic": - fstyle = FontStyle.Italic; - break; - case "strikethrough": - fstyle = FontStyle.Strikeout; - break; - case "underline": - fstyle = FontStyle.Underline; - break; - } - } + using var g = GetGraphics(); - // The text isn't written out using GenericTypographic, so measuring it using GenericTypographic seemed to make it worse. - // And writing it out with GenericTypographic just made it uglier. :p - var f = new StringFormat(StringFormat.GenericDefault); - var font = new Font(family, fontsize ?? 12, fstyle, GraphicsUnit.Pixel); - Size sizeOfText = g.MeasureString(message, font, 0, f).ToSize(); - if (horizalign != null) - { - switch (horizalign.ToLower()) - { - default: - case "left": - break; - case "center": - case "middle": - x -= sizeOfText.Width / 2; - break; - case "right": - x -= sizeOfText.Width; - break; - } - } + // The text isn't written out using GenericTypographic, so measuring it using GenericTypographic seemed to make it worse. + // And writing it out with GenericTypographic just made it uglier. :p + var font = new Font(family, fontsize ?? 12, fstyle, GraphicsUnit.Pixel); + var sizeOfText = g.MeasureString(message, font, 0, new StringFormat(StringFormat.GenericDefault)).ToSize(); - if (vertalign != null) - { - switch (vertalign.ToLower()) - { - default: - case "top": - break; - case "center": - case "middle": - y -= sizeOfText.Height / 2; - break; - case "bottom": - y -= sizeOfText.Height; - break; - } - } - - var bg = backcolor ?? _defaultBackground; - if (bg.HasValue) - { - for (var xd = -1; xd <= 1; xd++) - { - for (var yd = -1; yd <= 1; yd++) - { - g.DrawString(message, font, GetBrush(bg.Value), x + xd, y + yd); - } - } - } - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; - g.DrawString(message, font, GetBrush(forecolor ?? _defaultForeground), x, y); - } - catch (Exception) + switch (horizalign?.ToLower()) { - return; + default: + case "left": + break; + case "center": + case "middle": + x -= sizeOfText.Width / 2; + break; + case "right": + x -= sizeOfText.Width; + break; } + + switch (vertalign?.ToLower()) + { + default: + case "top": + break; + case "center": + case "middle": + y -= sizeOfText.Height / 2; + break; + case "bottom": + y -= sizeOfText.Height; + break; + } + + var bg = backcolor ?? _defaultBackground; + if (bg != null) + { + var brush = GetBrush(bg.Value); + for (var xd = -1; xd <= 1; xd++) for (var yd = -1; yd <= 1; yd++) + { + g.DrawString(message, font, brush, x + xd, y + yd); + } + } + g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; + g.DrawString(message, font, GetBrush(forecolor ?? _defaultForeground), x, y); + } + catch (Exception) + { + // ignored } } public void DrawText(int x, int y, string message, Color? forecolor = null, Color? backcolor = null, string fontfamily = null) { - using (var g = GetGraphics()) + try { - try + int index; + switch (fontfamily) { - var index = 0; - if (string.IsNullOrEmpty(fontfamily)) - { - index = _defaultPixelFont; - } - else - { - switch (fontfamily) + case "fceux": + case "0": + index = 0; + break; + case "gens": + case "1": + index = 1; + break; + default: + if (!string.IsNullOrEmpty(fontfamily)) // not a typo { - case "fceux": - case "0": - index = 0; - break; - case "gens": - case "1": - index = 1; - break; - default: - LogCallback($"Unable to find font family: {fontfamily}"); - return; + LogCallback($"Unable to find font family: {fontfamily}"); + return; } - } - - var f = new StringFormat(StringFormat.GenericTypographic) - { - FormatFlags = StringFormatFlags.MeasureTrailingSpaces - }; - var font = new Font(GlobalWin.DisplayManager.CustomFonts.Families[index], 8, FontStyle.Regular, GraphicsUnit.Pixel); - Size sizeOfText = g.MeasureString(message, font, 0, f).ToSize(); - var rect = new Rectangle(new Point(x, y), sizeOfText + new Size(1, 0)); - if (backcolor.HasValue) g.FillRectangle(GetBrush(backcolor.Value), rect); - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; - g.DrawString(message, font, GetBrush(forecolor ?? _defaultForeground), x, y); - } - catch (Exception) - { - return; + index = _defaultPixelFont; + break; } + using var g = GetGraphics(); + var font = new Font(GlobalWin.DisplayManager.CustomFonts.Families[index], 8, FontStyle.Regular, GraphicsUnit.Pixel); + var sizeOfText = g.MeasureString( + message, + font, + 0, + new StringFormat(StringFormat.GenericTypographic) { FormatFlags = StringFormatFlags.MeasureTrailingSpaces } + ).ToSize(); + if (backcolor.HasValue) g.FillRectangle(GetBrush(backcolor.Value), new Rectangle(new Point(x, y), sizeOfText + new Size(1, 0))); + g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; + g.DrawString(message, font, GetBrush(forecolor ?? _defaultForeground), x, y); + } + catch (Exception) + { + // ignored } } public void Text(int x, int y, string message, Color? forecolor = null, string anchor = null) { - var a = 0; - + int a = default; if (!string.IsNullOrEmpty(anchor)) { - switch (anchor) + a = anchor switch { - case "0": - case "topleft": - a = 0; - break; - case "1": - case "topright": - a = 1; - break; - case "2": - case "bottomleft": - a = 2; - break; - case "3": - case "bottomright": - a = 3; - break; - } + "0" => 0, + "topleft" => 0, + "1" => 1, + "topright" => 1, + "2" => 2, + "bottomleft" => 2, + "3" => 3, + "bottomright" => 3, + _ => default + }; } else { x -= Emulator.CoreComm.ScreenLogicalOffsetX; y -= Emulator.CoreComm.ScreenLogicalOffsetY; } - GlobalWin.OSD.AddGuiText(message, x, y, Color.Black, forecolor ?? Color.White, a); } + + public void Dispose() + { + foreach (var brush in _solidBrushes.Values) brush.Dispose(); + foreach (var brush in _pens.Values) brush.Dispose(); + } } } \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs b/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs index 56e2cd767f..35bcb60185 100644 --- a/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs +++ b/BizHawk.Client.EmuHawk/Api/Libraries/InputApi.cs @@ -1,33 +1,23 @@ -using System; +using System.Collections.Generic; using System.Linq; -using System.Collections.Generic; using System.Windows.Forms; -using BizHawk.Client.ApiHawk; using BizHawk.Client.Common; namespace BizHawk.Client.EmuHawk { public sealed class InputApi : IInput { - public InputApi() : base() - { } - - public Dictionary Get() + public Dictionary Get() { var buttons = new Dictionary(); - foreach (var kvp in Global.ControllerInputCoalescer.BoolButtons().Where(kvp => kvp.Value)) - { - buttons[kvp.Key] = true; - } - + foreach (var kvp in Global.ControllerInputCoalescer.BoolButtons().Where(kvp => kvp.Value)) buttons[kvp.Key] = true; return buttons; } public Dictionary GetMouse() { var buttons = new Dictionary(); - // TODO - need to specify whether in "emu" or "native" coordinate space. var p = GlobalWin.DisplayManager.UntransformPoint(Control.MousePosition); buttons["X"] = p.X; diff --git a/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateAPI.cs b/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateAPI.cs index e3802de5a0..91ae98df75 100644 --- a/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateAPI.cs +++ b/BizHawk.Client.EmuHawk/Api/Libraries/SaveStateAPI.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.IO; -using BizHawk.Client.ApiHawk; using BizHawk.Client.Common; namespace BizHawk.Client.EmuHawk @@ -23,32 +21,21 @@ namespace BizHawk.Client.EmuHawk if (!File.Exists(path)) { LogCallback($"could not find file: {path}"); + return; } - else - { - GlobalWin.MainForm.LoadState(path, Path.GetFileName(path), true, suppressOSD); - } + GlobalWin.MainForm.LoadState(path, Path.GetFileName(path), true, suppressOSD); } public void LoadSlot(int slotNum, bool suppressOSD) { - if (slotNum >= 0 && slotNum <= 9) - { - GlobalWin.MainForm.LoadQuickSave($"QuickSave{slotNum}", true, suppressOSD); - } + if (0 <= slotNum && slotNum <= 9) GlobalWin.MainForm.LoadQuickSave($"QuickSave{slotNum}", true, suppressOSD); } - public void Save(string path, bool suppressOSD) - { - GlobalWin.MainForm.SaveState(path, path, true, suppressOSD); - } + public void Save(string path, bool suppressOSD) => GlobalWin.MainForm.SaveState(path, path, true, suppressOSD); public void SaveSlot(int slotNum, bool suppressOSD) { - if (slotNum >= 0 && slotNum <= 9) - { - GlobalWin.MainForm.SaveQuickSave($"QuickSave{slotNum}", true, suppressOSD); - } + if (0 <= slotNum && slotNum <= 9) GlobalWin.MainForm.SaveQuickSave($"QuickSave{slotNum}", true, suppressOSD); } } } diff --git a/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs b/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs index d356761cdf..da4447c6a7 100644 --- a/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs +++ b/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs @@ -1,162 +1,38 @@ using System; -using System.Collections.Generic; using System.Linq; -using BizHawk.Common; -using BizHawk.Emulation.Common; -using BizHawk.Client.ApiHawk; using BizHawk.Client.Common; +using BizHawk.Common; namespace BizHawk.Client.EmuHawk { public sealed class ToolApi : ITool { - private class ToolStatic - { - public Type GetTool(string name) - { - var toolType = ReflectionUtil.GetTypeByName(name) - .FirstOrDefault(x => typeof(IToolForm).IsAssignableFrom(x) && !x.IsInterface); - - if (toolType != null) - { - GlobalWin.Tools.Load(toolType); - } - - var selectedTool = GlobalWin.Tools.AvailableTools - .FirstOrDefault(tool => tool.GetType().Name.ToLower() == name.ToLower()); - - if (selectedTool != null) - { - return selectedTool; - } - - return null; - } - - public object CreateInstance(string name) - { - var possibleTypes = ReflectionUtil.GetTypeByName(name); - - if (possibleTypes.Any()) - { - return Activator.CreateInstance(possibleTypes.First()); - } - - return null; - } - - public static void OpenCheats() - { - GlobalWin.Tools.Load(); - } - - public static void OpenHexEditor() - { - GlobalWin.Tools.Load(); - } - - public static void OpenRamWatch() - { - GlobalWin.Tools.LoadRamWatch(loadDialog: true); - } - - public static void OpenRamSearch() - { - GlobalWin.Tools.Load(); - } - - public static void OpenTasStudio() - { - GlobalWin.Tools.Load(); - } - - public static void OpenToolBox() - { - GlobalWin.Tools.Load(); - } - - public static void OpenTraceLogger() - { - GlobalWin.Tools.Load(); - } - - } - [RequiredService] - private static IEmulator Emulator { get; set; } - - [RequiredService] - private static IVideoProvider VideoProvider { get; set; } - - public ToolApi() - { } - public Type GetTool(string name) { - var toolType = ReflectionUtil.GetTypeByName(name) - .FirstOrDefault(x => typeof(IToolForm).IsAssignableFrom(x) && !x.IsInterface); - - if (toolType != null) - { - GlobalWin.Tools.Load(toolType); - } - - var selectedTool = GlobalWin.Tools.AvailableTools - .FirstOrDefault(tool => tool.GetType().Name.ToLower() == name.ToLower()); - - if (selectedTool != null) - { - return selectedTool; - } - - return null; + var toolType = ReflectionUtil.GetTypeByName(name).FirstOrDefault(x => typeof(IToolForm).IsAssignableFrom(x) && !x.IsInterface); + if (toolType != null) GlobalWin.Tools.Load(toolType); + return GlobalWin.Tools.AvailableTools.FirstOrDefault(tool => tool.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)); } public object CreateInstance(string name) { - var possibleTypes = ReflectionUtil.GetTypeByName(name); - - if (possibleTypes.Any()) - { - return Activator.CreateInstance(possibleTypes.First()); - } - - return null; + var found = ReflectionUtil.GetTypeByName(name).FirstOrDefault(); + return found != null ? Activator.CreateInstance(found) : null; } - public void OpenCheats() - { - ToolStatic.OpenCheats(); - } + public void OpenCheats() => GlobalWin.Tools.Load(); - public void OpenHexEditor() - { - ToolStatic.OpenHexEditor(); - } + public void OpenHexEditor() => GlobalWin.Tools.Load(); - public void OpenRamWatch() - { - ToolStatic.OpenRamWatch(); - } + public void OpenRamWatch() => GlobalWin.Tools.LoadRamWatch(loadDialog: true); - public void OpenRamSearch() - { - ToolStatic.OpenRamSearch(); - } + public void OpenRamSearch() => GlobalWin.Tools.Load(); - public void OpenTasStudio() - { - ToolStatic.OpenTasStudio(); - } + public void OpenTasStudio() => GlobalWin.Tools.Load(); - public void OpenToolBox() - { - ToolStatic.OpenToolBox(); - } + public void OpenToolBox() => GlobalWin.Tools.Load(); - public void OpenTraceLogger() - { - ToolStatic.OpenTraceLogger(); - } + public void OpenTraceLogger() => GlobalWin.Tools.Load(); } } diff --git a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs index 51034de78e..3ad8ec8f9d 100644 --- a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs +++ b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.Gui.cs @@ -21,9 +21,7 @@ namespace BizHawk.Client.EmuHawk public override string Name => "gui"; - #region Gui API - - public void Dispose() => APIs.Gui.Dispose(); + public bool HasLuaSurface => APIs.Gui.HasGUISurface; public bool SurfaceIsNull => !APIs.Gui.HasGUISurface; @@ -35,10 +33,6 @@ namespace BizHawk.Client.EmuHawk [LuaMethod("DrawFinish", "Finishes drawing to the current lua surface and causes it to get displayed.")] public void DrawFinish() => APIs.Gui.DrawFinish(); - public bool HasLuaSurface => APIs.Gui.HasGUISurface; - - #endregion - [LuaMethodExample("gui.addmessage( \"Some message\" );")] [LuaMethod("addmessage", "Adds a message to the OSD's message area")] public void AddMessage(string message) => APIs.Gui.AddMessage(message); @@ -194,5 +188,7 @@ namespace BizHawk.Client.EmuHawk canvas.Show(); return Lua.TableFromObject(canvas); } + + public void Dispose() => APIs.Gui.Dispose(); } }