mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-08 22:13:30 +08:00
Work in progress
This commit is contained in:
@@ -26,8 +26,8 @@ public class CompressSave : BaseUnityPlugin
|
|||||||
{
|
{
|
||||||
case CompressionType.LZ4: return "lz4";
|
case CompressionType.LZ4: return "lz4";
|
||||||
case CompressionType.Zstd: return "zstd";
|
case CompressionType.Zstd: return "zstd";
|
||||||
case CompressionType.None:
|
case CompressionType.None: return "none";
|
||||||
default: return "none";
|
default: throw new ArgumentException("Unknown compression type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ public class CompressSave : BaseUnityPlugin
|
|||||||
{
|
{
|
||||||
PatchSave.CompressionTypeForSaves = CompressionTypeFromString(
|
PatchSave.CompressionTypeForSaves = CompressionTypeFromString(
|
||||||
Config.Bind("Compression", "Type", StringFromCompresstionType(PatchSave.CompressionTypeForSaves),
|
Config.Bind("Compression", "Type", StringFromCompresstionType(PatchSave.CompressionTypeForSaves),
|
||||||
new ConfigDescription("Set default compression type.",
|
new ConfigDescription("Set default compression type for manual saves.",
|
||||||
new AcceptableValueList<string>("lz4", "zstd", "none"), new { }))
|
new AcceptableValueList<string>("lz4", "zstd", "none"), new { }))
|
||||||
.Value);
|
.Value);
|
||||||
PatchSave.CompressionLevelForSaves = Config.Bind("Compression", "Level", PatchSave.CompressionLevelForSaves,
|
PatchSave.CompressionLevelForSaves = Config.Bind("Compression", "Level", PatchSave.CompressionLevelForSaves,
|
||||||
@@ -62,7 +62,7 @@ public class CompressSave : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
patchSave = Harmony.CreateAndPatchAll(typeof(PatchSave));
|
patchSave = Harmony.CreateAndPatchAll(typeof(PatchSave));
|
||||||
if (PatchSave.EnableCompress && PatchSave.CompressionTypeForSaves != CompressionType.None)
|
if (PatchSave.EnableCompress)
|
||||||
patchUISave = Harmony.CreateAndPatchAll(typeof(PatchUISaveGame));
|
patchUISave = Harmony.CreateAndPatchAll(typeof(PatchUISaveGame));
|
||||||
patchUILoad = Harmony.CreateAndPatchAll(typeof(PatchUILoadGame));
|
patchUILoad = Harmony.CreateAndPatchAll(typeof(PatchUILoadGame));
|
||||||
}
|
}
|
||||||
@@ -88,36 +88,51 @@ public class CompressSave : BaseUnityPlugin
|
|||||||
|
|
||||||
class PatchSave
|
class PatchSave
|
||||||
{
|
{
|
||||||
public static readonly WrapperDefines LZ4Wrapper = new LZ4API(), ZstdWrapper = new ZstdAPI();
|
public static readonly WrapperDefines LZ4Wrapper = new LZ4API(), ZstdWrapper = new ZstdAPI(), NoneWrapper = new NoneAPI();
|
||||||
private const long SizeInMBytes = 1024 * 1024;
|
private const long SizeInMBytes = 1024 * 1024;
|
||||||
private static CompressionStream.CompressBuffer _compressBuffer;
|
private static CompressionStream.CompressBuffer _compressBuffer;
|
||||||
public static bool UseCompressSave;
|
public static bool UseCompressSave;
|
||||||
private static CompressionType _compressedType = CompressionType.None;
|
private static CompressionType _compressionTypeForLoading = CompressionType.None;
|
||||||
public static CompressionType CompressionTypeForSaves = CompressionType.LZ4;
|
public static CompressionType CompressionTypeForSaves = CompressionType.Zstd;
|
||||||
public static int CompressionLevelForSaves;
|
public static int CompressionLevelForSaves;
|
||||||
private static Stream _compressionStream;
|
private static Stream _compressionStream;
|
||||||
public static bool EnableCompress;
|
public static bool EnableCompress;
|
||||||
|
|
||||||
public static void CreateCompressBuffer()
|
public static void CreateCompressBuffer()
|
||||||
{
|
{
|
||||||
_compressBuffer =
|
switch (CompressionTypeForSaves)
|
||||||
CompressionStream.CreateBuffer(CompressionTypeForSaves == CompressionType.LZ4 ? LZ4Wrapper : ZstdWrapper,
|
{
|
||||||
(int)SizeInMBytes); //Bigger buffer for GS2 compatible
|
case CompressionType.LZ4:
|
||||||
|
_compressBuffer = CompressionStream.CreateBuffer(LZ4Wrapper, (int)SizeInMBytes);
|
||||||
|
break;
|
||||||
|
case CompressionType.Zstd:
|
||||||
|
_compressBuffer = CompressionStream.CreateBuffer(ZstdWrapper, (int)SizeInMBytes);
|
||||||
|
break;
|
||||||
|
case CompressionType.None:
|
||||||
|
_compressBuffer = CompressionStream.CreateBuffer(NoneWrapper, (int)SizeInMBytes);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unknown compression type.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteHeader(FileStream fileStream)
|
private static void WriteHeader(FileStream fileStream)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
fileStream.WriteByte(0xCC);
|
|
||||||
switch (CompressionTypeForSaves)
|
switch (CompressionTypeForSaves)
|
||||||
{
|
{
|
||||||
case CompressionType.Zstd:
|
case CompressionType.Zstd:
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
fileStream.WriteByte(0xCC);
|
||||||
fileStream.WriteByte(0xCD);
|
fileStream.WriteByte(0xCD);
|
||||||
break;
|
break;
|
||||||
case CompressionType.LZ4:
|
case CompressionType.LZ4:
|
||||||
default:
|
for (int i = 0; i < 4; i++)
|
||||||
fileStream.WriteByte(0xCC);
|
fileStream.WriteByte(0xCC);
|
||||||
break;
|
break;
|
||||||
|
case CompressionType.None:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unknown compression type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +141,7 @@ class PatchSave
|
|||||||
[HarmonyPatch(typeof(GameSave), "SaveAsLastExit")]
|
[HarmonyPatch(typeof(GameSave), "SaveAsLastExit")]
|
||||||
static void BeforeAutoSave()
|
static void BeforeAutoSave()
|
||||||
{
|
{
|
||||||
UseCompressSave = EnableCompress && CompressionTypeForSaves != CompressionType.None;
|
UseCompressSave = EnableCompress;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
@@ -160,7 +175,7 @@ class PatchSave
|
|||||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IDisposable), "Dispose")))
|
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IDisposable), "Dispose")))
|
||||||
.Advance(1)
|
.Advance(1)
|
||||||
.Insert(new CodeInstruction(OpCodes.Call,
|
.Insert(new CodeInstruction(OpCodes.Call,
|
||||||
AccessTools.Method(typeof(PatchSave), "DisposecompressionStream")));
|
AccessTools.Method(typeof(PatchSave), "DisposeCompressionStream")));
|
||||||
EnableCompress = true;
|
EnableCompress = true;
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
@@ -185,9 +200,19 @@ class PatchSave
|
|||||||
{
|
{
|
||||||
SaveUtil.logger.LogDebug("Begin compress save");
|
SaveUtil.logger.LogDebug("Begin compress save");
|
||||||
WriteHeader(fileStream);
|
WriteHeader(fileStream);
|
||||||
_compressionStream =
|
switch (CompressionTypeForSaves)
|
||||||
new CompressionStream(CompressionTypeForSaves == CompressionType.LZ4 ? LZ4Wrapper : ZstdWrapper,
|
{
|
||||||
CompressionLevelForSaves, fileStream, _compressBuffer, true); //need to dispose after use
|
case CompressionType.LZ4:
|
||||||
|
_compressionStream = new CompressionStream(LZ4Wrapper, CompressionLevelForSaves, fileStream, _compressBuffer, true);
|
||||||
|
break;
|
||||||
|
case CompressionType.Zstd:
|
||||||
|
_compressionStream = new CompressionStream(ZstdWrapper, CompressionLevelForSaves, fileStream, _compressBuffer, true);
|
||||||
|
break;
|
||||||
|
case CompressionType.None:
|
||||||
|
_compressionStream = new CompressionStream(NoneWrapper, 0, fileStream, _compressBuffer, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return ((CompressionStream)_compressionStream).BufferWriter;
|
return ((CompressionStream)_compressionStream).BufferWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,24 +223,49 @@ class PatchSave
|
|||||||
public static long FileLengthWrite0(FileStream fileStream, long offset, SeekOrigin origin)
|
public static long FileLengthWrite0(FileStream fileStream, long offset, SeekOrigin origin)
|
||||||
{
|
{
|
||||||
if (!UseCompressSave)
|
if (!UseCompressSave)
|
||||||
|
{
|
||||||
return fileStream.Seek(offset, origin);
|
return fileStream.Seek(offset, origin);
|
||||||
|
}
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FileLengthWrite1(BinaryWriter binaryWriter, long value)
|
public static void FileLengthWrite1(BinaryWriter binaryWriter, long value)
|
||||||
{
|
{
|
||||||
if (!UseCompressSave)
|
if (!UseCompressSave)
|
||||||
|
{
|
||||||
binaryWriter.Write(value);
|
binaryWriter.Write(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DisposecompressionStream()
|
public static void DisposeCompressionStream()
|
||||||
{
|
{
|
||||||
if (!UseCompressSave) return;
|
if (!UseCompressSave) return;
|
||||||
|
if (_compressionStream == null)
|
||||||
|
{
|
||||||
|
UseCompressSave = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
var writeflag = _compressionStream.CanWrite;
|
var writeflag = _compressionStream.CanWrite;
|
||||||
_compressionStream?.Dispose(); //Dispose need to be done before fstream closed.
|
Stream stream = null;
|
||||||
|
if (writeflag && CompressionTypeForSaves == CompressionType.None)
|
||||||
|
{
|
||||||
|
stream = ((CompressionStream)_compressionStream).outStream;
|
||||||
|
}
|
||||||
|
_compressionStream.Dispose(); //Dispose need to be done before fstream closed.
|
||||||
_compressionStream = null;
|
_compressionStream = null;
|
||||||
if (writeflag) //Reset UseCompressSave after writing to file
|
if (writeflag) //Reset UseCompressSave after writing to file
|
||||||
|
{
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
// Ugly implementation, but it works. May find a better solution someday.
|
||||||
|
var saveLen = stream.Seek(0L, SeekOrigin.End);
|
||||||
|
stream.Seek(6L, SeekOrigin.Begin);
|
||||||
|
var writer = new BinaryWriter(stream);
|
||||||
|
writer.Write(saveLen);
|
||||||
|
writer.Dispose();
|
||||||
|
}
|
||||||
UseCompressSave = false;
|
UseCompressSave = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
@@ -253,7 +303,7 @@ class PatchSave
|
|||||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IDisposable), "Dispose")))
|
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IDisposable), "Dispose")))
|
||||||
.Advance(1)
|
.Advance(1)
|
||||||
.Insert(new CodeInstruction(OpCodes.Call,
|
.Insert(new CodeInstruction(OpCodes.Call,
|
||||||
AccessTools.Method(typeof(PatchSave), "DisposecompressionStream")))
|
AccessTools.Method(typeof(PatchSave), "DisposeCompressionStream")))
|
||||||
.MatchBack(false,
|
.MatchBack(false,
|
||||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IO.Stream), "Seek")));
|
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IO.Stream), "Seek")));
|
||||||
if (matcher.IsValid)
|
if (matcher.IsValid)
|
||||||
@@ -273,14 +323,15 @@ class PatchSave
|
|||||||
|
|
||||||
public static BinaryReader CreateBinaryReader(FileStream fileStream)
|
public static BinaryReader CreateBinaryReader(FileStream fileStream)
|
||||||
{
|
{
|
||||||
switch (_compressedType = SaveUtil.SaveGetCompressType(fileStream))
|
switch (_compressionTypeForLoading = SaveUtil.SaveGetCompressType(fileStream))
|
||||||
{
|
{
|
||||||
case CompressionType.LZ4:
|
case CompressionType.LZ4:
|
||||||
|
UseCompressSave = true;
|
||||||
|
_compressionStream = new DecompressionStream(LZ4Wrapper, fileStream);
|
||||||
|
return new PeekableReader((DecompressionStream)_compressionStream);
|
||||||
case CompressionType.Zstd:
|
case CompressionType.Zstd:
|
||||||
UseCompressSave = true;
|
UseCompressSave = true;
|
||||||
_compressionStream =
|
_compressionStream = new DecompressionStream(ZstdWrapper, fileStream);
|
||||||
new DecompressionStream(_compressedType == CompressionType.LZ4 ? LZ4Wrapper : ZstdWrapper,
|
|
||||||
fileStream);
|
|
||||||
return new PeekableReader((DecompressionStream)_compressionStream);
|
return new PeekableReader((DecompressionStream)_compressionStream);
|
||||||
case CompressionType.None:
|
case CompressionType.None:
|
||||||
UseCompressSave = false;
|
UseCompressSave = false;
|
||||||
@@ -293,21 +344,22 @@ class PatchSave
|
|||||||
|
|
||||||
public static long FileLengthRead(BinaryReader binaryReader)
|
public static long FileLengthRead(BinaryReader binaryReader)
|
||||||
{
|
{
|
||||||
switch (_compressedType)
|
switch (_compressionTypeForLoading)
|
||||||
{
|
{
|
||||||
case CompressionType.LZ4:
|
case CompressionType.LZ4:
|
||||||
case CompressionType.Zstd:
|
case CompressionType.Zstd:
|
||||||
binaryReader.ReadInt64();
|
binaryReader.ReadInt64();
|
||||||
return _compressionStream.Length;
|
return _compressionStream.Length;
|
||||||
case CompressionType.None:
|
case CompressionType.None:
|
||||||
default:
|
|
||||||
return binaryReader.ReadInt64();
|
return binaryReader.ReadInt64();
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long ReadSeek(FileStream fileStream, long offset, SeekOrigin origin)
|
public static long ReadSeek(FileStream fileStream, long offset, SeekOrigin origin)
|
||||||
{
|
{
|
||||||
switch (_compressedType)
|
switch (_compressionTypeForLoading)
|
||||||
{
|
{
|
||||||
case CompressionType.LZ4:
|
case CompressionType.LZ4:
|
||||||
case CompressionType.Zstd:
|
case CompressionType.Zstd:
|
||||||
@@ -315,8 +367,9 @@ class PatchSave
|
|||||||
offset -= _compressionStream.Read(_compressBuffer.outBuffer, 0, (int)offset);
|
offset -= _compressionStream.Read(_compressBuffer.outBuffer, 0, (int)offset);
|
||||||
return _compressionStream.Position;
|
return _compressionStream.Position;
|
||||||
case CompressionType.None:
|
case CompressionType.None:
|
||||||
default:
|
|
||||||
return fileStream.Seek(offset, origin);
|
return fileStream.Seek(offset, origin);
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ add_library(lz4wrap SHARED
|
|||||||
lz4/lz4frame.c lz4/lz4frame.h lz4/lz4frame_static.h
|
lz4/lz4frame.c lz4/lz4frame.h lz4/lz4frame_static.h
|
||||||
lz4/lz4hc.c lz4/lz4hc.h
|
lz4/lz4hc.c lz4/lz4hc.h
|
||||||
lz4/xxhash.c lz4/xxhash.h
|
lz4/xxhash.c lz4/xxhash.h
|
||||||
dllmain.c lz4wrap.c lz4wrap.h)
|
dllmain.c LZ4Wrap.c LZ4Wrap.h)
|
||||||
|
|
||||||
target_compile_definitions(lz4wrap PRIVATE LZ4WRAP_EXPORTS)
|
target_compile_definitions(lz4wrap PRIVATE LZ4WRAP_EXPORTS)
|
||||||
target_include_directories(lz4wrap PRIVATE lz4)
|
target_include_directories(lz4wrap PRIVATE lz4)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
|||||||
switch (ul_reason_for_call)
|
switch (ul_reason_for_call)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
DisableThreadLibraryCalls(hModule);
|
||||||
|
break;
|
||||||
case DLL_THREAD_ATTACH:
|
case DLL_THREAD_ATTACH:
|
||||||
case DLL_THREAD_DETACH:
|
case DLL_THREAD_DETACH:
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
@@ -16,4 +18,3 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
|||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,23 +68,24 @@ static class PatchUISaveGame
|
|||||||
[HarmonyPatch(typeof(UISaveGameWindow), "_OnOpen"), HarmonyPostfix]
|
[HarmonyPatch(typeof(UISaveGameWindow), "_OnOpen"), HarmonyPostfix]
|
||||||
static void _OnOpen(UISaveGameWindow __instance, UIButton ___saveButton, Text ___saveButtonText)
|
static void _OnOpen(UISaveGameWindow __instance, UIButton ___saveButton, Text ___saveButtonText)
|
||||||
{
|
{
|
||||||
if (!context.buttonCompress)
|
if (context.buttonCompress) return;
|
||||||
{
|
context.saveButton = ___saveButton;
|
||||||
context.saveButton = ___saveButton;
|
context.saveButtonText = ___saveButtonText;
|
||||||
context.saveButtonText = ___saveButtonText;
|
|
||||||
|
|
||||||
context.ui = __instance;
|
context.ui = __instance;
|
||||||
context.buttonCompress = (__instance.transform.Find("button-compress")?.gameObject??GameObject.Instantiate(___saveButton.gameObject, ___saveButton.transform.parent)).GetComponent<UIButton>();
|
context.buttonCompress =
|
||||||
|
(__instance.transform.Find("button-compress")?.gameObject ??
|
||||||
context.buttonCompress.gameObject.name = "button-compress";
|
GameObject.Instantiate(___saveButton.gameObject, ___saveButton.transform.parent))
|
||||||
context.buttonCompress.transform.Translate(new Vector3(-2.0f, 0, 0));
|
.GetComponent<UIButton>();
|
||||||
context.buttonCompress.button.image.color = new Color32(0xfc,0x6f,00,0x77);
|
|
||||||
context.buttonCompressText = context.buttonCompress.transform.Find("button-text")?.GetComponent<Text>();
|
|
||||||
|
|
||||||
context.buttonCompress.onClick += __instance.OnSaveClick;
|
context.buttonCompress.gameObject.name = "button-compress";
|
||||||
context.saveButton.onClick -= __instance.OnSaveClick;
|
context.buttonCompress.transform.Translate(new Vector3(-2.0f, 0, 0));
|
||||||
context.saveButton.onClick += WrapClick;
|
context.buttonCompress.button.image.color = new Color32(0xfc, 0x6f, 00, 0x77);
|
||||||
}
|
context.buttonCompressText = context.buttonCompress.transform.Find("button-text")?.GetComponent<Text>();
|
||||||
|
|
||||||
|
context.buttonCompress.onClick += __instance.OnSaveClick;
|
||||||
|
context.saveButton.onClick -= __instance.OnSaveClick;
|
||||||
|
context.saveButton.onClick += WrapClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WrapClick(int data)
|
static void WrapClick(int data)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class CompressionStream : Stream
|
|||||||
// only use for game statistics
|
// only use for game statistics
|
||||||
public override long Position { get => BufferWriter.WriteSum; set => new NotImplementedException(); }
|
public override long Position { get => BufferWriter.WriteSum; set => new NotImplementedException(); }
|
||||||
|
|
||||||
readonly Stream outStream;
|
public readonly Stream outStream;
|
||||||
|
|
||||||
long totalWrite = 0;
|
long totalWrite = 0;
|
||||||
bool useMultiThread;
|
bool useMultiThread;
|
||||||
@@ -62,7 +62,7 @@ public class CompressionStream : Stream
|
|||||||
{
|
{
|
||||||
return new CompressBuffer
|
return new CompressBuffer
|
||||||
{
|
{
|
||||||
outBuffer = new byte[wrapper.CompressBufferBound(ExBufferSize) + 1],
|
outBuffer = new byte[wrapper.CompressBufferBound(ExBufferSize)],
|
||||||
readBuffer = new byte[ExBufferSize],
|
readBuffer = new byte[ExBufferSize],
|
||||||
writeBuffer = new byte[ExBufferSize],
|
writeBuffer = new byte[ExBufferSize],
|
||||||
};
|
};
|
||||||
@@ -74,19 +74,18 @@ public class CompressionStream : Stream
|
|||||||
return new CompressBuffer();
|
return new CompressBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferWriter BufferWriter => bfferWriter;
|
public BufferWriter BufferWriter { get; private set; }
|
||||||
BufferWriter bfferWriter;
|
|
||||||
|
|
||||||
public CompressionStream(WrapperDefines wrap, int compressionLevel, Stream outStream, CompressBuffer compressBuffer, bool useMultiThread)
|
public CompressionStream(WrapperDefines wrap, int compressionLevel, Stream outputStream, CompressBuffer compressBuffer, bool multiThread)
|
||||||
{
|
{
|
||||||
this.wrapper = wrap;
|
wrapper = wrap;
|
||||||
this.outStream = outStream;
|
outStream = outputStream;
|
||||||
InitBuffer(compressBuffer.readBuffer, compressBuffer.writeBuffer, compressBuffer.outBuffer);
|
InitBuffer(compressBuffer.readBuffer, compressBuffer.writeBuffer, compressBuffer.outBuffer);
|
||||||
long writeSize = wrapper.CompressBegin(out cctx, compressionLevel, outBuffer, outBuffer.Length);
|
long writeSize = wrapper.CompressBegin(out cctx, compressionLevel, outBuffer, outBuffer.Length);
|
||||||
HandleError(writeSize);
|
HandleError(writeSize);
|
||||||
outStream.Write(outBuffer, 0, (int)writeSize);
|
outputStream.Write(outBuffer, 0, (int)writeSize);
|
||||||
this.useMultiThread = useMultiThread;
|
useMultiThread = multiThread;
|
||||||
if(useMultiThread)
|
if(multiThread)
|
||||||
{
|
{
|
||||||
stopWorker = false;
|
stopWorker = false;
|
||||||
compressThread = new Thread(() => CompressAsync());
|
compressThread = new Thread(() => CompressAsync());
|
||||||
@@ -98,7 +97,7 @@ public class CompressionStream : Stream
|
|||||||
{
|
{
|
||||||
doubleBuffer = new DoubleBuffer(readBuffer ?? new byte[4 * MB], writeBuffer ?? new byte[4 * MB], Compress);
|
doubleBuffer = new DoubleBuffer(readBuffer ?? new byte[4 * MB], writeBuffer ?? new byte[4 * MB], Compress);
|
||||||
this.outBuffer = outBuffer ?? new byte[wrapper.CompressBufferBound(writeBuffer.Length)];
|
this.outBuffer = outBuffer ?? new byte[wrapper.CompressBufferBound(writeBuffer.Length)];
|
||||||
bfferWriter = new BufferWriter(doubleBuffer,this);
|
BufferWriter = new BufferWriter(doubleBuffer,this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Flush()
|
public override void Flush()
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ public class DecompressionStream : Stream
|
|||||||
|
|
||||||
public override long Length => inStream.Length;
|
public override long Length => inStream.Length;
|
||||||
|
|
||||||
public override long Position
|
public override long Position
|
||||||
{ get => readPos;
|
{
|
||||||
|
get => readPos;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value < readPos)
|
if (value < readPos)
|
||||||
@@ -28,7 +29,7 @@ public class DecompressionStream : Stream
|
|||||||
{
|
{
|
||||||
value -= Read(tmpBuffer, 0, (int)(value < 1024 ? value : 1024));
|
value -= Read(tmpBuffer, 0, (int)(value < 1024 ? value : 1024));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream inStream;
|
public Stream inStream;
|
||||||
@@ -41,11 +42,11 @@ public class DecompressionStream : Stream
|
|||||||
readonly long startPos = 0;
|
readonly long startPos = 0;
|
||||||
long readPos = 0; //sum of readlen
|
long readPos = 0; //sum of readlen
|
||||||
|
|
||||||
public DecompressionStream(WrapperDefines wrap, Stream inStream,int extraBufferSize = 512*1024)
|
public DecompressionStream(WrapperDefines wrap, Stream inputStream, int extraBufferSize = 512 * 1024)
|
||||||
{
|
{
|
||||||
this.wrapper = wrap;
|
wrapper = wrap;
|
||||||
this.inStream = inStream;
|
inStream = inputStream;
|
||||||
startPos = inStream.Position;
|
startPos = inputStream.Position;
|
||||||
srcBuffer = new ByteSpan(new byte[extraBufferSize]);
|
srcBuffer = new ByteSpan(new byte[extraBufferSize]);
|
||||||
int len = Fill();
|
int len = Fill();
|
||||||
long expect = wrapper.DecompressBegin(ref dctx, srcBuffer.Buffer, ref len, out var blockSize);
|
long expect = wrapper.DecompressBegin(ref dctx, srcBuffer.Buffer, ref len, out var blockSize);
|
||||||
@@ -67,23 +68,24 @@ public class DecompressionStream : Stream
|
|||||||
public int Fill()
|
public int Fill()
|
||||||
{
|
{
|
||||||
int suplus = srcBuffer.Length - srcBuffer.Position;
|
int suplus = srcBuffer.Length - srcBuffer.Position;
|
||||||
if (srcBuffer.Length> 0 && srcBuffer.Position >= suplus)
|
if (srcBuffer.Length > 0 && srcBuffer.Position >= suplus)
|
||||||
{
|
{
|
||||||
Array.Copy(srcBuffer, srcBuffer.Position, srcBuffer, 0, suplus);
|
Array.Copy(srcBuffer, srcBuffer.Position, srcBuffer, 0, suplus);
|
||||||
srcBuffer.Length -= srcBuffer.Position;
|
srcBuffer.Length -= srcBuffer.Position;
|
||||||
srcBuffer.Position = 0;
|
srcBuffer.Position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srcBuffer.IdleCapacity > 0)
|
if (srcBuffer.IdleCapacity > 0)
|
||||||
{
|
{
|
||||||
var readlen = inStream.Read(srcBuffer, srcBuffer.Length, srcBuffer.IdleCapacity);
|
var readlen = inStream.Read(srcBuffer, srcBuffer.Length, srcBuffer.IdleCapacity);
|
||||||
srcBuffer.Length += readlen;
|
srcBuffer.Length += readlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return srcBuffer.Length - srcBuffer.Position;
|
return srcBuffer.Length - srcBuffer.Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Flush()
|
public override void Flush()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
@@ -101,7 +103,8 @@ public class DecompressionStream : Stream
|
|||||||
var buffSize = Fill();
|
var buffSize = Fill();
|
||||||
if (buffSize <= 0) return readlen;
|
if (buffSize <= 0) return readlen;
|
||||||
|
|
||||||
var rt = wrapper.DecompressUpdateEx(dctx, dcmpBuffer, 0, dcmpBuffer.Capacity, srcBuffer, srcBuffer.Position,buffSize);
|
var rt = wrapper.DecompressUpdateEx(dctx, dcmpBuffer, 0, dcmpBuffer.Capacity, srcBuffer, srcBuffer.Position,
|
||||||
|
buffSize);
|
||||||
if (rt.Expect < 0) throw new Exception(rt.Expect.ToString());
|
if (rt.Expect < 0) throw new Exception(rt.Expect.ToString());
|
||||||
if (rt.Expect == 0) decompressFinish = true;
|
if (rt.Expect == 0) decompressFinish = true;
|
||||||
|
|
||||||
@@ -109,6 +112,7 @@ public class DecompressionStream : Stream
|
|||||||
dcmpBuffer.Position = 0;
|
dcmpBuffer.Position = 0;
|
||||||
dcmpBuffer.Length = (int)rt.WriteLen;
|
dcmpBuffer.Length = (int)rt.WriteLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
readPos += readlen;
|
readPos += readlen;
|
||||||
return readlen;
|
return readlen;
|
||||||
}
|
}
|
||||||
@@ -120,7 +124,8 @@ public class DecompressionStream : Stream
|
|||||||
var buffSize = Fill();
|
var buffSize = Fill();
|
||||||
if (buffSize <= 0) return -1;
|
if (buffSize <= 0) return -1;
|
||||||
|
|
||||||
var rt = wrapper.DecompressUpdateEx(dctx, dcmpBuffer, 0, dcmpBuffer.Capacity, srcBuffer, srcBuffer.Position, buffSize);
|
var rt = wrapper.DecompressUpdateEx(dctx, dcmpBuffer, 0, dcmpBuffer.Capacity, srcBuffer, srcBuffer.Position,
|
||||||
|
buffSize);
|
||||||
if (rt.Expect < 0) throw new Exception(rt.Expect.ToString());
|
if (rt.Expect < 0) throw new Exception(rt.Expect.ToString());
|
||||||
if (rt.Expect == 0) decompressFinish = true;
|
if (rt.Expect == 0) decompressFinish = true;
|
||||||
|
|
||||||
@@ -128,6 +133,7 @@ public class DecompressionStream : Stream
|
|||||||
dcmpBuffer.Position = 0;
|
dcmpBuffer.Position = 0;
|
||||||
dcmpBuffer.Length = (int)rt.WriteLen;
|
dcmpBuffer.Length = (int)rt.WriteLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dcmpBuffer.Buffer[dcmpBuffer.Position];
|
return dcmpBuffer.Buffer[dcmpBuffer.Position];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,11 +77,11 @@ public class DoubleBuffer
|
|||||||
Semaphore readEnd = new Semaphore(1, 1);
|
Semaphore readEnd = new Semaphore(1, 1);
|
||||||
Semaphore writeEnd = new Semaphore(0, 1);
|
Semaphore writeEnd = new Semaphore(0, 1);
|
||||||
|
|
||||||
public DoubleBuffer(byte[] readBuffer, byte[] writeBuffer, Action onReadBufferReady)
|
public DoubleBuffer(byte[] readingBuffer, byte[] writingBuffer, Action onReadBufferReadyAction)
|
||||||
{
|
{
|
||||||
this.onReadBufferReady = onReadBufferReady;
|
onReadBufferReady = onReadBufferReadyAction;
|
||||||
this.midBuffer = new ByteSpan(readBuffer);
|
midBuffer = new ByteSpan(readingBuffer);
|
||||||
this.writeBuffer = new ByteSpan(writeBuffer);
|
writeBuffer = new ByteSpan(writingBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteSpan ReadBegin()
|
public ByteSpan ReadBegin()
|
||||||
|
|||||||
68
CompressSave/Wrapper/NoneWrapper.cs
Normal file
68
CompressSave/Wrapper/NoneWrapper.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using MonoMod.Utils;
|
||||||
|
|
||||||
|
namespace CompressSave.Wrapper;
|
||||||
|
|
||||||
|
public class NoneAPI: WrapperDefines
|
||||||
|
{
|
||||||
|
public static readonly bool Avaliable;
|
||||||
|
|
||||||
|
static NoneAPI()
|
||||||
|
{
|
||||||
|
Avaliable = true;
|
||||||
|
string assemblyPath = System.Reflection.Assembly.GetAssembly(typeof(NoneAPI)).Location;
|
||||||
|
string root = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(assemblyPath))
|
||||||
|
{
|
||||||
|
root = Path.GetDirectoryName(assemblyPath) ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var map = new Dictionary<string, List<DynDllMapping>>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"nonewrap.dll", new List<DynDllMapping>
|
||||||
|
{
|
||||||
|
"nonewrap.dll",
|
||||||
|
"X64/nonewrap.dll",
|
||||||
|
"BepInEx/scripts/x64/nonewrap.dll",
|
||||||
|
Path.Combine(root, "X64/nonewrap.dll"),
|
||||||
|
Path.Combine(root, "nonewrap.dll")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
typeof(NoneAPI).ResolveDynDllImports(map);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Avaliable = false;
|
||||||
|
Console.WriteLine($"Error: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoneAPI()
|
||||||
|
{
|
||||||
|
CompressBufferBound = CompressBufferBound_;
|
||||||
|
CompressBegin = CompressBegin_;
|
||||||
|
CompressEnd = CompressEnd_;
|
||||||
|
CompressUpdate = CompressUpdate_;
|
||||||
|
CompressContextFree = CompressContextFree_;
|
||||||
|
DecompressBegin = DecompressBegin_;
|
||||||
|
DecompressEnd = DecompressEnd_;
|
||||||
|
DecompressUpdate = DecompressUpdate_;
|
||||||
|
DecompressContextReset = DecompressContextReset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "CompressBufferBound")] protected static CompressBufferBoundFunc CompressBufferBound_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "CompressBegin")] protected static CompressBeginFunc CompressBegin_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "CompressEnd")] protected static CompressEndFunc CompressEnd_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "CompressUpdate")] protected static CompressUpdateFunc CompressUpdate_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "CompressContextFree")] protected static CompressContextFreeFunc CompressContextFree_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "DecompressBegin")] protected static DecompressBeginFunc DecompressBegin_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "DecompressEnd")] protected static DecompressEndFunc DecompressEnd_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "DecompressUpdate")] protected static DecompressUpdateFunc DecompressUpdate_;
|
||||||
|
[DynDllImport(libraryName: "nonewrap.dll", "DecompressContextReset")] protected static DecompressContextResetFunc DecompressContextReset_;
|
||||||
|
}
|
||||||
@@ -2,10 +2,15 @@ cmake_minimum_required(VERSION 3.2)
|
|||||||
|
|
||||||
project(zstdwrap)
|
project(zstdwrap)
|
||||||
|
|
||||||
add_library(LZ4 SHARED
|
add_library(zstdwrap SHARED
|
||||||
dllmain.c zstdwrap.c zstdwrap.h)
|
dllmain.c zstdwrap.c zstdwrap.h)
|
||||||
|
|
||||||
target_compile_definitions(zstdwrap PRIVATE ZSTDWRAP_EXPORTS ZSTDLIB_STATIC_API)
|
target_compile_definitions(zstdwrap PRIVATE ZSTDWRAP_EXPORTS ZSTDLIB_STATIC_API)
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(zstdwrap PRIVATE /MT)
|
||||||
|
else()
|
||||||
|
target_link_options(zstdwrap PRIVATE -static)
|
||||||
|
endif()
|
||||||
target_link_libraries(zstdwrap PRIVATE zstd)
|
target_link_libraries(zstdwrap PRIVATE zstd)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set_target_properties(zstdwrap PROPERTIES PREFIX "")
|
set_target_properties(zstdwrap PROPERTIES PREFIX "")
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
|||||||
switch (ul_reason_for_call)
|
switch (ul_reason_for_call)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
DisableThreadLibraryCalls(hModule);
|
||||||
|
break;
|
||||||
case DLL_THREAD_ATTACH:
|
case DLL_THREAD_ATTACH:
|
||||||
case DLL_THREAD_DETACH:
|
case DLL_THREAD_DETACH:
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
@@ -16,4 +18,3 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
|||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
CompressSave/package/plugins/x64/nonewrap.dll
Normal file
BIN
CompressSave/package/plugins/x64/nonewrap.dll
Normal file
Binary file not shown.
Reference in New Issue
Block a user