public static GBAMapData GenerateMapData(IList <TileMap> tilemaps, int paletteBankIndexOffset) { List <GBAScreenEntry> seList = new List <GBAScreenEntry>(); List <int> mapStartOffsets = new List <int>(); // Write map sizes List <int> widthLists = new List <int>(); List <int> heightLists = new List <int>(); List <bool> mapIsDynamic = new List <bool>(); for (int tilemapIndex = 0; tilemapIndex < tilemaps.Count; ++tilemapIndex) { var tilemap = tilemaps[tilemapIndex]; int paletteIndex = tilemap.paletteIndex + paletteBankIndexOffset; if (paletteIndex >= PaletteHelper.MAX_PALETTE_INDEX) { throw new Exception(string.Format("Palette index {0} is not valid for map data", paletteIndex)); } int width = tilemap.mapData.GetLength(0); int height = tilemap.mapData.GetLength(1); widthLists.Add(width); heightLists.Add(height); mapStartOffsets.Add(seList.Count); bool widthValidForNesting = width % GBA_MAP_TILE_WIDTH == 0 && width >= REG_TILEMAP_MIN_SIZE && width <= REG_TILEMAP_MAX_SIZE; bool heightValidForNesting = height % GBA_MAP_TILE_HEIGHT == 0 && height >= REG_TILEMAP_MIN_SIZE && height <= REG_TILEMAP_MAX_SIZE; #if FORCE_DYNAMIC_RENDERING bool performGbaNesting = false; #else bool performGbaNesting = widthValidForNesting && heightValidForNesting; // Disable for dynamic maps #endif mapIsDynamic.Add(!performGbaNesting); if (performGbaNesting) { // GBA nesting: https://www.coranac.com/tonc/text/regbg.htm 9.3.1 for (int mapStartY = 0; mapStartY < tilemap.mapData.GetLength(1); mapStartY += GBA_MAP_TILE_HEIGHT) { for (int mapStartX = 0; mapStartX < tilemap.mapData.GetLength(0); mapStartX += GBA_MAP_TILE_WIDTH) { for (int j = mapStartY; j < mapStartY + GBA_MAP_TILE_HEIGHT; ++j) { for (int i = mapStartX; i < mapStartX + GBA_MAP_TILE_WIDTH; ++i) { var currentMapData = tilemap.mapData[i, j]; GBAScreenEntry screenEntry = new GBAScreenEntry(); screenEntry.SetTileIndex(currentMapData.tilesetIndex); if ((currentMapData.flags & TileMap.FlippingFlags.Horizontal) != 0) { screenEntry.SetHFlipFlag(); } if ((currentMapData.flags & TileMap.FlippingFlags.Vertical) != 0) { screenEntry.SetVFlipFlag(); } if (tilemap.paletteIndex >= 0) { screenEntry.SetPalIndex(paletteIndex); // May be wrong when merging the palette } seList.Add(screenEntry); } } } } } else { for (int mapY = 0; mapY < tilemap.mapData.GetLength(1); ++mapY) { for (int mapX = 0; mapX < tilemap.mapData.GetLength(0); ++mapX) { var currentMapData = tilemap.mapData[mapX, mapY]; GBAScreenEntry screenEntry = new GBAScreenEntry(); screenEntry.SetTileIndex(currentMapData.tilesetIndex); if ((currentMapData.flags & TileMap.FlippingFlags.Horizontal) != 0) { screenEntry.SetHFlipFlag(); } if ((currentMapData.flags & TileMap.FlippingFlags.Vertical) != 0) { screenEntry.SetVFlipFlag(); } if (tilemap.paletteIndex >= 0) { screenEntry.SetPalIndex(paletteIndex); } seList.Add(screenEntry); } } } Console.WriteLine("Processed tilemap {0}:", tilemapIndex); if (performGbaNesting) { Console.WriteLine("\tStatic/GBA nested map"); } else { Console.WriteLine("\tDynamically rendered map"); } } GBAScreenEntry[] mapEntries = seList.ToArray(); GBAMapData generatedMapData; generatedMapData.screenEntries = mapEntries; generatedMapData.mapIsDynamic = mapIsDynamic; generatedMapData.widthLists = widthLists; generatedMapData.heightLists = heightLists; return(generatedMapData); }
void WriteMapData(List <TileMap> tilemaps, StringBuilder sb) { const string tabs = namespaceTabs; List <GBAScreenEntry> seList = new List <GBAScreenEntry>(); List <int> mapStartOffsets = new List <int>(); // Write map sizes StringBuilder widthSb = new StringBuilder(); StringBuilder heightSb = new StringBuilder(); widthSb.Append(VAR_MAPWIDTHS); widthSb.Append(namespaceTabs + "{\n"); widthSb.Append(namespaceTabs + TAB_CHAR); heightSb.Append(VAR_MAPHEIGHTS); heightSb.Append(namespaceTabs + "{\n"); heightSb.Append(namespaceTabs + TAB_CHAR); foreach (var tilemap in tilemaps) { widthSb.AppendFormat("{0}, ", tilemap.mapData.GetLength(0)); heightSb.AppendFormat("{0}, ", tilemap.mapData.GetLength(1)); mapStartOffsets.Add(seList.Count); bool performGbaNesting = false; // Disable for dynamic maps if (performGbaNesting) { // GBA nesting: https://www.coranac.com/tonc/text/regbg.htm 9.3.1 for (int mapStartY = 0; mapStartY < tilemap.mapData.GetLength(1); mapStartY += GBA_MAP_TILE_HEIGHT) { for (int mapStartX = 0; mapStartX < tilemap.mapData.GetLength(0); mapStartX += GBA_MAP_TILE_WIDTH) { for (int j = mapStartY; j < mapStartY + GBA_MAP_TILE_HEIGHT; ++j) { for (int i = mapStartX; i < mapStartX + GBA_MAP_TILE_WIDTH; ++i) { var currentMapData = tilemap.mapData[i, j]; GBAScreenEntry screenEntry = new GBAScreenEntry(); screenEntry.SetTileIndex(currentMapData.tilesetIndex); if ((currentMapData.flags & TileMap.FlippingFlags.Horizontal) != 0) { screenEntry.SetHFlipFlag(); } if ((currentMapData.flags & TileMap.FlippingFlags.Vertical) != 0) { screenEntry.SetVFlipFlag(); } if (tilemap.paletteIndex >= 0) { screenEntry.SetPalIndex(tilemap.paletteIndex); } seList.Add(screenEntry); } } } } } else { for (int mapY = 0; mapY < tilemap.mapData.GetLength(1); ++mapY) { for (int mapX = 0; mapX < tilemap.mapData.GetLength(0); ++mapX) { var currentMapData = tilemap.mapData[mapX, mapY]; GBAScreenEntry screenEntry = new GBAScreenEntry(); screenEntry.SetTileIndex(currentMapData.tilesetIndex); if ((currentMapData.flags & TileMap.FlippingFlags.Horizontal) != 0) { screenEntry.SetHFlipFlag(); } if ((currentMapData.flags & TileMap.FlippingFlags.Vertical) != 0) { screenEntry.SetVFlipFlag(); } if (tilemap.paletteIndex >= 0) { screenEntry.SetPalIndex(tilemap.paletteIndex); } seList.Add(screenEntry); } } } } { widthSb.Append("\n"); widthSb.Append(namespaceTabs + "};\n"); heightSb.Append("\n"); heightSb.Append(namespaceTabs + "};\n"); } GBAScreenEntry[] mapEntries = seList.ToArray(); sb.AppendFormat(VAR_MAPCOUNT, tilemaps.Count); sb.AppendFormat(VAR_HEADER_TILEMAPLENGTH_FORMAT, mapEntries.Length); sb.Append(widthSb.ToString()); sb.Append("\n"); sb.Append(heightSb.ToString()); sb.Append("\n"); sb.Append(VAR_TILEMAP); sb.Append(namespaceTabs + "{\n\t" + namespaceTabs); int hexCount = 0; foreach (var mapEntry in mapEntries) { sb.AppendFormat("0x{0:X4}, ", mapEntry.m_data); if ((hexCount + 1) % c_arrayNewlineCount == 0) { sb.Append("\n\t" + tabs); } ++hexCount; } sb.Append("\n" + namespaceTabs + "};\n\n"); }