public BangData ReadAll(BangGameTarget target, BangGameType type) { BangData data = new BangData(); data.Header = BangDataHeader.Load(chunkReader, target, type); ReadBody(data); return(data); }
public static BangDataHeader Load(BangChunkReader <BangDataHeader> chunkReader, BangGameTarget target, BangGameType type) { BangDataHeader header = new BangDataHeader(); chunkReader.ReadExpectedTag(0x4742); header.FileVersion = chunkReader.ReadInt32(); header.VersionInformation = header.FileVersion >= 25 ? chunkReader.ReadString() : "Unknown"; var lenUnkArray = header.FileVersion >= 4 ? chunkReader.ReadInt32() : 0; header.UnkCArray = chunkReader.ReadASCIIString(lenUnkArray); if (header.FileVersion >= 23) { int unkLangId = chunkReader.ReadInt32(); // TODO: This is lang id --> would need to load lang xml files header.UnkStr = chunkReader.ReadString(); } if (header.FileVersion >= 33) { header.IsMultiplayerSave = chunkReader.ReadBoolean(); } chunkReader.Header = header; chunkReader.Header.GameTarget = target; chunkReader.Header.GameType = type; return(header); }
public static void ReadFromFile(string path, BangGameTarget target = BangGameTarget.TryDetect, BangGameType type = BangGameType.TryDetect) { if (!File.Exists(path)) { throw new FileNotFoundException($"File not found {path}"); } if (target == BangGameTarget.TryDetect) { string pathExt = Path.GetExtension(path).ToLower(); switch (pathExt) { case ".sav": case ".scn": case ".rec": case ".scx": case ".rcx": target = BangGameTarget.AgeOfMythology; break; case ".age3ysav": case ".age3yscn": case ".age3yrec": case ".age3xsav": case ".age3xscn": case ".age3xrec": case ".age3sav": case ".age3scn": case ".age3rec": target = BangGameTarget.AgeOfEmpires3; break; case ".age4sav": case ".age4scn": case ".age4rec": target = BangGameTarget.AgeOfEmpiresOnline; break; default: throw new InvalidOperationException("Failed to detect game target"); } } if (type == BangGameType.TryDetect) { string pathExt = Path.GetExtension(path).ToLower(); switch (pathExt) { case ".sav": case ".age3ysav": case ".age3xsav": case ".age3sav": case ".age4sav": type = BangGameType.Save; break; case ".scn": case ".scx": case ".age3yscn": case ".age3xscn": case ".age3scn": case ".age4scn": type = BangGameType.Scenario; break; case ".rec": case ".rcx": case ".age3yrec": case ".age3xrec": case ".age3rec": case ".age4rec": type = BangGameType.Recorded; break; default: throw new InvalidOperationException("Failed to detect game type"); } } // Check magic using (var sr = new BinaryReader(File.Open(path, FileMode.Open))) { byte[] magic = sr.ReadBytes(4); if (!magic.SequenceEqual(CompressMagic)) { sr.BaseStream.Position = 0; ProcessStream(sr, target, type); return; } uint archiveSize = sr.ReadUInt32(); using (ZlibStream stream = new ZlibStream(sr.BaseStream, CompressionMode.Decompress, CompressionLevel.Default, true)) using (BinaryReader binaryStreamReader = new BinaryReader(stream)) { stream.BufferSize = 32000; ProcessStream(new BinaryReader(stream), target, type); } } }
private static void ProcessStream(BinaryReader reader, BangGameTarget target, BangGameType type) { BangScenarioReader scReader = new BangScenarioReader(new BangChunkReader <BangDataHeader>(reader)); BangData data = scReader.ReadAll(target, type); }