mirror of
https://github.com/4sval/FModel.git
synced 2026-04-25 07:21:54 -05:00
automatic downloading of oodle dll if needed
This commit is contained in:
parent
aeded745cf
commit
f2d990e2ff
|
|
@ -136,6 +136,7 @@
|
||||||
<PackageReference Include="DotNetZip" Version="1.13.8" />
|
<PackageReference Include="DotNetZip" Version="1.13.8" />
|
||||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.0.1" />
|
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.0.1" />
|
||||||
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.1.11" />
|
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.1.11" />
|
||||||
|
<PackageReference Include="LZMA-SDK" Version="19.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="NVorbis" Version="0.10.1" />
|
<PackageReference Include="NVorbis" Version="0.10.1" />
|
||||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="1.1.0" />
|
<PackageReference Include="Ookii.Dialogs.Wpf" Version="1.1.0" />
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using FModel.Utils;
|
||||||
|
|
||||||
namespace PakReader.Parsers
|
namespace PakReader.Parsers
|
||||||
{
|
{
|
||||||
|
|
@ -14,17 +15,13 @@ namespace PakReader.Parsers
|
||||||
|
|
||||||
public OodleStream(byte[] input, long decompressedLength)
|
public OodleStream(byte[] input, long decompressedLength)
|
||||||
{
|
{
|
||||||
|
Oodle.LoadOodleDll();
|
||||||
_baseStream = new MemoryStream(Decompress(input, decompressedLength), false)
|
_baseStream = new MemoryStream(Decompress(input, decompressedLength), false)
|
||||||
{
|
{
|
||||||
Position = 0
|
Position = 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Oodle Library Path
|
|
||||||
/// </summary>
|
|
||||||
private const string OodleLibraryPath = "oo2core_5_win64";
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -45,7 +42,7 @@ namespace PakReader.Parsers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Oodle64 Decompression Method
|
/// Oodle64 Decompression Method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DllImport(OodleLibraryPath, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(Oodle.OODLE_DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||||
private static extern long OodleLZ_Decompress(byte[] buffer, long bufferSize, byte[] result, long outputBufferSize, int a, int b, int c, long d, long e, long f, long g, long h, long i, int ThreadModule);
|
private static extern long OodleLZ_Decompress(byte[] buffer, long bufferSize, byte[] result, long outputBufferSize, int a, int b, int c, long d, long e, long f, long g, long h, long i, int ThreadModule);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
74
FModel/Utils/Oodle.cs
Normal file
74
FModel/Utils/Oodle.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FModel.Logger;
|
||||||
|
|
||||||
|
namespace FModel.Utils
|
||||||
|
{
|
||||||
|
public static class Oodle
|
||||||
|
{
|
||||||
|
private const string WARFRAME_CDN_HOST = "https://origin.warframe.com";
|
||||||
|
private const string WARFRAME_INDEX_PATH = "/origin/E926E926/index.txt.lzma";
|
||||||
|
private const string WARFRAME_INDEX_URL = WARFRAME_CDN_HOST + WARFRAME_INDEX_PATH;
|
||||||
|
public const string OODLE_DLL_NAME = "oo2core_8_win64.dll";
|
||||||
|
|
||||||
|
public static bool LoadOodleDll()
|
||||||
|
{
|
||||||
|
if (File.Exists(OODLE_DLL_NAME))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return DownloadOodleDll().Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<bool> DownloadOodleDll()
|
||||||
|
{
|
||||||
|
using var client = new HttpClient {Timeout = TimeSpan.FromSeconds(2)};
|
||||||
|
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get,
|
||||||
|
new Uri(WARFRAME_INDEX_URL));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var httpResponseMessage = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||||
|
var lzma = await httpResponseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
|
||||||
|
var input = new MemoryStream(lzma);
|
||||||
|
var output = new MemoryStream();
|
||||||
|
LZMA.Decompress(input, output);
|
||||||
|
output.Position = 0;
|
||||||
|
using var reader = new StreamReader(output);
|
||||||
|
string line, dllUrl = null;
|
||||||
|
while ((line = reader.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
if (line.Contains(OODLE_DLL_NAME))
|
||||||
|
{
|
||||||
|
dllUrl = WARFRAME_CDN_HOST + line.Substring(0, line.IndexOf(','));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dllUrl == null)
|
||||||
|
{
|
||||||
|
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Oodle]", "Warframe index did not contain oodle dll");
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var dllRequest = new HttpRequestMessage(HttpMethod.Get, new Uri(dllUrl));
|
||||||
|
using var dllResponse = await client.SendAsync(dllRequest, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||||
|
var dllLzma = await dllResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
|
||||||
|
input = new MemoryStream(dllLzma);
|
||||||
|
output = new MemoryStream();
|
||||||
|
LZMA.Decompress(input, output);
|
||||||
|
output.Position = 0;
|
||||||
|
await File.WriteAllBytesAsync(OODLE_DLL_NAME, output.ToArray()).ConfigureAwait(false);
|
||||||
|
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Oodle]", "Successfully downloaded oodle dll");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Oodle]", $"Uncaught exception while downloading oodle dll: {e.GetType()}: {e.Message}");
|
||||||
|
/* TaskCanceledException
|
||||||
|
* HttpRequestException */
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
119
FModel/Utils/SevenZipHelper.cs
Normal file
119
FModel/Utils/SevenZipHelper.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
|
||||||
|
// https://gist.github.com/ststeiger/cb9750664952f775a341#gistcomment-2912797
|
||||||
|
namespace FModel.Utils
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using SevenZip;
|
||||||
|
using SevenZip.Compression.LZMA;
|
||||||
|
|
||||||
|
public enum LzmaSpeed
|
||||||
|
{
|
||||||
|
Fastest = 5,
|
||||||
|
VeryFast = 8,
|
||||||
|
Fast = 16,
|
||||||
|
Medium = 32,
|
||||||
|
Slow = 64,
|
||||||
|
VerySlow = 128,
|
||||||
|
}
|
||||||
|
public enum DictionarySize
|
||||||
|
{
|
||||||
|
///<summary>64 KiB</summary>
|
||||||
|
VerySmall = 1 << 16,
|
||||||
|
///<summary>1 MiB</summary>
|
||||||
|
Small = 1 << 20,
|
||||||
|
///<summary>4 MiB</summary>
|
||||||
|
Medium = 1 << 22,
|
||||||
|
///<summary>8 MiB</summary>
|
||||||
|
Large = 1 << 23,
|
||||||
|
///<summary>16 MiB</summary>
|
||||||
|
Larger = 1 << 24,
|
||||||
|
///<summary>64 MiB</summary>
|
||||||
|
VeryLarge = 1 << 26,
|
||||||
|
}
|
||||||
|
public static class LZMA
|
||||||
|
{
|
||||||
|
public static void Compress(Stream input, Stream output, LzmaSpeed speed = LzmaSpeed.Fastest, DictionarySize dictionarySize = DictionarySize.VerySmall, Action<long, long> onProgress = null)
|
||||||
|
{
|
||||||
|
int posStateBits = 2; // default: 2
|
||||||
|
int litContextBits = 3; // 3 for normal files, 0; for 32-bit data
|
||||||
|
int litPosBits = 0; // 0 for 64-bit data, 2 for 32-bit.
|
||||||
|
var numFastBytes = (int)speed;
|
||||||
|
string matchFinder = "BT4"; // default: BT4
|
||||||
|
bool endMarker = true;
|
||||||
|
|
||||||
|
CoderPropID[] propIDs =
|
||||||
|
{
|
||||||
|
CoderPropID.DictionarySize,
|
||||||
|
CoderPropID.PosStateBits, // (0 <= x <= 4).
|
||||||
|
CoderPropID.LitContextBits, // (0 <= x <= 8).
|
||||||
|
CoderPropID.LitPosBits, // (0 <= x <= 4).
|
||||||
|
CoderPropID.NumFastBytes,
|
||||||
|
CoderPropID.MatchFinder, // "BT2", "BT4".
|
||||||
|
CoderPropID.EndMarker
|
||||||
|
};
|
||||||
|
|
||||||
|
object[] properties =
|
||||||
|
{
|
||||||
|
(int)dictionarySize,
|
||||||
|
posStateBits,
|
||||||
|
litContextBits,
|
||||||
|
litPosBits,
|
||||||
|
numFastBytes,
|
||||||
|
matchFinder,
|
||||||
|
endMarker
|
||||||
|
};
|
||||||
|
|
||||||
|
var lzmaEncoder = new Encoder();
|
||||||
|
|
||||||
|
lzmaEncoder.SetCoderProperties(propIDs, properties);
|
||||||
|
lzmaEncoder.WriteCoderProperties(output);
|
||||||
|
var fileSize = input.Length;
|
||||||
|
for (int i = 0; i < 8; i++) output.WriteByte((byte)(fileSize >> (8 * i)));
|
||||||
|
|
||||||
|
ICodeProgress prg = null;
|
||||||
|
if (onProgress != null)
|
||||||
|
{
|
||||||
|
prg = new DelegateCodeProgress(onProgress);
|
||||||
|
}
|
||||||
|
lzmaEncoder.Code(input, output, -1, -1, prg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Decompress(Stream input, Stream output, Action<long, long>? onProgress = null)
|
||||||
|
{
|
||||||
|
var decoder = new Decoder();
|
||||||
|
|
||||||
|
byte[] properties = new byte[5];
|
||||||
|
if (input.Read(properties, 0, 5) != 5)
|
||||||
|
{
|
||||||
|
throw new Exception("input .lzma is too short");
|
||||||
|
}
|
||||||
|
decoder.SetDecoderProperties(properties);
|
||||||
|
|
||||||
|
long fileLength = 0;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
int v = input.ReadByte();
|
||||||
|
if (v < 0) throw new Exception("Can't Read 1");
|
||||||
|
fileLength |= ((long)(byte)v) << (8 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ICodeProgress prg = null;
|
||||||
|
if (onProgress != null)
|
||||||
|
{
|
||||||
|
prg = new DelegateCodeProgress(onProgress);
|
||||||
|
}
|
||||||
|
long compressedSize = input.Length - input.Position;
|
||||||
|
|
||||||
|
decoder.Code(input, output, compressedSize, fileLength, prg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DelegateCodeProgress : ICodeProgress
|
||||||
|
{
|
||||||
|
private readonly Action<long, long> _handler;
|
||||||
|
public DelegateCodeProgress(Action<long, long> handler) => this._handler = handler;
|
||||||
|
public void SetProgress(long inSize, long outSize) => _handler(inSize, outSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user