Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElie Rodrigue <elie.rodrigue@nubik.ca>2017-05-09 22:24:10 +0300
committerElie Rodrigue <elie.rodrigue@nubik.ca>2017-05-09 22:24:10 +0300
commit737a28334e7b0461c39cda6e83d2cebef9b622a9 (patch)
treeb690cad0b87d8bd3999c77fe1259fe273efbddd7
parent7174d150f4c2bed268dc9385d6d3cc4feb0f7af1 (diff)
Game detail update
-rw-r--r--MainForm.Designer.cs202
-rw-r--r--MainForm.cs294
-rw-r--r--MainForm.resx565
-rw-r--r--Manager/GameManager.cs148
-rw-r--r--Properties/app.manifest106
-rw-r--r--UI/Components/GameDetail.Designer.cs8
-rw-r--r--UI/Components/GameDetail.cs31
-rw-r--r--UI/Components/GameDetail.resx3
-rw-r--r--UI/Components/GameSelecter.Designer.cs20
-rw-r--r--UI/Components/GameSelecter.cs96
-rw-r--r--WorkerForm.cs2380
-rw-r--r--hakchi_gui.csproj17
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="&gt;&gt;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="&gt;&gt;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="&gt;&gt;buttonShowGameGenieDatabase.Name" xml:space="preserve">
- <value>buttonShowGameGenieDatabase</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;buttonShowGameGenieDatabase.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;maskedTextBoxReleaseDate.Name" xml:space="preserve">
- <value>maskedTextBoxReleaseDate</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;maskedTextBoxReleaseDate.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label1.Name" xml:space="preserve">
- <value>label1</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label1.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxGameGenie.Name" xml:space="preserve">
- <value>textBoxGameGenie</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxGameGenie.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label7.Name" xml:space="preserve">
- <value>label7</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label7.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label6.Name" xml:space="preserve">
- <value>label6</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label6.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;radioButtonTwoSim.Name" xml:space="preserve">
- <value>radioButtonTwoSim</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;radioButtonTwoSim.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;buttonGoogle.Name" xml:space="preserve">
- <value>buttonGoogle</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;buttonGoogle.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;buttonBrowseImage.Name" xml:space="preserve">
- <value>buttonBrowseImage</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;buttonBrowseImage.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;pictureBoxArt.Name" xml:space="preserve">
- <value>pictureBoxArt</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;pictureBoxArt.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label4.Name" xml:space="preserve">
- <value>label4</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label4.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxArguments.Name" xml:space="preserve">
- <value>textBoxArguments</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxArguments.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label3.Name" xml:space="preserve">
- <value>label3</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label3.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxPublisher.Name" xml:space="preserve">
- <value>textBoxPublisher</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxPublisher.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label2.Name" xml:space="preserve">
- <value>label2</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;label2.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;radioButtonTwo.Name" xml:space="preserve">
- <value>radioButtonTwo</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;radioButtonTwo.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;radioButtonOne.Name" xml:space="preserve">
- <value>radioButtonOne</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;radioButtonOne.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxName.Name" xml:space="preserve">
- <value>textBoxName</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;textBoxName.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;labelName.Name" xml:space="preserve">
- <value>labelName</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;labelName.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;labelID.Name" xml:space="preserve">
- <value>labelID</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;labelID.Parent" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;groupBoxOptions.Name" xml:space="preserve">
- <value>groupBoxOptions</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;groupBoxOptions.Parent" xml:space="preserve">
- <value>$this</value>
- </data>
- <data name="&gt;&gt;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="&gt;&gt;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="&gt;&gt;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="&gt;&gt;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="&gt;&gt;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="&gt;&gt;gameDetail1.Name" xml:space="preserve">
+ <value>gameDetail1</value>
+ </data>
+ <data name="&gt;&gt;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="&gt;&gt;gameDetail1.Parent" xml:space="preserve">
+ <value>$this</value>
+ </data>
+ <data name="&gt;&gt;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>