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)); } } } } }
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; }
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))); } } } }