private static string DataFormatToString(PvrDataFormat format) { switch (format) { case PvrDataFormat.SquareTwiddled: return("Square Twiddled"); case PvrDataFormat.SquareTwiddledMipmaps: return("Square Twiddled with Mipmaps"); case PvrDataFormat.Vq: return("VQ"); case PvrDataFormat.VqMipmaps: return("VQ with Mipmaps"); case PvrDataFormat.Index4: return("4-bit Indexed with External Palette"); case PvrDataFormat.Index8: return("8-bit Indexed with External Palette"); case PvrDataFormat.Rectangle: return("Rectangle"); case PvrDataFormat.RectangleTwiddled: return("Rectangle Twiddled"); case PvrDataFormat.SmallVq: return("Small VQ"); case PvrDataFormat.SmallVqMipmaps: return("Small VQ with Mipmaps"); case PvrDataFormat.SquareTwiddledMipmapsAlt: return("Square Twiddled with Mipmaps (Alternate)"); } return("Unknown"); }
/// <summary> /// Opens a texture to encode from a file. /// </summary> /// <param name="file">Filename of the file that contains the texture data.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(string file, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) : base(file) { if (decodedBitmap != null) { initalized = Initalize(pixelFormat, dataFormat); } }
public static PvrDataCodec GetDataCodec(PvrDataFormat format) { switch (format) { case PvrDataFormat.SquareTwiddled: return new SquareTwiddled(); case PvrDataFormat.SquareTwiddledMipmaps: case PvrDataFormat.SquareTwiddledMipmapsAlt: return new SquareTwiddledMipmaps(); case PvrDataFormat.Vq: return new Vq(); case PvrDataFormat.VqMipmaps: return new VqMipmaps(); case PvrDataFormat.Index4: return new Index4(); case PvrDataFormat.Index8: return new Index8(); case PvrDataFormat.Rectangle: return new Rectangle(); case PvrDataFormat.RectangleTwiddled: return new RectangleTwiddled(); case PvrDataFormat.SmallVq: return new SmallVq(); case PvrDataFormat.SmallVqMipmaps: return new SmallVqMipmaps(); } return null; }
/// <summary> /// Open a bitmap from a byte array. /// </summary> /// <param name="array">Byte array that contains the bitmap data.</param> /// <param name="PixelFormat">Pixel Format</param> /// <param name="DataFormat">Data Format</param> public PvrTextureEncoder(byte[] array, PvrPixelFormat PixelFormat, PvrDataFormat DataFormat) : base(array) { this.PixelFormat = (byte)PixelFormat; this.DataFormat = (byte)DataFormat; InitSuccess = Initalize(); }
/// <summary> /// Open a bitmap from a stream. /// </summary> /// <param name="stream">Stream that contains the bitmap data.</param> /// <param name="PixelFormat">Pixel Format</param> /// <param name="DataFormat">Data Format</param> public PvrTextureEncoder(Stream stream, PvrPixelFormat PixelFormat, PvrDataFormat DataFormat) : base(stream) { this.PixelFormat = (byte)PixelFormat; this.DataFormat = (byte)DataFormat; InitSuccess = Initalize(); }
PvrCompressionFormat CompressionFormat; // Compression Format #endregion Fields #region Constructors /// <summary> /// Open a bitmap from a file. /// </summary> /// <param name="file">Filename of the file that contains the bitmap data.</param> /// <param name="PixelFormat">Pixel Format</param> /// <param name="DataFormat">Data Format</param> public PvrTextureEncoder(string file, PvrPixelFormat PixelFormat, PvrDataFormat DataFormat) : base(file) { this.PixelFormat = (byte)PixelFormat; this.DataFormat = (byte)DataFormat; InitSuccess = Initalize(); }
/// <summary> /// Open a bitmap from a System.Drawing.Bitmap. /// </summary> /// <param name="bitmap">A System.Drawing.Bitmap instance.</param> /// <param name="PixelFormat">Pixel Format</param> /// <param name="DataFormat">Data Format</param> public PvrTextureEncoder(Bitmap bitmap, PvrPixelFormat PixelFormat, PvrDataFormat DataFormat) : base(bitmap) { this.PixelFormat = (byte)PixelFormat; this.DataFormat = (byte)DataFormat; InitSuccess = Initalize(); }
/// <summary> /// Opens a texture to encode from a byte array. /// </summary> /// <param name="source">Byte array that contains the texture data.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(byte[] source, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) : base(source) { if (decodedBitmap != null) { initalized = Initalize(pixelFormat, dataFormat); } }
/// <summary> /// Opens a texture to encode from a bitmap. /// </summary> /// <param name="source">Bitmap to encode.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(Bitmap source, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat, uint globalIndex, PvrCompressionFormat compression) : base(source) { if (decodedBitmap != null) { initalized = Initalize(pixelFormat, dataFormat, globalIndex, compressionFormat); } }
/// <summary> /// Opens a texture to encode from a stream. /// </summary> /// <param name="source">Stream that contains the texture data.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(Stream source, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) : base(source) { if (decodedBitmap != null) { initalized = Initalize(pixelFormat, dataFormat); } }
/// <summary> /// Opens a texture to encode from a byte array. /// </summary> /// <param name="source">Byte array that contains the texture data.</param> /// <param name="offset">Offset of the texture in the array.</param> /// <param name="length">Number of bytes to read.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(byte[] source, int offset, int length, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) : base(source, offset, length) { if (decodedBitmap != null) { initalized = Initalize(pixelFormat, dataFormat); } }
public PBTextureHeader(int offset, PvrPixelFormat pxformat, PvrDataFormat dataformat, uint gbix, ushort width, ushort height) { Offset = offset; PixelFormat = pxformat; DataFormat = dataformat; GBIX = gbix; Width = width; Height = height; }
/// <summary> /// Opens a texture to encode from a file. /// </summary> /// <param name="file">Filename of the file that contains the texture data.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(string file, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { Initalize(new Bitmap(file)); if (m_decodedBitmap != null) { Initalize(pixelFormat, dataFormat); } }
/// <summary> /// Opens a texture to encode from a bitmap. /// </summary> /// <param name="source">Bitmap to encode.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(Bitmap source, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { Initalize(source); if (m_decodedBitmap != null) { Initalize(pixelFormat, dataFormat); } }
/// <summary> /// Opens a texture to encode from a byte array. /// </summary> /// <param name="source">Byte array that contains the texture data.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(byte[] source, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { MemoryStream buffer = new MemoryStream(); buffer.Write(source, 0, source.Length); Initalize(new Bitmap(buffer)); if (m_decodedBitmap != null) { Initalize(pixelFormat, dataFormat); } }
/// <summary> /// Opens a texture to encode from a stream. /// </summary> /// <param name="source">Stream that contains the texture data.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(Stream source, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { MemoryStream buffer = new MemoryStream(); PTStream.CopyPartTo(source, buffer, (int)(source.Length - source.Position)); Initalize(new Bitmap(buffer)); if (m_decodedBitmap != null) { Initalize(pixelFormat, dataFormat); } }
private bool Initalize(PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { // Set the default values HasGlobalIndex = true; GlobalIndex = 0; CompressionFormat = PvrCompressionFormat.NONE; // Set the data format and pixel format and load the appropiate codecs this.PixelFormat = pixelFormat; PixelCodec = PvrPixelCodec.GetPixelCodec(pixelFormat); this.DataFormat = dataFormat; DataCodec = PvrDataCodec.GetDataCodec(dataFormat); // Make sure the pixel and data codecs exists and we can encode to it if (PixelCodec == null || !PixelCodec.CanEncode) { return(false); } if (DataCodec == null || !DataCodec.CanEncode) { return(false); } DataCodec.PixelCodec = PixelCodec; if (DataCodec.PaletteEntries != 0) { if (DataCodec.VQ) { m_decodedData = BitmapToRawVQ(m_decodedBitmap, DataCodec.PaletteEntries, out m_texturePalette); } else { // Convert the bitmap to an array containing indicies. m_decodedData = BitmapToRawIndexed(m_decodedBitmap, DataCodec.PaletteEntries, out m_texturePalette); // If this texture has an external palette file, set up the palette encoder if (DataCodec.NeedsExternalPalette) { PaletteEncoder = new PvpPaletteEncoder(m_texturePalette, (ushort)DataCodec.PaletteEntries, pixelFormat, PixelCodec); } } } else { // Convert the bitmap to an array m_decodedData = BitmapToRaw(m_decodedBitmap); } return(true); }
public static PvrDataCodec GetDataCodec(PvrDataFormat format) { switch (format) { case PvrDataFormat.SQUARE_TWIDDLED: return(new SquareTwiddled()); case PvrDataFormat.SQUARE_TWIDDLED_MIPMAP: case PvrDataFormat.SQUARE_TWIDDLED_MIPMAP_ALT: return(new SquareTwiddledMipmaps()); case PvrDataFormat.VECTOR_QUANTIZATION: return(new Vq()); case PvrDataFormat.VECTOR_QUANTIZATION_MIPMAP: return(new VqMipmaps()); case PvrDataFormat.PALETTIZE_4BIT: return(new Index4()); case PvrDataFormat.PALETTIZE_4BIT_MIPMAP: return(new Index4Mipmap()); case PvrDataFormat.PALETTIZE_8BIT: return(new Index8()); case PvrDataFormat.PALETTIZE_8BIT_MIPMAP: return(new Index8Mipmap()); case PvrDataFormat.RAW: case PvrDataFormat.RECTANGLE: case PvrDataFormat.RECTANGLE_STRIDE: return(new Rectangle()); case PvrDataFormat.RECTANGLE_TWIDDLED: return(new RectangleTwiddled()); case PvrDataFormat.VECTOR_QUANTIZATION_SMALL: return(new SmallVq()); case PvrDataFormat.VECTOR_QUANTIZATION_SMALL_MIPMAP: return(new SmallVqMipmaps()); } return(null); }
private bool Initalize(PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { // Set the default values hasGlobalIndex = true; globalIndex = 0; compressionFormat = PvrCompressionFormat.None; // Set the data format and pixel format and load the appropiate codecs this.pixelFormat = pixelFormat; pixelCodec = PvrPixelCodec.GetPixelCodec(pixelFormat); this.dataFormat = dataFormat; dataCodec = PvrDataCodec.GetDataCodec(dataFormat); // Make sure the pixel and data codecs exists and we can encode to it if (pixelCodec == null || !pixelCodec.CanEncode) { return(false); } if (dataCodec == null || !dataCodec.CanEncode) { return(false); } dataCodec.PixelCodec = pixelCodec; if (dataCodec.PaletteEntries != 0) { // Convert the bitmap to an array containing indicies. decodedData = BitmapToRawIndexed(decodedBitmap, dataCodec.PaletteEntries, out texturePalette); // If this texture has an external palette file, set up the palette encoder if (dataCodec.NeedsExternalPalette) { paletteEncoder = new PvpPaletteEncoder(texturePalette, (ushort)dataCodec.PaletteEntries, pixelFormat, pixelCodec); } } else { // Convert the bitmap to an array decodedData = BitmapToRaw(decodedBitmap); } return(true); }
public static PvrDataCodec GetDataCodec(PvrDataFormat format) { switch (format) { case PvrDataFormat.SquareTwiddled: return(new SquareTwiddled()); case PvrDataFormat.SquareTwiddledMipmaps: case PvrDataFormat.SquareTwiddledMipmapsAlt: return(new SquareTwiddledMipmaps()); case PvrDataFormat.Vq: return(new Vq()); case PvrDataFormat.VqMipmaps: return(new VqMipmaps()); case PvrDataFormat.Index4: return(new Index4()); case PvrDataFormat.Index8: return(new Index8()); case PvrDataFormat.Rectangle: return(new Rectangle()); case PvrDataFormat.RectangleTwiddled: return(new RectangleTwiddled()); case PvrDataFormat.SmallVq: return(new SmallVq()); case PvrDataFormat.SmallVqMipmaps: return(new SmallVqMipmaps()); } return(null); }
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, gbixFourCC)) { gbixOffset = 0x00; pvrtOffset = 0x08 + BitConverter.ToInt32(encodedData, gbixOffset + 4); } else if (PTMethods.Contains(encodedData, 0x04, gbixFourCC)) { gbixOffset = 0x04; pvrtOffset = 0x0C + BitConverter.ToInt32(encodedData, gbixOffset + 4); } else if (PTMethods.Contains(encodedData, 0x04, pvrtFourCC)) { 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 number of palette entries // The number in a Small Vq encoded texture various based on its size paletteEntries = dataCodec.PaletteEntries; if (dataFormat == PvrDataFormat.SmallVq || dataFormat == PvrDataFormat.SmallVqMipmaps) { if (textureWidth <= 16) { paletteEntries = 64; // Actually 16 } else if (textureWidth <= 32) { paletteEntries = 256; // Actually 64 } else if (textureWidth <= 64) { paletteEntries = 512; // Actually 128 } else { paletteEntries = 1024; // Actually 256 } } // Set the palette and data offsets if (!canDecode || paletteEntries == 0 || dataCodec.NeedsExternalPalette) { paletteOffset = -1; dataOffset = pvrtOffset + 0x10; } else { paletteOffset = pvrtOffset + 0x10; dataOffset = paletteOffset + (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; } else 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; }
private bool Initalize(PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { return(Initalize(pixelFormat, dataFormat, 0, PvrCompressionFormat.None)); }
static void Main(string[] args) { string directoryName; string FullLine; string texturename; UInt32 GBIX = 0; List <String> textureNames = new List <String>(); List <PvrTexture> finalTextureList = new List <PvrTexture>(); if (args.Length == 0) { Console.WriteLine("Error - no texturelist provided. Provide a path to a texturelist as your first command line argument"); Console.WriteLine("Press ENTER to continue..."); Console.ReadLine(); return; } String filePath = args[0]; directoryName = Path.GetDirectoryName(filePath); string archiveName = Path.GetFileNameWithoutExtension(filePath); if (File.Exists(filePath)) { StreamReader texlistStream = File.OpenText(filePath); while (!texlistStream.EndOfStream) { textureNames.Add(texlistStream.ReadLine()); } PvmArchive pvmArchive = new PvmArchive(); Stream pvmStream = File.Open(Path.ChangeExtension(filePath, ".pvm"), FileMode.Create); PvmArchiveWriter pvmWriter = (PvmArchiveWriter)pvmArchive.Create(pvmStream); // Reading in textures for (uint imgIndx = 0; imgIndx < textureNames.Count; imgIndx++) { FullLine = textureNames[(int)imgIndx]; if (string.IsNullOrEmpty(FullLine)) { continue; } String[] substrings = FullLine.Split(','); GBIX = UInt32.Parse(substrings[0]); texturename = substrings[1]; Bitmap tempTexture = new Bitmap(8, 8); string texturePath = Path.Combine(directoryName, Path.ChangeExtension(texturename, ".png")); if (File.Exists(texturePath)) { Console.WriteLine("Adding texture:" + (texturePath)); tempTexture = (Bitmap)Bitmap.FromFile(texturePath); tempTexture = tempTexture.Clone(new Rectangle(Point.Empty, tempTexture.Size), System.Drawing.Imaging.PixelFormat.Format32bppArgb); } else { Console.WriteLine(String.Concat("Texture ", textureNames[(int)imgIndx], " not found. Generating a placeholder. Check your files.")); } System.Drawing.Imaging.BitmapData bmpd = tempTexture.LockBits(new Rectangle(Point.Empty, tempTexture.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int stride = bmpd.Stride; byte[] bits = new byte[Math.Abs(stride) * bmpd.Height]; System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, bits, 0, bits.Length); tempTexture.UnlockBits(bmpd); int tlevels = 0; for (int y = 0; y < tempTexture.Height; y++) { int srcaddr = y * Math.Abs(stride); for (int x = 0; x < tempTexture.Width; x++) { Color c = Color.FromArgb(BitConverter.ToInt32(bits, srcaddr + (x * 4))); if (c.A == 0) { tlevels = 1; } else if (c.A < 255) { tlevels = 2; break; } } if (tlevels == 2) { break; } } PvrPixelFormat ppf = PvrPixelFormat.Rgb565; if (tlevels == 1) { ppf = PvrPixelFormat.Argb1555; } else if (tlevels == 2) { ppf = PvrPixelFormat.Argb4444; } PvrDataFormat pdf = PvrDataFormat.Rectangle; if (tempTexture.Width == tempTexture.Height) { pdf = PvrDataFormat.SquareTwiddled; } PvrTextureEncoder encoder = new PvrTextureEncoder(tempTexture, ppf, pdf); encoder.GlobalIndex = GBIX; string pvrPath = Path.ChangeExtension(texturePath, ".pvr"); encoder.Save(pvrPath); pvmWriter.CreateEntryFromFile(pvrPath); } pvmWriter.Flush(); pvmStream.Close(); Console.WriteLine("PVM was compiled successfully!"); Console.WriteLine("Press ENTER to continue..."); Console.ReadLine(); return; } else // error, supplied path is invalid { Console.WriteLine("Supplied texturelist does not exist!"); Console.WriteLine("Press ENTER to continue..."); Console.ReadLine(); return; } }
// Checks to see if we can encode the texture based on data format specific things private bool CanEncode(PvrPixelFormat PixelFormat, PvrDataFormat DataFormat, int width, int height) { // The converter should check to see that a pixel codec and data codec exists, // along with checking that width >= 8 and height >= 8, and width and height are powers of 2. switch (DataFormat) { case PvrDataFormat.SquareTwiddled: case PvrDataFormat.SquareTwiddledMipmaps: case PvrDataFormat.Vq: case PvrDataFormat.VqMipmaps: case PvrDataFormat.SquareTwiddledMipmapsDup: return (width == height); case PvrDataFormat.SmallVq: return (width == height && width <= 64); case PvrDataFormat.SmallVqMipmaps: return (width == height && width <= 32); } return true; }
private bool Initalize(PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) { // Set the default values hasGlobalIndex = true; globalIndex = 0; compressionFormat = PvrCompressionFormat.None; // Set the data format and pixel format and load the appropiate codecs this.pixelFormat = pixelFormat; pixelCodec = PvrPixelCodec.GetPixelCodec(pixelFormat); this.dataFormat = dataFormat; dataCodec = PvrDataCodec.GetDataCodec(dataFormat); // Make sure the pixel and data codecs exists and we can encode to it if (pixelCodec == null || !pixelCodec.CanEncode) return false; if (dataCodec == null || !dataCodec.CanEncode) return false; dataCodec.PixelCodec = pixelCodec; if (dataCodec.PaletteEntries != 0) { // Convert the bitmap to an array containing indicies. decodedData = BitmapToRawIndexed(decodedBitmap, dataCodec.PaletteEntries, out texturePalette); // If this texture has an external palette file, set up the palette encoder if (dataCodec.NeedsExternalPalette) { paletteEncoder = new PvpPaletteEncoder(texturePalette, (ushort)dataCodec.PaletteEntries, pixelFormat, pixelCodec); } } else { // Convert the bitmap to an array decodedData = BitmapToRaw(decodedBitmap); } return true; }
/// <summary> /// Convert a GBIX indexed texture pack to PVM. /// </summary> static void TexPack2PVM(string[] args) { bool compressPRS = false; if (args[args.Length - 1] == "-prs") { compressPRS = true; } filePath = args[1]; string FullLine; string texturename; uint GBIX = 0; List <string> textureNames = new List <String>(); List <PvrTexture> finalTextureList = new List <PvrTexture>(); directoryName = Path.GetDirectoryName(filePath); string archiveName = Path.GetFileNameWithoutExtension(filePath); if (Directory.Exists(filePath)) { Console.WriteLine("Converting texture pack to PVM: {0}", Path.GetFullPath(filePath)); StreamReader texlistStream = File.OpenText(Path.Combine(filePath, "index.txt")); while (!texlistStream.EndOfStream) { textureNames.Add(texlistStream.ReadLine()); } PuyoFile puyo = new PuyoFile(); outputPath = Path.ChangeExtension(filePath, ".pvm"); // Reading in textures for (uint imgIndx = 0; imgIndx < textureNames.Count; imgIndx++) { FullLine = textureNames[(int)imgIndx]; if (string.IsNullOrEmpty(FullLine)) { continue; } string[] substrings = FullLine.Split(','); GBIX = UInt32.Parse(substrings[0]); texturename = substrings[1]; Bitmap tempTexture = new Bitmap(8, 8); string texturePath = Path.Combine(filePath, Path.ChangeExtension(texturename, ".png")); if (File.Exists(texturePath)) { Console.WriteLine("Adding texture: " + (texturePath)); tempTexture = (Bitmap)Bitmap.FromFile(texturePath); tempTexture = tempTexture.Clone(new Rectangle(Point.Empty, tempTexture.Size), System.Drawing.Imaging.PixelFormat.Format32bppArgb); } else { Console.WriteLine(string.Concat("Texture ", textureNames[(int)imgIndx], " not found. Generating a placeholder. Check your files.")); } System.Drawing.Imaging.BitmapData bmpd = tempTexture.LockBits(new Rectangle(Point.Empty, tempTexture.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int stride = bmpd.Stride; byte[] bits = new byte[Math.Abs(stride) * bmpd.Height]; System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, bits, 0, bits.Length); tempTexture.UnlockBits(bmpd); int tlevels = 0; for (int y = 0; y < tempTexture.Height; y++) { int srcaddr = y * Math.Abs(stride); for (int x = 0; x < tempTexture.Width; x++) { Color c = Color.FromArgb(BitConverter.ToInt32(bits, srcaddr + (x * 4))); if (c.A == 0) { tlevels = 1; } else if (c.A < 255) { tlevels = 2; break; } } if (tlevels == 2) { break; } } PvrPixelFormat ppf = PvrPixelFormat.Rgb565; if (tlevels == 1) { ppf = PvrPixelFormat.Argb1555; } else if (tlevels == 2) { ppf = PvrPixelFormat.Argb4444; } PvrDataFormat pdf = PvrDataFormat.Rectangle; if (tempTexture.Width == tempTexture.Height) { pdf = PvrDataFormat.SquareTwiddled; } PvrTextureEncoder encoder = new PvrTextureEncoder(tempTexture, ppf, pdf); encoder.GlobalIndex = GBIX; string pvrPath = Path.ChangeExtension(texturePath, ".pvr"); encoder.Save(pvrPath); puyo.Entries.Add(new PVMEntry(pvrPath)); } File.WriteAllBytes(outputPath, puyo.GetBytes()); if (compressPRS) { Console.WriteLine("Compressing to PRS..."); byte[] pvmdata = File.ReadAllBytes(Path.ChangeExtension(filePath, ".pvm")); pvmdata = FraGag.Compression.Prs.Compress(pvmdata); outputPath = Path.ChangeExtension(filePath, ".prs"); File.WriteAllBytes(outputPath, pvmdata); File.Delete(Path.ChangeExtension(filePath, ".pvm")); } Console.WriteLine("Output file: {0}", Path.GetFullPath(outputPath)); Console.WriteLine("Archive was compiled successfully!"); } else { Console.WriteLine("Supplied texture list does not exist!"); Console.WriteLine("Press ENTER to continue..."); Console.ReadLine(); return; } }
/// <summary> /// 查找当前类型的图片 /// </summary> /// <param name="byData">当前打开文件的字节数据</param> /// <param name="file">当前文件</param> /// <param name="imgInfos">查找到的图片的信息</param> /// <returns>是否查找成功</returns> public override List <byte[]> SearchImg(byte[] byData, string file, List <string> imgInfos) { List <byte[]> imgList = new List <byte[]>(); // 分析文件内部是否包括Pvr文件 for (int i = 0; i < byData.Length - 1024; i++) { if (byData[i] == 0x50 && byData[i + 1] == 0x56 && byData[i + 2] == 0x52 && byData[i + 3] == 0x54 && byData[i - 0x10] == 0x47 && byData[i - 0xf] == 0x42 && byData[i - 0xe] == 0x49 && byData[i - 0xd] == 0x58) { PvrPixelFormat pixelFormat = (PvrPixelFormat)byData[i + 0x08]; PvrDataFormat dataFormat = (PvrDataFormat)byData[i + 0x09]; PvrPixelCodec pixelCodec = PvrPixelCodec.GetPixelCodec(pixelFormat); PvrDataCodec dataCodec = PvrDataCodec.GetDataCodec(dataFormat); if (dataCodec == null) { continue; } dataCodec.PixelCodec = pixelCodec; int byCountPalette = 0; if (pixelCodec == null && byData[i + 0x08] == 0x6) { byCountPalette = 4; } else { byCountPalette = pixelCodec.Bpp >> 3; } // 取得图片大小 int width = (byData[i + 0xD] << 8) | byData[i + 0xC]; int height = (byData[i + 0xF] << 8) | byData[i + 0xE]; int imgByCount = (width * height * dataCodec.Bpp / 8) + (dataCodec.PaletteEntries * byCountPalette); if (imgByCount == 0 || imgByCount > byData.Length) { throw new Exception("图片容量异常格式 : " + imgByCount); } byte[] byGvrData = new byte[0x20 + imgByCount]; Array.Copy(byData, i - 0x10, byGvrData, 0, byGvrData.Length); string imgFileInfo = Util.GetShortName(file) + " " + (i - 0x10).ToString("x") + "--" + (i - 0x10 + byGvrData.Length).ToString("x"); imgList.Add(byGvrData); imgInfos.Add(imgFileInfo); // 取得调色板大小 if (dataCodec.NeedsExternalPalette) { int paletteCount = dataCodec.PaletteEntries * byCountPalette; byte[] byPalette = new byte[paletteCount + 0x10]; int paletteDataStart = i - 0x30; if (byData[paletteDataStart] == 0x50 && byData[paletteDataStart + 1] == 0x50 && byData[paletteDataStart + 2] == 0x56 && byData[paletteDataStart + 3] == 0x52) { paletteDataStart = i - 0x20 - paletteCount - 0x10 - 0x20; } else { paletteDataStart = i - 0x20 - paletteCount - 0x10; } Array.Copy(byData, paletteDataStart, byPalette, 0, byPalette.Length); this.paletteData.Add(imgFileInfo + " " + paletteDataStart.ToString(), byPalette); } } } return(imgList); }
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> /// Opens a texture to encode from a stream. /// </summary> /// <param name="source">Stream that contains the texture data.</param> /// <param name="length">Number of bytes to read.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public PvrTextureEncoder(Stream source, int length, PvrPixelFormat pixelFormat, PvrDataFormat dataFormat) : base(source, length) { if (decodedBitmap != null) { initalized = Initalize(pixelFormat, dataFormat); } }
static void Main(string[] args) { ArchiveFromFolderMode folderMode; string dir; string filePath; string directoryName; ArchiveBase pvmArchive; ArchiveWriter pvmWriter; string archiveName; string path; byte[] filedata; bool isPRS; bool isBIN = false; string extension; // Usage if (args.Length == 0) { Console.WriteLine("ArchiveTool is a command line tool to extract and create PVM, GVM, PRS, DAT and PB archives.\nIt can also decompress SADX Gamecube 'SaCompGC' REL files.\n"); Console.WriteLine("Usage:\n"); Console.WriteLine("Extracting a PVM/GVM/PRS/PB/PVMX/DAT/REL file:\nArchiveTool <archivefile>\nIf the archive is PRS compressed, it will be decompressed first.\nIf the archive contains textures/sounds, the program will extract them and create a list of files named 'index.txt'.\n"); Console.WriteLine("Extracting an NjUtil archive: ArchiveTool -nju <archivefile>\n"); Console.WriteLine("Converting PVM/GVM to a folder texture pack: ArchiveTool -png <archivefile>\n"); Console.WriteLine("Creating a PB archive from a folder with textures: ArchiveTool -pb <foldername>"); Console.WriteLine("Creating a PVM/GVM/DAT/PVMX from a folder with textures/sounds: ArchiveTool <foldername> [-prs]\nThe program will create an archive from files listed in 'index.txt' in the folder.\nThe -prs option will make the program output a PRS compressed archive.\n"); Console.WriteLine("Creating a PVM from PNG textures: ArchiveTool -pvm <folder> [-prs]\nThe texture list 'index.txt' must contain global indices listed before each texture filename for this option to work.\n"); Console.WriteLine("Converting GVM to PVM (lossy): ArchiveTool -gvm2pvm <file.gvm> [-prs]\n"); Console.WriteLine("Creating a PRS compressed binary: ArchiveTool <file.bin>\nFile extension must be .BIN for this option to work.\n"); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } switch (args[0].ToLowerInvariant()) { // GVM2PVM mode case "-gvm2pvm": filePath = args[1]; isPRS = false; if (args.Length > 2 && args[2] == "-prs") { isPRS = true; } Console.WriteLine("Converting GVM to PVM: {0}", filePath); directoryName = Path.GetDirectoryName(filePath); extension = Path.GetExtension(filePath).ToLowerInvariant(); if (!File.Exists(filePath)) { Console.WriteLine("Supplied GVM archive does not exist!"); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } if (extension != ".gvm") { Console.WriteLine("GVM2PVM mode can only be used with GVM files."); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } path = Path.Combine(directoryName, Path.GetFileNameWithoutExtension(filePath)); Directory.CreateDirectory(path); filedata = File.ReadAllBytes(filePath); using (TextWriter texList = File.CreateText(Path.Combine(path, Path.GetFileName(path) + ".txt"))) { try { ArchiveBase gvmfile = null; byte[] gvmdata = File.ReadAllBytes(filePath); gvmfile = new GvmArchive(); ArchiveReader gvmReader = gvmfile.Open(gvmdata); Stream pvmStream = File.Open(Path.ChangeExtension(filePath, ".pvm"), FileMode.Create); pvmArchive = new PvmArchive(); pvmWriter = pvmArchive.Create(pvmStream); foreach (ArchiveEntry file in gvmReader.Entries) { if (!File.Exists(Path.Combine(path, file.Name))) { gvmReader.ExtractToFile(file, Path.Combine(path, file.Name)); } Stream data = File.Open(Path.Combine(path, file.Name), FileMode.Open); VrTexture vrfile = new GvrTexture(data); Bitmap tempTexture = vrfile.ToBitmap(); System.Drawing.Imaging.BitmapData bmpd = tempTexture.LockBits(new Rectangle(Point.Empty, tempTexture.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int stride = bmpd.Stride; byte[] bits = new byte[Math.Abs(stride) * bmpd.Height]; System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, bits, 0, bits.Length); tempTexture.UnlockBits(bmpd); int tlevels = 0; archiveName = Path.GetFileNameWithoutExtension(filePath); for (int y = 0; y < tempTexture.Height; y++) { int srcaddr = y * Math.Abs(stride); for (int x = 0; x < tempTexture.Width; x++) { Color c = Color.FromArgb(BitConverter.ToInt32(bits, srcaddr + (x * 4))); if (c.A == 0) { tlevels = 1; } else if (c.A < 255) { tlevels = 2; break; } } if (tlevels == 2) { break; } } PvrPixelFormat ppf = PvrPixelFormat.Rgb565; if (tlevels == 1) { ppf = PvrPixelFormat.Argb1555; } else if (tlevels == 2) { ppf = PvrPixelFormat.Argb4444; } PvrDataFormat pdf; if (!vrfile.HasMipmaps) { if (tempTexture.Width == tempTexture.Height) { pdf = PvrDataFormat.SquareTwiddled; } else { pdf = PvrDataFormat.Rectangle; } } else { if (tempTexture.Width == tempTexture.Height) { pdf = PvrDataFormat.SquareTwiddledMipmaps; } else { pdf = PvrDataFormat.RectangleTwiddled; } } PvrTextureEncoder encoder = new PvrTextureEncoder(tempTexture, ppf, pdf); encoder.GlobalIndex = vrfile.GlobalIndex; string pvrPath = Path.ChangeExtension(Path.Combine(path, file.Name), ".pvr"); if (!File.Exists(pvrPath)) { encoder.Save(pvrPath); } data.Close(); File.Delete(Path.Combine(path, file.Name)); pvmWriter.CreateEntryFromFile(pvrPath); texList.WriteLine(Path.GetFileName(pvrPath)); Console.WriteLine("Adding texture {0}", pvrPath); } pvmWriter.Flush(); pvmStream.Flush(); pvmStream.Close(); if (isPRS) { Console.WriteLine("Compressing to PRS..."); byte[] pvmdata = File.ReadAllBytes(Path.ChangeExtension(filePath, ".pvm")); pvmdata = FraGag.Compression.Prs.Compress(pvmdata); File.WriteAllBytes(Path.ChangeExtension(filePath, ".PVM.PRS"), pvmdata); File.Delete(Path.ChangeExtension(filePath, ".PVM")); } Console.WriteLine("Archive converted!"); } catch (Exception ex) { Console.WriteLine("Exception thrown: {0}", ex.ToString()); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } } break; // CompilePVM mode case "-pvm": bool IsPRS = false; if (args[args.Length - 1] == "-prs") { IsPRS = true; } filePath = args[1]; string FullLine; string texturename; uint GBIX = 0; List <string> textureNames = new List <String>(); List <PvrTexture> finalTextureList = new List <PvrTexture>(); directoryName = Path.GetDirectoryName(filePath); archiveName = Path.GetFileNameWithoutExtension(filePath); if (Directory.Exists(filePath)) { Console.WriteLine("Converting texture pack to PVM: {0}", filePath); StreamReader texlistStream = File.OpenText(Path.Combine(filePath, "index.txt")); while (!texlistStream.EndOfStream) { textureNames.Add(texlistStream.ReadLine()); } pvmArchive = new PvmArchive(); Stream pvmStream = File.Open(Path.ChangeExtension(filePath, ".pvm"), FileMode.Create); pvmWriter = (PvmArchiveWriter)pvmArchive.Create(pvmStream); // Reading in textures for (uint imgIndx = 0; imgIndx < textureNames.Count; imgIndx++) { FullLine = textureNames[(int)imgIndx]; if (string.IsNullOrEmpty(FullLine)) { continue; } String[] substrings = FullLine.Split(','); GBIX = UInt32.Parse(substrings[0]); texturename = substrings[1]; Bitmap tempTexture = new Bitmap(8, 8); string texturePath = Path.Combine(filePath, Path.ChangeExtension(texturename, ".png")); if (File.Exists(texturePath)) { Console.WriteLine("Adding texture: " + (texturePath)); tempTexture = (Bitmap)Bitmap.FromFile(texturePath); tempTexture = tempTexture.Clone(new Rectangle(Point.Empty, tempTexture.Size), System.Drawing.Imaging.PixelFormat.Format32bppArgb); } else { Console.WriteLine(String.Concat("Texture ", textureNames[(int)imgIndx], " not found. Generating a placeholder. Check your files.")); } System.Drawing.Imaging.BitmapData bmpd = tempTexture.LockBits(new Rectangle(Point.Empty, tempTexture.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int stride = bmpd.Stride; byte[] bits = new byte[Math.Abs(stride) * bmpd.Height]; System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, bits, 0, bits.Length); tempTexture.UnlockBits(bmpd); int tlevels = 0; for (int y = 0; y < tempTexture.Height; y++) { int srcaddr = y * Math.Abs(stride); for (int x = 0; x < tempTexture.Width; x++) { Color c = Color.FromArgb(BitConverter.ToInt32(bits, srcaddr + (x * 4))); if (c.A == 0) { tlevels = 1; } else if (c.A < 255) { tlevels = 2; break; } } if (tlevels == 2) { break; } } PvrPixelFormat ppf = PvrPixelFormat.Rgb565; if (tlevels == 1) { ppf = PvrPixelFormat.Argb1555; } else if (tlevels == 2) { ppf = PvrPixelFormat.Argb4444; } PvrDataFormat pdf = PvrDataFormat.Rectangle; if (tempTexture.Width == tempTexture.Height) { pdf = PvrDataFormat.SquareTwiddled; } PvrTextureEncoder encoder = new PvrTextureEncoder(tempTexture, ppf, pdf); encoder.GlobalIndex = GBIX; string pvrPath = Path.ChangeExtension(texturePath, ".pvr"); encoder.Save(pvrPath); pvmWriter.CreateEntryFromFile(pvrPath); } pvmWriter.Flush(); pvmStream.Close(); if (IsPRS) { Console.WriteLine("Compressing to PRS..."); byte[] pvmdata = File.ReadAllBytes(Path.ChangeExtension(filePath, ".pvm")); pvmdata = FraGag.Compression.Prs.Compress(pvmdata); File.WriteAllBytes(Path.ChangeExtension(filePath, ".prs"), pvmdata); File.Delete(Path.ChangeExtension(filePath, ".pvm")); } Console.WriteLine("Archive was compiled successfully!"); } else { Console.WriteLine("Supplied texture list does not exist!"); Console.WriteLine("Press ENTER to continue..."); Console.ReadLine(); return; } break; // Create PB mode case "-pb": filePath = args[1]; Console.WriteLine("Building PB from folder: {0}", filePath); if (Directory.Exists(filePath)) { string indexfilename = Path.Combine(filePath, "index.txt"); if (!File.Exists(indexfilename)) { Console.WriteLine("Supplied path does not have an index file."); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } List <string> filenames = new List <string>(File.ReadAllLines(indexfilename).Where(a => !string.IsNullOrEmpty(a))); PBFile pba = new PBFile(filenames.Count); int l = 0; foreach (string tex in filenames) { byte[] texbytes = File.ReadAllBytes(Path.Combine(filePath, tex)); pba.AddPVR(texbytes, l); l++; } path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filePath)), Path.GetFileNameWithoutExtension(filePath)); string filename_full = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filePath)), Path.GetFileName(filePath) + ".pb"); Console.WriteLine("Output file: {0}", filename_full); File.WriteAllBytes(filename_full, pba.GetBytes()); } else { Console.WriteLine("Supplied path does not exist."); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } break; // Extract NjArchive mode case "-nju": filePath = args[1]; filedata = File.ReadAllBytes(filePath); if (Path.GetExtension(filePath).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { filedata = FraGag.Compression.Prs.Decompress(filedata); } NjArchive njarc = new NjArchive(filedata); Console.WriteLine("Extracting Ninja archive: {0}", filePath); dir = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)); Console.WriteLine("Output folder: {0}", dir); Directory.CreateDirectory(dir); for (int i = 0; i < njarc.Entries.Count; i++) { byte[] data = njarc.Entries[i]; extension = ".bin"; string desc = "Unknown"; switch (System.Text.Encoding.ASCII.GetString(data, 0, 4)) { case "NJIN": desc = "Ninja Information"; extension = ".nji"; break; case "NJCM": desc = "Ninja Chunk model"; extension = ".nj"; break; case "GJCM": desc = "Ninja Chunk model (GC)"; extension = ".gj"; break; case "NJBM": desc = "Ninja Basic model"; extension = ".nj"; break; case "NMDM": desc = "Ninja Motion"; extension = ".njm"; break; case "NJLI": desc = "Ninja Light"; extension = ".njl"; break; case "NLIM": desc = "Ninja Light Motion"; extension = ".njlm"; break; case "NSSM": desc = "Ninja Simple Shape Motion"; extension = ".njsm"; break; case "NCAM": desc = "Ninja Camera Motion"; extension = ".ncm"; break; case "NJTL": desc = "Ninja Texlist"; extension = ".nj"; break; case "GJTL": desc = "Ninja Texlist (GC)"; extension = ".gj"; break; case "PVMH": desc = "PVM"; extension = ".pvm"; break; case "GVMH": desc = "GVM"; extension = ".gvm"; break; } Console.WriteLine("Entry {0} is {1}", i, desc); string outpath = Path.Combine(dir, i.ToString("D3") + extension); File.WriteAllBytes(outpath, njarc.Entries[i]); } break; // PVM2TexPack mode case "-png": Queue <string> files = new Queue <string>(); for (int u = 1; u < args.Length; u++) { files.Enqueue(args[u]); } if (files.Count == 0) { Console.Write("File: "); files.Enqueue(Console.ReadLine()); } while (files.Count > 0) { string filename = files.Dequeue(); path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename)); string filename_full = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileName(filename)); Console.WriteLine("Converting file to texture pack: {0}", filename_full); Directory.CreateDirectory(path); filedata = File.ReadAllBytes(filename_full); using (TextWriter texList = File.CreateText(Path.Combine(path, "index.txt"))) { try { if (PvrTexture.Is(filedata)) { if (!AddTexture(false, path, Path.GetFileName(filename_full), new MemoryStream(filedata), texList)) { texList.Close(); Directory.Delete(path, true); } continue; } else if (GvrTexture.Is(filedata)) { if (!AddTexture(true, path, Path.GetFileName(filename_full), new MemoryStream(filedata), texList)) { texList.Close(); Directory.Delete(path, true); } continue; } bool gvm = false; ArchiveBase pvmfile = null; byte[] pvmdata = File.ReadAllBytes(filename_full); if (Path.GetExtension(filename_full).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { pvmdata = FraGag.Compression.Prs.Decompress(pvmdata); } pvmfile = new PvmArchive(); MemoryStream stream = new MemoryStream(pvmdata); if (!PvmArchive.Identify(stream)) { pvmfile = new GvmArchive(); gvm = true; } ArchiveEntryCollection pvmentries = pvmfile.Open(pvmdata).Entries; bool fail = false; foreach (ArchiveEntry file in pvmentries) { if (!AddTexture(gvm, path, file.Name, file.Open(), texList)) { texList.Close(); Directory.Delete(path, true); fail = true; break; } } if (fail) { continue; } } catch (Exception ex) { Console.WriteLine("Exception thrown: " + ex.ToString() + "\nCanceling conversion."); return; } Console.WriteLine("Conversion complete!"); } } break; // Other modes default: filePath = args[0]; IsPRS = false; if (args.Length > 1 && args[1] == "-prs") { IsPRS = true; } extension = Path.GetExtension(filePath).ToLowerInvariant(); //Folder mode if (Directory.Exists(filePath)) { string indexfilename = Path.Combine(filePath, "index.txt"); List <string> filenames = new List <string>(File.ReadAllLines(indexfilename).Where(a => !string.IsNullOrEmpty(a))); string ext = Path.GetExtension(filenames[0]).ToLowerInvariant(); pvmArchive = new PvmArchive(); switch (ext) { case ".pvr": folderMode = ArchiveFromFolderMode.PVM; break; case ".gvr": pvmArchive = new GvmArchive(); folderMode = ArchiveFromFolderMode.GVM; break; case ".wav": folderMode = ArchiveFromFolderMode.DAT; break; case ".png": case ".jpg": case ".bmp": case ".dds": case ".gif": default: folderMode = ArchiveFromFolderMode.PVMX; break; } Console.WriteLine("Creating {0} archive from folder: {1}", folderMode.ToString(), filePath); switch (folderMode) { case ArchiveFromFolderMode.DAT: // Load index DATFile dat = new DATFile(); TextReader tr = File.OpenText(Path.Combine(filePath, "index.txt")); string line = tr.ReadLine(); while (line != null) { Console.WriteLine("Adding file {0}", Path.Combine(filePath, line)); dat.AddFile(Path.Combine(filePath, line)); line = tr.ReadLine(); } tr.Close(); // Save DAT archive File.WriteAllBytes(filePath + ".DAT", dat.GetBytes()); if (IsPRS) { Console.WriteLine("Compressing to PRS..."); byte[] datdata = File.ReadAllBytes(filePath + ".DAT"); datdata = FraGag.Compression.Prs.Compress(datdata); File.WriteAllBytes(filePath + ".PRS", datdata); File.Delete(filePath + ".DAT"); } Console.WriteLine("Archive compiled successfully!"); return; case ArchiveFromFolderMode.PVM: case ArchiveFromFolderMode.GVM: if (filenames.Any(a => !Path.GetExtension(a).Equals(ext, StringComparison.OrdinalIgnoreCase))) { Console.WriteLine("Cannot create archive from mixed file types."); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } ext = folderMode == ArchiveFromFolderMode.PVM ? ".pvm" : ".gvm"; using (Stream pvmStream = File.Open(Path.ChangeExtension(filePath, ext), FileMode.Create)) { pvmWriter = pvmArchive.Create(pvmStream); // Reading in textures foreach (string tex in filenames) { if (folderMode == ArchiveFromFolderMode.PVM) { pvmWriter.CreateEntryFromFile(Path.Combine(filePath, Path.ChangeExtension(tex, ".pvr"))); } else { pvmWriter.CreateEntryFromFile(Path.Combine(filePath, Path.ChangeExtension(tex, ".gvr"))); } Console.WriteLine("Adding file: {0}", tex); } pvmWriter.Flush(); } if (IsPRS) { Console.WriteLine("Compressing to PRS..."); byte[] pvmdata = File.ReadAllBytes(Path.ChangeExtension(filePath, ext)); pvmdata = FraGag.Compression.Prs.Compress(pvmdata); File.WriteAllBytes(Path.ChangeExtension(filePath, ".prs"), pvmdata); File.Delete(Path.ChangeExtension(filePath, ext)); } Console.WriteLine("Archive was compiled successfully!"); return; case ArchiveFromFolderMode.PVMX: // Load index PVMXFile pvmx = new PVMXFile(); TextReader trp = File.OpenText(Path.Combine(filePath, "index.txt")); foreach (string str in filenames) { string[] split = str.Split(','); string texfile = Path.Combine(Path.GetFullPath(filePath), split[1]); Console.WriteLine("Adding file {0}", texfile); if (split.Length > 2) { string[] dimensions = split[2].Split('x'); pvmx.AddFile(split[1], uint.Parse(split[0]), File.ReadAllBytes(texfile), int.Parse(dimensions[0]), int.Parse(dimensions[1])); } else { pvmx.AddFile(split[1], uint.Parse(split[0]), File.ReadAllBytes(texfile)); } } Console.WriteLine("Output file: {0}", Path.ChangeExtension(filePath, ".pvmx")); File.WriteAllBytes(Path.ChangeExtension(filePath, ".pvmx"), pvmx.GetBytes()); Console.WriteLine("Archive was compiled successfully!"); return; } } //Continue with file mode otherwise if (!File.Exists(filePath)) { Console.WriteLine("Supplied archive/texture list does not exist!"); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } switch (extension) { case ".rel": Console.WriteLine("Decompressing REL file: {0}", filePath); byte[] input = File.ReadAllBytes(args[0]); byte[] output = SA_Tools.HelperFunctions.DecompressREL(input); File.WriteAllBytes(Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + "_dec.rel"), output); return; case ".dat": Console.WriteLine("Extracting DAT file: {0}", filePath); DATFile dat = new DATFile(File.ReadAllBytes(filePath)); dir = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)); if (Directory.Exists(dir)) { Directory.Delete(dir, true); } Directory.CreateDirectory(dir); using (StreamWriter sw = File.CreateText(Path.Combine(dir, "index.txt"))) { dat.Entries.Sort((f1, f2) => StringComparer.OrdinalIgnoreCase.Compare(f1.name, f2.name)); for (int i = 0; i < dat.GetCount(); i++) { string fname = dat.Entries[i].name; sw.WriteLine(fname); if (dat.Steam) { fname = Path.GetFileNameWithoutExtension(fname) + ".adx"; } Console.WriteLine("Extracting file: {0}", fname); File.WriteAllBytes(Path.Combine(dir, fname), dat.GetFile(i)); } sw.Flush(); sw.Close(); } Console.WriteLine("Archive extracted!"); break; case ".pvmx": Console.WriteLine("Extracting PVMX file: {0}", filePath); byte[] pvmxdata = File.ReadAllBytes(filePath); dir = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)); Directory.CreateDirectory(dir); PVMXFile pvmx = new PVMXFile(pvmxdata); using (TextWriter texList = File.CreateText(Path.Combine(dir, "index.txt"))) { for (int u = 0; u < pvmx.GetCount(); u++) { byte[] tdata = pvmx.GetFile(u); string outpath = Path.Combine(dir, pvmx.GetName(u)); File.WriteAllBytes(outpath, tdata); string entry; string dimensions = string.Join("x", pvmx.GetWidth(u).ToString(), pvmx.GetHeight(u).ToString()); if (pvmx.HasDimensions(u)) { entry = string.Join(",", pvmx.GetGBIX(u).ToString(), pvmx.GetName(u), dimensions); } else { entry = string.Join(",", pvmx.GetGBIX(u).ToString(), pvmx.GetName(u)); } texList.WriteLine(entry); } texList.Flush(); texList.Close(); } Console.WriteLine("Archive extracted!"); break; case ".pb": Console.WriteLine("Extracting PB file: {0}", filePath); byte[] pbdata = File.ReadAllBytes(filePath); dir = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)); Directory.CreateDirectory(dir); PBFile pba = new PBFile(pbdata); using (TextWriter texList = File.CreateText(Path.Combine(dir, "index.txt"))) { for (int u = 0; u < pba.GetCount(); u++) { byte[] pvrt = pba.GetPVR(u); string outpath = Path.Combine(dir, u.ToString("D3") + ".pvr"); File.WriteAllBytes(outpath, pvrt); texList.WriteLine(u.ToString("D3") + ".pvr"); } texList.Flush(); texList.Close(); } Console.WriteLine("Archive extracted!"); break; case ".bin": Console.WriteLine("Compressing BIN file: {0}", filePath); byte[] bindata = File.ReadAllBytes(Path.ChangeExtension(filePath, ".bin")); bindata = FraGag.Compression.Prs.Compress(bindata); File.WriteAllBytes(Path.ChangeExtension(filePath, ".prs"), bindata); Console.WriteLine("PRS archive was compiled successfully!"); return; case ".prs": case ".pvm": case ".gvm": Console.WriteLine("Extracting archive: {0}", filePath); path = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)); Directory.CreateDirectory(path); filedata = File.ReadAllBytes(filePath); using (TextWriter texList = File.CreateText(Path.Combine(path, "index.txt"))) { try { ArchiveBase pvmfile = null; byte[] pvmdata = File.ReadAllBytes(filePath); if (extension == ".prs") { pvmdata = FraGag.Compression.Prs.Decompress(pvmdata); } pvmfile = new PvmArchive(); MemoryStream stream = new MemoryStream(pvmdata); if (!PvmArchive.Identify(stream)) { pvmfile = new GvmArchive(); if (!GvmArchive.Identify(stream)) { File.WriteAllBytes(Path.ChangeExtension(filePath, ".bin"), pvmdata); isBIN = true; Console.WriteLine("PRS archive extracted!"); } } if (!isBIN) { ArchiveReader pvmReader = pvmfile.Open(pvmdata); foreach (ArchiveEntry pvmentry in pvmReader.Entries) { Console.WriteLine("Extracting file: {0}", pvmentry.Name); texList.WriteLine(pvmentry.Name); pvmReader.ExtractToFile(pvmentry, Path.Combine(path, pvmentry.Name)); } Console.WriteLine("Archive extracted!"); } } catch { Console.WriteLine("Exception thrown. Canceling conversion."); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); Directory.Delete(path, true); throw; } } if (isBIN) { Directory.Delete(path, true); } break; default: Console.WriteLine("Unknown extension \"{0}\".", extension); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); break; } break; } }
private static string DataFormatToString(PvrDataFormat format) { switch (format) { case PvrDataFormat.SquareTwiddled: return "Square Twiddled"; case PvrDataFormat.SquareTwiddledMipmaps: return "Square Twiddled with Mipmaps"; case PvrDataFormat.Vq: return "VQ"; case PvrDataFormat.VqMipmaps: return "VQ with Mipmaps"; case PvrDataFormat.Index4: return "4-bit Indexed with External Palette"; case PvrDataFormat.Index8: return "8-bit Indexed with External Palette"; case PvrDataFormat.Rectangle: return "Rectangle"; case PvrDataFormat.RectangleTwiddled: return "Rectangle Twiddled"; case PvrDataFormat.SmallVq: return "Small VQ"; case PvrDataFormat.SmallVqMipmaps: return "Small VQ with Mipmaps"; case PvrDataFormat.SquareTwiddledMipmapsAlt: return "Square Twiddled with Mipmaps (Alternate)"; } return "Unknown"; }