Esempio n. 1
0
        public static void DumpTextures(byte[] romBytes, string outputDir)
        {
            Directory.CreateDirectory(outputDir + "Converted");
            string fullOutputPath = outputDir + "Converted/texture/";

            Directory.CreateDirectory(fullOutputPath);

            // ok this is dumb i need to fix this
            Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes);

            foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVTX"))
            {
                // TODO
                string   outputFileName = $"[0x{file.formLocationInROM:x6}]";
                UVTXFile uvtx           = new UVTXFile(file.Sections.Single().Item2);

                StringBuilder fileStringBuilder = new StringBuilder();

                fileStringBuilder.AppendLine("========================================");
                fileStringBuilder.AppendLine($"{outputFileName} ({uvtx.texelData.Length} data | {uvtx.displayListCommands.Length} cmds | {uvtx.palettes.Length} palettes)");
                fileStringBuilder.AppendLine($"(footer) size <{uvtx.imageWidth}, {uvtx.imageHeight}> | {uvtx.mipMapCount} mm |");

                string?cmdString = SaveAsPNG(uvtx, fullOutputPath + outputFileName);

                if (cmdString == null)
                {
                    continue;
                }
                fileStringBuilder.Append(cmdString);

                fileStringBuilder.AppendLine("Unknown: \n" + String.Join(" ", uvtx.unknownData.Select(b => b.ToString("X2"))));
                fileStringBuilder.AppendLine("Floats: " + String.Join(", ", uvtx.unknownFloats.Select(f => f.ToString("F8"))));
                Console.Write(fileStringBuilder.ToString());
            }
        }
Esempio n. 2
0
        public static void DisplayModels(byte[] romBytes)
        {
            Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes);

            foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVMD"))
            {
                UVMDFile uvmd = new UVMDFile(new PowerByteArray(file.Sections.Single().Item2), filesystem);
            }
        }
        public static void ParseUVCTs(byte[] romBytes)
        {
            // ok this is dumb i need to fix this
            Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes);

            foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVCT"))
            {
                PowerByteArray data = new PowerByteArray(file.Section("COMM"));

                new UVCTFile(data, filesystem);
            }
        }
Esempio n. 4
0
        public static void ParseUVTRs(byte[] romBytes)
        {
            //Directory.CreateDirectory(outputDir + "Converted");
            //string fullOutputPath = outputDir + "Converted/UVTR/";
            //Directory.CreateDirectory(fullOutputPath);

            // ok this is dumb i need to fix this
            Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes);

            foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVTR"))
            {
                PowerByteArray data = new PowerByteArray(file.Section("COMM"));

                UVTR uvtr = new UVTR();
                uvtr.h_6float = data.NextSubArray(24).AsFloats();
                uvtr.h_b1     = data.NextU8();
                uvtr.h_b2     = data.NextU8();
                uvtr.h_f1     = data.NextFloat();
                uvtr.h_f2     = data.NextFloat();
                uvtr.h_f3     = data.NextFloat();

                using (ThreeDDisplayWindow window = new ThreeDDisplayWindow())
                {
                    Console.WriteLine(uvtr.h_b1 * uvtr.h_b2);
                    uvtr.pB1xB2Mem = new UVTR140Struct[uvtr.h_b1 * uvtr.h_b2];
                    for (int i = 0; i < uvtr.pB1xB2Mem.Length; i++)
                    {
                        UVTR140Struct oneFourty = new UVTR140Struct();
                        if (data.NextU8() == 0)
                        {
                            continue;
                        }
                        oneFourty.m1 = new Matrix(data.NextSubArray(64).AsFloats());
                        byte unkByte = data.NextU8();

                        // m2 = identity matrix
                        oneFourty.m2 = new Matrix(new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 });

                        // Copy translation from m1 to m2
                        oneFourty.m2[12] = oneFourty.m1[12];
                        oneFourty.m2[13] = oneFourty.m1[13];
                        oneFourty.m2[14] = oneFourty.m1[14];

                        /* FUN_801360cc(m2, m2) */
                        Console.WriteLine(oneFourty.m1);
                        oneFourty.uvctFileIndex = data.NextU16();
                        var uvct = filesystem.GetFile("UVCT", oneFourty.uvctFileIndex);
                        Console.WriteLine($"{uvct.formLocationInROM:x6}");
                        var uvctFile = new UVCTFile(new PowerByteArray(uvct.Section("COMM")), filesystem);
                        uvctFile.AddToWindow(window, oneFourty.m1);


                        /* oneFourty.pUVCT = processed filesystem.GetFile("UVCT", oneFourty.uvctFileIndex); */

                        /* if uvct does not exist, set oneFourty.unkFloat to 0 and move to next loop*/

                        /* at this point some stuff happens with the UVCT, idk what exactly */

                        uvtr.pB1xB2Mem[i] = oneFourty;
                    }

                    window.Run();
                }

                uvtr.ushort1       = data.NextU16();
                uvtr.uvrwFileIndex = data.NextU16();

                /*
                 * if (DAT_8002d1a8 == 0) {
                 *  uvtrObj->ushort1 = 0;
                 *  uVar1 = uvtrObj->ushort1;
                 * }
                 * else {
                 *  uVar1 = uvtrObj->ushort1;
                 * }
                 */

                if (uvtr.ushort1 != 0)
                {
                    /* Load UVRW COMM section */

                    uvtr.unk4Bytes = data.NextU32();

                    data.NextU16();
                    data.NextU16();
                    data.NextU16();

                    /* a whole bunch of nonsense */

                    /* includes reading a few more shorts (maybe) */
                }
            }
        }
