public override void SerializeBlock(SerializerObject s) { // Serialize data Height = s.Serialize <byte>(Height, name: nameof(Height)); Width = s.Serialize <byte>(Width, name: nameof(Width)); UnkData0 = s.SerializeArray <byte>(UnkData0, 4, name: nameof(UnkData0)); PaletteCount = s.Serialize <byte>(PaletteCount, name: nameof(PaletteCount)); PaletteBlockCount = s.Serialize <byte>(PaletteBlockCount, name: nameof(PaletteBlockCount)); PaletteOffset = s.Serialize <uint>(PaletteOffset, name: nameof(PaletteOffset)); TileDataOffset = s.Serialize <uint>(TileDataOffset, name: nameof(TileDataOffset)); var basePtr = s.CurrentPointer; s.Goto(basePtr + TileDataOffset); TileSet = s.SerializeArray <byte>(TileSet, Width * Height * 0x10, name: nameof(TileSet)); PalIndices = s.SerializeArray <byte>(PalIndices, Width * Height, name: nameof(PalIndices)); s.Goto(basePtr + PaletteOffset); if (Palette == null) { Palette = new RGBA5551Color[PaletteBlockCount][]; } for (int i = 0; i < PaletteBlockCount; i++) { Palette[i] = s.SerializeObjectArray <RGBA5551Color>(Palette[i], PaletteCount * 4, name: $"{nameof(Palette)}[{i}]"); } }
protected override void InitMemoryLoading(SerializerObject s, Pointer offset) { s.Goto(offset); GameMemoryData.Update(s); s.Goto(offset); GlobalData.SetPointers(s); }
public override void SerializeImpl(SerializerObject s) { s.Goto(Offset + 0x1C); Name = s.SerializeString(Name, name: nameof(Name)); s.Goto(Offset + 0x2C); HuffTableOffset = s.Serialize <ushort>(HuffTableOffset, name: nameof(HuffTableOffset)); HuffTableLength = s.Serialize <ushort>(HuffTableLength, name: nameof(HuffTableLength)); s.DoAt(Offset + HuffTableOffset, () => { HuffTable = s.SerializeObjectArray <HuffTableEntry>(HuffTable, HuffTableLength / 6, name: nameof(HuffTable)); }); NumTables = s.Serialize <ushort>(NumTables, name: nameof(NumTables)); Tables = s.SerializeObjectArray <Table>(Tables, NumTables, onPreSerialize: t => t.HuffTable = HuffTable, name: nameof(Tables)); }
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}]"); } }
public override void SerializeBlock(SerializerObject s) { UShort_00 = s.Serialize <ushort>(UShort_00, name: nameof(UShort_00)); PatternOffsetsOffset = s.Serialize <ushort>(PatternOffsetsOffset, name: nameof(PatternOffsetsOffset)); Byte_04 = s.Serialize <byte>(Byte_04, name: nameof(Byte_04)); PatternCount = s.Serialize <byte>(PatternCount, name: nameof(PatternCount)); UInt_06 = s.Serialize <uint>(UInt_06, name: nameof(UInt_06)); s.DoAt(BlockStartPointer + PatternOffsetsOffset, () => { PatternOffsets = s.SerializeArray <ushort>(PatternOffsets, PatternCount, name: nameof(PatternOffsets)); }); if (Patterns == null) { Patterns = new Pattern[PatternCount]; } for (int i = 0; i < PatternCount; i++) { Patterns[i] = s.DoAt(BlockStartPointer + PatternOffsets[i], () => { return(s.SerializeObject <Pattern>(Patterns[i], name: $"{nameof(Patterns)}[{i}]")); }); } if (Patterns.Length > 0) { s.Goto(Patterns[Patterns.Length - 1].Offset + Patterns[Patterns.Length - 1].Size); } }
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); }); }); } } }
public override void SerializeBlock(SerializerObject s) { if (s.GameSettings.GBA_IsMilan && s.GameSettings.EngineVersion != EngineVersion.GBA_TomClancysRainbowSixRogueSpear) { // Copied from function at 0x080087e4 in The Mummy (US) // Serialize header s.DoAt(ShanghaiOffsetTable.GetPointer(0), () => { Milan_Ushort_00 = s.Serialize <ushort>(Milan_Ushort_00, name: nameof(Milan_Ushort_00)); Milan_Ushort_02 = s.Serialize <ushort>(Milan_Ushort_02, name: nameof(Milan_Ushort_02)); }); // Go to palette data s.Goto(ShanghaiOffsetTable.GetPointer(1)); if (Milan_Palettes == null) { Milan_Palettes = new Dictionary <int, RGBA5551Color[]>(); if (Milan_Ushort_00 == 0) { var palIndex = 0; do { if (BitHelpers.ExtractBits(Milan_Ushort_02, 1, palIndex) == 1) { var pal = s.SerializeObjectArray <RGBA5551Color>(default, 0x10, name: $"Palette[{palIndex}]");
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)); } } }); } } }
protected void SwitchSerializer(SerializerObject s) { if (s != CurrentSerializer) { s.Goto(CurrentSerializer.CurrentPointer); CurrentSerializer = s; } }
/// <summary> /// Gets the file bytes based on name /// </summary> /// <param name="s">The serializer object</param> /// <param name="fileName">The file name</param> /// <returns>The file bytes</returns> public async UniTask <byte[]> GetFileBytesAsync(SerializerObject s, string fileName) { // Attempt to find the file var file = GetFile(fileName); s.Goto(BaseOffset + file.FileOffset); await s.FillCacheForRead((int)file.FileSize); // Read the bytes byte[] buffer = s.SerializeArray <byte>(default, file.FileSize, name: nameof(buffer));
public override void SerializeImpl(SerializerObject s) { // Header SceneBlockLength = s.Serialize <uint>(SceneBlockLength, name: nameof(SceneBlockLength)); Scene = s.SerializeObject <GBA_Scene>(Scene, onPreSerialize: sc => sc.IsGCNBlock = true, name: nameof(Scene)); // Data s.Goto(Offset + SceneBlockLength); PlayFieldBlockLength = s.Serialize <uint>(PlayFieldBlockLength, name: nameof(PlayFieldBlockLength)); PlayField = s.SerializeObject <GBA_PlayField>(PlayField, onPreSerialize: pf => pf.IsGCNBlock = true, name: nameof(PlayField)); }
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()); } }
public override void SerializeBlock(SerializerObject s) { var blockOffset = s.CurrentPointer; // Serialize data (always little endian) s.DoEndian(R1Engine.Serialize.BinaryFile.Endian.Little, () => { // Parse data GameObjectsCount = s.Serialize <ushort>(GameObjectsCount, name: nameof(GameObjectsCount)); GameObjectsOffset = s.Serialize <ushort>(GameObjectsOffset, name: nameof(GameObjectsOffset)); KnotsHeight = s.Serialize <byte>(KnotsHeight, name: nameof(KnotsHeight)); KnotsWidth = s.Serialize <byte>(KnotsWidth, name: nameof(KnotsWidth)); KnotsOffset = s.Serialize <ushort>(KnotsOffset, name: nameof(KnotsOffset)); Height = s.Serialize <ushort>(Height, name: nameof(Height)); Width = s.Serialize <ushort>(Width, name: nameof(Width)); Timeout = s.Serialize <byte>(Timeout, name: nameof(Timeout)); Index_PlayField = s.Serialize <byte>(Index_PlayField, name: nameof(Index_PlayField)); IndexMin_ActorModels = s.Serialize <byte>(IndexMin_ActorModels, name: nameof(IndexMin_ActorModels)); IndexMax_ActorModels = s.Serialize <byte>(IndexMax_ActorModels, name: nameof(IndexMax_ActorModels)); ObjPalette = s.SerializeObjectArray <RGBA5551Color>(ObjPalette, 8 * 4, name: nameof(ObjPalette)); TilePalette = s.SerializeObjectArray <RGBA5551Color>(TilePalette, 8 * 4, name: nameof(TilePalette)); MainActor_0 = s.Serialize <ushort>(MainActor_0, name: nameof(MainActor_0)); MainActor_1 = s.Serialize <ushort>(MainActor_1, name: nameof(MainActor_1)); MainActor_2 = s.Serialize <ushort>(MainActor_2, name: nameof(MainActor_2)); Index_SoundBank = s.Serialize <byte>(Index_SoundBank, name: nameof(Index_SoundBank)); // TODO: Parse data (UnkActorStructs?) UnknownData = s.SerializeArray <byte>(UnknownData, (blockOffset + GameObjectsOffset).AbsoluteOffset - s.CurrentPointer.AbsoluteOffset, name: nameof(UnknownData)); // Parse from pointers GameObjects = s.DoAt(blockOffset + GameObjectsOffset, () => s.SerializeObjectArray <GBC_GameObject>(GameObjects, GameObjectsCount, name: nameof(GameObjects))); Knots = s.DoAt(blockOffset + KnotsOffset, () => s.SerializeObjectArray <GBC_Knot>(Knots, KnotsHeight * KnotsWidth, name: nameof(Knots))); s.Goto(Knots.Last().Offset + Knots.Last().ActorsCount * 2 + 1); // Go to end of the block }); // Parse data from pointers PlayField = s.DoAt(DependencyTable.GetPointer(Index_PlayField - 1), () => s.SerializeObject <GBC_PlayField>(PlayField, name: nameof(PlayField))); SoundBank = s.DoAt(DependencyTable.GetPointer(Index_SoundBank - 1), () => s.SerializeObject <GBC_SoundBank>(SoundBank, name: nameof(SoundBank))); // Parse actor models foreach (var actor in GameObjects.Where(x => x.Index_ActorModel > 1)) { actor.ActorModel = s.DoAt(DependencyTable.GetPointer(actor.Index_ActorModel - 1), () => s.SerializeObject <GBC_ActorModelBlock>(actor.ActorModel, name: $"{nameof(actor.ActorModel)}[{actor.Index_ActorModel}]")); } }
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}");
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); }
public override void SerializeImpl(SerializerObject s) { Length = s.Serialize <byte>(Length, name: nameof(Length)); if (Length == 0) { return; } ExtendedAttributeRecord = s.Serialize <byte>(ExtendedAttributeRecord, name: nameof(ExtendedAttributeRecord)); ExtentLBA = s.Serialize <uint>(ExtentLBA, name: nameof(ExtentLBA)); BigEndianValue = s.SerializeArray <byte>(BigEndianValue, 4, name: nameof(BigEndianValue)); ExtentSize = s.Serialize <uint>(ExtentSize, name: nameof(ExtentSize)); BigEndianValue = s.SerializeArray <byte>(BigEndianValue, 4, name: nameof(BigEndianValue)); RecordingDateTime = s.SerializeArray <byte>(RecordingDateTime, 7, name: nameof(RecordingDateTime)); FileFlags = s.Serialize <RecordFileFlags>(FileFlags, name: nameof(FileFlags)); InterleaveFileUnitSize = s.Serialize <byte>(InterleaveFileUnitSize, name: nameof(InterleaveFileUnitSize)); InterleaveFileGapSize = s.Serialize <byte>(InterleaveFileGapSize, name: nameof(InterleaveFileGapSize)); VolumeSequenceNumber = s.Serialize <ushort>(VolumeSequenceNumber, name: nameof(VolumeSequenceNumber)); BigEndianValue = s.SerializeArray <byte>(BigEndianValue, 2, name: nameof(BigEndianValue)); FileIdentifierLength = s.Serialize <byte>(FileIdentifierLength, name: nameof(FileIdentifierLength)); FileIdentifier = s.SerializeString(FileIdentifier, length: FileIdentifierLength, name: nameof(FileIdentifier)); if (s.CurrentPointer - Offset < Length && FileIdentifierLength % 2 != 0) { Padding = s.Serialize <byte>(Padding, name: nameof(Padding)); } if (s.CurrentPointer - Offset < Length) { SystemUse = s.SerializeArray <byte>(SystemUse, Length - (s.CurrentPointer - Offset), name: nameof(SystemUse)); } s.Goto(Offset + Length); }
public override void SerializeBlock(SerializerObject s) { // Serialize data if (s.GameSettings.EngineVersion == EngineVersion.GBC_R1_PocketPC) { if (PresetTilesCount.HasValue) { TilesCount = PresetTilesCount.Value; } else { TilesCount = s.Serialize <uint>(TilesCount, name: nameof(TilesCount)); } TileDataPocketPC = s.SerializeObjectArray <BGR565Color>(TileDataPocketPC, TilesCount * 8 * 8, name: nameof(TileDataPocketPC)); } else if (s.GameSettings.EngineVersion == EngineVersion.GBC_R1_Palm) { bool greyScale = s.GameSettings.GameModeSelection == GameModeSelection.RaymanGBCPalmOSGreyscale || s.GameSettings.GameModeSelection == GameModeSelection.RaymanGBCPalmOSGreyscaleDemo; TilesCount = s.Serialize <uint>(TilesCount, name: nameof(TilesCount)); TileData = s.SerializeArray <byte>(TileData, TilesCount * (greyScale ? 0x20 : 0x40), name: nameof(TileData)); } else { PaletteCount = s.Serialize <byte>(PaletteCount, name: nameof(PaletteCount)); PaletteOffset = s.Serialize <ushort>(PaletteOffset, name: nameof(PaletteOffset)); TileDataOffset = s.Serialize <ushort>(TileDataOffset, name: nameof(TileDataOffset)); TilesCount = s.Serialize <UInt24>((UInt24)TilesCount, name: nameof(TilesCount)); s.DoAt(BlockStartPointer + PaletteOffset, () => { Palette = s.SerializeObjectArray <RGBA5551Color>(Palette, PaletteCount * 4, name: nameof(Palette)); }); s.DoAt(BlockStartPointer + TileDataOffset, () => { TileData = s.SerializeArray <byte>(TileData, TilesCount * 0x10, name: nameof(TileData)); }); // Go to end of block s.Goto(BlockStartPointer + TileDataOffset + TilesCount * 0x10); } }
public override void SerializeBlock(SerializerObject s) { var basePointer = s.CurrentPointer; if (TileLayerDatas == null) { TileLayerDatas = new GBAVV_TileLayerData[MapData.MapLayers.Length]; } for (int i = 0; i < TileLayerDatas.Length; i++) { if (MapData.MapLayers[i] != null) { TileLayerDatas[i] = s.DoAt(basePointer + MapData.MapLayers[i].DataBlockOffset, () => s.SerializeObject <GBAVV_TileLayerData>(TileLayerDatas[i], x => x.MapLayer = MapData.MapLayers[i], name: $"{nameof(TileLayerDatas)}[{i}]")); } } if (MapData.CollisionDataPointer != null) { CollisionLayerData = s.DoAt(basePointer + MapData.CollisionLayer.DataBlockOffset, () => s.SerializeObject <GBAVV_TileLayerData>(CollisionLayerData, x => x.MapLayer = MapData.CollisionLayer, name: nameof(CollisionLayerData))); } s.Goto(basePointer + BlockLength); }
/// <summary> /// Serializes the data /// </summary> /// <param name="s">The serializer object</param> public override void SerializeImpl(SerializerObject s) { // HEADER BLOCK LevelDefines = s.SerializeObject <R1_PC_KitLevelDefinesBlock>(LevelDefines, name: nameof(LevelDefines)); // Serialize map size Width = s.Serialize <ushort>(Width, name: nameof(Width)); Height = s.Serialize <ushort>(Height, name: nameof(Height)); // Create the palettes if necessary if (ColorPalettes == null) { ColorPalettes = new RGB666Color[][] { new RGB666Color[256], new RGB666Color[256], new RGB666Color[256], }; } // Serialize each palette for (var paletteIndex = 0; paletteIndex < ColorPalettes.Length; paletteIndex++) { var palette = ColorPalettes[paletteIndex]; ColorPalettes[paletteIndex] = s.SerializeObjectArray <RGB666Color>(palette, palette.Length, name: nameof(ColorPalettes) + "[" + paletteIndex + "]"); } // Serialize unknown byte LastPlan1Palette = s.Serialize <byte>(LastPlan1Palette, name: nameof(LastPlan1Palette)); // Serialize unknown bytes Unk1_1 = s.Serialize <uint>(Unk1_1, name: nameof(Unk1_1)); LeftoverTextureOffsetTable = s.SerializeArray <uint>(LeftoverTextureOffsetTable, 1200, name: nameof(LeftoverTextureOffsetTable)); // Serialize event block header Unk3 = s.Serialize <uint>(Unk3, name: nameof(Unk3)); Unk4 = s.Serialize <uint>(Unk4, name: nameof(Unk4)); EventCount = s.Serialize <ushort>(EventCount, name: nameof(EventCount)); EventBlockSize = s.Serialize <uint>(EventBlockSize, name: nameof(EventBlockSize)); EventBlockPointer = s.CurrentPointer; s.Goto(EventBlockPointer + EventBlockSize); // Serialize event command counts EventNumCommands = s.SerializeArray <ushort>(EventNumCommands, EventCount, name: nameof(EventNumCommands)); EventNumLabelOffsets = s.SerializeArray <ushort>(EventNumLabelOffsets, EventCount, name: nameof(EventNumLabelOffsets)); // Serialize tile-set texture data TileTextures = s.SerializeArray <byte>(TileTextures, 512 * 256, name: nameof(TileTextures)); // Serialize the map tiles MapBlockSize = s.Serialize <uint>(MapBlockSize, name: nameof(MapBlockSize)); MapTiles = s.SerializeObjectArray <MapTile>(MapTiles, MapBlockSize / 6, name: nameof(MapTiles)); // Finally, read the events s.DoAt(EventBlockPointer, () => { // Helper method to get the current position inside of the event block int GetPosInEventBlock() { int currentPos = (int)(s.CurrentPointer - EventBlockPointer); return(currentPos); } // Serialize the events Events = s.SerializeObjectArray <R1_EventData>(Events, EventCount, name: nameof(Events)); // Padding... s.SerializeArray <byte>(Enumerable.Repeat((byte)0xCD, EventCount * 4).ToArray(), EventCount * 4, name: "Padding"); if (EventCount % 2 != 0) { const int padding = 4; s.SerializeArray <byte>(Enumerable.Repeat((byte)0xCD, padding).ToArray(), padding, name: "Padding"); } // Serialize the event link table EventLinkTable = s.SerializeArray <ushort>(EventLinkTable, EventCount, name: nameof(EventLinkTable)); // Padding... if (EventCount % 2 == 0) { const int padding = 2; s.SerializeArray <byte>(Enumerable.Repeat((byte)0xCD, padding).ToArray(), padding, name: "Padding"); } // Serialize the commands if (EventCommands == null) { EventCommands = new R1_PC_EventCommand[EventCount]; } for (int i = 0; i < EventCount; i++) { EventCommands[i] = new R1_PC_EventCommand(); if (EventNumCommands[i] != 0) { if (GetPosInEventBlock() % 4 != 0) { int padding = 4 - GetPosInEventBlock() % 4; s.SerializeArray <byte>(Enumerable.Repeat((byte)0xCD, padding).ToArray(), padding, name: "Padding"); } EventCommands[i].CommandLength = EventNumCommands[i]; EventCommands[i].Commands = s.SerializeObject <R1_EventCommandCollection>(EventCommands[i].Commands, name: nameof(R1_PC_EventCommand.Commands)); } else { EventCommands[i].Commands = new R1_EventCommandCollection() { Commands = new R1_EventCommand[0] }; } if (EventNumLabelOffsets[i] != 0) { if (GetPosInEventBlock() % 4 != 0) { int padding = 4 - GetPosInEventBlock() % 4; s.SerializeArray <byte>(Enumerable.Repeat((byte)0xCD, padding).ToArray(), padding, name: "Padding"); } EventCommands[i].LabelOffsetCount = EventNumLabelOffsets[i]; EventCommands[i].LabelOffsetTable = s.SerializeArray <ushort>(EventCommands[i].LabelOffsetTable, EventCommands[i].LabelOffsetCount, name: nameof(R1_PC_EventCommand.LabelOffsetTable)); } else { EventCommands[i].LabelOffsetTable = new ushort[0]; } } }); }
public override void SerializeImpl(SerializerObject s) { bool isShanghai = s.GameSettings.GBA_IsShanghai || s.GameSettings.GBA_IsMilan; Command = s.Serialize <InstructionCommand>(Command, name: nameof(Command)); if (isShanghai) { CommandSize = s.Serialize <byte>(CommandSize, name: nameof(CommandSize)); // In bytes } switch (Command) { case InstructionCommand.SpriteNew: LayerCount = s.Serialize <byte>(LayerCount, name: nameof(LayerCount)); Padding = s.SerializeArray <byte>(Padding, isShanghai ? 1 : 2, name: nameof(Padding)); Layers = s.SerializeObjectArray <GBA_BatmanVengeance_AnimationChannel>(Layers, LayerCount, name: nameof(Layers)); break; case InstructionCommand.SpriteTilemap: Padding = s.SerializeArray <byte>(Padding, isShanghai ? 2 : 3, name: nameof(Padding)); TileMap = s.SerializeObjectArray <TileGraphicsInfo>(TileMap, Puppet.TilemapWidth * Puppet.TilemapHeight, name: nameof(TileMap)); break; case InstructionCommand.Hitbox: HitboxXPos = s.Serialize <sbyte>(HitboxXPos, name: nameof(HitboxXPos)); HitboxYPos = s.Serialize <sbyte>(HitboxYPos, name: nameof(HitboxYPos)); HitboxHalfWidth = s.Serialize <ushort>(HitboxHalfWidth, name: nameof(HitboxHalfWidth)); HitboxHalfHeight = s.Serialize <ushort>(HitboxHalfHeight, name: nameof(HitboxHalfHeight)); break; case InstructionCommand.Unknown81: Byte_81_02 = s.Serialize <byte>(Byte_81_02, name: nameof(Byte_81_02)); Byte_81_03 = s.Serialize <byte>(Byte_81_03, name: nameof(Byte_81_03)); Byte_81_04 = s.Serialize <byte>(Byte_81_04, name: nameof(Byte_81_04)); break; case InstructionCommand.Unknown82: Byte_82_02 = s.Serialize <byte>(Byte_82_02, name: nameof(Byte_82_02)); Byte_82_03 = s.Serialize <byte>(Byte_82_03, name: nameof(Byte_82_03)); break; case InstructionCommand.Unknown83: Byte_83_02 = s.Serialize <byte>(Byte_83_02, name: nameof(Byte_83_02)); Byte_83_03 = s.Serialize <byte>(Byte_83_03, name: nameof(Byte_83_03)); break; case InstructionCommand.Hitbox_Batman: Padding = s.SerializeArray <byte>(Padding, isShanghai ? 2 : 3, name: nameof(Padding)); Hitbox_Y1 = s.Serialize <sbyte>(Hitbox_Y1, name: nameof(Hitbox_Y1)); Hitbox_X1 = s.Serialize <sbyte>(Hitbox_X1, name: nameof(Hitbox_X1)); Hitbox_Y2 = s.Serialize <sbyte>(Hitbox_Y2, name: nameof(Hitbox_Y2)); Hitbox_X2 = s.Serialize <sbyte>(Hitbox_X2, name: nameof(Hitbox_X2)); break; case InstructionCommand.Unknown85: Byte_85_02 = s.Serialize <byte>(Byte_85_02, name: nameof(Byte_85_02)); Byte_85_03 = s.Serialize <byte>(Byte_85_03, name: nameof(Byte_85_03)); break; case InstructionCommand.Unknown86: Byte_86_02 = s.Serialize <byte>(Byte_86_02, name: nameof(Byte_86_02)); Byte_86_03 = s.Serialize <byte>(Byte_86_03, name: nameof(Byte_86_03)); Byte_86_04 = s.Serialize <byte>(Byte_86_04, name: nameof(Byte_86_04)); Byte_86_05 = s.Serialize <byte>(Byte_86_05, name: nameof(Byte_86_05)); Byte_86_06 = s.Serialize <byte>(Byte_86_06, name: nameof(Byte_86_06)); Byte_86_07 = s.Serialize <byte>(Byte_86_07, name: nameof(Byte_86_07)); break; case InstructionCommand.Terminator0: case InstructionCommand.Terminator20: Time = s.Serialize <byte>(Time, name: nameof(Time)); Padding = s.SerializeArray <byte>(Padding, isShanghai ? 1 : 2, name: nameof(Padding)); break; default: throw new Exception($"Unknown command {Command}"); } if (isShanghai) { if (CommandSize < 2) { throw new Exception($"Command size {CommandSize} at {Offset}"); } s.Goto(Offset + CommandSize); } }
/// <summary> /// Serializes the data /// </summary> /// <param name="s">The serializer object</param> public override void SerializeImpl(SerializerObject s) { if (FileType == Type.World) { // Serialize header BG1 = s.Serialize <ushort>(BG1, name: nameof(BG1)); BG2 = s.Serialize <ushort>(BG2, name: nameof(BG2)); Plan0NumPcxCount = s.Serialize <byte>(Plan0NumPcxCount, name: nameof(Plan0NumPcxCount)); s.DoXOR(0x19, () => Plan0NumPcxFiles = s.SerializeStringArray(Plan0NumPcxFiles, Plan0NumPcxCount, 8, name: nameof(Plan0NumPcxFiles))); // Serialize counts DESCount = s.Serialize <ushort>(DESCount, name: nameof(DESCount)); ETACount = s.Serialize <byte>(ETACount, name: nameof(ETACount)); DESBlockLength = s.Serialize <uint>(DESBlockLength, name: nameof(DESBlockLength)); } else { // Serialize header ETACount = s.Serialize <byte>(ETACount, name: nameof(ETACount)); DESCount = s.Serialize <ushort>(DESCount, name: nameof(DESCount)); } // Serialize DES data DESData = s.SerializeObjectArray <R1_PS1Edu_DESData>(DESData, DESCount, name: nameof(DESData)); if (FileType == Type.World) { WorldDefine = WorldDefine = s.SerializeObject <R1_PC_WorldDefine>(WorldDefine, name: nameof(WorldDefine)); } // Serialize main data block length MainDataBlockLength = s.Serialize <uint>(MainDataBlockLength, name: nameof(MainDataBlockLength)); // We parse the main data block later... MainDataBlockPointer = s.CurrentPointer; s.Goto(MainDataBlockPointer + MainDataBlockLength); if (FileType == Type.Allfix) { DESDataIndices = s.SerializeArray <uint>(DESDataIndices, 8, name: nameof(DESDataIndices)); } // Serialize ETA tables if (FileType == Type.World) { ETAStateCountTableCount = s.Serialize <byte>(ETAStateCountTableCount, name: nameof(ETAStateCountTableCount)); ETAStateCountTable = s.SerializeArray <byte>(ETAStateCountTable, ETAStateCountTableCount, name: nameof(ETAStateCountTable)); } else { ETAStateCountTable = s.SerializeArray <byte>(ETAStateCountTable, ETACount, name: nameof(ETAStateCountTable)); } ETASubStateCountTableCount = s.Serialize <byte>(ETASubStateCountTableCount, name: nameof(ETASubStateCountTableCount)); ETASubStateCountTable = s.SerializeArray <byte>(ETASubStateCountTable, ETASubStateCountTableCount, name: nameof(ETASubStateCountTable)); // Serialize animation descriptor layer table AnimationDescriptorLayersBlockSizeTableCount = s.Serialize <uint>(AnimationDescriptorLayersBlockSizeTableCount, name: nameof(AnimationDescriptorLayersBlockSizeTableCount)); AnimationDescriptorLayersBlockSizeTable = s.SerializeArray <ushort>(AnimationDescriptorLayersBlockSizeTable, AnimationDescriptorLayersBlockSizeTableCount, name: nameof(AnimationDescriptorLayersBlockSizeTable)); // Serialize animation layers AnimationLayers = s.SerializeObjectArray <R1_AnimationLayer>(AnimationLayers, 0xFE, name: nameof(AnimationLayers)); // Serialize the main data block s.DoAt(MainDataBlockPointer, () => { if (FileType == Type.World) { SerializeDES(); SerializeETA(); } else { SerializeETA(); SerializeDES(); } // Helper method for serializing the DES void SerializeDES() { if (ImageDescriptors == null) { ImageDescriptors = new R1_ImageDescriptor[DESCount][]; } if (AnimationDescriptors == null) { AnimationDescriptors = new R1_PS1Edu_AnimationDescriptor[DESCount][]; } int curAnimDesc = 0; // Serialize data for every DES for (int i = 0; i < DESCount; i++) { // Serialize image descriptors ImageDescriptors[i] = s.SerializeObjectArray <R1_ImageDescriptor>(ImageDescriptors[i], DESData[i].ImageDescriptorsCount, name: $"{nameof(ImageDescriptors)}[{i}]"); // Serialize animation descriptors AnimationDescriptors[i] = s.SerializeObjectArray <R1_PS1Edu_AnimationDescriptor>(AnimationDescriptors[i], DESData[i].AnimationDescriptorsCount, name: $"{nameof(AnimationDescriptors)}[{i}]"); // Serialize animation descriptor data for (int j = 0; j < AnimationDescriptors[i].Length; j++) { var descriptor = AnimationDescriptors[i][j]; if (descriptor.FrameCount <= 0) { curAnimDesc++; continue; } // Serialize layer data descriptor.LayersData = s.SerializeArray <byte>(descriptor.LayersData, AnimationDescriptorLayersBlockSizeTable[curAnimDesc], name: nameof(descriptor.LayersData)); // Padding... if (AnimationDescriptorLayersBlockSizeTable[curAnimDesc] % 4 != 0) { // Padding seems to contain garbage data in this case instead of 0xCD? int paddingLength = 4 - AnimationDescriptorLayersBlockSizeTable[curAnimDesc] % 4; s.SerializeArray <byte>(Enumerable.Repeat((byte)0xCD, paddingLength).ToArray(), paddingLength, name: "Padding"); } // Serialize frames if (descriptor.AnimFramesPointer != 0xFFFFFFFF) { descriptor.Frames = s.SerializeObjectArray <R1_AnimationFrame>(descriptor.Frames, descriptor.FrameCount, name: nameof(descriptor.Frames)); } // Parse layers if (descriptor.Layers == null) { var layers = new List <R1_AnimationLayer>(); var offset = 0; while (offset < descriptor.LayersData.Length) { if (descriptor.LayersData[offset] < 2) { layers.Add(new R1_AnimationLayer() { IsFlippedHorizontally = descriptor.LayersData[offset + 0] == 1, XPosition = descriptor.LayersData[offset + 1], YPosition = descriptor.LayersData[offset + 2], ImageIndex = descriptor.LayersData[offset + 3], }); offset += 4; } else { layers.Add(AnimationLayers[descriptor.LayersData[offset] - 2]); offset++; } } descriptor.Layers = layers.ToArray(); } curAnimDesc++; } } } // Helper method for serializing the ETA void SerializeETA() { if (ETA == null) { ETA = new R1_EventState[ETACount][][]; } var stateIndex = 0; // Serialize every ETA for (int i = 0; i < ETA.Length; i++) { if (ETA[i] == null) { ETA[i] = new R1_EventState[ETAStateCountTable[i]][]; } // EDU serializes the pointer structs, but the pointers are invalid. They can be anything as they're overwritten with valid memory pointers upon load uint[] pointerStructs = Enumerable.Repeat((uint)1, ETA[i].Length).ToArray(); _ = s.SerializeArray <uint>(pointerStructs, pointerStructs.Length, name: $"ETAPointers[{i}]"); // Serialize every state for (int j = 0; j < ETA[i].Length; j++) { // Serialize sub-states ETA[i][j] = s.SerializeObjectArray <R1_EventState>(ETA[i][j], ETASubStateCountTable[stateIndex], name: $"{nameof(ETA)}[{i}][{j}]"); stateIndex++; } } } }); }
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(); } }