From 9e1f095d4d4b51e37a65a4be08f224cfabea4d18 Mon Sep 17 00:00:00 2001 From: Gericom Date: Tue, 11 Nov 2014 18:56:18 +0100 Subject: [PATCH] Implemented NDS Reading and Exploring --- 3DS/SARC.cs | 2 +- CommonFiles/DAE.cs | 7 +- LibEveryFileExplorer/Files/FileFormat.cs | 1 + NDS/NDS.cs | 383 +++++++++++++++++++++++ NDS/NDS.csproj | 10 + NDS/UI/NDSViewer.Designer.cs | 277 ++++++++++++++++ NDS/UI/NDSViewer.cs | 236 ++++++++++++++ NDS/UI/NDSViewer.resx | 160 ++++++++++ 8 files changed, 1074 insertions(+), 2 deletions(-) create mode 100644 NDS/NDS.cs create mode 100644 NDS/UI/NDSViewer.Designer.cs create mode 100644 NDS/UI/NDSViewer.cs create mode 100644 NDS/UI/NDSViewer.resx diff --git a/3DS/SARC.cs b/3DS/SARC.cs index 34ff3b5..c747120 100644 --- a/3DS/SARC.cs +++ b/3DS/SARC.cs @@ -296,7 +296,7 @@ public override Bitmap GetIcon() public override FormatMatch IsFormat(EFEFile File) { - if (File.Data.Length > 20 && File.Data[0] == 'S' && File.Data[1] == 'A' && File.Data[2] == 'R' && File.Data[3] == 'C') return FormatMatch.Content; + if (File.Data.Length > 20 && File.Data[0] == 'S' && File.Data[1] == 'A' && File.Data[2] == 'R' && File.Data[3] == 'C' && File.Data[0x14] == 'S' && File.Data[0x15] == 'F' && File.Data[0x16] == 'A' && File.Data[0x17] == 'T') return FormatMatch.Content; return FormatMatch.No; } diff --git a/CommonFiles/DAE.cs b/CommonFiles/DAE.cs index c4bb3b5..0267c38 100644 --- a/CommonFiles/DAE.cs +++ b/CommonFiles/DAE.cs @@ -1754,7 +1754,12 @@ public override Bitmap GetIcon() public override FormatMatch IsFormat(EFEFile File) { - String s = Encoding.ASCII.GetString(File.Data); + String s; + try + { + s = Encoding.ASCII.GetString(File.Data); + } + catch { return FormatMatch.No; } if(s.StartsWith(", IViewable + { + public NDS(byte[] data) + { + EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(data), Endianness.LittleEndian); + header = new ROM_Header(er); + + er.BaseStream.Position = header.main_rom_offset; + main_rom = er.ReadBytes((int)header.main_size); + + er.BaseStream.Position = header.sub_rom_offset; + sub_rom = er.ReadBytes((int)header.sub_size); + + er.BaseStream.Position = header.fnt_offset; + fnt = new ROM_FNT(er); + + er.BaseStream.Position = header.main_ovt_offset; + main_ovt = new ROM_OVT[header.main_ovt_size / 32]; + for (int i = 0; i < header.main_ovt_size / 32; i++) main_ovt[i] = new ROM_OVT(er); + + er.BaseStream.Position = header.sub_ovt_offset; + sub_ovt = new ROM_OVT[header.sub_ovt_size / 32]; + for (int i = 0; i < header.sub_ovt_size / 32; i++) sub_ovt[i] = new ROM_OVT(er); + + er.BaseStream.Position = header.fat_offset; + fat = new FileAllocationEntry[header.fat_size / 8]; + for (int i = 0; i < header.fat_size / 8; i++) fat[i] = new FileAllocationEntry(er); + + er.BaseStream.Position = header.banner_offset; + banner = new BannerFile(er); + + FileData = new byte[header.fat_size / 8][]; + for (int i = 0; i < header.fat_size / 8; i++) + { + er.BaseStream.Position = fat[i].fileTop; + FileData[i] = er.ReadBytes((int)fat[i].fileSize); + } + + er.Close(); + } + + public Form GetDialog() + { + return new NDSViewer(this); + } + + public ROM_Header header; + public class ROM_Header + { + public ROM_Header(EndianBinaryReader er) + { + game_name = er.ReadString(Encoding.ASCII, 12).Replace("\0", ""); + game_code = er.ReadString(Encoding.ASCII, 4).Replace("\0", ""); + maker_code = er.ReadString(Encoding.ASCII, 2).Replace("\0", ""); + product_id = er.ReadByte(); + device_type = er.ReadByte(); + device_size = er.ReadByte(); + reserved_A = er.ReadBytes(9); + game_version = er.ReadByte(); + property = er.ReadByte(); + + main_rom_offset = er.ReadUInt32(); + main_entry_address = er.ReadUInt32(); + main_ram_address = er.ReadUInt32(); + main_size = er.ReadUInt32(); + sub_rom_offset = er.ReadUInt32(); + sub_entry_address = er.ReadUInt32(); + sub_ram_address = er.ReadUInt32(); + sub_size = er.ReadUInt32(); + + fnt_offset = er.ReadUInt32(); + fnt_size = er.ReadUInt32(); + + fat_offset = er.ReadUInt32(); + fat_size = er.ReadUInt32(); + + main_ovt_offset = er.ReadUInt32(); + main_ovt_size = er.ReadUInt32(); + + sub_ovt_offset = er.ReadUInt32(); + sub_ovt_size = er.ReadUInt32(); + + rom_param_A = er.ReadBytes(8); + banner_offset = er.ReadUInt32(); + secure_crc = er.ReadUInt16(); + rom_param_B = er.ReadBytes(2); + + main_autoload_done = er.ReadUInt32(); + sub_autoload_done = er.ReadUInt32(); + + rom_param_C = er.ReadBytes(8); + rom_size = er.ReadUInt32(); + header_size = er.ReadUInt32(); + reserved_B = er.ReadBytes(0x38); + + logo_data = er.ReadBytes(0x9C); + logo_crc = er.ReadUInt16(); + header_crc = er.ReadUInt16(); + } + public String game_name;//12 + public String game_code;//4 + public String maker_code;//2 + public Byte product_id; + public Byte device_type; + public Byte device_size; + public byte[] reserved_A;//9 + public Byte game_version; + public Byte property; + + public UInt32 main_rom_offset; + public UInt32 main_entry_address; + public UInt32 main_ram_address; + public UInt32 main_size; + public UInt32 sub_rom_offset; + public UInt32 sub_entry_address; + public UInt32 sub_ram_address; + public UInt32 sub_size; + + public UInt32 fnt_offset; + public UInt32 fnt_size; + + public UInt32 fat_offset; + public UInt32 fat_size; + + public UInt32 main_ovt_offset; + public UInt32 main_ovt_size; + + public UInt32 sub_ovt_offset; + public UInt32 sub_ovt_size; + + public byte[] rom_param_A;//8 + public UInt32 banner_offset; + public UInt16 secure_crc; + public byte[] rom_param_B;//2 + + public UInt32 main_autoload_done; + public UInt32 sub_autoload_done; + + public byte[] rom_param_C;//8 + public UInt32 rom_size; + public UInt32 header_size; + public byte[] reserved_B;//0x38 + + public byte[] logo_data;//0x9C + public UInt16 logo_crc; + public UInt16 header_crc; + } + public Byte[] main_rom; + public Byte[] sub_rom; + public ROM_FNT fnt; + public class ROM_FNT + { + public ROM_FNT(EndianBinaryReader er) + { + directoryTable = new List(); + directoryTable.Add(new DirectoryTableEntry(er)); + for (int i = 0; i < directoryTable[0].dirParentID - 1; i++) + { + directoryTable.Add(new DirectoryTableEntry(er)); + } + entryNameTable = new List(); + int dirend = 0; + while (dirend < directoryTable[0].dirParentID) + { + byte entryNameLength = er.ReadByte(); + er.BaseStream.Position--; + if (entryNameLength == 0) + { + entryNameTable.Add(new EntryNameTableEndOfDirectoryEntry(er)); + dirend++; + } + else if (entryNameLength < 0x80) entryNameTable.Add(new EntryNameTableFileEntry(er)); + else entryNameTable.Add(new EntryNameTableDirectoryEntry(er)); + } + } + public List directoryTable; + public List entryNameTable; + } + public ROM_OVT[] main_ovt; + public ROM_OVT[] sub_ovt; + public class ROM_OVT + { + [Flags] + public enum OVT_Flag : byte + { + Compressed = 1, + Authentication_Code = 2 + } + public ROM_OVT(EndianBinaryReader er) + { + id = er.ReadUInt32(); + ram_address = er.ReadUInt32(); + ram_size = er.ReadUInt32(); + bss_size = er.ReadUInt32(); + sinit_init = er.ReadUInt32(); + sinit_init_end = er.ReadUInt32(); + file_id = er.ReadUInt32(); + UInt32 tmp = er.ReadUInt32(); + compressed = tmp & 0xFFFFFF; + flag = (OVT_Flag)(tmp >> 24); + } + public UInt32 id; + public UInt32 ram_address; + public UInt32 ram_size; + public UInt32 bss_size; + public UInt32 sinit_init; + public UInt32 sinit_init_end; + public UInt32 file_id; + + public UInt32 compressed;//:24; + public OVT_Flag flag;// :8; + } + public FileAllocationEntry[] fat; + public BannerFile banner; + public class BannerFile + { + public BannerFile(EndianBinaryReader er) + { + h = new BannerHeader(er); + v1 = new BannerFileV1(er); + } + BannerHeader h; + public class BannerHeader + { + public BannerHeader(EndianBinaryReader er) + { + version = er.ReadByte(); + reserved_A = er.ReadByte(); + crc16_v1 = er.ReadUInt16(); + reserved_B = er.ReadBytes(28); + } + public Byte version; + public Byte reserved_A; + public UInt16 crc16_v1; + public Byte[] reserved_B;//28 + } + BannerFileV1 v1; + public class BannerFileV1 + { + public BannerFileV1(EndianBinaryReader er) + { + image = er.ReadBytes(32 * 32 / 2); + pltt = er.ReadBytes(16 * 2); + gameName = new string[6]; + gameName[0] = er.ReadString(Encoding.Unicode, 128).Replace("\0", ""); + gameName[1] = er.ReadString(Encoding.Unicode, 128).Replace("\0", ""); + gameName[2] = er.ReadString(Encoding.Unicode, 128).Replace("\0", ""); + gameName[3] = er.ReadString(Encoding.Unicode, 128).Replace("\0", ""); + gameName[4] = er.ReadString(Encoding.Unicode, 128).Replace("\0", ""); + gameName[5] = er.ReadString(Encoding.Unicode, 128).Replace("\0", ""); + } + public Byte[] image;//32*32/2 + public Byte[] pltt;//16*2 + public String[] gameName;//6, 128 chars (UTF16-LE) + } + } + public Byte[][] FileData; + + public SFSDirectory ToFileSystem() + { + bool treereconstruct = false;//Some programs do not write the Directory Table well, so sometimes I need to reconstruct the tree based on the fnt, which is bad! + List dirs = new List(); + dirs.Add(new SFSDirectory("/", true)); + dirs[0].DirectoryID = 0xF000; + + uint nrdirs = fnt.directoryTable[0].dirParentID; + for (int i = 1; i < nrdirs; i++) + { + dirs.Add(new SFSDirectory((ushort)(0xF000 + i))); + } + for (int i = 1; i < nrdirs; i++) + { + if (fnt.directoryTable[i].dirParentID - 0xF000 == i) + { + treereconstruct = true; + foreach (var v in dirs) + { + v.Parent = null; + } + break; + } + dirs[i].Parent = dirs[fnt.directoryTable[i].dirParentID - 0xF000]; + } + if (!treereconstruct) + { + for (int i = 0; i < nrdirs; i++) + { + for (int j = 0; j < nrdirs; j++) + { + if (dirs[i] == dirs[j].Parent) + { + dirs[i].SubDirectories.Add(dirs[j]); + } + } + } + } + uint offset = nrdirs * 8; + ushort fileid = fnt.directoryTable[0].dirEntryFileID; + SFSDirectory curdir = null; + foreach (EntryNameTableEntry e in fnt.entryNameTable) + { + for (int i = 0; i < nrdirs; i++) + { + if (offset == fnt.directoryTable[i].dirEntryStart) + { + curdir = dirs[i]; + break; + } + } + if (e is EntryNameTableEndOfDirectoryEntry) + { + curdir = null; + offset++; + } + else if (e is EntryNameTableFileEntry) + { + curdir.Files.Add(new SFSFile(fileid++, ((EntryNameTableFileEntry)e).entryName, curdir)); + offset += 1u + e.entryNameLength; + } + else if (e is EntryNameTableDirectoryEntry) + { + if (treereconstruct) + { + dirs[((EntryNameTableDirectoryEntry)e).directoryID - 0xF000].Parent = curdir; + curdir.SubDirectories.Add(dirs[((EntryNameTableDirectoryEntry)e).directoryID - 0xF000]); + } + dirs[((EntryNameTableDirectoryEntry)e).directoryID - 0xF000].DirectoryName = ((EntryNameTableDirectoryEntry)e).entryName; + offset += 3u + (e.entryNameLength & 0x7Fu); + } + } + for (int i = (int)(header.main_ovt_size / 32 + header.sub_ovt_size / 32); i < header.fat_size / 8; i++) + { + //byte[] data = new byte[fat[i].fileSize]; + //Array.Copy(FileData FIMG.fileImage, fat[i].fileTop, data, 0, data.Length); + dirs[0].GetFileByID((ushort)i).Data = FileData[i];//data; + } + return dirs[0]; + } + + public class NDSIdentifier : FileFormatIdentifier + { + public override string GetCategory() + { + return Category_Roms; + } + + public override string GetFileDescription() + { + return "Nintendo DS Rom (NDS)"; + } + + public override string GetFileFilter() + { + return "Nintendo DS Rom (*.nds, *.srl)|*.nds;*.srl"; + } + + public override Bitmap GetIcon() + { + return null; + } + + public override FormatMatch IsFormat(EFEFile File) + { + if (File.Name.ToLower().EndsWith(".nds") || File.Name.ToLower().EndsWith(".srl")) return FormatMatch.Extension; + return FormatMatch.No; + } + + } + } +} diff --git a/NDS/NDS.csproj b/NDS/NDS.csproj index 5d509c8..d2e544b 100644 --- a/NDS/NDS.csproj +++ b/NDS/NDS.csproj @@ -54,6 +54,7 @@ + @@ -71,6 +72,12 @@ Resource.resx + + Form + + + NDSViewer.cs + UserControl @@ -119,6 +126,9 @@ ResXFileCodeGenerator Resource.Designer.cs + + NDSViewer.cs + MDL0MaterialEditor.cs diff --git a/NDS/UI/NDSViewer.Designer.cs b/NDS/UI/NDSViewer.Designer.cs new file mode 100644 index 0000000..b28b127 --- /dev/null +++ b/NDS/UI/NDSViewer.Designer.cs @@ -0,0 +1,277 @@ +namespace NDS.UI +{ + partial class NDSViewer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NDSViewer)); + this.fileBrowser1 = new LibEveryFileExplorer.UI.FileBrowser(); + this.mainMenu1 = new LibEveryFileExplorer.UI.MainMenu(this.components); + this.menuItem1 = new System.Windows.Forms.MenuItem(); + this.menuItem2 = new System.Windows.Forms.MenuItem(); + this.menuItem3 = new System.Windows.Forms.MenuItem(); + this.menuItem4 = new System.Windows.Forms.MenuItem(); + this.menuExport = new System.Windows.Forms.MenuItem(); + this.menuItem13 = new System.Windows.Forms.MenuItem(); + this.menuReplace = new System.Windows.Forms.MenuItem(); + this.menuRename = new System.Windows.Forms.MenuItem(); + this.menuDelete = new System.Windows.Forms.MenuItem(); + this.menuItem5 = new System.Windows.Forms.MenuItem(); + this.menuItem6 = new System.Windows.Forms.MenuItem(); + this.menuItem7 = new System.Windows.Forms.MenuItem(); + this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog(); + this.contextMenu1 = new System.Windows.Forms.ContextMenu(); + this.menuItem8 = new System.Windows.Forms.MenuItem(); + this.menuItem9 = new System.Windows.Forms.MenuItem(); + this.menuItem14 = new System.Windows.Forms.MenuItem(); + this.menuItem10 = new System.Windows.Forms.MenuItem(); + this.menuItem11 = new System.Windows.Forms.MenuItem(); + this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); + this.SuspendLayout(); + // + // fileBrowser1 + // + this.fileBrowser1.DeleteEnabled = false; + this.fileBrowser1.Dock = System.Windows.Forms.DockStyle.Fill; + this.fileBrowser1.Location = new System.Drawing.Point(0, 0); + this.fileBrowser1.Name = "fileBrowser1"; + this.fileBrowser1.RenameEnabled = false; + this.fileBrowser1.ShowAddDirectoryButton = false; + this.fileBrowser1.ShowAddFileButton = false; + this.fileBrowser1.ShowDeleteButton = false; + this.fileBrowser1.ShowRenameButton = false; + this.fileBrowser1.Size = new System.Drawing.Size(652, 338); + this.fileBrowser1.TabIndex = 0; + this.fileBrowser1.OnDirectoryChanged += new LibEveryFileExplorer.UI.FileBrowser.OnDirectoryChangedEventHandler(this.fileBrowser1_OnDirectoryChanged); + this.fileBrowser1.OnFileActivated += new LibEveryFileExplorer.UI.FileBrowser.OnFileActivatedEventHandler(this.fileBrowser1_OnFileActivated); + this.fileBrowser1.OnAddDirectory += new System.EventHandler(this.fileBrowser1_OnAddDirectory); + this.fileBrowser1.OnAddFile += new System.EventHandler(this.fileBrowser1_OnAddFile); + this.fileBrowser1.OnRemove += new System.EventHandler(this.fileBrowser1_OnRemove); + this.fileBrowser1.OnRename += new System.EventHandler(this.fileBrowser1_OnRename); + this.fileBrowser1.OnSelectionChanged += new System.EventHandler(this.fileBrowser1_OnSelectionChanged); + this.fileBrowser1.OnRightClick += new LibEveryFileExplorer.UI.FileBrowser.OnRightClickEventHandler(this.fileBrowser1_OnRightClick); + // + // mainMenu1 + // + this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItem1, + this.menuItem5}); + // + // menuItem1 + // + this.menuItem1.Index = 0; + this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItem2, + this.menuItem3, + this.menuItem4, + this.menuExport, + this.menuItem13, + this.menuReplace, + this.menuRename, + this.menuDelete}); + this.menuItem1.MergeOrder = 1; + this.menuItem1.MergeType = System.Windows.Forms.MenuMerge.MergeItems; + this.menuItem1.Text = "Edit"; + // + // menuItem2 + // + this.menuItem2.Index = 0; + this.menuItem2.Text = "Add Folder..."; + this.menuItem2.Visible = false; + this.menuItem2.Click += new System.EventHandler(this.fileBrowser1_OnAddDirectory); + // + // menuItem3 + // + this.menuItem3.Index = 1; + this.menuItem3.Text = "Add File..."; + this.menuItem3.Visible = false; + this.menuItem3.Click += new System.EventHandler(this.fileBrowser1_OnAddFile); + // + // menuItem4 + // + this.menuItem4.Index = 2; + this.menuItem4.Text = "-"; + this.menuItem4.Visible = false; + // + // menuExport + // + this.menuExport.Enabled = false; + this.menuExport.Index = 3; + this.menuExport.Text = "Export..."; + this.menuExport.Click += new System.EventHandler(this.menuExport_Click); + // + // menuItem13 + // + this.menuItem13.Index = 4; + this.menuItem13.Text = "-"; + this.menuItem13.Visible = false; + // + // menuReplace + // + this.menuReplace.Enabled = false; + this.menuReplace.Index = 5; + this.menuReplace.Text = "Replace..."; + this.menuReplace.Visible = false; + this.menuReplace.Click += new System.EventHandler(this.menuReplace_Click); + // + // menuRename + // + this.menuRename.Enabled = false; + this.menuRename.Index = 6; + this.menuRename.Text = "Rename..."; + this.menuRename.Visible = false; + this.menuRename.Click += new System.EventHandler(this.fileBrowser1_OnRename); + // + // menuDelete + // + this.menuDelete.Enabled = false; + this.menuDelete.Index = 7; + this.menuDelete.Text = "Delete"; + this.menuDelete.Visible = false; + this.menuDelete.Click += new System.EventHandler(this.fileBrowser1_OnRemove); + // + // menuItem5 + // + this.menuItem5.Index = 1; + this.menuItem5.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItem6, + this.menuItem7}); + this.menuItem5.MergeOrder = 3; + this.menuItem5.MergeType = System.Windows.Forms.MenuMerge.MergeItems; + this.menuItem5.Text = "Tools"; + // + // menuItem6 + // + this.menuItem6.Index = 0; + this.menuItem6.Text = "-"; + // + // menuItem7 + // + this.menuItem7.Index = 1; + this.menuItem7.Text = "Export Directory Content..."; + this.menuItem7.Click += new System.EventHandler(this.menuItem7_Click); + // + // openFileDialog1 + // + this.openFileDialog1.FileName = "openFileDialog1"; + this.openFileDialog1.Filter = "All Files (*.*)|*.*"; + this.openFileDialog1.Title = "Import File"; + // + // folderBrowserDialog1 + // + this.folderBrowserDialog1.Description = "Select the directory to export the content of current directory to."; + // + // contextMenu1 + // + this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItem8, + this.menuItem9, + this.menuItem14, + this.menuItem10, + this.menuItem11}); + // + // menuItem8 + // + this.menuItem8.Index = 0; + this.menuItem8.Text = "Export..."; + this.menuItem8.Click += new System.EventHandler(this.menuExport_Click); + // + // menuItem9 + // + this.menuItem9.Index = 1; + this.menuItem9.Text = "-"; + this.menuItem9.Visible = false; + // + // menuItem14 + // + this.menuItem14.Index = 2; + this.menuItem14.Text = "Replace..."; + this.menuItem14.Visible = false; + this.menuItem14.Click += new System.EventHandler(this.menuReplace_Click); + // + // menuItem10 + // + this.menuItem10.Index = 3; + this.menuItem10.Text = "Rename..."; + this.menuItem10.Visible = false; + this.menuItem10.Click += new System.EventHandler(this.fileBrowser1_OnRename); + // + // menuItem11 + // + this.menuItem11.Index = 4; + this.menuItem11.Text = "Delete"; + this.menuItem11.Visible = false; + this.menuItem11.Click += new System.EventHandler(this.fileBrowser1_OnRemove); + // + // saveFileDialog1 + // + this.saveFileDialog1.Title = "Export..."; + // + // NDSViewer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(652, 338); + this.Controls.Add(this.fileBrowser1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Menu = this.mainMenu1; + this.Name = "NDSViewer"; + this.Text = "NARC Viewer"; + this.Load += new System.EventHandler(this.NARCViewer_Load); + this.ResumeLayout(false); + + } + + #endregion + + private LibEveryFileExplorer.UI.FileBrowser fileBrowser1; + private LibEveryFileExplorer.UI.MainMenu mainMenu1; + private System.Windows.Forms.MenuItem menuItem1; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.MenuItem menuItem2; + private System.Windows.Forms.MenuItem menuItem3; + private System.Windows.Forms.MenuItem menuItem4; + private System.Windows.Forms.MenuItem menuRename; + private System.Windows.Forms.MenuItem menuDelete; + private System.Windows.Forms.MenuItem menuItem5; + private System.Windows.Forms.MenuItem menuItem6; + private System.Windows.Forms.MenuItem menuItem7; + private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1; + private System.Windows.Forms.ContextMenu contextMenu1; + private System.Windows.Forms.MenuItem menuItem8; + private System.Windows.Forms.MenuItem menuItem9; + private System.Windows.Forms.MenuItem menuItem10; + private System.Windows.Forms.MenuItem menuItem11; + private System.Windows.Forms.MenuItem menuExport; + private System.Windows.Forms.MenuItem menuItem13; + private System.Windows.Forms.SaveFileDialog saveFileDialog1; + private System.Windows.Forms.MenuItem menuReplace; + private System.Windows.Forms.MenuItem menuItem14; + } +} \ No newline at end of file diff --git a/NDS/UI/NDSViewer.cs b/NDS/UI/NDSViewer.cs new file mode 100644 index 0000000..791f996 --- /dev/null +++ b/NDS/UI/NDSViewer.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using LibEveryFileExplorer.Files.SimpleFileSystem; +using LibEveryFileExplorer; +using LibEveryFileExplorer.Files; +using NDS.NitroSystem.FND; + +namespace NDS.UI +{ + public partial class NDSViewer : Form, IChildReactive + { + NDS Archive; + SFSDirectory Root; + public NDSViewer(NDS Archive) + { + this.Archive = Archive; + Root = Archive.ToFileSystem(); + InitializeComponent(); + } + + private void NARCViewer_Load(object sender, EventArgs e) + { + fileBrowser1.UpdateDirectories(Root.GetTreeNodes()); + } + + private void fileBrowser1_OnDirectoryChanged(string Path) + { + var d = Root.GetDirectoryByPath(Path); + fileBrowser1.UpdateContent(d.GetContent()); + } + + private void fileBrowser1_OnFileActivated(string Path) + { + var s = Root.GetFileByPath(Path); + EveryFileExplorerUtil.OpenFile(new EFESFSFile(s), ((ViewableFile)Tag).File); + } + + private void fileBrowser1_OnAddDirectory(object sender, EventArgs e) + { + /*var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedFolderPath); + if (dir == null) return; + String name = null; + retry: + name = Microsoft.VisualBasic.Interaction.InputBox("Please give the name of the new directory:", "New Directory", name); + if (name == null || name.Length == 0) return; + if (dir.IsValidName(name)) + { + SFSDirectory d = new SFSDirectory(name, false); + d.Parent = dir; + dir.SubDirectories.Add(d); + Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true); + } + else + { + MessageBox.Show("The name contains either one or more invalid chars, or is already in use!", "Invalid Name"); + goto retry; + }*/ + } + + private void fileBrowser1_OnAddFile(object sender, EventArgs e) + { + /*if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && openFileDialog1.FileName.Length > 0) + { + var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedFolderPath); + if (!dir.IsValidName(System.IO.Path.GetFileName(openFileDialog1.FileName))) + { + switch (MessageBox.Show("A file with the same name as the selected file exists. Do you want to replace this file?", "Replace", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) + { + case System.Windows.Forms.DialogResult.Yes: + var file = Root.GetFileByPath(fileBrowser1.SelectedFolderPath + "/" + System.IO.Path.GetFileName(openFileDialog1.FileName)); + file.Data = System.IO.File.ReadAllBytes(openFileDialog1.FileName); + break; + case System.Windows.Forms.DialogResult.No: + int nr = 0; + String NewName; + do + { + NewName = System.IO.Path.GetFileNameWithoutExtension(openFileDialog1.FileName) + "_" + nr++ + System.IO.Path.GetExtension(openFileDialog1.FileName); + } + while (!dir.IsValidName(NewName)); + SFSFile f = new SFSFile(-1, NewName, dir); + f.Data = System.IO.File.ReadAllBytes(openFileDialog1.FileName); + dir.Files.Add(f); + break; + } + } + else + { + SFSFile f = new SFSFile(-1, System.IO.Path.GetFileName(openFileDialog1.FileName), dir); + f.Data = System.IO.File.ReadAllBytes(openFileDialog1.FileName); + dir.Files.Add(f); + } + Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true); + }*/ + } + + private void fileBrowser1_OnRemove(object sender, EventArgs e) + { + /*if (fileBrowser1.SelectedFolderPath == fileBrowser1.SelectedPath) return; + var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedPath); + if (dir != null) + { + if (MessageBox.Show("Are you sure you permanently want to delete this directory: " + dir.DirectoryName + ", and all of it's files and subfolders?", "Removal", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.No) return; + dir.Parent.SubDirectories.Remove(dir); + Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true); + } + else + { + var file = Root.GetFileByPath(fileBrowser1.SelectedPath); + if (MessageBox.Show("Are you sure you permanently want to delete this file: " + file.FileName + "?", "Removal", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.No) return; + file.Parent.Files.Remove(file); + Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true); + }*/ + } + + private void fileBrowser1_OnRename(object sender, EventArgs e) + { + /*if (fileBrowser1.SelectedFolderPath == fileBrowser1.SelectedPath) return; + var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedPath); + if (dir != null) + { + String name = dir.DirectoryName; + retryd: + name = Microsoft.VisualBasic.Interaction.InputBox("Please give the new name for this directory:", "Rename", name); + if (name == null || name.Length == 0) return; + if (dir.Parent.IsValidName(name)) + { + String oldpath = dir.ToString(); + dir.DirectoryName = name; + String newpath = dir.ToString(); + Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true, oldpath.Remove(oldpath.Length - 1), newpath.Remove(newpath.Length - 1)); + } + else + { + MessageBox.Show("The name contains either one or more invalid chars, or is already in use!", "Invalid Name"); + goto retryd; + } + } + else//file + { + var file = Root.GetFileByPath(fileBrowser1.SelectedPath); + String name = file.FileName; + retryf: + name = Microsoft.VisualBasic.Interaction.InputBox("Please give the new name for this file:", "Rename", name); + if (name == null || name.Length == 0) return; + if (file.Parent.IsValidName(name)) + { + file.FileName = name; + Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true); + } + else + { + MessageBox.Show("The name contains either one or more invalid chars, or is already in use!", "Invalid Name"); + goto retryf; + } + }*/ + } + + private void fileBrowser1_OnSelectionChanged(object sender, EventArgs e) + { + fileBrowser1.RenameEnabled = fileBrowser1.DeleteEnabled = menuRename.Enabled = menuDelete.Enabled = !(fileBrowser1.SelectedPath == fileBrowser1.SelectedFolderPath); + if (Root.GetDirectoryByPath(fileBrowser1.SelectedPath) == null) menuExport.Enabled = menuReplace.Enabled = true; + else menuExport.Enabled = menuReplace.Enabled = false; + } + + private void menuItem7_Click(object sender, EventArgs e) + { + var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedFolderPath); + if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && folderBrowserDialog1.SelectedPath.Length > 0) + { + dir.Export(folderBrowserDialog1.SelectedPath); + } + } + + private void fileBrowser1_OnRightClick(Point Location) + { + var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedPath); + if (dir != null) + { + + } + else + { + //var file = Root.GetFileByPath(fileBrowser1.SelectedPath); + contextMenu1.Show(fileBrowser1, Location); + } + } + + private void menuExport_Click(object sender, EventArgs e) + { + var file = Root.GetFileByPath(fileBrowser1.SelectedPath); + if (file == null) return; + saveFileDialog1.Filter = System.IO.Path.GetExtension(fileBrowser1.SelectedPath).Replace(".", "").ToUpper() + " Files (*" + System.IO.Path.GetExtension(fileBrowser1.SelectedPath).ToLower() + ")|*" + System.IO.Path.GetExtension(fileBrowser1.SelectedPath).ToLower() + "|All Files (*.*)|*.*"; + saveFileDialog1.FileName = System.IO.Path.GetFileName(fileBrowser1.SelectedPath); + if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && saveFileDialog1.FileName.Length > 0) + { + System.IO.File.Create(saveFileDialog1.FileName).Close(); + System.IO.File.WriteAllBytes(saveFileDialog1.FileName, file.Data); + } + } + + private void menuReplace_Click(object sender, EventArgs e) + { + /*if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK + && openFileDialog1.FileName.Length > 0) + { + var file = Root.GetFileByPath(fileBrowser1.SelectedPath); + file.Data = System.IO.File.ReadAllBytes(openFileDialog1.FileName); + Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true); + }*/ + } + + public void OnChildSave(ViewableFile File) + { + /*Archive.FromFileSystem(Root); + fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true); + */ + } + } +} diff --git a/NDS/UI/NDSViewer.resx b/NDS/UI/NDSViewer.resx new file mode 100644 index 0000000..74b5665 --- /dev/null +++ b/NDS/UI/NDSViewer.resx @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 134, 17 + + + 274, 17 + + + 443, 17 + + + 573, 17 + + + + + AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAADwAAABcAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAA + ABoAAAAXAAAADwAAAB4BM2aeAUSHxQFEh8UBRIfFAUSHxQFEh8UBRIfFAUSHxQFEh8UBRIfFAUSHxQFE + h8UBRIfFATNmngAAAB4AAAAAAUqUuHuu4P96rd//eq3f/3qt3/96rd//eq3f/3qt3/96rd//eq3f/3qt + 3/96rd//e67g/wFKlLgAAAAAAAAAAAJRoKuBtOT/fbDh/32w4f99sOH/fbDh/2yf0P9ajb//Wo2//1qN + v/9ajb//Wo2//3Cj0/8CUaCrAAAAAAAAAAACVKSmiLvq/4K15f+CteX/grXl/4K15f9jlsf/4uLR/+Li + 0f/i4tH/4uLR/+Li0f9pnMv/AlSkpgAAAAAAAAAAA1aoo4/C7v+Huun/h7rp/4e66f+Huun/cKPT/+zs + 2/+6uqn/0NC//83NvP/s7Nv/eKvY/wNWqKMAAAAAAAAAAANYrJ+WyfL/jL/s/4y/7P+Mv+z/RHeq/0J1 + qP/19eT/9fXk//X15P/19eT/9fXk/4i75f8DWKyfAAAAAAAAAAADWrCbm872/5HE8P+RxPD/kcTw/1WI + u/9Uh7r//8tD//zFPf/4vTX/87Ut//CuJv+WyfL/A1qwmwAAAAAAAAAAA1uzmJ/S+f+VyPP/lcjz/5XI + 8/9ViLv/VYi7/1WIu/9NgLP/lcjz/5XI8/+VyPP/n9L5/wNbs5gAAAAAAAAAAANdtpWn2/79qt3//6rd + //+q3f//d6rd/3eq3f93qt3/ZpnM/6rd//+q3f//qt3//6fb/v0DXbaVAAAAAAAAAAAEX7lta6bf4ICz + 5v+As+b/gLPm/06BtP9OgbT/ToG0/0h7rv+As+b/gLPm/4Cz5v9rpt/gBF+5bQAAAAAAAAAABGC8R02U + 2cSJvO//iLvu/4i77v9BdKf/QXSn/0F0p/8+caT/iLvu/4i77v+JvO//TZTZxARgvEcAAAAAAAAAAARh + viMqfMylibzv/4i77v+Iu+7/NWib/zVom/81aJv/NWib/4i77v+Iu+7/ibzv/yp8zKUEYb4jAAAAAAAA + AAAEYr8EBGLAaARiwIsEYsCLBGLAiwBAgMwAQIDMAECAzABAgMwEYsCLBGLAiwRiwIsEYsBoBGK/BAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA//8AAAAAAAAAAAAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB + AACAAQAA//8AAA== + + + \ No newline at end of file