Fixed bugs in RSC Meta/XML conversion

This commit is contained in:
dexy 2019-01-28 23:51:52 +11:00
parent 43f6acda7a
commit 75748ad3d0
5 changed files with 130 additions and 53 deletions

View File

@ -2690,41 +2690,67 @@ namespace CodeWalker.GameFiles
{ {
foreach (RpfEntry entry in file.AllEntries) foreach (RpfEntry entry in file.AllEntries)
{ {
try //try
{ {
var n = entry.NameLower; var n = entry.NameLower;
if (n.EndsWith(".ymap")) //if (n.EndsWith(".ymap"))
//{
// UpdateStatus(string.Format(entry.Path));
// YmapFile ymapfile = RpfMan.GetFile<YmapFile>(entry);
// if ((ymapfile != null) && (ymapfile.Meta != null))
// {
// MetaTypes.EnsureMetaTypes(ymapfile.Meta);
// }
//}
//else if (n.EndsWith(".ytyp"))
//{
// UpdateStatus(string.Format(entry.Path));
// YtypFile ytypfile = RpfMan.GetFile<YtypFile>(entry);
// if ((ytypfile != null) && (ytypfile.Meta != null))
// {
// MetaTypes.EnsureMetaTypes(ytypfile.Meta);
// }
//}
//else if (n.EndsWith(".ymt"))
//{
// UpdateStatus(string.Format(entry.Path));
// YmtFile ymtfile = RpfMan.GetFile<YmtFile>(entry);
// if ((ymtfile != null) && (ymtfile.Meta != null))
// {
// MetaTypes.EnsureMetaTypes(ymtfile.Meta);
// }
//}
if (n.EndsWith(".ymap") || n.EndsWith(".ytyp") || n.EndsWith(".ymt"))
{ {
var rfe = entry as RpfResourceFileEntry;
if (rfe == null) continue;
UpdateStatus(string.Format(entry.Path)); UpdateStatus(string.Format(entry.Path));
YmapFile ymapfile = RpfMan.GetFile<YmapFile>(entry);
if ((ymapfile != null) && (ymapfile.Meta != null)) var data = rfe.File.ExtractFile(rfe);
{ ResourceDataReader rd = new ResourceDataReader(rfe, data);
MetaTypes.EnsureMetaTypes(ymapfile.Meta); var meta = rd.ReadBlock<Meta>();
} var xml = MetaXml.GetXml(meta);
} var xdoc = new XmlDocument();
else if (n.EndsWith(".ytyp")) xdoc.LoadXml(xml);
{ var meta2 = XmlMeta.GetMeta(xdoc);
UpdateStatus(string.Format(entry.Path)); var xml2 = MetaXml.GetXml(meta2);
YtypFile ytypfile = RpfMan.GetFile<YtypFile>(entry);
if ((ytypfile != null) && (ytypfile.Meta != null)) if (xml.Length != xml2.Length)
{ { }
MetaTypes.EnsureMetaTypes(ytypfile.Meta); if ((xml != xml2)&&(!n.EndsWith("srl.ymt") && !n.StartsWith("des_")))
} { }
}
else if (n.EndsWith(".ymt"))
{
UpdateStatus(string.Format(entry.Path));
YmtFile ymtfile = RpfMan.GetFile<YmtFile>(entry);
if ((ymtfile != null) && (ymtfile.Meta != null))
{
MetaTypes.EnsureMetaTypes(ymtfile.Meta);
}
} }
} }
catch (Exception ex) //catch (Exception ex)
{ //{
UpdateStatus("Error! " + ex.ToString()); // UpdateStatus("Error! " + ex.ToString());
} //}
} }
} }

View File

