mirror of
https://github.com/4sval/FModel.git
synced 2026-03-22 01:34:37 -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="Extended.Wpf.Toolkit" Version="4.0.1" />
|
||||
<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="NVorbis" Version="0.10.1" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="1.1.0" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using FModel.Utils;
|
||||
|
||||
namespace PakReader.Parsers
|
||||
{
|
||||
|
|
@ -14,17 +15,13 @@ namespace PakReader.Parsers
|
|||
|
||||
public OodleStream(byte[] input, long decompressedLength)
|
||||
{
|
||||
Oodle.LoadOodleDll();
|
||||
_baseStream = new MemoryStream(Decompress(input, decompressedLength), false)
|
||||
{
|
||||
Position = 0
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Oodle Library Path
|
||||
/// </summary>
|
||||
private const string OodleLibraryPath = "oo2core_5_win64";
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
|
|
@ -45,7 +42,7 @@ namespace PakReader.Parsers
|
|||
/// <summary>
|
||||
/// Oodle64 Decompression Method
|
||||
/// </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);
|
||||
|
||||
/// <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