public override void SerializeImpl(SerializerObject s)
        {
            Offsets   = s.SerializePointerArray <Array <ushort> >(Offsets, 6, resolve: true, onPreSerialize: x => x.Length = 690, name: nameof(Offsets));
            LocTables = s.SerializePointerArray(LocTables, 6, name: nameof(LocTables));
            if (Localization == null)
            {
                Localization = new string[Offsets.Length][];
                for (int i = 0; i < Localization.Length; i++)
                {
                    Localization[i] = new string[Offsets[i].Value.Length];
                    s.DoAt(LocTables[i], () => {
                        s.DoEncoded(new RHREncoder(), () => {
                            Pointer basePtr = s.CurrentPointer;
                            for (int j = 0; j < Offsets[i].Value.Length; j++)
                            {
                                s.DoAt(basePtr + Offsets[i].Value.Value[j], () => {
                                    Localization[i][j] = s.SerializeString(Localization[i][j], encoding: Encoding.GetEncoding(1252), name: $"{nameof(Localization)}[{i}][{j}]");
                                });
                            }

                            // Go to end
                            s.Goto(s.CurrentPointer + s.CurrentLength);
                        });
                    });
                }
            }
        }
Esempio n. 2
0
        public void DecryptSaveFiles(GameSettings settings)
        {
            using (var context = new Context(settings))
            {
                foreach (var save in Directory.GetFiles(settings.GameDirectory, "*.sav", SearchOption.TopDirectoryOnly).Select(Path.GetFileName))
                {
                    LinearSerializedFile f = new LinearSerializedFile(context)
                    {
                        filePath = save
                    };
                    context.AddFile(f);
                    SerializerObject s        = context.Deserializer;
                    byte[]           saveData = null;
                    s.DoAt(f.StartPointer, () => {
                        s.DoEncoded(new PC_R1_SaveEncoder(), () => {
                            saveData = s.SerializeArray <byte>(saveData, s.CurrentLength, name: "SaveData");
                            Util.ByteArrayToFile(context.BasePath + save + ".dec", saveData);
                        });
                    });

                    /*LinearSerializedFile f2 = new LinearSerializedFile(context) {
                     *  filePath = save + ".recompressed"
                     * };
                     * context.AddFile(f2);
                     * s = context.Serializer;
                     * s.DoAt(f2.StartPointer, () => {
                     *  s.DoEncoded(new R1PCSaveEncoder(), () => {
                     *      saveData = s.SerializeArray<byte>(saveData, saveData.Length, name: "SaveData");
                     *  });
                     * });*/
                }
            }
        }
        public override void SerializeImpl(SerializerObject s)
        {
            TileSetPointer    = s.SerializePointer <GBAIsometric_RHR_TileSet>(TileSetPointer, resolve: true, name: nameof(TileSetPointer));
            StructType        = s.Serialize <MapLayerType>(StructType, name: nameof(StructType));
            Width             = s.Serialize <ushort>(Width, name: nameof(Width));
            Height            = s.Serialize <ushort>(Height, name: nameof(Height));
            Ushort_0A         = s.Serialize <ushort>(Ushort_0A, name: nameof(Ushort_0A));
            MapDataPointer    = s.SerializePointer(MapDataPointer, name: nameof(MapDataPointer));
            MapPalettePointer = s.SerializePointer(MapPalettePointer, name: nameof(MapPalettePointer));
            MapPalette        = s.DoAt(MapPalettePointer, () => s.SerializeObjectArray <RGBA5551Color>(MapPalette, 256, name: nameof(MapPalette)));

            s.DoAt(MapDataPointer, () =>
            {
                s.DoEncoded(new RHREncoder(), () => MapData = s.SerializeArray <ushort>(MapData, Width * Height, name: nameof(MapData)));
            });

            // Debug tilemaps
            //ushort[] fullMap = CreateFullMap(MapData);
            //string logString = $"{Offset}: Max Tilemap Value - {fullMap.Max()}";
            //UnityEngine.Debug.Log(logString);
            //s.Log(logString);
            //byte[] result = new byte[fullMap.Length * sizeof(ushort)];
            //Buffer.BlockCopy(fullMap, 0, result, 0, result.Length);
            //Util.ByteArrayToFile(s.Context.BasePath + "full_tilemap/" + Offset.StringAbsoluteOffset + ".bin", result);
        }
Esempio n. 4
0
        public override void SerializeImpl(SerializerObject s)
        {
            PointersPointer = s.SerializePointer <GBAIsometric_LevelDataLayerDataPointers>(PointersPointer, resolve: true, name: nameof(PointersPointer));
            StructType      = s.Serialize <MapLayerType>(StructType, name: nameof(StructType));
            Width           = s.Serialize <ushort>(Width, name: nameof(Width));
            Height          = s.Serialize <ushort>(Height, name: nameof(Height));
            Ushort_0A       = s.Serialize <ushort>(Ushort_0A, name: nameof(Ushort_0A));
            MapDataPointer  = s.SerializePointer(MapDataPointer, name: nameof(MapDataPointer));
            Pointer_20      = s.SerializePointer(Pointer_20, name: nameof(Pointer_20));

            if (StructType == MapLayerType.Map)
            {
                Palette       = s.SerializeObjectArray <ARGB1555Color>(Palette, 256, name: nameof(Palette));
                RemainingData = s.SerializeArray <byte>(RemainingData, 44, name: nameof(RemainingData));
            }

            // TODO: Remove try/catch
            try
            {
                s.DoAt(MapDataPointer, () =>
                {
                    s.DoEncoded(new RHREncoder(), () =>
                    {
                        MapData = s.SerializeArray <ushort>(MapData, Width * Height, name: nameof(MapData));
                    });
                });
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"Failed to decompress {MapDataPointer}: {ex.Message}\n{ex.InnerException?.StackTrace}");
            }
        }
