Beispiel #1
0
        private void narcWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;

            worker.ReportProgress(0, new Tuple <int, string, int, int>(0, "Reading Archive Header", 0, 0));

            if (!File.Exists(file))
            {
                DialogResult result = CustomMessageBox.Show(
                    "The file that you've specified doesn't exist or has changed locations."
                    + " Please check the path and file name for any errors and try again.",
                    "File Doesn't Exist",
                    400,
                    new List <string>(),
                    new List <DialogResult>());

                return;
            }
            ;

            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            if (!Directory.Exists(path))
            {
                try
                {
                    Directory.CreateDirectory(path);
                }
                catch (Exception exception)
                {
                    DialogResult dialog = CustomMessageBox.Show(
                        exception.Message,
                        exception.GetType().ToString(),
                        400,
                        new List <string>(),
                        new List <DialogResult>());

                    return;
                }
            }

            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            using (MemoryStream narcStream = new MemoryStream(File.ReadAllBytes(file)))
            {
                using (BinaryReader narcReader = new BinaryReader(narcStream))
                {
                    FileNDS archive = new FileNDS("", path, "", 0, Convert.ToInt32(narcStream.Length));
                    NARC    narc    = new NARC(narcStream, archive);

                    if (narc.isValid)
                    {
                        int workload = narc.dirList.Count + narc.fileList.Count;
                        worker.ReportProgress(workload, new Tuple <int, string, int, int>(0, "Writing Folder Structure", narc.dirList.Count, 0));

                        for (int i = 1; i < narc.dirList.Count; i++)
                        {
                            if (worker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }

                            Directory.CreateDirectory(narc.dirList[i]);

                            worker.ReportProgress(workload, new Tuple <int, string, int, int>(i + 1, "Writing Folder Structure", narc.dirList.Count, i + 1));
                        }

                        worker.ReportProgress(workload, new Tuple <int, string, int, int>(narc.dirList.Count, "Extracting Files", narc.fileList.Count, 0));

                        for (int i = 0; i < narc.fileList.Count; i++)
                        {
                            if (worker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }

                            FileNDS file = narc.fileList[i];
                            narcReader.BaseStream.Position = file.Offset;
                            byte[] image = new byte[file.Length];
                            narcReader.Read(image, 0, file.Length);

                            using (BinaryWriter writer = new BinaryWriter(File.Open(file.Path + "\\" + file.Name + file.Extension, FileMode.Create)))
                            {
                                writer.Write(image, 0, file.Length);
                            }

                            worker.ReportProgress(workload, new Tuple <int, string, int, int>(i + 1 + narc.dirList.Count, "Extracting Files", narc.fileList.Count, i + 1));
                        }
                    }
                }
            }
        }
Beispiel #2
0
        public NARC(Stream stream, FileNDS 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];
            if (narc.Name + narc.Extension == "")
            {
                directories[0] = narc.Path;
            }
            else
            {
                directories[0] = narc.Path + "\\" + narc.Name + narc.Extension;
            }

            FileNDS[] files = new FileNDS[FilesFAT];

            for (int i = 0; i < FilesFAT; i++)
            {
                FileNDS file        = new FileNDS();
                FileNDS 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 (FileNDS file in fileList)
            {
                file.GetExtension(stream);
            }

            bytes       = null;
            fatArray    = null;
            fntArray    = null;
            directories = null;
            files       = null;
        }
