From b3b07228a9a8a19b1328ca9c423caed3a9fc73b2 Mon Sep 17 00:00:00 2001
From: Li
Date: Sat, 7 Jan 2023 18:36:33 -0800
Subject: [PATCH] Implement Decompress function fully.
---
.gitignore | 3 ++-
LibXom/Data/XomCompressor.cs | 51 ++++++++----------------------------
LibXom/Data/XomContainer.cs | 35 ++++++++++++++++++-------
LibXom/Data/XomFile.cs | 20 +++++++-------
Worms4Editor/Program.cs | 26 +++++++++---------
5 files changed, 59 insertions(+), 76 deletions(-)
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