Exemple #1
0
        public override void SerializeImpl(SerializerObject s)
        {
            // Serialize ROM header
            base.SerializeImpl(s);

            // Get pointer table
            var pointerTable = PointerTables.GBARRR_PointerTable(s.GameSettings.GameModeSelection, Offset.file);

            // Serialize offset table
            OffsetTable = s.DoAt(pointerTable[GBARRR_Pointer.OffsetTable], () => s.SerializeObject <GBARRR_OffsetTable>(OffsetTable, name: nameof(OffsetTable)));

            // Serialize localization
            OffsetTable.DoAtBlock(s.Context, 3, size =>
                                  Localization = s.SerializeObject <GBARRR_LocalizationBlock>(Localization, name: nameof(Localization)));

            var gameMode = GBA_RRR_Manager.GetCurrentGameMode(s.GameSettings);

            if (gameMode == GBA_RRR_Manager.GameMode.Game || gameMode == GBA_RRR_Manager.GameMode.Village)
            {
                // Serialize level info
                VillageLevelInfo = s.DoAt(pointerTable[GBARRR_Pointer.VillageLevelInfo],
                                          () => s.SerializeObjectArray <GBARRR_LevelInfo>(VillageLevelInfo, 3,
                                                                                          name: nameof(VillageLevelInfo)));
                LevelInfo = s.DoAt(pointerTable[GBARRR_Pointer.LevelInfo],
                                   () => s.SerializeObjectArray <GBARRR_LevelInfo>(LevelInfo, 32, name: nameof(LevelInfo)));
                LevelProperties = s.DoAt(pointerTable[GBARRR_Pointer.LevelProperties],
                                         () => s.SerializeObjectArray <GBARRR_LevelProperties>(LevelProperties, 32, name: nameof(LevelProperties)));

                // Get the current level info
                var lvlInfo = GetLevelInfo(s.GameSettings);

                // Serialize tile maps
                OffsetTable.DoAtBlock(s.Context, lvlInfo.LevelTilesetIndex, size =>
                                      LevelTileset = s.SerializeObject <GBARRR_Tileset>(LevelTileset, name: nameof(LevelTileset),
                                                                                        onPreSerialize: x => x.BlockSize = size));
                OffsetTable.DoAtBlock(s.Context, lvlInfo.BG0TilesetIndex, size =>
                                      BG0TileSet = s.SerializeObject <GBARRR_Tileset>(BG0TileSet, name: nameof(BG0TileSet),
                                                                                      onPreSerialize: x => x.BlockSize = size));
                OffsetTable.DoAtBlock(s.Context, lvlInfo.FGTilesetIndex, size =>
                                      FGTileSet = s.SerializeObject <GBARRR_Tileset>(FGTileSet, name: nameof(FGTileSet),
                                                                                     onPreSerialize: x => x.BlockSize = size));
                OffsetTable.DoAtBlock(s.Context, lvlInfo.BG1TilesetIndex, size =>
                                      BG1TileSet = s.SerializeObject <GBARRR_Tileset>(BG1TileSet, name: nameof(BG1TileSet),
                                                                                      onPreSerialize: x => x.BlockSize = size));

                // Serialize level scene
                OffsetTable.DoAtBlock(s.Context, lvlInfo.ObjectArrayIndex,
                                      size => ObjectArray = s.SerializeObject <GBARRR_ObjectArray>(ObjectArray, name: nameof(ObjectArray)));

                // Serialize maps
                OffsetTable.DoAtBlock(s.Context, lvlInfo.BG0MapIndex, size =>
                                      BG0Map = s.SerializeObject <GBARRR_BGMapBlock>(BG0Map, name: nameof(BG0Map)));
                OffsetTable.DoAtBlock(s.Context, lvlInfo.BG1MapIndex, size =>
                                      BG1Map = s.SerializeObject <GBARRR_BGMapBlock>(BG1Map, name: nameof(BG1Map)));
                OffsetTable.DoAtBlock(s.Context, lvlInfo.CollisionMapIndex, size =>
                                      CollisionMap = s.SerializeObject <GBARRR_MapBlock>(CollisionMap, name: nameof(CollisionMap),
                                                                                         onPreSerialize: x => x.Type = GBARRR_MapBlock.MapType.Collision));
                OffsetTable.DoAtBlock(s.Context, lvlInfo.LevelMapIndex, size =>
                                      LevelMap = s.SerializeObject <GBARRR_MapBlock>(LevelMap, name: nameof(LevelMap),
                                                                                     onPreSerialize: x => x.Type = GBARRR_MapBlock.MapType.Tiles));
                OffsetTable.DoAtBlock(s.Context, lvlInfo.FGMapIndex, size =>
                                      FGMap = s.SerializeObject <GBARRR_MapBlock>(FGMap, name: nameof(FGMap),
                                                                                  onPreSerialize: x => x.Type = GBARRR_MapBlock.MapType.Foreground));

                // Serialize palettes
                var tilePalIndex = GetLevelTilePaletteOffsetIndex(s.GameSettings);
                if (tilePalIndex != null)
                {
                    OffsetTable.DoAtBlock(s.Context, tilePalIndex.Value, size =>
                                          TilePalette = s.SerializeObjectArray <RGBA5551Color>(TilePalette, 0x100, name: nameof(TilePalette)));
                }
                OffsetTable.DoAtBlock(s.Context, lvlInfo.SpritePaletteIndex, size =>
                                      SpritePalette = s.SerializeObjectArray <RGBA5551Color>(SpritePalette, 0x100, name: nameof(SpritePalette)));

                if (AnimatedPalettes == null)
                {
                    AnimatedPalettes = new RGBA5551Color[5][];
                }

                for (int i = 0; i < AnimatedPalettes.Length; i++)
                {
                    OffsetTable.DoAtBlock(s.Context, 764 + i, size =>
                                          AnimatedPalettes[i] = s.SerializeObjectArray <RGBA5551Color>(AnimatedPalettes[i], 0x100, name: $"{nameof(AnimatedPalettes)}[{i}]"));
                }

                // Serialize tables
                s.DoAt(pointerTable[GBARRR_Pointer.GraphicsTables], () =>
                {
                    var counts = new uint[] { 0x47, 0x40, 0x45, 0x44, 0x50, 0x42 };

                    if (GraphicsTable0 == null)
                    {
                        GraphicsTable0 = new GBARRR_GraphicsTableEntry[counts.Length][];
                    }
                    if (GraphicsTable1 == null)
                    {
                        GraphicsTable1 = new uint[counts.Length][];
                    }
                    if (GraphicsTable2 == null)
                    {
                        GraphicsTable2 = new uint[counts.Length][];
                    }
                    if (GraphicsTable3 == null)
                    {
                        GraphicsTable3 = new uint[counts.Length][];
                    }
                    if (GraphicsTable4 == null)
                    {
                        GraphicsTable4 = new uint[counts.Length][];
                    }

                    for (int i = 0; i < counts.Length; i++)
                    {
                        GraphicsTable0[i] = s.SerializeObjectArray <GBARRR_GraphicsTableEntry>(GraphicsTable0[i],
                                                                                               counts[i], name: $"{nameof(GraphicsTable0)}[{i}]");
                        GraphicsTable1[i] = s.SerializeArray <uint>(GraphicsTable1[i], counts[i],
                                                                    name: $"{nameof(GraphicsTable1)}[{i}]");
                        GraphicsTable2[i] = s.SerializeArray <uint>(GraphicsTable2[i], counts[i],
                                                                    name: $"{nameof(GraphicsTable2)}[{i}]");
                        GraphicsTable3[i] = s.SerializeArray <uint>(GraphicsTable3[i], counts[i],
                                                                    name: $"{nameof(GraphicsTable3)}[{i}]");
                        GraphicsTable4[i] = s.SerializeArray <uint>(GraphicsTable4[i], counts[i],
                                                                    name: $"{nameof(GraphicsTable4)}[{i}]");
                        if (i == 2 || i == 3)
                        {
                            s.Serialize <uint>(1, name: "Padding");
                        }
                    }
                });
            }
            else if (gameMode == GBA_RRR_Manager.GameMode.Mode7)
            {
                // Serialize pointer tables
                Mode7_MapTilesPointers         = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_MapTiles], () => s.SerializePointerArray(Mode7_MapTilesPointers, 3, name: nameof(Mode7_MapTilesPointers)));
                Mode7_BG1TilesPointers         = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_BG1Tiles], () => s.SerializePointerArray(Mode7_BG1TilesPointers, 3, name: nameof(Mode7_BG1TilesPointers)));
                Mode7_BG1MapPointers           = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_Bg1Map], () => s.SerializePointerArray(Mode7_BG1MapPointers, 3, name: nameof(Mode7_BG1MapPointers)));
                Mode7_BG0TilesPointers         = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_BG0Tiles], () => s.SerializePointerArray(Mode7_BG0TilesPointers, 3, name: nameof(Mode7_BG0TilesPointers)));
                Mode7_BG0MapPointers           = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_BG0Map], () => s.SerializePointerArray(Mode7_BG0MapPointers, 3, name: nameof(Mode7_BG0MapPointers)));
                Mode7_MapPointers              = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_MapData], () => s.SerializePointerArray(Mode7_MapPointers, 3, name: nameof(Mode7_MapPointers)));
                Mode7_CollisionMapDataPointers = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_CollisionMapData], () => s.SerializePointerArray(Mode7_CollisionMapDataPointers, 3, name: nameof(Mode7_CollisionMapDataPointers)));
                Mode7_MapPalettePointers       = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_TilePalette], () => s.SerializePointerArray(Mode7_MapPalettePointers, 3, name: nameof(Mode7_MapPalettePointers)));
                Mode7_BG1PalettePointers       = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_BG1Palette], () => s.SerializePointerArray(Mode7_BG1PalettePointers, 3, name: nameof(Mode7_BG1PalettePointers)));
                Mode7_BG0PalettePointers       = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_BG0Palette], () => s.SerializePointerArray(Mode7_BG0PalettePointers, 3, name: nameof(Mode7_BG0PalettePointers)));
                Mode7_ObjectsPointers          = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_Objects], () => s.SerializePointerArray(Mode7_ObjectsPointers, 3, name: nameof(Mode7_ObjectsPointers)));
                Mode7_CollisionTypesPointers   = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_CollisionTypesArray], () => s.SerializePointerArray(Mode7_CollisionTypesPointers, 3, name: nameof(Mode7_CollisionTypesPointers)));
                Mode7_WaypointsCount           = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_WaypointsCount], () => s.SerializeArray <short>(Mode7_WaypointsCount, 3, name: nameof(Mode7_WaypointsCount)));
                Mode7_WaypointsPointers        = s.DoAt(pointerTable[GBARRR_Pointer.Mode7_Waypoints], () => s.SerializePointerArray(Mode7_WaypointsPointers, 3, name: nameof(Mode7_WaypointsPointers)));

                // Serialize compressed tile data
                s.DoAt(Mode7_MapTilesPointers[s.GameSettings.Level], () => {
                    s.DoEncoded(new RNCEncoder(hasHeader: false), () => Mode7_MapTiles = s.SerializeArray <byte>(Mode7_MapTiles, s.CurrentLength, name: nameof(Mode7_MapTiles)));
                });
                s.DoAt(Mode7_BG0TilesPointers[s.GameSettings.Level], () => {
                    s.DoEncoded(new RNCEncoder(hasHeader: false), () => Mode7_BG0Tiles = s.SerializeArray <byte>(Mode7_BG0Tiles, s.CurrentLength, name: nameof(Mode7_BG0Tiles)));
                });
                s.DoAt(Mode7_BG1TilesPointers[s.GameSettings.Level], () => {
                    s.DoEncoded(new RNCEncoder(hasHeader: false), () => Mode7_BG1Tiles = s.SerializeArray <byte>(Mode7_BG1Tiles, s.CurrentLength, name: nameof(Mode7_BG1Tiles)));
                });

                // Serialize map data
                if (s.GameSettings.GameModeSelection == GameModeSelection.RaymanRavingRabbidsGBAEU)
                {
                    Mode7_MapData = s.DoAt(Mode7_MapPointers[s.GameSettings.Level], () => s.SerializeObjectArray <MapTile>(Mode7_MapData, 256 * 256, onPreSerialize: x => x.GBARRRType = GBARRR_MapBlock.MapType.Mode7Tiles, name: nameof(Mode7_MapData)));
                }
                else
                {
                    s.DoAt(Mode7_MapPointers[s.GameSettings.Level], () =>
                    {
                        s.DoEncoded(new RNCEncoder(hasHeader: false), () =>
                                    Mode7_MapData = s.SerializeObjectArray <MapTile>(Mode7_MapData, 256 * 256, onPreSerialize: x => x.GBARRRType = GBARRR_MapBlock.MapType.Mode7Tiles, name: nameof(Mode7_MapData)));
                    });
                }
                s.DoAt(Mode7_BG0MapPointers[s.GameSettings.Level], () =>
                {
                    s.DoEncoded(new RNCEncoder(hasHeader: false), () => Mode7_BG0MapData = s.SerializeObjectArray <MapTile>(Mode7_BG0MapData, 32 * 32,
                                                                                                                            onPreSerialize: x => x.GBARRRType = GBARRR_MapBlock.MapType.Foreground, name: nameof(Mode7_BG0MapData)));
                });
                s.DoAt(Mode7_BG1MapPointers[s.GameSettings.Level], () =>
                {
                    s.DoEncoded(new RNCEncoder(hasHeader: false), () => Mode7_BG1MapData = s.SerializeObjectArray <MapTile>(Mode7_BG1MapData, 32 * 32,
                                                                                                                            onPreSerialize: x => x.GBARRRType = GBARRR_MapBlock.MapType.Foreground,
                                                                                                                            name: nameof(Mode7_BG1MapData)));
                });
                s.DoAt(Mode7_ObjectsPointers[s.GameSettings.Level], () =>
                {
                    s.DoEncoded(new RNCEncoder(hasHeader: false), () => Mode7_Objects = s.SerializeObjectArray <GBARRR_Mode7Object>(Mode7_Objects, 141, name: nameof(Mode7_Objects)));
                });
                if (s.GameSettings.GameModeSelection == GameModeSelection.RaymanRavingRabbidsGBAEU)
                {
                    s.DoAt(Mode7_CollisionMapDataPointers[s.GameSettings.Level], () => {
                        Mode7_CollisionMapData = s.SerializeArray <ushort>(Mode7_CollisionMapData, 256 * 256, name: nameof(Mode7_CollisionMapData));
                    });
                }
                else
                {
                    s.DoAt(Mode7_CollisionMapDataPointers[s.GameSettings.Level], () => {
                        s.DoEncoded(new RNCEncoder(hasHeader: false), () =>
                                    Mode7_CollisionMapData = s.SerializeArray <ushort>(Mode7_CollisionMapData, 256 * 256, name: nameof(Mode7_CollisionMapData)));
                    });
                }
                s.DoAt(Mode7_CollisionTypesPointers[s.GameSettings.Level], () => {
                    s.DoEncoded(new RNCEncoder(hasHeader: false), () => Mode7_CollisionTypes = s.SerializeArray <byte>(Mode7_CollisionTypes, s.CurrentLength, name: nameof(Mode7_CollisionTypes)));
                });
                s.DoAt(Mode7_WaypointsPointers[s.GameSettings.Level], () => {
                    Mode7_Waypoints = s.SerializeObjectArray <GBARRR_Mode7Waypoint>(Mode7_Waypoints, Mode7_WaypointsCount[s.GameSettings.Level], name: nameof(Mode7_Waypoints));
                });

                // Serialize palettes
                Mode7_MapPalette = s.DoAt(Mode7_MapPalettePointers[s.GameSettings.Level], () => s.SerializeObjectArray <RGBA5551Color>(Mode7_MapPalette, 16 * 16, name: nameof(Mode7_MapPalette)));
                Mode7_BG1Palette = s.DoAt(Mode7_BG1PalettePointers[s.GameSettings.Level], () => s.SerializeObjectArray <RGBA5551Color>(Mode7_BG1Palette, 16, name: nameof(Mode7_BG1Palette)));
                Mode7_BG0Palette = s.DoAt(Mode7_BG0PalettePointers[s.GameSettings.Level], () => s.SerializeObjectArray <RGBA5551Color>(Mode7_BG0Palette, 16, name: nameof(Mode7_BG0Palette)));

                // Fill in full tilemap palette
                Mode7_TilemapPalette = new RGBA5551Color[16 * 16];

                for (int i = 0; i < 12 * 16; i++)
                {
                    Mode7_TilemapPalette[i] = Mode7_MapPalette[i];
                }
                for (int i = 0; i < 16; i++)
                {
                    Mode7_TilemapPalette[12 * 16 + i] = Mode7_BG0Palette[i];
                }
                for (int i = 0; i < 16; i++)
                {
                    Mode7_TilemapPalette[14 * 16 + i] = Mode7_BG1Palette[i];
                }
            }
            else if (gameMode == GBA_RRR_Manager.GameMode.Mode7Unused)
            {
                OffsetTable.DoAtBlock(s.Context, 1180, size =>
                {
                    ObjectArray   = s.SerializeObject <GBARRR_ObjectArray>(ObjectArray, onPreSerialize: x => x.IsUnusedMode7 = true, name: nameof(ObjectArray));
                    Mode7_MapData = s.SerializeObjectArray <MapTile>(Mode7_MapData, 256 * 256, onPreSerialize: x => x.GBARRRType = GBARRR_MapBlock.MapType.Foreground, name: nameof(Mode7_MapData));
                });
                OffsetTable.DoAtBlock(s.Context, 1181, size =>
                                      CollisionMap = s.SerializeObject <GBARRR_MapBlock>(CollisionMap, name: nameof(CollisionMap),
                                                                                         onPreSerialize: x => x.Type = GBARRR_MapBlock.MapType.Collision));

                OffsetTable.DoAtBlock(s.Context, 1177, size => BG0TileSet   = s.SerializeObject <GBARRR_Tileset>(BG0TileSet, onPreSerialize: x => x.BlockSize = size, name: nameof(BG0TileSet)));
                OffsetTable.DoAtBlock(s.Context, 1178, size => BG1TileSet   = s.SerializeObject <GBARRR_Tileset>(BG1TileSet, onPreSerialize: x => x.BlockSize = size, name: nameof(BG1TileSet)));
                OffsetTable.DoAtBlock(s.Context, 1179, size => LevelTileset = s.SerializeObject <GBARRR_Tileset>(LevelTileset, onPreSerialize: x => x.BlockSize = size, name: nameof(LevelTileset)));
            }
            else if (gameMode == GBA_RRR_Manager.GameMode.Menu)
            {
                Menu_Pointers = s.DoAt(pointerTable[GBARRR_Pointer.MenuArray], () => s.SerializePointerArray(Menu_Pointers, 15 * 3, name: nameof(Menu_Pointers)));

                var manager    = (GBA_RRR_Manager)s.GameSettings.GetGameManager;
                var menuLevels = manager.GetMenuLevels(s.GameSettings.Level);

                Menu_Tiles   = new byte[menuLevels.Length][];
                Menu_MapData = new MapTile[menuLevels.Length][];
                Menu_Palette = new RGBA5551Color[menuLevels.Length][];

                for (int i = 0; i < menuLevels.Length; i++)
                {
                    var lvl          = menuLevels[i];
                    var size         = manager.GetMenuSize(lvl);
                    var isCompressed = manager.IsMenuCompressed(lvl);
                    var mapType      = manager.HasMenuAlphaBlending(lvl) ? GBARRR_MapBlock.MapType.Menu : GBARRR_MapBlock.MapType.Foreground;

                    if (isCompressed)
                    {
                        s.DoAt(Menu_Pointers[lvl * 3 + 0], () => {
                            s.DoEncoded(new RNCEncoder(hasHeader: false), () => Menu_Tiles[i] = s.SerializeArray <byte>(Menu_Tiles[i], s.CurrentLength, name: $"{nameof(Menu_Tiles)}[{i}]"));
                        });
                        s.DoAt(Menu_Pointers[lvl * 3 + 1], () =>
                        {
                            s.DoEncoded(new RNCEncoder(hasHeader: false), () => Menu_MapData[i] = s.SerializeObjectArray <MapTile>(Menu_MapData[i], size.Width * size.Height, onPreSerialize: x => x.GBARRRType = mapType, name: $"{nameof(Menu_MapData)}[{i}]"));
                        });
                    }
                    else
                    {
                        s.DoAt(Menu_Pointers[lvl * 3 + 0], () =>
                               Menu_Tiles[i] = s.SerializeArray <byte>(Menu_Tiles[i], 0x4B00 * 2, name: $"{nameof(Menu_Tiles)}[{i}]"));
                        s.DoAt(Menu_Pointers[lvl * 3 + 1], () =>
                               Menu_MapData[i] = s.SerializeObjectArray <MapTile>(Menu_MapData[i], size.Width * size.Height, onPreSerialize: x => x.GBARRRType = mapType, name: $"{nameof(Menu_MapData)}[{i}]"));
                    }

                    Menu_Palette[i] = s.DoAt(Menu_Pointers[lvl * 3 + 2], () => s.SerializeObjectArray <RGBA5551Color>(Menu_Palette[i], 16 * 16, name: $"{nameof(Menu_Palette)}[{i}]"));
                }
            }
        }
