private void LoadPackage(int i, ClientHandler client, ContentManifestFile cmf)
        {
            var entry = m_packageEntries[i];

            using (Stream packageStream = cmf.OpenFile(client, entry.m_packageGUID) !)
                using (BinaryReader packageReader = new BinaryReader(packageStream)) {
                    var package = packageReader.Read <PackageHeader>();
                    m_packages[i] = package;

                    if (package.m_recordCount == 0)
                    {
                        m_packageRecords[i] = new PackageRecord[0];
                        return;
                    }

                    if (package.m_bundleCount > 0)
                    {
                        packageStream.Position = package.m_offsetBundles;
                        m_packageBundles[i]    = packageReader.ReadArray <ulong>((int)package.m_bundleCount);
                    }

                    packageStream.Position = package.m_offsetRecords;
                    using (GZipStream decompressedStream = new GZipStream(packageStream, CompressionMode.Decompress))
                        using (BinaryReader decompressedReader = new BinaryReader(decompressedStream)) {
                            m_packageRecords[i] = decompressedReader.ReadArray <PackageRecord>((int)package.m_recordCount);
                        }
                }
        }
Exemple #2
0
        private Dictionary <ulong, uint> CreateOffsetCache(ContentManifestFile cmf, ulong bundleGuid)
        {
            using (Stream bundleStream = cmf.OpenFile(_client, bundleGuid)) {
                Memory <byte> buf = new byte[(int)bundleStream.Length];
                bundleStream.Read(buf);
                lock (_bundleCache) {
                    _bundleCache[bundleGuid] = buf;
                }
                bundleStream.Position = 0;

                Bundle bundle = new Bundle(bundleStream);
                return(bundle.Entries.ToDictionary(x => x.GUID, x => x.Offset));
            }
        }
        private bool VerifyEntries(ContentManifestFile cmf)
        {
            for (var i = 0; i < m_header.m_entryCount; i++)
            {
                var a = m_entries[i];
                var b = cmf.m_entries[i];

                if (a.m_hashA != b.m_hashA)
                {
                    return(false);
                }
                // todo: HashB is always 0 in APM. what does this mean?
            }

            return(true);
        }
        private bool VerifyEntries(ContentManifestFile cmf)
        {
            for (int i = 0; i < Header.EntryCount; i++)
            {
                Entry a = Entries[i];
                Entry b = cmf.Entries[i];

                if (a.HashA != b.HashA)
                {
                    return(false);
                }
                // todo: HashB is always 0 in APM. what does this mean?
            }

            return(true);
        }
Exemple #5
0
 private void RegisterCMFAssets(ContentManifestFile contentManifestFile, int fakePackageIdx)
 {
     if (contentManifestFile == null)
     {
         return;
     }
     Parallel.For(0, contentManifestFile.m_hashList.Length, new ParallelOptions {
         MaxDegreeOfParallelism = 4
     }, j => {
         var cmfAsset = contentManifestFile.m_hashList[j];
         if (m_assets.ContainsKey(cmfAsset.GUID))
         {
             return;
         }
         m_assets[cmfAsset.GUID] = new Asset(fakePackageIdx, j);
     });
 }
