/// <summary> /// Handles the data serialization /// </summary> /// <param name="s">The serializer object</param> public override void SerializeImpl(SerializerObject s) { NumberOfLanguages = s.Serialize <byte>(NumberOfLanguages, name: nameof(NumberOfLanguages)); LanguageUtilized = s.Serialize <byte>(LanguageUtilized, name: nameof(LanguageUtilized)); KeyboardType = s.Serialize <KeyboardTypes>(KeyboardType, name: nameof(KeyboardType)); // Most versions have 3 languages, but sometimes the NumberOfLanguages is set to 1 because only 1 is available. Other versions may have up to 5. var numLangNames = Mathf.Clamp(NumberOfLanguages, 3, 5); if (s.GameSettings.EngineVersion == EngineVersion.R1_PS1_Edu && (s.GameSettings.EduVolume.StartsWith("IT") || s.GameSettings.EduVolume.StartsWith("CS"))) { numLangNames = 5; } if (s.GameSettings.EngineVersion == EngineVersion.R1_PC_Edu && (s.GameSettings.EduVolume.StartsWith("HN") || s.GameSettings.EduVolume.StartsWith("IS") || s.GameSettings.EduVolume.StartsWith("NL"))) { numLangNames = 5; } LanguageNames = s.SerializeStringArray(LanguageNames, numLangNames, 11, name: nameof(LanguageNames)); var align = 3 + LanguageNames.Length * 11 + 8; if (align % 4 != 0) { s.SerializeArray <byte>(new byte[align % 4], 4 - (align % 4), name: "Align"); } TextDefineCount = s.Serialize <uint>(TextDefineCount, name: nameof(TextDefineCount)); Unk1 = s.Serialize <ushort>(Unk1, name: nameof(Unk1)); Unk2 = s.Serialize <ushort>(Unk2, name: nameof(Unk2)); TextDefine = s.SerializeObjectArray <R1_PC_LocFileString>(TextDefine, TextDefineCount, name: nameof(TextDefine)); }
public override void SerializeImpl(SerializerObject s) { var manager = (R1_PS1BaseManager)s.GameSettings.GetGameManager; if (manager.TypeZDCOffset != null) { TypeZDC = s.DoAt(new Pointer(manager.TypeZDCOffset.Value, Offset.file), () => s.SerializeObjectArray <R1_ZDCEntry>(TypeZDC, manager.TypeZDCCount, name: nameof(TypeZDC))); } if (manager.ZDCDataOffset != null) { ZDCData = s.DoAt(new Pointer(manager.ZDCDataOffset.Value, Offset.file), () => s.SerializeObjectArray <R1_ZDCData>(ZDCData, manager.ZDCDataCount, name: nameof(ZDCData))); } if (manager.EventFlagsOffset != null) { if (s.GameSettings.EngineVersion == EngineVersion.R1_Saturn) { EventFlags = s.DoAt(new Pointer(manager.EventFlagsOffset.Value, Offset.file), () => s.SerializeArray <int>(EventFlags?.Select(x => BitHelpers.ReverseBits((int)x)).ToArray(), manager.EventFlagsCount, name: nameof(EventFlags))).Select(BitHelpers.ReverseBits).Select(x => (R1_EventFlags)x).ToArray(); } else { EventFlags = s.DoAt(new Pointer(manager.EventFlagsOffset.Value, Offset.file), () => s.SerializeArray <R1_EventFlags>(EventFlags, manager.EventFlagsCount, name: nameof(EventFlags))); } } if (manager.WorldInfoOffset != null) { WorldInfo = s.DoAt(new Pointer(manager.WorldInfoOffset.Value, Offset.file), () => s.SerializeObjectArray <R1_WorldMapInfo>(WorldInfo, 24, name: nameof(WorldInfo))); } if (manager.LevelBackgroundIndexTableOffset != null) { if (LevelBackgroundIndexTable == null) { LevelBackgroundIndexTable = new byte[6][]; } s.DoAt(new Pointer(manager.LevelBackgroundIndexTableOffset.Value, Offset.file), () => { for (int i = 0; i < LevelBackgroundIndexTable.Length; i++) { LevelBackgroundIndexTable[i] = s.SerializeArray <byte>(LevelBackgroundIndexTable[i], 30, name: $"{nameof(LevelBackgroundIndexTable)}[{i}]"); } }); } var fileTableInfos = manager.FileTableInfos; if (FileTable == null) { FileTable = new R1_PS1_FileTableEntry[fileTableInfos.Sum(x => x.Count)]; } var index = 0; foreach (var info in fileTableInfos) { s.DoAt(new Pointer(info.Offset, Offset.file), () => { for (int i = 0; i < info.Count; i++) { FileTable[index] = s.SerializeObject <R1_PS1_FileTableEntry>(FileTable[index], name: $"{nameof(FileTable)}_{info.FileType}[{i}]"); index++; } }); } if (s.GameSettings.EngineVersion == EngineVersion.R1_Saturn) { var saturnManager = (R1_Saturn_Manager)manager; Saturn_Palettes = s.DoAt(new Pointer(saturnManager.GetPalOffset, Offset.file), () => s.SerializeObjectArray <RGBA5551Color>(Saturn_Palettes, 25 * 256 * 2, name: nameof(Saturn_Palettes))); if (Saturn_FNDFileTable == null) { Saturn_FNDFileTable = new string[6][]; } s.DoAt(new Pointer(saturnManager.GetFndFileTableOffset, Offset.file), () => { for (int i = 0; i < Saturn_FNDFileTable.Length; i++) { Saturn_FNDFileTable[i] = s.SerializeStringArray(Saturn_FNDFileTable[i], 10, 12, name: $"{nameof(Saturn_FNDFileTable)}[{i}]"); } }); if (Saturn_FNDSPFileTable == null) { Saturn_FNDSPFileTable = new string[6][]; } s.DoAt(new Pointer(saturnManager.GetFndSPFileTableOffset, Offset.file), () => { for (int i = 0; i < Saturn_FNDSPFileTable.Length; i++) { Saturn_FNDSPFileTable[i] = s.SerializeStringArray(Saturn_FNDSPFileTable[i], 5, 12, name: $"{nameof(Saturn_FNDSPFileTable)}[{i}]"); } }); if (Saturn_FNDIndexTable == null) { Saturn_FNDIndexTable = new byte[7][]; } s.DoAt(new Pointer(saturnManager.GetFndIndexTableOffset, Offset.file), () => { for (int i = 0; i < Saturn_FNDIndexTable.Length; i++) { Saturn_FNDIndexTable[i] = s.SerializeArray <byte>(Saturn_FNDIndexTable[i], 25, name: $"{nameof(Saturn_FNDIndexTable)}[{i}]"); } }); } }
/// <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++; } } } }); }