internal PaletteArchive(AssetLoader loader) : base(loader) { for (int index = 0; index < 8; index++) { PaletteAsset asset = PaletteAsset.ReadRgb(Manager, "Palette " + index, loader.Reader, 256, 63); AddChild(asset); } }
void ReadIconAndTitle(int iconAndTitleOffset) { if (iconAndTitleOffset == 0) { return; } // Read the palette. Reader.BaseStream.Position = iconAndTitleOffset + 0x220; Color[] colors = new Color[16]; for (int index = 0; index < 16; index++) { Reader.ReadNDSColor(forceTransparent: index == 0); } PaletteAsset palette = new PaletteAsset(Manager, "Icon palette", colors); // Read the icon. Reader.BaseStream.Position = iconAndTitleOffset + 0x20; Vector2i iconSize = new Vector2i(32, 32); Vector2i tileSize = iconSize / 8; int[] indices = new int[iconSize.X * iconSize.Y]; for (Vector2i tile = Vector2i.Zero; tile.Y < tileSize.Y; tile.Y++) { for (tile.X = 0; tile.X < tileSize.X; tile.X++) { for (Vector2i pixel = Vector2i.Zero; pixel.Y < 8; pixel.Y++) { for (pixel.X = 0; pixel.X < 4; pixel.X++) { int x = pixel.X + tile.X * 4; int y = pixel.Y + tile.Y * 8; int offset = x + y * iconSize.X; byte pair = Reader.ReadByte(); indices[offset + 0] = pair & 0x0F; indices[offset + 1] = pair >> 4; } } } } Icon = new IndexedTextureAsset(Manager, "Icon", palette, iconSize.X, iconSize.Y, indices); // Read the title. Name = Reader.ReadStringzAt(iconAndTitleOffset + 0x240, Encoding.Unicode); TitleEnglish = Reader.ReadStringzAt(iconAndTitleOffset + 0x340, Encoding.Unicode); TitleFrench = Reader.ReadStringzAt(iconAndTitleOffset + 0x440, Encoding.Unicode); TitleGerman = Reader.ReadStringzAt(iconAndTitleOffset + 0x540, Encoding.Unicode); TitleItalian = Reader.ReadStringzAt(iconAndTitleOffset + 0x640, Encoding.Unicode); TitleSpanish = Reader.ReadStringzAt(iconAndTitleOffset + 0x740, Encoding.Unicode); }
internal Palette(AssetLoader loader) : base(loader) { BinaryReader reader = loader.Reader; Unknowns.ReadBytes(reader, 25); // Offset 0-24 int firstIndex = reader.ReadByte(); // Offset 25-25 Unknowns.ReadBytes(reader, 3); // Offset 26-28 int count = reader.ReadUInt16(); // Offset 29-30 Unknowns.ReadBytes(reader, 1); // Offset 31-31 byte format = reader.ReadByte(); // Offset 32-32 Unknowns.ReadBytes(reader, 4); // Offset 33-36 // Offset 37 PaletteColor[] colors = new PaletteColor[count]; Colors = new ReadOnlyCollection <PaletteColor>(colors); FlatColors = new Codex <Color>(256); for (int index = 0; index < firstIndex; index++) { FlatColors.Add(Color.Purple); } for (int index = 0; index < count; index++) { PaletteColor color; switch (format) { case 0: // Variable (byte used, byte red, byte green, byte blue) color = new PaletteColor(reader.ReadByte() != 0, reader.ReadByte(), reader.ReadByte(), reader.ReadByte()); break; case 1: // Constant (byte red, byte green, byte blue) color = new PaletteColor(reader.ReadByte(), reader.ReadByte(), reader.ReadByte()); break; default: throw new NotImplementedException(); } colors[index] = color; FlatColors.Add(color); } PaletteAsset = new PaletteAsset(Manager, Name ?? "Palette", FlatColors); }
internal GraphicArchive(int paletteIndex, AssetLoader loader, int[] sizes = null) : base(loader) { State state = State.Get(this); PaletteAsset palette = state.GetPalette(paletteIndex); using (BinaryReader reader = loader.Reader) { byte forceSizeCode = reader.ReadByte(); int forceSize = 0; if (forceSizeCode == 2) { forceSize = reader.ReadByte(); } else if (forceSizeCode != 1) { throw new InvalidDataException(); } int count = reader.ReadUInt16(); int[] offsets = reader.ReadArrayInt32(count + 1); for (int index = 0; index < count; index++) { int length = offsets[index + 1] - offsets[index]; reader.BaseStream.Position = offsets[index]; int width = -1, height = -1; if (sizes != null && index * 2 < sizes.Length) { width = sizes[index * 2 + 0]; height = sizes[index * 2 + 1]; } else if (forceSize != 0) { width = height = forceSize; } new Graphic(this, loader, index, length, width, height, palette); } } }
void Load(BinaryReader reader, int width, int height, PaletteAsset palette, byte format, int[] aux = null, int auxOffset = 0) { int[] indices = new int[width * height]; ushort dataSize; switch (format) { case 4: // Uncompressed dataSize = reader.ReadUInt16(); if (width * height != dataSize) { throw new InvalidDataException(); } reader.ReadBytesAsInt32(indices, 0, width * height); break; case 6: // 5-bit RLE dataSize = reader.ReadUInt16(); LoadRLE(indices, reader, width, height, 5, aux, auxOffset); break; case 8: // 4-bit RLE if (aux == null) { throw new NotImplementedException("Need to load auxiliary palette."); } dataSize = reader.ReadUInt16(); LoadRLE(indices, reader, width, height, 4, aux, auxOffset); break; case 10: // 4-bit aux palette indices. throw new NotImplementedException("Need to load auxiliary palette."); default: throw new NotImplementedException("Unknown graphic format " + format + "."); } Setup(palette, width, height, indices); }
internal Image(AssetManager manager, BinaryReader reader, string name, Asset context) : base(manager, name) { using (reader) { int height = reader.ReadByte(); int width = reader.ReadByte() * 8; reader.RequireZeroes(4); int frameCount = reader.ReadUInt16(); if (frameCount == 0) { throw new InvalidDataException(); } byte baseColorIndex = reader.ReadByte(); int colorCount = reader.ReadByte() + 1; // Need to initialize palette. Color[] colors = new Color[256]; for (int index = 0; index < 16; index++) { colors[index] = Raster.DefaultEgaColors[index]; } for (int index = 0; index < colorCount; index++) { colors[index + baseColorIndex] = Color.FromArgb(reader.ReadByte() * 255 / 63, reader.ReadByte() * 255 / 63, reader.ReadByte() * 255 / 63); } PaletteAsset palette = new PaletteAsset(Manager, Name + " palette", colors); Unknowns.ReadBytes(reader, (colorCount + 1) / 2); // EGA color map, two colours per byte. Unknowns.ReadBytes(reader, 4); int remaining = checked ((int)(reader.BaseStream.Length - reader.BaseStream.Position)); if (remaining == width * height * frameCount + 28) { Unknowns.ReadBytes(reader, 28); remaining -= 28; } if (remaining != width * height * frameCount || (height != 0 && remaining % height != 0)) { throw new InvalidDataException("Expected file length is not correct."); } int[] indices = new int[width * height]; if (width == 0 || height == 0) { AddChild(palette); } else { for (int index = 0; index < frameCount; index++) { reader.ReadBytesAsInt32(indices, 0, indices.Length); var resource = new IndexedTextureAsset(Manager, "Frame " + index, palette, width, height, indices); AddChild(resource); } } // Hack for "over.dax" files to use their multiple palettes. if (context is ArchiveRecord && ((ArchiveRecord)context).Id >= 51 && string.Equals(Path.GetFileName(context.Parent.Name), "over.dax", StringComparison.InvariantCultureIgnoreCase)) { Archive archive = (Archive)context.Parent; for (int id = 1; id <= 4; id++) { palette = (PaletteAsset)archive.RecordsById[id].Contents.Children[0]; var frame = new IndexedTextureAsset(Manager, "Palette " + id, palette, width, height, indices); AddChild(frame); } } } }
internal Graphic(GraphicArchive archive, AssetLoader loader, int index, int length, int width, int height, PaletteAsset palette, int[] aux = null, int auxOffset = 0) : base(archive, loader) { BinaryReader reader = loader.Reader; Name = index.ToString(); if (length == 0) { return; } if (width >= 0 && height >= 0) { int[] indices = reader.ReadBytesAsInt32(width * height); Setup(palette, width, height, indices); } else { byte format = reader.ReadByte(); width = reader.ReadByte(); height = reader.ReadByte(); Load(reader, width, height, palette, format, aux, auxOffset); } Center = new Vector2i(width / 2 - 4, height - 4); }
/// <summary>Load the PCX image file.</summary> /// <param name="loader"></param> /// <returns></returns> public override Asset Load(AssetLoader loader) { BinaryReader reader = loader.Reader; PcxHeader header = new PcxHeader(reader); int pitch = (header.BitsPerPixel * header.ColorPlaneCount + 7) / 8 * header.SizeX; int[] data = new int[pitch * header.SizeY + 1]; for (int row = 0; row < header.SizeY; row++) { switch (header.Compression) { case PcxCompression.None: for (int index = 0; index < pitch; index++) { data[pitch * row + index] = reader.ReadByte(); } break; case PcxCompression.RLE: for (int offset = pitch * row, end = offset + header.BytesPerScanLine; offset < end;) { byte value = reader.ReadByte(); if (value < 0xC0) { data[offset++] = value; } else { int runEnd = offset + value - 0xC0; byte code = reader.ReadByte(); while (offset < runEnd) { data[offset++] = code; } } } break; default: throw new NotImplementedException(); } } PaletteAsset palette = null; if (header.ColorPlaneCount == 1) { if (reader.BaseStream.ReadByte() == PaletteMagic) { palette = PaletteAsset.ReadRgb(Manager, loader.Name + " Palette", reader, 1 << header.BitsPerPixel, 255); } } if (palette != null) { return(new IndexedTextureAsset(loader, palette, header.SizeX, header.SizeY, data, pitch)); } else { throw new NotImplementedException(); } }