Exemple #6
0
        public ProductHandler_Tank(ClientHandler client, Stream stream)
        {
            m_client = client;

            var clientArgs = client.CreateArgs.HandlerArgs as ClientCreateArgs_Tank ?? new ClientCreateArgs_Tank();

            using (BinaryReader reader = new BinaryReader(stream)) {
                string str = Encoding.ASCII.GetString(reader.ReadBytes((int)stream.Length));

                string[] array = str.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                if (ROOT_FILE_FIELD_ORDER_CHECK != array[0])
                {
                    throw new InvalidDataException($"ProductHandler_Tank: Root file field list mismatch ({array[0]})");
                }

                m_rootFiles = new RootFile[array.Length - 1];
                for (int i = 1; i < array.Length; i++)
                {
                    m_rootFiles[i - 1] = new RootFile(array[i].Split('|'));
                }
            }

            if (!clientArgs.LoadManifest)
            {
                return;
            }

            int totalAssetCount = 0;

            foreach (RootFile rootFile in m_rootFiles.Reverse())    // cmf first, then apm
            {
                string extension = Path.GetExtension(rootFile.FileName);
                if (extension != ".cmf" && extension != ".apm" && extension != ".trg")
                {
                    continue;
                }

                var manifestName     = Path.GetFileNameWithoutExtension(rootFile.FileName);
                var manifestFileName = Path.GetFileName(rootFile.FileName);

                if (!manifestName.Contains(clientArgs.ManifestRegion ?? REGION_DEV))
                {
                    continue;                                                                  // is a CN (china) CMF. todo: support this
                }
                var locale = GetManifestLocale(manifestName);

                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (extension == ".cmf")
                {
                    bool speech = manifestName.Contains(SPEECH_MANIFEST_NAME);
                    bool text   = manifestName.Contains(TEXT_MANIFEST_NAME);

                    if (speech)
                    {
                        if (locale != client.CreateArgs.SpeechLanguage)
                        {
                            continue;
                        }
                    }
                    else if (locale != null)
                    {
                        // text or old root/text combo
                        if (locale != client.CreateArgs.TextLanguage)
                        {
                            continue;
                        }
                    }

                    ContentManifestFile cmf;
                    //using (Stream file = File.OpenWrite($"{manifestName}.cmf")) {
                    //    cmfStream.CopyTo(file);
                    //}
                    try {
                        using (Stream cmfStream = client.OpenCKey(rootFile.MD5))
                            cmf = new ContentManifestFile(client, cmfStream, manifestFileName);
                    } catch (CryptographicException) {
                        Logger.Error("CASC", OutdatedTACTLibErrorMessage);
                        if (Debugger.IsAttached)
                        {
                            Debugger.Break();
                        }
                        throw;
                    }
                    if (speech)
                    {
                        m_speechContentManifest = cmf;
                    }
                    else if (text)
                    {
                        m_textContentManifest = cmf;
                    }
                    else
                    {
                        m_rootContentManifest = cmf;
                    }
                    totalAssetCount += cmf.m_header.m_dataCount;
                }
                else if (extension == ".apm")
                {
                    if (locale != client.CreateArgs.TextLanguage)
                    {
                        continue;
                    }
                    using (Stream apmStream = client.OpenCKey(rootFile.MD5))
                        m_packageManifest = new ApplicationPackageManifest(client, this, apmStream, manifestName);
                }
                else if (extension == ".trg")
                {
                    try {
                        using (Stream trgStream = client.OpenCKey(rootFile.MD5)) {
                            //using (Stream file = File.OpenWrite($"{manifestName}.trg")) {
                            //    trgStream.CopyTo(file);
                            //}

                            m_resourceGraph = new ResourceGraph(client, trgStream, manifestFileName);
                        }
                    } catch (CryptographicException) {
                        Logger.Error("CASC", OutdatedTACTLibErrorMessage);
                        if (Debugger.IsAttached)
                        {
                            Debugger.Break();
                        }
                        throw;
                    }
                }
            }

            m_usingResourceGraph = m_rootContentManifest.m_header.m_buildVersion >= VERSION_148_PTR;
            m_assets             = new ConcurrentDictionary <ulong, Asset>(Environment.ProcessorCount + 2, totalAssetCount);

            if (!m_usingResourceGraph)
            {
                for (int i = 0; i < m_packageManifest.m_header.m_packageCount; i++)
                {
                    var records = m_packageManifest.m_packageRecords[i];

                    for (int j = 0; j < records.Length; j++)
                    {
                        var record = records[j];
                        //Console.Out.WriteLine($"{record.GUID:X8} {record.Unknown1} {record.Unknown2} {Manifests[0].ContentManifest.Exists(record.GUID)} {Manifests[1].ContentManifest.Exists(record.GUID)}");

                        if (m_assets.ContainsKey(record.m_GUID))
                        {
                            continue;
                        }
                        m_assets[record.m_GUID] = new Asset(i, j);
                    }
                }
            }

            RegisterCMFAssets(m_rootContentManifest, PACKAGE_IDX_FAKE_ROOT_CMF);
            RegisterCMFAssets(m_textContentManifest, PACKAGE_IDX_FAKE_TEXT_CMF);
            RegisterCMFAssets(m_speechContentManifest, PACKAGE_IDX_FAKE_SPEECH_CMF);

            if (m_usingResourceGraph)
            {
                m_hackedLookedUpBundles = new HashSet <ulong>();
                m_hackedBundleLookup    = new Dictionary <ulong, ulong>();
                DoBundleLookupHack();
            }
        }
