Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions Assets/Lua/GBA/SonicAdvance_CamHack.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,26 @@ local addr_offY = 0x5B98
local addr_camX = 0x59D0
local addr_camY = 0x59D2

while true do
client.invisibleemulation(true)
local memorystate = memorysavestate.savecorestate()
local id = client.show_future(function(f)
if f == 0 then
offX = mainmemory.read_u16_le(addr_offX)
offY = mainmemory.read_u16_le(addr_offY)
camX = mainmemory.read_u16_le(addr_camX)
camY = mainmemory.read_u16_le(addr_camY)

Xval = camX + offX - 128
Yval = camY + offY - 80

mainmemory.write_u16_le(addr_camX, Xval)
mainmemory.write_u16_le(addr_camY, Yval)
elseif f == 2 then
return true
end

offX = mainmemory.read_u16_le(addr_offX)
offY = mainmemory.read_u16_le(addr_offY)
camX = mainmemory.read_u16_le(addr_camX)
camY = mainmemory.read_u16_le(addr_camY)

Xval = camX + offX - 128
Yval = camY + offY - 80

mainmemory.write_u16_le(addr_camX, Xval)
mainmemory.write_u16_le(addr_camY, Yval)

client.seekframe(emu.framecount()+1)
client.invisibleemulation(false)
client.seekframe(emu.framecount()+1)
client.invisibleemulation(true)
memorysavestate.loadcorestate(memorystate)
memorysavestate.removestate(memorystate)
-- client.invisibleemulation(false)
return false
end, 2)
event.onexit(function() event.unregisterbyid(id) end)

while true do
emu.frameadvance()
end
end
21 changes: 12 additions & 9 deletions src/BizHawk.Client.Common/Api/Classes/EmuClientApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,6 @@ public void FrameSkip(int numFrames)
public int GetWindowSize()
=> _config.GetWindowScaleFor(Emulator.SystemId);

public void InvisibleEmulation(bool invisible) => _mainForm.InvisibleEmulation = invisible;

public bool IsPaused() => _mainForm.EmulatorPaused;

public bool IsSeeking() => _mainForm.IsSeeking;
Expand Down Expand Up @@ -186,13 +184,6 @@ public void Screenshot(string path)

public int ScreenWidth() => _displayManager.GetPanelNativeSize().Width;

public void SeekFrame(int frame)
{
var wasPaused = _mainForm.EmulatorPaused;
while (Emulator.Frame != frame) _mainForm.SeekFrameAdvance();
if (!wasPaused) _mainForm.UnpauseEmulator();
}

public void SetClientExtraPadding(int left, int top, int right, int bottom)
{
_displayManager.ClientExtraPadding = (left, top, right, bottom);
Expand Down Expand Up @@ -228,6 +219,18 @@ public void SetWindowSize(int size)
}
}

public void ShowFuture(ShowFutureCallback/*?*/ preFrameCallback, short maxFrames)
{
if (maxFrames < 1 && preFrameCallback != null)
{
_logCallback($"Invalid number of future frames ({maxFrames}); number must be positive.");
return;
}

_mainForm.PreFutureFrameCallback = preFrameCallback;
_mainForm.MaxFutureFrames = maxFrames;
}

