diff --git a/CommandLine/AnimJSONConverter/AnimJSONConverter.csproj b/CommandLine/AnimJSONConverter/AnimJSONConverter.csproj index e12aa5d10..89ece23b7 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 a3b0a7796..e81337772 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 311d3a792..590c87b50 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 311d3a792..590c87b50 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 311d3a792..590c87b50 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 284b21199..3895960ec 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 9be7fc0bf..a091bcaa8 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 d18b0e704..4883bc283 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 d1f0e8326..64e5e9f58 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 50d63fad0..8a3b7145c 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 e12aa5d10..89ece23b7 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 cfc3440f0..95c0b9e38 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 284b21199..3895960ec 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 d1f0e8326..64e5e9f58 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 69ddb0045..0b388d667 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 76053a170..e99afd841 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 66c02ba15..37438af0a 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 ad2b4c8a2..c1973d321 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 311d3a792..590c87b50 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 4d0f26a42..bf2a411f9 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 4546f06bf..1a3a42c86 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 311d3a792..590c87b50 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 4b4167bec..9e6c449f5 100644 --- a/DataToolbox/DataToolbox.csproj +++ b/DataToolbox/DataToolbox.csproj @@ -8,7 +8,6 @@ false en embedded - x64;x86 datatoolbox.ico diff --git a/Dependencies/SACompGC_x64.dll b/Dependencies/SACompGC_x64.dll deleted file mode 100644 index c32f26390..000000000 Binary files a/Dependencies/SACompGC_x64.dll and /dev/null differ diff --git a/Dependencies/SACompGC_x86.dll b/Dependencies/SACompGC_x86.dll deleted file mode 100644 index d260ac070..000000000 Binary files a/Dependencies/SACompGC_x86.dll and /dev/null differ diff --git a/Libraries/ArchiveLib/ArchiveLib.csproj b/Libraries/ArchiveLib/ArchiveLib.csproj index 1d944151c..2d482a877 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 a5458afaf..c35fdacd5 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 212bda9eb..6ec30dad5 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 6a1c43003..a3c3b7b58 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 1f5ae6358..221c2ab04 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 9e2529406..887665b0b 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 8579fc0cd..6cd570c5b 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 ed0387797..c94bcbc6d 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 e95509db8..def695421 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 452bcdf24..01a849622 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 f0360cef4..47f465a17 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 b77abb06b..394b8d01a 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 5e4b5e39b..94ff55776 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 0c6376349..664493edd 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 2a470ad5f..efebbf94e 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 f387d37a0..5a9edf35d 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 ae0ec1fa0..6a87f4866 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 cd2889c62..960b220fc 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 177386593..558b26be2 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 4e1bba33f..dbbb5408e 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 24e48b96c..3e1a44775 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 42d3d0e78..38f86a851 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 8be188160..2c29f22be 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 cc2bdad0f..169aaf465 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 05669803e..e7713a892 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 64937dd91..410ce2eb4 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 1fb70ad83..65f3569a2 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 935799df9..20190d76e 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 d835494ec..b5eed0199 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 55280f9f0..f0708cf03 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 48ce3b1e1..e48fc2e18 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 b0e059c44..b74d18a77 100644 --- a/SAToolsHub/SAToolsHub.csproj +++ b/SAToolsHub/SAToolsHub.csproj @@ -8,7 +8,6 @@ false false embedded - x64;x86 Resources\ToolsHub_ico.ico @@ -42,6 +41,6 @@ - + \ No newline at end of file diff --git a/TextureEditor/TextureEditor.csproj b/TextureEditor/TextureEditor.csproj index 3885c191d..fc6f954ce 100644 --- a/TextureEditor/TextureEditor.csproj +++ b/TextureEditor/TextureEditor.csproj @@ -10,7 +10,6 @@ icon_TexEdit.ico embedded True - x64;x86 true