Esempio n. 5
0
        public static void DumpFonts(byte[] romBytes, string outputDir)
        {
            Directory.CreateDirectory(outputDir + "Converted");
            string fullOutputPath = outputDir + "Converted/font/";

            Directory.CreateDirectory(fullOutputPath);

            // ok this is dumb i need to fix this
            Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes);

            foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVFT"))
            {
                // TODO
                string outputSubfolder = $"{fullOutputPath}[0x{file.formLocationInROM:x6}]/";
                Directory.CreateDirectory(outputSubfolder);

                List <byte[]> imageDatas       = file.SectionsOfType("IMAG");
                byte[]        charIndexToASCII = file.Section("STRG");
                byte[]        frmtSec          = file.Section("FRMT");
                if (frmtSec.Length != 8)
                {
                    throw new Exception();
                }
                Texels.ColorFormat colorFormat = (Texels.ColorFormat)frmtSec.ReadUInt32(0);
                Texels.BitSize     bitSize     = (Texels.BitSize)frmtSec.ReadUInt32(4);

                CharacterDescriptor[] characterDescriptors = file.Section("BITM")
                                                             .InGroupsOf(16)
                                                             .Select((charDescData, index) => new CharacterDescriptor(charDescData, index))
                                                             .ToArray();

                // First, save off the main images
                //for (int i = 0; i < imageDatas.Count; i++)
                //{
                //    byte[] imageData = imageDatas[i];
                //    IEnumerable<CharacterDescriptor> relevantChars = characterDescriptors.Where(c => c.sourceIMAGIndex == i);
                //    int texelsPerLine = relevantChars.First().sourceIMAGTexelsPerLine;
                //    if(relevantChars.Any(c => c.sourceIMAGTexelsPerLine != texelsPerLine))
                //    {
                //        throw new Exception("Inconsistent texels per line in BITM section!");
                //    }
                //    int imagHeightTexels = relevantChars.Max(c => c.heightTexels);
                //    int bytesPerLine = Texels.GetNumBytes(texelsPerLine, bitSize);

                //    Bitmap bitmap = Texels.ConvertToBitmap(imageData, colorFormat, bitSize, texelsPerLine, imagHeightTexels, bytesPerLine, false, false, null);
                //    bitmap.Save($"{outputSubfolder}{i+1}.png");
                //}

                // Now save each of the characters
                //string individualCharsDirectory = $"{outputSubfolder}Individual Characters/";
                //Directory.CreateDirectory(individualCharsDirectory);
                foreach (CharacterDescriptor charDesc in characterDescriptors)
                {
                    byte[] sourceIMAG = imageDatas[charDesc.sourceIMAGIndex];
                    byte[] texelData;
                    if (bitSize == Texels.BitSize._4)
                    {
                        texelData = GetByteArrayStartingFromFourBitIndex(sourceIMAG, charDesc.startTexel).ToArray();
                    }
                    else
                    {
                        texelData = sourceIMAG.Skip(Texels.GetNumBytes(charDesc.startTexel, bitSize)).ToArray();
                    }

                    int bytesPerLine = Texels.GetNumBytes(charDesc.sourceIMAGTexelsPerLine, bitSize);

                    Bitmap bitmap = Texels.ConvertToBitmap(texelData, colorFormat, bitSize, charDesc.widthTexels, charDesc.heightTexels, bytesPerLine, false, false, null);

                    string filename = $"{charDesc.indexInBITM:D2}";
                    char   ascii    = Convert.ToChar(charIndexToASCII[charDesc.indexInBITM]);
                    if (!Path.GetInvalidFileNameChars().Contains(ascii))
                    {
                        filename += $" ({ascii})";
                    }

                    bitmap.Save($"{outputSubfolder}{filename}.png");
                }
                Console.WriteLine($"Converted font at {file.formLocationInROM:x6}");
            }
        }
        public static void DumpBlits(byte[] romBytes, string outputDir)
        {
            Directory.CreateDirectory(outputDir + "Converted");
            string fullOutputPath = outputDir + "Converted/blit/";

            Directory.CreateDirectory(fullOutputPath);

            // ok this is dumb i need to fix this
            Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes);

            foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVBT"))
            {
                string outputFileName = $"[0x{file.formLocationInROM:x6}]";
                byte[] bytes          = file.Sections.Single().Item2;

                ColorFormat colorFormat   = (ColorFormat)bytes.ReadUInt16(0);
                BitSize     bitSize       = Texels.NumBitsToBitSize(bytes.ReadUInt16(2));
                ushort      width         = bytes.ReadUInt16(4);
                ushort      texelsPerLine = bytes.ReadUInt16(6);
                ushort      height        = bytes.ReadUInt16(8);
                ushort      tileWidth     = bytes.ReadUInt16(10);
                ushort      tileHeight    = bytes.ReadUInt16(12);

                byte[] colorData = bytes.Subsection(14, bytes.Length - 14);



                Console.WriteLine(bytes.Subsection(0, 14).PrettyPrint());
                Console.WriteLine($"{outputFileName} {bitSize}-bit {colorFormat}\t <{width} ({texelsPerLine}), {height}> [{tileWidth} {tileHeight}]");
                int bytesPerTile = (int)(tileWidth * tileHeight * Texels.BitSizeToNumBytesFloat(bitSize));

                Bitmap outBitmap   = new Bitmap(width, height);
                int    p           = 0;
                int    curTopLeftX = 0;
                int    curTopLeftY = 0;
                while (p < colorData.Length)
                {
                    if (curTopLeftY + tileHeight > height)
                    {
                        tileHeight   = (ushort)(height - curTopLeftY);
                        bytesPerTile = (int)(tileWidth * tileHeight * Texels.BitSizeToNumBytesFloat(bitSize));
                    }

                    byte[] tileColorData;
                    if (p + bytesPerTile >= colorData.Length)
                    {
                        tileColorData = new byte[bytesPerTile];
                        Array.Copy(colorData, p, tileColorData, 0, colorData.Length - p);
                    }
                    else
                    {
                        tileColorData = colorData.Subsection(p, bytesPerTile);
                    }
                    // TODO: why arent 32-bit textures deinterleaved?
                    Bitmap tile = Texels.ConvertToBitmap(tileColorData, colorFormat, bitSize, tileWidth, tileHeight, (int)(tileWidth * Texels.BitSizeToNumBytesFloat(bitSize)), false, bitSize != BitSize._32, null);
                    CopyToMainBitmap(tile, curTopLeftX, curTopLeftY, outBitmap);


                    p += bytesPerTile;

                    curTopLeftX += tileWidth;

                    if (curTopLeftX >= width)
                    {
                        curTopLeftX  = 0;
                        curTopLeftY += tileHeight;

                        if (curTopLeftY >= height)
                        {
                            break;
                        }
                    }
                }

                outBitmap.Save(fullOutputPath + outputFileName + ".png");
            }
        }
