diff options
author | Elie Rodrigue <elie.rodrigue@nubik.ca> | 2017-05-09 22:24:10 +0300 |
---|---|---|
committer | Elie Rodrigue <elie.rodrigue@nubik.ca> | 2017-05-09 22:24:10 +0300 |
commit | 737a28334e7b0461c39cda6e83d2cebef9b622a9 (patch) | |
tree | b690cad0b87d8bd3999c77fe1259fe273efbddd7 | |
parent | 7174d150f4c2bed268dc9385d6d3cc4feb0f7af1 (diff) |
Game detail update
-rw-r--r-- | MainForm.Designer.cs | 202 | ||||
-rw-r--r-- | MainForm.cs | 294 | ||||
-rw-r--r-- | MainForm.resx | 565 | ||||
-rw-r--r-- | Manager/GameManager.cs | 148 | ||||
-rw-r--r-- | Properties/app.manifest | 106 | ||||
-rw-r--r-- | UI/Components/GameDetail.Designer.cs | 8 | ||||
-rw-r--r-- | UI/Components/GameDetail.cs | 31 | ||||
-rw-r--r-- | UI/Components/GameDetail.resx | 3 | ||||
-rw-r--r-- | UI/Components/GameSelecter.Designer.cs | 20 | ||||
-rw-r--r-- | UI/Components/GameSelecter.cs | 96 | ||||
-rw-r--r-- | WorkerForm.cs | 2380 | ||||
-rw-r--r-- | hakchi_gui.csproj | 17 |
12 files changed, 1526 insertions, 2344 deletions
diff --git a/MainForm.Designer.cs b/MainForm.Designer.cs index f5a02e49..1da05612 100644 --- a/MainForm.Designer.cs +++ b/MainForm.Designer.cs @@ -108,27 +108,6 @@ this.fAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.checkedListBoxGames = new System.Windows.Forms.CheckedListBox(); - this.groupBoxOptions = new System.Windows.Forms.GroupBox(); - this.buttonShowGameGenieDatabase = new System.Windows.Forms.Button(); - this.maskedTextBoxReleaseDate = new System.Windows.Forms.MaskedTextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.textBoxGameGenie = new System.Windows.Forms.TextBox(); - this.label7 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.radioButtonTwoSim = new System.Windows.Forms.RadioButton(); - this.buttonGoogle = new System.Windows.Forms.Button(); - this.buttonBrowseImage = new System.Windows.Forms.Button(); - this.pictureBoxArt = new System.Windows.Forms.PictureBox(); - this.label4 = new System.Windows.Forms.Label(); - this.textBoxArguments = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.textBoxPublisher = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.radioButtonTwo = new System.Windows.Forms.RadioButton(); - this.radioButtonOne = new System.Windows.Forms.RadioButton(); - this.textBoxName = new System.Windows.Forms.TextBox(); - this.labelName = new System.Windows.Forms.Label(); - this.labelID = new System.Windows.Forms.Label(); this.label5 = new System.Windows.Forms.Label(); this.buttonAddGames = new System.Windows.Forms.Button(); this.statusStrip = new System.Windows.Forms.StatusStrip(); @@ -145,9 +124,8 @@ this.buttonStart = new System.Windows.Forms.Button(); this.timerCalculateGames = new System.Windows.Forms.Timer(this.components); this.timerConnectionCheck = new System.Windows.Forms.Timer(this.components); + this.gameDetail1 = new com.clusterrr.hakchi_gui.UI.Components.GameDetail(); this.menuStrip.SuspendLayout(); - this.groupBoxOptions.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBoxArt)).BeginInit(); this.statusStrip.SuspendLayout(); this.contextMenuStrip.SuspendLayout(); this.SuspendLayout(); @@ -717,152 +695,6 @@ this.checkedListBoxGames.KeyDown += new System.Windows.Forms.KeyEventHandler(this.checkedListBoxGames_KeyDown); this.checkedListBoxGames.MouseDown += new System.Windows.Forms.MouseEventHandler(this.checkedListBoxGames_MouseDown); // - // groupBoxOptions - // - resources.ApplyResources(this.groupBoxOptions, "groupBoxOptions"); - this.groupBoxOptions.Controls.Add(this.buttonShowGameGenieDatabase); - this.groupBoxOptions.Controls.Add(this.maskedTextBoxReleaseDate); - this.groupBoxOptions.Controls.Add(this.label1); - this.groupBoxOptions.Controls.Add(this.textBoxGameGenie); - this.groupBoxOptions.Controls.Add(this.label7); - this.groupBoxOptions.Controls.Add(this.label6); - this.groupBoxOptions.Controls.Add(this.radioButtonTwoSim); - this.groupBoxOptions.Controls.Add(this.buttonGoogle); - this.groupBoxOptions.Controls.Add(this.buttonBrowseImage); - this.groupBoxOptions.Controls.Add(this.pictureBoxArt); - this.groupBoxOptions.Controls.Add(this.label4); - this.groupBoxOptions.Controls.Add(this.textBoxArguments); - this.groupBoxOptions.Controls.Add(this.label3); - this.groupBoxOptions.Controls.Add(this.textBoxPublisher); - this.groupBoxOptions.Controls.Add(this.label2); - this.groupBoxOptions.Controls.Add(this.radioButtonTwo); - this.groupBoxOptions.Controls.Add(this.radioButtonOne); - this.groupBoxOptions.Controls.Add(this.textBoxName); - this.groupBoxOptions.Controls.Add(this.labelName); - this.groupBoxOptions.Controls.Add(this.labelID); - this.groupBoxOptions.Name = "groupBoxOptions"; - this.groupBoxOptions.TabStop = false; - // - // buttonShowGameGenieDatabase - // - resources.ApplyResources(this.buttonShowGameGenieDatabase, "buttonShowGameGenieDatabase"); - this.buttonShowGameGenieDatabase.Name = "buttonShowGameGenieDatabase"; - this.buttonShowGameGenieDatabase.UseVisualStyleBackColor = true; - this.buttonShowGameGenieDatabase.Click += new System.EventHandler(this.buttonShowGameGenieDatabase_Click); - // - // maskedTextBoxReleaseDate - // - resources.ApplyResources(this.maskedTextBoxReleaseDate, "maskedTextBoxReleaseDate"); - this.maskedTextBoxReleaseDate.Name = "maskedTextBoxReleaseDate"; - this.maskedTextBoxReleaseDate.TextChanged += new System.EventHandler(this.maskedTextBoxReleaseDate_TextChanged); - // - // label1 - // - resources.ApplyResources(this.label1, "label1"); - this.label1.Name = "label1"; - // - // textBoxGameGenie - // - resources.ApplyResources(this.textBoxGameGenie, "textBoxGameGenie"); - this.textBoxGameGenie.Name = "textBoxGameGenie"; - this.textBoxGameGenie.TextChanged += new System.EventHandler(this.textBoxGameGenie_TextChanged); - // - // label7 - // - resources.ApplyResources(this.label7, "label7"); - this.label7.Name = "label7"; - // - // label6 - // - resources.ApplyResources(this.label6, "label6"); - this.label6.Name = "label6"; - // - // radioButtonTwoSim - // - resources.ApplyResources(this.radioButtonTwoSim, "radioButtonTwoSim"); - this.radioButtonTwoSim.Name = "radioButtonTwoSim"; - this.radioButtonTwoSim.UseVisualStyleBackColor = true; - this.radioButtonTwoSim.CheckedChanged += new System.EventHandler(this.radioButtonOne_CheckedChanged); - // - // buttonGoogle - // - resources.ApplyResources(this.buttonGoogle, "buttonGoogle"); - this.buttonGoogle.Name = "buttonGoogle"; - this.buttonGoogle.UseVisualStyleBackColor = true; - this.buttonGoogle.Click += new System.EventHandler(this.buttonGoogle_Click); - // - // buttonBrowseImage - // - resources.ApplyResources(this.buttonBrowseImage, "buttonBrowseImage"); - this.buttonBrowseImage.Name = "buttonBrowseImage"; - this.buttonBrowseImage.UseVisualStyleBackColor = true; - this.buttonBrowseImage.Click += new System.EventHandler(this.buttonBrowseImage_Click); - // - // pictureBoxArt - // - resources.ApplyResources(this.pictureBoxArt, "pictureBoxArt"); - this.pictureBoxArt.Name = "pictureBoxArt"; - this.pictureBoxArt.TabStop = false; - // - // label4 - // - resources.ApplyResources(this.label4, "label4"); - this.label4.Name = "label4"; - // - // textBoxArguments - // - resources.ApplyResources(this.textBoxArguments, "textBoxArguments"); - this.textBoxArguments.Name = "textBoxArguments"; - this.textBoxArguments.TextChanged += new System.EventHandler(this.textBoxArguments_TextChanged); - // - // label3 - // - resources.ApplyResources(this.label3, "label3"); - this.label3.Name = "label3"; - // - // textBoxPublisher - // - resources.ApplyResources(this.textBoxPublisher, "textBoxPublisher"); - this.textBoxPublisher.Name = "textBoxPublisher"; - this.textBoxPublisher.TextChanged += new System.EventHandler(this.textBoxPublisher_TextChanged); - // - // label2 - // - resources.ApplyResources(this.label2, "label2"); - this.label2.Name = "label2"; - // - // radioButtonTwo - // - resources.ApplyResources(this.radioButtonTwo, "radioButtonTwo"); - this.radioButtonTwo.Name = "radioButtonTwo"; - this.radioButtonTwo.UseVisualStyleBackColor = true; - this.radioButtonTwo.CheckedChanged += new System.EventHandler(this.radioButtonOne_CheckedChanged); - // - // radioButtonOne - // - resources.ApplyResources(this.radioButtonOne, "radioButtonOne"); - this.radioButtonOne.Checked = true; - this.radioButtonOne.Name = "radioButtonOne"; - this.radioButtonOne.TabStop = true; - this.radioButtonOne.UseVisualStyleBackColor = true; - this.radioButtonOne.CheckedChanged += new System.EventHandler(this.radioButtonOne_CheckedChanged); - // - // textBoxName - // - resources.ApplyResources(this.textBoxName, "textBoxName"); - this.textBoxName.Name = "textBoxName"; - this.textBoxName.TextChanged += new System.EventHandler(this.textBoxName_TextChanged); - // - // labelName - // - resources.ApplyResources(this.labelName, "labelName"); - this.labelName.Name = "labelName"; - // - // labelID - // - resources.ApplyResources(this.labelID, "labelID"); - this.labelID.Name = "labelID"; - // // label5 // resources.ApplyResources(this.label5, "label5"); @@ -972,18 +804,23 @@ this.timerConnectionCheck.Interval = 500; this.timerConnectionCheck.Tick += new System.EventHandler(this.timerConnectionCheck_Tick); // + // gameDetail1 + // + resources.ApplyResources(this.gameDetail1, "gameDetail1"); + this.gameDetail1.Name = "gameDetail1"; + // // MainForm // this.AllowDrop = true; resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.gameDetail1); this.Controls.Add(this.buttonStart); this.Controls.Add(this.statusStrip); this.Controls.Add(this.buttonAddGames); this.Controls.Add(this.label5); this.Controls.Add(this.checkedListBoxGames); this.Controls.Add(this.menuStrip); - this.Controls.Add(this.groupBoxOptions); this.Cursor = System.Windows.Forms.Cursors.Default; this.KeyPreview = true; this.MaximizeBox = false; @@ -996,9 +833,6 @@ this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MainForm_KeyDown); this.menuStrip.ResumeLayout(false); this.menuStrip.PerformLayout(); - this.groupBoxOptions.ResumeLayout(false); - this.groupBoxOptions.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBoxArt)).EndInit(); this.statusStrip.ResumeLayout(false); this.statusStrip.PerformLayout(); this.contextMenuStrip.ResumeLayout(false); @@ -1013,22 +847,6 @@ private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem addMoreGamesToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; - private System.Windows.Forms.GroupBox groupBoxOptions; - private System.Windows.Forms.RadioButton radioButtonTwo; - private System.Windows.Forms.RadioButton radioButtonOne; - private System.Windows.Forms.TextBox textBoxName; - private System.Windows.Forms.Label labelName; - private System.Windows.Forms.Label labelID; - private System.Windows.Forms.TextBox textBoxPublisher; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.MaskedTextBox maskedTextBoxReleaseDate; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.TextBox textBoxArguments; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.PictureBox pictureBoxArt; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.Button buttonGoogle; - private System.Windows.Forms.Button buttonBrowseImage; private System.Windows.Forms.Label label5; private System.Windows.Forms.Button buttonAddGames; private System.Windows.Forms.StatusStrip statusStrip; @@ -1042,8 +860,6 @@ private System.Windows.Forms.ToolStripMenuItem dumpKernelToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem flashCustomKernelToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem flashOriginalKernelToolStripMenuItem; - private System.Windows.Forms.RadioButton radioButtonTwoSim; - private System.Windows.Forms.Label label6; private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem; private System.Windows.Forms.Timer timerCalculateGames; private System.Windows.Forms.ToolStripMenuItem selectAllToolStripMenuItem; @@ -1060,8 +876,6 @@ private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; protected internal System.Windows.Forms.CheckedListBox checkedListBoxGames; private System.Windows.Forms.ToolStripMenuItem searchToolStripMenuItem; - private System.Windows.Forms.TextBox textBoxGameGenie; - private System.Windows.Forms.Label label7; private System.Windows.Forms.ToolStripMenuItem epilepsyProtectionToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem cloverconHackToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem resetUsingCombinationOfButtonsToolStripMenuItem; @@ -1080,7 +894,6 @@ private System.Windows.Forms.ToolStripMenuItem automaticOriginalToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem foldersSplitByFirstLetterToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem customToolStripMenuItem; - private System.Windows.Forms.Button buttonShowGameGenieDatabase; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3; private System.Windows.Forms.ToolStripMenuItem pagesOriginalToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem foldersOriginalToolStripMenuItem; @@ -1124,6 +937,7 @@ private System.Windows.Forms.ToolStripMenuItem languageToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem8; private System.Windows.Forms.ToolStripMenuItem takeScreenshotToolStripMenuItem; + private UI.Components.GameDetail gameDetail1; } } diff --git a/MainForm.cs b/MainForm.cs index 13b604e1..1831c555 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -53,9 +53,13 @@ namespace com.clusterrr.hakchi_gui { try { + KernelDump = Path.Combine(Path.Combine(Program.BaseDirectoryExternal, "dump"), "kernel.img"); InternalMods = from m in Directory.GetFiles(Path.Combine(Program.BaseDirectoryInternal, "mods/hmods")) select Path.GetFileNameWithoutExtension(m); - LoadGames(); + Manager.GameManager.GetInstance().GamesRemoved += MainForm_GamesRemoved; ; + Manager.GameManager.GetInstance().NewGamesAdded += MainForm_NewGamesAdded; + Manager.GameManager.GetInstance().LoadLibrary(); + // LoadGames(); LoadPresets(); LoadLanguages(); @@ -105,14 +109,7 @@ namespace com.clusterrr.hakchi_gui max90toolStripMenuItem.Checked = ConfigIni.MaxGamesPerFolder == 90; max100toolStripMenuItem.Checked = ConfigIni.MaxGamesPerFolder == 100; - // Little tweak for easy translation - var tbl = textBoxName.Left; - textBoxName.Left = labelName.Left + labelName.Width; - textBoxName.Width -= textBoxName.Left - tbl; - maskedTextBoxReleaseDate.Left = label1.Left + label1.Width + 3; - tbl = textBoxPublisher.Left; - textBoxPublisher.Left = label2.Left + label2.Width; - textBoxPublisher.Width -= textBoxPublisher.Left - tbl; + // Tweeks for message boxes MessageBoxManager.Yes = MessageBoxManager.Retry = Resources.Yes; @@ -182,66 +179,32 @@ namespace com.clusterrr.hakchi_gui } } - public void LoadGames() + + + private void MainForm_NewGamesAdded(List<NesMiniApplication> e) { - /*Make sure its initialised*/ - Manager.GameManager.GetInstance(); - - foreach(var game in Manager.GameManager.GetInstance().getAllGames()) + foreach (var game in e.OrderBy(o=>o.Name)) { checkedListBoxGames.Items.Add(game, game.Selected); } - RecalculateSelectedGames(); + ShowStats(); ShowSelected(); } - public void ShowSelected() + private void MainForm_GamesRemoved(List<NesMiniApplication> e) { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null) + foreach (var game in e) { - - groupBoxOptions.Visible = true; - groupBoxOptions.Enabled = false; - labelID.Text = "ID: "; - textBoxName.Text = ""; - radioButtonOne.Checked = true; - radioButtonTwo.Checked = false; - radioButtonTwoSim.Checked = false; - maskedTextBoxReleaseDate.Text = ""; - textBoxPublisher.Text = ""; - textBoxArguments.Text = ""; - pictureBoxArt.Image = null; - } - else - { - var app = selected as NesMiniApplication; - - groupBoxOptions.Visible = true; - labelID.Text = "ID: " + app.Code; - textBoxName.Text = app.Name; - if (app.Simultaneous && app.Players == 2) - radioButtonTwoSim.Checked = true; - else if (app.Players == 2) - radioButtonTwo.Checked = true; - else - radioButtonOne.Checked = true; - maskedTextBoxReleaseDate.Text = app.ReleaseDate; - textBoxPublisher.Text = app.Publisher; - if (app is NesGame) - textBoxArguments.Text = (app as NesGame).Args; - else if (app is FdsGame) - textBoxArguments.Text = (app as FdsGame).Args; - else - textBoxArguments.Text = app.Command; - if (File.Exists(app.IconPath)) - pictureBoxArt.Image = NesMiniApplication.LoadBitmap(app.IconPath); - else - pictureBoxArt.Image = null; - buttonShowGameGenieDatabase.Enabled = textBoxGameGenie.Enabled = app is NesGame; - textBoxGameGenie.Text = (app is NesGame) ? (app as NesGame).GameGenie : ""; - groupBoxOptions.Enabled = true; + checkedListBoxGames.Items.Remove(e); } + ShowStats(); + ShowSelected(); + } + + public void ShowSelected() + { + NesMiniApplication selected = (NesMiniApplication)checkedListBoxGames.SelectedItem; + gameDetail1.SetGame(selected); } @@ -350,92 +313,12 @@ namespace com.clusterrr.hakchi_gui ShowSelected(); } - void SetImageForSelectedGame(string fileName) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesMiniApplication)) return; - var game = (selected as NesMiniApplication); - game.Image = NesMiniApplication.LoadBitmap(fileName); - ShowSelected(); - timerCalculateGames.Enabled = true; - } - - private void buttonBrowseImage_Click(object sender, EventArgs e) - { - openFileDialogImage.Filter = Resources.Images + " (*.bmp;*.png;*.jpg;*.jpeg;*.gif)|*.bmp;*.png;*.jpg;*.jpeg;*.gif|" + Resources.AllFiles + "|*.*"; - if (openFileDialogImage.ShowDialog() == System.Windows.Forms.DialogResult.OK) - { - SetImageForSelectedGame(openFileDialogImage.FileName); - } - } - private void buttonGoogle_Click(object sender, EventArgs e) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesMiniApplication)) return; - var game = (selected as NesMiniApplication); - var googler = new ImageGooglerForm(game); - if (googler.ShowDialog() == System.Windows.Forms.DialogResult.OK) - { - game.Image = googler.Result; - ShowSelected(); - timerCalculateGames.Enabled = true; - } - } - private void textBoxName_TextChanged(object sender, EventArgs e) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesMiniApplication)) return; - var game = (selected as NesMiniApplication); - game.Name = textBoxName.Text; - } - - private void radioButtonOne_CheckedChanged(object sender, EventArgs e) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesMiniApplication)) return; - var game = (selected as NesMiniApplication); - game.Players = (byte)(radioButtonOne.Checked ? 1 : 2); - game.Simultaneous = radioButtonTwoSim.Checked; - } - - private void textBoxPublisher_TextChanged(object sender, EventArgs e) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesMiniApplication)) return; - var game = (selected as NesMiniApplication); - game.Publisher = textBoxPublisher.Text.ToUpper(); - } - - private void textBoxArguments_TextChanged(object sender, EventArgs e) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesMiniApplication)) return; - var game = (selected as NesMiniApplication); - if (game is NesGame) - (game as NesGame).Args = textBoxArguments.Text; - else if (game is FdsGame) - (game as FdsGame).Args = textBoxArguments.Text; - else - game.Command = textBoxArguments.Text; - } + - private void maskedTextBoxReleaseDate_TextChanged(object sender, EventArgs e) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesMiniApplication)) return; - var game = (selected as NesMiniApplication); - game.ReleaseDate = maskedTextBoxReleaseDate.Text; - } - private void textBoxGameGenie_TextChanged(object sender, EventArgs e) - { - var selected = checkedListBoxGames.SelectedItem; - if (selected == null || !(selected is NesGame)) return; - var game = (selected as NesGame); - game.GameGenie = textBoxGameGenie.Text; - } + private void SaveConfig() @@ -453,21 +336,18 @@ namespace com.clusterrr.hakchi_gui } private void MainForm_FormClosed(object sender, FormClosedEventArgs e) { - Process.GetCurrentProcess().Kill(); // Suicide! Just easy and dirty way to kill all threads. + + //Process.GetCurrentProcess().Kill(); // Suicide! Just easy and dirty way to kill all threads. } - struct CountResult - { - public int Count; - public long Size; - } + void RecalculateSelectedGamesThread() { try { - var stats = RecalculateSelectedGames(); - showStats(stats); + + ShowStats(); } catch { @@ -475,38 +355,27 @@ namespace com.clusterrr.hakchi_gui timerCalculateGames.Enabled = true; } } - CountResult RecalculateSelectedGames() + void ShowStats() { - CountResult stats; - stats.Count = 0; - stats.Size = 0; - foreach (var game in checkedListBoxGames.CheckedItems) - { - if (game is NesMiniApplication) - { - stats.Count++; - stats.Size += (game as NesMiniApplication).Size(); - } - - } - return stats; + showStats(Manager.GameManager.GetInstance().GetStatistics()); } - void showStats(CountResult stats) + void showStats(Manager.GameManager.CountResult stats) { try { if (InvokeRequired) { - Invoke(new Action<CountResult>(showStats), new object[] { stats }); + Invoke(new Action<Manager.GameManager.CountResult>(showStats), new object[] { stats }); return; } + var maxGamesSize = DefaultMaxGamesSize * 1024 * 1024; if (WorkerForm.NandCTotal > 0) maxGamesSize = (WorkerForm.NandCFree + WorkerForm.WritedGamesSize) - WorkerForm.ReservedMemory * 1024 * 1024; - toolStripStatusLabelSelected.Text = stats.Count + " " + Resources.GamesSelected; - toolStripStatusLabelSize.Text = string.Format("{0:F1}MB / {1:F1}MB", stats.Size / 1024.0 / 1024.0, maxGamesSize / 1024.0 / 1024.0); + toolStripStatusLabelSelected.Text = stats.SelectedCount + " " + Resources.GamesSelected; + toolStripStatusLabelSize.Text = string.Format("{0:F1}MB / {1:F1}MB", stats.SelectedSize / 1024.0 / 1024.0, maxGamesSize / 1024.0 / 1024.0); toolStripProgressBar.Maximum = (int)maxGamesSize; - toolStripProgressBar.Value = Math.Min((int)stats.Size, toolStripProgressBar.Maximum); + toolStripProgressBar.Value = Math.Min((int)stats.SelectedSize, toolStripProgressBar.Maximum); toolStripStatusLabelSize.ForeColor = (toolStripProgressBar.Value < toolStripProgressBar.Maximum) ? SystemColors.ControlText : @@ -535,16 +404,6 @@ namespace com.clusterrr.hakchi_gui } } - private void checkedListBoxDefaultGames_MouseDown(object sender, MouseEventArgs e) - { - if (e.Button == System.Windows.Forms.MouseButtons.Right) - { - var i = checkedListBoxGames.IndexFromPoint(e.X, e.Y); - selectAllToolStripMenuItem.Tag = unselectAllToolStripMenuItem.Tag = 1; - deleteGameToolStripMenuItem.Enabled = false; - contextMenuStrip.Show(sender as Control, e.X, e.Y); - } - } DialogResult RequireKernelDump() { @@ -583,8 +442,8 @@ namespace com.clusterrr.hakchi_gui { SaveConfig(); - var stats = RecalculateSelectedGames(); - if (stats.Count == 0) + var stats = Manager.GameManager.GetInstance().GetStatistics(); + if (stats.SelectedCount == 0) { MessageBox.Show(Resources.SelectAtLeast, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); return; @@ -658,8 +517,7 @@ namespace com.clusterrr.hakchi_gui void AddGames(IEnumerable<string> files) { - SaveConfig(); - ICollection<NesMiniApplication> addedApps; + List<NesMiniApplication> addedApps; var workerForm = new WorkerForm(); workerForm.Text = Resources.LoadingGames; workerForm.Task = WorkerForm.Tasks.AddGames; @@ -667,47 +525,12 @@ namespace com.clusterrr.hakchi_gui workerForm.Start(); addedApps = workerForm.addedApplications; - if (addedApps != null) - { - // Add games, only new ones - var newApps = addedApps.Distinct(new NesMiniApplication.NesMiniAppEqualityComparer()); - var newCodes = from app in newApps select app.Code; - var oldAppsReplaced = from app in checkedListBoxGames.Items.Cast<object>().ToArray() - where (app is NesMiniApplication) && newCodes.Contains((app as NesMiniApplication).Code) - select app; - foreach (var replaced in oldAppsReplaced) - checkedListBoxGames.Items.Remove(replaced); - checkedListBoxGames.Items.AddRange(newApps.ToArray()); - var first = checkedListBoxGames.Items[0]; - bool originalChecked = (checkedListBoxGames.CheckedItems.Contains(first)); - checkedListBoxGames.Items.Remove(first); - checkedListBoxGames.Sorted = true; - checkedListBoxGames.Sorted = false; - checkedListBoxGames.Items.Insert(0, first); - checkedListBoxGames.SetItemChecked(0, originalChecked); - } - else - { - // Reload all games (maybe process was terminated?) - LoadGames(); - } - if (addedApps != null) // if added only one game select it + foreach (NesMiniApplication g in addedApps) { - bool first = true; - foreach (var addedApp in addedApps) - { - for (int i = 0; i < checkedListBoxGames.Items.Count; i++) - if ((checkedListBoxGames.Items[i] is NesMiniApplication) && - (checkedListBoxGames.Items[i] as NesMiniApplication).Code == addedApp.Code) - { - if (first) - checkedListBoxGames.SelectedIndex = i; - first = false; - checkedListBoxGames.SetItemChecked(i, true); - break; - } - } + g.Selected = true; } + Manager.GameManager.GetInstance().AddGames(addedApps); + // Schedule recalculation timerCalculateGames.Enabled = false; timerCalculateGames.Enabled = true; @@ -771,9 +594,9 @@ namespace com.clusterrr.hakchi_gui workerForm.Text = Resources.DownloadAllCoversTitle; workerForm.Task = WorkerForm.Tasks.DownloadAllCovers; workerForm.Games = new NesMenuCollection(); - foreach (var game in checkedListBoxGames.Items) + foreach (var game in Manager.GameManager.GetInstance().getAllGames()) { - if (game is NesMiniApplication) + if (game.GetType() != typeof(NesDefaultGame)) workerForm.Games.Add(game as NesMiniApplication); } return workerForm.Start() == DialogResult.OK; @@ -968,8 +791,7 @@ namespace com.clusterrr.hakchi_gui var game = checkedListBoxGames.Items[pos] as NesMiniApplication; if (MessageBox.Show(this, string.Format(Resources.DeleteGame, game.Name), Resources.AreYouSure, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.Yes) { - Directory.Delete(game.GamePath, true); - checkedListBoxGames.Items.RemoveAt(pos); + Manager.GameManager.GetInstance().DeleteGames(new List<NesMiniApplication>() { game }); } } catch (Exception ex) @@ -985,8 +807,14 @@ namespace com.clusterrr.hakchi_gui private void selectAllToolStripMenuItem_Click(object sender, EventArgs e) { if ((int)(sender as ToolStripMenuItem).Tag == 0) + { for (int i = 0; i < checkedListBoxGames.Items.Count; i++) + { checkedListBoxGames.SetItemChecked(i, true); + var game = checkedListBoxGames.Items[i] as NesMiniApplication; + game.Selected = true; + } + } } @@ -994,7 +822,11 @@ namespace com.clusterrr.hakchi_gui { if ((int)(sender as ToolStripMenuItem).Tag == 0) for (int i = 0; i < checkedListBoxGames.Items.Count; i++) + { checkedListBoxGames.SetItemChecked(i, false); + var game = checkedListBoxGames.Items[i] as NesMiniApplication; + game.Selected = false; + } } @@ -1015,7 +847,8 @@ namespace com.clusterrr.hakchi_gui var ext = Path.GetExtension(files[0]).ToLower(); if (ext == ".jpg" || ext == ".png") { - SetImageForSelectedGame(files[0]); + gameDetail1.SetImageForSelectedGame(files[0]); + return; } } @@ -1127,14 +960,7 @@ namespace com.clusterrr.hakchi_gui ConfigIni.Compress = compressGamesIfPossibleToolStripMenuItem.Checked; } - private void buttonShowGameGenieDatabase_Click(object sender, EventArgs e) - { - if (!(checkedListBoxGames.SelectedItem is NesGame)) return; - NesGame nesGame = checkedListBoxGames.SelectedItem as NesGame; - GameGenieCodeForm lFrm = new GameGenieCodeForm(nesGame); - if (lFrm.ShowDialog() == System.Windows.Forms.DialogResult.OK) - textBoxGameGenie.Text = nesGame.GameGenie; - } + private void pagesModefoldersToolStripMenuItem_Click(object sender, EventArgs e) { diff --git a/MainForm.resx b/MainForm.resx index b78b2cf2..2806eae8 100644 --- a/MainForm.resx +++ b/MainForm.resx @@ -144,7 +144,7 @@ <value>$this</value> </data> <data name=">>menuStrip.ZOrder" xml:space="preserve"> - <value>6</value> + <value>7</value> </data> <data name="fileToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing"> <value>37, 20</value> @@ -645,542 +645,8 @@ <value>$this</value> </data> <data name=">>checkedListBoxGames.ZOrder" xml:space="preserve"> - <value>5</value> - </data> - <data name="groupBoxOptions.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms"> - <value>None</value> - </data> - <data name="buttonShowGameGenieDatabase.Location" type="System.Drawing.Point, System.Drawing"> - <value>252, 286</value> - </data> - <data name="buttonShowGameGenieDatabase.Size" type="System.Drawing.Size, System.Drawing"> - <value>25, 20</value> - </data> - <data name="buttonShowGameGenieDatabase.TabIndex" type="System.Int32, mscorlib"> - <value>12</value> - </data> - <data name="buttonShowGameGenieDatabase.Text" xml:space="preserve"> - <value>+</value> - </data> - <data name=">>buttonShowGameGenieDatabase.Name" xml:space="preserve"> - <value>buttonShowGameGenieDatabase</value> - </data> - <data name=">>buttonShowGameGenieDatabase.Type" xml:space="preserve"> - <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>buttonShowGameGenieDatabase.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>buttonShowGameGenieDatabase.ZOrder" xml:space="preserve"> - <value>0</value> - </data> - <data name="maskedTextBoxReleaseDate.Location" type="System.Drawing.Point, System.Drawing"> - <value>210, 154</value> - </data> - <data name="maskedTextBoxReleaseDate.Mask" xml:space="preserve"> - <value>0000-00-00</value> - </data> - <data name="maskedTextBoxReleaseDate.Size" type="System.Drawing.Size, System.Drawing"> - <value>65, 20</value> - </data> - <data name="maskedTextBoxReleaseDate.TabIndex" type="System.Int32, mscorlib"> - <value>6</value> - </data> - <data name=">>maskedTextBoxReleaseDate.Name" xml:space="preserve"> - <value>maskedTextBoxReleaseDate</value> - </data> - <data name=">>maskedTextBoxReleaseDate.Type" xml:space="preserve"> - <value>System.Windows.Forms.MaskedTextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>maskedTextBoxReleaseDate.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>maskedTextBoxReleaseDate.ZOrder" xml:space="preserve"> - <value>1</value> - </data> - <data name="label1.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="label1.Location" type="System.Drawing.Point, System.Drawing"> - <value>15, 157</value> - </data> - <data name="label1.Size" type="System.Drawing.Size, System.Drawing"> - <value>150, 13</value> - </data> - <data name="label1.TabIndex" type="System.Int32, mscorlib"> - <value>5</value> - </data> - <data name="label1.Text" xml:space="preserve"> - <value>Release date (YYYY-MM-DD):</value> - </data> - <data name=">>label1.Name" xml:space="preserve"> - <value>label1</value> - </data> - <data name=">>label1.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>label1.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>label1.ZOrder" xml:space="preserve"> - <value>2</value> - </data> - <data name="textBoxGameGenie.Location" type="System.Drawing.Point, System.Drawing"> - <value>19, 286</value> - </data> - <data name="textBoxGameGenie.Size" type="System.Drawing.Size, System.Drawing"> - <value>227, 20</value> - </data> - <data name="textBoxGameGenie.TabIndex" type="System.Int32, mscorlib"> - <value>11</value> - </data> - <data name=">>textBoxGameGenie.Name" xml:space="preserve"> - <value>textBoxGameGenie</value> - </data> - <data name=">>textBoxGameGenie.Type" xml:space="preserve"> - <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>textBoxGameGenie.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>textBoxGameGenie.ZOrder" xml:space="preserve"> - <value>3</value> - </data> - <data name="label7.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="label7.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms"> - <value>NoControl</value> - </data> - <data name="label7.Location" type="System.Drawing.Point, System.Drawing"> - <value>16, 269</value> - </data> - <data name="label7.Size" type="System.Drawing.Size, System.Drawing"> - <value>194, 13</value> - </data> - <data name="label7.TabIndex" type="System.Int32, mscorlib"> - <value>17</value> - </data> - <data name="label7.Text" xml:space="preserve"> - <value>Game Genie codes (comma separated):</value> - </data> - <data name=">>label7.Name" xml:space="preserve"> - <value>label7</value> - </data> - <data name=">>label7.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>label7.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>label7.ZOrder" xml:space="preserve"> - <value>4</value> - </data> - <data name="label6.Location" type="System.Drawing.Point, System.Drawing"> - <value>15, 76</value> - </data> - <data name="label6.Size" type="System.Drawing.Size, System.Drawing"> - <value>82, 63</value> - </data> - <data name="label6.TabIndex" type="System.Int32, mscorlib"> - <value>16</value> - </data> - <data name="label6.Text" xml:space="preserve"> - <value>Max players:</value> - </data> - <data name="label6.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing"> - <value>MiddleLeft</value> - </data> - <data name=">>label6.Name" xml:space="preserve"> - <value>label6</value> - </data> - <data name=">>label6.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>label6.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>label6.ZOrder" xml:space="preserve"> - <value>5</value> - </data> - <data name="radioButtonTwoSim.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="radioButtonTwoSim.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms"> - <value>NoControl</value> - </data> - <data name="radioButtonTwoSim.Location" type="System.Drawing.Point, System.Drawing"> - <value>103, 122</value> - </data> - <data name="radioButtonTwoSim.Size" type="System.Drawing.Size, System.Drawing"> - <value>156, 17</value> - </data> - <data name="radioButtonTwoSim.TabIndex" type="System.Int32, mscorlib"> - <value>5</value> - </data> - <data name="radioButtonTwoSim.Text" xml:space="preserve"> - <value>Two players, simultaneously</value> - </data> - <data name=">>radioButtonTwoSim.Name" xml:space="preserve"> - <value>radioButtonTwoSim</value> - </data> - <data name=">>radioButtonTwoSim.Type" xml:space="preserve"> - <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>radioButtonTwoSim.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>radioButtonTwoSim.ZOrder" xml:space="preserve"> <value>6</value> </data> - <data name="buttonGoogle.Location" type="System.Drawing.Point, System.Drawing"> - <value>219, 427</value> - </data> - <data name="buttonGoogle.Size" type="System.Drawing.Size, System.Drawing"> - <value>61, 23</value> - </data> - <data name="buttonGoogle.TabIndex" type="System.Int32, mscorlib"> - <value>15</value> - </data> - <data name="buttonGoogle.Text" xml:space="preserve"> - <value>Google</value> - </data> - <data name=">>buttonGoogle.Name" xml:space="preserve"> - <value>buttonGoogle</value> - </data> - <data name=">>buttonGoogle.Type" xml:space="preserve"> - <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>buttonGoogle.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>buttonGoogle.ZOrder" xml:space="preserve"> - <value>7</value> - </data> - <data name="buttonBrowseImage.Location" type="System.Drawing.Point, System.Drawing"> - <value>219, 384</value> - </data> - <data name="buttonBrowseImage.Size" type="System.Drawing.Size, System.Drawing"> - <value>61, 23</value> - </data> - <data name="buttonBrowseImage.TabIndex" type="System.Int32, mscorlib"> - <value>13</value> - </data> - <data name="buttonBrowseImage.Text" xml:space="preserve"> - <value>Browse</value> - </data> - <data name=">>buttonBrowseImage.Name" xml:space="preserve"> - <value>buttonBrowseImage</value> - </data> - <data name=">>buttonBrowseImage.Type" xml:space="preserve"> - <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>buttonBrowseImage.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>buttonBrowseImage.ZOrder" xml:space="preserve"> - <value>8</value> - </data> - <data name="pictureBoxArt.Location" type="System.Drawing.Point, System.Drawing"> - <value>71, 316</value> - </data> - <data name="pictureBoxArt.Size" type="System.Drawing.Size, System.Drawing"> - <value>140, 204</value> - </data> - <data name="pictureBoxArt.SizeMode" type="System.Windows.Forms.PictureBoxSizeMode, System.Windows.Forms"> - <value>Zoom</value> - </data> - <data name="pictureBoxArt.TabIndex" type="System.Int32, mscorlib"> - <value>12</value> - </data> - <data name=">>pictureBoxArt.Name" xml:space="preserve"> - <value>pictureBoxArt</value> - </data> - <data name=">>pictureBoxArt.Type" xml:space="preserve"> - <value>System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>pictureBoxArt.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>pictureBoxArt.ZOrder" xml:space="preserve"> - <value>9</value> - </data> - <data name="label4.Location" type="System.Drawing.Point, System.Drawing"> - <value>15, 316</value> - </data> - <data name="label4.Size" type="System.Drawing.Size, System.Drawing"> - <value>53, 204</value> - </data> - <data name="label4.TabIndex" type="System.Int32, mscorlib"> - <value>11</value> - </data> - <data name="label4.Text" xml:space="preserve"> - <value>Box art:</value> - </data> - <data name="label4.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing"> - <value>MiddleCenter</value> - </data> - <data name=">>label4.Name" xml:space="preserve"> - <value>label4</value> - </data> - <data name=">>label4.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>label4.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>label4.ZOrder" xml:space="preserve"> - <value>10</value> - </data> - <data name="textBoxArguments.Location" type="System.Drawing.Point, System.Drawing"> - <value>18, 237</value> - </data> - <data name="textBoxArguments.Size" type="System.Drawing.Size, System.Drawing"> - <value>257, 20</value> - </data> - <data name="textBoxArguments.TabIndex" type="System.Int32, mscorlib"> - <value>10</value> - </data> - <data name=">>textBoxArguments.Name" xml:space="preserve"> - <value>textBoxArguments</value> - </data> - <data name=">>textBoxArguments.Type" xml:space="preserve"> - <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>textBoxArguments.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>textBoxArguments.ZOrder" xml:space="preserve"> - <value>11</value> - </data> - <data name="label3.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="label3.Location" type="System.Drawing.Point, System.Drawing"> - <value>15, 220</value> - </data> - <data name="label3.Size" type="System.Drawing.Size, System.Drawing"> - <value>253, 13</value> - </data> - <data name="label3.TabIndex" type="System.Int32, mscorlib"> - <value>9</value> - </data> - <data name="label3.Text" xml:space="preserve"> - <value>Command line arguments (for advanced users only!):</value> - </data> - <data name=">>label3.Name" xml:space="preserve"> - <value>label3</value> - </data> - <data name=">>label3.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>label3.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>label3.ZOrder" xml:space="preserve"> - <value>12</value> - </data> - <data name="textBoxPublisher.Location" type="System.Drawing.Point, System.Drawing"> - <value>71, 186</value> - </data> - <data name="textBoxPublisher.Size" type="System.Drawing.Size, System.Drawing"> - <value>204, 20</value> - </data> - <data name="textBoxPublisher.TabIndex" type="System.Int32, mscorlib"> - <value>8</value> - </data> - <data name=">>textBoxPublisher.Name" xml:space="preserve"> - <value>textBoxPublisher</value> - </data> - <data name=">>textBoxPublisher.Type" xml:space="preserve"> - <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>textBoxPublisher.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>textBoxPublisher.ZOrder" xml:space="preserve"> - <value>13</value> - </data> - <data name="label2.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="label2.Location" type="System.Drawing.Point, System.Drawing"> - <value>15, 189</value> - </data> - <data name="label2.Size" type="System.Drawing.Size, System.Drawing"> - <value>53, 13</value> - </data> - <data name="label2.TabIndex" type="System.Int32, mscorlib"> - <value>7</value> - </data> - <data name="label2.Text" xml:space="preserve"> - <value>Publisher:</value> - </data> - <data name=">>label2.Name" xml:space="preserve"> - <value>label2</value> - </data> - <data name=">>label2.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>label2.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>label2.ZOrder" xml:space="preserve"> - <value>14</value> - </data> - <data name="radioButtonTwo.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="radioButtonTwo.Location" type="System.Drawing.Point, System.Drawing"> - <value>103, 99</value> - </data> - <data name="radioButtonTwo.Size" type="System.Drawing.Size, System.Drawing"> - <value>174, 17</value> - </data> - <data name="radioButtonTwo.TabIndex" type="System.Int32, mscorlib"> - <value>4</value> - </data> - <data name="radioButtonTwo.Text" xml:space="preserve"> - <value>Two players, not simultaneously</value> - </data> - <data name=">>radioButtonTwo.Name" xml:space="preserve"> - <value>radioButtonTwo</value> - </data> - <data name=">>radioButtonTwo.Type" xml:space="preserve"> - <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>radioButtonTwo.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>radioButtonTwo.ZOrder" xml:space="preserve"> - <value>15</value> - </data> - <data name="radioButtonOne.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="radioButtonOne.Location" type="System.Drawing.Point, System.Drawing"> - <value>103, 76</value> - </data> - <data name="radioButtonOne.Size" type="System.Drawing.Size, System.Drawing"> - <value>76, 17</value> - </data> - <data name="radioButtonOne.TabIndex" type="System.Int32, mscorlib"> - <value>3</value> - </data> - <data name="radioButtonOne.Text" xml:space="preserve"> - <value>One player</value> - </data> - <data name=">>radioButtonOne.Name" xml:space="preserve"> - <value>radioButtonOne</value> - </data> - <data name=">>radioButtonOne.Type" xml:space="preserve"> - <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>radioButtonOne.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>radioButtonOne.ZOrder" xml:space="preserve"> - <value>16</value> - </data> - <data name="textBoxName.Location" type="System.Drawing.Point, System.Drawing"> - <value>59, 46</value> - </data> - <data name="textBoxName.Size" type="System.Drawing.Size, System.Drawing"> - <value>216, 20</value> - </data> - <data name="textBoxName.TabIndex" type="System.Int32, mscorlib"> - <value>2</value> - </data> - <data name=">>textBoxName.Name" xml:space="preserve"> - <value>textBoxName</value> - </data> - <data name=">>textBoxName.Type" xml:space="preserve"> - <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>textBoxName.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>textBoxName.ZOrder" xml:space="preserve"> - <value>17</value> - </data> - <data name="labelName.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="labelName.Location" type="System.Drawing.Point, System.Drawing"> - <value>15, 49</value> - </data> - <data name="labelName.Size" type="System.Drawing.Size, System.Drawing"> - <value>38, 13</value> - </data> - <data name="labelName.TabIndex" type="System.Int32, mscorlib"> - <value>1</value> - </data> - <data name="labelName.Text" xml:space="preserve"> - <value>Name:</value> - </data> - <data name=">>labelName.Name" xml:space="preserve"> - <value>labelName</value> - </data> - <data name=">>labelName.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>labelName.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>labelName.ZOrder" xml:space="preserve"> - <value>18</value> - </data> - <data name="labelID.AutoSize" type="System.Boolean, mscorlib"> - <value>True</value> - </data> - <data name="labelID.Location" type="System.Drawing.Point, System.Drawing"> - <value>15, 21</value> - </data> - <data name="labelID.Size" type="System.Drawing.Size, System.Drawing"> - <value>21, 13</value> - </data> - <data name="labelID.TabIndex" type="System.Int32, mscorlib"> - <value>0</value> - </data> - <data name="labelID.Text" xml:space="preserve"> - <value>ID:</value> - </data> - <data name=">>labelID.Name" xml:space="preserve"> - <value>labelID</value> - </data> - <data name=">>labelID.Type" xml:space="preserve"> - <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>labelID.Parent" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>labelID.ZOrder" xml:space="preserve"> - <value>19</value> - </data> - <data name="groupBoxOptions.Location" type="System.Drawing.Point, System.Drawing"> - <value>306, 33</value> - </data> - <data name="groupBoxOptions.Size" type="System.Drawing.Size, System.Drawing"> - <value>293, 529</value> - </data> - <data name="groupBoxOptions.TabIndex" type="System.Int32, mscorlib"> - <value>4</value> - </data> - <data name="groupBoxOptions.Text" xml:space="preserve"> - <value>Game options</value> - </data> - <data name=">>groupBoxOptions.Name" xml:space="preserve"> - <value>groupBoxOptions</value> - </data> - <data name=">>groupBoxOptions.Type" xml:space="preserve"> - <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </data> - <data name=">>groupBoxOptions.Parent" xml:space="preserve"> - <value>$this</value> - </data> - <data name=">>groupBoxOptions.ZOrder" xml:space="preserve"> - <value>7</value> - </data> <data name="label5.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms"> <value>None</value> </data> @@ -1209,7 +675,7 @@ <value>$this</value> </data> <data name=">>label5.ZOrder" xml:space="preserve"> - <value>4</value> + <value>5</value> </data> <data name="buttonAddGames.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms"> <value>None</value> @@ -1236,7 +702,7 @@ <value>$this</value> </data> <data name=">>buttonAddGames.ZOrder" xml:space="preserve"> - <value>3</value> + <value>4</value> </data> <metadata name="statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>109, 17</value> @@ -1263,7 +729,7 @@ <value>$this</value> </data> <data name=">>statusStrip.ZOrder" xml:space="preserve"> - <value>2</value> + <value>3</value> </data> <data name="toolStripStatusConnectionIcon.AutoSize" type="System.Boolean, mscorlib"> <value>False</value> @@ -1356,7 +822,7 @@ <value>$this</value> </data> <data name=">>buttonStart.ZOrder" xml:space="preserve"> - <value>1</value> + <value>2</value> </data> <metadata name="timerCalculateGames.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>473, 17</value> @@ -1364,6 +830,27 @@ <metadata name="timerConnectionCheck.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>775, 17</value> </metadata> + <data name="gameDetail1.Location" type="System.Drawing.Point, System.Drawing"> + <value>306, 18</value> + </data> + <data name="gameDetail1.Size" type="System.Drawing.Size, System.Drawing"> + <value>299, 538</value> + </data> + <data name="gameDetail1.TabIndex" type="System.Int32, mscorlib"> + <value>7</value> + </data> + <data name=">>gameDetail1.Name" xml:space="preserve"> + <value>gameDetail1</value> + </data> + <data name=">>gameDetail1.Type" xml:space="preserve"> + <value>com.clusterrr.hakchi_gui.UI.Components.GameDetail, hakchi, Version=2.0.17.14, Culture=neutral, PublicKeyToken=null</value> + </data> + <data name=">>gameDetail1.Parent" xml:space="preserve"> + <value>$this</value> + </data> + <data name=">>gameDetail1.ZOrder" xml:space="preserve"> + <value>0</value> + </data> <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <value>True</value> </metadata> diff --git a/Manager/GameManager.cs b/Manager/GameManager.cs index 28183241..e7bff70a 100644 --- a/Manager/GameManager.cs +++ b/Manager/GameManager.cs @@ -10,6 +10,16 @@ namespace com.clusterrr.hakchi_gui.Manager { public class GameManager { + public struct CountResult + { + public int SelectedCount; + public long SelectedSize; + public int TotalCount; + public long TotalSize; + } + public delegate void GameListEventHandler(List<NesMiniApplication> e); + public event GameListEventHandler NewGamesAdded; + public event GameListEventHandler GamesRemoved; static NesDefaultGame[] defaultNesGames = new NesDefaultGame[] { new NesDefaultGame { Code = "CLV-P-NAAAE", Name = "Super Mario Bros.", Size = 571031 }, new NesDefaultGame { Code = "CLV-P-NAACE", Name = "Super Mario Bros. 3", Size = 1163285 }, @@ -87,12 +97,94 @@ namespace com.clusterrr.hakchi_gui.Manager private List<NesMiniApplication> gameLibrary = new List<NesMiniApplication>(); private GameManager() { - LoadLibrary(); + + } + public CountResult GetStatistics() + { + CountResult stats = new CountResult(); + stats.SelectedCount = 0; + stats.SelectedSize = 0; + stats.TotalCount = 0; + stats.TotalSize = 0; + + foreach (var game in gameLibrary) + { + if (game is NesMiniApplication) + { + long size = game.Size(); + stats.TotalSize += size; + stats.TotalCount++; + if(game.Selected) + { + stats.SelectedCount++; + stats.SelectedSize += size; + } + + } + + } + return stats; } public IOrderedEnumerable<NesMiniApplication> getAllGames() { return gameLibrary.OrderBy(o => o.Name); } + public void DeleteGames(List<NesMiniApplication> toDelete) + { + foreach(NesMiniApplication game in toDelete) + { + try + { + + Directory.Delete(game.GamePath, true); + gameLibrary.Remove(game); + AppTypeCollection.AppInfo inf = AppTypeCollection.GetAppByClass(game.GetType()); + if (systemClassifiedGames.ContainsKey(inf)) + { + systemClassifiedGames[inf].Remove(game); + } + + + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message + ex.StackTrace); + MessageBox.Show(ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + if (GamesRemoved != null) + { + if (toDelete.Count() > 0) + { + GamesRemoved(toDelete); + } + } + } + public void AddGames(List<NesMiniApplication> newGames) + { + List<NesMiniApplication> reallyAdded = new List<NesMiniApplication>(); + foreach(NesMiniApplication g in newGames) + { + if (!gameLibrary.Contains(g)) + { + gameLibrary.Add(g); + reallyAdded.Add(g); + AppTypeCollection.AppInfo inf = AppTypeCollection.GetAppByClass(g.GetType()); + if (!systemClassifiedGames.ContainsKey(inf)) + { + systemClassifiedGames[inf] = new List<NesMiniApplication>(); + } + systemClassifiedGames[inf].Add(g); + } + } + if (NewGamesAdded != null) + { + if (reallyAdded.Count() > 0) + { + NewGamesAdded(reallyAdded); + } + } + } public void SaveChanges() { var selected = new List<string>(); @@ -124,7 +216,7 @@ namespace com.clusterrr.hakchi_gui.Manager public void ReloadDefault() { string[] selectedGames = ConfigIni.SelectedGames.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - List<NesDefaultGame> toremove = new List<NesDefaultGame>(); + List<NesMiniApplication> toremove = new List<NesMiniApplication>(); foreach (var game in gameLibrary) { if (game.GetType() == typeof(NesDefaultGame)) @@ -136,29 +228,39 @@ namespace com.clusterrr.hakchi_gui.Manager { gameLibrary.Remove(tr); } + if(GamesRemoved!=null) + { + if(toremove.Count() > 0) + { + GamesRemoved(toremove); + } + } AppTypeCollection.AppInfo inf = AppTypeCollection.GetAppByClass(typeof(NesDefaultGame)); if (systemClassifiedGames.ContainsKey(inf)) { systemClassifiedGames[inf].Clear(); } - + List<NesMiniApplication> toAdd = new List<NesMiniApplication>(); foreach (var game in new List<NesDefaultGame>(ConfigIni.ConsoleType == 0 ? defaultNesGames : defaultFamicomGames).OrderBy(o => o.Name)) { game.Selected = selectedGames.Contains(game.Code); - - gameLibrary.Add(game); - - AppTypeCollection.AppInfo inf2 = AppTypeCollection.GetAppByClass(game.GetType()); - if (!systemClassifiedGames.ContainsKey(inf2)) - { - systemClassifiedGames[inf2] = new List<NesMiniApplication>(); - } - systemClassifiedGames[inf2].Add(game); + toAdd.Add(game); + } + if(toAdd.Count()>0) + { + AddGames(toAdd); } + } - private void LoadLibrary() + public void LoadLibrary() { - + if (GamesRemoved != null) + { + if (gameLibrary.Count() > 0) + { + GamesRemoved(gameLibrary); + } + } gameLibrary.Clear(); ReloadDefault(); string[] selectedGames = ConfigIni.SelectedGames.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); @@ -167,7 +269,7 @@ namespace com.clusterrr.hakchi_gui.Manager Directory.CreateDirectory(NesMiniApplication.GamesDirectory); } var gameDirs = Directory.GetDirectories(NesMiniApplication.GamesDirectory); - + List<NesMiniApplication> toAdd = new List<NesMiniApplication>(); foreach (var gameDir in gameDirs) { try @@ -177,15 +279,8 @@ namespace com.clusterrr.hakchi_gui.Manager { var game = NesMiniApplication.FromDirectory(gameDir); game.Selected = selectedGames.Contains(game.Code); - - gameLibrary.Add(game); - - AppTypeCollection.AppInfo inf = AppTypeCollection.GetAppByClass(game.GetType()); - if(!systemClassifiedGames.ContainsKey(inf)) - { - systemClassifiedGames[inf] = new List<NesMiniApplication>(); - } - systemClassifiedGames[inf].Add(game); + toAdd.Add(game); + } catch (FileNotFoundException ex) // Remove bad directories if any { @@ -200,6 +295,11 @@ namespace com.clusterrr.hakchi_gui.Manager continue; } } + if(toAdd.Count() >0) + { + AddGames(toAdd); + } + } } } diff --git a/Properties/app.manifest b/Properties/app.manifest index c18985e1..7776278c 100644 --- a/Properties/app.manifest +++ b/Properties/app.manifest @@ -1,54 +1,54 @@ -<?xml version="1.0" encoding="utf-8"?>
-<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
- <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
- <security>
- <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
- <!-- UAC Manifest Options
- If you want to change the Windows User Account Control level replace the
- requestedExecutionLevel node with one of the following.
-
- <requestedExecutionLevel level="asInvoker" uiAccess="false" />
- <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
- <requestedExecutionLevel level="highestAvailable" uiAccess="false" />
-
- Specifying requestedExecutionLevel node will disable file and registry virtualization.
- If you want to utilize File and Registry Virtualization for backward
- compatibility then delete the requestedExecutionLevel node.
- -->
- <requestedExecutionLevel level="asInvoker" uiAccess="false" />
- </requestedPrivileges>
- <applicationRequestMinimum>
- <defaultAssemblyRequest permissionSetReference="Custom" />
- <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
- </applicationRequestMinimum>
- </security>
- </trustInfo>
- <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
- <application>
- <!-- A list of all Windows versions that this application is designed to work with.
- Windows will automatically select the most compatible environment.-->
- <!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node-->
- <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->
- <!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
- <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
- <!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node-->
- <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->
- <!-- If your application is designed to work with Windows 8.1, uncomment the following supportedOS node-->
- <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>-->
- </application>
- </compatibility>
- <!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
- <!-- <dependency>
- <dependentAssembly>
- <assemblyIdentity
- type="win32"
- name="Microsoft.Windows.Common-Controls"
- version="6.0.0.0"
- processorArchitecture="*"
- publicKeyToken="6595b64144ccf1df"
- language="*"
- />
- </dependentAssembly>
- </dependency>-->
+<?xml version="1.0" encoding="utf-8"?> +<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <assemblyIdentity version="1.0.0.0" name="MyApplication.app" /> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> + <!-- UAC Manifest Options + If you want to change the Windows User Account Control level replace the + requestedExecutionLevel node with one of the following. + + <requestedExecutionLevel level="asInvoker" uiAccess="false" /> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> + <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> + + Specifying requestedExecutionLevel node will disable file and registry virtualization. + If you want to utilize File and Registry Virtualization for backward + compatibility then delete the requestedExecutionLevel node. + --> + <requestedExecutionLevel level="asInvoker" uiAccess="false" /> + </requestedPrivileges> + <applicationRequestMinimum> + <defaultAssemblyRequest permissionSetReference="Custom" /> + <PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" /> + </applicationRequestMinimum> + </security> + </trustInfo> + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- A list of all Windows versions that this application is designed to work with. + Windows will automatically select the most compatible environment.--> + <!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node--> + <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>--> + <!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node--> + <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>--> + <!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node--> + <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>--> + <!-- If your application is designed to work with Windows 8.1, uncomment the following supportedOS node--> + <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>--> + </application> + </compatibility> + <!-- Enable themes for Windows common controls and dialogs (Windows XP and later) --> + <!-- <dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="*" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + </dependency>--> </asmv1:assembly>
\ No newline at end of file diff --git a/UI/Components/GameDetail.Designer.cs b/UI/Components/GameDetail.Designer.cs index 7f46a324..860fdb1e 100644 --- a/UI/Components/GameDetail.Designer.cs +++ b/UI/Components/GameDetail.Designer.cs @@ -49,6 +49,7 @@ this.textBoxName = new System.Windows.Forms.TextBox(); this.labelName = new System.Windows.Forms.Label(); this.labelID = new System.Windows.Forms.Label(); + this.openFileDialogImage = new System.Windows.Forms.OpenFileDialog(); this.groupBoxOptions.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxArt)).BeginInit(); this.SuspendLayout(); @@ -161,6 +162,7 @@ this.buttonGoogle.TabIndex = 15; this.buttonGoogle.Text = "Google"; this.buttonGoogle.UseVisualStyleBackColor = true; + this.buttonGoogle.Click += new System.EventHandler(this.buttonGoogle_Click); // // buttonBrowseImage // @@ -171,6 +173,7 @@ this.buttonBrowseImage.TabIndex = 13; this.buttonBrowseImage.Text = "Browse"; this.buttonBrowseImage.UseVisualStyleBackColor = true; + this.buttonBrowseImage.Click += new System.EventHandler(this.buttonBrowseImage_Click); // // pictureBoxArt // @@ -281,6 +284,10 @@ this.labelID.TabIndex = 0; this.labelID.Text = "ID:"; // + // openFileDialogImage + // + this.openFileDialogImage.FileName = "openFileDialog1"; + // // GameDetail // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -318,5 +325,6 @@ private System.Windows.Forms.TextBox textBoxName; private System.Windows.Forms.Label labelName; private System.Windows.Forms.Label labelID; + private System.Windows.Forms.OpenFileDialog openFileDialogImage; } } diff --git a/UI/Components/GameDetail.cs b/UI/Components/GameDetail.cs index ad278430..397f37b6 100644 --- a/UI/Components/GameDetail.cs +++ b/UI/Components/GameDetail.cs @@ -138,5 +138,36 @@ namespace com.clusterrr.hakchi_gui.UI.Components if (lFrm.ShowDialog() == System.Windows.Forms.DialogResult.OK) textBoxGameGenie.Text = nesGame.GameGenie; } + + public void SetImageForSelectedGame(string fileName) + { + + if (currentApp == null || !(currentApp is NesMiniApplication)) return; + var game = (currentApp as NesMiniApplication); + game.Image = NesMiniApplication.LoadBitmap(fileName); + SetGame(game); + + } + + private void buttonBrowseImage_Click(object sender, EventArgs e) + { + openFileDialogImage.Filter = Properties.Resources.Images + " (*.bmp;*.png;*.jpg;*.jpeg;*.gif)|*.bmp;*.png;*.jpg;*.jpeg;*.gif|" + Properties.Resources.AllFiles + "|*.*"; + if (openFileDialogImage.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + SetImageForSelectedGame(openFileDialogImage.FileName); + } + } + + private void buttonGoogle_Click(object sender, EventArgs e) + { + if (currentApp == null || !(currentApp is NesMiniApplication)) return; + var game = (currentApp as NesMiniApplication); + var googler = new ImageGooglerForm(game); + if (googler.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + game.Image = googler.Result; + SetGame(game); + } + } } } diff --git a/UI/Components/GameDetail.resx b/UI/Components/GameDetail.resx index 7080a7d1..14700763 100644 --- a/UI/Components/GameDetail.resx +++ b/UI/Components/GameDetail.resx @@ -117,4 +117,7 @@ <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> + <metadata name="openFileDialogImage.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> </root>
\ No newline at end of file diff --git a/UI/Components/GameSelecter.Designer.cs b/UI/Components/GameSelecter.Designer.cs index d10f7a79..9d2b7f17 100644 --- a/UI/Components/GameSelecter.Designer.cs +++ b/UI/Components/GameSelecter.Designer.cs @@ -28,23 +28,23 @@ /// </summary> private void InitializeComponent() { - this.tvGameSelecter = new System.Windows.Forms.TreeView(); + this.checkedListBox1 = new System.Windows.Forms.CheckedListBox(); this.SuspendLayout(); // - // tvGameSelecter + // checkedListBox1 // - this.tvGameSelecter.CheckBoxes = true; - this.tvGameSelecter.Dock = System.Windows.Forms.DockStyle.Fill; - this.tvGameSelecter.Location = new System.Drawing.Point(0, 0); - this.tvGameSelecter.Name = "tvGameSelecter"; - this.tvGameSelecter.Size = new System.Drawing.Size(495, 607); - this.tvGameSelecter.TabIndex = 0; + this.checkedListBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.checkedListBox1.FormattingEnabled = true; + this.checkedListBox1.Location = new System.Drawing.Point(0, 0); + this.checkedListBox1.Name = "checkedListBox1"; + this.checkedListBox1.Size = new System.Drawing.Size(495, 607); + this.checkedListBox1.TabIndex = 0; // // GameSelecter // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.tvGameSelecter); + this.Controls.Add(this.checkedListBox1); this.Name = "GameSelecter"; this.Size = new System.Drawing.Size(495, 607); this.ResumeLayout(false); @@ -53,6 +53,6 @@ #endregion - private System.Windows.Forms.TreeView tvGameSelecter; + private System.Windows.Forms.CheckedListBox checkedListBox1; } } diff --git a/UI/Components/GameSelecter.cs b/UI/Components/GameSelecter.cs index 749dfde6..605ad074 100644 --- a/UI/Components/GameSelecter.cs +++ b/UI/Components/GameSelecter.cs @@ -18,102 +18,6 @@ namespace com.clusterrr.hakchi_gui.UI.Components InitializeComponent(); } - public void RefreshGames() - { - string[] selectedGames = ConfigIni.SelectedGames.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - if(!System.IO.Directory.Exists(NesMiniApplication.GamesDirectory)) - { - Directory.CreateDirectory(NesMiniApplication.GamesDirectory); - } - var gameDirs = Directory.GetDirectories(NesMiniApplication.GamesDirectory); - var games = new List<NesMiniApplication>(); - foreach (var gameDir in gameDirs) - { - try - { - // Removing empty directories without errors - try - { - var game = NesMiniApplication.FromDirectory(gameDir); - games.Add(game); - } - catch (FileNotFoundException ex) // Remove bad directories if any - { - Debug.WriteLine(ex.Message + ex.StackTrace); - Directory.Delete(gameDir, true); - } - } - catch (Exception ex) - { - Debug.WriteLine(ex.Message + ex.StackTrace); - MessageBox.Show(this, ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - continue; - } - } - var gamesSorted = games.OrderBy(o => o.Name); - - tvGameSelecter.Nodes.Clear(); - TreeNode tn = new TreeNode(Resources.Default30games); - tn.Checked = selectedGames.Contains("default"); - tvGameSelecter.Nodes.Add(tn); - Dictionary<string, TreeNode> consolesTreeNode = new Dictionary<string, TreeNode>(); - foreach (var game in gamesSorted) - { - if(!consolesTreeNode.ContainsKey(AppTypeCollection.GetAppByClass(game.GetType()).SystemName)) - { - AppTypeCollection.AppInfo inf = AppTypeCollection.GetAppByClass(game.GetType()); - TreeNode systemNode = new TreeNode(inf.SystemName); - systemNode.Tag = inf; - consolesTreeNode[inf.SystemName]= systemNode; - tvGameSelecter.Nodes.Add(systemNode); - - } - TreeNode gameNode = new TreeNode(game.Name); - gameNode.Tag = game; - gameNode.Checked = selectedGames.Contains(game.Code); - consolesTreeNode[AppTypeCollection.GetAppByClass(game.GetType()).SystemName].Nodes.Add(gameNode); - } - // RecalculateSelectedGames(); - // ShowSelected(); - } - /* Debug.WriteLine("Loading games"); - var selected = ConfigIni.SelectedGames.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - Directory.CreateDirectory(NesMiniApplication.GamesDirectory); - var gameDirs = Directory.GetDirectories(NesMiniApplication.GamesDirectory); - var games = new List<NesMiniApplication>(); - foreach (var gameDir in gameDirs) - { - try - { - // Removing empty directories without errors - try - { - var game = NesMiniApplication.FromDirectory(gameDir); - games.Add(game); - } - catch (FileNotFoundException ex) // Remove bad directories if any - { - Debug.WriteLine(ex.Message + ex.StackTrace); - Directory.Delete(gameDir, true); - } - } - catch (Exception ex) - { - Debug.WriteLine(ex.Message + ex.StackTrace); - MessageBox.Show(this, ex.Message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); - continue; - } - } - - var gamesSorted = games.OrderBy(o => o.Name); - checkedListBoxGames.Items.Clear(); - checkedListBoxGames.Items.Add(Resources.Default30games, selected.Contains("default")); - foreach (var game in gamesSorted) - { - checkedListBoxGames.Items.Add(game, selected.Contains(game.Code)); - } - RecalculateSelectedGames(); - ShowSelected();*/ } } diff --git a/WorkerForm.cs b/WorkerForm.cs index de17240f..b0a64f13 100644 --- a/WorkerForm.cs +++ b/WorkerForm.cs @@ -1,1190 +1,1190 @@ -using com.clusterrr.Famicom;
-using com.clusterrr.FelLib;
-using com.clusterrr.hakchi_gui.Properties;
-using com.clusterrr.util;
-using SevenZip;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Windows.Forms;
-
-namespace com.clusterrr.hakchi_gui
-{
- public partial class WorkerForm : Form
- {
- public enum Tasks { DumpKernel, FlashKernel, Memboot, UploadGames, DownloadAllCovers, AddGames };
- public Tasks Task;
- //public string UBootDump;
- public string KernelDump;
- public string Mod = null;
- public Dictionary<string, string> Config = null;
- public NesMenuCollection Games;
- public IEnumerable<string> hmodsInstall;
- public IEnumerable<string> hmodsUninstall;
- public IEnumerable<string> GamesToAdd;
- public NesMenuCollection.SplitStyle FoldersMode = NesMenuCollection.SplitStyle.Auto;
- public int MaxGamesPerFolder = 35;
- public MainForm MainForm;
- Thread thread = null;
- Fel fel = null;
-
- const UInt16 vid = 0x1F3A;
- const UInt16 pid = 0xEFE8;
-
- readonly string baseDirectoryInternal;
- readonly string baseDirectoryExternal;
- readonly string fes1Path;
- readonly string ubootPath;
- readonly string tempDirectory;
- readonly string kernelDirectory;
- readonly string initramfs_cpio;
- readonly string initramfs_cpioPatched;
- readonly string ramfsDirectory;
- readonly string hakchiDirectory;
- readonly string modsDirectory;
- readonly string[] hmodDirectories;
- readonly string toolsDirectory;
- readonly string kernelPatched;
- readonly string ramdiskPatched;
- readonly string tempHmodsDirectory;
- readonly string cloverconDriverPath;
- readonly string argumentsFilePath;
- readonly string transferDirectory;
- string tempGamesDirectory;
- //string originalGamesConfigDirectory;
- //string hiddenPath;
- string[] correctKernels;
- const long maxCompressedsRamfsSize = 30 * 1024 * 1024;
- string selectedFile = null;
- public NesMiniApplication[] addedApplications;
- public static int NandCTotal, NandCUsed, NandCFree, WritedGamesSize, SaveStatesSize;
- public const long ReservedMemory = 10;
-
- public WorkerForm()
- {
- InitializeComponent();
- DialogResult = DialogResult.None;
- baseDirectoryInternal = Program.BaseDirectoryInternal;
- baseDirectoryExternal = Program.BaseDirectoryExternal;
- fes1Path = Path.Combine(Path.Combine(baseDirectoryInternal, "data"), "fes1.bin");
- ubootPath = Path.Combine(Path.Combine(baseDirectoryInternal, "data"), "uboot.bin");
-#if DEBUG
- tempDirectory = Path.Combine(baseDirectoryInternal, "temp");
-#else
- tempDirectory = Path.Combine(Path.GetTempPath(), "hakchi-temp");
-#endif
- kernelDirectory = Path.Combine(tempDirectory, "kernel");
- initramfs_cpio = Path.Combine(kernelDirectory, "initramfs.cpio");
- initramfs_cpioPatched = Path.Combine(kernelDirectory, "initramfs_mod.cpio");
- ramfsDirectory = Path.Combine(kernelDirectory, "initramfs");
- hakchiDirectory = Path.Combine(ramfsDirectory, "hakchi");
- modsDirectory = Path.Combine(baseDirectoryInternal, "mods");
- hmodDirectories = new string[]{
- Path.Combine(baseDirectoryExternal, "user_mods"),
- Path.Combine(modsDirectory, "hmods")
- };
- toolsDirectory = Path.Combine(baseDirectoryInternal, "tools");
- kernelPatched = Path.Combine(kernelDirectory, "patched_kernel.img");
- ramdiskPatched = Path.Combine(kernelDirectory, "kernel.img-ramdisk_mod.gz");
- cloverconDriverPath = Path.Combine(hakchiDirectory, "clovercon.ko");
- argumentsFilePath = Path.Combine(hakchiDirectory, "extra_args");
- transferDirectory = Path.Combine(hakchiDirectory, "transfer");
- tempHmodsDirectory = Path.Combine(transferDirectory, "hmod");
- correctKernels
- = new string[] {
- "5cfdca351484e7025648abc3b20032ff", "07bfb800beba6ef619c29990d14b5158", // NES Mini
- "ac8144c3ea4ab32e017648ee80bdc230" // Famicom Mini
- };
- }
-
- public DialogResult Start()
- {
- SetProgress(0, 1);
- thread = new Thread(StartThread);
- thread.IsBackground = true;
- thread.SetApartmentState(ApartmentState.STA);
- thread.Start();
- return ShowDialog();
- }
-
- DialogResult WaitForFelFromThread()
- {
- if (InvokeRequired)
- {
- return (DialogResult)Invoke(new Func<DialogResult>(WaitForFelFromThread));
- }
- SetStatus(Resources.WaitingForDevice);
- if (fel != null)
- fel.Close();
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused);
- var result = WaitingFelForm.WaitForDevice(vid, pid, this);
- if (result)
- {
- fel = new Fel();
- if (!File.Exists(fes1Path)) throw new FileNotFoundException(fes1Path + " not found");
- if (!File.Exists(ubootPath)) throw new FileNotFoundException(ubootPath + " not found");
- fel.Fes1Bin = File.ReadAllBytes(fes1Path);
- fel.UBootBin = File.ReadAllBytes(ubootPath);
- fel.Open(vid, pid);
- SetStatus(Resources.UploadingFes1);
- fel.InitDram(true);
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- return DialogResult.OK;
- }
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- return DialogResult.Abort;
- }
- DialogResult WaitForClovershellFromThread()
- {
- if (InvokeRequired)
- {
- return (DialogResult)Invoke(new Func<DialogResult>(WaitForClovershellFromThread));
- }
- SetStatus(Resources.WaitingForDevice);
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused);
- var result = WaitingClovershellForm.WaitForDevice(this);
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- if (result)
- return DialogResult.OK;
- else return DialogResult.Abort;
- }
-
- private delegate DialogResult MessageBoxFromThreadDelegate(IWin32Window owner, string text, string caption, MessageBoxButtons buttons,
- MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool tweak);
- DialogResult MessageBoxFromThread(IWin32Window owner, string text, string caption, MessageBoxButtons buttons,
- MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool tweak)
- {
- if (InvokeRequired)
- {
- return (DialogResult)Invoke(new MessageBoxFromThreadDelegate(MessageBoxFromThread),
- new object[] { owner, text, caption, buttons, icon, defaultButton, tweak });
- }
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused);
- if (tweak) MessageBoxManager.Register(); // Tweak button names
- var result = MessageBox.Show(owner, text, caption, buttons, icon, defaultButton);
- if (tweak) MessageBoxManager.Unregister();
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- return result;
- }
-
- DialogResult FoldersManagerFromThread(NesMenuCollection collection)
- {
- if (InvokeRequired)
- {
- return (DialogResult)Invoke(new Func<NesMenuCollection, DialogResult>(FoldersManagerFromThread), new object[] { collection });
- }
- var constructor = new FoldersManagerForm(collection, MainForm);
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused);
- var result = constructor.ShowDialog();
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- return result;
- }
-
- DialogResult SelectFileFromThread(string[] files)
- {
- if (InvokeRequired)
- {
- return (DialogResult)Invoke(new Func<string[], DialogResult>(SelectFileFromThread), new object[] { files });
- }
- var form = new SelectFileForm(files);
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused);
- var result = form.ShowDialog();
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- if (form.listBoxFiles.SelectedItem != null)
- selectedFile = form.listBoxFiles.SelectedItem.ToString();
- else
- selectedFile = null;
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- return result;
- }
-
- public void StartThread()
- {
- Thread.CurrentThread.CurrentUICulture = new CultureInfo(ConfigIni.Language);
- SetProgress(0, 1);
- try
- {
- DialogResult = DialogResult.None;
- Debug.WriteLine("Executing task: " + Task.ToString());
- switch (Task)
- {
- case Tasks.DumpKernel:
- DoKernelDump();
- break;
- case Tasks.FlashKernel:
- FlashKernel();
- break;
- case Tasks.UploadGames:
- UploadGames();
- break;
- case Tasks.Memboot:
- Memboot();
- break;
- case Tasks.DownloadAllCovers:
- DownloadAllCovers();
- break;
- case Tasks.AddGames:
- AddGames(GamesToAdd);
- break;
- }
- if (DialogResult == DialogResult.None)
- DialogResult = DialogResult.OK;
- }
- catch (ThreadAbortException) { }
- catch (Exception ex)
- {
- ShowError(ex);
- }
- finally
- {
- thread = null;
- if (fel != null)
- {
- fel.Close();
- fel = null;
- }
- GC.Collect();
- }
- }
-
- void SetStatus(string status)
- {
- if (Disposing) return;
- try
- {
- if (InvokeRequired)
- {
- Invoke(new Action<string>(SetStatus), new object[] { status });
- return;
- }
- labelStatus.Text = status;
- }
- catch { }
- }
-
- void SetProgress(int value, int max)
- {
- if (Disposing) return;
- try
- {
- if (InvokeRequired)
- {
- Invoke(new Action<int, int>(SetProgress), new object[] { value, max });
- if (value == max)
- Thread.Sleep(1000);
- return;
- }
- if (value > max) value = max;
- progressBar.Maximum = max;
- progressBar.Value = value;
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- TaskbarProgress.SetValue(this, value, max);
- }
- catch { }
- }
-
- void ShowError(Exception ex, bool dontStop = false)
- {
- if (Disposing) return;
- try
- {
- if (InvokeRequired)
- {
- Invoke(new Action<Exception, bool>(ShowError), new object[] { ex, dontStop });
- return;
- }
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Error);
- var message = ex.Message;
-#if DEBUG
- message += ex.StackTrace;
-#endif
- Debug.WriteLine(ex.Message + ex.StackTrace);
- //if (ex is MadWizard.WinUSBNet.USBException) // TODO
- // MessageBox.Show(this, message + "\r\n" + Resources.PleaseTryAgainUSB, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
- //else
- MessageBox.Show(this, message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- if (!dontStop)
- {
- thread = null;
- Close();
- }
- }
- catch { }
- }
-
- void ShowMessage(string text, string title)
- {
- if (Disposing) return;
- try
- {
- if (InvokeRequired)
- {
- Invoke(new Action<string, string>(ShowMessage), new object[] { text, title });
- return;
- }
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused);
- MessageBox.Show(this, text, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal);
- }
- catch { }
- }
-
- public void DoKernelDump()
- {
- int progress = 0;
- const int maxProgress = 80;
- if (WaitForFelFromThread() != DialogResult.OK)
- {
- DialogResult = DialogResult.Abort;
- return;
- }
- progress += 5;
- SetProgress(progress, maxProgress);
-
- SetStatus(Resources.DumpingKernel);
- var kernel = fel.ReadFlash(Fel.kernel_base_f, Fel.sector_size * 0x20,
- delegate(Fel.CurrentAction action, string command)
- {
- switch (action)
- {
- case Fel.CurrentAction.RunningCommand:
- SetStatus(Resources.ExecutingCommand + " " + command);
- break;
- case Fel.CurrentAction.ReadingMemory:
- SetStatus(Resources.DumpingKernel);
- break;
- }
- progress++;
- SetProgress(progress, maxProgress);
- }
- );
-
- var size = CalcKernelSize(kernel);
- if (size == 0 || size > Fel.kernel_max_size)
- throw new Exception(Resources.InvalidKernelSize + " " + size);
- if (kernel.Length > size)
- {
- var sm_kernel = new byte[size];
- Array.Copy(kernel, 0, sm_kernel, 0, size);
- kernel = sm_kernel;
- }
-
- SetProgress(maxProgress, maxProgress);
- SetStatus(Resources.Done);
-
- var md5 = System.Security.Cryptography.MD5.Create();
- var hash = BitConverter.ToString(md5.ComputeHash(kernel)).Replace("-", "").ToLower();
- if (!correctKernels.Contains(hash))
- {
- if (MessageBoxFromThread(this, Resources.MD5Failed + " " + hash + "\r\n" + Resources.MD5Failed2 +
- "\r\n" + Resources.DoYouWantToContinue, Resources.Warning, MessageBoxButtons.YesNo,
- MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, false)
- == DialogResult.No)
- {
- DialogResult = DialogResult.Abort;
- return;
- }
- }
-
- Directory.CreateDirectory(Path.GetDirectoryName(KernelDump));
- File.WriteAllBytes(KernelDump, kernel);
- }
-
- public void FlashKernel()
- {
- int progress = 0;
- int maxProgress = 115 + (string.IsNullOrEmpty(Mod) ? 0 : 30) +
- ((hmodsInstall != null && hmodsInstall.Count() > 0) ? 75 : 0);
- var hmods = hmodsInstall;
- hmodsInstall = null;
- if (WaitForFelFromThread() != DialogResult.OK)
- {
- DialogResult = DialogResult.Abort;
- return;
- }
- progress += 5;
- SetProgress(progress, maxProgress);
-
- byte[] kernel;
- if (!string.IsNullOrEmpty(Mod))
- {
- kernel = CreatePatchedKernel();
- progress += 5;
- SetProgress(progress, maxProgress);
- }
- else
- kernel = File.ReadAllBytes(KernelDump);
- var size = CalcKernelSize(kernel);
- if (size > kernel.Length || size > Fel.kernel_max_size)
- throw new Exception(Resources.InvalidKernelSize + " " + size);
-
- size = (size + Fel.sector_size - 1) / Fel.sector_size;
- size = size * Fel.sector_size;
- if (kernel.Length != size)
- {
- var newK = new byte[size];
- Array.Copy(kernel, newK, kernel.Length);
- kernel = newK;
- }
-
- fel.WriteFlash(Fel.kernel_base_f, kernel,
- delegate(Fel.CurrentAction action, string command)
- {
- switch (action)
- {
- case Fel.CurrentAction.RunningCommand:
- SetStatus(Resources.ExecutingCommand + " " + command);
- break;
- case Fel.CurrentAction.WritingMemory:
- SetStatus(Resources.UploadingKernel);
- break;
- }
- progress++;
- SetProgress(progress, maxProgress);
- }
- );
- var r = fel.ReadFlash((UInt32)Fel.kernel_base_f, (UInt32)kernel.Length,
- delegate(Fel.CurrentAction action, string command)
- {
- switch (action)
- {
- case Fel.CurrentAction.RunningCommand:
- SetStatus(Resources.ExecutingCommand + " " + command);
- break;
- case Fel.CurrentAction.ReadingMemory:
- SetStatus(Resources.Verifying);
- break;
- }
- progress++;
- SetProgress(progress, maxProgress);
- }
- );
- if (!kernel.SequenceEqual(r))
- throw new Exception(Resources.VerifyFailed);
-
- hmodsInstall = hmods;
- if (hmodsInstall != null && hmodsInstall.Count() > 0)
- {
- Memboot(maxProgress, progress); // Lets install some mods
- }
- else
- {
- var shutdownCommand = string.Format("shutdown", Fel.kernel_base_m);
- SetStatus(Resources.ExecutingCommand + " " + shutdownCommand);
- fel.RunUbootCmd(shutdownCommand, true);
- SetStatus(Resources.Done);
- SetProgress(maxProgress, maxProgress);
- }
- }
-
- public static void GetMemoryStats()
- {
- var clovershell = MainForm.Clovershell;
- var nandc = clovershell.ExecuteSimple("df /dev/nandc | tail -n 1 | awk '{ print $2 \" | \" $3 \" | \" $4 }'", 500, true).Split('|');
- WritedGamesSize = int.Parse(clovershell.ExecuteSimple("mkdir -p /var/lib/hakchi/rootfs/usr/share/games/ && du -s /var/lib/hakchi/rootfs/usr/share/games/ | awk '{ print $1 }'", 1000, true)) * 1024;
- SaveStatesSize = int.Parse(clovershell.ExecuteSimple("mkdir -p /var/lib/clover/profiles/0/ && du -s /var/lib/clover/profiles/0/ | awk '{ print $1 }'", 1000, true)) * 1024;
- NandCTotal = int.Parse(nandc[0]) * 1024;
- NandCUsed = int.Parse(nandc[1]) * 1024;
- NandCFree = int.Parse(nandc[2]) * 1024;
- Debug.WriteLine(string.Format("NANDC size: {0:F1}MB, used: {1:F1}MB, free: {2:F1}MB", NandCTotal / 1024.0 / 1024.0, NandCUsed / 1024.0 / 1024.0, NandCFree / 1024.0 / 1024.0));
- Debug.WriteLine(string.Format("Used by games: {0:F1}MB", WritedGamesSize / 1024.0 / 1024.0));
- Debug.WriteLine(string.Format("Used by save-states: {0:F1}MB", SaveStatesSize / 1024.0 / 1024.0));
- Debug.WriteLine(string.Format("Used by other files (mods, configs, etc.): {0:F1}MB", (NandCUsed - WritedGamesSize - SaveStatesSize) / 1024.0 / 1024.0));
- Debug.WriteLine(string.Format("Available for games: {0:F1}MB", (NandCFree + WritedGamesSize) / 1024.0 / 1024.0));
- }
-
- public static void ShowSplashScreen()
- {
- var clovershell = MainForm.Clovershell;
- var splashScreenPath = Path.Combine(Path.Combine(Program.BaseDirectoryInternal, "data"), "splash.gz");
- clovershell.ExecuteSimple("pkill -KILL clover-mcp");
- clovershell.ExecuteSimple("pkill -KILL ReedPlayer-Clover");
- clovershell.ExecuteSimple("pkill -KILL kachikachi");
- if (File.Exists(splashScreenPath))
- {
- using (var splash = new FileStream(splashScreenPath, FileMode.Open))
- {
- clovershell.Execute("gunzip -c - > /dev/fb0", splash, null, null, 3000);
- }
- }
- }
-
- public void UploadGames()
- {
- const string gamesPath = "/usr/share/games/nes/kachikachi";
- const string rootFsPath = "/var/lib/hakchi/rootfs";
- const string installPath = "/var/lib/hakchi";
- int progress = 0;
- int maxProgress = 400;
- if (Games == null || Games.Count == 0)
- throw new Exception("there are no games");
- SetStatus(Resources.BuildingFolders);
- if (FoldersMode == NesMenuCollection.SplitStyle.Custom)
- {
- if (FoldersManagerFromThread(Games) != System.Windows.Forms.DialogResult.OK)
- {
- DialogResult = DialogResult.Abort;
- return;
- }
- Games.AddBack();
- }
- else Games.Split(FoldersMode, MaxGamesPerFolder);
- progress += 5;
- SetProgress(progress, maxProgress);
-
- var clovershell = MainForm.Clovershell;
- try
- {
- if (WaitForClovershellFromThread() != DialogResult.OK)
- {
- DialogResult = DialogResult.Abort;
- return;
- }
- progress += 5;
- SetProgress(progress, maxProgress);
-
- ShowSplashScreen();
-
- SetStatus(Resources.BuildingFolders);
- if (Directory.Exists(tempDirectory))
- Directory.Delete(tempDirectory, true);
- Directory.CreateDirectory(tempDirectory);
- // Games!
- tempGamesDirectory = Path.Combine(tempDirectory, "games");
- Directory.CreateDirectory(tempDirectory);
- Directory.CreateDirectory(tempGamesDirectory);
- Dictionary<string, string> originalGames = new Dictionary<string, string>();
- var stats = new GamesTreeStats();
- AddMenu(Games, originalGames, stats);
- progress += 5;
- SetProgress(progress, maxProgress);
-
- GetMemoryStats();
- var maxGamesSize = (NandCFree + WritedGamesSize) - ReservedMemory * 1024 * 1024;
- if (stats.TotalSize > maxGamesSize)
- {
- throw new Exception(string.Format(Resources.MemoryFull, stats.TotalSize / 1024 / 1024) + "\r\n\r\n" +
- string.Format(Resources.MemoryStats.Replace("|", "\r\n"),
- NandCTotal / 1024.0 / 1024.0,
- (NandCFree + WritedGamesSize - ReservedMemory * 1024 * 1024) / 1024 / 1024,
- SaveStatesSize / 1024.0 / 1024.0,
- (NandCUsed - WritedGamesSize - SaveStatesSize) / 1024.0 / 1024.0));
- }
-
- int startProgress = progress;
- using (var gamesTar = new TarStream(tempGamesDirectory))
- {
- maxProgress = (int)(gamesTar.Length / 1024 / 1024 + 20 + originalGames.Count() * 2);
- SetProgress(progress, maxProgress);
-
- clovershell.ExecuteSimple(string.Format("umount {0}", gamesPath));
- clovershell.ExecuteSimple(string.Format("rm -rf {0}{1}/CLV-* {0}{1}/??? {2}/menu", rootFsPath, gamesPath, installPath), 5000, true);
-
- if (gamesTar.Length > 0)
- {
- gamesTar.OnReadProgress += delegate(long pos, long len)
- {
- progress = (int)(startProgress + pos / 1024 / 1024);
- SetProgress(progress, maxProgress);
- };
-
- SetStatus(Resources.UploadingGames);
- clovershell.Execute(string.Format("tar -xvC {0}{1}", rootFsPath, gamesPath), gamesTar, null, null, 30000, true);
- }
- }
-
- SetStatus(Resources.UploadingOriginalGames);
- startProgress = progress;
- foreach (var originalCode in originalGames.Keys)
- {
- clovershell.ExecuteSimple(string.Format(@"mkdir -p ""{2}{3}/{1}/{0}/"" && rsync -ac ""{3}/{0}/"" ""{2}{3}/{1}/{0}/"" && sed -i -e 's/\/usr\/bin\/clover-kachikachi/\/bin\/clover-kachikachi-wr/g' ""{2}{3}/{1}/{0}/{0}.desktop""", originalCode, originalGames[originalCode], rootFsPath, gamesPath), 5000, true);
- progress += 2;
- SetProgress(progress, maxProgress);
- };
-
- SetStatus(Resources.UploadingConfig);
- SyncConfig(Config);
-#if !DEBUG
- Directory.Delete(tempDirectory, true);
-#endif
- SetStatus(Resources.Done);
- SetProgress(maxProgress, maxProgress);
- }
- finally
- {
- try
- {
- if (clovershell.IsOnline)
- clovershell.ExecuteSimple("reboot", 100);
- }
- catch { }
- }
- }
-
- public static void SyncConfig(Dictionary<string, string> Config, bool reboot = false)
- {
- var clovershell = MainForm.Clovershell;
-
- // Writing config
- var config = new MemoryStream();
- if (Config != null && Config.Count > 0)
- {
- foreach (var key in Config.Keys)
- {
- var data = Encoding.UTF8.GetBytes(string.Format("cfg_{0}='{1}'\n", key, Config[key].Replace(@"'", @"\'")));
- config.Write(data, 0, data.Length);
- }
- }
- clovershell.Execute("cat > /tmp/config", config, null, null, 1000, true);
- clovershell.Execute("source /etc/preinit && script_init && source /tmp/config && source $preinit.d/pffff_config", null, null, null, 30000, true);
- config.Dispose();
- if (reboot)
- {
- try
- {
- clovershell.ExecuteSimple("reboot", 100);
- }
- catch { }
- }
- }
-
- public static Image TakeScreenshot()
- {
- var clovershell = MainForm.Clovershell;
- var screenshot = new Bitmap(1280, 720, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
- var rawStream = new MemoryStream();
- clovershell.Execute("cat /dev/fb0", null, rawStream, null, 1000, true);
- var raw = rawStream.ToArray();
- BitmapData data = screenshot.LockBits(
- new Rectangle(0, 0, screenshot.Width, screenshot.Height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
-
- int rawOffset = 0;
- unsafe
- {
- for (int y = 0; y < screenshot.Height; ++y)
- {
- byte* row = (byte*)data.Scan0 + (y * data.Stride);
- int columnOffset = 0;
- for (int x = 0; x < screenshot.Width; ++x)
- {
- row[columnOffset] = raw[rawOffset];
- row[columnOffset + 1] = raw[rawOffset + 1];
- row[columnOffset + 2] = raw[rawOffset + 2];
-
- columnOffset += 3;
- rawOffset += 4;
- }
- }
- }
- screenshot.UnlockBits(data);
- return screenshot;
- }
-
- public void Memboot(int maxProgress = -1, int progress = 0)
- {
- SetProgress(progress, maxProgress < 0 ? 1000 : maxProgress);
- // Connecting to NES Mini
- if (WaitForFelFromThread() != DialogResult.OK)
- {
- DialogResult = DialogResult.Abort;
- return;
- }
- progress += 5;
- SetProgress(progress, maxProgress > 0 ? maxProgress : 1000);
-
- byte[] kernel;
- if (!string.IsNullOrEmpty(Mod))
- kernel = CreatePatchedKernel();
- else
- kernel = File.ReadAllBytes(KernelDump);
- var size = CalcKernelSize(kernel);
- if (size > kernel.Length || size > Fel.kernel_max_size)
- throw new Exception(Resources.InvalidKernelSize + " " + size);
- size = (size + Fel.sector_size - 1) / Fel.sector_size;
- size = size * Fel.sector_size;
- if (kernel.Length != size)
- {
- var newK = new byte[size];
- Array.Copy(kernel, newK, kernel.Length);
- kernel = newK;
- }
- progress += 5;
- if (maxProgress < 0)
- maxProgress = (int)((double)kernel.Length / (double)67000 + 20);
- SetProgress(progress, maxProgress);
-
- SetStatus(Resources.UploadingKernel);
- fel.WriteMemory(Fel.flash_mem_base, kernel,
- delegate(Fel.CurrentAction action, string command)
- {
- switch (action)
- {
- case Fel.CurrentAction.WritingMemory:
- SetStatus(Resources.UploadingKernel);
- break;
- }
- progress++;
- SetProgress(progress, maxProgress);
- }
- );
-
- var bootCommand = string.Format("boota {0:x}", Fel.kernel_base_m);
- SetStatus(Resources.ExecutingCommand + " " + bootCommand);
- fel.RunUbootCmd(bootCommand, true);
- Thread.Sleep(7000);
- SetStatus(Resources.Done);
- SetProgress(maxProgress, maxProgress);
- }
-
- private byte[] CreatePatchedKernel()
- {
- SetStatus(Resources.BuildingCustom);
- if (Directory.Exists(tempDirectory))
- Directory.Delete(tempDirectory, true);
- Directory.CreateDirectory(tempDirectory);
- Directory.CreateDirectory(kernelDirectory);
- Directory.CreateDirectory(ramfsDirectory);
- if (!ExecuteTool("unpackbootimg.exe", string.Format("-i \"{0}\" -o \"{1}\"", KernelDump, kernelDirectory)))
- throw new Exception("Can't unpack kernel image");
- if (!ExecuteTool("lzop.exe", string.Format("-d \"{0}\" -o \"{1}\"",
- Path.Combine(kernelDirectory, "kernel.img-ramdisk.gz"), initramfs_cpio)))
- throw new Exception("Can't unpack ramdisk");
- ExecuteTool("cpio.exe", string.Format("-imd --no-preserve-owner --quiet -I \"{0}\"",
- @"..\initramfs.cpio"), ramfsDirectory);
- if (!File.Exists(Path.Combine(ramfsDirectory, "init"))) // cpio.exe fails on Windows XP for some reason. But working!
- throw new Exception("Can't unpack ramdisk 2");
- if (Directory.Exists(hakchiDirectory)) Directory.Delete(hakchiDirectory, true);
- NesMiniApplication.DirectoryCopy(Path.Combine(modsDirectory, Mod), ramfsDirectory, true);
- var ramfsFiles = Directory.GetFiles(ramfsDirectory, "*.*", SearchOption.AllDirectories);
- foreach (var file in ramfsFiles)
- {
- var fInfo = new FileInfo(file);
- if (fInfo.Length > 10 && fInfo.Length < 100 && ((fInfo.Attributes & FileAttributes.System) == 0) &&
- (Encoding.ASCII.GetString(File.ReadAllBytes(file), 0, 10)) == "!<symlink>")
- fInfo.Attributes |= FileAttributes.System;
- }
-
- if (hmodsInstall != null && hmodsInstall.Count() > 0)
- {
- Directory.CreateDirectory(tempHmodsDirectory);
- foreach (var hmod in hmodsInstall)
- {
- var modName = hmod + ".hmod";
- foreach (var dir in hmodDirectories)
- {
- if (Directory.Exists(Path.Combine(dir, modName)))
- {
- NesMiniApplication.DirectoryCopy(Path.Combine(dir, modName), Path.Combine(tempHmodsDirectory, modName), true);
- break;
- }
- if (File.Exists(Path.Combine(dir, modName)))
- {
- File.Copy(Path.Combine(dir, modName), Path.Combine(tempHmodsDirectory, modName));
- break;
- }
- }
- }
- }
- if (hmodsUninstall != null && hmodsUninstall.Count() > 0)
- {
- Directory.CreateDirectory(tempHmodsDirectory);
- var mods = new StringBuilder();
- foreach (var hmod in hmodsUninstall)
- mods.AppendFormat("{0}.hmod\n", hmod);
- File.WriteAllText(Path.Combine(tempHmodsDirectory, "uninstall"), mods.ToString());
- }
-
- // Building image
- byte[] ramdisk;
- if (!ExecuteTool("mkbootfs.exe", string.Format("\"{0}\"", ramfsDirectory), out ramdisk))
- throw new Exception("Can't repack ramdisk");
- File.WriteAllBytes(initramfs_cpioPatched, ramdisk);
- var argCmdline = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-cmdline")).Trim();
- var argBoard = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-board")).Trim();
- var argBase = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-base")).Trim();
- var argPagesize = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-pagesize")).Trim();
- var argKerneloff = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-kerneloff")).Trim();
- var argRamdiscoff = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-ramdiskoff")).Trim();
- var argTagsoff = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-tagsoff")).Trim();
- if (!ExecuteTool("lzop.exe", string.Format("--best -f -o \"{0}\" \"{1}\"",
- ramdiskPatched, initramfs_cpioPatched)))
- throw new Exception("Can't repack ramdisk 2");
- if (!ExecuteTool("mkbootimg.exe", string.Format("--kernel \"{0}\" --ramdisk \"{1}\" --cmdline \"{2}\" --board \"{3}\" --base \"{4}\" --pagesize \"{5}\" --kernel_offset \"{6}\" --ramdisk_offset \"{7}\" --tags_offset \"{8}\" -o \"{9}\"",
- Path.Combine(kernelDirectory, "kernel.img-zImage"), ramdiskPatched, argCmdline, argBoard, argBase, argPagesize, argKerneloff, argRamdiscoff, argTagsoff, kernelPatched)))
- throw new Exception("Can't rebuild kernel");
-
- var result = File.ReadAllBytes(kernelPatched);
-#if !DEBUG
- Directory.Delete(tempDirectory, true);
-#endif
- return result;
- }
-
- void DownloadAllCovers()
- {
- if (Games == null) return;
- int i = 0;
- foreach (NesMiniApplication game in Games)
- {
- SetStatus(Resources.GooglingFor + " " + game.Name);
- string[] urls = null;
- for (int tries = 0; tries < 5; tries++)
- {
- if (urls == null)
- {
- try
- {
- urls = ImageGooglerForm.GetImageUrls(game);
- break;
- }
- catch (Exception ex)
- {
- SetStatus(Resources.Error + ": " + ex.Message);
- Thread.Sleep(1500);
- continue;
- }
- }
- }
- if (urls != null && urls.Length == 0)
- SetStatus(Resources.NotFound + " " + game.Name);
- for (int tries = 0; urls != null && tries < 5 && tries < urls.Length; tries++)
- {
- try
- {
- var cover = ImageGooglerForm.DownloadImage(urls[tries]);
- game.Image = cover;
- break;
- }
- catch (Exception ex)
- {
- SetStatus(Resources.Error + ": " + ex.Message);
- Thread.Sleep(1500);
- continue;
- }
- }
- SetProgress(++i, Games.Count);
- Thread.Sleep(500); // not so fast, Google don't like it
- }
- }
-
- private class GamesTreeStats
- {
- public List<NesMenuCollection> allMenus = new List<NesMenuCollection>();
- public int TotalGames = 0;
- public long TotalSize = 0;
- public long TransferSize = 0;
- }
-
- private void AddMenu(NesMenuCollection menuCollection, Dictionary<string, string> originalGames, GamesTreeStats stats = null)
- {
- if (stats == null)
- stats = new GamesTreeStats();
- if (!stats.allMenus.Contains(menuCollection))
- stats.allMenus.Add(menuCollection);
- int menuIndex = stats.allMenus.IndexOf(menuCollection);
- string targetDirectory;
- if (menuIndex == 0)
- targetDirectory = tempGamesDirectory;
- else
- targetDirectory = Path.Combine(tempGamesDirectory, string.Format("{0:D3}", menuIndex));
- foreach (var element in menuCollection)
- {
- if (element is NesMiniApplication)
- {
- stats.TotalGames++;
- var game = element as NesMiniApplication;
- var gameSize = game.Size();
- Debug.WriteLine(string.Format("Processing {0} ('{1}'), size: {2}KB", game.Code, game.Name, gameSize / 1024));
- var gameCopy = game.CopyTo(targetDirectory);
- stats.TotalSize += gameSize;
- stats.TransferSize += gameSize;
- stats.TotalGames++;
- try
- {
- if (gameCopy is NesGame && File.Exists((gameCopy as NesGame).GameGeniePath))
- {
- (gameCopy as NesGame).ApplyGameGenie();
- File.Delete((gameCopy as NesGame).GameGeniePath);
- }
- }
- catch (GameGenieFormatException ex)
- {
- ShowError(new Exception(string.Format(Resources.GameGenieFormatError, ex.Code, game.Name)), dontStop: true);
- }
- catch (GameGenieNotFoundException ex)
- {
- ShowError(new Exception(string.Format(Resources.GameGenieNotFound, ex.Code, game.Name)), dontStop: true);
- }
- }
- if (element is NesMenuFolder)
- {
- var folder = element as NesMenuFolder;
- if (!stats.allMenus.Contains(folder.ChildMenuCollection))
- {
- stats.allMenus.Add(folder.ChildMenuCollection);
- AddMenu(folder.ChildMenuCollection, originalGames, stats);
- }
- folder.ChildIndex = stats.allMenus.IndexOf(folder.ChildMenuCollection);
- var folderDir = Path.Combine(targetDirectory, folder.Code);
- var folderSize = folder.Save(folderDir);
- stats.TotalSize += folderSize;
- stats.TransferSize += folderSize;
-
- }
- if (element is NesDefaultGame)
- {
- var game = element as NesDefaultGame;
- stats.TotalSize += game.Size;
- originalGames[game.Code] = menuIndex == 0 ? "." : string.Format("{0:D3}", menuIndex);
- }
- }
- }
-
- private bool ExecuteTool(string tool, string args, string directory = null, bool external = false)
- {
- byte[] output;
- return ExecuteTool(tool, args, out output, directory, external);
- }
-
- private bool ExecuteTool(string tool, string args, out byte[] output, string directory = null, bool external = false)
- {
- var process = new Process();
- var appDirectory = baseDirectoryInternal;
- var fileName = !external ? Path.Combine(toolsDirectory, tool) : tool;
- process.StartInfo.FileName = fileName;
- process.StartInfo.Arguments = args;
- if (string.IsNullOrEmpty(directory))
- directory = appDirectory;
- process.StartInfo.WorkingDirectory = directory;
- process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
- process.StartInfo.UseShellExecute = false;
- process.StartInfo.CreateNoWindow = true;
- process.StartInfo.StandardOutputEncoding = Encoding.GetEncoding(866);
- process.StartInfo.RedirectStandardInput = true;
- process.StartInfo.RedirectStandardOutput = true;
- process.StartInfo.RedirectStandardError = true;
- Debug.WriteLine("Executing: " + fileName);
- Debug.WriteLine("Arguments: " + args);
- Debug.WriteLine("Directory: " + directory);
- process.Start();
- string outputStr = process.StandardOutput.ReadToEnd();
- string errorStr = process.StandardError.ReadToEnd();
- process.WaitForExit();
- output = Encoding.GetEncoding(866).GetBytes(outputStr);
- Debug.WriteLineIf(outputStr.Length > 0 && outputStr.Length < 300, "Output:\r\n" + outputStr);
- Debug.WriteLineIf(errorStr.Length > 0, "Errors:\r\n" + errorStr);
- Debug.WriteLine("Exit code: " + process.ExitCode);
- return process.ExitCode == 0;
- }
-
- static UInt32 CalcKernelSize(byte[] header)
- {
- if (Encoding.ASCII.GetString(header, 0, 8) != "ANDROID!") throw new Exception(Resources.InvalidKernelHeader);
- UInt32 kernel_size = (UInt32)(header[8] | (header[9] * 0x100) | (header[10] * 0x10000) | (header[11] * 0x1000000));
- UInt32 kernel_addr = (UInt32)(header[12] | (header[13] * 0x100) | (header[14] * 0x10000) | (header[15] * 0x1000000));
- UInt32 ramdisk_size = (UInt32)(header[16] | (header[17] * 0x100) | (header[18] * 0x10000) | (header[19] * 0x1000000));
- UInt32 ramdisk_addr = (UInt32)(header[20] | (header[21] * 0x100) | (header[22] * 0x10000) | (header[23] * 0x1000000));
- UInt32 second_size = (UInt32)(header[24] | (header[25] * 0x100) | (header[26] * 0x10000) | (header[27] * 0x1000000));
- UInt32 second_addr = (UInt32)(header[28] | (header[29] * 0x100) | (header[30] * 0x10000) | (header[31] * 0x1000000));
- UInt32 tags_addr = (UInt32)(header[32] | (header[33] * 0x100) | (header[34] * 0x10000) | (header[35] * 0x1000000));
- UInt32 page_size = (UInt32)(header[36] | (header[37] * 0x100) | (header[38] * 0x10000) | (header[39] * 0x1000000));
- UInt32 dt_size = (UInt32)(header[40] | (header[41] * 0x100) | (header[42] * 0x10000) | (header[43] * 0x1000000));
- UInt32 pages = 1;
- pages += (kernel_size + page_size - 1) / page_size;
- pages += (ramdisk_size + page_size - 1) / page_size;
- pages += (second_size + page_size - 1) / page_size;
- pages += (dt_size + page_size - 1) / page_size;
- return pages * page_size;
- }
-
-
- bool YesForAllPatches = false;
- public ICollection<NesMiniApplication> AddGames(IEnumerable<string> files, Form parentForm = null)
- {
- var apps = new List<NesMiniApplication>();
- addedApplications = null;
- //bool NoForAllUnsupportedMappers = false;
- bool YesForAllUnsupportedMappers = false;
- YesForAllPatches = false;
- int count = 0;
- SetStatus(Resources.AddingGames);
- foreach (var sourceFileName in files)
- {
- NesMiniApplication app = null;
- try
- {
- var fileName = sourceFileName;
- var ext = Path.GetExtension(sourceFileName).ToLower();
- bool? needPatch = YesForAllPatches ? (bool?)true : null;
- byte[] rawData = null;
- string tmp = null;
- if (ext == ".7z" || ext == ".zip" || ext == ".rar")
- {
- SevenZipExtractor.SetLibraryPath(Path.Combine(baseDirectoryInternal, IntPtr.Size == 8 ? @"tools\7z64.dll" : @"tools\7z.dll"));
- using (var szExtractor = new SevenZipExtractor(sourceFileName))
- {
- var filesInArchive = new List<string>();
- var gameFilesInArchive = new List<string>();
- foreach (var f in szExtractor.ArchiveFileNames)
- {
- var e = Path.GetExtension(f).ToLower();
- if (e == ".desktop" || AppTypeCollection.GetAppByExtension(e) != null)
- gameFilesInArchive.Add(f);
- filesInArchive.Add(f);
- }
- if (gameFilesInArchive.Count == 1) // Only one NES file (or app)
- {
- fileName = gameFilesInArchive[0];
- }
- else if (gameFilesInArchive.Count > 1) // Many NES files, need to select
- {
- var r = SelectFileFromThread(gameFilesInArchive.ToArray());
- if (r == DialogResult.OK)
- fileName = selectedFile;
- else if (r == DialogResult.Ignore)
- fileName = sourceFileName;
- else continue;
- }
- else if (filesInArchive.Count == 1) // No NES files but only one another file
- {
- fileName = filesInArchive[0];
- }
- else // Need to select
- {
- var r = SelectFileFromThread(filesInArchive.ToArray());
- if (r == DialogResult.OK)
- fileName = selectedFile;
- else if (r == DialogResult.Ignore)
- fileName = sourceFileName;
- else continue;
- }
- if (fileName != sourceFileName)
- {
- var o = new MemoryStream();
- if (Path.GetExtension(fileName).ToLower() == ".desktop" // App in archive, need the whole directory
- || szExtractor.ArchiveFileNames.Contains(Path.GetFileNameWithoutExtension(fileName) + ".jpg") // Or it has cover in archive
- || szExtractor.ArchiveFileNames.Contains(Path.GetFileNameWithoutExtension(fileName) + ".png"))
- {
- tmp = Path.Combine(Path.GetTempPath(), fileName);
- Directory.CreateDirectory(tmp);
- szExtractor.ExtractArchive(tmp);
- fileName = Path.Combine(tmp, fileName);
- }
- else
- {
- szExtractor.ExtractFile(fileName, o);
- rawData = new byte[o.Length];
- o.Seek(0, SeekOrigin.Begin);
- o.Read(rawData, 0, (int)o.Length);
- }
- }
- }
- }
- if (Path.GetExtension(fileName).ToLower() == ".nes")
- {
- try
- {
- app = NesGame.Import(fileName, sourceFileName, YesForAllUnsupportedMappers ? (bool?)true : null, ref needPatch, needPatchCallback, this, rawData);
-
- // Trying to import Game Genie codes
- var lGameGeniePath = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".xml");
- if (File.Exists(lGameGeniePath))
- {
- GameGenieDataBase lGameGenieDataBase = new GameGenieDataBase(app);
- lGameGenieDataBase.ImportCodes(lGameGeniePath, true);
- lGameGenieDataBase.Save();
- }
- }
- catch (Exception ex)
- {
- if (ex is UnsupportedMapperException || ex is UnsupportedFourScreenException)
- {
- var r = MessageBoxFromThread(this,
- (ex is UnsupportedMapperException)
- ? string.Format(Resources.MapperNotSupported, Path.GetFileName(fileName), (ex as UnsupportedMapperException).ROM.Mapper)
- : string.Format(Resources.FourScreenNotSupported, Path.GetFileName(fileName)),
- Resources.AreYouSure,
- files.Count() <= 1 ? MessageBoxButtons.YesNo : MessageBoxButtons.AbortRetryIgnore,
- MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2, true);
- if (r == DialogResult.Abort)
- YesForAllUnsupportedMappers = true;
- if (r == DialogResult.Yes || r == DialogResult.Abort || r == DialogResult.Retry)
- app = NesGame.Import(fileName, sourceFileName, true, ref needPatch, needPatchCallback, this, rawData);
- else
- continue;
- }
- else throw ex;
- }
- }
- else
- {
- app = NesMiniApplication.Import(fileName, sourceFileName, rawData);
- }
- if (!string.IsNullOrEmpty(tmp) && Directory.Exists(tmp)) Directory.Delete(tmp, true);
- ConfigIni.SelectedGames += ";" + app.Code;
- }
- catch (Exception ex)
- {
- if (ex is ThreadAbortException) return null;
- Debug.WriteLine(ex.Message + ex.StackTrace);
- ShowError(ex, true);
- }
- if (app != null)
- apps.Add(app);
- SetProgress(++count, files.Count());
- }
- addedApplications = apps.ToArray();
- return apps; // Added games/apps
- }
-
- private bool needPatchCallback(Form parentForm, string nesFileName)
- {
- if (GamesToAdd == null || GamesToAdd.Count() <= 1)
- {
- return MessageBoxFromThread(parentForm,
- string.Format(Resources.PatchQ, Path.GetFileName(nesFileName)),
- Resources.PatchAvailable,
- MessageBoxButtons.YesNo,
- MessageBoxIcon.Question,
- MessageBoxDefaultButton.Button1, false) == DialogResult.Yes;
- }
- else
- {
- var r = MessageBoxFromThread(parentForm,
- string.Format(Resources.PatchQ, Path.GetFileName(nesFileName)),
- Resources.PatchAvailable,
- MessageBoxButtons.AbortRetryIgnore,
- MessageBoxIcon.Question,
- MessageBoxDefaultButton.Button2, true);
- if (r == DialogResult.Abort)
- YesForAllPatches = true;
- return r != DialogResult.Ignore;
- }
- }
-
- private void WorkerForm_FormClosing(object sender, FormClosingEventArgs e)
- {
- if ((thread != null) && (e.CloseReason == CloseReason.UserClosing))
- {
- if (MessageBox.Show(this, Resources.DoYouWantCancel, Resources.AreYouSure, MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
- == System.Windows.Forms.DialogResult.No)
- {
- e.Cancel = true;
- return;
- }
- if (thread != null) thread.Abort();
- TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.NoProgress);
- TaskbarProgress.SetValue(this, 0, 1);
- }
- }
- }
-}
+using com.clusterrr.Famicom; +using com.clusterrr.FelLib; +using com.clusterrr.hakchi_gui.Properties; +using com.clusterrr.util; +using SevenZip; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace com.clusterrr.hakchi_gui +{ + public partial class WorkerForm : Form + { + public enum Tasks { DumpKernel, FlashKernel, Memboot, UploadGames, DownloadAllCovers, AddGames }; + public Tasks Task; + //public string UBootDump; + public string KernelDump; + public string Mod = null; + public Dictionary<string, string> Config = null; + public NesMenuCollection Games; + public IEnumerable<string> hmodsInstall; + public IEnumerable<string> hmodsUninstall; + public IEnumerable<string> GamesToAdd; + public NesMenuCollection.SplitStyle FoldersMode = NesMenuCollection.SplitStyle.Auto; + public int MaxGamesPerFolder = 35; + public MainForm MainForm; + Thread thread = null; + Fel fel = null; + + const UInt16 vid = 0x1F3A; + const UInt16 pid = 0xEFE8; + + readonly string baseDirectoryInternal; + readonly string baseDirectoryExternal; + readonly string fes1Path; + readonly string ubootPath; + readonly string tempDirectory; + readonly string kernelDirectory; + readonly string initramfs_cpio; + readonly string initramfs_cpioPatched; + readonly string ramfsDirectory; + readonly string hakchiDirectory; + readonly string modsDirectory; + readonly string[] hmodDirectories; + readonly string toolsDirectory; + readonly string kernelPatched; + readonly string ramdiskPatched; + readonly string tempHmodsDirectory; + readonly string cloverconDriverPath; + readonly string argumentsFilePath; + readonly string transferDirectory; + string tempGamesDirectory; + //string originalGamesConfigDirectory; + //string hiddenPath; + string[] correctKernels; + const long maxCompressedsRamfsSize = 30 * 1024 * 1024; + string selectedFile = null; + public List<NesMiniApplication> addedApplications; + public static int NandCTotal, NandCUsed, NandCFree, WritedGamesSize, SaveStatesSize; + public const long ReservedMemory = 10; + + public WorkerForm() + { + InitializeComponent(); + DialogResult = DialogResult.None; + baseDirectoryInternal = Program.BaseDirectoryInternal; + baseDirectoryExternal = Program.BaseDirectoryExternal; + fes1Path = Path.Combine(Path.Combine(baseDirectoryInternal, "data"), "fes1.bin"); + ubootPath = Path.Combine(Path.Combine(baseDirectoryInternal, "data"), "uboot.bin"); +#if DEBUG + tempDirectory = Path.Combine(baseDirectoryInternal, "temp"); +#else + tempDirectory = Path.Combine(Path.GetTempPath(), "hakchi-temp"); +#endif + kernelDirectory = Path.Combine(tempDirectory, "kernel"); + initramfs_cpio = Path.Combine(kernelDirectory, "initramfs.cpio"); + initramfs_cpioPatched = Path.Combine(kernelDirectory, "initramfs_mod.cpio"); + ramfsDirectory = Path.Combine(kernelDirectory, "initramfs"); + hakchiDirectory = Path.Combine(ramfsDirectory, "hakchi"); + modsDirectory = Path.Combine(baseDirectoryInternal, "mods"); + hmodDirectories = new string[]{ + Path.Combine(baseDirectoryExternal, "user_mods"), + Path.Combine(modsDirectory, "hmods") + }; + toolsDirectory = Path.Combine(baseDirectoryInternal, "tools"); + kernelPatched = Path.Combine(kernelDirectory, "patched_kernel.img"); + ramdiskPatched = Path.Combine(kernelDirectory, "kernel.img-ramdisk_mod.gz"); + cloverconDriverPath = Path.Combine(hakchiDirectory, "clovercon.ko"); + argumentsFilePath = Path.Combine(hakchiDirectory, "extra_args"); + transferDirectory = Path.Combine(hakchiDirectory, "transfer"); + tempHmodsDirectory = Path.Combine(transferDirectory, "hmod"); + correctKernels + = new string[] { + "5cfdca351484e7025648abc3b20032ff", "07bfb800beba6ef619c29990d14b5158", // NES Mini + "ac8144c3ea4ab32e017648ee80bdc230" // Famicom Mini + }; + } + + public DialogResult Start() + { + SetProgress(0, 1); + thread = new Thread(StartThread); + thread.IsBackground = true; + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + return ShowDialog(); + } + + DialogResult WaitForFelFromThread() + { + if (InvokeRequired) + { + return (DialogResult)Invoke(new Func<DialogResult>(WaitForFelFromThread)); + } + SetStatus(Resources.WaitingForDevice); + if (fel != null) + fel.Close(); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused); + var result = WaitingFelForm.WaitForDevice(vid, pid, this); + if (result) + { + fel = new Fel(); + if (!File.Exists(fes1Path)) throw new FileNotFoundException(fes1Path + " not found"); + if (!File.Exists(ubootPath)) throw new FileNotFoundException(ubootPath + " not found"); + fel.Fes1Bin = File.ReadAllBytes(fes1Path); + fel.UBootBin = File.ReadAllBytes(ubootPath); + fel.Open(vid, pid); + SetStatus(Resources.UploadingFes1); + fel.InitDram(true); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + return DialogResult.OK; + } + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + return DialogResult.Abort; + } + DialogResult WaitForClovershellFromThread() + { + if (InvokeRequired) + { + return (DialogResult)Invoke(new Func<DialogResult>(WaitForClovershellFromThread)); + } + SetStatus(Resources.WaitingForDevice); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused); + var result = WaitingClovershellForm.WaitForDevice(this); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + if (result) + return DialogResult.OK; + else return DialogResult.Abort; + } + + private delegate DialogResult MessageBoxFromThreadDelegate(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, + MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool tweak); + DialogResult MessageBoxFromThread(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, + MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool tweak) + { + if (InvokeRequired) + { + return (DialogResult)Invoke(new MessageBoxFromThreadDelegate(MessageBoxFromThread), + new object[] { owner, text, caption, buttons, icon, defaultButton, tweak }); + } + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused); + if (tweak) MessageBoxManager.Register(); // Tweak button names + var result = MessageBox.Show(owner, text, caption, buttons, icon, defaultButton); + if (tweak) MessageBoxManager.Unregister(); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + return result; + } + + DialogResult FoldersManagerFromThread(NesMenuCollection collection) + { + if (InvokeRequired) + { + return (DialogResult)Invoke(new Func<NesMenuCollection, DialogResult>(FoldersManagerFromThread), new object[] { collection }); + } + var constructor = new FoldersManagerForm(collection, MainForm); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused); + var result = constructor.ShowDialog(); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + return result; + } + + DialogResult SelectFileFromThread(string[] files) + { + if (InvokeRequired) + { + return (DialogResult)Invoke(new Func<string[], DialogResult>(SelectFileFromThread), new object[] { files }); + } + var form = new SelectFileForm(files); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused); + var result = form.ShowDialog(); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + if (form.listBoxFiles.SelectedItem != null) + selectedFile = form.listBoxFiles.SelectedItem.ToString(); + else + selectedFile = null; + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + return result; + } + + public void StartThread() + { + Thread.CurrentThread.CurrentUICulture = new CultureInfo(ConfigIni.Language); + SetProgress(0, 1); + try + { + DialogResult = DialogResult.None; + Debug.WriteLine("Executing task: " + Task.ToString()); + switch (Task) + { + case Tasks.DumpKernel: + DoKernelDump(); + break; + case Tasks.FlashKernel: + FlashKernel(); + break; + case Tasks.UploadGames: + UploadGames(); + break; + case Tasks.Memboot: + Memboot(); + break; + case Tasks.DownloadAllCovers: + DownloadAllCovers(); + break; + case Tasks.AddGames: + AddGames(GamesToAdd); + break; + } + if (DialogResult == DialogResult.None) + DialogResult = DialogResult.OK; + } + catch (ThreadAbortException) { } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + thread = null; + if (fel != null) + { + fel.Close(); + fel = null; + } + GC.Collect(); + } + } + + void SetStatus(string status) + { + if (Disposing) return; + try + { + if (InvokeRequired) + { + Invoke(new Action<string>(SetStatus), new object[] { status }); + return; + } + labelStatus.Text = status; + } + catch { } + } + + void SetProgress(int value, int max) + { + if (Disposing) return; + try + { + if (InvokeRequired) + { + Invoke(new Action<int, int>(SetProgress), new object[] { value, max }); + if (value == max) + Thread.Sleep(1000); + return; + } + if (value > max) value = max; + progressBar.Maximum = max; + progressBar.Value = value; + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + TaskbarProgress.SetValue(this, value, max); + } + catch { } + } + + void ShowError(Exception ex, bool dontStop = false) + { + if (Disposing) return; + try + { + if (InvokeRequired) + { + Invoke(new Action<Exception, bool>(ShowError), new object[] { ex, dontStop }); + return; + } + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Error); + var message = ex.Message; +#if DEBUG + message += ex.StackTrace; +#endif + Debug.WriteLine(ex.Message + ex.StackTrace); + //if (ex is MadWizard.WinUSBNet.USBException) // TODO + // MessageBox.Show(this, message + "\r\n" + Resources.PleaseTryAgainUSB, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + //else + MessageBox.Show(this, message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + if (!dontStop) + { + thread = null; + Close(); + } + } + catch { } + } + + void ShowMessage(string text, string title) + { + if (Disposing) return; + try + { + if (InvokeRequired) + { + Invoke(new Action<string, string>(ShowMessage), new object[] { text, title }); + return; + } + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Paused); + MessageBox.Show(this, text, title, MessageBoxButtons.OK, MessageBoxIcon.Information); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.Normal); + } + catch { } + } + + public void DoKernelDump() + { + int progress = 0; + const int maxProgress = 80; + if (WaitForFelFromThread() != DialogResult.OK) + { + DialogResult = DialogResult.Abort; + return; + } + progress += 5; + SetProgress(progress, maxProgress); + + SetStatus(Resources.DumpingKernel); + var kernel = fel.ReadFlash(Fel.kernel_base_f, Fel.sector_size * 0x20, + delegate(Fel.CurrentAction action, string command) + { + switch (action) + { + case Fel.CurrentAction.RunningCommand: + SetStatus(Resources.ExecutingCommand + " " + command); + break; + case Fel.CurrentAction.ReadingMemory: + SetStatus(Resources.DumpingKernel); + break; + } + progress++; + SetProgress(progress, maxProgress); + } + ); + + var size = CalcKernelSize(kernel); + if (size == 0 || size > Fel.kernel_max_size) + throw new Exception(Resources.InvalidKernelSize + " " + size); + if (kernel.Length > size) + { + var sm_kernel = new byte[size]; + Array.Copy(kernel, 0, sm_kernel, 0, size); + kernel = sm_kernel; + } + + SetProgress(maxProgress, maxProgress); + SetStatus(Resources.Done); + + var md5 = System.Security.Cryptography.MD5.Create(); + var hash = BitConverter.ToString(md5.ComputeHash(kernel)).Replace("-", "").ToLower(); + if (!correctKernels.Contains(hash)) + { + if (MessageBoxFromThread(this, Resources.MD5Failed + " " + hash + "\r\n" + Resources.MD5Failed2 + + "\r\n" + Resources.DoYouWantToContinue, Resources.Warning, MessageBoxButtons.YesNo, + MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, false) + == DialogResult.No) + { + DialogResult = DialogResult.Abort; + return; + } + } + + Directory.CreateDirectory(Path.GetDirectoryName(KernelDump)); + File.WriteAllBytes(KernelDump, kernel); + } + + public void FlashKernel() + { + int progress = 0; + int maxProgress = 115 + (string.IsNullOrEmpty(Mod) ? 0 : 30) + + ((hmodsInstall != null && hmodsInstall.Count() > 0) ? 75 : 0); + var hmods = hmodsInstall; + hmodsInstall = null; + if (WaitForFelFromThread() != DialogResult.OK) + { + DialogResult = DialogResult.Abort; + return; + } + progress += 5; + SetProgress(progress, maxProgress); + + byte[] kernel; + if (!string.IsNullOrEmpty(Mod)) + { + kernel = CreatePatchedKernel(); + progress += 5; + SetProgress(progress, maxProgress); + } + else + kernel = File.ReadAllBytes(KernelDump); + var size = CalcKernelSize(kernel); + if (size > kernel.Length || size > Fel.kernel_max_size) + throw new Exception(Resources.InvalidKernelSize + " " + size); + + size = (size + Fel.sector_size - 1) / Fel.sector_size; + size = size * Fel.sector_size; + if (kernel.Length != size) + { + var newK = new byte[size]; + Array.Copy(kernel, newK, kernel.Length); + kernel = newK; + } + + fel.WriteFlash(Fel.kernel_base_f, kernel, + delegate(Fel.CurrentAction action, string command) + { + switch (action) + { + case Fel.CurrentAction.RunningCommand: + SetStatus(Resources.ExecutingCommand + " " + command); + break; + case Fel.CurrentAction.WritingMemory: + SetStatus(Resources.UploadingKernel); + break; + } + progress++; + SetProgress(progress, maxProgress); + } + ); + var r = fel.ReadFlash((UInt32)Fel.kernel_base_f, (UInt32)kernel.Length, + delegate(Fel.CurrentAction action, string command) + { + switch (action) + { + case Fel.CurrentAction.RunningCommand: + SetStatus(Resources.ExecutingCommand + " " + command); + break; + case Fel.CurrentAction.ReadingMemory: + SetStatus(Resources.Verifying); + break; + } + progress++; + SetProgress(progress, maxProgress); + } + ); + if (!kernel.SequenceEqual(r)) + throw new Exception(Resources.VerifyFailed); + + hmodsInstall = hmods; + if (hmodsInstall != null && hmodsInstall.Count() > 0) + { + Memboot(maxProgress, progress); // Lets install some mods + } + else + { + var shutdownCommand = string.Format("shutdown", Fel.kernel_base_m); + SetStatus(Resources.ExecutingCommand + " " + shutdownCommand); + fel.RunUbootCmd(shutdownCommand, true); + SetStatus(Resources.Done); + SetProgress(maxProgress, maxProgress); + } + } + + public static void GetMemoryStats() + { + var clovershell = MainForm.Clovershell; + var nandc = clovershell.ExecuteSimple("df /dev/nandc | tail -n 1 | awk '{ print $2 \" | \" $3 \" | \" $4 }'", 500, true).Split('|'); + WritedGamesSize = int.Parse(clovershell.ExecuteSimple("mkdir -p /var/lib/hakchi/rootfs/usr/share/games/ && du -s /var/lib/hakchi/rootfs/usr/share/games/ | awk '{ print $1 }'", 1000, true)) * 1024; + SaveStatesSize = int.Parse(clovershell.ExecuteSimple("mkdir -p /var/lib/clover/profiles/0/ && du -s /var/lib/clover/profiles/0/ | awk '{ print $1 }'", 1000, true)) * 1024; + NandCTotal = int.Parse(nandc[0]) * 1024; + NandCUsed = int.Parse(nandc[1]) * 1024; + NandCFree = int.Parse(nandc[2]) * 1024; + Debug.WriteLine(string.Format("NANDC size: {0:F1}MB, used: {1:F1}MB, free: {2:F1}MB", NandCTotal / 1024.0 / 1024.0, NandCUsed / 1024.0 / 1024.0, NandCFree / 1024.0 / 1024.0)); + Debug.WriteLine(string.Format("Used by games: {0:F1}MB", WritedGamesSize / 1024.0 / 1024.0)); + Debug.WriteLine(string.Format("Used by save-states: {0:F1}MB", SaveStatesSize / 1024.0 / 1024.0)); + Debug.WriteLine(string.Format("Used by other files (mods, configs, etc.): {0:F1}MB", (NandCUsed - WritedGamesSize - SaveStatesSize) / 1024.0 / 1024.0)); + Debug.WriteLine(string.Format("Available for games: {0:F1}MB", (NandCFree + WritedGamesSize) / 1024.0 / 1024.0)); + } + + public static void ShowSplashScreen() + { + var clovershell = MainForm.Clovershell; + var splashScreenPath = Path.Combine(Path.Combine(Program.BaseDirectoryInternal, "data"), "splash.gz"); + clovershell.ExecuteSimple("pkill -KILL clover-mcp"); + clovershell.ExecuteSimple("pkill -KILL ReedPlayer-Clover"); + clovershell.ExecuteSimple("pkill -KILL kachikachi"); + if (File.Exists(splashScreenPath)) + { + using (var splash = new FileStream(splashScreenPath, FileMode.Open)) + { + clovershell.Execute("gunzip -c - > /dev/fb0", splash, null, null, 3000); + } + } + } + + public void UploadGames() + { + const string gamesPath = "/usr/share/games/nes/kachikachi"; + const string rootFsPath = "/var/lib/hakchi/rootfs"; + const string installPath = "/var/lib/hakchi"; + int progress = 0; + int maxProgress = 400; + if (Games == null || Games.Count == 0) + throw new Exception("there are no games"); + SetStatus(Resources.BuildingFolders); + if (FoldersMode == NesMenuCollection.SplitStyle.Custom) + { + if (FoldersManagerFromThread(Games) != System.Windows.Forms.DialogResult.OK) + { + DialogResult = DialogResult.Abort; + return; + } + Games.AddBack(); + } + else Games.Split(FoldersMode, MaxGamesPerFolder); + progress += 5; + SetProgress(progress, maxProgress); + + var clovershell = MainForm.Clovershell; + try + { + if (WaitForClovershellFromThread() != DialogResult.OK) + { + DialogResult = DialogResult.Abort; + return; + } + progress += 5; + SetProgress(progress, maxProgress); + + ShowSplashScreen(); + + SetStatus(Resources.BuildingFolders); + if (Directory.Exists(tempDirectory)) + Directory.Delete(tempDirectory, true); + Directory.CreateDirectory(tempDirectory); + // Games! + tempGamesDirectory = Path.Combine(tempDirectory, "games"); + Directory.CreateDirectory(tempDirectory); + Directory.CreateDirectory(tempGamesDirectory); + Dictionary<string, string> originalGames = new Dictionary<string, string>(); + var stats = new GamesTreeStats(); + AddMenu(Games, originalGames, stats); + progress += 5; + SetProgress(progress, maxProgress); + + GetMemoryStats(); + var maxGamesSize = (NandCFree + WritedGamesSize) - ReservedMemory * 1024 * 1024; + if (stats.TotalSize > maxGamesSize) + { + throw new Exception(string.Format(Resources.MemoryFull, stats.TotalSize / 1024 / 1024) + "\r\n\r\n" + + string.Format(Resources.MemoryStats.Replace("|", "\r\n"), + NandCTotal / 1024.0 / 1024.0, + (NandCFree + WritedGamesSize - ReservedMemory * 1024 * 1024) / 1024 / 1024, + SaveStatesSize / 1024.0 / 1024.0, + (NandCUsed - WritedGamesSize - SaveStatesSize) / 1024.0 / 1024.0)); + } + + int startProgress = progress; + using (var gamesTar = new TarStream(tempGamesDirectory)) + { + maxProgress = (int)(gamesTar.Length / 1024 / 1024 + 20 + originalGames.Count() * 2); + SetProgress(progress, maxProgress); + + clovershell.ExecuteSimple(string.Format("umount {0}", gamesPath)); + clovershell.ExecuteSimple(string.Format("rm -rf {0}{1}/CLV-* {0}{1}/??? {2}/menu", rootFsPath, gamesPath, installPath), 5000, true); + + if (gamesTar.Length > 0) + { + gamesTar.OnReadProgress += delegate(long pos, long len) + { + progress = (int)(startProgress + pos / 1024 / 1024); + SetProgress(progress, maxProgress); + }; + + SetStatus(Resources.UploadingGames); + clovershell.Execute(string.Format("tar -xvC {0}{1}", rootFsPath, gamesPath), gamesTar, null, null, 30000, true); + } + } + + SetStatus(Resources.UploadingOriginalGames); + startProgress = progress; + foreach (var originalCode in originalGames.Keys) + { + clovershell.ExecuteSimple(string.Format(@"mkdir -p ""{2}{3}/{1}/{0}/"" && rsync -ac ""{3}/{0}/"" ""{2}{3}/{1}/{0}/"" && sed -i -e 's/\/usr\/bin\/clover-kachikachi/\/bin\/clover-kachikachi-wr/g' ""{2}{3}/{1}/{0}/{0}.desktop""", originalCode, originalGames[originalCode], rootFsPath, gamesPath), 5000, true); + progress += 2; + SetProgress(progress, maxProgress); + }; + + SetStatus(Resources.UploadingConfig); + SyncConfig(Config); +#if !DEBUG + Directory.Delete(tempDirectory, true); +#endif + SetStatus(Resources.Done); + SetProgress(maxProgress, maxProgress); + } + finally + { + try + { + if (clovershell.IsOnline) + clovershell.ExecuteSimple("reboot", 100); + } + catch { } + } + } + + public static void SyncConfig(Dictionary<string, string> Config, bool reboot = false) + { + var clovershell = MainForm.Clovershell; + + // Writing config + var config = new MemoryStream(); + if (Config != null && Config.Count > 0) + { + foreach (var key in Config.Keys) + { + var data = Encoding.UTF8.GetBytes(string.Format("cfg_{0}='{1}'\n", key, Config[key].Replace(@"'", @"\'"))); + config.Write(data, 0, data.Length); + } + } + clovershell.Execute("cat > /tmp/config", config, null, null, 1000, true); + clovershell.Execute("source /etc/preinit && script_init && source /tmp/config && source $preinit.d/pffff_config", null, null, null, 30000, true); + config.Dispose(); + if (reboot) + { + try + { + clovershell.ExecuteSimple("reboot", 100); + } + catch { } + } + } + + public static Image TakeScreenshot() + { + var clovershell = MainForm.Clovershell; + var screenshot = new Bitmap(1280, 720, System.Drawing.Imaging.PixelFormat.Format24bppRgb); + var rawStream = new MemoryStream(); + clovershell.Execute("cat /dev/fb0", null, rawStream, null, 1000, true); + var raw = rawStream.ToArray(); + BitmapData data = screenshot.LockBits( + new Rectangle(0, 0, screenshot.Width, screenshot.Height), + ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); + + int rawOffset = 0; + unsafe + { + for (int y = 0; y < screenshot.Height; ++y) + { + byte* row = (byte*)data.Scan0 + (y * data.Stride); + int columnOffset = 0; + for (int x = 0; x < screenshot.Width; ++x) + { + row[columnOffset] = raw[rawOffset]; + row[columnOffset + 1] = raw[rawOffset + 1]; + row[columnOffset + 2] = raw[rawOffset + 2]; + + columnOffset += 3; + rawOffset += 4; + } + } + } + screenshot.UnlockBits(data); + return screenshot; + } + + public void Memboot(int maxProgress = -1, int progress = 0) + { + SetProgress(progress, maxProgress < 0 ? 1000 : maxProgress); + // Connecting to NES Mini + if (WaitForFelFromThread() != DialogResult.OK) + { + DialogResult = DialogResult.Abort; + return; + } + progress += 5; + SetProgress(progress, maxProgress > 0 ? maxProgress : 1000); + + byte[] kernel; + if (!string.IsNullOrEmpty(Mod)) + kernel = CreatePatchedKernel(); + else + kernel = File.ReadAllBytes(KernelDump); + var size = CalcKernelSize(kernel); + if (size > kernel.Length || size > Fel.kernel_max_size) + throw new Exception(Resources.InvalidKernelSize + " " + size); + size = (size + Fel.sector_size - 1) / Fel.sector_size; + size = size * Fel.sector_size; + if (kernel.Length != size) + { + var newK = new byte[size]; + Array.Copy(kernel, newK, kernel.Length); + kernel = newK; + } + progress += 5; + if (maxProgress < 0) + maxProgress = (int)((double)kernel.Length / (double)67000 + 20); + SetProgress(progress, maxProgress); + + SetStatus(Resources.UploadingKernel); + fel.WriteMemory(Fel.flash_mem_base, kernel, + delegate(Fel.CurrentAction action, string command) + { + switch (action) + { + case Fel.CurrentAction.WritingMemory: + SetStatus(Resources.UploadingKernel); + break; + } + progress++; + SetProgress(progress, maxProgress); + } + ); + + var bootCommand = string.Format("boota {0:x}", Fel.kernel_base_m); + SetStatus(Resources.ExecutingCommand + " " + bootCommand); + fel.RunUbootCmd(bootCommand, true); + Thread.Sleep(7000); + SetStatus(Resources.Done); + SetProgress(maxProgress, maxProgress); + } + + private byte[] CreatePatchedKernel() + { + SetStatus(Resources.BuildingCustom); + if (Directory.Exists(tempDirectory)) + Directory.Delete(tempDirectory, true); + Directory.CreateDirectory(tempDirectory); + Directory.CreateDirectory(kernelDirectory); + Directory.CreateDirectory(ramfsDirectory); + if (!ExecuteTool("unpackbootimg.exe", string.Format("-i \"{0}\" -o \"{1}\"", KernelDump, kernelDirectory))) + throw new Exception("Can't unpack kernel image"); + if (!ExecuteTool("lzop.exe", string.Format("-d \"{0}\" -o \"{1}\"", + Path.Combine(kernelDirectory, "kernel.img-ramdisk.gz"), initramfs_cpio))) + throw new Exception("Can't unpack ramdisk"); + ExecuteTool("cpio.exe", string.Format("-imd --no-preserve-owner --quiet -I \"{0}\"", + @"..\initramfs.cpio"), ramfsDirectory); + if (!File.Exists(Path.Combine(ramfsDirectory, "init"))) // cpio.exe fails on Windows XP for some reason. But working! + throw new Exception("Can't unpack ramdisk 2"); + if (Directory.Exists(hakchiDirectory)) Directory.Delete(hakchiDirectory, true); + NesMiniApplication.DirectoryCopy(Path.Combine(modsDirectory, Mod), ramfsDirectory, true); + var ramfsFiles = Directory.GetFiles(ramfsDirectory, "*.*", SearchOption.AllDirectories); + foreach (var file in ramfsFiles) + { + var fInfo = new FileInfo(file); + if (fInfo.Length > 10 && fInfo.Length < 100 && ((fInfo.Attributes & FileAttributes.System) == 0) && + (Encoding.ASCII.GetString(File.ReadAllBytes(file), 0, 10)) == "!<symlink>") + fInfo.Attributes |= FileAttributes.System; + } + + if (hmodsInstall != null && hmodsInstall.Count() > 0) + { + Directory.CreateDirectory(tempHmodsDirectory); + foreach (var hmod in hmodsInstall) + { + var modName = hmod + ".hmod"; + foreach (var dir in hmodDirectories) + { + if (Directory.Exists(Path.Combine(dir, modName))) + { + NesMiniApplication.DirectoryCopy(Path.Combine(dir, modName), Path.Combine(tempHmodsDirectory, modName), true); + break; + } + if (File.Exists(Path.Combine(dir, modName))) + { + File.Copy(Path.Combine(dir, modName), Path.Combine(tempHmodsDirectory, modName)); + break; + } + } + } + } + if (hmodsUninstall != null && hmodsUninstall.Count() > 0) + { + Directory.CreateDirectory(tempHmodsDirectory); + var mods = new StringBuilder(); + foreach (var hmod in hmodsUninstall) + mods.AppendFormat("{0}.hmod\n", hmod); + File.WriteAllText(Path.Combine(tempHmodsDirectory, "uninstall"), mods.ToString()); + } + + // Building image + byte[] ramdisk; + if (!ExecuteTool("mkbootfs.exe", string.Format("\"{0}\"", ramfsDirectory), out ramdisk)) + throw new Exception("Can't repack ramdisk"); + File.WriteAllBytes(initramfs_cpioPatched, ramdisk); + var argCmdline = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-cmdline")).Trim(); + var argBoard = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-board")).Trim(); + var argBase = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-base")).Trim(); + var argPagesize = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-pagesize")).Trim(); + var argKerneloff = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-kerneloff")).Trim(); + var argRamdiscoff = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-ramdiskoff")).Trim(); + var argTagsoff = File.ReadAllText(Path.Combine(kernelDirectory, "kernel.img-tagsoff")).Trim(); + if (!ExecuteTool("lzop.exe", string.Format("--best -f -o \"{0}\" \"{1}\"", + ramdiskPatched, initramfs_cpioPatched))) + throw new Exception("Can't repack ramdisk 2"); + if (!ExecuteTool("mkbootimg.exe", string.Format("--kernel \"{0}\" --ramdisk \"{1}\" --cmdline \"{2}\" --board \"{3}\" --base \"{4}\" --pagesize \"{5}\" --kernel_offset \"{6}\" --ramdisk_offset \"{7}\" --tags_offset \"{8}\" -o \"{9}\"", + Path.Combine(kernelDirectory, "kernel.img-zImage"), ramdiskPatched, argCmdline, argBoard, argBase, argPagesize, argKerneloff, argRamdiscoff, argTagsoff, kernelPatched))) + throw new Exception("Can't rebuild kernel"); + + var result = File.ReadAllBytes(kernelPatched); +#if !DEBUG + Directory.Delete(tempDirectory, true); +#endif + return result; + } + + void DownloadAllCovers() + { + if (Games == null) return; + int i = 0; + foreach (NesMiniApplication game in Games) + { + SetStatus(Resources.GooglingFor + " " + game.Name); + string[] urls = null; + for (int tries = 0; tries < 5; tries++) + { + if (urls == null) + { + try + { + urls = ImageGooglerForm.GetImageUrls(game); + break; + } + catch (Exception ex) + { + SetStatus(Resources.Error + ": " + ex.Message); + Thread.Sleep(1500); + continue; + } + } + } + if (urls != null && urls.Length == 0) + SetStatus(Resources.NotFound + " " + game.Name); + for (int tries = 0; urls != null && tries < 5 && tries < urls.Length; tries++) + { + try + { + var cover = ImageGooglerForm.DownloadImage(urls[tries]); + game.Image = cover; + break; + } + catch (Exception ex) + { + SetStatus(Resources.Error + ": " + ex.Message); + Thread.Sleep(1500); + continue; + } + } + SetProgress(++i, Games.Count); + Thread.Sleep(500); // not so fast, Google don't like it + } + } + + private class GamesTreeStats + { + public List<NesMenuCollection> allMenus = new List<NesMenuCollection>(); + public int TotalGames = 0; + public long TotalSize = 0; + public long TransferSize = 0; + } + + private void AddMenu(NesMenuCollection menuCollection, Dictionary<string, string> originalGames, GamesTreeStats stats = null) + { + if (stats == null) + stats = new GamesTreeStats(); + if (!stats.allMenus.Contains(menuCollection)) + stats.allMenus.Add(menuCollection); + int menuIndex = stats.allMenus.IndexOf(menuCollection); + string targetDirectory; + if (menuIndex == 0) + targetDirectory = tempGamesDirectory; + else + targetDirectory = Path.Combine(tempGamesDirectory, string.Format("{0:D3}", menuIndex)); + foreach (var element in menuCollection) + { + if (element is NesMiniApplication) + { + stats.TotalGames++; + var game = element as NesMiniApplication; + var gameSize = game.Size(); + Debug.WriteLine(string.Format("Processing {0} ('{1}'), size: {2}KB", game.Code, game.Name, gameSize / 1024)); + var gameCopy = game.CopyTo(targetDirectory); + stats.TotalSize += gameSize; + stats.TransferSize += gameSize; + stats.TotalGames++; + try + { + if (gameCopy is NesGame && File.Exists((gameCopy as NesGame).GameGeniePath)) + { + (gameCopy as NesGame).ApplyGameGenie(); + File.Delete((gameCopy as NesGame).GameGeniePath); + } + } + catch (GameGenieFormatException ex) + { + ShowError(new Exception(string.Format(Resources.GameGenieFormatError, ex.Code, game.Name)), dontStop: true); + } + catch (GameGenieNotFoundException ex) + { + ShowError(new Exception(string.Format(Resources.GameGenieNotFound, ex.Code, game.Name)), dontStop: true); + } + } + if (element is NesMenuFolder) + { + var folder = element as NesMenuFolder; + if (!stats.allMenus.Contains(folder.ChildMenuCollection)) + { + stats.allMenus.Add(folder.ChildMenuCollection); + AddMenu(folder.ChildMenuCollection, originalGames, stats); + } + folder.ChildIndex = stats.allMenus.IndexOf(folder.ChildMenuCollection); + var folderDir = Path.Combine(targetDirectory, folder.Code); + var folderSize = folder.Save(folderDir); + stats.TotalSize += folderSize; + stats.TransferSize += folderSize; + + } + if (element is NesDefaultGame) + { + var game = element as NesDefaultGame; + stats.TotalSize += game.Size; + originalGames[game.Code] = menuIndex == 0 ? "." : string.Format("{0:D3}", menuIndex); + } + } + } + + private bool ExecuteTool(string tool, string args, string directory = null, bool external = false) + { + byte[] output; + return ExecuteTool(tool, args, out output, directory, external); + } + + private bool ExecuteTool(string tool, string args, out byte[] output, string directory = null, bool external = false) + { + var process = new Process(); + var appDirectory = baseDirectoryInternal; + var fileName = !external ? Path.Combine(toolsDirectory, tool) : tool; + process.StartInfo.FileName = fileName; + process.StartInfo.Arguments = args; + if (string.IsNullOrEmpty(directory)) + directory = appDirectory; + process.StartInfo.WorkingDirectory = directory; + process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + process.StartInfo.StandardOutputEncoding = Encoding.GetEncoding(866); + process.StartInfo.RedirectStandardInput = true; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + Debug.WriteLine("Executing: " + fileName); + Debug.WriteLine("Arguments: " + args); + Debug.WriteLine("Directory: " + directory); + process.Start(); + string outputStr = process.StandardOutput.ReadToEnd(); + string errorStr = process.StandardError.ReadToEnd(); + process.WaitForExit(); + output = Encoding.GetEncoding(866).GetBytes(outputStr); + Debug.WriteLineIf(outputStr.Length > 0 && outputStr.Length < 300, "Output:\r\n" + outputStr); + Debug.WriteLineIf(errorStr.Length > 0, "Errors:\r\n" + errorStr); + Debug.WriteLine("Exit code: " + process.ExitCode); + return process.ExitCode == 0; + } + + static UInt32 CalcKernelSize(byte[] header) + { + if (Encoding.ASCII.GetString(header, 0, 8) != "ANDROID!") throw new Exception(Resources.InvalidKernelHeader); + UInt32 kernel_size = (UInt32)(header[8] | (header[9] * 0x100) | (header[10] * 0x10000) | (header[11] * 0x1000000)); + UInt32 kernel_addr = (UInt32)(header[12] | (header[13] * 0x100) | (header[14] * 0x10000) | (header[15] * 0x1000000)); + UInt32 ramdisk_size = (UInt32)(header[16] | (header[17] * 0x100) | (header[18] * 0x10000) | (header[19] * 0x1000000)); + UInt32 ramdisk_addr = (UInt32)(header[20] | (header[21] * 0x100) | (header[22] * 0x10000) | (header[23] * 0x1000000)); + UInt32 second_size = (UInt32)(header[24] | (header[25] * 0x100) | (header[26] * 0x10000) | (header[27] * 0x1000000)); + UInt32 second_addr = (UInt32)(header[28] | (header[29] * 0x100) | (header[30] * 0x10000) | (header[31] * 0x1000000)); + UInt32 tags_addr = (UInt32)(header[32] | (header[33] * 0x100) | (header[34] * 0x10000) | (header[35] * 0x1000000)); + UInt32 page_size = (UInt32)(header[36] | (header[37] * 0x100) | (header[38] * 0x10000) | (header[39] * 0x1000000)); + UInt32 dt_size = (UInt32)(header[40] | (header[41] * 0x100) | (header[42] * 0x10000) | (header[43] * 0x1000000)); + UInt32 pages = 1; + pages += (kernel_size + page_size - 1) / page_size; + pages += (ramdisk_size + page_size - 1) / page_size; + pages += (second_size + page_size - 1) / page_size; + pages += (dt_size + page_size - 1) / page_size; + return pages * page_size; + } + + + bool YesForAllPatches = false; + public ICollection<NesMiniApplication> AddGames(IEnumerable<string> files, Form parentForm = null) + { + var apps = new List<NesMiniApplication>(); + addedApplications = null; + //bool NoForAllUnsupportedMappers = false; + bool YesForAllUnsupportedMappers = false; + YesForAllPatches = false; + int count = 0; + SetStatus(Resources.AddingGames); + foreach (var sourceFileName in files) + { + NesMiniApplication app = null; + try + { + var fileName = sourceFileName; + var ext = Path.GetExtension(sourceFileName).ToLower(); + bool? needPatch = YesForAllPatches ? (bool?)true : null; + byte[] rawData = null; + string tmp = null; + if (ext == ".7z" || ext == ".zip" || ext == ".rar") + { + SevenZipExtractor.SetLibraryPath(Path.Combine(baseDirectoryInternal, IntPtr.Size == 8 ? @"tools\7z64.dll" : @"tools\7z.dll")); + using (var szExtractor = new SevenZipExtractor(sourceFileName)) + { + var filesInArchive = new List<string>(); + var gameFilesInArchive = new List<string>(); + foreach (var f in szExtractor.ArchiveFileNames) + { + var e = Path.GetExtension(f).ToLower(); + if (e == ".desktop" || AppTypeCollection.GetAppByExtension(e) != null) + gameFilesInArchive.Add(f); + filesInArchive.Add(f); + } + if (gameFilesInArchive.Count == 1) // Only one NES file (or app) + { + fileName = gameFilesInArchive[0]; + } + else if (gameFilesInArchive.Count > 1) // Many NES files, need to select + { + var r = SelectFileFromThread(gameFilesInArchive.ToArray()); + if (r == DialogResult.OK) + fileName = selectedFile; + else if (r == DialogResult.Ignore) + fileName = sourceFileName; + else continue; + } + else if (filesInArchive.Count == 1) // No NES files but only one another file + { + fileName = filesInArchive[0]; + } + else // Need to select + { + var r = SelectFileFromThread(filesInArchive.ToArray()); + if (r == DialogResult.OK) + fileName = selectedFile; + else if (r == DialogResult.Ignore) + fileName = sourceFileName; + else continue; + } + if (fileName != sourceFileName) + { + var o = new MemoryStream(); + if (Path.GetExtension(fileName).ToLower() == ".desktop" // App in archive, need the whole directory + || szExtractor.ArchiveFileNames.Contains(Path.GetFileNameWithoutExtension(fileName) + ".jpg") // Or it has cover in archive + || szExtractor.ArchiveFileNames.Contains(Path.GetFileNameWithoutExtension(fileName) + ".png")) + { + tmp = Path.Combine(Path.GetTempPath(), fileName); + Directory.CreateDirectory(tmp); + szExtractor.ExtractArchive(tmp); + fileName = Path.Combine(tmp, fileName); + } + else + { + szExtractor.ExtractFile(fileName, o); + rawData = new byte[o.Length]; + o.Seek(0, SeekOrigin.Begin); + o.Read(rawData, 0, (int)o.Length); + } + } + } + } + if (Path.GetExtension(fileName).ToLower() == ".nes") + { + try + { + app = NesGame.Import(fileName, sourceFileName, YesForAllUnsupportedMappers ? (bool?)true : null, ref needPatch, needPatchCallback, this, rawData); + + // Trying to import Game Genie codes + var lGameGeniePath = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".xml"); + if (File.Exists(lGameGeniePath)) + { + GameGenieDataBase lGameGenieDataBase = new GameGenieDataBase(app); + lGameGenieDataBase.ImportCodes(lGameGeniePath, true); + lGameGenieDataBase.Save(); + } + } + catch (Exception ex) + { + if (ex is UnsupportedMapperException || ex is UnsupportedFourScreenException) + { + var r = MessageBoxFromThread(this, + (ex is UnsupportedMapperException) + ? string.Format(Resources.MapperNotSupported, Path.GetFileName(fileName), (ex as UnsupportedMapperException).ROM.Mapper) + : string.Format(Resources.FourScreenNotSupported, Path.GetFileName(fileName)), + Resources.AreYouSure, + files.Count() <= 1 ? MessageBoxButtons.YesNo : MessageBoxButtons.AbortRetryIgnore, + MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2, true); + if (r == DialogResult.Abort) + YesForAllUnsupportedMappers = true; + if (r == DialogResult.Yes || r == DialogResult.Abort || r == DialogResult.Retry) + app = NesGame.Import(fileName, sourceFileName, true, ref needPatch, needPatchCallback, this, rawData); + else + continue; + } + else throw ex; + } + } + else + { + app = NesMiniApplication.Import(fileName, sourceFileName, rawData); + } + if (!string.IsNullOrEmpty(tmp) && Directory.Exists(tmp)) Directory.Delete(tmp, true); + ConfigIni.SelectedGames += ";" + app.Code; + } + catch (Exception ex) + { + if (ex is ThreadAbortException) return null; + Debug.WriteLine(ex.Message + ex.StackTrace); + ShowError(ex, true); + } + if (app != null) + apps.Add(app); + SetProgress(++count, files.Count()); + } + addedApplications = apps; + return apps; // Added games/apps + } + + private bool needPatchCallback(Form parentForm, string nesFileName) + { + if (GamesToAdd == null || GamesToAdd.Count() <= 1) + { + return MessageBoxFromThread(parentForm, + string.Format(Resources.PatchQ, Path.GetFileName(nesFileName)), + Resources.PatchAvailable, + MessageBoxButtons.YesNo, + MessageBoxIcon.Question, + MessageBoxDefaultButton.Button1, false) == DialogResult.Yes; + } + else + { + var r = MessageBoxFromThread(parentForm, + string.Format(Resources.PatchQ, Path.GetFileName(nesFileName)), + Resources.PatchAvailable, + MessageBoxButtons.AbortRetryIgnore, + MessageBoxIcon.Question, + MessageBoxDefaultButton.Button2, true); + if (r == DialogResult.Abort) + YesForAllPatches = true; + return r != DialogResult.Ignore; + } + } + + private void WorkerForm_FormClosing(object sender, FormClosingEventArgs e) + { + if ((thread != null) && (e.CloseReason == CloseReason.UserClosing)) + { + if (MessageBox.Show(this, Resources.DoYouWantCancel, Resources.AreYouSure, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) + == System.Windows.Forms.DialogResult.No) + { + e.Cancel = true; + return; + } + if (thread != null) thread.Abort(); + TaskbarProgress.SetState(this, TaskbarProgress.TaskbarStates.NoProgress); + TaskbarProgress.SetValue(this, 0, 1); + } + } + } +} diff --git a/hakchi_gui.csproj b/hakchi_gui.csproj index 3f8c4f83..b27318a0 100644 --- a/hakchi_gui.csproj +++ b/hakchi_gui.csproj @@ -442,6 +442,12 @@ <Compile Include="FoldersManagerForm.Designer.cs"> <DependentUpon>FoldersManagerForm.cs</DependentUpon> </Compile> + <Compile Include="UI\Components\GameDetail.cs"> + <SubType>UserControl</SubType> + </Compile> + <Compile Include="UI\Components\GameDetail.Designer.cs"> + <DependentUpon>GameDetail.cs</DependentUpon> + </Compile> <Compile Include="UI\Components\GameSelecter.cs"> <SubType>UserControl</SubType> </Compile> @@ -958,6 +964,9 @@ <EmbeddedResource Include="FoldersManagerForm.ru-RU.resx"> <DependentUpon>FoldersManagerForm.cs</DependentUpon> </EmbeddedResource> + <EmbeddedResource Include="UI\Components\GameDetail.resx"> + <DependentUpon>GameDetail.cs</DependentUpon> + </EmbeddedResource> <EmbeddedResource Include="UI\Components\GameSelecter.resx"> <DependentUpon>GameSelecter.cs</DependentUpon> </EmbeddedResource> @@ -1652,22 +1661,22 @@ <ItemGroup> <PublishFile Include="data\GameGenieDB.xml"> <Visible>False</Visible> - <PublishState>Include</PublishState> - <IncludeHash>True</IncludeHash> <Group> </Group> <TargetPath> </TargetPath> + <PublishState>Include</PublishState> + <IncludeHash>True</IncludeHash> <FileType>File</FileType> </PublishFile> <PublishFile Include="data\nescarts.xml"> <Visible>False</Visible> - <PublishState>Include</PublishState> - <IncludeHash>True</IncludeHash> <Group> </Group> <TargetPath> </TargetPath> + <PublishState>Include</PublishState> + <IncludeHash>True</IncludeHash> <FileType>File</FileType> </PublishFile> </ItemGroup> |