Fixed YED/XML conversion

This commit is contained in:
dexy 2024-07-22 21:06:18 +10:00
parent 5d3849b682
commit 97c24710e4
3 changed files with 333 additions and 460 deletions

View File

@ -3203,9 +3203,7 @@ namespace CodeWalker.GameFiles
{ {
foreach (RpfEntry entry in file.AllEntries) foreach (RpfEntry entry in file.AllEntries)
{ {
#if !DEBUG //try
try
#endif
{ {
var n = entry.NameLower; var n = entry.NameLower;
if (!(n.EndsWith(".pso") || if (!(n.EndsWith(".pso") ||
@ -3273,13 +3271,11 @@ namespace CodeWalker.GameFiles
} }
} }
} }
#if !DEBUG //catch (Exception ex)
catch (Exception ex) //{
{ // UpdateStatus("Error! " + ex.ToString());
UpdateStatus("Error! " + ex.ToString()); // exceptions.Add(ex);
exceptions.Add(ex); //}
}
#endif
} }
} }
@ -3381,9 +3377,7 @@ namespace CodeWalker.GameFiles
{ {
foreach (RpfEntry entry in file.AllEntries) foreach (RpfEntry entry in file.AllEntries)
{ {
#if !DEBUG //try
try
#endif
{ {
var rfe = entry as RpfFileEntry; var rfe = entry as RpfFileEntry;
if (rfe == null) continue; if (rfe == null) continue;
@ -3398,13 +3392,11 @@ namespace CodeWalker.GameFiles
//PsoTypes.EnsurePsoTypes(cut.Pso); //PsoTypes.EnsurePsoTypes(cut.Pso);
} }
} }
#if !DEBUG //catch (Exception ex)
catch (Exception ex) //{
{ // UpdateStatus("Error! " + ex.ToString());
UpdateStatus("Error! " + ex.ToString()); // exceptions.Add(ex);
exceptions.Add(ex); //}
}
#endif
} }
} }
@ -3422,9 +3414,7 @@ namespace CodeWalker.GameFiles
{ {
foreach (RpfEntry entry in file.AllEntries) foreach (RpfEntry entry in file.AllEntries)
{ {
#if !DEBUG //try
try
#endif
{ {
var rfe = entry as RpfFileEntry; var rfe = entry as RpfFileEntry;
if (rfe == null) continue; if (rfe == null) continue;
@ -3438,13 +3428,11 @@ namespace CodeWalker.GameFiles
} }
} }
#if !DEBUG //catch (Exception ex)
catch (Exception ex) //{
{ // UpdateStatus("Error! " + ex.ToString());
UpdateStatus("Error! " + ex.ToString()); // exceptions.Add(ex);
exceptions.Add(ex); //}
}
#endif
} }
} }
@ -3453,16 +3441,14 @@ namespace CodeWalker.GameFiles
} }
public void TestYeds() public void TestYeds()
{ {
bool xmltest = true;
var exceptions = new List<Exception>(); var exceptions = new List<Exception>();
foreach (RpfFile file in AllRpfs) foreach (RpfFile file in AllRpfs)
{ {
foreach (RpfEntry entry in file.AllEntries) foreach (RpfEntry entry in file.AllEntries)
{ {
#if !DEBUG //try
try
#endif
{ {
var rfe = entry as RpfFileEntry; var rfe = entry as RpfFileEntry;
if (rfe == null) continue; if (rfe == null) continue;
@ -3474,24 +3460,25 @@ namespace CodeWalker.GameFiles
YedFile yed = new YedFile(rfe); YedFile yed = new YedFile(rfe);
RpfMan.LoadFile(yed, rfe); RpfMan.LoadFile(yed, rfe);
var xml = YedXml.GetXml(yed); if (xmltest)
var yed2 = XmlYed.GetYed(xml); {
var data2 = yed2.Save(); var xml = YedXml.GetXml(yed);
var yed3 = new YedFile(); var yed2 = XmlYed.GetYed(xml);
RpfFile.LoadResourceFile(yed3, data2, 25);//full roundtrip var data2 = yed2.Save();
var xml2 = YedXml.GetXml(yed3); var yed3 = new YedFile();
if (xml != xml2) RpfFile.LoadResourceFile(yed3, data2, 25);//full roundtrip
{ } var xml2 = YedXml.GetXml(yed3);
if (xml != xml2)
{ }//no hitting
}
} }
} }
#if !DEBUG //catch (Exception ex)
catch (Exception ex) //{
{ // UpdateStatus("Error! " + ex.ToString());
UpdateStatus("Error! " + ex.ToString()); // exceptions.Add(ex);
exceptions.Add(ex); //}
}
#endif
} }
} }
@ -4370,9 +4357,7 @@ namespace CodeWalker.GameFiles
{ {
foreach (RpfEntry entry in file.AllEntries) foreach (RpfEntry entry in file.AllEntries)
{ {
#if !DEBUG //try
try
#endif
{ {
var rfe = entry as RpfFileEntry; var rfe = entry as RpfFileEntry;
if (rfe == null) continue; if (rfe == null) continue;
@ -4397,13 +4382,11 @@ namespace CodeWalker.GameFiles
} }
} }
#if !DEBUG //catch (Exception ex)
catch (Exception ex) //{
{ // UpdateStatus("Error! " + ex.ToString());
UpdateStatus("Error! " + ex.ToString()); // exceptions.Add(ex);
exceptions.Add(ex); //}
}
#endif
} }
} }
@ -4419,9 +4402,7 @@ namespace CodeWalker.GameFiles
{ {
foreach (RpfEntry entry in file.AllEntries) foreach (RpfEntry entry in file.AllEntries)
{ {
#if !DEBUG //try
try
#endif
{ {
var rfe = entry as RpfFileEntry; var rfe = entry as RpfFileEntry;
if (rfe == null) continue; if (rfe == null) continue;
@ -4444,13 +4425,11 @@ namespace CodeWalker.GameFiles
} }
} }
#if !DEBUG //catch (Exception ex)
catch (Exception ex) //{
{ // UpdateStatus("Error! " + ex.ToString());
UpdateStatus("Error! " + ex.ToString()); // exceptions.Add(ex);
exceptions.Add(ex); //}
}
#endif
} }
} }

View File