Esempio n. 5
0
        public void SerializeLevelData(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion == EngineVersion.R1_GBA)
            {
                s.DoAt(MapDataPointer, () => {
                    if ((CompressionFlags & 1) == 1)
                    {
                        s.DoEncoded(new GBA_LZSSEncoder(), () => {
                            MapData = s.SerializeObject <MapData>(MapData, name: nameof(MapData));
                        });
                    }
                    else
                    {
                        MapData = s.SerializeObject <MapData>(MapData, name: nameof(MapData));
                    }
                });
                s.DoAt(TilePaletteIndicesPointer, () => {
                    if ((CompressionFlags & 2) == 2)
                    {
                        s.DoEncoded(new GBA_LZSSEncoder(), () => TilePaletteIndices = s.SerializeArray <byte>(TilePaletteIndices, s.CurrentLength, name: nameof(TilePaletteIndices)));
                    }
                    else
                    {
                        uint numTileBlocks = (TilePaletteIndicesPointer.AbsoluteOffset - TileBlockIndicesPointer.AbsoluteOffset) / 2;
                        TilePaletteIndices = s.SerializeArray <byte>(TilePaletteIndices, numTileBlocks, name: nameof(TilePaletteIndices));
                    }
                });

                s.DoAt(TileBlockIndicesPointer, () => TileBlockIndices = s.SerializeArray <ushort>(TileBlockIndices, TilePaletteIndices.Length, name: nameof(TileBlockIndices)));
                s.DoAt(TilePalettePointer, () => TilePalettes          = s.SerializeObjectArray <RGBA5551Color>(TilePalettes, 10 * 16, name: nameof(TilePalettes)));

                ushort maxBlockIndex = TileBlockIndices.Max();
                s.DoAt(TileDataPointer, () => TileData = s.SerializeArray <byte>(TileData, 0x20 * ((uint)maxBlockIndex + 1), name: nameof(TileData)));
            }
            else if (s.GameSettings.EngineVersion == EngineVersion.R1_DSi)
            {
                s.DoAt(MapDataPointer, () => s.DoEncoded(new GBA_LZSSEncoder(), () => MapData = s.SerializeObject <MapData>(MapData, name: nameof(MapData))));
                s.DoAt(TileDataPointer, () => {
                    s.DoEncoded(new GBA_LZSSEncoder(), () => TileData = s.SerializeArray <byte>(TileData, s.CurrentLength, name: nameof(TileData)));
                });
                s.DoAt(TilePalettePointer, () => TilePalettes = s.SerializeObjectArray <RGBA5551Color>(TilePalettes, 256, name: nameof(TilePalettes)));
                s.DoAt(TileBlockIndicesPointer, () => {
                    uint maxTileInd  = MapData.Tiles.Max(t => t.TileMapY);
                    TileBlockIndices = s.SerializeArray <ushort>(TileBlockIndices, (maxTileInd + 1) * 4, name: nameof(TileBlockIndices));
                });
            }
        }