Exemple #2
0
        public override void SerializeImpl(SerializerObject s)
        {
            // Serialize ROM header
            base.SerializeImpl(s);

            // Get the pointer table
            var pointerTable = PointerTables.GBAVV_PointerTable(s.GameSettings.GameModeSelection, Offset.file);

            // Get the current lev info
            var manager = (GBAVV_BaseManager)s.GameSettings.GetGameManager;

            if (pointerTable.ContainsKey(GBAVV_Pointer.Localization))
            {
                var multipleLanguages = s.GameSettings.GameModeSelection == GameModeSelection.Crash1GBAEU || s.GameSettings.GameModeSelection == GameModeSelection.Crash2GBAEU;

                if (multipleLanguages)
                {
                    LocTablePointers = s.DoAt(pointerTable[GBAVV_Pointer.Localization], () => s.SerializePointerArray(LocTablePointers, 6, name: nameof(LocTablePointers)));
                }
                else
                {
                    LocTablePointers = new Pointer[]
                    {
                        pointerTable[GBAVV_Pointer.Localization]
                    }
                };

                if (LocTables == null)
                {
                    LocTables = new GBAVV_LocTable[LocTablePointers.Length];
                }

                for (int i = 0; i < LocTables.Length; i++)
                {
                    LocTables[i] = s.DoAt(LocTablePointers[i], () => s.SerializeObject <GBAVV_LocTable>(LocTables[i], name: $"{nameof(LocTables)}[{i}]"));
                }
            }

            s.Context.StoreObject(GBAVV_BaseManager.LocTableID, LocTables?.FirstOrDefault());

            s.DoAt(pointerTable[GBAVV_Pointer.LevelInfo], () =>
            {
                if (LevelInfos == null)
                {
                    LevelInfos = new GBAVV_LevelInfo[manager.LevInfos.Max(x => x.LevelIndex) + 1];
                }

                for (int i = 0; i < LevelInfos.Length; i++)
                {
                    LevelInfos[i] = s.SerializeObject <GBAVV_LevelInfo>(LevelInfos[i], x => x.LevInfo = i == CurrentLevInfo.LevelIndex ? CurrentLevInfo : null, name: $"{nameof(LevelInfos)}[{i}]");
                }
            });

            if (CurrentMapInfo.MapType == GBAVV_MapInfo.GBAVV_MapType.Normal ||
                CurrentMapInfo.MapType == GBAVV_MapInfo.GBAVV_MapType.Normal_Vehicle_0 ||
                CurrentMapInfo.MapType == GBAVV_MapInfo.GBAVV_MapType.Normal_Vehicle_1 ||
                CurrentMapInfo.MapType == GBAVV_MapInfo.GBAVV_MapType.WorldMap)
            {
                Map2D_Graphics = s.DoAt(pointerTable[GBAVV_Pointer.Map2D_Graphics], () => s.SerializeObject <GBAVV_Map2D_Graphics>(Map2D_Graphics, name: nameof(Map2D_Graphics)));
            }

            if (CurrentMapInfo.MapType == GBAVV_MapInfo.GBAVV_MapType.Mode7)
            {
                s.DoAt(pointerTable[GBAVV_Pointer.Mode7_LevelInfo], () =>
                {
                    if (Mode7_LevelInfos == null)
                    {
                        Mode7_LevelInfos = new GBAVV_Mode7_LevelInfo[7];
                    }

                    var index3D = CurrentMapInfo.Index3D;

                    for (int i = 0; i < Mode7_LevelInfos.Length; i++)
                    {
                        Mode7_LevelInfos[i] = s.SerializeObject <GBAVV_Mode7_LevelInfo>(Mode7_LevelInfos[i], x => x.SerializeData = i == index3D, name: $"{nameof(Mode7_LevelInfos)}[{i}]");
                    }
                });

                if (s.GameSettings.EngineVersion == EngineVersion.GBAVV_Crash2)
                {
                    GBAVV_Pointer palPointer = CurrentMode7LevelInfo.LevelType == 0 ? GBAVV_Pointer.Mode7_TilePalette_Type0 : GBAVV_Pointer.Mode7_TilePalette_Type1_Flames;

                    Mode7_TilePalette = s.DoAt(pointerTable[palPointer], () => s.SerializeObjectArray <RGBA5551Color>(Mode7_TilePalette, CurrentMode7LevelInfo.LevelType == 0 ? 256 : 16, name: nameof(Mode7_TilePalette)));
                }
                else if (s.GameSettings.EngineVersion == EngineVersion.GBAVV_Crash1 && CurrentMode7LevelInfo.LevelType == 0)
                {
                    Mode7_Crash1_Type0_TilePalette_0F = s.DoAt(pointerTable[GBAVV_Pointer.Mode7_Crash1_Type0_TilePalette_0F], () => s.SerializeObjectArray <RGBA5551Color>(Mode7_Crash1_Type0_TilePalette_0F, 16, name: nameof(Mode7_Crash1_Type0_TilePalette_0F)));
                }

                if (s.GameSettings.EngineVersion == EngineVersion.GBAVV_Crash2 && CurrentMode7LevelInfo.LevelType == 0)
                {
                    Mode7_Crash2_Type0_BG1 = s.DoAt(pointerTable[GBAVV_Pointer.Mode7_Crash2_Type0_BG1], () => s.SerializeArray <byte>(Mode7_Crash2_Type0_BG1, 38 * 9 * 32, name: nameof(Mode7_Crash2_Type0_BG1)));
                }
                else if (s.GameSettings.EngineVersion == EngineVersion.GBAVV_Crash2 && CurrentMode7LevelInfo.LevelType == 1)
                {
                    Mode7_Crash2_Type1_FlamesTileMapsPointers = s.DoAt(pointerTable[GBAVV_Pointer.Mode7_Crash2_Type1_FlamesTileMaps], () => s.SerializePointerArray(Mode7_Crash2_Type1_FlamesTileMapsPointers, 20, name: nameof(Mode7_Crash2_Type1_FlamesTileMapsPointers)));

                    if (Mode7_Crash2_Type1_FlamesTileMaps == null)
                    {
                        Mode7_Crash2_Type1_FlamesTileMaps = new MapTile[20][];
                    }

                    for (int i = 0; i < Mode7_Crash2_Type1_FlamesTileMaps.Length; i++)
                    {
                        Mode7_Crash2_Type1_FlamesTileMaps[i] = s.DoAt(Mode7_Crash2_Type1_FlamesTileMapsPointers[i], () => s.SerializeObjectArray <MapTile>(Mode7_Crash2_Type1_FlamesTileMaps[i], 0x1E * 0x14, name: $"{nameof(Mode7_Crash2_Type1_FlamesTileMaps)}[{i}]"));
                    }

                    Mode7_Crash2_Type1_FlamesTileSetLengths = s.DoAt(pointerTable[GBAVV_Pointer.Mode7_Crash2_Type1_FlamesTileSetLengths], () => s.SerializeArray <uint>(Mode7_Crash2_Type1_FlamesTileSetLengths, 20, name: nameof(Mode7_Crash2_Type1_FlamesTileSetLengths)));

                    Mode7_Crash2_Type1_FlamesTileSetsPointers = s.DoAt(pointerTable[GBAVV_Pointer.Mode7_Crash2_Type1_FlamesTileSets], () => s.SerializePointerArray(Mode7_Crash2_Type1_FlamesTileSetsPointers, 20, name: nameof(Mode7_Crash2_Type1_FlamesTileSetsPointers)));

                    if (Mode7_Crash2_Type1_FlamesTileSets == null)
                    {
                        Mode7_Crash2_Type1_FlamesTileSets = new byte[20][];
                    }

                    for (int i = 0; i < Mode7_Crash2_Type1_FlamesTileSets.Length; i++)
                    {
                        Mode7_Crash2_Type1_FlamesTileSets[i] = s.DoAt(Mode7_Crash2_Type1_FlamesTileSetsPointers[i], () => s.SerializeArray <byte>(Mode7_Crash2_Type1_FlamesTileSets[i], Mode7_Crash2_Type1_FlamesTileSetLengths[i], name: $"{nameof(Mode7_Crash2_Type1_FlamesTileSets)}[{i}]"));
                    }
                }
            }

            if (CurrentMapInfo.MapType == GBAVV_MapInfo.GBAVV_MapType.Isometric)
            {
                var index3D = CurrentMapInfo.Index3D;

                s.DoAt(pointerTable[GBAVV_Pointer.Isometric_MapDatas], () =>
                {
                    if (Isometric_MapDatas == null)
                    {
                        Isometric_MapDatas = new GBAVV_Isometric_MapData[7];
                    }


                    for (int i = 0; i < Isometric_MapDatas.Length; i++)
                    {
                        Isometric_MapDatas[i] = s.SerializeObject <GBAVV_Isometric_MapData>(Isometric_MapDatas[i], x => x.SerializeData = i == index3D + 4, name: $"{nameof(Isometric_MapDatas)}[{i}]");
                    }
                });

                s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjectDatas], () =>
                {
                    if (Isometric_ObjectDatas == null)
                    {
                        Isometric_ObjectDatas = new GBAVV_Isometric_ObjectData[7];
                    }

                    for (int i = 0; i < Isometric_ObjectDatas.Length; i++)
                    {
                        Isometric_ObjectDatas[i] = s.SerializeObject <GBAVV_Isometric_ObjectData>(Isometric_ObjectDatas[i], x =>
                        {
                            x.SerializeData = i == index3D + 4;
                            x.IsMultiplayer = i < 4;
                        }, name: $"{nameof(Isometric_ObjectDatas)}[{i}]");
                    }
                });

                Isometric_CharacterInfos = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_Characters], () => s.SerializeObjectArray <GBAVV_Isometric_CharacterInfo>(Isometric_CharacterInfos, 12, name: nameof(Isometric_CharacterInfos)));
                Isometric_CharacterIcons = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_CharacterIcons], () => s.SerializeObjectArray <GBAVV_Isometric_CharacterIcon>(Isometric_CharacterIcons, 11, name: nameof(Isometric_CharacterIcons)));
                Isometric_ObjAnimations  = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjAnimations], () => s.SerializeObjectArray <GBAVV_Isometric_Animation>(Isometric_ObjAnimations, 22, name: nameof(Isometric_ObjAnimations)));

                Isometric_ObjPalette_0  = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjPalette_0], () => s.SerializeObjectArray <RGBA5551Color>(Isometric_ObjPalette_0, 16, name: nameof(Isometric_ObjPalette_0)));
                Isometric_ObjPalette_1  = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjPalette_1], () => s.SerializeObjectArray <RGBA5551Color>(Isometric_ObjPalette_1, 16, name: nameof(Isometric_ObjPalette_1)));
                Isometric_ObjPalette_2  = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjPalette_2], () => s.SerializeObjectArray <RGBA5551Color>(Isometric_ObjPalette_2, 16, name: nameof(Isometric_ObjPalette_2)));
                Isometric_ObjPalette_4  = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjPalette_4], () => s.SerializeObjectArray <RGBA5551Color>(Isometric_ObjPalette_4, 16, name: nameof(Isometric_ObjPalette_4)));
                Isometric_ObjPalette_11 = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjPalette_11], () => s.SerializeObjectArray <RGBA5551Color>(Isometric_ObjPalette_11, 16, name: nameof(Isometric_ObjPalette_11)));
                Isometric_ObjPalette_12 = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjPalette_12], () => s.SerializeObjectArray <RGBA5551Color>(Isometric_ObjPalette_12, 16, name: nameof(Isometric_ObjPalette_12)));
                Isometric_ObjPalette_13 = s.DoAt(pointerTable[GBAVV_Pointer.Isometric_ObjPalette_13], () => s.SerializeObjectArray <RGBA5551Color>(Isometric_ObjPalette_13, 16, name: nameof(Isometric_ObjPalette_13)));

                // These animations are all hard-coded from functions:
                Isometric_AdditionalAnimations = new GBAVV_Isometric_Animation[]
                {
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim0_Frames], 0x03, 4, 4, 2),                                                               // Green barrel
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim1_Frames], 0x03, 4, 4, 2),                                                               // Laser beam
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim2_Frames], 0x06, 4, 4, 1),                                                               // Crate breaks
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim3_Frames], 0x07, 4, 4, 1),                                                               // Checkpoint breaks
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim4_Frames], 0x18, 8, 4, 0),                                                               // Checkpoint text
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim5_Frames], 0x08, 4, 4, 2),                                                               // Nitro explosion
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim6_Frames], 0x08, 4, 4, 2),                                                               // Nitro switch
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim7_Frames], 0x0E, 4, 4, 0),                                                               // Wumpa HUD
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim8_Frames], 0x0A, 8, 8, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim8_Palette]),   // Crystal collected
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim9_Frames], 0x03, 4, 4, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim9_Palette]),   // Multiplayer base
                    GBAVV_Isometric_Animation.CrateAndSerialize(s, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim10_Frames], 0x0A, 2, 2, pointerTable[GBAVV_Pointer.Isometric_AdditionalAnim10_Palette]), // Multiplayer item
                };
            }

            if (CurrentMapInfo.MapType == GBAVV_MapInfo.GBAVV_MapType.WorldMap)
            {
                if (pointerTable.ContainsKey(GBAVV_Pointer.WorldMap))
                {
                    WorldMap = s.DoAt(pointerTable[GBAVV_Pointer.WorldMap], () => s.SerializeObject(WorldMap, name: nameof(WorldMap)));
                }

                if (s.GameSettings.EngineVersion == EngineVersion.GBAVV_Crash1)
                {
                    WorldMap_Crash1_LevelIcons = s.DoAt(pointerTable[GBAVV_Pointer.WorldMap_Crash1_LevelIcons], () => s.SerializeObjectArray <GBAVV_WorldMap_Crash1_LevelIcon>(WorldMap_Crash1_LevelIcons, 10, name: nameof(WorldMap_Crash1_LevelIcons)));
                }
            }
        }
    }