@ -929,6 +929,13 @@ namespace CodeWalker.GameFiles
public uint PointerDataIndex { get { return (Ptr0 & 0xFFF) - 1; } } public uint PointerDataIndex { get { return (Ptr0 & 0xFFF) - 1; } }
public uint PointerDataOffset { get { return ((Ptr0 >> 12) & 0xFFFFF); } } public uint PointerDataOffset { get { return ((Ptr0 >> 12) & 0xFFFFF); } }
public DataBlockPointer(int blockId, int offset)
{
Ptr0 = ((uint)blockId & 0xFFF) | (((uint)offset & 0xFFFFF) << 12);
Ptr1 = 0;
}
public override string ToString() public override string ToString()
{ {
return "DataBlockPointer: " + Ptr0.ToString() + ", " + Ptr1.ToString(); return "DataBlockPointer: " + Ptr0.ToString() + ", " + Ptr1.ToString();

View File

@ -27,6 +27,10 @@ namespace CodeWalker.GameFiles
} }
} }
} }
return AddBlock(type);
}
public MetaBuilderBlock AddBlock(MetaName type)
{
MetaBuilderBlock b = new MetaBuilderBlock(); MetaBuilderBlock b = new MetaBuilderBlock();
b.StructureNameHash = type; b.StructureNameHash = type;
b.Index = Blocks.Count; b.Index = Blocks.Count;
@ -91,12 +95,7 @@ namespace CodeWalker.GameFiles
MetaBuilderBlock block = EnsureBlock(MetaName.STRING); MetaBuilderBlock block = EnsureBlock(MetaName.STRING);
byte[] data = Encoding.ASCII.GetBytes(str); byte[] data = Encoding.ASCII.GetBytes(str);
int datalen = data.Length; int datalen = data.Length;
int newlen = datalen; int newlen = datalen + 1; //include null terminator
int lenrem = newlen % 16;
if (lenrem != 0) //need to pad the data length up to multiple of 16.
{
newlen += (16 - lenrem);
}
byte[] newdata = new byte[newlen]; byte[] newdata = new byte[newlen];
Buffer.BlockCopy(data, 0, newdata, 0, datalen); Buffer.BlockCopy(data, 0, newdata, 0, datalen);
int offs = block.TotalSize; int offs = block.TotalSize;
@ -104,7 +103,7 @@ namespace CodeWalker.GameFiles
MetaBuilderPointer r = new MetaBuilderPointer(); MetaBuilderPointer r = new MetaBuilderPointer();
r.BlockID = block.Index + 1; r.BlockID = block.Index + 1;
r.Offset = offs;// (idx * data.Length); r.Offset = offs;// (idx * data.Length);
r.Length = datalen; //actual length of string. r.Length = datalen; //actual length of string. (not incl null terminator)
return r; return r;
} }
@ -193,6 +192,14 @@ namespace CodeWalker.GameFiles
var ptr = AddString(str); var ptr = AddString(str);
return new CharPointer(ptr); return new CharPointer(ptr);
} }
public DataBlockPointer AddDataBlockPtr(byte[] data, MetaName type)
{
var block = AddBlock(type);
int offs = block.TotalSize;//should always be 0...
int idx = block.AddItem(data);
var ptr = new DataBlockPointer(block.Index + 1, offs);
return ptr;
}
public Array_StructurePointer AddPointerArray(MetaPOINTER[] arr) public Array_StructurePointer AddPointerArray(MetaPOINTER[] arr)
@ -351,19 +358,35 @@ namespace CodeWalker.GameFiles
m.RootBlockIndex = 1; //assume first block is root. todo: make adjustable? m.RootBlockIndex = 1; //assume first block is root. todo: make adjustable?
m.StructureInfos = new ResourceSimpleArray<MetaStructureInfo>(); if (StructureInfos.Count > 0)
foreach (var si in StructureInfos.Values)
{ {
m.StructureInfos.Add(si); m.StructureInfos = new ResourceSimpleArray<MetaStructureInfo>();
foreach (var si in StructureInfos.Values)
{
m.StructureInfos.Add(si);
}
m.StructureInfosCount = (short)m.StructureInfos.Count;
}
else
{
m.StructureInfos = null;
m.StructureInfosCount = 0;
} }
m.StructureInfosCount = (short)m.StructureInfos.Count;
m.EnumInfos = new ResourceSimpleArray<MetaEnumInfo>(); if (EnumInfos.Count > 0)
foreach (var ei in EnumInfos.Values)
{ {
m.EnumInfos.Add(ei); m.EnumInfos = new ResourceSimpleArray<MetaEnumInfo>();
foreach (var ei in EnumInfos.Values)
{
m.EnumInfos.Add(ei);
}
m.EnumInfosCount = (short)m.EnumInfos.Count;
}
else
{
m.EnumInfos = null;
m.EnumInfosCount = 0;
} }
m.EnumInfosCount = (short)m.EnumInfos.Count;
m.DataBlocks = new ResourceSimpleArray<MetaDataBlock>(); m.DataBlocks = new ResourceSimpleArray<MetaDataBlock>();
foreach (var bb in Blocks) foreach (var bb in Blocks)

