From 7fb0eaf3379d9b3e9e9cde8fc3f3c08f3f991371 Mon Sep 17 00:00:00 2001 From: Hathor86 Date: Sun, 29 May 2016 16:50:16 +0200 Subject: [PATCH] Add Save/Load state methods and events to ApiHawk Now, ApiHawk can save and load name state. There are also events that you can attached too. Furthermore, BeforeQuickSave/BeforeQuickLoad events occurs just after user pressed button. We can react to this and even override behavior. Finally, I just allow .bat to take xml files (for ApiHawk doc) PS: Yeah, I'm still alive --- .../BizHawk.Client.ApiHawk.csproj | 8 ++ BizHawk.Client.ApiHawk/Classes/ClientApi.cs | 113 +++++++++++++++++- .../EventArgs/BeforeQuickLoadEventArgs.cs | 68 +++++++++++ .../EventArgs/BeforeQuickSaveEventArgs.cs | 69 +++++++++++ .../Events/EventArgs/StateLoadedEventArgs.cs | 44 +++++++ .../Events/EventArgs/StateSavedEventArgs.cs | 44 +++++++ .../BeforeQuickLoadEventhandler.cs | 9 ++ .../BeforeQuickSaveEventhandler.cs | 9 ++ .../EventHandlers/StateLoadedEventHandler.cs | 9 ++ .../EventHandlers/StateSavedEventHandler.cs | 9 ++ .../Classes/ExternalToolManager.cs | 3 +- .../Resources/ApiClassDiagram.cd | 62 +++++++++- BizHawk.Client.EmuHawk/MainForm.cs | 19 +++ Dist/BuildAndPackage.bat | 2 +- 14 files changed, 460 insertions(+), 8 deletions(-) create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickLoadEventArgs.cs create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickSaveEventArgs.cs create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateLoadedEventArgs.cs create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateSavedEventArgs.cs create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickLoadEventhandler.cs create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickSaveEventhandler.cs create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateLoadedEventHandler.cs create mode 100644 BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateSavedEventHandler.cs diff --git a/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj b/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj index daac456de0..4444e73164 100644 --- a/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj +++ b/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj @@ -99,6 +99,14 @@ + + + + + + + + diff --git a/BizHawk.Client.ApiHawk/Classes/ClientApi.cs b/BizHawk.Client.ApiHawk/Classes/ClientApi.cs index 30b9424167..8dd45af913 100644 --- a/BizHawk.Client.ApiHawk/Classes/ClientApi.cs +++ b/BizHawk.Client.ApiHawk/Classes/ClientApi.cs @@ -4,11 +4,12 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; - using BizHawk.Client.Common; using BizHawk.Emulation.Cores.Nintendo.Gameboy; using BizHawk.Emulation.Cores.PCEngine; using BizHawk.Emulation.Cores.Sega.MasterSystem; +using BizHawk.Client.ApiHawk.Classes.Events; +using System.IO; namespace BizHawk.Client.ApiHawk { @@ -28,10 +29,31 @@ namespace BizHawk.Client.ApiHawk internal static readonly BizHawkSystemIdToEnumConverter SystemIdConverter = new BizHawkSystemIdToEnumConverter(); internal static readonly JoypadStringToEnumConverter JoypadConverter = new JoypadStringToEnumConverter(); - public static event EventHandler RomLoaded; - private static List allJoypads; + /// + /// Occurs before a quickload is done (just after user has pressed the shortcut button + /// or has click on the item menu) + /// + public static event BeforeQuickLoadEventHandler BeforeQuickLoad; + /// + /// Occurs before a quicksave is done (just after user has pressed the shortcut button + /// or has click on the item menu) + /// + public static event BeforeQuickSaveEventHandler BeforeQuickSave; + /// + /// Occurs when a ROM is succesfully loaded + /// + public static event EventHandler RomLoaded; + /// + /// Occurs when a savestate is sucessfully loaded + /// + public static event StateLoadedEventHandler StateLoaded; + /// + /// Occurs when a savestate is successfully saved + /// + public static event StateSavedEventHandler StateSaved; + #endregion #region cTor(s) @@ -95,6 +117,80 @@ namespace BizHawk.Client.ApiHawk } } + + /// + /// Load a savestate specified by its name + /// + /// Savetate friendly name + public static void LoadState(string name) + { + MethodInfo method = mainFormClass.GetMethod("LoadState"); + method.Invoke(clientMainFormInstance, new object[] { Path.Combine(PathManager.GetSaveStatePath(Global.Game), string.Format("{0}.{1}", name, "State")), name, false, false }); + } + + + /// + /// Raised before a quickload is done (just after pressing shortcut button) + /// + /// Object who raised the event + /// Slot used for quickload + /// A boolean that can be set if users want to handle save themselves; if so, BizHawk won't do anything + public static void OnBeforeQuickLoad(object sender, string quickSaveSlotName, out bool eventHandled) + { + eventHandled = false; + if (BeforeQuickLoad != null) + { + BeforeQuickLoadEventArgs e = new BeforeQuickLoadEventArgs(quickSaveSlotName); + BeforeQuickLoad(sender, e); + eventHandled = e.Handled; + } + } + + + /// + /// Raised before a quicksave is done (just after pressing shortcut button) + /// + /// Object who raised the event + /// Slot used for quicksave + /// A boolean that can be set if users want to handle save themselves; if so, BizHawk won't do anything + public static void OnBeforeQuickSave(object sender, string quickSaveSlotName, out bool eventHandled) + { + eventHandled = false; + if (BeforeQuickSave != null) + { + BeforeQuickSaveEventArgs e = new BeforeQuickSaveEventArgs(quickSaveSlotName); + BeforeQuickSave(sender, e); + eventHandled = e.Handled; + } + } + + + /// + /// Raise when a state is loaded + /// + /// Object who raised the event + /// User friendly name for saved state + public static void OnStateLoaded(object sender, string stateName) + { + if (StateLoaded != null) + { + StateLoaded(sender, new StateLoadedEventArgs(stateName)); + } + } + + /// + /// Raise when a state is saved + /// + /// Object who raised the event + /// User friendly name for saved state + public static void OnStateSaved(object sender, string stateName) + { + if (StateSaved != null) + { + StateSaved(sender, new StateSavedEventArgs(stateName)); + } + } + /// /// Raise when a rom is successfully Loaded /// @@ -113,6 +209,17 @@ namespace BizHawk.Client.ApiHawk } + /// + /// Save a state with specified name + /// + /// Savetate friendly name + public static void SaveState(string name) + { + MethodInfo method = mainFormClass.GetMethod("SaveState"); + method.Invoke(clientMainFormInstance, new object[] { Path.Combine(PathManager.GetSaveStatePath(Global.Game), string.Format("{0}.{1}", name, "State")), name, false }); + } + + /// /// Sets the extra padding added to the 'native' surface so that you can draw HUD elements in predictable placements /// diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickLoadEventArgs.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickLoadEventArgs.cs new file mode 100644 index 0000000000..85fe83d1f8 --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickLoadEventArgs.cs @@ -0,0 +1,68 @@ +using System; + +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// This class holds event data for BeforeQuickLoad event + /// + public sealed class BeforeQuickLoadEventArgs : EventArgs + { + #region Fields + + private bool _Handled = false; + private string _QuickSaveSlotName; + + #endregion + + #region cTor(s) + + internal BeforeQuickLoadEventArgs(string name) + { + _QuickSaveSlotName = name; + } + + #endregion + + #region Properties + + /// + /// Gets or sets value that defined if saved has been handled or not + /// + public bool Handled + { + get + { + return _Handled; + } + set + { + _Handled = value; + } + } + + /// + /// Gets quicksave name + /// + public string Name + { + get + { + return _QuickSaveSlotName; + } + } + + + /// + /// Gets slot used for quicksave + /// + public int Slot + { + get + { + return int.Parse(_QuickSaveSlotName.Substring(_QuickSaveSlotName.Length - 1)); + } + } + + #endregion + } +} diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickSaveEventArgs.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickSaveEventArgs.cs new file mode 100644 index 0000000000..b186f82aba --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/BeforeQuickSaveEventArgs.cs @@ -0,0 +1,69 @@ +using System; + +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// This class holds event data for BeforeQuickSave event + /// + public sealed class BeforeQuickSaveEventArgs : EventArgs + { + #region Fields + + private bool _Handled = false; + private string _QuickSaveSlotName; + + #endregion + + #region cTor(s) + + internal BeforeQuickSaveEventArgs(string name) + { + _QuickSaveSlotName = name; + } + + #endregion + + #region Properties + + /// + /// Gets or sets value that defined if saved has been handled or not + /// + public bool Handled + { + get + { + return _Handled; + } + set + { + _Handled = value; + } + } + + + /// + /// Gets quicksave name + /// + public string Name + { + get + { + return _QuickSaveSlotName; + } + } + + + /// + /// Gets slot used for quicksave + /// + public int Slot + { + get + { + return int.Parse(_QuickSaveSlotName.Substring(_QuickSaveSlotName.Length - 1)); + } + } + + #endregion + } +} diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateLoadedEventArgs.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateLoadedEventArgs.cs new file mode 100644 index 0000000000..0dfc5b3729 --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateLoadedEventArgs.cs @@ -0,0 +1,44 @@ +using System; + +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// This class holds event data for StateLoaded event + /// + public sealed class StateLoadedEventArgs: EventArgs + { + #region Fields + + string _Name; + + #endregion + + #region cTor(s) + + /// + /// Initialize a new instance of + /// + /// User friendly name of loaded state + internal StateLoadedEventArgs(string stateName) + { + _Name = stateName; + } + + #endregion + + #region Properties + + /// + /// Gets user friendly name of the loaded savestate + /// + public string Name + { + get + { + return _Name; + } + } + + #endregion + } +} diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateSavedEventArgs.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateSavedEventArgs.cs new file mode 100644 index 0000000000..a2d00690eb --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventArgs/StateSavedEventArgs.cs @@ -0,0 +1,44 @@ +using System; + +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// This class holds event data for StateSaved event + /// + public sealed class StateSavedEventArgs : EventArgs + { + #region Fields + + string _Name; + + #endregion + + #region cTor(s) + + /// + /// Initialize a new instance of + /// + /// User friendly name of loaded state + internal StateSavedEventArgs(string stateName) + { + _Name = stateName; + } + + #endregion + + #region Properties + + /// + /// Gets user friendly name of the loaded savestate + /// + public string Name + { + get + { + return _Name; + } + } + + #endregion + } +} diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickLoadEventhandler.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickLoadEventhandler.cs new file mode 100644 index 0000000000..86c19b7bef --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickLoadEventhandler.cs @@ -0,0 +1,9 @@ +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// Represent a method that will handle the event raised before a quickload is done + /// + /// Object that raised the event + /// Event arguments + public delegate void BeforeQuickLoadEventHandler(object sender, BeforeQuickLoadEventArgs e); +} diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickSaveEventhandler.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickSaveEventhandler.cs new file mode 100644 index 0000000000..fdb5ba6fab --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/BeforeQuickSaveEventhandler.cs @@ -0,0 +1,9 @@ +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// Represent a method that will handle the event raised before a quicksave is done + /// + /// Object that raised the event + /// Event arguments + public delegate void BeforeQuickSaveEventHandler(object sender, BeforeQuickSaveEventArgs e); +} diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateLoadedEventHandler.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateLoadedEventHandler.cs new file mode 100644 index 0000000000..e5debf85d6 --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateLoadedEventHandler.cs @@ -0,0 +1,9 @@ +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// Represent a method that will handle the event raised when a savestate is loaded + /// + /// Object that raised the event + /// Event arguments + public delegate void StateLoadedEventHandler(object sender, StateLoadedEventArgs e); +} diff --git a/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateSavedEventHandler.cs b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateSavedEventHandler.cs new file mode 100644 index 0000000000..ae8a026171 --- /dev/null +++ b/BizHawk.Client.ApiHawk/Classes/Events/EventHandlers/StateSavedEventHandler.cs @@ -0,0 +1,9 @@ +namespace BizHawk.Client.ApiHawk.Classes.Events +{ + /// + /// Represent a method that will handle the event raised when a savestate is saved + /// + /// Object that raised the event + /// Event arguments + public delegate void StateSavedEventHandler(object sender, StateSavedEventArgs e); +} diff --git a/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs b/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs index 1217959080..dc6ac9e114 100644 --- a/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs +++ b/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs @@ -75,12 +75,13 @@ namespace BizHawk.Client.ApiHawk /// /// File that will be reflected /// A new ; assembly path can be found in the Tag property - /// For the moment, you could only load a dll that have a form (which implements ) + /// For the moment, you could only load a dll that have a form (which implements ) private static ToolStripMenuItem GenerateToolTipFromFileName(string fileName) { Type customFormType; Assembly externalToolFile; ToolStripMenuItem item = null; + try { externalToolFile = Assembly.LoadFrom(fileName); diff --git a/BizHawk.Client.ApiHawk/Resources/ApiClassDiagram.cd b/BizHawk.Client.ApiHawk/Resources/ApiClassDiagram.cd index e67e4c43d9..8a40328080 100644 --- a/BizHawk.Client.ApiHawk/Resources/ApiClassDiagram.cd +++ b/BizHawk.Client.ApiHawk/Resources/ApiClassDiagram.cd @@ -53,7 +53,7 @@ - CQEAAAAAgAAAQAAAAAABQAIAAAAAoGAACCAAAAAQAAA= + CwEAAAAAgAMAQEAAAAAJQAoAAAEAgWAACCACAAAQAiA= Classes\ClientApi.cs @@ -81,14 +81,42 @@ - AQAACAAAAIAAAACBAAgAAABAEAAAAAAAAAAAAAAAAAA= + AQAACAAAAIAAAACBAAgAAABAEAAAAAAAAAACGAAAAAA= Classes\Joypad.cs - + + + + + AAAAAAAAAAAAAAAAAAAAIAQAAAAAAAAAAAAAAAAAAAA= + Classes\Events\EventArgs\StateLoadedEventArgs.cs + + + + + + AAAAAAAAAAAAAAAAAAAAIAQAAAAAAAAAAAAAAAAAAAA= + Classes\Events\EventArgs\StateSavedEventArgs.cs + + + + + + AAAAAAAAIAAAQAAAAACAAAAAAAAAAAAAAAAAAAAAAgA= + Classes\Events\EventArgs\BeforeQuickSaveEventArgs.cs + + + + + + AAAAAAAAIAAAQAAAAACAAAAAAAAAAAAAAAAAAAAAAgA= + Classes\Events\EventArgs\BeforeQuickLoadEventArgs.cs + + @@ -131,5 +159,33 @@ + + + + AAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAA= + Classes\Events\EventHandlers\StateLoadedEventHandler.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAgA= + Classes\Events\EventHandlers\StateSavedEventHandler.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAEA= + Classes\Events\EventHandlers\BeforeQuickSaveEventhandler.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAACAAAAA= + Classes\Events\EventHandlers\BeforeQuickLoadEventhandler.cs + + \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 0024be8a3c..ec38f97b5f 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -34,6 +34,7 @@ using BizHawk.Emulation.Cores.Nintendo.N64; using BizHawk.Client.EmuHawk.WinFormExtensions; using BizHawk.Client.EmuHawk.ToolExtensions; using BizHawk.Client.EmuHawk.CoreExtensions; +using BizHawk.Client.ApiHawk; namespace BizHawk.Client.EmuHawk { @@ -3700,6 +3701,8 @@ namespace BizHawk.Client.EmuHawk if (SavestateManager.LoadStateFile(path, userFriendlyStateName)) { + ClientApi.OnStateLoaded(this, userFriendlyStateName); + if (GlobalWin.Tools.Has()) { GlobalWin.Tools.LuaConsole.LuaImp.CallLoadStateEvent(userFriendlyStateName); @@ -3732,6 +3735,13 @@ namespace BizHawk.Client.EmuHawk return; } + bool handled; + ClientApi.OnBeforeQuickLoad(this, quickSlotName, out handled); + if (handled) + { + return; + } + if (IsSlave && master.WantsToControlSavestates) { master.LoadQuickSave(SlotToInt(quickSlotName)); @@ -3766,6 +3776,8 @@ namespace BizHawk.Client.EmuHawk { SavestateManager.SaveStateFile(path, userFriendlyStateName); + ClientApi.OnStateSaved(this, userFriendlyStateName); + GlobalWin.OSD.AddMessage("Saved state: " + userFriendlyStateName); } catch (IOException) @@ -3786,6 +3798,13 @@ namespace BizHawk.Client.EmuHawk return; } + bool handled; + ClientApi.OnBeforeQuickSave(this, quickSlotName, out handled); + if(handled) + { + return; + } + if (IsSlave && master.WantsToControlSavestates) { master.SaveQuickSave(SlotToInt(quickSlotName)); diff --git a/Dist/BuildAndPackage.bat b/Dist/BuildAndPackage.bat index 5c2e2cb9a2..c64992180c 100644 --- a/Dist/BuildAndPackage.bat +++ b/Dist/BuildAndPackage.bat @@ -33,7 +33,7 @@ rem explicitly list the OK ones here as individual copies. until then.... copy *.dll dll rem Now, we're about to zip and then unzip. Why, you ask? Because that's just the way this evolved. -..\dist\zip.exe -X -r ..\Dist\%NAME% EmuHawk.exe DiscoHawk.exe defctrl.json dll shaders gamedb Tools NES\Palettes Lua Gameboy\Palettes -x *.pdb -x *.lib -x *.pgd -x *.ipdb -x *.iobj -x *.exp -x dll\libsneshawk-64*.exe -x *.ilk -x dll\gpgx.elf -x dll\miniclient.* -x dll\*.xml +..\dist\zip.exe -X -r ..\Dist\%NAME% EmuHawk.exe DiscoHawk.exe defctrl.json dll shaders gamedb Tools NES\Palettes Lua Gameboy\Palettes -x *.pdb -x *.lib -x *.pgd -x *.ipdb -x *.iobj -x *.exp -x dll\libsneshawk-64*.exe -x *.ilk -x dll\gpgx.elf -x dll\miniclient.* cd ..\Dist .\unzip.exe %NAME% -d temp