private static RoadTileGenre[] GetTileGenres(byte[] data, int start, int size) { RoadTileGenre[] tileGenres = new RoadTileGenre[size]; for (int i = 0; i < size; i++) { tileGenres[i] = (RoadTileGenre)data[start + i]; } return(tileGenres); }
private void Init(byte[] romBuffer, Offsets offsets, TextCollection names) { // TODO: Retrieve order dynamically from the ROM int[] reorder = { 5, 4, 6, 9, 8, 10, 7, 12 }; // To reorder the themes, as they're not in the same order as the names int[] paletteOffsets = Utilities.ReadBlockOffset(romBuffer, offsets[Offset.ThemePalettes], this.themes.Length); int[] roadTileGfxOffsets = Utilities.ReadBlockOffset(romBuffer, offsets[Offset.ThemeRoadGraphics], this.themes.Length); int[] bgTileGfxOffsets = Utilities.ReadBlockOffset(romBuffer, offsets[Offset.ThemeBackgroundGraphics], this.themes.Length); int[] bgLayoutOffsets = Utilities.ReadBlockOffset(romBuffer, offsets[Offset.ThemeBackgroundLayouts], this.themes.Length); bool roadTilesetHackApplied = Themes.IsRoadTilesetHackApplied(romBuffer, offsets); byte[] commonRoadTilePaletteIndexes; byte[][] commonRoadTileGfx; if (roadTilesetHackApplied) { commonRoadTilePaletteIndexes = null; commonRoadTileGfx = null; } else { int commonRoadTileUpperByte = offsets[Offset.CommonTilesetGraphicsUpperByte]; int commonRoadTileLowerBytes = offsets[Offset.CommonTilesetGraphicsLowerBytes]; int commonRoadTileOffset = Utilities.BytesToOffset( romBuffer[commonRoadTileLowerBytes], romBuffer[commonRoadTileLowerBytes + 1], romBuffer[commonRoadTileUpperByte] ); byte[] commonRoadTileData = Codec.Decompress(romBuffer, commonRoadTileOffset); commonRoadTilePaletteIndexes = Themes.GetPaletteIndexes(commonRoadTileData, RoadTileset.CommonTileCount); commonRoadTileGfx = Utilities.ReadBlockGroupUntil(commonRoadTileData, RoadTileset.TileCount, -1, 32); } bool tileGenresRelocated = Themes.AreTileGenresRelocated(romBuffer, offsets[Offset.TileGenreLoad]); byte[] roadTileGenreData; byte[][] roadTileGenreIndexes; RoadTileGenre[] commonRoadTileGenres; if (tileGenresRelocated) { roadTileGenreData = null; roadTileGenreIndexes = null; commonRoadTileGenres = null; } else { roadTileGenreData = Codec.Decompress(romBuffer, offsets[Offset.TileGenres]); roadTileGenreIndexes = Utilities.ReadBlockGroup(romBuffer, offsets[Offset.TileGenreIndexes], 2, Theme.Count * 2); commonRoadTileGenres = Themes.GetTileGenres(roadTileGenreData, 0, RoadTileset.CommonTileCount); } for (int i = 0; i < this.themes.Length; i++) { TextItem nameItem = names[reorder[i]]; // HACK: Force the length to 512 in case the color palette data in the ROM is corrupt ("EarthBound Kart Beta" has this issue) byte[] paletteData = Codec.Decompress(romBuffer, paletteOffsets[i], 512); Palettes palettes = new Palettes(paletteData); byte[] roadTileData = Codec.Decompress(romBuffer, roadTileGfxOffsets[i]); byte[][] roadTileGfx = Utilities.ReadBlockGroupUntil(roadTileData, RoadTileset.TileCount, -1, 32); byte[] allRoadTilePaletteIndexes; byte[][] allRoadTileGfx; if (roadTilesetHackApplied) { allRoadTilePaletteIndexes = Themes.GetPaletteIndexes(roadTileData, RoadTileset.TileCount); allRoadTileGfx = roadTileGfx; } else { byte[] roadTilePaletteIndexes = Themes.GetPaletteIndexes(roadTileData, RoadTileset.ThemeTileCount); allRoadTilePaletteIndexes = new byte[RoadTileset.TileCount]; Buffer.BlockCopy(roadTilePaletteIndexes, 0, allRoadTilePaletteIndexes, 0, RoadTileset.ThemeTileCount); Buffer.BlockCopy(commonRoadTilePaletteIndexes, 0, allRoadTilePaletteIndexes, RoadTileset.ThemeTileCount, RoadTileset.CommonTileCount); allRoadTileGfx = new byte[RoadTileset.TileCount][]; Array.Copy(roadTileGfx, 0, allRoadTileGfx, 0, roadTileGfx.Length); // Clone the commonRoadTileGfx jagged array, // because we don't want theme-specific tile graphics update to affect other themes byte[][] commonRoadTileGfxClone = new byte[commonRoadTileGfx.Length][]; for (int j = 0; j < commonRoadTileGfxClone.Length; j++) { commonRoadTileGfxClone[j] = Utilities.ReadBlock(commonRoadTileGfx[j], 0, commonRoadTileGfx[j].Length); } Array.Copy(commonRoadTileGfxClone, 0, allRoadTileGfx, RoadTileset.ThemeTileCount, commonRoadTileGfxClone.Length); // Set empty tile default graphics value for (int j = roadTileGfx.Length; j < RoadTileset.ThemeTileCount; j++) { allRoadTileGfx[j] = new byte[32]; } } RoadTileGenre[] allRoadTileGenres; if (tileGenresRelocated) { int tileGenreOffset = offsets[Offset.TileGenresRelocated] + i * RoadTileset.TileCount; allRoadTileGenres = Themes.GetTileGenres(romBuffer, tileGenreOffset, RoadTileset.TileCount); } else { int roadTileGenreIndex = roadTileGenreIndexes[i][0] + (roadTileGenreIndexes[i][1] << 8); RoadTileGenre[] roadTileGenres = Themes.GetTileGenres(roadTileGenreData, roadTileGenreIndex, roadTileGfx.Length); allRoadTileGenres = new RoadTileGenre[RoadTileset.TileCount]; Array.Copy(roadTileGenres, 0, allRoadTileGenres, 0, roadTileGenres.Length); Array.Copy(commonRoadTileGenres, 0, allRoadTileGenres, RoadTileset.ThemeTileCount, commonRoadTileGenres.Length); // Set empty tile default genre value for (int j = roadTileGfx.Length; j < RoadTileset.ThemeTileCount; j++) { allRoadTileGenres[j] = RoadTileGenre.Road; } } RoadTileset roadTileset = Themes.GetRoadTileset(palettes, allRoadTilePaletteIndexes, allRoadTileGfx, allRoadTileGenres); byte[] bgTileData = Codec.Decompress(romBuffer, bgTileGfxOffsets[i]); byte[][] bgTileGfx = Utilities.ReadBlockGroupUntil(bgTileData, 0, -1, 16); BackgroundTileset bgTileset = Themes.GetBackgroundTileset(palettes, bgTileGfx); byte[] bgLayoutData = Codec.Decompress(romBuffer, bgLayoutOffsets[i]); BackgroundLayout bgLayout = new BackgroundLayout(bgLayoutData); Background background = new Background(bgTileset, bgLayout); this.themes[i] = new Theme(nameItem, palettes, roadTileset, background); } }