Skip to content

Commit 0c268f2

Browse files
committed
Do not copy state framebuffers into the core. Aside from modifying data belonging to the core, this ignores the other way that cores can provide video output, OpenGL. Instead, create a video provider for the state and use that.
1 parent a3acc76 commit 0c268f2

File tree

5 files changed

+63
-43
lines changed

5 files changed

+63
-43
lines changed

src/BizHawk.Client.Common/savestates/SavestateFile.cs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Collections.Generic;
22
using System.Diagnostics;
3-
using System.IO;
43

54
using BizHawk.Bizware.Graphics;
65
using BizHawk.Common;
@@ -25,6 +24,7 @@ public class SavestateFile
2524
private readonly IEmulator _emulator;
2625
private readonly IStatable _statable;
2726
private readonly IVideoProvider _videoProvider;
27+
public IVideoProvider LoadedVideoProvider = null;
2828
private readonly IMovieSession _movieSession;
2929

3030
private readonly SettingsAdapter _settable;
@@ -215,10 +215,8 @@ loadedSyncSettings is null
215215
}
216216
}
217217

218-
if (_videoProvider != null)
219-
{
220-
bl.GetLump(BinaryStateLump.Framebuffer, false, br => PopulateFramebuffer(br, _videoProvider));
221-
}
218+
219+
bl.GetLump(BinaryStateLump.Framebuffer, false, br => QuickBmpFile.LoadAuto(br.BaseStream, out LoadedVideoProvider));
222220

223221
string userData = "";
224222
bl.GetLump(BinaryStateLump.UserData, abort: false, tr =>
@@ -247,13 +245,5 @@ loadedSyncSettings is null
247245

248246
return true;
249247
}
250-
251-
private static void PopulateFramebuffer(BinaryReader br, IVideoProvider videoProvider)
252-
{
253-
using (new SimpleTime("Load Framebuffer"))
254-
{
255-
QuickBmpFile.Load(videoProvider, br.BaseStream);
256-
}
257-
}
258248
}
259249
}

src/BizHawk.Client.EmuHawk/IMainFormForTools.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.IO;
2+
13
using BizHawk.Bizware.Graphics;
24
using BizHawk.Client.Common;
35
using BizHawk.Emulation.Common;
@@ -64,6 +66,8 @@ public interface IMainFormForTools : IDialogController
6466
/// <remarks>only referenced from <see cref="BasicBot"/></remarks>
6567
bool LoadQuickSave(int slot, bool suppressOSD = false);
6668

69+
void LoadState(BinaryReader coreData, IVideoProvider stateScreenshotProvider, string userFriendlyStateName);
70+
6771
/// <remarks>only referenced from <see cref="MultiDiskBundler"/></remarks>
6872
bool LoadRom(string path, LoadRomArgs args);
6973

src/BizHawk.Client.EmuHawk/MainForm.cs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ public IEmulator Emulator
11631163
private set
11641164
{
11651165
_emulator = value;
1166-
_currentVideoProvider = value.AsVideoProviderOrDefault();
1166+
_currentVideoProvider = _coreVideoProvider = value.AsVideoProviderOrDefault();
11671167
_currentSoundProvider = value.AsSoundProviderOrDefault();
11681168
}
11691169
}
@@ -1180,6 +1180,7 @@ private set
11801180

11811181
private readonly InputManager InputManager;
11821182

1183+
private IVideoProvider _coreVideoProvider = NullVideo.Instance;
11831184
private IVideoProvider _currentVideoProvider = NullVideo.Instance;
11841185

11851186
private ISoundProvider _currentSoundProvider = new NullSound(44100 / 60); // Reasonable default until we have a core instance
@@ -3002,6 +3003,9 @@ private void StepRunLoop_Core(bool force = false)
30023003
// BlockFrameAdvance (true when input it being editted in TAStudio) supercedes all other frame advance conditions
30033004
if ((runFrame || force) && !BlockFrameAdvance)
30043005
{
3006+
// Reset the video provider. (It may have changed due to loading a save state.)
3007+
_currentVideoProvider = _coreVideoProvider;
3008+
30053009
var isFastForwarding = IsFastForwarding;
30063010
var isFastForwardingOrRewinding = isFastForwarding || isRewinding || Config.Unthrottled;
30073011

@@ -4102,24 +4106,64 @@ public void DisableRewind()
41024106
return File.Exists(path) ? SavestateFile.GetFrameBufferFrom(path) : null;
41034107
}
41044108

