public static VO64GraphicsCollection ReadCommands(F3DZEXCommandCollection commands) { //Set up the VO64 graphics VO64GraphicsCollection collection = new VO64GraphicsCollection(); VO64GraphicsElement element = VO64GraphicsElement.CreateNewElement(); Texture lastTexture = null; F3DZEX_G_SetTile lastSetTile = null; F3DZEX_G_Texture lastTextureCommand = null; List<uint> vertexOffsetList = new List<uint>(); //Keeps track of which vertices are loaded where List<Vertex> vertices = new List<Vertex>(); F3DZEXVertexWrapper newVertex = null; F3DZEXTextureWrapper newTexture = null; bool recordTileCommands = false; //Use RDPLoadSync and RDPTileSync to determine when it's okay to pick up SetTile commands //Note: Not guaranteed for all ways of using F3DZEX!! foreach(F3DZEXCommand command in commands.Commands) { switch (command.CommandID) { case F3DZEXCommandID.F3DZEX_G_RDPLOADSYNC: recordTileCommands = true; break; case F3DZEXCommandID.F3DZEX_G_RDPTILESYNC: recordTileCommands = false; break; case F3DZEXCommandID.F3DZEX_G_DL: //ignore this one for now break; case F3DZEXCommandID.F3DZEX_G_SETTILE: if (recordTileCommands) { //keep track of this command when setting up the texture lastSetTile = (F3DZEX_G_SetTile)command; recordTileCommands = false; } break; case F3DZEXCommandID.F3DZEX_G_TEXTURE: lastTextureCommand = (F3DZEX_G_Texture)command; break; case F3DZEXCommandID.F3DZEX_G_VTX: //Record the vertex offset here, to keep track of vertex counts F3DZEX_G_Vtx vtxCommand = (F3DZEX_G_Vtx)command; break; case F3DZEXCommandID.F3DZEX_G_TRI1: if (((F3DZEX_G_Tri2)command).TextureReference != null && lastTexture != ((F3DZEX_G_Tri2)command).TextureReference) { //save the element if (!element.IsEmpty) { collection.Add(element); element = VO64GraphicsElement.CreateNewElement(); } vertices.Clear(); //Set the texture here lastTexture = ((F3DZEX_G_Tri2)command).TextureReference; newTexture = new F3DZEXTextureWrapper(lastTexture, lastSetTile, lastTextureCommand); element.SetTexture(newTexture); } F3DZEX_G_Tri1 tri = (F3DZEX_G_Tri1)command; if (!vertices.Contains(tri.Vertex1Reference)) { vertices.Add(tri.Vertex1Reference); newVertex = new F3DZEXVertexWrapper(tri.Vertex1Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri.Vertex2Reference)) { vertices.Add(tri.Vertex2Reference); newVertex = new F3DZEXVertexWrapper(tri.Vertex2Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri.Vertex3Reference)) { vertices.Add(tri.Vertex3Reference); newVertex = new F3DZEXVertexWrapper(tri.Vertex3Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } VO64SimpleTriangle triangle = new VO64SimpleTriangle((ushort)vertices.IndexOf(tri.Vertex1Reference), (ushort)vertices.IndexOf(tri.Vertex2Reference), (ushort)vertices.IndexOf(tri.Vertex3Reference));//new F3DZEXTriangleWrapper((F3DZEX_G_Tri1)command); element.AddTriangle(triangle); break; case F3DZEXCommandID.F3DZEX_G_TRI2: if (((F3DZEX_G_Tri2)command).TextureReference != null && lastTexture != ((F3DZEX_G_Tri2)command).TextureReference) { //save the element if (!element.IsEmpty) { collection.Add(element); element = VO64GraphicsElement.CreateNewElement(); } vertices.Clear(); //Set the texture here lastTexture = ((F3DZEX_G_Tri2)command).TextureReference; newTexture = F3DZEXWrapperBank.GetTextureWrapper(lastTexture, lastSetTile, lastTextureCommand); element.SetTexture(newTexture); } F3DZEX_G_Tri2 tri2 = (F3DZEX_G_Tri2)command; if (!vertices.Contains(tri2.Vertex1Reference)) { vertices.Add(tri2.Vertex1Reference); newVertex = F3DZEXWrapperBank.GetVertexWrapper(tri2.Vertex1Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex2Reference)) { vertices.Add(tri2.Vertex2Reference); newVertex = F3DZEXWrapperBank.GetVertexWrapper(tri2.Vertex2Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex3Reference)) { vertices.Add(tri2.Vertex3Reference); newVertex = F3DZEXWrapperBank.GetVertexWrapper(tri2.Vertex3Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } VO64SimpleTriangle triangle2 = new VO64SimpleTriangle((ushort)vertices.IndexOf(tri2.Vertex1Reference), (ushort)vertices.IndexOf(tri2.Vertex2Reference), (ushort)vertices.IndexOf(tri2.Vertex3Reference));//new F3DZEXTriangleWrapper((F3DZEX_G_Tri1)command); element.AddTriangle(triangle2); if (!vertices.Contains(tri2.Vertex4Reference)) { vertices.Add(tri2.Vertex4Reference); newVertex = F3DZEXWrapperBank.GetVertexWrapper(tri2.Vertex4Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex5Reference)) { vertices.Add(tri2.Vertex5Reference); newVertex = F3DZEXWrapperBank.GetVertexWrapper(tri2.Vertex5Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex6Reference)) { vertices.Add(tri2.Vertex6Reference); newVertex = F3DZEXWrapperBank.GetVertexWrapper(tri2.Vertex6Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } triangle2 = new VO64SimpleTriangle((ushort)vertices.IndexOf(tri2.Vertex4Reference), (ushort)vertices.IndexOf(tri2.Vertex5Reference), (ushort)vertices.IndexOf(tri2.Vertex6Reference));//new F3DZEXTriangleWrapper((F3DZEX_G_Tri1)command); element.AddTriangle(triangle2); break; } } collection.Add(element); return collection; }
//public static public static F3DZEXReaderPackage ReadF3DZEXAt(RomFile file, int offset) { ResetReaderVariables(); byte[] data = file.GetAsBytes(); F3DZEXReaderPackage package = new F3DZEXReaderPackage(); if (offset < 0 || offset >= data.Length || offset % 8 != 0) return package; //Reset/Initialize what needs to be initialized/reset byte[] command = new byte[8]; while (offset < data.Length) { //read the command Array.Copy(data, offset, command, 0, 8); F3DZEXCommand f3Command = F3DZEXCommandFactory.ReadCommand(offset, command); if (f3Command == null) break; if (!_foundCommands.ContainsKey(file)) _foundCommands.Add(file, new List<F3DZEXCommand>()); _foundCommands[file].Add(f3Command); ParseCommand(f3Command); offset += 8; if (f3Command is F3DZEX_G_EndDL) break; } //Sort what needs to be sorted foreach(RomFile rom in _foundTextures.Keys) { _foundTextures[rom].Sort((s1, s2) => s1.FileOffset.CompareTo(s2.FileOffset)); for (int i = 0; i < _foundTextures[rom].Count - 1; i++) { if (_foundTextures[rom][i].FileOffset == _foundTextures[rom][i + 1].FileOffset) { _foundTextures[rom].RemoveAt(i); i--; } } } foreach (RomFile rom in _foundPalettes.Keys) { _foundPalettes[rom].Sort((s1, s2) => s1.FileOffset.CompareTo(s2.FileOffset)); for (int i = 0; i < _foundPalettes[rom].Count - 1; i++) { if (_foundPalettes[rom][i].FileOffset == _foundPalettes[rom][i + 1].FileOffset) { _foundPalettes[rom].RemoveAt(i); i--; } } } foreach (RomFile rom in _foundVertices.Keys) { _foundVertices[rom].Sort((s1, s2) => s1.FileOffset.CompareTo(s2.FileOffset)); for (int i = 0; i < _foundVertices[rom].Count - 1; i++) { if (_foundVertices[rom][i].FileOffset == _foundVertices[rom][i + 1].FileOffset) { _foundVertices[rom].RemoveAt(i); i--; } } } foreach (RomFile rom in _foundCommands.Keys) { _foundCommands[rom].Sort((s1, s2) => s1.FileOffset.CompareTo(s2.FileOffset)); for (int i = 0; i < _foundCommands[rom].Count - 1; i++) { if (_foundCommands[rom][i].FileOffset == _foundCommands[rom][i + 1].FileOffset) { _foundCommands[rom].RemoveAt(i); i--; } } } //Combine into the collections Dictionary<RomFile, List<F3DZEXCommandCollection>> commandColls = new Dictionary<RomFile, List<F3DZEXCommandCollection>>(); Dictionary<RomFile, List<VertexCollection>> vertexColls = new Dictionary<RomFile, List<VertexCollection>>(); //F3DZEX Commands foreach (RomFile rom in _foundCommands.Keys) { commandColls.Add(rom, new List<F3DZEXCommandCollection>()); int startColl = 0; for (int endColl = 0; endColl < _foundCommands[rom].Count; endColl++) { if (endColl == _foundCommands[rom].Count - 1 || _foundCommands[rom][endColl + 1].FileOffset != _foundCommands[rom][endColl].FileOffset + _foundCommands[rom][endColl].RawDataSize) { //Cut off the collection here F3DZEXCommandCollection newColl = new F3DZEXCommandCollection(_foundCommands[rom][startColl].FileOffset, _foundCommands[rom].GetRange(startColl, endColl - startColl + 1)); //NOTE: Shallow copying is done here commandColls[rom].Add(newColl); startColl = endColl + 1; } } } //Vertices foreach (RomFile rom in _foundVertices.Keys) { vertexColls.Add(rom, new List<VertexCollection>()); int startColl = 0; for (int endColl = 0; endColl < _foundVertices[rom].Count; endColl++) { if (endColl == _foundVertices[rom].Count - 1 || _foundVertices[rom][endColl + 1].FileOffset != _foundVertices[rom][endColl].FileOffset + _foundVertices[rom][endColl].RawDataSize) { //Cut off the collection here VertexCollection newVert = new VertexCollection(_foundVertices[rom][startColl].FileOffset, _foundVertices[rom].GetRange(startColl, endColl - startColl + 1)); //NOTE: Shallow copying is done here vertexColls[rom].Add(newVert); startColl = endColl + 1; } } } //double check that the package has all the files foreach (RomFile rom in _foundTextures.Keys.Union(_foundPalettes.Keys.Union( commandColls.Keys.Union(vertexColls.Keys)))) { if (!package.Elements.ContainsKey(rom)) package.Elements.Add(rom, new List<N64DataElement>()); } foreach (RomFile rom in _foundTextures.Keys) package.Elements[rom].AddRange(_foundTextures[rom]); foreach (RomFile rom in _foundPalettes.Keys) package.Elements[rom].AddRange(_foundPalettes[rom]); foreach (RomFile rom in commandColls.Keys) package.Elements[rom].AddRange(commandColls[rom]); foreach (RomFile rom in vertexColls.Keys) package.Elements[rom].AddRange(vertexColls[rom]); return package; }