void WritePalette(CppWriter writer, Color[] palette) { for (int i = 0; i < palette.Length; ++i) { Color colour = palette[i]; UInt16 rbgColor = PaletteHelper.ToRgb16(colour); writer.Write(rbgColor); } }
List <UInt32> WriteSpriteData( Bitmap bitmap, Color[] palette, int width, int height, int xPos, int yPos, Compression.CompressionType compressionType, uint destBpp) { int tilesWide = width / TileConfig.TileWidth; int tilesTall = height / TileConfig.TileHeight; int totalTiles = (width * height) / (TileConfig.TileWidth * TileConfig.TileHeight); List <int> colourPaletteIndicies = new List <int>(); for (int tileY = 0; tileY < tilesTall; ++tileY) { for (int tileX = 0; tileX < tilesWide; ++tileX) { int tileXOffset = xPos + tileX * TileConfig.TileWidth; int tileYOffset = yPos + tileY * TileConfig.TileHeight; for (int y = 0; y < TileConfig.TileHeight; ++y) { for (int x = 0; x < TileConfig.TileWidth; ++x) { Color color = bitmap.GetPixel(tileXOffset + x, tileYOffset + y); int index = PaletteHelper.ColorToPaletteIndex(palette, color); colourPaletteIndicies.Add(index); } } } } List <UInt32> compressedIndicies; switch (compressionType) { case Compression.CompressionType.BitPacked: { Compression.BitPack(colourPaletteIndicies, destBpp, out compressedIndicies); } break; default: throw new NotImplementedException(); } return(compressedIndicies); }
static Tile GetTile(Bitmap bitmap, Color[] palette, int x, int y) { Tile tile = new Tile(); for (int pixX = x; pixX < x + TileConfig.TileWidth; ++pixX) { for (int pixY = y; pixY < y + TileConfig.TileHeight; ++pixY) { Color color = bitmap.GetPixel(pixX, pixY); tile.paletteIndicies[pixX - x, pixY - y] = PaletteHelper.ColorToPaletteIndex(palette, color); } } return(tile); }
void WritePalette(Color[] palette, StringBuilder sb) { sb.Append(VAR_PALLET); sb.Append(namespaceTabs + "{\n\t" + namespaceTabs); for (int i = 0; i < palette.Length; ++i) { Color color = palette[i]; UInt16 rbgColor = (UInt16)(PaletteHelper.ScaleToRgb16(color.R) + (PaletteHelper.ScaleToRgb16(color.G) << 5) + (PaletteHelper.ScaleToRgb16(color.B) << 10)); sb.AppendFormat("0x{0:X4}, ", rbgColor); if ((i + 1) % c_arrayNewlineCount == 0) { sb.Append("\n\t" + namespaceTabs); } } sb.Append("\n" + namespaceTabs + "};\n\n"); }
/// <param name="inputPath">Input file path, namespace name is derived from this</param> /// <param name="outputPath">Output cpp file</param> /// <param name="bitmaps">List of image files to map tilemaps from</param> /// <param name="paletteBankIndexOffset">Allows us to force things like UI palettes into the back of the palette bank</param> public void Convert(string inputPath, string outputPath, IList <Bitmap> bitmaps, byte paletteBankIndexOffset = 0) { CppWriter cppWriter = new CppWriter(Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath)), outputPath); Console.WriteLine("Processing master palette"); Color[] masterPalette; Tile[] masterTileSet; TileMap[] tileMapList; GenerateTileMaps(bitmaps, paletteBankIndexOffset, out masterPalette, out masterTileSet, out tileMapList); GBAMapData gbaMapData = GenerateMapData(tileMapList, paletteBankIndexOffset); const int maxMaps = sizeof(byte) * 8; if (gbaMapData.mapIsDynamic.Count >= maxMaps) { // Can't store this in the current bitmask size throw new Exception(string.Format("Too many tilemaps found. Maps = {0}, max is {1}. Consider increasing the bitmask of \"mapIsDynamicBitMask\".", gbaMapData.mapIsDynamic.Count, maxMaps)); } Console.WriteLine("Total unique tiles = " + masterTileSet.Length); Console.WriteLine("Processing tilemaps"); Compression.CompressionType compressionType = Compression.CompressionType.BitPacked; uint destBpp = CalculateDestBitsPerPixel(masterTileSet); List <UInt32> tileSetData = GenerateTileSetData(masterTileSet, compressionType, destBpp); // Write palette { cppWriter.Write(paletteBankIndexOffset); cppWriter.Write((byte)masterPalette.Length); for (int i = 0; i < masterPalette.Length; ++i) { Color colour = masterPalette[i]; UInt16 rbgColor = PaletteHelper.ToRgb16(colour); cppWriter.Write(rbgColor); } } // Write tileset { // Compression flags UInt32 compressionTypeSize = Compression.ToGBACompressionHeader(compressionType, destBpp); cppWriter.Write(compressionTypeSize); // Actual data cppWriter.Write((UInt32)tileSetData.Count); for (int i = 0; i < tileSetData.Count; ++i) { cppWriter.Write(tileSetData[i]); } } // Write tile maps { cppWriter.Write((byte)tileMapList.Length); cppWriter.Write((UInt32)gbaMapData.screenEntries.Length); byte mapIsDynamicBitMask = BoolListToBitmaskU8(gbaMapData.mapIsDynamic); cppWriter.Write(mapIsDynamicBitMask); // Width and height arrays foreach (int width in gbaMapData.widthLists) { cppWriter.Write((byte)width); } foreach (int height in gbaMapData.heightLists) { cppWriter.Write((byte)height); } foreach (var mapEntry in gbaMapData.screenEntries) { cppWriter.Write(mapEntry.m_data); } } Console.WriteLine("Tilemap \"" + outputPath + "\" successfully converted"); cppWriter.Finalise(); }
public static void GenerateTileMaps( IList <Bitmap> bitmaps , byte paletteBankIndexOffset , out Color[] masterPalette , out Tile[] masterTileSet , out TileMap[] tileMaps , bool skipSort = false ) { List <ProcessedPaletteContainer> bitmapPalettes = new List <ProcessedPaletteContainer>(); // Validate bitmaps and collect palettes for (int bitmapIndex = 0; bitmapIndex < bitmaps.Count; ++bitmapIndex) { Bitmap bitmap = bitmaps[bitmapIndex]; Size size = bitmap.Size; if (size.Width % TileConfig.TileWidth != 0 || size.Height % TileConfig.TileHeight != 0) { throw new Exception("Size not compatible with GBA tiles. Width and height of pixels must be multiples of 8."); } int xStart = 0; int yStart = 0; int width = bitmap.Width; int height = bitmap.Height; Color[] preProcessedPalette = PaletteHelper.GeneratePaletteFromImage(bitmap, xStart, yStart, width, height); // Validate pallet length { if (preProcessedPalette.Length > PaletteHelper.MAX_PALETTE_LENGTH) { throw new Exception(string.Format("Palette length ({0}) out of range for the GBA ({1})", preProcessedPalette.Length, PaletteHelper.MAX_PALETTE_LENGTH)); } } ProcessedPaletteContainer palContainer = new ProcessedPaletteContainer(); palContainer.bitmapIndex = bitmapIndex; palContainer.palette = preProcessedPalette; bitmapPalettes.Add(palContainer); } if (!skipSort) { // Sort bitmap palette. Anything more than 16 colours should be grouped next to each other. Less than 16 should always be a full 16. bitmapPalettes.Sort(new ProcessedPaletteComparer()); } // Get palettes of each image, merge into a master palette List <Color> masterPaletteList = new List <Color>(); List <ProcessedBitmapContainer> processedBitmapList = new List <ProcessedBitmapContainer>(); { Color transparencyColour = Color.FromArgb(0); for (int i = 0; i < bitmapPalettes.Count; ++i) { var bp = bitmapPalettes[i]; Debug.Assert(bp.palette[0] == transparencyColour); bool pal4bbp = bp.palette.Length <= PaletteHelper.PALETTE_LENGTH_4BBP; int paletteIndex = pal4bbp ? Find4bbpPaletteIndex(masterPaletteList, bp.palette) : -1; if (pal4bbp && paletteIndex < 0) // Add the new palette in { // Make sure our 4bbp palette is aligned properly, every set of 16 colour palettes starts with pure transparency while (masterPaletteList.Count % PaletteHelper.PALETTE_LENGTH_4BBP != 0) { masterPaletteList.Add(transparencyColour); } // TODO // If 2 bitmap palettes can fit in the same GBA palette, merge them into one. paletteIndex = Get4bbpPaletteIndexForSize(masterPaletteList); masterPaletteList.AddRange(bp.palette); } if (!pal4bbp) { // Only add colour into the master palette if it's not already in there. foreach (Color col in bp.palette) { if (!masterPaletteList.Contains(col)) { masterPaletteList.Add(col); } } } if ((paletteIndex + paletteBankIndexOffset) >= PaletteHelper.MAX_PALETTE_INDEX) { throw new Exception(string.Format("Palette index {0} with palette bank offset {1} is not valid for map data", paletteIndex, paletteBankIndexOffset)); } ProcessedBitmapContainer pbc = new ProcessedBitmapContainer(); pbc.bitmapIndex = bp.bitmapIndex; pbc.paletteIndex = paletteIndex; pbc.bitmap = bitmaps[bp.bitmapIndex]; processedBitmapList.Add(pbc); } } masterPalette = masterPaletteList.ToArray(); Console.WriteLine("Total colours found = " + masterPalette.Length); if (masterPalette.Length >= PaletteHelper.MAX_PALETTE_LENGTH) { throw new Exception(string.Format("Master palette has too many colours ({0}/{1})", masterPalette.Length, PaletteHelper.MAX_PALETTE_LENGTH)); } Console.WriteLine("Processing master tileset"); // Get all unique tiles sorted via palette indicies. Need to check if local palette was greater than 16 or not List <Tile> uniqueTileSetList = new List <Tile>(); foreach (ProcessedBitmapContainer pbc in processedBitmapList) { Tile[,] rawTileMap = BitmapToTileArray(pbc.bitmap, masterPalette, pbc.paletteIndex); pbc.rawTileMap = rawTileMap; FillUniqueTileset(rawTileMap, uniqueTileSetList); } masterTileSet = uniqueTileSetList.ToArray(); // Generate tilemaps from master list. Remember palette index, but we should be able to forget about it. We can overlap tiles that are the same but different colours. List <TileMap> tileMapList = new List <TileMap>(); foreach (ProcessedBitmapContainer pbc in processedBitmapList) { TileMap tilemap = new TileMap(pbc.rawTileMap, masterTileSet, pbc.paletteIndex); tileMapList.Add(tilemap); } tileMaps = tileMapList.ToArray(); }
public void Convert(string inputPath, string outputPath, Bitmap bitmap, UVs[] sliceCoordinates) { string namespaceName = string.Format(NAMESPACE_FORMAT, Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath))); StringBuilder sb = new StringBuilder(); Size size = bitmap.Size; if (size.Width % TileConfig.c_TILEWIDTH != 0 || size.Height % TileConfig.c_TILEHEIGHT != 0) { throw new Exception("Size not compatible with GBA tiles. Width and height of pixels must be multiples of 8."); } Console.WriteLine("Processing colour palette"); int xStart = 0; int yStart = 0; int width = bitmap.Width; int height = bitmap.Height; Color[] preProcessedPalette = PaletteHelper.GeneratePaletteFromImage(bitmap, xStart, yStart, width, height); // Validate pallet length { if (preProcessedPalette.Length > 256) { throw new Exception("Palette length out of range for the GBA"); } // Todo, currently not supported if (preProcessedPalette.Length > 16) { throw new Exception("Palette length out of range for 4bbp format"); } } Compression.CompressionType compressionType = Compression.CompressionType.BitPacked; uint maxColours = MathX.IsPowerOf2((uint)preProcessedPalette.Length) ? (uint)preProcessedPalette.Length : MathX.NextPowerOf2((uint)preProcessedPalette.Length); uint destBpp = (uint)MathX.IndexOfHighestSetBit(maxColours); if (!MathX.IsPowerOf2(destBpp)) { destBpp = MathX.NextPowerOf2(destBpp); } Console.WriteLine(string.Format("Compression type = {0}", compressionType.ToString())); Console.WriteLine(string.Format("Destination Bit Depth = {0}", destBpp)); List <int> dataOffsets = new List <int>(); List <StringBuilder> spriteData = new List <StringBuilder>(); dataOffsets.Add(0); int totalData = 0; // Collect data and add offsets { Console.WriteLine("Processing sprite data"); for (int i = 0; i < sliceCoordinates.Length; ++i) { StringBuilder dataSb = new StringBuilder(); UVs slice = sliceCoordinates[i]; int spriteWidth = slice.width, spriteHeight = slice.height; int dataCount = WriteSpriteData(dataSb, bitmap, preProcessedPalette, spriteWidth, spriteHeight, slice.x, slice.y, compressionType, destBpp); spriteData.Add(dataSb); // Add offsets if (i < sliceCoordinates.Length - 1) { dataOffsets.Add(dataOffsets[i] + dataCount); } totalData += dataCount; } } sb.Append(MACRO_DEFINES); sb.Append(namespaceName); WriteHeader(sliceCoordinates, preProcessedPalette, totalData, compressionType, destBpp, sb); WritePalette(preProcessedPalette, sb); // Write width { sb.Append(VAR_WIDTHMAP); sb.Append(namespaceTabs + "{\n"); sb.Append(namespaceTabs + TAB_CHAR); for (int i = 0; i < sliceCoordinates.Length; ++i) { int spriteWidth = sliceCoordinates[i].width; sb.AppendFormat("{0}, ", spriteWidth); if ((i + 1) % c_arrayNewlineCount == 0) { sb.AppendFormat("\n" + namespaceTabs + TAB_CHAR); } } sb.Append("\n"); sb.Append(namespaceTabs + "};\n\n"); } // Write height { sb.Append(VAR_HEIGHTMAP); sb.Append(namespaceTabs + "{\n"); sb.Append(namespaceTabs + TAB_CHAR); for (int i = 0; i < sliceCoordinates.Length; ++i) { int spriteHeight = sliceCoordinates[i].height; // Todo sb.AppendFormat("{0}, ", spriteHeight); if ((i + 1) % c_arrayNewlineCount == 0) { sb.AppendFormat("\n" + namespaceTabs + TAB_CHAR); } } sb.Append("\n"); sb.Append(namespaceTabs + "};\n\n"); } // Write offsets { const string tabs = namespaceTabs + TAB_CHAR; sb.Append(VAR_OFFSETS); sb.Append(namespaceTabs + "{\n" + tabs); for (int i = 0; i < dataOffsets.Count; i++) { sb.AppendFormat("{0}, ", dataOffsets[i]); if ((i + 1) % c_arrayNewlineCount == 0) { sb.AppendFormat("\n" + tabs); } } sb.Append('\n' + namespaceTabs + "};\n\n"); } // Write data { sb.Append(VAR_DATA); sb.Append(namespaceTabs + "{\n"); foreach (StringBuilder dataSB in spriteData) { sb.Append(dataSB.ToString()); } sb.Append(namespaceTabs + "};\n\n"); } sb.Append("}\n"); Console.WriteLine("Sprite \"" + outputPath + "\" successfully converted"); File.WriteAllText(outputPath, sb.ToString()); }
int WriteSpriteData( StringBuilder sbOutput, Bitmap bitmap, Color[] palette, int width, int height, int xPos, int yPos, Compression.CompressionType compressionType, uint destBpp) { const string tabs = namespaceTabs; int tilesWide = width / TileConfig.c_TILEWIDTH; int tilesTall = height / TileConfig.c_TILEHEIGHT; int totalTiles = (width * height) / (TileConfig.c_TILEWIDTH * TileConfig.c_TILEHEIGHT); int hexCount = 0; List <int> colourPaletteIndicies = new List <int>(); sbOutput.Append(namespaceTabs + TAB_CHAR); for (int tileY = 0; tileY < tilesTall; ++tileY) { for (int tileX = 0; tileX < tilesWide; ++tileX) { int tileXOffset = xPos + tileX * TileConfig.c_TILEWIDTH; int tileYOffset = yPos + tileY * TileConfig.c_TILEHEIGHT; for (int y = 0; y < TileConfig.c_TILEHEIGHT; ++y) { for (int x = 0; x < TileConfig.c_TILEWIDTH; ++x) { Color color = bitmap.GetPixel(tileXOffset + x, tileYOffset + y); int index = PaletteHelper.ColorToPaletteIndex(palette, color); colourPaletteIndicies.Add(index); } } } } List <UInt32> compressedIndicies; switch (compressionType) { case Compression.CompressionType.BitPacked: { Compression.BitPack(colourPaletteIndicies, destBpp, out compressedIndicies); } break; default: throw new NotImplementedException(); } foreach (var hexNum in compressedIndicies) { sbOutput.AppendFormat("0x{0:X8}, ", hexNum); if ((hexCount + 1) % c_arrayNewlineCount == 0) { sbOutput.Append("\n\t" + tabs); } ++hexCount; } sbOutput.Append("\n\n"); return(hexCount); }
public void Convert(string inputPath, string outputPath, Bitmap bitmap, UVs[] sliceCoordinates) { CppWriter cppWriter = new CppWriter(Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath)), outputPath); Size size = bitmap.Size; if (size.Width % TileConfig.TileWidth != 0 || size.Height % TileConfig.TileHeight != 0) { throw new Exception("Size not compatible with GBA tiles. Width and height of pixels must be multiples of 8."); } Console.WriteLine("Processing colour palette"); int xStart = 0; int yStart = 0; int width = bitmap.Width; int height = bitmap.Height; Color[] preProcessedPalette = PaletteHelper.GeneratePaletteFromImage(bitmap, xStart, yStart, width, height); // Validate pallet length { if (preProcessedPalette.Length > 256) { throw new Exception("Palette length out of range for the GBA"); } // Todo, currently not supported if (preProcessedPalette.Length > 16) { throw new Exception("Palette length out of range for 4bbp format"); } } Console.WriteLine(String.Format("Palette length: {0}", preProcessedPalette.Length)); Compression.CompressionType compressionType = Compression.CompressionType.BitPacked; uint maxColours = MathX.IsPowerOf2((uint)preProcessedPalette.Length) ? (uint)preProcessedPalette.Length : MathX.NextPowerOf2((uint)preProcessedPalette.Length); uint destBpp = (uint)MathX.IndexOfHighestSetBit(maxColours); if (!MathX.IsPowerOf2(destBpp)) { destBpp = MathX.NextPowerOf2(destBpp); } Console.WriteLine(string.Format("Compression type = {0}", compressionType.ToString())); Console.WriteLine(string.Format("Destination Bit Depth = {0}", destBpp)); List <int> dataOffsets = new List <int>(); List <List <UInt32> > spriteData = new List <List <UInt32> >(); dataOffsets.Add(0); int totalData = 0; // Collect data and add offsets { Console.WriteLine("Processing sprite data"); for (int i = 0; i < sliceCoordinates.Length; ++i) { StringBuilder dataSb = new StringBuilder(); UVs slice = sliceCoordinates[i]; int spriteWidth = slice.width, spriteHeight = slice.height; List <UInt32> data = WriteSpriteData(bitmap, preProcessedPalette, spriteWidth, spriteHeight, slice.x, slice.y, compressionType, destBpp); spriteData.Add(data); // Add offsets if (i < sliceCoordinates.Length - 1) { dataOffsets.Add(dataOffsets[i] + data.Count); } totalData += data.Count; } } WriteHeader(cppWriter, sliceCoordinates, preProcessedPalette, totalData, compressionType, destBpp); WritePalette(cppWriter, preProcessedPalette); // Write width { for (int i = 0; i < sliceCoordinates.Length; ++i) { int spriteWidth = sliceCoordinates[i].width; cppWriter.Write((byte)spriteWidth); } } // Write height { for (int i = 0; i < sliceCoordinates.Length; ++i) { int spriteHeight = sliceCoordinates[i].height; cppWriter.Write((byte)spriteHeight); } } // Write offsets { for (int i = 0; i < dataOffsets.Count; i++) { cppWriter.Write((UInt32)dataOffsets[i]); } } // Write data { foreach (var dataList in spriteData) { foreach (UInt32 data in dataList) { cppWriter.Write((UInt32)data); } } } Console.WriteLine("Sprite \"" + outputPath + "\" successfully converted"); cppWriter.Finalise(); }
public void Convert(string inputPath, string outputPath, Bitmap inputBitmap) { string namespaceName = string.Format(NAMESPACE_FORMAT, Path.GetFileName(Path.GetFileNameWithoutExtension(inputPath))); List <Bitmap> bitmaps = new List <Bitmap>(); bitmaps.Add(inputBitmap); List <ProcessedPaletteContainer> bitmapPalettes = new List <ProcessedPaletteContainer>(); Console.WriteLine("Processing master palette"); // Validate bitmaps and collect palettes for (int bitmapIndex = 0; bitmapIndex < bitmaps.Count; ++bitmapIndex) { Bitmap bitmap = bitmaps[bitmapIndex]; Size size = bitmap.Size; if (size.Width % TileConfig.c_TILEWIDTH != 0 || size.Height % TileConfig.c_TILEHEIGHT != 0) { throw new Exception("Size not compatible with GBA tiles. Width and height of pixels must be multiples of 8."); } int xStart = 0; int yStart = 0; int width = bitmap.Width; int height = bitmap.Height; Color[] preProcessedPalette = PaletteHelper.GeneratePaletteFromImage(bitmap, xStart, yStart, width, height); // Validate pallet length { if (preProcessedPalette.Length > PaletteHelper.MAX_PALETTE_LENGTH) { throw new Exception(string.Format("Palette length ({0}) out of range for the GBA ({1})", preProcessedPalette.Length, PaletteHelper.MAX_PALETTE_LENGTH)); } } ProcessedPaletteContainer palContainer = new ProcessedPaletteContainer(); palContainer.bitmapIndex = bitmapIndex; palContainer.palette = preProcessedPalette; bitmapPalettes.Add(palContainer); } // Sort bitmap palette. Anything more than 16 colours should be grouped next to each other. Less than 16 should always be a full 16. bitmapPalettes.Sort(new ProcessedPaletteComparer()); // Get palettes of each image, merge into a master palette List <Color> masterPaletteList = new List <Color>(); List <ProcessedBitmapContainer> processedBitmapList = new List <ProcessedBitmapContainer>(); { Color transparencyColour = Color.FromArgb(0); for (int i = 0; i < bitmapPalettes.Count; ++i) { var bp = bitmapPalettes[i]; bool pal4bbp = bp.palette.Length <= PaletteHelper.PALETTE_LENGTH_4BBP; if (pal4bbp) { // Make sure our 4bbp palette align properly while (masterPaletteList.Count % PaletteHelper.PALETTE_LENGTH_4BBP != 0) { masterPaletteList.Add(transparencyColour); } } int currentPaletteIndex = masterPaletteList.Count / PaletteHelper.PALETTE_LENGTH_4BBP; masterPaletteList.AddRange(bp.palette); ProcessedBitmapContainer pbc = new ProcessedBitmapContainer(); pbc.bitmapIndex = bp.bitmapIndex; pbc.paletteIndex = pal4bbp ? currentPaletteIndex : -1; pbc.bitmap = bitmaps[bp.bitmapIndex]; processedBitmapList.Add(pbc); } } Color[] masterPalette = masterPaletteList.ToArray(); Console.WriteLine("Total colours found = " + masterPalette.Length); Console.WriteLine("Processing master tileset"); // Get all unique tiles sorted via palette indicies. Need to check if local palette was greater than 16 or not List <Tile> uniqueTileSetList = new List <Tile>(); foreach (ProcessedBitmapContainer pbc in processedBitmapList) { Tile[,] rawTileMap = BitmapToTileArray(pbc.bitmap, masterPalette, pbc.paletteIndex); pbc.rawTileMap = rawTileMap; FillUniqueTileset(rawTileMap, uniqueTileSetList); } Tile[] masterTileSet = uniqueTileSetList.ToArray(); if (masterTileSet.Length > MAX_UNIQUE_TILES) { throw new Exception(string.Format("Too many tiles present in tilemap. Max tiles = {0}. Total titles found = {1}", MAX_UNIQUE_TILES, masterTileSet.Length)); } Console.WriteLine("Total unique tiles = " + masterTileSet.Length); Console.WriteLine("Processing tilemaps"); // Generate tilemaps from master list. Remember palette index, but we should be able to forget about it. We can overlap tiles that are the same but different colours. List <TileMap> tileMapList = new List <TileMap>(); foreach (ProcessedBitmapContainer pbc in processedBitmapList) { TileMap tilemap = new TileMap(pbc.rawTileMap, masterTileSet, pbc.paletteIndex); tileMapList.Add(tilemap); } Compression.CompressionType compressionType = Compression.CompressionType.BitPacked; uint destBpp = 4; foreach (Tile tile in masterTileSet) { foreach (int index in tile.paletteIndicies) { if (index >= PaletteHelper.PALETTE_LENGTH_4BBP) { destBpp = 8; goto WriteMasterTileSetToSb; } } } WriteMasterTileSetToSb: int tilesetLength; StringBuilder tilesetSb = new StringBuilder(); WriteTileSet(masterTileSet, tilesetSb, compressionType, destBpp, out tilesetLength); StringBuilder sb = new StringBuilder(); sb.Append(MACRO_DEFINES); sb.Append(namespaceName); WriteHeader(masterPalette, tilesetLength, sb); WritePalette(masterPalette, sb); // Real write tileset sb.Append(tilesetSb); // Write tile maps WriteMapData(tileMapList, sb); sb.Append("}\n"); Console.WriteLine("Tilemap \"" + outputPath + "\" successfully converted"); File.WriteAllText(outputPath, sb.ToString()); }