Esempio n. 6
0
        public override void SerializeBlock(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion <= EngineVersion.GBA_BatmanVengeance)
            {
                Is8bpp = s.Serialize <bool>(Is8bpp, name: nameof(Is8bpp));

                if (s.GameSettings.GBA_IsMilan)
                {
                    CompressionType = s.Serialize <Milan_CompressionType>(CompressionType, name: nameof(CompressionType));
                }
                else
                {
                    IsCompressed    = s.Serialize <bool>(IsCompressed, name: nameof(IsCompressed));
                    CompressionType = IsCompressed ? Milan_CompressionType.LZSS : Milan_CompressionType.None;
                }

                if (Is8bpp)
                {
                    TileSet8bppSize = s.Serialize <ushort>(TileSet8bppSize, name: nameof(TileSet8bppSize));
                }
                else
                {
                    TileSet4bppSize = s.Serialize <ushort>(TileSet4bppSize, name: nameof(TileSet4bppSize));
                }
            }
            else
            {
                TileSet4bppSize             = s.Serialize <ushort>(TileSet4bppSize, name: nameof(TileSet4bppSize));
                TileSet8bppSize             = s.Serialize <ushort>(TileSet8bppSize, name: nameof(TileSet8bppSize));
                IsCompressed                = s.Serialize <bool>(IsCompressed, name: nameof(IsCompressed));
                AnimatedTileKitManagerIndex = s.Serialize <byte>(AnimatedTileKitManagerIndex, name: nameof(AnimatedTileKitManagerIndex)); // Can be 0xFF which means this block doesn't exist
                PaletteCount                = s.Serialize <byte>(PaletteCount, name: nameof(PaletteCount));
                Byte_07        = s.Serialize <byte>(Byte_07, name: nameof(Byte_07));
                PaletteIndices = s.SerializeArray <byte>(PaletteIndices, PaletteCount, name: nameof(PaletteIndices));

                CompressionType = IsCompressed && s.GameSettings.EngineVersion != EngineVersion.GBA_R3_NGage ? Milan_CompressionType.LZSS : Milan_CompressionType.None;
            }

            // Serialize tilemap data
            switch (CompressionType)
            {
            case Milan_CompressionType.None:
            default:
                TileSet4bpp = s.SerializeArray <byte>(TileSet4bpp, TileSet4bppSize * 0x20, name: nameof(TileSet4bpp));
                TileSet8bpp = s.SerializeArray <byte>(TileSet8bpp, TileSet8bppSize * 0x40, name: nameof(TileSet8bpp));
                break;

            case Milan_CompressionType.RL:
                throw new NotImplementedException();

            case Milan_CompressionType.LZSS:
                s.DoEncoded(new GBA_LZSSEncoder(), () => {
                    TileSet4bpp = s.SerializeArray <byte>(TileSet4bpp, TileSet4bppSize * 0x20, name: nameof(TileSet4bpp));
                    TileSet8bpp = s.SerializeArray <byte>(TileSet8bpp, TileSet8bppSize * 0x40, name: nameof(TileSet8bpp));
                });
                s.Align();
                break;
            }
        }
        public override void SerializeImpl(SerializerObject s)
        {
            bool determineTileSize = false;

            if (Count == 0)
            {
                Headers = s.SerializeObjectArray <Header>(Headers, 2, name: nameof(Headers));

                if (Headers[0].TileOffset % 4 != 0 || Headers[0].ExtraBytes >= 4 || (Headers[0].TileOffset / 4) < 2)
                {
                    return;                                                                                                 // Invalid
                }
                Count             = (uint)(Headers[0].TileOffset / 4) - 1;
                determineTileSize = true;
                s.Goto(Offset);
            }
            Headers = s.SerializeObjectArray <Header>(Headers, Count + 1, name: nameof(Headers));
            if (TileData == null)
            {
                TileData = new byte[Count][];
                for (int i = 0; i < Count; i++)
                {
                    s.DoAt(Offset + Headers[i].TileOffset, () => {
                        int length = (Headers[i + 1].TileOffset - Headers[i].TileOffset - Headers[i].ExtraBytes);

                        if (determineTileSize && i == 0)
                        {
                            if (Math.Sqrt(length * 2) % 1 == 0)
                            {
                                int val = Mathf.RoundToInt(Mathf.Sqrt(length * 2));
                                if ((val != 0) && ((val & (val - 1)) == 0))
                                {
                                    TileSize = (uint)val;
                                }
                            }
                        }

                        if (length != TileSize * TileSize / 2)
                        {
                            s.DoEncoded(new LZSSEncoder((uint)length, hasHeader: false), () => {
                                TileData[i] = s.SerializeArray <byte>(TileData[i], s.CurrentLength, name: $"{nameof(TileData)}[{i}]");
                            });
                        }
                        else
                        {
                            TileData[i] = s.SerializeArray <byte>(TileData[i], length, name: $"{nameof(TileData)}[{i}]");
                        }
                        if (determineTileSize && i == 0)
                        {
                            int len = TileData[i].Length;
                            if (Math.Sqrt(len * 2) % 1 == 0)
                            {
                                TileSize = (uint)Mathf.RoundToInt(Mathf.Sqrt(len * 2));
                            }
                        }
                    });
                }
            }
        }
