protected override void OnOpen(EndianBinaryReader reader) { MagicNumber = Encoding.ASCII.GetString(reader.ReadBytes(4), 0, 4); FileSize = reader.ReadUInt32(); NumberOfChunks = reader.ReadUInt32(); Unknown1 = reader.ReadUInt32(); TexChunkOffset = reader.ReadUInt32(); TextureDataOffset = reader.ReadUInt32(); reader.BaseStream.Seek(TexChunkOffset, SeekOrigin.Begin); TexChunkTag = Encoding.ASCII.GetString(reader.ReadBytes(4), 0, 4); TexChunkSize = reader.ReadUInt32(); TextureCount = reader.ReadUInt32(); if (TexChunkTag != "tex ") { throw new Exception("CTXB parsing error"); } Textures = new CTXBTexture[TextureCount]; pixelData = new byte[TextureCount][]; for (int i = 0; i < Textures.Length; i++) { reader.BaseStream.Seek(TexChunkOffset + 0xC + (i * 0x24), SeekOrigin.Begin); Textures[i] = new CTXBTexture(reader); reader.BaseStream.Seek(TextureDataOffset + Textures[i].DataOffset, SeekOrigin.Begin); pixelData[i] = reader.ReadBytes((int)Textures[i].DataLength); } }
protected override Bitmap OnGetBitmap(int imageIndex, int paletteIndex) { CTXBTexture texture = Textures[imageIndex]; PicaPixelFormat pixelFormat = texture.PixelFormat; PicaDataType dataType = ((pixelFormat == PicaPixelFormat.ETC1RGB8NativeDMP || pixelFormat == PicaPixelFormat.ETC1AlphaRGB8A4NativeDMP) ? PicaDataType.UnsignedByte : texture.DataType); ImageBinary imageBinary = new ImageBinary(); imageBinary.Width = texture.Width; imageBinary.Height = texture.Height; imageBinary.InputPixelFormat = N3DS.GetPixelDataFormat(dataType, pixelFormat); imageBinary.InputEndianness = Endian.LittleEndian; imageBinary.AddInputPixels(pixelData[imageIndex]); return(imageBinary.GetBitmap(0, 0)); }
protected override void OnOpen(EndianBinaryReader reader) { /* cmb */ MagicNumber = Encoding.ASCII.GetString(reader.ReadBytes(4), 0, 4); FileSize = reader.ReadUInt32(); Revision = reader.ReadUInt32(); Unknown0x0C = reader.ReadUInt32(); ModelName = Encoding.ASCII.GetString(reader.ReadBytes(16), 0, 16).TrimEnd('\0'); Unknown0x20 = reader.ReadUInt32(); int chunkCount = -1, texChunkIdx = -1, rawDataCount = -1, textureDataIdx = -1; if (Revision == 0x0F || Revision == 0x0C || Revision == 0x0A) { chunkCount = 7; texChunkIdx = 3; rawDataCount = 3; textureDataIdx = 1; } else if (Revision == 0x06) { chunkCount = 6; texChunkIdx = 2; rawDataCount = 2; textureDataIdx = 1; } else { throw new Exception($"Unhandled CMB revision 0x{Revision:X2}"); } ChunkOffsets = new uint[chunkCount]; for (int i = 0; i < ChunkOffsets.Length; i++) { ChunkOffsets[i] = reader.ReadUInt32(); } RawDataOffsets = new uint[rawDataCount]; for (int i = 0; i < RawDataOffsets.Length; i++) { RawDataOffsets[i] = reader.ReadUInt32(); } /* Ensure we actually have texture data, otherwise bail */ if (RawDataOffsets[textureDataIdx] == 0x00) { return; } /* tex */ uint texChunkOffset = ChunkOffsets[texChunkIdx]; uint texDataOffset = RawDataOffsets[textureDataIdx]; reader.BaseStream.Seek(texChunkOffset, SeekOrigin.Begin); TexChunkTag = Encoding.ASCII.GetString(reader.ReadBytes(4), 0, 4); TexChunkSize = reader.ReadUInt32(); TextureCount = reader.ReadUInt32(); if (TexChunkTag != expectedTexChunkTag) { throw new Exception($"Unexpected data in CMB; wanted '{expectedTexChunkTag}', got '{TexChunkTag}'"); } Textures = new CTXBTexture[TextureCount]; pixelData = new byte[TextureCount][]; for (int i = 0; i < Textures.Length; i++) { reader.BaseStream.Seek(texChunkOffset + 0xC + (i * 0x24), SeekOrigin.Begin); Textures[i] = new CTXBTexture(reader); reader.BaseStream.Seek(texDataOffset + Textures[i].DataOffset, SeekOrigin.Begin); pixelData[i] = reader.ReadBytes((int)Textures[i].DataLength); } }