public void SpeedMode(int percent)
{
if (percent is > 0 and <= 6400) _mainForm.ClickSpeedItem(percent);
Expand Down
23 changes: 11 additions & 12 deletions src/BizHawk.Client.Common/Api/Interfaces/IEmuClientApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@ public interface IEmuClientApi : IDisposable, IExternalApi

int GetWindowSize();

/// <summary>
/// Use with <see cref="SeekFrame(int)"/> for CamHack.
/// Refer to <c>MainForm.InvisibleEmulation</c> for the workflow details.
/// </summary>
void InvisibleEmulation(bool invisible);
Comment thread
vadosnaprimer marked this conversation as resolved.

bool IsPaused();

bool IsSeeking();
Expand Down Expand Up @@ -116,12 +110,6 @@ public interface IEmuClientApi : IDisposable, IExternalApi

int ScreenWidth();

/// <summary>
/// Use with <see cref="InvisibleEmulation(bool)"/> for CamHack.
/// Refer to <c>MainForm.InvisibleEmulation</c> for the workflow details.
/// </summary>
void SeekFrame(int frame);

/// <summary>
/// Sets the extra padding added to the 'native' surface so that you can draw HUD elements in predictable placements
/// </summary>
Expand All @@ -148,6 +136,17 @@ public interface IEmuClientApi : IDisposable, IExternalApi

void SetWindowSize(int size);

/// <summary>
/// Tell the client to display a frame from the future, instead of the current frame.
/// </summary>
/// <param name="preFrameCallback">This will be called before emulating each future frame.
/// The parameter is the number of frames into the future that have already been emulated.
/// Return false to emulate another future frame.
/// When the callback returns true, emulation will rewind to the real current frame and the just-run future frame will be displayed.
/// <br/>Pass null to disable future frame display.</param>
/// <param name="maxFrames">The maximum number of future frames to emulate. Useful to avoid freezing the client UI in case of accidentally never returning true from the callback.</param>
void ShowFuture(ShowFutureCallback/*?*/ preFrameCallback, short maxFrames);

void SpeedMode(int percent);

void TogglePause();
Expand Down
7 changes: 7 additions & 0 deletions src/BizHawk.Client.Common/EventTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,11 @@ public StateSavedEventArgs(string stateName)
/// <param name="sender">Object that raised the event</param>
/// <param name="e">Event arguments</param>
public delegate void StateSavedEventHandler(object sender, StateSavedEventArgs e);

/// <summary>
/// Represent a method that will control future emulation.
/// </summary>
/// <param name="futureFramesEmulated">The number of frames into the future that have been emulated. This is a short purely to help avoid accidentally passing in absurdly large numbers.</param>
/// <returns>True to display the current frame, false to continue emulating into the future.</returns>
public delegate bool ShowFutureCallback(short futureFramesEmulated);
}
12 changes: 6 additions & 6 deletions src/BizHawk.Client.Common/IMainFormForApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ public interface IMainFormForApi
/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
bool EmulatorPaused { get; }

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
bool InvisibleEmulation { get; set; }

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
bool IsSeeking { get; }

Expand All @@ -28,12 +25,18 @@ public interface IMainFormForApi
/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
bool IsRewinding { get; }

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
public int MaxFutureFrames { get; set; }

/// <remarks>only referenced from <see cref="CommApi"/></remarks>
(HttpCommunication HTTP, MemoryMappedFiles MMF, SocketServer Sockets) NetworkingHelpers { get; }

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
bool PauseAvi { get; set; }

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
public ShowFutureCallback/*?*/ PreFutureFrameCallback { get; set; }

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
void ClearHolds();

Expand Down Expand Up @@ -109,9 +112,6 @@ public interface IMainFormForApi
/// <remarks>referenced from <see cref="EmuClientApi"/> and <see cref="SaveStateApi"/></remarks>
FileWriteResult SaveState(string path, string userFriendlyStateName, bool suppressOSD = false);

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
void SeekFrameAdvance();

/// <remarks>only referenced from <see cref="EmuClientApi"/></remarks>
void StepRunLoop_Throttle();

Expand Down
3 changes: 0 additions & 3 deletions src/BizHawk.Client.Common/IMainFormForTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ public interface IMainFormForTools : IDialogController
/// <remarks>only referenced from PlaybackBox</remarks>
bool HoldFrameAdvance { get; set; }

/// <remarks>only referenced from BasicBot</remarks>
bool InvisibleEmulation { get; set; }

/// <remarks>only referenced from LuaConsole</remarks>
bool IsTurboing { get; }

