Skip to content

Commit 90de42c

Browse files
author
Not Officer
committed
initial commit
1 parent dfdbac8 commit 90de42c

8 files changed

Lines changed: 314 additions & 0 deletions

File tree

icon.png

258 KB
Loading
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
6+
<IsPackable>false</IsPackable>
7+
</PropertyGroup>
8+
9+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
10+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
11+
<PlatformTarget>x64</PlatformTarget>
12+
</PropertyGroup>
13+
14+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
15+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
16+
<PlatformTarget>x64</PlatformTarget>
17+
</PropertyGroup>
18+
19+
<ItemGroup>
20+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
21+
<PackageReference Include="xunit" Version="2.4.1" />
22+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
23+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24+
<PrivateAssets>all</PrivateAssets>
25+
</PackageReference>
26+
<PackageReference Include="coverlet.collector" Version="3.0.3">
27+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
28+
<PrivateAssets>all</PrivateAssets>
29+
</PackageReference>
30+
</ItemGroup>
31+
32+
<ItemGroup>
33+
<ProjectReference Include="..\Oodle.NET\Oodle.NET.csproj" />
34+
</ItemGroup>
35+
36+
</Project>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Text;
3+
4+
using Xunit;
5+
6+
namespace Oodle.NET.Tests
7+
{
8+
public class OodleCompressorTests
9+
{
10+
private readonly OodleCompressor _oodle;
11+
12+
public OodleCompressorTests()
13+
{
14+
_oodle = new OodleCompressor(@"C:\Games\Fortnite\FortniteGame\Binaries\Win64\oo2core_5_win64.dll");
15+
}
16+
17+
[Fact]
18+
public unsafe void CompressAndDecompress()
19+
{
20+
const OodleLZ_Compressor compressor = OodleLZ_Compressor.Kraken;
21+
var encoding = new ASCIIEncoding();
22+
var randomString = GetRandomString(0xFFF);
23+
var randomStringBuffer = encoding.GetBytes(randomString);
24+
25+
//var memorySizeNeeded = OodleCompressor.GetCompressionBound((uint)randomStringBuffer.Length);
26+
var memorySizeNeeded = _oodle.MemorySizeNeeded(compressor, randomStringBuffer.Length);
27+
Assert.NotEqual(0L, memorySizeNeeded);
28+
29+
var compressedBuffer = new byte[memorySizeNeeded];
30+
var compressedCount = _oodle.Compress(compressor, randomStringBuffer, randomStringBuffer.Length, compressedBuffer, OodleLZ_CompressionLevel.Normal, 0L, 0L, 0L, 0L, 0L);
31+
Assert.NotEqual(0L, compressedCount);
32+
33+
var decompressedBuffer = new byte[randomStringBuffer.Length];
34+
var decompressedCount = _oodle.Decompress(compressedBuffer, compressedCount, decompressedBuffer, decompressedBuffer.Length, OodleLZ_FuzzSafe.No, OodleLZ_CheckCRC.No, OodleLZ_Verbosity.None, 0L, 0L, 0L, 0L, 0L, 0L, OodleLZ_Decode_ThreadPhase.Unthreaded);
35+
Assert.NotEqual(0L, decompressedCount);
36+
37+
var decompressedRandomString = encoding.GetString(decompressedBuffer);
38+
39+
Assert.Equal((int)decompressedCount, randomStringBuffer.Length);
40+
Assert.Equal(randomString, decompressedRandomString);
41+
}
42+
43+
private static string GetRandomString(int length)
44+
{
45+
const string chars = "0123456789ABCDEF";
46+
var stringChars = new char[length];
47+
var random = new Random();
48+
49+
for (var i = 0; i < stringChars.Length; i++)
50+
{
51+
stringChars[i] = chars[random.Next(chars.Length)];
52+
}
53+
54+
return new string(stringChars);
55+
}
56+
}
57+
}

