From f0692111d7d6089561f57832f7510a926ad1d4cb Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sun, 23 Feb 2020 09:54:42 -0500 Subject: [PATCH] SubGBHawk: add --- BizHawk.Client.Common/RomLoader.cs | 18 ++- BizHawk.Client.Common/config/Config.cs | 1 + BizHawk.Client.EmuHawk/MainForm.Designer.cs | 13 +- BizHawk.Client.EmuHawk/MainForm.Events.cs | 12 ++ .../Nintendo/GBHawk/GBHawk.IEmulator.cs | 2 +- .../Consoles/Nintendo/GBHawk/GBHawk.cs | 2 +- .../Nintendo/GBHawk/Mappers/Mapper_Camera.cs | 4 +- .../Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs | 143 ++++++++++++++++++ .../SubGBHawk/SubGBHawk.IInputPollable.cs | 24 +++ .../Nintendo/SubGBHawk/SubGBHawk.IStatable.cs | 50 ++++++ .../Consoles/Nintendo/SubGBHawk/SubGBHawk.cs | 66 ++++++++ 11 files changed, 327 insertions(+), 8 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IInputPollable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index 6e35d5d839..5bdd41b8df 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -1042,9 +1042,16 @@ namespace BizHawk.Client.Common case "GB": if (!Global.Config.GbAsSgb) { - core = Global.Config.GbUseGbHawk + if (Global.Config.UseSubGBHawk) + { + core = CoreInventory.Instance["GB", "SubGBHawk"]; + } + else + { + core = Global.Config.GbUseGbHawk ? CoreInventory.Instance["GB", "GBHawk"] : CoreInventory.Instance["GB", "Gambatte"]; + } } else { @@ -1064,9 +1071,16 @@ namespace BizHawk.Client.Common case "GBC": if (!Global.Config.GbAsSgb) { - core = Global.Config.GbUseGbHawk + if (Global.Config.UseSubGBHawk) + { + core = CoreInventory.Instance["GB", "SubGBHawk"]; + } + else + { + core = Global.Config.GbUseGbHawk ? CoreInventory.Instance["GBC", "GBHawk"] : CoreInventory.Instance["GBC", "Gambatte"]; + } } else { diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs index 810ddb4de5..7391c6dbe2 100644 --- a/BizHawk.Client.Common/config/Config.cs +++ b/BizHawk.Client.Common/config/Config.cs @@ -306,6 +306,7 @@ namespace BizHawk.Client.Common // it hasn't been absorbed into the new system public bool GbAsSgb { get; set; } public bool UseSubNESHawk { get; set; } + public bool UseSubGBHawk { get; set; } public bool NesInQuickNes { get; set; } = true; public bool SnesInSnes9x { get; set; } = true; public bool GbaUsemGba { get; set; } = true; diff --git a/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/BizHawk.Client.EmuHawk/MainForm.Designer.cs index f43889f87d..93eff34d39 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -187,6 +187,7 @@ this.NesCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator38 = new System.Windows.Forms.ToolStripSeparator(); this.SubNesHawkMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SubGBHawkMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.CoreSNESSubMenu = new System.Windows.Forms.ToolStripMenuItem(); this.Coresnes9xMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.CorebsnesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -1849,6 +1850,13 @@ this.SubNesHawkMenuItem.Text = "SubNesHawk (Experimental)"; this.SubNesHawkMenuItem.Click += new System.EventHandler(this.SubNesCorePick_Click); // + // SubGBHawkMenuItem + // + this.SubGBHawkMenuItem.Name = "SubGBHawkMenuItem"; + this.SubGBHawkMenuItem.Size = new System.Drawing.Size(209, 22); + this.SubGBHawkMenuItem.Text = "SubGBHawk (Experimental)"; + this.SubGBHawkMenuItem.Click += new System.EventHandler(this.SubGBCorePick_Click); + // // CoreSNESSubMenu // this.CoreSNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -1925,7 +1933,9 @@ // this.GBCoreSubmenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.GBGambatteMenuItem, - this.GBGBHawkMenuItem}); + this.GBGBHawkMenuItem, + this.toolStripSeparator38, + this.SubGBHawkMenuItem}); this.GBCoreSubmenu.Name = "GBCoreSubmenu"; this.GBCoreSubmenu.Size = new System.Drawing.Size(223, 22); this.GBCoreSubmenu.Text = "GB"; @@ -4451,6 +4461,7 @@ private System.Windows.Forms.ToolStripMenuItem cpcd1ToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem AmstradCPCNonSyncSettingsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem SubNesHawkMenuItem; + private System.Windows.Forms.ToolStripMenuItem SubGBHawkMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator38; private System.Windows.Forms.ToolStripMenuItem arcadeToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem2; diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index 96d68d6bc1..ecf78f3592 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -1228,6 +1228,16 @@ namespace BizHawk.Client.EmuHawk } } + private void SubGBCorePick_Click(object sender, EventArgs e) + { + Config.UseSubGBHawk ^= true; + + if (!Emulator.IsNull()) + { + FlagNeedsReboot(); + } + } + private void CoreSNESSubMenu_DropDownOpened(object sender, EventArgs e) { Coresnes9xMenuItem.Checked = Config.SnesInSnes9x; @@ -1269,6 +1279,7 @@ namespace BizHawk.Client.EmuHawk { GBGambatteMenuItem.Checked = !Config.GbUseGbHawk; GBGBHawkMenuItem.Checked = Config.GbUseGbHawk; + SubGBHawkMenuItem.Checked = Config.UseSubGBHawk; } private void SgbCorePick_Click(object sender, EventArgs e) @@ -1284,6 +1295,7 @@ namespace BizHawk.Client.EmuHawk private void GBCorePick_Click(object sender, EventArgs e) { Config.GbUseGbHawk ^= true; + Config.UseSubGBHawk = false; // TODO: only flag if one of these cores if (!Emulator.IsNull()) { diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index 39d03f2acf..18d75f5e71 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -317,7 +317,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk _vidbuffer[i] = (int)color_palette[0]; } } - + for (int j = 0; j < frame_buffer.Length; j++) { frame_buffer[j] = _vidbuffer[j]; } ppu.blank_frame = false; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs index 33ad85a7f7..377fb60fad 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs @@ -341,7 +341,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk case 0x1E: mapper = new MapperMBC5(); mppr = "MBC5"; has_bat = true; break; case 0x20: mapper = new MapperMBC6(); mppr = "MBC6"; break; case 0x22: mapper = new MapperMBC7(); mppr = "MBC7"; has_bat = true; break; - case 0xFC: mapper = new MapperCamera(); mppr = "CAM"; break; + case 0xFC: mapper = new MapperCamera(); mppr = "CAM"; has_bat = true; break; case 0xFD: mapper = new MapperTAMA5(); mppr = "TAMA5"; has_bat = true; break; case 0xFE: mapper = new MapperHuC3(); mppr = "HuC3"; break; case 0xFF: mapper = new MapperHuC1(); mppr = "HuC1"; break; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Camera.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Camera.cs index 7adde78772..11140cadc0 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Camera.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Camera.cs @@ -1,5 +1,6 @@ using BizHawk.Common; using BizHawk.Emulation.Cores.Components.LR35902; +using System; namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { @@ -22,10 +23,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk RAM_enable = false; ROM_mask = Core._rom.Length / 0x4000 - 1; - RAM_mask = 0; - RAM_mask = Core.cart_RAM.Length / 0x2000 - 1; - if (Core.cart_RAM.Length == 0x800) { RAM_mask = 0; } regs_enable = false; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs new file mode 100644 index 0000000000..b7f5547879 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs @@ -0,0 +1,143 @@ +using System; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk +{ + public partial class SubGBHawk : IEmulator + { + public IEmulatorServiceProvider ServiceProvider { get; } + + public ControllerDefinition ControllerDefinition => _GBCore.ControllerDefinition; + + public bool FrameAdvance(IController controller, bool render, bool renderSound) + { + //Console.WriteLine("-----------------------FRAME-----------------------"); + //Update the color palette if a setting changed + if (GetSettings().Palette == GBHawk.GBHawk.GBSettings.PaletteType.BW) + { + _GBCore.color_palette[0] = GBHawk.GBHawk.color_palette_BW[0]; + _GBCore.color_palette[1] = GBHawk.GBHawk.color_palette_BW[1]; + _GBCore.color_palette[2] = GBHawk.GBHawk.color_palette_BW[2]; + _GBCore.color_palette[3] = GBHawk.GBHawk.color_palette_BW[3]; + } + else + { + _GBCore.color_palette[0] = GBHawk.GBHawk.color_palette_Gr[0]; + _GBCore.color_palette[1] = GBHawk.GBHawk.color_palette_Gr[1]; + _GBCore.color_palette[2] = GBHawk.GBHawk.color_palette_Gr[2]; + _GBCore.color_palette[3] = GBHawk.GBHawk.color_palette_Gr[3]; + } + if (_tracer.Enabled) + { + _GBCore.cpu.TraceCallback = s => _tracer.Put(s); + } + else + { + _GBCore.cpu.TraceCallback = null; + } + + _frame++; + + reset_frame = false; + if (controller.IsPressed("P1 Power")) + { + reset_frame = true; + } + + input_frame_length = controller.GetFloat("Input Cycle"); + input_frame_length_int = (int)Math.Floor(input_frame_length); + + if (input_frame_length_int == 0) + { + input_frame_length_int = 70224; + } + + pass_a_frame = false; + + InputCallbacks.Call(); + + DoFrame(controller); + + bool ret = pass_a_frame; + + if (pass_a_frame) { frame_cycle = 0; } + current_cycle = 0; + + _isLag = pass_a_frame; + + if (_isLag) + { + _lagCount++; + VBL_CNT++; + } + + reset_frame = false; + return ret; + } + + private bool stop_cur_frame; + private bool pass_new_input; + private bool pass_a_frame; + private bool reset_frame; + private int current_cycle; + private int frame_cycle; + private float input_frame_length; + private int input_frame_length_int; + + private void DoFrame(IController controller) + { + stop_cur_frame = false; + _GBCore.GetControllerState(controller); + _GBCore.do_controller_check(); + while (!stop_cur_frame) + { + _GBCore.do_single_step(); + + if (reset_frame) + { + HardReset(); + reset_frame = false; + stop_cur_frame |= true; + pass_a_frame |= true; + } + + current_cycle++; + frame_cycle++; + + if (frame_cycle == 70224) + { + stop_cur_frame |= true; + pass_a_frame |= true; + } + + if (current_cycle == input_frame_length_int) + { + stop_cur_frame |= true; + } + + if (_GBCore.vblank_rise) + { + _GBCore.SendVideoBuffer(); + _GBCore.vblank_rise = false; + } + } + } + + public int Frame => _frame; + + public string SystemId => "GB"; + + public bool DeterministicEmulation => _GBCore.DeterministicEmulation; + + public void ResetCounters() + { + _frame = 0; + _lagCount = 0; + _isLag = false; + } + + public CoreComm CoreComm => _GBCore.CoreComm; + + public void Dispose() => _GBCore.Dispose(); + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IInputPollable.cs new file mode 100644 index 0000000000..12a664b65d --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IInputPollable.cs @@ -0,0 +1,24 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk +{ + public partial class SubGBHawk : IInputPollable + { + public int LagCount + { + get => _lagCount; + set => _lagCount = value; + } + + public bool IsLagFrame + { + get => _isLag; + set => _isLag = value; + } + + public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem(); + + public bool _isLag = true; + private int _lagCount; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs new file mode 100644 index 0000000000..560eb0e50c --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IStatable.cs @@ -0,0 +1,50 @@ +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk +{ + public partial class SubGBHawk : IStatable + { + private readonly IStatable _GBStatable; + + public void SaveStateBinary(BinaryWriter bw) + { + _GBStatable.SaveStateBinary(bw); + // other variables + SyncState(new Serializer(bw)); + } + + public void LoadStateBinary(BinaryReader br) + { + _GBStatable.LoadStateBinary(br); + // other variables + SyncState(new Serializer(br)); + } + + public byte[] SaveStateBinary() + { + using var ms = new MemoryStream(); + using var bw = new BinaryWriter(ms); + SaveStateBinary(bw); + bw.Flush(); + return ms.ToArray(); + } + + private void SyncState(Serializer ser) + { + ser.Sync("Lag", ref _lagCount); + ser.Sync("Frame", ref _frame); + ser.Sync("IsLag", ref _isLag); + ser.Sync(nameof(pass_a_frame), ref pass_a_frame); + ser.Sync(nameof(reset_frame), ref reset_frame); + ser.Sync(nameof(pass_new_input), ref pass_new_input); + ser.Sync(nameof(current_cycle), ref current_cycle); + ser.Sync(nameof(frame_cycle), ref frame_cycle); + ser.Sync(nameof(input_frame_length), ref input_frame_length); + ser.Sync(nameof(input_frame_length_int), ref input_frame_length_int); + ser.Sync(nameof(VBL_CNT), ref VBL_CNT); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs new file mode 100644 index 0000000000..65744e8f7f --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs @@ -0,0 +1,66 @@ +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Nintendo.GBHawk; + +namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk +{ + [Core( + "SubGBHawk", + "", + isPorted: false, + isReleased: true)] + [ServiceNotApplicable(new [] { typeof(IDriveLight) })] + public partial class SubGBHawk : IEmulator, IStatable, IInputPollable, + ISettable + { + [CoreConstructor(new[] { "GB", "GBC" })] + public SubGBHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings) + { + + var subGBSettings = (GBHawk.GBHawk.GBSettings)settings ?? new GBHawk.GBHawk.GBSettings(); + var subGBSyncSettings = (GBHawk.GBHawk.GBSyncSettings)syncSettings ?? new GBHawk.GBHawk.GBSyncSettings(); + + _GBCore = new GBHawk.GBHawk(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider }, + game, rom, subGBSettings, subGBSyncSettings); + + HardReset(); + current_cycle = 0; + VBL_CNT = 0; + + _GBStatable = _GBCore.ServiceProvider.GetService(); + + var ser = new BasicServiceProvider(this); + ServiceProvider = ser; + + ser.Register(_GBCore.ServiceProvider.GetService()); + ser.Register(_GBCore.ServiceProvider.GetService()); + ser.Register(_GBCore.ServiceProvider.GetService()); + ser.Register(_GBCore.ServiceProvider.GetService()); + ser.Register(_GBCore.ServiceProvider.GetService()); + ser.Register(_GBCore.ServiceProvider.GetService()); + ser.Register(_GBCore.ServiceProvider.GetService()); + ser.Register(_GBCore.ServiceProvider.GetService()); + + _tracer = new TraceBuffer { Header = _GBCore.cpu.TraceHeader }; + ser.Register(_tracer); + + _GBCore.ControllerDefinition.FloatControls.Add("Input Cycle"); + _GBCore.ControllerDefinition.FloatRanges.Add(new ControllerDefinition.FloatRange(0, 70224, 70224)); + } + + public GBHawk.GBHawk _GBCore; + + // needed for movies to accurately calculate timing + public int VBL_CNT; + + public void HardReset() => _GBCore.HardReset(); + + private int _frame; + + private readonly ITraceable _tracer; + + public GBHawk.GBHawk.GBSettings GetSettings() => _GBCore.GetSettings(); + public GBHawk.GBHawk.GBSyncSettings GetSyncSettings() => _GBCore.GetSyncSettings(); + public bool PutSettings(GBHawk.GBHawk.GBSettings o) => _GBCore.PutSettings(o); + public bool PutSyncSettings(GBHawk.GBHawk.GBSyncSettings o) => _GBCore.PutSyncSettings(o); + } +}