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 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); }
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}"); } }
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)); }); } }
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)); } } }); } } }
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));
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"));
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}");
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)); } }
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(); } }
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}]")); } } }
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))); }