diff --git a/Assets/Scripts/CallbackHandler.cs b/Assets/Scripts/CallbackHandler.cs index 0cec3c9..d044144 100644 --- a/Assets/Scripts/CallbackHandler.cs +++ b/Assets/Scripts/CallbackHandler.cs @@ -6,17 +6,23 @@ public abstract class CallbackHandler where THandler: CallbackHandler { private GCHandle selfHandle; + private GCHandle callbacksHandle; private List delegateHandles = new List(); - public IntPtr SelfPtr => GCHandle.ToIntPtr(selfHandle); + public IntPtr ToIntPtr => callbacksHandle.AddrOfPinnedObject(); + + protected IntPtr SelfPtr => GCHandle.ToIntPtr(selfHandle); protected CallbackHandler() { selfHandle = GCHandle.Alloc(this); } - public virtual void Destroy() + public void Destroy() { + if (callbacksHandle.IsAllocated) + callbacksHandle.Free(); + foreach (var handle in delegateHandles) { if (handle.IsAllocated) @@ -32,6 +38,11 @@ public abstract class CallbackHandler return Marshal.GetFunctionPointerForDelegate(callback); } + protected void RegisterCallbacks(TCallbacks callbacks) + { + callbacksHandle = GCHandle.Alloc(callbacks, GCHandleType.Pinned); + } + protected static THandler GetSelf(IntPtr target) { return (THandler)GCHandle.FromIntPtr(target).Target; diff --git a/Assets/Scripts/SysCalls.cs b/Assets/Scripts/SysCalls.cs index 74f79f3..e97de9c 100644 --- a/Assets/Scripts/SysCalls.cs +++ b/Assets/Scripts/SysCalls.cs @@ -6,39 +6,29 @@ public class SysCalls: CallbackHandler { private readonly UniQuake uq; private readonly double startTime; - - private Callbacks callbacks; - private GCHandle callbacksHandle; - - public IntPtr CallbacksPtr => callbacksHandle.AddrOfPinnedObject(); public SysCalls(UniQuake uniQuake) { uq = uniQuake; startTime = Time.timeAsDouble; - callbacks = new Callbacks + var callbacks = new Callbacks { + target = SelfPtr, SysPrint = CreateCallback(Callback_SysPrint), SysError = CreateCallback(Callback_SysError), SysQuit = CreateCallback(Callback_SysQuit), SysFloatTime = CreateCallback(Callback_SysFloatTime), }; - - callbacksHandle = GCHandle.Alloc(callbacks, GCHandleType.Pinned); - } - - public override void Destroy() - { - if (callbacksHandle.IsAllocated) - callbacksHandle.Free(); - base.Destroy(); + RegisterCallbacks(callbacks); } [StructLayout(LayoutKind.Sequential, Pack = 0)] private class Callbacks { + public IntPtr target; + public IntPtr SysPrint; public IntPtr SysError; public IntPtr SysQuit; diff --git a/Assets/Scripts/UniQuake.cs b/Assets/Scripts/UniQuake.cs index fb6ba8d..4db221c 100644 --- a/Assets/Scripts/UniQuake.cs +++ b/Assets/Scripts/UniQuake.cs @@ -30,7 +30,7 @@ public class UniQuake: MonoBehaviour sysCalls = new SysCalls(this); - UniQuake_Init(sysCalls.CallbacksPtr, sysCalls.SelfPtr, quakeParms); + UniQuake_Init(quakeParms, sysCalls.ToIntPtr); } void Update() @@ -50,7 +50,7 @@ public class UniQuake: MonoBehaviour } [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - private static extern void UniQuake_Init(IntPtr callbacks, IntPtr callbackTarget, QuakeParms parms); + private static extern void UniQuake_Init(QuakeParms parms, IntPtr syscalls); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern void UniQuake_Update(float deltaTime); diff --git a/engine/projects/uniquake/uniquake.c b/engine/projects/uniquake/uniquake.c index 040174f..de8c7fa 100644 --- a/engine/projects/uniquake/uniquake.c +++ b/engine/projects/uniquake/uniquake.c @@ -7,8 +7,7 @@ #include "../../code/quakedef.h" -const unity_callbacks_t *unity_callbacks; -void *unity_callbackTarget; +const unity_syscalls_t *unity_syscalls; void Sys_Error(char *error, ...) { @@ -19,7 +18,7 @@ void Sys_Error(char *error, ...) vsprintf(text, error, argptr); va_end(argptr); - unity_callbacks->SysError(unity_callbackTarget, text); + unity_syscalls->SysError(unity_syscalls->target, text); } void Sys_Printf(char *fmt, ...) @@ -31,24 +30,23 @@ void Sys_Printf(char *fmt, ...) vsprintf(text, fmt, argptr); va_end(argptr); - unity_callbacks->SysPrint(unity_callbackTarget, text); + unity_syscalls->SysPrint(unity_syscalls->target, text); } void Sys_Quit(void) { Host_Shutdown(); - unity_callbacks->SysQuit(unity_callbackTarget); + unity_syscalls->SysQuit(unity_syscalls->target); } double Sys_FloatTime(void) { - return unity_callbacks->SysFloatTime(unity_callbackTarget); + return unity_syscalls->SysFloatTime(unity_syscalls->target); } -UNIQUAKE_API void UniQuake_Init(const unity_callbacks_t *callbacks, void *callbackTarget, quakeparms_t *parms) +UNIQUAKE_API void UniQuake_Init(quakeparms_t *parms, const unity_syscalls_t *syscalls) { - unity_callbacks = callbacks; - unity_callbackTarget = callbackTarget; + unity_syscalls = syscalls; COM_InitArgv(parms->argc, parms->argv); parms->argc = com_argc; diff --git a/engine/projects/uniquake/uniquake.h b/engine/projects/uniquake/uniquake.h index cd9aabe..2802759 100644 --- a/engine/projects/uniquake/uniquake.h +++ b/engine/projects/uniquake/uniquake.h @@ -4,12 +4,14 @@ #define UNIQUAKE_API __declspec(dllimport) #endif -typedef struct unity_callbacks_s +typedef struct unity_syscalls_s { + void *target; + void(__stdcall *SysPrint)(void *target, const char *msg); void(__stdcall *SysError)(void *target, const char *msg); void(__stdcall *SysQuit)(void *target); double(__stdcall *SysFloatTime)(void *target); -} unity_callbacks_t; +} unity_syscalls_t; -extern const unity_callbacks_t *unity_callbacks; +extern const unity_syscalls_t *unity_syscalls;