diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index 290b2429bf..21c72d1312 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -25,6 +25,7 @@ using BizHawk.Client.EmuHawk.ToolExtensions; using BizHawk.Emulation.Cores.Computers.AppleII; using BizHawk.Client.ApiHawk; using BizHawk.Emulation.Cores.Computers.Commodore64; +using BizHawk.Emulation.Cores.Nintendo.Gameboy; namespace BizHawk.Client.EmuHawk { @@ -2002,7 +2003,14 @@ namespace BizHawk.Client.EmuHawk private void GBCoreSettingsMenuItem_Click(object sender, EventArgs e) { - GBPrefs.DoGBPrefsDialog(this); + if (Global.Emulator is Gameboy) + { + GBPrefs.DoGBPrefsDialog(this); + } + else // sameboy + { + GenericCoreConfig.DoDialog(this, "Gameboy Settings"); + } } private void LoadGbInSgbMenuItem_Click(object sender, EventArgs e) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs index 928ab1bd62..1b7231b02d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs @@ -4,6 +4,7 @@ using BizHawk.Emulation.Cores.Properties; using BizHawk.Emulation.Cores.Waterbox; using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Linq; using System.Text; @@ -13,7 +14,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy { [Core("SameBoy", "LIJI32", true, false, "efc11783c7fb6da66e1dd084e41ba6a85c0bd17e", "https://sameboy.github.io/", false)] - public class Sameboy : WaterboxCore, IGameboyCommon, ISaveRam + public class Sameboy : WaterboxCore, + IGameboyCommon, ISaveRam, + ISettable { /// /// the nominal length of one frame @@ -35,16 +38,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy private bool _sgb; [CoreConstructor("SGB")] - public Sameboy(byte[] rom, CoreComm comm) - : this(rom, comm, true) + public Sameboy(byte[] rom, CoreComm comm, SyncSettings syncSettings, bool deterministic) + : this(rom, comm, true, syncSettings, deterministic) { } [CoreConstructor("GB")] - public Sameboy(CoreComm comm, byte[] rom) - : this(rom, comm, false) + public Sameboy(CoreComm comm, byte[] rom, SyncSettings syncSettings, bool deterministic) + : this(rom, comm, false, syncSettings, deterministic) { } - public Sameboy(byte[] rom, CoreComm comm, bool sgb) + public Sameboy(byte[] rom, CoreComm comm, bool sgb, SyncSettings syncSettings, bool deterministic) : base(comm, new Configuration { DefaultWidth = sgb ? 256 : 160, @@ -70,8 +73,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy _cgb = (rom[0x143] & 0xc0) == 0xc0 && !sgb; _sgb = sgb; Console.WriteLine("Automaticly detected CGB to " + _cgb); - var bios = Util.DecompressGzipFile(new MemoryStream(_cgb ? Resources.SameboyCgbBoot : Resources.SameboyDmgBoot)); - // var bios = comm.CoreFileProvider.GetFirmware(_cgb ? "GBC" : "GB", "World", true); + _syncSettings = syncSettings ?? new SyncSettings(); + + var bios = _syncSettings.UseRealBIOS && !sgb + ? comm.CoreFileProvider.GetFirmware(_cgb ? "GBC" : "GB", "World", true) + : Util.DecompressGzipFile(new MemoryStream(_cgb ? Resources.SameboyCgbBoot : Resources.SameboyDmgBoot)); + var spc = sgb ? Util.DecompressGzipFile(new MemoryStream(Resources.SgbCartPresent_SPC)) : null; @@ -92,6 +99,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy var scratch = new IntPtr[4]; _core.GetGpuMemory(scratch); _gpuMemory = new GPUMemoryAreas(scratch[0], scratch[1], scratch[3], scratch[2], _exe); + + DeterministicEmulation = deterministic || !_syncSettings.UseRealTime; + InitializeRtc(_syncSettings.InitialTime); } #region Controller @@ -167,11 +177,71 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy #endregion + #region ISettable + + private SyncSettings _syncSettings; + + public class SyncSettings + { + [DisplayName("Initial Time")] + [Description("Initial time of emulation. Only relevant when UseRealTime is false.")] + [DefaultValue(typeof(DateTime), "2010-01-01")] + public DateTime InitialTime { get; set; } + + [DisplayName("Use RealTime")] + [Description("If true, RTC clock will be based off of real time instead of emulated time. Ignored (set to false) when recording a movie.")] + [DefaultValue(false)] + public bool UseRealTime { get; set; } + + [Description("If true, real BIOS files will be used. Ignored in SGB mode.")] + [DefaultValue(false)] + public bool UseRealBIOS { get; set; } + + public SyncSettings Clone() + { + return (SyncSettings)MemberwiseClone(); + } + + public static bool NeedsReboot(SyncSettings x, SyncSettings y) + { + return !DeepEquality.DeepEquals(x, y); + } + + public SyncSettings() + { + SettingsUtil.SetDefaultValues(this); + } + } + + public object GetSettings() + { + return null; + } + + public SyncSettings GetSyncSettings() + { + return _syncSettings.Clone(); + } + + public bool PutSettings(object o) + { + return false; + } + + public bool PutSyncSettings(SyncSettings o) + { + var ret = SyncSettings.NeedsReboot(_syncSettings, o); + _syncSettings = o; + return ret; + } + + #endregion + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) { return new LibSameboy.FrameInfo { - Time = 0, + Time = GetRtcTime(!DeterministicEmulation), Keys = GetButtons(controller) }; } diff --git a/waterbox/sameboy/bizhawk.cpp b/waterbox/sameboy/bizhawk.cpp index f37c60a0eb..28c6cda11e 100644 --- a/waterbox/sameboy/bizhawk.cpp +++ b/waterbox/sameboy/bizhawk.cpp @@ -154,6 +154,7 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo &f) sound_start_clock = GB_epoch(&GB); CurrentFramebuffer = f.VideoBuffer; GB_set_lagged(&GB, true); + GB.frontend_rtc_time = f.Time; uint32_t target = 35112 - FrameOverflow; f.Cycles = GB_run_cycles(&GB, target); diff --git a/waterbox/sameboy/gb.h b/waterbox/sameboy/gb.h index 91d29effe4..098a3d2ea3 100644 --- a/waterbox/sameboy/gb.h +++ b/waterbox/sameboy/gb.h @@ -434,6 +434,8 @@ struct GB_gameboy_internal_s { uint32_t ram_size; // Different between CGB and DMG uint8_t boot_rom[0x900]; bool vblank_just_occured; // For slow operations involving syscalls; these should only run once per vblank + + int64_t frontend_rtc_time; }; #ifndef GB_INTERNAL diff --git a/waterbox/sameboy/timing.c b/waterbox/sameboy/timing.c index e67992c167..bb2501b31a 100644 --- a/waterbox/sameboy/timing.c +++ b/waterbox/sameboy/timing.c @@ -133,7 +133,7 @@ void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac) void GB_rtc_run(GB_gameboy_t *gb) { if ((gb->rtc_real.high & 0x40) == 0) { /* is timer running? */ - time_t current_time = time(NULL); + time_t current_time = gb->frontend_rtc_time; while (gb->last_rtc_second < current_time) { gb->last_rtc_second++; if (++gb->rtc_real.seconds == 60)