protected override void OnOpen(EndianBinaryReader reader) { Header = new SceGxtHeader(reader); Func <EndianBinaryReader, SceGxtTextureInfo> textureInfoGeneratorFunc; switch (Header.Version) { case 0x10000003: textureInfoGeneratorFunc = new Func <EndianBinaryReader, SceGxtTextureInfo>((r) => { return(new SceGxtTextureInfoV301(r)); }); break; case 0x10000002: textureInfoGeneratorFunc = new Func <EndianBinaryReader, SceGxtTextureInfo>((r) => { return(new SceGxtTextureInfoV201(r)); }); break; case 0x10000001: textureInfoGeneratorFunc = new Func <EndianBinaryReader, SceGxtTextureInfo>((r) => { return(new SceGxtTextureInfoV101(r)); }); break; default: throw new Exception("GXT version not implemented"); } TextureInfos = new SceGxtTextureInfo[Header.NumTextures]; for (int i = 0; i < TextureInfos.Length; i++) { TextureInfos[i] = textureInfoGeneratorFunc(reader); } // TODO: any other way to detect these? if (Encoding.ASCII.GetString(reader.ReadBytes(4)) == BUVChunk.ExpectedMagicNumber) { reader.BaseStream.Seek(-4, SeekOrigin.Current); BUVChunk = new BUVChunk(reader); } ReadAllBasePalettes(reader); ReadAllTextures(reader); }
private static byte[] PixelProviderP4(BinaryReader reader, SceGxtTextureInfo info) { byte[] pixelData = new byte[info.DataSize]; for (int i = 0; i < pixelData.Length; i++) { byte idx = reader.ReadByte(); pixelData[i] = (byte)(idx >> 4 | idx << 4); } return(pixelData); }
public TextureBundle(BinaryReader reader, SceGxtTextureInfo info) { reader.BaseStream.Seek(info.DataOffset, SeekOrigin.Begin); Width = info.GetWidth(); Height = info.GetHeight(); PaletteIndex = info.PaletteIndex; RawLineSize = (int)(info.DataSize / info.GetHeightRounded()); TextureFormat = info.GetTextureFormat(); RoundedWidth = Width; //info.GetWidthRounded(); RoundedHeight = Height; //info.GetHeightRounded(); if (!PixelDataProviders.PixelFormatMap.ContainsKey(TextureFormat) || !PixelDataProviders.ProviderFunctions.ContainsKey(TextureFormat)) { throw new FormatNotImplementedException(TextureFormat); } PixelFormat = PixelDataProviders.PixelFormatMap[TextureFormat]; PixelData = PixelDataProviders.ProviderFunctions[TextureFormat](reader, info); SceGxmTextureBaseFormat textureBaseFormat = info.GetTextureBaseFormat(); // TODO: is this right? PVRTC/PVRTC2 doesn't need this, but everything else does? if (textureBaseFormat != SceGxmTextureBaseFormat.PVRT2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRT4BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRTII2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRTII4BPP) { SceGxmTextureType textureType = info.GetTextureType(); switch (textureType) { case SceGxmTextureType.Linear: // Nothing to be done! break; case SceGxmTextureType.Tiled: // TODO: verify me! PixelData = PostProcessing.UntileTexture(PixelData, info.GetWidthRounded(), info.GetHeightRounded(), PixelFormat); break; case SceGxmTextureType.Swizzled: case SceGxmTextureType.Cube: // TODO: is cube really the same as swizzled? seems that way from CS' *env* files... PixelData = PostProcessing.UnswizzleTexture(PixelData, info.GetWidthRounded(), info.GetHeightRounded(), PixelFormat); break; case (SceGxmTextureType)0xA0000000: // TODO: mehhhhh PixelData = PostProcessing.UnswizzleTexture(PixelData, info.GetWidthRounded(), info.GetHeightRounded(), PixelFormat); break; default: throw new TypeNotImplementedException(textureType); } } }
private void ReadAllTextures(EndianBinaryReader reader) { PixelData = new byte[Header.NumTextures][]; for (int i = 0; i < TextureInfos.Length; i++) { SceGxtTextureInfo info = TextureInfos[i]; reader.BaseStream.Seek(info.DataOffset, SeekOrigin.Begin); PixelData[i] = reader.ReadBytes((int)info.DataSize); } }
private static byte[] PixelProviderU8U8_RGGG(BinaryReader reader, SceGxtTextureInfo info) { byte[] pixelData = new byte[info.DataSize * 4]; for (int i = 0; i < pixelData.Length; i += 4) { pixelData[i + 3] = reader.ReadByte(); pixelData[i + 0] = pixelData[i + 1] = pixelData[i + 2] = reader.ReadByte(); } ; return(pixelData); }
// Shim function for GXT public static byte[] Decompress(BinaryReader reader, SceGxtTextureInfo info) { byte[] pixelData = new byte[info.DataSize * 8]; PVRTDecompressPVRTC( reader.ReadBytes((int)info.DataSize), (info.GetTextureBaseFormat() == SceGxmTextureBaseFormat.PVRT2BPP || info.GetTextureBaseFormat() == SceGxmTextureBaseFormat.PVRTII2BPP ? 1 : 0), info.GetWidth(), info.GetHeight(), (info.GetTextureBaseFormat() == SceGxmTextureBaseFormat.PVRTII2BPP || info.GetTextureBaseFormat() == SceGxmTextureBaseFormat.PVRTII4BPP ? 1 : 0), ref pixelData); return(pixelData); }
private static byte[] PixelProviderU4U4U4U4_ARGB(BinaryReader reader, SceGxtTextureInfo info) { byte[] pixelData = new byte[info.DataSize * 4]; for (int i = 0; i < pixelData.Length; i += 4) { ushort rgba = reader.ReadUInt16(); pixelData[i + 0] = (byte)(((rgba >> 4) << 4) & 0xFF); pixelData[i + 1] = (byte)(((rgba >> 8) << 4) & 0xFF); pixelData[i + 2] = (byte)(((rgba >> 12) << 4) & 0xFF); pixelData[i + 3] = (byte)((rgba << 4) & 0xFF); } ; return(pixelData); }
public static byte[] Decompress(BinaryReader reader, SceGxtTextureInfo info) { byte[] pixelData = new byte[info.DataSize * 8]; int pixelOffset = 0; for (int y = 0; y < info.GetHeightRounded(); y += 4) { for (int x = 0; x < info.GetWidthRounded(); x += 4) { byte[] decodedBlock = DecompressDxtBlock(reader, info.GetTextureBaseFormat()); for (int b = 0; b < dxtOrder.Length; b++) { Buffer.BlockCopy(decodedBlock, b * 4, pixelData, pixelOffset + (dxtOrder[b] * 4), 4); } pixelOffset += decodedBlock.Length; } } return(pixelData); }
private Bitmap CreateBitmap(int infoIdx, int forcePaletteIdx = -1) { SceGxtTextureInfo info = TextureInfos[infoIdx]; ImageBinary imageBinary = new ImageBinary(); imageBinary.Width = info.GetWidth(); imageBinary.Height = info.GetHeight(); imageBinary.InputPixelFormat = PSVita.GetPixelDataFormat(info.GetTextureFormat()); imageBinary.InputEndianness = Endian.LittleEndian; imageBinary.AddInputPixels(PixelData[infoIdx]); // TODO: verify all this crap, GXT conversion wrt image [dimension/format/type] is fragile as all hell SceGxmTextureBaseFormat textureBaseFormat = info.GetTextureBaseFormat(); SceGxmTextureType textureType = info.GetTextureType(); if (textureType == SceGxmTextureType.Linear && textureBaseFormat != SceGxmTextureBaseFormat.UBC1 && textureBaseFormat != SceGxmTextureBaseFormat.UBC2 && textureBaseFormat != SceGxmTextureBaseFormat.UBC3 && textureBaseFormat != SceGxmTextureBaseFormat.PVRT2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRT4BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRTII2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRTII4BPP) { imageBinary.PhysicalWidth = (int)(((info.DataSize / imageBinary.Height) * 8) / PSVita.GetBitsPerPixel(textureBaseFormat)); imageBinary.PhysicalHeight = info.GetHeight(); } else { imageBinary.PhysicalWidth = info.GetWidthRounded(); imageBinary.PhysicalHeight = info.GetHeightRounded(); } if (textureBaseFormat != SceGxmTextureBaseFormat.PVRT2BPP && textureBaseFormat != SceGxmTextureBaseFormat.PVRT4BPP) { switch (textureType) { case SceGxmTextureType.Linear: // Nothing to be done! break; case SceGxmTextureType.Tiled: // TODO: verify me! imageBinary.InputPixelFormat |= PixelDataFormat.PixelOrderingTiled3DS; break; case SceGxmTextureType.Swizzled: case SceGxmTextureType.Cube: // TODO: is cube really the same as swizzled? seems that way from CS' *env* files... imageBinary.InputPixelFormat |= PixelDataFormat.PixelOrderingSwizzledVita; break; case (SceGxmTextureType)0xA0000000: // TODO: this is odd and needs investigation, found ex. in Odin Sphere, Puyo Puyo Tetris, ... imageBinary.InputPixelFormat |= PixelDataFormat.PixelOrderingSwizzledVita; break; } } if (textureBaseFormat == SceGxmTextureBaseFormat.P4 || textureBaseFormat == SceGxmTextureBaseFormat.P8) { imageBinary.InputPaletteFormat = PSVita.GetPaletteFormat(info.GetTextureFormat()); if (textureBaseFormat == SceGxmTextureBaseFormat.P4) { foreach (byte[] paletteData in P4Palettes) { imageBinary.AddInputPalette(paletteData); } } else if (textureBaseFormat == SceGxmTextureBaseFormat.P8) { foreach (byte[] paletteData in P8Palettes) { imageBinary.AddInputPalette(paletteData); } } } return(imageBinary.GetBitmap(0, forcePaletteIdx != -1 ? forcePaletteIdx : info.PaletteIndex)); }
private static void ProcessInputFile(FileInfo inputFile, DirectoryInfo inputDir, DirectoryInfo outputDir) { try { if (!outputDir.Exists) { Directory.CreateDirectory(outputDir.FullName); } string displayPath = inputFile.FullName.Replace(inputDir.FullName, string.Empty).TrimStart(directorySeparators); IndentWriteLine("File '{0}'... ", displayPath); baseIndent = indent++; string relativeDirectory = inputFile.DirectoryName.TrimEnd(directorySeparators).Replace(inputDir.FullName.TrimEnd(directorySeparators), string.Empty).TrimStart(directorySeparators); if (keepFiles) { string existenceCheckPath = Path.Combine(outputDir.FullName, relativeDirectory); string existenceCheckPattern = Path.GetFileNameWithoutExtension(inputFile.Name) + "*"; if (Directory.Exists(existenceCheckPath) && Directory.EnumerateFiles(existenceCheckPath, existenceCheckPattern).Any()) { IndentWriteLine("Already exists."); return; } } using (FileStream fileStream = new FileStream(inputFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { GxtBinary gxtInstance = new GxtBinary(fileStream); for (int i = 0; i < gxtInstance.TextureInfos.Length; i++) { string outputFilename = string.Format("{0} (Texture {1}).png", Path.GetFileNameWithoutExtension(inputFile.Name), i); FileInfo outputFile = new FileInfo(Path.Combine(outputDir.FullName, relativeDirectory, outputFilename)); SceGxtTextureInfo info = gxtInstance.TextureInfos[i]; IndentWriteLine("Texture #{0}: {1}x{2} ({3}, {4})", (i + 1), info.GetWidth(), info.GetHeight(), info.GetTextureFormat(), info.GetTextureType()); indent++; if (!outputFile.Directory.Exists) { Directory.CreateDirectory(outputFile.Directory.FullName); } gxtInstance.Textures[i].Save(outputFile.FullName, System.Drawing.Imaging.ImageFormat.Png); indent--; } if (gxtInstance.BUVChunk != null) { indent++; for (int i = 0; i < gxtInstance.BUVTextures.Length; i++) { string outputFilename = string.Format("{0} (Block {1}).png", Path.GetFileNameWithoutExtension(inputFile.Name), i); FileInfo outputFile = new FileInfo(Path.Combine(outputDir.FullName, relativeDirectory, outputFilename)); BUVEntry entry = gxtInstance.BUVChunk.Entries[i]; IndentWriteLine("Block #{0}: {1}x{2} (Origin X:{3}, Y:{4})", (i + 1), entry.Width, entry.Height, entry.X, entry.Y); indent++; if (!outputFile.Directory.Exists) { Directory.CreateDirectory(outputFile.Directory.FullName); } gxtInstance.BUVTextures[i].Save(outputFile.FullName, System.Drawing.Imaging.ImageFormat.Png); indent--; } indent--; } } } #if !DEBUG catch (VersionNotImplementedException vniEx) { IndentWriteLine("GXT version {0:D2} (0x{1:X8}) not implemented.", (vniEx.Version & 0xFFFF), vniEx.Version); } catch (FormatNotImplementedException fniEx) { IndentWriteLine("Format '{0}' not implemented.", fniEx.Format); } catch (PaletteNotImplementedException pniEx) { IndentWriteLine("Palette '{0}' not implemented.", pniEx.Format); } catch (TypeNotImplementedException tniEx) { IndentWriteLine("Type '{0}' not implemented.", tniEx.Type); } catch (UnknownMagicException umEx) { IndentWriteLine("Unknown magic number: {0}.", umEx.Message); } catch (Exception ex) { IndentWriteLine("Exception occured: {0}.", ex.Message); } #endif finally { indent = baseIndent; } }
private static byte[] PixelProviderPVRTC(BinaryReader reader, SceGxtTextureInfo info) { return(Compression.PVRTC.Decompress(reader, info)); }
private static byte[] PixelProviderDirect(BinaryReader reader, SceGxtTextureInfo info) { return(reader.ReadBytes((int)info.DataSize)); }