Esempio n. 8
0
        public override void SerializeImpl(SerializerObject s)
        {
            GraphicsDataPointer        = s.SerializePointer <GBAIsometric_RHR_GraphicsData>(GraphicsDataPointer, resolve: true, name: nameof(GraphicsDataPointer));
            PaletteIndexTablePointer   = s.SerializePointer <GBAIsometric_RHR_PaletteIndexTable>(PaletteIndexTablePointer, resolve: true, onPreSerialize: pit => pit.Length = GraphicsDataPointer.Value.CompressionLookupBufferLength, name: nameof(PaletteIndexTablePointer));
            CombinedTileDataPointer    = s.SerializePointer(CombinedTileDataPointer, name: nameof(CombinedTileDataPointer));
            CombinedTileOffsetsPointer = s.SerializePointer(CombinedTileOffsetsPointer, name: nameof(CombinedTileOffsetsPointer));
            for (int i = 0; i < 4; i++)
            {
                AssembleData[i] = s.SerializeObject <GBAIsometric_RHR_TileAssemble>(AssembleData[i], onPreSerialize: ad => ad.TileCompression = (GBAIsometric_RHR_TileAssemble.Compression)i, name: $"{nameof(AssembleData)}[{i}]");
            }
            PalettesPointer = s.SerializePointer(PalettesPointer, name: nameof(PalettesPointer));

            // Todo: Read these in a less hacky way
            s.DoAt(CombinedTileDataPointer, () => {
                CombinedTileData = s.SerializeArray <ushort>(CombinedTileData, (CombinedTileOffsetsPointer - CombinedTileDataPointer) / 2, name: nameof(CombinedTileData));
            });
            s.DoAt(CombinedTileOffsetsPointer, () => {
                if (CombinedTileDataPointer == CombinedTileOffsetsPointer)
                {
                    CombinedTileOffsets = new ushort[0];
                }
                else
                {
                    uint length = 0;
                    s.DoAt(CombinedTileOffsetsPointer, () => {
                        ushort CombinedTileOffsetsLengthHack = 0;
                        while (CombinedTileOffsetsLengthHack < CombinedTileData.Length)
                        {
                            CombinedTileOffsetsLengthHack = s.Serialize <ushort>(CombinedTileOffsetsLengthHack, name: nameof(CombinedTileOffsetsLengthHack));
                        }
                        length = (uint)((s.CurrentPointer - CombinedTileOffsetsPointer) / 2);
                    });
                    CombinedTileOffsets = s.SerializeArray <ushort>(CombinedTileOffsets, length, name: nameof(CombinedTileOffsets));
                }
            });

            s.DoAt(PalettesPointer, () =>
            {
                if (Palettes == null)
                {
                    Palettes = new RGBA5551Color[PaletteIndexTablePointer.Value.GetMaxPaletteIndex() + 1][];
                }

                for (int i = 0; i < Palettes.Length; i++)
                {
                    Palettes[i] = s.SerializeObjectArray <RGBA5551Color>(Palettes[i], 16, name: $"{nameof(Palettes)}[i]");
                }
            });

            s.DoEncoded(new RHR_SpriteEncoder(false, GraphicsDataPointer.Value.CompressionLookupBuffer, GraphicsDataPointer.Value.CompressedDataPointer), () => {
                byte[] fullSheet = s.SerializeArray <byte>(default, s.CurrentLength, name: nameof(fullSheet));
Esempio n. 9
0
 public void ReadSaveFiles(GameSettings settings)
 {
     using (var context = new Context(settings))
     {
         foreach (var save in Directory.GetFiles(settings.GameDirectory, "*.sav", SearchOption.TopDirectoryOnly).Select(Path.GetFileName))
         {
             LinearSerializedFile f = new LinearSerializedFile(context)
             {
                 filePath = save
             };
             context.AddFile(f);
             SerializerObject s = context.Deserializer;
             s.DoAt(f.StartPointer, () => {
                 s.DoEncoded(new PC_R1_SaveEncoder(), () => s.SerializeObject <R1_PC_SaveFile>(default, name: "SaveFile"));
Esempio n. 10
0
 public override void SerializeImpl(SerializerObject s)
 {
     ID         = s.Serialize <byte>(ID, name: nameof(ID));
     NumEntries = s.Serialize <ushort>(NumEntries, name: nameof(NumEntries));
     Pos        = s.Serialize <ushort>(Pos, name: nameof(Pos));
     Padding    = s.Serialize <ushort>(Padding, name: nameof(Padding));
     s.DoAt(new Pointer(Pos, Offset.file), () => {
         Entries = s.SerializeObjectArray <Entry>(Entries, NumEntries, name: nameof(Entries));
     });
     Strings = new string[NumEntries];
     for (int i = 0; i < Entries.Length; i++)
     {
         s.DoAt(new Pointer(Entries[i].Pos, Offset.file), () => {
             s.DoEncoded(new Eclipse_StringEncoder(HuffTable, Entries[i]), () => {
                 var bytes  = s.SerializeArray <byte>(default, s.CurrentLength, "bytes[" + i + "]");
        public IEnumerable <Texture2D> GetAnimationFrames(Context context, GBAIsometric_RHR_AnimSet animSet, GBAIsometric_RHR_Animation anim, Dictionary <ushort, byte[]> decompressedDictionary, RGBA5551Color[] palette)
        {
            SerializerObject s = context.Deserializer;

            var startFrame = anim.StartFrameIndex;
            var frameCount = anim.FrameCount;

            Color[] pal = Util.ConvertGBAPalette(palette);

            for (int f = 0; f < frameCount; f++)
            {
                var frame = animSet.Frames[startFrame + f];

                Texture2D tex = TextureHelpers.CreateTexture2D(animSet.Width * CellSize, animSet.Height * CellSize, clear: true);

                if (frame.PatternIndex == 0xFFFF || frame.TileIndicesIndex == 0xFFFF)
                {
                    // Empty frame
                }
                else
                {
                    var patIndex = frame.PatternIndex;

                    int curTile = frame.TileIndicesIndex;

                    for (int p = 0; p < animSet.Patterns[patIndex].Length; p++)
                    {
                        var pattern = animSet.Patterns[patIndex][p];
                        for (int y = 0; y < pattern.Height; y++)
                        {
                            for (int x = 0; x < pattern.Width; x++)
                            {
                                int    actualX   = x + pattern.XPosition;
                                int    actualY   = y + pattern.YPosition;
                                ushort tileIndex = animSet.TileIndices[curTile];

                                if (!decompressedDictionary.ContainsKey(tileIndex))
                                {
                                    s.Goto(animSet.GraphicsDataPointer.Value.CompressedDataPointer);

                                    s.DoEncoded(new RHR_SpriteEncoder(animSet.Is8Bit,
                                                                      animSet.GraphicsDataPointer.Value.CompressionLookupBuffer,
                                                                      animSet.GraphicsDataPointer.Value.CompressedDataPointer,
                                                                      tileIndex), () => {
                                        decompressedDictionary[tileIndex] = s.SerializeArray <byte>(default, s.CurrentLength, name: $"{animSet.Name}:Tiles[{curTile}]:{tileIndex}");
Esempio n. 12
0
        public override void SerializeBlock(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion <= EngineVersion.GBA_R3_MadTrax)
            {
                Is8bpp       = s.Serialize <bool>(Is8bpp, name: nameof(Is8bpp));
                IsCompressed = s.Serialize <bool>(IsCompressed, name: nameof(IsCompressed));
                if (Is8bpp)
                {
                    TileSet8bppSize = s.Serialize <ushort>(TileSet8bppSize, name: nameof(TileSet8bppSize));
                }
                else
                {
                    TileSet4bppSize = s.Serialize <ushort>(TileSet4bppSize, name: nameof(TileSet4bppSize));
                }
            }
            else
            {
                TileSet4bppSize             = s.Serialize <ushort>(TileSet4bppSize, name: nameof(TileSet4bppSize));
                TileSet8bppSize             = s.Serialize <ushort>(TileSet8bppSize, name: nameof(TileSet8bppSize));
                IsCompressed                = s.Serialize <bool>(IsCompressed, name: nameof(IsCompressed));
                AnimatedTileKitManagerIndex = s.Serialize <byte>(AnimatedTileKitManagerIndex, name: nameof(AnimatedTileKitManagerIndex)); // Can be 0xFF which means this block doesn't exist
                PaletteCount                = s.Serialize <byte>(PaletteCount, name: nameof(PaletteCount));
                Byte_07        = s.Serialize <byte>(Byte_07, name: nameof(Byte_07));
                PaletteIndices = s.SerializeArray <byte>(PaletteIndices, PaletteCount, name: nameof(PaletteIndices));
            }

            // Serialize tilemap data
            if (IsCompressed && s.GameSettings.EngineVersion != EngineVersion.GBA_R3_NGage)
            {
                s.DoEncoded(new GBA_LZSSEncoder(), () => {
                    TileSet4bpp = s.SerializeArray <byte>(TileSet4bpp, TileSet4bppSize * 0x20, name: nameof(TileSet4bpp));
                    TileSet8bpp = s.SerializeArray <byte>(TileSet8bpp, TileSet8bppSize * 0x40, name: nameof(TileSet8bpp));
                });
                s.Align();
            }
            else
            {
                TileSet4bpp = s.SerializeArray <byte>(TileSet4bpp, TileSet4bppSize * 0x20, name: nameof(TileSet4bpp));
                TileSet8bpp = s.SerializeArray <byte>(TileSet8bpp, TileSet8bppSize * 0x40, name: nameof(TileSet8bpp));
            }
        }
Esempio n. 13
0
        public override void SerializeBlock(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion == EngineVersion.GBA_BatmanVengeance)
            {
                if (StructType != Type.Collision)
                {
                    Unk_02 = s.Serialize <byte>(Unk_02, name: nameof(Unk_02));
                    Unk_03 = s.Serialize <byte>(Unk_03, name: nameof(Unk_03));

                    LayerID      = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ClusterIndex = s.Serialize <byte>(ClusterIndex, name: nameof(ClusterIndex));
                    // TODO: figure out what this is. One of these
                    UnkBytes = s.SerializeArray <byte>(UnkBytes, 5, name: nameof(UnkBytes));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    Unk_0E    = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    ColorMode = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                }
            }
            else if (s.GameSettings.EngineVersion == EngineVersion.GBA_R3_MadTrax)
            {
                MadTrax_Uint_00 = s.Serialize <uint>(MadTrax_Uint_00, name: nameof(MadTrax_Uint_00));
                MadTrax_Uint_04 = s.Serialize <uint>(MadTrax_Uint_04, name: nameof(MadTrax_Uint_04));
                MadTrax_Uint_08 = s.Serialize <uint>(MadTrax_Uint_08, name: nameof(MadTrax_Uint_08));

                Width  = s.Serialize <ushort>(Width, name: nameof(Width));
                Height = s.Serialize <ushort>(Height, name: nameof(Height));

                MadTraxUnk = s.SerializeArray <byte>(MadTraxUnk, 16, name: nameof(MadTraxUnk));

                // TODO: Are these in the above values?
                ColorMode    = GBA_ColorMode.Color4bpp;
                IsCompressed = false;
                StructType   = Type.Layer2D;
            }
            else
            {
                StructType = s.Serialize <Type>(StructType, name: nameof(StructType));

                if (StructType != Type.TextLayerMode7)
                {
                    IsCompressed = s.Serialize <bool>(IsCompressed, name: nameof(IsCompressed));
                }
                else
                {
                    Unk_01 = s.Serialize <bool>(Unk_01, name: nameof(Unk_01));
                }

                Unk_02 = s.Serialize <byte>(Unk_02, name: nameof(Unk_02));
                Unk_03 = s.Serialize <byte>(Unk_03, name: nameof(Unk_03));

                Width  = s.Serialize <ushort>(Width, name: nameof(Width));
                Height = s.Serialize <ushort>(Height, name: nameof(Height));

                switch (StructType)
                {
                case Type.TextLayerMode7:
                    LayerID = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));
                    UnkBytes  = s.SerializeArray <byte>(UnkBytes, 0x14, name: nameof(UnkBytes));
                    ColorMode = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                    // 21 bytes
                    // Prio is 0x1D
                    // ColorMode is 0x1F
                    // Width & height seems duplicates again (is it actually width and height?)

                    break;

                case Type.RotscaleLayerMode7:
                    LayerID = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));
                    // The game hard-codes the color mode
                    ColorMode = GBA_ColorMode.Color8bpp;

                    Unk_0C   = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                    Unk_0D   = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                    Unk_0E   = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    Unk_0F   = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    Mode7_10 = s.Serialize <byte>(Mode7_10, name: nameof(Mode7_10));
                    Mode7_11 = s.Serialize <byte>(Mode7_11, name: nameof(Mode7_11));
                    Mode7_12 = s.Serialize <byte>(Mode7_12, name: nameof(Mode7_12));
                    Mode7_13 = s.Serialize <byte>(Mode7_13, name: nameof(Mode7_13));
                    Mode7_14 = s.Serialize <byte>(Mode7_14, name: nameof(Mode7_14));
                    break;

                case Type.SplinterCellZoom:
                    if (LayerID < 2)
                    {
                        Unk_0C = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                        Unk_0D = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                        Unk_0E = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                        Unk_0F = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                        if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell_NGage)
                        {
                            ColorMode = GBA_ColorMode.Color8bpp;
                        }
                        else
                        {
                            ColorMode = GBA_ColorMode.Color4bpp;
                        }
                    }
                    else
                    {
                        ColorMode = GBA_ColorMode.Color8bpp;
                    }
                    UsesTileKitDirectly = true;
                    break;

                case Type.PoP:
                    Unk_0C    = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                    Unk_0D    = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                    Unk_0E    = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    Unk_0F    = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    ColorMode = GBA_ColorMode.Color8bpp;
                    break;

                case Type.Layer2D:
                    LayerID                  = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ClusterIndex             = s.Serialize <byte>(ClusterIndex, name: nameof(ClusterIndex));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));

                    UsesTileKitDirectly = s.Serialize <bool>(UsesTileKitDirectly, name: nameof(UsesTileKitDirectly));
                    ColorMode           = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                    TileKitIndex        = s.Serialize <byte>(TileKitIndex, name: nameof(TileKitIndex));
                    Unk_0F = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    break;
                }
            }

            if (StructType != Type.TextLayerMode7)
            {
                if (!IsCompressed)
                {
                    SerializeTileMap(s);
                }
                else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_PrinceOfPersia && StructType != Type.PoP)
                {
                    s.DoEncoded(new HuffmanEncoder(), () => s.DoEncoded(new GBA_LZSSEncoder(), () => SerializeTileMap(s)));
                }
                else
                {
                    s.DoEncoded(new GBA_LZSSEncoder(), () => SerializeTileMap(s));
                }
                s.Align();
            }
        }
Esempio n. 14
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}]"));
                }
            }
        }
Esempio n. 15
0
        public override void SerializeBlock(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion == EngineVersion.GBA_BatmanVengeance)
            {
                if (StructType != Type.Collision)
                {
                    Unk_02 = s.Serialize <byte>(Unk_02, name: nameof(Unk_02));
                    Unk_03 = s.Serialize <byte>(Unk_03, name: nameof(Unk_03));

                    LayerID      = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ClusterIndex = s.Serialize <byte>(ClusterIndex, name: nameof(ClusterIndex));
                    // TODO: figure out what this is. One of these
                    UnkBytes = s.SerializeArray <byte>(UnkBytes, 5, name: nameof(UnkBytes));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    Unk_0E    = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    ColorMode = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                }
            }
            else if (s.GameSettings.GBA_IsMilan)
            {
                ColorMode = GBA_ColorMode.Color4bpp;

                // Serialize cluster
                Cluster = s.DoAt(ShanghaiOffsetTable.GetPointer(0), () => s.SerializeObject <GBA_Cluster>(Cluster, name: nameof(Cluster)));

                IStreamEncoder encoder = null;

                switch (Cluster.Milan_MapCompressionType)
                {
                case GBA_Cluster.Milan_CompressionType.Collision_RL:
                case GBA_Cluster.Milan_CompressionType.Map_RL:
                    encoder = new GBA_RLEEncoder();
                    break;

                case GBA_Cluster.Milan_CompressionType.Collsiion_LZSS:
                case GBA_Cluster.Milan_CompressionType.Map_LZSS:
                    encoder = new GBA_LZSSEncoder();
                    break;
                }

                // Go to the map data
                s.Goto(ShanghaiOffsetTable.GetPointer(2));

                if (StructType == Type.Layer2D)
                {
                    s.DoEncodedIf(encoder, encoder != null, () => Shanghai_MapIndices_16 = s.SerializeArray <ushort>(Shanghai_MapIndices_16, ((Width + Width % 2) * (Height + Height % 2)) / 4, name: nameof(Shanghai_MapIndices_16)));

                    var end = s.CurrentPointer;

                    // Go to the map tiles
                    s.Goto(ShanghaiOffsetTable.GetPointer(1));

                    s.DoEncodedIf(encoder, encoder != null, () => Shanghai_MapTiles = s.SerializeObjectArray <MapTile>(Shanghai_MapTiles, (Shanghai_MapIndices_16.Max(x => BitHelpers.ExtractBits(x, 12, 0)) + 1) * 4, name: nameof(Shanghai_MapTiles)));

                    s.Goto(end);
                }
                else // Collision
                {
                    s.DoEncodedIf(encoder, encoder != null, () => SerializeTileMap(s));
                }

                s.Align();

                // Return to avoid serializing the map tile array normally
                return;
            }
            else if (s.GameSettings.GBA_IsShanghai)
            {
                ColorMode    = GBA_ColorMode.Color4bpp;
                IsCompressed = false;

                if (StructType == Type.Layer2D)
                {
                    // Serialize cluster
                    Cluster = s.DoAt(ShanghaiOffsetTable.GetPointer(0), () => s.SerializeObject <GBA_Cluster>(Cluster, name: nameof(Cluster)));

                    // Go to the map data
                    s.Goto(ShanghaiOffsetTable.GetPointer(2));

                    // If the map tile size is not 0 the map is split into a 32x8 index array and 8x8 map tiles
                    if (Cluster.Shanghai_MapTileSize != 0)
                    {
                        var indexArrayLength = Mathf.CeilToInt(Width / 4f) * Height;

                        // The tile size is either 1 or 2 bytes
                        if (Cluster.Shanghai_MapTileSize == 1)
                        {
                            Shanghai_MapIndices_8 = s.SerializeArray <byte>(Shanghai_MapIndices_8, indexArrayLength, name: nameof(Shanghai_MapIndices_8));
                        }
                        else
                        {
                            Shanghai_MapIndices_16 = s.SerializeArray <ushort>(Shanghai_MapIndices_16, indexArrayLength, name: nameof(Shanghai_MapIndices_16));
                        }

                        var indexArray = Cluster.Shanghai_MapTileSize == 1 ? Shanghai_MapIndices_8.Select(x => (ushort)x).ToArray() : Shanghai_MapIndices_16;

                        Shanghai_MapTiles = s.SerializeObjectArray <MapTile>(Shanghai_MapTiles, (indexArray.Max() + 1) * 4, name: nameof(Shanghai_MapTiles));

                        // Return to avoid serializing the map tile array normally
                        return;
                    }
                }
                else
                {
                    // Go to the collision data
                    s.Goto(ShanghaiOffsetTable.GetPointer(0));

                    // Serialize header properties
                    Shanghai_CollisionValue1 = s.Serialize <ushort>(Shanghai_CollisionValue1, name: nameof(Shanghai_CollisionValue1));
                    Width  = s.Serialize <ushort>(Width, name: nameof(Width));
                    Height = s.Serialize <ushort>(Height, name: nameof(Height));
                    Shanghai_CollisionValue2 = s.Serialize <ushort>(Shanghai_CollisionValue2, name: nameof(Shanghai_CollisionValue2));
                }
            }
            else
            {
                StructType = s.Serialize <Type>(StructType, name: nameof(StructType));

                if (StructType != Type.TextLayerMode7)
                {
                    IsCompressed = s.Serialize <bool>(IsCompressed, name: nameof(IsCompressed));
                }
                else
                {
                    Unk_01 = s.Serialize <bool>(Unk_01, name: nameof(Unk_01));
                }

                Unk_02 = s.Serialize <byte>(Unk_02, name: nameof(Unk_02));
                Unk_03 = s.Serialize <byte>(Unk_03, name: nameof(Unk_03));

                Width  = s.Serialize <ushort>(Width, name: nameof(Width));
                Height = s.Serialize <ushort>(Height, name: nameof(Height));

                switch (StructType)
                {
                case Type.TextLayerMode7:
                    LayerID = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));
                    UnkBytes  = s.SerializeArray <byte>(UnkBytes, 0x14, name: nameof(UnkBytes));
                    ColorMode = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                    // 21 bytes
                    // Prio is 0x1D
                    // ColorMode is 0x1F
                    // Width & height seems duplicates again (is it actually width and height?)

                    break;

                case Type.RotscaleLayerMode7:
                    LayerID = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));
                    // The game hard-codes the color mode
                    ColorMode = GBA_ColorMode.Color8bpp;

                    Unk_0C   = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                    Unk_0D   = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                    Unk_0E   = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    Unk_0F   = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    Mode7_10 = s.Serialize <byte>(Mode7_10, name: nameof(Mode7_10));
                    Mode7_11 = s.Serialize <byte>(Mode7_11, name: nameof(Mode7_11));
                    Mode7_12 = s.Serialize <byte>(Mode7_12, name: nameof(Mode7_12));
                    Mode7_13 = s.Serialize <byte>(Mode7_13, name: nameof(Mode7_13));
                    Mode7_14 = s.Serialize <byte>(Mode7_14, name: nameof(Mode7_14));
                    break;

                case Type.SplinterCellZoom:
                    if (LayerID < 2)
                    {
                        Unk_0C = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                        Unk_0D = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                        Unk_0E = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                        Unk_0F = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                        if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell_NGage)
                        {
                            ColorMode = GBA_ColorMode.Color8bpp;
                        }
                        else
                        {
                            ColorMode = GBA_ColorMode.Color4bpp;
                        }
                    }
                    else
                    {
                        ColorMode = GBA_ColorMode.Color8bpp;
                    }
                    UsesTileKitDirectly = true;
                    break;

                case Type.PoP:
                    Unk_0C    = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                    Unk_0D    = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                    Unk_0E    = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    Unk_0F    = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    ColorMode = GBA_ColorMode.Color8bpp;
                    break;

                case Type.Layer2D:
                    LayerID                  = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ClusterIndex             = s.Serialize <byte>(ClusterIndex, name: nameof(ClusterIndex));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));

                    UsesTileKitDirectly = s.Serialize <bool>(UsesTileKitDirectly, name: nameof(UsesTileKitDirectly));
                    ColorMode           = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                    TileKitIndex        = s.Serialize <byte>(TileKitIndex, name: nameof(TileKitIndex));
                    Unk_0F = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    break;
                }
            }

            if (StructType != Type.TextLayerMode7)
            {
                if (!IsCompressed)
                {
                    SerializeTileMap(s);
                }
                else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_PrinceOfPersia && StructType != Type.PoP)
                {
                    s.DoEncoded(new GBA_Huffman4Encoder(), () => s.DoEncoded(new GBA_LZSSEncoder(), () => SerializeTileMap(s)));
                }
                else
                {
                    s.DoEncoded(new GBA_LZSSEncoder(), () => SerializeTileMap(s));
                }
                s.Align();
            }
        }
        public override void SerializeImpl(SerializerObject s)
        {
            Pointer0  = s.SerializePointer(Pointer0, name: nameof(Pointer0));
            Pointer1  = s.SerializePointer(Pointer1, name: nameof(Pointer1));
            Pointer2  = s.SerializePointer(Pointer2, name: nameof(Pointer2));
            Pointer3  = s.SerializePointer(Pointer3, name: nameof(Pointer3));
            Pointer4  = s.SerializePointer(Pointer4, name: nameof(Pointer4));
            Pointer5  = s.SerializePointer(Pointer5, name: nameof(Pointer5));
            Pointer6  = s.SerializePointer(Pointer6, name: nameof(Pointer6));
            Pointer7  = s.SerializePointer(Pointer7, name: nameof(Pointer7));
            Pointer8  = s.SerializePointer(Pointer8, name: nameof(Pointer8));
            Pointer9  = s.SerializePointer(Pointer9, name: nameof(Pointer9));
            Pointer10 = s.SerializePointer(Pointer10, name: nameof(Pointer10));
            Pointer11 = s.SerializePointer(Pointer11, name: nameof(Pointer11));
            AnimatedPalettesPointer = s.SerializePointer(AnimatedPalettesPointer, name: nameof(AnimatedPalettesPointer));

            // TODO: Remove try/catch
            try
            {
                s.DoAt(Pointer5, () =>
                {
                    s.DoEncoded(new RHREncoder(), () =>
                    {
                        Pointer5_Data = s.SerializeArray <byte>(Pointer5_Data, s.CurrentLength, name: nameof(Pointer5_Data));
                    });
                });
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"Failed to decompress {Pointer5}: {ex.Message}\n{ex.InnerException?.StackTrace}");
            }
            try
            {
                s.DoAt(Pointer7, () =>
                {
                    s.DoEncoded(new RHREncoder(), () =>
                    {
                        Pointer7_Data = s.SerializeArray <byte>(Pointer7_Data, s.CurrentLength, name: nameof(Pointer7_Data));
                    });
                });
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"Failed to decompress: {ex.Message}");
            }
            try
            {
                s.DoAt(Pointer9, () =>
                {
                    s.DoEncoded(new RHREncoder(), () =>
                    {
                        Pointer9_Data = s.SerializeArray <byte>(Pointer9_Data, s.CurrentLength, name: nameof(Pointer9_Data));
                    });
                });
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"Failed to decompress: {ex.Message}");
            }
            try
            {
                s.DoAt(Pointer11, () =>
                {
                    s.DoEncoded(new RHREncoder(), () =>
                    {
                        Pointer11_Data = s.SerializeArray <byte>(Pointer11_Data, s.CurrentLength, name: nameof(Pointer11_Data));
                    });
                });
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"Failed to decompress: {ex.Message}");
            }

            //AnimatedPalettes = s.DoAt(PalettesPointer, () => s.SerializeObjectArray<ARGB1555Color>(AnimatedPalettes, 16 * 45, name: nameof(AnimatedPalettes)));
        }