From fdb3ee2ee508f242cef1e2264b0b4e3939ccd340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 11 Dec 2023 15:21:38 +0100 Subject: [PATCH] Move over various TERA.exe interop definitions from TERA Arise. Closes #86. --- src/interop/.globalconfig | 1 + src/interop/FArchive.cs | 120 ++++++++++++++++++ src/interop/FBufferReader.cs | 56 ++++++++ src/interop/FName.cs | 11 ++ src/interop/FString.cs | 16 +++ src/interop/ILauncherEvent.cs | 22 ++++ src/interop/IS1ConnectionEventHandler.cs | 24 ++++ src/interop/IS1ConnectionInfo.cs | 23 ++++ src/interop/IS1MemoryObject.cs | 21 +++ src/interop/S1.cs | 21 +++ src/interop/S1ClientSocket.cs | 79 ++++++++++++ src/interop/S1ClientSocketBuffer.cs | 32 +++++ src/interop/S1CommandQueue.cs | 17 +++ src/interop/S1Connection.cs | 20 +++ src/interop/S1ConnectionManager.cs | 32 +++++ src/interop/S1Context.cs | 11 ++ src/interop/S1DataDB.cs | 13 ++ src/interop/S1ExitReason.cs | 14 ++ src/interop/S1GameServerConnection.cs | 50 ++++++++ src/interop/S1LauncherEvent.cs | 47 +++++++ src/interop/S1LauncherProxy.cs | 86 +++++++++++++ src/interop/S1LobbySceneServer.cs | 50 ++++++++ src/interop/S1SceneBase.cs | 31 +++++ src/interop/S1ServerDataEvent.cs | 23 ++++ src/interop/S1ServerInfo.cs | 40 ++++++ src/interop/S1ServerList.cs | 22 ++++ src/interop/S1ServerListSortCriteria.cs | 10 ++ src/interop/S1Type.cs | 17 +++ src/interop/Support/Tera.cs | 20 +++ src/interop/System/BOOL.cs | 65 ++++++++++ src/interop/System/HWND.cs | 59 +++++++++ src/interop/System/SOCKET.cs | 57 +++++++++ src/interop/System/WSAEVENT.cs | 57 +++++++++ src/interop/System/in_addr.cs | 55 ++++++++ src/interop/TArray`1.cs | 15 +++ .../Vezel.Novadrop.Interop.targets | 1 + src/interop/interop.csproj | 4 + 37 files changed, 1242 insertions(+) create mode 100644 src/interop/FArchive.cs create mode 100644 src/interop/FBufferReader.cs create mode 100644 src/interop/FName.cs create mode 100644 src/interop/FString.cs create mode 100644 src/interop/ILauncherEvent.cs create mode 100644 src/interop/IS1ConnectionEventHandler.cs create mode 100644 src/interop/IS1ConnectionInfo.cs create mode 100644 src/interop/IS1MemoryObject.cs create mode 100644 src/interop/S1.cs create mode 100644 src/interop/S1ClientSocket.cs create mode 100644 src/interop/S1ClientSocketBuffer.cs create mode 100644 src/interop/S1CommandQueue.cs create mode 100644 src/interop/S1Connection.cs create mode 100644 src/interop/S1ConnectionManager.cs create mode 100644 src/interop/S1Context.cs create mode 100644 src/interop/S1DataDB.cs create mode 100644 src/interop/S1ExitReason.cs create mode 100644 src/interop/S1GameServerConnection.cs create mode 100644 src/interop/S1LauncherEvent.cs create mode 100644 src/interop/S1LauncherProxy.cs create mode 100644 src/interop/S1LobbySceneServer.cs create mode 100644 src/interop/S1SceneBase.cs create mode 100644 src/interop/S1ServerDataEvent.cs create mode 100644 src/interop/S1ServerInfo.cs create mode 100644 src/interop/S1ServerList.cs create mode 100644 src/interop/S1ServerListSortCriteria.cs create mode 100644 src/interop/S1Type.cs create mode 100644 src/interop/Support/Tera.cs create mode 100644 src/interop/System/BOOL.cs create mode 100644 src/interop/System/HWND.cs create mode 100644 src/interop/System/SOCKET.cs create mode 100644 src/interop/System/WSAEVENT.cs create mode 100644 src/interop/System/in_addr.cs create mode 100644 src/interop/TArray`1.cs diff --git a/src/interop/.globalconfig b/src/interop/.globalconfig index fb71466..0a82f4f 100644 --- a/src/interop/.globalconfig +++ b/src/interop/.globalconfig @@ -1,5 +1,6 @@ global_level = 2 +dotnet_diagnostic.CA1008.severity = none dotnet_diagnostic.CA1707.severity = none dotnet_diagnostic.CA1711.severity = none dotnet_diagnostic.CA1815.severity = none diff --git a/src/interop/FArchive.cs b/src/interop/FArchive.cs new file mode 100644 index 0000000..92cf901 --- /dev/null +++ b/src/interop/FArchive.cs @@ -0,0 +1,120 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8c)] +public unsafe struct FArchive +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public delegate* unmanaged __vdtor; + + public delegate* unmanaged Serialize; + + public delegate* unmanaged SerializeBits; + + public delegate* unmanaged SerializeInt; + + public void* __slot4; + + public delegate* unmanaged CountBytes; + + public void* __slot6; + + public void* __slot7; + + public void* __slot8; + + public void* __slot9; + + public delegate* unmanaged Tell; + + public delegate* unmanaged TotalSize; + + public delegate* unmanaged AtEnd; + + public delegate* unmanaged Seek; + + public void* __slot14; + + public void* __slot15; + + public void* __slot16; + + public void* __slot17; + + public void* __slot18; + + public void* __slot19; + + public delegate* unmanaged Flush; + + public delegate* unmanaged Close; + + public delegate* unmanaged GetError; + + public void* __slot23; + + public void* __slot24; + + public void* __slot25; + + public void* __slot26; + + public void* __slot27; + + public void* __slot28; + + public void* __slot29; + } + + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a843f10); + + public static delegate* unmanaged __vdtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a845fe0); + + public static delegate* unmanaged AtEnd { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a846ac0); + + public static delegate* unmanaged ByteOrderSerialize { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a846b10); + + public static delegate* unmanaged Close { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a846ba0); + + public static delegate* unmanaged GetError { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a8488f0); + + public static delegate* unmanaged SerializeBits { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a84bf20); + + public static delegate* unmanaged SerializeInt { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a84bf90); + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; + + [FieldOffset(0xc)] + public int package_version; + + [FieldOffset(0x10)] + public int network_version; + + [FieldOffset(0x14)] + public int licensee_version; + + [FieldOffset(0x18)] + public BOOL is_reader; + + [FieldOffset(0x2c)] + public BOOL is_persistent; + + [FieldOffset(0x3c)] + public BOOL has_errors; + + [FieldOffset(0x50)] + public BOOL force_order_swap; +} diff --git a/src/interop/FBufferReader.cs b/src/interop/FBufferReader.cs new file mode 100644 index 0000000..6e305a1 --- /dev/null +++ b/src/interop/FBufferReader.cs @@ -0,0 +1,56 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0xa0)] +public unsafe struct FBufferReader +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public FArchive.VirtualFunctionTable FArchive; + } + + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a852b50); + + public static delegate* unmanaged __dtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a854b20); + + public static delegate* unmanaged __vdtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a8582e0); + + public static delegate* unmanaged AtEnd { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a85be40); + + public static delegate* unmanaged Close { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a85bfc0); + + public static delegate* unmanaged Seek { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a879ef0); + + public static delegate* unmanaged Serialize { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a87a370); + + public static delegate* unmanaged Tell { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a87faf0); + + [FieldOffset(0x0)] + public FArchive FArchive; + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; + + [FieldOffset(0x8c)] + public void* data; + + [FieldOffset(0x94)] + public int position; + + [FieldOffset(0x98)] + public int size; + + [FieldOffset(0x9c)] + public BOOL free_on_close; +} diff --git a/src/interop/FName.cs b/src/interop/FName.cs new file mode 100644 index 0000000..e8ad5af --- /dev/null +++ b/src/interop/FName.cs @@ -0,0 +1,11 @@ +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8)] +public unsafe struct FName +{ + [FieldOffset(0x0)] + public int name_index; + + [FieldOffset(0x4)] + public int number; +} diff --git a/src/interop/FString.cs b/src/interop/FString.cs new file mode 100644 index 0000000..e3e4aea --- /dev/null +++ b/src/interop/FString.cs @@ -0,0 +1,16 @@ +using Vezel.Novadrop.Interop.Support; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x14)] +public unsafe struct FString +{ + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a844310); + + public static delegate* unmanaged __ctor2 { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a844140); + + [FieldOffset(0x0)] + public TArray TArray_char; +} diff --git a/src/interop/ILauncherEvent.cs b/src/interop/ILauncherEvent.cs new file mode 100644 index 0000000..e8169bd --- /dev/null +++ b/src/interop/ILauncherEvent.cs @@ -0,0 +1,22 @@ +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8)] +public unsafe struct ILauncherEvent +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public delegate* unmanaged OnServerList; + + public delegate* unmanaged OnCreateRoom; + + public delegate* unmanaged OnJoinRoom; + + public delegate* unmanaged OnLeaveRoom; + } + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; +} diff --git a/src/interop/IS1ConnectionEventHandler.cs b/src/interop/IS1ConnectionEventHandler.cs new file mode 100644 index 0000000..2a2be87 --- /dev/null +++ b/src/interop/IS1ConnectionEventHandler.cs @@ -0,0 +1,24 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8)] +public unsafe struct IS1ConnectionEventHandler +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public delegate* unmanaged OnConnect; + + public delegate* unmanaged OnDisconnect; + + public delegate* unmanaged OnReceive; + } + + public static delegate* unmanaged OnReceive { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69b9c1ce0); + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; +} diff --git a/src/interop/IS1ConnectionInfo.cs b/src/interop/IS1ConnectionInfo.cs new file mode 100644 index 0000000..5bb17bc --- /dev/null +++ b/src/interop/IS1ConnectionInfo.cs @@ -0,0 +1,23 @@ +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8)] +public unsafe struct IS1ConnectionInfo +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public IS1MemoryObject.VirtualFunctionTable IS1MemoryObject; + + public void* __slot2; + + public void* __slot3; + + public delegate* unmanaged CreateSocket; + } + + [FieldOffset(0x0)] + public IS1MemoryObject IS1MemoryObject; + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; +} diff --git a/src/interop/IS1MemoryObject.cs b/src/interop/IS1MemoryObject.cs new file mode 100644 index 0000000..c05ee77 --- /dev/null +++ b/src/interop/IS1MemoryObject.cs @@ -0,0 +1,21 @@ +using Vezel.Novadrop.Interop.Support; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8)] +public unsafe struct IS1MemoryObject +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public delegate* unmanaged __vdtor; + + public delegate* unmanaged GetSize; + } + + public static delegate* unmanaged __vdtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69b4579e0); + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; +} diff --git a/src/interop/S1.cs b/src/interop/S1.cs new file mode 100644 index 0000000..65fce63 --- /dev/null +++ b/src/interop/S1.cs @@ -0,0 +1,21 @@ +using Vezel.Novadrop.Interop.Support; + +namespace Vezel.Novadrop.Interop; + +public static unsafe class S1 +{ + public static ref S1Context* Context => ref *(S1Context**)Tera.Resolve(0x7ff69d7b2040); + + public static ref S1LauncherProxy* LauncherProxy => ref *(S1LauncherProxy**)Tera.Resolve(0x7ff69d87de00); + + public static ref S1ServerDataEvent ServerDataEvent => ref *(S1ServerDataEvent*)Tera.Resolve(0x7ff69d4f6840); + + public static delegate* unmanaged appMalloc { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a8977d0); + + public static delegate* unmanaged appRealloc { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a897870); + + public static delegate* unmanaged appFree { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69a897750); +} diff --git a/src/interop/S1ClientSocket.cs b/src/interop/S1ClientSocket.cs new file mode 100644 index 0000000..1f137ca --- /dev/null +++ b/src/interop/S1ClientSocket.cs @@ -0,0 +1,79 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x2002c)] +public unsafe struct S1ClientSocket +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public IS1MemoryObject.VirtualFunctionTable IS1MemoryObject; + + public delegate* unmanaged Send; + + public delegate* unmanaged Register; + + public delegate* unmanaged Receive; + + public delegate* unmanaged Disconnect; + } + + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69ba9fe80); + + public static delegate* unmanaged __dtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baa38d0); + + public static delegate* unmanaged __vdtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baa5540); + + public static delegate* unmanaged Connect { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baa9de0); + + public static delegate* unmanaged Disconnect { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bab89f0); + + public static delegate* unmanaged Dispose { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baaa4d0); + + public static delegate* unmanaged FlushSend { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69babe860); + + public static delegate* unmanaged ProcessEvents { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69babbfe0); + + public static delegate* unmanaged Receive { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baba0f0); + + public static delegate* unmanaged Register { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bab8ef0); + + public static delegate* unmanaged Send { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69babe6b0); + + [FieldOffset(0x0)] + public IS1MemoryObject IS1MemoryObject; + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; + + [FieldOffset(0x8)] + public SOCKET socket; + + [FieldOffset(0x10)] + public WSAEVENT @event; + + [FieldOffset(0x18)] + public BOOL connected; + + [FieldOffset(0x1c)] + public S1ClientSocketBuffer receive_buffer; + + [FieldOffset(0x10020)] + public S1ClientSocketBuffer send_buffer; + + [FieldOffset(0x20024)] + public IS1ConnectionEventHandler* handler; +} diff --git a/src/interop/S1ClientSocketBuffer.cs b/src/interop/S1ClientSocketBuffer.cs new file mode 100644 index 0000000..2e1c2d6 --- /dev/null +++ b/src/interop/S1ClientSocketBuffer.cs @@ -0,0 +1,32 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x10004)] +public unsafe struct S1ClientSocketBuffer +{ + [InlineArray(0x10000)] + public struct InlineArray_data + { + private byte _element; + } + + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baa27a0); + + public static delegate* unmanaged Consume { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69babc170); + + public static delegate* unmanaged GetPosition { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bab21f0); + + public static delegate* unmanaged Write { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bacacd0); + + [FieldOffset(0x0)] + public InlineArray_data data; + + [FieldOffset(0x10000)] + public int position; +} diff --git a/src/interop/S1CommandQueue.cs b/src/interop/S1CommandQueue.cs new file mode 100644 index 0000000..d9c195e --- /dev/null +++ b/src/interop/S1CommandQueue.cs @@ -0,0 +1,17 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x64)] +public unsafe struct S1CommandQueue +{ + public static delegate* unmanaged EnqueuePacket { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baac250); + + public static delegate* unmanaged RunCommands { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baaa560); + + public static delegate* unmanaged RunPacketHandler { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baad410); +} diff --git a/src/interop/S1Connection.cs b/src/interop/S1Connection.cs new file mode 100644 index 0000000..bae52a6 --- /dev/null +++ b/src/interop/S1Connection.cs @@ -0,0 +1,20 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x10)] +public unsafe struct S1Connection +{ + public static delegate* unmanaged Connect { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baa9fc0); + + public static delegate* unmanaged Disconnect { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baaa530); + + [FieldOffset(0x0)] + public IS1ConnectionInfo* info; + + [FieldOffset(0x8)] + public S1ClientSocket* socket; +} diff --git a/src/interop/S1ConnectionManager.cs b/src/interop/S1ConnectionManager.cs new file mode 100644 index 0000000..f40611e --- /dev/null +++ b/src/interop/S1ConnectionManager.cs @@ -0,0 +1,32 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x50)] +public unsafe struct S1ConnectionManager +{ + public static delegate* unmanaged ComputeChecksum { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69b472da0); + + public static delegate* unmanaged Dispose { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69babc8a0); + + public static delegate* unmanaged GetConnection { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69baafcc0); + + public static delegate* unmanaged GetAccountServerName { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69b9b47e0); + + public static delegate* unmanaged GetGameServerName { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bc12b60); + + public static delegate* unmanaged SendGamePacket { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69babe750); + + public static delegate* unmanaged SendPacket { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69babe7b0); + + [FieldOffset(0x4c)] + public BOOL exiting; +} diff --git a/src/interop/S1Context.cs b/src/interop/S1Context.cs new file mode 100644 index 0000000..8b3bbca --- /dev/null +++ b/src/interop/S1Context.cs @@ -0,0 +1,11 @@ +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x470)] +public unsafe struct S1Context +{ + [FieldOffset(0x8)] + public S1CommandQueue* command_queue; + + [FieldOffset(0x18)] + public S1ConnectionManager* connection_manager; +} diff --git a/src/interop/S1DataDB.cs b/src/interop/S1DataDB.cs new file mode 100644 index 0000000..5af7aae --- /dev/null +++ b/src/interop/S1DataDB.cs @@ -0,0 +1,13 @@ +using Vezel.Novadrop.Interop.Support; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x128)] +public unsafe struct S1DataDB +{ + public static delegate* unmanaged Initialize { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bb19f30); + + public static delegate* unmanaged UnpackArchive { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69b884ac0); +} diff --git a/src/interop/S1ExitReason.cs b/src/interop/S1ExitReason.cs new file mode 100644 index 0000000..59a38f7 --- /dev/null +++ b/src/interop/S1ExitReason.cs @@ -0,0 +1,14 @@ +namespace Vezel.Novadrop.Interop; + +public enum S1ExitReason : uint +{ + S1_EXIT_REASON_SUCCESS = 0x0, + S1_EXIT_REASON_INVALID_DATA_CENTER = 0x6, + S1_EXIT_REASON_CONNECTION_DROPPED = 0x8, + S1_EXIT_REASON_INVALID_AUTHENTICATION_INFO = 0x9, + S1_EXIT_REASON_OUT_OF_MEMORY = 0xa, + S1_EXIT_REASON_SHADER_MODEL_3_UNAVAILABLE = 0xc, + S1_EXIT_REASON_SPEED_HACK_DETECTED = 0x10, + S1_EXIT_REASON_UNSUPPORTED_VERSION = 0x13, + S1_EXIT_REASON_ALREADY_ONLINE = 0x106, +} diff --git a/src/interop/S1GameServerConnection.cs b/src/interop/S1GameServerConnection.cs new file mode 100644 index 0000000..e82efac --- /dev/null +++ b/src/interop/S1GameServerConnection.cs @@ -0,0 +1,50 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x10)] +public unsafe struct S1GameServerConnection +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public IS1ConnectionInfo.VirtualFunctionTable IS1ConnectionInfo; + } + + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable_IS1ConnectionEventHandler + { + public IS1ConnectionEventHandler.VirtualFunctionTable IS1ConnectionEventHandler; + } + + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bc05b20); + + public static delegate* unmanaged __vdtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bc082b0); + + public static delegate* unmanaged CreateSocket { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bc0ab30); + + public static delegate* unmanaged OnConnect { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bc191c0); + + public static delegate* unmanaged OnDisconnect { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bc18890); + + [FieldOffset(0x0)] + public IS1MemoryObject IS1MemoryObject; + + [FieldOffset(0x0)] + public IS1ConnectionInfo IS1ConnectionInfo; + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; + + [FieldOffset(0x8)] + public IS1ConnectionEventHandler IS1ConnectionEventHandler; + + [FieldOffset(0x8)] + public VirtualFunctionTable_IS1ConnectionEventHandler VFT_IS1ConnectionEventHandler; +} diff --git a/src/interop/S1LauncherEvent.cs b/src/interop/S1LauncherEvent.cs new file mode 100644 index 0000000..67fa535 --- /dev/null +++ b/src/interop/S1LauncherEvent.cs @@ -0,0 +1,47 @@ +namespace Vezel.Novadrop.Interop; + +public enum S1LauncherEvent : uint +{ + S1_LAUNCHER_EVENT_ACCOUNT_NAME_REQUEST = 0x1, + S1_LAUNCHER_EVENT_ACCOUNT_NAME_RESPONSE = 0x2, + S1_LAUNCHER_EVENT_SESSION_TICKET_REQUEST = 0x3, + S1_LAUNCHER_EVENT_SESSION_TICKET_RESPONSE = 0x4, + S1_LAUNCHER_EVENT_SERVER_LIST_REQUEST = 0x5, + S1_LAUNCHER_EVENT_SERVER_LIST_RESPONSE = 0x6, + S1_LAUNCHER_EVENT_ENTER_LOBBY_OR_WORLD_NOTIFICATION = 0x7, + S1_LAUNCHER_EVENT_CREATE_ROOM_REQUEST = 0x8, + S1_LAUNCHER_EVENT_CREATE_ROOM_RESPONSE = 0x9, + S1_LAUNCHER_EVENT_JOIN_ROOM_REQUEST = 0xa, + S1_LAUNCHER_EVENT_JOIN_ROOM_RESPONSE = 0xb, + S1_LAUNCHER_EVENT_LEAVE_ROOM_REQUEST = 0xc, + S1_LAUNCHER_EVENT_LEAVE_ROOM_RESPONSE = 0xd, + S1_LAUNCHER_EVENT_SET_VOLUME_COMMAND = 0x13, + S1_LAUNCHER_EVENT_SET_MICROPHONE_COMMAND = 0x14, + S1_LAUNCHER_EVENT_SILENCE_USER_COMMAND = 0x15, + S1_LAUNCHER_EVENT_OPEN_WEBSITE_COMMAND = 0x19, + S1_LAUNCHER_EVENT_WEB_URL_REQUEST = 0x1a, + S1_LAUNCHER_EVENT_WEB_URL_RESPONSE = 0x1b, + S1_LAUNCHER_EVENT_GAME_START_NOTIFICATION = 0x3e8, + S1_LAUNCHER_EVENT_ENTERED_INTO_CINEMATIC_NOTIFICATION = 0x3e9, + S1_LAUNCHER_EVENT_ENTERED_SERVER_LIST_NOTIFICATION = 0x3ea, + S1_LAUNCHER_EVENT_ENTERING_LOBBY_NOTIFICATION = 0x3eb, + S1_LAUNCHER_EVENT_ENTERED_LOBBY_NOTIFICATION = 0x3ec, + S1_LAUNCHER_EVENT_ENTERING_CHARACTER_CREATION_NOTIFICATION = 0x3ed, + S1_LAUNCHER_EVENT_LEFT_LOBBY_NOTIFICATION = 0x3ee, + S1_LAUNCHER_EVENT_DELETED_CHARACTER_NOTIFICATION = 0x3ef, + S1_LAUNCHER_EVENT_CANCELED_CHARACTER_CREATION_NOTIFICATION = 0x3f0, + S1_LAUNCHER_EVENT_ENTERED_CHARACTER_CREATION_NOTIFICATION = 0x3f1, + S1_LAUNCHER_EVENT_CREATED_CHARACTER_NOTIFICATION = 0x3f2, + S1_LAUNCHER_EVENT_ENTERED_WORLD_NOTIFICATION = 0x3f3, + S1_LAUNCHER_EVENT_FINISHED_LOADING_SCREEN_NOTIFICATION = 0x3f4, + S1_LAUNCHER_EVENT_LEFT_WORLD_NOTIFICATION = 0x3f5, + S1_LAUNCHER_EVENT_MOUNTED_PEGASUS_NOTIFICATION = 0x3f6, + S1_LAUNCHER_EVENT_DISMOUNTED_PEGASUS_NOTIFICATION = 0x3f7, + S1_LAUNCHER_EVENT_CHANGED_CHANNEL_NOTIFICATION = 0x3f8, + S1_LAUNCHER_EVENT_GAME_EXIT_NOTIFICATION = 0x3fc, + S1_LAUNCHER_EVENT_GAME_CRASH_NOTIFICATION = 0x3fd, + S1_LAUNCHER_EVENT_ANTI_CHEAT_STARTING_NOTIFICATION = 0x3fe, + S1_LAUNCHER_EVENT_ANTI_CHEAT_STARTED_NOTIFICATION = 0x3ff, + S1_LAUNCHER_EVENT_ANTI_CHEAT_ERROR_NOTIFICATION = 0x400, + S1_LAUNCHER_EVENT_OPEN_SUPPORT_WEBSITE_COMMAND = 0x401, +} diff --git a/src/interop/S1LauncherProxy.cs b/src/interop/S1LauncherProxy.cs new file mode 100644 index 0000000..1871545 --- /dev/null +++ b/src/interop/S1LauncherProxy.cs @@ -0,0 +1,86 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0xe0)] +public unsafe struct S1LauncherProxy +{ + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcc1ad0); + + public static delegate* unmanaged __dtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcc29d0); + + public static delegate* unmanaged Dispose { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bccc1e0); + + public static delegate* unmanaged HandleAccountNameResponse { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcd9ad0); + + public static delegate* unmanaged HandleCreateRoomResult { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bce7420); + + public static delegate* unmanaged HandleJoinRoomResult { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bce7300); + + public static delegate* unmanaged HandleLeaveRoomResult { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bce7390); + + public static delegate* unmanaged HandleServerListResponse { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcd91c0); + + public static delegate* unmanaged HandleSessionTicketResponse { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcd99e0); + + public static delegate* unmanaged HandleWebUrlResponse { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcd4800); + + public static delegate* unmanaged Initialize { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcd0390); + + public static delegate* unmanaged SendAccountNameRequest { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bccfa90); + + public static delegate* unmanaged SendCrashEvent { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcdea20); + + public static delegate* unmanaged SendEvent { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcdeda0); + + public static delegate* unmanaged SendExitEvent { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcdebb0); + + public static delegate* unmanaged SendGameEvent { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcdecf0); + + public static delegate* unmanaged SendOpenWebsiteCommand { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcd9e60); + + public static delegate* unmanaged SendServerListRequest { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcdd2f0); + + public static delegate* unmanaged*> SendSessionTicketRequest { get; } = + (delegate* unmanaged*>)Tera.Resolve(0x7ff69bccf390); + + public static delegate* unmanaged SendWebUrlRequest { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcd9f80); + + [FieldOffset(0x0)] + public HWND game_window; + + [FieldOffset(0x8)] + public HWND launcher_window; + + [FieldOffset(0x70)] + public BOOL exited; + + [FieldOffset(0x74)] + public FString account_name; + + [FieldOffset(0x88)] + public TArray session_ticket; + + [FieldOffset(0xa0)] + public S1ServerList server_list; +} diff --git a/src/interop/S1LobbySceneServer.cs b/src/interop/S1LobbySceneServer.cs new file mode 100644 index 0000000..9185061 --- /dev/null +++ b/src/interop/S1LobbySceneServer.cs @@ -0,0 +1,50 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x108)] +public unsafe struct S1LobbySceneServer +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public S1SceneBase.VirtualFunctionTable S1SceneBase; + } + + public static delegate* unmanaged __ctor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd26010); + + public static delegate* unmanaged __vdtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd27e00); + + public static delegate* unmanaged OnEnter { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd3b720); + + public static delegate* unmanaged OnExit { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd3b860); + + public static delegate* unmanaged GetName { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd35d90); + + public static new delegate* unmanaged GetType { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd361b0); + + public static delegate* unmanaged SnoopLoginArbiter { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd409c0); + + public static delegate* unmanaged Tick { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd49380); + + [FieldOffset(0x0)] + public IS1MemoryObject IS1MemoryObject; + + [FieldOffset(0x0)] + public S1SceneBase S1SceneBase; + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; + + [FieldOffset(0x8)] + public S1ServerList server_list; +} diff --git a/src/interop/S1SceneBase.cs b/src/interop/S1SceneBase.cs new file mode 100644 index 0000000..59bb3f6 --- /dev/null +++ b/src/interop/S1SceneBase.cs @@ -0,0 +1,31 @@ +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8)] +public unsafe struct S1SceneBase +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public IS1MemoryObject.VirtualFunctionTable IS1MemoryObject; + + public new delegate* unmanaged GetType; + + public delegate* unmanaged GetName; + + public delegate* unmanaged OnEnter; + + public delegate* unmanaged OnExit; + + public delegate* unmanaged Tick; + + public void* __slot7; + + public void* __slot8; + } + + [FieldOffset(0x0)] + public IS1MemoryObject IS1MemoryObject; + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; +} diff --git a/src/interop/S1ServerDataEvent.cs b/src/interop/S1ServerDataEvent.cs new file mode 100644 index 0000000..6f6400f --- /dev/null +++ b/src/interop/S1ServerDataEvent.cs @@ -0,0 +1,23 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x8)] +public unsafe struct S1ServerDataEvent +{ + [StructLayout(LayoutKind.Sequential)] + public struct VirtualFunctionTable + { + public ILauncherEvent.VirtualFunctionTable ILauncherEvent; + } + + public static delegate* unmanaged OnServerList { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bd24dd0); + + [FieldOffset(0x0)] + public ILauncherEvent ILauncherEvent; + + [FieldOffset(0x0)] + public VirtualFunctionTable* VFT; +} diff --git a/src/interop/S1ServerInfo.cs b/src/interop/S1ServerInfo.cs new file mode 100644 index 0000000..8107e86 --- /dev/null +++ b/src/interop/S1ServerInfo.cs @@ -0,0 +1,40 @@ +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x9c)] +public unsafe struct S1ServerInfo +{ + [FieldOffset(0x0)] + public int id; + + [FieldOffset(0x4)] + public FString name; + + [FieldOffset(0x18)] + public FString category; + + [FieldOffset(0x2c)] + public FString title; + + [FieldOffset(0x40)] + public FString queue; + + [FieldOffset(0x54)] + public FString population; + + [FieldOffset(0x68)] + public in_addr address; + + [FieldOffset(0x6c)] + public ushort port; + + [FieldOffset(0x70)] + public BOOL available; + + [FieldOffset(0x74)] + public FString unavailable_message; + + [FieldOffset(0x88)] + public FString host; +} diff --git a/src/interop/S1ServerList.cs b/src/interop/S1ServerList.cs new file mode 100644 index 0000000..3b44599 --- /dev/null +++ b/src/interop/S1ServerList.cs @@ -0,0 +1,22 @@ +using Vezel.Novadrop.Interop.Support; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x18)] +public unsafe struct S1ServerList +{ + public static delegate* unmanaged __dtor { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bcc2500); + + public static delegate* unmanaged Reset { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69bccab30); + + [FieldOffset(0x0)] + public TArray servers; + + [FieldOffset(0x10)] + public int last_server_id; + + [FieldOffset(0x14)] + public S1ServerListSortCriteria sort_criterion; +} diff --git a/src/interop/S1ServerListSortCriteria.cs b/src/interop/S1ServerListSortCriteria.cs new file mode 100644 index 0000000..ffeccc4 --- /dev/null +++ b/src/interop/S1ServerListSortCriteria.cs @@ -0,0 +1,10 @@ +namespace Vezel.Novadrop.Interop; + +public enum S1ServerListSortCriteria +{ + S1_SERVER_LIST_SORTING_NONE = -0x1, + S1_SERVER_LIST_SORTING_CHARACTERS = 0x0, + S1_SERVER_LIST_SORTING_CATEGORY = 0x1, + S1_SERVER_LIST_SORTING_NAME = 0x2, + S1_SERVER_LIST_SORTING_POPULATION = 0x4, +} diff --git a/src/interop/S1Type.cs b/src/interop/S1Type.cs new file mode 100644 index 0000000..e405958 --- /dev/null +++ b/src/interop/S1Type.cs @@ -0,0 +1,17 @@ +using Vezel.Novadrop.Interop.Support; +using Vezel.Novadrop.Interop.System; + +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x10)] +public unsafe struct S1Type +{ + public static delegate* unmanaged IsSubtypeOf { get; } = + (delegate* unmanaged)Tera.Resolve(0x7ff69b4142f0); + + [FieldOffset(0x0)] + public char* name; + + [FieldOffset(0x8)] + public S1Type* @base; +} diff --git a/src/interop/Support/Tera.cs b/src/interop/Support/Tera.cs new file mode 100644 index 0000000..4f20354 --- /dev/null +++ b/src/interop/Support/Tera.cs @@ -0,0 +1,20 @@ +namespace Vezel.Novadrop.Interop.Support; + +public static unsafe class Tera +{ + public delegate void* Resolver(ulong address); + + private static volatile Resolver _resolver = static addr => (void*)addr; + + public static void SetResolver(Resolver resolver) + { + Check.Null(resolver); + + _resolver = resolver; + } + + internal static void* Resolve(ulong address) + { + return _resolver(address); + } +} diff --git a/src/interop/System/BOOL.cs b/src/interop/System/BOOL.cs new file mode 100644 index 0000000..5922476 --- /dev/null +++ b/src/interop/System/BOOL.cs @@ -0,0 +1,65 @@ +namespace Vezel.Novadrop.Interop.System; + +[StructLayout(LayoutKind.Sequential)] +public readonly unsafe struct BOOL : + IEquatable, + IEqualityOperators, + IComparable, + IComparisonOperators +{ + public static BOOL TRUE { get; } = new(1); + + public static BOOL FALSE { get; } = new(0); + + private readonly int _value; + + public BOOL(int value) + { + _value = value; + } + + public static bool operator true(BOOL value) => value; + + public static bool operator false(BOOL value) => !value; + + public static implicit operator BOOL(bool value) => new(value ? 1 : 0); + + public static implicit operator bool(BOOL value) => value._value != 0; + + public static bool operator ==(BOOL left, BOOL right) => left.Equals(right); + + public static bool operator !=(BOOL left, BOOL right) => !left.Equals(right); + + public static bool operator <(BOOL left, BOOL right) => left.CompareTo(right) < 0; + + public static bool operator <=(BOOL left, BOOL right) => left.CompareTo(right) <= 0; + + public static bool operator >(BOOL left, BOOL right) => left.CompareTo(right) > 0; + + public static bool operator >=(BOOL left, BOOL right) => left.CompareTo(right) >= 0; + + public bool Equals(BOOL other) + { + return _value == other._value; + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + return obj is BOOL b && Equals(b); + } + + public int CompareTo(BOOL other) + { + return _value.CompareTo(other._value); + } + + public override int GetHashCode() + { + return HashCode.Combine(_value); + } + + public override string ToString() + { + return this ? "TRUE" : "FALSE"; + } +} diff --git a/src/interop/System/HWND.cs b/src/interop/System/HWND.cs new file mode 100644 index 0000000..319194d --- /dev/null +++ b/src/interop/System/HWND.cs @@ -0,0 +1,59 @@ +namespace Vezel.Novadrop.Interop.System; + +[StructLayout(LayoutKind.Sequential)] +public readonly unsafe struct HWND : + IEquatable, + IEqualityOperators, + IComparable, + IComparisonOperators +{ + public static HWND INVALID_HANDLE_VALUE { get; } = new((void*)-1); + + public static HWND NULL { get; } = new(null); + + private readonly void* _value; + + public HWND(void* value) + { + _value = value; + } + + public static explicit operator void*(HWND value) => value._value; + + public static bool operator ==(HWND left, HWND right) => left.Equals(right); + + public static bool operator !=(HWND left, HWND right) => !left.Equals(right); + + public static bool operator <(HWND left, HWND right) => left.CompareTo(right) < 0; + + public static bool operator <=(HWND left, HWND right) => left.CompareTo(right) <= 0; + + public static bool operator >(HWND left, HWND right) => left.CompareTo(right) > 0; + + public static bool operator >=(HWND left, HWND right) => left.CompareTo(right) >= 0; + + public bool Equals(HWND other) + { + return _value == other._value; + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + return obj is HWND w && Equals(w); + } + + public int CompareTo(HWND other) + { + return ((nuint)_value).CompareTo((nuint)other._value); + } + + public override int GetHashCode() + { + return HashCode.Combine((nuint)_value); + } + + public override string ToString() + { + return $"0x{(nuint)_value:x}"; + } +} diff --git a/src/interop/System/SOCKET.cs b/src/interop/System/SOCKET.cs new file mode 100644 index 0000000..26ebe0b --- /dev/null +++ b/src/interop/System/SOCKET.cs @@ -0,0 +1,57 @@ +namespace Vezel.Novadrop.Interop.System; + +[StructLayout(LayoutKind.Sequential)] +public readonly unsafe struct SOCKET : + IEquatable, + IEqualityOperators, + IComparable, + IComparisonOperators +{ + public static SOCKET INVALID_SOCKET { get; } = new(~0u); + + private readonly ulong _value; + + public SOCKET(ulong value) + { + _value = value; + } + + public static explicit operator ulong(SOCKET value) => value._value; + + public static bool operator ==(SOCKET left, SOCKET right) => left.Equals(right); + + public static bool operator !=(SOCKET left, SOCKET right) => !left.Equals(right); + + public static bool operator <(SOCKET left, SOCKET right) => left.CompareTo(right) < 0; + + public static bool operator <=(SOCKET left, SOCKET right) => left.CompareTo(right) <= 0; + + public static bool operator >(SOCKET left, SOCKET right) => left.CompareTo(right) > 0; + + public static bool operator >=(SOCKET left, SOCKET right) => left.CompareTo(right) >= 0; + + public bool Equals(SOCKET other) + { + return _value == other._value; + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + return obj is SOCKET s && Equals(s); + } + + public int CompareTo(SOCKET other) + { + return _value.CompareTo(other._value); + } + + public override int GetHashCode() + { + return HashCode.Combine(_value); + } + + public override string ToString() + { + return _value.ToString(CultureInfo.InvariantCulture); + } +} diff --git a/src/interop/System/WSAEVENT.cs b/src/interop/System/WSAEVENT.cs new file mode 100644 index 0000000..723c05b --- /dev/null +++ b/src/interop/System/WSAEVENT.cs @@ -0,0 +1,57 @@ +namespace Vezel.Novadrop.Interop.System; + +[StructLayout(LayoutKind.Sequential)] +public readonly unsafe struct WSAEVENT : + IEquatable, + IEqualityOperators, + IComparable, + IComparisonOperators +{ + public static WSAEVENT WSA_INVALID_EVENT { get; } = new(null); + + private readonly void* _value; + + public WSAEVENT(void* value) + { + _value = value; + } + + public static explicit operator void*(WSAEVENT value) => value._value; + + public static bool operator ==(WSAEVENT left, WSAEVENT right) => left.Equals(right); + + public static bool operator !=(WSAEVENT left, WSAEVENT right) => !left.Equals(right); + + public static bool operator <(WSAEVENT left, WSAEVENT right) => left.CompareTo(right) < 0; + + public static bool operator <=(WSAEVENT left, WSAEVENT right) => left.CompareTo(right) <= 0; + + public static bool operator >(WSAEVENT left, WSAEVENT right) => left.CompareTo(right) > 0; + + public static bool operator >=(WSAEVENT left, WSAEVENT right) => left.CompareTo(right) >= 0; + + public bool Equals(WSAEVENT other) + { + return _value == other._value; + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + return obj is WSAEVENT w && Equals(w); + } + + public int CompareTo(WSAEVENT other) + { + return ((nuint)_value).CompareTo((nuint)other._value); + } + + public override int GetHashCode() + { + return HashCode.Combine((nuint)_value); + } + + public override string ToString() + { + return $"0x{(nuint)_value:x}"; + } +} diff --git a/src/interop/System/in_addr.cs b/src/interop/System/in_addr.cs new file mode 100644 index 0000000..2c326d0 --- /dev/null +++ b/src/interop/System/in_addr.cs @@ -0,0 +1,55 @@ +namespace Vezel.Novadrop.Interop.System; + +[StructLayout(LayoutKind.Sequential)] +public readonly unsafe struct in_addr : + IEquatable, + IEqualityOperators, + IComparable, + IComparisonOperators +{ + private readonly uint _value; + + public in_addr(uint value) + { + _value = value; + } + + public static explicit operator uint(in_addr value) => value._value; + + public static bool operator ==(in_addr left, in_addr right) => left.Equals(right); + + public static bool operator !=(in_addr left, in_addr right) => !left.Equals(right); + + public static bool operator <(in_addr left, in_addr right) => left.CompareTo(right) < 0; + + public static bool operator <=(in_addr left, in_addr right) => left.CompareTo(right) <= 0; + + public static bool operator >(in_addr left, in_addr right) => left.CompareTo(right) > 0; + + public static bool operator >=(in_addr left, in_addr right) => left.CompareTo(right) >= 0; + + public bool Equals(in_addr other) + { + return _value == other._value; + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + return obj is in_addr a && Equals(a); + } + + public int CompareTo(in_addr other) + { + return _value.CompareTo(other._value); + } + + public override int GetHashCode() + { + return HashCode.Combine(_value); + } + + public override string ToString() + { + return $"{(byte)_value}.{(byte)(_value >> 8)}.{(byte)(_value >> 16)}.{(byte)(_value >> 24)}"; + } +} diff --git a/src/interop/TArray`1.cs b/src/interop/TArray`1.cs new file mode 100644 index 0000000..0b23403 --- /dev/null +++ b/src/interop/TArray`1.cs @@ -0,0 +1,15 @@ +namespace Vezel.Novadrop.Interop; + +[StructLayout(LayoutKind.Explicit, Size = 0x10)] +public unsafe struct TArray + where T : unmanaged +{ + [FieldOffset(0x0)] + public T* elements; + + [FieldOffset(0x8)] + public int count; + + [FieldOffset(0xc)] + public int capacity; +} diff --git a/src/interop/buildTransitive/Vezel.Novadrop.Interop.targets b/src/interop/buildTransitive/Vezel.Novadrop.Interop.targets index 0cb1f67..001bbae 100644 --- a/src/interop/buildTransitive/Vezel.Novadrop.Interop.targets +++ b/src/interop/buildTransitive/Vezel.Novadrop.Interop.targets @@ -2,5 +2,6 @@ + diff --git a/src/interop/interop.csproj b/src/interop/interop.csproj index 50142b5..babcabc 100644 --- a/src/interop/interop.csproj +++ b/src/interop/interop.csproj @@ -10,6 +10,10 @@ TERA client. Vezel.Novadrop.Interop + + + +