View File

@ -234,10 +234,10 @@ namespace CodeWalker.GameFiles
OneLineTag(sb, cind, ename, charStr); OneLineTag(sb, cind, ename, charStr);
break; break;
case MetaStructureEntryDataType.DataBlockPointer: case MetaStructureEntryDataType.DataBlockPointer:
OpenTag(sb, cind, ename);
var dataPtr = MetaTypes.ConvertData<DataBlockPointer>(data, eoffset); var dataPtr = MetaTypes.ConvertData<DataBlockPointer>(data, eoffset);
ErrorXml(sb, cind + 1, "DataBlockPointer not currently supported here!"); //TODO! ymap occludeModels vertices data is this type! //need to just get all the data from that block, since this pointer is referring to the whole block! it should be of type BYTE!
CloseTag(sb, cind, ename); var dblock = cont.Meta.GetBlock((int)dataPtr.PointerDataId);
WriteRawArray(sb, dblock.Data, cind, ename, "ByteArray", FormatHexByte, 32);
break; break;
case MetaStructureEntryDataType.Float: case MetaStructureEntryDataType.Float:
var floatVal = BitConverter.ToSingle(data, eoffset); var floatVal = BitConverter.ToSingle(data, eoffset);
@ -577,14 +577,14 @@ namespace CodeWalker.GameFiles
{ {
Meta = meta; Meta = meta;
if (meta.StructureInfos != null) if (meta.StructureInfos?.Data != null)
{ {
foreach (var si in meta.StructureInfos) foreach (var si in meta.StructureInfos)
{ {
structInfos[si.StructureNameHash] = si; structInfos[si.StructureNameHash] = si;
} }
} }
if (meta.EnumInfos != null) if (meta.EnumInfos?.Data != null)
{ {
foreach (var ei in meta.EnumInfos) foreach (var ei in meta.EnumInfos)
{ {

View File

@ -86,11 +86,11 @@ namespace CodeWalker.GameFiles
case MetaStructureEntryDataType.ArrayOfChars: case MetaStructureEntryDataType.ArrayOfChars:
{ {
int offset = entry.DataOffset; int offset = entry.DataOffset;
var split = Split(cnode.InnerText, 2); var split = cnode.InnerText;// Split(cnode.InnerText, 1);
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
byte val = Convert.ToByte(split[j], 16); byte val = (byte)split[j];// Convert.ToByte(split[j], 16);
data[offset] = val; data[offset] = val;
offset += sizeof(byte); offset += sizeof(byte);
} }
@ -128,7 +128,23 @@ namespace CodeWalker.GameFiles
case MetaStructureEntryDataType.DataBlockPointer: case MetaStructureEntryDataType.DataBlockPointer:
{ {
// TODO var ns = NumberStyles.HexNumber;
var ic = CultureInfo.InvariantCulture;
var sa = new[] { ' ', '\n' };
var so = StringSplitOptions.RemoveEmptyEntries;
var split = cnode.InnerText.Trim().Split(sa, so); //split = Split(node.InnerText, 2); to read as unsplitted HEX
var bytes = new List<byte>();
for (int j = 0; j < split.Length; j++)
{
byte val;// = Convert.ToByte(split[j], 10);
if (byte.TryParse(split[j].Trim(), ns, ic, out val))
{
bytes.Add(val);
}
}
var ptr = mb.AddDataBlockPtr(bytes.ToArray(), MetaName.BYTE);
var byt = MetaTypes.ConvertToBytes(ptr);
Buffer.BlockCopy(byt, 0, data, entry.DataOffset, byt.Length);
break; break;
} }
@ -735,8 +751,13 @@ namespace CodeWalker.GameFiles
private static int GetEnumInt(MetaName type, string enumString, MetaStructureEntryDataType dataType) private static int GetEnumInt(MetaName type, string enumString, MetaStructureEntryDataType dataType)
{ {
var infos = MetaTypes.GetEnumInfo(type); var intval = 0;
if (int.TryParse(enumString, out intval))
{
return intval; //it's already an int.... maybe enum not found or has no entries... or original value didn't match anything
}
var infos = MetaTypes.GetEnumInfo(type);
if (infos == null) if (infos == null)
{ {
return 0; return 0;