diff --git a/BizHawk.Client.Common/FirmwareManager.cs b/BizHawk.Client.Common/FirmwareManager.cs index 91769d02ea..f6bbbe3abf 100644 --- a/BizHawk.Client.Common/FirmwareManager.cs +++ b/BizHawk.Client.Common/FirmwareManager.cs @@ -126,7 +126,37 @@ namespace BizHawk.Client.Common public Dictionary Dict { get; } = new Dictionary(); } - public void DoScanAndResolve() + /// + /// Test to determine whether the supplied firmware file matches something in the firmware database + /// + /// + /// + public bool CanFileBeImported(string f) + { + try + { + var fi = new FileInfo(f); + if (!fi.Exists) + return false; + + // weed out filesizes first to reduce the unnecessary overhead of a hashing operation + if (FirmwareDatabase.FirmwareFiles.Where(a => a.Size == fi.Length).FirstOrDefault() == null) + return false; + + // check the hash + using (var reader = new RealFirmwareReader()) + { + reader.Read(fi); + if (FirmwareDatabase.FirmwareFiles.Where(a => a.Hash == reader.Dict.FirstOrDefault().Value.Hash).FirstOrDefault() != null) + return true; + } + } + catch { } + + return false; + } + + public void DoScanAndResolve() { // build a list of file sizes. Only those will be checked during scanning HashSet sizes = new HashSet(); diff --git a/BizHawk.Client.EmuHawk/config/FirmwaresConfig.Designer.cs b/BizHawk.Client.EmuHawk/config/FirmwaresConfig.Designer.cs index edc5e1384e..ee81cbecb3 100644 --- a/BizHawk.Client.EmuHawk/config/FirmwaresConfig.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/FirmwaresConfig.Designer.cs @@ -55,6 +55,7 @@ this.tbbClose = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.tbbCloseReload = new System.Windows.Forms.ToolStripButton(); + this.tbbOpenFolder = new System.Windows.Forms.ToolStripButton(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.panel2 = new System.Windows.Forms.Panel(); this.linkBasePath = new System.Windows.Forms.LinkLabel(); @@ -201,7 +202,8 @@ this.tbbImport, this.tbbClose, this.toolStripSeparator1, - this.tbbCloseReload}); + this.tbbCloseReload, + this.tbbOpenFolder}); this.toolStrip1.Location = new System.Drawing.Point(0, 0); this.toolStrip1.Name = "toolStrip1"; this.toolStrip1.Size = new System.Drawing.Size(824, 25); @@ -289,6 +291,16 @@ this.tbbCloseReload.Visible = false; this.tbbCloseReload.Click += new System.EventHandler(this.tbbCloseReload_Click); // + // tbbOpenFolder + // + this.tbbOpenFolder.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.tbbOpenFolder.Image = ((System.Drawing.Image)(resources.GetObject("tbbOpenFolder.Image"))); + this.tbbOpenFolder.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tbbOpenFolder.Name = "tbbOpenFolder"; + this.tbbOpenFolder.Size = new System.Drawing.Size(128, 22); + this.tbbOpenFolder.Text = "Open Firmware Folder"; + this.tbbOpenFolder.Click += new System.EventHandler(this.tbbOpenFolder_Click); + // // tableLayoutPanel1 // this.tableLayoutPanel1.ColumnCount = 1; @@ -345,7 +357,7 @@ this.label2.Location = new System.Drawing.Point(5, 5); this.label2.Margin = new System.Windows.Forms.Padding(5, 5, 3, 0); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(383, 13); + this.label2.Size = new System.Drawing.Size(395, 13); this.label2.TabIndex = 27; this.label2.Text = "Firmware such as BIOS files are copyrighted material and not provided by BizHawk"; // @@ -407,5 +419,6 @@ private System.Windows.Forms.ToolStripButton tbbCloseReload; private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; private System.Windows.Forms.Label label2; - } + private System.Windows.Forms.ToolStripButton tbbOpenFolder; + } } \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs b/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs index 379f4540ee..d7a062cc1e 100644 --- a/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs +++ b/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs @@ -58,6 +58,8 @@ namespace BizHawk.Client.EmuHawk public string TargetSystem = null; + private CheckBox cbAllowImport; + private const int idUnsure = 0; private const int idMissing = 1; private const int idOk = 2; @@ -179,6 +181,16 @@ namespace BizHawk.Client.EmuHawk } RefreshBasePath(); + + cbAllowImport = new CheckBox(); + cbAllowImport.Text = "Allow Importing of Unknown Files"; + cbAllowImport.BackColor = Color.Transparent; + cbAllowImport.CheckAlign = ContentAlignment.MiddleLeft; + cbAllowImport.TextAlign = ContentAlignment.MiddleLeft; + cbAllowImport.Font = new Font("Segeo UI", 9, FontStyle.Regular, GraphicsUnit.Point, 1, false); + cbAllowImport.Checked = false; + ToolStripControlHost host = new ToolStripControlHost(cbAllowImport); + toolStrip1.Items.Add(host); } @@ -342,7 +354,13 @@ namespace BizHawk.Client.EmuHawk DoScan(); } - private void lvFirmwares_KeyDown(object sender, KeyEventArgs e) + private void tbbOpenFolder_Click(object sender, EventArgs e) + { + var frmWares = PathManager.MakeAbsolutePath(Global.Config.PathEntries.FirmwaresPathFragment, null); + System.Diagnostics.Process.Start(frmWares); + } + + private void lvFirmwares_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.C && e.Control && !e.Alt && !e.Shift) { @@ -368,20 +386,81 @@ namespace BizHawk.Client.EmuHawk { ofd.InitialDirectory = currSelectorDir; ofd.RestoreDirectory = true; + string frmwarePath = PathManager.MakeAbsolutePath(Global.Config.PathEntries.FirmwaresPathFragment, null); - if (ofd.ShowDialog() == DialogResult.OK) + if (ofd.ShowDialog() == DialogResult.OK) { // remember the location we selected this firmware from, maybe there are others currSelectorDir = Path.GetDirectoryName(ofd.FileName); - // for each selected item, set the user choice (even though multiple selection for this operation is no longer allowed) - foreach (ListViewItem lvi in lvFirmwares.SelectedItems) - { - var fr = lvi.Tag as FirmwareDatabase.FirmwareRecord; - Global.Config.FirmwareUserSpecifications[fr.ConfigKey] = ofd.FileName; - } + try + { + using (var hf = new HawkFile(ofd.FileName)) + { + // for each selected item, set the user choice (even though multiple selection for this operation is no longer allowed) + foreach (ListViewItem lvi in lvFirmwares.SelectedItems) + { + var fr = lvi.Tag as FirmwareDatabase.FirmwareRecord; + string filePath = ofd.FileName; - DoScan(); + // if the selected file is an archive, allow the user to pick the inside file + // to always be copied to the global firmwares directory + if (hf.IsArchive) + { + var ac = new ArchiveChooser(new HawkFile(filePath)); + int memIdx = -1; + + if (ac.ShowDialog(this) == DialogResult.OK) + { + memIdx = ac.SelectedMemberIndex; + } + else + { + return; + } + + var insideFile = hf.BindArchiveMember(memIdx); + var fileData = insideFile.ReadAllBytes(); + + // write to file in the firmwares folder + File.WriteAllBytes(Path.Combine(frmwarePath, insideFile.Name), fileData); + filePath = Path.Combine(frmwarePath, insideFile.Name); + } + else + { + // selected file is not an archive + // check whether this file is currently outside of the global firmware directory + if (currSelectorDir != frmwarePath) + { + var askMoveResult = MessageBox.Show(this, "The selected custom firmware does not reside in the root of the global firmware directory.\nDo you want to copy it there?", "Import Custom Firmware", MessageBoxButtons.YesNo); + if (askMoveResult == DialogResult.Yes) + { + try + { + FileInfo fi = new FileInfo(filePath); + filePath = Path.Combine(frmwarePath, fi.Name); + File.Copy(ofd.FileName, filePath); + } + catch (Exception ex) + { + MessageBox.Show(this, "There was an issue copying the file. The customization has NOT been set.\n\n" + ex.StackTrace); + continue; + } + } + } + } + + Global.Config.FirmwareUserSpecifications[fr.ConfigKey] = filePath; + } + } + } + catch (Exception ex) + { + MessageBox.Show(this, "There was an issue during the process. The customization has NOT been set.\n\n" + ex.StackTrace); + return; + } + + DoScan(); } } } @@ -585,7 +664,11 @@ namespace BizHawk.Client.EmuHawk outfile = Path.Combine(extractpath, myname); File.WriteAllBytes(outfile, ms.ToArray()); hf.Unbind(); - didSomething |= RunImportJobSingle(basepath, outfile, ref errors); + + if (cbAllowImport.Checked || Manager.CanFileBeImported(outfile)) + { + didSomething |= RunImportJobSingle(basepath, outfile, ref errors); + } } } finally @@ -595,7 +678,10 @@ namespace BizHawk.Client.EmuHawk } else { - didSomething |= RunImportJobSingle(basepath, f, ref errors); + if (cbAllowImport.Checked || Manager.CanFileBeImported(hf.CanonicalFullPath)) + { + didSomething |= RunImportJobSingle(basepath, f, ref errors); + } } } } @@ -622,7 +708,7 @@ namespace BizHawk.Client.EmuHawk return base.ProcessCmdKey(ref msg, keyData); } - private void lvFirmwares_DragEnter(object sender, DragEventArgs e) + private void lvFirmwares_DragEnter(object sender, DragEventArgs e) { e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None; } diff --git a/BizHawk.Client.EmuHawk/config/FirmwaresConfig.resx b/BizHawk.Client.EmuHawk/config/FirmwaresConfig.resx index 7345957162..18c3d121ad 100644 --- a/BizHawk.Client.EmuHawk/config/FirmwaresConfig.resx +++ b/BizHawk.Client.EmuHawk/config/FirmwaresConfig.resx @@ -215,6 +215,21 @@ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg==