Add Weapon Factory Parsing pt.1
This commit is contained in:
parent
0247b45335
commit
835c9002ab
|
@ -2,4 +2,6 @@ Worms4Editor/obj/*
|
||||||
Worms4Editor/bin/*
|
Worms4Editor/bin/*
|
||||||
LibXom/obj/*
|
LibXom/obj/*
|
||||||
LibXom/bin/*
|
LibXom/bin/*
|
||||||
|
LibW4M/obj/*
|
||||||
|
LibW4M/bin/*
|
||||||
.vs/*
|
.vs/*
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
using LibXom.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LibW4M.Data
|
||||||
|
{
|
||||||
|
internal abstract class SaveDataEntry
|
||||||
|
{
|
||||||
|
internal Guid guid = Guid.NewGuid();
|
||||||
|
internal W4SaveFile fileBelongs;
|
||||||
|
internal XomContainer mainContainer;
|
||||||
|
internal string uuid
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return guid.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public abstract void Delete();
|
||||||
|
public abstract void Load();
|
||||||
|
public abstract void Save();
|
||||||
|
public SaveDataEntry (W4SaveFile fileBelongs, XomContainer mainContainer)
|
||||||
|
{
|
||||||
|
this.fileBelongs = fileBelongs;
|
||||||
|
this.mainContainer = mainContainer;
|
||||||
|
this.Load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
using LibXom.Data;
|
||||||
|
using LibXom.Streams;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LibW4M.Data.WeaponFactory
|
||||||
|
{
|
||||||
|
internal class WeaponEntry : SaveDataEntry
|
||||||
|
{
|
||||||
|
|
||||||
|
private int weaponNameId;
|
||||||
|
public string WeaponName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.fileBelongs.w4Save.GetStringById(this.weaponNameId).Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int weaponType;
|
||||||
|
private WeaponType detonationType;
|
||||||
|
|
||||||
|
private bool homing;
|
||||||
|
private bool homingAvoidLand;
|
||||||
|
private bool effectedByWind;
|
||||||
|
private bool fireOnGround;
|
||||||
|
private bool poison;
|
||||||
|
private int retreatTime;
|
||||||
|
|
||||||
|
private float wormDamageRadius;
|
||||||
|
private float wormDamageMagnitude;
|
||||||
|
private float landDamageRadius;
|
||||||
|
|
||||||
|
private float projectileCollisionRadius;
|
||||||
|
private float push;
|
||||||
|
private int fuseTime;
|
||||||
|
|
||||||
|
private int[] graphicalResourceIds;
|
||||||
|
private int[] graphicalLocatorIds;
|
||||||
|
|
||||||
|
private int launchFX;
|
||||||
|
private int arielFX;
|
||||||
|
private int detonationFX;
|
||||||
|
|
||||||
|
private int payloadResourceId;
|
||||||
|
private int projectileLaunchType;
|
||||||
|
private bool projectilePowersUp;
|
||||||
|
private int projectileNumClusters;
|
||||||
|
private float projectileMaxPower;
|
||||||
|
private float clusterSpread;
|
||||||
|
private float clusterMaxSpeed;
|
||||||
|
|
||||||
|
|
||||||
|
private XomContainer[] dataContainers;
|
||||||
|
|
||||||
|
public WeaponEntry(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Delete()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Load()
|
||||||
|
{
|
||||||
|
int[] sWpFc = this.mainContainer.Decompress();
|
||||||
|
XomContainer top = this.fileBelongs.w4Save.GetContainerById(sWpFc[1]);
|
||||||
|
XomContainer btm = this.fileBelongs.w4Save.GetContainerById(sWpFc[1]);
|
||||||
|
|
||||||
|
// parse top
|
||||||
|
using(XomStreamReader reader = new XomStreamReader(new MemoryStream(top.GetData())))
|
||||||
|
{
|
||||||
|
this.weaponNameId = XomCompressor.DecompressInt(reader.ReadInt32());
|
||||||
|
|
||||||
|
reader.Skip(1);
|
||||||
|
this.detonationType = (WeaponType)reader.ReadInt32();
|
||||||
|
|
||||||
|
reader.Skip(1);
|
||||||
|
|
||||||
|
this.homing = (reader.ReadByte() == 0x01);
|
||||||
|
this.homingAvoidLand = (reader.ReadByte() == 0x01);
|
||||||
|
|
||||||
|
this.effectedByWind = (reader.ReadByte() == 0x01);
|
||||||
|
this.fireOnGround = (reader.ReadByte() == 0x01);
|
||||||
|
this.poison = (reader.ReadByte() == 0x01);
|
||||||
|
this.retreatTime = reader.ReadInt32();
|
||||||
|
|
||||||
|
this.wormDamageRadius = reader.ReadFloat();
|
||||||
|
this.wormDamageMagnitude = reader.ReadFloat();
|
||||||
|
this.landDamageRadius = reader.ReadFloat();
|
||||||
|
this.projectileCollisionRadius = reader.ReadFloat();
|
||||||
|
this.push = reader.ReadFloat();
|
||||||
|
|
||||||
|
this.fuseTime = reader.ReadInt32();
|
||||||
|
|
||||||
|
// read GraphicalResourceIds
|
||||||
|
int totalGraphicalResourceIds = reader.ReadCompressedInt();
|
||||||
|
this.graphicalResourceIds = new int[totalGraphicalResourceIds];
|
||||||
|
for (int i = 0; i < totalGraphicalResourceIds; i++) this.graphicalResourceIds[i] = reader.ReadCompressedInt();
|
||||||
|
|
||||||
|
// read GraphicalLocatorIds
|
||||||
|
int totalGraphicalLocatorIds = reader.ReadCompressedInt();
|
||||||
|
this.graphicalLocatorIds = new int[totalGraphicalLocatorIds];
|
||||||
|
for (int i = 0; i < totalGraphicalLocatorIds; i++) this.graphicalLocatorIds[i] = reader.ReadCompressedInt();
|
||||||
|
|
||||||
|
|
||||||
|
this.launchFX = reader.ReadCompressedInt();
|
||||||
|
this.arielFX = reader.ReadCompressedInt();
|
||||||
|
this.detonationFX = reader.ReadCompressedInt();
|
||||||
|
|
||||||
|
this.payloadResourceId = reader.ReadInt32();
|
||||||
|
this.projectileLaunchType = reader.ReadInt32();
|
||||||
|
|
||||||
|
this.projectilePowersUp = (reader.ReadByte() == 0x01);
|
||||||
|
this.projectileNumClusters = reader.ReadInt32();
|
||||||
|
|
||||||
|
this.projectileMaxPower = reader.ReadFloat();
|
||||||
|
this.clusterSpread = reader.ReadFloat();
|
||||||
|
this.clusterMaxSpeed = reader.ReadFloat();
|
||||||
|
}
|
||||||
|
// parse btm
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Save()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LibW4M.Data.WeaponFactory
|
||||||
|
{
|
||||||
|
public enum WeaponType : int
|
||||||
|
{
|
||||||
|
StopsMoving = 0,
|
||||||
|
Fuse = 1,
|
||||||
|
User = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LibXom\LibXom.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
using LibXom.Data;
|
||||||
|
|
||||||
|
namespace LibW4M
|
||||||
|
{
|
||||||
|
public class W4SaveFile
|
||||||
|
{
|
||||||
|
|
||||||
|
public XomFile w4Save;
|
||||||
|
public W4SaveFile(XomFile w4Save)
|
||||||
|
{
|
||||||
|
this.w4Save = w4Save;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ namespace LibXom.Data
|
||||||
throw new XomException("Number is too large or too small.");
|
throw new XomException("Number is too large or too small.");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int readCompressedIntFromStream(MemoryStream ms)
|
public static int ReadCompressedIntFromStream(Stream ms)
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[4];
|
byte[] buffer = new byte[4];
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ namespace LibXom.Data
|
||||||
{
|
{
|
||||||
while (inputStream.Position < inputStream.Length)
|
while (inputStream.Position < inputStream.Length)
|
||||||
{
|
{
|
||||||
int n = readCompressedIntFromStream(inputStream);
|
int n = ReadCompressedIntFromStream(inputStream);
|
||||||
decompressedData.Add(n);
|
decompressedData.Add(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,11 @@ namespace LibXom.Data
|
||||||
}
|
}
|
||||||
public XomString GetStringById(int stringId)
|
public XomString GetStringById(int stringId)
|
||||||
{
|
{
|
||||||
return XomStrings[stringId];
|
return XomStrings[stringId - 1];
|
||||||
}
|
}
|
||||||
public XomContainer GetContainerById(int containerId)
|
public XomContainer GetContainerById(int containerId)
|
||||||
{
|
{
|
||||||
return XomContainers[containerId];
|
return XomContainers[containerId - 1];
|
||||||
}
|
}
|
||||||
public XomType GetTypeByName(string typeName)
|
public XomType GetTypeByName(string typeName)
|
||||||
{
|
{
|
||||||
|
@ -60,7 +60,7 @@ namespace LibXom.Data
|
||||||
internal int calculateIdForXomFileComponent(string searchUuid, XomFileComponent[] components)
|
internal int calculateIdForXomFileComponent(string searchUuid, XomFileComponent[] components)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < components.Length; i++)
|
for (int i = 0; i < components.Length; i++)
|
||||||
if (components[i].uuid.Equals(searchUuid, StringComparison.CurrentCultureIgnoreCase)) return i;
|
if (components[i].uuid.Equals(searchUuid, StringComparison.CurrentCultureIgnoreCase)) return i + 1;
|
||||||
|
|
||||||
throw new XomFileComponentNotFoundException("A XOM Components ID could not be found in the Component List.");
|
throw new XomFileComponentNotFoundException("A XOM Components ID could not be found in the Component List.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
using LibXom.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LibXom.Streams
|
||||||
|
{
|
||||||
|
public class XomStreamReader : IDisposable
|
||||||
|
{
|
||||||
|
private Stream xStream;
|
||||||
|
public Stream BaseStream
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return xStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int ReadCompressedInt()
|
||||||
|
{
|
||||||
|
return XomCompressor.ReadCompressedIntFromStream(xStream);
|
||||||
|
}
|
||||||
|
public byte[] ReadBytes(int amt)
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[amt];
|
||||||
|
xStream.Read(buffer, 0, amt);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
public byte ReadByte()
|
||||||
|
{
|
||||||
|
return Convert.ToByte(xStream.ReadByte());
|
||||||
|
}
|
||||||
|
public string ReadStrLen(int len)
|
||||||
|
{
|
||||||
|
byte[] buf = ReadBytes(len);
|
||||||
|
|
||||||
|
int rlen = 0;
|
||||||
|
for (rlen = 0; rlen < len; rlen++)
|
||||||
|
if (buf[rlen] == 0) break;
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(buf, 0, rlen);
|
||||||
|
}
|
||||||
|
public string ReadCStr()
|
||||||
|
{
|
||||||
|
StringBuilder cstr = new StringBuilder();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char c = (char)ReadByte();
|
||||||
|
if (c == 0) break;
|
||||||
|
cstr.Append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cstr.ToString();
|
||||||
|
}
|
||||||
|
public void Skip(int amt)
|
||||||
|
{
|
||||||
|
xStream.Seek(amt, SeekOrigin.Current);
|
||||||
|
}
|
||||||
|
public float ReadFloat()
|
||||||
|
{
|
||||||
|
return BitConverter.ToSingle(ReadBytes(0x4));
|
||||||
|
}
|
||||||
|
public int ReadInt32()
|
||||||
|
{
|
||||||
|
return BitConverter.ToInt32(ReadBytes(0x4));
|
||||||
|
}
|
||||||
|
public int ReadInt32BE()
|
||||||
|
{
|
||||||
|
byte[] buffer = ReadBytes(0x4);
|
||||||
|
buffer.Reverse();
|
||||||
|
return BitConverter.ToInt32(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.xStream.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XomStreamReader(Stream xStream)
|
||||||
|
{
|
||||||
|
this.xStream = xStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LibXom.Streams
|
||||||
|
{
|
||||||
|
public class XomStreamWriter : IDisposable
|
||||||
|
{
|
||||||
|
private Stream xStream;
|
||||||
|
public Stream BaseStream
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return xStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void WriteByte(byte b)
|
||||||
|
{
|
||||||
|
xStream.WriteByte(b);
|
||||||
|
}
|
||||||
|
public int Pos()
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(xStream.Position);
|
||||||
|
}
|
||||||
|
public void Rewind(int amt)
|
||||||
|
{
|
||||||
|
xStream.Seek(-amt, SeekOrigin.Current);
|
||||||
|
}
|
||||||
|
public void Skip(int amt)
|
||||||
|
{
|
||||||
|
int cpos = Pos();
|
||||||
|
int len = Convert.ToInt32(xStream.Length);
|
||||||
|
int remain = len - cpos;
|
||||||
|
|
||||||
|
if (amt > remain)
|
||||||
|
{
|
||||||
|
xStream.Seek(remain, SeekOrigin.Current);
|
||||||
|
amt -= remain;
|
||||||
|
WritePadding(0, amt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xStream.Seek(amt, SeekOrigin.Current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void WritePadding(byte pad, int len)
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[len];
|
||||||
|
if (pad != 0)
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
buf[i] = pad;
|
||||||
|
WriteBytes(buf);
|
||||||
|
}
|
||||||
|
public void WriteBytes(byte[] bytes)
|
||||||
|
{
|
||||||
|
xStream.Write(bytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
public void WriteInt32(int value)
|
||||||
|
{
|
||||||
|
byte[] buffer = BitConverter.GetBytes(value);
|
||||||
|
WriteBytes(buffer);
|
||||||
|
}
|
||||||
|
public void WriteInt32BE(int value)
|
||||||
|
{
|
||||||
|
byte[] buffer = BitConverter.GetBytes(value);
|
||||||
|
buffer.Reverse();
|
||||||
|
WriteBytes(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteStrLen(string str, int len)
|
||||||
|
{
|
||||||
|
WriteStr(str);
|
||||||
|
|
||||||
|
int padLen = len - str.Length;
|
||||||
|
if (padLen > 0)
|
||||||
|
Skip(padLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteStr(string str)
|
||||||
|
{
|
||||||
|
byte[] buffer = Encoding.UTF8.GetBytes(str);
|
||||||
|
WriteBytes(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteCStr(string str)
|
||||||
|
{
|
||||||
|
WriteStr(str);
|
||||||
|
WriteByte(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.xStream.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XomStreamWriter(Stream xStream)
|
||||||
|
{
|
||||||
|
this.xStream = xStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,60 +1,14 @@
|
||||||
using LibXom.Blocks;
|
using LibXom.Blocks;
|
||||||
using LibXom.Data;
|
using LibXom.Data;
|
||||||
|
using LibXom.Streams;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace LibXom
|
namespace LibXom
|
||||||
{
|
{
|
||||||
public class XomReader
|
public class XomReader
|
||||||
{
|
{
|
||||||
private Stream xomStream;
|
private XomStreamReader xomStream;
|
||||||
private byte[] readBytes(int amt)
|
|
||||||
{
|
|
||||||
byte[] buffer = new byte[amt];
|
|
||||||
xomStream.Read(buffer, 0, amt);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
private byte readByte()
|
|
||||||
{
|
|
||||||
return Convert.ToByte(xomStream.ReadByte());
|
|
||||||
}
|
|
||||||
private string readStrLen(int len)
|
|
||||||
{
|
|
||||||
byte[] buf = readBytes(len);
|
|
||||||
|
|
||||||
int rlen = 0;
|
|
||||||
for (rlen = 0; rlen < len; rlen++)
|
|
||||||
if (buf[rlen] == 0) break;
|
|
||||||
|
|
||||||
return Encoding.UTF8.GetString(buf, 0, rlen);
|
|
||||||
}
|
|
||||||
private string readCStr()
|
|
||||||
{
|
|
||||||
StringBuilder cstr = new StringBuilder();
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
char c = (char)readByte();
|
|
||||||
if (c == 0) break;
|
|
||||||
cstr.Append(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cstr.ToString();
|
|
||||||
}
|
|
||||||
private int readInt32BE()
|
|
||||||
{
|
|
||||||
byte[] buffer = readBytes(0x4);
|
|
||||||
buffer.Reverse();
|
|
||||||
return BitConverter.ToInt32(buffer);
|
|
||||||
}
|
|
||||||
private void skip(int amt)
|
|
||||||
{
|
|
||||||
xomStream.Seek(amt, SeekOrigin.Current);
|
|
||||||
}
|
|
||||||
private int readInt32()
|
|
||||||
{
|
|
||||||
return BitConverter.ToInt32(readBytes(0x4));
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool bufferEndsWith(List<byte> buffer, byte[] search)
|
public bool bufferEndsWith(List<byte> buffer, byte[] search)
|
||||||
{
|
{
|
||||||
int len = search.Length;
|
int len = search.Length;
|
||||||
|
@ -79,12 +33,12 @@ namespace LibXom
|
||||||
public CtnrBlock readCtnr()
|
public CtnrBlock readCtnr()
|
||||||
{
|
{
|
||||||
List<byte> buffer = new List<byte>();
|
List<byte> buffer = new List<byte>();
|
||||||
while (xomStream.Position < xomStream.Length)
|
while (xomStream.BaseStream.Position < xomStream.BaseStream.Length)
|
||||||
{
|
{
|
||||||
buffer.Add(readByte());
|
buffer.Add(xomStream.ReadByte());
|
||||||
if (bufferEndsWith(buffer, Encoding.UTF8.GetBytes("CTNR")))
|
if (bufferEndsWith(buffer, Encoding.UTF8.GetBytes("CTNR")))
|
||||||
{
|
{
|
||||||
skip(-4);
|
xomStream.Skip(-4);
|
||||||
int i = buffer.Count - 1;
|
int i = buffer.Count - 1;
|
||||||
int endAt = i - 4;
|
int endAt = i - 4;
|
||||||
for (; i != endAt; i--)
|
for (; i != endAt; i--)
|
||||||
|
@ -97,58 +51,58 @@ namespace LibXom
|
||||||
|
|
||||||
public MoikBlock readMoik()
|
public MoikBlock readMoik()
|
||||||
{
|
{
|
||||||
int version = readInt32BE();
|
int version = xomStream.ReadInt32BE();
|
||||||
skip(0x10);
|
xomStream.Skip(0x10);
|
||||||
int numTypes = readInt32();
|
int numTypes = xomStream.ReadInt32();
|
||||||
int numCtnr = readInt32();
|
int numCtnr = xomStream.ReadInt32();
|
||||||
int numCtnr2 = readInt32();
|
int numCtnr2 = xomStream.ReadInt32();
|
||||||
skip(0x1C);
|
xomStream.Skip(0x1C);
|
||||||
return new MoikBlock(version, numCtnr, numTypes);
|
return new MoikBlock(version, numCtnr, numTypes);
|
||||||
}
|
}
|
||||||
public TypeBlock readType()
|
public TypeBlock readType()
|
||||||
{
|
{
|
||||||
skip(0x4);
|
xomStream.Skip(0x4);
|
||||||
int numCtnr = readInt32();
|
int numCtnr = xomStream.ReadInt32();
|
||||||
skip(0x4);
|
xomStream.Skip(0x4);
|
||||||
byte[] md5 = readBytes(0x10);
|
byte[] md5 = xomStream.ReadBytes(0x10);
|
||||||
string typeName = readStrLen(0x20);
|
string typeName = xomStream.ReadStrLen(0x20);
|
||||||
return new TypeBlock(numCtnr, md5, typeName);
|
return new TypeBlock(numCtnr, md5, typeName);
|
||||||
}
|
}
|
||||||
public SchmBlock readSchm()
|
public SchmBlock readSchm()
|
||||||
{
|
{
|
||||||
int unk0 = readInt32();
|
int unk0 = xomStream.ReadInt32();
|
||||||
int unk1 = readInt32();
|
int unk1 = xomStream.ReadInt32();
|
||||||
int unk2 = readInt32();
|
int unk2 = xomStream.ReadInt32();
|
||||||
return new SchmBlock(unk0, unk1, unk2);
|
return new SchmBlock(unk0, unk1, unk2);
|
||||||
}
|
}
|
||||||
public GuidBlock readGuid()
|
public GuidBlock readGuid()
|
||||||
{
|
{
|
||||||
int unk0 = readInt32();
|
int unk0 = xomStream.ReadInt32();
|
||||||
int unk1 = readInt32();
|
int unk1 = xomStream.ReadInt32();
|
||||||
int unk2 = readInt32();
|
int unk2 = xomStream.ReadInt32();
|
||||||
return new GuidBlock(unk0, unk1, unk2);
|
return new GuidBlock(unk0, unk1, unk2);
|
||||||
}
|
}
|
||||||
public StrsBlock readStrs()
|
public StrsBlock readStrs()
|
||||||
{
|
{
|
||||||
int numStrs = readInt32();
|
int numStrs = xomStream.ReadInt32();
|
||||||
int strsSz = readInt32();
|
int strsSz = xomStream.ReadInt32();
|
||||||
|
|
||||||
int[] offsets = new int[numStrs];
|
int[] offsets = new int[numStrs];
|
||||||
string[] strings = new string[numStrs];
|
string[] strings = new string[numStrs];
|
||||||
|
|
||||||
for (int i = 0; i < numStrs; i++)
|
for (int i = 0; i < numStrs; i++)
|
||||||
{
|
{
|
||||||
offsets[i] = readInt32();
|
offsets[i] = xomStream.ReadInt32();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < numStrs; i++)
|
for (int i = 0; i < numStrs; i++)
|
||||||
{
|
{
|
||||||
strings[i] = readCStr();
|
strings[i] = xomStream.ReadCStr();
|
||||||
}
|
}
|
||||||
return new StrsBlock(numStrs, strsSz, offsets, strings); ;
|
return new StrsBlock(numStrs, strsSz, offsets, strings); ;
|
||||||
}
|
}
|
||||||
public XomBlock? readBlock()
|
public XomBlock? readBlock()
|
||||||
{
|
{
|
||||||
string hdr = readStrLen(0x4);
|
string hdr = xomStream.ReadStrLen(0x4);
|
||||||
|
|
||||||
switch (hdr)
|
switch (hdr)
|
||||||
{
|
{
|
||||||
|
@ -171,7 +125,7 @@ namespace LibXom
|
||||||
private XomBlock[] readAllBlocks()
|
private XomBlock[] readAllBlocks()
|
||||||
{
|
{
|
||||||
List<XomBlock> xomBlocks = new List<XomBlock>();
|
List<XomBlock> xomBlocks = new List<XomBlock>();
|
||||||
while (xomStream.Position < xomStream.Length)
|
while (xomStream.BaseStream.Position < xomStream.BaseStream.Length)
|
||||||
{
|
{
|
||||||
XomBlock? block = readBlock();
|
XomBlock? block = readBlock();
|
||||||
if (block == null) break;
|
if (block == null) break;
|
||||||
|
@ -200,7 +154,7 @@ namespace LibXom
|
||||||
}
|
}
|
||||||
internal XomReader(Stream xom)
|
internal XomReader(Stream xom)
|
||||||
{
|
{
|
||||||
this.xomStream = xom;
|
this.xomStream = new XomStreamReader(xom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,139 +1,66 @@
|
||||||
using LibXom.Blocks;
|
using LibXom.Blocks;
|
||||||
using LibXom.Data;
|
using LibXom.Data;
|
||||||
|
using LibXom.Streams;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace LibXom
|
namespace LibXom
|
||||||
{
|
{
|
||||||
public class XomWriter
|
public class XomWriter
|
||||||
{
|
{
|
||||||
private Stream xomStream;
|
private XomStreamWriter xomStream;
|
||||||
private XomFile xomFile;
|
private XomFile xomFile;
|
||||||
|
|
||||||
private void writeByte(byte b)
|
|
||||||
{
|
|
||||||
xomStream.WriteByte(b);
|
|
||||||
}
|
|
||||||
private int pos()
|
|
||||||
{
|
|
||||||
return Convert.ToInt32(xomStream.Position);
|
|
||||||
}
|
|
||||||
private void rewind(int amt)
|
|
||||||
{
|
|
||||||
xomStream.Seek(-amt, SeekOrigin.Current);
|
|
||||||
}
|
|
||||||
private void skip(int amt)
|
|
||||||
{
|
|
||||||
int cpos = pos();
|
|
||||||
int len = Convert.ToInt32(xomStream.Length);
|
|
||||||
int remain = len - cpos;
|
|
||||||
|
|
||||||
if(amt > remain)
|
|
||||||
{
|
|
||||||
xomStream.Seek(remain, SeekOrigin.Current);
|
|
||||||
amt -= remain;
|
|
||||||
writePadding(0, amt);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xomStream.Seek(amt, SeekOrigin.Current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void writePadding(byte pad, int len)
|
|
||||||
{
|
|
||||||
byte[] buf = new byte[len];
|
|
||||||
if(pad != 0)
|
|
||||||
for(int i = 0; i < len; i++)
|
|
||||||
buf[i] = pad;
|
|
||||||
writeBytes(buf);
|
|
||||||
}
|
|
||||||
private void writeBytes(byte[] bytes)
|
|
||||||
{
|
|
||||||
xomStream.Write(bytes, 0, bytes.Length);
|
|
||||||
}
|
|
||||||
private void writeInt32(int value)
|
|
||||||
{
|
|
||||||
byte[] buffer = BitConverter.GetBytes(value);
|
|
||||||
writeBytes(buffer);
|
|
||||||
}
|
|
||||||
private void writeInt32BE(int value)
|
|
||||||
{
|
|
||||||
byte[] buffer = BitConverter.GetBytes(value);
|
|
||||||
buffer.Reverse();
|
|
||||||
writeBytes(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeStrLen(string str, int len)
|
|
||||||
{
|
|
||||||
writeStr(str);
|
|
||||||
|
|
||||||
int padLen = (len - str.Length);
|
|
||||||
if (padLen > 0)
|
|
||||||
skip(padLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeStr(string str)
|
|
||||||
{
|
|
||||||
byte[] buffer = Encoding.UTF8.GetBytes(str);
|
|
||||||
writeBytes(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeCStr(string str)
|
|
||||||
{
|
|
||||||
writeStr(str);
|
|
||||||
writeByte(0);
|
|
||||||
}
|
|
||||||
private void writeMoik(MoikBlock moikBlock)
|
private void writeMoik(MoikBlock moikBlock)
|
||||||
{
|
{
|
||||||
writeStr(moikBlock.Name);
|
xomStream.WriteStr(moikBlock.Name);
|
||||||
writeInt32BE(moikBlock.Version);
|
xomStream.WriteInt32BE(moikBlock.Version);
|
||||||
skip(0x10);
|
xomStream.Skip(0x10);
|
||||||
writeInt32(moikBlock.NumTypes);
|
xomStream.WriteInt32(moikBlock.NumTypes);
|
||||||
writeInt32(moikBlock.NumCtnr);
|
xomStream.WriteInt32(moikBlock.NumCtnr);
|
||||||
writeInt32(moikBlock.NumCtnr);
|
xomStream.WriteInt32(moikBlock.NumCtnr);
|
||||||
skip(0x1C);
|
xomStream.Skip(0x1C);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeType(TypeBlock typeBlock)
|
private void writeType(TypeBlock typeBlock)
|
||||||
{
|
{
|
||||||
writeStr(typeBlock.Name);
|
xomStream.WriteStr(typeBlock.Name);
|
||||||
skip(0x4);
|
xomStream.Skip(0x4);
|
||||||
writeInt32(typeBlock.NumCtnr);
|
xomStream.WriteInt32(typeBlock.NumCtnr);
|
||||||
skip(0x4);
|
xomStream.Skip(0x4);
|
||||||
writeBytes(typeBlock.Md5);
|
xomStream.WriteBytes(typeBlock.Md5);
|
||||||
writeStrLen(typeBlock.TypeName, 0x20);
|
xomStream.WriteStrLen(typeBlock.TypeName, 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void writeGuid(GuidBlock guidBlock)
|
private void writeGuid(GuidBlock guidBlock)
|
||||||
{
|
{
|
||||||
writeStr(guidBlock.Name);
|
xomStream.WriteStr(guidBlock.Name);
|
||||||
writeInt32(guidBlock.Unk0);
|
xomStream.WriteInt32(guidBlock.Unk0);
|
||||||
writeInt32(guidBlock.Unk1);
|
xomStream.WriteInt32(guidBlock.Unk1);
|
||||||
writeInt32(guidBlock.Unk2);
|
xomStream.WriteInt32(guidBlock.Unk2);
|
||||||
}
|
}
|
||||||
private void writeSchm(SchmBlock schmBlock)
|
private void writeSchm(SchmBlock schmBlock)
|
||||||
{
|
{
|
||||||
writeStr(schmBlock.Name);
|
xomStream.WriteStr(schmBlock.Name);
|
||||||
writeInt32(schmBlock.Unk0);
|
xomStream.WriteInt32(schmBlock.Unk0);
|
||||||
writeInt32(schmBlock.Unk1);
|
xomStream.WriteInt32(schmBlock.Unk1);
|
||||||
writeInt32(schmBlock.Unk2);
|
xomStream.WriteInt32(schmBlock.Unk2);
|
||||||
}
|
}
|
||||||
private void writeStrs(StrsBlock strsBlock)
|
private void writeStrs(StrsBlock strsBlock)
|
||||||
{
|
{
|
||||||
writeStr(strsBlock.Name);
|
xomStream.WriteStr(strsBlock.Name);
|
||||||
writeInt32(strsBlock.NumStrs);
|
xomStream.WriteInt32(strsBlock.NumStrs);
|
||||||
writeInt32(strsBlock.StringsSectionSz);
|
xomStream.WriteInt32(strsBlock.StringsSectionSz);
|
||||||
|
|
||||||
foreach (int offset in strsBlock.OffsetList)
|
foreach (int offset in strsBlock.OffsetList)
|
||||||
writeInt32(offset);
|
xomStream.WriteInt32(offset);
|
||||||
foreach (string str in strsBlock.StringList)
|
foreach (string str in strsBlock.StringList)
|
||||||
writeCStr(str);
|
xomStream.WriteCStr(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeCtnr(CtnrBlock ctnrBlock)
|
private void writeCtnr(CtnrBlock ctnrBlock)
|
||||||
{
|
{
|
||||||
writeStr(ctnrBlock.Name);
|
xomStream.WriteStr(ctnrBlock.Name);
|
||||||
writeBytes(ctnrBlock.Data);
|
xomStream.WriteBytes(ctnrBlock.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeBlocks(XomBlock[] blocks)
|
private void writeBlocks(XomBlock[] blocks)
|
||||||
|
@ -165,7 +92,7 @@ namespace LibXom
|
||||||
}
|
}
|
||||||
internal XomWriter(Stream xomStream, XomFile xomFile)
|
internal XomWriter(Stream xomStream, XomFile xomFile)
|
||||||
{
|
{
|
||||||
this.xomStream = xomStream;
|
this.xomStream = new XomStreamWriter(xomStream);
|
||||||
this.xomFile = xomFile;
|
this.xomFile = xomFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.4.33205.214
|
VisualStudioVersion = 17.4.33205.214
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worms4Editor", "Worms4Editor\Worms4Editor.csproj", "{FBAA43A5-824F-4C9A-97BC-7B18A42413B9}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worms4Editor", "Worms4Editor\Worms4Editor.csproj", "{FBAA43A5-824F-4C9A-97BC-7B18A42413B9}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibXom", "LibXom\LibXom.csproj", "{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibXom", "LibXom\LibXom.csproj", "{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibW4M", "LibW4M\LibW4M.csproj", "{ABA3728B-4745-4622-B140-A82C07AF4992}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -21,6 +23,10 @@ Global
|
||||||
{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7B60E17C-780E-44D3-BF02-9F5712DD3AE2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{ABA3728B-4745-4622-B140-A82C07AF4992}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{ABA3728B-4745-4622-B140-A82C07AF4992}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{ABA3728B-4745-4622-B140-A82C07AF4992}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{ABA3728B-4745-4622-B140-A82C07AF4992}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -10,20 +10,22 @@ namespace Worms4Editor
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
XomFile xfile = XomReader.ReadXomFile(@"Original.xom");
|
XomFile xfile = XomReader.ReadXomFile(@"SaveGame.xom");
|
||||||
//XomFile ps2file = XomReader.ReadXomFile(@"ps2.xom");
|
|
||||||
|
foreach(XomType type in xfile.XomTypes)
|
||||||
XomType type = xfile.GetTypeByName("StoredStatsCollective");
|
|
||||||
XomContainer container = type.Containers.First();
|
|
||||||
File.WriteAllBytes("StoredStatsCollective.bin", container.DecompressToBytes());
|
|
||||||
|
|
||||||
for(int i = 0; i < xfile.XomStrings.Length; i++)
|
|
||||||
{
|
{
|
||||||
XomString str = xfile.XomStrings[i];
|
Console.WriteLine(type.Name);
|
||||||
Console.WriteLine(str.Id.ToString("X") + ": " + str.Value);
|
|
||||||
|
if (Directory.Exists(type.Name)) Directory.Delete(type.Name, true);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(type.Name);
|
||||||
|
foreach(XomContainer container in type.Containers)
|
||||||
|
{
|
||||||
|
string name = Path.Combine(type.Name, container.Id.ToString("X") + ".bin");
|
||||||
|
File.WriteAllBytes(name, container.GetData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XomWriter.WriteXom(xfile, @"Original2.xom");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue