From d4f5ed2f50bb326aeba49d431788a5f4a9ec0877 Mon Sep 17 00:00:00 2001 From: goyuken Date: Mon, 1 Oct 2012 14:39:52 +0000 Subject: [PATCH] Movie playback and recording will now set IEmulator.DeterministicEmulation = true; only snes core actually does anything with this. It hasn't been explained before in a log; so I'll do it now: When in deterministic mode, the snes core internally does exactly one savestate each and every frame. Then, if the frontend calls savestate at all, it always gets the same internal cached savestate. If the frontend doesn't call savestate, then the internal savestate is simply discarded. This way, the exact same number of RunToSave() calls occur every time. --- BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs | 9 ++++++--- BizHawk.MultiClient/MainForm.Movie.cs | 4 ++-- BizHawk.MultiClient/MainForm.cs | 6 +++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs index 5d87343448..1e020944f7 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -637,7 +637,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES get { return _DeterministicEmulation; } set { - if (_DeterministicEmulationProtected) + if (_DeterministicEmulationProtected && value != _DeterministicEmulation) throw new Exception("snes: DeterministicEmulation must be set before load!"); _DeterministicEmulation = value; } @@ -762,19 +762,22 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES /// internal function handling savestate /// this can cause determinism problems if called improperly! /// - byte[] CoreSaveStateInternal(bool store) + byte[] CoreSaveStateInternal(bool cache) { int size = LibsnesDll.snes_serialize_size(); byte[] buf = new byte[size]; fixed (byte* pbuf = &buf[0]) LibsnesDll.snes_serialize(new IntPtr(pbuf), size); - if (store) + if (cache) { savestatebuff = buf; return null; } else + { + savestatebuff = null; return buf; + } } // Arbitrary extensible core comm mechanism diff --git a/BizHawk.MultiClient/MainForm.Movie.cs b/BizHawk.MultiClient/MainForm.Movie.cs index a0dc81f0eb..d0adf52dc4 100644 --- a/BizHawk.MultiClient/MainForm.Movie.cs +++ b/BizHawk.MultiClient/MainForm.Movie.cs @@ -24,7 +24,7 @@ namespace BizHawk.MultiClient Global.MovieSession.Movie = m; RewireInputChain(); - LoadRom(Global.MainForm.CurrentlyOpenRom); + LoadRom(Global.MainForm.CurrentlyOpenRom, true); if (!record) { Global.MovieSession.Movie.LoadMovie(); @@ -90,7 +90,7 @@ namespace BizHawk.MultiClient { if (Global.MovieSession.Movie.IsActive) { - LoadRom(CurrentlyOpenRom); + LoadRom(CurrentlyOpenRom, true); if (Global.MovieSession.Movie.StartsFromSavestate) { LoadStateFile(Global.MovieSession.Movie.Filename, Path.GetFileName(Global.MovieSession.Movie.Filename)); diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index ad3221d84a..8d7d16e086 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -1274,7 +1274,7 @@ namespace BizHawk.MultiClient Global.MovieOutputHardpoint.Source = Global.MovieInputSourceAdapter; } - public bool LoadRom(string path) + public bool LoadRom(string path, bool deterministicemulation = false) { if (path == null) return false; using (var file = new HawkFile()) @@ -1401,6 +1401,7 @@ namespace BizHawk.MultiClient { game.System = "SNES"; var snes = new LibsnesCore(); + if (deterministicemulation) snes.DeterministicEmulation = true; nextEmulator = snes; nextEmulator.CoreInputComm = Global.CoreInputComm; snes.Load(game, rom.FileData, null); @@ -1491,6 +1492,7 @@ namespace BizHawk.MultiClient game.AddOption("SGB"); game.System = "SGB"; var snes = new LibsnesCore(); + if (deterministicemulation) snes.DeterministicEmulation = true; nextEmulator = snes; snes.Load(game, rom.FileData, sgbrom); } @@ -1528,6 +1530,8 @@ namespace BizHawk.MultiClient if (nextEmulator == null) throw new Exception(); + if (deterministicemulation) nextEmulator.DeterministicEmulation = true; + CloseGame(); Global.Emulator.Dispose(); Global.Emulator = nextEmulator;