Пример #1
0
 public static void ParseF3DDL(ROM SM64ROM, uint SegOffset, bool ColourBuffer)
 {
     F3D.DecodeF3DCommands(SM64ROM, SegOffset, ColourBuffer);
     GL.Disable(EnableCap.Texture2D);
     CICount        = 0;
     TextureIndex   = 0;
     ColourCombiner = false;
 }
Пример #2
0
    public static void DecodeGeoLayout(ROM SM64ROM, uint offset, bool ColourBuffer)
    {
        for (uint i = offset; i < SM64ROM.getEndROMAddr();)
        {
            if (SM64ROM.getByte(i) > 0x20)
            {
                return;
            }
            uint segaddr;
            switch (SM64ROM.getByte(i))
            {
            case 0:
                increment = 8;
                break;

            case 1:;
                return;

            case 2:
                JumpAddr = SM64ROM.readSegmentAddr(SM64ROM.ReadFourBytes(i + 4));
                GeoLayouts.DecodeGeoLayout(SM64ROM, JumpAddr, ColourBuffer);
                if (SM64ROM.getByte(i + 1) == 0)
                {
                    return;
                }
                increment = 8;
                break;

            case 3:
                return;

            case 4:
                //open node
                increment = 4;
                break;

            case 5:
                //close node
                increment = 4;
                break;

            case 8:
                increment = 12;
                break;

            case 9:
                increment = 4;
                break;

            case 0x0A:
                if (SM64ROM.getByte(i + 1) > 0)
                {
                    increment = 12;
                }
                else
                {
                    increment = 8;
                }
                break;

            case 0x0B:
                increment = 4;
                break;

            case 0x0C:
                increment = 4;
                break;

            case 0x0D:
                increment = 8;
                break;

            case 0x0E:
                increment = 8;
                break;

            case 0x0F:
                increment = 0x14;
                break;

            case 0x10:
                //rotate
                increment = 16;
                break;

            case 0x13:
                //Load DL with rotation
                increment = 12;
                if (SM64ROM.getByte(i + 8) == 0)
                {
                    break;
                }
                drawlayer = SM64ROM.getByte(i + 1);
                if (drawlayer > (4 - Convert.ToInt32(LevelScripts.IsRomManager)) && !GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                if (drawlayer <= (4 - Convert.ToInt32(LevelScripts.IsRomManager)) && GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                segaddr = SM64ROM.ReadFourBytes(i + 8);
                DecideBufferAndAddr(SM64ROM.getByte(i + 1), segaddr, ColourBuffer);
                if (F3D.Culling)
                {
                    F3D.GeoMode |= 0x022000;                  //Generate geomode for vector lighting and backface culling
                }
                else
                {
                    F3D.GeoMode |= 0x020000;      //If culling is off, only generate vector lighting
                }
                F3D.ParseF3DDL(SM64ROM, segaddr, ColourBuffer);
                break;

            case 0x14:
                //billboard
                increment = 8;
                break;

            case 0x15:
                //Load DL
                increment = 8;
                segaddr   = SM64ROM.ReadFourBytes(i + 4);
                if (ModelsList.Contains(segaddr))
                {
                    break;
                }
                drawlayer = SM64ROM.getByte(i + 1);
                if (drawlayer >= (4 - Convert.ToInt32(LevelScripts.IsRomManager)))
                {
                    ExtAlphaDLPointer = i;
                }
                if (drawlayer > (4 - Convert.ToInt32(LevelScripts.IsRomManager)) && !GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                if (drawlayer <= (4 - Convert.ToInt32(LevelScripts.IsRomManager)) && GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                DecideBufferAndAddr(SM64ROM.ReadEightBytes(i), segaddr, ColourBuffer);
                if (F3D.Culling)
                {
                    F3D.GeoMode |= 0x022000;                 //Generate geomode for vector lighting and backface culling
                }
                else
                {
                    F3D.GeoMode |= 0x020000;      //If culling is off, only generate vector lighting
                }
                F3D.ParseF3DDL(SM64ROM, segaddr, ColourBuffer);
                Array.Resize(ref ModelsList, ModelsList.Length + 1);
                ModelsList[ModelsList.Length - 1] = segaddr;
                if (!Textures.FirstTexLoad)
                {
                    break;
                }
                Array.Resize(ref ExtDLPointers[drawlayer], ExtDLPointers[drawlayer].Length + 1); //Increase size by one to add
                ExtDLPointers[drawlayer][ExtDLPointers[drawlayer].Length - 1] = i;               //set last index to addr
                break;

            case 0x16:
                increment = 8;
                break;

            case 0x17:
                increment = 4;
                break;

            case 0x18:
                increment = 8;
                break;

            case 0x19:
                increment = 8;
                break;

            case 0x1A:
                increment = 8;
                break;

            case 0x1D:
                //scale, can be 12 length in rare occurence
                increment = 8;
                break;

            case 0x1E:
                increment = 8;
                break;

            case 0x1F:
                increment = 16;
                break;

            case 0x20:
                increment = 4;
                break;
            }
            if (Textures.FirstTexLoad && ROMManager.debug) // Debug TXT
            {
                Array.Resize(ref LevelScripts.DebugScript, LevelScripts.DebugScript.Length + 1);
                LevelScripts.DebugScript[LevelScripts.DebugScript.Length - 1] = i.ToString("x") + ": ";
                for (uint j = i; j < i + increment; j++)
                {
                    LevelScripts.DebugScript[LevelScripts.DebugScript.Length - 1] += SM64ROM.getByte(j).ToString("x") + " ";
                }
            }
            i += increment;
        }
    }
Пример #3
0
    public static void DecodeGeoLayout(ROM SM64ROM, uint offset, bool ColourBuffer)
    {
        for (uint i = offset; i < SM64ROM.getEndROMAddr();)
        {
            if (SM64ROM.getByte(i) > 0x20)
            {
                return;
            }
            uint segaddr;
            switch (SM64ROM.getByte(i))
            {
            case 0:
                increment = 8;
                break;

            case 1:;
                return;

            case 2:
                JumpAddr = SM64ROM.readSegmentAddr(SM64ROM.ReadFourBytes(i + 4));
                GeoLayouts.DecodeGeoLayout(SM64ROM, JumpAddr, ColourBuffer);
                if (SM64ROM.getByte(i + 1) == 0)
                {
                    return;
                }
                increment = 8;
                break;

            case 3:
                return;

            case 4:
                //open node
                increment = 4;
                break;

            case 5:
                //close node
                increment = 4;
                break;

            case 8:
                increment = 12;
                break;

            case 9:
                increment = 4;
                break;

            case 0x0A:
                if (SM64ROM.getByte(i + 1) > 0)
                {
                    increment = 12;
                }
                else
                {
                    increment = 8;
                }
                break;

            case 0x0B:
                increment = 4;
                break;

            case 0x0C:
                increment = 4;
                break;

            case 0x0D:
                increment = 8;
                break;

            case 0x0E:
                increment = 8;
                break;

            case 0x0F:
                increment = 0x14;
                break;

            case 0x10:
                //rotate
                increment = 16;
                break;

            case 0x13:
                //Load DL with rotation
                increment = 12;
                if (SM64ROM.getByte(i + 8) == 0)
                {
                    break;
                }
                drawlayer = SM64ROM.getByte(i + 1);
                if (drawlayer > 4 && !GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                if (drawlayer <= 4 && GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                segaddr = SM64ROM.ReadFourBytes(i + 8);
                DecideBufferAndAddr(SM64ROM.getByte(i + 1), segaddr, ColourBuffer);
                F3D.ParseF3DDL(SM64ROM, segaddr, ColourBuffer);
                break;

            case 0x14:
                //billboard
                increment = 8;
                break;

            case 0x15:
                //Load DL
                increment = 8;
                drawlayer = SM64ROM.getByte(i + 1);
                if (drawlayer >= 4)
                {
                    ExtAlphaDLPointer = i;
                }
                if (drawlayer > 4 && !GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                if (drawlayer <= 4 && GeoLayouts.OpaqueRendered)
                {
                    break;
                }
                segaddr = SM64ROM.ReadFourBytes(i + 4);
                DecideBufferAndAddr(SM64ROM.ReadEightBytes(i), segaddr, ColourBuffer);
                F3D.ParseF3DDL(SM64ROM, segaddr, ColourBuffer);
                if (!Textures.FirstTexLoad)
                {
                    break;
                }
                Array.Resize(ref ExtDLPointers[drawlayer], ExtDLPointers[drawlayer].Length + 1); //Increase size by one to add
                ExtDLPointers[drawlayer][ExtDLPointers[drawlayer].Length - 1] = i;               //set last index to addr
                break;

            case 0x16:
                increment = 8;
                break;

            case 0x17:
                increment = 4;
                break;

            case 0x18:
                increment = 8;
                break;

            case 0x19:
                increment = 8;
                break;

            case 0x1A:
                increment = 8;
                break;

            case 0x1D:
                //scale, can be 12 length in rare occurence
                increment = 8;
                break;

            case 0x1E:
                increment = 8;
                break;

            case 0x1F:
                increment = 16;
                break;

            case 0x20:
                increment = 4;
                break;
            }

            /*if(Textures.FirstTexLoad)using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"e:\test4.txt", true)) //Debug Txt
             * {
             *  file.Write(i.ToString("x") + ": ");
             *  for (uint j = i; j < i + increment; j++)
             *  {
             *      file.Write(SM64ROM.getByte(j).ToString("x") + " ");
             *  }
             *  file.WriteLine("\n");
             *  file.Close();
             * }*/
            i += increment;
        }
    }
Пример #4
0
    private static void DecodeF3DCommands(ROM SM64ROM, uint SegOffset, bool ColourBuffer)
    {
        uint Offset   = SM64ROM.readSegmentAddr(SegOffset);
        uint CMDCount = 0;

        for (uint i = Offset; i < SM64ROM.getEndROMAddr(); i += 8)
        {
            if (SM64ROM.getByte(i) == 0xB8)
            {
                CMDCount = ((i - Offset) / 8) + 1;//Plus one command for B8
                break;
            }
        }
        byte[][] DisplayList = new byte[CMDCount][];
        //Copy DL into 2D Byte array with double loop
        for (uint i = 0; i < CMDCount; i++)
        {
            DisplayList[i] = new byte[8];
            for (uint j = 0; j < 8; j++)
            {
                DisplayList[i][j] = SM64ROM.getByte(Offset + (i * 8) + j);
            }
        }

        for (int i = 0; i < SM64ROM.getEndROMAddr(); i++)
        {
            byte[] CMD = DisplayList[i];

            /*if (Textures.FirstTexLoad) //Debug Txt
             * {
             *  using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"e:\test4.txt", true))
             *  {
             *      for (uint j = 0; j < 8; j++)
             *      {
             *          file.Write(CMD[j].ToString("x") + " ");
             *      }
             *      file.WriteLine("\n");
             *      file.Close();
             *  }
             * } */
            if (!ColourBuffer)
            {
                switch (DisplayList[i][0])
                {
                case 0x01:
                    break;

                case 0x03:
                    if (RenderEdges)
                    {
                        break;
                    }
                    EnableShading();
                    LightingEnabled = true;
                    if (CMD[1] == 0x86)
                    {
                        float[] light0_diffuse = new float[4];
                        uint    rgbaAddr       = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                        for (uint j = 0; j < 4; j++)
                        {
                            light0_diffuse[j] = (float)SM64ROM.getByte(rgbaAddr + j) / 255f;
                        }
                        GL.Light(LightName.Light0, LightParameter.Diffuse, light0_diffuse);
                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse);
                    }
                    else if (CMD[1] == 0x88)
                    {
                        float[] light0_ambient = new float[4];
                        uint    rgbaAddr       = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                        for (uint j = 0; j < 4; j++)
                        {
                            light0_ambient[j] = (((float)SM64ROM.getByte(rgbaAddr + j) / 255f) - 0.2f) * 1.25f;
                        }
                        GL.Light(LightName.Light0, LightParameter.Ambient, light0_ambient);
                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Ambient);
                    }
                    GL.Enable(EnableCap.ColorMaterial);
                    break;

                case 0x04:
                    UInt32 VTXStart    = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    short  numVerts    = (short)((CMD[1] >> 4) + 1);
                    int    bufferIndex = CMD[1] & 0x0F;
                    for (int j = 0; j < numVerts; j++)
                    {
                        VTXBuffer[bufferIndex + j] = Vertex.getVertex(VTXStart + (uint)(j * 0x10), SM64ROM);
                    }
                    Renderer.VertexCount += (uint)numVerts;
                    break;

                case 0x06:
                    F3D.DecodeF3DCommands(SM64ROM, returnSegmentAddr(CMD), ColourBuffer);
                    break;

                case 0xB1:
                    /*GL.Begin(BeginMode.Triangles); //0xB1 is not used in F3D v1.0
                     * for (int j = 1; j < 8; j++)
                     * {
                     *  if (j == 4) j++;
                     *  int VertIndex = CMD[j] / 2;
                     *  GL.TexCoord2(VTXBuffer[VertIndex].getUVVector());
                     *  GL.Color4(VTXBuffer[VertIndex].getRGBAColor());
                     *  GL.Vertex3(VTXBuffer[VertIndex].getCoordVector());
                     * }
                     * Renderer.TriCount += 2;
                     * GL.End();*/
                    break;

                case 0xB2:
                    break;

                case 0xB3:
                    break;

                case 0xB4:
                    break;

                case 0xB5:
                    break;

                case 0xB6:
                case 0xB7:
                    if (RenderEdges)
                    {
                        break;
                    }
                    if (CMD[6] >> 4 == 2)
                    {
                        GL.Disable(EnableCap.CullFace);
                    }
                    else if (CMD[6] >> 4 == 0)
                    {
                        GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Back);
                    }
                    else if (CMD[6] >> 4 == 1)
                    {
                        GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Front);
                    }
                    if ((CMD[5] & 0x0F) == 2)
                    {
                        GL.Disable(EnableCap.Lighting); LightingEnabled = false;
                    }
                    else
                    {
                        EnableShading(); LightingEnabled = true;
                    }
                    break;

                case 0xB9:
                    break;

                case 0xBA:
                    break;

                case 0xBB:
                    Textures.S_Scale *= 0x10000 / (float)(CMD[4] * 0x100 + CMD[5]); //0x10000/
                    Textures.T_Scale *= 0x10000 / (float)(CMD[6] * 0x100 + CMD[7]);
                    if (CMD[3] == 0x01 && Renderer.TextureEnabler && !RenderEdges)
                    {
                        GL.Enable(EnableCap.Texture2D);
                    }
                    else
                    {
                        GL.Disable(EnableCap.Texture2D);
                        Textures.T_Scale = 1f; Textures.S_Scale = 1f;
                    }
                    if (DisplayList[i][2] == 0x12)
                    {
                        Textures.MipMapping = true;
                        Textures.T_Scale    = 1f; Textures.S_Scale = 1f;//Revert mipmapping for now
                    }
                    break;

                case 0xBC:
                    break;

                case 0xBD:
                    break;

                case 0xBF: //TRI1
                    if (LightingEnabled && !Renderer.ViewNonRGBA)
                    {
                        break;
                    }
                    GL.Begin(BeginMode.Triangles);
                    for (int j = 5; j < 8; j++)
                    {
                        int VertIndex = CMD[j] / 0x0A;
                        if (!EnvMapping)
                        {
                            GL.TexCoord2(VTXBuffer[VertIndex].getUVVector());
                        }

                        if (LightingEnabled)
                        {
                            GL.Normal3(VTXBuffer[VertIndex].getRGBColor());                  //Normals
                        }
                        else
                        {
                            GL.Color4(VTXBuffer[VertIndex].getRGBAColor());  //RGBA
                        }
                        if (RenderEdges)
                        {
                            GL.Color4(0, 0, 0, 0xFF);
                        }
                        GL.Vertex3(VTXBuffer[VertIndex].getCoordVector());
                    }
                    if (!RenderEdges)
                    {
                        Renderer.TriCount++;
                    }
                    GL.End();
                    break;

                case 0xF0:
                    if (!Textures.FirstTexLoad)
                    {
                        break;
                    }
                    CICount = (uint)((((CMD[5] << 4) + ((CMD[6] & 0xF0) >> 4)) >> 2) + 1);
                    Textures.currentPalette = Textures.LoadRGBA16TextureData(CICount, SM64ROM);
                    break;

                case 0xF2:
                    Textures.S_Scale = ((CMD[5]) * 0x10 + ((CMD[6] & 0xF0) >> 4)) / 124f; //124 = 0x7C = scale 1.0
                    Textures.T_Scale = ((CMD[6] & 0x0F) * 0x100 + CMD[7]) / 124f;         //0x7C
                    break;

                case 0xF3:
                    if (SM64ROM.getSegmentStart(0x0E) < 0x1200000)
                    {
                        TextureLoadRoutine(SM64ROM, 0);
                    }
                    break;

                case 0xF5:
                    Textures.MODE    = (byte)(CMD[1] >> 5);
                    Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3)));
                    Textures.TFlags  = (uint)(CMD[5] >> 2) & 3;
                    Textures.SFlags  = (uint)CMD[6] & 3;
                    int WidthBits = (((CMD[1] & 3) << 7) + CMD[2] >> 1) * 64;
                    if (CMD[4] != 0)
                    {
                        break;              //If RenderTile, continue
                    }
                    int HeightPower = ((CMD[5] & 3) << 2) | (CMD[6] >> 6);
                    int WidthPower  = (CMD[7] >> 4);
                    Textures.Width  = (uint)Math.Pow(2, WidthPower);
                    Textures.Height = (uint)Math.Pow(2, HeightPower);
                    if (Textures.currentTexAddr == 0)
                    {
                        break;
                    }
                    TextureLoadRoutine(SM64ROM, Offset + (uint)(i * 8));
                    break;

                case 0xFB:
                    if (RenderEdges)
                    {
                        break;
                    }
                    ColourCombiner = true;
                    GL.Color4((float)CMD[4] / 255f, (float)CMD[5] / 255f, (float)CMD[6] / 255f, (float)CMD[7] / 255f);
                    break;

                case 0xFD:
                    Textures.currentSegment = CMD[4];
                    Textures.currentTexAddr = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    if (!Textures.FirstTexLoad)
                    {
                        break;
                    }
                    Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3)));
                    Textures.MODE    = (byte)(CMD[1] >> 5);
                    break;

                case 0xB8:
                    return;
                }
            }
            else
            {
                switch (DisplayList[i][0])  //Vertex Selection Colour buffer here
                {
                case 0x03:
                    LightingEnabled = true;
                    break;

                case 0x04:
                    UInt32 VTXStart    = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    short  numVerts    = (short)((CMD[1] >> 4) + 1);
                    int    bufferIndex = CMD[1] & 0x0F;
                    for (int j = 0; j < numVerts; j++)
                    {
                        VTXBuffer[bufferIndex + j] = Vertex.getVertex(VTXStart + (uint)(j * 0x10), SM64ROM);
                    }
                    Renderer.VertexCount += (uint)numVerts;
                    break;

                case 0x06:
                    F3D.DecodeF3DCommands(SM64ROM, returnSegmentAddr(CMD), ColourBuffer);
                    break;

                case 0xB6:
                case 0xB7:
                    if (CMD[6] >> 4 == 2)
                    {
                        GL.Disable(EnableCap.CullFace);
                    }
                    else if (CMD[6] >> 4 == 0)
                    {
                        GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Back);
                    }
                    else if (CMD[6] >> 4 == 1)
                    {
                        GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Front);
                    }
                    if ((CMD[5] & 0x0F) == 2)
                    {
                        LightingEnabled = false;
                    }
                    else
                    {
                        LightingEnabled = true;
                    }
                    break;

                case 0xBF:
                    if (LightingEnabled)
                    {
                        break;
                    }
                    Vertex[] Triangle = new Vertex[3];
                    Color4[] colour   = new Color4[3];
                    for (int j = 5; j < 8; j++)
                    {
                        int VertIndex = CMD[j] / 0x0A;
                        Triangle[j - 5] = VTXBuffer[VertIndex];
                        UInt32 Addr = Triangle[j - 5].getAddr();
                        colour[j - 5] = new Color4((byte)(Addr >> 24), (byte)((Addr >> 16) & 0xFF), (byte)((Addr >> 8) & 0xFF), (byte)(Addr & 0xFF));   //Addr to RGBA
                    }
                    Vector3 CentreCoord = new Vector3
                                          (
                        (Triangle[0].getCoordVector().X + Triangle[1].getCoordVector().X + Triangle[2].getCoordVector().X) / 3,
                        (Triangle[0].getCoordVector().Y + Triangle[1].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 3,
                        (Triangle[0].getCoordVector().Z + Triangle[1].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 3
                                          );
                    Vector3 OneTwoAVG = new Vector3
                                        (
                        (Triangle[0].getCoordVector().X + Triangle[1].getCoordVector().X) / 2,
                        (Triangle[0].getCoordVector().Y + Triangle[1].getCoordVector().Y) / 2,
                        (Triangle[0].getCoordVector().Z + Triangle[1].getCoordVector().Z) / 2
                                        );
                    Vector3 TwoThreeAVG = new Vector3
                                          (
                        (Triangle[1].getCoordVector().X + Triangle[2].getCoordVector().X) / 2,
                        (Triangle[1].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 2,
                        (Triangle[1].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 2
                                          );
                    Vector3 OneThreeAVG = new Vector3
                                          (
                        (Triangle[0].getCoordVector().X + Triangle[2].getCoordVector().X) / 2,
                        (Triangle[0].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 2,
                        (Triangle[0].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 2
                                          );

                    GL.Begin(BeginMode.Quads);
                    GL.Color4(colour[0]);     //Vert 1 quad
                    GL.Vertex3(Triangle[0].getCoordVector());
                    GL.Vertex3(OneTwoAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(OneThreeAVG);

                    GL.Color4(colour[1]);     //Vert 2 quad
                    GL.Vertex3(Triangle[1].getCoordVector());
                    GL.Vertex3(TwoThreeAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(OneTwoAVG);

                    GL.Color4(colour[2]);     //Vert 3 quad
                    GL.Vertex3(Triangle[2].getCoordVector());
                    GL.Vertex3(OneThreeAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(TwoThreeAVG);
                    GL.End();
                    break;

                case 0xB8:
                    return;
                }
            }
        }
    }
Пример #5
0
    private static void DecodeF3DCommands(ROM SM64ROM, uint SegOffset, bool ColourBuffer)
    {
        uint Offset   = SM64ROM.readSegmentAddr(SegOffset);
        uint CMDCount = 0;

        for (uint i = Offset; i < SM64ROM.getEndROMAddr(); i += 8)
        {
            if (SM64ROM.getByte(i) == 0xB8)
            {
                CMDCount = ((i - Offset) / 8) + 1;//Plus one command for B8
                break;
            }
        }
        byte[][] DisplayList = new byte[CMDCount][];
        //Copy DL into 2D Byte array with double loop
        for (uint i = 0; i < CMDCount; i++)
        {
            DisplayList[i] = new byte[8];
            for (uint j = 0; j < 8; j++)
            {
                DisplayList[i][j] = SM64ROM.getByte(Offset + (i * 8) + j);
            }
        }

        for (uint i = 0; i < SM64ROM.getEndROMAddr(); i++)
        {
            byte[] CMD = DisplayList[i];
            if (Textures.FirstTexLoad && ROMManager.debug) //Debug Txt
            {
                Array.Resize(ref DebugText, DebugText.Length + 1);
                DebugText[DebugText.Length - 1] = (Offset + (i * 8)).ToString("x") + ": "; //Addr:
                for (uint j = 0; j < 8; j++)
                {
                    DebugText[DebugText.Length - 1] += CMD[j].ToString("x") + " "; //F3D CMD bytes in hex
                }
            }
            if (!ColourBuffer)
            {
                switch (DisplayList[i][0])
                {
                case 0x01: //G_MTX
                    break;

                case 0x03: //movemem
                    if (RenderEdges)
                    {
                        break;
                    }
                    if (CMD[1] == 0x86)
                    {
                        float[] light0_diffuse = new float[4];
                        uint    rgbaAddr       = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                        for (uint j = 0; j < 4; j++)
                        {
                            light0_diffuse[j] = (float)SM64ROM.getByte(rgbaAddr + j) / 255f;
                        }
                        GL.Light(LightName.Light0, LightParameter.Diffuse, light0_diffuse);
                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse);
                    }
                    else if (CMD[1] == 0x88)
                    {
                        float[] light0_ambient = new float[4];
                        uint    rgbaAddr       = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                        for (uint j = 0; j < 4; j++)
                        {
                            light0_ambient[j] = (((float)SM64ROM.getByte(rgbaAddr + j) / 255f) - 0.2f) * 1.25f;
                        }
                        GL.Light(LightName.Light0, LightParameter.Ambient, light0_ambient);
                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Ambient);
                    }
                    GL.Enable(EnableCap.ColorMaterial);
                    break;

                case 0x04: //G_VTX
                    UInt32 VTXStart    = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    short  numVerts    = (short)((CMD[1] >> 4) + 1);
                    int    bufferIndex = CMD[1] & 0x0F;
                    for (int j = 0; j < numVerts; j++)
                    {
                        VTXBuffer[bufferIndex + j] = Vertex.getVertex(VTXStart + (uint)(j * 0x10), SM64ROM);
                    }
                    Renderer.VertexCount += (uint)numVerts;
                    break;

                case 0x06: //LoadDL (jump)
                    F3D.DecodeF3DCommands(SM64ROM, returnSegmentAddr(CMD), ColourBuffer);
                    if (CMD[1] == 1)
                    {
                        return;
                    }
                    break;

                case 0xB1:
                    //0xB1 (TRI2) is not used in F3D v1.0
                    break;

                case 0xB2: // Unused in F3D v1.0
                    break;

                case 0xB3: //G_RDP_Half2
                    break;

                case 0xB4: //G_RDP_Half1
                    break;

                case 0xB5: //G_Quad (Unused in F3D v1.0)
                    break;

                case 0xB6: //ClearGeoMode
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 ClearBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode &= ~ClearBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xB7: //SetGeoMode
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 SetBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode |= SetBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xB9: //SetOtherMode
                    break;

                case 0xBA: //SetOtherMode
                    break;

                case 0xBB: //G_Texture
                    Vertex.U_Scale = Convert.ToSingle((CMD[4] << 8) | CMD[5]) / Convert.ToSingle(0xFFFF);
                    Vertex.V_Scale = Convert.ToSingle((CMD[6] << 8) | CMD[7]) / Convert.ToSingle(0xFFFF);
                    if (CMD[3] == 0x01 && Renderer.TextureEnabler && !RenderEdges)
                    {
                        GL.Enable(EnableCap.Texture2D);
                    }
                    else
                    {
                        GL.Disable(EnableCap.Texture2D);
                        Textures.T_Scale = 1f; Textures.S_Scale = 1f;
                    }
                    if (DisplayList[i][2] == 0x12)
                    {
                        Textures.MipMapping = true;
                        Textures.T_Scale    = 1f; Textures.S_Scale = 1f;//Revert mipmapping for now
                    }
                    break;

                case 0xBC: //moveword
                    break;

                case 0xBD: //PopMTX
                    break;

                case 0xBF: //TRI1
                    if (LightingEnabled && !Renderer.ViewNonRGBA)
                    {
                        break;
                    }
                    GL.Begin(BeginMode.Triangles);
                    for (int j = 5; j < 8; j++)
                    {
                        int VertIndex = CMD[j] / 0x0A;
                        if (!EnvMapping)
                        {
                            GL.TexCoord2(VTXBuffer[VertIndex].getUVVector());
                        }

                        if (LightingEnabled)     //Normals
                        {
                            Vector3 normals = new Vector3(VTXBuffer[VertIndex].getRGBColor());
                            if (!EnvMapping)
                            {
                                GL.Normal3(Vector3.Normalize(normals));
                            }
                            else
                            {
                                Vector4 normals4 = new Vector4(normals, 1f);
                                normals4 = Vector4.Normalize(Renderer.projection * normals4);
                                Vector3 newnorms = new Vector3(normals4.X, normals4.Y, normals4.Z);
                                GL.Normal3(newnorms);
                            }
                        }


                        else
                        {
                            GL.Color4(VTXBuffer[VertIndex].getRGBAColor());  //RGBA
                        }
                        if (RenderEdges)
                        {
                            GL.Color4(0, 0, 0, 0xFF);
                        }
                        GL.Vertex3(VTXBuffer[VertIndex].getCoordVector());
                    }
                    if (!RenderEdges)
                    {
                        Renderer.TriCount++;
                    }
                    GL.End();
                    break;

                case 0xF0: //LoadTLUT
                    if (!Textures.FirstTexLoad)
                    {
                        break;
                    }
                    CICount = (uint)((((CMD[5] << 4) + ((CMD[6] & 0xF0) >> 4)) >> 2) + 1);
                    Textures.currentPalette = Textures.LoadRGBA16TextureData(CICount, SM64ROM);
                    break;

                case 0xF2: //Settilesize
                    Textures.S_Scale = Convert.ToSingle((((CMD[5] << 4) | ((CMD[6] & 0xF0) >> 4)) >> 2) + 1);
                    Textures.T_Scale = Convert.ToSingle(((((CMD[6] & 0x0F) << 8) | CMD[7]) >> 2) + 1);
                    break;

                case 0xF3: //LoadBlock
                    if (SM64ROM.getSegmentStart(0x0E) < 0x1200000 && !Renderer.ObjectView)
                    {
                        TextureLoadRoutine(SM64ROM, 0);
                    }
                    break;

                case 0xF5: //Settile
                    Textures.MODE    = (byte)(CMD[1] >> 5);
                    Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3)));
                    Textures.TFlags  = (uint)(CMD[5] >> 2) & 3;
                    Textures.SFlags  = (uint)CMD[6] & 3;
                    int WidthBits = (((CMD[1] & 3) << 7) + CMD[2] >> 1) * 64;
                    if (CMD[4] != 0)
                    {
                        break;              //If RenderTile, continue
                    }
                    int HeightPower = ((CMD[5] & 3) << 2) | (CMD[6] >> 6);
                    int WidthPower  = (CMD[7] >> 4);
                    Textures.Width  = (uint)Math.Pow(2, WidthPower);
                    Textures.Height = (uint)Math.Pow(2, HeightPower);
                    if (Textures.currentTexAddr == 0)
                    {
                        break;
                    }
                    TextureLoadRoutine(SM64ROM, Offset + (uint)(i * 8));
                    break;

                case 0xFB: //Set Env Colour
                    if (RenderEdges)
                    {
                        break;
                    }
                    ColourCombiner = true;
                    GL.Color4((float)CMD[4] / 255f, (float)CMD[5] / 255f, (float)CMD[6] / 255f, (float)CMD[7] / 255f);
                    break;

                case 0xFC: //Setcombine
                    if (CMD[7] == 0x3C && CMD[6] == 0x79 && CMD[5] == 0xFE)
                    {
                        GL.Disable(EnableCap.Texture2D);
                    }
                    else if (Renderer.TextureEnabler)
                    {
                        GL.Enable(EnableCap.Texture2D);
                    }
                    break;

                case 0xFD: //SetTIMG
                    Textures.currentSegment = CMD[4];
                    Textures.currentTexAddr = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    if (!Textures.FirstTexLoad)
                    {
                        break;
                    }
                    Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3)));
                    Textures.MODE    = (byte)(CMD[1] >> 5);
                    break;

                case 0xB8: //End DL
                    return;
                }
            }
            else
            {
                switch (DisplayList[i][0])  //Vertex Selection Colour buffer here
                {
                case 0x03:
                    break;

                case 0x04:
                    UInt32 VTXStart    = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    short  numVerts    = (short)((CMD[1] >> 4) + 1);
                    int    bufferIndex = CMD[1] & 0x0F;
                    for (int j = 0; j < numVerts; j++)
                    {
                        VTXBuffer[bufferIndex + j] = Vertex.getVertex(VTXStart + (uint)(j * 0x10), SM64ROM);
                    }
                    Renderer.VertexCount += (uint)numVerts;
                    break;

                case 0x06:
                    F3D.DecodeF3DCommands(SM64ROM, returnSegmentAddr(CMD), ColourBuffer);
                    if (CMD[1] == 1)
                    {
                        return;
                    }
                    break;

                case 0xB6:
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 ClearBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode &= ~ClearBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xB7:
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 SetBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode |= SetBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xBF:
                    if (LightingEnabled)
                    {
                        break;                      //Disable painting on non-RGBA meshes
                    }
                    Vertex[] Triangle = new Vertex[3];
                    Color4[] colour   = new Color4[3];
                    for (int j = 5; j < 8; j++)
                    {
                        int VertIndex = CMD[j] / 0x0A;
                        Triangle[j - 5] = VTXBuffer[VertIndex];
                        UInt32 Addr = Triangle[j - 5].getAddr();
                        colour[j - 5] = new Color4((byte)(Addr >> 24), (byte)((Addr >> 16) & 0xFF), (byte)((Addr >> 8) & 0xFF), (byte)(Addr & 0xFF));   //Addr to RGBA
                    }
                    Vector3 CentreCoord = new Vector3
                                          (
                        (Triangle[0].getCoordVector().X + Triangle[1].getCoordVector().X + Triangle[2].getCoordVector().X) / 3,
                        (Triangle[0].getCoordVector().Y + Triangle[1].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 3,
                        (Triangle[0].getCoordVector().Z + Triangle[1].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 3
                                          );
                    Vector3 OneTwoAVG = new Vector3
                                        (
                        (Triangle[0].getCoordVector().X + Triangle[1].getCoordVector().X) / 2,
                        (Triangle[0].getCoordVector().Y + Triangle[1].getCoordVector().Y) / 2,
                        (Triangle[0].getCoordVector().Z + Triangle[1].getCoordVector().Z) / 2
                                        );
                    Vector3 TwoThreeAVG = new Vector3
                                          (
                        (Triangle[1].getCoordVector().X + Triangle[2].getCoordVector().X) / 2,
                        (Triangle[1].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 2,
                        (Triangle[1].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 2
                                          );
                    Vector3 OneThreeAVG = new Vector3
                                          (
                        (Triangle[0].getCoordVector().X + Triangle[2].getCoordVector().X) / 2,
                        (Triangle[0].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 2,
                        (Triangle[0].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 2
                                          );

                    GL.Begin(BeginMode.Quads);
                    GL.Color4(colour[0]);     //Vert 1 quad
                    GL.Vertex3(Triangle[0].getCoordVector());
                    GL.Vertex3(OneTwoAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(OneThreeAVG);

                    GL.Color4(colour[1]);     //Vert 2 quad
                    GL.Vertex3(Triangle[1].getCoordVector());
                    GL.Vertex3(TwoThreeAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(OneTwoAVG);

                    GL.Color4(colour[2]);     //Vert 3 quad
                    GL.Vertex3(Triangle[2].getCoordVector());
                    GL.Vertex3(OneThreeAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(TwoThreeAVG);
                    GL.End();
                    break;

                case 0xB8:
                    return;
                }
            }
        }
    }