Expand Down
42 changes: 29 additions & 13 deletions src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
namespace BizHawk.Client.Common
{
[Description("A library for manipulating the EmuHawk client UI")]
public sealed class ClientLuaLibrary : LuaLibraryBase
public sealed class ClientLuaLibrary : LuaLibraryBase, IRegisterFunctions
{
public Lazy<string> AllAPINames { get; set; }

public NLFAddCallback CreateAndRegisterNamedFunction { get; set; }

[OptionalService]
private IVideoProvider VideoProvider { get; set; }

Expand Down Expand Up @@ -96,18 +98,6 @@ public void FrameSkip(int numFrames)
public string GetLuaEngine()
=> "NLua+Lua";

[LuaMethodExample("client.invisibleemulation( true );")]
[LuaMethod("invisibleemulation", "Enters/exits turbo mode and disables/enables most emulator updates.")]
public void InvisibleEmulation(bool invisible)
Comment thread
vadosnaprimer marked this conversation as resolved.
=> APIs.EmuClient.InvisibleEmulation(invisible);

[LuaDeprecatedMethod]
[LuaMethod("seekframe", "Does nothing. Use the pause/unpause functions instead and a loop that waits for the desired frame.")]
public void SeekFrame(int frame)
{
Log("Deprecated function client.seekframe() used. Replace the call with pause/unpause functions and a loop that waits for the desired frame.");
}

[LuaMethodExample("local sounds_terrible = client.get_approx_framerate() < 55;")]
[LuaMethod("get_approx_framerate", "Gets the (host) framerate, approximated from frame durations.")]
public int GetApproxFramerate()
Expand Down Expand Up @@ -285,6 +275,32 @@ public int ScreenWidth()
public void SetWindowSize(int size)
=> APIs.EmuClient.SetWindowSize(size);

[LuaMethodExample("client.show_future(function(frame) return frame == 1 end, 1)")]
[LuaMethod(
name: "show_future",
description: "Tell the client to display a frame from the future, instead of the current frame. " +
"The given lua function will be called before emulating each future frame. " +
"It can have 1 parameter, which is the number of frames into the future that have already been emulated. " +
"Return false to emulate another future frame. " +
"When the callback returns true, emulation will rewind to the real current frame and the just-run future frame will be displayed. " +
"Unregister the callback with event.unregister____ to disable future frame display. " +
"No more than `maxFrames` future frames will be emulated. Useful to avoid freezing " +
"the client UI in case of accidentally never returning true from the callback.")]
public string ShowFuture(LuaFunction luaf, long maxFrames, string name = null)
{
if (maxFrames < 1 || maxFrames > short.MaxValue)
{
Log($"Invalid number of future frames ({maxFrames}); number must be positive and less than 2^15.");
return "";
}

INamedLuaFunction nlf = CreateAndRegisterNamedFunction(luaf, NamedLuaFunction.EVENT_TYPE_FUTURE, prohibitedApis: ApiGroup.PROHIBITED_MID_FRAME, name: name);
ShowFutureCallback FutureCallback = (f) => nlf.Call(f) is [ bool r ] ? r : false;
APIs.EmuClient.ShowFuture(FutureCallback, (short)maxFrames);
nlf.OnRemove += () => APIs.EmuClient.ShowFuture(null, 0);
return nlf.GuidStr;
}

[LuaMethodExample("client.speedmode( 75 );")]
[LuaMethod("speedmode", "Sets the speed of the emulator (in terms of percent)")]
public void SpeedMode(int percent)
Expand Down
2 changes: 2 additions & 0 deletions src/BizHawk.Client.Common/lua/NamedLuaFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public sealed class NamedLuaFunction : INamedLuaFunction

public const string EVENT_TYPE_SAVESTATE = "OnSavestateSave";

public const string EVENT_TYPE_FUTURE = "BeforeFutureFrame";

private readonly LuaFunction _function;

private readonly ILuaLibraries _luaImp;
Expand Down
Loading