mirror of
https://github.com/WB3000/nusdownloader.git
synced 2024-11-17 07:09:21 +01:00
e7ce3414f1
Changed when/how Patch IOS checkbox works
2253 lines
92 KiB
C#
2253 lines
92 KiB
C#
///////////////////////////////////////
|
|
// NUS Downloader: Form1.cs //
|
|
// $Rev:: $ //
|
|
// $Author:: $ //
|
|
// $Date:: $ //
|
|
///////////////////////////////////////
|
|
|
|
///////////////////////////////////////
|
|
// Copyright (C) 2010
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
///////////////////////////////////////
|
|
|
|
|
|
using System;
|
|
using System.Windows.Forms;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Security.Cryptography;
|
|
using System.Xml;
|
|
using System.Drawing;
|
|
using System.Text.RegularExpressions;
|
|
using System.ComponentModel;
|
|
using System.Threading;
|
|
using System.Text;
|
|
using System.Diagnostics;
|
|
|
|
|
|
namespace NUS_Downloader
|
|
{
|
|
public partial class Form1 : Form
|
|
{
|
|
private readonly string CURRENT_DIR = Directory.GetCurrentDirectory();
|
|
|
|
// TODO: Always remember to change version!
|
|
private string version = "v2.0 Beta";
|
|
|
|
private static bool dsidecrypt = false;
|
|
|
|
// Cross-thread Windows Formsing
|
|
private delegate void AddToolStripItemToStripCallback(
|
|
int type, ToolStripMenuItem additionitem, XmlAttributeCollection attributes);
|
|
private delegate void WriteStatusCallback(string Update);
|
|
private delegate void BootChecksCallback();
|
|
private delegate void SetEnableForDownloadCallback(bool enabled);
|
|
private delegate void SetPropertyThreadSafeCallback(System.ComponentModel.Component what, object setto, string property);
|
|
private delegate string OfficialWADNamingCallback(string whut);
|
|
|
|
// Images do not compare unless globalized...
|
|
private Image green = Properties.Resources.bullet_green;
|
|
private Image orange = Properties.Resources.bullet_orange;
|
|
private Image redorb = Properties.Resources.bullet_red;
|
|
private Image redgreen = Properties.Resources.bullet_redgreen;
|
|
private Image redorange = Properties.Resources.bullet_redorange;
|
|
|
|
private string WAD_Saveas_Filename;
|
|
|
|
// TODO: OOP scripting
|
|
private string script_filename;
|
|
private bool script_mode = false;
|
|
private string[] nusentries;
|
|
|
|
// Proxy stuff...
|
|
private string proxy_url;
|
|
private string proxy_usr;
|
|
private string proxy_pwd;
|
|
|
|
// Database thread
|
|
private BackgroundWorker fds;
|
|
|
|
// Scripts Thread
|
|
private BackgroundWorker scriptsWorker;
|
|
|
|
// This is the standard entry to the GUI
|
|
public Form1()
|
|
{
|
|
this.Font = new System.Drawing.Font("Tahoma", 8);
|
|
InitializeComponent();
|
|
this.MaximumSize = this.MinimumSize = this.Size; // Lock size down PATCHOW :D
|
|
if (Type.GetType("Mono.Runtime") != null)
|
|
{
|
|
saveaswadbtn.Text = "Save As";
|
|
clearButton.Text = "Clear";
|
|
keepenccontents.Text = "Keep Enc. Contents";
|
|
clearButton.Left -= 41;
|
|
}
|
|
else
|
|
statusbox.Font = new System.Drawing.Font("Microsoft Sans Serif", 7);
|
|
|
|
KoreaMassUpdate.DropDownItemClicked += new ToolStripItemClickedEventHandler(upditem_itemclicked);
|
|
NTSCMassUpdate.DropDownItemClicked += new ToolStripItemClickedEventHandler(upditem_itemclicked);
|
|
PALMassUpdate.DropDownItemClicked += new ToolStripItemClickedEventHandler(upditem_itemclicked);
|
|
|
|
// Database BGLoader
|
|
this.fds = new BackgroundWorker();
|
|
this.fds.DoWork += new DoWorkEventHandler(DoAllDatabaseyStuff);
|
|
this.fds.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DoAllDatabaseyStuff_Completed);
|
|
this.fds.ProgressChanged += new ProgressChangedEventHandler(DoAllDatabaseyStuff_ProgressChanged);
|
|
this.fds.WorkerReportsProgress = true;
|
|
|
|
// Scripts BGLoader
|
|
this.scriptsWorker = new BackgroundWorker();
|
|
this.scriptsWorker.DoWork += new DoWorkEventHandler(OrganizeScripts);
|
|
this.scriptsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(scriptsWorker_RunWorkerCompleted);
|
|
RunScriptOrganizer();
|
|
|
|
BootChecks();
|
|
}
|
|
|
|
// CLI Mode
|
|
public Form1(string[] args)
|
|
{
|
|
InitializeComponent();
|
|
Application.DoEvents();
|
|
|
|
BootChecks();
|
|
|
|
// Fix proxy entry.
|
|
if (!(String.IsNullOrEmpty(proxy_url)))
|
|
while (String.IsNullOrEmpty(proxy_pwd))
|
|
Thread.Sleep(1000);
|
|
|
|
if ((args.Length == 1) && (File.Exists(args[0])))
|
|
{
|
|
script_filename = args[0];
|
|
BackgroundWorker scripter = new BackgroundWorker();
|
|
scripter.DoWork += new DoWorkEventHandler(RunScript);
|
|
scripter.RunWorkerAsync();
|
|
}
|
|
}
|
|
|
|
private void Form1_Load(object sender, EventArgs e)
|
|
{
|
|
this.Text = String.Format("NUSD - {0}", version); ;
|
|
this.Size = this.MinimumSize;
|
|
consoleCBox.SelectedIndex = 0;
|
|
}
|
|
|
|
private bool NUSDFileExists(string filename)
|
|
{
|
|
return File.Exists(Path.Combine(CURRENT_DIR, filename));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks certain file existances, etc.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private void BootChecks()
|
|
{
|
|
//Check if correct thread...
|
|
if (this.InvokeRequired)
|
|
{
|
|
Debug.WriteLine("InvokeRequired...");
|
|
BootChecksCallback bcc = new BootChecksCallback(BootChecks);
|
|
this.Invoke(bcc);
|
|
return;
|
|
}
|
|
|
|
// Check for DSi common key bin file...
|
|
if (NUSDFileExists("dsikey.bin") == true)
|
|
{
|
|
WriteStatus("DSi Common Key detected.");
|
|
dsidecrypt = true;
|
|
}
|
|
|
|
// Check for database.xml
|
|
if (NUSDFileExists("database.xml") == false)
|
|
{
|
|
WriteStatus("Database.xml not found. Title database not usable!");
|
|
/*databaseButton.Click -= new System.EventHandler(this.button4_Click);
|
|
databaseButton.Click += new System.EventHandler(this.updateDatabaseToolStripMenuItem_Click);
|
|
databaseButton.Text = "Download DB"; */
|
|
DatabaseEnabled(false);
|
|
updateDatabaseToolStripMenuItem.Enabled = true;
|
|
updateDatabaseToolStripMenuItem.Text = "Download Database";
|
|
}
|
|
else
|
|
{
|
|
string version = GetDatabaseVersion("database.xml");
|
|
WriteStatus("Database.xml detected.");
|
|
WriteStatus(" - Version: " + version);
|
|
updateDatabaseToolStripMenuItem.Text = "Update Database";
|
|
//databaseButton.Enabled = false;
|
|
databaseButton.Text = "DB Loading";
|
|
// Load it up...
|
|
this.fds.RunWorkerAsync();
|
|
}
|
|
|
|
// Check for Proxy Settings file...
|
|
if (NUSDFileExists("proxy.txt") == true)
|
|
{
|
|
WriteStatus("Proxy settings detected.");
|
|
string[] proxy_file = File.ReadAllLines(Path.Combine(CURRENT_DIR, "proxy.txt"));
|
|
proxy_url = proxy_file[0];
|
|
|
|
// If proxy\nuser\npassword
|
|
if (proxy_file.Length > 2)
|
|
{
|
|
proxy_usr = proxy_file[1];
|
|
proxy_pwd = proxy_file[2];
|
|
}
|
|
else if (proxy_file.Length > 1)
|
|
{
|
|
proxy_usr = proxy_file[1];
|
|
SetAllEnabled(false);
|
|
ProxyVerifyBox.Visible = true;
|
|
ProxyVerifyBox.Enabled = true;
|
|
ProxyPwdBox.Enabled = true;
|
|
SaveProxyBtn.Enabled = true;
|
|
ProxyVerifyBox.Select();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DoAllDatabaseyStuff(object sender, System.ComponentModel.DoWorkEventArgs e)
|
|
{
|
|
BackgroundWorker worker = sender as BackgroundWorker;
|
|
ClearDatabaseStrip();
|
|
FillDatabaseStrip(worker);
|
|
LoadRegionCodes();
|
|
ShowInnerToolTips(false);
|
|
}
|
|
|
|
private void DoAllDatabaseyStuff_Completed(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
|
{
|
|
//this.databaseButton.Enabled = true;
|
|
this.databaseButton.Text = "Database...";
|
|
if (this.KoreaMassUpdate.HasDropDownItems || this.PALMassUpdate.HasDropDownItems || this.NTSCMassUpdate.HasDropDownItems)
|
|
{
|
|
this.scriptsbutton.Enabled = true;
|
|
}
|
|
}
|
|
|
|
private void DoAllDatabaseyStuff_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
|
|
{
|
|
this.databaseButton.Text = "DB: " + e.ProgressPercentage + "%";
|
|
}
|
|
|
|
private void RunScriptOrganizer()
|
|
{
|
|
this.scriptsWorker.RunWorkerAsync();
|
|
}
|
|
|
|
private void SetAllEnabled(bool enabled)
|
|
{
|
|
for (int a = 0; a < this.Controls.Count; a++)
|
|
{
|
|
try
|
|
{
|
|
this.Controls[a].Enabled = enabled;
|
|
}
|
|
catch
|
|
{
|
|
// ...
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the database version.
|
|
/// </summary>
|
|
/// <param name="file">The database file.</param>
|
|
/// <returns></returns>
|
|
private string GetDatabaseVersion(string file)
|
|
{
|
|
// Read version of Database.xml
|
|
XmlDocument xDoc = new XmlDocument();
|
|
if (file.Contains("<"))
|
|
xDoc.LoadXml(file);
|
|
else
|
|
{
|
|
if (File.Exists(file))
|
|
{
|
|
xDoc.Load(file);
|
|
}
|
|
else
|
|
{
|
|
return "None Found";
|
|
}
|
|
}
|
|
XmlNodeList DatabaseList = xDoc.GetElementsByTagName("database");
|
|
XmlAttributeCollection Attributes = DatabaseList[0].Attributes;
|
|
return Attributes[0].Value;
|
|
}
|
|
|
|
private void extrasMenuButton_Click(object sender, EventArgs e)
|
|
{
|
|
// Show extras menu
|
|
extrasStrip.Show(Extrasbtn, 2, (2+Extrasbtn.Height));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the title info from TMD.
|
|
/// </summary>
|
|
private void LoadTitleFromTMD()
|
|
{
|
|
// Show dialog for opening TMD file...
|
|
OpenFileDialog opentmd = new OpenFileDialog();
|
|
opentmd.Filter = "TMD Files|tmd";
|
|
opentmd.Title = "Open TMD";
|
|
if (opentmd.ShowDialog() != DialogResult.Cancel)
|
|
{
|
|
libWiiSharp.TMD tmdLocal = new libWiiSharp.TMD();
|
|
tmdLocal.LoadFile(opentmd.FileName);
|
|
WriteStatus(String.Format("TMD Loaded ({0} blocks)", tmdLocal.GetNandBlocks()));
|
|
|
|
titleidbox.Text = tmdLocal.TitleID.ToString("X16");
|
|
WriteStatus("Title ID: " + tmdLocal.TitleID.ToString("X16"));
|
|
|
|
titleversion.Text = tmdLocal.TitleVersion.ToString();
|
|
WriteStatus("Version: " + tmdLocal.TitleVersion);
|
|
|
|
if (tmdLocal.StartupIOS.ToString("X") != "0")
|
|
WriteStatus("Requires: IOS" + int.Parse(tmdLocal.StartupIOS.ToString("X").Substring(7, 2).ToString(), System.Globalization.NumberStyles.HexNumber));
|
|
|
|
WriteStatus("Content Count: " + tmdLocal.NumOfContents);
|
|
|
|
for (int a = 0; a < tmdLocal.Contents.Length; a++)
|
|
{
|
|
WriteStatus(String.Format(" Content {0}: {1} ({2} bytes)", a, tmdLocal.Contents[a].ContentID.ToString("X8"), tmdLocal.Contents[a].Size.ToString()));
|
|
WriteStatus(String.Format(" - Index: {0}", tmdLocal.Contents[a].Index.ToString()));
|
|
WriteStatus(String.Format(" - Type: {0}", tmdLocal.Contents[a].Type.ToString()));
|
|
WriteStatus(String.Format(" - Hash: {0}...", DisplayBytes(tmdLocal.Contents[a].Hash, String.Empty).Substring(0, 8)));
|
|
}
|
|
|
|
WriteStatus("TMD information parsed!");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes the status to the statusbox.
|
|
/// </summary>
|
|
/// <param name="Update">The update.</param>
|
|
public void WriteStatus(string Update)
|
|
{
|
|
// Check if thread-safe
|
|
if (this.InvokeRequired)
|
|
{
|
|
Debug.WriteLine("InvokeRequired...");
|
|
WriteStatusCallback wsc = new WriteStatusCallback(WriteStatus);
|
|
this.Invoke(wsc, new object[] {Update});
|
|
return;
|
|
}
|
|
// Small function for writing text to the statusbox...
|
|
if (statusbox.Text == "")
|
|
statusbox.Text = Update;
|
|
else
|
|
statusbox.Text += "\r\n" + Update;
|
|
|
|
// Scroll to end of text box.
|
|
statusbox.SelectionStart = statusbox.TextLength;
|
|
statusbox.ScrollToCaret();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads the type of the Title ID.
|
|
/// </summary>
|
|
/// <param name="ttlid">The TitleID.</param>
|
|
private void ReadIDType(string ttlid)
|
|
{
|
|
/* Wiibrew TitleID Info...
|
|
# 3 00000001: Essential system titles
|
|
# 4 00010000 and 00010004 : Disc-based games
|
|
# 5 00010001: Downloaded channels
|
|
|
|
* 5.1 000010001-Cxxx : Commodore 64 Games
|
|
* 5.2 000010001-Exxx : NeoGeo Games
|
|
* 5.3 000010001-Fxxx : NES Games
|
|
* 5.4 000010001-Hxxx : Channels
|
|
* 5.5 000010001-Jxxx : SNES Games
|
|
* 5.6 000010001-Nxxx : Nintendo 64 Games
|
|
* 5.7 000010001-Wxxx : WiiWare
|
|
|
|
# 6 00010002: System channels
|
|
# 7 00010004: Game channels and games that use them
|
|
# 8 00010005: Downloaded Game Content
|
|
# 9 00010008: "Hidden" channels
|
|
*/
|
|
|
|
if (ttlid.Substring(0, 8) == "00000001")
|
|
WriteStatus("ID Type: System Title. BE CAREFUL!");
|
|
else if ((ttlid.Substring(0, 8) == "00010000") || (ttlid.Substring(0, 8) == "00010004"))
|
|
WriteStatus("ID Type: Disc-Based Game. Unlikely NUS Content!");
|
|
else if (ttlid.Substring(0, 8) == "00010001")
|
|
WriteStatus("ID Type: Downloaded Channel. Possible NUS Content.");
|
|
else if (ttlid.Substring(0, 8) == "00010002")
|
|
WriteStatus("ID Type: System Channel. BE CAREFUL!");
|
|
else if (ttlid.Substring(0, 8) == "00010004")
|
|
WriteStatus("ID Type: Game Channel. Unlikely NUS Content!");
|
|
else if (ttlid.Substring(0, 8) == "00010005")
|
|
WriteStatus("ID Type: Downloaded Game Content. Unlikely NUS Content!");
|
|
else if (ttlid.Substring(0, 8) == "00010008")
|
|
WriteStatus("ID Type: 'Hidden' Channel. Unlikely NUS Content!");
|
|
else
|
|
WriteStatus("ID Type: Unknown. Unlikely NUS Content!");
|
|
}
|
|
|
|
private void DownloadBtn_Click(object sender, EventArgs e)
|
|
{
|
|
if (titleidbox.Text == String.Empty)
|
|
{
|
|
// Prevent mass deletion and fail
|
|
WriteStatus("Please enter a Title ID!");
|
|
return;
|
|
}
|
|
else if (!(packbox.Checked) && !(decryptbox.Checked) && !(keepenccontents.Checked))
|
|
{
|
|
// Prevent pointless running by n00bs.
|
|
WriteStatus("Running with your current settings will produce no output!");
|
|
WriteStatus(" - To amend this, look below and check an output type.");
|
|
return;
|
|
}
|
|
else if (!(script_mode))
|
|
{
|
|
try
|
|
{
|
|
if (!statusbox.Lines[0].StartsWith(" ---"))
|
|
SetTextThreadSafe(statusbox, " --- " + titleidbox.Text + " ---");
|
|
}
|
|
catch // No lines present...
|
|
{
|
|
SetTextThreadSafe(statusbox, " --- " + titleidbox.Text + " ---");
|
|
}
|
|
}
|
|
else
|
|
SetTextThreadSafe(statusbox, statusbox.Text + "\r\n --- " + titleidbox.Text + " ---");
|
|
|
|
|
|
// Running Downloads in background so no form freezing
|
|
NUSDownloader.RunWorkerAsync();
|
|
}
|
|
|
|
private void SetTextThreadSafe(System.Windows.Forms.Control what, string setto)
|
|
{
|
|
SetPropertyThreadSafe(what, "Name", setto);
|
|
}
|
|
|
|
private void SetPropertyThreadSafe(System.ComponentModel.Component what, object setto, string property)
|
|
{
|
|
if (this.InvokeRequired)
|
|
{
|
|
SetPropertyThreadSafeCallback sptscb = new SetPropertyThreadSafeCallback(SetPropertyThreadSafe);
|
|
try
|
|
{
|
|
this.Invoke(sptscb, new object[] { what, setto, property });
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// FFFFF!
|
|
}
|
|
return;
|
|
}
|
|
what.GetType().GetProperty(property).SetValue(what, setto, null);
|
|
//what.Text = setto;
|
|
}
|
|
|
|
private void NUSDownloader_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
|
|
{
|
|
Control.CheckForIllegalCrossThreadCalls = false; // this function would need major rewriting to get rid of this...
|
|
if (!(script_mode))
|
|
WriteStatus("Starting NUS Download. Please be patient!");
|
|
SetEnableforDownload(false);
|
|
downloadstartbtn.Text = "Starting NUS Download!";
|
|
|
|
// WebClient configuration
|
|
WebClient nusWC = new WebClient();
|
|
nusWC = ConfigureWithProxy(nusWC);
|
|
nusWC.Headers.Add("User-Agent", "wii libnup/1.0"); // Set UserAgent to Wii value
|
|
|
|
// Create\Configure NusClient
|
|
libWiiSharp.NusClient nusClient = new libWiiSharp.NusClient();
|
|
nusClient.ConfigureNusClient(nusWC);
|
|
nusClient.UseLocalFiles = localuse.Checked;
|
|
nusClient.ContinueWithoutTicket = true;
|
|
|
|
// Server
|
|
if (consoleCBox.SelectedIndex == 0)
|
|
nusClient.SetToWiiServer();
|
|
else if (consoleCBox.SelectedIndex == 1)
|
|
nusClient.SetToDSiServer();
|
|
|
|
// Events
|
|
nusClient.Debug += new EventHandler<libWiiSharp.MessageEventArgs>(nusClient_Debug);
|
|
nusClient.Progress += new EventHandler<ProgressChangedEventArgs>(nusClient_Progress);
|
|
|
|
libWiiSharp.StoreType[] storeTypes = new libWiiSharp.StoreType[3];
|
|
if (packbox.Checked) storeTypes[0] = libWiiSharp.StoreType.WAD; else storeTypes[0] = libWiiSharp.StoreType.Empty;
|
|
if (decryptbox.Checked) storeTypes[1] = libWiiSharp.StoreType.DecryptedContent; else storeTypes[1] = libWiiSharp.StoreType.Empty;
|
|
if (keepenccontents.Checked) storeTypes[2] = libWiiSharp.StoreType.EncryptedContent; else storeTypes[2] = libWiiSharp.StoreType.Empty;
|
|
|
|
string wadName;
|
|
if (String.IsNullOrEmpty(WAD_Saveas_Filename))
|
|
wadName = wadnamebox.Text;
|
|
else
|
|
wadName = WAD_Saveas_Filename;
|
|
|
|
try
|
|
{
|
|
nusClient.DownloadTitle(titleidbox.Text, titleversion.Text, Path.Combine(CURRENT_DIR, "titles"), wadName, storeTypes);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
WriteStatus("Uhoh, the download bombed: \"" + ex.Message + " ):\"");
|
|
}
|
|
|
|
if (iosPatchCheckbox.Checked == true) { // Apply patches then...
|
|
// Okay, it's checked.
|
|
libWiiSharp.IosPatcher iosp = new libWiiSharp.IosPatcher();
|
|
libWiiSharp.WAD ioswad = new libWiiSharp.WAD();
|
|
if (wadName.Contains(Path.DirectorySeparatorChar.ToString()) || wadName.Contains(Path.AltDirectorySeparatorChar.ToString()))
|
|
ioswad.LoadFile(wadName);
|
|
else
|
|
ioswad.LoadFile(Path.Combine(Path.Combine(Path.Combine(Path.Combine(CURRENT_DIR, "titles"), titleidbox.Text), nusClient.TitleVersion.ToString()), wadName));
|
|
try
|
|
{
|
|
iosp.LoadIOS(ref ioswad);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
WriteStatus("NUS Download Finished.");
|
|
return;
|
|
}
|
|
foreach (object checkItem in iosPatchesListBox.CheckedItems)
|
|
{
|
|
// ensure not 'indeterminate'
|
|
if (iosPatchesListBox.GetItemCheckState(iosPatchesListBox.Items.IndexOf(checkItem)).ToString() == "Checked") {
|
|
switch (checkItem.ToString()) {
|
|
case "Trucha bug":
|
|
if (iosp.PatchFakeSigning() > 0)
|
|
WriteStatus(" - Patched in fake-signing");
|
|
else
|
|
WriteStatus(" - Could not patch fake-signing");
|
|
break;
|
|
case "ES_Identify":
|
|
if (iosp.PatchEsIdentify() > 0)
|
|
WriteStatus(" - Patched in ES_Identify");
|
|
else
|
|
WriteStatus(" - Could not patch ES_Identify");
|
|
break;
|
|
case "NAND permissions":
|
|
if (iosp.PatchNandPermissions() > 0)
|
|
WriteStatus(" - Patched in NAND permissions");
|
|
else
|
|
WriteStatus(" - Could not patch NAND permissions");
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
// WriteStatus(iosPatchesListBox.GetItemCheckState(iosPatchesListBox.Items.IndexOf(checkItem)).ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
WriteStatus("NUS Download Finished.");
|
|
|
|
}
|
|
|
|
void nusClient_Progress(object sender, ProgressChangedEventArgs e)
|
|
{
|
|
dlprogress.Value = e.ProgressPercentage;
|
|
}
|
|
|
|
void nusClient_Debug(object sender, libWiiSharp.MessageEventArgs e)
|
|
{
|
|
WriteStatus(e.Message);
|
|
}
|
|
|
|
private void NUSDownloader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
WAD_Saveas_Filename = String.Empty;
|
|
|
|
SetEnableforDownload(true);
|
|
downloadstartbtn.Text = "Start NUS Download!";
|
|
dlprogress.Value = 0;
|
|
|
|
if (IsWin7())
|
|
dlprogress.ShowInTaskbar = false;
|
|
|
|
if (script_mode)
|
|
statusbox.Text = "";
|
|
}
|
|
|
|
private void consoleCBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (consoleCBox.SelectedIndex == 0)
|
|
{
|
|
// Can pack WADs / Decrypt
|
|
packbox.Enabled = true;
|
|
decryptbox.Enabled = true;
|
|
}
|
|
if (consoleCBox.SelectedIndex == 1)
|
|
{
|
|
// Cannot Pack WADs
|
|
packbox.Checked = false;
|
|
packbox.Enabled = false;
|
|
|
|
// Can decrypt if dsikey exists...
|
|
if (dsidecrypt == false)
|
|
{
|
|
decryptbox.Checked = false;
|
|
decryptbox.Enabled = false;
|
|
}
|
|
|
|
wadnamebox.Enabled = false;
|
|
wadnamebox.Text = "";
|
|
}
|
|
}
|
|
|
|
private void packbox_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (packbox.Checked == true)
|
|
{
|
|
wadnamebox.Enabled = true;
|
|
saveaswadbtn.Enabled = true;
|
|
// Change WAD name if applicable
|
|
UpdatePackedName();
|
|
}
|
|
else
|
|
{
|
|
wadnamebox.Enabled = false;
|
|
saveaswadbtn.Enabled = false;
|
|
wadnamebox.Text = String.Empty;
|
|
if (iosPatchCheckbox.Checked)
|
|
iosPatchCheckbox.Checked = false;
|
|
}
|
|
}
|
|
|
|
private void titleidbox_TextChanged(object sender, EventArgs e)
|
|
{
|
|
UpdatePackedName();
|
|
EnablePatchIOSBox();
|
|
}
|
|
|
|
private void titleversion_TextChanged(object sender, EventArgs e)
|
|
{
|
|
UpdatePackedName();
|
|
}
|
|
|
|
private void EnablePatchIOSBox()
|
|
{
|
|
iosPatchCheckbox.Enabled = TitleIsIOS(titleidbox.Text);
|
|
if (iosPatchCheckbox.Enabled == false)
|
|
iosPatchCheckbox.Checked = false;
|
|
}
|
|
|
|
private bool TitleIsIOS(string titleid)
|
|
{
|
|
if (titleid.Length != 16)
|
|
return false;
|
|
|
|
if ((titleid == "0000000100000001") || (titleid == "0000000100000002"))
|
|
return false;
|
|
|
|
if (titleid.Substring(0, 14) == "00000001000000")
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Displays the bytes.
|
|
/// </summary>
|
|
/// <param name="bytes">The bytes.</param>
|
|
/// <param name="spacer">What separates the bytes</param>
|
|
/// <returns></returns>
|
|
public string DisplayBytes(byte[] bytes, string spacer)
|
|
{
|
|
string output = "";
|
|
for (int i = 0; i < bytes.Length; ++i)
|
|
{
|
|
output += bytes[i].ToString("X2") + spacer;
|
|
}
|
|
return output;
|
|
}
|
|
|
|
private void DatabaseButton_Click(object sender, EventArgs e)
|
|
{
|
|
// Open Database button menu...
|
|
databaseStrip.Show(databaseButton, 2, (2+databaseButton.Height));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears the database strip.
|
|
/// </summary>
|
|
private void ClearDatabaseStrip()
|
|
{
|
|
object[] thingstoclear = new object[] {
|
|
SystemMenuList, IOSMenuList, WiiWareMenuList, VCMenuList,
|
|
|
|
// Now Virtual Console
|
|
C64MenuList, NeoGeoMenuList, NESMenuList,
|
|
SNESMenuList, N64MenuList, TurboGrafx16MenuList,
|
|
TurboGrafxCDMenuList, MSXMenuList, SegaMSMenuList,
|
|
GenesisMenuList, VCArcadeMenuList
|
|
};
|
|
|
|
foreach (System.Windows.Forms.ToolStripMenuItem tsmiclear in thingstoclear)
|
|
{
|
|
if (tsmiclear.Name != "VCMenuList") // Don't clear the VC Menu...
|
|
tsmiclear.DropDownItems.Clear();
|
|
|
|
if (tsmiclear.OwnerItem != VCMenuList) // and don't disable the VC menu subparts...
|
|
tsmiclear.Enabled = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fills the database strip with the local database.xml file.
|
|
/// </summary>
|
|
private void FillDatabaseStrip(BackgroundWorker worker)
|
|
{
|
|
// Load database.xml into memorystream to perhaps reduce disk reads?
|
|
string databasestr = File.ReadAllText(Path.Combine(CURRENT_DIR, "database.xml"));
|
|
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
|
|
byte[] databasebytes = encoding.GetBytes(databasestr);
|
|
|
|
// Load the memory stream
|
|
MemoryStream databaseStream = new MemoryStream(databasebytes);
|
|
databaseStream.Seek(0, SeekOrigin.Begin);
|
|
|
|
XmlDocument xDoc = new XmlDocument();
|
|
xDoc.Load(databaseStream);
|
|
|
|
// Variables
|
|
string[] XMLNodeTypes = new string[5] {"SYS", "IOS", "VC", "WW", "UPD"};
|
|
|
|
int totalLength = xDoc.SelectNodes("/database/*").Count;
|
|
int rnt = 0;
|
|
// Loop through XMLNodeTypes
|
|
for (int i = 0; i < XMLNodeTypes.Length; i++)
|
|
{
|
|
XmlNodeList XMLSpecificNodeTypeList = xDoc.GetElementsByTagName(XMLNodeTypes[i]);
|
|
|
|
for (int x = 0; x < XMLSpecificNodeTypeList.Count; x++)
|
|
{
|
|
ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem();
|
|
XmlAttributeCollection XMLAttributes = XMLSpecificNodeTypeList[x].Attributes;
|
|
|
|
string titleID = "";
|
|
string updateScript;
|
|
string descname = "";
|
|
bool dangerous = false;
|
|
bool ticket = true;
|
|
|
|
// Okay, so now report the progress...
|
|
rnt = rnt + 1;
|
|
float currentProgress = ((float) rnt/(float) totalLength)*(float) 100;
|
|
if (Convert.ToInt16(Math.Round(currentProgress))%10 == 0)
|
|
worker.ReportProgress(Convert.ToInt16(Math.Round(currentProgress)));
|
|
|
|
// Lol.
|
|
XmlNodeList ChildrenOfTheNode = XMLSpecificNodeTypeList[x].ChildNodes;
|
|
|
|
for (int z = 0; z < ChildrenOfTheNode.Count; z++)
|
|
{
|
|
switch (ChildrenOfTheNode[z].Name)
|
|
{
|
|
case "name":
|
|
descname = ChildrenOfTheNode[z].InnerText;
|
|
break;
|
|
case "titleID":
|
|
titleID = ChildrenOfTheNode[z].InnerText;
|
|
break;
|
|
case "titleIDs":
|
|
updateScript = ChildrenOfTheNode[z].InnerText;
|
|
XMLToolStripItem.AccessibleDescription = updateScript;
|
|
// TODO: Find somewhere better to put this. AND FAST.
|
|
break;
|
|
case "version":
|
|
string[] versions = ChildrenOfTheNode[z].InnerText.Split(',');
|
|
// Add to region things?
|
|
if (XMLToolStripItem.DropDownItems.Count > 0)
|
|
{
|
|
for (int b = 0; b < XMLToolStripItem.DropDownItems.Count; b++)
|
|
{
|
|
if (ChildrenOfTheNode[z].InnerText != "")
|
|
{
|
|
ToolStripMenuItem regitem =
|
|
(ToolStripMenuItem) XMLToolStripItem.DropDownItems[b];
|
|
regitem.DropDownItems.Add("Latest Version");
|
|
for (int y = 0; y < versions.Length; y++)
|
|
{
|
|
regitem.DropDownItems.Add("v" + versions[y]);
|
|
}
|
|
regitem.DropDownItemClicked +=
|
|
new ToolStripItemClickedEventHandler(deepitem_clicked);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XMLToolStripItem.DropDownItems.Add("Latest Version");
|
|
if (ChildrenOfTheNode[z].InnerText != "")
|
|
{
|
|
for (int y = 0; y < versions.Length; y++)
|
|
{
|
|
XMLToolStripItem.DropDownItems.Add("v" + versions[y]);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case "region":
|
|
string[] regions = ChildrenOfTheNode[z].InnerText.Split(',');
|
|
if (ChildrenOfTheNode[z].InnerText != "")
|
|
{
|
|
for (int y = 0; y < regions.Length; y++)
|
|
{
|
|
XMLToolStripItem.DropDownItems.Add(RegionFromIndex(Convert.ToInt32(regions[y]),
|
|
xDoc));
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
case "ticket":
|
|
ticket = Convert.ToBoolean(ChildrenOfTheNode[z].InnerText);
|
|
break;
|
|
case "danger":
|
|
dangerous = true;
|
|
XMLToolStripItem.ToolTipText = ChildrenOfTheNode[z].InnerText;
|
|
break;
|
|
}
|
|
XMLToolStripItem.Image = SelectItemImage(ticket, dangerous);
|
|
|
|
if (titleID != "")
|
|
{
|
|
XMLToolStripItem.Text = String.Format("{0} - {1}", titleID, descname);
|
|
}
|
|
else
|
|
{
|
|
XMLToolStripItem.Text = descname;
|
|
}
|
|
}
|
|
AddToolStripItemToStrip(i, XMLToolStripItem, XMLAttributes);
|
|
}
|
|
// Now enable the specific toolbar
|
|
switch (XMLNodeTypes[i])
|
|
{
|
|
case "IOS":
|
|
//IOSMenuList.Enabled = true;
|
|
SetPropertyThreadSafe(IOSMenuList, true, "Enabled");
|
|
break;
|
|
case "SYS":
|
|
SetPropertyThreadSafe(SystemMenuList, true, "Enabled");
|
|
break;
|
|
case "VC":
|
|
SetPropertyThreadSafe(VCMenuList, true, "Enabled");
|
|
break;
|
|
case "WW":
|
|
SetPropertyThreadSafe(WiiWareMenuList, true, "Enabled");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the tool strip item to strip.
|
|
/// </summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <param name="additionitem">The additionitem.</param>
|
|
/// <param name="attributes">The attributes.</param>
|
|
private void AddToolStripItemToStrip(int type, ToolStripMenuItem additionitem, XmlAttributeCollection attributes)
|
|
{
|
|
Debug.WriteLine(String.Format("Adding item (Type: {0})...", type));
|
|
// Check if thread-safe
|
|
if (this.InvokeRequired)
|
|
{
|
|
Debug.WriteLine("InvokeRequired...");
|
|
AddToolStripItemToStripCallback atsitsc = new AddToolStripItemToStripCallback(AddToolStripItemToStrip);
|
|
this.Invoke(atsitsc, new object[] {type, additionitem, attributes});
|
|
return;
|
|
}
|
|
// Deal with VC list depth...
|
|
if (type == 2)
|
|
{
|
|
Debug.WriteLine("Adding:");
|
|
Debug.WriteLine(additionitem);
|
|
switch (attributes[0].Value)
|
|
{
|
|
case "C64":
|
|
C64MenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "NEO":
|
|
NeoGeoMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "NES":
|
|
NESMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "SNES":
|
|
SNESMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "N64":
|
|
N64MenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "TG16":
|
|
TurboGrafx16MenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "TGCD":
|
|
TurboGrafxCDMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "MSX":
|
|
MSXMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "SMS":
|
|
SegaMSMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "GEN":
|
|
GenesisMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case "ARC":
|
|
VCArcadeMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
additionitem.DropDownItemClicked += new ToolStripItemClickedEventHandler(wwitem_regionclicked);
|
|
}
|
|
else if (type == 4)
|
|
{
|
|
// I am a brand new combine harvester
|
|
//MassUpdateList.DropDownItems.Add(additionitem);
|
|
switch (attributes[0].Value)
|
|
{
|
|
case "KOR":
|
|
KoreaMassUpdate.DropDownItems.Add(additionitem);
|
|
KoreaMassUpdate.Enabled = true;
|
|
break;
|
|
case "PAL":
|
|
PALMassUpdate.DropDownItems.Add(additionitem);
|
|
PALMassUpdate.Enabled = true;
|
|
break;
|
|
case "NTSC":
|
|
NTSCMassUpdate.DropDownItems.Add(additionitem);
|
|
NTSCMassUpdate.Enabled = true;
|
|
break;
|
|
default:
|
|
Debug.WriteLine("Oops - database error");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Add SYS, IOS, WW items
|
|
// I thought using index would work in .Items, but I
|
|
// guess this switch will have to do...
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
SystemMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case 1:
|
|
IOSMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
case 3:
|
|
WiiWareMenuList.DropDownItems.Add(additionitem);
|
|
break;
|
|
}
|
|
additionitem.DropDownItemClicked += new ToolStripItemClickedEventHandler(sysitem_versionclicked);
|
|
}
|
|
}
|
|
|
|
private void deepitem_clicked(object sender, ToolStripItemClickedEventArgs e)
|
|
{
|
|
titleidbox.Text = e.ClickedItem.OwnerItem.OwnerItem.Text.Substring(0, 16);
|
|
titleidbox.Text = titleidbox.Text.Replace("XX", e.ClickedItem.OwnerItem.Text.Substring(0, 2));
|
|
|
|
if (e.ClickedItem.Text != "Latest Version")
|
|
{
|
|
if (e.ClickedItem.Text.Contains("v"))
|
|
{
|
|
if (e.ClickedItem.Text.Contains(" "))
|
|
titleversion.Text = e.ClickedItem.Text.Substring(1, e.ClickedItem.Text.IndexOf(' ') - 1);
|
|
else
|
|
titleversion.Text = e.ClickedItem.Text.Substring(1, e.ClickedItem.Text.Length - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
titleversion.Text = "";
|
|
}
|
|
|
|
// Prepare StatusBox...
|
|
string titlename = e.ClickedItem.OwnerItem.OwnerItem.Text.Substring(19,
|
|
(e.ClickedItem.OwnerItem.OwnerItem.Text.
|
|
Length - 19));
|
|
statusbox.Text = " --- " + titlename + " ---";
|
|
|
|
// Check if a ticket is present...
|
|
if ((e.ClickedItem.OwnerItem.OwnerItem.Image) == (orange) ||
|
|
(e.ClickedItem.OwnerItem.OwnerItem.Image) == (redorange))
|
|
{
|
|
//ignoreticket.Checked = true;
|
|
WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!");
|
|
packbox.Checked = false;
|
|
decryptbox.Checked = false;
|
|
}
|
|
|
|
// Change WAD name if packed is already checked...
|
|
if (packbox.Checked)
|
|
{
|
|
OfficialWADNaming(titlename);
|
|
}
|
|
|
|
// Check for danger item
|
|
if ((e.ClickedItem.OwnerItem.OwnerItem.Image) == (redgreen) ||
|
|
(e.ClickedItem.OwnerItem.OwnerItem.Image) == (redorange))
|
|
{
|
|
WriteStatus("\r\n" + e.ClickedItem.OwnerItem.OwnerItem.ToolTipText);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mods WAD names to be official.
|
|
/// </summary>
|
|
/// <param name="titlename">The titlename.</param>
|
|
public string OfficialWADNaming(string titlename)
|
|
{
|
|
if (titlename == "MIOS")
|
|
titlename = "RVL-mios-[v].wad";
|
|
else if (titlename.Contains("IOS"))
|
|
titlename = titlename + "-64-[v].wad";
|
|
else if (titlename.Contains("System Menu"))
|
|
titlename = "RVL-WiiSystemmenu-[v].wad";
|
|
else if (titlename.Contains("System Menu"))
|
|
titlename = "RVL-WiiSystemmenu-[v].wad";
|
|
else if (titlename == "BC")
|
|
titlename = "RVL-bc-[v].wad";
|
|
else if (titlename.Contains("Mii Channel"))
|
|
titlename = "RVL-NigaoeNR-[v].wad";
|
|
else if (titlename.Contains("Shopping Channel"))
|
|
titlename = "RVL-Shopping-[v].wad";
|
|
else if (titlename.Contains("Weather Channel"))
|
|
titlename = "RVL-Weather-[v].wad";
|
|
else
|
|
titlename = titlename + "-NUS-[v].wad";
|
|
|
|
if (wadnamebox.InvokeRequired)
|
|
{
|
|
OfficialWADNamingCallback ownc = new OfficialWADNamingCallback(OfficialWADNaming);
|
|
wadnamebox.Invoke(ownc, new object[] { titlename });
|
|
return titlename;
|
|
}
|
|
|
|
wadnamebox.Text = titlename;
|
|
|
|
if (titleversion.Text != "")
|
|
wadnamebox.Text = wadnamebox.Text.Replace("[v]", "v" + titleversion.Text);
|
|
|
|
return titlename;
|
|
}
|
|
|
|
private void wwitem_regionclicked(object sender, ToolStripItemClickedEventArgs e)
|
|
{
|
|
titleidbox.Text = e.ClickedItem.OwnerItem.Text.Substring(0, 16);
|
|
titleversion.Text = "";
|
|
titleidbox.Text = titleidbox.Text.Replace("XX", e.ClickedItem.Text.Substring(0, 2));
|
|
|
|
// Prepare StatusBox...
|
|
string titlename = e.ClickedItem.OwnerItem.Text.Substring(19, (e.ClickedItem.OwnerItem.Text.Length - 19));
|
|
statusbox.Text = " --- " + titlename + " ---";
|
|
|
|
// Check if a ticket is present...
|
|
if ((e.ClickedItem.OwnerItem.Image) == (orange) || (e.ClickedItem.OwnerItem.Image) == (redorange))
|
|
{
|
|
//ignoreticket.Checked = true;
|
|
WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!");
|
|
packbox.Checked = false;
|
|
decryptbox.Checked = false;
|
|
}
|
|
|
|
// Change WAD name if packed is already checked...
|
|
if (packbox.Checked)
|
|
{
|
|
OfficialWADNaming(titlename);
|
|
}
|
|
|
|
// Check for danger item
|
|
if ((e.ClickedItem.OwnerItem.Image) == (redgreen) || (e.ClickedItem.OwnerItem.Image) == (redorange))
|
|
{
|
|
WriteStatus("\r\n" + e.ClickedItem.OwnerItem.ToolTipText);
|
|
}
|
|
}
|
|
|
|
private void upditem_itemclicked(object sender, ToolStripItemClickedEventArgs e)
|
|
{
|
|
WriteStatus("Preparing to run download script...");
|
|
script_mode = true;
|
|
SetTextThreadSafe(statusbox, "");
|
|
WriteStatus("Starting script download. Please be patient!");
|
|
string[] NUS_Entries = e.ClickedItem.AccessibleDescription.Split('\n');
|
|
// TODO: Find somewhere better to put this. AND FAST!
|
|
for (int i = 0; i < NUS_Entries.Length; i++)
|
|
{
|
|
WriteStatus(NUS_Entries[i]);
|
|
}
|
|
script_filename = "\000";
|
|
nusentries = NUS_Entries;
|
|
BackgroundWorker scripter = new BackgroundWorker();
|
|
scripter.DoWork += new DoWorkEventHandler(RunScript);
|
|
scripter.RunWorkerAsync();
|
|
}
|
|
|
|
|
|
private void sysitem_versionclicked(object sender, ToolStripItemClickedEventArgs e)
|
|
{
|
|
titleidbox.Text = e.ClickedItem.OwnerItem.Text.Substring(0, 16);
|
|
|
|
if (e.ClickedItem.Text != "Latest Version")
|
|
{
|
|
if (e.ClickedItem.Text.Contains("v"))
|
|
{
|
|
if (e.ClickedItem.Text.Contains(" "))
|
|
titleversion.Text = e.ClickedItem.Text.Substring(1, e.ClickedItem.Text.IndexOf(' ') - 1);
|
|
else
|
|
titleversion.Text = e.ClickedItem.Text.Substring(1, e.ClickedItem.Text.Length - 1);
|
|
}
|
|
else
|
|
{
|
|
// Apparently it's a region code..
|
|
titleidbox.Text = titleidbox.Text.Replace("XX", e.ClickedItem.Text.Substring(0, 2));
|
|
titleversion.Text = "";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
titleversion.Text = "";
|
|
}
|
|
|
|
// Prepare StatusBox...
|
|
string titlename = e.ClickedItem.OwnerItem.Text.Substring(19, (e.ClickedItem.OwnerItem.Text.Length - 19));
|
|
statusbox.Text = " --- " + titlename + " ---";
|
|
|
|
if ((e.ClickedItem.OwnerItem.Image) == (orange) || (e.ClickedItem.OwnerItem.Image) == (redorange))
|
|
{
|
|
//ignoreticket.Checked = true;
|
|
WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!");
|
|
packbox.Checked = false;
|
|
decryptbox.Checked = false;
|
|
}
|
|
|
|
// Change WAD name if packed is already checked...
|
|
if (packbox.Checked)
|
|
{
|
|
if (titlename.Contains("IOS"))
|
|
wadnamebox.Text = titlename + "-64-[v].wad";
|
|
else
|
|
wadnamebox.Text = titlename + "-NUS-[v].wad";
|
|
if (titleversion.Text != "")
|
|
wadnamebox.Text = wadnamebox.Text.Replace("[v]", "v" + titleversion.Text);
|
|
}
|
|
|
|
// Check for danger item
|
|
if ((e.ClickedItem.OwnerItem.Image) == (redgreen) || (e.ClickedItem.OwnerItem.Image) == (redorange))
|
|
{
|
|
WriteStatus("\n" + e.ClickedItem.OwnerItem.ToolTipText);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gathers the region based on index
|
|
/// </summary>
|
|
/// <param name="index">The index.</param>
|
|
/// <param name="databasexml">XmlDocument with database inside</param>
|
|
/// <returns>Region desc</returns>
|
|
private string RegionFromIndex(int index, XmlDocument databasexml)
|
|
{
|
|
/* Typical Region XML
|
|
* <REGIONS>
|
|
<region index="0">41 (All/System)</region>
|
|
<region index=1>44 (German)</region>
|
|
<region index=2>45 (USA/NTSC)</region>
|
|
<region index=3>46 (French)</region>
|
|
<region index=4>4A (Japan)</region>
|
|
<region index=5>4B (Korea)</region>
|
|
<region index=6>4C (Japanese Import to Europe/Australia/PAL)</region>
|
|
<region index=7>4D (American Import to Europe/Australia/PAL)</region>
|
|
<region index=8>4E (Japanese Import to USA/NTSC)</region>
|
|
<region index=9>50 (Europe/PAL)</region>
|
|
<region index=10>51 (Korea w/ Japanese Language)</region>
|
|
<region index=11>54 (Korea w/ English Language)</region>
|
|
<region index=12>58 (Some Homebrew)</region>
|
|
</REGIONS>
|
|
*/
|
|
|
|
XmlNodeList XMLRegionList = databasexml.GetElementsByTagName("REGIONS");
|
|
XmlNodeList ChildrenOfTheNode = XMLRegionList[0].ChildNodes;
|
|
|
|
// For each child node (region node)
|
|
for (int z = 0; z < ChildrenOfTheNode.Count; z++)
|
|
{
|
|
// Gather attributes (index='x')
|
|
XmlAttributeCollection XMLAttributes = ChildrenOfTheNode[z].Attributes;
|
|
|
|
// Return value of node if index matches
|
|
if (Convert.ToInt32(XMLAttributes[0].Value) == index)
|
|
return ChildrenOfTheNode[z].InnerText;
|
|
}
|
|
|
|
return "XX (Error)";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the region codes.
|
|
/// </summary>
|
|
private void LoadRegionCodes()
|
|
{
|
|
// TODO: make this check InvokeRequired...
|
|
if (this.InvokeRequired)
|
|
{
|
|
Debug.Write("TOLDYOUSO!");
|
|
BootChecksCallback bcc = new BootChecksCallback(LoadRegionCodes);
|
|
this.Invoke(bcc);
|
|
return;
|
|
}
|
|
XmlDocument xDoc = new XmlDocument();
|
|
xDoc.Load("database.xml");
|
|
|
|
XmlNodeList XMLRegionList = xDoc.GetElementsByTagName("REGIONS");
|
|
XmlNodeList ChildrenOfTheNode = XMLRegionList[0].ChildNodes;
|
|
|
|
// For each child node (region node)
|
|
for (int z = 0; z < ChildrenOfTheNode.Count; z++)
|
|
{
|
|
RegionCodesList.DropDownItems.Add(ChildrenOfTheNode[z].InnerText);
|
|
}
|
|
}
|
|
|
|
private void RegionCodesList_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
|
|
{
|
|
if (titleidbox.Text.Length == 16)
|
|
titleidbox.Text = titleidbox.Text.Substring(0, 14) + e.ClickedItem.Text.Substring(0, 2);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the illegal characters.
|
|
/// </summary>
|
|
/// <param name="databasestr">removes the illegal chars</param>
|
|
/// <returns>legal string</returns>
|
|
private static string RemoveIllegalCharacters(string databasestr)
|
|
{
|
|
// Database strings must contain filename-legal characters.
|
|
foreach (char illegalchar in System.IO.Path.GetInvalidFileNameChars())
|
|
{
|
|
if (databasestr.Contains(illegalchar.ToString()))
|
|
databasestr = databasestr.Replace(illegalchar, '-');
|
|
}
|
|
return databasestr;
|
|
}
|
|
|
|
private void ClearStatusbox(object sender, EventArgs e)
|
|
{
|
|
// Clear Statusbox.text
|
|
statusbox.Text = "";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Makes everything disabled/enabled.
|
|
/// </summary>
|
|
/// <param name="enabled">if set to <c>true</c> [enabled].</param>
|
|
private void SetEnableforDownload(bool enabled)
|
|
{
|
|
if (this.InvokeRequired)
|
|
{
|
|
SetEnableForDownloadCallback sefdcb = new SetEnableForDownloadCallback(SetEnableforDownload);
|
|
this.Invoke(sefdcb, new object[] { enabled });
|
|
return;
|
|
}
|
|
// Disable things the user should not mess with during download...
|
|
downloadstartbtn.Enabled = enabled;
|
|
titleidbox.Enabled = enabled;
|
|
titleversion.Enabled = enabled;
|
|
Extrasbtn.Enabled = enabled;
|
|
databaseButton.Enabled = enabled;
|
|
packbox.Enabled = enabled;
|
|
localuse.Enabled = enabled;
|
|
saveaswadbtn.Enabled = enabled;
|
|
decryptbox.Enabled = enabled;
|
|
keepenccontents.Enabled = enabled;
|
|
scriptsbutton.Enabled = enabled;
|
|
consoleCBox.Enabled = enabled;
|
|
iosPatchCheckbox.Enabled = enabled;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Makes tooltips disappear in the database, as many contain danger tag info.
|
|
/// </summary>
|
|
/// <param name="enabled">if set to <c>true</c> [enabled].</param>
|
|
private void ShowInnerToolTips(bool enabled)
|
|
{
|
|
// Force tooltips to GTFO in sub menus...
|
|
foreach (ToolStripItem item in databaseStrip.Items)
|
|
{
|
|
try
|
|
{
|
|
ToolStripMenuItem menuitem = (ToolStripMenuItem) item;
|
|
menuitem.DropDown.ShowItemToolTips = false;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// Do nothing, some objects will not cast.
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Selects the database item image.
|
|
/// </summary>
|
|
/// <param name="ticket">if set to <c>true</c> [ticket].</param>
|
|
/// <param name="danger">if set to <c>true</c> [danger].</param>
|
|
/// <returns>Correct Image</returns>
|
|
private System.Drawing.Image SelectItemImage(bool ticket, bool danger)
|
|
{
|
|
// All is good, go green...
|
|
if ((ticket) && (!danger))
|
|
return green;
|
|
|
|
// There's no ticket, but danger is clear...
|
|
if ((!ticket) && (!danger))
|
|
return orange;
|
|
|
|
// DANGER WILL ROBINSON...
|
|
if ((ticket) && (danger))
|
|
return redgreen;
|
|
|
|
// Double bad...
|
|
if ((!ticket) && (danger))
|
|
return redorange;
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the name of the packed WAD in the textbox.
|
|
/// </summary>
|
|
private void UpdatePackedName()
|
|
{
|
|
// Change WAD name if applicable
|
|
|
|
string title_name = null;
|
|
|
|
if ((titleidbox.Enabled == true || script_mode == true) && (packbox.Checked == true))
|
|
{
|
|
if (titleversion.Text != "")
|
|
{
|
|
wadnamebox.Text = titleidbox.Text + "-NUS-v" + titleversion.Text + ".wad";
|
|
}
|
|
else
|
|
{
|
|
wadnamebox.Text = titleidbox.Text + "-NUS-[v]" + titleversion.Text + ".wad";
|
|
}
|
|
|
|
if ((File.Exists("database.xml") == true) && (titleidbox.Text.Length == 16))
|
|
title_name = NameFromDatabase(titleidbox.Text);
|
|
|
|
if (title_name != null)
|
|
{
|
|
wadnamebox.Text = wadnamebox.Text.Replace(titleidbox.Text, title_name);
|
|
OfficialWADNaming(title_name);
|
|
}
|
|
}
|
|
wadnamebox.Text = RemoveIllegalCharacters(wadnamebox.Text);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether OS is win7.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// <c>true</c> if OS = win7; otherwise, <c>false</c>.
|
|
/// </returns>
|
|
private static bool IsWin7()
|
|
{
|
|
return (Environment.OSVersion.VersionString.Contains("6.1") == true);
|
|
}
|
|
|
|
private byte[] NewIntegertoByteArray(int theInt, int arrayLen)
|
|
{
|
|
byte[] resultArray = new byte[arrayLen];
|
|
|
|
for (int i = arrayLen - 1; i >= 0; i--)
|
|
{
|
|
resultArray[i] = (byte) ((theInt >> (8*i)) & 0xFF);
|
|
}
|
|
Array.Reverse(resultArray);
|
|
|
|
// Fix duplication, rewrite extra to 0x00;
|
|
if (arrayLen > 4)
|
|
{
|
|
for (int i = 0; i < (arrayLen - 4); i++)
|
|
{
|
|
resultArray[i] = 0x00;
|
|
}
|
|
}
|
|
return resultArray;
|
|
}
|
|
|
|
/*
|
|
/// <summary>
|
|
/// Does byte[] contain byte[]?
|
|
/// </summary>
|
|
/// <param name="bigboy">The large byte[].</param>
|
|
/// <param name="littleman">Small byte[] which may be in large one.</param>
|
|
/// <returns>messed up int[] with offsets.</returns>
|
|
private int[] ByteArrayContainsByteArray(byte[] bigboy, byte[] littleman)
|
|
{
|
|
// bigboy.Contains(littleman);
|
|
// returns offset { cnt , ofst };
|
|
int[] offset = new int[5];
|
|
for (int a = 0; a < (bigboy.Length - littleman.Length); a++)
|
|
{
|
|
int matches = 0;
|
|
for (int b = 0; b < littleman.Length; b++)
|
|
{
|
|
if (bigboy[a + b] == littleman[b])
|
|
matches += 1;
|
|
}
|
|
if (matches == littleman.Length)
|
|
{
|
|
offset[offset[0] + 1] = a;
|
|
offset[0] += 1;
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}*/
|
|
|
|
private WebClient ConfigureWithProxy(WebClient client)
|
|
{
|
|
// Proxy
|
|
if (!(String.IsNullOrEmpty(proxy_url)))
|
|
{
|
|
WebProxy customproxy = new WebProxy();
|
|
customproxy.Address = new Uri(proxy_url);
|
|
if (String.IsNullOrEmpty(proxy_usr))
|
|
customproxy.UseDefaultCredentials = true;
|
|
else
|
|
{
|
|
NetworkCredential cred = new NetworkCredential();
|
|
cred.UserName = proxy_usr;
|
|
|
|
if (!(String.IsNullOrEmpty(proxy_pwd)))
|
|
cred.Password = proxy_pwd;
|
|
|
|
customproxy.Credentials = cred;
|
|
}
|
|
client.Proxy = customproxy;
|
|
WriteStatus(" - Custom proxy settings applied!");
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
client.Proxy = WebRequest.GetSystemWebProxy();
|
|
client.UseDefaultCredentials = true;
|
|
}
|
|
catch (NotImplementedException)
|
|
{
|
|
// Linux support
|
|
WriteStatus("This operating system does not support automatic system proxy usage. Operating without a proxy...");
|
|
}
|
|
}
|
|
return client;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the new database via WiiBrew.
|
|
/// </summary>
|
|
/// <returns>Database as a String</returns>
|
|
private void RetrieveNewDatabase(object sender, DoWorkEventArgs e)
|
|
{
|
|
// Retrieve Wiibrew database page source code
|
|
WebClient databasedl = new WebClient();
|
|
|
|
// Proxy
|
|
databasedl = ConfigureWithProxy(databasedl);
|
|
|
|
string wiibrewsource =
|
|
databasedl.DownloadString("http://www.wiibrew.org/wiki/NUS_Downloader/database?cachesmash=" +
|
|
System.DateTime.Now.ToString());
|
|
|
|
// Strip out HTML
|
|
wiibrewsource = Regex.Replace(wiibrewsource, @"<(.|\n)*?>", "");
|
|
|
|
// Shrink to fix only the database
|
|
string startofdatabase = "<database v";
|
|
string endofdatabase = "</database>";
|
|
wiibrewsource = wiibrewsource.Substring(wiibrewsource.IndexOf(startofdatabase),
|
|
wiibrewsource.Length - wiibrewsource.IndexOf(startofdatabase));
|
|
wiibrewsource = wiibrewsource.Substring(0, wiibrewsource.IndexOf(endofdatabase) + endofdatabase.Length);
|
|
|
|
// Fix ", <, >, and spaces
|
|
wiibrewsource = wiibrewsource.Replace("<", "<");
|
|
wiibrewsource = wiibrewsource.Replace(">", ">");
|
|
wiibrewsource = wiibrewsource.Replace(""", '"'.ToString());
|
|
wiibrewsource = wiibrewsource.Replace(" ", " "); // Shouldn't occur, but they happen...
|
|
|
|
// Return parsed xml database...
|
|
e.Result = wiibrewsource;
|
|
}
|
|
|
|
private void RetrieveNewDatabase_Completed(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
string database = e.Result.ToString();
|
|
string currentversion = GetDatabaseVersion("database.xml");
|
|
string onlineversion = GetDatabaseVersion(database);
|
|
WriteStatus(" - Database successfully parsed!");
|
|
WriteStatus(" - Current Database Version: " + currentversion);
|
|
WriteStatus(" - Online Database Version: " + onlineversion);
|
|
|
|
if (currentversion == onlineversion)
|
|
{
|
|
WriteStatus(" - You have the latest database version!");
|
|
return;
|
|
}
|
|
|
|
bool isCreation = false;
|
|
if (File.Exists("database.xml"))
|
|
{
|
|
WriteStatus(" - Overwriting your current database.xml...");
|
|
WriteStatus(" - The old database will become 'olddatabase.xml' in case the new one is faulty.");
|
|
|
|
string olddatabase = File.ReadAllText("database.xml");
|
|
File.WriteAllText("olddatabase.xml", olddatabase);
|
|
File.Delete("database.xml");
|
|
File.WriteAllText("database.xml", database);
|
|
}
|
|
else
|
|
{
|
|
WriteStatus(" - database.xml has been created.");
|
|
File.WriteAllText("database.xml", database);
|
|
isCreation = true;
|
|
}
|
|
|
|
// Load it up...
|
|
this.fds.RunWorkerAsync();
|
|
|
|
if (isCreation)
|
|
{
|
|
WriteStatus("Database successfully created!");
|
|
databaseButton.Visible = true;
|
|
//databaseButton.Enabled = false;
|
|
updateDatabaseToolStripMenuItem.Text = "Download Database";
|
|
}
|
|
else
|
|
{
|
|
WriteStatus("Database successfully updated!");
|
|
}
|
|
}
|
|
|
|
private void updateDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
statusbox.Text = "";
|
|
WriteStatus("Updating your database.xml from Wiibrew.org");
|
|
|
|
BackgroundWorker dbFetcher = new BackgroundWorker();
|
|
dbFetcher.DoWork += new DoWorkEventHandler(RetrieveNewDatabase);
|
|
dbFetcher.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RetrieveNewDatabase_Completed);
|
|
dbFetcher.RunWorkerAsync();
|
|
}
|
|
|
|
private void loadInfoFromTMDToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// Extras menu -> Load TMD...
|
|
LoadTitleFromTMD();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends the SOAP request to NUS.
|
|
/// </summary>
|
|
/// <param name="soap_xml">The Request</param>
|
|
/// <returns></returns>
|
|
public string SendSOAPRequest(string soap_xml)
|
|
{
|
|
System.Net.HttpWebRequest req =
|
|
(System.Net.HttpWebRequest)
|
|
System.Net.HttpWebRequest.Create("http://nus.shop.wii.com:80/nus/services/NetUpdateSOAP");
|
|
req.Method = "POST";
|
|
req.UserAgent = "wii libnup/1.0";
|
|
req.Headers.Add("SOAPAction", '"' + "urn:nus.wsapi.broadon.com/" + '"');
|
|
|
|
// Proxy
|
|
if (!(String.IsNullOrEmpty(proxy_url)))
|
|
{
|
|
WebProxy customproxy = new WebProxy();
|
|
customproxy.Address = new Uri(proxy_url);
|
|
if (String.IsNullOrEmpty(proxy_usr))
|
|
customproxy.UseDefaultCredentials = true;
|
|
else
|
|
{
|
|
NetworkCredential cred = new NetworkCredential();
|
|
cred.UserName = proxy_usr;
|
|
|
|
if (!(String.IsNullOrEmpty(proxy_pwd)))
|
|
cred.Password = proxy_pwd;
|
|
|
|
customproxy.Credentials = cred;
|
|
}
|
|
req.Proxy = customproxy;
|
|
WriteStatus(" - Custom proxy settings applied!");
|
|
}
|
|
else
|
|
{
|
|
req.Proxy = WebRequest.GetSystemWebProxy();
|
|
req.UseDefaultCredentials = true;
|
|
}
|
|
|
|
Stream writeStream = req.GetRequestStream();
|
|
|
|
UTF8Encoding encoding = new UTF8Encoding();
|
|
byte[] bytes = encoding.GetBytes(soap_xml);
|
|
req.ContentType = "text/xml; charset=utf-8";
|
|
//req.ContentLength = bytes.Length;
|
|
writeStream.Write(bytes, 0, bytes.Length);
|
|
writeStream.Close();
|
|
Application.DoEvents();
|
|
try
|
|
{
|
|
string result;
|
|
System.Net.HttpWebResponse resp = (System.Net.HttpWebResponse) req.GetResponse();
|
|
|
|
using (Stream responseStream = resp.GetResponseStream())
|
|
{
|
|
using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
|
|
{
|
|
result = readStream.ReadToEnd();
|
|
}
|
|
}
|
|
req.Abort();
|
|
Application.DoEvents();
|
|
return result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
req.Abort();
|
|
|
|
return ex.Message.ToString();
|
|
}
|
|
}
|
|
|
|
private void emulateUpdate_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
|
|
{
|
|
// Begin Wii System Update
|
|
statusbox.Text = "";
|
|
WriteStatus("Starting Wii System Update...");
|
|
|
|
scriptsStrip.Close();
|
|
|
|
string deviceID = "4362227770";
|
|
string messageID = "13198105123219138";
|
|
string attr = "2";
|
|
|
|
string RegionID = e.ClickedItem.Text.Substring(0, 3);
|
|
if (RegionID == "JAP") // Japan fix, only region not w/ 1st 3 letters same as ID.
|
|
RegionID = "JPN";
|
|
|
|
string CountryCode = RegionID.Substring(0, 2);
|
|
|
|
/* [14:26] <Galaxy|> RegionID: USA, Country: US;
|
|
RegionID: JPN, Country: JP;
|
|
RegionID: EUR, Country: EU;
|
|
RegionID: KOR, Country: KO; */
|
|
|
|
string soap_req = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
|
|
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
|
|
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
|
|
"<soapenv:Body>\n<GetSystemUpdateRequest xmlns=\"urn:nus.wsapi.broadon.com\">\n" +
|
|
"<Version>1.0</Version>\n<MessageId>" + messageID + "</MessageId>\n<DeviceId>" + deviceID +
|
|
"</DeviceId>\n" +
|
|
"<RegionId>" + RegionID + "</RegionId>\n<CountryCode>" + CountryCode +
|
|
"</CountryCode>\n<TitleVersion>\n<TitleId>0000000100000001</TitleId>\n" +
|
|
"<Version>2</Version>\n</TitleVersion>\n<TitleVersion>\n<TitleId>0000000100000002</TitleId>\n" +
|
|
"<Version>33</Version>\n</TitleVersion>\n<TitleVersion>\n<TitleId>0000000100000009</TitleId>\n" +
|
|
"<Version>516</Version>\n</TitleVersion>\n<Attribute>" + attr +
|
|
"</Attribute>\n<AuditData></AuditData>\n" +
|
|
"</GetSystemUpdateRequest>\n</soapenv:Body>\n</soapenv:Envelope>";
|
|
|
|
WriteStatus(" - Sending SOAP Request to NUS...");
|
|
WriteStatus(" - Region: " + RegionID);
|
|
string update_xml = SendSOAPRequest(soap_req);
|
|
if (update_xml != null)
|
|
WriteStatus(" - Recieved Update Info!");
|
|
else
|
|
{
|
|
WriteStatus(" - Fail.");
|
|
return;
|
|
}
|
|
WriteStatus(" - Title information:");
|
|
|
|
string script_text = "";
|
|
|
|
XmlDocument xDoc = new XmlDocument();
|
|
xDoc.LoadXml(update_xml);
|
|
XmlNodeList TitleList = xDoc.GetElementsByTagName("TitleVersion");
|
|
for (int a = 0; a < TitleList.Count; a++)
|
|
{
|
|
XmlNodeList TitleInfo = TitleList[a].ChildNodes;
|
|
string TitleID = "";
|
|
string Version = "";
|
|
|
|
for (int b = 0; b < TitleInfo.Count; b++)
|
|
{
|
|
switch (TitleInfo[b].Name)
|
|
{
|
|
case "TitleId":
|
|
TitleID = TitleInfo[b].InnerText;
|
|
break;
|
|
case "Version":
|
|
Version = TitleInfo[b].InnerText;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
WriteStatus(String.Format(" - {0} [v{1}]", TitleID, Version));
|
|
|
|
if ((NUSDFileExists("database.xml") == true) && ((!(String.IsNullOrEmpty(NameFromDatabase(TitleID))))))
|
|
statusbox.Text += String.Format(" [{0}]", NameFromDatabase(TitleID));
|
|
|
|
script_text += String.Format("{0} {1}\n", TitleID,
|
|
DisplayBytes(NewIntegertoByteArray(Convert.ToInt32(Version), 2), ""));
|
|
}
|
|
|
|
WriteStatus(" - Outputting results to NUS script...");
|
|
|
|
if (!(Directory.Exists(Path.Combine(CURRENT_DIR, "scripts"))))
|
|
{
|
|
Directory.CreateDirectory(Path.Combine(CURRENT_DIR, "scripts"));
|
|
WriteStatus(" - Created 'scripts\' directory.");
|
|
}
|
|
string time = RemoveIllegalCharacters(DateTime.Now.ToShortTimeString());
|
|
File.WriteAllText(
|
|
String.Format(Path.Combine(CURRENT_DIR, Path.Combine("scripts","{0}_Update_{1}_{2}_{3} at {4}.nus")), RegionID,
|
|
DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Year, time), script_text);
|
|
WriteStatus(" - Script written!");
|
|
scriptsLocalMenuEntry.Enabled = false;
|
|
this.scriptsWorker.RunWorkerAsync();
|
|
|
|
WriteStatus(" - Run this script if you feel like downloading the update!");
|
|
// TODO: run the script...
|
|
}
|
|
|
|
/// <summary>
|
|
/// Looks for a title's name by TitleID in Database.
|
|
/// </summary>
|
|
/// <param name="titleid">The titleid.</param>
|
|
/// <returns>Existing name; else null</returns>
|
|
private string NameFromDatabase(string titleid)
|
|
{
|
|
// DANGER: BAD h4x HERE!!
|
|
// Fix MIOS/BC naming
|
|
if (titleid == "0000000100000101")
|
|
return "MIOS";
|
|
else if (titleid == "0000000100000100")
|
|
return "BC";
|
|
|
|
XmlDocument xDoc = new XmlDocument();
|
|
xDoc.Load("database.xml");
|
|
|
|
// Variables
|
|
string[] XMLNodeTypes = new string[4] {"SYS", "IOS", "VC", "WW"};
|
|
|
|
// Loop through XMLNodeTypes
|
|
for (int i = 0; i < XMLNodeTypes.Length; i++) // FOR THE FOUR TYPES OF NODES
|
|
{
|
|
XmlNodeList XMLSpecificNodeTypeList = xDoc.GetElementsByTagName(XMLNodeTypes[i]);
|
|
|
|
for (int x = 0; x < XMLSpecificNodeTypeList.Count; x++) // FOR EACH ITEM IN THE LIST OF A NODE TYPE
|
|
{
|
|
bool found_it = false;
|
|
|
|
// Lol.
|
|
XmlNodeList ChildrenOfTheNode = XMLSpecificNodeTypeList[x].ChildNodes;
|
|
|
|
for (int z = 0; z < ChildrenOfTheNode.Count; z++) // FOR EACH CHILD NODE
|
|
{
|
|
switch (ChildrenOfTheNode[z].Name)
|
|
{
|
|
case "titleID":
|
|
if (ChildrenOfTheNode[z].InnerText == titleid)
|
|
found_it = true;
|
|
else if ((ChildrenOfTheNode[z].InnerText.Substring(0, 14) + "XX") ==
|
|
(titleid.Substring(0, 14) + "XX") &&
|
|
(titleid.Substring(0, 14) != "00000001000000"))
|
|
found_it = true;
|
|
else
|
|
found_it = false;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found_it)
|
|
{
|
|
for (int z = 0; z < ChildrenOfTheNode.Count; z++) // FOR EACH CHILD NODE
|
|
{
|
|
switch (ChildrenOfTheNode[z].Name)
|
|
{
|
|
case "name":
|
|
return ChildrenOfTheNode[z].InnerText;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void packbox_EnabledChanged(object sender, EventArgs e)
|
|
{
|
|
saveaswadbtn.Enabled = packbox.Enabled;
|
|
//deletecontentsbox.Enabled = packbox.Enabled;
|
|
}
|
|
|
|
private void SaveProxyBtn_Click(object sender, EventArgs e)
|
|
{
|
|
if ((String.IsNullOrEmpty(ProxyURL.Text)) && (String.IsNullOrEmpty(ProxyUser.Text)) &&
|
|
((File.Exists(Path.Combine(CURRENT_DIR, "proxy.txt")))))
|
|
{
|
|
File.Delete(Path.Combine(CURRENT_DIR, "proxy.txt"));
|
|
proxyBox.Visible = false;
|
|
proxy_usr = "";
|
|
proxy_url = "";
|
|
proxy_pwd = "";
|
|
WriteStatus("Proxy settings deleted!");
|
|
return;
|
|
}
|
|
else if ((String.IsNullOrEmpty(ProxyURL.Text)) && (String.IsNullOrEmpty(ProxyUser.Text)) &&
|
|
((!(File.Exists(Path.Combine(CURRENT_DIR, "proxy.txt"))))))
|
|
{
|
|
proxyBox.Visible = false;
|
|
WriteStatus("No proxy settings saved!");
|
|
return;
|
|
}
|
|
|
|
string proxy_file = "";
|
|
|
|
if (!(String.IsNullOrEmpty(ProxyURL.Text)))
|
|
{
|
|
proxy_file += ProxyURL.Text + "\n";
|
|
proxy_url = ProxyURL.Text;
|
|
}
|
|
|
|
if (!(String.IsNullOrEmpty(ProxyUser.Text)))
|
|
{
|
|
proxy_file += ProxyUser.Text;
|
|
proxy_usr = ProxyUser.Text;
|
|
}
|
|
|
|
if (!(String.IsNullOrEmpty(proxy_file)))
|
|
{
|
|
File.WriteAllText(Path.Combine(CURRENT_DIR, "proxy.txt"), proxy_file);
|
|
WriteStatus("Proxy settings saved!");
|
|
}
|
|
|
|
proxyBox.Visible = false;
|
|
|
|
SetAllEnabled(false);
|
|
ProxyVerifyBox.Visible = true;
|
|
ProxyVerifyBox.Enabled = true;
|
|
ProxyPwdBox.Enabled = true;
|
|
SaveProxyBtn.Enabled = true;
|
|
ProxyVerifyBox.Select();
|
|
}
|
|
|
|
private void proxySettingsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// Check for Proxy Settings file...
|
|
if (File.Exists(Path.Combine(CURRENT_DIR, "proxy.txt")) == true)
|
|
{
|
|
string[] proxy_file = File.ReadAllLines(Path.Combine(CURRENT_DIR, "proxy.txt"));
|
|
|
|
ProxyURL.Text = proxy_file[0];
|
|
if (proxy_file.Length > 1)
|
|
{
|
|
ProxyUser.Text = proxy_file[1];
|
|
}
|
|
}
|
|
|
|
proxyBox.Visible = true;
|
|
}
|
|
|
|
private void SaveProxyPwdButton_Click(object sender, EventArgs e)
|
|
{
|
|
proxy_pwd = ProxyPwdBox.Text;
|
|
ProxyVerifyBox.Visible = false;
|
|
SetAllEnabled(true);
|
|
}
|
|
|
|
private void ProxyPwdBox_KeyPress(object sender, KeyPressEventArgs e)
|
|
{
|
|
if (e.KeyChar == Convert.ToChar(Keys.Enter))
|
|
SaveProxyPwdButton_Click("LOLWUT", EventArgs.Empty);
|
|
}
|
|
|
|
private void ProxyAssistBtn_Click(object sender, EventArgs e)
|
|
{
|
|
MessageBox.Show("If you are behind a proxy, set these settings to get through to NUS." +
|
|
" If you have an alternate port for accessing your proxy, add ':' followed by the port.");
|
|
}
|
|
|
|
private void loadNUSScriptToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// Open a NUS script.
|
|
OpenFileDialog ofd = new OpenFileDialog();
|
|
ofd.Multiselect = false;
|
|
ofd.Filter = "NUS Scripts|*.nus|All Files|*.*";
|
|
if (Directory.Exists(Path.Combine(CURRENT_DIR, "scripts")))
|
|
ofd.InitialDirectory = Path.Combine(CURRENT_DIR, "scripts");
|
|
ofd.Title = "Load a NUS/Wiimpersonator script.";
|
|
|
|
if (ofd.ShowDialog() != DialogResult.Cancel)
|
|
{
|
|
script_filename = ofd.FileName;
|
|
BackgroundWorker scripter = new BackgroundWorker();
|
|
scripter.DoWork += new DoWorkEventHandler(RunScript);
|
|
scripter.RunWorkerAsync();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs a NUS script (BG).
|
|
/// </summary>
|
|
/// <param name="sender">The sender.</param>
|
|
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
|
|
private void RunScript(object sender, System.ComponentModel.DoWorkEventArgs e)
|
|
{
|
|
script_mode = true;
|
|
SetTextThreadSafe(statusbox, "");
|
|
WriteStatus("Starting script download. Please be patient!");
|
|
if (!File.Exists(Path.Combine(CURRENT_DIR, "output_" + Path.GetFileNameWithoutExtension(script_filename))))
|
|
Directory.CreateDirectory(Path.Combine(CURRENT_DIR, "output_" + Path.GetFileNameWithoutExtension(script_filename)));
|
|
string[] NUS_Entries;
|
|
if (script_filename != "\000")
|
|
{
|
|
NUS_Entries = File.ReadAllLines(script_filename);
|
|
}
|
|
else
|
|
{
|
|
NUS_Entries = nusentries;
|
|
}
|
|
WriteStatus(String.Format(" - Script loaded ({0} Titles)", NUS_Entries.Length));
|
|
|
|
for (int a = 0; a < NUS_Entries.Length; a++)
|
|
{
|
|
// Download the title
|
|
WriteStatus(String.Format("===== Running Download ({0}/{1}) =====", a + 1, NUS_Entries.Length));
|
|
string[] title_info = NUS_Entries[a].Split(' ');
|
|
// don't let the delete issue reappear...
|
|
if (string.IsNullOrEmpty(title_info[0]))
|
|
break;
|
|
|
|
// WebClient configuration
|
|
WebClient nusWC = new WebClient();
|
|
nusWC = ConfigureWithProxy(nusWC);
|
|
nusWC.Headers.Add("User-Agent", "wii libnup/1.0"); // Set UserAgent to Wii value
|
|
|
|
// Create\Configure NusClient
|
|
libWiiSharp.NusClient nusClient = new libWiiSharp.NusClient();
|
|
nusClient.ConfigureNusClient(nusWC);
|
|
nusClient.UseLocalFiles = localuse.Checked;
|
|
nusClient.ContinueWithoutTicket = true;
|
|
nusClient.Debug += new EventHandler<libWiiSharp.MessageEventArgs>(nusClient_Debug);
|
|
|
|
libWiiSharp.StoreType[] storeTypes = new libWiiSharp.StoreType[1];
|
|
// There's no harm in outputting everything i suppose
|
|
storeTypes[0] = libWiiSharp.StoreType.All;
|
|
|
|
int title_version = int.Parse(title_info[1], System.Globalization.NumberStyles.HexNumber);
|
|
|
|
string wadName = NameFromDatabase(title_info[0]);
|
|
if (wadName != null)
|
|
wadName = OfficialWADNaming(wadName);
|
|
else
|
|
wadName = title_info[0] + "-NUS-v" + title_version + ".wad";
|
|
|
|
nusClient.DownloadTitle(title_info[0], title_version.ToString(), Path.Combine(CURRENT_DIR, ("output_" + Path.GetFileNameWithoutExtension(script_filename))), wadName, storeTypes);
|
|
|
|
/*
|
|
SetTextThreadSafe(titleidbox, title_info[0]);
|
|
SetTextThreadSafe(titleversion,
|
|
Convert.ToString(256*
|
|
(byte.Parse(title_info[1].Substring(0, 2),
|
|
System.Globalization.NumberStyles.HexNumber))));
|
|
SetTextThreadSafe(titleversion,
|
|
Convert.ToString(Convert.ToInt32(titleversion.Text) +
|
|
byte.Parse(title_info[1].Substring(2, 2),
|
|
System.Globalization.NumberStyles.HexNumber)));
|
|
|
|
button3_Click("Scripter", EventArgs.Empty);
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
while (NUSDownloader.IsBusy)
|
|
{
|
|
Thread.Sleep(1000);
|
|
} */
|
|
}
|
|
script_mode = false;
|
|
WriteStatus("Script completed!");
|
|
}
|
|
|
|
private void scriptsbutton_Click(object sender, EventArgs e)
|
|
{
|
|
// Show scripts menu
|
|
scriptsStrip.Show(scriptsbutton, 2, (2+scriptsbutton.Height));
|
|
}
|
|
|
|
private void DatabaseEnabled(bool enabled)
|
|
{
|
|
for (int a = 0; a < databaseStrip.Items.Count; a++)
|
|
{
|
|
databaseStrip.Items[a].Enabled = false;
|
|
}
|
|
}
|
|
|
|
void scriptsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
scriptsLocalMenuEntry.Enabled = true;
|
|
}
|
|
|
|
void OrganizeScripts(object sender, DoWorkEventArgs e)
|
|
{
|
|
//throw new NotImplementedException();
|
|
|
|
if (Directory.Exists(Path.Combine(CURRENT_DIR, "scripts")) == false)
|
|
{
|
|
WriteStatus("Scripts directory not found...");
|
|
WriteStatus("- Creating it.");
|
|
Directory.CreateDirectory(Path.Combine(CURRENT_DIR, "scripts"));
|
|
}
|
|
|
|
// Clear any entries from previous runthrough
|
|
if (scriptsLocalMenuEntry.DropDownItems.Count > 0)
|
|
{
|
|
// TODO: i suppose this is bad amiright
|
|
Control.CheckForIllegalCrossThreadCalls = false;
|
|
scriptsLocalMenuEntry.DropDownItems.Clear();
|
|
}
|
|
|
|
|
|
// Add directories w/ scripts in \scripts\
|
|
foreach (string directory in Directory.GetDirectories(Path.Combine(CURRENT_DIR, "scripts"), "*", SearchOption.TopDirectoryOnly))
|
|
{
|
|
if (Directory.GetFiles(directory, "*.nus", SearchOption.TopDirectoryOnly).Length > 0)
|
|
{
|
|
DirectoryInfo dinfo = new DirectoryInfo(directory);
|
|
ToolStripMenuItem folder_item = new ToolStripMenuItem();
|
|
folder_item.Text = dinfo.Name + Path.DirectorySeparatorChar;
|
|
folder_item.Image = Properties.Resources.folder_table;
|
|
|
|
|
|
foreach (string nusscript in Directory.GetFiles(directory, "*.nus", SearchOption.TopDirectoryOnly))
|
|
{
|
|
FileInfo finfo = new FileInfo(nusscript);
|
|
ToolStripMenuItem nus_script_item = new ToolStripMenuItem();
|
|
nus_script_item.Text = finfo.Name;
|
|
nus_script_item.Image = Properties.Resources.script_start;
|
|
folder_item.DropDownItems.Add(nus_script_item);
|
|
|
|
nus_script_item.Click += new EventHandler(nus_script_item_Click);
|
|
}
|
|
|
|
scriptsLocalMenuEntry.DropDownItems.Add(folder_item);
|
|
}
|
|
}
|
|
|
|
// Add scripts in \scripts\
|
|
foreach (string nusscript in Directory.GetFiles(Path.Combine(CURRENT_DIR, "scripts"), "*.nus", SearchOption.TopDirectoryOnly))
|
|
{
|
|
FileInfo finfo = new FileInfo(nusscript);
|
|
ToolStripMenuItem nus_script_item = new ToolStripMenuItem();
|
|
nus_script_item.Text = finfo.Name;
|
|
nus_script_item.Image = Properties.Resources.script_start;
|
|
scriptsLocalMenuEntry.DropDownItems.Add(nus_script_item);
|
|
|
|
nus_script_item.Click += new EventHandler(nus_script_item_Click);
|
|
}
|
|
}
|
|
|
|
private void aboutNUSDToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// Display About Text...
|
|
statusbox.Text = "";
|
|
WriteStatus("NUS Downloader (NUSD)");
|
|
WriteStatus("You are running version: " + version);
|
|
WriteStatus("This application created by WB3000");
|
|
WriteStatus("Various sections contributed by lukegb");
|
|
WriteStatus("");
|
|
|
|
if (NUSDFileExists("key.bin") == false)
|
|
WriteStatus("Wii Decryption: Need (key.bin)");
|
|
else
|
|
WriteStatus("Wii Decryption: OK");
|
|
|
|
if (NUSDFileExists("kkey.bin") == false)
|
|
WriteStatus("Wii Korea Decryption: Need (kkey.bin)");
|
|
else
|
|
WriteStatus("Wii Korea Decryption: OK");
|
|
|
|
if (NUSDFileExists("dsikey.bin") == false)
|
|
WriteStatus("DSi Decryption: Need (dsikey.bin)");
|
|
else
|
|
WriteStatus("DSi Decryption: OK");
|
|
|
|
if (NUSDFileExists("database.xml") == false)
|
|
WriteStatus("Database: Need (database.xml)");
|
|
else
|
|
WriteStatus("Database: OK");
|
|
|
|
if (IsWin7())
|
|
WriteStatus("Windows 7 Features: Enabled");
|
|
|
|
WriteStatus("");
|
|
WriteStatus("Special thanks to:");
|
|
WriteStatus(" * Crediar for his wadmaker tool + source, and for the advice!");
|
|
WriteStatus(" * Leathl for libWiiSharp.");
|
|
WriteStatus(" * SquidMan/Galaxy/comex/Xuzz for advice/sources.");
|
|
WriteStatus(" * Pasta for database compilation assistance.");
|
|
WriteStatus(" * Napo7 for testing proxy usage.");
|
|
WriteStatus(" * Wyatt O'Day for the Windows7ProgressBar Control.");
|
|
WriteStatus(" * Famfamfam for the Silk Icon Set.");
|
|
WriteStatus(" * #WiiDev for answering the tough questions.");
|
|
WriteStatus(" * Anyone who helped beta test!");
|
|
}
|
|
|
|
private void checkBox1_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
SaveProxyPwdPermanentBtn.Enabled = checkBox1.Checked;
|
|
}
|
|
|
|
private void SaveProxyPwdPermanentBtn_Click(object sender, EventArgs e)
|
|
{
|
|
proxy_pwd = ProxyPwdBox.Text;
|
|
|
|
string proxy_file = File.ReadAllText(Path.Combine(CURRENT_DIR, "proxy.txt"));
|
|
|
|
proxy_file += String.Format("\n{0}", proxy_pwd);
|
|
|
|
File.WriteAllText(Path.Combine(CURRENT_DIR, "proxy.txt"), proxy_file);
|
|
|
|
ProxyVerifyBox.Visible = false;
|
|
SetAllEnabled(true);
|
|
WriteStatus("To delete all traces of proxy settings, delete the proxy.txt file!");
|
|
}
|
|
|
|
private void clearButton_MouseEnter(object sender, EventArgs e)
|
|
{
|
|
// expand clear button
|
|
/*button3.Left = 194;
|
|
button3.Size = new System.Drawing.Size(68, 21);*/
|
|
clearButton.Text = "Clear";
|
|
//button3.ImageAlign = ContentAlignment.MiddleLeft;
|
|
}
|
|
|
|
private void clearButton_MouseLeave(object sender, EventArgs e)
|
|
{
|
|
// shrink clear button
|
|
/*button3.Left = 239;
|
|
button3.Size = new System.Drawing.Size(23, 21);*/
|
|
if (Type.GetType ("Mono.Runtime") == null)
|
|
clearButton.Text = String.Empty;
|
|
//button3.ImageAlign = ContentAlignment.MiddleCenter;
|
|
}
|
|
|
|
private void saveaswadbtn_MouseEnter(object sender, EventArgs e)
|
|
{
|
|
/*saveaswadbtn.Left = 190;
|
|
saveaswadbtn.Size = new Size(72, 22);*/
|
|
saveaswadbtn.Text = "Save As";
|
|
/*saveaswadbtn.ImageAlign = ContentAlignment.MiddleLeft;*/
|
|
}
|
|
|
|
private void saveaswadbtn_MouseLeave(object sender, EventArgs e)
|
|
{
|
|
/*saveaswadbtn.Left = 230;
|
|
saveaswadbtn.Size = new Size(32, 22);*/
|
|
if (Type.GetType("Mono.Runtime") == null)
|
|
saveaswadbtn.Text = String.Empty;
|
|
//saveaswadbtn.ImageAlign = ContentAlignment.MiddleCenter;
|
|
}
|
|
|
|
void nus_script_item_Click(object sender, EventArgs e)
|
|
{
|
|
ToolStripMenuItem tsmi = (ToolStripMenuItem)sender;
|
|
string folderpath = "";
|
|
if (!tsmi.OwnerItem.Equals(this.scriptsLocalMenuEntry))
|
|
{
|
|
folderpath = Path.Combine(tsmi.OwnerItem.Text, folderpath);
|
|
}
|
|
folderpath = Path.Combine(this.CURRENT_DIR, Path.Combine("scripts", Path.Combine(folderpath, tsmi.Text)));
|
|
script_filename = folderpath;
|
|
BackgroundWorker scripter = new BackgroundWorker();
|
|
scripter.DoWork += new DoWorkEventHandler(RunScript);
|
|
scripter.RunWorkerAsync();
|
|
}
|
|
|
|
private void saveaswadbtn_Click(object sender, EventArgs e)
|
|
{
|
|
SaveFileDialog wad_saveas = new SaveFileDialog();
|
|
wad_saveas.Title = "Save WAD File...";
|
|
wad_saveas.Filter = "WAD Files|*.wad|All Files|*.*";
|
|
wad_saveas.AddExtension = true;
|
|
DialogResult dres = wad_saveas.ShowDialog();
|
|
if (dres != DialogResult.Cancel)
|
|
WAD_Saveas_Filename = wad_saveas.FileName;
|
|
}
|
|
|
|
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
// This prevents errors when exiting before the database is parsed.
|
|
// This is also probably not the best way to accomplish this...
|
|
Environment.Exit(0);
|
|
}
|
|
|
|
private void iosPatchCheckbox_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (iosPatchCheckbox.Checked == true)
|
|
{
|
|
//packbox.Enabled = false;
|
|
packbox.Checked = true;
|
|
SetAllEnabled(false);
|
|
iosPatchGroupBox.Visible = true;
|
|
iosPatchGroupBox.Enabled = true;
|
|
iosPatchesListBox.Enabled = true;
|
|
iosPatchGroupBoxOKbtn.Enabled = true;
|
|
}
|
|
else
|
|
{
|
|
//packbox.Enabled = true;
|
|
}
|
|
}
|
|
|
|
private void iosPatchGroupBoxOKbtn_Click(object sender, EventArgs e)
|
|
{
|
|
SetAllEnabled(true);
|
|
iosPatchGroupBox.Visible = false;
|
|
//packbox.Enabled = false;
|
|
}
|
|
}
|
|
} |