public void Save(Stream output) { MemoryStream memory = new MemoryStream(); UnrealStream stream = new UnrealStream(memory, false, this.Version); memory.WriteUInt32(this.Version); this.Serialize(stream); if (this.Version >= 27) { memory.Position = 0; uint checksum = 0; byte[] data = new byte[1024]; while (memory.Position < memory.Length) { int read = memory.Read(data, 0, 1024); checksum = CRC32.Compute(data, 0, read, checksum); } this.Checksum = checksum; memory.WriteUInt32(checksum); } // copy out { memory.Position = 0; byte[] data = new byte[1024]; while (memory.Position < memory.Length) { int read = memory.Read(data, 0, 1024); output.Write(data, 0, read); } } }
public static SaveFileGame2 Load(Stream input, string fileName = null, MEGame expectedGame = MEGame.Unknown) { SaveFileGame2 save = new SaveFileGame2(); save.Version = input.ReadUInt32(); if (fileName != null) { // Setup save params save.FileName = fileName; var sgName = Path.GetFileNameWithoutExtension(fileName); if (sgName.StartsWith("Save_")) { // Parse number var numStr = sgName.Substring(sgName.IndexOf("_") + 1); if (int.TryParse(numStr, out var saveNum)) { save.SaveNumber = saveNum; save.SaveGameType = ESFXSaveGameType.SaveGameType_Manual; } } else if (sgName.StartsWith("AutoSave")) { save.SaveGameType = ESFXSaveGameType.SaveGameType_Auto; } else if (sgName.StartsWith("ChapterSave")) { save.SaveGameType = ESFXSaveGameType.SaveGameType_Chapter; } else if (sgName.StartsWith("QuickSave")) { save.SaveGameType = ESFXSaveGameType.SaveGameType_Quick; } } if (save.Version != 29 && save.Version != 30) { throw new FormatException("Save version not supported. This parser only supports ME2 (29) and LE2 (30)"); } if (save.Version == 29) { save.Game = MEGame.ME2; } if (save.Version == 30) { save.Game = MEGame.LE2; } if (expectedGame != MEGame.Unknown && expectedGame != save.Game) { throw new Exception($@"Sanity check failure: Save loader expected save for {expectedGame} but save appears to be for {{Game}}"); } UnrealStream stream = new UnrealStream(input, true, save.Version); save.Serialize(stream); save.BindableDebugName = save.DebugName; if (save.Version >= 27) { // sanity check, cos if we read a strange crc it'll break anyway if (input.Position != input.Length - 4) { throw new FormatException("bad checksum position"); } save.Checksum = input.ReadUInt32(); } // did we consume the entire save file? if (input.Position != input.Length) { throw new FormatException("did not consume entire file"); } return(save); }