Esempio n. 7
0
        public UVMDFile(PowerByteArray fileBytes, Filesystem.Filesystem filesystem)
        {
            Console.WriteLine("NEW UVMD");

            {
                lodCount    = fileBytes.NextU8();
                partsPerLOD = fileBytes.NextU8();
                b3          = fileBytes.NextU8();
                byte alwaysZero = fileBytes.NextU8();
                if (alwaysZero != 0)
                {
                    throw new Exception();
                }

                vertexCount = fileBytes.NextU16();
                // These are here for memory allocation, but we don't care!
                ushort totalMaterials = fileBytes.NextU16(); //24 structs
                ushort totalCommands  = fileBytes.NextU16();

                if ((b3 & 0x80) != 0)
                {
                    // appears to be 10 floats, 3 signed shorts, 1 byte
                    // TODO
                    UnknownOptionalHeaderData unknownOptionalData = new UnknownOptionalHeaderData(fileBytes.NextSubArray(0x2F));
                }

                float1 = fileBytes.NextFloat();
                float2 = fileBytes.NextFloat();
                float3 = fileBytes.NextFloat();
            }

            // Lets allocate all memory here since this is where it happens anyway
            // 36 bytes: already done, that's the response struct

            // b1 * 12: subsections
            pLODs = new LOD[lodCount];

            // b2 * 64: matrices
            pMatrices = new Matrix[partsPerLOD];

            // b1 * b2 * 44: parts
            // this is initialized in the loop

            // short1 * 16
            // this is initialized in the loop

            // short2 * 24
            // this is initialized in the loop

            // short3 * 8
            // this is initialized in the loop

            ////////////////////////////////

            // Overall structure here is correct, but the processing is not implemented yet



            for (int i = 0; i < lodCount; i++)
            {
                Console.WriteLine("  LOD " + i);
                LOD lodInfo;

                lodInfo.partCount = fileBytes.NextU8();
                lodInfo.b2        = fileBytes.NextU8();
                lodInfo.f         = fileBytes.NextFloat();
                lodInfo.f         = lodInfo.f * lodInfo.f;

                lodInfo.pModelParts = new ModelPart[lodInfo.partCount];

                for (int j = 0; j < lodInfo.partCount; j++)
                {
                    Console.WriteLine("    PART " + j);

                    ModelPart modelPart;

                    modelPart.b5        = fileBytes.NextU8();
                    modelPart.b6        = fileBytes.NextU8();
                    modelPart.b7        = fileBytes.NextU8();
                    modelPart.sixFloats = fileBytes.NextSubArray(24).AsFloats();

                    modelPart.sixFloats = modelPart.sixFloats.Select(fl => fl * float2).ToArray();

                    byte stackByte1 = fileBytes.NextU8();
                    byte stackByte2 = fileBytes.NextU8();
                    modelPart.materialCount = fileBytes.NextU8();

                    modelPart.pMaterials = new Material[modelPart.materialCount];

                    byte firstWordEverHadHighBitSet = 0;

                    for (int k = 0; k < modelPart.materialCount; k++)
                    {
                        Console.WriteLine("      MATERIAL " + k);

                        Material material = new Material();

                        material.unk4 = fileBytes.NextU32();
                        float unk2 = fileBytes.NextFloat();
                        float unk3 = fileBytes.NextFloat();
                        float unk4 = fileBytes.NextFloat();
                        material.vertCount = fileBytes.NextU16();
                        material.unksh18   = fileBytes.NextU16();
                        material.unksh16   = fileBytes.NextU16();
                        material.unksh20   = fileBytes.NextU16();
                        ushort shortsCount  = fileBytes.NextU16();
                        ushort commandCount = fileBytes.NextU16();

                        uint textureRef = material.unk4 & 0xFFF;
                        Console.WriteLine($"      {material.unk4:X8}");
                        if (textureRef != 0xFFF)
                        {
                            //Filesystem.Filesystem.File textureFile = filesystem.GetFile("UVTX", (int)textureRef);
                            // TODO: load texture
                            Console.WriteLine("      Textured!");
                        }

                        if ((int)(material.unk4 << 13) < 0)
                        {
                            //Console.WriteLine($"{twentyFourStruct.unk4:X8} {twentyFourStruct.unk4 << 13:X8}");

                            // TODO: lighting information?
                            // twentyFourStruct.unksh12 = response from light function
                            Console.WriteLine("      Lit!");
                        }
                        else
                        {
                            material.unk_someLightingThing = -1;
                        }

                        if ((material.unk4 & 0x08_000000) != 0)
                        {
                            firstWordEverHadHighBitSet = 1;
                        }

                        material.pVertices = fileBytes.NextSubArray(material.vertCount * 16).InGroupsOf(16).Select(d => new Vertex(d)).ToArray();


                        if (textureRef != 0xFFF)
                        {
                            foreach (var x in material.pVertices)
                            {
                                Console.WriteLine(x);
                            }
                        }

                        RSPCommand[] commands = UnpackTriangleCommands(fileBytes, shortsCount, commandCount);

                        material.pCommandsInRDRAM = commands;

                        modelPart.pMaterials[k] = material;
                    }

                    modelPart.unk1 = firstWordEverHadHighBitSet;

                    lodInfo.pModelParts[j] = modelPart;
                }

                pLODs[i] = lodInfo;
            }

            for (int m = 0; m < partsPerLOD; m++)
            {
                pMatrices[m] = new Matrix(fileBytes.NextSubArray(64).AsFloats());
            }

            if (fileBytes.Length != (int)Math.Ceiling(fileBytes.Position / 8f) * 8)
            {
                throw new Exception();
            }



            ////////////////////////////////

            using (ThreeDDisplayWindow window = new ThreeDDisplayWindow())
            {
                foreach (LOD lod in pLODs)
                {
                    bool hadTextured = false;
                    for (int i = 0; i < lod.partCount; i++)
                    {
                        ModelPart part = lod.pModelParts[i];
                        Matrix    m    = pMatrices[i];

                        foreach (Material material in part.pMaterials)
                        {
                            List <Vertex> verts      = MaterialToVertexData(material.pVertices, material.pCommandsInRDRAM, m);
                            uint          textureRef = material.unk4 & 0xFFF;
                            if (textureRef != 0xFFF)
                            {
                                Filesystem.Filesystem.File textureFile = filesystem.GetFile("UVTX", (int)textureRef) !;
                                Console.WriteLine($"{textureFile.formLocationInROM:x6}");
                                window.AddTexturedVertices(verts, new UVTX.UVTXFile(textureFile.Section("COMM")));
                                hadTextured = true;
                            }
                            else
                            {
                                window.AddVertices(verts);
                            }
                        }

                        //lodData.AddRange(part.pMaterials.SelectMany(material => MaterialToVertexData(material.pVertices, material.pCommandsInRDRAM, m)));
                    }

                    if (hadTextured)
                    {
                        window.Run();
                    }
                }
            }
        }