public static void ExportDisplayList(BlastCorpsRom rom, BlastCorpsLevel level, string filename, float scale)
        {
            Model3D model = new Model3D(level);

            string mtlFileName = filename + ".mtl";

            using (System.IO.StreamWriter file = new System.IO.StreamWriter(filename))
            {
                int vertCount = 1;
                file.WriteLine(fileHeader());
                file.WriteLine("mtllib {0}", Path.GetFileName(mtlFileName));
                foreach (Triangle tri in model.triangles)
                {
                    float uScale = 32.0f * tri.texture.width;
                    float vScale = 32.0f * tri.texture.height;
                    file.WriteLine();
                    file.WriteLine("usemtl Texture{0:X4}", tri.texture.address);
                    file.WriteLine(toObjVert(tri.vertices[0], scale, uScale, vScale));
                    file.WriteLine(toObjVert(tri.vertices[1], scale, uScale, vScale));
                    file.WriteLine(toObjVert(tri.vertices[2], scale, uScale, vScale));
                    file.WriteLine("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", vertCount, (vertCount + 1), (vertCount + 2));
                    vertCount += 3;
                }
            }

            // create textures directory
            string textureDirName = "textures";
            string textureDir     = Path.Combine(Path.GetDirectoryName(filename), textureDirName);

            Directory.CreateDirectory(textureDir);
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(mtlFileName))
            {
                List <uint> processedTextures = new List <uint>();
                file.WriteLine(fileHeader());
                foreach (Texture t in model.textures)
                {
                    if (!processedTextures.Contains(t.address))
                    {
                        string textureFilename = String.Format("{0:X4}.png", t.address);
                        string textureFile     = String.Format(textureDirName + "/" + textureFilename);
                        file.WriteLine("newmtl Texture{0:X4}", t.address);
                        file.WriteLine("Ka 0.0 0.0 0.0"); // ambiant color
                        file.WriteLine("Kd 1.0 1.0 1.0"); // diffuse color
                        file.WriteLine("Ks 0.3 0.3 0.3"); // specular color
                        file.WriteLine("d 1");            // dissolved
                        file.WriteLine("map_Kd {0}", textureFile);
                        file.WriteLine();

                        BlastCorpsTexture bct = new BlastCorpsTexture(rom.GetRawData(), t.address, 0);
                        bct.decode();
                        byte[]    n64Texture = bct.GetInflated();
                        N64Format format     = N64Format.RGBA;
                        int       depth      = 16;

                        switch (bct.type)
                        {
                        case 0: // IA8?
                            // TODO: memcpy, no info
                            format = N64Format.IA;
                            depth  = 8;
                            break;

                        case 1: // RBGA16?
                            format = N64Format.RGBA;
                            depth  = 16;
                            break;

                        case 2: // RGBA32?
                            format = N64Format.RGBA;
                            depth  = 32;
                            break;

                        case 3: // IA8?
                            format = N64Format.IA;
                            depth  = 8;
                            break;

                        case 4: // IA16?
                            format = N64Format.IA;
                            depth  = 16;
                            break;

                        case 5: // RGBA32?
                            format = N64Format.RGBA;
                            depth  = 32;
                            break;

                        case 6: // IA8?
                            format = N64Format.IA;
                            depth  = 8;
                            break;
                        }

                        Bitmap loadedBitmap;
                        switch (format)
                        {
                        case N64Format.RGBA:
                            loadedBitmap = N64Graphics.RGBA(n64Texture, t.width, t.height, depth);
                            break;

                        case N64Format.IA:
                        default:
                            loadedBitmap = N64Graphics.IA(n64Texture, t.width, t.height, depth);
                            break;
                        }
                        loadedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
                        loadedBitmap.Save(Path.Combine(textureDir, textureFilename));

                        processedTextures.Add(t.address);
                    }
                }
            }
        }
        public static void ExportDisplayList(BlastCorpsRom rom, BlastCorpsLevel level, string filename, float scale)
        {
            Model3D model = new Model3D(level);

             string mtlFileName = filename + ".mtl";

             using (System.IO.StreamWriter file = new System.IO.StreamWriter(filename))
             {
            int vertCount = 1;
            file.WriteLine(fileHeader());
            file.WriteLine("mtllib {0}", Path.GetFileName(mtlFileName));
            foreach (Triangle tri in model.triangles)
            {
               float uScale = 32.0f * tri.texture.width;
               float vScale = 32.0f * tri.texture.height;
               file.WriteLine();
               file.WriteLine("usemtl Texture{0:X4}", tri.texture.address);
               file.WriteLine(toObjVert(tri.vertices[0], scale, uScale, vScale));
               file.WriteLine(toObjVert(tri.vertices[1], scale, uScale, vScale));
               file.WriteLine(toObjVert(tri.vertices[2], scale, uScale, vScale));
               file.WriteLine("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", vertCount, (vertCount + 1), (vertCount + 2));
               vertCount += 3;
            }
             }

             // create textures directory
             string textureDirName = "textures";
             string textureDir = Path.Combine(Path.GetDirectoryName(filename), textureDirName);
             Directory.CreateDirectory(textureDir);
             using (System.IO.StreamWriter file = new System.IO.StreamWriter(mtlFileName))
             {
            List<uint> processedTextures = new List<uint>();
            file.WriteLine(fileHeader());
            foreach (Texture t in model.textures)
            {
               if (!processedTextures.Contains(t.address))
               {
                  string textureFilename = String.Format("{0:X4}.png", t.address);
                  string textureFile = String.Format(textureDirName + "/" + textureFilename);
                  file.WriteLine("newmtl Texture{0:X4}", t.address);
                  file.WriteLine("Ka 0.0 0.0 0.0"); // ambiant color
                  file.WriteLine("Kd 1.0 1.0 1.0"); // diffuse color
                  file.WriteLine("Ks 0.3 0.3 0.3"); // specular color
                  file.WriteLine("d 1");            // dissolved
                  file.WriteLine("map_Kd {0}", textureFile);
                  file.WriteLine();

                  BlastCorpsTexture bct = new BlastCorpsTexture(rom.GetRawData(), t.address, 0);
                  bct.decode();
                  byte[] n64Texture = bct.GetInflated();
                  N64Format format = N64Format.RGBA;
                  int depth = 16;

                  switch (bct.type)
                  {
                     case 0: // IA8?
                        // TODO: memcpy, no info
                        format = N64Format.IA;
                        depth = 8;
                        break;
                     case 1: // RBGA16?
                        format = N64Format.RGBA;
                        depth = 16;
                        break;
                     case 2: // RGBA32?
                        format = N64Format.RGBA;
                        depth = 32;
                        break;
                     case 3: // IA8?
                        format = N64Format.IA;
                        depth = 8;
                        break;
                     case 4: // IA16?
                        format = N64Format.IA;
                        depth = 16;
                        break;
                     case 5: // RGBA32?
                        format = N64Format.RGBA;
                        depth = 32;
                        break;
                     case 6: // IA8?
                        format = N64Format.IA;
                        depth = 8;
                        break;
                  }

                  Bitmap loadedBitmap;
                  switch (format)
                  {
                     case N64Format.RGBA:
                        loadedBitmap = N64Graphics.RGBA(n64Texture, t.width, t.height, depth);
                        break;
                     case N64Format.IA:
                     default:
                        loadedBitmap = N64Graphics.IA(n64Texture, t.width, t.height, depth);
                        break;
                  }
                  loadedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
                  loadedBitmap.Save(Path.Combine(textureDir, textureFilename));

                  processedTextures.Add(t.address);
               }
            }
             }
        }
        private void LoadImage(uint index, int width, int height, N64Format format, int depth)
        {
            BlastCorpsTexture texture = new BlastCorpsTexture(rom.GetRawData(), index, (uint)numericLut.Value);

            texture.decode();
            byte[] n64Texture = texture.GetInflated();
            textBoxOffset.Text = texture.offset.ToString("X");
            textBoxLength.Text = texture.length.ToString("X");
            textBoxType.Text   = texture.type.ToString();
            loadedBitmap       = null;
            if (n64Texture == null || n64Texture.Length == 0)
            {
                textBoxUncompressed.Text = "null";
            }
            else
            {
                textBoxUncompressed.Text = n64Texture.Length.ToString("X");
                if (width == 0)
                {
                    GuessDims(texture.type, n64Texture.Length, ref width, ref height, ref format, ref depth);
                    numericHeight.Value = height;
                    numericWidth.Value  = width;
                    switch (format)
                    {
                    case N64Format.RGBA:
                        comboBoxFormat.SelectedIndex = (depth == 32) ? 1 : 0;
                        break;

                    case N64Format.IA:
                        switch (depth)
                        {
                        case 16: comboBoxFormat.SelectedIndex = 2; break;

                        case 8: comboBoxFormat.SelectedIndex = 3; break;

                        case 4: comboBoxFormat.SelectedIndex = 4; break;

                        case 1: comboBoxFormat.SelectedIndex = 5; break;
                        }
                        break;
                    }
                }
                switch (format)
                {
                case N64Format.RGBA:
                    loadedBitmap = N64Graphics.RGBA(n64Texture, width, height, depth);
                    break;

                case N64Format.IA:
                    loadedBitmap = N64Graphics.IA(n64Texture, width, height, depth);
                    break;
                }

                if (loadedBitmap != null)
                {
                    loadedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
                }
            }
            pictureBoxTexture.Image = loadedBitmap;
            pictureBoxActual.Image  = loadedBitmap;
            buttonExport.Enabled    = (loadedBitmap != null);
            numericLut.Enabled      = (texture.type == 4 || texture.type == 5);
        }
        private void LoadImage(uint index, int width, int height, N64Format format, int depth)
        {
            BlastCorpsTexture texture = new BlastCorpsTexture(rom.GetRawData(), index, (uint)numericLut.Value);
             texture.decode();
             byte[] n64Texture = texture.GetInflated();
             textBoxOffset.Text = texture.offset.ToString("X");
             textBoxLength.Text = texture.length.ToString("X");
             textBoxType.Text = texture.type.ToString();
             loadedBitmap = null;
             if (n64Texture == null || n64Texture.Length == 0)
             {
            textBoxUncompressed.Text = "null";
             }
             else
             {
            textBoxUncompressed.Text = n64Texture.Length.ToString("X");
            if (width == 0)
            {
               GuessDims(texture.type, n64Texture.Length, ref width, ref height, ref format, ref depth);
               numericHeight.Value = height;
               numericWidth.Value = width;
               switch (format)
               {
                  case N64Format.RGBA:
                     comboBoxFormat.SelectedIndex = (depth == 32) ? 1 : 0;
                     break;
                  case N64Format.IA:
                     switch (depth)
                     {
                        case 16: comboBoxFormat.SelectedIndex = 2; break;
                        case 8: comboBoxFormat.SelectedIndex = 3; break;
                        case 4: comboBoxFormat.SelectedIndex = 4; break;
                        case 1: comboBoxFormat.SelectedIndex = 5; break;
                     }
                     break;
               }
            }
            switch (format)
            {
               case N64Format.RGBA:
                  loadedBitmap = N64Graphics.RGBA(n64Texture, width, height, depth);
                  break;
               case N64Format.IA:
                  loadedBitmap = N64Graphics.IA(n64Texture, width, height, depth);
                  break;
            }

            if (loadedBitmap != null)
            {
               loadedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
            }
             }
             pictureBoxTexture.Image = loadedBitmap;
             pictureBoxActual.Image = loadedBitmap;
             buttonExport.Enabled = (loadedBitmap != null);
             numericLut.Enabled = (texture.type == 4 || texture.type == 5);
        }