private static void Extract(string[] args) { string output = args.FirstOrDefault(); ulong[] guids = args.Skip(1).Select(x => ulong.Parse(x, NumberStyles.HexNumber)).ToArray(); if (string.IsNullOrWhiteSpace(output)) { return; } Dictionary <ulong, PackageRecord[]> records = new Dictionary <ulong, PackageRecord[]>(); Dictionary <ulong, PackageRecord[]> totalRecords = new Dictionary <ulong, PackageRecord[]>(); Dictionary <ulong, PackageHeader> packages = new Dictionary <ulong, PackageHeader>(); ApplicationPackageManifest apm = TankHandler.m_packageManifest; for (int i = 0; i < apm.m_packageEntries.Length; ++i) { PackageEntry entry = apm.m_packageEntries[i]; if (guids.Contains(teResourceGUID.LongKey(entry.m_packageGUID)) || guids.Contains(teResourceGUID.Index(entry.m_packageGUID))) { packages[entry.m_packageGUID] = apm.m_packages[i]; records[entry.m_packageGUID] = apm.m_packageRecords[i]; } totalRecords[entry.m_packageGUID] = apm.m_packageRecords[i]; } foreach (ulong key in records.Keys) { Save(output, key, records[key]); } }
private static void SearchType(IEnumerable <string> args) { ulong[] guids = args.Select(x => ulong.Parse(x, NumberStyles.HexNumber)).ToArray(); ApplicationPackageManifest apm = TankHandler.m_packageManifest; for (int i = 0; i < apm.m_packageEntries.Length; ++i) { PackageEntry entry = apm.m_packageEntries[i]; PackageRecord[] records = apm.m_packageRecords[i]; foreach (PackageRecord record in records.Where(x => guids.Contains(teResourceGUID.Type(x.m_GUID)))) { Log("Found {0} in package {1:X12}", teResourceGUID.AsString(record.m_GUID), teResourceGUID.LongKey(entry.m_packageGUID)); } } }
private static void ExtractType(string[] args) { string output = args.FirstOrDefault(); ulong[] guids = args.Skip(1).Select(x => ulong.Parse(x, NumberStyles.HexNumber)).ToArray(); if (string.IsNullOrWhiteSpace(output)) { return; } ApplicationPackageManifest apm = TankHandler.m_packageManifest; foreach (ContentManifestFile contentManifest in new [] { TankHandler.m_textContentManifest, TankHandler.m_speechContentManifest }) { var ids = contentManifest.m_indexMap.Where(x => guids.Length == 0 || guids.Contains(teResourceGUID.Type(x.Key))).Select(x => x.Key); Save(output, apm.m_header.m_checksum, ids, contentManifest); } }
private static void Info(IEnumerable <string> args) { ulong[] guids = args.Select(x => ulong.Parse(x, NumberStyles.HexNumber)).ToArray(); ApplicationPackageManifest apm = TankHandler.m_packageManifest; for (int i = 0; i < apm.m_packageEntries.Length; ++i) { PackageEntry entry = apm.m_packageEntries[i]; if (!guids.Contains(teResourceGUID.LongKey(entry.m_packageGUID)) && !guids.Contains(teResourceGUID.Index(entry.m_packageGUID))) { continue; } Log("Package {0:X12}:", teResourceGUID.LongKey(entry.m_packageGUID)); Log("\tUnknowns: {0}, {1}", entry.m_unknown1, entry.m_unknown2); Log("\t{0} records", apm.m_packageRecords[i].Length); } }
private void AddEntry(string path, ulong guid, ApplicationPackageManifest apm, MD5Hash hash, int size, int offset, ContentFlags flags, LocaleFlags locale) { string dir = guid != 0 ? path : Path.GetDirectoryName(path); string filename = guid != 0 ? teResourceGUID.AsString(guid) : Path.GetFileName(path); Folder d = Data; foreach (string part in dir.Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries)) { if (!d.HasFolder(part)) { d.Add(part); } d = d[part]; } if (size == 0 && guid == 0) { if (CASC.EncodingHandler.GetEntry(hash, out EncodingEntry enc)) { size = enc.Size; } } d.Files.Add(new GUIDEntry { Filename = filename, GUID = guid, FullPath = Path.Combine(d.FullPath, filename), Size = size, Offset = offset, Flags = flags, Locale = locale, Hash = hash, APM = apm }); }
public RootHandler(BinaryReader stream, ProgressReportSlave worker, CASCHandler casc) { worker?.ReportProgress(0, "Loading APM data..."); string str = Encoding.ASCII.GetString(stream.ReadBytes((int)stream.BaseStream.Length)); string[] array = str.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); List <string> components = array[0].Substring(1).ToUpper().Split('|').ToList(); components = components.Select(c => c.Split('!')[0]).ToList(); int nameComponentIdx = components.IndexOf("FILENAME"); if (nameComponentIdx == -1) { nameComponentIdx = 0; } int md5ComponentIdx = components.IndexOf("MD5"); if (md5ComponentIdx == -1) { md5ComponentIdx = 1; } components.Clear(); Dictionary <string, MD5Hash> cmfHashes = new Dictionary <string, MD5Hash>(); for (int i = 1; i < array.Length; i++) { string[] filedata = array[i].Split('|'); string name = filedata[nameComponentIdx]; MD5Hash md5 = filedata[md5ComponentIdx].ToByteArray().ToMD5(); RootFiles[name] = md5; if (Path.GetExtension(name) != ".cmf" || !name.Contains("RDEV")) { continue; } if (!IsValidLanguage(casc.Config, name)) { continue; } if (!casc.EncodingHandler.GetEntry(md5, out _)) { continue; } cmfHashes.Add(name, md5); } LoadedAPMWithoutErrors = true; for (int i = 1; i < array.Length; i++) { string[] filedata = array[i].Split('|'); string name = filedata[nameComponentIdx]; if (Path.GetExtension(name) == ".apm") { MD5Hash apmMD5 = filedata[md5ComponentIdx].ToByteArray().ToMD5(); LocaleFlags apmLang = HeurFigureLangFromName(Path.GetFileNameWithoutExtension(name)); if (!name.Contains("RDEV")) { continue; } if (!IsValidLanguage(casc.Config, name)) { continue; } if (!casc.EncodingHandler.GetEntry(apmMD5, out EncodingEntry apmEnc)) { continue; } MD5Hash cmf; string cmfname = $"{Path.GetDirectoryName(name)}/{Path.GetFileNameWithoutExtension(name)}.cmf"; if (cmfHashes.ContainsKey(cmfname)) { cmfHashes.TryGetValue(cmfname, out cmf); } if (casc.Config.LoadPackageManifest) { using (Stream apmStream = casc.OpenFile(apmEnc.Key)) { ApplicationPackageManifest apm = new ApplicationPackageManifest(); try { TankLib.Helpers.Logger.Info("CASC", $"Loading APM {Path.GetFileNameWithoutExtension(name)}"); worker?.ReportProgress(0, $"Loading APM {name}..."); apm.Load(name, cmf, apmStream, casc, cmfname, apmLang, worker); } catch (CryptographicException) { LoadedAPMWithoutErrors = false; if (!casc.Config.APMFailSilent) { worker?.ReportProgress(0, "CMF decryption failed"); TankLib.Helpers.Logger.Error("CASC", "Fatal - CMF deryption failed. Please update DataTool."); Debugger.Log(0, "CASC", $"RootHandler: CMF decryption procedure outdated, unable to parse {name}\r\n"); if (Debugger.IsAttached) { Debugger.Break(); } Environment.Exit(0x636D6614); //Logger.GracefulExit(0x636D6614); } } catch (LocalIndexMissingException) { // something doesn't exist for this language, we can't load continue; } APMFiles.Add(apm); } } } worker?.ReportProgress((int)(i / (array.Length / 100f))); } }