src/Oodle.NET.sln

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.31112.23
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Oodle.NET", "Oodle.NET\Oodle.NET.csproj", "{AFF75C15-8DFA-454A-B24B-09F19BE68559}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Oodle.NET.Tests", "Oodle.NET.Tests\Oodle.NET.Tests.csproj", "{0482F51C-6992-49AD-90AC-A4689FA32C52}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{AFF75C15-8DFA-454A-B24B-09F19BE68559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{AFF75C15-8DFA-454A-B24B-09F19BE68559}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{AFF75C15-8DFA-454A-B24B-09F19BE68559}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{AFF75C15-8DFA-454A-B24B-09F19BE68559}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{0482F51C-6992-49AD-90AC-A4689FA32C52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{0482F51C-6992-49AD-90AC-A4689FA32C52}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{0482F51C-6992-49AD-90AC-A4689FA32C52}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{0482F51C-6992-49AD-90AC-A4689FA32C52}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {A3254214-0CAC-436D-8F0B-0E5A89201113}
30+
EndGlobalSection
31+
EndGlobal

src/Oodle.NET/Oodle.NET.csproj

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net5.0;netcoreapp3.1</TargetFrameworks>
5+
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
6+
<Authors>NotOfficer</Authors>
7+
<Description>A .NET wrapper for Oodle</Description>
8+
<Company>NotOfficer</Company>
9+
<Copyright>Copyright (c) 2021 NotOfficer</Copyright>
10+
<PackageLicenseFile>LICENSE</PackageLicenseFile>
11+
<PackageProjectUrl>https://github.com/NotOfficer/Oodle.NET</PackageProjectUrl>
12+
<RepositoryUrl>https://github.com/NotOfficer/Oodle.NET</RepositoryUrl>
13+
<RepositoryType>git</RepositoryType>
14+
<PackageIcon>icon.png</PackageIcon>
15+
<PackageTags>oodle, decompress, compress</PackageTags>
16+
</PropertyGroup>
17+
18+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
19+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
20+
<PlatformTarget>x64</PlatformTarget>
21+
</PropertyGroup>
22+
23+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
24+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
25+
<PlatformTarget>x64</PlatformTarget>
26+
</PropertyGroup>
27+
28+
<ItemGroup>
29+
<None Include="..\..\icon.png">
30+
<Pack>True</Pack>
31+
<PackagePath></PackagePath>
32+
</None>
33+
<None Include="..\..\LICENSE">
34+
<Pack>True</Pack>
35+
<PackagePath></PackagePath>
36+
</None>
37+
</ItemGroup>
38+
39+
</Project>

src/Oodle.NET/OodleCompressor.cs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Runtime.InteropServices;
4+
5+
namespace Oodle.NET
6+
{
7+
#if NET5_0_OR_GREATER
8+
public unsafe class OodleCompressor : IDisposable
9+
#else
10+
public class OodleCompressor : IDisposable
11+
#endif
12+
{
13+
private readonly IntPtr _handle;
14+
15+
#if NET5_0_OR_GREATER
16+
public readonly delegate* unmanaged[Cdecl]<OodleLZ_Compressor, byte[], long, byte[], OodleLZ_CompressionLevel, long, long, long, long, long, long> Compress;
17+
public readonly delegate* unmanaged[Cdecl]<byte[], long, byte[], long, OodleLZ_FuzzSafe, OodleLZ_CheckCRC, OodleLZ_Verbosity, long, long, long, long, long, long, OodleLZ_Decode_ThreadPhase, long> Decompress;
18+
public readonly delegate* unmanaged[Cdecl]<OodleLZ_Compressor, long, long> MemorySizeNeeded;
19+
#else
20+
public delegate long OodleLZ_Compress(OodleLZ_Compressor compressor, byte[] src, long src_size, byte[] dst, OodleLZ_CompressionLevel level, long opts, long context, long unused, long scratch, long scratch_size);
21+
public readonly OodleLZ_Compress Compress;
22+
23+
public delegate long OodleLZ_Decompress(byte[] src, long src_size, byte[] dst, long dst_size, OodleLZ_FuzzSafe fuzz, OodleLZ_CheckCRC crc, OodleLZ_Verbosity verbosity, long context, long e, long callback, long callback_ctx, long scratch, long scratch_size, OodleLZ_Decode_ThreadPhase thread_phase);
24+
public readonly OodleLZ_Decompress Decompress;
25+
26+
public delegate long OodleLZDecoder_MemorySizeNeeded(OodleLZ_Compressor compressor, long size);
27+
public readonly OodleLZDecoder_MemorySizeNeeded MemorySizeNeeded;
28+
#endif
29+
30+
public OodleCompressor(string libraryPath, Assembly assembly, DllImportSearchPath? searchPath = null) : this(NativeLibrary.Load(libraryPath, assembly, searchPath)) { }
31+
public OodleCompressor(string libraryPath) : this(NativeLibrary.Load(libraryPath)) { }
32+
public OodleCompressor(IntPtr handle)
33+
{
34+
if (handle == IntPtr.Zero)
35+
{
36+
throw new ArgumentOutOfRangeException(nameof(handle), $"Failed to initialize {nameof(OodleCompressor)}");
37+
}
38+
39+
_handle = handle;
40+
var compressAddress = NativeLibrary.GetExport(_handle, "OodleLZ_Compress");
41+
var decompressAddress = NativeLibrary.GetExport(_handle, "OodleLZ_Decompress");
42+
var memorySizeNeededAddress = NativeLibrary.GetExport(_handle, "OodleLZDecoder_MemorySizeNeeded");
43+
44+
#if NET5_0_OR_GREATER
45+
Compress = (delegate* unmanaged[Cdecl]<OodleLZ_Compressor, byte[], long, byte[], OodleLZ_CompressionLevel, long, long, long, long, long, long>)compressAddress;
46+
Decompress = (delegate* unmanaged[Cdecl]<byte[], long, byte[], long, OodleLZ_FuzzSafe, OodleLZ_CheckCRC, OodleLZ_Verbosity, long, long, long, long, long, long, OodleLZ_Decode_ThreadPhase, long>)decompressAddress;
47+
MemorySizeNeeded = (delegate* unmanaged[Cdecl]<OodleLZ_Compressor, long, long>)memorySizeNeededAddress;
48+
#else
49+
Compress = Marshal.GetDelegateForFunctionPointer<OodleLZ_Compress>(compressAddress);
50+
Decompress = Marshal.GetDelegateForFunctionPointer<OodleLZ_Decompress>(decompressAddress);
51+
MemorySizeNeeded = Marshal.GetDelegateForFunctionPointer<OodleLZDecoder_MemorySizeNeeded>(memorySizeNeededAddress);
52+
#endif
53+
}
54+
55+
public static uint GetCompressionBound(uint bufferSize)
56+
{
57+
return bufferSize + 274 * ((bufferSize + 0x3FFFF) / 0x40000);
58+
}
59+
60+
protected virtual void Dispose(bool disposing)
61+
{
62+
if (!disposing)
63+
{
64+
return;
65+
}
66+
67+
if (_handle != IntPtr.Zero)
68+
{
69+
NativeLibrary.Free(_handle);
70+
}
71+
}
72+
73+
public void Dispose()
74+
{
75+
Dispose(true);
76+
GC.SuppressFinalize(this);
77+
}
78+
}
79+
80+
public enum OodleLZ_FuzzSafe
81+
{
82+
No,
83+
Yes
84+
}
85+
86+
public enum OodleLZ_CheckCRC
87+
{
88+
No,
89+
Yes
90+
}
91+
92+
public enum OodleLZ_Verbosity
93+
{
94+
None,
95+
Max = 3
96+
}
97+
98+
public enum OodleLZ_Decode_ThreadPhase
99+
{
100+
ThreadPhase1 = 0x1,
101+
ThreadPhase2 = 0x2,
102+
103+
Unthreaded = ThreadPhase1 | ThreadPhase2
104+
}
105+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace Oodle.NET
2+
{
3+
public enum OodleLZ_CompressionLevel
4+
{
5+
HyperFast4 = -4,
6+
HyperFast3,
7+
HyperFast2,
8+
HyperFast1,
9+
None,
10+
SuperFast,
11+
VeryFast,
12+
Fast,
13+
Normal,
14+
Optimal1,
15+
Optimal2,
16+
Optimal3,
17+
Optimal4,
18+
Optimal5,
19+
// TooHigh,
20+
21+
Min = HyperFast4,
22+
Max = Optimal5
23+
}
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace Oodle.NET
2+
{
3+
public enum OodleLZ_Compressor
4+
{
5+
Invalid = -1,
6+
7+
LZH,
8+
LZHLW,
9+
LZNIB,
10+
None,
11+
LZB16,
12+
LZBLW,
13+
LZA,
14+
LZNA,
15+
Kraken,
16+
Mermaid,
17+
BitKnit,
18+
Selkie,
19+
Hydra,
20+
Leviathan
21+
}
22+
}

0 commit comments

Comments
 (0)