Exemple #1
0
        /**
         * Creates a FST by the given raw byte data
         *
         * @param fstData
         *            raw decrypted FST data
         * @param contentsMappedByIndex
         *            map of index/content
         * @return
         */
        public static FST parseFST(byte[] fstData, Dictionary <int, Content> contentsMappedByIndex)
        {
            if (!Arrays.Equals(Arrays.copyOfRange(fstData, 0, 3), new byte[] { 0x46, 0x53, 0x54 }))
            {
                //throw new NullPointerException();
                return(null);
                // throw new IllegalArgumentException("Not a FST. Maybe a wrong key?");
            }

            int unknownValue = Utils.SwapEndianness(BitConverter.ToInt32(fstData, 0x04));
            int contentCount = Utils.SwapEndianness(BitConverter.ToInt32(fstData, 0x08));

            FST result = new FST(unknownValue, contentCount);

            int contentfst_offset = 0x20;
            int contentfst_size   = 0x20 * contentCount;

            int fst_offset = contentfst_offset + contentfst_size;

            int fileCount = Utils.SwapEndianness(BitConverter.ToInt32(fstData, fst_offset + 0x08));
            int fst_size  = fileCount * 0x10;

            int nameOff  = fst_offset + fst_size;
            int nameSize = nameOff + 1;

            // Get list with null-terminated Strings. Ends with \0\0.
            for (int i = nameOff; i < fstData.Length - 1; i++)
            {
                if (fstData[i] == 0 && fstData[i + 1] == 0)
                {
                    nameSize = i - nameOff;
                }
            }

            Dictionary <int, ContentFSTInfo> contentFSTInfos = result.contentFSTInfos;

            for (int i = 0; i < contentCount; i++)
            {
                byte[] contentFST = Arrays.copyOfRange(fstData, contentfst_offset + (i * 0x20), contentfst_offset + ((i + 1) * 0x20));
                contentFSTInfos.Add(i, ContentFSTInfo.parseContentFST(contentFST));
            }

            byte[] fstSection  = Arrays.copyOfRange(fstData, fst_offset, fst_offset + fst_size);
            byte[] nameSection = Arrays.copyOfRange(fstData, nameOff, nameOff + nameSize);

            FSTEntry root = result.root;

            FSTService.parseFST(root, fstSection, nameSection, contentsMappedByIndex, contentFSTInfos);

            return(result);
        }
Exemple #2
0
        private static byte[] getFSTEntryAsByte(String filename, WUDPartition partition, FST fst, WUDDiscReader discReader, byte[] key)
        {
            FSTEntry       entry = getEntryByName(fst.root, filename);
            ContentFSTInfo info  = fst.contentFSTInfos[((int)entry.contentFSTID)];

            // Calculating the IV
            ByteBuffer byteBuffer = ByteBuffer.allocate(0x10);

            byteBuffer.position(0x08);
            long l = entry.fileOffset >> 16;

            byte[] ar = BitConverter.GetBytes(l);
            byte[] IV = new byte[0x10];//= copybyteBuffer.putLong(entry.fileOffset >> 16).ToArray();
            Array.ConstrainedCopy(ar, 0, IV, 0x08, 0x08);

            return(discReader.readDecryptedToByteArray(Settings.WIIU_DECRYPTED_AREA_OFFSET + (long)partition.partitionOffset + (long)info.getOffset(),
                                                       entry.fileOffset, (int)entry.fileSize, key, IV));
        }
Exemple #3
0
        public static void parseFST(FSTEntry rootEntry, byte[] fstSection, byte[] namesSection, Dictionary <int, Content> contentsByIndex,
                                    Dictionary <int, ContentFSTInfo> contentsFSTByIndex)
        {
            int totalEntries = Utils.SwapEndianness(BitConverter.ToInt32(fstSection, 0x08));

            int level = 0;

            int[]    LEntry      = new int[16];
            int[]    Entry       = new int[16];
            String[] pathStrings = new String[16];
            for (int i = 0; i < 16; i++)
            {
                pathStrings[i] = "";
            }

            Dictionary <int, FSTEntry> fstEntryToOffsetMap = new Dictionary <int, FSTEntry>();

            Entry[level]    = 0;
            LEntry[level++] = 0;

            fstEntryToOffsetMap.Add(0, rootEntry);

            int    lastlevel = level;
            String path      = "\\";

            FSTEntry last = null;

            for (int i = 1; i < totalEntries; i++)
            {
                int entryOffset = i;
                if (level > 0)
                {
                    while (LEntry[level - 1] == i)
                    {
                        level--;
                    }
                }

                byte[] curEntry = Arrays.copyOfRange(fstSection, i * 0x10, (i + 1) * 0x10);

                FSTEntryParam entryParam = new FSTEntryParam();

                if (lastlevel != level)
                {
                    path      = pathStrings[level] + getFullPath(level - 1, level, fstSection, namesSection, Entry);
                    lastlevel = level;
                }

                String filename = getName(curEntry, namesSection);

                long fileOffset = Utils.SwapEndianness(BitConverter.ToInt32(curEntry, 0x04));
                long fileSize   = (uint)Utils.SwapEndianness(BitConverter.ToInt32(curEntry, 0x08));

                short flags        = Utils.SwapEndianness(BitConverter.ToInt16(curEntry, 0x0C));
                short contentIndex = Utils.SwapEndianness(BitConverter.ToInt16(curEntry, 0x0E));

                if ((curEntry[0] & FSTEntry.FSTEntry_notInNUS) == FSTEntry.FSTEntry_notInNUS)
                {
                    entryParam.notInPackage = (true);
                }
                FSTEntry parent = null;
                if ((curEntry[0] & FSTEntry.FSTEntry_DIR) == FSTEntry.FSTEntry_DIR)
                {
                    entryParam.isDir = (true);
                    int parentOffset = (int)fileOffset;
                    int nextOffset   = (int)fileSize;

                    parent             = fstEntryToOffsetMap[parentOffset];
                    Entry[level]       = i;
                    LEntry[level++]    = nextOffset;
                    pathStrings[level] = path;

                    if (level > 15)
                    {
                        //MessageBox.Show("level > 15");
                        break;
                    }
                }
                else
                {
                    entryParam.FileOffset = (fileOffset << 5);

                    entryParam.FileSize = (fileSize);
                    parent = fstEntryToOffsetMap[(Entry[level - 1])];
                }

                entryParam.Flags    = (flags);
                entryParam.Filename = (filename);
                entryParam.Path     = (path);

                if (contentsByIndex != null)
                {
                    Content content = contentsByIndex[contentIndex];
                    if (content == null)
                    {
                        //MessageBox.Show("Content for FST Entry not found");
                    }
                    else
                    {
                        if (content.isHashed() && (content.getDecryptedFileSize() < (fileOffset << 5)))
                        { // TODO: Figure out how this works...
                            entryParam.FileOffset = (fileOffset);
                        }

                        entryParam.Content = (content);

                        ContentFSTInfo contentFSTInfo = contentsFSTByIndex[(int)contentIndex];
                        if (contentFSTInfo == null)
                        {
                            //MessageBox.Show("ContentFSTInfo for FST Entry not found");
                        }
                        else
                        {
                            content.contentFSTInfo = (contentFSTInfo);
                        }
                    }
                }

                entryParam.ContentFSTID = (contentIndex);
                entryParam.Parent       = (parent);

                FSTEntry entry = new FSTEntry(entryParam);
                last = entry;
                fstEntryToOffsetMap.Add(entryOffset, entry);
            }
        }