@ -38,11 +38,8 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public class ExpressionDictionary : ResourceFileBase [TC(typeof(EXP))] public class ExpressionDictionary : ResourceFileBase
{ {
// pgDictionaryBase // pgDictionary<crExpressions> : pgDictionaryBase
// pgDictionary<crExpressions>
public override long BlockLength => 0x40; public override long BlockLength => 0x40;
// structure data
public uint Unknown_10h { get; set; } = 0; public uint Unknown_10h { get; set; } = 0;
public uint Unknown_14h { get; set; } = 0; public uint Unknown_14h { get; set; } = 0;
public uint Unknown_18h { get; set; } = 1; public uint Unknown_18h { get; set; } = 1;
@ -50,40 +47,32 @@ namespace CodeWalker.GameFiles
public ResourceSimpleList64_s<MetaHash> ExpressionNameHashes { get; set; } public ResourceSimpleList64_s<MetaHash> ExpressionNameHashes { get; set; }
public ResourcePointerList64<Expression> Expressions { get; set; } public ResourcePointerList64<Expression> Expressions { get; set; }
public Dictionary<MetaHash, Expression> ExprMap { get; set; } public Dictionary<MetaHash, Expression> ExprMap { get; set; }
public override void Read(ResourceDataReader reader, params object[] parameters) public override void Read(ResourceDataReader reader, params object[] parameters)
{ {
base.Read(reader, parameters); base.Read(reader, parameters);
Unknown_10h = reader.ReadUInt32();
// read structure data Unknown_14h = reader.ReadUInt32();
this.Unknown_10h = reader.ReadUInt32(); Unknown_18h = reader.ReadUInt32();
this.Unknown_14h = reader.ReadUInt32(); Unknown_1Ch = reader.ReadUInt32();
this.Unknown_18h = reader.ReadUInt32(); ExpressionNameHashes = reader.ReadBlock<ResourceSimpleList64_s<MetaHash>>();
this.Unknown_1Ch = reader.ReadUInt32(); Expressions = reader.ReadBlock<ResourcePointerList64<Expression>>();
this.ExpressionNameHashes = reader.ReadBlock<ResourceSimpleList64_s<MetaHash>>();
this.Expressions = reader.ReadBlock<ResourcePointerList64<Expression>>();
BuildMap(); BuildMap();
} }
public override void Write(ResourceDataWriter writer, params object[] parameters) public override void Write(ResourceDataWriter writer, params object[] parameters)
{ {
base.Write(writer, parameters); base.Write(writer, parameters);
writer.Write(Unknown_10h);
// write structure data writer.Write(Unknown_14h);
writer.Write(this.Unknown_10h); writer.Write(Unknown_18h);
writer.Write(this.Unknown_14h); writer.Write(Unknown_1Ch);
writer.Write(this.Unknown_18h); writer.WriteBlock(ExpressionNameHashes);
writer.Write(this.Unknown_1Ch); writer.WriteBlock(Expressions);
writer.WriteBlock(this.ExpressionNameHashes);
writer.WriteBlock(this.Expressions);
} }
public void WriteXml(StringBuilder sb, int indent) public void WriteXml(StringBuilder sb, int indent)
{ {
if (Expressions?.data_items != null) if (Expressions?.data_items != null)
{ {
foreach (var e in Expressions.data_items) foreach (var e in Expressions.data_items)
@ -93,7 +82,6 @@ namespace CodeWalker.GameFiles
YedXml.CloseTag(sb, indent, "Item"); YedXml.CloseTag(sb, indent, "Item");
} }
} }
} }
public void ReadXml(XmlNode node) public void ReadXml(XmlNode node)
{ {
@ -108,6 +96,12 @@ namespace CodeWalker.GameFiles
var e = new Expression(); var e = new Expression();
e.ReadXml(inode); e.ReadXml(inode);
expressions.Add(e); expressions.Add(e);
}
//expressions in the file should be sorted by hash
expressions.Sort((a, b) => a.NameHash.Hash.CompareTo(b.NameHash.Hash));
foreach (var e in expressions)
{
expressionhashes.Add(e.NameHash); expressionhashes.Add(e.NameHash);
} }
} }
@ -182,11 +176,8 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public class Expression : ResourceSystemBlock [TC(typeof(EXP))] public class Expression : ResourceSystemBlock
{ {
// pgBase // crExpressions : pgBase
// crExpressions
public override long BlockLength => 0x90; public override long BlockLength => 0x90;
// structure data
public uint VFT { get; set; } public uint VFT { get; set; }
public uint Unknown_4h { get; set; } = 1; public uint Unknown_4h { get; set; } = 1;
public uint Unknown_8h { get; set; } // 0x00000000 public uint Unknown_8h { get; set; } // 0x00000000
@ -206,13 +197,12 @@ namespace CodeWalker.GameFiles
public uint Unknown_70h { get; set; } = 1; public uint Unknown_70h { get; set; } = 1;
public uint Signature { get; set; } public uint Signature { get; set; }
public uint MaxStreamSize { get; set; } // max length of any item in Streams public uint MaxStreamSize { get; set; } // max length of any item in Streams
public uint Unknown_7Ch { get; set; } // 3 or 2 public uint Unknown_7Ch { get; set; } // 3 or 2 - type or flags?
public uint Unknown_80h { get; set; } // 0x00000000 public uint Unknown_80h { get; set; } // 0x00000000
public uint Unknown_84h { get; set; } // 0x00000000 public uint Unknown_84h { get; set; } // 0x00000000
public uint Unknown_88h { get; set; } // 0x00000000 public uint Unknown_88h { get; set; } // 0x00000000
public uint Unknown_8Ch { get; set; } // 0x00000000 public uint Unknown_8Ch { get; set; } // 0x00000000
// reference data
public string_r Name { get; set; } public string_r Name { get; set; }
public MetaHash NameHash { get; set; } public MetaHash NameHash { get; set; }
@ -221,36 +211,32 @@ namespace CodeWalker.GameFiles
public override void Read(ResourceDataReader reader, params object[] parameters) public override void Read(ResourceDataReader reader, params object[] parameters)
{ {
// read structure data VFT = reader.ReadUInt32();
this.VFT = reader.ReadUInt32(); Unknown_4h = reader.ReadUInt32();
this.Unknown_4h = reader.ReadUInt32(); Unknown_8h = reader.ReadUInt32();
this.Unknown_8h = reader.ReadUInt32(); Unknown_Ch = reader.ReadUInt32();
this.Unknown_Ch = reader.ReadUInt32(); Unknown_10h = reader.ReadUInt32();
this.Unknown_10h = reader.ReadUInt32(); Unknown_14h = reader.ReadUInt32();
this.Unknown_14h = reader.ReadUInt32(); Unknown_18h = reader.ReadUInt32();
this.Unknown_18h = reader.ReadUInt32(); Unknown_1Ch = reader.ReadUInt32();
this.Unknown_1Ch = reader.ReadUInt32(); Streams = reader.ReadBlock<ResourcePointerList64<ExpressionStream>>();
this.Streams = reader.ReadBlock<ResourcePointerList64<ExpressionStream>>(); Tracks = reader.ReadBlock<ResourceSimpleList64_s<ExpressionTrack>>();
this.Tracks = reader.ReadBlock<ResourceSimpleList64_s<ExpressionTrack>>(); Springs = reader.ReadBlock<ResourceSimpleList64<ExpressionSpringDescriptionBlock>>();
this.Springs = reader.ReadBlock<ResourceSimpleList64<ExpressionSpringDescriptionBlock>>(); Variables = reader.ReadBlock<ResourceSimpleList64_s<MetaHash>>();
this.Variables = reader.ReadBlock<ResourceSimpleList64_s<MetaHash>>(); NamePointer = reader.ReadUInt64();
this.NamePointer = reader.ReadUInt64(); NameLength = reader.ReadUInt16();
this.NameLength = reader.ReadUInt16(); NameCapacity = reader.ReadUInt16();
this.NameCapacity = reader.ReadUInt16(); Unknown_6Ch = reader.ReadUInt32();
this.Unknown_6Ch = reader.ReadUInt32(); Unknown_70h = reader.ReadUInt32();
this.Unknown_70h = reader.ReadUInt32(); Signature = reader.ReadUInt32();
this.Signature = reader.ReadUInt32(); MaxStreamSize = reader.ReadUInt32();
this.MaxStreamSize = reader.ReadUInt32(); Unknown_7Ch = reader.ReadUInt32();
this.Unknown_7Ch = reader.ReadUInt32(); Unknown_80h = reader.ReadUInt32();
this.Unknown_80h = reader.ReadUInt32(); Unknown_84h = reader.ReadUInt32();
this.Unknown_84h = reader.ReadUInt32(); Unknown_88h = reader.ReadUInt32();
this.Unknown_88h = reader.ReadUInt32(); Unknown_8Ch = reader.ReadUInt32();
this.Unknown_8Ch = reader.ReadUInt32();
// read reference data Name = reader.ReadBlockAt<string_r>(NamePointer);
this.Name = reader.ReadBlockAt<string_r>(
this.NamePointer // offset
);
JenkIndex.Ensure(GetShortName()); JenkIndex.Ensure(GetShortName());
@ -261,120 +247,46 @@ namespace CodeWalker.GameFiles
#region testing #region testing
//if (Streams?.data_items != null)
//{ }
////if ((this.JiggleData?.data_items?.Length ?? 0) > 0)
//{
// var cnt1 = JiggleData?.data_items?.Length ?? 0;
// var cnt2 = 0;
// foreach (var stream in Streams.data_items)
// {
// foreach (var node in stream.Items)
// {
// if (node is ExpressionNodeJiggle jnode)
// {
// var trackrot = BoneTracks.data_items[jnode.BoneTrackRot];
// var trackpos = BoneTracks.data_items[jnode.BoneTrackPos];
// var jd1 = jnode.JiggleData;
// var jd2 = JiggleData.data_items[cnt2].JiggleData;
// if (!jd1.Compare(jd2))
// { }//no hit
// if (jd2.BoneTag != trackrot.BoneTag)
// { }//no hit
// cnt2++;
// }
// }
// }
// if (cnt1 != cnt2)
// { }//no hit
//}
//long tlen = 0; //long tlen = 0;
//if (Streams?.data_items != null) foreach (var item in Streams.data_items) tlen = Math.Max(tlen, item.BlockLength); //if (Streams?.data_items != null) foreach (var item in Streams.data_items) tlen = Math.Max(tlen, item.BlockLength);
//if (MaxStreamSize != tlen) //if (MaxStreamSize != tlen)
//{ }//no hit //{ }//no hit
//if (Unknown_4h != 1)
//{ }//no hit
//if (Unknown_8h != 0)
//{ }//no hit
//if (Unknown_Ch != 0)
//{ }//no hit
//if (Unknown_10h != 0)
//{ }//no hit
//if (Unknown_14h != 0)
//{ }//no hit
//if (Unknown_18h != 0)
//{ }//no hit
//if (Unknown_1Ch != 0)
//{ }//no hit
//if (NameLength != (Name?.Value?.Length ?? 0))
//{ }//no hit
//if (NameCapacity != (NameLength + 1))
//{ }//no hit
//if (Unknown_6Ch != 0)
//{ }//no hit
//if (Unknown_70h != 1)
//{ }//no hit
//switch (Unknown_74h)
//{
// default:
// break;
//}
//switch (Unknown_7Ch)
//{
// case 3:
// case 2:
// break;
// default:
// break;//no hit
//}
//if (Unknown_80h != 0)
//{ }//no hit
//if (Unknown_84h != 0)
//{ }//no hit
//if (Unknown_88h != 0)
//{ }//no hit
//if (Unknown_8Ch != 0)
//{ }//no hit
#endregion #endregion
} }
public override void Write(ResourceDataWriter writer, params object[] parameters) public override void Write(ResourceDataWriter writer, params object[] parameters)
{ {
// update structure data NamePointer = (ulong)(Name != null ? Name.FilePosition : 0);
this.NamePointer = (ulong)(this.Name != null ? this.Name.FilePosition : 0);
// write structure data writer.Write(VFT);
writer.Write(this.VFT); writer.Write(Unknown_4h);
writer.Write(this.Unknown_4h); writer.Write(Unknown_8h);
writer.Write(this.Unknown_8h); writer.Write(Unknown_Ch);
writer.Write(this.Unknown_Ch); writer.Write(Unknown_10h);
writer.Write(this.Unknown_10h); writer.Write(Unknown_14h);
writer.Write(this.Unknown_14h); writer.Write(Unknown_18h);
writer.Write(this.Unknown_18h); writer.Write(Unknown_1Ch);
writer.Write(this.Unknown_1Ch); writer.WriteBlock(Streams);
writer.WriteBlock(this.Streams); writer.WriteBlock(Tracks);
writer.WriteBlock(this.Tracks); writer.WriteBlock(Springs);
writer.WriteBlock(this.Springs); writer.WriteBlock(Variables);
writer.WriteBlock(this.Variables); writer.Write(NamePointer);
writer.Write(this.NamePointer); writer.Write(NameLength);
writer.Write(this.NameLength); writer.Write(NameCapacity);
writer.Write(this.NameCapacity); writer.Write(Unknown_6Ch);
writer.Write(this.Unknown_6Ch); writer.Write(Unknown_70h);
writer.Write(this.Unknown_70h); writer.Write(Signature);
writer.Write(this.Signature); writer.Write(MaxStreamSize);
writer.Write(this.MaxStreamSize); writer.Write(Unknown_7Ch);
writer.Write(this.Unknown_7Ch); writer.Write(Unknown_80h);
writer.Write(this.Unknown_80h); writer.Write(Unknown_84h);
writer.Write(this.Unknown_84h); writer.Write(Unknown_88h);
writer.Write(this.Unknown_88h); writer.Write(Unknown_8Ch);
writer.Write(this.Unknown_8Ch);
} }
public void WriteXml(StringBuilder sb, int indent) public void WriteXml(StringBuilder sb, int indent)
{ {
YedXml.StringTag(sb, indent, "Name", Name?.Value ?? ""); YedXml.StringTag(sb, indent, "Name", Name?.Value ?? "");
YedXml.ValueTag(sb, indent, "Signature", Signature.ToString()); // TODO: calculate signature YedXml.ValueTag(sb, indent, "Signature", Signature.ToString()); // TODO: calculate signature?
YedXml.ValueTag(sb, indent, "Unk7C", Unknown_7Ch.ToString()); YedXml.ValueTag(sb, indent, "Unk7C", Unknown_7Ch.ToString());
if ((Tracks?.data_items?.Length ?? 0) > 0) if ((Tracks?.data_items?.Length ?? 0) > 0)
@ -408,6 +320,7 @@ namespace CodeWalker.GameFiles
BuildSpringsList(); BuildSpringsList();
UpdateVariables(); UpdateVariables();
UpdateStreamBuffers(); UpdateStreamBuffers();
UpdateJumpInstructions();
} }
public override IResourceBlock[] GetReferences() public override IResourceBlock[] GetReferences()
@ -449,7 +362,6 @@ namespace CodeWalker.GameFiles
} }
} }
public void BuildSpringsList() public void BuildSpringsList()
{ {
var springs = new List<ExpressionSpringDescriptionBlock>(); var springs = new List<ExpressionSpringDescriptionBlock>();
@ -471,7 +383,6 @@ namespace CodeWalker.GameFiles
Springs = new ResourceSimpleList64<ExpressionSpringDescriptionBlock>(); Springs = new ResourceSimpleList64<ExpressionSpringDescriptionBlock>();
Springs.data_items = springs.ToArray(); Springs.data_items = springs.ToArray();
} }
public void UpdateVariables() public void UpdateVariables()
{ {
var dict = new Dictionary<MetaHash, uint>(); var dict = new Dictionary<MetaHash, uint>();
@ -513,7 +424,6 @@ namespace CodeWalker.GameFiles
Variables.data_items = list.ToArray(); Variables.data_items = list.ToArray();
} }
public void UpdateStreamBuffers() public void UpdateStreamBuffers()
{ {
MaxStreamSize = 0; MaxStreamSize = 0;
@ -526,6 +436,26 @@ namespace CodeWalker.GameFiles
} }
} }
} }
public void UpdateJumpInstructions()
{
if (Streams?.data_items != null)
{
foreach (var stream in Streams.data_items)
{
if (stream?.Instructions == null) continue;
foreach (var node in stream.Instructions)
{
if (node is ExpressionInstrJump jump)
{
//indexes and offsets need to be updated already - done by UpdateMaxStreamSize()
var target = stream.Instructions[jump.Index + jump.Data3Offset];
jump.Data1Offset = (uint)(target.Offset1 - jump.Offset1);
jump.Data2Offset = (uint)(target.Offset2 - jump.Offset2);
}
}
}
}
}
public string GetShortName() public string GetShortName()
@ -544,17 +474,12 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public class ExpressionStream : ResourceSystemBlock, IMetaXmlItem [TC(typeof(EXP))] public class ExpressionStream : ResourceSystemBlock, IMetaXmlItem
{ {
public override long BlockLength public override long BlockLength => 16 + Data1.Length + Data2.Length + Data3.Length;
{ public MetaHash NameHash { get; set; }
get { return 16 + Data1.Length + Data2.Length + Data3.Length; }
}
// structure data
public MetaHash NameHash { get; set; }//presumably name hash
public uint Data1Length { get; set; } public uint Data1Length { get; set; }
public uint Data2Length { get; set; } public uint Data2Length { get; set; }
public ushort Data3Length { get; set; } public ushort Data3Length { get; set; }
public ushort Unk0E { get; set; }//what is this? possibly max hierarchy depth public ushort Depth { get; set; }//or stack size?
public byte[] Data1 { get; set; } public byte[] Data1 { get; set; }
public byte[] Data2 { get; set; } public byte[] Data2 { get; set; }
public byte[] Data3 { get; set; } public byte[] Data3 { get; set; }
@ -566,37 +491,32 @@ namespace CodeWalker.GameFiles
public override void Read(ResourceDataReader reader, params object[] parameters) public override void Read(ResourceDataReader reader, params object[] parameters)
{ {
// read structure data NameHash = reader.ReadUInt32();
this.NameHash = reader.ReadUInt32(); Data1Length = reader.ReadUInt32();
this.Data1Length = reader.ReadUInt32(); Data2Length = reader.ReadUInt32();
this.Data2Length = reader.ReadUInt32(); Data3Length = reader.ReadUInt16();
this.Data3Length = reader.ReadUInt16(); Depth = reader.ReadUInt16();
this.Unk0E = reader.ReadUInt16(); Data1 = reader.ReadBytes((int)Data1Length);
this.Data1 = reader.ReadBytes((int)Data1Length); Data2 = reader.ReadBytes((int)Data2Length);
this.Data2 = reader.ReadBytes((int)Data2Length); Data3 = reader.ReadBytes((int)Data3Length);
this.Data3 = reader.ReadBytes((int)Data3Length);
ReadInstructions(); ReadInstructions();
} }
public override void Write(ResourceDataWriter writer, params object[] parameters) public override void Write(ResourceDataWriter writer, params object[] parameters)
{ {
//WriteItems();//should already be done by Expression.UpdateStreamBuffers //WriteInstructions();//should already be done by Expression.UpdateStreamBuffers
writer.Write(NameHash);
// write structure data writer.Write(Data1Length);
writer.Write(this.NameHash); writer.Write(Data2Length);
writer.Write(this.Data1Length); writer.Write(Data3Length);
writer.Write(this.Data2Length); writer.Write(Depth);
writer.Write(this.Data3Length); writer.Write(Data1);
writer.Write(this.Unk0E); writer.Write(Data2);
writer.Write(this.Data1); writer.Write(Data3);
writer.Write(this.Data2);
writer.Write(this.Data3);
} }
public void WriteXml(StringBuilder sb, int indent) public void WriteXml(StringBuilder sb, int indent)
{ {
YedXml.StringTag(sb, indent, "Name", YedXml.HashString(NameHash)); YedXml.StringTag(sb, indent, "Name", YedXml.HashString(NameHash));
YedXml.ValueTag(sb, indent, "Unk0E", Unk0E.ToString()); YedXml.ValueTag(sb, indent, "Depth", Depth.ToString());
YedXml.OpenTag(sb, indent, "Instructions"); YedXml.OpenTag(sb, indent, "Instructions");
var cind = indent + 1; var cind = indent + 1;
@ -621,7 +541,7 @@ namespace CodeWalker.GameFiles
public void ReadXml(XmlNode node) public void ReadXml(XmlNode node)
{ {
NameHash = XmlMeta.GetHash(Xml.GetChildInnerText(node, "Name")); NameHash = XmlMeta.GetHash(Xml.GetChildInnerText(node, "Name"));
Unk0E = (ushort)Xml.GetChildUIntAttribute(node, "Unk0E", "value"); Depth = (ushort)Xml.GetChildUIntAttribute(node, "Depth", "value");
var items = new List<ExpressionInstrBase>(); var items = new List<ExpressionInstrBase>();
var instnode = node.SelectSingleNode("Instructions"); var instnode = node.SelectSingleNode("Instructions");
@ -639,6 +559,8 @@ namespace CodeWalker.GameFiles
item.ReadXml(inode); item.ReadXml(inode);
items.Add(item); items.Add(item);
} }
else
{ }
} }
} }
} }
@ -647,81 +569,37 @@ namespace CodeWalker.GameFiles
public void ReadInstructions() public void ReadInstructions()
{ {
var insts = new ExpressionInstrBase[Data3.Length];
var s1 = new MemoryStream(Data1); var s1 = new MemoryStream(Data1);
var s2 = new MemoryStream(Data2); var s2 = new MemoryStream(Data2);
var s3 = new MemoryStream(Data3);
var r1 = new DataReader(s1); var r1 = new DataReader(s1);
var r2 = new DataReader(s2); var r2 = new DataReader(s2);
var r3 = new DataReader(s3);
var unresolvedJumps = new Dictionary<(long, long, long), List<ExpressionInstrJump>>(); //dexy: removed unresolvedjumps stuff from here as it should all resolve to jump.Data3Offset+1
var instructions = new List<ExpressionInstrBase>();
while (s3.Position < s3.Length) for (int i = 0; i < insts.Length; i++)
{ {
var loc = (s1.Position, s2.Position, s3.Position); var type = (ExpressionInstrType)Data3[i];
if (type == ExpressionInstrType.End)
var type = (ExpressionInstrType)r3.ReadByte();
if (type == ExpressionInstrType.None)
{ {
if (s3.Position != s3.Length) if (i != insts.Length - 1)
{ }//no hit { }//no hit
break;
} }
var instr = CreateInstruction(type); var instr = CreateInstruction(type);
instr.Type = type; instr.Type = type;
instr.Index = i;
instr.Offset1 = (int)r1.Position;
instr.Offset2 = (int)r2.Position;
instr.Read(r1, r2); instr.Read(r1, r2);
var instrIndex = (uint)instructions.Count; insts[i] = instr;
instructions.Add(instr);
// resolve jumps by converting data byte offsets to instruction indices offsets
// this is to make it easier to edit the XML
if (unresolvedJumps.TryGetValue(loc, out var jumps))
{
foreach (var jump in jumps)
{
// relative offset between jump and target instructions
jump.InstructionOffset = instrIndex - jump.InstructionOffset;
}
unresolvedJumps.Remove(loc);
}
if (instr is ExpressionInstrJump j)
{
j.InstructionOffset = instrIndex;
var targetLoc = (s1.Position + j.Data1Offset, s2.Position + j.Data2Offset, s3.Position + j.Data3Offset);
if (!unresolvedJumps.TryGetValue(targetLoc, out jumps))
{
jumps = new List<ExpressionInstrJump>();
unresolvedJumps[targetLoc] = jumps;
}
jumps.Add(j);
}
} }
// special case to resolve jumps to the end of the instructions list since we don't store the finish marker instruction
var endLoc = (s1.Position, s2.Position, s3.Position - 1);
if (unresolvedJumps.TryGetValue(endLoc, out var endJumps))
{
foreach (var jump in endJumps)
{
jump.InstructionOffset = (uint)instructions.Count - jump.InstructionOffset;
}
unresolvedJumps.Remove(endLoc);
}
if ((r1.Length - r1.Position) != 0) if ((r1.Length - r1.Position) != 0)
{ }//no hit { }//no hit
if ((r2.Length - r2.Position) != 0) if ((r2.Length - r2.Position) != 0)
{ }//no hit { }//no hit
if ((r3.Length - r3.Position) != 0)
{ }//no hit
// there should be no unresolved jumps at this point Instructions = insts;
if (unresolvedJumps.Count != 0)
{ }//no hit
Instructions = instructions.ToArray();
} }
public void WriteInstructions() public void WriteInstructions()
@ -735,10 +613,12 @@ namespace CodeWalker.GameFiles
foreach (var instr in Instructions) foreach (var instr in Instructions)
{ {
instr.Offset1 = (int)w1.Position;
instr.Offset2 = (int)w2.Position;
instr.Index = (int)w3.Position;
w3.Write((byte)instr.Type); w3.Write((byte)instr.Type);
instr.Write(w1, w2); instr.Write(w1, w2);
} }
w3.Write((byte)0);
Data1 = s1.ToArray(); Data1 = s1.ToArray();
Data2 = s2.ToArray(); Data2 = s2.ToArray();
@ -753,6 +633,7 @@ namespace CodeWalker.GameFiles
{ {
switch (type) switch (type)
{ {
case ExpressionInstrType.End:
case ExpressionInstrType.Pop: case ExpressionInstrType.Pop:
case ExpressionInstrType.Dup: case ExpressionInstrType.Dup:
case ExpressionInstrType.Push0: case ExpressionInstrType.Push0:
@ -838,7 +719,7 @@ namespace CodeWalker.GameFiles
public enum ExpressionInstrType : byte public enum ExpressionInstrType : byte
{ {
None = 0, End = 0,
Pop = 0x01, Pop = 0x01,
Dup = 0x02, Dup = 0x02,
Push0 = 0x03, Push0 = 0x03,
@ -903,6 +784,9 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public abstract class ExpressionInstrBase [TC(typeof(EXP))] public abstract class ExpressionInstrBase
{ {
public ExpressionInstrType Type { get; set; } public ExpressionInstrType Type { get; set; }
public int Offset1 { get; set; }
public int Offset2 { get; set; }
public int Index { get; set; }
public virtual void Read(DataReader r1, DataReader r2) public virtual void Read(DataReader r1, DataReader r2)
{ } { }
@ -922,12 +806,22 @@ namespace CodeWalker.GameFiles
{ } { }
[TC(typeof(EXP))] public class ExpressionInstrBlend : ExpressionInstrBase [TC(typeof(EXP))] public class ExpressionInstrBlend : ExpressionInstrBase
{ {
public struct SourceInfo
{
public ushort TrackIndex;
public ushort ComponentOffset;
public override string ToString()
{
return $"{TrackIndex} : {ComponentOffset}";
}
}
[TC(typeof(EXP))] public class SourceComponent : IMetaXmlItem [TC(typeof(EXP))] public class SourceComponent : IMetaXmlItem
{ {
public float[] Weights { get; set; } public float[] Weights { get; set; }
public float[] Offsets { get; set; } public float[] Offsets { get; set; }
public float[] Thresholds { get; set; } public float[] Thresholds { get; set; }
public SourceComponent() { }
public SourceComponent(uint numSourceWeights) public SourceComponent(uint numSourceWeights)
{ {
Weights = new float[numSourceWeights]; Weights = new float[numSourceWeights];
@ -941,25 +835,59 @@ namespace CodeWalker.GameFiles
YedXml.WriteRawArray(sb, Offsets, indent, "Offsets", "", FloatUtil.ToString, 32); YedXml.WriteRawArray(sb, Offsets, indent, "Offsets", "", FloatUtil.ToString, 32);
YedXml.WriteRawArray(sb, Thresholds, indent, "Thresholds", "", FloatUtil.ToString, 32); YedXml.WriteRawArray(sb, Thresholds, indent, "Thresholds", "", FloatUtil.ToString, 32);
} }
public void ReadXml(XmlNode node) public void ReadXml(XmlNode node)
{ {
throw new NotImplementedException(); if (node == null) return;
Weights = Xml.GetChildRawFloatArray(node, "Weights");
Offsets = Xml.GetChildRawFloatArray(node, "Offsets");
Thresholds = Xml.GetChildRawFloatArray(node, "Thresholds");
} }
} }
[TC(typeof(EXP))] public class Source : IMetaXmlItem [TC(typeof(EXP))] public class Source : IMetaXmlItem
{ {
public ushort TrackIndex { get; set; } public SourceInfo Info { get; set; }
public ushort ComponentOffset { get; set; }
public SourceComponent X { get; set; } public SourceComponent X { get; set; }
public SourceComponent Y { get; set; } public SourceComponent Y { get; set; }
public SourceComponent Z { get; set; } public SourceComponent Z { get; set; }
public Source()
{ }
public Source(SourceInfo info, uint numSourceWeights, int index, Vector4[] values)
{
Info = info;
X = new SourceComponent(numSourceWeights);
Y = new SourceComponent(numSourceWeights);
Z = new SourceComponent(numSourceWeights);
var j = index / 4;
var k = index % 4;
var v = j * (6 + 9 * (int)(numSourceWeights - 1));
X.Weights[0] = values[v + 0][k];
Y.Weights[0] = values[v + 1][k];
Z.Weights[0] = values[v + 2][k];
X.Offsets[0] = values[v + 3][k];
Y.Offsets[0] = values[v + 4][k];
Z.Offsets[0] = values[v + 5][k];
for (int n = 1; n < numSourceWeights; n++)
{
var m = n - 1;
var b = v + 6 + (9 * m);
X.Thresholds[m] = values[b + 0][k];
Y.Thresholds[m] = values[b + 1][k];
Z.Thresholds[m] = values[b + 2][k];
X.Weights[n] = values[b + 3][k];
Y.Weights[n] = values[b + 4][k];
Z.Weights[n] = values[b + 5][k];
X.Offsets[n] = values[b + 6][k];
Y.Offsets[n] = values[b + 7][k];
Z.Offsets[n] = values[b + 8][k];
}
}
public void WriteXml(StringBuilder sb, int indent) public void WriteXml(StringBuilder sb, int indent)
{ {
YedXml.ValueTag(sb, indent, "TrackIndex", TrackIndex.ToString()); YedXml.ValueTag(sb, indent, "TrackIndex", Info.TrackIndex.ToString());
YedXml.ValueTag(sb, indent, "ComponentIndex", (ComponentOffset / 4).ToString()); YedXml.ValueTag(sb, indent, "ComponentIndex", (Info.ComponentOffset / 4).ToString());
YedXml.OpenTag(sb, indent, "X"); YedXml.OpenTag(sb, indent, "X");
X.WriteXml(sb, indent + 1); X.WriteXml(sb, indent + 1);
YedXml.CloseTag(sb, indent, "X"); YedXml.CloseTag(sb, indent, "X");
@ -970,25 +898,74 @@ namespace CodeWalker.GameFiles
Z.WriteXml(sb, indent + 1); Z.WriteXml(sb, indent + 1);
YedXml.CloseTag(sb, indent, "Z"); YedXml.CloseTag(sb, indent, "Z");
} }
public void ReadXml(XmlNode node) public void ReadXml(XmlNode node)
{ {
throw new NotImplementedException(); var info = new SourceInfo();
info.TrackIndex = (ushort)Xml.GetChildUIntAttribute(node, "TrackIndex", "value");
info.ComponentOffset = (ushort)(Xml.GetChildUIntAttribute(node, "ComponentIndex", "value") * 4);
Info = info;
X = new SourceComponent();
X.ReadXml(node.SelectSingleNode("X"));
Y = new SourceComponent();
Y.ReadXml(node.SelectSingleNode("Y"));
Z = new SourceComponent();
Z.ReadXml(node.SelectSingleNode("Z"));
}
public void UpdateValues(uint numSourceWeights, int index, Vector4[] values)
{
if (X == null) return;
if (Y == null) return;
if (Z == null) return;
if (X.Weights?.Length < numSourceWeights) return;
if (Y.Weights?.Length < numSourceWeights) return;
if (Z.Weights?.Length < numSourceWeights) return;
if (X.Offsets?.Length < numSourceWeights) return;
if (Y.Offsets?.Length < numSourceWeights) return;
if (Z.Offsets?.Length < numSourceWeights) return;
if (X.Thresholds?.Length < (numSourceWeights - 1)) return;
if (Y.Thresholds?.Length < (numSourceWeights - 1)) return;
if (Z.Thresholds?.Length < (numSourceWeights - 1)) return;
var j = index / 4;
var k = index % 4;
var v = j * (6 + 9 * (int)(numSourceWeights - 1));
values[v + 0][k] = X.Weights[0];
values[v + 1][k] = Y.Weights[0];
values[v + 2][k] = Z.Weights[0];
values[v + 3][k] = X.Offsets[0];
values[v + 4][k] = Y.Offsets[0];
values[v + 5][k] = Z.Offsets[0];
for (int n = 1; n < numSourceWeights; n++)
{
var m = n - 1;
var b = v + 6 + (9 * m);
values[b + 0][k] = X.Thresholds[m];
values[b + 1][k] = Y.Thresholds[m];
values[b + 2][k] = Z.Thresholds[m];
values[b + 3][k] = X.Weights[n];
values[b + 4][k] = Y.Weights[n];
values[b + 5][k] = Z.Weights[n];
values[b + 6][k] = X.Offsets[n];
values[b + 7][k] = Y.Offsets[n];
values[b + 8][k] = Z.Offsets[n];
}
} }
public override string ToString() public override string ToString()
{ {
return "TODO"; // TODO return $"TrackIndex {Info.TrackIndex}, ComponentIndex {Info.ComponentOffset / 4} (offset {Info.ComponentOffset})";
} }
} }
public uint ByteLength { get; set; } //updated automatically public uint ByteLength { get; set; } //updated automatically
public uint SourceCount { get; set; } //updated automatically public uint SourceCount { get; set; } //updated automatically //0-84+, multiple of 4
public uint NumSourceWeights { get; set; } public uint NumSourceWeights { get; set; }//1-4
public uint Unk1 { get; set; } // 0x00000000 public uint Unk1 { get; set; } // 0x00000000
public Source[] Sources { get; set; } public SourceInfo[] SourceInfos { get; set; }
public Vector4[] Values { get; set; } public Vector4[] Values { get; set; }
public uint RequiredValueCount => (SourceCount / 4) * (6 + ((NumSourceWeights - 1) * 9));
public override void Read(DataReader r1, DataReader r2) public override void Read(DataReader r1, DataReader r2)
{ {
ByteLength = r1.ReadUInt32(); ByteLength = r1.ReadUInt32();
@ -996,106 +973,23 @@ namespace CodeWalker.GameFiles
NumSourceWeights = r1.ReadUInt32(); NumSourceWeights = r1.ReadUInt32();
Unk1 = r1.ReadUInt32(); Unk1 = r1.ReadUInt32();
Sources = new Source[SourceCount]; SourceInfos = new SourceInfo[SourceCount];
for (int i = 0; i < SourceCount; i++) for (int i = 0; i < SourceCount; i++)
{ {
var s = new Source(); var s = new SourceInfo();
s.TrackIndex = r1.ReadUInt16(); s.TrackIndex = r1.ReadUInt16();
s.ComponentOffset = r1.ReadUInt16(); s.ComponentOffset = r1.ReadUInt16();
s.X = new SourceComponent(NumSourceWeights); SourceInfos[i] = s;
s.Y = new SourceComponent(NumSourceWeights);
s.Z = new SourceComponent(NumSourceWeights);
Sources[i] = s;
} }
Values = new Vector4[RequiredValueCount];
// TODO: rename for (int i = 0; i < Values.Length; i++)
var numIters = SourceCount / 4;
var numSubpasses = NumSourceWeights - 1;
var numValues = (numIters * 6) + (numIters * numSubpasses * 9);
Values = new Vector4[numValues];
for (int i = 0; i < numValues; i++)
{ {
Values[i] = r1.ReadVector4(); Values[i] = r1.ReadVector4();
} }
switch (SourceCount)
{
case 0:
case 4:
case 8:
case 12:
case 20:
case 24:
case 48:
case 52:
case 76:
case 32:
case 16:
case 40:
case 44:
case 60:
case 72:
case 56:
case 28:
case 68:
break;
default:
break; //no hit
}
switch (NumSourceWeights)
{
case 1: break;
case 2: break;
case 3: break;
case 4: break;
default:
break; //no hit
}
if (Unk1 != 0)
{
} //no hit
// organize data into more human-readable layout
// the file layout is optimized for vectorized operations
for (int i = 0; i < (Sources.Length / 4); i++)
{
var it = i * 4;
int v = i * 6 + (i * (int)(NumSourceWeights - 1) * 9);
for (int k = 0; k < 4; k++)
{
Sources[it + k].X.Weights[0] = Values[v + 0][k];
Sources[it + k].Y.Weights[0] = Values[v + 1][k];
Sources[it + k].Z.Weights[0] = Values[v + 2][k];
Sources[it + k].X.Offsets[0] = Values[v + 3][k];
Sources[it + k].Y.Offsets[0] = Values[v + 4][k];
Sources[it + k].Z.Offsets[0] = Values[v + 5][k];
for (int n = 1; n < NumSourceWeights; n++)
{
int b = v + 6 + (n - 1) * 9;
Sources[it + k].X.Thresholds[n - 1] = Values[b + 0][k];
Sources[it + k].Y.Thresholds[n - 1] = Values[b + 1][k];
Sources[it + k].Z.Thresholds[n - 1] = Values[b + 2][k];
Sources[it + k].X.Weights[n] = Values[b + 3][k];
Sources[it + k].Y.Weights[n] = Values[b + 4][k];
Sources[it + k].Z.Weights[n] = Values[b + 5][k];
Sources[it + k].X.Offsets[n] = Values[b + 6][k];
Sources[it + k].Y.Offsets[n] = Values[b + 7][k];
Sources[it + k].Z.Offsets[n] = Values[b + 8][k];
}
}
}
} }
public override void Write(DataWriter w1, DataWriter w2) public override void Write(DataWriter w1, DataWriter w2)
{ {
// TODO SourceCount = (uint)(SourceInfos?.Length ?? 0);
SourceCount = (uint)(Sources?.Length ?? 0);
NumSourceWeights = Math.Max(NumSourceWeights, 1); NumSourceWeights = Math.Max(NumSourceWeights, 1);
var valcnt = (NumSourceWeights - 1) * 9 + 6; var valcnt = (NumSourceWeights - 1) * 9 + 6;
var hlen = SourceCount * 4 + 16; var hlen = SourceCount * 4 + 16;
@ -1107,32 +1001,43 @@ namespace CodeWalker.GameFiles
w1.Write(NumSourceWeights); w1.Write(NumSourceWeights);
w1.Write(Unk1); w1.Write(Unk1);
// TODO
for (int i = 0; i < SourceCount; i++) for (int i = 0; i < SourceCount; i++)
{ {
// Sources[i].Write(w1); var si = SourceInfos[i];
w1.Write(si.TrackIndex);
w1.Write(si.ComponentOffset);
}
for (int i = 0; i < Values.Length; i++)
{
w1.Write(Values[i]);
} }
// TODO
// for (int n = 0; n < valcnt; n++)
// {
// for (int i = 0; i < ItemCount; i++)
// {
// var vals = Items[i].Values;
// w1.Write((n < (vals?.Length ?? 0)) ? vals[n] : 0.0f);
// }
// }
} }
public override void WriteXml(StringBuilder sb, int indent) public override void WriteXml(StringBuilder sb, int indent)
{ {
YedXml.ValueTag(sb, indent, "NumSourceWeights", NumSourceWeights.ToString()); // organize data into more human-readable layout
YedXml.WriteItemArray(sb, Sources, indent, "Sources"); // the file layout is optimized for vectorized operations
} var sources = new Source[SourceCount];
for (int i = 0; i < SourceCount; i++)
{
sources[i] = new Source(SourceInfos[i], NumSourceWeights, i, Values);
}
YedXml.ValueTag(sb, indent, "NumSourceWeights", NumSourceWeights.ToString());
YedXml.WriteItemArray(sb, sources, indent, "Sources");
}
public override void ReadXml(XmlNode node) public override void ReadXml(XmlNode node)
{ {
NumSourceWeights = Xml.GetChildUIntAttribute(node, "NumSourceWeights"); NumSourceWeights = Math.Max(Xml.GetChildUIntAttribute(node, "NumSourceWeights"), 1);
Sources = XmlMeta.ReadItemArray<Source>(node, "Sources"); var sources = XmlMeta.ReadItemArray<Source>(node, "Sources");
SourceCount = (uint)(sources?.Length ?? 0);
SourceInfos = new SourceInfo[SourceCount];
Values = new Vector4[RequiredValueCount];
for (int i = 0; i < SourceCount; i++)
{
var s = sources[i];
SourceInfos[i] = s.Info;
s.UpdateValues(NumSourceWeights, i, Values);
}
} }
public override string ToString() public override string ToString()
@ -1140,7 +1045,6 @@ namespace CodeWalker.GameFiles
return base.ToString() + " - " + SourceCount + ", " + NumSourceWeights; return base.ToString() + " - " + SourceCount + ", " + NumSourceWeights;
} }
} }
[TC(typeof(EXP))] public class ExpressionInstrBone : ExpressionInstrBase [TC(typeof(EXP))] public class ExpressionInstrBone : ExpressionInstrBase
{ {
public ushort TrackIndex { get; set; } //index of the BoneTag in the Expression.BoneTracks array public ushort TrackIndex { get; set; } //index of the BoneTag in the Expression.BoneTracks array
@ -1179,7 +1083,7 @@ namespace CodeWalker.GameFiles
} }
public override void ReadXml(XmlNode node) public override void ReadXml(XmlNode node)
{ {
TrackIndex = (ushort)Xml.GetChildUIntAttribute(node, "BoneTrack", "value"); TrackIndex = (ushort)Xml.GetChildUIntAttribute(node, "TrackIndex", "value");
BoneId = (ushort)Xml.GetChildUIntAttribute(node, "BoneId", "value"); BoneId = (ushort)Xml.GetChildUIntAttribute(node, "BoneId", "value");
Track = (byte)Xml.GetChildUIntAttribute(node, "Track", "value"); Track = (byte)Xml.GetChildUIntAttribute(node, "Track", "value");
Format = (byte)Xml.GetChildUIntAttribute(node, "Format", "value"); Format = (byte)Xml.GetChildUIntAttribute(node, "Format", "value");
@ -1223,12 +1127,9 @@ namespace CodeWalker.GameFiles
} }
[TC(typeof(EXP))] public class ExpressionInstrJump : ExpressionInstrBase [TC(typeof(EXP))] public class ExpressionInstrJump : ExpressionInstrBase
{ {
// note: unsigned so can only jump forwards public uint Data1Offset { get; set; } // note: unsigned so can only jump forwards
public uint Data1Offset { get; set; }
public uint Data2Offset { get; set; } public uint Data2Offset { get; set; }
public uint Data3Offset { get; set; } public uint Data3Offset { get; set; } //instruction offset
public uint InstructionOffset { get; set; }
public override void Read(DataReader r1, DataReader r2) public override void Read(DataReader r1, DataReader r2)
{ {
@ -1244,18 +1145,11 @@ namespace CodeWalker.GameFiles
} }
public override void WriteXml(StringBuilder sb, int indent) public override void WriteXml(StringBuilder sb, int indent)
{ {
YedXml.ValueTag(sb, indent, "InstructionOffset", InstructionOffset.ToString()); YedXml.ValueTag(sb, indent, "InstructionOffset", Data3Offset.ToString());
// YedXml.ValueTag(sb, indent, "Data1Offset", Data1Offset.ToString());
// YedXml.ValueTag(sb, indent, "Data2Offset", Data2Offset.ToString());
// YedXml.ValueTag(sb, indent, "Data3Offset", Data3Offset.ToString());
} }
public override void ReadXml(XmlNode node) public override void ReadXml(XmlNode node)
{ {
// TODO: calculate data offsets Data3Offset = Xml.GetChildUIntAttribute(node, "InstructionOffset");
InstructionOffset = Xml.GetChildUIntAttribute(node, "InstructionOffset");
// Data1Offset = Xml.GetChildUIntAttribute(node, "Data1Offset");
// Data2Offset = Xml.GetChildUIntAttribute(node, "Data2Offset");
// Data3Offset = Xml.GetChildUIntAttribute(node, "Data3Offset");
} }
public override string ToString() public override string ToString()

View File

@ -343,11 +343,11 @@ namespace CodeWalker.GameFiles
//BaseSize = 0x2000 << BaseShift (max BaseShift = 0xF) //BaseSize = 0x2000 << BaseShift (max BaseShift = 0xF)
//then allocate page counts for the page sizes: //then allocate page counts for the page sizes:
//allows for 5 page sizes, each double the size of the previous, with max counts 0x7F, 0x3F, 0xF, 3, 1 //allows for 5 page sizes, each double the size of the previous, with max counts 0x7F, 0x3F, 0xF, 3, 1
//also allows for 4 tail pages, each half the size of the previous, only one page of each size //also allows for 4 tail pages, each half the size of the previous, only one page of each size [TODO?]
var sys = (basePosition == 0x50000000); var sys = (basePosition == 0x50000000);
var maxPageSizeMult = 16L;//the biggest page is 16x the base page size. var maxPageSizeMult = 16L;//the biggest page is 16x the base page size.
var maxPageSize = (0x2000 << 0xF) * maxPageSizeMult; //this is the size of the biggest possible page [256MB!] var maxPageSize = (0x2000 << 0xF) * maxPageSizeMult; //this is the size of the biggest possible page [4GB!]
var maxBlockSize = 0L; var maxBlockSize = 0L;
var minBlockSize = (blocks.Count == 0) ? 0 : maxPageSize; var minBlockSize = (blocks.Count == 0) ? 0 : maxPageSize;
foreach (var block in blocks) foreach (var block in blocks)
@ -389,7 +389,6 @@ namespace CodeWalker.GameFiles
pageSizes[i] = null; pageSizes[i] = null;
} }
var testOk = true;
var largestPageSizeI = 0; var largestPageSizeI = 0;
var largestPageSize = baseSize; var largestPageSize = baseSize;
while (largestPageSize < maxBlockSize) while (largestPageSize < maxBlockSize)
@ -457,6 +456,7 @@ namespace CodeWalker.GameFiles
} }
} }
var testOk = true;
var totalPageCount = 0u; var totalPageCount = 0u;
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {