예제 #1
0
        private TreeNode InitializeNode(NDSFile file)
        {
            TreeNode node = new TreeNode();

            if (file.NARCTables.IsValid)
            {
                node                    = new TreeNode();
                node.Name               = file.Name;
                node.Text               = file.Name + file.Extension;
                node.Tag                = file;
                node.ImageIndex         = 3;
                node.SelectedImageIndex = 3;

                NARC narc = file.NARCTables;

                foreach (NDSDirectory child in narc.DirectoryTable[0].Children)
                {
                    node.Nodes.Add(InitializeNode(child));
                    romTree.Update();
                }
                foreach (NDSFile sub_file in narc.DirectoryTable[0].Contents)
                {
                    node.Nodes.Add(InitializeNode(sub_file));
                    romTree.Update();
                }
            }
            else
            {
                node = new FileNode(file);
            }

            return(node);
        }
예제 #2
0
 private void romTree_AfterCollapse(object sender, TreeViewEventArgs e)
 {
     if (e.Node.Tag is NDSFile)
     {
         NDSFile file = e.Node.Tag as NDSFile;
         if (file.Extension == ".narc")
         {
             e.Node.ImageIndex         = 3;
             e.Node.SelectedImageIndex = 3;
         }
     }
     if (e.Node.Tag is NDSDirectory || e.Node.Tag is "dir")
     {
         e.Node.ImageIndex         = 0;
         e.Node.SelectedImageIndex = 0;
     }
 }
