fix passing numbers for string args in .net lua functions (old engine had this behavior, granted "bad user" if they relied on this), add appropriate test
fix passing sbyte/char as args, add appropriate tests cleanup the lua auto unlock hack, using a nice ref struct + dispose to handle it
This commit is contained in:
parent
920682688b
commit
eb00019c86
Binary file not shown.
Binary file not shown.
|
@ -151,11 +151,22 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ThisIsTheLuaAutounlockHack()
|
public readonly ref struct LuaAutoUnlockHack
|
||||||
{
|
{
|
||||||
UnlockSurface(DisplaySurfaceID.EmuCore);
|
private readonly GuiApi _guiApi;
|
||||||
UnlockSurface(DisplaySurfaceID.Client);
|
|
||||||
|
internal LuaAutoUnlockHack(GuiApi guiApi)
|
||||||
|
=> _guiApi = guiApi;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_guiApi.UnlockSurface(DisplaySurfaceID.EmuCore);
|
||||||
|
_guiApi.UnlockSurface(DisplaySurfaceID.Client);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaAutoUnlockHack ThisIsTheLuaAutoUnlockHack()
|
||||||
|
=> new(this);
|
||||||
|
|
||||||
public void DrawNew(string name, bool clear)
|
public void DrawNew(string name, bool clear)
|
||||||
{
|
{
|
||||||
|
|
|
@ -184,6 +184,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public LuaFunctionList RegisteredFunctions { get; }
|
public LuaFunctionList RegisteredFunctions { get; }
|
||||||
|
|
||||||
public void CallSaveStateEvent(string name)
|
public void CallSaveStateEvent(string name)
|
||||||
|
{
|
||||||
|
using (GuiAPI.ThisIsTheLuaAutoUnlockHack())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -191,16 +193,17 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
lf.Call(name);
|
lf.Call(name);
|
||||||
}
|
}
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
LogToLuaConsole($"error running function attached by lua function event.onsavestate\nError message: {e.Message}");
|
LogToLuaConsole($"error running function attached by lua function event.onsavestate\nError message: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CallLoadStateEvent(string name)
|
public void CallLoadStateEvent(string name)
|
||||||
|
{
|
||||||
|
using (GuiAPI.ThisIsTheLuaAutoUnlockHack())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -208,52 +211,57 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
lf.Call(name);
|
lf.Call(name);
|
||||||
}
|
}
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
LogToLuaConsole($"error running function attached by lua function event.onloadstate\nError message: {e.Message}");
|
LogToLuaConsole($"error running function attached by lua function event.onloadstate\nError message: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CallFrameBeforeEvent()
|
public void CallFrameBeforeEvent()
|
||||||
{
|
{
|
||||||
if (IsUpdateSupressed) return;
|
if (IsUpdateSupressed) return;
|
||||||
|
|
||||||
|
using (GuiAPI.ThisIsTheLuaAutoUnlockHack())
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_PREFRAME).ToList())
|
foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_PREFRAME).ToList())
|
||||||
{
|
{
|
||||||
lf.Call();
|
lf.Call();
|
||||||
}
|
}
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
LogToLuaConsole($"error running function attached by lua function event.onframestart\nError message: {e.Message}");
|
LogToLuaConsole($"error running function attached by lua function event.onframestart\nError message: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CallFrameAfterEvent()
|
public void CallFrameAfterEvent()
|
||||||
{
|
{
|
||||||
if (IsUpdateSupressed) return;
|
if (IsUpdateSupressed) return;
|
||||||
|
|
||||||
|
using (GuiAPI.ThisIsTheLuaAutoUnlockHack())
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_POSTFRAME).ToList())
|
foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_POSTFRAME).ToList())
|
||||||
{
|
{
|
||||||
lf.Call();
|
lf.Call();
|
||||||
}
|
}
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
LogToLuaConsole($"error running function attached by lua function event.onframeend\nError message: {e.Message}");
|
LogToLuaConsole($"error running function attached by lua function event.onframeend\nError message: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CallExitEvent(LuaFile lf)
|
public void CallExitEvent(LuaFile lf)
|
||||||
|
{
|
||||||
|
using (GuiAPI.ThisIsTheLuaAutoUnlockHack())
|
||||||
{
|
{
|
||||||
foreach (var exitCallback in RegisteredFunctions
|
foreach (var exitCallback in RegisteredFunctions
|
||||||
.Where(l => l.Event == NamedLuaFunction.EVENT_TYPE_ENGINESTOP
|
.Where(l => l.Event == NamedLuaFunction.EVENT_TYPE_ENGINESTOP
|
||||||
|
@ -262,7 +270,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
exitCallback.Call();
|
exitCallback.Call();
|
||||||
}
|
}
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
|
@ -318,6 +326,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
=> _lua.DoString(command);
|
=> _lua.DoString(command);
|
||||||
|
|
||||||
public (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf)
|
public (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf)
|
||||||
|
{
|
||||||
|
using (GuiAPI.ThisIsTheLuaAutoUnlockHack())
|
||||||
{
|
{
|
||||||
_currThread = lf.Thread;
|
_currThread = lf.Thread;
|
||||||
|
|
||||||
|
@ -326,26 +336,24 @@ namespace BizHawk.Client.EmuHawk
|
||||||
LuaLibraryBase.SetCurrentThread(lf);
|
LuaLibraryBase.SetCurrentThread(lf);
|
||||||
|
|
||||||
var execResult = _currThread.Resume();
|
var execResult = _currThread.Resume();
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
|
|
||||||
_currThread = null;
|
_currThread = null;
|
||||||
var result = execResult == KeraLua.LuaStatus.OK
|
var result = execResult switch
|
||||||
? (WaitForFrame: false, Terminated: true) // terminated
|
{
|
||||||
: (WaitForFrame: FrameAdvanceRequested, Terminated: false); // yielded
|
KeraLua.LuaStatus.OK => (WaitForFrame: false, Terminated: true),
|
||||||
|
KeraLua.LuaStatus.Yield => (WaitForFrame: FrameAdvanceRequested, Terminated: false),
|
||||||
|
_ => throw new InvalidOperationException($"{nameof(_currThread.Resume)}() returned {execResult}?")
|
||||||
|
};
|
||||||
|
|
||||||
FrameAdvanceRequested = false;
|
FrameAdvanceRequested = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
GuiAPI.ThisIsTheLuaAutounlockHack();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
LuaLibraryBase.ClearCurrentThread();
|
LuaLibraryBase.ClearCurrentThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void Print(params object[] outputs)
|
public static void Print(params object[] outputs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -591,7 +591,9 @@ namespace BizHawk.Tests.Client.Common.Lua
|
||||||
public void Net_Return_Char()
|
public void Net_Return_Char()
|
||||||
{
|
{
|
||||||
ReturnValue = 'a';
|
ReturnValue = 'a';
|
||||||
Assert.IsTrue((bool)LuaInstance.DoString($"return return_char() == {(byte)'a'}")[0]);
|
Assert.IsTrue((bool)LuaInstance.DoString($"return return_char() == {(ushort)'a'}")[0]);
|
||||||
|
ReturnValue = 'こ';
|
||||||
|
Assert.IsTrue((bool)LuaInstance.DoString($"return return_char() == {(ushort)'こ'}")[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -612,7 +614,7 @@ namespace BizHawk.Tests.Client.Common.Lua
|
||||||
public void Net_Return_Color()
|
public void Net_Return_Color()
|
||||||
{
|
{
|
||||||
ReturnValue = ExpectedValue = Color.Aqua;
|
ReturnValue = ExpectedValue = Color.Aqua;
|
||||||
LuaInstance.DoString("return pass_color(return_color())");
|
LuaInstance.DoString("pass_color(return_color())");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -679,16 +681,14 @@ namespace BizHawk.Tests.Client.Common.Lua
|
||||||
LuaInstance.DoString("pass_bool(true)");
|
LuaInstance.DoString("pass_bool(true)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// this doesn't work for some reason
|
[TestMethod]
|
||||||
// just results in an exception due to "Invalid arguments to method call"
|
|
||||||
/*[TestMethod]
|
|
||||||
public void Net_Argument_S8()
|
public void Net_Argument_S8()
|
||||||
{
|
{
|
||||||
ExpectedValue = (sbyte)123;
|
ExpectedValue = (sbyte)123;
|
||||||
LuaInstance.DoString("pass_s8(123)");
|
LuaInstance.DoString("pass_s8(123)");
|
||||||
ExpectedValue = (sbyte)-123;
|
ExpectedValue = (sbyte)-123;
|
||||||
LuaInstance.DoString("pass_s8(-123)");
|
LuaInstance.DoString("pass_s8(-123)");
|
||||||
}*/
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Net_Argument_U8()
|
public void Net_Argument_U8()
|
||||||
|
@ -772,13 +772,11 @@ namespace BizHawk.Tests.Client.Common.Lua
|
||||||
LuaInstance.DoString("pass_decimal(-123.0)");
|
LuaInstance.DoString("pass_decimal(-123.0)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// these don't work either, although these make a bit more sense
|
// these don't work, although there is reasoning behind this
|
||||||
// IntPtr/UIntPtr are meant as handles to "userdata"
|
// IntPtr/UIntPtr are meant as handles to "userdata"
|
||||||
// so raw integers result in "Invalid arguments to method call"
|
// so raw integers result in "Invalid arguments to method call"
|
||||||
// not sure why char doesn't work (same exception here)
|
|
||||||
|
|
||||||
/*
|
/*[TestMethod]
|
||||||
[TestMethod]
|
|
||||||
public void Net_Argument_IntPtr()
|
public void Net_Argument_IntPtr()
|
||||||
{
|
{
|
||||||
ExpectedValue = (IntPtr)123;
|
ExpectedValue = (IntPtr)123;
|
||||||
|
@ -787,20 +785,21 @@ namespace BizHawk.Tests.Client.Common.Lua
|
||||||
LuaInstance.DoString("pass_intptr(-123)");
|
LuaInstance.DoString("pass_intptr(-123)");
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*
|
/*[TestMethod]
|
||||||
[TestMethod]
|
|
||||||
public void Net_Argument_UIntPtr()
|
public void Net_Argument_UIntPtr()
|
||||||
{
|
{
|
||||||
ExpectedValue = (UIntPtr)123;
|
ExpectedValue = (UIntPtr)123;
|
||||||
LuaInstance.DoString("pass_uintptr(123)");
|
LuaInstance.DoString("pass_uintptr(123)");
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*[TestMethod]
|
[TestMethod]
|
||||||
public void Net_Argument_Char()
|
public void Net_Argument_Char()
|
||||||
{
|
{
|
||||||
ExpectedValue = 'a';
|
ExpectedValue = 'a';
|
||||||
LuaInstance.DoString($"pass_char({(byte)'a'})");
|
LuaInstance.DoString($"pass_char({(ushort)'a'})");
|
||||||
}*/
|
ExpectedValue = 'こ';
|
||||||
|
LuaInstance.DoString($"pass_char({(ushort)'こ'})");
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Net_Argument_String()
|
public void Net_Argument_String()
|
||||||
|
@ -816,6 +815,19 @@ namespace BizHawk.Tests.Client.Common.Lua
|
||||||
LuaInstance.DoString($"pass_string(\"こんにちは\")");
|
LuaInstance.DoString($"pass_string(\"こんにちは\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Net_Argument_String_Implicit_Number_Conversion()
|
||||||
|
{
|
||||||
|
ExpectedValue = "123";
|
||||||
|
LuaInstance.DoString("pass_string(123)");
|
||||||
|
ExpectedValue = "-123";
|
||||||
|
LuaInstance.DoString("pass_string(-123)");
|
||||||
|
ExpectedValue = "0.321";
|
||||||
|
LuaInstance.DoString("pass_string(0.321)");
|
||||||
|
ExpectedValue = "-0.321";
|
||||||
|
LuaInstance.DoString("pass_string(-0.321)");
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Net_Argument_Color()
|
public void Net_Argument_Color()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue