Example #1
0
        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]);
            }
        }
Example #2
0
        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));
                }
            }
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
            }
        }
Example #5
0
        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
            });
        }
Example #6
0
        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)));
            }
        }