예제 #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}]"));
                }
            }
        }