From edc901fbb8de4ee7388542549f24df1313b57321 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> Date: Wed, 18 Dec 2024 19:29:13 +0000 Subject: [PATCH 1/3] SplitTools Cleanup --- .../AnimJSONConverter.csproj | 1 - CommandLine/ArchiveTool/ArchiveTool.csproj | 1 - CommandLine/BuildEvent/BuildEvent.csproj | 1 - CommandLine/BuildMDL/BuildMDL.csproj | 1 - CommandLine/BuildMTN/BuildMTN.csproj | 1 - .../BuildShapeMotion/BuildShapeMotion.csproj | 1 - .../LevelConverter/LevelConverter.csproj | 1 - .../ModelConverter/ModelConverter.csproj | 1 - CommandLine/ModelFixes/ModelFixes.csproj | 1 - .../ModelRelabeler/ModelRelabeler.csproj | 1 - CommandLine/OptimizeAnim/OptimizeAnim.csproj | 1 - CommandLine/PAKtool/PAKtool.csproj | 1 - .../SplitShapeMotion/SplitShapeMotion.csproj | 1 - CommandLine/TextureRemap/TextureRemap.csproj | 1 - .../WeldConverter/WeldConverter.csproj | 1 - CommandLine/buildSATools/buildSATools.csproj | 1 - CommandLine/split/split.csproj | 1 - CommandLine/splitEvent/Program.cs | 39 +- CommandLine/splitEvent/splitEvent.csproj | 1 - CommandLine/splitMDL/splitMDL.csproj | 1 - CommandLine/splitMTN/Program.cs | 16 +- CommandLine/splitMTN/splitMTN.csproj | 1 - DataToolbox/DataToolbox.csproj | 1 - Libraries/ArchiveLib/ArchiveLib.csproj | 1 - .../FraGag.Compression.Prs.csproj | 1 - .../NvTriStripDotNet/NvTriStripDotNet.csproj | 1 - .../SAEditorCommon/SAEditorCommon.csproj | 1 - .../SAModel.Direct3D/SAModel.Direct3D.csproj | 1 - Libraries/SAModel/SAModel.csproj | 2 - Libraries/SplitTools/HelperFunctions.cs | 950 +++++++++++------- Libraries/SplitTools/IniData.cs | 1 - Libraries/SplitTools/IniData_SplitDLL.cs | 1 - Libraries/SplitTools/SplitBinary.cs | 1 - Libraries/SplitTools/SplitDLL.cs | 1 - Libraries/SplitTools/SplitEventCyclone.cs | 108 +- Libraries/SplitTools/SplitEventExtra.cs | 227 ++++- Libraries/SplitTools/SplitMTN.cs | 5 +- Libraries/SplitTools/SplitMiniEvent.cs | 116 ++- Libraries/SplitTools/SplitTools.csproj | 5 - Libraries/VrSharp/VrSharp.csproj | 1 - SA1Tools/PLTool/PLTool.csproj | 1 - .../SADXObjectDefinitions.csproj | 1 - SA1Tools/SADXTweaker2/SADXTweaker2.csproj | 1 - SA1Tools/SADXsndSharp/SADXsndSharp.csproj | 1 - SA1Tools/SASave/SASave.csproj | 1 - SA1Tools/VMSEditor/VMSEditor.csproj | 1 - .../SA2CutsceneTextEditor.csproj | 1 - SA2Tools/SA2EventViewer/SA2EventViewer.csproj | 1 - .../SA2MessageFileEditor.csproj | 1 - .../SA2ObjectDefinitions.csproj | 1 - .../SA2StageSelEdit/SA2StageSelEdit.csproj | 1 - SAFontEdit/SAFontEdit.csproj | 1 - SALVL/SALVL.csproj | 1 - SAMDL/SAMDL.csproj | 1 - SAToolsHub/SAToolsHub.csproj | 1 - TextureEditor/TextureEditor.csproj | 1 - 56 files changed, 1006 insertions(+), 509 deletions(-) diff --git a/CommandLine/AnimJSONConverter/AnimJSONConverter.csproj b/CommandLine/AnimJSONConverter/AnimJSONConverter.csproj index e12aa5d1..89ece23b 100644 --- a/CommandLine/AnimJSONConverter/AnimJSONConverter.csproj +++ b/CommandLine/AnimJSONConverter/AnimJSONConverter.csproj @@ -9,7 +9,6 @@ false false embedded - x64;x86 diff --git a/CommandLine/ArchiveTool/ArchiveTool.csproj b/CommandLine/ArchiveTool/ArchiveTool.csproj index a3b0a779..e8133777 100644 --- a/CommandLine/ArchiveTool/ArchiveTool.csproj +++ b/CommandLine/ArchiveTool/ArchiveTool.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/BuildEvent/BuildEvent.csproj b/CommandLine/BuildEvent/BuildEvent.csproj index 311d3a79..590c87b5 100644 --- a/CommandLine/BuildEvent/BuildEvent.csproj +++ b/CommandLine/BuildEvent/BuildEvent.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/BuildMDL/BuildMDL.csproj b/CommandLine/BuildMDL/BuildMDL.csproj index 311d3a79..590c87b5 100644 --- a/CommandLine/BuildMDL/BuildMDL.csproj +++ b/CommandLine/BuildMDL/BuildMDL.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/BuildMTN/BuildMTN.csproj b/CommandLine/BuildMTN/BuildMTN.csproj index 311d3a79..590c87b5 100644 --- a/CommandLine/BuildMTN/BuildMTN.csproj +++ b/CommandLine/BuildMTN/BuildMTN.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/BuildShapeMotion/BuildShapeMotion.csproj b/CommandLine/BuildShapeMotion/BuildShapeMotion.csproj index 284b2119..3895960e 100644 --- a/CommandLine/BuildShapeMotion/BuildShapeMotion.csproj +++ b/CommandLine/BuildShapeMotion/BuildShapeMotion.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/LevelConverter/LevelConverter.csproj b/CommandLine/LevelConverter/LevelConverter.csproj index 9be7fc0b..a091bcaa 100644 --- a/CommandLine/LevelConverter/LevelConverter.csproj +++ b/CommandLine/LevelConverter/LevelConverter.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/ModelConverter/ModelConverter.csproj b/CommandLine/ModelConverter/ModelConverter.csproj index d18b0e70..4883bc28 100644 --- a/CommandLine/ModelConverter/ModelConverter.csproj +++ b/CommandLine/ModelConverter/ModelConverter.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/ModelFixes/ModelFixes.csproj b/CommandLine/ModelFixes/ModelFixes.csproj index d1f0e832..64e5e9f5 100644 --- a/CommandLine/ModelFixes/ModelFixes.csproj +++ b/CommandLine/ModelFixes/ModelFixes.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/ModelRelabeler/ModelRelabeler.csproj b/CommandLine/ModelRelabeler/ModelRelabeler.csproj index 50d63fad..8a3b7145 100644 --- a/CommandLine/ModelRelabeler/ModelRelabeler.csproj +++ b/CommandLine/ModelRelabeler/ModelRelabeler.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/OptimizeAnim/OptimizeAnim.csproj b/CommandLine/OptimizeAnim/OptimizeAnim.csproj index e12aa5d1..89ece23b 100644 --- a/CommandLine/OptimizeAnim/OptimizeAnim.csproj +++ b/CommandLine/OptimizeAnim/OptimizeAnim.csproj @@ -9,7 +9,6 @@ false false embedded - x64;x86 diff --git a/CommandLine/PAKtool/PAKtool.csproj b/CommandLine/PAKtool/PAKtool.csproj index cfc3440f..95c0b9e3 100644 --- a/CommandLine/PAKtool/PAKtool.csproj +++ b/CommandLine/PAKtool/PAKtool.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/SplitShapeMotion/SplitShapeMotion.csproj b/CommandLine/SplitShapeMotion/SplitShapeMotion.csproj index 284b2119..3895960e 100644 --- a/CommandLine/SplitShapeMotion/SplitShapeMotion.csproj +++ b/CommandLine/SplitShapeMotion/SplitShapeMotion.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/TextureRemap/TextureRemap.csproj b/CommandLine/TextureRemap/TextureRemap.csproj index d1f0e832..64e5e9f5 100644 --- a/CommandLine/TextureRemap/TextureRemap.csproj +++ b/CommandLine/TextureRemap/TextureRemap.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/WeldConverter/WeldConverter.csproj b/CommandLine/WeldConverter/WeldConverter.csproj index 69ddb004..0b388d66 100644 --- a/CommandLine/WeldConverter/WeldConverter.csproj +++ b/CommandLine/WeldConverter/WeldConverter.csproj @@ -8,7 +8,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/buildSATools/buildSATools.csproj b/CommandLine/buildSATools/buildSATools.csproj index 76053a17..e99afd84 100644 --- a/CommandLine/buildSATools/buildSATools.csproj +++ b/CommandLine/buildSATools/buildSATools.csproj @@ -7,6 +7,5 @@ embedded false false - x64;x86 \ No newline at end of file diff --git a/CommandLine/split/split.csproj b/CommandLine/split/split.csproj index 66c02ba1..37438af0 100644 --- a/CommandLine/split/split.csproj +++ b/CommandLine/split/split.csproj @@ -8,7 +8,6 @@ false false embedded - x64;x86 diff --git a/CommandLine/splitEvent/Program.cs b/CommandLine/splitEvent/Program.cs index ad2b4c8a..c1973d32 100644 --- a/CommandLine/splitEvent/Program.cs +++ b/CommandLine/splitEvent/Program.cs @@ -7,23 +7,14 @@ namespace splitEvent { static class Program { - public class Wildcard : Regex + private class Wildcard : Regex { - /// - /// Initializes a wildcard with the given search pattern. - /// - /// The wildcard pattern to match. - public Wildcard(string pattern) - : base(WildcardToRegex(pattern)) - { - } - /// /// Initializes a wildcard with the given search pattern and options. /// /// The wildcard pattern to match. /// A combination of one or more - /// . + /// . public Wildcard(string pattern, RegexOptions options) : base(WildcardToRegex(pattern), options) { @@ -45,19 +36,23 @@ static void Main(string[] args) { string fullpath_out; string fullpath_bin; + if (args.Length == 0) { Console.Write("Filename: "); - args = new string[] { Console.ReadLine().Trim('"') }; + args = [Console.ReadLine().Trim('"')]; } + fullpath_bin = Path.GetFullPath(args[0]); string name = Path.GetFileName(fullpath_bin); + Wildcard evwcard = new Wildcard("e*", RegexOptions.IgnoreCase); Wildcard mevwcard = new Wildcard("me*", RegexOptions.IgnoreCase); Wildcard evxwcard = new Wildcard("e*_*", RegexOptions.IgnoreCase); Wildcard mevxwcard = new Wildcard("me*_*", RegexOptions.IgnoreCase); Wildcard exfwcard = new Wildcard("e*_*.*", RegexOptions.IgnoreCase); Wildcard mexfwcard = new Wildcard("me*_*.*", RegexOptions.IgnoreCase); + if (!name.EndsWith("texlist.prs", StringComparison.OrdinalIgnoreCase)) { if (mevwcard.IsMatch(name)) @@ -111,22 +106,40 @@ static void Main(string[] args) if (args.Length > 1) { fullpath_out = args[1]; - if (fullpath_out[fullpath_out.Length - 1] != '/') fullpath_out = string.Concat(fullpath_out, '/'); + if (fullpath_out[fullpath_out.Length - 1] != '/') + { + fullpath_out = string.Concat(fullpath_out, '/'); + } + fullpath_out = Path.GetFullPath(fullpath_out); } + Console.WriteLine("Output folder: {0}", fullpath_out); + if (name.Contains("tailsplain", StringComparison.OrdinalIgnoreCase)) + { sa2EventTailsPlane.Split(fullpath_bin, fullpath_out); + } else if (name.EndsWith("texlist.prs", StringComparison.OrdinalIgnoreCase)) + { SA2Event.SplitExternalTexList(fullpath_bin, fullpath_out); + } else if (mexfwcard.IsMatch(name)) + { sa2EventExtra.SplitMini(fullpath_bin, fullpath_out); + } else if (exfwcard.IsMatch(name)) + { sa2EventExtra.Split(fullpath_bin, fullpath_out); + } else if (name.StartsWith("me", StringComparison.OrdinalIgnoreCase)) + { SA2MiniEvent.Split(fullpath_bin, fullpath_out); + } else + { SA2Event.Split(fullpath_bin, fullpath_out); + } } } } \ No newline at end of file diff --git a/CommandLine/splitEvent/splitEvent.csproj b/CommandLine/splitEvent/splitEvent.csproj index 311d3a79..590c87b5 100644 --- a/CommandLine/splitEvent/splitEvent.csproj +++ b/CommandLine/splitEvent/splitEvent.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/CommandLine/splitMDL/splitMDL.csproj b/CommandLine/splitMDL/splitMDL.csproj index 4d0f26a4..bf2a411f 100644 --- a/CommandLine/splitMDL/splitMDL.csproj +++ b/CommandLine/splitMDL/splitMDL.csproj @@ -9,7 +9,6 @@ false en embedded - x64;x86 diff --git a/CommandLine/splitMTN/Program.cs b/CommandLine/splitMTN/Program.cs index 4546f06b..1a3a42c8 100644 --- a/CommandLine/splitMTN/Program.cs +++ b/CommandLine/splitMTN/Program.cs @@ -4,24 +4,26 @@ namespace splitMTN { - class Program + internal static class Program { - static void Main(string[] args) + private static void Main(string[] args) { - Queue argq = new Queue(args); + var argQueue = new Queue(args); + string filename; - if (argq.Count > 0) + + if (argQueue.Count > 0) { - filename = argq.Dequeue(); + filename = argQueue.Dequeue(); Console.WriteLine("File: {0}", filename); - SA2MTN.Split(filename); } else { Console.Write("File: "); filename = Console.ReadLine(); - SA2MTN.Split(filename); } + + SA2MTN.Split(filename); } } } \ No newline at end of file diff --git a/CommandLine/splitMTN/splitMTN.csproj b/CommandLine/splitMTN/splitMTN.csproj index 311d3a79..590c87b5 100644 --- a/CommandLine/splitMTN/splitMTN.csproj +++ b/CommandLine/splitMTN/splitMTN.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/DataToolbox/DataToolbox.csproj b/DataToolbox/DataToolbox.csproj index 4b4167be..9e6c449f 100644 --- a/DataToolbox/DataToolbox.csproj +++ b/DataToolbox/DataToolbox.csproj @@ -8,7 +8,6 @@ false en embedded - x64;x86 datatoolbox.ico diff --git a/Libraries/ArchiveLib/ArchiveLib.csproj b/Libraries/ArchiveLib/ArchiveLib.csproj index 1d944151..2d482a87 100644 --- a/Libraries/ArchiveLib/ArchiveLib.csproj +++ b/Libraries/ArchiveLib/ArchiveLib.csproj @@ -8,7 +8,6 @@ false false embedded - x64;x86 diff --git a/Libraries/FraGag.Compression.Prs/FraGag.Compression.Prs.csproj b/Libraries/FraGag.Compression.Prs/FraGag.Compression.Prs.csproj index a5458afa..c35fdacd 100644 --- a/Libraries/FraGag.Compression.Prs/FraGag.Compression.Prs.csproj +++ b/Libraries/FraGag.Compression.Prs/FraGag.Compression.Prs.csproj @@ -7,6 +7,5 @@ embedded false false - x64;x86 \ No newline at end of file diff --git a/Libraries/NvTriStripDotNet/NvTriStripDotNet.csproj b/Libraries/NvTriStripDotNet/NvTriStripDotNet.csproj index 212bda9e..6ec30dad 100644 --- a/Libraries/NvTriStripDotNet/NvTriStripDotNet.csproj +++ b/Libraries/NvTriStripDotNet/NvTriStripDotNet.csproj @@ -7,7 +7,6 @@ false false true - x64;x86 diff --git a/Libraries/SAEditorCommon/SAEditorCommon.csproj b/Libraries/SAEditorCommon/SAEditorCommon.csproj index 6a1c4300..a3c3b7b5 100644 --- a/Libraries/SAEditorCommon/SAEditorCommon.csproj +++ b/Libraries/SAEditorCommon/SAEditorCommon.csproj @@ -9,7 +9,6 @@ false false embedded - x64;x86 diff --git a/Libraries/SAModel.Direct3D/SAModel.Direct3D.csproj b/Libraries/SAModel.Direct3D/SAModel.Direct3D.csproj index 1f5ae635..221c2ab0 100644 --- a/Libraries/SAModel.Direct3D/SAModel.Direct3D.csproj +++ b/Libraries/SAModel.Direct3D/SAModel.Direct3D.csproj @@ -8,7 +8,6 @@ embedded false false - x64;x86 diff --git a/Libraries/SAModel/SAModel.csproj b/Libraries/SAModel/SAModel.csproj index 9e252940..887665b0 100644 --- a/Libraries/SAModel/SAModel.csproj +++ b/Libraries/SAModel/SAModel.csproj @@ -1,6 +1,5 @@ - net8.0-windows7.0 Library true @@ -8,7 +7,6 @@ en false false - x64;x86 diff --git a/Libraries/SplitTools/HelperFunctions.cs b/Libraries/SplitTools/HelperFunctions.cs index 8579fc0c..6cd570c5 100644 --- a/Libraries/SplitTools/HelperFunctions.cs +++ b/Libraries/SplitTools/HelperFunctions.cs @@ -1,8 +1,11 @@ using SAModel; using System; -using System.Collections.Generic; +using System.Buffers; +using System.Buffers.Binary; using System.Globalization; using System.IO; +using System.Linq; +using System.Numerics; using System.Runtime.InteropServices; using System.Text; @@ -10,42 +13,201 @@ namespace SplitTools { public static class HelperFunctions { - // X86 SACompGC - [DllImport("SACompGC_x86.dll", EntryPoint = "GetDecompressedSize", CallingConvention = CallingConvention.Cdecl, SetLastError = true)] - private static extern uint GetDecompressedSizeX86(IntPtr InputBuffer); - [DllImport("SACompGC_x86.dll", EntryPoint = "DecompressBuffer", CallingConvention = CallingConvention.Cdecl, SetLastError = true)] - private static extern void DecompressBufferX86(IntPtr InputBuffer, IntPtr OutputBuffer); - // X64 SACompGC - [DllImport("SACompGC_x64.dll", EntryPoint = "GetDecompressedSize", CallingConvention = CallingConvention.Cdecl, SetLastError = true)] - private static extern uint GetDecompressedSizeX64(IntPtr InputBuffer); - [DllImport("SACompGC_x64.dll", EntryPoint = "DecompressBuffer", CallingConvention = CallingConvention.Cdecl, SetLastError = true)] - private static extern void DecompressBufferX64(IntPtr InputBuffer, IntPtr OutputBuffer); + private static T ReadAs(Span span, int byteIndex) where T : unmanaged + { + return MemoryMarshal.Read(span[byteIndex..]); + } + + private static uint SACompGC_GetData(uint numBits, ref SACompGCStatus data) + { + uint retVal; + + if (data.BitBufferRemaining < numBits) + { + var v6 = (int)(numBits - data.BitBufferRemaining); + retVal = data.BitBuffer << (int)(numBits - data.BitBufferRemaining); + + if (data.ReadOffset != 0 || data.ChunkCount != 0) + { + var v9 = BinaryPrimitives.ReverseEndianness(ReadAs(data.InputBuffer, data.ReadHead + (int)data.ReadOffset)); + data.ReadOffset += 4; + + var clearBits = 32 - v6; + retVal |= v9 << clearBits >> clearBits; + data.BitBufferRemaining = (byte)clearBits; + data.BitBuffer = v9 >> v6; + + if (data.ReadOffset == 0x8000) + { + data.ReadOffset = 0; + data.ReadHead += 0x8000; + if (data.ReadHead == data.EndOffset) + { + data.ReadHead = 0; + } + data.ChunkCount--; + } + } + } + else + { + var v4 = data.BitBuffer; + data.BitBufferRemaining -= (byte)numBits; + data.BitBuffer >>= (int)numBits; + + var clearBits = (int)(32 - numBits); + retVal = v4 << clearBits >> clearBits; + } + + return retVal; + } + + private static void SACompGCStatus_Process(ref SACompGCStatus data) + { + while (true) + { + if (SACompGC_GetData(1, ref data) != 0) + { + data.OutputBuffer[data.WriteHead] = (byte)SACompGC_GetData(8, ref data); + data.WriteHead++; + data.LengthLeft--; + + if (data.LengthLeft == 0) + { + return; + } + + continue; + } + + // Perform RLE lookback + var copyIdx = (int)SACompGC_GetData(data.CopyOffsetBits, ref data) + 1; + var numBytes = SACompGC_GetData(data.CopySizeBits, ref data) + 2; + data.LengthLeft -= numBytes; + + var lookbackHead = data.WriteHead - copyIdx; + + if (!((int)data.LengthLeft < 0 || lookbackHead < 0)) + { + // Copies a slice from earlier in the output buffer to place at the head. + data.OutputBuffer.Slice(lookbackHead, (int)numBytes) + .CopyTo(data.OutputBuffer.Slice(data.WriteHead, (int)numBytes)); + + data.WriteHead += (int)numBytes; + + if (data.LengthLeft == 0) + { + return; + } + } + else + { + // Invalid? + return; + } + } + } + + private static uint SACompGC_GetDecompressedSize(byte[] inputBuffer, out byte[] dataStart) + { + var saCompGcData = MemoryMarshal.Cast(inputBuffer); + + if (inputBuffer != null) + { + while (saCompGcData[0] != 0x6F436153) + { + saCompGcData = saCompGcData[1..]; + + // Do not read out of bounds + if (saCompGcData.Length == 0) + { + dataStart = null; + return 0; + } + } + + dataStart = MemoryMarshal.Cast(saCompGcData).ToArray(); + + return BinaryPrimitives.ReverseEndianness(saCompGcData[2]) & 0x0FFFFFFF; + } + + dataStart = null; + return 0; + } + + private static byte[] SACompGC_DecompressBuffer(byte[] input) + { + if (input == null) + { + return []; + } + + var size = SACompGC_GetDecompressedSize(input, out input); + var output = new byte[size]; + + if (size == 0) + { + throw new ArgumentOutOfRangeException(nameof(input), "Empty file!"); + } + + SACompGCStatus data = new() + { + CopyOffsetBits = input[12], + CopySizeBits = input[13], + Field0x2D = (byte)(input[8] >> 6), + ReadOffset = 16, + LengthLeft = size, + Length = size, + ChunkCount = 0xFF, // -1 as byte + OutputBuffer = output, + WriteHead = 0, + InputBuffer = input, + ReadHead = 0, + EndOffset = (int)((size + 47) & 0xFFFFFFE0) + }; + + SACompGCStatus_Process(ref data); + + return output.ToArray(); + } + public static uint? SetupEXE(ref byte[] exefile) { if (ByteConverter.ToUInt16(exefile, 0) != 0x5A4D) + { return null; - int ptr = ByteConverter.ToInt32(exefile, 0x3c); - if (ByteConverter.ToInt32(exefile, (int)ptr) != 0x4550) //PE\0\0 + } + + var ptr = ByteConverter.ToInt32(exefile, 0x3c); + + if (ByteConverter.ToInt32(exefile, ptr) != 0x4550) //PE\0\0 + { return null; + } + try { ptr += 4; - UInt16 numsects = ByteConverter.ToUInt16(exefile, (int)ptr + 2); + var numSects = ByteConverter.ToUInt16(exefile, ptr + 2); ptr += 0x14; - int PEHead = ptr; - uint imageBase = ByteConverter.ToUInt32(exefile, ptr + 28); + + var imageBase = ByteConverter.ToUInt32(exefile, ptr + 28); + if (imageBase != 0x82000000) // SADX X360 EXE doesn't like this { - byte[] result = new byte[ByteConverter.ToUInt32(exefile, ptr + 56)]; + var result = new byte[ByteConverter.ToUInt32(exefile, ptr + 56)]; Array.Copy(exefile, result, ByteConverter.ToUInt32(exefile, ptr + 60)); ptr += 0xe0; - for (int i = 0; i < numsects; i++) + + for (var i = 0; i < numSects; i++) { Array.Copy(exefile, ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.FAddr), result, ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.VAddr), ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.FSize)); ptr += (int)SectOffs.Size; } + exefile = result; } + return imageBase; } catch @@ -53,162 +215,92 @@ public static class HelperFunctions return null; } } - - public static uint GetNewSectionAddress(byte[] exefile) - { - int ptr = ByteConverter.ToInt32(exefile, 0x3c); - ptr += 4; - UInt16 numsects = ByteConverter.ToUInt16(exefile, (int)ptr + 2); - ptr += 0x14; - ptr += 0xe0; - ptr += (int)SectOffs.Size * (numsects - 1); - return HelperFunctions.Align(ByteConverter.ToUInt32(exefile, ptr + (int)SectOffs.VAddr) + ByteConverter.ToUInt32(exefile, ptr + (int)SectOffs.VSize)); - } - - public static void CreateNewSection(ref byte[] exefile, string name, byte[] data, bool isCode) + + public static void FixRELPointers(byte[] file, uint imageBase = 0) { - int ptr = ByteConverter.ToInt32(exefile, 0x3c); - ptr += 4; - UInt16 numsects = ByteConverter.ToUInt16(exefile, ptr + 2); - int sectnumptr = ptr + 2; - ptr += 0x14; - int PEHead = ptr; - ptr += 0xe0; - int sectptr = ptr; - ptr += (int)SectOffs.Size * numsects; - ByteConverter.GetBytes((ushort)(numsects + 1)).CopyTo(exefile, sectnumptr); - Array.Clear(exefile, ptr, 8); - Encoding.ASCII.GetBytes(name).CopyTo(exefile, ptr); - UInt32 vaddr = HelperFunctions.Align(ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.VAddr) + ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.VSize)); - ByteConverter.GetBytes(vaddr).CopyTo(exefile, ptr + (int)SectOffs.VAddr); - UInt32 faddr = HelperFunctions.Align(ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.FAddr) + ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.FSize)); - ByteConverter.GetBytes(faddr).CopyTo(exefile, ptr + (int)SectOffs.FAddr); - ByteConverter.GetBytes(isCode ? 0x60000020 : 0xC0000040).CopyTo(exefile, ptr + (int)SectOffs.Flags); - int diff = (int)HelperFunctions.Align((uint)data.Length); - ByteConverter.GetBytes(diff).CopyTo(exefile, ptr + (int)SectOffs.VSize); - ByteConverter.GetBytes(diff).CopyTo(exefile, ptr + (int)SectOffs.FSize); - if (isCode) - ByteConverter.GetBytes(Convert.ToUInt32(ByteConverter.ToUInt32(exefile, PEHead + 4) + diff)).CopyTo(exefile, PEHead + 4); - else - ByteConverter.GetBytes(Convert.ToUInt32(ByteConverter.ToUInt32(exefile, PEHead + 8) + diff)).CopyTo(exefile, PEHead + 8); - ByteConverter.GetBytes(Convert.ToUInt32(ByteConverter.ToUInt32(exefile, PEHead + 0x38) + diff)).CopyTo(exefile, PEHead + 0x38); - Array.Resize(ref exefile, exefile.Length + diff); - data.CopyTo(exefile, vaddr); - } + var header = new OsModuleHeader(file, 0); + var sections = new OsSectionInfo[header.Info.NumSections]; + + for (var i = 0; i < header.Info.NumSections; i++) + { + sections[i] = new OsSectionInfo(file, (int)header.Info.SectionInfoOffset + (i * 8)); + } - public static void CompactEXE(ref byte[] exefile) - { - if (ByteConverter.ToUInt16(exefile, 0) != 0x5A4D) - return; - int ptr = ByteConverter.ToInt32(exefile, 0x3c); - if (ByteConverter.ToInt32(exefile, (int)ptr) != 0x4550) //PE\0\0 - return; - ptr += 4; - UInt16 numsects = ByteConverter.ToUInt16(exefile, (int)ptr + 2); - ptr += 0x14; - int PEHead = ptr; - uint imageBase = ByteConverter.ToUInt32(exefile, ptr + 28); - byte[] result = new byte[ByteConverter.ToInt32(exefile, ptr + 0xe0 + ((int)SectOffs.Size * (numsects - 1)) + (int)SectOffs.FAddr) + ByteConverter.ToInt32(exefile, ptr + 0xe0 + ((int)SectOffs.Size * (numsects - 1)) + (int)SectOffs.FSize)]; - Array.Copy(exefile, result, ByteConverter.ToUInt32(exefile, ptr + 60)); - ptr += 0xe0; - for (int i = 0; i < numsects; i++) + var imports = new OsImportInfo[header.ImpSize / 8]; + + for (var i = 0; i < imports.Length; i++) { - Array.Copy(exefile, ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.VAddr), result, ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.FAddr), ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.FSize)); - ptr += (int)SectOffs.Size; + imports[i] = new OsImportInfo(file, (int)header.ImpOffset + (i * 8)); } - exefile = result; - } - public static void FixRELPointers(byte[] file, uint imageBase = 0) - { - OSModuleHeader header = new OSModuleHeader(file, 0); - OSSectionInfo[] sections = new OSSectionInfo[header.info.numSections]; - for (int i = 0; i < header.info.numSections; i++) - sections[i] = new OSSectionInfo(file, (int)header.info.sectionInfoOffset + (i * 8)); - OSImportInfo[] imports = new OSImportInfo[header.impSize / 8]; - for (int i = 0; i < imports.Length; i++) - imports[i] = new OSImportInfo(file, (int)header.impOffset + (i * 8)); - int reladdr = 0; - for (int i = 0; i < imports.Length; i++) - if (imports[i].id == header.info.id) - { - reladdr = (int)imports[i].offset; - break; - } - OSRel rel = new OSRel(file, reladdr); - int dataaddr = 0; - unchecked + var relAddr = (from import in imports where import.Id == header.Info.Id select (int)import.Offset).FirstOrDefault(); + + var rel = new OsRel(file, relAddr); + var dataAddr = 0; + + unchecked + { + while (rel.Type != (byte)RelocTypes.R_DOLPHIN_END) { - while (rel.type != (byte)RelocTypes.R_DOLPHIN_END) + dataAddr += rel.Offset; + var sectionBase = (uint)(sections[rel.Section].Offset & ~1); + + switch (rel.Type) { - dataaddr += rel.offset; - uint sectionbase = (uint)(sections[rel.section].offset & ~1); - switch (rel.type) - { - case 0x01: - ByteConverter.GetBytes(rel.addend + sectionbase + imageBase).CopyTo(file, dataaddr); - break; - case 0x02: - ByteConverter.GetBytes((ByteConverter.ToUInt32(file, dataaddr) & 0xFC000003) | ((rel.addend + sectionbase) & 0x3FFFFFC) + imageBase).CopyTo(file, dataaddr); - break; - case 0x03: - case 0x04: - ByteConverter.GetBytes((ushort)(rel.addend + sectionbase) + imageBase).CopyTo(file, dataaddr); - break; - case 0x05: - ByteConverter.GetBytes((ushort)((rel.addend + sectionbase) >> 16) + imageBase).CopyTo(file, dataaddr); - break; - case 0x06: - ByteConverter.GetBytes((ushort)(((rel.addend + sectionbase) >> 16) + (((rel.addend + sectionbase) & 0x8000) == 0x8000 ? 1 : 0)) + imageBase).CopyTo(file, dataaddr); - break; - case 0x0A: - ByteConverter.GetBytes((uint)((ByteConverter.ToUInt32(file, dataaddr) & 0xFC000003) | (((rel.addend + sectionbase) - dataaddr) & 0x3FFFFFC)) + imageBase).CopyTo(file, dataaddr); - break; - case 0x00: - case (byte)RelocTypes.R_DOLPHIN_NOP: - case (byte)RelocTypes.R_DOLPHIN_END: - break; - case (byte)RelocTypes.R_DOLPHIN_SECTION: - dataaddr = (int)sectionbase; - break; - default: - throw new NotImplementedException(); - } - reladdr += 8; - rel = new OSRel(file, reladdr); + case 0x01: + ByteConverter.GetBytes(rel.Addend + sectionBase + imageBase).CopyTo(file, dataAddr); + break; + case 0x02: + ByteConverter.GetBytes((ByteConverter.ToUInt32(file, dataAddr) & 0xFC000003) | ((rel.Addend + sectionBase) & 0x3FFFFFC) + imageBase).CopyTo(file, dataAddr); + break; + case 0x03: + case 0x04: + ByteConverter.GetBytes((ushort)(rel.Addend + sectionBase) + imageBase).CopyTo(file, dataAddr); + break; + case 0x05: + ByteConverter.GetBytes((ushort)((rel.Addend + sectionBase) >> 16) + imageBase).CopyTo(file, dataAddr); + break; + case 0x06: + ByteConverter.GetBytes((ushort)(((rel.Addend + sectionBase) >> 16) + (((rel.Addend + sectionBase) & 0x8000) == 0x8000 ? 1 : 0)) + imageBase).CopyTo(file, dataAddr); + break; + case 0x0A: + ByteConverter.GetBytes((uint)((ByteConverter.ToUInt32(file, dataAddr) & 0xFC000003) | (((rel.Addend + sectionBase) - dataAddr) & 0x3FFFFFC)) + imageBase).CopyTo(file, dataAddr); + break; + case 0x00: + case (byte)RelocTypes.R_DOLPHIN_NOP: + case (byte)RelocTypes.R_DOLPHIN_END: + break; + case (byte)RelocTypes.R_DOLPHIN_SECTION: + dataAddr = (int)sectionBase; + break; + default: + throw new NotImplementedException(); } + relAddr += 8; + rel = new OsRel(file, relAddr); } + } } - public static void AlignCode(this List me) - { - while (me.Count % 0x10 > 0) - me.Add(0x90); - } + private static readonly System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); - public static uint Align(uint address) + public static string FileHash(string path, int rangeStart = 0, int rangeFinish = 0) { - if (address % 0x1000 == 0) return address; - return ((address / 0x1000) + 1) * 0x1000; + return FileHash(File.ReadAllBytes(path), rangeStart, rangeFinish); } - static readonly System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); - - public static string FileHash(string path, int rangeStart = 0, int rangeFinish = 0) { return FileHash(File.ReadAllBytes(path), rangeStart, rangeFinish); } - public static string FileHash(byte[] file, int rangeStart = 0, int rangeFinish = 0) { if (rangeStart != 0 || rangeFinish != 0) { - byte[] newfile = new byte[rangeFinish - rangeStart]; - Array.Copy(file, rangeStart, newfile, 0, newfile.Length); - file = newfile; + var newFile = new byte[rangeFinish - rangeStart]; + Array.Copy(file, rangeStart, newFile, 0, newFile.Length); + file = newFile; } + file = md5.ComputeHash(file); - string result = string.Empty; - foreach (byte item in file) - result += item.ToString("x2"); - return result; + + return file.Aggregate(string.Empty, (current, item) => current + item.ToString("x2")); } private static readonly Encoding jpenc = Encoding.GetEncoding(932); @@ -223,24 +315,17 @@ public static string FileHash(byte[] file, int rangeStart = 0, int rangeFinish = public static Encoding GetEncoding(Game game, Languages language) { - switch (language) + return language switch { - case Languages.Japanese: - return KoreanMode ? krenc : jpenc; - case Languages.English: - switch (game) - { - case Game.SA1: - case Game.SADX: - return KoreanMode ? krenc : jpenc; - case Game.SA2: - case Game.SA2B: - return euenc; - } - throw new ArgumentOutOfRangeException("game"); - default: - return euenc; - } + Languages.Japanese => KoreanMode ? krenc : jpenc, + Languages.English => game switch + { + Game.SA1 or Game.SADX => KoreanMode ? krenc : jpenc, + Game.SA2 or Game.SA2B => euenc, + _ => throw new ArgumentOutOfRangeException(nameof(game)) + }, + _ => euenc + }; } public static string GetCString(this byte[] file, int address) @@ -250,29 +335,40 @@ public static string GetCString(this byte[] file, int address) public static int GetPointer(this byte[] file, int address, uint imageBase) { - uint tmp = ByteConverter.ToUInt32(file, address); - if (tmp == 0) return 0; + var tmp = ByteConverter.ToUInt32(file, address); + + if (tmp == 0) + { + return 0; + } + return (int)(tmp - imageBase); } public static string UnescapeNewlines(this string line) { - StringBuilder sb = new StringBuilder(line.Length); - for (int c = 0; c < line.Length; c++) + var sb = new StringBuilder(line.Length); + + for (var c = 0; c < line.Length; c++) + { switch (line[c]) { - case '\\': // escape character - if (c + 1 == line.Length) goto default; + case '\\': // Escape character + if (c + 1 == line.Length) + { + goto default; + } + c++; switch (line[c]) { - case 'n': // line feed + case 'n': // Line feed sb.Append('\n'); break; - case 'r': // carriage return + case 'r': // Carriage return sb.Append('\r'); break; - default: // literal character + default: // Literal character sb.Append(line[c]); break; } @@ -281,6 +377,8 @@ public static string UnescapeNewlines(this string line) sb.Append(line[c]); break; } + } + return sb.ToString(); } @@ -292,9 +390,11 @@ public static string EscapeNewlines(this string line) public static string ToCHex(this ushort i) { if (i < 10) + { return i.ToString(NumberFormatInfo.InvariantInfo); - else - return "0x" + i.ToString("X"); + } + + return "0x" + i.ToString("X"); } public static string ToC(this string str) => str.ToC(Languages.Japanese); @@ -303,40 +403,64 @@ public static string ToCHex(this ushort i) public static string ToC(this string str, Game game, Languages language) { - if (str == null) return "NULL"; - Encoding enc = GetEncoding(game, language); - StringBuilder result = new StringBuilder("\""); - foreach (char item in str) + if (str == null) { - if (item == '\0') - result.Append(@"\0"); - else if (item == '\a') - result.Append(@"\a"); - else if (item == '\b') - result.Append(@"\b"); - else if (item == '\f') - result.Append(@"\f"); - else if (item == '\n') - result.Append(@"\n"); - else if (item == '\r') - result.Append(@"\r"); - else if (item == '\t') - result.Append(@"\t"); - else if (item == '\v') - result.Append(@"\v"); - else if (item == '"') - result.Append(@"\"""); - else if (item == '\\') - result.Append(@"\\"); - else if (item < ' ') - result.AppendFormat(@"\{0}", Convert.ToString((short)item, 8).PadLeft(3, '0')); - else if (item > '\x7F') - foreach (byte b in enc.GetBytes(item.ToString())) - result.AppendFormat(@"\{0}", Convert.ToString(b, 8).PadLeft(3, '0')); - else - result.Append(item); + return "NULL"; } - result.Append("\""); + + var enc = GetEncoding(game, language); + var result = new StringBuilder("\""); + + foreach (var item in str) + { + switch (item) + { + case '\0': + result.Append(@"\0"); + break; + case '\a': + result.Append(@"\a"); + break; + case '\b': + result.Append(@"\b"); + break; + case '\f': + result.Append(@"\f"); + break; + case '\n': + result.Append(@"\n"); + break; + case '\r': + result.Append(@"\r"); + break; + case '\t': + result.Append(@"\t"); + break; + case '\v': + result.Append(@"\v"); + break; + case '"': + result.Append(@"\"""); + break; + case '\\': + result.Append(@"\\"); + break; + case < ' ': + result.Append($@"\{Convert.ToString((short)item, 8).PadLeft(3, '0')}"); + break; + case > '\x7F': + { + foreach (byte b in enc.GetBytes(item.ToString())) + result.Append($@"\{Convert.ToString(b, 8).PadLeft(3, '0')}"); + break; + } + default: + result.Append(item); + break; + } + } + + result.Append('"'); return result.ToString(); } @@ -345,38 +469,59 @@ public static string ToComment(this string str) return "/* " + str.ToCNoEncoding().Replace("*/", @"*\/") + " */"; } - public static string ToCNoEncoding(this string str) + private static string ToCNoEncoding(this string str) { - if (str == null) return "NULL"; - StringBuilder result = new StringBuilder("\""); - foreach (char item in str) + if (str == null) { - if (item == '\0') - result.Append(@"\0"); - else if (item == '\a') - result.Append(@"\a"); - else if (item == '\b') - result.Append(@"\b"); - else if (item == '\f') - result.Append(@"\f"); - else if (item == '\n') - result.Append(@"\n"); - else if (item == '\r') - result.Append(@"\r"); - else if (item == '\t') - result.Append(@"\t"); - else if (item == '\v') - result.Append(@"\v"); - else if (item == '"') - result.Append(@"\"""); - else if (item == '\\') - result.Append(@"\\"); - else if (item < ' ') - result.AppendFormat(@"\{0}", Convert.ToString((short)item, 8).PadLeft(3, '0')); - else - result.Append(item); + return "NULL"; + } + + var result = new StringBuilder("\""); + + foreach (var item in str) + { + switch (item) + { + case '\0': + result.Append(@"\0"); + break; + case '\a': + result.Append(@"\a"); + break; + case '\b': + result.Append(@"\b"); + break; + case '\f': + result.Append(@"\f"); + break; + case '\n': + result.Append(@"\n"); + break; + case '\r': + result.Append(@"\r"); + break; + case '\t': + result.Append(@"\t"); + break; + case '\v': + result.Append(@"\v"); + break; + case '"': + result.Append(@"\"""); + break; + case '\\': + result.Append(@"\\"); + break; + case < ' ': + result.Append($@"\{Convert.ToString((short)item, 8).PadLeft(3, '0')}"); + break; + default: + result.Append(item); + break; + } } - result.Append("\""); + + result.Append('"'); return result.ToString(); } @@ -386,56 +531,72 @@ public static string ToC(this T item) return item.ToC(typeof(T).Name); } - public static string ToC(this T item, string enumname) + public static string ToC(this T item, string enumName) where T : Enum { - Type type = typeof(T); + var type = typeof(T); if (type.GetCustomAttributes(typeof(FlagsAttribute), false).Length == 0) + { if (Enum.IsDefined(typeof(T), item)) - return enumname + "_" + item.ToString(); - else - return item.ToString(); - else + { + return enumName + "_" + item; + } + + return item.ToString(); + } + + var num = Convert.ToUInt64(item); + var values = Array.ConvertAll((T[])Enum.GetValues(type), (a) => Convert.ToUInt64(a)); + var num2 = values.Length - 1; + var stringBuilder = new StringBuilder(); + var flag = true; + var num3 = num; + + while (num2 >= 0 && (num2 != 0 || values[num2] != 0uL)) { - ulong num = Convert.ToUInt64(item); - ulong[] values = Array.ConvertAll((T[])Enum.GetValues(type), (a) => Convert.ToUInt64(a)); - int num2 = values.Length - 1; - StringBuilder stringBuilder = new StringBuilder(); - bool flag = true; - ulong num3 = num; - while (num2 >= 0 && (num2 != 0 || values[num2] != 0uL)) + if ((num & values[num2]) == values[num2]) { - if ((num & values[num2]) == values[num2]) + num -= values[num2]; + if (!flag) { - num -= values[num2]; - if (!flag) - stringBuilder.Insert(0, " | "); - stringBuilder.Insert(0, enumname + "_" + Enum.GetName(type, values[num2])); - flag = false; + stringBuilder.Insert(0, " | "); } - num2--; + + stringBuilder.Insert(0, enumName + "_" + Enum.GetName(type, values[num2])); + flag = false; } - if (num != 0uL) + num2--; + } + + if (num != 0uL) + { + if (flag) { - if (flag) - return item.ToString(); - else - return stringBuilder.ToString() + " | " + item.ToString(); + return item.ToString(); } - if (num3 != 0uL) - return stringBuilder.ToString(); - if (values.Length > 0 && values[0] == 0uL) - return enumname + "_" + Enum.GetName(type, 0); - return "0"; + + return stringBuilder + " | " + item; } + + if (num3 != 0uL) + { + return stringBuilder.ToString(); + } + + if (values.Length > 0 && values[0] == 0uL) + { + return enumName + "_" + Enum.GetName(type, 0); + } + + return "0"; } public static bool CheckBigEndianInt16(byte[] file, int address) { - bool bigEndState = ByteConverter.BigEndian; + var bigEndState = ByteConverter.BigEndian; ByteConverter.BigEndian = true; - bool isBigEndian = BitConverter.ToUInt16(file, address) > ByteConverter.ToUInt16(file, address); + var isBigEndian = BitConverter.ToUInt16(file, address) > ByteConverter.ToUInt16(file, address); ByteConverter.BigEndian = bigEndState; @@ -443,10 +604,10 @@ public static bool CheckBigEndianInt16(byte[] file, int address) } public static bool CheckBigEndianInt32(byte[] file, int address) { - bool bigEndState = ByteConverter.BigEndian; + var bigEndState = ByteConverter.BigEndian; ByteConverter.BigEndian = true; - bool isBigEndian = BitConverter.ToUInt32(file, address) > ByteConverter.ToUInt32(file, address); + var isBigEndian = BitConverter.ToUInt32(file, address) > ByteConverter.ToUInt32(file, address); ByteConverter.BigEndian = bigEndState; @@ -456,11 +617,12 @@ public static bool CheckBigEndianInt32(byte[] file, int address) public static byte[] DecompressREL(byte[] file) { // Scan the array for the last instance of the "SaCompGC" string because there are some files with redundant headers - int start = 0; - bool isCompressed = false; - bool bigend = ByteConverter.BigEndian; + var start = 0; + var isCompressed = false; + var bigEndian = ByteConverter.BigEndian; ByteConverter.BigEndian = true; - for (int u = file.Length - 8; u >= 0; u--) + + for (var u = file.Length - 8; u >= 0; u--) { if (ByteConverter.ToUInt32(file, u) == 0x5361436F)// && BitConverter.ToUInt32(file, u + 4) == 0x4347706D) { @@ -469,33 +631,42 @@ public static byte[] DecompressREL(byte[] file) break; } } - if (!isCompressed) return file; - byte[] input = new byte[file.Length - start]; + + if (!isCompressed) + { + return file; + } + + var input = new byte[file.Length - start]; Array.Copy(file, start, input, 0, input.Length); - // Process the new array - IntPtr pnt_input = Marshal.AllocHGlobal(input.Length); - Marshal.Copy(input, 0, pnt_input, input.Length); - int size_output; - if (Environment.Is64BitProcess) - size_output = (int)GetDecompressedSizeX64(pnt_input); - else - size_output = (int)GetDecompressedSizeX86(pnt_input); - IntPtr pnt_output = Marshal.AllocHGlobal(size_output); - if (Environment.Is64BitProcess) - DecompressBufferX64(pnt_input, pnt_output); - else - DecompressBufferX86(pnt_input, pnt_output); - byte[] decompbuf = new byte[size_output]; - Marshal.Copy(pnt_output, decompbuf, 0, size_output); - Marshal.FreeHGlobal(pnt_output); - Marshal.FreeHGlobal(pnt_input); - ByteConverter.BigEndian = bigend; - return decompbuf; + var decompBuf = SACompGC_DecompressBuffer(input); + + ByteConverter.BigEndian = bigEndian; + return decompBuf; } } - + ref struct SACompGCStatus + { + public uint LengthLeft; + public uint Length; + public uint ReadOffset; // 0x8 + public uint BitBuffer; // 0xc + public Span OutputBuffer; + public int ReadHead; + public Span InputBuffer; + public int EndOffset; // 0x1c + public int WriteHead; // byte offset instead of pointer + + public byte ChunkCount; // 0x28 + public byte BitBufferRemaining; // 0x29 + public byte CopyOffsetBits; //0x2a + public byte CopySizeBits; //0x2b + // special note: missing 0x2c for some reason. bad decomp? + public byte Field0x2D; + } + enum SectOffs { VSize = 8, @@ -561,7 +732,7 @@ public enum SA1Characters : byte MetalSonic = 8 } - [Flags()] + [Flags] public enum SA1CharacterFlags { Sonic = 1 << SA1Characters.Sonic, @@ -711,8 +882,7 @@ public enum SA2DCLevelIDs : byte ChaoWorld = 90, Invalid = 91 } - - + public enum SA2Characters { Sonic = 0, @@ -739,7 +909,7 @@ public enum SA2KartCharacters Rouge = 7 } - [Flags()] + [Flags] public enum SA2CharacterFlags { Sonic = 1 << SA2Characters.Sonic, @@ -764,149 +934,147 @@ public enum Languages public enum ChaoItemCategory { - ChaoItemCategory_Egg = 1, - ChaoItemCategory_Fruit = 3, - ChaoItemCategory_Seed = 7, - ChaoItemCategory_Hat = 9, - ChaoItemCategory_MenuTheme = 0x10 + Egg = 1, + Fruit = 3, + Seed = 7, + Hat = 9, + MenuTheme = 0x10 } - class OSModuleLink + internal class OsModuleLink { - public uint next; - public uint prev; + public uint Next; + public uint Prev; - public OSModuleLink(byte[] file, int address) + public OsModuleLink(byte[] file, int address) { - next = ByteConverter.ToUInt32(file, address); - prev = ByteConverter.ToUInt32(file, address + 4); + Next = ByteConverter.ToUInt32(file, address); + Prev = ByteConverter.ToUInt32(file, address + 4); } } - class OSModuleInfo + internal class OsModuleInfo { - public uint id; // unique identifier for the module - public OSModuleLink link; // doubly linked list of modules - public uint numSections; // # of sections - public uint sectionInfoOffset; // offset to section info table - public uint nameOffset; // offset to module name - public uint nameSize; // size of module name - public uint version; // version number - - public OSModuleInfo(byte[] file, int address) + public uint Id; // Unique identifier for the module + public OsModuleLink Link; // Doubly linked list of modules + public uint NumSections; // # of sections + public uint SectionInfoOffset; // Offset to section info table + public uint NameOffset; // Offset to module name + public uint NameSize; // Size of module name + public uint Version; // Version number + + public OsModuleInfo(byte[] file, int address) { - id = ByteConverter.ToUInt32(file, address); + Id = ByteConverter.ToUInt32(file, address); address += 4; - link = new OSModuleLink(file, address); + Link = new OsModuleLink(file, address); address += 8; - numSections = ByteConverter.ToUInt32(file, address); + NumSections = ByteConverter.ToUInt32(file, address); address += 4; - sectionInfoOffset = ByteConverter.ToUInt32(file, address); + SectionInfoOffset = ByteConverter.ToUInt32(file, address); address += 4; - nameOffset = ByteConverter.ToUInt32(file, address); + NameOffset = ByteConverter.ToUInt32(file, address); address += 4; - nameSize = ByteConverter.ToUInt32(file, address); + NameSize = ByteConverter.ToUInt32(file, address); address += 4; - version = ByteConverter.ToUInt32(file, address); + Version = ByteConverter.ToUInt32(file, address); } } - class OSModuleHeader + internal class OsModuleHeader { - // CAUTION: info must be the 1st member - public OSModuleInfo info; + // CAUTION: Info must be the 1st member + public OsModuleInfo Info; // OS_MODULE_VERSION == 1 - public uint bssSize; // total size of bss sections in bytes - public uint relOffset; - public uint impOffset; - public uint impSize; // size in bytes - public byte prologSection; // section # for prolog function - public byte epilogSection; // section # for epilog function - public byte unresolvedSection; // section # for unresolved function - public byte padding0; - public uint prolog; // prolog function offset - public uint epilog; // epilog function offset - public uint unresolved; // unresolved function offset + public uint BssSize; // Total size of bss sections in bytes + public uint RelOffset; + public uint ImpOffset; + public uint ImpSize; // Size in bytes + public byte PrologSection; // Section # for prolog function + public byte EpilogSection; // Section # for epilog function + public byte UnresolvedSection; // Section # for unresolved function + public byte Padding0; + public uint Prolog; // Prolog function offset + public uint Epilog; // Epilog function offset + public uint Unresolved; // Unresolved function offset // OS_MODULE_VERSION == 2 - public uint align; // module alignment constraint - public uint bssAlign; // bss alignment constraint + public uint Align; // Module alignment constraint + public uint BssAlign; // Bss alignment constraint - public OSModuleHeader(byte[] file, int address) + public OsModuleHeader(byte[] file, int address) { - info = new OSModuleInfo(file, address); + Info = new OsModuleInfo(file, address); address += 0x20; - bssSize = ByteConverter.ToUInt32(file, address); + BssSize = ByteConverter.ToUInt32(file, address); address += 4; - relOffset = ByteConverter.ToUInt32(file, address); + RelOffset = ByteConverter.ToUInt32(file, address); address += 4; - impOffset = ByteConverter.ToUInt32(file, address); + ImpOffset = ByteConverter.ToUInt32(file, address); address += 4; - impSize = ByteConverter.ToUInt32(file, address); + ImpSize = ByteConverter.ToUInt32(file, address); address += 4; - prologSection = file[address++]; - epilogSection = file[address++]; - unresolvedSection = file[address++]; - padding0 = file[address++]; - prolog = ByteConverter.ToUInt32(file, address); + PrologSection = file[address++]; + EpilogSection = file[address++]; + UnresolvedSection = file[address++]; + Padding0 = file[address++]; + Prolog = ByteConverter.ToUInt32(file, address); address += 4; - epilog = ByteConverter.ToUInt32(file, address); + Epilog = ByteConverter.ToUInt32(file, address); address += 4; - unresolved = ByteConverter.ToUInt32(file, address); + Unresolved = ByteConverter.ToUInt32(file, address); address += 4; - align = ByteConverter.ToUInt32(file, address); + Align = ByteConverter.ToUInt32(file, address); address += 4; - bssAlign = ByteConverter.ToUInt32(file, address); + BssAlign = ByteConverter.ToUInt32(file, address); } } - class OSSectionInfo + class OsSectionInfo { - public uint offset; - public uint size; + public uint Offset; + public uint Size; - public OSSectionInfo(byte[] file, int address) + public OsSectionInfo(byte[] file, int address) { - offset = ByteConverter.ToUInt32(file, address); - size = ByteConverter.ToUInt32(file, address + 4); + Offset = ByteConverter.ToUInt32(file, address); + Size = ByteConverter.ToUInt32(file, address + 4); } } - class OSImportInfo + class OsImportInfo { - public uint id; // external module id - public uint offset; // offset to OSRel instructions + public uint Id; // External module id + public uint Offset; // Offset to OSRel instructions - public OSImportInfo(byte[] file, int address) + public OsImportInfo(byte[] file, int address) { - id = ByteConverter.ToUInt32(file, address); - offset = ByteConverter.ToUInt32(file, address + 4); + Id = ByteConverter.ToUInt32(file, address); + Offset = ByteConverter.ToUInt32(file, address + 4); } } - class OSRel + class OsRel { - public ushort offset; // byte offset from the previous entry - public byte type; - public byte section; - public uint addend; + public ushort Offset; // Byte offset from the previous entry + public byte Type; + public byte Section; + public uint Addend; - public OSRel(byte[] file, int address) + public OsRel(byte[] file, int address) { - offset = ByteConverter.ToUInt16(file, address); - type = file[address + 2]; - section = file[address + 3]; - addend = ByteConverter.ToUInt32(file, address + 4); + Offset = ByteConverter.ToUInt16(file, address); + Type = file[address + 2]; + Section = file[address + 3]; + Addend = ByteConverter.ToUInt32(file, address + 4); } } enum RelocTypes { R_DOLPHIN_NOP = 201, // C9h current offset += OSRel.offset - R_DOLPHIN_SECTION = 202, // CAh current section = OSRel.section - R_DOLPHIN_END = 203 // CBh + R_DOLPHIN_SECTION = 202, // CAh current section = OSRel.section + R_DOLPHIN_END = 203 // CBh } - - } diff --git a/Libraries/SplitTools/IniData.cs b/Libraries/SplitTools/IniData.cs index ed038779..c94bcbc6 100644 --- a/Libraries/SplitTools/IniData.cs +++ b/Libraries/SplitTools/IniData.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using System.Text; using ByteConverter = SAModel.ByteConverter; diff --git a/Libraries/SplitTools/IniData_SplitDLL.cs b/Libraries/SplitTools/IniData_SplitDLL.cs index e95509db..def69542 100644 --- a/Libraries/SplitTools/IniData_SplitDLL.cs +++ b/Libraries/SplitTools/IniData_SplitDLL.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Text; -using SplitTools; namespace SplitTools.SplitDLL { diff --git a/Libraries/SplitTools/SplitBinary.cs b/Libraries/SplitTools/SplitBinary.cs index 452bcdf2..01a84962 100644 --- a/Libraries/SplitTools/SplitBinary.cs +++ b/Libraries/SplitTools/SplitBinary.cs @@ -4,7 +4,6 @@ using System.Globalization; using System.IO; using System.Linq; -using SplitTools; using SAModel; using SAModel.GC; diff --git a/Libraries/SplitTools/SplitDLL.cs b/Libraries/SplitTools/SplitDLL.cs index f0360cef..47f465a1 100644 --- a/Libraries/SplitTools/SplitDLL.cs +++ b/Libraries/SplitTools/SplitDLL.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; -using SplitTools; using SAModel; using SAModel.GC; using SplitTools.Split; diff --git a/Libraries/SplitTools/SplitEventCyclone.cs b/Libraries/SplitTools/SplitEventCyclone.cs index b77abb06..394b8d01 100644 --- a/Libraries/SplitTools/SplitEventCyclone.cs +++ b/Libraries/SplitTools/SplitEventCyclone.cs @@ -3,23 +3,19 @@ using SAModel; using System; using System.Collections.Generic; -using System.Diagnostics.Metrics; using System.IO; using System.Linq; -using System.Reflection.Metadata; using System.Text; -using System.Web.Services.Description; -using static System.Windows.Forms.Design.AxImporter; namespace SplitTools.SAArc { public static class sa2EventTailsPlane { - static List nodenames = new List(); - static Dictionary modelfiles = new Dictionary(); - static Dictionary motionfiles = new Dictionary(); - static Dictionary camarrayfiles = new Dictionary(); - static Dictionary texanimfiles = new Dictionary(); + static List nodenames = new(); + static Dictionary modelfiles = new(); + static Dictionary motionfiles = new(); + static Dictionary camarrayfiles = new(); + static Dictionary texanimfiles = new(); public static void Split(string filename, string outputPath, string labelFile = null) { @@ -28,49 +24,75 @@ public static void Split(string filename, string outputPath, string labelFile = camarrayfiles.Clear(); motionfiles.Clear(); texanimfiles.Clear(); + string dir = Environment.CurrentDirectory; + try { - if (outputPath[outputPath.Length - 1] != '/') outputPath = string.Concat(outputPath, "/"); + if (outputPath[outputPath.Length - 1] != '/') + { + outputPath = string.Concat(outputPath, "/"); + } + // get file name, read it from the console if nothing string evfilename = filename; evfilename = Path.GetFullPath(evfilename); string EventFileName = Path.GetFileNameWithoutExtension(evfilename); if (Path.GetExtension(evfilename).Equals(".bin", StringComparison.OrdinalIgnoreCase)) + { EventFileName += "_bin"; + } Console.WriteLine("Splitting file {0}...", evfilename); byte[] fc; if (Path.GetExtension(evfilename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) + { fc = Prs.Decompress(evfilename); + } else + { fc = File.ReadAllBytes(evfilename); + } + if (Path.GetExtension(evfilename).Equals(".bin", StringComparison.OrdinalIgnoreCase) && fc[0] == 0x0F && fc[1] == 0x81) + { fc = Prs.Decompress(evfilename); + } + EventCycloneIniData ini = new EventCycloneIniData() { Name = Path.GetFileNameWithoutExtension(evfilename) }; if (outputPath.Length != 0) { if (!Directory.Exists(outputPath)) + { Directory.CreateDirectory(outputPath); + } + Environment.CurrentDirectory = outputPath; } else + { Environment.CurrentDirectory = Path.GetDirectoryName(evfilename); - Directory.CreateDirectory(EventFileName); + } + + Directory.CreateDirectory(EventFileName); // Metadata for SAMDL Project Mode byte[] mlength = null; Dictionary evsectionlist = new Dictionary(); Dictionary evsplitfilenames = new Dictionary(); - if (labelFile != null) labelFile = Path.GetFullPath(labelFile); + if (labelFile != null) + { + labelFile = Path.GetFullPath(labelFile); + } + if (File.Exists(labelFile)) { evsplitfilenames = IniSerializer.Deserialize>(labelFile); mlength = File.ReadAllBytes(labelFile); } string evname = Path.GetFileNameWithoutExtension(evfilename); - string[] evmetadata = new string[0]; + string[] evmetadata = []; string evtexname = Path.Combine("EVENT", evname); @@ -122,10 +144,15 @@ public static void Split(string filename, string outputPath, string labelFile = { EntityName = modelfiles[ini.Model].MetaName; if (battle) + { outResult += modelfiles[ini.Model].MetaName + "|" + $"{evtexname}TEX"; - + } + else + { outResult += modelfiles[ini.Model].MetaName + "|" + $"{evtexname}"; + } + evsectionlist[modelfiles[ini.Model].Filename] = outResult; } } @@ -191,10 +218,17 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa string dir = Environment.CurrentDirectory; try { - if (fileOutputPath[fileOutputPath.Length - 1] != '/') fileOutputPath = string.Concat(fileOutputPath, "/"); + if (fileOutputPath[fileOutputPath.Length - 1] != '/') + { + fileOutputPath = string.Concat(fileOutputPath, "/"); + } + filename = Path.GetFullPath(filename); if (Directory.Exists(filename)) + { filename += ".prs"; + } + Environment.CurrentDirectory = Path.GetDirectoryName(filename); string path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename)); JsonSerializer js = new JsonSerializer(); @@ -204,9 +238,14 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa evinfo = js.Deserialize(jtr); uint gamekey; if (!isBigEndian.HasValue) + { ByteConverter.BigEndian = evinfo.BigEndian; + } else + { ByteConverter.BigEndian = isBigEndian.Value; + } + List evfile = new List(); List databytes = new List(); Dictionary animaddrs = new Dictionary(); @@ -214,9 +253,14 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa Dictionary panimaddrs = new Dictionary(); Dictionary labels = new Dictionary(); if (evinfo.BigEndian == true) + { gamekey = 0x8162FE60; + } else + { gamekey = 0xCB00000; + } + uint imageBase = gamekey + 0x10; uint tlsstart = gamekey + 0x10; NJS_TEXLIST tex = NJS_TEXLIST.Load(Path.Combine(path, "tailsPlain.satex")); @@ -286,7 +330,10 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa if (fileOutputPath.Length != 0) { if (!Directory.Exists(fileOutputPath)) + { Directory.CreateDirectory(fileOutputPath); + } + filename = Path.Combine(fileOutputPath, Path.GetFileName(filename)); } @@ -294,10 +341,14 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa { FraGag.Compression.Prs.Compress(evfile.ToArray(), filename); if (!File.Exists(filename)) + { File.Create(filename); + } } else + { File.WriteAllBytes(filename, evfile.ToArray()); + } } finally { @@ -320,7 +371,10 @@ private static string GetModel(byte[] fc, int address, uint key, string fn, stri List names = new List(obj.GetObjects().Select((o) => o.Name)); foreach (string s in names) if (modelfiles.ContainsKey(s)) + { modelfiles.Remove(s); + } + nodenames.AddRange(names); modelfiles.Add(obj.Name, new ModelInfo(fn, obj, ModelFormat.Chunk, meta)); } @@ -332,7 +386,9 @@ private static string GetMotion(byte[] fc, int address, uint key, string fn, Lis { NJS_MOTION mtn = null; if (motions != null) + { mtn = motions[ByteConverter.ToInt32(fc, address)]; + } else { int ptr3 = fc.GetPointer(address, key); @@ -343,9 +399,16 @@ private static string GetMotion(byte[] fc, int address, uint key, string fn, Lis mtn.OptimizeShape(); } } - if (mtn == null) return null; + if (mtn == null) + { + return null; + } + if (!motionfiles.ContainsKey(mtn.Name) || motionfiles[mtn.Name].Filename == null) + { motionfiles[mtn.Name] = new MotionInfo(fn, mtn); + } + return mtn.Name; } @@ -386,7 +449,9 @@ private static string GetCamData(byte[] fc, int address, uint key, string fn, Li { NJS_CAMERA ncam = null; if (ncams != null) + { ncam = ncams[ByteConverter.ToInt32(fc, address + 0xC)]; + } else { int ptr3 = fc.GetPointer(address, key); @@ -395,9 +460,16 @@ private static string GetCamData(byte[] fc, int address, uint key, string fn, Li ncam = new NJS_CAMERA(fc, ptr3 + 0xC, key); } } - if (ncam == null) return null; + if (ncam == null) + { + return null; + } + if (!camarrayfiles.ContainsKey(ncam.Name) || camarrayfiles[ncam.Name].Filename == null) + { camarrayfiles[ncam.Name] = new CameraInfo(fn, ncam); + } + return ncam.Name; } } @@ -413,7 +485,7 @@ public string GameString set { Game = (Game)Enum.Parse(typeof(Game), value); } } public bool BigEndian { get; set; } - public Dictionary Files { get; set; } = new Dictionary(); + public Dictionary Files { get; set; } = new(); public string Texlist { get; set; } public string Model { get; set; } public string Animation { get; set; } diff --git a/Libraries/SplitTools/SplitEventExtra.cs b/Libraries/SplitTools/SplitEventExtra.cs index 5e4b5e39..94ff5577 100644 --- a/Libraries/SplitTools/SplitEventExtra.cs +++ b/Libraries/SplitTools/SplitEventExtra.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; namespace SplitTools.SAArc @@ -16,7 +15,11 @@ public static void Split(string filename, string outputPath) string dir = Environment.CurrentDirectory; try { - if (outputPath[outputPath.Length - 1] != '/') outputPath = string.Concat(outputPath, "/"); + if (outputPath[outputPath.Length - 1] != '/') + { + outputPath = string.Concat(outputPath, "/"); + } + // get file name, read it from the console if nothing string evfilename = filename; @@ -24,18 +27,29 @@ public static void Split(string filename, string outputPath) Console.WriteLine("Splitting file {0}...", filename); byte[] fc; if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) + { fc = Prs.Decompress(filename); + } else + { fc = File.ReadAllBytes(filename); + } + EventExtraIniData ini = new EventExtraIniData() { Name = Path.GetFileNameWithoutExtension(filename) }; if (outputPath.Length != 0) { if (!Directory.Exists(outputPath)) + { Directory.CreateDirectory(outputPath); + } + Environment.CurrentDirectory = outputPath; } else + { Environment.CurrentDirectory = Path.GetDirectoryName(evfilename); + } + Directory.CreateDirectory(Path.GetFileNameWithoutExtension(evfilename)); bool battle; bool beta; @@ -81,7 +95,10 @@ public static void Split(string filename, string outputPath) ini.LanguageOnly = false; } if (lang) + { Console.WriteLine("File only contains audio/subtitle timings."); + } + int address = 0; int subcount = 0; int timestamps = 0; @@ -91,20 +108,35 @@ public static void Split(string filename, string outputPath) SubtitleInfo subs = new SubtitleInfo(); subs.FrameStart = ByteConverter.ToInt32(fc, address); if (subs.FrameStart != 0) + { subcount++; + } + if (subs.FrameStart == -1) + { timestamps++; + } + subs.VisibleTime = ByteConverter.ToUInt32(fc, address + 4); ini.Subtitles.Add(subs); } if (subcount != 0) + { Console.WriteLine("Event contains {0} active subtitle entr{1}.", subcount, subcount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use subtitles."); + } + if (timestamps != 0) + { Console.WriteLine("Event contains {0} opening text screen entr{1}.", timestamps, timestamps == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not have an opening text screen."); + } int audiocount = 0; for (int i = 0; i < 512; i++) @@ -113,7 +145,10 @@ public static void Split(string filename, string outputPath) AudioInfo audio = new AudioInfo(); audio.FrameStart = ByteConverter.ToInt32(fc, address); if (audio.FrameStart != 0) + { audiocount++; + } + audio.SFXInit = fc[address + 4]; // Sets the credits scroll speed. Higher values equal slower speeds. audio.CreditsControl = fc[address + 5]; @@ -124,9 +159,13 @@ public static void Split(string filename, string outputPath) ini.AudioInfo.Add(audio); } if (audiocount != 0) + { Console.WriteLine("Event contains {0} active audio entr{1}.", audiocount, audiocount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not contain active audio entries."); + } if (fc.Length > 0x9900) { @@ -137,7 +176,10 @@ public static void Split(string filename, string outputPath) ScreenEffects screen = new ScreenEffects(); screen.FrameStart = ByteConverter.ToInt32(fc, address); if (screen.FrameStart != 0) + { screencount++; + } + screen.Type = fc[address + 4]; if (battle) { @@ -163,9 +205,13 @@ public static void Split(string filename, string outputPath) ini.ScreenEffects.Add(screen); } if (screencount != 0) + { Console.WriteLine("Event contains {0} active screen effect entr{1}.", screencount, screencount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use screen effects."); + } int particlecount = 0; for (int i = 0; i < 2048; i++) @@ -174,7 +220,10 @@ public static void Split(string filename, string outputPath) ParticleEffects particle = new ParticleEffects(); particle.FrameStart = ByteConverter.ToInt32(fc, address); if (particle.FrameStart != 0) + { particlecount++; + } + particle.ParticleID = fc[address + 4]; particle.MotionID = fc[address + 5]; particle.TextureID = ByteConverter.ToSingle(fc, address + 0x8); @@ -184,9 +233,13 @@ public static void Split(string filename, string outputPath) ini.ParticleEffects.Add(particle); } if (particlecount != 0) + { Console.WriteLine("Event contains {0} active standard particle effect entr{1}.", particlecount, particlecount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use standard particle effects."); + } int lightcount = 0; if (beta) @@ -196,16 +249,28 @@ public static void Split(string filename, string outputPath) address = 0x26800 + (0x44 * i); LightingInfo light = new LightingInfo(); if (i < 64) + { light.LightSet = "Light1"; + } else if (i < 128) + { light.LightSet = "Light2"; + } else if (i < 192) + { light.LightSet = "Light3"; + } else + { light.LightSet = "Light4"; + } + light.FrameStart = ByteConverter.ToInt32(fc, address); if (light.FrameStart != 0) + { lightcount++; + } + light.FadeType = ByteConverter.ToInt32(fc, address + 4); light.LightDirection = new Vertex(fc, address + 8); light.Color = new Vertex(fc, address + 0x14); @@ -214,9 +279,13 @@ public static void Split(string filename, string outputPath) ini.Lighting.Add(light); } if (lightcount != 0) + { Console.WriteLine("Event contains {0} active lighting entr{1}.", lightcount, lightcount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use lighting."); + } int blurcount = 0; for (int i = 0; i < 64; i++) @@ -225,7 +294,10 @@ public static void Split(string filename, string outputPath) BlurInfo blur = new BlurInfo(); blur.FrameStart = ByteConverter.ToInt32(fc, address); if (blur.FrameStart != 0) + { blurcount++; + } + blur.Duration = ByteConverter.ToInt32(fc, address + 4); blur.BlurModelID1 = fc[address + 8]; blur.BlurModelID2 = fc[address + 9]; @@ -237,9 +309,13 @@ public static void Split(string filename, string outputPath) ini.BlurInfo.Add(blur); } if (blurcount != 0) + { Console.WriteLine("Event contains {0} active blur entr{1}.", blurcount, blurcount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use blur effects."); + } int particle2count = 0; for (int i = 0; i < 64; i++) @@ -254,7 +330,10 @@ public static void Split(string filename, string outputPath) particle2.Unk6 = ByteConverter.ToInt16(fc, address + 0x1E); particle2.FrameStart = ByteConverter.ToInt32(fc, address + 0x20); if (particle2.FrameStart != 0) + { particle2count++; + } + particle2.Spread = new Vertex(fc, address + 0x24); particle2.Count = ByteConverter.ToInt32(fc, address + 0x30); particle2.Unk9 = ByteConverter.ToInt32(fc, address + 0x34); @@ -263,9 +342,13 @@ public static void Split(string filename, string outputPath) ini.ParticleGenerators.Add(particle2); } if (particle2count != 0) + { Console.WriteLine("Event contains {0} active particle generator entr{1}.", particle2count, particle2count == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use particle generators."); + } int videocount = 0; for (int i = 0; i < 64; i++) @@ -274,7 +357,10 @@ public static void Split(string filename, string outputPath) VideoInfo video = new VideoInfo(); video.FrameStart = ByteConverter.ToInt32(fc, address); if (video.FrameStart != 0) + { videocount++; + } + video.PosX = ByteConverter.ToInt16(fc, address + 0x4); video.PosY = ByteConverter.ToInt16(fc, address + 0x6); video.Depth = ByteConverter.ToSingle(fc, address + 0x8); @@ -284,9 +370,13 @@ public static void Split(string filename, string outputPath) ini.VideoInfo.Add(video); } if (videocount != 0) + { Console.WriteLine("Event contains {0} active video entr{1}.", videocount, videocount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use video effects."); + } } else { @@ -295,16 +385,28 @@ public static void Split(string filename, string outputPath) address = 0x26800 + (0x44 * i); LightingInfo light = new LightingInfo(); if (i < 256) + { light.LightSet = "Light1"; + } else if (i < 512) + { light.LightSet = "Light2"; + } else if (i < 768) + { light.LightSet = "Light3"; + } else + { light.LightSet = "Light4"; + } + light.FrameStart = ByteConverter.ToInt32(fc, address); if (light.FrameStart != 0) + { lightcount++; + } + light.FadeType = ByteConverter.ToInt32(fc, address + 4); light.LightDirection = new Vertex(fc, address + 8); light.Color = new Vertex(fc, address + 0x14); @@ -313,9 +415,13 @@ public static void Split(string filename, string outputPath) ini.Lighting.Add(light); } if (lightcount != 0) + { Console.WriteLine("Event contains {0} active lighting entr{1}.", lightcount, lightcount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use lighting."); + } int blurcount = 0; for (int i = 0; i < 64; i++) @@ -324,7 +430,10 @@ public static void Split(string filename, string outputPath) BlurInfo blur = new BlurInfo(); blur.FrameStart = ByteConverter.ToInt32(fc, address); if (blur.FrameStart != 0) + { blurcount++; + } + blur.Duration = ByteConverter.ToInt32(fc, address + 4); blur.BlurModelID1 = fc[address + 8]; blur.BlurModelID2 = fc[address + 9]; @@ -336,9 +445,13 @@ public static void Split(string filename, string outputPath) ini.BlurInfo.Add(blur); } if (blurcount != 0) + { Console.WriteLine("Event contains {0} active blur entr{1}.", blurcount, blurcount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use blur effects."); + } int particle2count = 0; for (int i = 0; i < 64; i++) @@ -353,7 +466,10 @@ public static void Split(string filename, string outputPath) particle2.Unk6 = ByteConverter.ToInt16(fc, address + 0x1E); particle2.FrameStart = ByteConverter.ToInt32(fc, address + 0x20); if (particle2.FrameStart != 0) + { particle2count++; + } + particle2.Spread = new Vertex(fc, address + 0x24); particle2.Count = ByteConverter.ToInt32(fc, address + 0x30); particle2.Unk9 = ByteConverter.ToInt32(fc, address + 0x34); @@ -362,9 +478,13 @@ public static void Split(string filename, string outputPath) ini.ParticleGenerators.Add(particle2); } if (particle2count != 0) + { Console.WriteLine("Event contains {0} active particle generator entr{1}.", particle2count, particle2count == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use particle generators."); + } int videocount = 0; for (int i = 0; i < 64; i++) @@ -373,7 +493,10 @@ public static void Split(string filename, string outputPath) VideoInfo video = new VideoInfo(); video.FrameStart = ByteConverter.ToInt32(fc, address); if (video.FrameStart != 0) + { videocount++; + } + video.PosX = ByteConverter.ToInt16(fc, address + 0x4); video.PosY = ByteConverter.ToInt16(fc, address + 0x6); video.Depth = ByteConverter.ToSingle(fc, address + 0x8); @@ -383,9 +506,13 @@ public static void Split(string filename, string outputPath) ini.VideoInfo.Add(video); } if (videocount != 0) + { Console.WriteLine("Event contains {0} active video entr{1}.", videocount, videocount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Event does not use video effects."); + } } } JsonSerializer js = new JsonSerializer @@ -407,7 +534,11 @@ public static void SplitMini(string filename, string outputPath) string dir = Environment.CurrentDirectory; try { - if (outputPath[outputPath.Length - 1] != '/') outputPath = string.Concat(outputPath, "/"); + if (outputPath[outputPath.Length - 1] != '/') + { + outputPath = string.Concat(outputPath, "/"); + } + // get file name, read it from the console if nothing string evfilename = filename; @@ -415,18 +546,29 @@ public static void SplitMini(string filename, string outputPath) Console.WriteLine("Splitting file {0}...", filename); byte[] fc; if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) + { fc = Prs.Decompress(filename); + } else + { fc = File.ReadAllBytes(filename); + } + MiniEventExtraIniData ini = new MiniEventExtraIniData() { Name = Path.GetFileNameWithoutExtension(filename) }; if (outputPath.Length != 0) { if (!Directory.Exists(outputPath)) + { Directory.CreateDirectory(outputPath); + } + Environment.CurrentDirectory = outputPath; } else + { Environment.CurrentDirectory = Path.GetDirectoryName(evfilename); + } + Directory.CreateDirectory(Path.GetFileNameWithoutExtension(evfilename)); if (fc[4] > 0 || fc[8] > 0 || fc[0x100] > 0) { @@ -450,14 +592,21 @@ public static void SplitMini(string filename, string outputPath) SubtitleInfo subs = new SubtitleInfo(); subs.FrameStart = ByteConverter.ToInt32(fc, addr); if (subs.FrameStart != 0) + { subcount++; + } + subs.VisibleTime = ByteConverter.ToUInt32(fc, addr + 4); ini.Subtitles.Add(subs); } if (subcount != 0) + { Console.WriteLine("Mini-Event contains {0} active subtitle entr{1}.", subcount, subcount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Mini-Event does not use subtitles."); + } int effectcount = 0; for (int i = 0; i < 64; i++) @@ -467,7 +616,10 @@ public static void SplitMini(string filename, string outputPath) int frame = fc.GetPointer(addr, 0); fx.FrameStart = ByteConverter.ToUInt32(fc, addr); if (frame != 0) + { effectcount++; + } + fx.FadeType = fc[addr + 4]; fx.SFXEntry1 = fc[addr + 5]; fx.SFXEntry2 = fc[addr + 6]; @@ -478,9 +630,14 @@ public static void SplitMini(string filename, string outputPath) ini.Effects.Add(fx); } if (effectcount != 0) + { Console.WriteLine("Mini-Event contains {0} active effect entr{1}.", effectcount, effectcount == 1 ? "y" : "ies"); + } else + { Console.WriteLine("Mini-Event does not use additional effects."); + } + int misccount = 0; for (int i = 0; i < 1; i++) { @@ -492,13 +649,20 @@ public static void SplitMini(string filename, string outputPath) int unkdata2 = fc.GetPointer(addr + 0x10, 0); misc.Unk3 = new Vertex(fc, addr + 0x10); if (unkdata1 != 0 || unkdata2 != 0) + { misccount++; + } + ini.Unknown.Add(misc); } if (misccount != 0) + { Console.WriteLine("Mini-Event contains an unknown effect entry."); + } else + { Console.WriteLine("Mini-Event does not use unknown effects."); + } JsonSerializer js = new JsonSerializer { @@ -518,7 +682,11 @@ public static void Build(bool? isBigEndian, bool? isLanguageFile, string filenam string dir = Environment.CurrentDirectory; try { - if (fileOutputPath[fileOutputPath.Length - 1] != '/') fileOutputPath = string.Concat(fileOutputPath, "/"); + if (fileOutputPath[fileOutputPath.Length - 1] != '/') + { + fileOutputPath = string.Concat(fileOutputPath, "/"); + } + string path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename)); JsonSerializer js = new JsonSerializer(); EventExtraIniData ini; @@ -537,22 +705,35 @@ public static void Build(bool? isBigEndian, bool? isLanguageFile, string filenam { ByteConverter.BigEndian = isBigEndian.Value; if (ByteConverter.BigEndian == true) + { battle = true; + } else + { battle = false; - + } } if (!isLanguageFile.HasValue) + { language = ini.LanguageOnly; + } else + { language = isLanguageFile.Value; + } + List extradata = new List(); foreach (SubtitleInfo subs in ini.Subtitles) { if (subs.FrameStart != -1) - extradata.AddRange(ByteConverter.GetBytes(subs.FrameStart)); + { + extradata.AddRange(ByteConverter.GetBytes(subs.FrameStart)); + } else + { extradata.AddRange(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }); + } + extradata.AddRange(ByteConverter.GetBytes(subs.VisibleTime)); } foreach (AudioInfo audio in ini.AudioInfo) @@ -564,9 +745,13 @@ public static void Build(bool? isBigEndian, bool? isLanguageFile, string filenam foreach (ScreenEffects screen in ini.ScreenEffects) { if (battle) + { extradata.AddRange(screen.GetBytesGC()); + } else + { extradata.AddRange(screen.GetBytesDC()); + } } foreach (ParticleEffects particle in ini.ParticleEffects) @@ -594,17 +779,24 @@ public static void Build(bool? isBigEndian, bool? isLanguageFile, string filenam if (fileOutputPath.Length != 0) { if (!Directory.Exists(fileOutputPath)) + { Directory.CreateDirectory(fileOutputPath); + } + filename = Path.Combine(fileOutputPath, Path.GetFileName(filename)); } if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { FraGag.Compression.Prs.Compress(extradata.ToArray(), filename); if (!File.Exists(filename)) + { File.Create(filename); + } } else + { File.WriteAllBytes(filename, extradata.ToArray()); + } } finally { @@ -616,7 +808,11 @@ public static void BuildMini(bool? isBigEndian, string filename, string fileOutp string dir = Environment.CurrentDirectory; try { - if (fileOutputPath[fileOutputPath.Length - 1] != '/') fileOutputPath = string.Concat(fileOutputPath, "/"); + if (fileOutputPath[fileOutputPath.Length - 1] != '/') + { + fileOutputPath = string.Concat(fileOutputPath, "/"); + } + string path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename)); JsonSerializer js = new JsonSerializer(); MiniEventExtraIniData ini; @@ -624,9 +820,14 @@ public static void BuildMini(bool? isBigEndian, string filename, string fileOutp using (JsonTextReader jtr = new JsonTextReader(tr)) ini = js.Deserialize(jtr); if (!isBigEndian.HasValue) + { ByteConverter.BigEndian = ini.BigEndian; + } else + { ByteConverter.BigEndian = isBigEndian.Value; + } + List extradata = new List(); foreach (SubtitleInfo subs in ini.Subtitles) { @@ -644,17 +845,24 @@ public static void BuildMini(bool? isBigEndian, string filename, string fileOutp if (fileOutputPath.Length != 0) { if (!Directory.Exists(fileOutputPath)) + { Directory.CreateDirectory(fileOutputPath); + } + filename = Path.Combine(fileOutputPath, Path.GetFileName(filename)); } if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { FraGag.Compression.Prs.Compress(extradata.ToArray(), filename); if (!File.Exists(filename)) + { File.Create(filename); + } } else + { File.WriteAllBytes(filename, extradata.ToArray()); + } } finally { @@ -927,9 +1135,14 @@ public byte[] GetBytes() result.AddRange(new byte[2]); // Some files are cute and have leftover text in them. This ensures the strings aren't too long. if (VideoName.Length < 0x30) + { result.AddRange(Encoding.ASCII.GetBytes(VideoName)); + } else + { result.AddRange(Encoding.ASCII.GetBytes(VideoName.Remove(0x30))); + } + result.Align(0x40); return result.ToArray(); } diff --git a/Libraries/SplitTools/SplitMTN.cs b/Libraries/SplitTools/SplitMTN.cs index 0c637634..664493ed 100644 --- a/Libraries/SplitTools/SplitMTN.cs +++ b/Libraries/SplitTools/SplitMTN.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Windows.Forms; namespace SplitTools.SAArc { @@ -117,9 +116,7 @@ public static void Build(bool? isBigEndian, string mtnFilename) { if (!animParts.TryGetValue(item.Value, out short animPart)) { - var msgError = "Error, The animation \"" + item.Value + "\" is missing. Please check your ini file and make sure the animation name matches."; - MessageBox.Show(msgError, "Missing Anim File"); - return; + throw new ArgumentOutOfRangeException(nameof(mtnFilename), $"The animation {item.Value} is missing. Please check your .ini file and make sure the animation name matches."); } mtnFile.AddRange(ByteConverter.GetBytes(item.Key)); diff --git a/Libraries/SplitTools/SplitMiniEvent.cs b/Libraries/SplitTools/SplitMiniEvent.cs index 2a470ad5..efebbf94 100644 --- a/Libraries/SplitTools/SplitMiniEvent.cs +++ b/Libraries/SplitTools/SplitMiniEvent.cs @@ -1,21 +1,19 @@ using FraGag.Compression; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using SAModel; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Web.Services.Description; namespace SplitTools.SAArc { public static class SA2MiniEvent { - static List nodenames = new List(); - static Dictionary modelfiles = new Dictionary(); - static Dictionary motionfiles = new Dictionary(); - static Dictionary camarrayfiles = new Dictionary(); + static List nodenames = new(); + static Dictionary modelfiles = new(); + static Dictionary motionfiles = new(); + static Dictionary camarrayfiles = new(); public static void Split(string filename, string outputPath, string labelFile = null) { @@ -26,7 +24,11 @@ public static void Split(string filename, string outputPath, string labelFile = string dir = Environment.CurrentDirectory; try { - if (outputPath[outputPath.Length - 1] != '/') outputPath = string.Concat(outputPath, "/"); + if (outputPath[outputPath.Length - 1] != '/') + { + outputPath = string.Concat(outputPath, "/"); + } + // get file name, read it from the console if nothing string evfilename = filename; evfilename = Path.GetFullPath(evfilename); @@ -34,24 +36,39 @@ public static void Split(string filename, string outputPath, string labelFile = Console.WriteLine("Splitting file {0}...", evfilename); byte[] fc; if (Path.GetExtension(evfilename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) + { fc = Prs.Decompress(evfilename); + } else + { fc = File.ReadAllBytes(evfilename); + } + MiniEventIniData ini = new MiniEventIniData() { Name = Path.GetFileNameWithoutExtension(evfilename) }; if (outputPath.Length != 0) { if (!Directory.Exists(outputPath)) + { Directory.CreateDirectory(outputPath); + } + Environment.CurrentDirectory = outputPath; } else + { Environment.CurrentDirectory = Path.GetDirectoryName(evfilename); + } + Directory.CreateDirectory(Path.GetFileNameWithoutExtension(evfilename)); // Metadata for SAMDL Project Mode byte[] mlength = null; Dictionary evsectionlist = new Dictionary(); Dictionary evsplitfilenames = new Dictionary(); - if (labelFile != null) labelFile = Path.GetFullPath(labelFile); + if (labelFile != null) + { + labelFile = Path.GetFullPath(labelFile); + } + if (File.Exists(labelFile)) { evsplitfilenames = IniSerializer.Deserialize>(labelFile); @@ -185,10 +202,16 @@ public static void Split(string filename, string outputPath, string labelFile = { parts.Anims = GetMotion(fc, address2 + 4, key, $"{chnm}\\{prnm}.saanim", motions, modelfiles[parts.Model].Model.CountAnimated(), $"{evname} {chnm} EV {partmetaname} Animation"); if (parts.Anims != null) + { modelfiles[parts.Model].Motions.Add($"{prnm}.saanim"); + } + parts.ShapeMotions = GetMotion(fc, address2 + 8, key, $"{chnm}\\{prnm}Shape.saanim", motions, modelfiles[parts.Model].Model.CountMorph(), $"{evname} {chnm} EV {partmetaname} Shape Motion"); if (parts.ShapeMotions != null) + { modelfiles[parts.Model].Motions.Add($"{prnm}Shape.saanim"); + } + // populating metadata file string outResult = null; // checks if the source ini is a placeholder @@ -207,7 +230,9 @@ public static void Split(string filename, string outputPath, string labelFile = data.Parts.Add(parts); } else + { data.Parts.Add(null); + } } ini.MainData.Add(data); } @@ -225,7 +250,10 @@ public static void Split(string filename, string outputPath, string labelFile = ini.NinjaCamera = GetCamData(fc, 4, key, "CameraAttributes.ini", ncams); } else + { Console.WriteLine("Mini-Event does not contain a camera."); + } + ini.CharacterFlags = (SA2CharacterFlags)ByteConverter.ToInt32(fc, 0); foreach (var item in motionfiles.Values) { @@ -278,10 +306,17 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa string dir = Environment.CurrentDirectory; try { - if (fileOutputPath[fileOutputPath.Length - 1] != '/') fileOutputPath = string.Concat(fileOutputPath, "/"); + if (fileOutputPath[fileOutputPath.Length - 1] != '/') + { + fileOutputPath = string.Concat(fileOutputPath, "/"); + } + filename = Path.GetFullPath(filename); if (Directory.Exists(filename)) + { filename += ".prs"; + } + Environment.CurrentDirectory = Path.GetDirectoryName(filename); string path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename)); JsonSerializer js = new JsonSerializer(); @@ -291,9 +326,14 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa evinfo = js.Deserialize(jtr); uint gamekey; if (!isBigEndian.HasValue) + { ByteConverter.BigEndian = evinfo.BigEndian; + } else + { ByteConverter.BigEndian = isBigEndian.Value; + } + List evfile = new List(); List databytes = new List(); Dictionary animaddrs = new Dictionary(); @@ -303,9 +343,14 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa Dictionary pshapeaddrs = new Dictionary(); Dictionary labels = new Dictionary(); if (ByteConverter.BigEndian) + { gamekey = 0x816DFE60; + } else + { gamekey = 0xCB00000; + } + uint imageBase = gamekey + 0x2C; // Character flags evfile.AddRange(ByteConverter.GetBytes(Convert.ToUInt32(evinfo.CharacterFlags))); @@ -404,7 +449,9 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa imageBase += 0x34; } else + { evfile.AddRange(new byte[4]); + } } evfile.AddRange(new byte[4]); // Raw data goes here @@ -426,16 +473,27 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa { evfile.AddRange(ByteConverter.GetBytes(mdladdrs[constant + p])); if (part.Anims != null) + { evfile.AddRange(ByteConverter.GetBytes(panimaddrs[constant + p])); + } else + { evfile.AddRange(new byte[4]); + } + if (part.ShapeMotions != null) + { evfile.AddRange(ByteConverter.GetBytes(pshapeaddrs[constant + p])); + } else + { evfile.AddRange(new byte[4]); + } } else + { evfile.AddRange(new byte[0xC]); + } } } } @@ -444,7 +502,10 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa if (fileOutputPath.Length != 0) { if (!Directory.Exists(fileOutputPath)) + { Directory.CreateDirectory(fileOutputPath); + } + filename = Path.Combine(fileOutputPath, Path.GetFileName(filename)); } @@ -452,10 +513,14 @@ public static void Build(bool? isBigEndian, string filename, string fileOutputPa { FraGag.Compression.Prs.Compress(evfile.ToArray(), filename); if (!File.Exists(filename)) + { File.Create(filename); + } } else + { File.WriteAllBytes(filename, evfile.ToArray()); + } } finally { @@ -478,7 +543,10 @@ private static string GetModel(byte[] fc, int address, uint key, string fn, stri List names = new List(obj.GetObjects().Select((o) => o.Name)); foreach (string s in names) if (modelfiles.ContainsKey(s)) + { modelfiles.Remove(s); + } + nodenames.AddRange(names); modelfiles.Add(obj.Name, new ModelInfo(fn, obj, ModelFormat.Chunk, meta)); } @@ -490,7 +558,9 @@ private static string GetMotion(byte[] fc, int address, uint key, string fn, Lis { NJS_MOTION mtn = null; if (motions != null) + { mtn = motions[ByteConverter.ToInt32(fc, address)]; + } else { int ptr3 = fc.GetPointer(address, key); @@ -501,9 +571,16 @@ private static string GetMotion(byte[] fc, int address, uint key, string fn, Lis mtn.OptimizeShape(); } } - if (mtn == null) return null; + if (mtn == null) + { + return null; + } + if (!motionfiles.ContainsKey(mtn.Name) || motionfiles[mtn.Name].Filename == null) + { motionfiles[mtn.Name] = new MotionInfo(fn, mtn, meta); + } + return mtn.Name; } @@ -511,7 +588,9 @@ private static string GetCamData(byte[] fc, int address, uint key, string fn, Li { NJS_CAMERA ncam = null; if (ncams != null) + { ncam = ncams[ByteConverter.ToInt32(fc, address)]; + } else { int ptr3 = fc.GetPointer(address, key); @@ -520,9 +599,16 @@ private static string GetCamData(byte[] fc, int address, uint key, string fn, Li ncam = new NJS_CAMERA(fc, ptr3 + 0xC, key); } } - if (ncam == null) return null; + if (ncam == null) + { + return null; + } + if (!camarrayfiles.ContainsKey(ncam.Name) || camarrayfiles[ncam.Name].Filename == null) + { camarrayfiles[ncam.Name] = new CameraInfo(fn, ncam); + } + return ncam.Name; } } @@ -539,7 +625,7 @@ public string GameString set { Game = (Game)Enum.Parse(typeof(Game), value); } } public bool BigEndian { get; set; } - public Dictionary Files { get; set; } = new Dictionary(); + public Dictionary Files { get; set; } = new(); [JsonIgnore] public SA2CharacterFlags CharacterFlags { get; set; } [JsonProperty(PropertyName = "CharacterFlags")] @@ -550,8 +636,8 @@ public string CharFlagString } public string Camera { get; set; } public string NinjaCamera { get; set; } - public Dictionary MainDataAddrs { get; set; } = new Dictionary(); - public List MainData { get; set; } = new List(); + public Dictionary MainDataAddrs { get; set; } = new(); + public List MainData { get; set; } = new(); } public class MiniEventMaster @@ -559,7 +645,7 @@ public class MiniEventMaster public string Name { get; set; } public string Character { get; set; } public string BodyAnims { get; set; } - public List Parts { get; set; } = new List(); + public List Parts { get; set; } = new(); } public class MiniEventParts diff --git a/Libraries/SplitTools/SplitTools.csproj b/Libraries/SplitTools/SplitTools.csproj index f387d37a..5a9edf35 100644 --- a/Libraries/SplitTools/SplitTools.csproj +++ b/Libraries/SplitTools/SplitTools.csproj @@ -2,13 +2,11 @@ net8.0-windows7.0 Library - true en false false ..\..\build\lib\ embedded - x64;x86 @@ -21,7 +19,4 @@ - - - \ No newline at end of file diff --git a/Libraries/VrSharp/VrSharp.csproj b/Libraries/VrSharp/VrSharp.csproj index ae0ec1fa..6a87f486 100644 --- a/Libraries/VrSharp/VrSharp.csproj +++ b/Libraries/VrSharp/VrSharp.csproj @@ -7,7 +7,6 @@ ..\..\build\lib\ false false - x64;x86 diff --git a/SA1Tools/PLTool/PLTool.csproj b/SA1Tools/PLTool/PLTool.csproj index cd2889c6..960b220f 100644 --- a/SA1Tools/PLTool/PLTool.csproj +++ b/SA1Tools/PLTool/PLTool.csproj @@ -7,7 +7,6 @@ en false false - x64;x86 PLTool_100.ico diff --git a/SA1Tools/SADXObjectDefinitions/SADXObjectDefinitions.csproj b/SA1Tools/SADXObjectDefinitions/SADXObjectDefinitions.csproj index 17738659..558b26be 100644 --- a/SA1Tools/SADXObjectDefinitions/SADXObjectDefinitions.csproj +++ b/SA1Tools/SADXObjectDefinitions/SADXObjectDefinitions.csproj @@ -7,7 +7,6 @@ embedded false false - x64;x86 diff --git a/SA1Tools/SADXTweaker2/SADXTweaker2.csproj b/SA1Tools/SADXTweaker2/SADXTweaker2.csproj index 4e1bba33..dbbb5408 100644 --- a/SA1Tools/SADXTweaker2/SADXTweaker2.csproj +++ b/SA1Tools/SADXTweaker2/SADXTweaker2.csproj @@ -7,7 +7,6 @@ en false false - x64;x86 sadxtweaker.ico diff --git a/SA1Tools/SADXsndSharp/SADXsndSharp.csproj b/SA1Tools/SADXsndSharp/SADXsndSharp.csproj index 24e48b96..3e1a4477 100644 --- a/SA1Tools/SADXsndSharp/SADXsndSharp.csproj +++ b/SA1Tools/SADXsndSharp/SADXsndSharp.csproj @@ -9,7 +9,6 @@ false false embedded - x64;x86 diff --git a/SA1Tools/SASave/SASave.csproj b/SA1Tools/SASave/SASave.csproj index 42d3d0e7..38f86a85 100644 --- a/SA1Tools/SASave/SASave.csproj +++ b/SA1Tools/SASave/SASave.csproj @@ -9,7 +9,6 @@ false false embedded - x64;x86 diff --git a/SA1Tools/VMSEditor/VMSEditor.csproj b/SA1Tools/VMSEditor/VMSEditor.csproj index 8be18816..2c29f22b 100644 --- a/SA1Tools/VMSEditor/VMSEditor.csproj +++ b/SA1Tools/VMSEditor/VMSEditor.csproj @@ -10,7 +10,6 @@ embedded false false - x64;x86 diff --git a/SA2Tools/SA2CutsceneTextEditor/SA2CutsceneTextEditor.csproj b/SA2Tools/SA2CutsceneTextEditor/SA2CutsceneTextEditor.csproj index cc2bdad0..169aaf46 100644 --- a/SA2Tools/SA2CutsceneTextEditor/SA2CutsceneTextEditor.csproj +++ b/SA2Tools/SA2CutsceneTextEditor/SA2CutsceneTextEditor.csproj @@ -9,7 +9,6 @@ embedded false false - x64;x86 true diff --git a/SA2Tools/SA2EventViewer/SA2EventViewer.csproj b/SA2Tools/SA2EventViewer/SA2EventViewer.csproj index 05669803..e7713a89 100644 --- a/SA2Tools/SA2EventViewer/SA2EventViewer.csproj +++ b/SA2Tools/SA2EventViewer/SA2EventViewer.csproj @@ -5,7 +5,6 @@ true ..\..\build\tools\ en - x64;x86 icon_sa2EvView.ico diff --git a/SA2Tools/SA2MessageFileEditor/SA2MessageFileEditor.csproj b/SA2Tools/SA2MessageFileEditor/SA2MessageFileEditor.csproj index 64937dd9..410ce2eb 100644 --- a/SA2Tools/SA2MessageFileEditor/SA2MessageFileEditor.csproj +++ b/SA2Tools/SA2MessageFileEditor/SA2MessageFileEditor.csproj @@ -9,7 +9,6 @@ embedded false false - x64;x86 true diff --git a/SA2Tools/SA2ObjectDefinitions/SA2ObjectDefinitions.csproj b/SA2Tools/SA2ObjectDefinitions/SA2ObjectDefinitions.csproj index 1fb70ad8..65f3569a 100644 --- a/SA2Tools/SA2ObjectDefinitions/SA2ObjectDefinitions.csproj +++ b/SA2Tools/SA2ObjectDefinitions/SA2ObjectDefinitions.csproj @@ -8,7 +8,6 @@ embedded false false - x64;x86 true diff --git a/SA2Tools/SA2StageSelEdit/SA2StageSelEdit.csproj b/SA2Tools/SA2StageSelEdit/SA2StageSelEdit.csproj index 935799df..20190d76 100644 --- a/SA2Tools/SA2StageSelEdit/SA2StageSelEdit.csproj +++ b/SA2Tools/SA2StageSelEdit/SA2StageSelEdit.csproj @@ -9,7 +9,6 @@ embedded false false - x64;x86 diff --git a/SAFontEdit/SAFontEdit.csproj b/SAFontEdit/SAFontEdit.csproj index d835494e..b5eed019 100644 --- a/SAFontEdit/SAFontEdit.csproj +++ b/SAFontEdit/SAFontEdit.csproj @@ -8,7 +8,6 @@ false en embedded - x64;x86 true sadxfontedit.ico diff --git a/SALVL/SALVL.csproj b/SALVL/SALVL.csproj index 55280f9f..f0708cf0 100644 --- a/SALVL/SALVL.csproj +++ b/SALVL/SALVL.csproj @@ -10,7 +10,6 @@ false icon_dxLvl2.ico embedded - x64;x86 diff --git a/SAMDL/SAMDL.csproj b/SAMDL/SAMDL.csproj index 48ce3b1e..e48fc2e1 100644 --- a/SAMDL/SAMDL.csproj +++ b/SAMDL/SAMDL.csproj @@ -10,7 +10,6 @@ false ico_samdl.ico embedded - x64;x86 TRACE diff --git a/SAToolsHub/SAToolsHub.csproj b/SAToolsHub/SAToolsHub.csproj index b0e059c4..20b34110 100644 --- a/SAToolsHub/SAToolsHub.csproj +++ b/SAToolsHub/SAToolsHub.csproj @@ -8,7 +8,6 @@ false false embedded - x64;x86 Resources\ToolsHub_ico.ico diff --git a/TextureEditor/TextureEditor.csproj b/TextureEditor/TextureEditor.csproj index 3885c191..fc6f954c 100644 --- a/TextureEditor/TextureEditor.csproj +++ b/TextureEditor/TextureEditor.csproj @@ -10,7 +10,6 @@ icon_TexEdit.ico embedded True - x64;x86 true From 9773d986da7f1c1d61c21a7506b605a636104ddd Mon Sep 17 00:00:00 2001 From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:38:13 +0000 Subject: [PATCH 2/3] Remove SACompGC DLLs --- Dependencies/SACompGC_x64.dll | Bin 13824 -> 0 bytes Dependencies/SACompGC_x86.dll | Bin 10240 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Dependencies/SACompGC_x64.dll delete mode 100644 Dependencies/SACompGC_x86.dll diff --git a/Dependencies/SACompGC_x64.dll b/Dependencies/SACompGC_x64.dll deleted file mode 100644 index c32f263903ec9e7d17f70479aa52a09d4ac3f52a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13824 zcmeHNe|%KcmA{i@!XzP1v>6Nv>jNhxip0PmCWOEY%-|b4sVO9g@*|lfZ^+bSW_IQc z1lJ#7C$Slxv!z{asXw|Xwzd1QU92t*XuA`FCgFz$a5adoDBJoVuAfNzK~U@4?|JV{ zGNH8nW4E8(?fUY$bIv{I+;i?d_ug~QeJ|B_Zey8@u`CotVXOy`9=rPcCw>f!U3Sgh z%h>ZdhiCK{Jcno0w)i7lC>-1n_O@|N-asHIa*YBPjs`e?fOFoql4}b#3#Iw_xmI2E z>o?Ud_;&3=Aypo|;m5*5s3&JsHh)WnOPas0!o|&xsIWq%Kd_{-c^m5AuB{Ya1l&Jk zUi06paG?%g60~}`T3_LBY9SjJkEq7QSn~tf?Cjk48dAJbHj~TCxNJI`0?JH{+AtNc zK*c*SYz@y~EL$awL$(bBaweWk)&NnhQ40KiU89sOWGsm`qk!$yIKx_0Ze^3m@N%Adqpo} zg(L%=>UKW%K^ZSy;1i;C^&VPAiscN)7%vUWdlf}-*#`NzXyrUoKQA5QC6i)# zj@YsNW%cXVj46i=`%3ffr4=6Os8hOga%HbM_5&z$N=sq$9&3?#_l4O5_Uq3(j-7IK zC8Gt-@}=d`TwVgpA@!~4djU!rSt{VAaFKM-e*HU+?mH`7(&REnEScpn4?3h?XMCy2 zZr=UI>;uP69+Ra5j$@~tdBd*wt&<&F&eNKR7W0V*2yyf;H9;YB$CnnlE0>l;O>Su^ zM>WUix0dq~?7*yQeof!?y{h%@r4_S}JEUXB&PWH*O~!`W&7m)Kv2WUX;H2#oh_MlDSr6XG^R(h8O zEYv#S$9Ch=QCf^2?+Cvx*h5Q zk+1k1N>J-ciluwV%`zj3R6XRBs&{l7c%|2&VA-G!v!}lU3F+0-w^L7dSHCGA`<;rM zAQg$#2DuM)Y8Xpq@KW87bM}Bos@ug&2Ru!EZ~^IX+YWflzc?=D?^yz6j@bvD((#dO z#|w6LQ;ENj~;+mL?oM=9KO;In1v* zw!BZCGUyL$0oB9%q0?(VRg_c( zkXG6xUMYSEXZZNa9p4XpW&XPr2$=MCMq z3}OlWOo@GB5OaHIzR}H+K6xWDfDxm73xIidQl+`2A%dsP5W?y zmbxJKK&Ue*-X{0wp!P`?ex`!NCoGR(#PF5`Ab+067|xsP}97K|2oq?h+n19d59dZhew$RZue z5ykjYIZ|!v;7EooN$Ultt7yfMbB~pWFF42gzCBRFFM)O2|Q8%r9>jlZ!h4x*^ z`}4KNb~Gug?^6ci##S)ol^CY#87@|JwhEn&-Yjpx$mCoa{{?h6R{SRD48zET0ozgg z)>q}}z|IX{eIjn1Qm9!j!CHxo)iIBiXhS#HCze zEsloRe!F9R{d(F@gZhRY4#wQ4mC9(aCZB&AMySPvcc{9Q@fUHR0qKg&S7V4N=HCvE~g?#bd(L<2A7hf+i|yx~gpP@(CI z?JtKT?OGCQ=cVI{<(n3?mYzEgr8eZANj_0)ZGaCI%T2_=SS$Egv$Y&O@K{@T30w~% zKipD==_6u@DkYS)uBB5h8_ksdn38eNvov{n&Z;uiJWh>4#$nte_!s6q`Ocj0%?4K4 z7Zv%KPy{R0MT+GtZce=9Dng!Apje(lO-k}}370iIQO#-flT>$cXojeIlH+Z_ZLR{| z*30j~8HNX%u0_Q*Zi+WMd*S`M`DA1*g2cx|s4k`|W`12C#bH`h1$?aPeT;@hvlYwj zFf<;C55cX65zDbk7Jz}ZnaKYI>ZdPz_QW1pO*3F9iLEHGL^vn;_Sjj8da3FTIDkFCq3X=d>N}C$R2c8Y z%_Q2+H|6gFfQ?kMCFUn}A>hk$1DiOC(F z#AIBb3a#$SBVv(s>ts)5Z#WmX$;@6)Wio8SWvFE29prsDm}sRG#_qPVdkM?My37X5 zP?u>@pXQ^j$K`&w)^-$r$?H53oy32`vX?@b>dKTK{|OYf^|+YTc{Dm%{tyjtj=m3& z8ZfP~gz-4U`eMatl{HbWQIDT5*ECw#UOp0WLm+<|my}ugiAAi5CJ}MgyYI>e%wpEkYpbl#WWH zwn0Z?nZcDeV1ClE<*Yv-xZ_z?SKa~W$&xO>@g}@%nH;U*WBK32doQJUbctfFN@g3F zSW?xHox#KzRUrab8FyXy47n7y$;u)rHNwA0vI<~){p5mQ)iID~uip;piZ;`Y6SZ)!zry-(mIl zfcpEQ`ukJ$cZd4BPyIcl{*wHmL%R%p(5;<^)sh3@A9wR3GI;5yEyZ1zgr2|Yh@Co* zOTFV9%fj_u{E|bmo2r{?vOXU6WFFz020YguaX0ndDis#+(y{^^rvRpNPD7?y%rox> zjGY|yWDa<2Ff+L3wEygc8ypR5{Jy4~)W$jSH;rE$MnCO!ICC&PXSP<`DYmUU{Tc3< zhtkNLd()>`b)C)R%_r>!+;DK#)YsT|D?zZ&2qQm!e__+?x>T+-CFsZ{I z>TriHceh?|(4kX@WjdUuL(Ljv!;3WRybhB(O!4odYbu_<)1g+wD}CMGzv=Y-I{cXq zpVHxW9Wq_MP_IwZ>nVMWI-S?yMjbBDp;d>|bZFOMs}3K~VM^Z(Ggt=&=oB2fR;!O* z1XJ?=RajG_>(^mQAKfO>pKznbS?+HYIDD+5FLYjxUc0r0Zdt~8!%Z#zjY4TINo|5` zabzJ^7ia=EEJPwgGglnt8aInVgeyrA{lNei_KN->S6n*JS6qCZ)|xcjVW;2Jw>6{+ zj0kVxka_E`fZ$2-CIc@-nRXM(HN+X`QD9w-#%17@UBttiya`V^IsMP@m@e{b%Eaoq zn%`S=n4*utKU06k^k0N@%-8yJ5t%jU{R`=^U56#BE-im?`#)E`2#P6{*^V_qp9l8? z5>1)P*x%sQ+cuO6ywJQ2WW6&$hr`8 zjAO3$t+KSNtjV_l-)2y!_a~*xR^Xbs%t12U6KS|P!7meNZdGpkM4BqMV*;&4m3w+3 zO_kd9T@A4twn#dx^-i)RcvcUo%Z-MV{+EJ@4maa5yNBM zxEQMA3yV!ww?nnFZ3691)z0>GTCFCxV**W+dm6NEveT}8M^1f5FBP;peNU(U=ss7! z7}r*6bE(s8V6zs`(&h%e$2f5o)n<;hrRi0_W!nK#-?!~G7!T6n(#A-H*sMYOUZ47| zP2cfBf`9P++FAzhp$-}y4mwTk6Vd3XJ4%Vzm2az-beG$u0}GE}=IWH&#H<%?!!oPQY` z#h!W{o2*5*kzR+p*yR=zvxqs&(maV-=4Ug@yvt9H&eYz?4?KOv#Y{WP8No~)Ij>F-(JYxf_SzN`Ut9hS&>m=FlRF}#$v`;%=7X> zh8zRSX$0St#Z2L>5d2i8_q)tMewv@d^5iVbwEHtsg zW|Z1VtPnN|=M{tu79)JOmst!wESqFhe`K@VdD$VYKj_PRBQsx-7b0I!|LI9V!YQ91 zxD|Vg=yYeJvKsYPln#_p1WlSh`ahBez-=gxg8mH33n(w6yoo{@GFT?&Ar*_&@Y~$l z%A7(f!&n;i`Gjy9fwC92JS+%0=N3U6mlm2=`tKIlC1|d8CS#wco($w{9c7Gh*ypKd zG4jG5&_Zdn2GC5{xu!H)2WUGWM{y(dWZQv(cB$u!JX`b1e|Mg3V)gaQ>LVec$?x+w z)wg&9&8=7}tQho&*jz7e4hi-CfG=3zEJVa`aC3dDKO!P_u{NPCA^=;pY(?EyYu(kZ zx%10PY2C3pCbav(i8CKw=70cQ-lniv?+-TC`=Ws+CNf`BYcL`(_6_EX2*O=h!Kyuf zupW!HEf}cZ=nIAY0nx{{GT)}KUxe&^%ohv^f%*vRV7^dPj3CqTVG-lK2tjW%o66d} zt?K_TEnw)iUlfIK8@qWNuNT-7Rv!^s>V5uJFzczqMGQs*KL3VjSf~$p!{OkjdT)5c zM!dMwTKc`M*bym~5ZLGs2Lo+F0Arj#K_VESk=KjfM(i*A>s!6hE;L0&p?(5m3hZef z@`n6#+9Go{`2%y{pE>wHKhfVN%xRrFXYL%$nHNc5O8mh;!fz40p>#I;*Q^y{>oRXh z#MqVv@p29SrS=xlJi*{y(a>_t25ue!S3nGJX6zJkR{6tX)Z1DYK)0H4iW}|x-zF@e`8)(8P;3XKJ@%!4{&8#?$TH8X40z~#3qORN= z5rwu|IM@-P07w`sHaPtenl4S)<8KUm!<(036-8Ju(~TvhP5w#`mOW2vtP8z$3XRbX z8-#GGmtS$M_^Qieo2RY+OU17*Xn&a=IJ}NK>U&L5QeQPwXFHwi87Mb$`nb<)km%9v zI_(Saf8GNH1&j$ObdO5EAJBc`rzkIiPVjo<`$ND9dQj+pJks;~^!ota3lb(BKcRL|zH{ z(||V=K_75}>yT@EAVdGV{W!`!z;^(?hOz@V!5?0QcLuC!5QQPvCW!ZuDqaS71b2wZpwk`j z4ixIcTEL&9&|MPmEZI>Mj@km!dzBL41nDj$!_Nfio(#w^0a3kaktgnp;{n zixcoZx!E7sP&KQrcKMw0SzJU!+U{*dl36utvk;lJWO07(A}?Myw>7qI=Aa-DshSlH z2Np(}T7))lWKNsEDIAOhec~Ks+Y7ysw$hDrXK_fc{61v)tJ1AO6~`?S!_kQ7#x+3K zHuFztv&~f7p=AUKFw*zUdL5Lo@YhjT5t?hl{*B1PHVBb1W;)xY=FS+lN7yK|a;@}R zHOm`u2Q~)p62h~%sNc~#pS!- z?k8aZY1+G+o4dKmj&|SfdvD*qef#$9ek;d@JtUD3qDGcwLJkAcRLaUPF2+Hgk@4yb za&YR&xrbG&PR_0L`htemK+EQUyV+3h_WN6SLmg)b2!4alZzzAH!qD8(z~!W*Ov{Xl z{^Q8V<`;K$=f(2AOSAI+8ST&HF3U>{c36JEV5en2gHKvs0DSF(F3S%AU)?#6YWPkFsOiG3n39;_vI7PM#)Y>hQWPX+C<1s z;5V5F6MY*!iZ}y$X*|&g+41dL>Nz~u#sfD#69v_a&NZqxYAhKrY)+uT&ASO1ng$eP z5-sv9q^A@(gt%AP8(j?m>=ArI>O~AQ-3zj?EQwW_&Rxi1LE3G$+6{wSbY% zooqs;^6o{BOQnQ77}xx=`roj?;XP$U-#2t4trbVBL_yQ2lGA#OL?1e??saHaH*Ix|#GvNBOJ|3B z1UYOU@4hM|cYHIG@ZS{6QjZv*^g7+4a|_=TZN|_EweGao9}a5H4xg38H>cXi4;b#V z%V+;B{7r37S(dBwI_V%pFra4=t@W2_(4U0MQj5yw2+3kuI;z(n&J^wAwU3JbTGMym z+dWX`%-KJ%ffhQ(&klzxv}YxSdSkjn(7&Q;o%pHvo_MWW=9hIYsc@II@C(GX8eK*? zA>F^=?+{Om$3h<@hK45=o=!YfG!QgE-_8=sDEy}T0-q2zi_0`F-9T*?ETnt1rq5Mt zjsRd7W}m$0)ulvlej{w3sHhS@7T@c>s_S|f9^QRH*Hs3%&K&8tpQketKRaRnm@K^R z3EMwWh7iy7*st;T>oPhh9XieuPl^3eeNH95Su~&v^?(vOrtU0cI$aPS(ukLIgPk8x zb##Z8X?yIK08)DFmjN^pDY?gfrFZG#(C~1-{T&(w5>JF3Lt)366ZSDVT=RaoW;85Z z3=6|yyVSdO=m_16(#-1!vTKLBBfQ}VwZ24v5FMjEs-4QIE^h1uz=+oP(l74}v*gh)0yYO7UeH{IXD7@dhK0!RTpk~N?LibvPpL!$%=!F9# zNo>{5{tiN?f4p-ZYQ{<{)-*Qk1?EDw#Sgv;Uf(e6QA_XbSUB|0W*%_kp~<|1HF z2Z$~)>@V6i&^e>i%2sxID56%X!Y5*>MmNCLtftQ#iLI9`=*6{K(V>xk1C_A@ZU~F5 zXX@m7Lb&MA!iBu=V^27H?c-s`m{U&MiVBCgzeZkn?f8s()kNrcs`;d=_ECu*7IZ-y6O@qT^bXTe z(>j=Ov@}v}LN#u^+2YlF)Hxx`bpI*qKP_z6)W}&>3R|&xW5n5QX!M?^Rk_^%i%+N~BuoV+{o_6kzJgzoJ zMtm#wGg0#LaQj7S0x2I8>#+}q+b0xjBnVriKhhb$gawjR=pV{rR$|-*7>Vv7jiPY1 z?$Fq^U*C0g-Zez6*aYtZk9gu%&BXSLvM?;oVv38xMd^nagzEbU(^u<#hU$BQ+N53E zEepDWVyfxmQ_PW%ehGM2EG`2 z_YL&^geZ4NRtecS9OqRysT2`-oC{HpdKHURT~WoRimnL%Ng+8=SfPl1a8fjHQBdVf ziIGeMW>K|THhR@*bVuW-r9wEEGju$?Pvj)?)k$mJZYXSuD$#NV3lG)UM)(R1jHeVi zF_);N&JNa4yH+J6NnP;U$+2F6?xEw_C=1prO-=ns(8y_XQ1MPxlZc$AK^3t^3&5@u zouir1vGGnhO%D_zcT!_Q^~nYM=PxDta7rdE(+sq{dk!rv>9j0PMd{g{R?0w19s_sl z8A#GHkfmW@ks9FHZzov+L_67kKZEN1M!;UXX1|TLyWdCb=uc|H%BzTqJWq-H^U&%~ znvaqy-k)?oqtYE~jn*2~>$gNme}@fitRhj`A`3R*RY~J$9~~xQ3IUzAz3*U#(lE?4 zs9dB{L);b8YrhiW#%Y{3fQ%cB*?t8#2RSVhO%tumS1P^sQ83-ln8tb?6K4CU**;-D zI@qTSS+(xxU;ka{PhY2Bc15Rob@wUZUTH5jzc^5IT9|U=5fDda06Q&Z=5j)g4(q26 zgqgC}-gaR-L(5vG7hT*tLdDb>h%l8cAVD3GfUd1~1p=0wmJUoGt4qIOyX&x%UM;2X zeu4p4s6(2}@Cvo`dpbOAC7?xxBRW@!D{P4ax_?=k+PgYE@eC@-TgK)mUMf1r&&J_e z^pG|%O?*(3_@K6EAfOE$n_qNJ_=7ou+oyPJ#I(psMYY%u0tT(pqf(k#s2oZKvd*T0>4^Zlq6IhQAV%w~v*o`iPSJO7V@^@cFXt}Nu>LgsTsXgz- z#=l3=q=a_GOmyB>s@P(s$uG=}j2J_MayW(R8&2`EvWb-)LgJrcpqSOHMQsA-Qb}vpaipu z_-KZU<;ew&iPEP~zF(a=gt_;!c+&_U{2>d^+Hm)7OeoyjL(8YTX!%?REq}6;many; z^z456`wa9x!@zSq1Kq6*{Gf?}fARu6`|a*$0Ytkx+`Si-URv3QNc)(9-QFJ*td!1N|+i4X+OG-PUQNY8rY?mOUxjr-$LGMk zk10DdtBX!CG@2Po(St$NI4yRh>AGH|%-k3;N1%pzu($pF3f=d_%a4Yqgtw`~k7&$; z;dNTk{ywfNxVU#-^YdJjXqPNLKerO9iS}X3a?UTn+z7%-*IsUe z1`_&{s9~rt?WdS)M+wZN>-r85p#il*MfXW6(eT?T7t!Rzdtz?z1}mb}o(FL_Z7y9iSbe+!Xp zuPMGZC;kbk2f^|&gd1#40k13vDB8Hc~kT8H;AfWSG}hxxM9R!GPpT&Leb zmXIfqUjl9~@^?|M1zdrgi=2*3)A&P>Z{~h^n zkzYp60ga}Os6U9@iflyw8uBdULSzqe2Qp2S*uF~buP^BptqnO)N60c?6KBAqG<}J7 z8|Vu_bL;XlgF8^~^=;*H=<6og2EMFdp<%7R9@GFA3~~*IEWuE>o#%pv`7xxg#cv3> zd0&emD<{{Jm9;?WO(j&9((?8+wv^&xZ_L!GOOcP~BB!H*6r<7SRr=(tHY3lblt~)> zu$qs~>7b?GLYu)jCySp=R{zsA8pa~I%GRV`d^ZVzul-M^4jL=}3kl(!tf?rkIQiIn zSDyUGlgqjvdFa?>&*@)Nb;}DkF8A>(gu0CtOO&}`8ll(SbU^AqnY-j z&)mz)DpygB=sP)kGtX@H1I^yT_W|Vi=)-p=J6B*U_Jp2eG}e1I6M~O#rCqkBGIMwd|2X4kOzJoX6oQ&`A%{a#Qvzu_0j4uM5p6bhVsbqY($CEJ? zaM3q@thu5GYi9=AqHp@tPj|xa6u!(IJ9aeGVS1z#v!(}mPJpk^T)C8ug9AJcw}Fkb zA|6+%@Zs>DKSk-Z?-=SazIWo}{PIqsA4jGIu&B(P@m94kY)|qbC8Y5XJAOt6g(a-5Qm^qm@Er$T$Hk$<0rYfh6>*fj(iTz-bPko?P6&H zb)2`v8;7&vJi&=e_Qc^f0M`cG#yH##;L3rc{t-*B7orB-=cWJa=VBIdxq^Iyi{IYL zxqN<4i>rYP@`0A^t|niQ$C*uT(6Y_t4s71a zW=*B|+)ePU7>V<5^#xk|&72=|%vWSbIa>U5<}Th{2TvuL)Mi}0z;mvf2zO#U#X{~@ z-=gN=qHR9^BG_jU{^90*&D^3U(<0L%#hABnV6l8HUqJVA?$&rR`BBnZzp`QtcD8=F ze_$VB>V$kFseESmD)$Acu@&Z3zPf-ru)PdE5G0<&l{c2IVinwZ1@(|8plvxHHUxQ`OztLx+T!f(Trhh{Ny;>v8=qm#bxqq15a16MXA1#;VX)rIHM@h0ntkd{f*=ou*AWZo@I0dWXM}sJX!Nv!KAiomFWK`Nce?gl09@Y;%gE$6o zh;5IyfeCQm5HJeY;0*Y-BA#vLf;WiqWIH=SFzr>`R<6m=M9boAcW|YDYs(fckZllr zOY3QHF3$G2n}S@nVet()w#9#b6x-sPbh0hJF*$U%Esog@ja$~@bDMhHjj?Vj<6Xvl z<7U$X=7-Gd&9&xM^AqO1=I6|xnDu#g=iQ%Y$t%h8 z`jYj4^^o;v)??NI>uKvb>#wXAts~Y;)=#aff~f^F3+^tsw_ss`si3I9Ua+=+D-a4E zD|oKp<$|9S94k0qa7W=?h4&X)3(E^1Ds&cZEIeDdt?2KI28uo_nrk!KmfIY*3R|_! zW#epHY#p|zZO_`iXFF(n-F9!Wxp-Z1V{v{-RmrB3?Ill?JXP}Dl2=N8Tymo1gOckd zrAzEfHZJijX;}g*8E{twm}Sf`W*h5_O-8}^nDINtXN_+e-!cBmIAXkFoMpP(WHc3; zN=?g5t4wQ5>rJ($22-P{)wI?0B>h^zy)qMEA9|cOYIF6u>A5|*UQ3Tn87A^ From e9ba4e1d5c9597749595bea0dedf20d29292b13c Mon Sep 17 00:00:00 2001 From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:23:51 +0000 Subject: [PATCH 3/3] Remove SACompGC BuildEvent --- SAToolsHub/SAToolsHub.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SAToolsHub/SAToolsHub.csproj b/SAToolsHub/SAToolsHub.csproj index 20b34110..b74d18a7 100644 --- a/SAToolsHub/SAToolsHub.csproj +++ b/SAToolsHub/SAToolsHub.csproj @@ -41,6 +41,6 @@ - + \ No newline at end of file