public static void newGeoLayout(BTBinFile Bin) { uint GeoAddress = Bin.ReadFourBytes(0x04); Bin.writeByteArray(GeoAddress, BTGeoLayout()); Bin.changeEndBinAddr(GeoAddress + 0x1C); }
public static int LoadCITexture(BTBinFile Binfile) { int id = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, id); uint TextureDataAddr = Binfile.getTextureDataAddr(); byte[] CITex; short[] NewTexture; if (currentPalette.Length <= 16) { CITex = Binfile.copyBytestoArray(TextureDataAddr + currentTexAddr, (uint)(Width * Height / 2));//4bpp NewTexture = CI4ToRGB5A1(CITex, currentPalette); } else { CITex = Binfile.copyBytestoArray(TextureDataAddr + currentTexAddr, (uint)(Width * Height));//8bpp NewTexture = CI8ToRGB5A1(CITex, currentPalette); } GL.TexImage2D ( TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb5A1, Width, Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedShort5551, NewTexture ); getTSFlags(); getSTDTextureFilters(); return(id); }
public static int LoadIA8Texture(BTBinFile Binfile) { int id = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, id); uint TextureDataAddr = Binfile.getTextureDataAddr(); byte[] TexData = Binfile.copyBytestoArray(TextureDataAddr + currentTexAddr, (uint)(Width * Height)); GL.TexImage2D ( TextureTarget.Texture2D, 0, PixelInternalFormat.Alpha, Width, Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Alpha, PixelType.UnsignedByte, TexData ); getTSFlags(); getSTDTextureFilters(); return(id); }
public static int LoadRGBA32Texture(BTBinFile Binfile) { int id = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, id); uint TexDataAddr = Binfile.getTextureDataAddr(); UInt32[] TexData = new UInt32[ShortstoLoad]; //actually FloatsToLoad but accounted for as Shorts for (uint i = 0; i < ShortstoLoad; i++) { TexData[i] = Binfile.ReadFourBytes(TexDataAddr + currentTexAddr + (i * 4)); } GL.TexImage2D ( TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, Width, Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedInt8888, TexData ); getTSFlags(); getSTDTextureFilters(); return(id); }
public static Vertex getVertex(UInt32 Addr, BTBinFile BTBin, uint AlphaBin) { Addr += BTBin.getVTXAddr(); Vertex NewVert = new Vertex ( (short)BTBin.ReadTwoBytes(Addr), (short)BTBin.ReadTwoBytes(Addr + 2), (short)BTBin.ReadTwoBytes(Addr + 4), (short)BTBin.ReadTwoBytes(Addr + 8), (short)BTBin.ReadTwoBytes(Addr + 10), BTBin.getByte(Addr + 12), BTBin.getByte(Addr + 13), BTBin.getByte(Addr + 14), BTBin.getByte(Addr + 15), Addr ); if (Textures.FirstTexLoad[AlphaBin]) { Array.Resize(ref CurrentVertexList, CurrentVertexList.Length + 1); CurrentVertexList[CurrentVertexList.Length - 1] = (UInt32)(Addr | (AlphaBin << 31)); uint[] test = CurrentVertexList; } return(NewVert); }
public static void ConvertBKtoBT(BTBinFile Bin) { F3DEXtoF3DEX2(Bin); TextureHeaderBK2BT(Bin); useCommonVertexHeader(Bin); newGeoLayout(Bin); updateCollision(Bin); }
public static void ConvertBTtoBK(BTBinFile Bin) { if (Bin.getTextureSetupAddr() == 0x38) { return; //Already BK Bin } //TODO }
public static void TextureHeaderBK2BT(BTBinFile Bin) { UInt16 SetupAddr = Bin.getTextureSetupAddr(); Bin.copyBytes(SetupAddr, 0x50, Bin.getEndBinAddr() - SetupAddr); //Shift bin file so TexSetup is at 0x50 Bin.WriteTwoBytes(0x08, 0x0050); UInt32 TriVertCount = Bin.ReadFourBytes(0x30); //Keep TriCount & VertCount for (int i = 0; i < 4; i++) { Bin.WriteEightBytes((uint)(SetupAddr - 8 + (i * 8)), 0); } //fill ext texture addr with 0 Bin.WriteFourBytes(0x44, TriVertCount); //Place the Tri/Vert counts back in SetupAddr = Bin.getTextureSetupAddr(); if (Bin.getByte((uint)SetupAddr + 0x06) == 01) { return; } //External texture flag UInt16 numTextures = Bin.ReadTwoBytes((uint)SetupAddr + 4); uint BKCommandBeginAddr = (uint)SetupAddr + 8; uint BTCommandBeginAddr = (uint)SetupAddr + 8; for (int i = 0; i < numTextures; i++) //convert 128bit commands into 64bit commands { Bin.copyBytes(BKCommandBeginAddr, BTCommandBeginAddr, 6); //TexAddr & Type Bin.copyBytes(BKCommandBeginAddr + 8, BTCommandBeginAddr + 6, 2); //XX and YY grid BTCommandBeginAddr += 0x08; BKCommandBeginAddr += 0x10; } Bin.copyBytes(BKCommandBeginAddr, BTCommandBeginAddr, (uint)(Bin.getEndBinAddr() - BKCommandBeginAddr)); //shift all data back Bin.changeEndBinAddr((uint)(Bin.getEndBinAddr() - (numTextures * 8))); //remove data at end after backshift int AddressesShift = (0x18 - (numTextures * 8)); UInt32 TexLoadBytes = (uint)(Bin.ReadFourBytes(0x50) - (numTextures * 8)); UInt32 NewGeoAddr = (uint)(Bin.ReadFourBytes(0x04) + AddressesShift);//declare new addresses after shift UInt32 NewF3DEX2Addr = (uint)(Bin.ReadFourBytes(0x0C) + AddressesShift); UInt32 NewVertAddr = (uint)(Bin.ReadFourBytes(0x10) + AddressesShift); UInt32 NewCollisionAddr = (uint)(Bin.ReadFourBytes(0x1C) + AddressesShift); Int32 NewFXSetupAddr = (int)Bin.ReadFourBytes(0x24); Int32 NewFXSetupEndAddr = (int)Bin.ReadFourBytes(0x20); if (NewFXSetupAddr != 0) { NewFXSetupAddr += AddressesShift; } if (NewFXSetupEndAddr != 0) { NewFXSetupEndAddr += AddressesShift; } Bin.WriteFourBytes(0x50, TexLoadBytes); Bin.WriteFourBytes(0x04, NewGeoAddr); Bin.WriteFourBytes(0x0C, NewF3DEX2Addr); Bin.WriteFourBytes(0x10, NewVertAddr); Bin.WriteFourBytes(0x1C, NewCollisionAddr); Bin.WriteFourBytes(0x20, (uint)NewFXSetupEndAddr); Bin.WriteFourBytes(0x24, (uint)NewFXSetupAddr); //Bin.changeByte(0x0B, 0x00); THIS IS A TYPE, 2 for mipmapping may be necessary. 04 for env mapping. So far all match between BK/BT }
public static short[] LoadRGBA16TextureData(int ShortsToLoad, BTBinFile Binfile) { uint TexDataAddr = Binfile.getTextureDataAddr(); short[] data = new short[ShortsToLoad]; for (uint i = 0; i < ShortsToLoad; i++) { data[i] = (short)Binfile.ReadTwoBytes(TexDataAddr + currentTexAddr + (uint)(i * 2)); } return(data); }
public static void LoadBIN(String BinDirectory) { using (FileStream fs = new FileStream(BinDirectory, FileMode.Open, FileAccess.Read)) { byte[] binFile = new byte[fs.Length]; fs.Read(binFile, 0, (int)fs.Length); BTBinFile NewBTBin = new BTBinFile(binFile); MainBin = NewBTBin; fs.Close(); } Textures.InitialiseTextures(MainBin, 0); }
public static void SetVertRGBA(BTBinFile BTBin, uint Addr, UInt32 colour, bool AlphaOnly) { byte alpha = (byte)(colour & 0xFF); if (AlphaOnly) { BTBin.changeByte(Addr + 15, alpha); } else { BTBin.WriteFourBytes(Addr + 12, colour); } }
public static void updateCollision(BTBinFile Bin) { //TODO uint CollisionAddr = Bin.getCollisionSetupAddr(); uint CollisionSize = Bin.getGeoAddr() - CollisionAddr; for (uint i = CollisionAddr; i < CollisionAddr + CollisionSize; i += 4) { if (Bin.getByte(i) == 0x88) { Bin.changeByte(i, 0x41); //Update common group header with one that allows HQ Shadow and ambient lighting } } }
public static byte[] BTVertexHeader(BTBinFile Bin) { uint VertexStartAddr = Bin.ReadFourBytes(0x10) + 0x18; UInt16 numVerts = ((UInt16)((Bin.ReadFourBytes(0x1C) - VertexStartAddr) / 0x10)); byte numVertsByte1; byte numVertsByte2; FromShortToByte(numVerts, out numVertsByte1, out numVertsByte2); byte[] geolayout = new byte[24]; geolayout[0] = 0xBC; geolayout[1] = 0x47; geolayout[2] = 0xED; geolayout[3] = 0xAE; geolayout[4] = 0xC1; geolayout[5] = 0x40; geolayout[6] = 0x3E; geolayout[7] = 0x01; geolayout[8] = 0x37; geolayout[9] = 0x58; geolayout[0x0a] = 0x3D; geolayout[0x0b] = 0x2A; geolayout[0x0c] = 0xFD; geolayout[0x0d] = 0x24; geolayout[0x0e] = 0x12; geolayout[0x0f] = 0x83; geolayout[0x10] = 0xFF; geolayout[0x11] = 0x35; geolayout[0x12] = 0xA0; geolayout[0x13] = 0xC0; geolayout[0x14] = 0xA0; geolayout[0x15] = 0xC0; geolayout[0x16] = numVertsByte1; geolayout[0x17] = numVertsByte2; return(geolayout); }
public static int LoadTexture(BTBinFile Bin) { uint CICount = (uint)currentPalette.Length; int NewTexture = 0; if (MODE == CIMODE) { NewTexture = LoadCITexture(Bin); } else if (MODE == RGBAMODE && BitSize == 16) { NewTexture = LoadRGBA16Texture(Bin); } else if (MODE == RGBAMODE && BitSize == 32) { NewTexture = LoadRGBA32Texture(Bin); } else if (MODE == IAMODE) { NewTexture = LoadIA8Texture(Bin); } return(NewTexture); }
public static int LoadRGBA16Texture(BTBinFile Binfile) { int id = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, id); uint TextureDataAddr = Binfile.getTextureDataAddr(); short[] TexData = LoadRGBA16TextureData(Width * Height, Binfile); GL.TexImage2D ( TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb5A1, Width, Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedShort5551, TexData ); getTSFlags(); getSTDTextureFilters(); return(id); }
public static void F3DEXtoF3DEX2(BTBinFile Bin) { uint CommandsLength = Bin.F3DCommandsLength(); UInt32 F3DSetupAddr = Bin.ReadFourBytes(0x0C); byte[][] DisplayList = new byte[CommandsLength][]; uint newCommandAddr = F3DSetupAddr + 0x08; //Copy DL into 2D Byte array with double loop for (int i = 0; i < CommandsLength; i++) { DisplayList[i] = new byte[8]; for (int j = 0; j < 8; j++) { DisplayList[i][j] = Bin.getByte((uint)(newCommandAddr + (i * 8) + j)); } } //change or convert commands byte MaxVertIndex = 0x00; bool firstVTX = true; int previousVTX = 0; for (int i = 0; i < DisplayList.Length; i++) { switch (DisplayList[i][0]) { case 0x01: DisplayList[i][0] = 0xDA; break; case 0x03: DisplayList[i][0] = 0xDC; break; case 0x04: DisplayList[i][0] = 0x01; Int16 numvert = (Int16)(DisplayList[i][2] / 4); DisplayList[i][1] = (byte)(numvert >> 4); DisplayList[i][2] = (byte)(numvert << 4); numvert = (short)(numvert * 2); DisplayList[i][3] = (byte)(numvert); //Fix Banjo's Backpack's overloaded 04 commands below, but it breaks conversions from original bins! /*if (firstVTX) { firstVTX = false; previousVTX = i; break; } * byte MaxVertNum = (byte)((MaxVertIndex / 2) + 1); * DisplayList[previousVTX][1] = (byte)(MaxVertNum >> 4); * DisplayList[previousVTX][2] = (byte)(MaxVertNum << 4); * DisplayList[previousVTX][3] = (byte)(MaxVertIndex+2); * MaxVertIndex = 0x00; * previousVTX = i;*/ break; case 0x06: DisplayList[i][0] = 0xDE; break; case 0xB1: DisplayList[i][0] = 0x06; MaxVertIndex = MaxVertexCheck(MaxVertIndex, DisplayList, i); break; case 0xB2: DisplayList[i][0] = 0x02; break; case 0xB3: DisplayList[i][0] = 0xF1; break; case 0xB4: DisplayList[i][0] = 0xE1; break; case 0xB5: DisplayList[i][0] = 0x07; MaxVertIndex = MaxVertexCheck(MaxVertIndex, DisplayList, i); break; case 0xB6: DisplayList[i][0] = 0xD9; if (DisplayList[i + 1][5] == 0x08 && DisplayList[i + 1][6] == 0x22 && DisplayList[i + 1][7] == 0x04) //VertRGBABackCull, i+1 for SETGEO { DisplayList[i][1] = 0xC0; DisplayList[i][2] = 0xFF; DisplayList[i][3] = 0xFB; } else if (DisplayList[i + 1][5] == 0x08 && DisplayList[i + 1][6] == 0x02 && DisplayList[i + 1][7] == 0x04) //VertRGBANoCull, i+1 for SETGEO { DisplayList[i][1] = 0xC0; DisplayList[i][2] = 0xF9; DisplayList[i][3] = 0xFB; } else { DisplayList[i][1] = 0xC0; DisplayList[i][2] = 0xF9; DisplayList[i][3] = 0xFB; } DisplayList[i][5] = 0x00; //NOP Clear for now DisplayList[i][6] = 0x00; DisplayList[i][7] = 0x00; break; case 0xB7: DisplayList[i][0] = 0xD9; DisplayList[i][1] = 0xFF; //NOP Set for now DisplayList[i][2] = 0xFF; DisplayList[i][3] = 0xFF; if (DisplayList[i][5] == 0x06) { DisplayList[i][5] = 0x26; } else { DisplayList[i][5] = 0x20; } DisplayList[i][5] = 0x20; //VertRGBA only for now (later env mapping flag) DisplayList[i][6] = 0x00; DisplayList[i][7] = 0x04; break; case 0xB9: DisplayList[i][0] = 0xE2; break; case 0xBA: DisplayList[i][0] = 0xE3; break; case 0xBB: DisplayList[i][0] = 0xD7; if (DisplayList[i][3] == 0x01) { DisplayList[i][3] = 0x02; } break; case 0xBC: DisplayList[i][0] = 0xDB; break; case 0xBD: DisplayList[i][0] = 0xD8; break; case 0xBF: DisplayList[i][0] = 0x05; DisplayList[i][1] = DisplayList[i][5]; DisplayList[i][2] = DisplayList[i][6]; DisplayList[i][3] = DisplayList[i][7]; for (int j = 5; j < 8; j++) { DisplayList[i][j] = 0x00; } MaxVertIndex = MaxVertexCheck(MaxVertIndex, DisplayList, i); break; case 0xF0: if (DisplayList[i][4] == 0x01) { DisplayList[i][4] = 0x06; } break; case 0xF5: if (DisplayList[i][4] == 0x01) { DisplayList[i][4] = 0x06; } break; case 0xB8: DisplayList[i][0] = 0xDF; if (i != DisplayList.Length - 1) { DisplayList[i][0] = 0x00; } break; } } //Load converted DL back into bin for (int i = 0; i < CommandsLength; i++) { for (int j = 0; j < 8; j++) { Bin.changeByte((uint)(newCommandAddr + (i * 8) + j), DisplayList[i][j]); } } }
public static void InitialiseTextures(BTBinFile Bin, int BinNum) { TextureArray[BinNum] = new uint[Bin.getTextureCount()]; FirstTexLoad[BinNum] = true; }
public static void useCommonVertexHeader(BTBinFile Bin) { UInt32 VertexSetupAddr = Bin.ReadFourBytes(0x10); Bin.writeByteArray(VertexSetupAddr, BTVertexHeader(Bin)); }
public static void ParseF3DEXDL(BTBinFile BinFile, uint BinNum, bool ColourBuffer) { UInt32 DLAddr = BinFile.getDLAddr(); uint CommandsLength = BinFile.F3DCommandsLength(); UInt32 F3DSetupAddr = BinFile.ReadFourBytes(0x0C); byte[][] DisplayList = new byte[CommandsLength][]; uint newCommandAddr = F3DSetupAddr + 0x08; uint AllVTXAddr = BinFile.getVTXAddr(); Vertex[] GVTXArray = new Vertex[32]; int TextureCount = BinFile.getTextureCount(); int CICount = 0; int TextureIndex = 0; Textures.ShortstoLoad = 0; Textures.TextureAddrArray[BinNum] = new uint[TextureCount + 1]; for (int i = 0; i < TextureCount; i++) { Textures.TextureAddrArray[BinNum][i] = BinFile.ReadFourBytes((uint)(BinFile.getTextureSetupAddr() + 8 + (i * 0x10))); //Load all texture addresses into array } if (TextureCount != 0) { Textures.TextureAddrArray[BinNum][TextureCount] = Textures.TextureAddrArray[BinNum][TextureCount - 1] + 0x500; //allow last item to always be greater than last addr } //Copy DL into 2D Byte array with double loop for (uint i = 0; i < CommandsLength; i++) { DisplayList[i] = new byte[8]; for (int j = 0; j < 8; j++) { DisplayList[i][j] = BinFile.getByte((uint)(newCommandAddr + (i * 8) + j)); } } GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); if (ColourBuffer || RenderEdges) { GL.Disable(EnableCap.Blend); } for (int i = 0; i < DisplayList.Length; i++) { byte[] CMD = DisplayList[i]; if (!ColourBuffer) { switch (DisplayList[i][0]) { case 0x01: break; case 0x03: //movemem if (RenderEdges) { break; } if (CMD[1] == 0x86) { float[] light0_diffuse = new float[4]; for (uint j = 0; j < 4; j++) { light0_diffuse[j] = (float)0xFF / 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]; for (uint j = 0; j < 4; j++) { light0_ambient[j] = (((float)0x3F / 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 = readSegmentAddr(CMD); short numVerts = (short)(CMD[2] / 0x04); int bufferIndex = CMD[1] / 0x02; for (int j = 0; j < numVerts; j++) { GVTXArray[bufferIndex + j] = Vertex.getVertex((uint)(VTXStart + (j * 0x10)), BinFile, (byte)BinNum); } Renderer.VertexCount += (uint)numVerts; break; case 0x06: break; case 0xB1: GL.Begin(BeginMode.Triangles); for (int j = 1; j < 8; j++) { if (j == 4) { j++; } int VertIndex = CMD[j] / 0x02; if (!EnvMapping) { GL.TexCoord2(GVTXArray[VertIndex].getUVVector()); } if (LightingEnabled) //Normals { Vector3 normals = new Vector3(GVTXArray[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(GVTXArray[VertIndex].getRGBAColor()); //RGBA } if (RenderEdges) { GL.Color4(0, 0, 0, 0xFF); } GL.Vertex3(GVTXArray[VertIndex].getCoordVector()); } if (!RenderEdges) { Renderer.TriCount++; } GL.End(); break; case 0xB2: break; case 0xB3: break; case 0xB4: break; case 0xB5: 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: 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) { 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 = 32f; Textures.S_Scale = 32f;//Revert mipmapping for now } break; case 0xBC: break; case 0xBD: break; case 0xBF: GL.Begin(BeginMode.Triangles); for (int j = 5; j < 8; j++) { int VertIndex = CMD[j] / 0x02; if (!EnvMapping) { GL.TexCoord2(GVTXArray[VertIndex].getUVVector()); } if (LightingEnabled) //Normals { Vector3 normals = new Vector3(GVTXArray[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(GVTXArray[VertIndex].getRGBAColor()); //RGBA } if (RenderEdges) { GL.Color4(0, 0, 0, 0xFF); } GL.Vertex3(GVTXArray[VertIndex].getCoordVector()); } if (!RenderEdges) { Renderer.TriCount++; } GL.End(); break; case 0xF0: CICount = (((CMD[5] << 4) + ((CMD[6] & 0xF0) >> 4)) >> 2) + 1; Textures.currentPalette = Textures.LoadRGBA16TextureData(CICount, BinFile); 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; //To avoid TMEM emulation, we will run a hybrid of 0xF3 and 0xF5 in this section to accurately interpret texture sizes case 0xF3: TextureIndex = 0; CICount = Textures.currentPalette.Length; for (int j = 0; j < TextureCount; j++) // Compare currentTexAddr to our texture address array { if (Textures.currentTexAddr >= Textures.TextureAddrArray[BinNum][j] && Textures.currentTexAddr < Textures.TextureAddrArray[BinNum][j + 1]) { TextureIndex = j; } } if (Textures.FirstTexLoad[BinNum]) { int TexLoadRange = ((CMD[6] & 0x0F) * 0x100 + CMD[7]); Textures.ShortstoLoad = (CMD[5]) * 0x10 + ((CMD[6] & 0xF0) >> 4) + 1; Textures.BytestoLoad = Textures.ShortstoLoad * 2; byte Mode = Textures.MODE; if (Mode == Textures.CIMODE && CICount == 16) { Textures.Width = TexLoadRange / 8; Textures.Height = (Textures.BytestoLoad * 2) / Textures.Width;//4bpp } else if (Mode == Textures.CIMODE && CICount == 256) { Textures.Width = TexLoadRange / 16; Textures.Height = (Textures.BytestoLoad) / Textures.Width;//8bpp } else if (Mode == Textures.RGBAMODE && Textures.BitSize == 16) { if (Textures.MipMapping) { Textures.ShortstoLoad -= 0x200; } Textures.Width = TexLoadRange / 8; Textures.Height = (Textures.ShortstoLoad) / Textures.Width;//16bpp } else if (Mode == Textures.IAMODE && Textures.BitSize == 16) { Textures.Width = TexLoadRange / 4; Textures.Height = (Textures.BytestoLoad) / Textures.Width;//16bpp } else if (Textures.MODE == Textures.RGBAMODE && Textures.BitSize == 32) { Textures.Width = TexLoadRange / 4; Textures.Height = (Textures.ShortstoLoad) / Textures.Width;//32bpp } else { return; } Textures.TextureArray[BinNum][TextureIndex] = (uint)Textures.LoadTexture(BinFile); } GL.BindTexture(TextureTarget.Texture2D, Textures.TextureArray[BinNum][TextureIndex]); break; case 0xF5: Textures.MODE = (byte)(CMD[1] >> 5); Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3))); Textures.TFlags = (CMD[5] >> 2) & 3; Textures.SFlags = CMD[6] & 3; int WidthBits = (((CMD[1] & 3) << 7) + CMD[2] >> 1) * 64; if (CMD[4] != 0 || !Textures.FirstTexLoad[BinNum]) { break; } int HeightPower = ((CMD[5] & 3) << 2) | (CMD[6] >> 6); int WidthPower = (CMD[7] >> 4); Textures.Width = (int)Math.Pow(2, WidthPower);//(int)Math.Pow(2, WidthPower); Textures.Height = (int)Math.Pow(2, HeightPower); GL.DeleteTexture(Textures.TextureArray[BinNum][TextureIndex]); if (Textures.MODE == Textures.CIMODE) { Textures.TextureArray[BinNum][TextureIndex] = (uint)Textures.LoadCITexture(BinFile); } else if (Textures.MODE == Textures.RGBAMODE && Textures.BitSize == 16) { Textures.TextureArray[BinNum][TextureIndex] = (uint)Textures.LoadRGBA16Texture(BinFile); } else if (Textures.MODE == Textures.RGBAMODE && Textures.BitSize == 32) { Textures.TextureArray[BinNum][TextureIndex] = (uint)Textures.LoadRGBA32Texture(BinFile); } else if (Textures.MODE == Textures.IAMODE) { Textures.TextureArray[BinNum][TextureIndex] = (uint)Textures.LoadIA8Texture(BinFile); } GL.BindTexture(TextureTarget.Texture2D, Textures.TextureArray[BinNum][TextureIndex]); break; case 0xFD: Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3))); Textures.MODE = (byte)(CMD[1] >> 5); Textures.currentTexAddr = readSegmentAddr(CMD); break; case 0xB8: Textures.T_Scale = 1; Textures.S_Scale = 1; break; } } else { switch (DisplayList[i][0]) { case 0x04: UInt32 VTXStart = readSegmentAddr(CMD); short numVerts = (short)(CMD[2] / 0x04); int bufferIndex = CMD[1] / 0x02; for (int j = 0; j < numVerts; j++) { GVTXArray[bufferIndex + j] = Vertex.getVertex((uint)(VTXStart + (j * 0x10)), BinFile, (byte)(BinNum)); } Renderer.VertexCount += (uint)numVerts; 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 0xB1: if (LightingEnabled) { break; //Disable painting on non-RGBA meshes } for (uint j = 0; j < 2; j++) { Vertex[] Triangle2 = new Vertex[3]; Color4[] colour2 = new Color4[3]; for (int k = 1; k < 4; k++) { int idx = (int)(k + (j * 4)); //bytes 1-3, and 5-8 int VertIndex = CMD[idx] / 0x02; Triangle2[k - 1] = GVTXArray[VertIndex]; UInt32 Addr = Triangle2[k - 1].getAddr(); colour2[k - 1] = new Color4((byte)((Addr >> 24) | (BinNum << 7)), (byte)((Addr >> 16) & 0xFF), (byte)((Addr >> 8) & 0xFF), (byte)(Addr & 0xFF)); //Addr to RGBA } RenderColourBufferQuads(Triangle2, colour2); //if(BinNum > 0)throw new Exception(((byte)(colour2[0].B)).ToString("x")); } 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] / 0x02; Triangle[j - 5] = GVTXArray[VertIndex]; UInt32 Addr = Triangle[j - 5].getAddr(); colour[j - 5] = new Color4((byte)((Addr >> 24) | (BinNum << 7)), (byte)((Addr >> 16) & 0xFF), (byte)((Addr >> 8) & 0xFF), (byte)(Addr & 0xFF)); //Addr to RGBA } RenderColourBufferQuads(Triangle, colour); break; case 0xB8: break; } } } Textures.FirstTexLoad[BinNum] = false; GL.Disable(EnableCap.Texture2D); }