/// <summary> /// Reads a generic Pokémon container from a Stream. /// Those containers are the ones that starts with "GR", "MM", "AD" and so on... /// </summary> /// <param name="data">Stream with container data</param> /// <returns></returns> public static GenericContainer.OContainer load(Stream data) { BinaryReader input = new BinaryReader(data); GenericContainer.OContainer output = new GenericContainer.OContainer(); output.fileIdentifier = IOUtils.readString(input, 0, 2); //Magic ushort sectionCount = input.ReadUInt16(); for (int i = 0; i < sectionCount; i++) { GenericContainer.OContainerEntry entry = new GenericContainer.OContainerEntry(); data.Seek(4 + (i * 4), SeekOrigin.Begin); uint startOffset = input.ReadUInt32(); uint endOffset = input.ReadUInt32(); uint length = endOffset - startOffset; data.Seek(startOffset, SeekOrigin.Begin); byte[] buffer = new byte[length]; input.Read(buffer, 0, (int)length); entry.data = buffer; output.content.Add(entry); } data.Close(); return output; }
/// <summary> /// Reads FPT0 containers from Dragon Quest VII. /// </summary> /// <param name="data">Stream with container data</param> /// <returns></returns> public static GenericContainer.OContainer load(Stream data) { BinaryReader input = new BinaryReader(data); GenericContainer.OContainer output = new GenericContainer.OContainer(); output.fileIdentifier = IOUtils.readString(input, 0, 4); //FPT0 magic input.ReadUInt32(); uint entries = input.ReadUInt32(); uint baseAddress = 0x10 + (entries * 0x20) + 0x80; input.ReadUInt32(); List<sectionEntry> files = new List<sectionEntry>(); for (int i = 0; i < entries; i++) { sectionEntry entry = new sectionEntry(); entry.name = IOUtils.readString(input, (uint)(0x10 + (i * 0x20))); data.Seek(0x20 + (i * 0x20), SeekOrigin.Begin); input.ReadUInt32(); //Memory address? entry.offset = input.ReadUInt32() + baseAddress; entry.length = input.ReadUInt32(); input.ReadUInt32(); //Padding? files.Add(entry); } foreach (sectionEntry file in files) { GenericContainer.OContainerEntry entry = new GenericContainer.OContainerEntry(); data.Seek(file.offset, SeekOrigin.Begin); byte[] buffer = new byte[file.length]; input.Read(buffer, 0, buffer.Length); entry.data = buffer; entry.name = file.name; output.content.Add(entry); } data.Close(); return output; }
/// <summary> /// Reads the Model PACKage from Dragon Quest VII. /// </summary> /// <param name="data">Stream of the data</param> /// <returns></returns> public static GenericContainer.OContainer load(Stream data) { BinaryReader input = new BinaryReader(data); GenericContainer.OContainer output = new GenericContainer.OContainer(); List<sectionEntry> mainSection = getSection(input); //World nodes section data.Seek(mainSection[0].offset, SeekOrigin.Begin); List<node> nodes = new List<node>(); List<sectionEntry> worldNodesSection = getSection(input); foreach (sectionEntry entry in worldNodesSection) { data.Seek(entry.offset, SeekOrigin.Begin); node n = new node(); //Geometry node input.ReadUInt32(); //GNOD magic number input.ReadUInt32(); input.ReadUInt32(); n.parentId = input.ReadInt32(); n.name = IOUtils.readString(input, (uint)data.Position); data.Seek(entry.offset + 0x20, SeekOrigin.Begin); n.transform = new RenderBase.OMatrix(); RenderBase.OVector4 t = new RenderBase.OVector4(input.ReadSingle(), input.ReadSingle(), input.ReadSingle(), input.ReadSingle()); RenderBase.OVector4 r = new RenderBase.OVector4(input.ReadSingle(), input.ReadSingle(), input.ReadSingle(), input.ReadSingle()); RenderBase.OVector4 s = new RenderBase.OVector4(input.ReadSingle(), input.ReadSingle(), input.ReadSingle(), input.ReadSingle()); n.transform *= RenderBase.OMatrix.scale(new RenderBase.OVector3(s.x, s.y, s.z)); n.transform *= RenderBase.OMatrix.rotateX(r.x); n.transform *= RenderBase.OMatrix.rotateY(r.y); n.transform *= RenderBase.OMatrix.rotateZ(r.z); n.transform *= RenderBase.OMatrix.translate(new RenderBase.OVector3(t.x, t.y, t.z)); nodes.Add(n); } RenderBase.OMatrix[] nodesTransform = new RenderBase.OMatrix[nodes.Count]; for (int i = 0; i < nodes.Count; i++) { RenderBase.OMatrix transform = new RenderBase.OMatrix(); transformNode(nodes, i, ref transform); nodesTransform[i] = transform; } //Models section data.Seek(mainSection[1].offset, SeekOrigin.Begin); List<sectionEntry> modelsSection = getSection(input); foreach (sectionEntry entry in modelsSection) { data.Seek(entry.offset, SeekOrigin.Begin); //Field Data section /* * Usually have 3 entries. * 1st entry: Model CGFX * 2nd entry: Unknow CGFX, possibly animations * 3rd entry: Another FieldData section, possibly child object */ List<sectionEntry> fieldDataSection = getSection(input); data.Seek(fieldDataSection[0].offset, SeekOrigin.Begin); uint length = fieldDataSection[0].length; while ((length & 0x7f) != 0) length++; //Align byte[] buffer = new byte[length]; input.Read(buffer, 0, buffer.Length); GenericContainer.OContainerEntry file = new GenericContainer.OContainerEntry(); file.name = CGFX.getName(new MemoryStream(buffer)) + ".bcmdl"; file.data = buffer; output.content.Add(file); } //FILE section data.Seek(mainSection[2].offset, SeekOrigin.Begin); //TODO //Collision section data.Seek(mainSection[3].offset, SeekOrigin.Begin); //TODO //PARM(???) section data.Seek(mainSection[4].offset, SeekOrigin.Begin); //TODO //Textures CGFX data.Seek(mainSection[5].offset, SeekOrigin.Begin); byte[] texBuffer = new byte[mainSection[5].length]; input.Read(texBuffer, 0, texBuffer.Length); GenericContainer.OContainerEntry texFile = new GenericContainer.OContainerEntry(); texFile.name = "textures.bctex"; texFile.data = texBuffer; output.content.Add(texFile); data.Close(); return output; }
public void launch(GenericContainer.OContainer _container) { container = _container; foreach (GenericContainer.OContainerEntry entry in container.content) FileList.addItem(entry.name); }