Esempio n. 1
0
        static void GetDirectoriesRecursive(VirtualFilesystemDirectory root, string rootString)
        {
            List <string> files = new List <string>(Directory.GetFiles(rootString));

            // The entries in this subdir need to be in a particular order.
            // We'll fill them in with null so that we can replace them later.
            if (Path.GetFileName(rootString).ToLowerInvariant() == "&&systemdata")
            {
                for (int i = 0; i < 4; i++)
                {
                    root.Children.Add(null);
                }
            }

            foreach (string str in files)
            {
                string fileName          = Path.GetFileNameWithoutExtension(str);
                string fileExt           = Path.GetExtension(str);
                VirtualFileContents cont = new VirtualFileContents(File.ReadAllBytes(str));

                VirtualFilesystemFile newFile = new VirtualFilesystemFile(fileName, fileExt, cont);

                string fileNameLower = fileName.ToLowerInvariant();
                string fileExtLower  = fileExt.ToLowerInvariant();
                string fullFileName  = fileNameLower + fileExtLower;

                // These will replace the nulls we put in &&systemdata's child list earlier.
                if ((fullFileName == "iso.hdr") || (fullFileName == "isoheader.hdr"))
                {
                    root.Children[0] = newFile;
                }
                else if (fullFileName == "apploader.ldr")
                {
                    root.Children[2] = newFile;
                }
                else if (fullFileName == "start.dol")
                {
                    root.Children[1] = newFile;
                }
                else if (fullFileName == "game.toc")
                {
                    root.Children[3] = newFile;
                }
                else
                {
                    root.Children.Add(newFile);
                }
            }

            List <string> dirs = new List <string>(Directory.GetDirectories(rootString));

            foreach (string str in dirs)
            {
                string dirName                 = Path.GetFileName(str);
                string dirNameLower            = dirName.ToLowerInvariant();
                VirtualFilesystemDirectory dir = new VirtualFilesystemDirectory(dirName);

                GetDirectoriesRecursive(dir, str);

                if (dirNameLower == "&&systemdata")
                {
                    root.Children.Insert(0, dir);
                }
                else
                {
                    root.Children.Add(dir);
                }
            }
        }
Esempio n. 2
0
        public VirtualFilesystemDirectory ReadFile(EndianBinaryReader reader)
        {
            if (reader.ReadUInt32() != 0x52415243) // "RARC"
            {
                throw new InvalidDataException("Invalid Magic, not a RARC File");
            }

            uint fileSize = reader.ReadUInt32();

            reader.SkipUInt32(); // Unknown
            uint dataOffset = reader.ReadUInt32() + 0x20;

            reader.Skip(16); // Unknown - 4 unsigned ints
            uint numNodes = reader.ReadUInt32();

            reader.Skip(8); // Unknown - 2 unsigned ints
            uint fileEntryOffset = reader.ReadUInt32() + 0x20;

            reader.SkipUInt32(); // Unknown
            uint stringTableOffset = reader.ReadUInt32() + 0x20;

            reader.Skip(8); // Unknown - 2 unsigned ints.

            // Read all of the node headers.
            Node[] nodes = new Node[numNodes];

            for (int i = 0; i < numNodes; i++)
            {
                nodes[i] = new Node
                {
                    Type            = new string(reader.ReadChars(4)),
                    Name            = ReadStringAtOffset(reader, stringTableOffset, reader.ReadUInt32()),
                    NameHashcode    = reader.ReadUInt16(),
                    Entries         = new FileEntry[reader.ReadUInt16()],
                    FirstFileOffset = reader.ReadUInt32()
                };
            }


            // Create a virtual directory for every folder within the ARC before we process any of them.
            List <VirtualFilesystemDirectory> allDirs = new List <VirtualFilesystemDirectory>(nodes.Length);

            foreach (Node node in nodes)
            {
                VirtualFilesystemDirectory vfDir = new VirtualFilesystemDirectory(node.Name);
                allDirs.Add(vfDir);
            }

            for (int k = 0; k < nodes.Length; k++)
            {
                Node node = nodes[k];
                VirtualFilesystemDirectory curDir = allDirs[k];

                for (int i = 0; i < node.Entries.Length; i++)
                {
                    // Jump to the entry's offset in the file.
                    reader.BaseStream.Position = fileEntryOffset + ((node.FirstFileOffset + i) * 0x14); // 0x14 is the size of a File Entry in bytes
                    node.Entries[i]            = new FileEntry
                    {
                        ID           = reader.ReadUInt16(),
                        NameHashcode = reader.ReadUInt16(),
                        Type         = reader.ReadByte(),
                        Padding      = reader.ReadByte(),
                        Name         = ReadStringAtOffset(reader, stringTableOffset, reader.ReadUInt16())
                    };

                    // Skip these ones cause I don't know how computers work.
                    if (node.Entries[i].Name == "." || node.Entries[i].Name == "..")
                    {
                        continue;
                    }

                    uint entryDataOffset = reader.ReadUInt32();
                    uint dataSize        = reader.ReadUInt32();

                    // If it's a directory, then entryDataOffset contains the index of the parent node
                    if (node.Entries[i].IsDirectory)
                    {
                        node.Entries[i].SubDirIndex = entryDataOffset;
                        var newSubDir = allDirs[(int)entryDataOffset];
                        curDir.Children.Add(newSubDir);
                    }
                    else
                    {
                        node.Entries[i].Data = reader.ReadBytesAt(dataOffset + entryDataOffset, (int)dataSize);

                        string fileName  = Path.GetFileNameWithoutExtension(node.Entries[i].Name);
                        string extension = Path.GetExtension(node.Entries[i].Name);

                        var vfFileContents           = new VirtualFileContents(node.Entries[i].Data);
                        VirtualFilesystemFile vfFile = new VirtualFilesystemFile(fileName, extension, vfFileContents);
                        curDir.Children.Add(vfFile);
                    }
                    node.Entries[i].ZeroPadding = reader.ReadUInt32();
                }
            }

            // The ROOT directory should always be the first node. We don't have access to the node's TYPE anymore
            // so we're going to assume its always the first one listed.
            return(allDirs.Count > 0 ? allDirs[0] : null);
        }