Esempio n. 1
0
        /// <summary>
        /// Load all HFS0 partitions starting at the root. The calling function is expected to set stream.Position at the start of the root/first HFS0 Header (always 0xF000 for XCIs)
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static HFS0Root Load(string path, Stream stream)
        {
            // The "SHA-256 File System" or "HFS0" starts at offset 0xF000 in the Gamecard. The first 0x200 bytes act as a global header and represent the root partition which points to the other partitions ("normal", "logo", "update" and "secure").
            // Where "logo" only exists in 4.0.0+ gamecards and if "logo" exists then "normal" is empty (but still exists)

            Logger.Info("stream.Position = " + stream.Position);

            // Root HFS0
            HFS0Root root = new HFS0Root(path, stream, stream.Position);

            // Since we just loaded the root HFS0 partition all the files inside it (FileEntries) are actually also HFS0 parititons
            root.Partitions = new HFS0[root.Header.NumberOfFiles];
            for (int i = 0; i < root.Header.NumberOfFiles; i++)
            {
                root.Partitions[i] = new HFS0(
                    path,
                    root.StringTable[i],
                    stream,
                    root.Offset + root.HeaderSize + (long)root.FileEntries[i].Offset, // Partition offset

                    // Partition offset (calc)
                    // root.Offset                          = 0xF000 for gamecards
                    // root.Size                            = 0x200 for gamecards
                    // root.FileEntries[i].Offset           = partition offset relative to root.Offset + root.Size
                    // absolute offset for first partition  = 0xF200

                    (long)root.FileEntries[i].Size
                    );
            }

            // TODO: Calculate Size (used for trimming, I think)

            return(root);
        }
Esempio n. 2
0
        /// <summary>
        /// Load XCI file from disk
        /// </summary>
        /// <param name="path">Path to XCI file</param>
        /// <param name="verify">Verify hashes and signatures</param>
        /// <returns></returns>
        public static XCI Load(string path, Keyset keyset, bool verify = true)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (BinaryReader br = new BinaryReader(fs))
                {
                    XCI xci = new XCI(path);
                    xci.Keyset = keyset;

                    // Gamecard Header
                    byte[] bytes = br.ReadBytes(0x200); // sizeof XCIHeader
                    xci.GamecardHeader = bytes.ToStruct <XCIHeader>();

                    if (xci.GamecardHeader.MagicString != "HEAD")
                    {
                        throw new Exception("Invalid GamecardHeader magic! Maybe this isn't an XCI file?");
                    }

                    // TODO: Gamecard Info
                    // TODO: Gamecard Certificate
                    // TODO: Initial Data

                    // HFS0, see comments in HFS0Root and HFS0Partition
                    fs.Position    = 0xF000; // start of HFS0Header
                    xci.FileSystem = HFS0Root.Load(path, fs);

                    return(xci);
                }
        }