Beispiel #3
0
        private void romWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;

            worker.ReportProgress(0, new Tuple <int, string, int, int>(0, "Reading System Files", 0, 0));

            if (!File.Exists(file))
            {
                DialogResult result = CustomMessageBox.Show(
                    "The file that you've specified doesn't exist or has changed locations."
                    + " Please check the path and file name for any errors and try again.",
                    "File Doesn't Exist",
                    400,
                    new List <string>(),
                    new List <DialogResult>());

                return;
            }
            ;

            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            if (!Directory.Exists(path))
            {
                try
                {
                    Directory.CreateDirectory(path);
                }
                catch (Exception exception)
                {
                    DialogResult dialog = CustomMessageBox.Show(
                        exception.Message,
                        exception.GetType().ToString(),
                        400,
                        new List <string>(),
                        new List <DialogResult>());

                    return;
                }
            }

            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            using (MemoryStream romStream = new MemoryStream(File.ReadAllBytes(file)))
            {
                using (BinaryReader romReader = new BinaryReader(romStream))
                {
                    romReader.BaseStream.Position = 32;
                    int arm9Offset = Convert.ToInt32(romReader.ReadUInt32());
                    romReader.BaseStream.Position = 44;
                    int arm9Length = Convert.ToInt32(romReader.ReadUInt32());
                    int arm7Offset = Convert.ToInt32(romReader.ReadUInt32());
                    romReader.BaseStream.Position = 60;
                    int arm7Length = Convert.ToInt32(romReader.ReadUInt32());
                    int fntOffset  = Convert.ToInt32(romReader.ReadUInt32());
                    int fntLength  = Convert.ToInt32(romReader.ReadUInt32());
                    int fatOffset  = Convert.ToInt32(romReader.ReadUInt32());
                    int fatLength  = Convert.ToInt32(romReader.ReadUInt32());
                    int oat9Offset = Convert.ToInt32(romReader.ReadUInt32());
                    int oat9Length = Convert.ToInt32(romReader.ReadUInt32());
                    int oat7Offset = Convert.ToInt32(romReader.ReadUInt32());
                    int oat7Length = Convert.ToInt32(romReader.ReadUInt32());
                    romReader.BaseStream.Position = 104;
                    int bnrOffset = Convert.ToInt32(romReader.ReadUInt32());
                    romReader.BaseStream.Position = bnrOffset;
                    int bnrLength = Convert.ToInt32(romReader.ReadUInt16());
                    switch (bnrLength)
                    {
                    case 1:
                        bnrLength = 2112;
                        break;

                    case 2:
                        bnrLength = 2112;
                        break;

                    case 3:
                        bnrLength = 3072;
                        break;

                    case 259:
                        bnrLength = 9216;
                        break;
                    }

                    byte[] fntArray = new byte[fntLength];
                    byte[] fatArray = new byte[fatLength];

                    romReader.BaseStream.Position = fntOffset;
                    romReader.Read(fntArray, 0, fntLength);
                    romReader.BaseStream.Position = fatOffset;
                    romReader.Read(fatArray, 0, fatLength);

                    if (fatArray.Count() % 8 > 0)
                    {
                        // Exception handling for rewrite later.
                        throw new Exception(
                                  "Table length must be a multiple of 8. This table has a length of " + fatArray.Count() + "."
                                  + "\n " + fatArray.Count() + " ÷ 8 = " + (fatArray.Count() / 8)
                                  + "\n Remainder: " + (fatArray.Count() % 8)
                                  );
                    }

                    List <FileNDS> fileList = new List <FileNDS>();
                    fileList.Add(new FileNDS("Header", "", "", 0, 16384));
                    fileList.Add(new FileNDS("File Name Table", "", "", fntOffset, fntLength));
                    fileList.Add(new FileNDS("File Allocation Table", "", "", fatOffset, fatLength));
                    fileList.Add(new FileNDS("Banner", "", ".bnr", bnrOffset, bnrLength));
                    fileList.Add(new FileNDS("ARM9 Binary", "", ".bin", arm9Offset, arm9Length));
                    fileList.Add(new FileNDS("ARM9 Overlay Table", "", "", oat9Offset, oat9Length));
                    if (arm7Length > 0)
                    {
                        fileList.Add(new FileNDS("ARM7 Binary", "", ".bin", arm7Offset, arm9Length));
                    }
                    if (oat7Length > 0)
                    {
                        fileList.Add(new FileNDS("ARM7 Overlay Table", "", "", oat7Offset, oat9Length));
                    }

                    int directoryCount = BitConverter.ToUInt16(fntArray, 6);
                    int firstFile      = BitConverter.ToInt16(fntArray, 4);
                    int fileCount      = fatArray.Count() / 8;
                    int workload       = (fileCount * 4) + (directoryCount * 2);
                    int progress       = 0;

                    worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading File Name And Allocation Tables", fileCount, 0));
                    FileNDS[] files = new FileNDS[fileCount];

                    for (int i = 0; i < fileCount; i++)
                    {
                        if (worker.CancellationPending)
                        {
                            e.Cancel = true;
                            return;
                        }

                        files[i] = new FileNDS();
                        FileNDS currentFile = files[i];
                        files[i].Offset = Convert.ToInt32(BitConverter.ToUInt32(fatArray, i * 8));
                        files[i].Length = Convert.ToInt32(BitConverter.ToUInt32(fatArray, i * 8 + 4)) - files[i].Offset;

                        progress++;
                        worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading File Allocation Table", fileCount, i + 1));
                    }

                    worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading Overlay Allocation Table", firstFile, 0));

                    string[]      directories;
                    List <string> dirList = new List <string>();
                    directories = new string[directoryCount];
                    if (firstFile > 0)
                    {
                        directories[0] = "\\Root";
                        dirList.Add("\\Overlays");
                        for (int i = 0; i < firstFile; i++)
                        {
                            if (worker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }

                            files[i].Name = "Overlay " + i.ToString("D" + firstFile.ToString().Length) + ".bin";
                            files[i].Path = "\\Overlays";

                            progress++;
                            worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading Overlay Allocation Table", firstFile, i + 1));
                        }
                    }
                    else
                    {
                        directories[0] = "";
                    }

                    worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading File Name Table", fileCount + directoryCount, 0));

                    int unnamedCount = 0;
                    int dirProgress  = 0;
                    int fileProgress = 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)
                        {
                            if (worker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }

                            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++;
                                dirProgress++;
                                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);
                                dirProgress++;
                                entryPos += (entryByte - 128) + 2;
                            }

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

                            progress++;
                            worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading File Name Table", fileCount + directoryCount, dirProgress + fileProgress));
                        }
                    }

                    worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Getting File Extensions", fileCount, 0));

                    fileList.AddRange(files.ToList());
                    dirList.AddRange(directories.ToList());
                    files       = null;
                    directories = null;
                    List <FileNDS> narcList = new List <FileNDS>();
                    for (int i = 0; i < fileCount; i++)
                    {
                        if (worker.CancellationPending)
                        {
                            e.Cancel = true;
                            return;
                        }

                        FileNDS file = fileList[i];
                        file.GetExtension(romStream);

                        if (narcCheckBox.Checked && file.Extension == ".narc")
                        {
                            narcList.Add(file);
                            workload++;
                        }

                        progress++;
                        worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Getting File Extensions", fileCount, i + 1));
                    }

                    worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading NARC Files", directoryCount, 0));

                    if (narcCheckBox.Checked && narcList.Count > 0)
                    {
                        for (int i = 0; i < narcList.Count; i++)
                        {
                            if (worker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }

                            FileNDS file = narcList[i];
                            NARC    narc = new NARC(romStream, file);
                            if (narc.isValid)
                            {
                                fileList.Remove(file);
                                dirList.AddRange(narc.dirList);
                                fileList.AddRange(narc.fileList);
                            }

                            progress++;
                            worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Reading NARC Files", narcList.Count, i + 1));
                        }
                    }

                    worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Writing Folder Structure", directoryCount, 0));

                    double compWorkload = directoryCount / dirList.Count;
                    for (int i = 0; i < dirList.Count; i++)
                    {
                        if (worker.CancellationPending)
                        {
                            e.Cancel = true;
                            return;
                        }

                        Directory.CreateDirectory(path + dirList[i]);

                        int p = Convert.ToInt32((i + 1) * compWorkload);
                        worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress + p, "Writing Folder Structure", directoryCount, (int)((i + 1) * compWorkload)));
                    }

                    progress += directoryCount;
                    worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress, "Extracting Files", fileList.Count, 0));

                    compWorkload = (double)fileCount / (double)fileList.Count;
                    for (int i = 0; i < fileList.Count; i++)
                    {
                        if (worker.CancellationPending)
                        {
                            e.Cancel = true;
                            return;
                        }

                        FileNDS file = fileList[i];
                        romReader.BaseStream.Position = file.Offset;
                        byte[] image = new byte[file.Length];
                        romReader.Read(image, 0, file.Length);

                        using (BinaryWriter writer = new BinaryWriter(File.Open(path + file.Path + "\\" + file.Name + file.Extension, FileMode.Create)))
                        {
                            writer.Write(image, 0, file.Length);
                        }

                        int p = Convert.ToInt32((i + 1) * compWorkload);
                        worker.ReportProgress(workload, new Tuple <int, string, int, int>(progress + p, "Extracting Files", fileList.Count, (i + 1)));
                    }
                }
            }
        }