diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs index a48f85d6a0..46f058d065 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs @@ -73,7 +73,11 @@ namespace BizHawk.Client.Common [LuaMethodExample("client.closerom( );")] [LuaMethod("closerom", "Closes the loaded Rom")] public void CloseRom() - => APIs.EmuClient.CloseRom(); + { + _luaLibsImpl.IsRebootingCore = true; + APIs.EmuClient.CloseRom(); + _luaLibsImpl.IsRebootingCore = false; + } [LuaMethodExample("client.enablerewind( true );")] [LuaMethod("enablerewind", "Sets whether or not the rewind feature is enabled")] @@ -197,9 +201,9 @@ namespace BizHawk.Client.Common [LuaMethod("openrom", "opens the Open ROM dialog")] public void OpenRom([LuaArbitraryStringParam] string path) { - _luaLibsImpl.IsUpdateSupressed = _luaLibsImpl.IsRebootingCore = true; + _luaLibsImpl.IsRebootingCore = true; APIs.EmuClient.OpenRom(path); - _luaLibsImpl.IsUpdateSupressed = _luaLibsImpl.IsRebootingCore = false; + _luaLibsImpl.IsRebootingCore = false; } [LuaMethodExample("client.opentasstudio( );")] @@ -231,9 +235,9 @@ namespace BizHawk.Client.Common [LuaMethod("reboot_core", "Reboots the currently loaded core")] public void RebootCore() { - _luaLibsImpl.IsUpdateSupressed = _luaLibsImpl.IsRebootingCore = true; + _luaLibsImpl.IsRebootingCore = true; APIs.EmuClient.RebootCore(); - _luaLibsImpl.IsUpdateSupressed = _luaLibsImpl.IsRebootingCore = false; + _luaLibsImpl.IsRebootingCore = false; } [LuaMethodExample("local incliscr = client.screenheight( );")] diff --git a/src/BizHawk.Client.Common/lua/LuaFile.cs b/src/BizHawk.Client.Common/lua/LuaFile.cs index d4eca1f3df..869ac4a647 100644 --- a/src/BizHawk.Client.Common/lua/LuaFile.cs +++ b/src/BizHawk.Client.Common/lua/LuaFile.cs @@ -37,7 +37,6 @@ namespace BizHawk.Client.Common public bool Enabled => State != RunState.Disabled; public bool Paused => State == RunState.Paused; public bool IsSeparator { get; } - public Lua LuaRef { get; set; } public LuaThread Thread { get; set; } public bool FrameWaiting { get; set; } public string CurrentDirectory { get; set; } @@ -56,13 +55,7 @@ namespace BizHawk.Client.Common return; } - if (State == RunState.Running && Thread.State.Status == KeraLua.LuaStatus.OK) - { - Thread.Yield(); // we MUST yield this thread, else old references to lua libs might be used (and those may contain references to a Dispose()'d emulator) - } - State = RunState.Disabled; - LuaRef = null; Thread.Dispose(); Thread = null; } diff --git a/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs b/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs index cc30cb25af..324bed0036 100644 --- a/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs +++ b/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs @@ -31,11 +31,12 @@ namespace BizHawk.Client.Common private readonly LuaFunction _function; - public NamedLuaFunction(LuaFunction function, string theEvent, Action logCallback, LuaFile luaFile, string name = null) + public NamedLuaFunction(LuaFunction function, string theEvent, Action logCallback, LuaFile luaFile, Func createThreadCallback, string name = null) { _function = function; Name = name ?? "Anonymous"; Event = theEvent; + CreateThreadCallback = createThreadCallback; // When would a file be null? // When a script is loaded with a callback, but no infinite loop so it closes @@ -71,14 +72,13 @@ namespace BizHawk.Client.Common public void DetachFromScript() { - var lua = LuaFile.LuaRef; - lua.NewThread(out var thread); + var thread = CreateThreadCallback(); // Current dir will have to do for now, but this will inevitably not be desired // Users will expect it to be the same directly as the thread that spawned this callback // But how do we know what that directory was? LuaSandbox.CreateSandbox(thread, "."); - LuaFile = new LuaFile(".") { LuaRef = lua, Thread = thread }; + LuaFile = new LuaFile(".") { Thread = thread }; } public Guid Guid { get; } @@ -87,6 +87,8 @@ namespace BizHawk.Client.Common public LuaFile LuaFile { get; private set; } + private Func CreateThreadCallback { get; } + public string Event { get; } private Action Callback { get; } diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index 4226ce0d50..9303a9d126 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -197,6 +197,9 @@ namespace BizHawk.Client.EmuHawk return; } + runningScripts = luaLibsImpl.ScriptList.Where(lf => lf.Enabled).ToList(); + + // we don't use runningScripts here as the other scripts need to be stopped too foreach (var file in luaLibsImpl.ScriptList) { if (file.Enabled) luaLibsImpl.CallExitEvent(file); @@ -538,7 +541,7 @@ namespace BizHawk.Client.EmuHawk protected override void UpdateBefore() { - if (!(LuaImp is Win32LuaLibraries luaLibsImpl) || luaLibsImpl.IsUpdateSupressed) + if (LuaImp is not Win32LuaLibraries luaLibsImpl || luaLibsImpl.IsUpdateSupressed) { return; } @@ -548,7 +551,7 @@ namespace BizHawk.Client.EmuHawk protected override void UpdateAfter() { - if (!(LuaImp is Win32LuaLibraries luaLibsImpl) || LuaImp.IsUpdateSupressed) + if (LuaImp is not Win32LuaLibraries luaLibsImpl || luaLibsImpl.IsUpdateSupressed) { return; } @@ -595,7 +598,7 @@ namespace BizHawk.Client.EmuHawk /// should frame waiters be waken up? only use this immediately before a frame of emulation public void ResumeScripts(bool includeFrameWaiters) { - if (!(LuaImp is Win32LuaLibraries luaLibsImpl) + if (LuaImp is not Win32LuaLibraries luaLibsImpl || !luaLibsImpl.ScriptList.Any() || luaLibsImpl.IsUpdateSupressed || (MainForm.IsTurboing && !Config.RunLuaDuringTurbo)) @@ -612,8 +615,8 @@ namespace BizHawk.Client.EmuHawk var prohibit = lf.FrameWaiting && !includeFrameWaiters; if (!prohibit) { - var result = luaLibsImpl.ResumeScript(lf); - if (result.Terminated) + var (waitForFrame, terminated) = luaLibsImpl.ResumeScript(lf); + if (terminated) { luaLibsImpl.CallExitEvent(lf); lf.Stop(); @@ -621,7 +624,7 @@ namespace BizHawk.Client.EmuHawk UpdateDialog(); } - lf.FrameWaiting = result.WaitForFrame; + lf.FrameWaiting = waitForFrame; } }, () => { diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs index cb9898d86e..1d2be896eb 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Win32LuaLibraries.cs @@ -288,7 +288,8 @@ namespace BizHawk.Client.EmuHawk LuaFile luaFile, [LuaArbitraryStringParam] string name = null) { - var nlf = new NamedLuaFunction(function, theEvent, logCallback, luaFile, name); + var nlf = new NamedLuaFunction(function, theEvent, logCallback, luaFile, + () => { _lua.NewThread(out var thread); return thread; }, name); RegisteredFunctions.Add(nlf); return nlf; } @@ -311,10 +312,7 @@ namespace BizHawk.Client.EmuHawk } public void SpawnAndSetFileThread(string pathToLoad, LuaFile lf) - { - lf.LuaRef = _lua; // ref kept around for DetachFromScript in NamedLuaFunction - lf.Thread = SpawnCoroutine(pathToLoad); - } + => lf.Thread = SpawnCoroutine(pathToLoad); public void ExecuteString(string command) => _lua.DoString(command);