diff --git a/BlendFile/BlendFile.csproj b/BlendFile/BlendFile.csproj
index f45969b..df6f659 100644
--- a/BlendFile/BlendFile.csproj
+++ b/BlendFile/BlendFile.csproj
@@ -14,6 +14,9 @@
BlendFile.cs
+
+ StrExt.cs
+
diff --git a/BlendFile/Reader.cs b/BlendFile/Reader.cs
index 815fd52..0426b27 100644
--- a/BlendFile/Reader.cs
+++ b/BlendFile/Reader.cs
@@ -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()!.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()!.IsPointer).ToList();
+ // for each pointer field
foreach (var f in list) {
+ // get the pointer value
var addr = GetBlockFieldDataOffset(obj.Key.Item1, f.GetCustomAttribute()!.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