예제 #3
0
        public NARC(Stream stream, NDSFile narc)
        {
            stream.Position = narc.Offset;
            byte[] bytes = new byte[narc.Length];
            stream.Read(bytes, 0, narc.Length);

            try
            {
                if (BitConverter.ToUInt32(bytes, 0) != Signature ||
                    BitConverter.ToUInt16(bytes, 4) != ByteOrder ||
                    BitConverter.ToUInt16(bytes, 6) != Version ||
                    BitConverter.ToUInt32(bytes, 8) != bytes.Count() ||
                    BitConverter.ToUInt16(bytes, 12) != HeaderSize ||
                    BitConverter.ToUInt16(bytes, 14) != DataBlocks)
                {
                    Console.WriteLine(narc.Path + narc.Name + narc.Extension + " has a malformed header.");
                }

                SizeFAT  = BitConverter.ToUInt32(bytes, HeaderSize + 4);
                FilesFAT = BitConverter.ToUInt16(bytes, HeaderSize + 8);

                if (BitConverter.ToUInt32(bytes, 16) != SignatureFAT ||
                    SizeFAT != (FilesFAT * 8) + 12)
                {
                    Console.WriteLine(narc.Path + narc.Name + narc.Extension + " has a malformed file allocation table data block.");
                }

                SizeFNT = BitConverter.ToUInt32(bytes, HeaderSize + Convert.ToInt32(SizeFAT) + 4);

                if (BitConverter.ToUInt32(bytes, HeaderSize + Convert.ToInt32(SizeFAT)) != SignatureFNT)
                {
                    Console.WriteLine(narc.Path + narc.Name + narc.Extension + " has a malformed file name table data block.");
                }

                SizeIMG = BitConverter.ToUInt32(bytes, HeaderSize + Convert.ToInt32(SizeFAT + SizeFNT) + 4);

                if (BitConverter.ToInt32(bytes, HeaderSize + Convert.ToInt32(SizeFAT + SizeFNT)) != SignatureIMG)
                {
                    Console.WriteLine(narc.Path + narc.Name + narc.Extension + " has a malformed file image data block.");
                }
            }
            catch
            {
                Console.WriteLine(narc.Path + narc.Name + narc.Extension + " is not a valid NARC file.");
                isValid = false;
                return;
            }

            byte[] fatArray = new byte[SizeFAT - 12];
            byte[] fntArray = new byte[SizeFNT - 8];

            Array.Copy(bytes, HeaderSize + 12, fatArray, 0, SizeFAT - 12);
            Array.Copy(bytes, HeaderSize + Convert.ToInt32(SizeFAT) + 8, fntArray, 0, SizeFNT - 8);

            int directoryCount = BitConverter.ToUInt16(fntArray, 6);

            string[] directories = new string[directoryCount];
            directories[0] = narc.Path + "\\" + narc.Name + ".narc";

            NDSFile[] files = new NDSFile[FilesFAT];

            for (int i = 0; i < FilesFAT; i++)
            {
                NDSFile file        = new NDSFile();
                NDSFile currentFile = file;
                file.Name    = "File " + i.ToString("D" + FilesFAT.ToString().Length);
                file.Path    = directories[0];
                file.Offset  = Convert.ToInt32(BitConverter.ToUInt32(fatArray, i * 8));
                file.Length  = Convert.ToInt32(BitConverter.ToUInt32(fatArray, i * 8 + 4)) - file.Offset;
                file.Offset += narc.Offset + Convert.ToInt32(HeaderSize + SizeFAT + SizeFNT) + 8;
                files[i]     = file;
            }

            int unnamedCount = 0;

            for (int i = 0; i < directoryCount; i++)
            {
                int entryPos  = Convert.ToInt32(BitConverter.ToUInt32(fntArray, i * 8));
                int fileIndex = Convert.ToInt32(BitConverter.ToUInt16(fntArray, (i * 8) + 4));

                while (true)
                {
                    byte entryByte = fntArray[entryPos++];

                    if (entryByte == 0)
                    {
                        break;
                    }

                    else if (entryByte == 128)
                    {
                        int index = BitConverter.ToUInt16(fntArray, entryPos) - 61440;
                        directories[index] = directories[i] + "\\Unnamed " + unnamedCount++;
                        entryPos          += 2;
                    }

                    else if (entryByte > 128)
                    {
                        int index = BitConverter.ToUInt16(fntArray, (entryPos) + (entryByte - 128)) - 61440;
                        directories[index] = directories[i] + "\\" + System.Text.Encoding.UTF8.GetString(fntArray, entryPos, entryByte - 128);
                        entryPos          += (entryByte - 128) + 2;
                    }

                    else
                    {
                        files[fileIndex].Name = System.Text.Encoding.UTF8.GetString(fntArray, entryPos, entryByte);
                        files[fileIndex].Path = narc.Path + directories[i];
                        fileIndex++;
                        entryPos += entryByte;
                    }
                }
            }

            dirList  = directories.ToList();
            fileList = files.ToList();
            foreach (NDSFile file in fileList)
            {
                file.GetExtension(stream);
            }

            bytes       = null;
            fatArray    = null;
            fntArray    = null;
            directories = null;
            files       = null;
        }
