private RenderDataSource createRenderDataSourceFromNodes(CNode rdsNode, CNode dbNode) { MiscUtil.Conversion.BigEndianBitConverter bc = new MiscUtil.Conversion.BigEndianBitConverter(); CustomVertex.PositionNormalColored[] vertices = new CustomVertex.PositionNormalColored[(int)dbNode.attributes["elementCount"].data]; Vector3 pos = new Vector3(); int color; Vector3 normal = new Vector3(); int vertexCount = 0; for (int i = 0; i < (int)dbNode.attributes["size"].data; i += 28) { pos.X = bc.ToSingle(dbNode.subNodes[3].data, i); pos.Y = bc.ToSingle(dbNode.subNodes[3].data, i + 4); pos.Z = bc.ToSingle(dbNode.subNodes[3].data, i + 8); color = bc.ToInt32(dbNode.subNodes[3].data, i + 12); normal.X = bc.ToSingle(dbNode.subNodes[3].data, i + 16); normal.Y = bc.ToSingle(dbNode.subNodes[3].data, i + 20); normal.Z = bc.ToSingle(dbNode.subNodes[3].data, i + 24); vertices[vertexCount] = new CustomVertex.PositionNormalColored(pos, normal, color); vertexCount++; } int indexCount = (int)rdsNode.subNodes[0].attributes["count"].data; ushort[] indices = new ushort[indexCount]; for (int i = 0; i < indexCount; i++) { indices[i] = bc.ToUInt16(rdsNode.subNodes[0].subNodes[0].data, i * 2); } return(new RenderDataSource(rdsNode.attributes["id"].value, vertices, indices)); }
public CNode(EndianBinaryReaderEx reader, CPSSGFile file) { this.file = file; id = reader.ReadInt32(); int size = reader.ReadInt32(); long end = reader.BaseStream.Position + size; int attributeSize = reader.ReadInt32(); long attributeEnd = reader.BaseStream.Position + attributeSize; // Each attr is at least 8 bytes (id + size), so take a conservative guess attributes = new Dictionary <string, CAttribute>(); CAttribute attr; while (reader.BaseStream.Position < attributeEnd) { attr = new CAttribute(reader, file); attributes.Add(attr.name, attr); } switch (name) { case "BOUNDINGBOX": case "DATA": case "DATABLOCKDATA": case "DATABLOCKBUFFERED": case "INDEXSOURCEDATA": case "INVERSEBINDMATRIX": case "MODIFIERNETWORKINSTANCEUNIQUEMODIFIERINPUT": case "NeAnimPacketData_B1": case "NeAnimPacketData_B4": case "RENDERINTERFACEBOUNDBUFFERED": case "SHADERINPUT": case "TEXTUREIMAGEBLOCKDATA": case "TRANSFORM": isDataNode = true; break; } if (isDataNode) { data = reader.ReadBytes((int)(end - reader.BaseStream.Position)); } else { // Each node at least 12 bytes (id + size + arg size) subNodes = new CNode[(end - reader.BaseStream.Position) / 12]; int nodeCount = 0; while (reader.BaseStream.Position < end) { subNodes[nodeCount] = new CNode(reader, file); nodeCount++; } Array.Resize(ref subNodes, nodeCount); } }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "PSSG files|*.pssg|All files|*.*"; dialog.Title = "Select a PSSG file"; if (dialog.ShowDialog() == DialogResult.OK) { closeFile(); StreamReader sr = new StreamReader(dialog.FileName); CPSSGFile f = new CPSSGFile(sr.BaseStream); pssgFile = f; treeView.Nodes.Add(createTreeViewNode(f.rootNode)); listBoxModels.Items.Clear(); Model[] models = new Model[f.findNodes("MATRIXPALETTEJOINTRENDERINSTANCE").Count]; modelView1.renderDataSources = new Dictionary <string, RenderDataSource>(); int i = 0; List <CNode> mpbnNodes = f.findNodes("MATRIXPALETTEBUNDLENODE"); foreach (CNode mpbnNode in mpbnNodes) { List <CNode> mpjnNodes = mpbnNode.findNodes("MATRIXPALETTEJOINTNODE"); foreach (CNode mpjnNode in mpjnNodes) { Matrix transform = getTransform((byte[])mpjnNode.subNodes[0].data); foreach (CNode mpjriNode in mpjnNode.findNodes("MATRIXPALETTEJOINTRENDERINSTANCE")) { string rdsId = mpjriNode.attributes["indices"].value.Substring(1); RenderDataSource renderDataSource; if (!modelView1.renderDataSources.TryGetValue(rdsId, out renderDataSource)) { CNode rdsNode = f.findNodes("RENDERDATASOURCE", "id", rdsId)[0]; CNode dbNode = f.findNodes("DATABLOCK", "id", rdsNode.subNodes[1].attributes["dataBlock"].value.Substring(1))[0]; renderDataSource = createRenderDataSourceFromNodes(rdsNode, dbNode); modelView1.renderDataSources.Add(rdsNode.attributes["id"].value, renderDataSource); } models[i] = new Model(mpjnNode.attributes["id"].ToString() + mpjriNode.attributes["shader"].ToString(), renderDataSource, transform, (int)mpjriNode.attributes["streamOffset"].data, (int)mpjriNode.attributes["elementCountFromOffset"].data, (int)mpjriNode.attributes["indexOffset"].data, (int)mpjriNode.attributes["indicesCountFromOffset"].data); listBoxModels.Items.Add(models[i]); i++; } } } createTreeViewTexturesList(f.rootNode); } else { } }
private TreeNode createTreeViewNode(CNode node) { TreeNode treeNode = new TreeNode(); treeNode.Text = node.name; treeNode.Tag = node; if (node.subNodes != null) { foreach (CNode subNode in node.subNodes) { treeNode.Nodes.Add(createTreeViewNode(subNode)); } } return(treeNode); }
private void writeNodesToXml(XmlWriter writer, CNode node) { writer.WriteStartElement(node.name.ToLower()); foreach (KeyValuePair <string, CAttribute> pair in node.attributes) { writer.WriteElementString(pair.Key, pair.Value.ToString()); } if (node.subNodes != null) { foreach (CNode subNode in node.subNodes) { writeNodesToXml(writer, subNode); } } writer.WriteEndElement(); }
private void toolStripButtonExport_Click(object sender, EventArgs e) { if (treeViewTextures.Nodes.Count == 0 || treeViewTextures.SelectedNode.Index == -1) { return; } CNode node = ((CNode)treeViewTextures.SelectedNode.Tag); SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "DDS files|*.dds|All files|*.*"; dialog.Title = "Select the dds save location and file name"; dialog.FileName = node.attributes["id"].value + ".dds"; if (dialog.ShowDialog() == DialogResult.OK) { writeDDS(dialog.FileName, node); } }
private void createTreeViewTexturesList(CNode node) { if (node.name == "TEXTURE") { TreeNode treeNode = new TreeNode(); treeNode.Text = node.attributes["id"].value; treeNode.Tag = node; treeViewTextures.Nodes.Add(treeNode); } if (node.subNodes != null) { foreach (CNode subNode in node.subNodes) { createTreeViewTexturesList(subNode); } } }
private void toolStripButtonImport_Click(object sender, EventArgs e) { if (treeViewTextures.Nodes.Count == 0 || treeViewTextures.SelectedNode.Index == -1) { return; } CNode node = ((CNode)treeViewTextures.SelectedNode.Tag); OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "DDS files|*.dds|All files|*.*"; dialog.Title = "Select a dds file"; dialog.FileName = node.attributes["id"].value + ".dds"; if (dialog.ShowDialog() == DialogResult.OK) { readDDS(dialog.FileName, node); createPreview(); } }
private void readDDS(string ddsPath, CNode node) { if (node == null) { node = node = ((CNode)treeViewTextures.SelectedNode.Tag); } int nMML = 0; using (BinaryReader b = new BinaryReader(File.Open(ddsPath, FileMode.Open))) { // Skip first 12 bytes b.ReadBytes(12); // Height node.attributes["height"].data = b.ReadInt32(); // Width node.attributes["width"].data = b.ReadInt32(); // Skip 8 b.ReadBytes(8); // numberMipMapLevels nMML = b.ReadInt32() - 1; if (nMML >= 0) { node.attributes["numberMipMapLevels"].data = nMML; } else { node.attributes["numberMipMapLevels"].data = 0; } // Skip 52 b.ReadBytes(52); // texelFormat node.attributes["texelFormat"].data = Encoding.UTF8.GetString(b.ReadBytes(4)).ToLower(); // Skip 40 b.ReadBytes(40); // Code node.subNodes[0].subNodes[0].data = b.ReadBytes((int)(b.BaseStream.Length - (long)128)); // TEXTUREIMAGEBLOCKDATA-Size //sections[sectionIndex + 2].Size = sections[sectionIndex + 2].Code.Length + 4; // TEXTUREIMAGEBLOCK_size node.subNodes[0].attributes["size"].data = node.subNodes[0].subNodes[0].data.Length; // TEXTUREIMAGEBLOCK-Size //sections[sectionIndex + 1].Size = bytesToInt(sections[sectionIndex + 1].Subsections["size"].Value) + sections[sectionIndex + 1].Size2 + 16; } }
public CPSSGFile(System.IO.Stream fileStream) { EndianBinaryReaderEx reader = new EndianBinaryReaderEx(new BigEndianBitConverter(), fileStream); magic = reader.ReadPSSGString(4); // TODO: Check magic int size = reader.ReadInt32(); int attributeInfoCount = reader.ReadInt32(); int nodeInfoCount = reader.ReadInt32(); attributeInfo = new CAttributeInfo[attributeInfoCount]; nodeInfo = new CNodeInfo[nodeInfoCount]; for (int i = 0; i < nodeInfoCount; i++) { nodeInfo[i] = new CNodeInfo(reader, this); } rootNode = new CNode(reader, this); }
private void writeDDS(string ddsPath, CNode node) { byte[] ddh; if (node == null) { node = ((CNode)treeViewTextures.SelectedNode.Tag); } using (BinaryReader b = new BinaryReader(File.Open(Application.StartupPath + "\\dxt.ddh", FileMode.Open))) { ddh = b.ReadBytes(128); } using (BinaryWriter b = new BinaryWriter(File.Open(ddsPath, FileMode.Create))) { b.Write(ddh); b.Write(node.subNodes[0].subNodes[0].data); } using (Stream outStream = File.Open(ddsPath, FileMode.Open)) { outStream.Seek(12, SeekOrigin.Begin); // Change Height and Width outStream.Write(BitConverter.GetBytes((int)node.attributes["height"].data), 0, 4); outStream.Write(BitConverter.GetBytes((int)node.attributes["width"].data), 0, 4); // Change size switch ((string)node.attributes["texelFormat"].data) { case "dxt1": outStream.Write(BitConverter.GetBytes(((int)node.attributes["width"].data) * ((int)node.attributes["height"].data) / 2), 0, 4); break; default: outStream.Write(BitConverter.GetBytes(((int)node.attributes["width"].data) * ((int)node.attributes["height"].data)), 0, 4); break; } // Skip 4 outStream.Seek(4, SeekOrigin.Current); // Change numberMipMapLevels + 1 outStream.Write(BitConverter.GetBytes((int)node.attributes["numberMipMapLevels"].data + 1), 0, 4); // Skip 52 outStream.Seek(52, SeekOrigin.Current); // Change Format outStream.Write(Encoding.UTF8.GetBytes(((string)node.attributes["texelFormat"].data).ToUpper()), 0, 4); } }
private void writeNodesToXml(XmlWriter writer, CNode node) { writer.WriteStartElement(node.name.ToLower()); foreach (KeyValuePair<string, CAttribute> pair in node.attributes) { writer.WriteElementString(pair.Key, pair.Value.ToString()); } if (node.subNodes != null) { foreach (CNode subNode in node.subNodes) { writeNodesToXml(writer, subNode); } } writer.WriteEndElement(); }
private TreeNode createTreeViewNode(CNode node) { TreeNode treeNode = new TreeNode(); treeNode.Text = node.name; treeNode.Tag = node; if (node.subNodes != null) { foreach (CNode subNode in node.subNodes) { treeNode.Nodes.Add(createTreeViewNode(subNode)); } } return treeNode; }
private RenderDataSource createRenderDataSourceFromNodes(CNode rdsNode, CNode dbNode) { MiscUtil.Conversion.BigEndianBitConverter bc = new MiscUtil.Conversion.BigEndianBitConverter(); CustomVertex.PositionNormalColored[] vertices = new CustomVertex.PositionNormalColored[(int)dbNode.attributes["elementCount"].data]; Vector3 pos = new Vector3(); int color; Vector3 normal = new Vector3(); int vertexCount = 0; for (int i = 0; i < (int)dbNode.attributes["size"].data; i += 28) { pos.X = bc.ToSingle(dbNode.subNodes[3].data, i); pos.Y = bc.ToSingle(dbNode.subNodes[3].data, i + 4); pos.Z = bc.ToSingle(dbNode.subNodes[3].data, i + 8); color = bc.ToInt32(dbNode.subNodes[3].data, i + 12); normal.X = bc.ToSingle(dbNode.subNodes[3].data, i + 16); normal.Y = bc.ToSingle(dbNode.subNodes[3].data, i + 20); normal.Z = bc.ToSingle(dbNode.subNodes[3].data, i + 24); vertices[vertexCount] = new CustomVertex.PositionNormalColored(pos, normal, color); vertexCount++; } int indexCount = (int)rdsNode.subNodes[0].attributes["count"].data; ushort[] indices = new ushort[indexCount]; for (int i = 0; i < indexCount; i++) { indices[i] = bc.ToUInt16(rdsNode.subNodes[0].subNodes[0].data, i * 2); } return new RenderDataSource(rdsNode.attributes["id"].value, vertices, indices); }
public CNode(EndianBinaryReaderEx reader, CPSSGFile file) { this.file = file; id = reader.ReadInt32(); int size = reader.ReadInt32(); long end = reader.BaseStream.Position + size; int attributeSize = reader.ReadInt32(); long attributeEnd = reader.BaseStream.Position + attributeSize; // Each attr is at least 8 bytes (id + size), so take a conservative guess attributes = new Dictionary<string, CAttribute>(); CAttribute attr; while (reader.BaseStream.Position < attributeEnd) { attr = new CAttribute(reader, file); attributes.Add(attr.name, attr); } switch (name) { case "BOUNDINGBOX": case "DATABLOCKDATA": case "DATABLOCKBUFFERED": case "INDEXSOURCEDATA": case "INVERSEBINDMATRIX": case "MODIFIERNETWORKINSTANCEUNIQUEMODIFIERINPUT": case "RENDERINTERFACEBOUNDBUFFERED": case "SHADERINPUT": case "TEXTUREIMAGEBLOCKDATA": case "TRANSFORM": isDataNode = true; break; } if (isDataNode) { data = reader.ReadBytes((int)(end - reader.BaseStream.Position)); } else { // Each node at least 12 bytes (id + size + arg size) subNodes = new CNode[(end - reader.BaseStream.Position) / 12]; int nodeCount = 0; while (reader.BaseStream.Position < end) { subNodes[nodeCount] = new CNode(reader, file); nodeCount++; } Array.Resize(ref subNodes, nodeCount); } }