173 lines
4.9 KiB
C#
173 lines
4.9 KiB
C#
using LibXom.Blocks;
|
|
using LibXom.Data;
|
|
using System.Text;
|
|
|
|
namespace LibXom
|
|
{
|
|
public class XomWriter
|
|
{
|
|
private Stream xomStream;
|
|
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)
|
|
{
|
|
writeStr(moikBlock.Name);
|
|
writeInt32BE(moikBlock.Version);
|
|
skip(0x10);
|
|
writeInt32(moikBlock.NumTypes);
|
|
writeInt32(moikBlock.NumCtnr);
|
|
writeInt32(moikBlock.NumCtnr);
|
|
skip(0x1C);
|
|
}
|
|
|
|
private void writeType(TypeBlock typeBlock)
|
|
{
|
|
writeStr(typeBlock.Name);
|
|
skip(0x4);
|
|
writeInt32(typeBlock.NumCtnr);
|
|
skip(0x4);
|
|
writeBytes(typeBlock.Md5);
|
|
writeStrLen(typeBlock.TypeName, 0x20);
|
|
}
|
|
|
|
|
|
private void writeGuid(GuidBlock guidBlock)
|
|
{
|
|
writeStr(guidBlock.Name);
|
|
writeInt32(guidBlock.Unk0);
|
|
writeInt32(guidBlock.Unk1);
|
|
writeInt32(guidBlock.Unk2);
|
|
}
|
|
private void writeSchm(SchmBlock schmBlock)
|
|
{
|
|
writeStr(schmBlock.Name);
|
|
writeInt32(schmBlock.Unk0);
|
|
writeInt32(schmBlock.Unk1);
|
|
writeInt32(schmBlock.Unk2);
|
|
}
|
|
private void writeStrs(StrsBlock strsBlock)
|
|
{
|
|
writeStr(strsBlock.Name);
|
|
writeInt32(strsBlock.NumStrs);
|
|
writeInt32(strsBlock.StringsSectionSz);
|
|
|
|
foreach (int offset in strsBlock.OffsetList)
|
|
writeInt32(offset);
|
|
foreach (string str in strsBlock.StringList)
|
|
writeCStr(str);
|
|
}
|
|
|
|
private void writeCtnr(CtnrBlock ctnrBlock)
|
|
{
|
|
writeStr(ctnrBlock.Name);
|
|
writeBytes(ctnrBlock.Data);
|
|
}
|
|
|
|
private void writeBlocks(XomBlock[] blocks)
|
|
{
|
|
foreach(XomBlock block in blocks)
|
|
{
|
|
if (block is MoikBlock) writeMoik(block as MoikBlock);
|
|
if (block is GuidBlock) writeGuid(block as GuidBlock);
|
|
if (block is SchmBlock) writeSchm(block as SchmBlock);
|
|
if (block is StrsBlock) writeStrs(block as StrsBlock);
|
|
if (block is TypeBlock) writeType(block as TypeBlock);
|
|
if (block is CtnrBlock) writeCtnr(block as CtnrBlock);
|
|
|
|
}
|
|
}
|
|
|
|
public static void WriteXom(XomFile xfile, string filename)
|
|
{
|
|
using(FileStream fs = File.OpenWrite(filename))
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
{
|
|
XomWriter writer = new XomWriter(ms, xfile);
|
|
writer.writeBlocks(writer.xomFile.generateBlocks());
|
|
ms.Seek(0, SeekOrigin.Begin);
|
|
ms.CopyTo(fs);
|
|
}
|
|
}
|
|
}
|
|
internal XomWriter(Stream xomStream, XomFile xomFile)
|
|
{
|
|
this.xomStream = xomStream;
|
|
this.xomFile = xomFile;
|
|
}
|
|
}
|
|
}
|