2013-07-31 15:54:08 +00:00
using System ;
2013-08-03 19:34:51 +00:00
using System.Collections ;
2013-07-31 15:54:08 +00:00
using System.Collections.Generic ;
using System.ComponentModel ;
using System.Drawing ;
using System.IO ;
using System.Linq ;
using System.Windows.Forms ;
2014-10-26 14:22:26 +00:00
using BizHawk.Common ;
2013-10-25 00:57:23 +00:00
using BizHawk.Client.Common ;
2013-11-04 01:06:36 +00:00
using BizHawk.Emulation.Common ;
2014-07-27 15:22:30 +00:00
using BizHawk.Client.EmuHawk.WinFormExtensions ;
2013-10-25 00:57:23 +00:00
2017-05-31 15:28:06 +00:00
// notes: eventually, we intend to have a "firmware acquisition interface" exposed to the emulator cores.
// it will be implemented by emuhawk, and use firmware keys to fetch the firmware content.
// however, for now, the cores are using strings from the config class. so we have the `configMember` which is
// used by reflection to set the configuration for firmwares which were found
2013-08-02 03:43:58 +00:00
2017-05-31 15:28:06 +00:00
// TODO - we may eventually need to add a progress dialog for this. we should have one for other reasons.
// I started making one in Bizhawk.Util as QuickProgressPopup but ran out of time
2013-08-02 03:43:58 +00:00
2017-05-31 15:28:06 +00:00
// IDEA: show current path in tooltip (esp. for custom resolved)
// IDEA: prepop set customization to dir of current custom
2013-08-10 01:17:06 +00:00
2017-05-31 15:28:06 +00:00
// TODO - display some kind if [!] if you have a user-specified file which is known but defined as incompatible by the firmware DB
2013-11-03 03:54:37 +00:00
namespace BizHawk.Client.EmuHawk
2013-07-31 15:54:08 +00:00
{
2013-08-02 03:43:58 +00:00
public partial class FirmwaresConfig : Form
{
2017-05-31 15:28:06 +00:00
// friendlier names than the system Ids
2017-07-12 02:13:36 +00:00
// Redundant with SystemLookup? Not so fast. That datadrives things. This is one step abstracted. Don't be such a smart guy. Keep this redundant list up to date.
2017-05-31 15:28:06 +00:00
private static readonly Dictionary < string , string > SystemGroupNames = new Dictionary < string , string >
{
{ "NES" , "NES" } ,
{ "SNES" , "SNES" } ,
{ "PCECD" , "PCE-CD" } ,
{ "SAT" , "Saturn" } ,
{ "A78" , "Atari 7800" } ,
{ "Coleco" , "Colecovision" } ,
{ "GBA" , "GBA" } ,
{ "TI83" , "TI-83" } ,
{ "INTV" , "Intellivision" } ,
{ "C64" , "C64" } ,
{ "GEN" , "Genesis" } ,
{ "SMS" , "Sega Master System" } ,
2017-07-12 02:13:36 +00:00
{ "PSX" , "PlayStation" } ,
{ "Lynx" , "Lynx" } ,
{ "AppleII" , "Apple II" } ,
{ "O2" , "Odyssey 2" } ,
{ "GB" , "Game Boy" } ,
{ "GBC" , "Game Boy Color" } ,
{ "PCFX" , "PC-FX" } ,
{ "32X" , "32X" } ,
2019-11-04 01:55:38 +00:00
{ "ZXSpectrum" , "ZX Spectrum" } ,
{ "AmstradCPC" , "Amstrad CPC" } ,
2019-08-03 13:26:30 +00:00
{ "ChannelF" , "Channel F" } ,
{ "Vectrex" , "Vectrex" }
} ;
2013-08-02 03:43:58 +00:00
2013-08-11 19:05:05 +00:00
public string TargetSystem = null ;
2013-08-10 01:17:06 +00:00
2018-09-21 16:44:17 +00:00
private CheckBox cbAllowImport ;
2013-08-02 03:51:33 +00:00
private const int idUnsure = 0 ;
private const int idMissing = 1 ;
private const int idOk = 2 ;
2017-05-31 15:28:06 +00:00
private Font fixedFont , boldFont , boldFixedFont ;
2013-08-03 19:34:51 +00:00
2017-05-31 15:28:06 +00:00
private class ListViewSorter : IComparer
2013-08-03 19:34:51 +00:00
{
public FirmwaresConfig dialog ;
public int column ;
public int sign ;
public ListViewSorter ( FirmwaresConfig dialog , int column )
{
this . dialog = dialog ;
this . column = column ;
}
public int Compare ( object a , object b )
{
var lva = ( ListViewItem ) a ;
var lvb = ( ListViewItem ) b ;
2013-08-10 01:17:06 +00:00
return sign * string . Compare ( lva . SubItems [ column ] . Text , lvb . SubItems [ column ] . Text ) ;
2013-08-03 19:34:51 +00:00
}
}
2017-05-31 15:28:06 +00:00
private string currSelectorDir ;
private readonly ListViewSorter listviewSorter ;
2013-08-03 19:34:51 +00:00
2015-07-15 06:31:03 +00:00
public FirmwaresConfig ( bool retryLoadRom = false , string reloadRomPath = null )
2013-08-02 03:43:58 +00:00
{
InitializeComponent ( ) ;
2017-05-31 15:28:06 +00:00
// prep imagelist for listview with 3 item states for {idUnsure, idMissing, idOk}
2014-06-29 02:28:48 +00:00
imageList1 . Images . AddRange ( new [ ] { Properties . Resources . RetroQuestion , Properties . Resources . ExclamationRed , Properties . Resources . GreenCheck } ) ;
2013-08-03 19:34:51 +00:00
listviewSorter = new ListViewSorter ( this , - 1 ) ;
2015-07-12 19:30:26 +00:00
if ( retryLoadRom )
{
toolStripSeparator1 . Visible = true ;
tbbCloseReload . Visible = true ;
tbbCloseReload . Enabled = true ;
2015-07-15 06:31:03 +00:00
if ( string . IsNullOrWhiteSpace ( reloadRomPath ) )
{
tbbCloseReload . ToolTipText = "Close Firmware Manager and reload ROM" ;
}
else
{
2019-03-18 14:06:37 +00:00
tbbCloseReload . ToolTipText = $"Close Firmware Manager and reload {reloadRomPath}" ;
2015-07-15 06:31:03 +00:00
}
2015-07-12 19:30:26 +00:00
}
2013-08-02 03:43:58 +00:00
}
2013-08-10 01:17:06 +00:00
2017-05-31 15:28:06 +00:00
// makes sure that the specified SystemId is selected in the list (and that all the firmwares for it are visible)
2013-08-11 19:05:05 +00:00
private void WarpToSystemId ( string sysid )
2013-08-11 15:48:47 +00:00
{
bool selectedFirst = false ;
foreach ( ListViewItem lvi in lvFirmwares . Items )
{
if ( lvi . SubItems [ 1 ] . Text = = sysid )
{
if ( ! selectedFirst ) lvi . Selected = true ;
lvi . EnsureVisible ( ) ;
selectedFirst = true ;
}
}
}
2013-08-02 03:43:58 +00:00
private void FirmwaresConfig_Load ( object sender , EventArgs e )
{
2017-05-31 15:28:06 +00:00
// we'll use this font for displaying the hash, so they dont look all jagged in a long list
2013-08-02 03:43:58 +00:00
fixedFont = new Font ( new FontFamily ( "Courier New" ) , 8 ) ;
2013-08-10 01:17:06 +00:00
boldFont = new Font ( lvFirmwares . Font , FontStyle . Bold ) ;
boldFixedFont = new Font ( fixedFont , FontStyle . Bold ) ;
2013-08-02 03:43:58 +00:00
2017-05-31 15:28:06 +00:00
// populate listview from firmware DB
2013-08-02 03:43:58 +00:00
var groups = new Dictionary < string , ListViewGroup > ( ) ;
2013-08-10 01:17:06 +00:00
foreach ( var fr in FirmwareDatabase . FirmwareRecords )
2013-08-02 03:43:58 +00:00
{
var lvi = new ListViewItem ( ) ;
2013-08-10 01:17:06 +00:00
lvi . Tag = fr ;
2013-08-02 03:43:58 +00:00
lvi . UseItemStyleForSubItems = false ;
lvi . ImageIndex = idUnsure ;
2014-12-04 00:37:06 +00:00
lvi . ToolTipText = null ;
2017-04-27 15:55:22 +00:00
lvi . SubItems . Add ( fr . SystemId ) ;
lvi . SubItems . Add ( fr . FirmwareId ) ;
lvi . SubItems . Add ( fr . Descr ) ;
2017-05-31 15:28:06 +00:00
lvi . SubItems . Add ( "" ) ; // resolved with
lvi . SubItems . Add ( "" ) ; // location
lvi . SubItems . Add ( "" ) ; // size
lvi . SubItems . Add ( "" ) ; // hash
lvi . SubItems [ 6 ] . Font = fixedFont ; // would be used for hash and size
lvi . SubItems [ 7 ] . Font = fixedFont ; // would be used for hash and size
2013-08-02 03:43:58 +00:00
lvFirmwares . Items . Add ( lvi ) ;
2013-08-02 03:51:33 +00:00
2017-05-31 15:28:06 +00:00
// build the groups in the listview as we go:
2017-04-27 15:55:22 +00:00
if ( ! groups . ContainsKey ( fr . SystemId ) )
2013-08-02 03:43:58 +00:00
{
2013-12-16 19:00:05 +00:00
string name ;
2017-04-27 15:55:22 +00:00
if ( ! SystemGroupNames . TryGetValue ( fr . SystemId , out name ) )
2013-12-16 19:00:05 +00:00
name = "FIX ME (FirmwaresConfig.cs)" ;
2017-04-27 15:55:22 +00:00
lvFirmwares . Groups . Add ( fr . SystemId , name ) ;
2013-08-02 03:43:58 +00:00
var lvg = lvFirmwares . Groups [ lvFirmwares . Groups . Count - 1 ] ;
2017-04-27 15:55:22 +00:00
groups [ fr . SystemId ] = lvg ;
2013-08-02 03:43:58 +00:00
}
2017-04-27 15:55:22 +00:00
lvi . Group = groups [ fr . SystemId ] ;
2013-08-02 03:43:58 +00:00
}
2017-05-31 15:28:06 +00:00
// now that we have some items in the listview, we can size some columns to sensible widths
2013-08-02 03:51:33 +00:00
lvFirmwares . AutoResizeColumn ( 1 , ColumnHeaderAutoResizeStyle . ColumnContent ) ;
2013-08-02 03:43:58 +00:00
lvFirmwares . AutoResizeColumn ( 2 , ColumnHeaderAutoResizeStyle . ColumnContent ) ;
2013-08-10 01:28:51 +00:00
lvFirmwares . AutoResizeColumn ( 3 , ColumnHeaderAutoResizeStyle . ColumnContent ) ;
2013-08-02 03:43:58 +00:00
2013-08-11 19:05:05 +00:00
if ( TargetSystem ! = null )
{
WarpToSystemId ( TargetSystem ) ;
}
2013-12-19 16:59:23 +00:00
RefreshBasePath ( ) ;
2018-09-21 16:44:17 +00:00
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 ) ;
2018-09-21 16:45:23 +00:00
cbAllowImport . Checked = false ;
2018-09-21 16:44:17 +00:00
ToolStripControlHost host = new ToolStripControlHost ( cbAllowImport ) ;
2018-09-21 17:06:26 +00:00
toolStrip1 . Items . Add ( host ) ;
2013-08-02 03:43:58 +00:00
}
2015-07-12 19:30:26 +00:00
private void tbbClose_Click ( object sender , EventArgs e )
{
this . Close ( ) ;
DialogResult = DialogResult . Cancel ;
}
private void tbbCloseReload_Click ( object sender , EventArgs e )
{
this . Close ( ) ;
DialogResult = DialogResult . Retry ;
}
2013-08-02 03:43:58 +00:00
private void FirmwaresConfig_FormClosed ( object sender , FormClosedEventArgs e )
{
fixedFont . Dispose ( ) ;
2013-08-10 01:17:06 +00:00
boldFont . Dispose ( ) ;
boldFixedFont . Dispose ( ) ;
2013-08-02 03:43:58 +00:00
}
2013-08-02 03:51:33 +00:00
private void tbbGroup_Click ( object sender , EventArgs e )
{
2017-05-31 15:28:06 +00:00
// toggle the grouping state
2013-08-02 03:51:33 +00:00
lvFirmwares . ShowGroups = ! lvFirmwares . ShowGroups ;
}
private void lvFirmwares_ColumnClick ( object sender , ColumnClickEventArgs e )
2013-08-02 03:43:58 +00:00
{
2013-08-03 19:34:51 +00:00
if ( listviewSorter . column ! = e . Column )
{
listviewSorter . column = e . Column ;
listviewSorter . sign = 1 ;
}
else listviewSorter . sign * = - 1 ;
lvFirmwares . ListViewItemSorter = listviewSorter ;
lvFirmwares . SetSortIcon ( e . Column , listviewSorter . sign = = 1 ? SortOrder . Descending : SortOrder . Ascending ) ;
lvFirmwares . Sort ( ) ;
2013-08-02 03:43:58 +00:00
}
2013-08-02 03:51:33 +00:00
private void tbbScan_Click ( object sender , EventArgs e )
{
2017-05-31 15:28:06 +00:00
// user-initiated scan
2013-08-02 03:51:33 +00:00
DoScan ( ) ;
}
2013-08-02 03:43:58 +00:00
2017-05-31 15:28:06 +00:00
private FirmwareManager Manager = > Global . FirmwareManager ;
2013-08-02 03:43:58 +00:00
private void DoScan ( )
{
2013-08-10 01:17:06 +00:00
lvFirmwares . BeginUpdate ( ) ;
Manager . DoScanAndResolve ( ) ;
2017-05-31 15:28:06 +00:00
// for each type of firmware, try resolving and record the result
2013-08-10 01:17:06 +00:00
foreach ( ListViewItem lvi in lvFirmwares . Items )
2013-08-02 03:43:58 +00:00
{
2013-08-10 01:17:06 +00:00
var fr = lvi . Tag as FirmwareDatabase . FirmwareRecord ;
2014-11-12 00:04:08 +00:00
var ri = Manager . Resolve ( fr , true ) ;
2014-11-13 00:09:16 +00:00
for ( int i = 4 ; i < = 7 ; i + + )
2013-08-10 01:17:06 +00:00
lvi . SubItems [ i ] . Text = "" ;
if ( ri = = null )
2013-08-02 03:43:58 +00:00
{
2013-08-10 01:17:06 +00:00
lvi . ImageIndex = idMissing ;
2017-07-12 02:05:14 +00:00
lvi . ToolTipText = "No file bound for this firmware!" ;
2013-08-02 03:43:58 +00:00
}
2013-08-10 01:17:06 +00:00
else
{
2017-05-31 15:28:06 +00:00
// lazy substring extraction. really should do a better job
2013-12-13 05:20:50 +00:00
var basePath = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . FirmwaresPathFragment , null ) + Path . DirectorySeparatorChar ;
2013-08-10 01:17:06 +00:00
var path = ri . FilePath . Replace ( basePath , "" ) ;
2013-08-02 03:43:58 +00:00
2017-05-31 15:28:06 +00:00
// bolden the item if the user has specified a path for it
2013-08-10 01:17:06 +00:00
bool bolden = ri . UserSpecified ;
2013-08-02 03:51:33 +00:00
2017-05-31 15:28:06 +00:00
// set columns based on whether it was a known file
2013-08-10 01:17:06 +00:00
if ( ri . KnownFirmwareFile = = null )
2013-08-02 03:43:58 +00:00
{
2013-08-10 01:17:06 +00:00
lvi . ImageIndex = idUnsure ;
2017-07-12 02:05:14 +00:00
lvi . ToolTipText = "You've bound a custom choice here. Hope you know what you're doing." ;
2013-08-10 01:17:06 +00:00
lvi . SubItems [ 4 ] . Text = "-custom-" ;
}
else
{
lvi . ImageIndex = idOk ;
2017-07-12 02:05:14 +00:00
lvi . ToolTipText = "Good! This file has been bound to some kind of a decent choice" ;
2017-04-27 15:55:22 +00:00
lvi . SubItems [ 4 ] . Text = ri . KnownFirmwareFile . Description ;
2013-08-02 03:43:58 +00:00
}
2017-05-31 15:28:06 +00:00
// bolden the item if necessary
2013-08-10 01:17:06 +00:00
if ( bolden )
{
foreach ( ListViewItem . ListViewSubItem lvsi in lvi . SubItems ) lvsi . Font = boldFont ;
lvi . SubItems [ 6 ] . Font = boldFixedFont ;
}
else
{
foreach ( ListViewItem . ListViewSubItem lvsi in lvi . SubItems ) lvsi . Font = lvFirmwares . Font ;
lvi . SubItems [ 6 ] . Font = fixedFont ;
}
2013-08-02 03:43:58 +00:00
2017-05-31 15:28:06 +00:00
// if the user specified a file but its missing, mark it as such
2014-12-04 00:37:06 +00:00
if ( ri . Missing )
{
2013-08-10 01:17:06 +00:00
lvi . ImageIndex = idMissing ;
2017-07-12 02:05:14 +00:00
lvi . ToolTipText = "The file that's specified is missing!" ;
2014-12-04 00:37:06 +00:00
}
2013-08-02 03:43:58 +00:00
2017-05-31 15:28:06 +00:00
// if the user specified a known firmware file but its for some other firmware, it was probably a mistake. mark it as suspicious
2013-08-10 01:17:06 +00:00
if ( ri . KnownMismatching )
2017-07-12 02:05:14 +00:00
{
2013-08-10 01:17:06 +00:00
lvi . ImageIndex = idUnsure ;
2017-07-12 02:05:14 +00:00
lvi . ToolTipText = "You've manually specified a firmware file, and we're sure it's wrong. Hope you know what you're doing." ;
}
2013-08-02 03:43:58 +00:00
2013-08-10 01:17:06 +00:00
lvi . SubItems [ 5 ] . Text = path ;
2014-11-13 00:09:16 +00:00
lvi . SubItems [ 6 ] . Text = ri . Size . ToString ( ) ;
2019-03-18 14:06:37 +00:00
if ( ri . Hash ! = null ) lvi . SubItems [ 7 ] . Text = $"sha1:{ri.Hash}" ;
2014-11-13 00:09:16 +00:00
else lvi . SubItems [ 7 ] . Text = "" ;
2013-08-10 01:17:06 +00:00
}
2013-08-02 03:43:58 +00:00
}
2013-08-10 01:17:06 +00:00
lvFirmwares . EndUpdate ( ) ;
2013-08-02 03:43:58 +00:00
}
private void tbbOrganize_Click ( object sender , EventArgs e )
{
2014-06-29 02:28:48 +00:00
if ( MessageBox . Show ( this , "This is going to move/rename every automatically-selected firmware file under your configured firmwares directory to match our recommended organizational scheme (which is not super great right now). Proceed?" , "Firmwares Organization Confirm" , MessageBoxButtons . OKCancel ) = = DialogResult . Cancel )
2017-05-31 15:28:06 +00:00
{
return ;
}
2013-08-10 01:17:06 +00:00
Manager . DoScanAndResolve ( ) ;
2013-08-02 03:43:58 +00:00
2013-08-10 01:17:06 +00:00
foreach ( var fr in FirmwareDatabase . FirmwareRecords )
2013-08-02 03:43:58 +00:00
{
2013-08-10 01:17:06 +00:00
var ri = Manager . Resolve ( fr ) ;
2014-08-03 22:38:27 +00:00
if ( ri = = null ) continue ;
2013-08-10 01:17:06 +00:00
if ( ri . KnownFirmwareFile = = null ) continue ;
if ( ri . UserSpecified ) continue ;
2017-04-27 15:55:22 +00:00
string fpTarget = PathManager . StandardFirmwareName ( ri . KnownFirmwareFile . RecommendedName ) ;
2013-08-10 01:17:06 +00:00
string fpSource = ri . FilePath ;
2013-08-02 03:43:58 +00:00
try
{
2013-08-10 01:17:06 +00:00
File . Move ( fpSource , fpTarget ) ;
2013-08-02 03:43:58 +00:00
}
catch
{
2017-05-31 15:28:06 +00:00
// sometimes moves fail. especially in newer versions of windows with explorers more fragile than your great-grandma.
// I am embarassed that I know that. about windows, not your great-grandma.
2013-08-02 03:43:58 +00:00
}
}
DoScan ( ) ;
}
2019-11-04 04:30:05 +00:00
private void tbbOpenFolder_Click ( object sender , EventArgs e ) = > System . Diagnostics . Process . Start ( PathManager . MakeAbsolutePath ( Global . Config . PathEntries . FirmwaresPathFragment , null ) ) ;
2018-09-13 14:07:52 +00:00
2019-11-03 22:04:42 +00:00
private void lvFirmwares_KeyDown ( object sender , KeyEventArgs e )
2013-08-03 19:34:51 +00:00
{
if ( e . KeyCode = = Keys . C & & e . Control & & ! e . Alt & & ! e . Shift )
{
2013-10-25 00:57:23 +00:00
PerformListCopy ( ) ;
2013-08-03 19:34:51 +00:00
}
}
2013-08-02 14:23:59 +00:00
2013-10-25 00:57:23 +00:00
void PerformListCopy ( )
{
var str = lvFirmwares . CopyItemsAsText ( ) ;
if ( str . Length > 0 ) Clipboard . SetDataObject ( str ) ;
}
2013-08-10 01:17:06 +00:00
private void lvFirmwares_MouseClick ( object sender , MouseEventArgs e )
2013-08-03 19:34:51 +00:00
{
2014-06-29 02:28:48 +00:00
if ( e . Button = = MouseButtons . Right & & lvFirmwares . GetItemAt ( e . X , e . Y ) ! = null )
2013-08-10 01:17:06 +00:00
lvFirmwaresContextMenuStrip . Show ( lvFirmwares , e . Location ) ;
}
private void tsmiSetCustomization_Click ( object sender , EventArgs e )
{
using ( var ofd = new OpenFileDialog ( ) )
2013-08-03 19:34:51 +00:00
{
2013-08-10 01:17:06 +00:00
ofd . InitialDirectory = currSelectorDir ;
ofd . RestoreDirectory = true ;
2019-11-04 01:55:38 +00:00
string frmwarePath = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . FirmwaresPathFragment , null ) ;
2013-08-10 01:17:06 +00:00
2019-11-04 01:55:38 +00:00
if ( ofd . ShowDialog ( ) = = DialogResult . OK )
2013-08-03 19:34:51 +00:00
{
2017-05-31 15:28:06 +00:00
// remember the location we selected this firmware from, maybe there are others
2013-08-10 01:17:06 +00:00
currSelectorDir = Path . GetDirectoryName ( ofd . FileName ) ;
2019-11-04 01:55:38 +00:00
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 ;
// 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 ( ) ;
2013-08-10 01:17:06 +00:00
}
2013-08-03 19:34:51 +00:00
}
2013-08-10 01:17:06 +00:00
}
2013-08-03 19:34:51 +00:00
2013-08-10 01:17:06 +00:00
private void tsmiClearCustomization_Click ( object sender , EventArgs e )
{
2017-05-31 15:28:06 +00:00
// for each selected item, clear the user choice
2013-08-10 01:17:06 +00:00
foreach ( ListViewItem lvi in lvFirmwares . SelectedItems )
{
var fr = lvi . Tag as FirmwareDatabase . FirmwareRecord ;
Global . Config . FirmwareUserSpecifications . Remove ( fr . ConfigKey ) ;
}
2013-08-03 19:34:51 +00:00
2013-08-10 01:17:06 +00:00
DoScan ( ) ;
2013-08-03 19:34:51 +00:00
}
2013-08-02 03:43:58 +00:00
2013-10-25 00:57:23 +00:00
private void tsmiInfo_Click ( object sender , EventArgs e )
{
var lvi = lvFirmwares . SelectedItems [ 0 ] ;
2017-05-31 15:28:06 +00:00
var fr = ( FirmwareDatabase . FirmwareRecord ) lvi . Tag ;
2013-10-25 00:57:23 +00:00
2017-05-31 15:28:06 +00:00
// get all options for this firmware (in order)
2013-10-25 00:57:23 +00:00
var options =
from fo in FirmwareDatabase . FirmwareOptions
2017-04-27 15:55:22 +00:00
where fo . SystemId = = fr . SystemId & & fo . FirmwareId = = fr . FirmwareId
2013-10-25 00:57:23 +00:00
select fo ;
2017-05-31 15:28:06 +00:00
FirmwaresConfigInfo fciDialog = new FirmwaresConfigInfo
{
lblFirmware =
{
Text = $"{fr.SystemId} : {fr.FirmwareId} ({fr.Descr})"
}
} ;
2013-10-25 00:57:23 +00:00
foreach ( var o in options )
{
ListViewItem olvi = new ListViewItem ( ) ;
olvi . SubItems . Add ( new ListViewItem . ListViewSubItem ( ) ) ;
olvi . SubItems . Add ( new ListViewItem . ListViewSubItem ( ) ) ;
2014-06-21 06:40:07 +00:00
olvi . SubItems . Add ( new ListViewItem . ListViewSubItem ( ) ) ;
2014-11-13 00:09:16 +00:00
olvi . SubItems . Add ( new ListViewItem . ListViewSubItem ( ) ) ;
2017-04-27 15:55:22 +00:00
var ff = FirmwareDatabase . FirmwareFilesByHash [ o . Hash ] ;
if ( o . Status = = FirmwareDatabase . FirmwareOptionStatus . Ideal )
2017-07-12 02:02:24 +00:00
{
2014-06-21 06:40:07 +00:00
olvi . ImageIndex = FirmwaresConfigInfo . idIdeal ;
2017-07-12 02:02:24 +00:00
olvi . ToolTipText = FirmwaresConfigInfo . ttIdeal ;
}
2017-04-27 15:55:22 +00:00
if ( o . Status = = FirmwareDatabase . FirmwareOptionStatus . Acceptable )
2017-07-12 02:02:24 +00:00
{
2014-06-21 06:40:07 +00:00
olvi . ImageIndex = FirmwaresConfigInfo . idAcceptable ;
2017-07-12 02:02:24 +00:00
olvi . ToolTipText = FirmwaresConfigInfo . ttAcceptable ;
}
2017-04-27 15:55:22 +00:00
if ( o . Status = = FirmwareDatabase . FirmwareOptionStatus . Unacceptable )
2017-07-12 02:02:24 +00:00
{
2014-06-21 06:40:07 +00:00
olvi . ImageIndex = FirmwaresConfigInfo . idUnacceptable ;
2017-07-12 02:02:24 +00:00
olvi . ToolTipText = FirmwaresConfigInfo . ttUnacceptable ;
}
2017-04-27 15:55:22 +00:00
if ( o . Status = = FirmwareDatabase . FirmwareOptionStatus . Bad )
2017-07-12 02:02:24 +00:00
{
2014-06-21 06:40:07 +00:00
olvi . ImageIndex = FirmwaresConfigInfo . idBad ;
2017-07-12 02:02:24 +00:00
olvi . ToolTipText = FirmwaresConfigInfo . ttBad ;
}
2017-04-27 15:55:22 +00:00
olvi . SubItems [ 0 ] . Text = ff . Size . ToString ( ) ;
2017-05-31 15:28:06 +00:00
olvi . SubItems [ 0 ] . Font = this . Font ; // why doesnt this work?
2019-03-18 14:06:37 +00:00
olvi . SubItems [ 1 ] . Text = $"sha1:{o.Hash}" ;
2014-11-13 00:09:16 +00:00
olvi . SubItems [ 1 ] . Font = fixedFont ;
2017-04-27 15:55:22 +00:00
olvi . SubItems [ 2 ] . Text = ff . RecommendedName ;
2017-05-31 15:28:06 +00:00
olvi . SubItems [ 2 ] . Font = this . Font ; // why doesnt this work?
2017-04-27 15:55:22 +00:00
olvi . SubItems [ 3 ] . Text = ff . Description ;
2017-05-31 15:28:06 +00:00
olvi . SubItems [ 3 ] . Font = this . Font ; // why doesnt this work?
2017-04-27 15:55:22 +00:00
olvi . SubItems [ 4 ] . Text = ff . Info ;
2017-05-31 15:28:06 +00:00
olvi . SubItems [ 4 ] . Font = this . Font ; // why doesnt this work?
2013-10-25 00:57:23 +00:00
fciDialog . lvOptions . Items . Add ( olvi ) ;
}
fciDialog . lvOptions . AutoResizeColumn ( 0 , ColumnHeaderAutoResizeStyle . ColumnContent ) ;
fciDialog . lvOptions . AutoResizeColumn ( 1 , ColumnHeaderAutoResizeStyle . ColumnContent ) ;
fciDialog . lvOptions . AutoResizeColumn ( 2 , ColumnHeaderAutoResizeStyle . ColumnContent ) ;
2014-06-21 06:40:07 +00:00
fciDialog . lvOptions . AutoResizeColumn ( 3 , ColumnHeaderAutoResizeStyle . ColumnContent ) ;
2013-10-25 00:57:23 +00:00
2014-06-21 06:40:07 +00:00
fciDialog . ShowDialog ( this ) ;
2013-10-25 00:57:23 +00:00
}
private void lvFirmwaresContextMenuStrip_Opening ( object sender , CancelEventArgs e )
{
2017-05-31 15:28:06 +00:00
// hide menu items that arent appropriate for multi-select
2013-10-25 00:57:23 +00:00
tsmiSetCustomization . Visible = lvFirmwares . SelectedItems . Count = = 1 ;
tsmiInfo . Visible = lvFirmwares . SelectedItems . Count = = 1 ;
}
private void tsmiCopy_Click ( object sender , EventArgs e )
{
PerformListCopy ( ) ;
}
2013-12-19 16:59:23 +00:00
private void linkBasePath_LinkClicked ( object sender , LinkLabelLinkClickedEventArgs e )
{
2013-12-19 22:53:06 +00:00
if ( Owner is PathConfig )
{
MessageBox . Show ( "C-C-C-Combo Breaker!" , "Nice try, but" ) ;
return ;
}
2017-05-31 15:28:06 +00:00
2019-11-02 04:29:09 +00:00
using var pathConfig = new PathConfig ( ) ;
pathConfig . ShowDialog ( this ) ;
2013-12-19 16:59:23 +00:00
RefreshBasePath ( ) ;
}
2017-05-31 15:28:06 +00:00
private void RefreshBasePath ( )
2013-12-19 16:59:23 +00:00
{
string oldBasePath = currSelectorDir ;
linkBasePath . Text = currSelectorDir = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . FirmwaresPathFragment , null ) ;
if ( oldBasePath ! = currSelectorDir )
2017-05-31 15:28:06 +00:00
{
2013-12-19 16:59:23 +00:00
DoScan ( ) ;
2017-05-31 15:28:06 +00:00
}
2013-12-19 16:59:23 +00:00
}
2014-10-26 04:23:56 +00:00
private void tbbImport_Click ( object sender , EventArgs e )
{
2017-05-31 15:28:06 +00:00
using ( var ofd = new OpenFileDialog ( ) )
2014-10-26 04:23:56 +00:00
{
ofd . Multiselect = true ;
2016-12-06 18:21:05 +00:00
if ( ofd . ShowDialog ( ) ! = DialogResult . OK )
{
2014-10-26 04:23:56 +00:00
return ;
2016-12-06 18:21:05 +00:00
}
2014-10-26 04:23:56 +00:00
RunImportJob ( ofd . FileNames ) ;
}
}
2016-12-06 18:21:05 +00:00
private bool RunImportJobSingle ( string basepath , string f , ref string errors )
2014-10-26 14:22:26 +00:00
{
try
{
var fi = new FileInfo ( f ) ;
2016-12-06 18:21:05 +00:00
if ( ! fi . Exists )
{
return false ;
}
2014-10-26 14:22:26 +00:00
string target = Path . Combine ( basepath , fi . Name ) ;
if ( new FileInfo ( target ) . Exists )
{
2016-12-06 18:21:05 +00:00
// compare the files, if theyre the same. dont do anything
2014-10-26 14:22:26 +00:00
if ( File . ReadAllBytes ( target ) . SequenceEqual ( File . ReadAllBytes ( f ) ) )
2016-12-06 18:21:05 +00:00
{
2014-10-26 14:22:26 +00:00
return false ;
2016-12-06 18:21:05 +00:00
}
// hmm theyre different. import but rename it
2014-10-26 14:22:26 +00:00
string dir = Path . GetDirectoryName ( target ) ;
string ext = Path . GetExtension ( target ) ;
string name = Path . GetFileNameWithoutExtension ( target ) ;
name + = " (variant)" ;
target = Path . Combine ( dir , name ) + ext ;
}
2016-12-06 18:21:05 +00:00
2015-07-11 19:06:28 +00:00
Directory . CreateDirectory ( Path . GetDirectoryName ( target ) ) ;
2014-10-26 14:22:26 +00:00
fi . CopyTo ( target , false ) ;
return true ;
}
catch
{
2017-05-31 15:28:06 +00:00
if ( errors ! = "" )
{
errors + = "\n" ;
}
2014-10-26 14:22:26 +00:00
errors + = f ;
return false ;
}
}
2016-12-06 18:21:05 +00:00
private void RunImportJob ( IEnumerable < string > files )
2014-10-26 04:23:56 +00:00
{
bool didSomething = false ;
var basepath = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . FirmwaresPathFragment , null ) ;
string errors = "" ;
foreach ( var f in files )
{
2014-10-26 14:22:26 +00:00
using ( var hf = new HawkFile ( f ) )
2014-10-26 04:23:56 +00:00
{
2014-10-26 14:22:26 +00:00
if ( hf . IsArchive )
2014-10-26 04:23:56 +00:00
{
2017-05-31 15:28:06 +00:00
// blech. the worst extraction code in the universe.
2019-03-18 14:06:37 +00:00
string extractpath = $"{Path.GetTempFileName()}.dir" ;
2016-12-06 18:21:05 +00:00
DirectoryInfo di = Directory . CreateDirectory ( extractpath ) ;
2014-10-26 14:22:26 +00:00
try
{
foreach ( var ai in hf . ArchiveItems )
{
hf . BindArchiveMember ( ai ) ;
var stream = hf . GetStream ( ) ;
var ms = new MemoryStream ( ) ;
Util . CopyStream ( hf . GetStream ( ) , ms , stream . Length ) ;
string outfile = ai . Name ;
string myname = Path . GetFileName ( outfile ) ;
outfile = Path . Combine ( extractpath , myname ) ;
File . WriteAllBytes ( outfile , ms . ToArray ( ) ) ;
hf . Unbind ( ) ;
2018-09-13 14:07:52 +00:00
2019-11-04 01:55:38 +00:00
if ( cbAllowImport . Checked | | Manager . CanFileBeImported ( outfile ) )
{
didSomething | = RunImportJobSingle ( basepath , outfile , ref errors ) ;
}
2014-10-26 14:22:26 +00:00
}
}
finally
{
di . Delete ( true ) ;
}
2014-10-26 04:23:56 +00:00
}
2014-10-26 14:22:26 +00:00
else
2016-12-06 18:21:05 +00:00
{
2019-11-04 01:55:38 +00:00
if ( cbAllowImport . Checked | | Manager . CanFileBeImported ( hf . CanonicalFullPath ) )
{
didSomething | = RunImportJobSingle ( basepath , f , ref errors ) ;
}
2016-12-06 18:21:05 +00:00
}
2014-10-26 04:23:56 +00:00
}
}
2016-12-06 18:21:05 +00:00
if ( ! string . IsNullOrEmpty ( errors ) )
{
MessageBox . Show ( errors , "Error importing these files" ) ;
}
2014-10-26 04:23:56 +00:00
2016-12-06 18:21:05 +00:00
if ( didSomething )
{
DoScan ( ) ;
}
2014-10-26 04:23:56 +00:00
}
2015-10-16 00:47:38 +00:00
protected override bool ProcessCmdKey ( ref Message msg , Keys keyData )
{
if ( keyData = = Keys . Escape )
{
2016-12-06 18:21:05 +00:00
Close ( ) ;
2015-10-16 00:47:38 +00:00
return true ;
}
2016-12-06 18:21:05 +00:00
2015-10-16 00:47:38 +00:00
return base . ProcessCmdKey ( ref msg , keyData ) ;
}
2019-11-04 01:55:38 +00:00
private void lvFirmwares_DragEnter ( object sender , DragEventArgs e )
2014-10-26 04:23:56 +00:00
{
2017-05-31 15:28:06 +00:00
e . Effect = e . Data . GetDataPresent ( DataFormats . FileDrop ) ? DragDropEffects . Copy : DragDropEffects . None ;
2014-10-26 04:23:56 +00:00
}
private void lvFirmwares_DragDrop ( object sender , DragEventArgs e )
{
if ( e . Data . GetDataPresent ( DataFormats . FileDrop ) )
{
string [ ] files = ( string [ ] ) e . Data . GetData ( DataFormats . FileDrop ) ;
RunImportJob ( files ) ;
}
}
2017-05-31 15:28:06 +00:00
} // class FirmwaresConfig
2013-07-31 15:54:08 +00:00
}