diff --git a/src/BizHawk.Client.Common/savestates/SavestateFile.cs b/src/BizHawk.Client.Common/savestates/SavestateFile.cs index 36643397bf..d277d8d104 100644 --- a/src/BizHawk.Client.Common/savestates/SavestateFile.cs +++ b/src/BizHawk.Client.Common/savestates/SavestateFile.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using BizHawk.Bizware.BizwareGL; using BizHawk.Common; using BizHawk.Emulation.Common; @@ -13,6 +14,15 @@ namespace BizHawk.Client.Common /// public class SavestateFile { + public static BitmapBuffer/*?*/ GetFrameBufferFrom(string path) + { + using var bl = ZipStateLoader.LoadAndDetect(path); + if (bl is null) return null; + IVideoProvider/*?*/ vp = null; + bl.GetLump(BinaryStateLump.Framebuffer, abort: false, br => QuickBmpFile.LoadAuto(br.BaseStream, out vp)); + return vp is null ? null : new(width: vp.BufferWidth, height: vp.BufferHeight, vp.GetVideoBuffer()); + } + private readonly IEmulator _emulator; private readonly IStatable _statable; private readonly IVideoProvider _videoProvider; diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs index e2fd81db5d..af71ec51f9 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -2472,6 +2472,43 @@ namespace BizHawk.Client.EmuHawk } } + private readonly ScreenshotForm _screenshotTooltip = new(); + + private void SlotStatusButtons_MouseEnter(object/*?*/ sender, EventArgs e) + { + var slot = 10; + if (sender == Slot1StatusButton) slot = 1; + else if (sender == Slot2StatusButton) slot = 2; + else if (sender == Slot3StatusButton) slot = 3; + else if (sender == Slot4StatusButton) slot = 4; + else if (sender == Slot5StatusButton) slot = 5; + else if (sender == Slot6StatusButton) slot = 6; + else if (sender == Slot7StatusButton) slot = 7; + else if (sender == Slot8StatusButton) slot = 8; + else if (sender == Slot9StatusButton) slot = 9; + //TODO just put the slot number in Control.Tag already + if (!(HasSlot(slot) && ReadScreenshotFromSavestate(slot: slot) is {} bb)) + { + _screenshotTooltip.FadeOut(); + return; + } + var width = bb.Width; + var height = bb.Height; + var location = PointToScreen(MainStatusBar.Location); + location.Offset(((e as MouseEventArgs)?.X ?? 50) - width/2, -height); + _screenshotTooltip.UpdateValues( + bb, + captionText: string.Empty, + location, + width: width, + height: height, + Graphics.FromHwnd(Handle).MeasureString); + _screenshotTooltip.FadeIn(); + } + + private void SlotStatusButtons_MouseLeave(object/*?*/ sender, EventArgs e) + => _screenshotTooltip.FadeOut(); + private void SlotStatusButtons_MouseUp(object sender, MouseEventArgs e) { var slot = 10; diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index 87eae0f4a7..da46f59d2b 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -195,6 +195,18 @@ namespace BizHawk.Client.EmuHawk SetStatusBar(); _stateSlots.Update(Emulator, MovieSession.Movie, SaveStatePrefix()); + var quickslotButtons = new[] + { + Slot1StatusButton, Slot2StatusButton, Slot3StatusButton, Slot4StatusButton, Slot5StatusButton, + Slot6StatusButton, Slot7StatusButton, Slot8StatusButton, Slot9StatusButton, Slot0StatusButton, + }; + for (var i = 0; i < quickslotButtons.Length; i++) + { + ref var button = ref quickslotButtons[i]; + button.MouseEnter += SlotStatusButtons_MouseEnter; + button.MouseLeave += SlotStatusButtons_MouseLeave; + } + // New version notification UpdateChecker.CheckComplete += (s2, e2) => { @@ -4235,6 +4247,11 @@ namespace BizHawk.Client.EmuHawk return int.Parse(slot.Substring(slot.Length - 1, 1)); } + public BitmapBuffer/*?*/ ReadScreenshotFromSavestate(int slot) + => Emulator.HasSavestates() + ? SavestateFile.GetFrameBufferFrom($"{SaveStatePrefix()}.QuickSave{slot % 10}.State") + : null; + public bool LoadState(string path, string userFriendlyStateName, bool suppressOSD = false) // Move to client.common { if (!Emulator.HasSavestates()) return false;