/// <summary> /// Returns a GBA.Image of this GBA.Tileset, with the given palette. /// </summary> public Image ToImage(Palette colors) { int width = Tile.SIZE * Width; int height = Tile.SIZE * Height; byte[] result = new byte[(width / 2) * height]; byte[] tile; int ix, iy; int index = 0; int t = 0; for (int i = 0; i < Count; i++) { ix = (i % Width) * Tile.SIZE; iy = (i / Width) * Tile.SIZE; tile = Sheet[i].Bytes; index = (ix / 2) + (iy * (width / 2)); t = 0; for (int y = 0; y < Tile.SIZE; y++) { for (int x = 0; x < Tile.SIZE; x += 2) { result[index++] = tile[t++]; } index += (width - Tile.SIZE) / 2; } } return(new Image(width, height, colors.ToBytes(false), result)); }
/// <summary> /// Creates an affine/transformed sprite from a block of OAM data and the affine data with it /// </summary> public Sprite(Palette palette, Tileset tileset, OAM oam, OAM_Affine transform) { Size size = oam.GetDimensions(); Load(palette, tileset, new TileMap(oam.GetTileMap(size)), false, false); int width = (oam.OBJMode == OAM_OBJMode.BigAffine) ? size.Width * 16 : size.Width * 8; int height = (oam.OBJMode == OAM_OBJMode.BigAffine) ? size.Height * 16: size.Height * 8; byte[] data = new byte[width * height]; int tileX, tileY; int affX, affY; int halfW = width / 2; int halfH = height / 2; for (int y = halfH * -1; y < halfH; y++) { for (int x = halfW * -1; x < halfW; x++) { affX = (int)(transform.Ux * x + transform.Vx * y) + size.Width * 4; affY = (int)(transform.Uy * x + transform.Vy * y) + size.Height * 4; if (affX < 0 || affX >= size.Width * 8) { continue; } if (affY < 0 || affY >= size.Height * 8) { continue; } tileX = affX / Tile.SIZE; tileY = affY / Tile.SIZE; int index = Tiles[tileX, tileY]; if (index < 0 || index >= Sheet.Count) { continue; } tileX = affX % Tile.SIZE; tileY = affY % Tile.SIZE; data[(halfW + x) + (halfH + y) * width] = (byte)Sheet[index][tileX, tileY]; } } Transform = new Bitmap(width, height, palette.ToBytes(false), data); }
/// <summary> /// Creates a Palette from a palette file (if its an image file, must be 16 pixels in width) /// </summary> public Palette(string filepath, int maximum = MAX) { Colors = new List <Color>(maximum); if (filepath.EndsWith(".png", StringComparison.OrdinalIgnoreCase) || filepath.EndsWith(".gif", StringComparison.OrdinalIgnoreCase) || filepath.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase)) { Bitmap source; try { source = new GBA.Bitmap(filepath); } catch { throw new Exception("Could not open palette file:\n" + filepath); } bool addEveryPixel = (source.Width == 16); int index = 0; Color color; for (int y = 0; y < source.Height; y++) { for (int x = 0; x < source.Width; x++) { color = source.GetColor(x, y); if (!addEveryPixel && this.Contains(color)) { continue; } else { if (this.IsFull) { throw new Exception("This palette cannot hold more than " + maximum + " colors."); } else { this.Colors.Add(color); index++; } } } } } else if (filepath.EndsWith(".pal", StringComparison.OrdinalIgnoreCase)) { byte[] palette = File.ReadAllBytes(filepath); if (palette[0] == 0x43 && palette[1] == 0x4C && palette[2] == 0x52 && palette[3] == 0x58) // 'CLRX' is the header for usenti .pal files { string[] file = File.ReadAllLines(filepath); int channelBits; int colorAmount; int parse = 5; int length = 0; while (parse + length < file[0].Length && file[0][parse + length] != ' ') { length++; } channelBits = int.Parse(file[0].Substring(parse, length)); parse += length + 1; length = 0; while (parse + length < file[0].Length && file[0][parse + length] != ' ') { length++; } colorAmount = int.Parse(file[0].Substring(parse, length)); uint color = 0x00000000; Palette colors = new Palette(colorAmount); for (int i = 0; i < (colorAmount / 4); i++) { parse = 0; length = 0; for (int j = 0; j < 4; j++) { while (parse + length < file[1 + i].Length && file[1 + i][parse + length] != ' ') { length++; } color = Util.HexToInt(file[1 + i].Substring(parse, length)); colors.Add(new Color(color)); parse += length + 1; length = 0; } } palette = colors.ToBytes(false); } else if (palette.Length != maximum * 2) { throw new Exception( "Cannot load palette, the file given is of invalid length.\n" + "It should be " + maximum * 2 + " bytes long."); } byte[] buffer = new byte[2]; for (int i = 0; i < palette.Length / 2; i++) { buffer[0] = palette[i * 2 + 1]; buffer[1] = palette[i * 2]; Colors.Add(new Color(buffer)); } } else { throw new Exception("Invalid filetype given to load palette."); } }