/// <summary> /// Determines if this is a SVR texture. /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">Length of the data (in bytes).</param> /// <returns>True if this is a SVR texture, false otherwise.</returns> public static bool Is(byte[] source, int offset, int length) { // GBIX and PVRT if (length >= 0x20 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("GBIX")) && PTMethods.Contains(source, offset + 0x10, Encoding.UTF8.GetBytes("PVRT")) && source[offset + 0x19] >= 0x60 && source[offset + 0x19] < 0x70) { // Some SVR files have an extra byte at the end for seemingly no reason. UInt32 expected_length = BitConverter.ToUInt32(source, offset + 0x14); if (expected_length == length - 24 || expected_length == length - 24 - 1) { return(true); } } // PVRT (and no GBIX chunk) else if (length >= 0x10 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("PVRT")) && source[offset + 0x09] >= 0x60 && source[offset + 0x09] < 0x70) { // Some SVR files have an extra byte at the end for seemingly no reason. UInt32 expected_length = BitConverter.ToUInt32(source, offset + 0x04); if (expected_length == length - 8 || expected_length == length - 8 - 1) { return(true); } } return(false); }
/// <summary> /// Determines if this is a GVR texture. /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">Length of the data (in bytes).</param> /// <returns>True if this is a GVR texture, false otherwise.</returns> public static bool Is(byte[] source, int offset, int length) { // GBIX and GVRT if (length >= 32 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("GBIX")) && PTMethods.Contains(source, offset + 0x10, Encoding.UTF8.GetBytes("GVRT")) && BitConverter.ToUInt32(source, offset + 0x14) == length - 24) { return(true); } // GCIX and GVRT else if (length >= 32 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("GCIX")) && PTMethods.Contains(source, offset + 0x10, Encoding.UTF8.GetBytes("GVRT")) && BitConverter.ToUInt32(source, offset + 0x14) == length - 24) { return(true); } // GVRT (and no GBIX or GCIX chunk) else if (length > 16 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("GVRT")) && BitConverter.ToUInt32(source, offset + 0x04) == length - 8) { return(true); } return(false); }
/// <summary> /// Determines if this is a PVP palette. /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">Length of the data (in bytes).</param> /// <returns>True if this is a PVP palette, false otherwise.</returns> public static bool Is(byte[] source, int offset, int length) { if (length >= 16 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("PVPL")) && BitConverter.ToUInt32(source, offset + 0x04) == length - 8) { return(true); } return(false); }
/// <summary> /// Checks for and validates GBIX headers as well as PVRT. /// <para>See also: <seealso cref="IsValidPvrt"/></para> /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">The expected length of the data minus the preceding header sizes.</param> /// <returns>True if the header is GBIX and it passes validation, false otherwise.</returns> private static bool IsValidGbix(byte[] source, int offset, int length) { if (!PTMethods.Contains(source, offset, gbixFourCC)) { return(false); } // Immediately after the "GBIX" part of the GBIX header, there is // an offset indicating where the PVRT header begins relative to 0x08. int pvrtOffset = PTMethods.ToInt32(source, offset + 0x04, true) + 8; return(IsValidPvrt(source, offset + pvrtOffset, length - pvrtOffset)); }
/// <summary> /// Checks for and validates GBIX headers as well as PVRT. /// <para>See also: <seealso cref="IsValidPvrt"/></para> /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">The expected length of the data minus the preceding header sizes.</param> /// <returns>True if the header is GBIX and it passes validation, false otherwise.</returns> private static bool IsValidGbix(byte[] source, int offset, uint length) { if (!PTMethods.Contains(source, offset + 0x00, gbixFourCC)) { return(false); } // Immediately after the "GBIX" part of the GBIX header, there is // an offset indicating where the PVRT header begins relative to 0x08. var dataOffset = offset + BitConverter.ToInt32(source, offset + 0x04) + (gbixSizeInBytes - gbixFourCC.Length); return(IsValidPvrt(source, dataOffset, length - (uint)(dataOffset - offset))); }
/// <summary> /// Determines if this is a PVR texture. /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">Length of the data (in bytes).</param> /// <returns>True if this is a PVR texture, false otherwise.</returns> public static bool Is(byte[] source, int offset, int length) { // GBIX and PVRT //if (length >= 0x20 && // PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("GBIX")) && // PTMethods.Contains(source, offset + 0x10, Encoding.UTF8.GetBytes("PVRT")) && // source[offset + 0x19] < 0x60 && // BitConverter.ToUInt32(source, offset + 0x14) == length - 24) if (length >= 0x20 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("GBIX")) && PTMethods.Contains(source, offset + 0x10, Encoding.UTF8.GetBytes("PVRT"))) { return(true); } // PVRT (and no GBIX chunk) else if (length >= 0x10 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("PVRT")) && source[offset + 0x09] < 0x60 && BitConverter.ToUInt32(source, offset + 0x04) == length - 8) { return(true); } // GBIX and PVRT with RLE compression else if (length >= 0x24 && PTMethods.Contains(source, offset + 0x04, Encoding.UTF8.GetBytes("GBIX")) && PTMethods.Contains(source, offset + 0x14, Encoding.UTF8.GetBytes("PVRT")) && source[offset + 0x1D] < 0x60 && BitConverter.ToUInt32(source, offset + 0x18) == BitConverter.ToUInt32(source, offset + 0x00) - 24) { return(true); } // PVRT (and no GBIX chunk) with RLE compression else if (length >= 0x14 && PTMethods.Contains(source, offset + 0x04, Encoding.UTF8.GetBytes("PVRT")) && source[offset + 0x0D] < 0x60 && BitConverter.ToUInt32(source, offset + 0x08) == BitConverter.ToUInt32(source, offset + 0x00) - 8) { return(true); } return(false); }
/// <summary> /// Checks for the PVRT header and validates it. /// <para>See also: <seealso cref="IsValidGbix"/></para> /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">The expected length of the PVR data minus the preceding header sizes.</param> /// <returns>True if the header is PVRT and it passes validation, false otherwise.</returns> private static bool IsValidPvrt(byte[] source, int offset, uint length) { if (!PTMethods.Contains(source, offset + 0x00, pvrtFourCC)) { return(false); } if (source[offset + 0x09] >= 0x60) { return(false); } if (BitConverter.ToUInt32(source, offset + 0x04) != length - 8) { return(false); } return(true); }
/// <summary> /// Determines if this is a SVR texture. /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">Length of the data (in bytes).</param> /// <returns>True if this is a SVR texture, false otherwise.</returns> public static bool Is(byte[] source, int offset, int length) { // GBIX and PVRT if (length >= 0x20 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("GBIX")) && PTMethods.Contains(source, offset + 0x10, Encoding.UTF8.GetBytes("PVRT")) && source[offset + 0x19] >= 0x60 && source[offset + 0x19] < 0x70 && BitConverter.ToUInt32(source, offset + 0x14) == length - 24) { return(true); } // PVRT (and no GBIX chunk) else if (length >= 0x10 && PTMethods.Contains(source, offset + 0x00, Encoding.UTF8.GetBytes("PVRT")) && source[offset + 0x19] >= 0x60 && source[offset + 0x19] < 0x70 && BitConverter.ToUInt32(source, offset + 0x04) == length - 8) { return(true); } return(false); }
protected override void Initalize() { // Check to see if what we are dealing with is a PVR texture if (!Is(encodedData)) { throw new NotAValidTextureException("This is not a valid PVR texture."); } // Determine the offsets of the GBIX (if present) and PVRT header chunks. if (PTMethods.Contains(encodedData, 0x00, Encoding.UTF8.GetBytes("GBIX"))) { gbixOffset = 0x00; pvrtOffset = 0x10; } else if (PTMethods.Contains(encodedData, 0x04, Encoding.UTF8.GetBytes("GBIX"))) { gbixOffset = 0x04; pvrtOffset = 0x14; } else if (PTMethods.Contains(encodedData, 0x04, Encoding.UTF8.GetBytes("PVRT"))) { gbixOffset = -1; pvrtOffset = 0x04; } else { gbixOffset = -1; pvrtOffset = 0x00; } // Read the global index (if it is present). If it is not present, just set it to 0. if (gbixOffset != -1) { globalIndex = BitConverter.ToUInt32(encodedData, gbixOffset + 0x08); } else { globalIndex = 0; } // Read information about the texture textureWidth = BitConverter.ToUInt16(encodedData, pvrtOffset + 0x0C); textureHeight = BitConverter.ToUInt16(encodedData, pvrtOffset + 0x0E); pixelFormat = (PvrPixelFormat)encodedData[pvrtOffset + 0x08]; dataFormat = (PvrDataFormat)encodedData[pvrtOffset + 0x09]; // Get the codecs and make sure we can decode using them pixelCodec = PvrPixelCodec.GetPixelCodec(pixelFormat); dataCodec = PvrDataCodec.GetDataCodec(dataFormat); if (dataCodec != null && pixelCodec != null) { dataCodec.PixelCodec = pixelCodec; canDecode = true; } // Set the palette and data offsets if (!canDecode || dataCodec.PaletteEntries == 0 || dataCodec.NeedsExternalPalette) { paletteOffset = -1; dataOffset = pvrtOffset + 0x10; } else { paletteOffset = pvrtOffset + 0x10; dataOffset = paletteOffset + (dataCodec.PaletteEntries * (pixelCodec.Bpp >> 3)); } // Get the compression format and determine if we need to decompress this texture compressionFormat = GetCompressionFormat(encodedData, pvrtOffset, dataOffset); compressionCodec = PvrCompressionCodec.GetCompressionCodec(compressionFormat); if (compressionFormat != PvrCompressionFormat.None && compressionCodec != null) { encodedData = compressionCodec.Decompress(encodedData, dataOffset, pixelCodec, dataCodec); // Now place the offsets in the appropiate area if (compressionFormat == PvrCompressionFormat.Rle) { if (gbixOffset != -1) { gbixOffset -= 4; } pvrtOffset -= 4; if (paletteOffset != -1) { paletteOffset -= 4; } dataOffset -= 4; } } // If the texture contains mipmaps, gets the offsets of them if (canDecode && dataCodec.HasMipmaps) { mipmapOffsets = new int[(int)Math.Log(textureWidth, 2) + 1]; int mipmapOffset = 0; // Calculate the padding for the first mipmap offset if (dataFormat == PvrDataFormat.SquareTwiddledMipmaps) { // A 1x1 mipmap takes up as much space as a 2x1 mipmap mipmapOffset = (dataCodec.Bpp) >> 3; } if (dataFormat == PvrDataFormat.SquareTwiddledMipmapsAlt) { // A 1x1 mipmap takes up as much space as a 2x2 mipmap mipmapOffset = (3 * dataCodec.Bpp) >> 3; } for (int i = mipmapOffsets.Length - 1, size = 1; i >= 0; i--, size <<= 1) { mipmapOffsets[i] = mipmapOffset; mipmapOffset += Math.Max((size * size * dataCodec.Bpp) >> 3, 1); } } initalized = true; }
/// <summary> /// Checks for the PVRT header and validates it. /// <para>See also: <seealso cref="IsValidGbix"/></para> /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">The expected length of the PVR data minus the preceding header sizes.</param> /// <returns>True if the header is PVRT and it passes validation, false otherwise.</returns> private static bool IsValidPvrt(byte[] source, int offset, int length) { return(PTMethods.Contains(source, offset, pvrtFourCC) && source[offset + 0x09] < 0x60 && PTMethods.ToUInt32(source, offset + 0x04, true) == length - 8); }
protected override void Initalize() { // Check to see if what we are dealing with is a GVR texture if (!Is(encodedData)) { throw new NotAValidTextureException("This is not a valid GVR texture."); } // Determine the offsets of the GBIX/GCIX (if present) and GCIX header chunks. if (PTMethods.Contains(encodedData, 0, Encoding.UTF8.GetBytes("GBIX")) || PTMethods.Contains(encodedData, 0, Encoding.UTF8.GetBytes("GCIX"))) { gbixOffset = 0x00; pvrtOffset = 0x10; } else { gbixOffset = -1; pvrtOffset = 0x00; } // Read the global index (if it is present). If it is not present, just set it to 0. if (gbixOffset != -1) { globalIndex = PTMethods.ToUInt32BE(encodedData, gbixOffset + 0x08); } else { globalIndex = 0; } // Read information about the texture textureWidth = PTMethods.ToUInt16BE(encodedData, pvrtOffset + 0x0C); textureHeight = PTMethods.ToUInt16BE(encodedData, pvrtOffset + 0x0E); pixelFormat = (GvrPixelFormat)(encodedData[pvrtOffset + 0x0A] >> 4); // Only the first 4 bits matter dataFlags = (GvrDataFlags)(encodedData[pvrtOffset + 0x0A] & 0x0F); // Only the last 4 bits matter dataFormat = (GvrDataFormat)encodedData[pvrtOffset + 0x0B]; // Get the codecs and make sure we can decode using them dataCodec = GvrDataCodec.GetDataCodec(dataFormat); // We need a pixel codec if this is a palettized texture if (dataCodec != null && dataCodec.PaletteEntries != 0) { pixelCodec = GvrPixelCodec.GetPixelCodec(pixelFormat); if (pixelCodec != null) { dataCodec.PixelCodec = pixelCodec; canDecode = true; } } else { pixelFormat = GvrPixelFormat.Unknown; if (dataCodec != null) { canDecode = true; } } // Set the palette and data offsets paletteEntries = dataCodec.PaletteEntries; if (!canDecode || paletteEntries == 0 || (paletteEntries != 0 && (dataFlags & GvrDataFlags.ExternalPalette) != 0)) { paletteOffset = -1; dataOffset = pvrtOffset + 0x10; } else { paletteOffset = pvrtOffset + 0x10; dataOffset = paletteOffset + (paletteEntries * (pixelCodec.Bpp >> 3)); } // If the texture contains mipmaps, gets the offsets of them if (canDecode && paletteEntries == 0 && (dataFlags & GvrDataFlags.Mipmaps) != 0) { mipmapOffsets = new int[(int)Math.Log(textureWidth, 2) + 1]; int mipmapOffset = 0; for (int i = 0, size = textureWidth; i < mipmapOffsets.Length; i++, size >>= 1) { mipmapOffsets[i] = mipmapOffset; mipmapOffset += Math.Max(size * size * (dataCodec.Bpp >> 3), 32); } } initalized = true; }
protected override void Initalize() { // Check to see if what we are dealing with is a SVR texture if (!Is(encodedData)) { throw new NotAValidTextureException("This is not a valid GVR texture."); } // Determine the offsets of the GBIX (if present) and PVRT header chunks. if (PTMethods.Contains(encodedData, 0, Encoding.UTF8.GetBytes("GBIX"))) { gbixOffset = 0x00; pvrtOffset = 0x10; } else { gbixOffset = -1; pvrtOffset = 0x00; } // Read the global index (if it is present). If it is not present, just set it to 0. if (gbixOffset != -1) { globalIndex = BitConverter.ToUInt32(encodedData, gbixOffset + 0x08); } else { globalIndex = 0; } // Read information about the texture textureWidth = BitConverter.ToUInt16(encodedData, pvrtOffset + 0x0C); textureHeight = BitConverter.ToUInt16(encodedData, pvrtOffset + 0x0E); pixelFormat = (SvrPixelFormat)encodedData[pvrtOffset + 0x08]; dataFormat = (SvrDataFormat)encodedData[pvrtOffset + 0x09]; // Get the codecs and make sure we can decode using them pixelCodec = SvrPixelCodec.GetPixelCodec(pixelFormat); dataCodec = SvrDataCodec.GetDataCodec(dataFormat); if (dataCodec != null && pixelCodec != null) { dataCodec.PixelCodec = pixelCodec; canDecode = true; } // Set the palette and data offsets paletteEntries = dataCodec.PaletteEntries; if (!canDecode || paletteEntries == 0 || dataCodec.NeedsExternalPalette) { paletteOffset = -1; dataOffset = pvrtOffset + 0x10; } else { paletteOffset = pvrtOffset + 0x10; dataOffset = paletteOffset + (paletteEntries * (pixelCodec.Bpp >> 3)); } initalized = true; }
/// <summary> /// Checks for the XVRT header and validates it. /// </summary> /// <param name="source">Byte array containing the data.</param> /// <param name="offset">The offset in the byte array to start at.</param> /// <param name="length">The expected length of the PVR data minus the preceding header sizes.</param> /// <returns>True if the header is XVRT and it passes validation, false otherwise.</returns> private static bool IsValidXvrt(byte[] source, int offset, int length) { return(PTMethods.Contains(source, offset, xvrtFourCC) && BitConverter.ToUInt32(source, offset + 0x04) == length - 8); }