diff --git a/Assets/Scripts/SysCalls.cs b/Assets/Scripts/SysCalls.cs index 36fb1f6..ba6da75 100644 --- a/Assets/Scripts/SysCalls.cs +++ b/Assets/Scripts/SysCalls.cs @@ -99,9 +99,8 @@ public class SysCalls: CallbackHandler private void Error(string message) { - Debug.LogError(message); - // TODO: kill execution of the DLL entirely (Sys_Quit expects immediate exit, which this doesn't do) - Application.Quit(1); + // Use an exception to emulate Quake's behavior of immediately terminating the game's code execution on error + throw new QuakeException(message, 1); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -115,8 +114,8 @@ public class SysCalls: CallbackHandler private void Quit() { - Debug.Log($"Quitting application normally"); - Application.Quit(0); + // This exception will be caught by the UniQuake update loop where the game will be shut down + throw new QuakeException("Quitting application normally"); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] diff --git a/Assets/Scripts/UniQuake.cs b/Assets/Scripts/UniQuake.cs index 2d04ce3..1933449 100644 --- a/Assets/Scripts/UniQuake.cs +++ b/Assets/Scripts/UniQuake.cs @@ -11,6 +11,8 @@ public class UniQuake: MonoBehaviour private SysCalls sysCalls; private ModCalls modCalls; + private bool initialized = false; + void Start() { string[] arguments = @@ -33,16 +35,62 @@ public class UniQuake: MonoBehaviour sysCalls = new SysCalls(this); modCalls = new ModCalls(this); - UniQuake_Init(quakeParms, sysCalls.ToIntPtr, modCalls.ToIntPtr); + try + { + UniQuake_Init(quakeParms, sysCalls.ToIntPtr, modCalls.ToIntPtr); + initialized = true; + } + catch (QuakeException ex) + { + if (ex.ExitCode == 0) + Debug.Log(ex.Message); + else + Debug.LogException(ex); + + Shutdown(); + } + catch (Exception ex) + { + Debug.LogException(ex); + Shutdown(); + } } void Update() { - UniQuake_Update(Time.deltaTime); + if (!initialized) + return; + + try + { + UniQuake_Update(Time.deltaTime); + } + catch (QuakeException ex) + { + if (ex.ExitCode == 0) + Debug.Log(ex.Message); + else + Debug.LogException(ex); + + Shutdown(); + } + catch (Exception ex) + { + Debug.LogException(ex); + Shutdown(); + } + } + + private void Shutdown() + { + initialized = false; + UniQuake_Shutdown(); + Destroy(this); } private void OnDestroy() { + modCalls.Destroy(); sysCalls.Destroy(); if (quakeParms != null) @@ -57,4 +105,18 @@ public class UniQuake: MonoBehaviour [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern void UniQuake_Update(float deltaTime); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + private static extern void UniQuake_Shutdown(); } + +public class QuakeException: Exception +{ + public int ExitCode { get; } + + public QuakeException(string message, int exitCode = 0) + : base(message) + { + ExitCode = exitCode; + } +} diff --git a/engine/projects/uniquake/sys_uniquake.c b/engine/projects/uniquake/sys_uniquake.c index 3d2f838..1f3e1f9 100644 --- a/engine/projects/uniquake/sys_uniquake.c +++ b/engine/projects/uniquake/sys_uniquake.c @@ -30,7 +30,6 @@ void Sys_Printf(char *fmt, ...) void Sys_Quit(void) { - Host_Shutdown(); unity_syscalls->SysQuit(unity_syscalls->target); } diff --git a/engine/projects/uniquake/uniquake.c b/engine/projects/uniquake/uniquake.c index 5a3e606..f520d2f 100644 --- a/engine/projects/uniquake/uniquake.c +++ b/engine/projects/uniquake/uniquake.c @@ -20,3 +20,8 @@ UNIQUAKE_API void UniQuake_Update(float deltaTime) Host_Frame(deltaTime); } + +UNIQUAKE_API void UniQuake_Shutdown() +{ + Host_Shutdown(); +}