Exemple #7
0
        public ProductHandler_Tank(ClientHandler client, Stream stream)
        {
            _client = client;

            var clientArgs = client.CreateArgs.HandlerArgs as ClientCreateArgs_Tank ?? new ClientCreateArgs_Tank();

            using (BinaryReader reader = new BinaryReader(stream)) {
                string str = Encoding.ASCII.GetString(reader.ReadBytes((int)stream.Length));

                string[] array = str.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                if (FieldOrderCheck != array[0])
                {
                    throw new InvalidDataException($"ProductHandler_Tank: Root file field list mismatch ({array[0]})");
                }

                RootFiles = new RootFile[array.Length - 1];
                for (int i = 1; i < array.Length; i++)
                {
                    RootFiles[i - 1] = new RootFile(array[i].Split('|'));
                }
            }

            if (!clientArgs.LoadManifest)
            {
                return;
            }

            int totalAssetCount = 0;

            foreach (RootFile rootFile in RootFiles.Reverse())    // cmf first, then apm
            {
                string extension = Path.GetExtension(rootFile.FileName);
                if (extension != ".cmf" && extension != ".apm")
                {
                    continue;
                }

                string manifestName = Path.GetFileNameWithoutExtension(rootFile.FileName);
                if (manifestName == null)
                {
                    throw new InvalidDataException();
                }

                if (!manifestName.Contains(RegionDev))
                {
                    continue;                                    // is a CN (china?) CMF. todo: support this
                }
                var locale = GetManifestLocale(manifestName);

                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (extension == ".cmf")
                {
                    bool speech = manifestName.Contains(SpeechManifestName);

                    if (speech)
                    {
                        if (locale != client.CreateArgs.SpeechLanguage)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (locale != client.CreateArgs.TextLanguage)
                        {
                            continue;
                        }
                    }

                    ContentManifestFile cmf;
                    using (Stream cmfStream = client.OpenCKey(rootFile.MD5)) {
                        try {
                            cmf = new ContentManifestFile(client, cmfStream, $"{manifestName}.cmf");
                        } catch (CryptographicException) {
                            Logger.Error("CASC", "Fatal - CMF decryption failed. Please update TACTLib.");
                            if (Debugger.IsAttached)
                            {
                                Debugger.Break();
                            }
                            throw;
                        }
                    }
                    if (speech)
                    {
                        SpeechContentManifest = cmf;
                    }
                    else
                    {
                        MainContentManifest = cmf;
                    }
                    totalAssetCount += cmf.Header.DataCount;
                }
                else if (extension == ".apm")
                {
                    if (locale != client.CreateArgs.TextLanguage)
                    {
                        continue;
                    }
                    using (Stream apmStream = client.OpenCKey(rootFile.MD5)) {
                        PackageManifest = new ApplicationPackageManifest(client, this, apmStream, manifestName);
                    }
                }
            }

            Assets = new ConcurrentDictionary <ulong, Asset>(Environment.ProcessorCount + 2, totalAssetCount);

            for (int i = 0; i < PackageManifest.Header.PackageCount; i++)
            {
                var records = PackageManifest.Records[i];

                for (int j = 0; j < records.Length; j++)
                {
                    var record = records[j];
                    //Console.Out.WriteLine($"{record.GUID:X8} {record.Unknown1} {record.Unknown2} {Manifests[0].ContentManifest.Exists(record.GUID)} {Manifests[1].ContentManifest.Exists(record.GUID)}");

                    if (Assets.ContainsKey(record.GUID))
                    {
                        continue;
                    }
                    Assets[record.GUID] = new Asset(i, j);
                }
            }

            for (int i = 0; i < 2; i++)
            {
                ContentManifestFile contentManifestFile;

                int cmfId = -(i + 1);
                if (cmfId == -1)
                {
                    contentManifestFile = MainContentManifest;
                }
                else if (cmfId == -2)
                {
                    contentManifestFile = SpeechContentManifest;
                }
                else
                {
                    throw new Exception("wat");
                }
                // main = -1
                // speech = -2

                Parallel.For(0, contentManifestFile.HashList.Length, new ParallelOptions {
                    MaxDegreeOfParallelism = 4
                }, j => {
                    var cmfAsset = contentManifestFile.HashList[j];
                    if (Assets.ContainsKey(cmfAsset.GUID))
                    {
                        return;
                    }
                    Assets[cmfAsset.GUID] = new Asset(cmfId, j);
                });
            }
        }