Пример #1
0
        private TreeNode InitializeNode(NDSDirectory dir)
        {
            TreeNode node = new TreeNode();

            node.Name = dir.Name;
            node.Text = dir.Name;
            node.Tag  = dir;

            if (dir.Children.Count > 0)
            {
                foreach (NDSDirectory child in dir.Children)
                {
                    node.Nodes.Add(InitializeNode(child));
                    romTree.Update();
                }
            }

            if (dir.Contents.Count > 0)
            {
                foreach (NDSFile file in dir.Contents)
                {
                    node.Nodes.Add(InitializeNode(file));
                    romTree.Update();
                }
            }

            return(node);
        }
Пример #2
0
 public NDSFile(string name, string path, string extension, uint offset, uint length, NDSDirectory parent)
 {
     Name      = name;
     Path      = path;
     Extension = extension;
     Offset    = offset;
     Length    = length;
     Parent    = parent;
 }
Пример #3
0
        /// <summary>
        /// Reads and breaks down the file tables from the specified stream.<para />
        /// Currently Supports: File Name Table (FNT); File Allocation Table (FAT); Overlay Tables (OVT); NARC.
        /// </summary>
        /// <param name="stream">ROM file to read tables from.</param>
        ///
        public void ReadFileTables(Stream stream)
        {
            if (FATOffset == 0 || FATLength == 0 ||
                FNTOffset == 0 || FNTLength == 0 ||
                ARM9OverlayOffset == 0 || ARM9OverlayLength == 0)
            {
                return;
            }

            // We initiate a BinaryReader with using() and set it to leave the stream open after disposal.
            using (BinaryReader reader = new BinaryReader(stream, new UTF8Encoding(), true))
            {
                // The File Allocation Table contain eight bytes per file entry;
                // a four byte file offset followed by a four byte file length.
                // We start by determining the file count and then dividing the
                // offsets and lenghts into separate indexed arrays.
                int file_count = Convert.ToInt32(FATLength) / 8;
                FileTable = new NDSFile[file_count];

                reader.BaseStream.Position = FATOffset;
                for (int i = 0; i < file_count; i++)
                {
                    FileTable[i]        = new NDSFile();
                    FileTable[i].ID     = i;
                    FileTable[i].Offset = reader.ReadUInt32();
                    FileTable[i].Length = reader.ReadUInt32() - FileTable[i].Offset;
                }

                // The File Name Table contains two sections; the first is the
                // main directory table. It's length is eight bytes per entry.
                // The first four bytes represent an offset to the entry in the
                // second section; the sub-directory table. This is followed by
                // two byte index corresponding to the first file entry in the
                // directory. Finally we have a two byte index corresponding to
                // the parent directory.

                // The first entry in the table is slightly different though.
                // The last two bytes in the first entry actually denote the
                // number of directories in the first section. Let's read that,
                // then use it to iterate through the main directory table and
                // split the table into three seperate indexed arrays.
                reader.BaseStream.Position = FNTOffset + 6;

                int directory_count = reader.ReadUInt16();

                DirectoryTable = new NDSDirectory[directory_count];
                int[] entry_offset = new int[directory_count];
                int[] first_file   = new int[directory_count];
                int[] parent_index = new int[directory_count];

                reader.BaseStream.Position = FNTOffset;
                for (int i = 0; i < directory_count; i++)
                {
                    entry_offset[i] = Convert.ToInt32(reader.ReadUInt32() + FNTOffset);
                    first_file[i]   = reader.ReadUInt16();
                    parent_index[i] = reader.ReadUInt16() - 61440;
                }

                // Setting up the root directory.
                DirectoryTable[0]      = new NDSDirectory();
                DirectoryTable[0].Name = "File Table";
                DirectoryTable[0].Path = "File Table";

                // The second section is the sub-directory table. This table is
                // a bit more complex. We start by iterating through the main
                // directory table and using the entry offset to locate its
                // position in the sub-directory table.
                int file_index = first_file[0];

                for (int i = 0; i < directory_count; i++)
                {
                    // Initialize the directory arrays.
                    reader.BaseStream.Position = entry_offset[i];
                    NDSDirectory parent_directory = DirectoryTable[i];
                    parent_directory.Children = new List <NDSDirectory>();
                    parent_directory.Contents = new List <NDSFile>();

                    while (true)
                    {
                        // A small sanity check to make sure we havent overrun the table.
                        if (reader.BaseStream.Position > FNTOffset + FNTLength)
                        {
                            break;
                        }

                        // The first byte in the sub-directory entry indicates how to continue.
                        byte entry_byte = reader.ReadByte();

                        // 0 indicates the end of a directory.
                        if (entry_byte == 0)
                        {
                            break;
                        }

                        // 128 is actually invalid, and shouldn't be encountered. It would
                        // indicate a directory with no name, which isn't actually valid.
                        else if (entry_byte == 128)
                        {
                            continue;
                        }

                        // The first bit indicates a directory entry, so anything over 128
                        // is a sub-directory. The other seven bits indicate the length of
                        // the sub-directory name. We simply need to subtract 128, and the
                        // next so many bytes are the sub-directory name. The following
                        // two bytes are the sub-directory's ID in the main directory table.
                        else if (entry_byte > 128)
                        {
                            string       name            = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(entry_byte - 128));
                            NDSDirectory child_directory = new NDSDirectory();
                            child_directory.Name   = name;
                            child_directory.Parent = parent_directory;
                            child_directory.Path   = parent_directory.Path + "\\" + child_directory.Name;
                            child_directory.ID     = reader.ReadUInt16() - 61440;

                            DirectoryTable[child_directory.ID] = child_directory;
                            parent_directory.Children.Add(child_directory);
                        }

                        // Anything under 128 indicates a file. Same as the previous, the
                        // other seven bits indicate the length of the file name. Unlike
                        // sub-directories, there is no index proceeding the file name.
                        else
                        {
                            string  name = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(entry_byte));
                            NDSFile file = FileTable[file_index++];
                            file.Name   = name;
                            file.Parent = parent_directory;
                            file.Path   = parent_directory.Path + "\\" + file.Name;

                            parent_directory.Contents.Add(file);
                        }
                    }
                }

                // We run this now so that we don't mess up the memory stream.
                foreach (NDSFile file in FileTable)
                {
                    file.GetExtension(stream);

                    if (file.Extension == ".narc")
                    {
                        file.NARCTables = FileHandler.NARC(stream, file, true);
                    }
                    else if (file.Extension == ".arc")
                    {
                        file.NARCTables = FileHandler.NARC(stream, file, false);
                    }
                }

                // Header Represented As A File
                Header        = new NDSFile();
                Header.Name   = "Header";
                Header.Offset = 0;
                Header.Length = 16384;

                // Header Represented As A File
                Banner        = new NDSBanner();
                Banner.Name   = "Banner";
                Banner.Offset = BannerOffset;
                Banner.Length = 9216;
                Banner.ReadBanner(stream);

                // ARM9 and ARM9 Overlay Table reading.
                ARM9            = new NDSBinary();
                ARM9.Name       = "ARM9";
                ARM9.Extension  = ".bin";
                ARM9.Offset     = ARM9Offset;
                ARM9.Length     = ARM9Length;
                ARM9.Load       = ARM9Load;
                ARM9.AutoLoad   = ARM9AutoLoad;
                ARM9.AutoParams = ARM9AutoParam;

                if (ARM9iLength > 0)
                {
                    ARM9i           = new NDSBinary();
                    ARM9i.Name      = "ARM9i";
                    ARM9i.Extension = ".bin";
                    ARM9i.Offset    = ARM9iOffset;
                    ARM9i.Length    = ARM9iLength;
                }

                int overlay9_count = Convert.ToInt32(ARM9OverlayLength / 32);
                reader.BaseStream.Position = ARM9OverlayOffset;
                OverlayTable9 = new NDSOverlay[overlay9_count];

                for (int i = 0; i < overlay9_count; i++)
                {
                    NDSOverlay overlay = new NDSOverlay();
                    overlay.OverlayID          = reader.ReadUInt32();
                    overlay.AddressRAM         = reader.ReadUInt32();
                    overlay.SizeRAM            = reader.ReadUInt32();
                    overlay.SizeBSS            = reader.ReadUInt32();
                    overlay.StaticStartAddress = reader.ReadUInt32();
                    overlay.StaticEndAddress   = reader.ReadUInt32();
                    overlay.ID     = Convert.ToInt32(reader.ReadUInt32());
                    overlay.Offset = FileTable[overlay.ID].Offset;
                    overlay.Length = FileTable[overlay.ID].Length;
                    uint temp = reader.ReadUInt32();
                    uint flag = temp >> 24;
                    if ((flag & 2) != 0)
                    {
                        overlay.Authenticated = true;
                    }
                    if ((flag & 1) != 0)
                    {
                        overlay.Compressed     = true;
                        overlay.CompressedSize = (temp << 8) >> 8;
                    }

                    overlay.Name      = "Overlay " + overlay.OverlayID;
                    overlay.Path      = "ARM9 Overlay Table\\" + overlay.Name;
                    overlay.Extension = ".bin";

                    OverlayTable9[i]      = overlay;
                    FileTable[overlay.ID] = overlay;
                }

                // ARM7 and ARM7 Overlay Table reading.
                if (ARM7Length > 0)
                {
                    ARM7            = new NDSBinary();
                    ARM7.Name       = "ARM7";
                    ARM7.Extension  = ".bin";
                    ARM7.Offset     = ARM7Offset;
                    ARM7.Length     = ARM7Length;
                    ARM7.Load       = ARM7Load;
                    ARM7.AutoLoad   = ARM7AutoLoad;
                    ARM7.AutoParams = ARM7AutoParam;
                }
                if (ARM7iLength > 0)
                {
                    ARM7i           = new NDSBinary();
                    ARM7i.Name      = "ARM7i";
                    ARM7i.Extension = ".bin";
                    ARM7i.Offset    = ARM7iOffset;
                    ARM7i.Length    = ARM7Length;
                }

                int overlay7_count = Convert.ToInt32(ARM7OverlayLength / 32);
                OverlayTable7 = new NDSOverlay[overlay7_count];
                if (overlay7_count > 0)
                {
                    reader.BaseStream.Position = ARM7OverlayOffset;

                    for (int i = 0; i < overlay7_count; i++)
                    {
                        NDSOverlay overlay = new NDSOverlay();
                        overlay.OverlayID          = reader.ReadUInt32();
                        overlay.AddressRAM         = reader.ReadUInt32();
                        overlay.SizeRAM            = reader.ReadUInt32();
                        overlay.SizeBSS            = reader.ReadUInt32();
                        overlay.StaticStartAddress = reader.ReadUInt32();
                        overlay.StaticEndAddress   = reader.ReadUInt32();
                        overlay.ID     = Convert.ToInt32(reader.ReadUInt32());
                        overlay.Offset = FileTable[overlay.ID].Offset;
                        overlay.Length = FileTable[overlay.ID].Length;
                        uint temp = reader.ReadUInt32();
                        uint flag = temp >> 24;
                        if ((flag & 2) != 0)
                        {
                            overlay.Authenticated = true;
                        }
                        if ((flag & 1) != 0)
                        {
                            overlay.Compressed     = true;
                            overlay.CompressedSize = (temp << 8) >> 8;
                        }

                        overlay.Name      = "Overlay " + overlay.OverlayID;
                        overlay.Path      = "ARM9 Overlay Table\\" + overlay.Name;
                        overlay.Extension = ".bin";

                        OverlayTable7[i]      = overlay;
                        FileTable[overlay.ID] = overlay;
                    }
                }
            }
        }
