Added pointers and list handling in reader
This commit is contained in:
@@ -14,6 +14,9 @@
|
||||
<Compile Include="..\CodeGenerator\BlendFile.cs">
|
||||
<Link>BlendFile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\CodeGenerator\StrExt.cs">
|
||||
<Link>StrExt.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using CodeGenerator;
|
||||
using Kaitai;
|
||||
using static Kaitai.BlendFile;
|
||||
|
||||
@@ -102,17 +103,40 @@ public class Reader {
|
||||
blockOffset += t.GetCustomAttribute<DNAClassAttribute>()!.Size;
|
||||
}
|
||||
}
|
||||
foreach (var obj in objects) {
|
||||
foreach (var obj in objects) { // for each converted object
|
||||
// get the fields of the object
|
||||
FieldInfo[] fieldInfo = obj.Value.GetType().GetFields();
|
||||
// get all fields that are pointers
|
||||
var list = fieldInfo.Where(fldInfo => fldInfo.GetCustomAttribute<DNAFieldAttribute>()!.IsPointer).ToList();
|
||||
|
||||
// for each pointer field
|
||||
foreach (var f in list) {
|
||||
// get the pointer value
|
||||
var addr = GetBlockFieldDataOffset(obj.Key.Item1, f.GetCustomAttribute<DNAFieldAttribute>()!.OriginalIndex,
|
||||
fieldInfo);
|
||||
// get the object that the pointer is pointing to if we've already converted it
|
||||
var newobj = objects.GetValueOrDefault((addr, f.FieldType));
|
||||
if (newobj != null) f.SetValue(obj.Value, newobj);
|
||||
if (newobj != null)
|
||||
f.SetValue(obj.Value, newobj);
|
||||
else // if we haven't converted the object yet, we need to convert it now
|
||||
{
|
||||
newobj = ActivateInstance(f.FieldType);
|
||||
if (newobj != null)
|
||||
{
|
||||
FillObject(addr, ref newobj, f.FieldType.GetFields());
|
||||
f.SetValue(obj.Value, newobj);
|
||||
Objects.Add((addr, f.FieldType), newobj);
|
||||
} // should never happen
|
||||
else throw new NotSupportedException($"Type \"{f.FieldType}\" is unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var ptr in pointers) {
|
||||
var obj = objects.GetValueOrDefault((ptr.Key, typeof(object)));
|
||||
if (obj == null) continue;
|
||||
InstantiatedObjects.Add(ptr.Key, obj);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -179,6 +203,15 @@ public class Reader {
|
||||
objects.Add((block.MemAddr.ToPointer() + startOffset, obj!.GetType()), obj!);
|
||||
}
|
||||
|
||||
private void FillObject(IntPtr ptr, ref object? obj, FieldInfo[] fieldMetadata)
|
||||
{
|
||||
var block = GetBlock(ptr.ToInt64());
|
||||
if (block == null) throw new($"Block for pointer {ptr.ToInt64():X} not found");
|
||||
|
||||
var blockOffset = ptr.ToInt64() - block.MemAddr.ToPointer();
|
||||
FillObject(block, ref obj, fieldMetadata, new IntPtr(blockOffset));
|
||||
}
|
||||
|
||||
private object? ConvertNormalField(FileBlock block, DNAFieldAttribute attrib, IntPtr startOffset) {
|
||||
//Calculate the offset from where the data of the field starts.
|
||||
//Because the order of the fields is not guaranteed we need to compute it each time
|
||||
@@ -219,11 +252,50 @@ public class Reader {
|
||||
throw new NotSupportedException($"Unknown type \"{attrib.OriginalType}\"");
|
||||
}
|
||||
|
||||
private object? ConvertListField(FileBlock block, FieldInfo field, DNAListAttribute attrib, IntPtr startOffset) {/*
|
||||
IntPtr offset = attrib.MemoryOffset + startOffset;
|
||||
int size = Array.Copy((byte[])block.Body, startOffset+attrib.)
|
||||
var data = new byte[]*/
|
||||
return null;
|
||||
private object? ConvertListField(FileBlock block, FieldInfo field, DNAListAttribute attrib, IntPtr startOffset) {
|
||||
IntPtr countOffset = attrib.CountMemoryOffset + startOffset;
|
||||
IntPtr ptrOffset = attrib.PtrMemoryOffset + startOffset;
|
||||
|
||||
var countLen = attrib.CountFieldName.ParseFSize();
|
||||
var countData = new byte[countLen];
|
||||
Array.Copy((byte[])block.Body, countOffset, countData, 0, countLen);
|
||||
var tmpCount = ConvertFieldData(countData, attrib.CountFieldName);
|
||||
int count;
|
||||
|
||||
switch (tmpCount)
|
||||
{
|
||||
case int i:
|
||||
count = i;
|
||||
break;
|
||||
case short s:
|
||||
count = s;
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException($"Unknown type \"{attrib.CountFieldName}\"");
|
||||
}
|
||||
|
||||
List<Object?> objList = new();
|
||||
|
||||
for(IntPtr ptr = ptrOffset; ptr < ptrOffset + count * sizeof(Int64); ptr += sizeof(Int64)) {
|
||||
var data = new byte[sizeof(Int64)];
|
||||
Array.Copy((byte[])block.Body, ptr, data, 0, sizeof(Int64));
|
||||
IntPtr memAddr = new IntPtr(BitConverter.ToInt64(data, 0));
|
||||
|
||||
if (memAddr == IntPtr.Zero) {
|
||||
objList.Add(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
var obj = ActivateInstance(attrib.UnderlyingType);
|
||||
if (obj == null) throw new NotSupportedException($"Type \"{attrib.UnderlyingType}\" is unknown");
|
||||
|
||||
var fieldMetadata = obj.GetType().GetFields();
|
||||
|
||||
FillObject(memAddr, ref obj, fieldMetadata);
|
||||
objList.Add(obj);
|
||||
}
|
||||
|
||||
return objList;
|
||||
}
|
||||
|
||||
private object? ConvertFieldData(byte[] data, string type) {
|
||||
|
||||
Reference in New Issue
Block a user