diff --git a/ExternalToolProjects/.build_from_cwd_debug.sh b/ExternalToolProjects/.build_net48_from_cwd_debug.sh similarity index 65% rename from ExternalToolProjects/.build_from_cwd_debug.sh rename to ExternalToolProjects/.build_net48_from_cwd_debug.sh index d9cec13428..2f0184cb55 100755 --- a/ExternalToolProjects/.build_from_cwd_debug.sh +++ b/ExternalToolProjects/.build_net48_from_cwd_debug.sh @@ -1,3 +1,3 @@ #!/bin/sh name="$(basename "$PWD").dll" -CscToolExe="$(which csc)" dotnet build -c Debug -m && cp -f "bin/Debug/$name" "../../output/ExternalTools/$name" +CscToolExe="$(which csc)" dotnet build -c Debug -m && cp -f "bin/Debug/net48/$name" "../../output/ExternalTools/$name" diff --git a/ExternalToolProjects/.build_from_cwd_release.sh b/ExternalToolProjects/.build_net48_from_cwd_release.sh similarity index 63% rename from ExternalToolProjects/.build_from_cwd_release.sh rename to ExternalToolProjects/.build_net48_from_cwd_release.sh index 3315f6f4e6..40d7ba70db 100755 --- a/ExternalToolProjects/.build_from_cwd_release.sh +++ b/ExternalToolProjects/.build_net48_from_cwd_release.sh @@ -1,3 +1,3 @@ #!/bin/sh name="$(basename "$PWD").dll" -CscToolExe="$(which csc)" dotnet build -c Release -m && cp -f "bin/Release/$name" "../../output/ExternalTools/$name" +CscToolExe="$(which csc)" dotnet build -c Release -m && cp -f "bin/Release/net48/$name" "../../output/ExternalTools/$name" diff --git a/ExternalToolProjects/Common.props b/ExternalToolProjects/Common.props new file mode 100644 index 0000000000..76d80bbf9a --- /dev/null +++ b/ExternalToolProjects/Common.props @@ -0,0 +1,29 @@ + + + $(ProjectDir)../../Common.ruleset + prompt + false + 8.0 + enable + $(ProjectDir)bin/$(Configuration) + AnyCPU + false + false + + + true + full + DEBUG;TRACE + false + + + false + pdbonly + TRACE + true + + + + + + diff --git a/ExternalToolProjects/HelloWorld/CustomMainForm.cs b/ExternalToolProjects/HelloWorld/CustomMainForm.cs index d112a3da4b..14a80644b6 100644 --- a/ExternalToolProjects/HelloWorld/CustomMainForm.cs +++ b/ExternalToolProjects/HelloWorld/CustomMainForm.cs @@ -5,65 +5,115 @@ using System.IO; using BizHawk.Client.ApiHawk; using BizHawk.Client.Common; using BizHawk.Emulation.Common; -using BizHawk.Client.ApiHawk.Classes.Events; + +using DisplayType = BizHawk.Client.Common.DisplayType; namespace BizHawk.Client.EmuHawk { - /// - /// Here your first form - /// /!\ it MUST be called CustomMainForm and implements IExternalToolForm - /// Take also care of the namespace - /// + /// ExternalToolForms must be a class named CustomMainForm in namespace BizHawk.Client.EmuHawk. public partial class CustomMainForm : Form, IExternalToolForm { - #region Fields - - /* - The following stuff will be automatically filled - by BizHawk runtime - */ + /// RequiredServices are populated by EmuHawk at runtime. [RequiredService] - internal IMemoryDomains _memoryDomains { get; set; } + private IEmulator? _emu { get; set; } + [RequiredService] - private IEmulator _emu { get; set; } + private IMemoryDomains? _memoryDomains { get; set; } - /*private members for our needed*/ - private WatchList _watches; + private WatchList? _watches; - #endregion - - #region cTor(s) + private WatchList Watches + { + get + { + WatchList CreateWatches() + { + var w = new WatchList(_memoryDomains, _emu?.SystemId ?? string.Empty); + w.AddRange(new[] { + Watch.GenerateWatch(_memoryDomains?.MainMemory, 0x40, WatchSize.Byte, DisplayType.Hex, true), + Watch.GenerateWatch(_memoryDomains?.MainMemory, 0x50, WatchSize.Word, DisplayType.Unsigned, true), + Watch.GenerateWatch(_memoryDomains?.MainMemory, 0x60, WatchSize.DWord, DisplayType.Hex, true) + }); + return w; + } + _watches ??= CreateWatches(); + return _watches; + } + } public CustomMainForm() { InitializeComponent(); - label_GameHash.Click += Label_GameHash_Click; + label_GameHash.Click += label_GameHash_Click; - ClientApi.BeforeQuickSave += ClientApi_BeforeQuickSave; - ClientApi.BeforeQuickLoad += ClientApi_BeforeQuickLoad; + ClientApi.BeforeQuickSave += (sender, e) => + { + if (e.Slot != 0) return; // only take effect on slot 0 + var basePath = Path.Combine(PathManager.GetSaveStatePath(Global.Game), "Test"); + if (!Directory.Exists(basePath)) Directory.CreateDirectory(basePath); + ClientApi.SaveState(Path.Combine(basePath, e.Name)); + e.Handled = true; + }; + ClientApi.BeforeQuickLoad += (sender, e) => + { + if (e.Slot != 0) return; // only take effect on slot 0 + var basePath = Path.Combine(PathManager.GetSaveStatePath(Global.Game), "Test"); + ClientApi.LoadState(Path.Combine(basePath, e.Name)); + e.Handled = true; + }; } - #endregion + /// We want to be called before rendering. + public bool UpdateBefore => true; - #region Methods + public bool AskSaveChanges() => true; - private void button1_Click(object sender, EventArgs e) + /// This is called instead of the usual when EmuHawk is turboing. + public void FastUpdate() {} + + public void NewUpdate(ToolFormUpdateType type) {} + + /// This is called once when the form is opened, and every time a new movie session starts. + public void Restart() { - ClientApi.DoFrameAdvance(); +#if false + ClientApi.SetExtraPadding(50, 50); +#endif + + if (Global.Game.Name != "Null") + { + Watches.RefreshDomains(_memoryDomains); + label_Game.Text = $"You're playing {Global.Game.Name}"; + label_GameHash.Text = $"Hash: {Global.Game.Hash}"; + } + else + { + label_Game.Text = "You're playing... nothing"; + label_GameHash.Text = string.Empty; + } } - private void button2_Click(object sender, EventArgs e) + /// Called just before every video frame. + public void UpdateValues() { - ClientApi.GetInput(1); + if (Global.Game.Name == "Null" || Watches.Count < 3) return; + Watches.UpdateValues(); + label_Watch1.Text = $"First watch ({Watches[0].AddressString}) current value: {Watches[0].ValueString}"; + label_Watch2.Text = $"Second watch ({Watches[1].AddressString}) current value: {Watches[1].ValueString}"; + label_Watch3.Text = $"Third watch ({Watches[2].AddressString}) current value: {Watches[2].ValueString}"; } + private void button1_Click(object sender, EventArgs e) => ClientApi.DoFrameAdvance(); + + private void button2_Click(object sender, EventArgs e) => ClientApi.GetInput(1); + private void button3_Click(object sender, EventArgs e) { - for (int i = 0; i < 600; i++) + for (var i = 0; i < 600; i++) { if (i % 60 == 0) { - Joypad j1 = ClientApi.GetInput(1); + var j1 = ClientApi.GetInput(1); j1.AddInput(JoypadButton.A); ClientApi.SetInput(1, j1); @@ -75,154 +125,29 @@ namespace BizHawk.Client.EmuHawk } ClientApi.DoFrameAdvance(); } - Joypad j = ClientApi.GetInput(1); + var j = ClientApi.GetInput(1); j.ClearInputs(); ClientApi.SetInput(1, j); } - private void Label_GameHash_Click(object sender, EventArgs e) - { - Clipboard.SetText(Global.Game.Hash); - } + private void label_GameHash_Click(object sender, EventArgs e) => Clipboard.SetText(Global.Game.Hash); private void loadstate_Click(object sender, EventArgs e) { - if (savestateName.Text.Trim() != string.Empty) + if (string.IsNullOrWhiteSpace(savestateName.Text)) return; + ClientApi.LoadState(savestateName.Text); +#if false + static void Test(BinaryReader r) { - ClientApi.LoadState(savestateName.Text); - //BinaryStateLoader.LoadAndDetect(savestateName.Text + ".State").GetLump(BinaryStateLump.Framebuffer, false, Test); + var b = new System.Drawing.Bitmap(r.BaseStream); } + BinaryStateLoader.LoadAndDetect($"{savestateName.Text}.State").GetLump(BinaryStateLump.Framebuffer, false, Test); +#endif } - /*private void Test(BinaryReader r) - { - System.Drawing.Bitmap b = new System.Drawing.Bitmap(r.BaseStream); - }*/ - private void saveState_Click(object sender, EventArgs e) { - if (savestateName.Text.Trim() != string.Empty) - { - ClientApi.SaveState(savestateName.Text); - } + if (!string.IsNullOrWhiteSpace(savestateName.Text)) ClientApi.SaveState(savestateName.Text); } - - //We will override F10 quicksave behavior - private void ClientApi_BeforeQuickSave(object sender, BeforeQuickSaveEventArgs e) - { - if(e.Slot == 0) - { - string basePath = Path.Combine(PathManager.GetSaveStatePath(Global.Game), "Test"); - if (!Directory.Exists(basePath)) - { - Directory.CreateDirectory(basePath); - } - ClientApi.SaveState(Path.Combine(basePath, e.Name)); - e.Handled = true; - } - } - - //We will override F10 quickload behavior - private void ClientApi_BeforeQuickLoad(object sender, BeforeQuickLoadEventArgs e) - { - if (e.Slot == 0) - { - string basePath = Path.Combine(PathManager.GetSaveStatePath(Global.Game), "Test"); - ClientApi.LoadState(Path.Combine(basePath, e.Name)); - e.Handled = true; - } - } - - #endregion - - #region BizHawk Required methods - - /// - /// Return true if you want the method - /// to be called before rendering - /// - public bool UpdateBefore - { - get - { - return true; - } - } - - public bool AskSaveChanges() - { - return true; - } - - /// - /// This method is called instead of regular - /// when emulator is runnig in turbo mode - /// - public void FastUpdate() - { } - - public void NewUpdate(ToolFormUpdateType type) {} - - /// - /// Restart is called the first time you call the form - /// but also when you start playing a movie - /// - public void Restart() - { - //set a client padding -// ClientApi.SetExtraPadding(50, 50); - - if (Global.Game.Name != "Null") - { - //first initialization of WatchList - if (_watches == null) - { - _watches = new WatchList(_memoryDomains, _emu.SystemId ?? string.Empty); - - //Create some watch - Watch myFirstWatch = Watch.GenerateWatch(_memoryDomains.MainMemory, 0x40, WatchSize.Byte, BizHawk.Client.Common.DisplayType.Hex, true); - Watch mySecondWatch = Watch.GenerateWatch(_memoryDomains.MainMemory, 0x50, WatchSize.Word, BizHawk.Client.Common.DisplayType.Unsigned, true); - Watch myThirdWatch = Watch.GenerateWatch(_memoryDomains.MainMemory, 0x60, WatchSize.DWord, BizHawk.Client.Common.DisplayType.Hex, true); - - //add them into the list - _watches.Add(myFirstWatch); - _watches.Add(mySecondWatch); - _watches.Add(myThirdWatch); - - label_Game.Text = string.Format("You're playing {0}", Global.Game.Name); - label_GameHash.Text = string.Format("Hash: {0}", Global.Game.Hash); - } - //refresh it - else - { - _watches.RefreshDomains(_memoryDomains); - label_Game.Text = string.Format("You're playing {0}", Global.Game.Name); - label_GameHash.Text = string.Format("Hash: {0}", Global.Game.Hash); - } - } - else - { - label_Game.Text = string.Format("You aren't playing to anything"); - label_GameHash.Text = string.Empty; - } - } - - /// - /// This method is called when a frame is rendered - /// You can comapre it the lua equivalent emu.frameadvance() - /// - public void UpdateValues() - { - if (Global.Game.Name != "Null") - { - //we update our watches - _watches.UpdateValues(); - label_Watch1.Text = string.Format("First watch ({0}) current value: {1}", _watches[0].AddressString, _watches[0].ValueString); - label_Watch2.Text = string.Format("Second watch ({0}) current value: {1}", _watches[1].AddressString, _watches[1].ValueString); - label_Watch3.Text = string.Format("Third watch ({0}) current value: {1}", _watches[2].AddressString, _watches[2].ValueString); - } - } - - #endregion BizHawk Required methods } } diff --git a/ExternalToolProjects/HelloWorld/CustomMainForm.resx b/ExternalToolProjects/HelloWorld/CustomMainForm.resx deleted file mode 100644 index 29dcb1b3a3..0000000000 --- a/ExternalToolProjects/HelloWorld/CustomMainForm.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/ExternalToolProjects/HelloWorld/HelloWorld.csproj b/ExternalToolProjects/HelloWorld/HelloWorld.csproj index f79340d31e..7827027f2b 100644 --- a/ExternalToolProjects/HelloWorld/HelloWorld.csproj +++ b/ExternalToolProjects/HelloWorld/HelloWorld.csproj @@ -1,80 +1,11 @@ - - - - - - Debug - AnyCPU - {288D598F-1019-4EA2-802D-14D3CC73EE90} - Library - Properties - HelloWorld - HelloWorld - v4.6.1 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - x64 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - x64 - - - - - - - - - - - - - - - - - - Form - - - CustomMainForm.cs - - - - - - CustomMainForm.cs - - - - - - - - + + + + + + + + + + + diff --git a/ExternalToolProjects/HelloWorld/build_debug.sh b/ExternalToolProjects/HelloWorld/build_debug.sh index 43e0170d2e..c4d41e9cbf 120000 --- a/ExternalToolProjects/HelloWorld/build_debug.sh +++ b/ExternalToolProjects/HelloWorld/build_debug.sh @@ -1 +1 @@ -../.build_from_cwd_debug.sh \ No newline at end of file +../.build_net48_from_cwd_debug.sh \ No newline at end of file diff --git a/ExternalToolProjects/HelloWorld/build_release.sh b/ExternalToolProjects/HelloWorld/build_release.sh index 89b0b361c0..73e473fcc2 120000 --- a/ExternalToolProjects/HelloWorld/build_release.sh +++ b/ExternalToolProjects/HelloWorld/build_release.sh @@ -1 +1 @@ -../.build_from_cwd_release.sh \ No newline at end of file +../.build_net48_from_cwd_release.sh \ No newline at end of file diff --git a/ExternalToolProjects/NET48ExternalToolForm.props b/ExternalToolProjects/NET48ExternalToolForm.props new file mode 100644 index 0000000000..740015a650 --- /dev/null +++ b/ExternalToolProjects/NET48ExternalToolForm.props @@ -0,0 +1,27 @@ + + + net48 + + + + + + + + + + + +