diff --git a/src/G2DataGUI.Common/Data/Maps/Maps.cs b/src/G2DataGUI.Common/Data/Maps/Maps.cs
index ec892bf..6a6adb3 100644
--- a/src/G2DataGUI.Common/Data/Maps/Maps.cs
+++ b/src/G2DataGUI.Common/Data/Maps/Maps.cs
@@ -3,6 +3,7 @@
using System.IO;
using System.Threading.Tasks;
using G2DataGUI.Common.Data.Errors;
+using G2DataGUI.Common.Data.Models;
namespace G2DataGUI.Common.Data.Maps;
@@ -36,6 +37,12 @@ private void ReadMaps()
}
CollectionRefreshed?.Invoke(this, EventArgs.Empty);
+
+ using var modelFile = File.Open(
+ "F:\\programming\\languages\\c#\\programs\\G2DataGUI\\build\\Debug\\net7.0\\models\\2a00.chr_model_1.nj",
+ FileMode.Open,
+ FileAccess.Read);
+ NJCM model = NJCM.ReadNJCM(modelFile, 0);
}
catch (Exception ex)
{
diff --git a/src/G2DataGUI.Common/Data/Models/Model.cs b/src/G2DataGUI.Common/Data/Models/Model.cs
new file mode 100644
index 0000000..ffcf941
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/Model.cs
@@ -0,0 +1,6 @@
+namespace G2DataGUI.Common.Data.Models;
+
+public class Model
+{
+
+}
diff --git a/src/G2DataGUI.Common/Data/Models/Models.cs b/src/G2DataGUI.Common/Data/Models/Models.cs
new file mode 100644
index 0000000..a16beab
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/Models.cs
@@ -0,0 +1,7 @@
+using G2DataGUI.Common.Data.Common;
+
+namespace G2DataGUI.Common.Data.Models;
+
+public class Models : BaseContainer
+{
+}
diff --git a/src/G2DataGUI.Common/Data/Models/NJCM.cs b/src/G2DataGUI.Common/Data/Models/NJCM.cs
new file mode 100644
index 0000000..6312169
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/NJCM.cs
@@ -0,0 +1,38 @@
+using System.IO;
+using System.Linq;
+using G2DataGUI.IO.Streams;
+
+namespace G2DataGUI.Common.Data.Models;
+
+public class NJCM
+{
+ public uint ByteLength { get; private set; }
+ public NJSBone BaseBone { get; private set; } = null;
+
+ ///
+ /// Represents the ASCII string "NJCM"
+ ///
+ public static byte[] Identifier => new byte[] { 0x4E, 0x4A, 0x43, 0x4D };
+
+ ///
+ /// Offsets do not account for Identifier or ByteLength
+ ///
+ public static long DataOffset => 0x08;
+
+ public static NJCM ReadNJCM(Stream reader, long instanceOffset)
+ {
+ var identifier = reader.ReadRawByteArray((uint)Identifier.Length);
+ if (!Identifier.SequenceEqual(identifier))
+ {
+ return null;
+ }
+
+ NJCM njcm = new()
+ {
+ ByteLength = reader.ReadRawUInt(),
+ BaseBone = NJSBone.ReadNJSObject(reader, instanceOffset + DataOffset),
+ };
+
+ return njcm;
+ }
+}
diff --git a/src/G2DataGUI.Common/Data/Models/NJSBone.cs b/src/G2DataGUI.Common/Data/Models/NJSBone.cs
new file mode 100644
index 0000000..88b3cde
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/NJSBone.cs
@@ -0,0 +1,57 @@
+using System.IO;
+using G2DataGUI.Common.Data.Common;
+using G2DataGUI.IO.Streams;
+
+namespace G2DataGUI.Common.Data.Models;
+
+public class NJSBone
+{
+ public uint Flags { get; set; }
+ public NJSMesh Model { get; set; } = null;
+ public Vector3 Position { get; set; }
+ public Vector3 Angle { get; set; }
+ public Vector3 Scale { get; set; }
+ public NJSBone Child { get; set; } = null;
+ public NJSBone Sibling { get; set; } = null;
+
+ public static NJSBone ReadNJSObject(Stream reader, long instanceOffset)
+ {
+ NJSBone obj = new()
+ {
+ Flags = reader.ReadRawUInt(),
+ };
+
+ var modelOffset = reader.ReadRawUInt();
+ if (modelOffset > 0)
+ {
+ long position = reader.Position;
+ reader.Seek(instanceOffset + modelOffset, SeekOrigin.Begin);
+ obj.Model = NJSMesh.ReadNJSModel(reader, instanceOffset);
+ reader.Seek(position, SeekOrigin.Begin);
+ }
+
+ obj.Position = Vector3.ReadVector3(reader);
+ obj.Angle = Vector3.ReadVector3(reader);
+ obj.Scale = Vector3.ReadVector3(reader);
+
+ var childOffset = reader.ReadRawUInt();
+ if (childOffset > 0)
+ {
+ long position = reader.Position;
+ reader.Seek(instanceOffset + childOffset, SeekOrigin.Begin);
+ obj.Child = ReadNJSObject(reader, instanceOffset);
+ reader.Seek(position, SeekOrigin.Begin);
+ }
+
+ var siblingOffset = reader.ReadRawUInt();
+ if (siblingOffset > 0)
+ {
+ long position = reader.Position;
+ reader.Seek(instanceOffset + siblingOffset, SeekOrigin.Begin);
+ obj.Sibling = ReadNJSObject(reader, instanceOffset);
+ reader.Seek(position, SeekOrigin.Begin);
+ }
+
+ return obj;
+ }
+}
diff --git a/src/G2DataGUI.Common/Data/Models/NJSMesh.cs b/src/G2DataGUI.Common/Data/Models/NJSMesh.cs
new file mode 100644
index 0000000..a504d85
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/NJSMesh.cs
@@ -0,0 +1,32 @@
+using System.IO;
+using G2DataGUI.Common.Data.Common;
+using G2DataGUI.IO.Streams;
+
+namespace G2DataGUI.Common.Data.Models;
+
+public class NJSMesh
+{
+ public NJSVertexList VertexList { get; set; } = null;
+ // indices
+ public Vector3 Center { get; set; }
+ public float Radius { get; set; }
+
+ public static NJSMesh ReadNJSModel(Stream reader, long instanceOffset)
+ {
+ NJSMesh model = new();
+
+ var vertexOffset = reader.ReadRawUInt();
+ if (vertexOffset > 0)
+ {
+ var position = reader.Position;
+ reader.Seek(instanceOffset + vertexOffset, SeekOrigin.Begin);
+ model.VertexList = NJSVertexList.ReadNJSVertexList(reader);
+ reader.Seek(position, SeekOrigin.Begin);
+ }
+
+ model.Center = Vector3.ReadVector3(reader);
+ model.Radius = reader.ReadRawFloat();
+
+ return model;
+ }
+}
diff --git a/src/G2DataGUI.Common/Data/Models/NJSVertexList.cs b/src/G2DataGUI.Common/Data/Models/NJSVertexList.cs
new file mode 100644
index 0000000..b573772
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/NJSVertexList.cs
@@ -0,0 +1,52 @@
+using System.Collections.Generic;
+using System.IO;
+using G2DataGUI.Common.Data.Common;
+using G2DataGUI.IO.Streams;
+
+namespace G2DataGUI.Common.Data.Models;
+
+public class NJSVertexList
+{
+ ///
+ /// Always 0x2900?
+ ///
+ public short Format { get; set; }
+
+ ///
+ /// No idea
+ ///
+ public short Unknown1 { get; set; }
+
+ ///
+ /// Always 0x0000?
+ ///
+ public short Flags { get; set; }
+
+ ///
+ /// Number of Vertices
+ ///
+ public short Count { get; set; }
+
+ ///
+ /// Should end with a 0xFF000000?
+ ///
+ public List VertexList { get; set; } = new List();
+
+ public static NJSVertexList ReadNJSVertexList(Stream reader)
+ {
+ NJSVertexList list = new()
+ {
+ Format = reader.ReadRawShort(),
+ Unknown1 = reader.ReadRawShort(),
+ Flags = reader.ReadRawShort(),
+ Count = reader.ReadRawShort(),
+ };
+
+ for (int index = 0; index < list.Count; index++)
+ {
+ list.VertexList.Add(Vector3.ReadVector3(reader));
+ }
+
+ return list;
+ }
+}
diff --git a/src/G2DataGUI.Common/Data/Models/NJTL.cs b/src/G2DataGUI.Common/Data/Models/NJTL.cs
new file mode 100644
index 0000000..834b4e6
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/NJTL.cs
@@ -0,0 +1,6 @@
+namespace G2DataGUI.Common.Data.Models;
+
+public class NJTL
+{
+
+}
diff --git a/src/G2DataGUI.Common/Data/Models/NMDM.cs b/src/G2DataGUI.Common/Data/Models/NMDM.cs
new file mode 100644
index 0000000..e1225cf
--- /dev/null
+++ b/src/G2DataGUI.Common/Data/Models/NMDM.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace G2DataGUI.Common.Data.Models;
+internal class NMDM
+{
+}