Пример #4
0
        public static NARC NARC(Stream stream, NDSFile narc, bool is_nitro)
        {
            NDSFile[]      file_table;
            NDSDirectory[] directory_table;

            using (BinaryReader reader = new BinaryReader(stream, new UTF8Encoding(), true))
            {
                reader.BaseStream.Position = narc.Offset;

                uint   fnt_offset = 0;
                uint   fnt_length = 0;
                uint   fat_offset = 0;
                uint   fat_length = 0;
                ushort file_count = 0;

                if (is_nitro)
                {
                    // Here we read the header of the file. These are constants,
                    // so if any of this is wrong, it's probably a malformed NARC
                    // or not a NARC at all.
                    if (reader.ReadUInt32() != 1129464142 ||
                        reader.ReadUInt16() != 65534 ||
                        reader.ReadUInt16() != 256 ||
                        reader.ReadUInt32() != narc.Length ||
                        reader.ReadUInt16() != 16 ||
                        reader.ReadUInt16() != 3)
                    {
                        return(new NARC(new NDSFile[0], new NDSDirectory[0], false));
                    }

                    // FAT Signature Check
                    if (reader.ReadUInt32() != 1178686530)
                    {
                        return(new NARC(new NDSFile[0], new NDSDirectory[0], false));
                    }

                    fat_length = reader.ReadUInt32();
                    file_count = reader.ReadUInt16();
                    reader.BaseStream.Position += 2;

                    // Another validity check ...
                    if (fat_length != (file_count * 8) + 12)
                    {
                        return(new NARC(new NDSFile[0], new NDSDirectory[0], false));
                    }
                }
                else
                {
                    fnt_offset = narc.Offset + reader.ReadUInt32();
                    fnt_length = reader.ReadUInt32();
                    fat_offset = narc.Offset + reader.ReadUInt32();
                    fat_length = reader.ReadUInt32();
                    file_count = Convert.ToUInt16(fat_length / 8);


                    reader.BaseStream.Position = fat_offset;
                }


                // The File Allocation Table contain eight bytes per file entry;
                // a four byte file offset followed by a four byte file length.
                // We start by determining the file count and then dividing the
                // offsets and lenghts into separate indexed arrays.
                file_table = new NDSFile[file_count];
                for (int i = 0; i < file_count; i++)
                {
                    file_table[i]        = new NDSFile();
                    file_table[i].Name   = "File " + i.ToString("D" + file_count.ToString().Length);
                    file_table[i].ID     = i;
                    file_table[i].Offset = reader.ReadUInt32();
                    file_table[i].Length = reader.ReadUInt32() - file_table[i].Offset;
                }

                if (is_nitro)
                {
                    // FNT Signature check
                    if (reader.ReadUInt32() != 1179538498)
                    {
                        return(new NARC(new NDSFile[0], new NDSDirectory[0], false));
                    }

                    fnt_length = reader.ReadUInt32();
                    fnt_offset = narc.Offset + 16 + fat_length + 8;
                }

                // The File Name Table contains two sections; the first is the
                // main directory table. It's length is eight bytes per entry.
                // The first four bytes represent an offset to the entry in the
                // second section; the sub-directory table. This is followed by
                // two byte index corresponding to the first file entry in the
                // directory. Finally we have a two byte index corresponding to
                // the parent directory.

                // The first entry in the table is slightly different though.
                // The last two bytes in the first entry actually denote the
                // number of directories in the first section. Let's read that,
                // then use it to iterate through the main directory table and
                // split the table into three seperate indexed arrays.
                reader.BaseStream.Position = fnt_offset + 6;
                int directory_count = reader.ReadUInt16();
                reader.BaseStream.Position = fnt_offset;


                // Setting up the root directory.
                directory_table         = new NDSDirectory[directory_count];
                directory_table[0]      = new NDSDirectory();
                directory_table[0].Name = narc.Name;
                directory_table[0].Path = narc.Path;

                int[] entry_offset = new int[directory_count];
                int[] first_file   = new int[directory_count];
                int[] parent_index = new int[directory_count];

                reader.BaseStream.Position = fnt_offset;
                for (int i = 0; i < directory_count; i++)
                {
                    entry_offset[i] = Convert.ToInt32(reader.ReadUInt32() + fnt_offset);
                    first_file[i]   = reader.ReadUInt16();
                    parent_index[i] = reader.ReadUInt16() - 61440;
                }

                // The second section is the sub-directory table. This table is
                // a bit more complex. We start by iterating through the main
                // directory table and using the entry offset to locate its
                // position in the sub-directory table.
                int file_index = first_file[0];

                for (int i = 0; i < directory_count; i++)
                {
                    // Initialize the directory arrays.
                    reader.BaseStream.Position = entry_offset[i];
                    NDSDirectory parent_directory = directory_table[i];
                    parent_directory.Children = new List <NDSDirectory>();
                    parent_directory.Contents = new List <NDSFile>();

                    while (true)
                    {
                        // A small sanity check to make sure we havent overrun the table.
                        if (reader.BaseStream.Position > fnt_offset + fnt_length)
                        {
                            break;
                        }

                        // The first byte in the sub-directory entry indicates how to continue.
                        byte entry_byte = reader.ReadByte();

                        // 0 indicates the end of a directory.
                        if (entry_byte == 0)
                        {
                            break;
                        }

                        // 128 is actually invalid, and shouldn't be encountered. It would
                        // indicate a directory with no name, which isn't actually valid.
                        else if (entry_byte == 128)
                        {
                            continue;
                        }

                        // The first bit indicates a directory entry, so anything over 128
                        // is a sub-directory. The other seven bits indicate the length of
                        // the sub-directory name. We simply need to subtract 128, and the
                        // next so many bytes are the sub-directory name. The following
                        // two bytes are the sub-directory's ID in the main directory table.
                        else if (entry_byte > 128)
                        {
                            string       name            = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(entry_byte - 128));
                            NDSDirectory child_directory = new NDSDirectory();
                            child_directory.Name   = name;
                            child_directory.Parent = parent_directory;
                            child_directory.Path   = parent_directory.Path + "\\" + child_directory.Name;
                            child_directory.ID     = reader.ReadUInt16() - 61440;

                            directory_table[child_directory.ID] = child_directory;
                            parent_directory.Children.Add(child_directory);
                        }

                        // Anything under 128 indicates a file. Same as the previous, the
                        // other seven bits indicate the length of the file name. Unlike
                        // sub-directories, there is no index proceeding the file name.
                        else
                        {
                            string  name = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(entry_byte));
                            NDSFile file = file_table[file_index++];
                            file.Name   = name;
                            file.Parent = parent_directory;
                            file.Path   = parent_directory.Path + "\\" + file.Name;

                            parent_directory.Contents.Add(file);
                        }
                    }
                }

                // We run this now so that we don't have to jump the memory stream a ton.
                foreach (NDSFile file in file_table)
                {
                    if (file.Parent == null)
                    {
                        file.Parent = directory_table[0];
                        file.Path   = file.Parent.Path + "\\" + file.Name;
                        file.Parent.Contents.Add(file);
                    }
                    file.Offset += narc.Offset + 16 + fat_length + fnt_length + 8;
                    file.GetExtension(stream);

                    if (file.Extension == ".narc")
                    {
                        file.NARCTables = FileHandler.NARC(stream, file, true);
                    }
                    else if (file.Extension == ".arc")
                    {
                        file.NARCTables = FileHandler.NARC(stream, file, false);
                    }
                }
            }

            return(new NARC(file_table, directory_table, true));
        }