예제 #4
0
        private void romTree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Tag is NDSFile)
            {
                if (e.Node.Tag is NDSBinary)
                {
                    DataGridView grid = propertyView;
                    NDSBinary    file = e.Node.Tag as NDSBinary;

                    grid.Rows.Clear();
                    string[] row = new string[] { "Name:", file.Name + file.Extension };
                    grid.Rows.Add(row);
                    row = new string[] { "Path:", "Root" };
                    grid.Rows.Add(row);

                    if (file.Name.Contains("9"))
                    {
                        if (!file.Name.Contains("i"))
                        {
                            row = new string[] { "File Type:", "ARM9i Binary", "ARMv5TE Compiled Binary, DSi Extended" };
                        }
                        else
                        {
                            row = new string[] { "File Type:", "ARM7i Binary", "ARMv5TE Compiled Binary." };
                        }
                    }
                    else if (file.Name.Contains("7"))
                    {
                        if (!file.Name.Contains("i"))
                        {
                            row = new string[] { "File Type:", "ARM9 Binary", "ARMv4T Compiled Binary, DSi Extended" };
                        }
                        else
                        {
                            row = new string[] { "File Type:", "ARM7 Binary", "ARMv4T Compiled Binary." };
                        }
                    }
                    else
                    {
                        row = new string[] { "File Type:", "ARM Binary", "ARM Compiled Binary" };
                    }
                    grid.Rows.Add(row);

                    row = new string[] { "Address:", file.Offset.ToString(), "Offset from beginning of ROM to start of the binary." };
                    grid.Rows.Add(row);
                    row = new string[] { "Length:", file.Length.ToString(), "The length of the binary." };
                    grid.Rows.Add(row);
                    row = new string[] { "RAM Address:", file.Load.ToString(), "The RAM address this binary is loaded to." };

                    if (!file.Name.Contains("i"))
                    {
                        grid.Rows.Add(row);
                        row = new string[] { "Hook Address:", file.AutoLoad.ToString(), "The RAM auto-load hook address." };
                        grid.Rows.Add(row);
                        row = new string[] { "Parameters:", file.AutoParams.ToString(), "Offset to auto-load parameter table." };
                    }
                    grid.Rows.Add(row);

                    grid.Refresh();
                }
                else if (e.Node.Tag is NDSOverlay)
                {
                    DataGridView grid = propertyView;
                    NDSOverlay   file = e.Node.Tag as NDSOverlay;

                    grid.Rows.Clear();
                    string[] row = new string[] { "Name:", file.Name + file.Extension };
                    grid.Rows.Add(row);
                    row = new string[] { "Path:", file.Path };
                    grid.Rows.Add(row);

                    if (file.Path.Contains("9"))
                    {
                        row = new string[] { "File Type:", "ARM9 Binary Overlay", "ARMv5TE Compiled Binary Overlay" };
                    }
                    else if (file.Path.Contains("7"))
                    {
                        row = new string[] { "File Type:", "ARM7 Binary Overlay", "ARMv4T Compiled Binary Overlay" };
                    }
                    else
                    {
                        row = new string[] { "File Type:", "ARM Binary Overlay", "ARM Compiled Binary Overlay" };
                    }
                    grid.Rows.Add(row);

                    row = new string[] { "File ID:", file.ID.ToString(), "The ID of the overlay in the file allocation table." };
                    grid.Rows.Add(row);
                    row = new string[] { "Overlay ID:", file.OverlayID.ToString(), "The ID of the overlay in the overlay table." };
                    grid.Rows.Add(row);
                    row = new string[] { "Offset:", "0x" + file.Offset.ToString("X"), "Offset from beginning of ROM to start of the overlay." };
                    grid.Rows.Add(row);
                    row = new string[] { "Size:", file.Length.ToString("N0") + " bytes", "The length of the overlay." };
                    grid.Rows.Add(row);
                    row = new string[] { "RAM Size:", file.SizeRAM.ToString("N0") + " bytes", "The size of the RAM section of the overlay." };
                    grid.Rows.Add(row);
                    row = new string[] { "BSS Size:", file.SizeBSS.ToString("N0") + " bytes", "The size of the BSS section of the overlay." };
                    grid.Rows.Add(row);
                    row = new string[] { "Compressed:", file.Compressed.ToString(), "Flag that indicates a compressed overlay." };
                    grid.Rows.Add(row);
                    if (file.Compressed)
                    {
                        row = new string[] { "Compressed Size:", file.CompressedSize.ToString("N0") + " bytes", "The compressed size of the overlay." };
                        grid.Rows.Add(row);
                        row = new string[] { "Total Size:", (file.SizeRAM + file.SizeBSS).ToString("N0") + " bytes", "The total size of the uncompressed overlay." };
                        grid.Rows.Add(row);
                    }

                    row = new string[] { "RAM Address:", "0x" + file.AddressRAM.ToString("X"), "The overlay transfer desitation address in RAM." };
                    grid.Rows.Add(row);
                    row = new string[] { "Start Address:", "0x" + file.StaticStartAddress.ToString("X"), "The static initializer start address of the overlay." };
                    grid.Rows.Add(row);
                    row = new string[] { "End Address:", "0x" + file.StaticEndAddress.ToString("X"), "The static initializer end address of the overlay." };
                    grid.Rows.Add(row);

                    grid.Refresh();
                }
                else if (e.Node.Tag is NDSBanner)
                {
                    DataGridView grid   = propertyView;
                    NDSBanner    banner = e.Node.Tag as NDSBanner;

                    grid.Rows.Clear();

                    string[] row = new string[] { };
                    grid.Rows.Add(row);
                }
                else
                {
                    DataGridView grid = propertyView;
                    NDSFile      file = e.Node.Tag as NDSFile;

                    grid.Rows.Clear();

                    string[] row = new string[] { "Name:", file.Name + file.Extension };
                    grid.Rows.Add(row);
                    row = new string[] { "Path:", file.Path };
                    grid.Rows.Add(row);
                    row = new string[] { "File Type:", file.Type, file.About };
                    grid.Rows.Add(row);
                    row = new string[] { "Offset:", file.Offset.ToString(), "The length of the file." };
                    grid.Rows.Add(row);
                    row = new string[] { "Size:", file.Length.ToString(), "Offset from beginning of ROM to start of the overlay." };
                    grid.Rows.Add(row);



                    grid.Refresh();
                }
            }
        }
