//public static public static F3DEXReaderPackage ReadF3DEXAt(RomFile file, int offset) { ResetReaderVariables(); byte[] data = file.GetAsBytes(); F3DEXReaderPackage package = new F3DEXReaderPackage(); 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); F3DEXCommand f3Command = F3DEXCommandFactory.ReadCommand(offset, command); if (f3Command == null) break; if (!_foundCommands.ContainsKey(file)) _foundCommands.Add(file, new List<F3DEXCommand>()); _foundCommands[file].Add(f3Command); ParseCommand(f3Command); offset += 8; if (f3Command is F3DEX_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<F3DEXCommandCollection>> commandColls = new Dictionary<RomFile, List<F3DEXCommandCollection>>(); Dictionary<RomFile, List<VertexCollection>> vertexColls = new Dictionary<RomFile, List<VertexCollection>>(); //F3DEX Commands foreach (RomFile rom in _foundCommands.Keys) { commandColls.Add(rom, new List<F3DEXCommandCollection>()); 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 F3DEXCommandCollection newColl = new F3DEXCommandCollection(_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; }
public void SetCommands(F3DEXCommandCollection commands) { openGLControl.GraphicsCollections.Add(VO64F3DEXReader.ReadCommands(commands)); }
private void btnRender_Click(object sender, EventArgs e) { if (SelectedCourse == null) return; for (; RomProject.Instance.Files.Count > 0;) RomProject.Instance.RemoveRomFile(RomProject.Instance.Files[0]); for (; RomProject.Instance.DMAProfiles.Count > 0; ) RomProject.Instance.RemoveDmaProfile(RomProject.Instance.DMAProfiles[0]); //Take the blocks, and export them byte[] displayListBlock = new byte[SelectedCourse.DisplayListBlockEnd - SelectedCourse.DisplayListBlockStart]; Array.Copy(_romData, SelectedCourse.DisplayListBlockStart, displayListBlock, 0, displayListBlock.Length); int vertexEndPackedDLStartOffset = SelectedCourse.DisplayListOffset & 0x00FFFFFF; byte[] vertexBlock = new byte[vertexEndPackedDLStartOffset]; Array.Copy(_romData, SelectedCourse.VertexBlockStart, vertexBlock, 0, vertexBlock.Length); byte[] packedBlock = new byte[(SelectedCourse.VertexBlockEnd - SelectedCourse.VertexBlockStart) - vertexEndPackedDLStartOffset]; Array.Copy(_romData, SelectedCourse.VertexBlockStart + vertexEndPackedDLStartOffset, packedBlock, 0, packedBlock.Length); byte[] textureBlock = new byte[SelectedCourse.TextureBlockEnd - SelectedCourse.TextureBlockStart]; Array.Copy(_romData, SelectedCourse.TextureBlockStart, textureBlock, 0, textureBlock.Length); byte[] decodedDLData = Cereal64.Common.Utils.Encoding.MIO0.Decode(displayListBlock); List<Vertex> vertices = VertexPacker.BytesToVertices(Cereal64.Common.Utils.Encoding.MIO0.Decode(vertexBlock).ToList()); VertexCollection vertCollection = new VertexCollection(0x00, vertices); byte[] vertsData = vertCollection.RawData; List<F3DEXCommand> commands = F3DEXPacker.BytesToCommands(packedBlock.ToList()); F3DEXCommandCollection commandColl = new F3DEXCommandCollection(0x00, commands); byte[] commandsData = commandColl.RawData; List<TextureMIORef> textureSegPointers = ReadTextureBank(textureBlock); byte[] textureSegData = new byte[textureSegPointers.Sum(t => t.DecompressedSize)]; int bytePointer = 0; for (int i = 0; i < textureSegPointers.Count; i++) { byte[] tempHolder = new byte[textureSegPointers[i].CompressedSize]; Array.Copy(_romData, (textureSegPointers[i].RomOffset & 0x00FFFFFF) + MK64_TEXTURE_BANK_OFFSET, tempHolder, 0, textureSegPointers[i].CompressedSize); byte[] decompressed = Cereal64.Common.Utils.Encoding.MIO0.Decode(tempHolder); Array.Copy(decompressed, 0, textureSegData, bytePointer, decompressed.Length); bytePointer += decompressed.Length; } //Use the F3DEXReader here RomProject.Instance.AddRomFile(new RomFile("Verts", 1, new Cereal64.Common.DataElements.UnknownData(0x00, vertsData))); RomProject.Instance.Files[0].FileLength = vertsData.Length; RomProject.Instance.AddRomFile(new RomFile("PackedDLs", 2, new Cereal64.Common.DataElements.UnknownData(0x00, commandsData))); RomProject.Instance.Files[1].FileLength = commandsData.Length; RomProject.Instance.AddRomFile(new RomFile("Textures", 3, new Cereal64.Common.DataElements.UnknownData(0x00, textureSegData))); RomProject.Instance.Files[2].FileLength = textureSegData.Length; DmaProfile profile = new DmaProfile("Levelviewer"); DmaSegment segment = new DmaSegment(); segment.File = RomProject.Instance.Files[0]; segment.RamSegment = 0x04; segment.RamStartOffset = 0x00; segment.FileStartOffset = 0x00; segment.FileEndOffset = segment.File.FileLength; segment.TagInfo = "Vertices"; profile.AddDmaSegment(0x04, segment); segment = new DmaSegment(); segment.File = RomProject.Instance.Files[1]; segment.RamSegment = 0x07; segment.RamStartOffset = 0x00; segment.FileStartOffset = 0x00; segment.FileEndOffset = segment.File.FileLength; segment.TagInfo = "PackedDLs"; profile.AddDmaSegment(0x07, segment); segment = new DmaSegment(); segment.File = RomProject.Instance.Files[2]; segment.RamSegment = 0x05; segment.RamStartOffset = 0x00; segment.FileStartOffset = 0x00; segment.FileEndOffset = segment.File.FileLength; segment.TagInfo = "Textures"; profile.AddDmaSegment(0x05, segment); RomProject.Instance.AddDmaProfile(profile); DmaManager.Instance.AddNewDmaProfile(profile); F3DEXReaderPackage package = F3DEXReader.ReadF3DEXAt(RomProject.Instance.Files[1], 0x00); F3DEXReaderPackage newPackage = package; newPackage = null; if (package.Elements[RomProject.Instance.Files[1]][0] is F3DEXCommandCollection) { OpenGLForm glForm = new OpenGLForm(); glForm.Show(); glForm.SetCommands((F3DEXCommandCollection)package.Elements[RomProject.Instance.Files[1]][0]); } }
public static VO64GraphicsCollection ReadCommands(F3DEXCommandCollection commands) { //Set up the VO64 graphics VO64GraphicsCollection collection = new VO64GraphicsCollection(); VO64GraphicsElement element = VO64GraphicsElement.CreateNewElement(); Texture lastTexture = null; F3DEX_G_SetTile lastSetTile = null; F3DEX_G_Texture lastTextureCommand = null; List<uint> vertexOffsetList = new List<uint>(); //Keeps track of which vertices are loaded where List<Vertex> vertices = new List<Vertex>(); F3DEXVertexWrapper newVertex = null; F3DEXTextureWrapper newTexture = null; bool recordTileCommands = true; //Use RDPLoadSync and RDPTileSync to determine when it's okay to pick up SetTile commands //Note: Not guaranteed for all ways of using F3DEX!! foreach(F3DEXCommand command in commands.Commands) { switch (command.CommandID) { case F3DEXCommandID.F3DEX_G_RDPLOADSYNC: recordTileCommands = true; break; case F3DEXCommandID.F3DEX_G_RDPTILESYNC: recordTileCommands = true; break; case F3DEXCommandID.F3DEX_G_DL: //ignore this one for now break; case F3DEXCommandID.F3DEX_G_SETTILE: if (((F3DEX_G_SetTile)command).Line != 0)//recordTileCommands) { //keep track of this command when setting up the texture lastSetTile = (F3DEX_G_SetTile)command; recordTileCommands = true; } break; case F3DEXCommandID.F3DEX_G_TEXTURE: lastTextureCommand = (F3DEX_G_Texture)command; break; case F3DEXCommandID.F3DEX_G_VTX: //Record the vertex offset here, to keep track of vertex counts F3DEX_G_Vtx vtxCommand = (F3DEX_G_Vtx)command; break; case F3DEXCommandID.F3DEX_G_TRI1: if (((F3DEX_G_Tri1)command).TextureReference != null && lastTexture != ((F3DEX_G_Tri1)command).TextureReference) { //save the element if (!element.IsEmpty) { collection.Add(element); element = VO64GraphicsElement.CreateNewElement(); } vertices.Clear(); //Set the texture here lastTexture = ((F3DEX_G_Tri1)command).TextureReference; newTexture = new F3DEXTextureWrapper(lastTexture, lastSetTile, lastTextureCommand); element.SetTexture(newTexture); } F3DEX_G_Tri1 tri = (F3DEX_G_Tri1)command; if (tri.Vertex1Reference != null && tri.Vertex2Reference != null && tri.Vertex3Reference != null) { if (!vertices.Contains(tri.Vertex1Reference)) { vertices.Add(tri.Vertex1Reference); newVertex = new F3DEXVertexWrapper(tri.Vertex1Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri.Vertex2Reference)) { vertices.Add(tri.Vertex2Reference); newVertex = new F3DEXVertexWrapper(tri.Vertex2Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri.Vertex3Reference)) { vertices.Add(tri.Vertex3Reference); newVertex = new F3DEXVertexWrapper(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 F3DEXTriangleWrapper((F3DEX_G_Tri1)command); element.AddTriangle(triangle); } break; case F3DEXCommandID.F3DEX_G_TRI2: if (((F3DEX_G_Tri2)command).TextureReference != null && lastTexture != ((F3DEX_G_Tri2)command).TextureReference) { //save the element if (!element.IsEmpty) { collection.Add(element); element = VO64GraphicsElement.CreateNewElement(); } vertices.Clear(); //Set the texture here lastTexture = ((F3DEX_G_Tri2)command).TextureReference; newTexture = F3DEXWrapperBank.GetTextureWrapper(lastTexture, lastSetTile, lastTextureCommand); element.SetTexture(newTexture); } F3DEX_G_Tri2 tri2 = (F3DEX_G_Tri2)command; if (tri2.Vertex1Reference != null && tri2.Vertex2Reference != null && tri2.Vertex3Reference != null) { if (!vertices.Contains(tri2.Vertex1Reference)) { vertices.Add(tri2.Vertex1Reference); newVertex = F3DEXWrapperBank.GetVertexWrapper(tri2.Vertex1Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex2Reference)) { vertices.Add(tri2.Vertex2Reference); newVertex = F3DEXWrapperBank.GetVertexWrapper(tri2.Vertex2Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex3Reference)) { vertices.Add(tri2.Vertex3Reference); newVertex = F3DEXWrapperBank.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 F3DEXTriangleWrapper((F3DEX_G_Tri1)command); element.AddTriangle(triangle2); } if (tri2.Vertex4Reference != null && tri2.Vertex5Reference != null && tri2.Vertex6Reference != null) { if (!vertices.Contains(tri2.Vertex4Reference)) { vertices.Add(tri2.Vertex4Reference); newVertex = F3DEXWrapperBank.GetVertexWrapper(tri2.Vertex4Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex5Reference)) { vertices.Add(tri2.Vertex5Reference); newVertex = F3DEXWrapperBank.GetVertexWrapper(tri2.Vertex5Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } if (!vertices.Contains(tri2.Vertex6Reference)) { vertices.Add(tri2.Vertex6Reference); newVertex = F3DEXWrapperBank.GetVertexWrapper(tri2.Vertex6Reference); newVertex.SetTextureProperties(newTexture); element.AddVertex(newVertex); } VO64SimpleTriangle triangle2 = new VO64SimpleTriangle((ushort)vertices.IndexOf(tri2.Vertex4Reference), (ushort)vertices.IndexOf(tri2.Vertex5Reference), (ushort)vertices.IndexOf(tri2.Vertex6Reference));//new F3DEXTriangleWrapper((F3DEX_G_Tri1)command); element.AddTriangle(triangle2); } break; } } collection.Add(element); return collection; }