diff --git a/.gitignore b/.gitignore index 83f617d..b8d5662 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ Worms4Editor/obj/* Worms4Editor/bin/* LibXom/obj/* -LibXom/bin/* \ No newline at end of file +LibXom/bin/* +.vs/* diff --git a/LibXom/Data/XomCompressor.cs b/LibXom/Data/XomCompressor.cs index 013229d..1b142ee 100644 --- a/LibXom/Data/XomCompressor.cs +++ b/LibXom/Data/XomCompressor.cs @@ -24,7 +24,7 @@ namespace LibXom.Data return DecompressInt(BitConverter.ToInt32(buffer)); } - public static int[] Decompress(byte[] input) + internal static int[] decompressBuffer(byte[] input) { List decompressedData = new List(); @@ -48,50 +48,21 @@ namespace LibXom.Data if (unum <= 0xFFFFFFFF) return 4; throw new XomException("Number is too large or too small."); } - private static int decompressInt16(int compressedInt) + private static int pow(int val, int pow) { - int mul = (compressedInt >> 8); - int add = (compressedInt & 0xFF); - - return (mul * 0x80) + (add % 0x80); + return Convert.ToInt32(Math.Pow(val, pow)); } - private static int decompressInt24(int compressedInt) - { - int mul = (compressedInt >> 8) & 0xFF; - int mul2 = (compressedInt >> 16); - - int add = (compressedInt & 0xFF); - - return ((mul2 * 0x80) * mul) + (add % 0x80); - } - - private static int decompressInt32(int compressedInt) - { - int mul = (compressedInt >> 8) & 0xFF; - int mul2 = (compressedInt >> 16) & 0xFF; - int mul3 = (compressedInt >> 24); - - int add = (compressedInt & 0xFF); - - return (((mul3 * 0x80) * mul2 * 0x80) * mul * 0x80) + (add % 0x80); - } - + // TODO: Write the inverse of this; "CompressInt()" public static int DecompressInt(int compressedInt) { - switch (getNumberByteCount(compressedInt)) - { - case 1: - return compressedInt; - case 2: - return decompressInt16(compressedInt); - case 3: - return decompressInt24(compressedInt); - case 4: - return decompressInt32(compressedInt); - default: - throw new XomException("Number is too large or too small."); - } + int b1 = (compressedInt & 0xFF); + int b2 = (compressedInt >> 8) & 0xFF; + int b3 = (compressedInt >> 16) & 0xFF; + int b4 = (compressedInt >> 24) & 0xFF; + + return (b4 * pow(0x80, 3)) + ((b3 % 0x80) * pow(0x80, 0x2)) + ((b2 % 0x80) * pow(0x80, 1)) + (b1 % 0x80); } + public static int NextCompressedInterger(int compressedInt) { // Some parts of XOM follow a particular pattern, diff --git a/LibXom/Data/XomContainer.cs b/LibXom/Data/XomContainer.cs index c0dbabf..e900d7f 100644 --- a/LibXom/Data/XomContainer.cs +++ b/LibXom/Data/XomContainer.cs @@ -26,25 +26,40 @@ namespace LibXom.Data return this.fileBelongs.calculateIdForXomFileComponent(this.uuid, fileBelongs.XomContainers); } } - public byte[] Data + public byte[] GetData() { - get + return data; + } + public void SetData(byte[] data) + { + this.Type.ReplaceContainerData(this, data); + } + private byte[] intArrayToByteArray(int[] intArray) + { + using (MemoryStream ms = new MemoryStream()) { - return data; - } - set - { - this.Type.ReplaceContainerData(this, value); + foreach (int i in intArray) + { + byte[] buf = BitConverter.GetBytes(i); + ms.Write(buf, 0, buf.Length); + } + + ms.Seek(0, SeekOrigin.Begin); + return ms.ToArray(); } } public int[] Decompress() { - byte[] compressedData = new byte[Data.Length - 3]; - Array.ConstrainedCopy(Data, 3, compressedData, 0, compressedData.Length); - return XomCompressor.Decompress(compressedData); + byte[] compressedData = new byte[data.Length - 3]; + Array.ConstrainedCopy(data, 3, compressedData, 0, compressedData.Length); + return XomCompressor.decompressBuffer(compressedData); } + public byte[] DecompressToBytes() + { + return intArrayToByteArray(this.Decompress()); + } internal XomContainer(XomFile fromFile, string fromType, byte[] data) { fileBelongs = fromFile; diff --git a/LibXom/Data/XomFile.cs b/LibXom/Data/XomFile.cs index f9c11be..2d452ca 100644 --- a/LibXom/Data/XomFile.cs +++ b/LibXom/Data/XomFile.cs @@ -42,12 +42,13 @@ namespace LibXom.Data return xomContainers.ToArray(); } } - + public XomString GetStringById(int stringId) + { + return XomStrings[stringId]; + } public XomContainer GetContainerById(int containerId) { - foreach(XomContainer container in XomContainers) - if (container.Id.Equals(containerId)) return container; - throw new XomContainerNotFoundException("No container with id " + containerId + " was found."); + return XomContainers[containerId]; } public XomType GetTypeByName(string typeName) { @@ -58,13 +59,10 @@ namespace LibXom.Data } internal int calculateIdForXomFileComponent(string searchUuid, XomFileComponent[] components) { - int id = 0; - foreach(XomFileComponent component in components) - { - if (component.uuid.Equals(searchUuid, StringComparison.InvariantCultureIgnoreCase)) return id; - id = XomCompressor.NextCompressedInterger(id); - } - return id; + for (int i = 0; i < components.Length; i++) + if (components[i].uuid.Equals(searchUuid, StringComparison.CurrentCultureIgnoreCase)) return i; + + throw new XomFileComponentNotFoundException("A XOM Components ID could not be found in the Component List."); } internal XomFile(XomBlock[] xomBlocks) { diff --git a/Worms4Editor/Program.cs b/Worms4Editor/Program.cs index 06b3ad8..d08a8a7 100644 --- a/Worms4Editor/Program.cs +++ b/Worms4Editor/Program.cs @@ -2,6 +2,7 @@ using LibXom.Blocks; using LibXom.Data; using System.Security.Cryptography; +using System.Text; namespace Worms4Editor { @@ -9,28 +10,25 @@ namespace Worms4Editor { static void Main(string[] args) { - Console.WriteLine(XomCompressor.DecompressInt(32767).ToString("X")); - Console.WriteLine(XomCompressor.DecompressInt(98432).ToString("X")); - Console.WriteLine(XomCompressor.DecompressInt(98433).ToString("X")); - Console.WriteLine(XomCompressor.DecompressInt(8388607).ToString("X")); - int id = 0; - for (int i = 0; i < 0x9000; i++) { + /* int id = 0; + for (int i = 0; i < 0x7FFFFF; i++) { int d = XomCompressor.DecompressInt(id); if (d != i) Console.WriteLine("FAIL; " + i.ToString("X") + " id " + id.ToString("X") + " d " + d.ToString("X")); else Console.WriteLine("PASS; " + i.ToString("X") + " id " + id.ToString("X") + " d " + d.ToString("X")); id = XomCompressor.NextCompressedInterger(id); - } - XomFile xfile = XomReader.ReadXomFile(@"SaveGame.xom"); - XomFile ps2file = XomReader.ReadXomFile(@"ps2.xom"); + } */ + XomFile xfile = XomReader.ReadXomFile(@"Original.xom"); + //XomFile ps2file = XomReader.ReadXomFile(@"ps2.xom"); XomType type = xfile.GetTypeByName("StoredStatsCollective"); - File.WriteAllBytes("StoredStatsCollective.bin", type.Containers.First().Data); + XomContainer container = type.Containers.First(); + File.WriteAllBytes("StoredStatsCollective.bin", container.DecompressToBytes()); - /*foreach(int d in data) + for(int i = 0; i < xfile.XomStrings.Length; i++) { - Console.WriteLine(d + ": "+ BitConverter.ToString(ps2file.GetContainerById(d).Data).Replace("-", " ")); - }*/ - + XomString str = xfile.XomStrings[i]; + Console.WriteLine(str.Id.ToString("X") + ": " + str.Value); + } } } } \ No newline at end of file