4109+
public void LoadState(BinaryReader coreData, IVideoProvider stateScreenshotProvider, string userFriendlyStateName)
4110+
{
4111+
IStatable emulator = Emulator.ServiceProvider.GetService<IStatable>();
4112+
if (emulator == null) return;
4113+
4114+
emulator.LoadStateBinary(coreData);
4115+
if (stateScreenshotProvider != null)
4116+
{
4117+
_currentVideoProvider = stateScreenshotProvider;
4118+
}
4119+
else
4120+
{
4121+
DisplayManager.DiscardApiHawkSurfaces();
4122+
}
4123+
// Apparently, we don't reset the counters BEFORE capturing the movie start state. So...
4124+
if (Emulator.Frame == 0 && MovieSession.Movie.StartsFromSavestate)
4125+
{
4126+
Emulator.ResetCounters();
4127+
}
4128+
4129+
LoadStateCommon(userFriendlyStateName);
4130+
}
4131+
41054132
public bool LoadState(string path, string userFriendlyStateName, bool suppressOSD = false) // Move to client.common
41064133
{
41074134
if (!Emulator.HasSavestates()) return false;
41084135
if (ToolControllingSavestates is { } tool) return tool.LoadState();
41094136

4110-
if (!new SavestateFile(Emulator, MovieSession, MovieSession.UserBag).Load(path, this))
4137+
SavestateFile stateFile = new SavestateFile(Emulator, MovieSession, MovieSession.UserBag);
4138+
if (!stateFile.Load(path, this))
41114139
{
41124140
AddOnScreenMessage("Loadstate error!");
41134141
return false;
41144142
}
4143+
else
4144+
{
4145+
_currentVideoProvider = stateFile.LoadedVideoProvider;
4146+
}
41154147

4148+
RA?.OnLoadState(path);
4149+
LoadStateCommon(userFriendlyStateName);
4150+
4151+
if (!suppressOSD)
4152+
{
4153+
AddOnScreenMessage($"Loaded state: {userFriendlyStateName}");
4154+
}
4155+
4156+
return true;
4157+
}
4158+
4159+
private void LoadStateCommon(string userFriendlyStateName)
4160+
{
41164161
OSD.ClearGuiText();
41174162
if (SavestateLoaded is not null)
41184163
{
41194164
StateLoadedEventArgs args = new(userFriendlyStateName);
41204165
SavestateLoaded(this, args);
41214166
}
4122-
RA?.OnLoadState(path);
41234167

41244168
if (Tools.Has<LuaConsole>())
41254169
{
@@ -4138,12 +4182,6 @@ public bool LoadState(string path, string userFriendlyStateName, bool suppressOS
41384182
{
41394183
Rewinder?.Clear();
41404184
}
4141-
4142-
if (!suppressOSD)
4143-
{
4144-
AddOnScreenMessage($"Loaded state: {userFriendlyStateName}");
4145-
}
4146-
return true;
41474185
}
41484186

41494187
public bool LoadQuickSave(int slot, bool suppressOSD = false)

src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using BizHawk.Client.Common;
1+
using System.IO;
2+
3+
using BizHawk.Client.Common;
24

35
namespace BizHawk.Client.EmuHawk
46
{
@@ -26,7 +28,7 @@ public void GoToFrame(int frame, bool OnLeftMouseDown = false)
2628
var closestState = GetPriorStateForFramebuffer(frame);
2729
if (frame < Emulator.Frame || closestState.Key > Emulator.Frame)
2830
{
29-
LoadState(closestState, true);
31+
MainForm.LoadState(new BinaryReader(closestState.Value), null, $"frame {closestState.Key}");
3032
}
3133
closestState.Value.Dispose();
3234

src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -860,22 +860,6 @@ private KeyValuePair<int,Stream> GetPriorStateForFramebuffer(int frame)
860860
return CurrentTasMovie.TasStateManager.GetStateClosestToFrame(frame > 0 ? frame - 1 : 0);
861861
}
862862

863-
public void LoadState(KeyValuePair<int, Stream> state, bool discardApiHawkSurfaces = false)
864-
{
865-
StatableEmulator.LoadStateBinary(new BinaryReader(state.Value));
866-
867-
if (state.Key == 0 && CurrentTasMovie.StartsFromSavestate)
868-
{
869-
Emulator.ResetCounters();
870-
}
871-
872-
UpdateTools();
873-
if (discardApiHawkSurfaces)
874-
{
875-
DisplayManager.DiscardApiHawkSurfaces();
876-
}
877-
}
878-
879863
public void AddBranchExternal() => BookMarkControl.AddBranchExternal();
880864
public void RemoveBranchExternal() => BookMarkControl.RemoveBranchExternal();
881865

@@ -1146,10 +1130,12 @@ public void LoadBranch(TasBranch branch)
11461130
}
11471131

11481132
CurrentTasMovie.LoadBranch(branch);
1149-
LoadState(new(branch.Frame, new MemoryStream(branch.CoreData, false)));
1150-
1133+
MainForm.LoadState(
1134+
new BinaryReader(new MemoryStream(branch.CoreData)),
1135+
new BitmapBufferVideoProvider(branch.CoreFrameBuffer),
1136+
$"branch {branch.UserText}"
1137+
);
11511138
CurrentTasMovie.TasStateManager.Capture(Emulator.Frame, Emulator.AsStatable());
1152-
QuickBmpFile.Copy(new BitmapBufferVideoProvider(branch.CoreFrameBuffer), VideoProvider);
11531139

11541140
if (Settings.OldControlSchemeForBranches && TasPlaybackBox.RecordingMode)
11551141
{

0 commit comments

Comments
 (0)