Exemplo n.º 1
0
            bool Read()
            {
                Types.Header header = new Types.Header();

                byte[] buffer = new byte[4];
                IO.Position = 0;

                header.headerHash = new byte[0x14];
                IO.Read(header.headerHash, 0, 0x14);

                IO.Read(buffer, 0, 4);
                header.magic = buffer.ToUInt32(false);

                IO.Read(buffer, 0, 4);
                header.headerSize = buffer.ToUInt32(false);
                header.headerType = (Types.HeaderType)header.headerSize;

                IO.Read(buffer, 0, 4);
                header.contentType = buffer.ToUInt32(false);

                IO.Read(buffer, 0, 4);
                header.contentFlags = buffer.ToUInt32(false);

                IO.Read(buffer, 0, 4);
                header.titleId = buffer.ToUInt32(false);

                IO.Read(buffer, 0, 4);
                header.offerId = buffer.ToUInt32(false);

                IO.Read(buffer, 0, 4);
                header.offerTitleId = buffer.ToUInt32(false);

                IO.Read(buffer, 0, 4);
                header.publisherFlags = buffer.ToUInt32(false);

                Header = header;

                uint sectionCount = ((header.headerSize - 0x34) / 0x1C);

                if (sectionCount < 2)
                {
                    buffer = null;
                    IO.Dispose();
                    IO = null;
                    return(false);
                }

                Sections = new Types.Section[sectionCount];

                for (int i = 0; i < sectionCount; i++)
                {
                    Types.Section section = new Types.Section();

                    IO.Read(buffer, 0, 4);
                    section.sectionOffset = buffer.ToUInt32(false);

                    IO.Read(buffer, 0, 4);
                    section.sectionLength = buffer.ToUInt32(false);

                    section.hashOffset  = (uint)IO.Position; //for convenience when signing
                    section.sectionHash = new byte[0x14];
                    IO.Read(section.sectionHash, 0, 0x14);

                    Sections[i] = section;
                }

                for (int i = 0; i < sectionCount; i++)
                {
                    IO.Position             = Sections[i].sectionOffset;
                    Sections[i].sectionData = new byte[Sections[i].sectionLength];
                    IO.Read(Sections[i].sectionData, 0, (int)Sections[i].sectionLength);
                }

                buffer = null;

                //section types always in the same order depending on header size
                if (header.headerType == Types.HeaderType.Content) //0x88 = content
                {
                    Sections[0].sectionType = Types.SectionType.Language;
                    Sections[1].sectionType = Types.SectionType.TableOfContents;
                    Sections[2].sectionType = Types.SectionType.Optional;
                }
                if (header.headerType == Types.HeaderType.Update) //0x6C = update
                {
                    Sections[0].sectionType = Types.SectionType.Unknown;
                    Sections[1].sectionType = Types.SectionType.TableOfContents;
                }

                return(true);
            }
Exemplo n.º 2
0
        public void Load(string name, MD5Hash cmfhash, Stream stream, CASCHandler casc, string cmfname, LocaleFlags locale,
                         ProgressReportSlave worker = null)
        {
            Locale  = locale;
            Name    = name;
            CMFHash = cmfhash;
            CMFName = Path.GetFileName(cmfname);

            //using (Stream file = File.OpenWrite(Path.GetFileName(name))) {
            //    stream.CopyTo(file);
            //    stream.Position = 0;
            //}

            if (!casc.EncodingHandler.GetEntry(cmfhash, out EncodingEntry cmfEncoding))
            {
                return;
            }

            if (!casc.Config.LoadContentManifest)
            {
                return;
            }
            using (Stream cmfStream = casc.OpenFile(cmfEncoding.Key)) {
                CMF = new ContentManifestFile(CMFName, cmfStream, worker);
            }

            FirstOccurence = new ConcurrentDictionary <ulong, Types.PackageRecord>(Environment.ProcessorCount + 2, CMF.Map.Count);

            using (BinaryReader reader = new BinaryReader(stream)) {
                ulong build = reader.ReadUInt64();
                reader.BaseStream.Position = 0;

                if (CMFHeaderCommon.IsV22((uint)build))
                {
                    Header = reader.Read <Types.Header22>().Upgrade();
                }
                else
                {
                    Header = reader.Read <Types.Header>();
                }

                if (CMFHeaderCommon.IsV22((uint)Header.Build))
                {
                    Entries        = reader.ReadArray <Types.Entry>((int)Header.EntryCount);
                    PackageEntries = reader.ReadArray <Types.PackageEntry>((int)Header.PackageCount);
                }
                else
                {
                    Entries        = reader.ReadArray <Types.Entry21>((int)Header.EntryCount).Select(x => x.GetEntry()).ToArray();
                    PackageEntries = reader.ReadArray <Types.PackageEntry21>((int)Header.PackageCount).Select(x => x.GetPackage()).ToArray();
                }

                if (CASCHandler.Cache.CacheAPM && CacheFileExists(Header.Build))
                {
                    worker?.ReportProgress(0, "Loading cached data...");

                    try {
                        if (LoadCache(Header.Build))    // if cache is invalid, we'll regenerate
                        {
                            GatherFirstCMF(casc, worker);
                            return;
                        }
                    }
                    catch {
                        TankLib.Helpers.Logger.Error("CASC", $"Failed to load APM Cache {Path.GetFileName(CacheFile(Header.Build))}");
                        File.Delete(CacheFile(Header.Build));
                    }
                }

                Packages        = new Types.Package[Header.PackageCount];
                Records         = new Types.PackageRecord[Header.PackageCount][];
                PackageSiblings = new ulong[Header.PackageCount][];
                worker?.ReportProgress(0, $"Loading {Name} packages");
                try {
                    LoadPackages(casc, worker);
                } catch (AggregateException e) {
                    // return nice exception to RootHandler
                    if (e.InnerException != null)
                    {
                        throw e.InnerException;
                    }
                }
            }
            if (!Console.IsOutputRedirected)
            {
                Console.Write(new string(' ', Console.WindowWidth - 1) + "\r");
            }

            if (CASCHandler.Cache.CacheAPM)
            {
                TankLib.Helpers.Logger.Debug("CASC", $"Caching APM {name}");
                worker?.ReportProgress(0, "Caching data...");
                SaveCache(Header.Build);
            }

            GatherFirstCMF(casc, worker);
        }