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