Пример #1
0
        public override void SerializeBlock(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell)
            {
                MatrixOffsets = s.SerializeArray <ushort>(MatrixOffsets, FrameCount, name: nameof(MatrixOffsets));
                s.Align(4);
                if (Matrices == null)
                {
                    Matrices = new GBA_AffineMatrix[FrameCount][];
                }

                for (int i = 0; i < Matrices.Length; i++)
                {
                    ushort offset = MatrixOffsets[i];
                    uint   count  = (uint)Math.Min((BlockSize - offset) / 8, 32);
                    s.DoAt(Offset + offset, () => {
                        Matrices[i] = s.SerializeObjectArray <GBA_AffineMatrix>(Matrices[i], count, name: $"{nameof(Matrices)}[{i}]");
                    });
                }
                s.Goto(Offset + BlockSize);
            }
            else
            {
                if (Matrices == null)
                {
                    Matrices = new GBA_AffineMatrix[1][];
                }
                Matrices[0] = s.SerializeObjectArray <GBA_AffineMatrix>(Matrices[0], BlockSize / 8, name: $"{nameof(Matrices)}[{0}]");
            }
        }
Пример #2
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)
 {
     TileSet_4bpp = s.SerializeArray <byte>(TileSet_4bpp, TileSetCount_4bpp * 0x20, name: nameof(TileSet_4bpp));
     TileSet_8bpp = s.SerializeArray <byte>(TileSet_8bpp, (TileSetCount_Total - TileSetCount_4bpp) * 0x40, name: nameof(TileSet_8bpp));
     TileSet_4bpp_ConvertIndexTable = s.SerializeArray <ushort>(TileSet_4bpp_ConvertIndexTable, TileSetCount_4bpp, name: nameof(TileSet_4bpp_ConvertIndexTable));
     s.Align();
     TileSet_4bpp_ConvertDatas = s.SerializeObjectArray <ConvertData>(TileSet_4bpp_ConvertDatas, TileSet_4bpp_ConvertIndexTable.Max() + 1, name: nameof(TileSet_4bpp_ConvertDatas));
 }
Пример #4
0
        public override void SerializeBlock(SerializerObject s)
        {
            Flags = s.Serialize <byte>(Flags, name: nameof(Flags));

            if (!s.GameSettings.GBA_IsMilan)
            {
                Byte_01             = s.Serialize <byte>(Byte_01, name: nameof(Byte_01));
                AffineMatricesIndex = s.Serialize <byte>((byte)AffineMatricesIndex, name: nameof(AffineMatricesIndex));
                Byte_03             = s.Serialize <byte>(Byte_03, name: nameof(Byte_03));
                FrameCount          = (byte)BitHelpers.ExtractBits(Byte_03, 6, 0);

                LayersPerFrame = s.SerializeArray <byte>(LayersPerFrame, FrameCount, name: nameof(LayersPerFrame));

                s.Align();

                if (Layers == null)
                {
                    Layers = new GBA_AnimationChannel[FrameCount][];
                }

                for (int i = 0; i < FrameCount; i++)
                {
                    Layers[i] = s.SerializeObjectArray <GBA_AnimationChannel>(Layers[i], LayersPerFrame[i], name: $"{nameof(Layers)}[{i}]");
                }
            }
            else
            {
                FrameCount          = s.Serialize <byte>(FrameCount, name: nameof(FrameCount));
                Milan_Ushort_02     = s.Serialize <ushort>(Milan_Ushort_02, name: nameof(Milan_Ushort_02));
                AffineMatricesIndex = s.Serialize <ushort>(AffineMatricesIndex, name: nameof(AffineMatricesIndex));
                Milan_Int_06        = s.Serialize <int>(Milan_Int_06, name: nameof(Milan_Int_06));

                var offsetBase = s.CurrentPointer;

                Milan_LayerOffsets = s.SerializeArray <ushort>(Milan_LayerOffsets, FrameCount + 1, name: nameof(Milan_LayerOffsets)); // +1 since last offset is the end

                if (Layers == null)
                {
                    Layers = new GBA_AnimationChannel[FrameCount][];
                }

                for (int i = 0; i < FrameCount; i++)
                {
                    Layers[i] = s.DoAt(offsetBase + Milan_LayerOffsets[i], () => s.SerializeObjectArray <GBA_AnimationChannel>(Layers[i], (Milan_LayerOffsets[i + 1] - Milan_LayerOffsets[i]) / 6, name: $"{nameof(Layers)}[{i}]"));
                }

                s.Goto(offsetBase + Milan_LayerOffsets.LastOrDefault());
            }
        }
Пример #5
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));
            }
        }
Пример #6
0
        public override void SerializeImpl(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion == EngineVersion.GBC_R1)
            {
                GBC_Header      = s.SerializeObject <GBC_BlockHeader>(GBC_Header, name: nameof(GBC_Header));
                GBC_DataLength  = s.Serialize <ushort>(GBC_DataLength, name: nameof(GBC_DataLength));
                GBC_DataPointer = s.SerializeObject <GBC_Pointer>(GBC_DataPointer, onPreSerialize: x => x.HasMemoryBankValue = false, name: nameof(GBC_DataPointer));
            }
            else
            {
                LUDI_Header = s.SerializeObject <LUDI_BlockIdentifier>(LUDI_Header, name: nameof(LUDI_Header));
            }

            DependencyTable = s.SerializeObject <GBC_DependencyTable>(DependencyTable, name: nameof(DependencyTable));
            s.Goto(BlockStartPointer);
            SerializeBlock(s);

            if (s.GameSettings.EngineVersion == EngineVersion.GBC_R1_Palm || s.GameSettings.EngineVersion == EngineVersion.GBC_R1_PocketPC)
            {
                s.Align(baseOffset: BlockStartPointer);
            }
            CheckBlockSize(s);
        }
Пример #7
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();
            }
        }
Пример #8
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();
            }
        }