public override void Load(ExtendedBinaryReader reader, bool keepOpen = false) { // Height of the character in pixels CharacterHeight = reader.ReadInt32(); // The amount of characters defined int characterCount = reader.ReadInt32(); // Unknown WidthScale = reader.ReadSingle(); HeightScale = reader.ReadSingle(); for (int i = 0; i < characterCount; ++i) { var fontEntry = new FontEntry { Character = ReadReversedUTF8Char(reader), // The read UTF8 character XScale = reader.ReadSingle(), // X position on the texture (Multiply by the textures width to get pixels) YScale = reader.ReadSingle(), // Y position on the texture (Multiply by the textures height to get pixels) }; if (!MonospaceOnly) { fontEntry.Kerning = reader.ReadInt32(); // -X offset for positioning when rendering fontEntry.Width = reader.ReadInt32(); // The width of the character in pixels } else { fontEntry.Width = CharacterHeight; // Force square character } Characters.Add(fontEntry); } }
private static IDictionary <int, SizeF[]> ReadBoxSizes(string path) { var result = new Dictionary <int, SizeF[]>(); var file = System.IO.Path.Combine(path, "resources_00001.-13"); using (var fs = new FileStream(file, FileMode.Open)) using (var input = new ExtendedBinaryReader(fs)) { input.BaseStream.Seek(0x150, SeekOrigin.Begin); var heightCount = input.ReadInt32(); for (var i = 0; i < heightCount; i++) { var nameLength = input.ReadInt32(); var name = input.ReadString(); var msgEnum = input.ReadInt32(); var langCount = input.ReadInt32(); var sizes = new SizeF[langCount]; for (var j = 0; j < langCount; j++) { var sz = new SizeF(input.ReadSingle(), input.ReadSingle()); sizes[j] = sz; } result.Add(msgEnum, sizes); } } return(result); }
public override void Read(ExtendedBinaryReader reader, Action <Vector2> synchronizationCallback) { float x = reader.ReadSingle(); float y = reader.ReadSingle(); synchronizationCallback(new Vector2(x, y)); }
public override void Deserialize(ExtendedBinaryReader reader, Action <Vector2> valueFixup) { float x = reader.ReadSingle(); float y = reader.ReadSingle(); valueFixup(new Vector2(x, y)); }
public void Load(ExtendedBinaryReader reader) { SourceX = reader.ReadSingle(); SourceY = reader.ReadSingle(); DestinX = reader.ReadSingle(); DestinY = reader.ReadSingle(); reader.JumpAhead(0x30); // Unknown }
private static object ReadValueType(Type valueType, ExtendedBinaryReader br, bool noAlign = false) { if (!noAlign) { br.AlignStream(); } if (valueType == typeof(string)) { return(br.ReadAlignedString()); } else if (valueType == typeof(Int32)) { return(br.ReadInt32()); } else if (valueType == typeof(UInt32)) { return(br.ReadUInt32()); } else if (valueType == typeof(Int64)) { return(br.ReadInt64()); } else if (valueType == typeof(UInt64)) { return(br.ReadUInt64()); } else if (valueType == typeof(Int16)) { return(br.ReadInt16()); } else if (valueType == typeof(UInt16)) { return(br.ReadUInt16()); } else if (valueType == typeof(Byte)) { return(br.ReadByte()); } else if (valueType == typeof(SByte)) { return(br.ReadSByte()); } else if (valueType == typeof(Boolean)) { return(br.ReadBoolean()); } else if (valueType == typeof(Double)) { return(br.ReadDouble()); } else if (valueType == typeof(Single)) { return(br.ReadSingle()); } else { throw new ArgumentException($"{valueType} is not a value type"); } }
public static void LoadLight(string filePath) { using (var fileStream = File.OpenRead(filePath)) { var reader = new ExtendedBinaryReader(fileStream, true); uint fileSize = reader.ReadUInt32(); uint rootNodeType = reader.ReadUInt32(); uint finalTableOffset = reader.ReadUInt32(); uint rootNodeOffset = reader.ReadUInt32(); uint finalTableOffsetAbs = reader.ReadUInt32(); uint padding = reader.ReadUInt32(); lightType = (LightType)reader.ReadUInt32(); float XPos = reader.ReadSingle(); float YPos = reader.ReadSingle(); float ZPos = reader.ReadSingle(); float ColorR = reader.ReadSingle(); float ColorG = reader.ReadSingle(); float ColorB = reader.ReadSingle(); // Generate XML var rootElement = new XElement("SonicLightXml"); rootElement.Add(new XElement("LightType", lightType)); var lightPosition = new XElement("Position"); lightPosition.Add(new XElement("X", XPos)); lightPosition.Add(new XElement("Y", YPos)); lightPosition.Add(new XElement("Z", ZPos)); rootElement.Add(lightPosition); var lightColor = new XElement("Color"); lightColor.Add(new XElement("R", ColorR)); lightColor.Add(new XElement("G", ColorG)); lightColor.Add(new XElement("B", ColorB)); rootElement.Add(lightColor); // Omni-Specific Values if (lightType == LightType.Omni) { uint Unknown1 = reader.ReadUInt32(); uint Unknown2 = reader.ReadUInt32(); uint Unknown3 = reader.ReadUInt32(); float OmniInnerRange = reader.ReadSingle(); float OmniOuterRange = reader.ReadSingle(); var OmniLightRange = new XElement("OmniLightRange"); OmniLightRange.Add(new XElement("OmniLightInnerRange", OmniInnerRange)); OmniLightRange.Add(new XElement("OmniLightOuterRange", OmniOuterRange)); rootElement.Add(OmniLightRange); } // Save the Generated XML File var xml = new XDocument(rootElement); xml.Save($"{filePath}.xml"); } }
private void Load_Xex(string filename) { Xex_Name = Path.GetFileName(filename); Xex_File = File.ReadAllBytes(filename); RenderingRes_X_TextBox.Enabled = true; RenderingRes_Y_TextBox.Enabled = true; GammaColor_R_TextBox.Enabled = true; GammaColor_G_TextBox.Enabled = true; GammaColor_B_TextBox.Enabled = true; SaveXex.Enabled = true; RestoreOriginalResBtn.Enabled = true; RestoreOriginalGammaBtn.Enabled = true; DisableGammaCorrectionBtn.Enabled = true; using (MemoryStream file = new MemoryStream(Xex_File)) using (ExtendedBinaryReader read = new ExtendedBinaryReader(file, true)) { // Get Rendering Res -- In Order Of Xex File file.Seek(0xBA5026, SeekOrigin.Begin); RenderingRes_Y = read.ReadInt16(); file.Seek(0xBA502A, SeekOrigin.Begin); RenderingRes_X = read.ReadInt16(); //Get Gamma Color -- In Order Of Xex File file.Seek(0x1277450, SeekOrigin.Begin); GammaColor_R = read.ReadSingle(); file.Seek(0x1277454, SeekOrigin.Begin); GammaColor_G = read.ReadSingle(); file.Seek(0x1277458, SeekOrigin.Begin); GammaColor_B = read.ReadSingle(); } RenderingRes_X_TextBox.Text = RenderingRes_X.ToString(); RenderingRes_Y_TextBox.Text = RenderingRes_Y.ToString(); GammaColor_R_TextBox.Text = GammaColor_R.ToString(); GammaColor_G_TextBox.Text = GammaColor_G.ToString(); GammaColor_B_TextBox.Text = GammaColor_B.ToString(); }
protected virtual void LoadChanges(IList <Subtitle> subtitles) { if (HasChanges) { using (var fs = new FileStream(ChangesFile, FileMode.Open)) using (var input = new ExtendedBinaryReader(fs, System.Text.Encoding.Unicode)) { var version = input.ReadInt32(); if (version != ChangesFileVersion) { //File.Delete(ChangesFile); return; } var subtitleCount = input.ReadInt32(); for (var i = 0; i < subtitleCount; i++) { var offset = input.ReadInt64(); var text = input.ReadString(); var width = input.ReadSingle(); var height = input.ReadSingle(); var subtitle = subtitles.FirstOrDefault(x => x.Offset == offset); if (subtitle != null) { subtitle.PropertyChanged -= SubtitlePropertyChanged; subtitle.Translation = text; subtitle.Width = width; subtitle.Height = height; subtitle.Loaded = subtitle.Translation; subtitle.LoadedWidth = subtitle.Width; subtitle.LoadedHeight = subtitle.Height; subtitle.PropertyChanged += SubtitlePropertyChanged; } } } } }
private void LoadFontTableChanges(CharacterInfo[] data) { if (HasChanges) { using (var fs = new FileStream(ChangesFile, FileMode.Open)) using (var input = new ExtendedBinaryReader(fs, Encoding.Unicode)) { var version = input.ReadInt32(); if (version != ChangesFileVersion) { //System.IO.File.Delete(ChangesFile); return; } for (var i = 0; i < 256; i++) { data[i][0] = input.ReadSingle(); data[i][1] = input.ReadSingle(); data[i][2] = input.ReadSingle(); data[i][3] = input.ReadSingle(); data[i][4] = input.ReadSingle(); data[i][5] = input.ReadSingle(); } } } }
public void Load(ExtendedBinaryReader reader) { LayerName = reader.ReadSignature(0x20); uint unknown20 = reader.ReadUInt32(); TextureID = reader.ReadInt32(); uint Offset = reader.ReadUInt32(); uint unknown2C = reader.ReadUInt32(); // uint oldpos = (uint)reader.GetPosition(); reader.JumpTo(Offset); reader.JumpAhead(0x164); LayerOffX = reader.ReadSingle(); LayerOffY = reader.ReadSingle(); reader.JumpAhead(4); LayerWidth = reader.ReadSingle(); LayerHeight = reader.ReadSingle(); reader.JumpAhead(0x88); // Unknown /* * Top Left * Top Right * Bottom Left * Bottom Right */ for (int i = 0; i < 4; ++i) { Verts.Add(new MAVert(reader)); } reader.JumpTo(oldpos); reader.JumpAhead(0x84); // Unknown }
public void LoadLight(string filePath) { using (var fileStream = File.OpenRead(filePath)) { var reader = new ExtendedBinaryReader(fileStream, true); uint fileSize = reader.ReadUInt32(); uint rootNodeType = reader.ReadUInt32(); uint finalTableOffset = reader.ReadUInt32(); uint rootNodeOffset = reader.ReadUInt32(); uint finalTableOffsetAbs = reader.ReadUInt32(); uint padding = reader.ReadUInt32(); uint value_LightType = reader.ReadUInt32(); float XPos = reader.ReadSingle(); float YPos = reader.ReadSingle(); float ZPos = reader.ReadSingle(); float ColorR = reader.ReadSingle(); float ColorG = reader.ReadSingle(); float ColorB = reader.ReadSingle(); // Read Omni-Specific Values bool isOmniLight = (value_LightType == 1); if (isOmniLight) { uint Unknown1 = reader.ReadUInt32(); uint Unknown2 = reader.ReadUInt32(); uint Unknown3 = reader.ReadUInt32(); float OmniInnerRange = reader.ReadSingle(); float OmniOuterRange = reader.ReadSingle(); TextBoxOmniLightInnerRange.Text = OmniInnerRange.ToString(); TextBoxOmniLightOuterRange.Text = OmniOuterRange.ToString(); } // Update UI Elements TextBoxPosX.Text = XPos.ToString(); TextBoxPosY.Text = YPos.ToString(); TextBoxPosZ.Text = ZPos.ToString(); TextBoxColorR.Text = ColorR.ToString(); TextBoxColorG.Text = ColorG.ToString(); TextBoxColorB.Text = ColorB.ToString(); LightType.Text = string.Format("Light Type: {0}", (isOmniLight) ? "Omni" : "Directional"); RefreshUI(true, isOmniLight); } }
public static void LoadLight(string filePath) { using (var fileStream = File.OpenRead(filePath)) { var reader = new ExtendedBinaryReader(fileStream, true); uint fileSize = reader.ReadUInt32(); uint rootNodeType = reader.ReadUInt32(); uint finalTableOffset = reader.ReadUInt32(); uint rootNodeOffset = reader.ReadUInt32(); uint finalTableOffsetAbs = reader.ReadUInt32(); uint padding = reader.ReadUInt32(); uint value_LightType = reader.ReadUInt32(); float XPos = reader.ReadSingle(); float YPos = reader.ReadSingle(); float ZPos = reader.ReadSingle(); float ColorR = reader.ReadSingle(); float ColorG = reader.ReadSingle(); float ColorB = reader.ReadSingle(); // Print out Light information Console.WriteLine($"Light type: {value_LightType}"); Console.WriteLine($"PosX: {XPos}"); Console.WriteLine($"PosY: {YPos}"); Console.WriteLine($"PosZ: {ZPos}"); Console.WriteLine($"ColorR: {ColorR}"); Console.WriteLine($"ColorG: {ColorG}"); Console.WriteLine($"ColorB: {ColorB}"); // Read Omni-Specific Values and print them, if present. bool isOmniLight = (value_LightType == 1); if (isOmniLight) { uint Unknown1 = reader.ReadUInt32(); uint Unknown2 = reader.ReadUInt32(); uint Unknown3 = reader.ReadUInt32(); float OmniInnerRange = reader.ReadSingle(); float OmniOuterRange = reader.ReadSingle(); Console.WriteLine($"OmniLightInnerRange: {OmniInnerRange}"); Console.WriteLine($"OmniLightOuterRange: {OmniOuterRange}"); } } }
public static object ReadByType(ExtendedBinaryReader reader, ArgumentType type) { switch (type) { case AT_Bool: return(reader.ReadBoolean()); case AT_Byte: return(reader.ReadByte()); case AT_Int16: return(reader.ReadInt16()); case AT_Int32: return(reader.ReadInt32()); case AT_Float: return(reader.ReadSingle()); case AT_String: return(reader.ReadStringElsewhere()); case AT_StringPtr: return(reader.ReadNullTerminatedStringPointer()); case AT_CodePointer: return(reader.ReadInt32()); case AT_DataReference: return(reader.ReadUInt32()); case AT_DataBlock: long position = reader.ReadUInt32(); long length = reader.ReadUInt32(); if (reader.Offset > position) { reader.Offset = (uint)position; } return(new StreamBlock(position, length)); default: return(null); } }
protected virtual CharacterInfo[] GetFontTable() { var result = new CharacterInfo[256]; using (var fs = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fs, FileEncoding, Endianness.LittleEndian)) { input.Seek(FontTableOffset, SeekOrigin.Begin); for (var i = 0; i < 256; i++) { var tl = input.ReadSingle(); var tr = input.ReadSingle(); var ml = input.ReadSingle(); var mr = input.ReadSingle(); var bl = input.ReadSingle(); var br = input.ReadSingle(); result[i] = new CharacterInfo((byte)i) { OriginalData = { [0] = tl, [1] = tr, [2] = ml, [3] = mr, [4] = bl, [5] = br }, Data = { [0] = tl, [1] = tr, [2] = ml, [3] = mr, [4] = bl, [5] = br } }; } } LoadFontTableChanges(result); for (var i = 0; i < 256; i++) { result[i].SetLoadedData(); result[i].PropertyChanged += SubtitlePropertyChanged; } return(result); }
public static void LoadLight(string filePath) { using (var fileStream = File.OpenRead(filePath)) { var reader = new ExtendedBinaryReader(fileStream, true); uint fileSize = reader.ReadUInt32(); uint rootNodeType = reader.ReadUInt32(); uint finalTableOffset = reader.ReadUInt32(); uint rootNodeOffset = reader.ReadUInt32(); uint finalTableOffsetAbs = reader.ReadUInt32(); uint padding = reader.ReadUInt32(); lightType = (LightType)reader.ReadUInt32(); XPos = reader.ReadSingle(); YPos = reader.ReadSingle(); ZPos = reader.ReadSingle(); ColorR = reader.ReadSingle(); ColorG = reader.ReadSingle(); ColorB = reader.ReadSingle(); // Print out Light information Console.WriteLine($"Light type: {lightType}"); Console.WriteLine(""); Console.WriteLine($"ColorR is {ColorR}," + $" It should Be {ColorR/10000} after re-saving"); Console.WriteLine($"ColorG is {ColorG}," + $" It should Be {ColorG/10000} after re-saving"); Console.WriteLine($"ColorB is {ColorB}," + $" It should Be {ColorB/10000} after re-saving"); Console.WriteLine(""); // Read Omni-Specific Values if present. if (lightType == LightType.Omni) { Unknown1 = reader.ReadUInt32(); Unknown2 = reader.ReadUInt32(); Unknown3 = reader.ReadUInt32(); OmniInnerRange = reader.ReadSingle(); OmniOuterRange = reader.ReadSingle(); } } }
public NXOB ReadNodes(ExtendedBinaryReader reader, long pos) { /* * Sonic 4 Decompilation Ref * public NNS_NODE( AppMain.NNS_NODE node ) * { * this.fType = node.fType; * this.iMatrix = node.iMatrix; * this.iParent = node.iParent; * this.iChild = node.iChild; * this.iSibling = node.iSibling; * this.Translation.Assign( node.Translation ); * this.Rotation = node.Rotation; * this.Scaling.Assign( node.Scaling ); * this.InvInitMtx.Assign( node.InvInitMtx ); * this.Center.Assign( node.Center ); * this.Radius = node.Radius; * this.User = node.User; * this.SIIKBoneLength = node.SIIKBoneLength; * this.BoundingBoxY = node.BoundingBoxY; * this.BoundingBoxZ = node.BoundingBoxZ; * } */ ObjectList = new NXOB() { ObjectList = new string(reader.ReadChars(4)), NodeLength = reader.ReadUInt32() }; pos = reader.BaseStream.Position; //Save Position reader.JumpTo(reader.ReadUInt32(), false); reader.JumpAhead(0x10); //Variable Names Copy & Pasted from MaxScript var TexElmTotal = reader.ReadUInt32(); var TexElmOffset = reader.ReadUInt32(); var VertGroupTotal = reader.ReadUInt32(); var VertGroupOffset = reader.ReadUInt32(); var PolyElmTotal = reader.ReadUInt32(); var PolyElmOffset = reader.ReadUInt32(); //Nodes var NodeTotal = reader.ReadUInt32(); var UnknownCount1 = reader.ReadUInt32(); //Count of SOMETHING? var NodeOffset = reader.ReadUInt32(); var UnknownCount2 = reader.ReadUInt32(); //MaxScript calls this NodeTotal, but I'm sure what they call BoneTotal is actually NodeTotal? Seems to be a Count of something var LinkTotal = reader.ReadUInt32(); var LinkOffset = reader.ReadUInt32(); var UnknownCount3 = reader.ReadUInt32(); //Count of SOMETHING? //NNS_NODE reader.JumpTo(NodeOffset, false); for (int i = 0; i < NodeTotal; i++) { Node node = new Node(); node.NODE_TYPE = reader.ReadUInt32(); node.NODE_MATRIX = reader.ReadUInt16(); node.NODE_PARENT = reader.ReadUInt16(); node.NODE_CHILD = reader.ReadUInt16(); node.NODE_SIBLING = reader.ReadUInt16(); for (int n = 0; n < 3; n++) { node.NODE_TRN.Add(reader.ReadSingle()); } for (int n = 0; n < 3; n++) { node.NODE_ROT.Add(reader.ReadSingle()); } for (int n = 0; n < 3; n++) { node.NODE_SCL.Add(reader.ReadSingle()); } for (int n = 0; n < 16; n++) { node.NODE_INVINIT_MTX.Add(reader.ReadSingle()); } for (int n = 0; n < 3; n++) { node.NODE_CENTER.Add(reader.ReadSingle()); } node.NODE_RADIUS = reader.ReadSingle(); node.NODE_USER = reader.ReadUInt32(); node.NODE_RSV0 = reader.ReadUInt32(); node.NODE_RSV1 = reader.ReadUInt32(); node.NODE_RSV2 = reader.ReadUInt32(); ObjectList.Nodes.Add(node); } reader.JumpTo(TexElmOffset, false); var Unknown1 = reader.ReadUInt32(); //Assume this is a count??? reader.JumpTo(reader.ReadUInt32(), false); return(ObjectList); }
public NinjaObject ReadNinjaObject(ExtendedBinaryReader reader, long pos) { NinjaObject = new NinjaObject() { NodeName = new string(reader.ReadChars(4)) }; uint NodeLength = reader.ReadUInt32(); pos = reader.BaseStream.Position; //Save Position uint NodeOffset = reader.ReadUInt32(); reader.JumpTo(NodeOffset, false); NinjaObject.ObjectCenter = reader.ReadVector3(); NinjaObject.ObjectRadius = reader.ReadSingle(); uint ObjectMaterialCount = reader.ReadUInt32(); uint ObjectMaterialOffset = reader.ReadUInt32(); uint ObjectVTXCount = reader.ReadUInt32(); uint ObjectVTXOffset = reader.ReadUInt32(); uint ObjectPrimitiveCount = reader.ReadUInt32(); uint ObjectPrimitiveOffset = reader.ReadUInt32(); uint ObjectNodeCount = reader.ReadUInt32(); NinjaObject.ObjectMaxNodeDepth = reader.ReadUInt32(); uint ObjectNodeOffset = reader.ReadUInt32(); NinjaObject.ObjectMTXPAL = reader.ReadUInt32(); uint ObjectSubObjectCount = reader.ReadUInt32(); uint ObjectSubObjectOffset = reader.ReadUInt32(); NinjaObject.ObjectTextureCount = reader.ReadUInt32(); //Materials reader.JumpTo(ObjectMaterialOffset, false); for (int i = 0; i < ObjectMaterialCount; i++) { //TO-DO: Figure out how all this fits together NinjaObjectMaterial ObjectMaterial = new NinjaObjectMaterial() { MaterialType = reader.ReadUInt32() }; uint MaterialOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(MaterialOffset, false); ObjectMaterial.MaterialFlags = reader.ReadUInt32(); ObjectMaterial.User = reader.ReadUInt32(); uint MaterialColourOffset = reader.ReadUInt32(); uint MaterialLogicOffset = reader.ReadUInt32(); uint MaterialTexDescOffset = reader.ReadUInt32(); reader.JumpTo(MaterialColourOffset, false); ObjectMaterial.MaterialDiffuse = reader.ReadVector4(); ObjectMaterial.MaterialAmbient = reader.ReadVector4(); ObjectMaterial.MaterialSpecular = reader.ReadVector4(); ObjectMaterial.MaterialEmissive = reader.ReadVector4(); ObjectMaterial.MaterialPower = reader.ReadSingle(); reader.JumpTo(MaterialLogicOffset, false); ObjectMaterial.MaterialBlendenable = reader.ReadUInt32(); ObjectMaterial.MaterialSRCBlend = reader.ReadUInt32(); ObjectMaterial.MaterialDSTBlend = reader.ReadUInt32(); ObjectMaterial.MaterialBlendFactor = reader.ReadUInt32(); ObjectMaterial.MaterialBlendOP = reader.ReadUInt32(); ObjectMaterial.MaterialLogicOP = reader.ReadUInt32(); ObjectMaterial.MaterialAlphaEnable = reader.ReadUInt32(); ObjectMaterial.MaterialAlphaFunction = reader.ReadUInt32(); ObjectMaterial.MaterialAlphaRef = reader.ReadUInt32(); ObjectMaterial.MaterialZCompenable = reader.ReadUInt32(); ObjectMaterial.MaterialZFunction = reader.ReadUInt32(); ObjectMaterial.MaterialZUpdateEnable = reader.ReadUInt32(); reader.JumpTo(MaterialTexDescOffset, false); ObjectMaterial.TextureTexMapType = reader.ReadUInt32(); ObjectMaterial.TextureID = reader.ReadUInt32(); ObjectMaterial.TextureOffset = reader.ReadVector2(); ObjectMaterial.TextureBlend = reader.ReadSingle(); ObjectMaterial.TextureInfoPTR = reader.ReadUInt32(); ObjectMaterial.TextureMinFilter = reader.ReadUInt32(); ObjectMaterial.TextureMagFilter = reader.ReadUInt32(); ObjectMaterial.TextureMipMapBias = reader.ReadSingle(); ObjectMaterial.TextureMaxMipLevel = reader.ReadUInt32(); reader.JumpTo(currentPos, true); NinjaObject.ObjectMaterialList.Add(ObjectMaterial); } //Vertexes reader.JumpTo(ObjectVTXOffset, false); for (int i = 0; i < ObjectVTXCount; i++) { NinjaObjectVertex ObjectVertex = new NinjaObjectVertex() { Type = reader.ReadUInt32() }; uint VTXOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(VTXOffset, false); ObjectVertex.VTXFormat = reader.ReadUInt32(); ObjectVertex.VTXFVF = reader.ReadUInt32(); ObjectVertex.VTXSize = reader.ReadUInt32(); uint VTXNumber = reader.ReadUInt32(); uint VTXListOffset = reader.ReadUInt32(); ObjectVertex.VTXBlendNum = reader.ReadUInt32(); uint VTXMTXOffset = reader.ReadUInt32(); ObjectVertex.VTXHDRCommon = reader.ReadUInt32(); ObjectVertex.VTXHDRData = reader.ReadUInt32(); ObjectVertex.VTXHDRLock = reader.ReadUInt32(); reader.JumpTo(VTXListOffset, false); for (int v = 0; v < VTXNumber; v++) { NinjaObjectVertexList Vertex = new NinjaObjectVertexList(); switch (ObjectVertex.VTXSize) { //Any ones other than 52 & 76 are probably wrong here, as they're not in the XTO and are instead based on the MaxScript //This is such a mess case 20: Vertex.Position = reader.ReadVector3(); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 24: Vertex.Position = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 28: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); ObjectVertex.Vertexes.Add(Vertex); break; case 32: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 36: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 44: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); Vertex.UnknownV2 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 48: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 52: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.MTXIDX = reader.ReadBytes(4); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 60: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.Tan = reader.ReadVector3(); Vertex.BNormal = reader.ReadVector3(); ObjectVertex.Vertexes.Add(Vertex); break; case 72: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.MTXIDX = reader.ReadBytes(4); Vertex.Normals = reader.ReadVector3(); Vertex.ST0 = reader.ReadVector2(); Vertex.Tan = reader.ReadVector3(); Vertex.BNormal = reader.ReadVector3(); ObjectVertex.Vertexes.Add(Vertex); break; case 76: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.MTXIDX = reader.ReadBytes(4); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); Vertex.Tan = reader.ReadVector3(); Vertex.BNormal = reader.ReadVector3(); ObjectVertex.Vertexes.Add(Vertex); break; default: Console.WriteLine($"Vertex Size of {ObjectVertex.VTXSize} not handled!"); continue; } } if (VTXMTXOffset != 0) { reader.JumpTo(VTXMTXOffset, false); ObjectVertex.VTXMTX = reader.ReadInt32(); } reader.JumpTo(currentPos, true); NinjaObject.ObjectVertexList.Add(ObjectVertex); } reader.JumpTo(ObjectPrimitiveOffset, false); for (int i = 0; i < ObjectPrimitiveCount; i++) { NinjaObjectPrimitive ObjectPrimitive = new NinjaObjectPrimitive() { Type = reader.ReadUInt32() }; uint PrimitiveListOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(PrimitiveListOffset, false); ObjectPrimitive.Format = reader.ReadUInt32(); ObjectPrimitive.Index = reader.ReadUInt32(); ObjectPrimitive.Strip = reader.ReadUInt32(); uint LengthOffset = reader.ReadUInt32(); uint IndexOffset = reader.ReadUInt32(); ObjectPrimitive.IndexBuf = reader.ReadUInt32(); reader.JumpTo(LengthOffset, false); ObjectPrimitive.IndexLength = reader.ReadUInt16(); //May be the same as Index all the time??? reader.JumpTo(IndexOffset, false); for (int v = 0; v < ObjectPrimitive.Index; v++) { ObjectPrimitive.VertexIndexList.Add(reader.ReadUInt16()); } reader.JumpTo(currentPos, true); NinjaObject.ObjectPrimitiveList.Add(ObjectPrimitive); } reader.JumpTo(ObjectNodeOffset, false); for (int i = 0; i < ObjectNodeCount; i++) { NinjaObjectNodeList Node = new NinjaObjectNodeList() { Type = reader.ReadUInt32(), Matrix = reader.ReadUInt16(), Parent = reader.ReadUInt16(), Child = reader.ReadUInt16(), Sibling = reader.ReadUInt16(), Transform = reader.ReadVector3(), Rotation = reader.ReadVector3(), Scale = reader.ReadVector3() }; for (int v = 0; v < 16; v++) { Node.Invinit.Add(reader.ReadSingle()); } Node.Center = reader.ReadVector3(); Node.User = reader.ReadUInt32(); Node.RSV0 = reader.ReadUInt32(); Node.RSV1 = reader.ReadUInt32(); Node.RSV2 = reader.ReadUInt32(); reader.JumpAhead(0x4); NinjaObject.ObjectNodeList.Add(Node); } reader.JumpTo(ObjectSubObjectOffset, false); for (int i = 0; i < ObjectSubObjectCount; i++) { uint Type = reader.ReadUInt32(); uint NMSST = reader.ReadUInt32(); uint MSSTOffset = reader.ReadUInt32(); uint Textures = reader.ReadUInt32(); uint TexturesOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(MSSTOffset, false); for (int v = 0; v < NMSST; v++) { NinjaObjectSubObject SubObject = new NinjaObjectSubObject() { Center = reader.ReadVector3(), Radius = reader.ReadSingle(), Node = reader.ReadUInt32(), Matrix = reader.ReadUInt32(), Material = reader.ReadUInt32(), VertexList = reader.ReadUInt32(), PrimList = reader.ReadUInt32(), ShaderList = reader.ReadUInt32() }; NinjaObject.ObjectSubObjectList.Add(SubObject); } reader.JumpTo(currentPos, true); } reader.JumpTo(pos, true); reader.JumpAhead(NodeLength); return(NinjaObject); }
public override object Read(ExtendedBinaryReader reader) => reader.ReadSingle();
private static SetObject ReadObject(ExtendedBinaryReader reader, SetObjectType objTemplate, string objType, SOBJType type, bool rawDataMode = false) // true = full, false = only remaining bytes { // For some reason these separate values are saved as one uint rather than two ushorts. // Because of this, the values are in a different order depending on endianness, and // this is the easiest known way to read them. uint unknownValue = reader.ReadUInt32(); ushort unknown1 = (ushort)((unknownValue >> 16) & 0xFFFF); ushort objID = (ushort)(unknownValue & 0xFFFF); var obj = new SetObject() { ObjectType = objType, ObjectID = objID }; uint unknown2 = reader.ReadUInt32(); uint unknown3 = reader.ReadUInt32(); float unknown4 = reader.ReadSingle(); float rangeIn = reader.ReadSingle(); float rangeOut = reader.ReadSingle(); uint parent = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0; uint transformsOffset = reader.ReadUInt32(); uint transformCount = reader.ReadUInt32(); uint unknown5 = reader.ReadUInt32(); uint unknown6 = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0; uint unknown7 = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0; // Call me crazy, but I have a weird feeling these values aren't JUST padding if (unknown3 != 0 || unknown5 != 0 || unknown6 != 0 || unknown7 != 0) { Console.WriteLine("WARNING: Not padding?! ({0},{1},{2},{3})", unknown3, unknown5, unknown6, unknown7); } // Add custom data to object obj.CustomData.Add("Unknown1", new SetObjectParam(typeof(ushort), unknown1)); obj.CustomData.Add("Unknown2", new SetObjectParam(typeof(uint), unknown2)); obj.CustomData.Add("Unknown3", new SetObjectParam(typeof(uint), unknown3)); obj.CustomData.Add("Unknown4", new SetObjectParam(typeof(float), unknown4)); obj.CustomData.Add("RangeIn", new SetObjectParam(typeof(float), rangeIn)); obj.CustomData.Add("RangeOut", new SetObjectParam(typeof(float), rangeOut)); if (type == SOBJType.LostWorld) { obj.CustomData.Add("Parent", new SetObjectParam(typeof(uint), parent)); } // Skip loading parameters if template doesn't exist if (objTemplate != null) { // Get Raw Byte Length var rawDataLenExtra = objTemplate.GetExtra("RawByteLength"); long paramBegin = reader.BaseStream.Position; int rawLength = 0; if (rawDataLenExtra != null && !string.IsNullOrEmpty(rawDataLenExtra.Value)) { int.TryParse(rawDataLenExtra.Value, out rawLength); } // Read all the data then return to beginning if (rawDataMode == true && rawLength != 0) { obj.CustomData.Add("RawParamData", new SetObjectParam(typeof(byte[]), reader.ReadBytes(rawLength))); reader.JumpTo(paramBegin); } // Parameters foreach (var param in objTemplate.Parameters) { // For compatibility with SonicGlvl templates. if (param.Name == "Unknown1" || param.Name == "Unknown2" || param.Name == "Unknown3" || param.Name == "RangeIn" || param.Name == "RangeOut" || param.Name == "Parent") { continue; } // Read Special Types/Fix Padding if (param.DataType == typeof(uint[])) { // Data Info reader.FixPadding(4); uint arrOffset = reader.ReadUInt32(); uint arrLength = reader.ReadUInt32(); uint arrUnknown = reader.ReadUInt32(); long curPos = reader.BaseStream.Position; // Data var arr = new uint[arrLength]; reader.JumpTo(arrOffset, false); for (uint i = 0; i < arrLength; ++i) { arr[i] = reader.ReadUInt32(); } obj.Parameters.Add(new SetObjectParam(param.DataType, arr)); reader.BaseStream.Position = curPos; continue; } else if (param.DataType == typeof(string)) { // Data Info uint strOffset = reader.ReadUInt32(); uint strUnknown = reader.ReadUInt32(); string str = null; // Data if (strOffset != 0) { long curPos = reader.BaseStream.Position; reader.JumpTo(strOffset, false); str = reader.ReadNullTerminatedString(); reader.BaseStream.Position = curPos; } obj.Parameters.Add(new SetObjectParam(param.DataType, str)); continue; } else if (param.DataType == typeof(float) || param.DataType == typeof(int) || param.DataType == typeof(uint)) { reader.FixPadding(4); } else if (type == SOBJType.LostWorld && param.DataType == typeof(Vector3)) { reader.FixPadding(16); } // Read Data var objParam = new SetObjectParam(param.DataType, reader.ReadByType(param.DataType)); obj.Parameters.Add(objParam); } if (rawDataMode == false) { long knownParamLength = (reader.BaseStream.Position - paramBegin); long remainingBytes = (rawLength - knownParamLength); obj.CustomData.Add("RawParamData", new SetObjectParam(typeof(byte[]), reader.ReadBytes((int)remainingBytes))); } } // Transforms uint childCount = transformCount - 1; obj.Children = new SetObjectTransform[childCount]; reader.JumpTo(transformsOffset, false); obj.Transform = ReadTransform(reader, type == SOBJType.LostWorld); for (uint i = 0; i < childCount; ++i) { obj.Children[i] = ReadTransform(reader, type == SOBJType.LostWorld); } return(obj); }
public override void Deserialize(ExtendedBinaryReader reader, Action <float> valueFixup) { valueFixup(reader.ReadSingle()); }
/// <summary> /// Reads a SEAnim from a stream /// </summary> /// <param name="Stream">The stream to read from</param> /// <returns>A SEAnim if successful, otherwise throws an error and returns null</returns> public static SEModel Read(Stream Stream) { // Create a new model var model = new SEModel(); // Setup a new reader using (ExtendedBinaryReader readFile = new ExtendedBinaryReader(Stream)) { // Magic var Magic = readFile.ReadChars(7); // Version var Version = readFile.ReadInt16(); // Header size var HeaderSize = readFile.ReadInt16(); // Check magic if (!Magic.SequenceEqual(new char[] { 'S', 'E', 'M', 'o', 'd', 'e', 'l' })) { // Bad file throw new Exception("Bad SEModel file, magic was invalid"); } // Data present flags var DataPresentFlags = readFile.ReadByte(); // Bone data present flags var BoneDataPresentFlags = readFile.ReadByte(); // Mesh data present flags var MeshDataPresentFlags = readFile.ReadByte(); // Read counts var BoneCount = readFile.ReadInt32(); var MeshCount = readFile.ReadInt32(); var MatCount = readFile.ReadInt32(); // Skip 3 reserved bytes readFile.BaseStream.Position += 3; // Read bone tag names List <string> BoneNames = new List <string>(); // Loop for (int i = 0; i < BoneCount; i++) { BoneNames.Add(readFile.ReadNullTermString()); } // Loop and read bones for (int i = 0; i < BoneCount; i++) { // Read bone flags (unused) var BoneFlags = readFile.ReadByte(); // Read bone index var ParentIndex = readFile.ReadInt32(); // Check for global matricies Vector3 GlobalPosition = Vector3.Zero; Quaternion GlobalRotation = Quaternion.Identity; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_GLOBAL_MATRIX)) { GlobalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); GlobalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Check for local matricies Vector3 LocalPosition = Vector3.Zero; Quaternion LocalRotation = Quaternion.Identity; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_LOCAL_MATRIX)) { LocalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); LocalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Check for scales Vector3 Scale = Vector3.One; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_SCALES)) { Scale = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Add the bone model.AddBone(BoneNames[i], ParentIndex, GlobalPosition, GlobalRotation, LocalPosition, LocalRotation, Scale); } // Loop and read meshes for (int i = 0; i < MeshCount; i++) { // Make a new submesh var mesh = new SEModelMesh(); // Read mesh flags (unused) var MeshFlags = readFile.ReadByte(); // Read counts var MatIndiciesCount = readFile.ReadByte(); var MaxSkinInfluenceCount = readFile.ReadByte(); var VertexCount = readFile.ReadInt32(); var FaceCount = readFile.ReadInt32(); // Loop and read positions for (int v = 0; v < VertexCount; v++) { mesh.AddVertex(new SEModelVertex() { Position = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()) }); } // Read uvlayers if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_UVSET)) { for (int v = 0; v < VertexCount; v++) { for (int l = 0; l < MatIndiciesCount; l++) { mesh.Verticies[v].UVSets.Add(new Vector2(readFile.ReadSingle(), readFile.ReadSingle())); } } } // Read normals if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_NORMALS)) { // Loop and read vertex normals for (int v = 0; v < VertexCount; v++) { mesh.Verticies[v].VertexNormal = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } } // Read colors if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_COLOR)) { // Loop and read colors for (int v = 0; v < VertexCount; v++) { mesh.Verticies[v].VertexColor = new Color(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte()); } } // Read weights if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_WEIGHTS)) { for (int v = 0; v < VertexCount; v++) { // Read IDs and Values for (int l = 0; l < MaxSkinInfluenceCount; l++) { if (BoneCount <= 0xFF) { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadByte(), BoneWeight = readFile.ReadSingle() }); } else if (BoneCount <= 0xFFFF) { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadUInt16(), BoneWeight = readFile.ReadSingle() }); } else { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadUInt32(), BoneWeight = readFile.ReadSingle() }); } } } } // Loop and read faces for (int f = 0; f < FaceCount; f++) { if (VertexCount <= 0xFF) { mesh.AddFace(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte()); } else if (VertexCount <= 0xFFFF) { mesh.AddFace(readFile.ReadUInt16(), readFile.ReadUInt16(), readFile.ReadUInt16()); } else { mesh.AddFace(readFile.ReadUInt32(), readFile.ReadUInt32(), readFile.ReadUInt32()); } } // Read material reference indicies for (int f = 0; f < MatIndiciesCount; f++) { mesh.AddMaterialIndex(readFile.ReadInt32()); } // Add the mesh model.AddMesh(mesh); } // Loop and read materials for (int m = 0; m < MatCount; m++) { var mat = new SEModelMaterial(); // Read the name mat.Name = readFile.ReadNullTermString(); // Read IsSimpleMaterial var IsSimpleMaterial = readFile.ReadBoolean(); // Read the material if (IsSimpleMaterial) { mat.MaterialData = new SEModelSimpleMaterial() { DiffuseMap = readFile.ReadNullTermString(), NormalMap = readFile.ReadNullTermString(), SpecularMap = readFile.ReadNullTermString() }; } // Add the material model.AddMaterial(mat); } } // Return result return(model); }
public override void Read(ExtendedBinaryReader reader, Action <float> synchronizationCallback) { synchronizationCallback(reader.ReadSingle()); }
// Methods public override void Load(Stream fileStream) { // Header var reader = new ExtendedBinaryReader(fileStream); uint header = reader.ReadUInt32(); uint sig = (header & 0xFFFFFF); byte version = (byte)((header & 0xFF000000) >> 24); if (sig != Signature) { throw new InvalidSignatureException("MDL", Encoding.ASCII.GetString(BitConverter.GetBytes(sig), 0, 3)); } if (version > Version) { throw new NotSupportedException( $"Cannot read version {version} of the format."); } // Meshes Mesh mesh; uint len, i, i2; uint meshCount = reader.ReadUInt32(); byte indicesType; for (i = 0; i < meshCount; ++i) { // Vertex Data mesh = new Mesh(); len = reader.ReadUInt32(); mesh.VertexData = new float[len]; for (i2 = 0; i2 < len; ++i2) { mesh.VertexData[i2] = reader.ReadSingle(); } // Triangle Indices len = reader.ReadUInt32(); indicesType = (byte)((len & 0xC0000000) >> 30); len &= 0x3FFFFFFF; mesh.Triangles = new uint[len]; for (i2 = 0; i2 < len; ++i2) { // 0 = 32-bit, 1 = 16-bit, 2 = 8-bit switch (indicesType) { case 0: default: mesh.Triangles[i2] = reader.ReadUInt32(); continue; case 1: mesh.Triangles[i2] = reader.ReadUInt16(); continue; case 2: mesh.Triangles[i2] = reader.ReadByte(); continue; } } // Material Name mesh.MaterialName = reader.ReadString(); Meshes.Add(mesh); } }