diff --git a/CompressSave/CompressSave.cs b/CompressSave/CompressSave.cs index aed69cf..868011f 100644 --- a/CompressSave/CompressSave.cs +++ b/CompressSave/CompressSave.cs @@ -9,6 +9,13 @@ using CompressSave.Wrapper; namespace CompressSave; +public enum CompressionType +{ + None = 0, + LZ4 = 1, + Zstd = 2, +} + [BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] public class CompressSave : BaseUnityPlugin { @@ -43,8 +50,7 @@ public class CompressSave : BaseUnityPlugin new AcceptableValueList("lz4", "zstd", "none"), new {})) .Value); PatchSave.CompressionLevelForSaves = Config.Bind("Compression", "Level", PatchSave.CompressionLevelForSaves, - new ConfigDescription("Set default compression level. -1 for fastest level, 0 for default level. And positive levels for lz4: 3-12, for zstd: 1-22.", - new AcceptableValueRange(-1, 22), new {})) + "Set default compression level.\n0 for default level.\n3 ~ 12 for lz4, -5 ~ 22 for zstd.\nSmaller level leads to faster speed and less compression ratio.") .Value; PatchSave.CreateCompressBuffer(); if (GameConfig.gameVersion != SaveUtil.VerifiedVersion) @@ -217,10 +223,6 @@ class PatchSave .MatchBack(false, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(System.IO.Stream), "Seek"))); if (matcher.IsValid) matcher.Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "ReadSeek")); - matcher.Start() - .MatchForward(false, new CodeMatch(OpCodes.Newobj, AccessTools.Constructor(typeof(GameSaveHeader)))); - if (matcher.IsValid) - matcher.Set(OpCodes.Newobj, AccessTools.Constructor(typeof(CompressionGameSaveHeader))); //ReadHeader EnableDecompress = true; return matcher.InstructionEnumeration(); @@ -233,15 +235,6 @@ class PatchSave return instructions; } - [HarmonyPostfix] - [HarmonyPatch(typeof(GameSave), "ReadHeader")] - [HarmonyPatch(typeof(GameSave), "ReadHeaderAndDescAndProperty")] - static void ReadHeader_Postfix(ref GameSaveHeader header) - { - if (header != null) - ((CompressionGameSaveHeader)header).CompressionType = CompressedType; - } - public static BinaryReader CreateBinaryReader(FileStream fileStream) { switch (CompressedType = SaveUtil.SaveGetCompressType(fileStream)) diff --git a/CompressSave/CompressSave.csproj b/CompressSave/CompressSave.csproj index 427a191..10dce80 100644 --- a/CompressSave/CompressSave.csproj +++ b/CompressSave/CompressSave.csproj @@ -4,7 +4,7 @@ CompressSave org.soardev.compresssave DSP MOD - CompressSave - 1.2.0 + 1.2.1 true latest net472 @@ -23,6 +23,6 @@ - + diff --git a/CompressSave/CompressionGameSaveHeader.cs b/CompressSave/CompressionGameSaveHeader.cs deleted file mode 100644 index b90abb5..0000000 --- a/CompressSave/CompressionGameSaveHeader.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace CompressSave; - -public enum CompressionType -{ - None = 0, - LZ4 = 1, - Zstd = 2, -} - -internal class CompressionGameSaveHeader: GameSaveHeader -{ - public CompressionType CompressionType = CompressionType.None; -} diff --git a/CompressSave/PatchUILoadGame.cs b/CompressSave/PatchUILoadGame.cs index 3cec55d..7433625 100644 --- a/CompressSave/PatchUILoadGame.cs +++ b/CompressSave/PatchUILoadGame.cs @@ -12,56 +12,25 @@ class PatchUILoadGame { static UIButton decompressButton; - [HarmonyTranspiler] - [HarmonyPatch(typeof(UISaveGameWindow), "OnSelectedChange")] - [HarmonyPatch(typeof(UILoadGameWindow), "OnSelectedChange")] - static IEnumerable OnSelectedChange_Transpiler(IEnumerable instructions, ILGenerator generator) - { - var ReadHeader = typeof(GameSave).GetMethod("ReadHeaderAndDescAndProperty", BindingFlags.Static | BindingFlags.Public); - if (ReadHeader == null) return instructions; - var codes = new List(instructions); - for (int i = 0; i < codes.Count; i++) - { - var code = codes[i]; - if (code.opcode == OpCodes.Ldstr && code.OperandIs("#,##0")) - { - var iffalse = generator.DefineLabel(); - var ifzstd = generator.DefineLabel(); - var callLabel = generator.DefineLabel(); - code.WithLabels(iffalse) - .operand = "(N)#,##0"; - codes[i + 1].WithLabels(callLabel); - var IL = new List { - new CodeInstruction(OpCodes.Ldloc_0), - new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(CompressionGameSaveHeader),"CompressionType")), - new CodeInstruction(OpCodes.Ldc_I4_S, 0), - new CodeInstruction(OpCodes.Beq_S, iffalse), - new CodeInstruction(OpCodes.Ldloc_0), - new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(CompressionGameSaveHeader),"CompressionType")), - new CodeInstruction(OpCodes.Ldc_I4_S, 2), - new CodeInstruction(OpCodes.Beq_S, ifzstd), - new CodeInstruction(OpCodes.Ldstr,"(LZ4)#,##0"), - new CodeInstruction(OpCodes.Br_S,callLabel), - new CodeInstruction(OpCodes.Ldstr,"(ZSTD)#,##0").WithLabels(ifzstd), - new CodeInstruction(OpCodes.Br_S,callLabel), - }; - codes.InsertRange(i, IL); - break; - } - } - - return codes.AsEnumerable(); - } - [HarmonyPatch(typeof(UILoadGameWindow), "OnSelectedChange"), HarmonyPostfix] - static void OnSelectedChange(UILoadGameWindow __instance, UIButton ___loadButton, Text ___prop3Text) + static void OnSelectedChange(UILoadGameWindow __instance, Text ___prop3Text) { - bool compressedSave = (___prop3Text != null && (___prop3Text.text.Contains("(LZ4)") || ___prop3Text.text.Contains("(ZSTD)"))) || (___loadButton.button.interactable == false && SaveUtil.SaveGetCompressType(__instance.selected?.saveName) != CompressionType.None); - if (decompressButton) + var compressedType = SaveUtil.SaveGetCompressType(__instance.selected?.saveName); + switch (compressedType) { - decompressButton.button.interactable = compressedSave; - decompressButton.gameObject.SetActive(compressedSave); + case CompressionType.LZ4: + ___prop3Text.text = "(LZ4)" + ___prop3Text.text; + break; + case CompressionType.Zstd: + ___prop3Text.text = "(ZSTD)" + ___prop3Text.text; + break; + default: + ___prop3Text.text = "(N)" + ___prop3Text.text; + break; } + if (!decompressButton) return; + decompressButton.button.interactable = compressedType != CompressionType.None; + decompressButton.gameObject.SetActive(compressedType != CompressionType.None); } [HarmonyPatch(typeof(UILoadGameWindow), "_OnOpen"), HarmonyPostfix] diff --git a/CompressSave/PatchUISaveGame.cs b/CompressSave/PatchUISaveGame.cs index d6aa0e3..9788c1a 100644 --- a/CompressSave/PatchUISaveGame.cs +++ b/CompressSave/PatchUISaveGame.cs @@ -6,35 +6,31 @@ namespace CompressSave; static class PatchUISaveGame { + [HarmonyPatch(typeof(UISaveGameWindow), "OnSelectedChange"), HarmonyPostfix] + static void OnSelectedChange(UISaveGameWindow __instance, Text ___prop3Text) + { + var compressedType = SaveUtil.SaveGetCompressType(__instance.selected?.saveName); + switch (compressedType) + { + case CompressionType.LZ4: + ___prop3Text.text = "(LZ4)" + ___prop3Text.text; + break; + case CompressionType.Zstd: + ___prop3Text.text = "(ZSTD)" + ___prop3Text.text; + break; + default: + ___prop3Text.text = "(N)" + ___prop3Text.text; + break; + } + } + [HarmonyPatch(typeof(UISaveGameWindow), "_OnDestroy"), HarmonyPostfix] static void _OnDestroy() { //Console.WriteLine("OnCreate"); context = new UIContext(); } - //[HarmonyPatch(typeof(UISaveGameWindow), "_OnRegEvent"), HarmonyPostfix] - //static void _OnRegEvent() - //{ - // Console.WriteLine("OnRegEvent"); - //} - //[HarmonyPatch(typeof(UISaveGameWindow), "_OnUnregEvent"), HarmonyPostfix] - //static void _OnUnregEvent() - //{ - // Console.WriteLine("OnUnregEvent"); - //} - - static void Test() - { - GameSave.ReadHeaderAndDescAndProperty("aa", true, out var header, out var desc, out var property); - if (header != null) - if (header is CompressionGameSaveHeader) - "b".Translate(); - else - "a".Translate(); - "d.A".Translate(); - return; - } - + [HarmonyPatch(typeof(UISaveGameWindow), "OnSaveClick"), HarmonyReversePatch] static void OSaveGameAs(this UISaveGameWindow ui, int data) { } diff --git a/CompressSave/README.md b/CompressSave/README.md index f9af3e2..bffd5ff 100644 --- a/CompressSave/README.md +++ b/CompressSave/README.md @@ -7,6 +7,14 @@ ## Updates +### 1.2.1 +* Simplified codes to display compression type and `Decompress` button on save/load UI, making CompressSave compatible with other MODs(like GalacticScale) which override `UILoadGameWindow::OnSelectedChange()`. +* Add compression level -5 to -1 for zstd, which makes it working better than lz4(which is actually lz4hc used by lz4frame) now: + * -5 gets faster compression speed than lz4 with still a little better compression ratio. + * -1 has almost the same speed against lz4 with greater compression ratio. + * Due to bug of r2modman UI which does not support negative integer, the config value of compression level is not limited any more. +* move native wrapper DLLs into `x64` folder to avoid warning logs on loading BepInEx plugins. + ### 1.2.0 * Match game version 0.9.27.15033. * Add new compression type: zstd (a bit slower but get better compression ratio than lz4). diff --git a/CompressSave/package/manifest.json b/CompressSave/package/manifest.json index c555dbf..5ca66f0 100644 --- a/CompressSave/package/manifest.json +++ b/CompressSave/package/manifest.json @@ -1,6 +1,6 @@ { "name": "CompressSave", - "version_number": "1.2.0", + "version_number": "1.2.1", "website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CompressSave", "description": "Compress game saves to reduce space use and boost save speed / 压缩游戏存档以降低空间使用并提升保存速度", "dependencies": ["xiaoye97-BepInEx-5.4.17"] diff --git a/CompressSave/package/lz4wrap.dll b/CompressSave/package/x64/lz4wrap.dll similarity index 100% rename from CompressSave/package/lz4wrap.dll rename to CompressSave/package/x64/lz4wrap.dll diff --git a/CompressSave/package/zstdwrap.dll b/CompressSave/package/x64/zstdwrap.dll similarity index 99% rename from CompressSave/package/zstdwrap.dll rename to CompressSave/package/x64/zstdwrap.dll index 0f28c2d..a0ff270 100644 Binary files a/CompressSave/package/zstdwrap.dll and b/CompressSave/package/x64/zstdwrap.dll differ