예제 #5
0
            public FileNode(NDSFile node_file)
            {
                NodeFile = node_file;

                Name               = NodeFile.Name;
                Text               = NodeFile.Name + NodeFile.Extension;
                Tag                = NodeFile;
                ImageIndex         = 9;
                SelectedImageIndex = 9;

                switch (NodeFile.Extension)
                {
                case ".l":
                    ImageIndex         = 8;
                    SelectedImageIndex = 8;
                    break;

                case ".spa":
                    ImageIndex         = 14;
                    SelectedImageIndex = 14;
                    break;

                case ".bmg":
                    ImageIndex         = 15;
                    SelectedImageIndex = 15;
                    break;

                case ".txt":
                    ImageIndex         = 7;
                    SelectedImageIndex = 7;
                    break;

                case ".dat":
                    ImageIndex         = 9;
                    SelectedImageIndex = 9;
                    break;

                case ".bin":
                    ImageIndex         = 10;
                    SelectedImageIndex = 10;
                    break;

                case ".sdat":
                    ImageIndex         = 13;
                    SelectedImageIndex = 13;
                    break;

                case ".narc":
                    ImageIndex         = 3;
                    SelectedImageIndex = 3;
                    break;

                case ".arc":
                    ImageIndex         = 3;
                    SelectedImageIndex = 3;
                    break;

                case ".nce":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nan":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nam":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".ncg":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".ncb":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".ncl":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nmc":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nen":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nsc":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".ncer":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nanr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".namr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".ncgr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".ncbr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nclr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nmcr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nenr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nscr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nftr":
                    ImageIndex         = 11;
                    SelectedImageIndex = 11;
                    break;

                case ".nsbmd":
                    ImageIndex         = 12;
                    SelectedImageIndex = 12;
                    break;

                case ".nsbtx":
                    ImageIndex         = 12;
                    SelectedImageIndex = 12;
                    break;

                case ".nsbca":
                    ImageIndex         = 12;
                    SelectedImageIndex = 12;
                    break;

                case ".nsbtp":
                    ImageIndex         = 12;
                    SelectedImageIndex = 12;
                    break;

                case ".nsbma":
                    ImageIndex         = 12;
                    SelectedImageIndex = 12;
                    break;

                case ".nsbva":
                    ImageIndex         = 12;
                    SelectedImageIndex = 12;
                    break;

                case ".nsbta":
                    ImageIndex         = 12;
                    SelectedImageIndex = 12;
                    break;
                }
            }
예제 #6
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;
                    }
                }
            }
        }
예제 #7
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));
        }