diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs new file mode 100644 index 0000000..84240ed --- /dev/null +++ b/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("NUS Downloader")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NUS Downloader")] +[assembly: AssemblyCopyright("Copyright © 2009")] +[assembly: AssemblyTrademark("")] +[assembly: ComVisible(false)] +[assembly: Guid("cb4ee0f5-7ba8-4ee6-a09e-7a09d4350582")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/NUS Downloader/COPYING b/LICENSE similarity index 99% rename from NUS Downloader/COPYING rename to LICENSE index 94a9ed0..e72bfdd 100644 --- a/NUS Downloader/COPYING +++ b/LICENSE @@ -1,7 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found. 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 . + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see -. +. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. +. \ No newline at end of file diff --git a/LocalTestRun.testrunconfig b/LocalTestRun.testrunconfig deleted file mode 100644 index 5561d35..0000000 --- a/LocalTestRun.testrunconfig +++ /dev/null @@ -1,5 +0,0 @@ - - - This is a default test run configuration for a local test run. - - \ No newline at end of file diff --git a/NUS Downloader.csproj b/NUS Downloader.csproj new file mode 100644 index 0000000..e255711 --- /dev/null +++ b/NUS Downloader.csproj @@ -0,0 +1,82 @@ + + + + + Debug + AnyCPU + {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1} + WinExe + NUS Downloader + v3.5 + 1.0.0.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NUS Downloader.pdb b/NUS Downloader.pdb new file mode 100644 index 0000000..51bc3c3 Binary files /dev/null and b/NUS Downloader.pdb differ diff --git a/NUS Downloader.sln b/NUS Downloader.sln index 399f9b3..89d6504 100644 --- a/NUS Downloader.sln +++ b/NUS Downloader.sln @@ -1,27 +1,20 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUS Downloader", "NUS Downloader\NUS Downloader.csproj", "{DB1289FA-BA83-408F-A576-326E5EC4CC6D}" + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUS Downloader", "NUS Downloader.csproj", "{9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}" EndProject Global - GlobalSection(SubversionScc) = preSolution - Svn-Managed = True - Manager = AnkhSVN - Subversion Support for Visual Studio - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DB1289FA-BA83-408F-A576-326E5EC4CC6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DB1289FA-BA83-408F-A576-326E5EC4CC6D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DB1289FA-BA83-408F-A576-326E5EC4CC6D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DB1289FA-BA83-408F-A576-326E5EC4CC6D}.Release|Any CPU.Build.0 = Release|Any CPU + {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - VisualSVNWorkingCopyRoot = . - EndGlobalSection EndGlobal diff --git a/NUS Downloader.vsmdi b/NUS Downloader.vsmdi deleted file mode 100644 index b120e32..0000000 --- a/NUS Downloader.vsmdi +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/NUS Downloader/COMTypes.cs b/NUS Downloader/COMTypes.cs deleted file mode 100644 index 49e79e0..0000000 --- a/NUS Downloader/COMTypes.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using System; -using System.Runtime.InteropServices; - -namespace wyDay.Controls -{ - /// - /// Represents the thumbnail progress bar state. - /// - public enum ThumbnailProgressState - { - /// - /// No progress is displayed. - /// - NoProgress = 0, - /// - /// The progress is indeterminate (marquee). - /// - Indeterminate = 0x1, - /// - /// Normal progress is displayed. - /// - Normal = 0x2, - /// - /// An error occurred (red). - /// - Error = 0x4, - /// - /// The operation is paused (yellow). - /// - Paused = 0x8 - } - - //Based on Rob Jarett's wrappers for the desktop integration PDC demos. - [ComImportAttribute()] - [GuidAttribute("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")] - [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - internal interface ITaskbarList3 - { - // ITaskbarList - [PreserveSig] - void HrInit(); - [PreserveSig] - void AddTab(IntPtr hwnd); - [PreserveSig] - void DeleteTab(IntPtr hwnd); - [PreserveSig] - void ActivateTab(IntPtr hwnd); - [PreserveSig] - void SetActiveAlt(IntPtr hwnd); - - // ITaskbarList2 - [PreserveSig] - void MarkFullscreenWindow( - IntPtr hwnd, - [MarshalAs(UnmanagedType.Bool)] bool fFullscreen); - - // ITaskbarList3 - void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal); - void SetProgressState(IntPtr hwnd, ThumbnailProgressState tbpFlags); - - // yadda, yadda - there's more to the interface, but we don't need it. - } - - [GuidAttribute("56FDF344-FD6D-11d0-958A-006097C9A090")] - [ClassInterfaceAttribute(ClassInterfaceType.None)] - [ComImportAttribute()] - internal class CTaskbarList { } -} \ No newline at end of file diff --git a/NUS Downloader/CertificateChain.cs b/NUS Downloader/CertificateChain.cs deleted file mode 100644 index b2e7634..0000000 --- a/NUS Downloader/CertificateChain.cs +++ /dev/null @@ -1,518 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.IO; -using System.Security.Cryptography; - -namespace libWiiSharp -{ - public class CertificateChain : IDisposable - { - private const string certCaHash = "5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318"; - private const string certCpHash = "6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C"; - private const string certXsHash = "09787045037121477824BC6A3E5E076156573F8A"; - private SHA1 sha = SHA1.Create(); - private bool[] certsComplete = new bool[3]; - - private byte[] certCa = new byte[0x400]; - private byte[] certCp = new byte[0x300]; - private byte[] certXs = new byte[0x300]; - - /// - /// If false, the Certificate Chain is not complete (i.e. at least one certificate is missing). - /// - public bool CertsComplete { get { return (certsComplete[0] && certsComplete[1] && certsComplete[2]); } } - - #region IDisposable Members - private bool isDisposed = false; - - ~CertificateChain() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !isDisposed) - { - sha.Clear(); - sha = null; - - certsComplete = null; - certCa = null; - certCp = null; - certXs = null; - } - - isDisposed = true; - } - #endregion - - #region Public Functions - /// - /// Loads a cert file. - /// - /// - /// - public static CertificateChain Load(string pathToCert) - { - return Load(File.ReadAllBytes(pathToCert)); - } - - /// - /// Loads a cert file. - /// - /// - /// - public static CertificateChain Load(byte[] certFile) - { - CertificateChain c = new CertificateChain(); - MemoryStream ms = new MemoryStream(certFile); - - try { c.parseCert(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - return c; - } - - /// - /// Loads a cert file. - /// - /// - /// - public static CertificateChain Load(Stream cert) - { - CertificateChain c = new CertificateChain(); - c.parseCert(cert); - return c; - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - /// - public static CertificateChain FromTikTmd(string pathToTik, string pathToTmd) - { - return FromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - /// - public static CertificateChain FromTikTmd(string pathToTik, byte[] tmdFile) - { - return FromTikTmd(File.ReadAllBytes(pathToTik), tmdFile); - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - /// - public static CertificateChain FromTikTmd(byte[] tikFile, byte[] tmdFile) - { - CertificateChain c = new CertificateChain(); - MemoryStream ms = new MemoryStream(tikFile); - - try { c.grabFromTik(ms); } - catch { ms.Dispose(); throw; } - - ms = new MemoryStream(tmdFile); - - try { c.grabFromTmd(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - - if (!c.CertsComplete) throw new Exception("Couldn't locate all certs!"); - - return c; - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - /// - public static CertificateChain FromTikTmd(Stream tik, Stream tmd) - { - CertificateChain c = new CertificateChain(); - c.grabFromTik(tik); - c.grabFromTmd(tmd); - return c; - } - - - - /// - /// Loads a cert file. - /// - /// - public void LoadFile(string pathToCert) - { - LoadFile(File.ReadAllBytes(pathToCert)); - } - - /// - /// Loads a cert file. - /// - /// - public void LoadFile(byte[] certFile) - { - MemoryStream ms = new MemoryStream(certFile); - - try { parseCert(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - } - - /// - /// Loads a cert file. - /// - /// - public void LoadFile(Stream cert) - { - parseCert(cert); - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - /// - public void LoadFromTikTmd(string pathToTik, string pathToTmd) - { - LoadFromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - /// - public void LoadFromTikTmd(string pathToTik, byte[] tmdFile) - { - LoadFromTikTmd(File.ReadAllBytes(pathToTik), tmdFile); - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - public void LoadFromTikTmd(byte[] tikFile, byte[] tmdFile) - { - MemoryStream ms = new MemoryStream(tikFile); - - try { grabFromTik(ms); } - catch { ms.Dispose(); throw; } - - ms = new MemoryStream(tmdFile); - - try { grabFromTmd(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - - if (!CertsComplete) throw new Exception("Couldn't locate all certs!"); - } - - /// - /// Grabs certificates from Ticket and Tmd. - /// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!) - /// - /// - /// - public void LoadFromTikTmd(Stream tik, Stream tmd) - { - grabFromTik(tik); - grabFromTmd(tmd); - } - - - - /// - /// Saves the Certificate Chain. - /// - /// - public void Save(string savePath) - { - if (File.Exists(savePath)) File.Delete(savePath); - - using (FileStream fs = new FileStream(savePath, FileMode.Create)) - writeToStream(fs); - } - - /// - /// Returns the Certificate Chain as a memory stream. - /// - /// - public MemoryStream ToMemoryStream() - { - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - return ms; - } - - /// - /// Returns the Certificate Chain as a byte array. - /// - /// - public byte[] ToByteArray() - { - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - byte[] res = ms.ToArray(); - ms.Dispose(); - return res; - } - #endregion - - #region Private Functions - private void writeToStream(Stream writeStream) - { - fireDebug("Writing Certificate Chain..."); - - if (!CertsComplete) - { fireDebug(" Certificate Chain incomplete..."); throw new Exception("At least one certificate is missing!"); } - - writeStream.Seek(0, SeekOrigin.Begin); - - fireDebug(" Writing Certificate CA... (Offset: 0x{0})", writeStream.Position.ToString("x8")); - writeStream.Write(certCa, 0, certCa.Length); - - fireDebug(" Writing Certificate CP... (Offset: 0x{0})", writeStream.Position.ToString("x8")); - writeStream.Write(certCp, 0, certCp.Length); - - fireDebug(" Writing Certificate XS... (Offset: 0x{0})", writeStream.Position.ToString("x8")); - writeStream.Write(certXs, 0, certXs.Length); - - fireDebug("Writing Certificate Chain Finished..."); - } - - private void parseCert(Stream certFile) - { - fireDebug("Parsing Certificate Chain..."); - int off = 0; - - for (int i = 0; i < 3; i++) - { - fireDebug(" Scanning at Offset 0x{0}:", off.ToString("x8")); - - try - { - certFile.Seek(off, SeekOrigin.Begin); - byte[] temp = new byte[0x400]; - - certFile.Read(temp, 0, temp.Length); - - fireDebug(" Checking for Certificate CA..."); - if (isCertCa(temp) && !certsComplete[1]) - { fireDebug(" Certificate CA detected..."); certCa = temp; certsComplete[1] = true; off += 0x400; continue; } - - fireDebug(" Checking for Certificate CP..."); - if (isCertCp(temp) && !certsComplete[2]) - { fireDebug(" Certificate CP detected..."); Array.Resize(ref temp, 0x300); certCp = temp; certsComplete[2] = true; off += 0x300; continue; } - - fireDebug(" Checking for Certificate XS..."); - if (isCertXs(temp) && !certsComplete[0]) - { fireDebug(" Certificate XS detected..."); Array.Resize(ref temp, 0x300); certXs = temp; certsComplete[0] = true; off += 0x300; continue; } - } - catch (Exception ex) { fireDebug("Error: {0}", ex.Message); } - - off += 0x300; - } - - if (!CertsComplete) - { fireDebug(" Couldn't locate all Certificates..."); throw new Exception("Couldn't locate all certs!"); } - - fireDebug("Parsing Certificate Chain Finished..."); - } - - private void grabFromTik(Stream tik) - { - fireDebug("Scanning Ticket for Certificates..."); - int off = 676; - - for (int i = 0; i < 3; i++) - { - fireDebug(" Scanning at Offset 0x{0}:", off.ToString("x8")); - - try - { - tik.Seek(off, SeekOrigin.Begin); - byte[] temp = new byte[0x400]; - - tik.Read(temp, 0, temp.Length); - - fireDebug(" Checking for Certificate CA..."); - if (isCertCa(temp) && !certsComplete[1]) - { fireDebug(" Certificate CA detected..."); certCa = temp; certsComplete[1] = true; off += 0x400; continue; } - - fireDebug(" Checking for Certificate CP..."); - if (isCertCp(temp) && !certsComplete[2]) - { fireDebug(" Certificate CP detected..."); Array.Resize(ref temp, 0x300); certCp = temp; certsComplete[2] = true; off += 0x300; continue; } - - fireDebug(" Checking for Certificate XS..."); - if (isCertXs(temp) && !certsComplete[0]) - { fireDebug(" Certificate XS detected..."); Array.Resize(ref temp, 0x300); certXs = temp; certsComplete[0] = true; off += 0x300; continue; } - } - catch { } - - off += 0x300; - } - - fireDebug("Scanning Ticket for Certificates Finished..."); - } - - private void grabFromTmd(Stream tmd) - { - fireDebug("Scanning TMD for Certificates..."); - - byte[] temp = new byte[2]; - tmd.Seek(478, SeekOrigin.Begin); - tmd.Read(temp, 0, 2); - - int numContents = Shared.Swap(BitConverter.ToUInt16(temp, 0)); - int off = 484 + numContents * 36; - - for (int i = 0; i < 3; i++) - { - fireDebug(" Scanning at Offset 0x{0}:", off.ToString("x8")); - - try - { - tmd.Seek(off, SeekOrigin.Begin); - temp = new byte[0x400]; - - tmd.Read(temp, 0, temp.Length); - - fireDebug(" Checking for Certificate CA..."); - if (isCertCa(temp) && !certsComplete[1]) - { fireDebug(" Certificate CA detected..."); certCa = temp; certsComplete[1] = true; off += 0x400; continue; } - - fireDebug(" Checking for Certificate CP..."); - if (isCertCp(temp) && !certsComplete[2]) - { fireDebug(" Certificate CP detected..."); Array.Resize(ref temp, 0x300); certCp = temp; certsComplete[2] = true; off += 0x300; continue; } - - fireDebug(" Checking for Certificate XS..."); - if (isCertXs(temp) && !certsComplete[0]) - { fireDebug(" Certificate XS detected..."); Array.Resize(ref temp, 0x300); certXs = temp; certsComplete[0] = true; off += 0x300; continue; } - } - catch { } - - off += 0x300; - } - - fireDebug("Scanning TMD for Certificates Finished..."); - } - - private bool isCertXs(byte[] part) - { - if (part.Length < 0x300) return false; - else if (part.Length > 0x300) Array.Resize(ref part, 0x300); - - if (part[0x184] == 'X' && part[0x185] == 'S') - { - byte[] newHash = sha.ComputeHash(part); - byte[] oldHash = Shared.HexStringToByteArray(certXsHash); - - if (Shared.CompareByteArrays(newHash, oldHash)) return true; - } - - return false; - } - - private bool isCertCa(byte[] part) - { - if (part.Length < 0x400) return false; - else if (part.Length > 0x400) Array.Resize(ref part, 0x400); - - if (part[0x284] == 'C' && part[0x285] == 'A') - { - byte[] newHash = sha.ComputeHash(part); - byte[] oldHash = Shared.HexStringToByteArray(certCaHash); - - if (Shared.CompareByteArrays(newHash, oldHash)) return true; - } - - return false; - } - - private bool isCertCp(byte[] part) - { - if (part.Length < 0x300) return false; - else if (part.Length > 0x300) Array.Resize(ref part, 0x300); - - if (part[0x184] == 'C' && part[0x185] == 'P') - { - byte[] newHash = sha.ComputeHash(part); - byte[] oldHash = Shared.HexStringToByteArray(certCpHash); - - if (Shared.CompareByteArrays(newHash, oldHash)) return true; - } - - return false; - } - #endregion - - #region Events - /// - /// Fires debugging messages. You may write them into a log file or log textbox. - /// - public event EventHandler Debug; - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = Debug; - if (debug != null) - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - #endregion - } -} diff --git a/NUS Downloader/CommonKey.cs b/NUS Downloader/CommonKey.cs deleted file mode 100644 index 13766ee..0000000 --- a/NUS Downloader/CommonKey.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -namespace libWiiSharp -{ - public class CommonKey - { - private static string standardKey = "ebe42a225e8593e448d9c5457381aaf7"; - private static string koreanKey = "63b82bb4f4614e2e13f2fefbba4c9b7e"; - private static string dsiKey = "af1bf516a807d21aea45984f04742861"; - - private static string currentDir = System.IO.Directory.GetCurrentDirectory(); - - private static string standardKeyName = "key.bin"; - private static string koreanKeyName = "kkey.bin"; - private static string dsiKeyName = "dsikey.bin"; - - public static byte[] GetStandardKey() - { - if (System.IO.File.Exists(System.IO.Path.Combine(currentDir, standardKeyName))) - return System.IO.File.ReadAllBytes(System.IO.Path.Combine(currentDir, standardKeyName)); - else - return Shared.HexStringToByteArray(standardKey); - } - - public static byte[] GetKoreanKey() - { - if (System.IO.File.Exists(System.IO.Path.Combine(currentDir, koreanKeyName))) - return System.IO.File.ReadAllBytes(System.IO.Path.Combine(currentDir, koreanKeyName)); - else - return Shared.HexStringToByteArray(koreanKey); - } - - public static byte[] GetDSiKey() - { - if (System.IO.File.Exists(System.IO.Path.Combine(currentDir, dsiKeyName))) - return System.IO.File.ReadAllBytes(System.IO.Path.Combine(currentDir, dsiKeyName)); - else - return Shared.HexStringToByteArray(dsiKey); - } - } -} diff --git a/NUS Downloader/ContentIndices.cs b/NUS Downloader/ContentIndices.cs deleted file mode 100644 index 483d778..0000000 --- a/NUS Downloader/ContentIndices.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace libWiiSharp -{ - internal struct ContentIndices : IComparable - { - private int index; - private int contentIndex; - - public int Index { get { return index; } } - public int ContentIndex { get { return contentIndex; } } - - public ContentIndices(int index, int contentIndex) - { - this.index = index; - this.contentIndex = contentIndex; - } - - public int CompareTo(object obj) - { - if (obj is ContentIndices) return contentIndex.CompareTo(((ContentIndices)obj).contentIndex); - else throw new ArgumentException(); - } - } -} diff --git a/NUS Downloader/Crystal_Clear_app_ark2.ico b/NUS Downloader/Crystal_Clear_app_ark2.ico deleted file mode 100644 index 726d2e1..0000000 Binary files a/NUS Downloader/Crystal_Clear_app_ark2.ico and /dev/null differ diff --git a/NUS Downloader/Database.cs b/NUS Downloader/Database.cs deleted file mode 100644 index b30c625..0000000 --- a/NUS Downloader/Database.cs +++ /dev/null @@ -1,834 +0,0 @@ -/////////////////////////////////////////// -// NUS Downloader: Database.cs // -// $Rev:: $ // -// $Author:: $ // -// $Date:: $ // -/////////////////////////////////////////// - -using System; -using System.Windows.Forms; -using System.IO; -using System.Xml; -using System.Drawing; - -namespace NUS_Downloader -{ - class Database - { - private string SystemTag = "SYS"; - private string IosTag = "IOS"; - private string VcTag = "VC"; - private string WwTag = "WW"; - private string UpdateTag = "UPD"; - - private string DSiSystemTag = "DSISYSTEM"; - private string DSiWareTag = "DSIWARE"; - - private string[] VcConsoles = new string[11] { "C64", "GEN", "MSX", "N64", "NEO", "NES", - "SMS", "SNES", "TG16", "TGCD", "ARC" }; - - private string databaseString; - - public static Image green = Properties.Resources.bullet_green; - public static Image orange = Properties.Resources.bullet_orange; - public static Image redgreen = Properties.Resources.bullet_redgreen; - public static Image redorange = Properties.Resources.bullet_redorange; - - public static Image green_blue = Properties.Resources.bullet_green_blue; - public static Image orange_blue = Properties.Resources.bullet_orange_blue; - public static Image redgreen_blue = Properties.Resources.bullet_redgreen_blue; - public static Image redorange_blue = Properties.Resources.bullet_redorange_blue; - - public void LoadDatabaseToStream(string databaseFile) - { - // Does it exist? - if (!File.Exists(databaseFile)) - throw new FileNotFoundException("I couldn't find the database file!", "database.xml"); - - databaseString = File.ReadAllText(databaseFile); - - } - - public string GetDatabaseVersion() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - XmlNodeList DatabaseList = xDoc.GetElementsByTagName("database"); - XmlAttributeCollection Attributes = DatabaseList[0].Attributes; - return Attributes[0].Value; - } - - public static string GetDatabaseVersion(string databaseString) - { - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - XmlNodeList DatabaseList = xDoc.GetElementsByTagName("database"); - XmlAttributeCollection Attributes = DatabaseList[0].Attributes; - return Attributes[0].Value; - } - - public ToolStripMenuItem[] LoadSystemTitles() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - - XmlNodeList SystemTitlesXMLNodes = xDoc.GetElementsByTagName(SystemTag); - - ToolStripMenuItem[] systemTitleCollection = new ToolStripMenuItem[SystemTitlesXMLNodes.Count]; - - for (int x = 0; x < SystemTitlesXMLNodes.Count; x++) - { - ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem(); - XmlAttributeCollection XMLAttributes = SystemTitlesXMLNodes[x].Attributes; - - string titleID = ""; - string descname = ""; - bool dangerous = false; - bool ticket = true; - - XmlNodeList ChildrenOfTheNode = SystemTitlesXMLNodes[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 "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(Application.); - } - } - } - 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]))); - } - } - 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 - { // Wait what? - XMLToolStripItem.Text = descname; - } - } - //AddToolStripItemToStrip(i, XMLToolStripItem, XMLAttributes); - systemTitleCollection[x] = XMLToolStripItem; - } - - return systemTitleCollection; - } - - public ToolStripMenuItem[] LoadIosTitles() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - XmlNodeList IosTitlesXMLNodes = xDoc.GetElementsByTagName(IosTag); - ToolStripMenuItem[] iosTitleCollection = new ToolStripMenuItem[IosTitlesXMLNodes.Count]; - - for (int x = 0; x < IosTitlesXMLNodes.Count; x++) - { - ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem(); - XmlAttributeCollection XMLAttributes = IosTitlesXMLNodes[x].Attributes; - - string titleID = ""; - string descname = ""; - bool dangerous = false; - bool ticket = true; - - XmlNodeList ChildrenOfTheNode = IosTitlesXMLNodes[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 "version": - string[] versions = ChildrenOfTheNode[z].InnerText.Split(','); - 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 "ticket": - ticket = Convert.ToBoolean(ChildrenOfTheNode[z].InnerText); - break; - case "danger": - dangerous = true; - XMLToolStripItem.ToolTipText = ChildrenOfTheNode[z].InnerText; - break; - default: - break; - } - XMLToolStripItem.Image = SelectItemImage(ticket, dangerous); - - if (titleID != "") - XMLToolStripItem.Text = String.Format("{0} - {1}", titleID, descname); - else - XMLToolStripItem.Text = descname; //Huh - } - - iosTitleCollection[x] = XMLToolStripItem; - } - - return iosTitleCollection; - } - - public ToolStripMenuItem[][] LoadVirtualConsoleTitles() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - XmlNodeList VirtualConsoleXMLNodes = xDoc.GetElementsByTagName(VcTag); - ToolStripMenuItem[][] vcTitleCollection = new ToolStripMenuItem[VcConsoles.Length][]; - - for (int j = 0; j < vcTitleCollection.Length; j++) - { - vcTitleCollection[j] = new ToolStripMenuItem[0]; - } - - for (int x = 0; x < VirtualConsoleXMLNodes.Count; x++) - { - ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem(); - XmlAttributeCollection XMLAttributes = VirtualConsoleXMLNodes[x].Attributes; - - string titleID = ""; - string descname = ""; - bool dangerous = false; - bool ticket = true; - - XmlNodeList ChildrenOfTheNode = VirtualConsoleXMLNodes[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 "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]))); - } - } - 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 - { // Wait what? - XMLToolStripItem.Text = descname; - } - } - - for (int a = 0; a < VcConsoles.Length; a++) - { - if (XMLAttributes[0].Value == VcConsoles[a]) - { - Array.Resize(ref vcTitleCollection[a], vcTitleCollection[a].Length + 1); - vcTitleCollection[a][vcTitleCollection[a].Length - 1] = XMLToolStripItem; - } - } - } - - return vcTitleCollection; - } - - public ToolStripMenuItem[] LoadWiiWareTitles() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - XmlNodeList WiiWareTitlesXMLNodes = xDoc.GetElementsByTagName(WwTag); - ToolStripMenuItem[] wwTitleCollection = new ToolStripMenuItem[WiiWareTitlesXMLNodes.Count]; - - for (int x = 0; x < WiiWareTitlesXMLNodes.Count; x++) - { - ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem(); - XmlAttributeCollection XMLAttributes = WiiWareTitlesXMLNodes[x].Attributes; - - string titleID = ""; - string descname = ""; - bool dangerous = false; - bool ticket = true; - - XmlNodeList ChildrenOfTheNode = WiiWareTitlesXMLNodes[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 "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]))); - } - } - 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 - { // Wait what? - XMLToolStripItem.Text = descname; - } - } - - wwTitleCollection[x] = XMLToolStripItem; - } - - return wwTitleCollection; - } - - /// - /// Gathers the region based on index - /// - /// The index. - /// XmlDocument with database inside - /// Region desc - private string RegionFromIndex(int index) - { - /* Typical Region XML - * - 41 (All/System) - 44 (German) - 45 (USA/NTSC) - 46 (French) - 4A (Japan) - 4B (Korea) - 4C (Japanese Import to Europe/Australia/PAL) - 4D (American Import to Europe/Australia/PAL) - 4E (Japanese Import to USA/NTSC) - 50 (Europe/PAL) - 51 (Korea w/ Japanese Language) - 54 (Korea w/ English Language) - 58 (Some Homebrew) - - */ - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - - XmlNodeList XMLRegionList = xDoc.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)"; - } - - /// - /// Selects the database item image. - /// - /// if set to true [ticket]. - /// if set to true [danger]. - /// Correct Image - 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; - } - - /// - /// Loads the region codes. - /// - public ToolStripMenuItem[] LoadRegionCodes() - { - /* TODO: make this check InvokeRequired... - if (this.InvokeRequired) - { - Debug.Write("TOLDYOUSO!"); - BootChecksCallback bcc = new BootChecksCallback(LoadRegionCodes); - this.Invoke(bcc); - return; - }*/ - - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - - XmlNodeList XMLRegionList = xDoc.GetElementsByTagName("REGIONS"); - XmlNodeList ChildrenOfTheNode = XMLRegionList[0].ChildNodes; - - ToolStripMenuItem[] regionItems = new ToolStripMenuItem[ChildrenOfTheNode.Count]; - - // For each child node (region node) - for (int z = 0; z < ChildrenOfTheNode.Count; z++) - { - regionItems[z] = new ToolStripMenuItem(); - regionItems[z].Text = ChildrenOfTheNode[z].InnerText; - } - - return regionItems; - } - - public ToolStripMenuItem[] LoadScripts() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - - XmlNodeList ScriptXMLNodes = xDoc.GetElementsByTagName(UpdateTag); - - ToolStripMenuItem[] scriptCollection = new ToolStripMenuItem[ScriptXMLNodes.Count]; - - for (int x = 0; x < ScriptXMLNodes.Count; x++) - { - ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem(); - XmlAttributeCollection XMLAttributes = ScriptXMLNodes[x].Attributes; - XmlNodeList ChildrenOfTheNode = ScriptXMLNodes[x].ChildNodes; - - for (int z = 0; z < ChildrenOfTheNode.Count; z++) - { - switch (ChildrenOfTheNode[z].Name) - { - case "name": - XMLToolStripItem.Text = ChildrenOfTheNode[z].InnerText; - break; - case "script": - XMLToolStripItem.ToolTipText = ChildrenOfTheNode[z].InnerText; - break; - default: - break; - } - XMLToolStripItem.Image = Properties.Resources.script_start; - - } - scriptCollection[x] = XMLToolStripItem; - } - - return scriptCollection; - } - - public ToolStripMenuItem[] LoadDSiSystemTitles() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - XmlNodeList DSiSystemTitlesXMLNodes = xDoc.GetElementsByTagName(DSiSystemTag); - ToolStripMenuItem[] dsiSystemTitleCollection = new ToolStripMenuItem[DSiSystemTitlesXMLNodes.Count]; - - for (int x = 0; x < DSiSystemTitlesXMLNodes.Count; x++) - { - ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem(); - XmlAttributeCollection XMLAttributes = DSiSystemTitlesXMLNodes[x].Attributes; - - string titleID = ""; - string descname = ""; - bool dangerous = false; - bool ticket = true; - - XmlNodeList ChildrenOfTheNode = DSiSystemTitlesXMLNodes[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 "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]))); - } - } - 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 - { // Wait what? - XMLToolStripItem.Text = descname; - } - } - - dsiSystemTitleCollection[x] = XMLToolStripItem; - } - - return dsiSystemTitleCollection; - } - - public ToolStripMenuItem[] LoadDsiWareTitles() - { - if (databaseString.Length < 1) - { - throw new Exception("Load the database into a memory stream first!"); - } - - XmlDocument xDoc = new XmlDocument(); - xDoc.LoadXml(databaseString); - XmlNodeList DSiWareTitlesXMLNodes = xDoc.GetElementsByTagName(DSiWareTag); - ToolStripMenuItem[] DSiWareTitleCollection = new ToolStripMenuItem[DSiWareTitlesXMLNodes.Count]; - - for (int x = 0; x < DSiWareTitlesXMLNodes.Count; x++) - { - ToolStripMenuItem XMLToolStripItem = new ToolStripMenuItem(); - XmlAttributeCollection XMLAttributes = DSiWareTitlesXMLNodes[x].Attributes; - - string titleID = ""; - string descname = ""; - bool dangerous = false; - bool ticket = true; - - XmlNodeList ChildrenOfTheNode = DSiWareTitlesXMLNodes[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 "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]))); - } - } - 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 - { // Wait what? - XMLToolStripItem.Text = descname; - } - } - - DSiWareTitleCollection[x] = XMLToolStripItem; - } - - return DSiWareTitleCollection; - } - } -} diff --git a/NUS Downloader/Form1.Designer.cs b/NUS Downloader/Form1.Designer.cs deleted file mode 100644 index e241734..0000000 --- a/NUS Downloader/Form1.Designer.cs +++ /dev/null @@ -1,1199 +0,0 @@ -/////////////////////////////////////////// -// NUS Downloader: Form1.Designer.cs // -// $Rev:: $ // -// $Author:: $ // -// $Date:: $ // -/////////////////////////////////////////// - -namespace NUS_Downloader -{ - partial class Form1 - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); - this.Extrasbtn = new System.Windows.Forms.Button(); - this.downloadstartbtn = new System.Windows.Forms.Button(); - this.statusbox = new System.Windows.Forms.RichTextBox(); - this.NUSDownloader = new System.ComponentModel.BackgroundWorker(); - this.label1 = new System.Windows.Forms.Label(); - this.wadnamebox = new System.Windows.Forms.TextBox(); - this.databaseStrip = new System.Windows.Forms.ContextMenuStrip(this.components); - this.SystemMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.systemFakeMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.IOSMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.iosFakeMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VCMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.C64MenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.GenesisMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.MSXMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.N64MenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.NeoGeoMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.NESMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.SegaMSMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.SNESMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.TurboGrafx16MenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.TurboGrafxCDMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.VCArcadeMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.vcFakeMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.WiiWareMenuList = new System.Windows.Forms.ToolStripMenuItem(); - this.wwFakeMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); - this.dsiSystemToolStripMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.dsiFakeSystemToolStripMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.dSiWareToolStripMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.dSiWareFakeToolStripMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.RegionCodesList = new System.Windows.Forms.ToolStripMenuItem(); - this.wiiRegionCodesMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.dsiRegionCodesMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); - this.updateDatabaseToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.extrasStrip = new System.Windows.Forms.ContextMenuStrip(this.components); - this.loadInfoFromTMDToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.proxySettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); - this.openNUSDDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.moreExtrasToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.runFolderFixToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.wiiBrewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.mainPageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.databasePageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.removeNUSDFilesFoldersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.databaseToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.localTicketInventoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.donateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.aboutNUSDToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.proxyBox = new System.Windows.Forms.GroupBox(); - this.label13 = new System.Windows.Forms.Label(); - this.label12 = new System.Windows.Forms.Label(); - this.ProxyUser = new System.Windows.Forms.TextBox(); - this.SaveProxyBtn = new System.Windows.Forms.Button(); - this.ProxyAssistBtn = new System.Windows.Forms.Button(); - this.ProxyURL = new System.Windows.Forms.TextBox(); - this.ProxyVerifyBox = new System.Windows.Forms.GroupBox(); - this.SaveProxyPwdPermanentBtn = new System.Windows.Forms.Button(); - this.checkBox1 = new System.Windows.Forms.CheckBox(); - this.SaveProxyPwdBtn = new System.Windows.Forms.Button(); - this.label14 = new System.Windows.Forms.Label(); - this.ProxyPwdBox = new System.Windows.Forms.TextBox(); - this.scriptsbutton = new System.Windows.Forms.Button(); - this.scriptsStrip = new System.Windows.Forms.ContextMenuStrip(this.components); - this.scriptsLocalMenuEntry = new System.Windows.Forms.ToolStripMenuItem(); - this.scriptsDatabaseToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.loadNUSScriptToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.emulateUpdate = new System.Windows.Forms.ToolStripMenuItem(); - this.uSANTSCToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.europePALToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.japanNTSCJToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.koreaToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.iosPatchGroupBox = new System.Windows.Forms.GroupBox(); - this.label2 = new System.Windows.Forms.Label(); - this.iosPatchesListBox = new System.Windows.Forms.CheckedListBox(); - this.iosPatchGroupBoxOKbtn = new System.Windows.Forms.Button(); - this.richPanel = new System.Windows.Forms.Panel(); - this.databaseButton = new System.Windows.Forms.Button(); - this.saveaswadbtn = new System.Windows.Forms.Button(); - this.iosPatchCheckbox = new System.Windows.Forms.CheckBox(); - this.keepenccontents = new System.Windows.Forms.CheckBox(); - this.clearButton = new System.Windows.Forms.Button(); - this.packbox = new System.Windows.Forms.CheckBox(); - this.decryptbox = new System.Windows.Forms.CheckBox(); - this.localuse = new System.Windows.Forms.CheckBox(); - this.serverLbl = new System.Windows.Forms.Label(); - this.titleidbox = new wmgCMS.WaterMarkTextBox(); - this.dlprogress = new wyDay.Controls.Windows7ProgressBar(); - this.titleversion = new wmgCMS.WaterMarkTextBox(); - this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); - this.databaseStrip.SuspendLayout(); - this.extrasStrip.SuspendLayout(); - this.proxyBox.SuspendLayout(); - this.ProxyVerifyBox.SuspendLayout(); - this.scriptsStrip.SuspendLayout(); - this.iosPatchGroupBox.SuspendLayout(); - this.richPanel.SuspendLayout(); - this.SuspendLayout(); - // - // Extrasbtn - // - this.Extrasbtn.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.Extrasbtn.Location = new System.Drawing.Point(194, 5); - this.Extrasbtn.Name = "Extrasbtn"; - this.Extrasbtn.Size = new System.Drawing.Size(68, 27); - this.Extrasbtn.TabIndex = 2; - this.Extrasbtn.Text = "Extras..."; - this.Extrasbtn.UseVisualStyleBackColor = true; - this.Extrasbtn.Click += new System.EventHandler(this.extrasMenuButton_Click); - // - // downloadstartbtn - // - this.downloadstartbtn.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.downloadstartbtn.Location = new System.Drawing.Point(12, 64); - this.downloadstartbtn.Name = "downloadstartbtn"; - this.downloadstartbtn.Size = new System.Drawing.Size(250, 25); - this.downloadstartbtn.TabIndex = 5; - this.downloadstartbtn.Text = "Start NUS Download!"; - this.downloadstartbtn.UseVisualStyleBackColor = true; - this.downloadstartbtn.Click += new System.EventHandler(this.DownloadBtn_Click); - // - // statusbox - // - this.statusbox.BackColor = System.Drawing.SystemColors.ControlLightLight; - this.statusbox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.statusbox.Location = new System.Drawing.Point(-2, -2); - this.statusbox.Name = "statusbox"; - this.statusbox.ReadOnly = true; - this.statusbox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None; - this.statusbox.Size = new System.Drawing.Size(252, 269); - this.statusbox.TabIndex = 0; - this.statusbox.Text = ""; - // - // NUSDownloader - // - this.NUSDownloader.DoWork += new System.ComponentModel.DoWorkEventHandler(this.NUSDownloader_DoWork); - this.NUSDownloader.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.NUSDownloader_RunWorkerCompleted); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.BackColor = System.Drawing.Color.Transparent; - this.label1.Location = new System.Drawing.Point(159, 45); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(13, 13); - this.label1.TabIndex = 0; - this.label1.Text = "v"; - // - // wadnamebox - // - this.wadnamebox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.wadnamebox.Enabled = false; - this.wadnamebox.Location = new System.Drawing.Point(102, 390); - this.wadnamebox.MaxLength = 99999; - this.wadnamebox.Name = "wadnamebox"; - this.wadnamebox.Size = new System.Drawing.Size(161, 20); - this.wadnamebox.TabIndex = 17; - // - // databaseStrip - // - this.databaseStrip.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.databaseStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SystemMenuList, - this.systemFakeMenuItem, - this.IOSMenuList, - this.iosFakeMenuItem, - this.VCMenuList, - this.vcFakeMenuItem, - this.WiiWareMenuList, - this.wwFakeMenuItem, - this.toolStripSeparator5, - this.dsiSystemToolStripMenu, - this.dsiFakeSystemToolStripMenu, - this.dSiWareToolStripMenu, - this.dSiWareFakeToolStripMenu, - this.toolStripSeparator1, - this.RegionCodesList, - this.toolStripSeparator4, - this.updateDatabaseToolStripMenuItem}); - this.databaseStrip.Name = "databaseStrip"; - this.databaseStrip.ShowItemToolTips = false; - this.databaseStrip.Size = new System.Drawing.Size(164, 330); - this.databaseStrip.Text = "Hidden"; - this.databaseStrip.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(this.anyStrip_Closed); - // - // SystemMenuList - // - this.SystemMenuList.AutoSize = false; - this.SystemMenuList.Image = ((System.Drawing.Image)(resources.GetObject("SystemMenuList.Image"))); - this.SystemMenuList.Name = "SystemMenuList"; - this.SystemMenuList.Size = new System.Drawing.Size(158, 22); - this.SystemMenuList.Text = "System"; - // - // systemFakeMenuItem - // - this.systemFakeMenuItem.Image = global::NUS_Downloader.Properties.Resources.arrow_ticker; - this.systemFakeMenuItem.Name = "systemFakeMenuItem"; - this.systemFakeMenuItem.Size = new System.Drawing.Size(163, 22); - this.systemFakeMenuItem.Text = "System"; - this.systemFakeMenuItem.Visible = false; - // - // IOSMenuList - // - this.IOSMenuList.Image = ((System.Drawing.Image)(resources.GetObject("IOSMenuList.Image"))); - this.IOSMenuList.Name = "IOSMenuList"; - this.IOSMenuList.Size = new System.Drawing.Size(163, 22); - this.IOSMenuList.Text = "IOS"; - // - // iosFakeMenuItem - // - this.iosFakeMenuItem.Image = global::NUS_Downloader.Properties.Resources.arrow_ticker; - this.iosFakeMenuItem.Name = "iosFakeMenuItem"; - this.iosFakeMenuItem.Size = new System.Drawing.Size(163, 22); - this.iosFakeMenuItem.Text = "IOS"; - this.iosFakeMenuItem.Visible = false; - // - // VCMenuList - // - this.VCMenuList.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.C64MenuList, - this.GenesisMenuList, - this.MSXMenuList, - this.N64MenuList, - this.NeoGeoMenuList, - this.NESMenuList, - this.SegaMSMenuList, - this.SNESMenuList, - this.TurboGrafx16MenuList, - this.TurboGrafxCDMenuList, - this.VCArcadeMenuList}); - this.VCMenuList.Image = ((System.Drawing.Image)(resources.GetObject("VCMenuList.Image"))); - this.VCMenuList.Name = "VCMenuList"; - this.VCMenuList.Size = new System.Drawing.Size(163, 22); - this.VCMenuList.Text = "Virtual Console"; - // - // C64MenuList - // - this.C64MenuList.Name = "C64MenuList"; - this.C64MenuList.Size = new System.Drawing.Size(182, 22); - this.C64MenuList.Text = "Commodore 64"; - // - // GenesisMenuList - // - this.GenesisMenuList.Name = "GenesisMenuList"; - this.GenesisMenuList.Size = new System.Drawing.Size(182, 22); - this.GenesisMenuList.Text = "Mega Drive/Genesis"; - // - // MSXMenuList - // - this.MSXMenuList.Name = "MSXMenuList"; - this.MSXMenuList.Size = new System.Drawing.Size(182, 22); - this.MSXMenuList.Text = "MSX"; - // - // N64MenuList - // - this.N64MenuList.Name = "N64MenuList"; - this.N64MenuList.Size = new System.Drawing.Size(182, 22); - this.N64MenuList.Text = "Nintendo 64"; - // - // NeoGeoMenuList - // - this.NeoGeoMenuList.Name = "NeoGeoMenuList"; - this.NeoGeoMenuList.Size = new System.Drawing.Size(182, 22); - this.NeoGeoMenuList.Text = "NeoGeo"; - // - // NESMenuList - // - this.NESMenuList.Name = "NESMenuList"; - this.NESMenuList.Size = new System.Drawing.Size(182, 22); - this.NESMenuList.Text = "NES"; - // - // SegaMSMenuList - // - this.SegaMSMenuList.Name = "SegaMSMenuList"; - this.SegaMSMenuList.Size = new System.Drawing.Size(182, 22); - this.SegaMSMenuList.Text = "Sega Master System"; - // - // SNESMenuList - // - this.SNESMenuList.Name = "SNESMenuList"; - this.SNESMenuList.Size = new System.Drawing.Size(182, 22); - this.SNESMenuList.Text = "SNES"; - // - // TurboGrafx16MenuList - // - this.TurboGrafx16MenuList.Name = "TurboGrafx16MenuList"; - this.TurboGrafx16MenuList.Size = new System.Drawing.Size(182, 22); - this.TurboGrafx16MenuList.Text = "TruboGrafx-16"; - // - // TurboGrafxCDMenuList - // - this.TurboGrafxCDMenuList.Name = "TurboGrafxCDMenuList"; - this.TurboGrafxCDMenuList.Size = new System.Drawing.Size(182, 22); - this.TurboGrafxCDMenuList.Text = "TurboGrafx-CD"; - // - // VCArcadeMenuList - // - this.VCArcadeMenuList.Name = "VCArcadeMenuList"; - this.VCArcadeMenuList.Size = new System.Drawing.Size(182, 22); - this.VCArcadeMenuList.Text = "Virtual Console Arcade"; - // - // vcFakeMenuItem - // - this.vcFakeMenuItem.Image = global::NUS_Downloader.Properties.Resources.arrow_ticker; - this.vcFakeMenuItem.Name = "vcFakeMenuItem"; - this.vcFakeMenuItem.Size = new System.Drawing.Size(163, 22); - this.vcFakeMenuItem.Text = "Virtual Console"; - this.vcFakeMenuItem.Visible = false; - // - // WiiWareMenuList - // - this.WiiWareMenuList.Image = ((System.Drawing.Image)(resources.GetObject("WiiWareMenuList.Image"))); - this.WiiWareMenuList.Name = "WiiWareMenuList"; - this.WiiWareMenuList.Size = new System.Drawing.Size(163, 22); - this.WiiWareMenuList.Text = "WiiWare"; - // - // wwFakeMenuItem - // - this.wwFakeMenuItem.Image = global::NUS_Downloader.Properties.Resources.arrow_ticker; - this.wwFakeMenuItem.Name = "wwFakeMenuItem"; - this.wwFakeMenuItem.Size = new System.Drawing.Size(163, 22); - this.wwFakeMenuItem.Text = "WiiWare"; - this.wwFakeMenuItem.Visible = false; - // - // toolStripSeparator5 - // - this.toolStripSeparator5.Name = "toolStripSeparator5"; - this.toolStripSeparator5.Size = new System.Drawing.Size(160, 6); - // - // dsiSystemToolStripMenu - // - this.dsiSystemToolStripMenu.Image = global::NUS_Downloader.Properties.Resources.dsi16x16; - this.dsiSystemToolStripMenu.Name = "dsiSystemToolStripMenu"; - this.dsiSystemToolStripMenu.Size = new System.Drawing.Size(163, 22); - this.dsiSystemToolStripMenu.Text = "System"; - // - // dsiFakeSystemToolStripMenu - // - this.dsiFakeSystemToolStripMenu.Image = global::NUS_Downloader.Properties.Resources.arrow_ticker; - this.dsiFakeSystemToolStripMenu.Name = "dsiFakeSystemToolStripMenu"; - this.dsiFakeSystemToolStripMenu.Size = new System.Drawing.Size(163, 22); - this.dsiFakeSystemToolStripMenu.Text = "System"; - this.dsiFakeSystemToolStripMenu.Visible = false; - // - // dSiWareToolStripMenu - // - this.dSiWareToolStripMenu.Image = global::NUS_Downloader.Properties.Resources.dsi16x16; - this.dSiWareToolStripMenu.Name = "dSiWareToolStripMenu"; - this.dSiWareToolStripMenu.Size = new System.Drawing.Size(163, 22); - this.dSiWareToolStripMenu.Text = "DSiWare"; - // - // dSiWareFakeToolStripMenu - // - this.dSiWareFakeToolStripMenu.Image = global::NUS_Downloader.Properties.Resources.arrow_ticker; - this.dSiWareFakeToolStripMenu.Name = "dSiWareFakeToolStripMenu"; - this.dSiWareFakeToolStripMenu.Size = new System.Drawing.Size(163, 22); - this.dSiWareFakeToolStripMenu.Text = "DSiWare"; - this.dSiWareFakeToolStripMenu.Visible = false; - // - // toolStripSeparator1 - // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(160, 6); - // - // RegionCodesList - // - this.RegionCodesList.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.wiiRegionCodesMenu, - this.dsiRegionCodesMenu}); - this.RegionCodesList.Name = "RegionCodesList"; - this.RegionCodesList.Size = new System.Drawing.Size(163, 22); - this.RegionCodesList.Text = "Region Codes"; - // - // wiiRegionCodesMenu - // - this.wiiRegionCodesMenu.Name = "wiiRegionCodesMenu"; - this.wiiRegionCodesMenu.Size = new System.Drawing.Size(89, 22); - this.wiiRegionCodesMenu.Text = "Wii"; - this.wiiRegionCodesMenu.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.wiiRegionCodesMenu_DropDownItemClicked); - // - // dsiRegionCodesMenu - // - this.dsiRegionCodesMenu.Name = "dsiRegionCodesMenu"; - this.dsiRegionCodesMenu.Size = new System.Drawing.Size(89, 22); - this.dsiRegionCodesMenu.Text = "DSi"; - this.dsiRegionCodesMenu.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.dsiRegionCodesMenu_DropDownItemClicked); - // - // toolStripSeparator4 - // - this.toolStripSeparator4.Name = "toolStripSeparator4"; - this.toolStripSeparator4.Size = new System.Drawing.Size(160, 6); - // - // updateDatabaseToolStripMenuItem - // - this.updateDatabaseToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.database_save; - this.updateDatabaseToolStripMenuItem.Name = "updateDatabaseToolStripMenuItem"; - this.updateDatabaseToolStripMenuItem.Size = new System.Drawing.Size(163, 22); - this.updateDatabaseToolStripMenuItem.Text = "Update Databases"; - this.updateDatabaseToolStripMenuItem.Click += new System.EventHandler(this.updateDatabaseToolStripMenuItem_Click); - // - // extrasStrip - // - this.extrasStrip.AllowMerge = false; - this.extrasStrip.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.extrasStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.loadInfoFromTMDToolStripMenuItem, - this.toolStripSeparator3, - this.proxySettingsToolStripMenuItem, - this.toolStripSeparator6, - this.openNUSDDirectoryToolStripMenuItem, - this.moreExtrasToolStripMenuItem, - this.donateToolStripMenuItem, - this.toolStripSeparator7, - this.aboutNUSDToolStripMenuItem}); - this.extrasStrip.Name = "extrasStrip"; - this.extrasStrip.Size = new System.Drawing.Size(178, 154); - this.extrasStrip.Text = "Hidden"; - this.extrasStrip.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(this.anyStrip_Closed); - this.extrasStrip.Opening += new System.ComponentModel.CancelEventHandler(this.extrasStrip_Opening); - // - // loadInfoFromTMDToolStripMenuItem - // - this.loadInfoFromTMDToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.page_white_magnify; - this.loadInfoFromTMDToolStripMenuItem.Name = "loadInfoFromTMDToolStripMenuItem"; - this.loadInfoFromTMDToolStripMenuItem.Size = new System.Drawing.Size(177, 22); - this.loadInfoFromTMDToolStripMenuItem.Text = "Load Info from TMD"; - this.loadInfoFromTMDToolStripMenuItem.Click += new System.EventHandler(this.loadInfoFromTMDToolStripMenuItem_Click); - // - // toolStripSeparator3 - // - this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(174, 6); - // - // proxySettingsToolStripMenuItem - // - this.proxySettingsToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.server_link; - this.proxySettingsToolStripMenuItem.Name = "proxySettingsToolStripMenuItem"; - this.proxySettingsToolStripMenuItem.Size = new System.Drawing.Size(177, 22); - this.proxySettingsToolStripMenuItem.Text = "Proxy Settings"; - this.proxySettingsToolStripMenuItem.Click += new System.EventHandler(this.proxySettingsToolStripMenuItem_Click); - // - // toolStripSeparator6 - // - this.toolStripSeparator6.Name = "toolStripSeparator6"; - this.toolStripSeparator6.Size = new System.Drawing.Size(174, 6); - // - // openNUSDDirectoryToolStripMenuItem - // - this.openNUSDDirectoryToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.folder; - this.openNUSDDirectoryToolStripMenuItem.Name = "openNUSDDirectoryToolStripMenuItem"; - this.openNUSDDirectoryToolStripMenuItem.Size = new System.Drawing.Size(177, 22); - this.openNUSDDirectoryToolStripMenuItem.Text = "Open NUSD Directory"; - this.openNUSDDirectoryToolStripMenuItem.Click += new System.EventHandler(this.openNUSDDirectoryToolStripMenuItem_Click); - // - // moreExtrasToolStripMenuItem - // - this.moreExtrasToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.runFolderFixToolStripMenuItem, - this.wiiBrewToolStripMenuItem, - this.removeNUSDFilesFoldersToolStripMenuItem, - this.databaseToolStripMenuItem}); - this.moreExtrasToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.wrench; - this.moreExtrasToolStripMenuItem.Name = "moreExtrasToolStripMenuItem"; - this.moreExtrasToolStripMenuItem.Size = new System.Drawing.Size(177, 22); - this.moreExtrasToolStripMenuItem.Text = "More Extras..."; - this.moreExtrasToolStripMenuItem.Visible = false; - // - // runFolderFixToolStripMenuItem - // - this.runFolderFixToolStripMenuItem.Name = "runFolderFixToolStripMenuItem"; - this.runFolderFixToolStripMenuItem.Size = new System.Drawing.Size(206, 22); - this.runFolderFixToolStripMenuItem.Text = "Run \'FolderFix\'"; - this.runFolderFixToolStripMenuItem.Click += new System.EventHandler(this.runFolderFixToolStripMenuItem_Click); - // - // wiiBrewToolStripMenuItem - // - this.wiiBrewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.mainPageToolStripMenuItem, - this.databasePageToolStripMenuItem}); - this.wiiBrewToolStripMenuItem.Name = "wiiBrewToolStripMenuItem"; - this.wiiBrewToolStripMenuItem.Size = new System.Drawing.Size(206, 22); - this.wiiBrewToolStripMenuItem.Text = "WiiBrew"; - // - // mainPageToolStripMenuItem - // - this.mainPageToolStripMenuItem.Name = "mainPageToolStripMenuItem"; - this.mainPageToolStripMenuItem.Size = new System.Drawing.Size(147, 22); - this.mainPageToolStripMenuItem.Text = "Main Page"; - this.mainPageToolStripMenuItem.Click += new System.EventHandler(this.mainPageToolStripMenuItem_Click); - // - // databasePageToolStripMenuItem - // - this.databasePageToolStripMenuItem.Name = "databasePageToolStripMenuItem"; - this.databasePageToolStripMenuItem.Size = new System.Drawing.Size(147, 22); - this.databasePageToolStripMenuItem.Text = "Database Page"; - this.databasePageToolStripMenuItem.Click += new System.EventHandler(this.databasePageToolStripMenuItem_Click); - // - // removeNUSDFilesFoldersToolStripMenuItem - // - this.removeNUSDFilesFoldersToolStripMenuItem.Name = "removeNUSDFilesFoldersToolStripMenuItem"; - this.removeNUSDFilesFoldersToolStripMenuItem.Size = new System.Drawing.Size(206, 22); - this.removeNUSDFilesFoldersToolStripMenuItem.Text = "Remove NUSD Files\\Folders"; - this.removeNUSDFilesFoldersToolStripMenuItem.Click += new System.EventHandler(this.removeNUSDFilesFoldersToolStripMenuItem_Click); - // - // databaseToolStripMenuItem - // - this.databaseToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.localTicketInventoryToolStripMenuItem}); - this.databaseToolStripMenuItem.Name = "databaseToolStripMenuItem"; - this.databaseToolStripMenuItem.Size = new System.Drawing.Size(206, 22); - this.databaseToolStripMenuItem.Text = "Database"; - // - // localTicketInventoryToolStripMenuItem - // - this.localTicketInventoryToolStripMenuItem.Name = "localTicketInventoryToolStripMenuItem"; - this.localTicketInventoryToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.localTicketInventoryToolStripMenuItem.Text = "Local Ticket Inventory"; - this.localTicketInventoryToolStripMenuItem.Click += new System.EventHandler(this.localTicketInventoryToolStripMenuItem_Click); - // - // donateToolStripMenuItem - // - this.donateToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.money; - this.donateToolStripMenuItem.Name = "donateToolStripMenuItem"; - this.donateToolStripMenuItem.Size = new System.Drawing.Size(177, 22); - this.donateToolStripMenuItem.Text = "Donate!"; - this.donateToolStripMenuItem.Visible = false; - this.donateToolStripMenuItem.Click += new System.EventHandler(this.donateToolStripMenuItem_Click); - // - // aboutNUSDToolStripMenuItem - // - this.aboutNUSDToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.information; - this.aboutNUSDToolStripMenuItem.Name = "aboutNUSDToolStripMenuItem"; - this.aboutNUSDToolStripMenuItem.Size = new System.Drawing.Size(177, 22); - this.aboutNUSDToolStripMenuItem.Text = "About NUSD"; - this.aboutNUSDToolStripMenuItem.Click += new System.EventHandler(this.aboutNUSDToolStripMenuItem_Click); - // - // proxyBox - // - this.proxyBox.BackColor = System.Drawing.Color.White; - this.proxyBox.Controls.Add(this.label13); - this.proxyBox.Controls.Add(this.label12); - this.proxyBox.Controls.Add(this.ProxyUser); - this.proxyBox.Controls.Add(this.SaveProxyBtn); - this.proxyBox.Controls.Add(this.ProxyAssistBtn); - this.proxyBox.Controls.Add(this.ProxyURL); - this.proxyBox.Location = new System.Drawing.Point(31, 250); - this.proxyBox.Name = "proxyBox"; - this.proxyBox.Size = new System.Drawing.Size(212, 114); - this.proxyBox.TabIndex = 45; - this.proxyBox.TabStop = false; - this.proxyBox.Text = "Proxy Settings"; - this.proxyBox.Visible = false; - // - // label13 - // - this.label13.AutoSize = true; - this.label13.Location = new System.Drawing.Point(6, 55); - this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(32, 13); - this.label13.TabIndex = 32; - this.label13.Text = "User:"; - // - // label12 - // - this.label12.AutoSize = true; - this.label12.Location = new System.Drawing.Point(6, 29); - this.label12.Name = "label12"; - this.label12.Size = new System.Drawing.Size(36, 13); - this.label12.TabIndex = 31; - this.label12.Text = "Proxy:"; - // - // ProxyUser - // - this.ProxyUser.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.ProxyUser.Location = new System.Drawing.Point(55, 53); - this.ProxyUser.Name = "ProxyUser"; - this.ProxyUser.Size = new System.Drawing.Size(151, 20); - this.ProxyUser.TabIndex = 30; - // - // SaveProxyBtn - // - this.SaveProxyBtn.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.SaveProxyBtn.Location = new System.Drawing.Point(6, 79); - this.SaveProxyBtn.Name = "SaveProxyBtn"; - this.SaveProxyBtn.Size = new System.Drawing.Size(161, 26); - this.SaveProxyBtn.TabIndex = 29; - this.SaveProxyBtn.Text = "Save Proxy Settings"; - this.SaveProxyBtn.UseVisualStyleBackColor = true; - this.SaveProxyBtn.Click += new System.EventHandler(this.SaveProxyBtn_Click); - // - // ProxyAssistBtn - // - this.ProxyAssistBtn.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.ProxyAssistBtn.Image = global::NUS_Downloader.Properties.Resources.help; - this.ProxyAssistBtn.Location = new System.Drawing.Point(177, 79); - this.ProxyAssistBtn.Name = "ProxyAssistBtn"; - this.ProxyAssistBtn.Size = new System.Drawing.Size(29, 26); - this.ProxyAssistBtn.TabIndex = 28; - this.ProxyAssistBtn.UseVisualStyleBackColor = true; - this.ProxyAssistBtn.Click += new System.EventHandler(this.ProxyAssistBtn_Click); - // - // ProxyURL - // - this.ProxyURL.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.ProxyURL.Location = new System.Drawing.Point(55, 27); - this.ProxyURL.Name = "ProxyURL"; - this.ProxyURL.Size = new System.Drawing.Size(151, 20); - this.ProxyURL.TabIndex = 0; - // - // ProxyVerifyBox - // - this.ProxyVerifyBox.BackColor = System.Drawing.SystemColors.Control; - this.ProxyVerifyBox.Controls.Add(this.SaveProxyPwdPermanentBtn); - this.ProxyVerifyBox.Controls.Add(this.checkBox1); - this.ProxyVerifyBox.Controls.Add(this.SaveProxyPwdBtn); - this.ProxyVerifyBox.Controls.Add(this.label14); - this.ProxyVerifyBox.Controls.Add(this.ProxyPwdBox); - this.ProxyVerifyBox.Location = new System.Drawing.Point(31, 222); - this.ProxyVerifyBox.Name = "ProxyVerifyBox"; - this.ProxyVerifyBox.Size = new System.Drawing.Size(212, 133); - this.ProxyVerifyBox.TabIndex = 46; - this.ProxyVerifyBox.TabStop = false; - this.ProxyVerifyBox.Text = "Verify Credentials"; - this.ProxyVerifyBox.Visible = false; - // - // SaveProxyPwdPermanentBtn - // - this.SaveProxyPwdPermanentBtn.Enabled = false; - this.SaveProxyPwdPermanentBtn.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.SaveProxyPwdPermanentBtn.Location = new System.Drawing.Point(9, 104); - this.SaveProxyPwdPermanentBtn.Name = "SaveProxyPwdPermanentBtn"; - this.SaveProxyPwdPermanentBtn.Size = new System.Drawing.Size(197, 23); - this.SaveProxyPwdPermanentBtn.TabIndex = 36; - this.SaveProxyPwdPermanentBtn.Text = "Save (To File)"; - this.SaveProxyPwdPermanentBtn.UseVisualStyleBackColor = true; - this.SaveProxyPwdPermanentBtn.Click += new System.EventHandler(this.SaveProxyPwdPermanentBtn_Click); - // - // checkBox1 - // - this.checkBox1.AutoSize = true; - this.checkBox1.Location = new System.Drawing.Point(9, 72); - this.checkBox1.Name = "checkBox1"; - this.checkBox1.Size = new System.Drawing.Size(199, 30); - this.checkBox1.TabIndex = 35; - this.checkBox1.Text = "I understand that NUSD stores proxy\r\npasswords in plain text."; - this.checkBox1.UseVisualStyleBackColor = true; - this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); - // - // SaveProxyPwdBtn - // - this.SaveProxyPwdBtn.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.SaveProxyPwdBtn.Location = new System.Drawing.Point(9, 43); - this.SaveProxyPwdBtn.Name = "SaveProxyPwdBtn"; - this.SaveProxyPwdBtn.Size = new System.Drawing.Size(197, 23); - this.SaveProxyPwdBtn.TabIndex = 34; - this.SaveProxyPwdBtn.Text = "Save (This Session Only)"; - this.SaveProxyPwdBtn.UseVisualStyleBackColor = true; - this.SaveProxyPwdBtn.Click += new System.EventHandler(this.SaveProxyPwdButton_Click); - // - // label14 - // - this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(6, 21); - this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(62, 13); - this.label14.TabIndex = 33; - this.label14.Text = "Proxy Pass:"; - // - // ProxyPwdBox - // - this.ProxyPwdBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.ProxyPwdBox.Location = new System.Drawing.Point(71, 19); - this.ProxyPwdBox.Name = "ProxyPwdBox"; - this.ProxyPwdBox.Size = new System.Drawing.Size(135, 20); - this.ProxyPwdBox.TabIndex = 32; - this.ProxyPwdBox.UseSystemPasswordChar = true; - this.ProxyPwdBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ProxyPwdBox_KeyPress); - // - // scriptsbutton - // - this.scriptsbutton.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.scriptsbutton.Location = new System.Drawing.Point(103, 5); - this.scriptsbutton.Name = "scriptsbutton"; - this.scriptsbutton.Size = new System.Drawing.Size(85, 27); - this.scriptsbutton.TabIndex = 1; - this.scriptsbutton.Text = "Scripts..."; - this.scriptsbutton.UseVisualStyleBackColor = true; - this.scriptsbutton.Click += new System.EventHandler(this.scriptsbutton_Click); - // - // scriptsStrip - // - this.scriptsStrip.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.scriptsStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.scriptsLocalMenuEntry, - this.scriptsDatabaseToolStripMenuItem, - this.loadNUSScriptToolStripMenuItem, - this.toolStripSeparator2, - this.emulateUpdate}); - this.scriptsStrip.Name = "scriptsStrip"; - this.scriptsStrip.ShowItemToolTips = false; - this.scriptsStrip.Size = new System.Drawing.Size(206, 98); - this.scriptsStrip.Text = "Hidden"; - this.scriptsStrip.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(this.anyStrip_Closed); - // - // scriptsLocalMenuEntry - // - this.scriptsLocalMenuEntry.Enabled = false; - this.scriptsLocalMenuEntry.Image = global::NUS_Downloader.Properties.Resources.script_code; - this.scriptsLocalMenuEntry.Name = "scriptsLocalMenuEntry"; - this.scriptsLocalMenuEntry.Overflow = System.Windows.Forms.ToolStripItemOverflow.AsNeeded; - this.scriptsLocalMenuEntry.Size = new System.Drawing.Size(205, 22); - this.scriptsLocalMenuEntry.Text = "Scripts (Local)"; - // - // scriptsDatabaseToolStripMenuItem - // - this.scriptsDatabaseToolStripMenuItem.Enabled = false; - this.scriptsDatabaseToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.script_code_red; - this.scriptsDatabaseToolStripMenuItem.Name = "scriptsDatabaseToolStripMenuItem"; - this.scriptsDatabaseToolStripMenuItem.Size = new System.Drawing.Size(205, 22); - this.scriptsDatabaseToolStripMenuItem.Text = "Scripts (Database)"; - // - // loadNUSScriptToolStripMenuItem - // - this.loadNUSScriptToolStripMenuItem.Image = global::NUS_Downloader.Properties.Resources.script_go; - this.loadNUSScriptToolStripMenuItem.Name = "loadNUSScriptToolStripMenuItem"; - this.loadNUSScriptToolStripMenuItem.Size = new System.Drawing.Size(205, 22); - this.loadNUSScriptToolStripMenuItem.Text = "Load NUS Script"; - this.loadNUSScriptToolStripMenuItem.Click += new System.EventHandler(this.loadNUSScriptToolStripMenuItem_Click); - // - // toolStripSeparator2 - // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(202, 6); - // - // emulateUpdate - // - this.emulateUpdate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.uSANTSCToolStripMenuItem, - this.europePALToolStripMenuItem, - this.japanNTSCJToolStripMenuItem, - this.koreaToolStripMenuItem}); - this.emulateUpdate.Image = global::NUS_Downloader.Properties.Resources.server_connect; - this.emulateUpdate.Name = "emulateUpdate"; - this.emulateUpdate.Size = new System.Drawing.Size(205, 22); - this.emulateUpdate.Text = "Emulate Wii System Update"; - this.emulateUpdate.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.emulateUpdate_DropDownItemClicked); - // - // uSANTSCToolStripMenuItem - // - this.uSANTSCToolStripMenuItem.Name = "uSANTSCToolStripMenuItem"; - this.uSANTSCToolStripMenuItem.Size = new System.Drawing.Size(114, 22); - this.uSANTSCToolStripMenuItem.Text = "USA"; - // - // europePALToolStripMenuItem - // - this.europePALToolStripMenuItem.Name = "europePALToolStripMenuItem"; - this.europePALToolStripMenuItem.Size = new System.Drawing.Size(114, 22); - this.europePALToolStripMenuItem.Text = "EUROPE"; - // - // japanNTSCJToolStripMenuItem - // - this.japanNTSCJToolStripMenuItem.Name = "japanNTSCJToolStripMenuItem"; - this.japanNTSCJToolStripMenuItem.Size = new System.Drawing.Size(114, 22); - this.japanNTSCJToolStripMenuItem.Text = "JAPAN"; - // - // koreaToolStripMenuItem - // - this.koreaToolStripMenuItem.Name = "koreaToolStripMenuItem"; - this.koreaToolStripMenuItem.Size = new System.Drawing.Size(114, 22); - this.koreaToolStripMenuItem.Text = "KOREA"; - // - // iosPatchGroupBox - // - this.iosPatchGroupBox.Controls.Add(this.label2); - this.iosPatchGroupBox.Controls.Add(this.iosPatchesListBox); - this.iosPatchGroupBox.Controls.Add(this.iosPatchGroupBoxOKbtn); - this.iosPatchGroupBox.Location = new System.Drawing.Point(31, 187); - this.iosPatchGroupBox.Name = "iosPatchGroupBox"; - this.iosPatchGroupBox.Size = new System.Drawing.Size(212, 115); - this.iosPatchGroupBox.TabIndex = 55; - this.iosPatchGroupBox.TabStop = false; - this.iosPatchGroupBox.Text = "IOS Patches"; - this.iosPatchGroupBox.Visible = false; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(9, 16); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(184, 26); - this.label2.TabIndex = 2; - this.label2.Text = "Patch the following bugs into any IOS\r\nI download:"; - // - // iosPatchesListBox - // - this.iosPatchesListBox.BackColor = System.Drawing.SystemColors.Menu; - this.iosPatchesListBox.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.iosPatchesListBox.CheckOnClick = true; - this.iosPatchesListBox.FormattingEnabled = true; - this.iosPatchesListBox.Items.AddRange(new object[] { - "Trucha bug", - "ES_Identify", - "NAND permissions"}); - this.iosPatchesListBox.Location = new System.Drawing.Point(6, 62); - this.iosPatchesListBox.Name = "iosPatchesListBox"; - this.iosPatchesListBox.Size = new System.Drawing.Size(115, 45); - this.iosPatchesListBox.TabIndex = 1; - // - // iosPatchGroupBoxOKbtn - // - this.iosPatchGroupBoxOKbtn.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.iosPatchGroupBoxOKbtn.Location = new System.Drawing.Point(127, 84); - this.iosPatchGroupBoxOKbtn.Name = "iosPatchGroupBoxOKbtn"; - this.iosPatchGroupBoxOKbtn.Size = new System.Drawing.Size(75, 23); - this.iosPatchGroupBoxOKbtn.TabIndex = 0; - this.iosPatchGroupBoxOKbtn.Text = "OK"; - this.iosPatchGroupBoxOKbtn.UseVisualStyleBackColor = true; - this.iosPatchGroupBoxOKbtn.Click += new System.EventHandler(this.iosPatchGroupBoxOKbtn_Click); - // - // richPanel - // - this.richPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.richPanel.Controls.Add(this.statusbox); - this.richPanel.Location = new System.Drawing.Point(12, 116); - this.richPanel.Name = "richPanel"; - this.richPanel.Size = new System.Drawing.Size(250, 268); - this.richPanel.TabIndex = 56; - // - // databaseButton - // - this.databaseButton.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.databaseButton.Location = new System.Drawing.Point(12, 5); - this.databaseButton.Name = "databaseButton"; - this.databaseButton.Size = new System.Drawing.Size(85, 27); - this.databaseButton.TabIndex = 0; - this.databaseButton.Text = "Database..."; - this.databaseButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.databaseButton.UseVisualStyleBackColor = true; - this.databaseButton.Click += new System.EventHandler(this.DatabaseButton_Click); - // - // saveaswadbtn - // - this.saveaswadbtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.saveaswadbtn.AutoSize = true; - this.saveaswadbtn.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.saveaswadbtn.BackColor = System.Drawing.Color.Transparent; - this.saveaswadbtn.Enabled = false; - this.saveaswadbtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - this.saveaswadbtn.Image = global::NUS_Downloader.Properties.Resources.disk; - this.saveaswadbtn.Location = new System.Drawing.Point(239, 409); - this.saveaswadbtn.MaximumSize = new System.Drawing.Size(0, 24); - this.saveaswadbtn.MinimumSize = new System.Drawing.Size(0, 24); - this.saveaswadbtn.Name = "saveaswadbtn"; - this.saveaswadbtn.Size = new System.Drawing.Size(24, 24); - this.saveaswadbtn.TabIndex = 11; - this.saveaswadbtn.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.saveaswadbtn.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.saveaswadbtn.UseVisualStyleBackColor = false; - this.saveaswadbtn.Click += new System.EventHandler(this.saveaswadbtn_Click); - this.saveaswadbtn.MouseEnter += new System.EventHandler(this.saveaswadbtn_MouseEnter); - this.saveaswadbtn.MouseLeave += new System.EventHandler(this.saveaswadbtn_MouseLeave); - // - // iosPatchCheckbox - // - this.iosPatchCheckbox.Enabled = false; - this.iosPatchCheckbox.Image = global::NUS_Downloader.Properties.Resources.bug_add; - this.iosPatchCheckbox.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.iosPatchCheckbox.Location = new System.Drawing.Point(11, 487); - this.iosPatchCheckbox.Name = "iosPatchCheckbox"; - this.iosPatchCheckbox.Size = new System.Drawing.Size(104, 24); - this.iosPatchCheckbox.TabIndex = 10; - this.iosPatchCheckbox.Text = "Patch IOS..."; - this.iosPatchCheckbox.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.iosPatchCheckbox.UseVisualStyleBackColor = true; - this.iosPatchCheckbox.CheckedChanged += new System.EventHandler(this.iosPatchCheckbox_CheckedChanged); - // - // keepenccontents - // - this.keepenccontents.Checked = true; - this.keepenccontents.CheckState = System.Windows.Forms.CheckState.Checked; - this.keepenccontents.Image = global::NUS_Downloader.Properties.Resources.package; - this.keepenccontents.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.keepenccontents.Location = new System.Drawing.Point(11, 410); - this.keepenccontents.Name = "keepenccontents"; - this.keepenccontents.Size = new System.Drawing.Size(177, 26); - this.keepenccontents.TabIndex = 8; - this.keepenccontents.Text = "Keep Encrypted Contents"; - this.keepenccontents.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.keepenccontents.UseVisualStyleBackColor = true; - // - // clearButton - // - this.clearButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.clearButton.AutoSize = true; - this.clearButton.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.clearButton.BackColor = System.Drawing.Color.Transparent; - this.clearButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - this.clearButton.Image = global::NUS_Downloader.Properties.Resources.bin_closed; - this.clearButton.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.clearButton.Location = new System.Drawing.Point(238, 360); - this.clearButton.MaximumSize = new System.Drawing.Size(0, 24); - this.clearButton.MinimumSize = new System.Drawing.Size(0, 24); - this.clearButton.Name = "clearButton"; - this.clearButton.Size = new System.Drawing.Size(24, 24); - this.clearButton.TabIndex = 12; - this.clearButton.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.clearButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.clearButton.UseVisualStyleBackColor = false; - this.clearButton.Click += new System.EventHandler(this.ClearStatusbox); - this.clearButton.MouseEnter += new System.EventHandler(this.clearButton_MouseEnter); - this.clearButton.MouseLeave += new System.EventHandler(this.clearButton_MouseLeave); - // - // packbox - // - this.packbox.Image = global::NUS_Downloader.Properties.Resources.box; - this.packbox.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.packbox.Location = new System.Drawing.Point(11, 388); - this.packbox.Name = "packbox"; - this.packbox.Size = new System.Drawing.Size(98, 22); - this.packbox.TabIndex = 7; - this.packbox.Text = "Pack WAD"; - this.packbox.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.packbox.UseVisualStyleBackColor = true; - this.packbox.CheckedChanged += new System.EventHandler(this.packbox_CheckedChanged); - this.packbox.EnabledChanged += new System.EventHandler(this.packbox_EnabledChanged); - // - // decryptbox - // - this.decryptbox.Image = global::NUS_Downloader.Properties.Resources.package_green; - this.decryptbox.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.decryptbox.Location = new System.Drawing.Point(11, 436); - this.decryptbox.Name = "decryptbox"; - this.decryptbox.Size = new System.Drawing.Size(231, 26); - this.decryptbox.TabIndex = 9; - this.decryptbox.Text = "Create Decrypted Contents (*.app)"; - this.decryptbox.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.decryptbox.UseVisualStyleBackColor = true; - // - // localuse - // - this.localuse.AutoSize = true; - this.localuse.Checked = true; - this.localuse.CheckState = System.Windows.Forms.CheckState.Checked; - this.localuse.Image = global::NUS_Downloader.Properties.Resources.drive_disk; - this.localuse.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.localuse.Location = new System.Drawing.Point(11, 463); - this.localuse.MinimumSize = new System.Drawing.Size(0, 22); - this.localuse.Name = "localuse"; - this.localuse.Size = new System.Drawing.Size(162, 22); - this.localuse.TabIndex = 12; - this.localuse.Text = "Use Local Files If Present"; - this.localuse.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.localuse.UseVisualStyleBackColor = true; - // - // serverLbl - // - this.serverLbl.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.serverLbl.Location = new System.Drawing.Point(233, 38); - this.serverLbl.Name = "serverLbl"; - this.serverLbl.Size = new System.Drawing.Size(29, 20); - this.serverLbl.TabIndex = 57; - this.serverLbl.Text = "Wii"; - this.serverLbl.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.serverLbl.TextChanged += new System.EventHandler(this.serverLbl_TextChanged); - this.serverLbl.Click += new System.EventHandler(this.serverLbl_Click); - this.serverLbl.MouseEnter += new System.EventHandler(this.serverLbl_MouseEnter); - this.serverLbl.MouseLeave += new System.EventHandler(this.serverLbl_MouseLeave); - // - // titleidbox - // - this.titleidbox.Font = new System.Drawing.Font("Tahoma", 8.25F); - this.titleidbox.Location = new System.Drawing.Point(12, 38); - this.titleidbox.MaxLength = 16; - this.titleidbox.Name = "titleidbox"; - this.titleidbox.Size = new System.Drawing.Size(141, 21); - this.titleidbox.TabIndex = 3; - this.titleidbox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; - this.titleidbox.WaterMarkColor = System.Drawing.Color.Silver; - this.titleidbox.WaterMarkText = "Title ID"; - this.titleidbox.TextChanged += new System.EventHandler(this.titleidbox_TextChanged); - // - // dlprogress - // - this.dlprogress.ContainerControl = this; - this.dlprogress.Location = new System.Drawing.Point(12, 95); - this.dlprogress.Name = "dlprogress"; - this.dlprogress.Size = new System.Drawing.Size(250, 15); - this.dlprogress.TabIndex = 47; - // - // titleversion - // - this.titleversion.Font = new System.Drawing.Font("Tahoma", 8.25F); - this.titleversion.Location = new System.Drawing.Point(169, 38); - this.titleversion.MaxLength = 8; - this.titleversion.Name = "titleversion"; - this.titleversion.Size = new System.Drawing.Size(58, 21); - this.titleversion.TabIndex = 4; - this.titleversion.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; - this.titleversion.WaterMarkColor = System.Drawing.Color.Silver; - this.titleversion.WaterMarkText = "Version"; - this.titleversion.TextChanged += new System.EventHandler(this.titleversion_TextChanged); - // - // toolStripSeparator7 - // - this.toolStripSeparator7.Name = "toolStripSeparator7"; - this.toolStripSeparator7.Size = new System.Drawing.Size(174, 6); - // - // Form1 - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.ClientSize = new System.Drawing.Size(274, 516); - this.Controls.Add(this.serverLbl); - this.Controls.Add(this.iosPatchGroupBox); - this.Controls.Add(this.ProxyVerifyBox); - this.Controls.Add(this.proxyBox); - this.Controls.Add(this.scriptsbutton); - this.Controls.Add(this.titleidbox); - this.Controls.Add(this.dlprogress); - this.Controls.Add(this.titleversion); - this.Controls.Add(this.databaseButton); - this.Controls.Add(this.iosPatchCheckbox); - this.Controls.Add(this.downloadstartbtn); - this.Controls.Add(this.clearButton); - this.Controls.Add(this.keepenccontents); - this.Controls.Add(this.label1); - this.Controls.Add(this.Extrasbtn); - this.Controls.Add(this.wadnamebox); - this.Controls.Add(this.richPanel); - this.Controls.Add(this.decryptbox); - this.Controls.Add(this.packbox); - this.Controls.Add(this.saveaswadbtn); - this.Controls.Add(this.localuse); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.Name = "Form1"; - this.Text = " "; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing); - this.Load += new System.EventHandler(this.Form1_Load); - this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseWheel); - this.databaseStrip.ResumeLayout(false); - this.extrasStrip.ResumeLayout(false); - this.proxyBox.ResumeLayout(false); - this.proxyBox.PerformLayout(); - this.ProxyVerifyBox.ResumeLayout(false); - this.ProxyVerifyBox.PerformLayout(); - this.scriptsStrip.ResumeLayout(false); - this.iosPatchGroupBox.ResumeLayout(false); - this.iosPatchGroupBox.PerformLayout(); - this.richPanel.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Button Extrasbtn; - private System.Windows.Forms.Button downloadstartbtn; - private System.Windows.Forms.RichTextBox statusbox; - private System.Windows.Forms.CheckBox packbox; - private System.Windows.Forms.CheckBox localuse; - private System.ComponentModel.BackgroundWorker NUSDownloader; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.TextBox wadnamebox; - private System.Windows.Forms.CheckBox decryptbox; - private System.Windows.Forms.Button databaseButton; - private System.Windows.Forms.ContextMenuStrip databaseStrip; - private System.Windows.Forms.ToolStripMenuItem SystemMenuList; - private System.Windows.Forms.ToolStripMenuItem IOSMenuList; - private System.Windows.Forms.ToolStripMenuItem VCMenuList; - private System.Windows.Forms.ToolStripMenuItem WiiWareMenuList; - private System.Windows.Forms.ToolStripMenuItem C64MenuList; - private System.Windows.Forms.ToolStripMenuItem NeoGeoMenuList; - private System.Windows.Forms.ToolStripMenuItem NESMenuList; - private System.Windows.Forms.ToolStripMenuItem SNESMenuList; - private System.Windows.Forms.ToolStripMenuItem N64MenuList; - private System.Windows.Forms.ToolStripMenuItem MSXMenuList; - private System.Windows.Forms.ToolStripMenuItem TurboGrafx16MenuList; - private System.Windows.Forms.ToolStripMenuItem SegaMSMenuList; - private System.Windows.Forms.ToolStripMenuItem GenesisMenuList; - private System.Windows.Forms.ToolStripMenuItem VCArcadeMenuList; - private System.Windows.Forms.ToolStripMenuItem TurboGrafxCDMenuList; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; - private System.Windows.Forms.ToolStripMenuItem RegionCodesList; - private System.Windows.Forms.Button clearButton; - private System.Windows.Forms.ContextMenuStrip extrasStrip; - private System.Windows.Forms.ToolStripMenuItem loadInfoFromTMDToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; - private System.Windows.Forms.ToolStripMenuItem proxySettingsToolStripMenuItem; - private System.Windows.Forms.GroupBox proxyBox; - private System.Windows.Forms.TextBox ProxyUser; - private System.Windows.Forms.Button SaveProxyBtn; - private System.Windows.Forms.Button ProxyAssistBtn; - private System.Windows.Forms.TextBox ProxyURL; - private System.Windows.Forms.Label label13; - private System.Windows.Forms.Label label12; - private System.Windows.Forms.GroupBox ProxyVerifyBox; - private System.Windows.Forms.Button SaveProxyPwdBtn; - private System.Windows.Forms.Label label14; - private System.Windows.Forms.TextBox ProxyPwdBox; - private wyDay.Controls.Windows7ProgressBar dlprogress; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; - private wmgCMS.WaterMarkTextBox titleidbox; - private wmgCMS.WaterMarkTextBox titleversion; - private System.Windows.Forms.Button scriptsbutton; - private System.Windows.Forms.ContextMenuStrip scriptsStrip; - private System.Windows.Forms.ToolStripMenuItem loadNUSScriptToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem emulateUpdate; - private System.Windows.Forms.ToolStripMenuItem uSANTSCToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem europePALToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem japanNTSCJToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem koreaToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; - private System.Windows.Forms.ToolStripMenuItem updateDatabaseToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem scriptsLocalMenuEntry; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; - private System.Windows.Forms.ToolStripMenuItem scriptsDatabaseToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem aboutNUSDToolStripMenuItem; - private System.Windows.Forms.CheckBox checkBox1; - private System.Windows.Forms.Button SaveProxyPwdPermanentBtn; - private System.Windows.Forms.CheckBox keepenccontents; - private System.Windows.Forms.Button saveaswadbtn; - private System.Windows.Forms.CheckBox iosPatchCheckbox; - private System.Windows.Forms.GroupBox iosPatchGroupBox; - private System.Windows.Forms.CheckedListBox iosPatchesListBox; - private System.Windows.Forms.Button iosPatchGroupBoxOKbtn; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Panel richPanel; - private System.Windows.Forms.ToolStripMenuItem systemFakeMenuItem; - private System.Windows.Forms.ToolStripMenuItem iosFakeMenuItem; - private System.Windows.Forms.ToolStripMenuItem vcFakeMenuItem; - private System.Windows.Forms.ToolStripMenuItem wwFakeMenuItem; - private System.Windows.Forms.ToolStripMenuItem openNUSDDirectoryToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem moreExtrasToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem runFolderFixToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem wiiBrewToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem mainPageToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem databasePageToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem removeNUSDFilesFoldersToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem databaseToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem localTicketInventoryToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem donateToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; - private System.Windows.Forms.ToolStripMenuItem dsiSystemToolStripMenu; - private System.Windows.Forms.ToolStripMenuItem dsiFakeSystemToolStripMenu; - private System.Windows.Forms.ToolStripMenuItem dSiWareToolStripMenu; - private System.Windows.Forms.ToolStripMenuItem dSiWareFakeToolStripMenu; - private System.Windows.Forms.ToolStripMenuItem wiiRegionCodesMenu; - private System.Windows.Forms.ToolStripMenuItem dsiRegionCodesMenu; - private System.Windows.Forms.Label serverLbl; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; - } -} - diff --git a/NUS Downloader/Form1.cs b/NUS Downloader/Form1.cs deleted file mode 100644 index 3711a01..0000000 --- a/NUS Downloader/Form1.cs +++ /dev/null @@ -1,3063 +0,0 @@ -/////////////////////////////////////////// -// 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 -/////////////////////////////////////// - - -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 -{ - partial class Form1 : Form - { - private readonly string CURRENT_DIR = Directory.GetCurrentDirectory(); - -#if DEBUG - private static string svnversion = "$Rev$"; - private static string version = String.Format("SVN r{0}", ((int.Parse(svnversion.Replace("$"+"R"+"e"+"v"+": ","").Replace(" "+"$","")))+1)); -#else - // TODO: Always remember to change version! - private string version = "v1.9"; -#endif - - // Cross-thread Windows Formsing - private delegate void AddToolStripItemToStripCallback( - ToolStripMenuItem menulist, ToolStripMenuItem[] additionitems); - private delegate void WriteStatusCallback(string Update, Color writecolor); - 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); - - 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 threads - private BackgroundWorker databaseWorker; - private BackgroundWorker dsiDatabaseWorker; - - // Scripts Thread - private BackgroundWorker scriptsWorker; - - // Colours for status box - private System.Drawing.Color normalcolor = Color.FromName("Black"); - private System.Drawing.Color warningcolor = Color.FromName("DarkGoldenrod"); - private System.Drawing.Color errorcolor = Color.FromName("Crimson"); - private System.Drawing.Color infocolor = Color.FromName("RoyalBlue"); - - // Statuses of disabled things - private bool[] disabledStorage = new bool[13]; - - // This is the standard entry to the GUI - public Form1() - { - InitializeComponent(); - - GUISetup(); - - BootChecks(); - } - - // CLI Mode - public Form1(string[] args) - { - InitializeComponent(); - Debug.WriteLine("CLI Parameters passed"); - - GUISetup(); - - if ((args.Length == 1) && (File.Exists(args[0]))) - { - BootChecks(); - - string script_content = File.ReadAllText(args[0]); - FileInfo script_file = new FileInfo(args[0]); - script_content += String.Format(";{0}", script_file.Name.Replace("." + script_file.Extension, "")); - - BackgroundWorker scripter = new BackgroundWorker(); - scripter.DoWork += new DoWorkEventHandler(RunScriptBg); - scripter.RunWorkerAsync(script_content); - } - else if (args.Length >= 2) - { - RunCommandMode(args); - Environment.Exit(0); - //this.Close(); - } - else - { - BootChecks(); - } - } - - private void RunCommandMode(string[] args) - { - // CLI mode, inspired and taken from wiiNinja's mod. - - // Initialize the checkboxes and radio boxes - packbox.Checked = false; // Create wad - default OFF - localuse.Checked = true; // Use local content if already downloaded - default ON - decryptbox.Checked = false; - keepenccontents.Checked = false; - //consoleCBox.SelectedIndex = 0; // 0 is Wii, 1 is DS - - // Clear 3 items in ios patches list. This feature is not supported in the command line version at this time. - iosPatchCheckbox.Checked = false; - iosPatchesListBox.SetItemChecked(0, false); - iosPatchesListBox.SetItemChecked(1, false); - iosPatchesListBox.SetItemChecked(2, false); - - Console.WriteLine("NUS Downloader - v{0}", version); - - if (args.Length < 2) - { - Console.WriteLine("Usage:"); - Console.WriteLine(" nusd [optionalArgs]"); - Console.WriteLine("\nWhere:"); - Console.WriteLine(" titleID = The ID of the title to be downloaded"); - Console.WriteLine(" titleVersion = The version of the title to be downloaded"); - Console.WriteLine(" Use \"*\" (no quotes) to get the latest version"); - Console.WriteLine(" OptionalArgs:"); - Console.WriteLine(" packwad = A wad file will be generated"); - Console.WriteLine(" localuse = Use local contents if available"); - Console.WriteLine(" decrypt = Create decrypted contents"); - Console.WriteLine(" keepencrypt = Keep encrypted contents"); - } - else - { - for (int i = 0; i < args.Length; i++) - { - Console.WriteLine("{0}", args[i]); - switch (i) - { - case 0: - // First command line argument is ALWAYS the TitleID - titleidbox.Text = args[i]; - break; - - case 1: - // Second command line argument is ALWAYS the TitleVersion. - // User may specify a "*" to retrieve the latest version - if (args[i] == "*") - titleversion.Text = ""; - else - titleversion.Text = args[i]; - break; - - default: - // Any other arguments beyond the 2nd one are considered optional - if (args[i] == "packwad") - packbox.Checked = true; - else if (args[i] == "localuse") - localuse.Checked = true; - else if (args[i] == "decrypt") - decryptbox.Checked = true; - else if (args[i] == "keepencrypt") - keepenccontents.Checked = true; - else - Console.WriteLine("\n>>>> Warning: Unrecognized command line argument: {0}. This option is ignored...", args[i]); - break; - } - } - - // Do this to set the wad file name - UpdatePackedName(); - - // Call to get the files from server - NUSDownloader_DoWork(null, null); - - Console.WriteLine("\nSuccessfully downloaded the title {0} version {1}", args[0], args[1]); - } - } - - private void GUISetup() - { - this.Font = new System.Drawing.Font("Tahoma", 8); - 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); - statusbox.SelectionColor = statusbox.ForeColor = normalcolor; - if (version.StartsWith("SVN")) - { - WriteStatus("!!!!! THIS IS A DEBUG BUILD FROM SVN !!!!!"); - WriteStatus("Features CAN and WILL be broken in this build!"); - WriteStatus("Devs: REMEMBER TO CHANGE TO THE RELEASE CONFIGURATION AND CHANGE VERSION NUMBER BEFORE BUILDING!"); - WriteStatus("\r\n"); - } - - // Database BackgroundWorker - this.databaseWorker = new BackgroundWorker(); - this.databaseWorker.DoWork += new DoWorkEventHandler(DoAllDatabaseyStuff); - this.databaseWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DoAllDatabaseyStuff_Completed); - this.databaseWorker.ProgressChanged += new ProgressChangedEventHandler(DoAllDatabaseyStuff_ProgressChanged); - this.databaseWorker.WorkerReportsProgress = true; - - // DSi Database BackgroundWorker - this.dsiDatabaseWorker = new BackgroundWorker(); - this.dsiDatabaseWorker.DoWork += new DoWorkEventHandler(DSiDatabaseWork); - this.dsiDatabaseWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DSiDatabaseWork_Completed); - this.dsiDatabaseWorker.ProgressChanged += new ProgressChangedEventHandler(DSiDatabaseWork_ProgressChanged); - this.dsiDatabaseWorker.WorkerReportsProgress = true; - - // Scripts BGLoader - this.scriptsWorker = new BackgroundWorker(); - this.scriptsWorker.DoWork += new DoWorkEventHandler(OrganizeScripts); - this.scriptsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(scriptsWorker_RunWorkerCompleted); - } - - private void Form1_Load(object sender, EventArgs e) - { - this.Text = String.Format("NUSD - {0}", version); ; - this.Size = this.MinimumSize; - serverLbl.Text = "Wii"; - } - - private bool NUSDFileExists(string filename) - { - return File.Exists(Path.Combine(CURRENT_DIR, filename)); - } - - /// - /// Checks certain file existances, etc. - /// - /// - 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!"); - DatabaseEnabled(false); - updateDatabaseToolStripMenuItem.Enabled = true; - updateDatabaseToolStripMenuItem.Visible = true; - updateDatabaseToolStripMenuItem.Text = "Download Database"; - } - else - { - Database db = new Database(); - db.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "database.xml")); - string version = db.GetDatabaseVersion(); - WriteStatus("Database.xml detected."); - WriteStatus(" - Version: " + version); - updateDatabaseToolStripMenuItem.Text = "Update Database"; - //databaseButton.Enabled = false; - //databaseButton.Text = "DB Loading"; - databaseButton.Text = " [ ]"; - databaseButton.Image = Properties.Resources.arrow_ticker; - // Load it up... - this.fds.RunWorkerAsync(); - } - - // Check for database.xml - if (NUSDFileExists("dsidatabase.xml") == false) - { - WriteStatus("DSiDatabase.xml not found. DSi database not usable!"); - DatabaseEnabled(false); - updateDatabaseToolStripMenuItem.Enabled = true; - updateDatabaseToolStripMenuItem.Visible = true; - updateDatabaseToolStripMenuItem.Text = "Download Database"; - } - else - { - Database db = new Database(); - db.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "database.xml")); - string version = db.GetDatabaseVersion(); - WriteStatus("Database.xml detected."); - WriteStatus(" - Version: " + version); - updateDatabaseToolStripMenuItem.Text = "Update Database"; - //databaseButton.Enabled = false; - //databaseButton.Text = "DB Loading"; - databaseButton.Text = " [ ]"; - databaseButton.Image = Properties.Resources.arrow_ticker; - // Load it up... - this.fds.RunWorkerAsync(); - }*/ - - if (NUSDFileExists("database.xml") == true) - { - Database db = new Database(); - db.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "database.xml")); - string version = db.GetDatabaseVersion(); - WriteStatus("Database.xml detected."); - WriteStatus(" - Version: " + version); - updateDatabaseToolStripMenuItem.Text = "Update Database"; - databaseButton.Text = " [ ]"; - databaseButton.Image = Properties.Resources.arrow_ticker; - // Load it up... - this.databaseWorker.RunWorkerAsync(); - } - - if (NUSDFileExists("dsidatabase.xml") == true) - { - Database db = new Database(); - db.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "dsidatabase.xml")); - string version = db.GetDatabaseVersion(); - WriteStatus("DSiDatabase.xml detected."); - WriteStatus(" - Version: " + version); - updateDatabaseToolStripMenuItem.Text = "Update Database"; - databaseButton.Text = " [ ]"; - databaseButton.Image = Properties.Resources.arrow_ticker; - // Load it up... - this.dsiDatabaseWorker.RunWorkerAsync(); - } - - // Load scripts (local) - RunScriptOrganizer(); - - // 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(); - FillDatabaseScripts(); - ShowInnerToolTips(false); - } - - private void DoAllDatabaseyStuff_Completed(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) - { - //this.databaseButton.Enabled = true; - this.databaseButton.Text = "Database..."; - this.databaseButton.Image = null; - /* - if (this.KoreaMassUpdate.HasDropDownItems || this.PALMassUpdate.HasDropDownItems || this.NTSCMassUpdate.HasDropDownItems) - { - this.scriptsbutton.Enabled = true; - }*/ - } - - private void DoAllDatabaseyStuff_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) - { - if (e.ProgressPercentage == 25) - databaseButton.Text = " [. ]"; - else if (e.ProgressPercentage == 50) - databaseButton.Text = " [.. ]"; - else if (e.ProgressPercentage == 75) - databaseButton.Text = " [... ]"; - else if (e.ProgressPercentage == 100) - databaseButton.Text = " [....]"; - } - - 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 - { - // ... - } - } - } - - /* - /// - /// Gets the database version. - /// - /// The database file. - /// - 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.Text = "Showing"; - extrasStrip.Show(Extrasbtn, 2, (2+Extrasbtn.Height)); - - - { - System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); - timer.Interval = 52; - timer.Tick += new EventHandler(contextmenusTimer_Tick); - timer.Start(); - } - } - - /// - /// Loads the title info from TMD. - /// - 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!"); - } - } - - /// - /// Writes the status to the statusbox. - /// - /// The update. - /// The color to use for writing text into the text box. - public void WriteStatus(string Update, Color writecolor) - { - // Check if thread-safe - if (statusbox.InvokeRequired) - { - Debug.WriteLine("InvokeRequired..."); - WriteStatusCallback wsc = new WriteStatusCallback(WriteStatus); - this.Invoke(wsc, new object[] { Update, writecolor }); - return; - } - // Small function for writing text to the statusbox... - int startlen = statusbox.TextLength; - if (statusbox.Text == "") - statusbox.Text = Update; - else - statusbox.AppendText("\r\n" + Update); - int endlen = statusbox.TextLength; - - // Set the color - statusbox.Select(startlen, endlen - startlen); - statusbox.SelectionColor = writecolor; - - // Scroll to end of text box. - statusbox.SelectionStart = statusbox.TextLength; - statusbox.SelectionLength = 0; - statusbox.ScrollToCaret(); - - // Also write to console - Console.WriteLine(Update); - } - - /// - /// Writes the status to the statusbox. - /// - /// The update. - public void WriteStatus(string Update) - { - WriteStatus(Update, normalcolor); - } - - /// - /// Reads the type of the Title ID. - /// - /// The TitleID. - 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!", warningcolor); - 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!", warningcolor); - 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!", errorcolor); - return; - } - else if (!(packbox.Checked) && !(decryptbox.Checked) && !(keepenccontents.Checked)) - { - // Prevent pointless running by n00bs. - WriteStatus("Running with your current settings will produce no output!", errorcolor); - WriteStatus(" - To amend this, look below and check an output type.", errorcolor); - return; - }/* - else if (!(script_mode)) - { - try - { - if (!statusbox.Lines[0].StartsWith(" ---")) - SetTextThreadSafe(statusbox, " --- " + titleidbox.Text + " ---"); - } - catch // No lines present... - { - SetTextThreadSafe(statusbox, " --- " + titleidbox.Text + " ---"); - } - } - else - WriteStatus(" --- " + 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... - - WriteStatus("Starting NUS Download. Please be patient!", infocolor); - SetEnableforDownload(false); - downloadstartbtn.Text = "Starting NUS Download!"; - - // WebClient configuration - WebClient nusWC = new WebClient(); - nusWC = ConfigureWithProxy(nusWC); - - // Create\Configure NusClient - libWiiSharp.NusClient nusClient = new libWiiSharp.NusClient(); - nusClient.ConfigureNusClient(nusWC); - nusClient.UseLocalFiles = localuse.Checked; - nusClient.ContinueWithoutTicket = true; - - // Server - if (serverLbl.Text == "Wii") - nusClient.SetToWiiServer(); - else if (serverLbl.Text == "DSi") - nusClient.SetToDSiServer(); - - // Events - nusClient.Debug += new EventHandler(nusClient_Debug); - nusClient.Progress += new EventHandler(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("Download failed: \"" + ex.Message + " ):\"", errorcolor); - } - - if (iosPatchCheckbox.Checked == true) { // Apply patches then... - bool didpatch = false; - int noofpatches = 0; - string appendpatch = ""; - // Okay, it's checked. - libWiiSharp.IosPatcher iosp = new libWiiSharp.IosPatcher(); - libWiiSharp.WAD ioswad = new libWiiSharp.WAD(); - wadName = wadName.Replace("[v]", nusClient.TitleVersion.ToString()); - 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.", infocolor); - 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": - noofpatches = iosp.PatchFakeSigning(); - if (noofpatches > 0) - { - WriteStatus(" - Patched in fake-signing:", infocolor); - if (noofpatches > 1) - appendpatch = "es"; - else - appendpatch = ""; - WriteStatus(String.Format(" {0} patch{1} applied.", noofpatches, appendpatch)); - didpatch = true; - } - else - WriteStatus(" - Could not patch fake-signing", errorcolor); - break; - case "ES_Identify": - noofpatches = iosp.PatchEsIdentify(); - if (noofpatches > 0) - { - WriteStatus(" - Patched in ES_Identify:", infocolor); - if (noofpatches > 1) - appendpatch = "es"; - else - appendpatch = ""; - WriteStatus(String.Format(" {0} patch{1} applied.", noofpatches, appendpatch)); - didpatch = true; - } - else - WriteStatus(" - Could not patch ES_Identify", errorcolor); - break; - case "NAND permissions": - noofpatches = iosp.PatchNandPermissions(); - if (noofpatches > 0) - { - WriteStatus(" - Patched in NAND permissions:", infocolor); - if (noofpatches > 1) - appendpatch = "es"; - else - appendpatch = ""; - WriteStatus(String.Format(" {0} patch{1} applied.", noofpatches, appendpatch)); - didpatch = true; - } - else - WriteStatus(" - Could not patch NAND permissions", errorcolor); - break; - } - } - else { - // WriteStatus(iosPatchesListBox.GetItemCheckState(iosPatchesListBox.Items.IndexOf(checkItem)).ToString()); - } - } - if (didpatch) - { - wadName = wadName.Replace(".wad",".patched.wad"); - try - { - if (wadName.Contains(Path.DirectorySeparatorChar.ToString()) || wadName.Contains(Path.AltDirectorySeparatorChar.ToString())) - ioswad.Save(wadName); - else - ioswad.Save(Path.Combine(Path.Combine(Path.Combine(Path.Combine(CURRENT_DIR, "titles"), titleidbox.Text), nusClient.TitleVersion.ToString()), wadName)); - WriteStatus(String.Format("Patched WAD saved as: {0}", Path.GetFileName(wadName)), infocolor); - } - catch (Exception ex) - { - WriteStatus(String.Format("Couldn't save patched WAD: \"{0}\" :(",ex.Message), errorcolor); - } - } - } - - 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; - } - - 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; - } - - /// - /// Displays the bytes. - /// - /// The bytes. - /// What separates the bytes - /// - 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.Text = "Showing"; - databaseStrip.Show(databaseButton, 2, (2+databaseButton.Height)); - - //if (!e.Equals(EventArgs.Empty)) - { - System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); - timer.Interval = 50; - timer.Tick += new EventHandler(contextmenusTimer_Tick); - timer.Start(); - } - } - - void contextmenusTimer_Tick(object sender, EventArgs e) - { - if (SystemMenuList.Pressed || IOSMenuList.Pressed || VCMenuList.Pressed || WiiWareMenuList.Pressed - || RegionCodesList.Pressed || scriptsLocalMenuEntry.Pressed || scriptsDatabaseToolStripMenuItem.Pressed - || emulateUpdate.Pressed) - return; - - if (databaseButton.ClientRectangle.Contains(databaseButton.PointToClient(MousePosition)) && ((System.Windows.Forms.Timer)sender).Interval != 50) - { - databaseStrip.Close(); - scriptsStrip.Close(); - extrasStrip.Close(); - DatabaseButton_Click(sender, EventArgs.Empty); - ((System.Windows.Forms.Timer)sender).Stop(); - } - - if (scriptsbutton.ClientRectangle.Contains(scriptsbutton.PointToClient(MousePosition)) && ((System.Windows.Forms.Timer)sender).Interval != 51) - { - databaseStrip.Close(); - scriptsStrip.Close(); - extrasStrip.Close(); - scriptsbutton_Click(sender, EventArgs.Empty); - ((System.Windows.Forms.Timer)sender).Stop(); - } - - if (Extrasbtn.ClientRectangle.Contains(Extrasbtn.PointToClient(MousePosition)) && ((System.Windows.Forms.Timer)sender).Interval != 52) - { - databaseStrip.Close(); - scriptsStrip.Close(); - extrasStrip.Close(); - extrasMenuButton_Click(sender, EventArgs.Empty); - ((System.Windows.Forms.Timer)sender).Stop(); - } - - //Debug.Write(((databaseStrip.Text == "Hidden").ToString() + (extrasStrip.Text == "Hidden").ToString() + (scriptsStrip.Text == "Hidden").ToString())); - - - if ((databaseStrip.Visible == false) && (extrasStrip.Visible == false) && (scriptsStrip.Visible == false)) - ((System.Windows.Forms.Timer)sender).Stop(); - - - } - - /// - /// Clears the database strip. - /// - private void ClearDatabaseStrip() - { - Control.CheckForIllegalCrossThreadCalls = false; - object[] thingstoclear = new object[] { - SystemMenuList, IOSMenuList, WiiWareMenuList, VCMenuList, - - // Now Virtual Console - C64MenuList, NeoGeoMenuList, NESMenuList, - SNESMenuList, N64MenuList, TurboGrafx16MenuList, - TurboGrafxCDMenuList, MSXMenuList, SegaMSMenuList, - GenesisMenuList, VCArcadeMenuList, - - // DSi Entries - dsiSystemToolStripMenu, dSiWareToolStripMenu - }; - - 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;*/ - } - } - - /// - /// Fills the database strip with the local database.xml file. - /// - private void FillDatabaseStrip(BackgroundWorker worker) - { - // Something needs to be done to remove this i guess - //Control.CheckForIllegalCrossThreadCalls = false; - - // Set fake items visible and real ones not. Only way to stop buggy enabled stuff. - SetPropertyThreadSafe(SystemMenuList, false, "Visible"); - SetPropertyThreadSafe(IOSMenuList, false, "Visible"); - SetPropertyThreadSafe(VCMenuList, false, "Visible"); - SetPropertyThreadSafe(WiiWareMenuList, false, "Visible"); - - SetPropertyThreadSafe(systemFakeMenuItem, true, "Visible"); - SetPropertyThreadSafe(iosFakeMenuItem, true, "Visible"); - SetPropertyThreadSafe(vcFakeMenuItem, true, "Visible"); - SetPropertyThreadSafe(wwFakeMenuItem, true, "Visible"); - - Database databaseObj = new Database(); - databaseObj.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "database.xml")); - - ToolStripMenuItem[] systemItems = databaseObj.LoadSystemTitles(); - for (int a = 0; a < systemItems.Length; a++) - { - systemItems[a].DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - for (int b = 0; b < systemItems[a].DropDownItems.Count; b++) - { - ToolStripMenuItem syslowerentry = (ToolStripMenuItem)systemItems[a].DropDownItems[b]; - if (syslowerentry.DropDownItems.Count > 0) - { - syslowerentry.DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - } - } - //AddToolStripItemToStrip(SystemMenuList, systemItems[a]); - //SystemMenuList.DropDownItems.Add(systemItems[a]); - } - Array.Sort(systemItems, delegate(ToolStripMenuItem tsmi1, ToolStripMenuItem tsmi2) - { - return tsmi1.Text - .Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)); - }); - AddToolStripItemToStrip(SystemMenuList, systemItems); - - SetPropertyThreadSafe(systemFakeMenuItem, false, "Visible"); - SetPropertyThreadSafe(SystemMenuList, true, "Visible"); - - Debug.WriteLine("Database: SysTitles added"); - worker.ReportProgress(25); - - ToolStripMenuItem[] iosItems = databaseObj.LoadIosTitles(); - for (int a = 0; a < iosItems.Length; a++) - { - iosItems[a].DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - //AddToolStripItemToStrip(IOSMenuList, iosItems[a]); - //IOSMenuList.DropDownItems.Add(iosItems[a]); - } - AddToolStripItemToStrip(IOSMenuList, iosItems); - - SetPropertyThreadSafe(iosFakeMenuItem, false, "Visible"); - SetPropertyThreadSafe(IOSMenuList, true, "Visible"); - Debug.WriteLine("Database: IosTitles added"); - worker.ReportProgress(50); - - ToolStripMenuItem[][] vcItems = databaseObj.LoadVirtualConsoleTitles(); - for (int a = 0; a < vcItems.Length; a++) - { - for (int b = 0; b < vcItems[a].Length; b++) - { - vcItems[a][b].DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - for (int c = 0; c < vcItems[a][b].DropDownItems.Count; c++) - { - ToolStripMenuItem lowerentry = (ToolStripMenuItem)vcItems[a][b].DropDownItems[c]; - lowerentry.DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - } - } - Array.Sort(vcItems[a], delegate(ToolStripMenuItem tsmi1, ToolStripMenuItem tsmi2) - { - return tsmi1.Text - .Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)); - }); - AddToolStripItemToStrip((ToolStripMenuItem)VCMenuList.DropDownItems[a], vcItems[a]); - } - - SetPropertyThreadSafe(vcFakeMenuItem, false, "Visible"); - SetPropertyThreadSafe(VCMenuList, true, "Visible"); - Debug.WriteLine("Database: VCTitles added"); - worker.ReportProgress(75); - - ToolStripMenuItem[] wwItems = databaseObj.LoadWiiWareTitles(); - for (int a = 0; a < wwItems.Length; a++) - { - wwItems[a].DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - for (int b = 0; b < wwItems[a].DropDownItems.Count; b++) - { - ToolStripMenuItem lowerentry = (ToolStripMenuItem)wwItems[a].DropDownItems[b]; - if (lowerentry.DropDownItems.Count > 0) - { - lowerentry.DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - } - - } - //AddToolStripItemToStrip(WiiWareMenuList, wwItems[a]); - //WiiWareMenuList.DropDownItems.Add(wwItems[a]); - } - Array.Sort(wwItems, delegate(ToolStripMenuItem tsmi1, ToolStripMenuItem tsmi2) - { - return tsmi1.Text - .Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)); - }); - AddToolStripItemToStrip(WiiWareMenuList, wwItems); - - SetPropertyThreadSafe(wwFakeMenuItem, false, "Visible"); - SetPropertyThreadSafe(WiiWareMenuList, true, "Visible"); - Debug.WriteLine("Database: WiiWareTitles added"); - worker.ReportProgress(100); - } - - /// - /// Fills the database strip with the local database.xml file. - /// - private void FillDSiDatabaseStrip(BackgroundWorker worker) - { - // Set fake items visible and real ones not. Only way to stop buggy enabled stuff. - SetPropertyThreadSafe(dsiSystemToolStripMenu, false, "Visible"); - SetPropertyThreadSafe(dSiWareToolStripMenu, false, "Visible"); - - SetPropertyThreadSafe(dsiFakeSystemToolStripMenu, true, "Visible"); - SetPropertyThreadSafe(dSiWareFakeToolStripMenu, true, "Visible"); - - Database databaseObj = new Database(); - databaseObj.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "dsidatabase.xml")); - - ToolStripMenuItem[] systemItems = databaseObj.LoadDSiSystemTitles(); - for (int a = 0; a < systemItems.Length; a++) - { - systemItems[a].DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - for (int b = 0; b < systemItems[a].DropDownItems.Count; b++) - { - ToolStripMenuItem syslowerentry = (ToolStripMenuItem)systemItems[a].DropDownItems[b]; - if (syslowerentry.DropDownItems.Count > 0) - { - syslowerentry.DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - } - } - } - Array.Sort(systemItems, delegate(ToolStripMenuItem tsmi1, ToolStripMenuItem tsmi2) - { - return tsmi1.Text - .Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)); - }); - AddToolStripItemToStrip(dsiSystemToolStripMenu, systemItems); - - SetPropertyThreadSafe(dsiFakeSystemToolStripMenu, false, "Visible"); - SetPropertyThreadSafe(dsiSystemToolStripMenu, true, "Visible"); - - Debug.WriteLine("Database: DSiSysTitles added"); - worker.ReportProgress(50); - - ToolStripMenuItem[] dsiWareItems = databaseObj.LoadDsiWareTitles(); - for (int a = 0; a < dsiWareItems.Length; a++) - { - dsiWareItems[a].DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - for (int b = 0; b < dsiWareItems[a].DropDownItems.Count; b++) - { - ToolStripMenuItem lowerentry = (ToolStripMenuItem)dsiWareItems[a].DropDownItems[b]; - if (lowerentry.DropDownItems.Count > 0) - { - lowerentry.DropDownItemClicked += new ToolStripItemClickedEventHandler(DatabaseItem_Clicked); - } - - } - } - Array.Sort(dsiWareItems, delegate(ToolStripMenuItem tsmi1, ToolStripMenuItem tsmi2) - { - return tsmi1.Text - .Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)); - }); - AddToolStripItemToStrip(dSiWareToolStripMenu, dsiWareItems); - - SetPropertyThreadSafe(dSiWareFakeToolStripMenu, false, "Visible"); - SetPropertyThreadSafe(dSiWareToolStripMenu, true, "Visible"); - Debug.WriteLine("Database: DSiWareTitles added"); - worker.ReportProgress(100); - } - - /// - /// Adds the tool strip item to strip. - /// - /// The type. - /// The additionitem. - /// The attributes. - // private void AddToolStripItemToStrip(ToolStripMenuItem menulist, ToolStripMenuItem additionitem) - private void AddToolStripItemToStrip(ToolStripMenuItem menulist, ToolStripMenuItem[] additionitems) - { - //Control.CheckForIllegalCrossThreadCalls = false; - //Debug.WriteLine(String.Format("Adding item")); - - if (this.InvokeRequired) - { - //Debug.WriteLine("InvokeRequired..."); - AddToolStripItemToStripCallback atsitsc = new AddToolStripItemToStripCallback(AddToolStripItemToStrip); - this.Invoke(atsitsc, new object[] { menulist, additionitems }); - return; - - } - - menulist.DropDownItems.AddRange(additionitems); - /* - // Do not sort IOS menu (alphabetization fail) - if (menulist.Text == IOSMenuList.Text) - { - menulist.DropDownItems.Add(additionitem); - return; - } - - if (menulist.DropDownItems.Count < 1) - { - menulist.DropDownItems.Add(additionitem); - return; - } - - // Sorting of items by name 18 chars in... - //try - //{ - for (int a = 0; a < menulist.DropDownItems.Count; a++) - { - if (menulist.DropDownItems[a].Text - .Substring(18, menulist.DropDownItems[a].Text.Length - 19) - .CompareTo(additionitem.Text.Substring(18, additionitem.Text.Length - 19)) == 1) - { - menulist.DropDownItems.Insert((a), additionitem); - return; - } - - - } - //} - - //catch (Exception) - //{ - //Debug.WriteLine("Tryfail at : " + additionitem.Text); - //menulist.DropDownItems.Add(additionitem); - //}*/ - - //menulist.DropDownItems.Add(additionitem); - } - - /// - /// Mods WAD names to be official. - /// - /// The titlename. - 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 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(); - }*/ - - public void DatabaseItem_Clicked(object sender, ToolStripItemClickedEventArgs e) - { - Regex IdandTitle = new Regex(@"[0-9A-Z]*\s-\s.*"); - Regex RegionEntry = new Regex(@"[0-9A-Z][0-9A-Z] \(.*\)"); - Regex VersionEntry = new Regex(@"v[0-9]*.*"); - - object[] wiiMenuLists = new object[] { - SystemMenuList, IOSMenuList, WiiWareMenuList, VCMenuList - }; - object[] dsiMenuLists = new object[] { - dsiSystemToolStripMenu, dSiWareToolStripMenu - }; - - // This item is a Titleid - Descname entry - if (IdandTitle.IsMatch(e.ClickedItem.Text)) - { - string text = e.ClickedItem.Text.Replace(" - ", "~"); - string[] values = text.Split('~'); - titleidbox.Text = values[0]; - statusbox.Text = String.Format(" --- {0} ---", values[1]); - titleversion.Text = String.Empty; - - if ((e.ClickedItem.Image) == (Database.orange) || (e.ClickedItem.Image) == (Database.redorange)) - { - WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); - packbox.Checked = false; - decryptbox.Checked = false; - } - - // Check for danger item - if ((e.ClickedItem.Image) == (Database.redgreen) || (e.ClickedItem.Image) == (Database.redorange)) - WriteStatus("\n" + e.ClickedItem.ToolTipText); - - // Set server selection - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in wiiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.Name) - serverLbl.Text = "Wii"; - } - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in dsiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.Name) - serverLbl.Text = "DSi"; - } - } - - // Region ClickedItem - if (RegionEntry.IsMatch(e.ClickedItem.Text)) - { - string text = e.ClickedItem.OwnerItem.Text.Replace(" - ", "~"); - string[] values = text.Split('~'); - titleidbox.Text = values[0]; - statusbox.Text = String.Format(" --- {0} ---", values[1]); - titleversion.Text = String.Empty; - - // Put 'XX' into title ID - titleidbox.Text = titleidbox.Text.Replace("XX", e.ClickedItem.Text.Substring(0, 2)); - - if ((e.ClickedItem.OwnerItem.Image) == (Database.orange) || (e.ClickedItem.OwnerItem.Image) == (Database.redorange)) - { - WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); - packbox.Checked = false; - decryptbox.Checked = false; - } - - // Check for danger item - if ((e.ClickedItem.OwnerItem.Image) == (Database.redgreen) || (e.ClickedItem.OwnerItem.Image) == (Database.redorange)) - WriteStatus("\n" + e.ClickedItem.OwnerItem.ToolTipText); - - // Set server selection - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in wiiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) - serverLbl.Text = "Wii"; - } - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in dsiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) - serverLbl.Text = "DSi"; - } - } - - // Version ClickedItem - if (VersionEntry.IsMatch(e.ClickedItem.Text) || e.ClickedItem.Text == "Latest Version") - { - if (RegionEntry.IsMatch(e.ClickedItem.OwnerItem.Text)) - { - string text = e.ClickedItem.OwnerItem.OwnerItem.Text.Replace(" - ", "~"); - string[] values = text.Split('~'); - titleidbox.Text = values[0]; - statusbox.Text = String.Format(" --- {0} ---", values[1]); - - // Put 'XX' into title ID - titleidbox.Text = titleidbox.Text.Replace("XX", e.ClickedItem.OwnerItem.Text.Substring(0, 2)); - } - else - { - string text = e.ClickedItem.OwnerItem.Text.Replace(" - ", "~"); - string[] values = text.Split('~'); - titleidbox.Text = values[0]; - statusbox.Text = String.Format(" --- {0} ---", values[1]); - } - - // Set version - if (e.ClickedItem.Text == "Latest Version") - titleversion.Text = String.Empty; - else - { - string[] version = e.ClickedItem.Text.Replace("v", "").Split(' '); - titleversion.Text = version[0]; - } - - if (RegionEntry.IsMatch(e.ClickedItem.OwnerItem.Text)) - { - if ((e.ClickedItem.OwnerItem.OwnerItem.Image) == (Database.orange) || (e.ClickedItem.OwnerItem.OwnerItem.Image) == (Database.redorange)) - { - WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); - packbox.Checked = false; - decryptbox.Checked = false; - } - - // Check for danger item - if ((e.ClickedItem.OwnerItem.OwnerItem.Image) == (Database.redgreen) || (e.ClickedItem.OwnerItem.OwnerItem.Image) == (Database.redorange)) - WriteStatus("\n" + e.ClickedItem.OwnerItem.OwnerItem.ToolTipText); - - // Set server selection - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in wiiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.OwnerItem.OwnerItem.Name) - serverLbl.Text = "Wii"; - } - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in dsiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.OwnerItem.OwnerItem.Name) - serverLbl.Text = "DSi"; - } - } - else - { - if ((e.ClickedItem.OwnerItem.Image) == (Database.orange) || (e.ClickedItem.OwnerItem.Image) == (Database.redorange)) - { - WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); - packbox.Checked = false; - decryptbox.Checked = false; - } - - // Check for danger item - if ((e.ClickedItem.OwnerItem.Image) == (Database.redgreen) || (e.ClickedItem.OwnerItem.Image) == (Database.redorange)) - WriteStatus("\n" + e.ClickedItem.OwnerItem.ToolTipText); - - // Set server selection - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in wiiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) - serverLbl.Text = "Wii"; - } - foreach (System.Windows.Forms.ToolStripMenuItem tsmi in dsiMenuLists) - { - if (tsmi.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) - serverLbl.Text = "DSi"; - } - } - } - } - - /// - /// Gathers the region based on index - /// - /// The index. - /// XmlDocument with database inside - /// Region desc - private string RegionFromIndex(int index, XmlDocument databasexml) - { - /* Typical Region XML - * - 41 (All/System) - 44 (German) - 45 (USA/NTSC) - 46 (French) - 4A (Japan) - 4B (Korea) - 4C (Japanese Import to Europe/Australia/PAL) - 4D (American Import to Europe/Australia/PAL) - 4E (Japanese Import to USA/NTSC) - 50 (Europe/PAL) - 51 (Korea w/ Japanese Language) - 54 (Korea w/ English Language) - 58 (Some Homebrew) - - */ - - 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)"; - } - - /// - /// Loads the region codes. - /// - private void LoadRegionCodes() - { - // TODO: make this check InvokeRequired... - if (this.InvokeRequired) - { - BootChecksCallback bcc = new BootChecksCallback(LoadRegionCodes); - this.Invoke(bcc); - return; - } - - wiiRegionCodesMenu.DropDownItems.Clear(); - dsiRegionCodesMenu.DropDownItems.Clear(); - - Database databaseObj = new Database(); - databaseObj.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "database.xml")); - - ToolStripMenuItem[] regionItems = databaseObj.LoadRegionCodes(); - - // For each child node (region node) - for (int z = 0; z < regionItems.Length; z++) - { - wiiRegionCodesMenu.DropDownItems.Add(regionItems[z].Text); - } - - Database dsiDatabaseObj = new Database(); - dsiDatabaseObj.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "dsidatabase.xml")); - - ToolStripMenuItem[] dsiRegionItems = dsiDatabaseObj.LoadRegionCodes(); - - // For each child node (region node) - for (int z = 0; z < dsiRegionItems.Length; z++) - { - dsiRegionCodesMenu.DropDownItems.Add(dsiRegionItems[z].Text); - } - } - - /// - /// Removes the illegal characters. - /// - /// removes the illegal chars - /// legal string - 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 = ""; - } - - /// - /// Makes everything disabled/enabled. - /// - /// if set to true [enabled]. - 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... - if (enabled) - { // we're enabling things that were enabled BEFORE: - downloadstartbtn.Enabled = disabledStorage[0]; - titleidbox.Enabled = disabledStorage[1]; - titleversion.Enabled = disabledStorage[2]; - Extrasbtn.Enabled = disabledStorage[3]; - databaseButton.Enabled = disabledStorage[4]; - packbox.Enabled = disabledStorage[5]; - localuse.Enabled = disabledStorage[6]; - saveaswadbtn.Enabled = disabledStorage[7]; - decryptbox.Enabled = disabledStorage[8]; - keepenccontents.Enabled = disabledStorage[9]; - scriptsbutton.Enabled = disabledStorage[10]; - serverLbl.Enabled = disabledStorage[11]; - iosPatchCheckbox.Enabled = disabledStorage[12]; - } - else - { - disabledStorage[0] = downloadstartbtn.Enabled; - disabledStorage[1] = titleidbox.Enabled; - disabledStorage[2] = titleversion.Enabled; - disabledStorage[3] = Extrasbtn.Enabled; - disabledStorage[4] = databaseButton.Enabled; - disabledStorage[5] = packbox.Enabled; - disabledStorage[6] = localuse.Enabled; - disabledStorage[7] = saveaswadbtn.Enabled; - disabledStorage[8] = decryptbox.Enabled; - disabledStorage[9] = keepenccontents.Enabled; - disabledStorage[10] = scriptsbutton.Enabled; - disabledStorage[11] = serverLbl.Enabled; - disabledStorage[12] = iosPatchCheckbox.Enabled; - - 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; - serverLbl.Enabled = enabled; - iosPatchCheckbox.Enabled = enabled; - } - } - - /// - /// Makes tooltips disappear in the database, as many contain danger tag info. - /// - /// if set to true [enabled]. - 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. - } - } - foreach (ToolStripItem item in scriptsStrip.Items) - { - try - { - ToolStripMenuItem menuitem = (ToolStripMenuItem)item; - menuitem.DropDown.ShowItemToolTips = false; - } - catch (Exception) - { - // Do nothing, some objects will not cast. - } - } - } - - /// - /// Updates the name of the packed WAD in the textbox. - /// - private void UpdatePackedName() - { - // Change WAD name if applicable - - string title_name = null; - - if ((titleidbox.Enabled == 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); - } - - /// - /// Determines whether OS is win7. - /// - /// - /// true if OS = win7; otherwise, false. - /// - 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; - } - - 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; - } - - /// - /// Retrieves the new database file. - /// - /// Database as a String - private void RetrieveNewDatabase(object sender, DoWorkEventArgs e) - { - // Retrieve Wiibrew/DSiBrew database page source code - WebClient databasedl = new WebClient(); - - // Proxy - //databasedl = ConfigureWithProxy(databasedl); - - string databaseSource = - databasedl.DownloadString(e.Argument.ToString() + "?cachesmash=" + - System.DateTime.Now.ToString()); - - // Strip out HTML - databaseSource = Regex.Replace(databaseSource, @"<(.|\n)*?>", ""); - - // Shrink to fix only the database - string startofdatabase = "<database v"; - string endofdatabase = "</database>"; - databaseSource = databaseSource.Substring(databaseSource.IndexOf(startofdatabase), - databaseSource.Length - databaseSource.IndexOf(startofdatabase)); - databaseSource = databaseSource.Substring(0, databaseSource.IndexOf(endofdatabase) + endofdatabase.Length); - - // Fix ", <, >, and spaces - databaseSource = databaseSource.Replace("<", "<"); - databaseSource = databaseSource.Replace(">", ">"); - databaseSource = databaseSource.Replace(""", '"'.ToString()); - databaseSource = databaseSource.Replace(" ", " "); // Shouldn't occur, but they happen... - - // Return parsed xml database... - e.Result = databaseSource; - } - - private void RetrieveNewDatabase_Completed(object sender, RunWorkerCompletedEventArgs e) - { - string database = e.Result.ToString(); - - string databaseFilename = ""; - if (database.Contains("DSISYSTEM")) - { - databaseFilename = "dsidatabase.xml"; - } - else if (database.Contains("0000000100000002")) - { - databaseFilename = "database.xml"; - } - - try - { - Database db = new Database(); - db.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, databaseFilename)); - string currentversion = db.GetDatabaseVersion(); - string onlineversion = Database.GetDatabaseVersion(database); - WriteStatus(String.Format(" - Database successfully parsed! ({0})", databaseFilename)); - WriteStatus(" - Current Database Version: " + currentversion); - WriteStatus(" - Online Database Version: " + onlineversion); - - if (currentversion == onlineversion) - { - WriteStatus(" - You have the latest database version!"); - return; - } - } - catch (FileNotFoundException) - { - WriteStatus(" - Database does not yet exist."); - WriteStatus(" - Online Database Version: " + Database.GetDatabaseVersion(database)); - } - - bool isCreation = false; - if (File.Exists(databaseFilename)) - { - WriteStatus(" - Overwriting your current database..."); - WriteStatus(String.Format(" - The old database will become 'old{0}' in case the new one is faulty.", databaseFilename)); - - string olddatabase = File.ReadAllText(databaseFilename); - File.WriteAllText("old" + databaseFilename, olddatabase); - File.Delete(databaseFilename); - File.WriteAllText(databaseFilename, database); - } - else - { - WriteStatus(String.Format(" - {0} has been created.", databaseFilename)); - File.WriteAllText(databaseFilename, database); - isCreation = true; - } - - // Load it up... - this.databaseWorker.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 databases from Wiibrew/DSibrew"); - - string[] wiibrewValues = new string[] { "http://www.wiibrew.org/wiki/NUS_Downloader/database", "http://www.dsibrew.org/wiki/NUS_Downloader/database" }; - - BackgroundWorker dbFetcher = new BackgroundWorker(); - dbFetcher.DoWork += new DoWorkEventHandler(RetrieveNewDatabase); - dbFetcher.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RetrieveNewDatabase_Completed); - dbFetcher.RunWorkerAsync(wiibrewValues[0]); - - BackgroundWorker dbDsiFetcher = new BackgroundWorker(); - dbDsiFetcher.DoWork += new DoWorkEventHandler(RetrieveNewDatabase); - dbDsiFetcher.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RetrieveNewDatabase_Completed); - dbDsiFetcher.RunWorkerAsync(wiibrewValues[1]); - } - - private void loadInfoFromTMDToolStripMenuItem_Click(object sender, EventArgs e) - { - // Extras menu -> Load TMD... - LoadTitleFromTMD(); - } - - /// - /// Sends the SOAP request to NUS. - /// - /// The Request - /// - public string SendSOAPRequest(string soap_xml) - { - System.Net.HttpWebRequest req = - (System.Net.HttpWebRequest) - System.Net.HttpWebRequest.Create("http://nus.shop.wii.com/nus/services/NetUpdateSOAP"); - - req.Method = "POST"; - req.UserAgent = "wii libnup/1.0"; - req.Headers.Add("SOAPAction", '"' + "urn:nus.wsapi.broadon.com/GetSystemUpdate" + '"'); - - // 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; - } - - UTF8Encoding encoding = new UTF8Encoding(); - byte[] bytes = encoding.GetBytes(soap_xml); - - req.ContentType = "text/xml; charset=utf-8"; - req.ContentLength = bytes.Length; - - Stream writeStream = req.GetRequestStream(); - 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(); - WriteStatus(" --- An Error Occurred: " + ex.Message.ToString()); - return null; // Ugh. - //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 = "4362227774"; - string messageID = "13198105123219138"; - string attr = "2";*/ - string deviceID = "4362227770"; - string messageID = "13198105123219038"; - string attr = "1"; - - 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] RegionID: USA, Country: US; - RegionID: JPN, Country: JP; - RegionID: EUR, Country: EU; - RegionID: KOR, Country: KO; */ - - string soap_req = "\n" + - "\n" + - "\n" + - "\n" + - "1.0\n" + - "" + messageID + "\n" + - "" + deviceID + "\n" + - "" + RegionID + "\n" + - "" + CountryCode + "\n" + - "\n" + - "0000000100000001\n" + - "2\n"+ - "\n" + - "\n" + - "0000000100000002\n" + - "33\n"+ - "\n" + - "\n" + - "0000000100000009\n" + - "516\n" + - "\n" + - "" + attr + "\n" + - "\n" + - "\n" + - "\n" + - ""; - - 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)); - WriteStatus(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... - } - - /// - /// Looks for a title's name by TitleID in Database. - /// - /// The titleid. - /// Existing name; else null - 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) - { - string script_content = File.ReadAllText(ofd.FileName); - FileInfo script_file = new FileInfo(ofd.FileName); - script_content += String.Format(";{0}", script_file.Name.Replace("." + script_file.Extension, "")); - BackgroundWorker scripter = new BackgroundWorker(); - scripter.DoWork += new DoWorkEventHandler(RunScriptBg); - scripter.RunWorkerAsync(script_content); - } - } - - /// - /// Runs a NUS script (BG). - /// - /// The sender. - /// The instance containing the event data. - private void RunScriptBg(object sender, System.ComponentModel.DoWorkEventArgs e) - { - char ArgsSplitChar = ';'; - string[] scriptArgs = e.Argument.ToString().Split(ArgsSplitChar); - - if (scriptArgs.Length < 2) - RunScript(scriptArgs[0], "random"); - else - { - RunScript(scriptArgs[0], RemoveIllegalCharacters(scriptArgs[1])); - } - /* - 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(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.Text = "Showing"; - scriptsStrip.Show(scriptsbutton, 2, (2+scriptsbutton.Height)); - - //if (!e.Equals(EventArgs.Empty)) - { - System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); - timer.Interval = 51; - timer.Tick += new EventHandler(contextmenusTimer_Tick); - timer.Start(); - } - } - - private void DatabaseEnabled(bool enabled) - { - for (int a = 0; a < databaseStrip.Items.Count; a++) - { - databaseStrip.Items[a].Enabled = enabled; - databaseStrip.Items[a].Visible = enabled; - } - - for (int b = 0; b < VCMenuList.DropDownItems.Count; b++) - { - VCMenuList.DropDownItems[b].Enabled = true; - VCMenuList.DropDownItems[b].Visible = true; - } - } - - 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); - if (version.StartsWith("SVN")) - WriteStatus("SVN BUILD: DO NOT REPORT BROKEN FEATURES!"); - - WriteStatus("This application created by WB3000"); - WriteStatus("Various contributions by lukegb"); - WriteStatus(String.Empty); - - if (NUSDFileExists("key.bin") == true) - WriteStatus("Wii Decryption: Local (key.bin)"); - - - if (NUSDFileExists("kkey.bin") == true) - WriteStatus("Wii Korea Decryption: Local (kkey.bin)"); - - - if (NUSDFileExists("dsikey.bin") == true) - WriteStatus("DSi Decryption: Local (dsikey.bin)"); - - if (NUSDFileExists("database.xml") == false) - WriteStatus("Database (Wii): Need (database.xml)"); - else - WriteStatus("Database (Wii): OK"); - - if (NUSDFileExists("dsidatabase.xml") == false) - WriteStatus("Database (DSi): Need (dsidatabase.xml)"); - else - WriteStatus("Database (DSi): 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/#WiiDev for advice."); - WriteStatus(" * Pasta for impressive database contributions."); - WriteStatus(" * Napo7 for testing proxy settings."); - WriteStatus(" * Wyatt O'Day for the Windows7ProgressBar Control."); - WriteStatus(" * Famfamfam for the Silk Icon Set."); - WriteStatus(" * Anyone who has 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))); - string script_content = File.ReadAllText(folderpath); - script_content += String.Format(";{0}", tsmi.Text.Replace(".nus", "")); - BackgroundWorker scripter = new BackgroundWorker(); - scripter.DoWork += new DoWorkEventHandler(RunScriptBg); - scripter.RunWorkerAsync(script_content); - } - - 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; - } - } - - private void iosPatchGroupBoxOKbtn_Click(object sender, EventArgs e) - { - SetAllEnabled(true); - iosPatchGroupBox.Visible = false; - if (iosPatchesListBox.CheckedIndices.Count == 0) - // Uncheck the checkbox to indicate no patches - iosPatchCheckbox.Checked = false; - } - - private void FillDatabaseScripts() - { - SetPropertyThreadSafe(scriptsDatabaseToolStripMenuItem, false, "Visible"); - Database databaseObj = new Database(); - databaseObj.LoadDatabaseToStream(Path.Combine(CURRENT_DIR, "database.xml")); - - ToolStripMenuItem[] scriptItems = databaseObj.LoadScripts(); - for (int a = 0; a < scriptItems.Length; a++) - { - scriptItems[a].Click += new EventHandler(ScriptItem_Clicked); - - //AddToolStripItemToStrip(scriptsDatabaseToolStripMenuItem, scriptItems[a]); - //SystemMenuList.DropDownItems.Add(systemItems[a]); - } - AddToolStripItemToStrip(scriptsDatabaseToolStripMenuItem, scriptItems); - SetPropertyThreadSafe(scriptsDatabaseToolStripMenuItem, true, "Enabled"); - SetPropertyThreadSafe(scriptsDatabaseToolStripMenuItem, true, "Visible"); - } - - public void ScriptItem_Clicked(object sender, EventArgs e) - { - // Scripts from database are stored in tooltips... - ToolStripMenuItem tsmi = (ToolStripMenuItem)sender; - string script_content = tsmi.ToolTipText; - script_content += String.Format(";{0}", tsmi.Text); - - BackgroundWorker scripter = new BackgroundWorker(); - scripter.DoWork += new DoWorkEventHandler(RunScriptBg); - scripter.RunWorkerAsync(script_content); - } - - void ReorganizePreviousFolderStructure(object sender, DoWorkEventArgs e) - { - // 0000000000000000v000\* become titles\0000000000000000\v000\* - Regex TitleDirectoryRegex = new Regex(@"[a-zA-Z0-9]{16}v?([0-9]*)?"); - - if (Directory.Exists(Path.Combine(CURRENT_DIR, "titles")) == false) - Directory.CreateDirectory(Path.Combine(CURRENT_DIR, "titles")); - - string[] directories = Directory.GetDirectories(CURRENT_DIR, "*", SearchOption.TopDirectoryOnly); - Debug.WriteLine("Dirs: " + directories.Length); - foreach (string directory in directories) - { - Debug.WriteLine("ff: " + directory); - DirectoryInfo dinfo = new DirectoryInfo(directory); - - // name is XXXXXXXXXXXXXXXXvYYYY - if (TitleDirectoryRegex.IsMatch(dinfo.Name.ToString()) && dinfo.Name.Contains("v")) - { - string[] title_info = dinfo.Name.Split('v'); - string titleid_dir = Path.Combine(Path.Combine(CURRENT_DIR, "titles"), title_info[0]); - string newfull_dir = Path.Combine(titleid_dir, String.Format("{0}", title_info[1])); - - if (Directory.Exists(titleid_dir) == false) - Directory.CreateDirectory(titleid_dir); - - if (Directory.Exists(newfull_dir) == false) - Directory.CreateDirectory(newfull_dir); - - string[] files = Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly); - foreach (string file in files) - { - FileInfo titlefile = new FileInfo(file); - if (File.Exists(Path.Combine(newfull_dir, titlefile.Name)) == false) - titlefile.MoveTo(Path.Combine(newfull_dir, titlefile.Name)); - } - - if (dinfo.GetFiles().Length <= 0 && dinfo.GetDirectories().Length <= 0) - Directory.Delete(directory); - - - } - else if (TitleDirectoryRegex.IsMatch(dinfo.Name.ToString())) - { - string titleid_dir = Path.Combine(Path.Combine(CURRENT_DIR, "titles"), dinfo.Name.ToString()); - - libWiiSharp.TMD tmdfile = new libWiiSharp.TMD(); - int count = 0; - - string[] tmdfiles = Directory.GetFiles(directory, "*tmd*", SearchOption.TopDirectoryOnly); - if (tmdfiles.Length > 1) - continue; //Too many TMD files ? - - foreach (string file in tmdfiles) - { - if (file.Contains("tmd")) - { - tmdfile.LoadFile(file); - count++; - } - } - if (count == 0) - continue; - - string version = tmdfile.TitleVersion.ToString(); - string newfull_dir = Path.Combine(titleid_dir, String.Format("{0}", version)); - - if (Directory.Exists(titleid_dir) == false) - Directory.CreateDirectory(titleid_dir); - - if (Directory.Exists(newfull_dir) == false) - Directory.CreateDirectory(newfull_dir); - - string[] files = Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly); - foreach (string file in files) - { - FileInfo titlefile = new FileInfo(file); - if (File.Exists(Path.Combine(newfull_dir, titlefile.Name)) == false) - titlefile.MoveTo(Path.Combine(newfull_dir, titlefile.Name)); - } - - if (dinfo.GetFiles().Length <= 0 && dinfo.GetDirectories().Length <= 0) - Directory.Delete(directory); - - } - } - - } - - void ReorganizePreviousFolderStructure_Completed(object sender, RunWorkerCompletedEventArgs e) - { - WriteStatus(" - Operation complete!"); - } - - private void RunScript(string scriptstr, string scriptname) - { - // Form and folder stuffs - SetTextThreadSafe(statusbox, ""); - WriteStatus("Starting script download. Please be patient!"); - string scriptdir; - if (scriptname == "random") - scriptdir = Path.Combine(Path.Combine(CURRENT_DIR, "scripts"), RandomString(7) + "_output"); - else - scriptdir = Path.Combine(Path.Combine(CURRENT_DIR, "scripts"), scriptname + "_output"); - - if (!File.Exists(scriptdir)) - Directory.CreateDirectory(scriptdir); - - // Parse entries - string[] NUS_Entries = scriptstr.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); - - WriteStatus(String.Format(" - Script loaded ({0} Titles)", NUS_Entries.Length)); - WriteStatus(" - Output: " + scriptdir.Replace(CURRENT_DIR, "")); - - 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])) - continue; - - // 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(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(), scriptdir, wadName, storeTypes); - - } - WriteStatus("Script completed!"); - } - - // Random string function for temp foldernames in RunScript. - // Probably going to be removed TODO - private readonly Random _rng = new Random(); - private const string _chars = "abcdefghijklmnopqrstuvwxyz"; - - private string RandomString(int size) - { - char[] buffer = new char[size]; - - for (int i = 0; i < size; i++) - { - buffer[i] = _chars[_rng.Next(_chars.Length)]; - } - return new string(buffer); - - } - - void Form1_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e) - { - //Debug.WriteLine("Delta: " + e.Delta.ToString()); - - if (SystemMenuList.DropDown.DisplayRectangle.Contains(e.Location) || - SystemMenuList.DropDown.Bounds.Contains(e.Location) || - WiiWareMenuList.DropDown.DisplayRectangle.Contains(e.Location) || - WiiWareMenuList.DropDown.Bounds.Contains(e.Location) || - VCMenuList.DropDown.DisplayRectangle.Contains(e.Location) || - VCMenuList.DropDown.Bounds.Contains(e.Location) || - IOSMenuList.DropDown.DisplayRectangle.Contains(e.Location) || - IOSMenuList.DropDown.Bounds.Contains(e.Location)) - { - if (e.Delta > 0) - { - System.Windows.Forms.SendKeys.Send("{UP}"); - System.Windows.Forms.SendKeys.Send("{UP}"); - System.Windows.Forms.SendKeys.Send("{UP}"); - System.Windows.Forms.SendKeys.Send("{UP}"); - System.Windows.Forms.SendKeys.Send("{UP}"); - } - else - { - System.Windows.Forms.SendKeys.Send("{DOWN}"); - System.Windows.Forms.SendKeys.Send("{DOWN}"); - System.Windows.Forms.SendKeys.Send("{DOWN}"); - System.Windows.Forms.SendKeys.Send("{DOWN}"); - System.Windows.Forms.SendKeys.Send("{DOWN}"); - } - - } - } - - private void openNUSDDirectoryToolStripMenuItem_Click(object sender, EventArgs e) - { - // Opens the directory NUSD is working in... (CURREND_DIR) - Process.Start(CURRENT_DIR); - } - - private void mainPageToolStripMenuItem_Click(object sender, EventArgs e) - { - Process.Start("http://www.wiibrew.org/wiki/NUS_Downloader"); - } - - private void databasePageToolStripMenuItem_Click(object sender, EventArgs e) - { - Process.Start("http://www.wiibrew.org/wiki/NUS_Downloader/database"); - } - - private void extrasStrip_Opening(object sender, CancelEventArgs e) - { - // Show additional features based on held keys... - #if DEBUG - moreExtrasToolStripMenuItem.Visible = true; - #else - moreExtrasToolStripMenuItem.Visible = Control.ModifierKeys == Keys.Control; // If Ctrl Pressed. - #endif - } - - private void runFolderFixToolStripMenuItem_Click(object sender, EventArgs e) - { - // Run folderfix to make \titles\ - // Organizing folders from past NUSD releases... - BackgroundWorker folder_fixer = new BackgroundWorker(); - folder_fixer.DoWork += new DoWorkEventHandler(ReorganizePreviousFolderStructure); - folder_fixer.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ReorganizePreviousFolderStructure_Completed); - Debug.WriteLine("folderfix active"); - WriteStatus("Organizing your old folder structure..."); - folder_fixer.RunWorkerAsync(); - } - - private void removeNUSDFilesFoldersToolStripMenuItem_Click(object sender, EventArgs e) - { - // Extras thing, remove all of NUSD files... - if (MessageBox.Show("This will delete all the files\folders you have downloaded from NUS! Are you sure you want to do this?", "Wait a second!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != System.Windows.Forms.DialogResult.Yes) - return; - - if (Directory.Exists(Path.Combine(CURRENT_DIR, "titles"))) - Directory.Delete(Path.Combine(CURRENT_DIR, "titles"), true); - if (Directory.Exists(Path.Combine(CURRENT_DIR, "scripts"))) - Directory.Delete(Path.Combine(CURRENT_DIR, "scripts"), true); - - if (File.Exists(Path.Combine(CURRENT_DIR, "database.xml"))) - File.Delete(Path.Combine(CURRENT_DIR, "database.xml")); - if (File.Exists(Path.Combine(CURRENT_DIR, "dsidatabase.xml"))) - File.Delete(Path.Combine(CURRENT_DIR, "dsidatabase.xml")); - if (File.Exists(Path.Combine(CURRENT_DIR, "olddatabase.xml"))) - File.Delete(Path.Combine(CURRENT_DIR, "olddatabase.xml")); - - if (File.Exists(Path.Combine(CURRENT_DIR, "proxy.txt"))) - File.Delete(Path.Combine(CURRENT_DIR, "proxy.txt")); - - if (File.Exists(Path.Combine(CURRENT_DIR, "key.bin"))) - File.Delete(Path.Combine(CURRENT_DIR, "key.bin")); - if (File.Exists(Path.Combine(CURRENT_DIR, "kkey.bin"))) - File.Delete(Path.Combine(CURRENT_DIR, "kkey.bin")); - if (File.Exists(Path.Combine(CURRENT_DIR, "dsikey.bin"))) - File.Delete(Path.Combine(CURRENT_DIR, "dsikey.bin")); - } - - private void anyStrip_Closed(object sender, ToolStripDropDownClosedEventArgs e) - { - ((ContextMenuStrip)sender).Text = "Hidden"; - //Debug.Write(((ContextMenuStrip)sender).Name); - } - - private void localTicketInventoryToolStripMenuItem_Click(object sender, EventArgs e) - { - // Alters icons if tickets exist locally... - WriteStatus("Adding ticket information to database entries..."); - ToolStripMenuItem[] Lists = new ToolStripMenuItem[6] { SystemMenuList, IOSMenuList, VCMenuList, WiiWareMenuList, dsiSystemToolStripMenu, dSiWareToolStripMenu }; - - for (int l = 0; l < Lists.Length; l++) - { - for (int a = 0; a < Lists[l].DropDownItems.Count; a++) - { - if (Lists[l].DropDownItems[a].Text.Length < 16) - continue; - - string itemTitleId = Lists[l].DropDownItems[a].Text.Substring(0, 16); - string itemDir = Path.Combine(Path.Combine(CURRENT_DIR, "titles"), itemTitleId); - - if (Directory.Exists(itemDir) == false) - continue; - - string[] files = Directory.GetFiles(itemDir, "cetk", SearchOption.AllDirectories); - if (files.Length > 0) - { - if (Lists[l].DropDownItems[a].Image == Database.green) - Lists[l].DropDownItems[a].Image = Database.green_blue; - if (Lists[l].DropDownItems[a].Image == Database.orange) - Lists[l].DropDownItems[a].Image = Database.orange_blue; - if (Lists[l].DropDownItems[a].Image == Database.redorange) - Lists[l].DropDownItems[a].Image = Database.redorange_blue; - if (Lists[l].DropDownItems[a].Image == Database.redgreen) - Lists[l].DropDownItems[a].Image = Database.redgreen_blue; - } - } - } - WriteStatus(" - Operation completed!"); - } - - private void donateToolStripMenuItem_Click(object sender, EventArgs e) - { - //TODO: Organize how this will work... - Process.Start("http://wb3000.atspace.name/donations.html"); - } - - private void DSiDatabaseWork(object sender, System.ComponentModel.DoWorkEventArgs e) - { - while (databaseWorker.IsBusy) - { - Thread.Sleep(1000); - } - BackgroundWorker worker = sender as BackgroundWorker; - FillDSiDatabaseStrip(worker); - LoadRegionCodes(); - //FillDatabaseScripts(); - ShowInnerToolTips(false); - } - - private void DSiDatabaseWork_Completed(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) - { - this.databaseButton.Text = "Database..."; - this.databaseButton.Image = null; - } - - private void DSiDatabaseWork_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) - { - if (e.ProgressPercentage == 50) - databaseButton.Text = " [. ]"; - else if (e.ProgressPercentage == 100) - databaseButton.Text = " [..]"; - } - - private void wiiRegionCodesMenu_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) - { - if (titleidbox.Text.Length == 16) - titleidbox.Text = titleidbox.Text.Substring(0, 14) + e.ClickedItem.Text.Substring(0, 2); - } - - private void dsiRegionCodesMenu_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) - { - if (titleidbox.Text.Length == 16) - titleidbox.Text = titleidbox.Text.Substring(0, 14) + e.ClickedItem.Text.Substring(0, 2); - } - - private void serverLbl_MouseEnter(object sender, EventArgs e) - { - serverLbl.Font = new Font(serverLbl.Font, FontStyle.Underline); - } - - private void serverLbl_MouseLeave(object sender, EventArgs e) - { - serverLbl.Font = new Font(serverLbl.Font, FontStyle.Regular); - } - - private void serverLbl_TextChanged(object sender, EventArgs e) - { - if (serverLbl.Text == "Wii") - { - // Can pack WADs / Decrypt - packbox.Enabled = true; - } - if (serverLbl.Text == "DSi") - { - // Cannot Pack WADs - packbox.Checked = false; - packbox.Enabled = false; - wadnamebox.Enabled = false; - wadnamebox.Text = ""; - } - } - - private void serverLbl_Click(object sender, EventArgs e) - { - // Switch what server is displayed in the label, when clicked. - string[] serverLblServers = new string[2] { "Wii", "DSi" }; - - for (int a = 0; a < serverLblServers.Length; a++) - { - if (serverLbl.Text == serverLblServers[a]) - { - if (serverLblServers.Length == (a + 1)) - serverLbl.Text = serverLblServers[0]; - else - serverLbl.Text = serverLblServers[a+1]; - break; - } - } - } - } -} \ No newline at end of file diff --git a/NUS Downloader/Form1.resx b/NUS Downloader/Form1.resx deleted file mode 100644 index af6baad..0000000 --- a/NUS Downloader/Form1.resx +++ /dev/null @@ -1,2080 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - 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 - 71CQAAAAAElFTkSuQmCC - - - - - AAABAAYAEBAAAAAAIABoBAAAZgAAABgYAAAAACAAiAkAAM4EAAAgIAAAAAAgAKgQAABWDgAAMDAAAAAA - IACoJQAA/h4AAEBAAAAAACAAKEIAAKZEAACAgAAAAAAgACgIAQDOhgAAKAAAABAAAAAgAAAAAQAgAAAA - AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFyBS0NxlopDc5aKRnSWikh2mIpEdJaKRHOWikRz - lopEc5aKRHOWikNxlookT3MqAAAAAAAAAAAAAAAAAAAAAF2axZ96tdv/h8Hj/4jC5P+Kw+X/i8Tl/4vE - 5f+MxeX/i8Pl/4a/4f96t93/U464aAAAAAAAAAAAAAAAAAAAAABknsmpeLXd/3Ow2f9zsdn/c7HZ/3Ox - 2f9zsdn/c7HZ/3Sx2f9xr9j/fLng/1uXv3gAAAAAAAAAAAAAAAAAAAAAYp/Ks3Cv2/9oqNb/aKnW/2ip - 1v9qqtb/aqrW/2qr1v9pqtb/ZqfV/3W03v9gm8SHAAAAAAAAAAAAAAAAAAAAAGKfyr5lptT/XJ3N/1yd - zv9bnc3/WpzN/1qczf9anM3/WpzN/1ibzP9vr9z/ZKDHlgAAAAAAAAAAAAAAAAAAAAFhnsnIV5jJ/0OI - u/9Eibz/RIm8/0OJvP9Eibz/RIm8/0OIvP9Chrr/ZabU/2SgyKYAAAAAAAAAAAAAAAAAAAABa6bO0Wys - 2f9vsNv/b7Hd/3Cx3f9xsN3/cbHd/22u3P9ur93/bKzZ/2yt2/9rpMy0AAAAAAAAAAAAAAAAAAAAAIS5 - 2rFViKr/SXqa/01+nP9Ofpz/Z5Oj/1mGnP9QgJ3/T3+d/0x9nP9jl7n/hLjYlwAAAAAAAAAAAAAAAAAA - AABuqMtYXZO1/zhvk/83bpH/SIqR/63qyf+W2bv/OniN/zdvkv83bpL/a6HD/2WewToAAAAAAAAAAAAA - AAAAAAAAKlVqDHGnyfJclbL/RaWU/1nikP966aX/cuif/0nYif9MmqD/WpKw/3yy0doAAAACAAAAAAAA - AAAAAAAAAAAAAAAAAABdi6pCM6l01zHYb/9G4YD/WeWN/1Djh/8q3W//Ec1e/zuYebBpocIuAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAI5A8g2fSg/9s2oz/Zt6N/2bhkP9m4I//ZtyL/27YjP9OxW79D3AiRAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqZUlplsnOpUblq1obbm/+G3Z3/ht2d/4LZl/9KsGO+Za9xqSuC - MS8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAESkUoal3a3/pd6u/6Xdrv+g2qn/AHsVPgAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSoFaGxeTH/8Xkx//F5Mf/v+HA/wBv - BD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKgAGaapptZ7HnvGex57xnsee8Ya4 - hssAYAAYAAAAAAAAAAAAAAAAAAAAAAAAAADgBwAAwAcAAMAHAADAAwAAwAMAAMADAADAAwAAwAMAAOAH - AADgBwAA8A8AAOAPAADwDwAA+D8AAPg/AAD4PwAAKAAAABgAAAAwAAAAAQAgAAAAAAAAEgAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwjOhYiQFdMJkJVUSZCVVEmQlVRKUVYUSlFWFEpQlhRJkJYUSZC - WFEmQlhRJkJYUSZCWFEmQlhRJkJVUSZCWFEhPlI+ACBACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdn - i09cmsfuaKLJ8W6nzfFvqc/xcqvQ8XOr0PF1rdHxc6vQ8XKr0PFzrNHxc6vQ8XKr0PFyqtDxbaXJ8Wij - zfFWkLzNNGmOIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER7oGFwrtj/gLre/4jB4/+IweT/iMHk/4jC - 5P+JwuT/icLk/4nC5P+JwuT/icLk/4nC5P+JwuT/hL7h/4O+4f9mpc3lSXmeKgAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAE6CqGx3td//eLTd/3i13v94tt7/eLbe/3i23v94tt7/eLbe/3i23v94tt7/eLbe/3m2 - 3v94tt7/dLPc/4O+4v9sq9XuR3WZMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFOKsHh0tN//b67Y/2uq - 1v9rq9f/a6vX/2ur1/9sq9f/bq3X/26s1/9urNf/bq3X/22s1/9sq9f/aKjV/3674f9rq9b2SXaWOAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFmOtYNusN3/a6nV/2Wl0f9mptH/ZqbR/2am0f9mptL/Z6bS/2em - 0v9nptL/Z6bS/2am0f9mptH/Y6PQ/3q34P9srNr9SXWSPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCV - upBoq9r/Y6TU/2Ci0/9fotT/YKLU/16i0/9dodP/XKDT/1yh0v9codL/XKHS/1yh0v9codL/WZ7R/3Oy - 3f9tr93/THqVTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGYvJpkp9j/W5rK/1CTxP9Rk8X/UZPF/1GT - xf9Qk8X/UJPF/1CSxP9QksT/UJLE/1CSxP9Qk8T/TpDC/2+u2v9prNr/V4WlXgAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAWadwaVcoNH/To6//z6Dtf8/g7X/P4O1/z+Dtf8/g7X/QIS3/0GEt/9Bhbf/QIS3/0CE - t/8/g7b/PIC0/2ip1f9hpNL/Xo6sbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmmgw69dotX/XKDR/1+k - 1f9hptj/YabY/2Km2P9iptj/YqbY/2Om2f9jptj/YqbY/2On2f9kp9n/X6HR/2Gk1/9ipdf/apu5fwAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAniszKp+tdn/dqvM/3eryv98sM7/frHP/3+yz/+Ass//fa7K/4Cx - zP9+sc//e7DP/3uvz/96r8//eK3N/3qy1P9/uNv/dqnFfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWo - x2R0qsz/OW+U/zBlh/8xZoj/MmeI/zJmiP8xZIH/eaSo/09+jv8xY4P/M2eI/zJniP8yZ4j/MWWH/0J6 - ov96r8/5cKK9QgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGeeuiV6sNHjQnme/zNqjv8zao7/M2qO/zJs - h/9vq6T/uu/S/67kyv9LiJH/MWmJ/zNqjv8zao7/MmmN/0uFqv+BtNTKbJ26GgAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAEl/pA55r9KpWI+w/0Z/oP9Gf6D/Q4OY/1a3l/+H56//ne6+/5XtuP9z2qT/SJ2V/0V+ - nf9Gf6D/RX2e/22jw/1+stWMKn9/BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFmoMpueKvH+Gae - uf9anqr/OcWE/0bggv9i5pT/cuif/23nm/9V5Iv/Ndp8/0Cwkf9hmrT/Ypm1/4q72O5fmcROAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYk8Qad63Ndlmhn7wwxHj6Idpp/zngef9P44f/WeWO/1Dj - iP824Hj/FNtj/wvSXf84toPpaqOyn3q12GgqaqoMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAGAGIYaxyqSuRH0nP/VduA/1bfhv9a4ov/XeSO/1zjjf9W4Yj/S9x9/zrUbf8iw1j7BY8xvQA5 - BTEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwATPrFY037Vk/+F25v/bNmL/2zc - jv9s3pD/bOCS/2zgkv9s3o//a9qM/3fakv+B2Jb/a8yC/heKMYMAAAABAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAJwANW6djvnS7guJzv4XjUMRv+oHbmP+B3Zr/gd2b/4Hdmv+B3Jn/e9iS/0+7 - bO50vYTidLiA4jSHOHEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGnsaHSWD - LCkfayQyQrBY15bbpP+W3KX/lt2m/5bdpf+W3KT/j9id/waLIn8lgywpJXwlKQBqAAwAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKTK1Zz6rdsP+q3rH/qt6y/6re - sf+q3bH/odmo/wB8FGcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAKVqtaz77hwP++4cH/vuLB/77iwf++4cD/tdy3/wByBWcAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJWKRZzrrZ - uv+62bv/utm7/7rZu/+62br/sdSx/wNoA2QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAUTphOvXStdN10rXTddK103XStdN10rXTdZqVmwgZh - BioAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wDwAA8A8AAPAPAADwDwAA8A4AAPAOAA - DwDgAA8A4AAPAOAADwDgAA8A8AAPAPAADwDwAA8A+AAfAPwAPwD8AD8A+AAfAPgAPwD/Af8A/wH/AP8B - /wD/Af8A/wH/ACgAAAAgAAAAQAAAAAEAIAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAABwAAACoAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMwAA - ADMAAAAzAAAAMwAAADMAAAAzAAAAMwAAADMAAAAzAAAAMgAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAANIi8mQHut11OMuOFSi7bhU4y44VOOuOFVj7jhW5K64VuRuuFYkbrhV5C54VSO - ueFUjrnhVI654VSOueFVjrnhVY654VWOueFVjrnhVIy24VWPueFPibXhLWCLjQAAAAUAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAACNOcDtpq9n/cLDa/4G62/+FvuH/iMLk/4jC5P+IwuT/iMLl/5DH - 5/+Pxub/jsbm/47G5v+Oxub/ksno/43G5v+Nxeb/jcXm/4vE5v+Budn/fbng/3Sz3P9TkL7BAAAACAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKVZ0RG2u2/90r9T/g7zg/4jB4/+IweP/iMHj/4jB - 4/+IweP/iMHj/4jB4/+IweP/iMHj/4jB4/+IweP/iMHj/4jB4/+IweP/iMHj/4S+4f+JwuT/b63S/1ua - xcwAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1YIRNdLPe/3u44P95td7/e7jg/3u5 - 4P97ueD/e7ng/3u54P97ueD/e7ng/3u54P97ueD/e7ng/3u54P97ueD/e7ng/3u54P97ueD/drXe/4bA - 4/92td7/YZ/K2QAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEN0l1htrtz/frvh/26q - 0/9rp9H/bKjR/2yo0f9sqNH/bKjR/2yo0f9sqNH/bKjR/2yo0f9sqNH/bKjR/2yo0f9tqdL/banS/2yo - 0f9opdD/g77i/3Gx3P9mpc/mAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS3qcYmyt - 3P96uOD/bKzZ/2ut2/9rrdz/a63c/2ut3P9rrdz/bK3c/26w3f9wsd3/cLDd/2+w3f9wsd3/cLHd/26v - 3P9tr9z/a63c/2iq2f+AvOL/ba7a/2mp1PEAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AABVhKVsaKva/3Oz3v9ppdL/ZKPP/2Wkz/9lpM//ZaTP/2Wkz/9lpM//ZaTP/2Wkz/9lpM//ZaTP/2Wk - z/9lpM//ZaTP/2Wkz/9lpM//YqHN/3y44P9srdv/ba3Z+wAAABoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAV2NrXlkqNj/ba7c/2Kj1P9ipdb/YaXW/2Gl1/9ipdf/YKTW/2Ck1v9eo9b/XaLV/12j - 1f9do9X/XaPV/12j1f9do9X/XaPV/12j1f9an9P/drTd/2ut3P9wsd3/HCkwJQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAABYZKwgWOn2P9oqtj/XpvI/1eVw/9XlcT/V5XE/1eVxP9XlcT/V5XE/1eV - xP9XlcT/V5XE/1eVxP9XlcT/V5XE/1eVxP9XlcT/V5XE/1STwv9yr9r/aKva/2+w3P81UmU1AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJllrSLYKXY/2Sn1/9Tk8b/SpDE/0uRxf9LkcX/S5HF/0uR - xv9Lkcb/SpHF/0qQxf9Jj8P/SY/D/0mPw/9Jj8P/SY/D/0qQxP9KkMT/R4zB/3Gv2v9iptf/bK7b/05v - gUUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmydvJVantH/XZ/O/0mIuf88gLL/PYCy/z2A - sv89gLL/PYCy/z2Asv89gLL/PoK0/z+Ctf9Ag7X/P4K1/z+Ctf8+grX/PoC0/z2As/86fbH/aqrW/1ia - x/9oq9r/XIGTUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADbZ++nVmg1f9UmtH/VJnM/1ed - 0f9ZoNX/WaDV/1mg1f9aoNX/WqDV/1ug1f9boNX/XKHW/1yh1v9dodb/XaLW/16j1/9fo9f/X6PX/1ia - y/9boNT/WZ3S/2Km2P9tlKZiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARyo8CmerXc/4W/ - 4/+EvuH/hcDi/4bB4/+GweP/hsHk/4fB5P+HweT/h8Hk/4bA4/+GwOP/hsDj/3y64f99u+L/fbvi/327 - 4v9+u+L/fbnf/3+84/99uuH/crDZ/2+Yr3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXut - yo2JweP/b6C//2eWtf9olbH/cZ+5/3Whuv92orv/eKO7/3iju/96pLv/dJuv/3mhtf98pbz/e6W8/3ql - vP95pLz/eKS8/3SivP9yoLr/dKbE/4Cwzf+OxeX/d6S+WgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAW4mkOI/G5/9Viq7/KGCH/yVbfv8lW37/JVt+/yVbfv8lW37/JFl7/yNXcP+MtbL/T36K/yBS - c/8lWn7/JVt+/yVbfv8lW37/JVt+/yRZfP8uaZT/ap29/4a/4O8qOUcSAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAHfbbZ1neqyf80bJL/MWiM/zFojP8xaIz/MWiM/y5khv8wan//oNXC/8P0 - 2P/B8db/WJWX/ytff/8vZon/MWiM/zFojP8xaIz/MGaK/zt2nv+Ju9f/c6rMogAAAAIAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhnMODibza/0J7n/8/d5n/P3eZ/z53mP88c5T/O3+N/4bb - sv+h78D/r/DK/6bvxP+X7br/V6ma/zpykv89dZb/P3eZ/z93mf89dZf/U42v/5TH5v9RhapFAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADFhhiqEvN/+WpCu/06Hp/9Oh6f/Toem/0iT - mP9j3Jr/ceie/4bqrf+Q7LT/iuuw/3joo/9m5pn/TraV/0yHo/9Oh6b/Toen/0yEpP9/sMv/dbHW3wAA - AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmSizsuCscr/a6K8/2ui - vP9No5n/Mdh6/zzge/9V44v/ZuaX/27nnP9q5pn/W+SP/0TigP8s33X/N72G/2Gdsv9on7v/Zp24/5LC - 3f9ZlsCKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXJfHQIK6 - 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 - AB4AAAAeAAAAHgAAAB4AAAAeAAAAHgAAAB4AAAAdAAAAEgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChIvQUcdQF+DHUBdjB1AXYwdQF2MHUBdjB1A - XYwdQF2MHUBdjB1AXYwdQF2MHUBdjB1AXYwdQF2MHUBdjB1AXYwdQF2MHUBdjB1AXYwdQF2MHUBdjB1A - XYwdQF2MHUBdjB1AXYwdQF2MHUBdjB1AXYwdQF2MHUBdjB1AXYweQV+JFTNLXwAAABYAAAABAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBgkFTJrn51Xlsj0aafS9mmn - 0vZlpM32aafQ9mmn0vZpqNL2aqjS9nGt0/Z1r9T2dK7U9nOu1PZxrdT2ca3U9m2q0/ZrqNL2a6jS9mup - 0vZrqdL2a6nS9mup0vZsqdL2bKnS9myp0vZsqdL2banS9m2p0vZppc72banS9m2q0vZfncv1P3+21xg6 - VzUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEy9MG06N - urNsq9j/ba3Y/3q53/9tp8n/eLTY/3684f9/vOL/f7zi/3+84v9/vOL/f7zi/4S/4/+Oxub/isLk/4rC - 5P+JwuT/icLk/4nC5P+Jw+T/j8fn/4zF5v+HwuT/hsLk/4bB5P+GweT/hcDk/4G94/9pocH/f7zi/3Ox - 2v9zsdv/XaDP6idVeEgAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAGjVGHVGPurZzs93/bqvS/4S94f+Rx+X/lMnn/5XJ5/+Vyuf/lcrn/5XK5/+Vyuf/lcrn/5XK - 5/+Vyuf/lcrn/5XK5/+Vyuf/lcrn/5XK5/+Vyuf/lcrn/5XK5/+Vyuf/lcrn/5XK5/+Vyuf/lcrn/5bK - 5/+Tyeb/j8bl/3Ox2f91s9n/ZKXT7S9ehFEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAHjxSIlaSwL5ystz/aKXK/4S+4v94td3/f7zg/4C84f+AveH/gLzh/4C8 - 4f+AveH/gLzh/4C84f+AveH/gLzh/4C84f+AveH/gLzh/4C84f+AveH/gLzh/4C84f+AveH/gLzh/4C8 - 4f+AveH/gLzh/4C84f95tt7/k8nn/3Sz2f9wrdL/aqvW7zhqklsAAAADAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI0BcJFmWwsJ8uN//drXe/4G84f9ysdz/ebjf/3q4 - 4P96uOD/erjg/3q44P96uOD/erjg/3q44P96uOD/erjg/3q44P96uOD/erjg/3q44P96uOD/erjg/3q4 - 4P96uOD/erjg/3q44P96uOD/erjg/3q44P9zstz/kcjn/3e23/94tt//bKvV8j1wlmQAAAAFAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkZZKFyYxcd0tN//e7jg/3+5 - 3/9sp9D/cavS/3Ks0/9yrNP/cqzT/3Ks0/9yrNP/cqzT/3Ks0/9yrNP/cqzT/3Ks0/9yrNP/cqzT/3Ks - 0/9yrNP/cqzT/3Ks0/9yrNP/cqzT/3Ks0/9yrNP/cqzT/3Ks0/9rp9D/j8bl/3W03v9zs93/bq7Y9UR4 - n3AAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALktiLGCd - yM5ur9z/fbrh/3y43/9oqNb/bq3Z/2+u2f9vrtn/b67Z/2+u2f9vrtn/b67Z/2+u2f9vrtn/b67Z/2+u - 2f9vrtn/b67Z/2+u2f9vrtn/b67Z/2+u2f9vrtn/cK/a/3Ox2v9xr9r/b67Z/2+u2f9pqNb/jMXl/3Oz - 3f9ur9r/cK/Z+E2CqHsAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAK0xiL2GdyNJtrtz/erjg/3q23/9mp9f/bK3b/2yu3P9srtz/bK7c/2yu3P9srtz/bK7c/2yu - 3P9urtz/cbLe/3Ky3v92td//dbTf/3Ky3f9zs97/dbTf/3S03/90tN//cbHd/3Gx3f9usNz/bK7c/2yu - 3P9mqdj/isPl/3Ky3f9qq9j/bq7Z+lKHq4IAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAANVJqNWWjzttrrdv/drbf/3m13v9qqNT/bqzX/2+t1/9vrdf/b63X/2+t - 1/9vrdf/b63X/2+t1/9vrdf/b63X/2+t1/9vrdf/b63X/2+t1/9vrdf/b63X/2+t1/9vrdf/b63X/2+t - 1/9vrdf/b63X/2+t1/9qqNT/iMHk/2+w3f9qq9n/ba7c/FaMso4AAAALAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABM1NrN2Wkzt1mqdj/ba/c/3Sx2/9Ymcr/WpzM/1ud - zf9bnc3/W53N/1udzf9bnc3/W53N/1udzf9bnc3/W53N/1udzf9bnc3/W53N/1udzf9bnc3/W53N/1ud - zf9bnc3/W53N/1udzf9bnc3/W53N/1udzf9XmMn/hb7j/22u3P9srdv/bK3a/16TuJgAAAANAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABO1htPWin0eZjptf/aavb/3Ox - 3P9bn9P/YqbX/2Wo2P9kqNj/ZajY/2eq2f9mqdn/ZKfY/2Km1/9iptf/YaXX/1+k1/9fpNf/X6TX/1+k - 1/9fpNf/X6TX/1+k1/9fpNf/X6TX/1+k1/9fpNf/X6TX/1+k1/9antP/gr3h/2mr2v9srtz/bq/d/2GW - up4AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACO1pqQWin - 0upkqNj/Y6bW/3Cv2v9Vmc7/W57R/1md0f9YndH/WJ3R/1id0f9YndH/WJ3R/1id0f9YndH/WJ3R/1id - 0f9YndH/WJ3R/1id0f9YndH/WJ3R/1id0f9YndH/WJ3R/1id0f9YndH/WJ3R/1id0f9TmM3/f7rf/2ap - 2P9qrNv/bK7b/2ScvqoXLjoWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAACO1xvRWqp1PBiptj/X6PU/2+s1v9Xkb3/V5K9/1iSvf9Xkr3/V5K9/1iSvf9Xkr3/V5K9/1iS - vf9Xkr3/V5K9/1iSvf9Xkr3/V5K9/1iSvf9Xkr3/V5K9/1iSvf9Xkr3/V5K9/1iSvf9Xkr3/V5K9/1iS - vf9Uj7v/fLfc/2Sn2P9oqtr/aqzb/2mgw7QkQEkcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAADP15wSWur1vVhptj/XaHU/2qp1v9JjML/SpDE/0uRxf9LkcX/S5HF/0uR - xf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9KkcX/SpDF/0qQxf9KkMX/SpDF/0qQxf9KkMX/SpDF/0qQ - xf9KkcX/SpHF/0qQxf9Hi8H/erXc/2Om1/9lqdj/aKva/2igw7swSFAgAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADP11wTW2t2fheotb/XKDT/2Wk0v9Dhrv/RIm9/0aM - v/9Gi77/RYy+/0aMv/9Gi77/Rou//0aLv/9Fi7//RYu//0aMv/9GjMD/Rou//0eMwP9GjMD/RYu//0aM - wP9GjMD/RovA/0WLv/9Gi7//Roq//0SJvv9AhLr/d7LZ/1+j1f9iptb/ZqrZ/2ukx8Q2UF4mAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEP15xUW6u2/9VmMn/UZHA/2Gg - zf87e67/OXyu/zp8rv86fK7/Onyu/zp8rv86fK7/Onyu/zp8rv86fK7/Onyu/zp8rv87fK//O32v/zt9 - r/87fa//O3yv/zt9r/87fa//O32v/zp8r/86fK//Onyv/zp8rv82d6z/banR/1aYxv9Ym8n/ZKfZ/22m - zMxBWWUrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFQWJ0Vm6v - 3P9aodX/WJ7T/1Wa0f9YndH/WJ7S/1if1P9Yn9T/WJ/U/1if1P9Yn9T/Wp/U/1mf1P9Zn9X/Wp/V/1ug - 1f9boNX/XaLW/12i1v9dotb/XaLW/16j1/9eo9f/X6PX/1+j1/9fpNf/YKTX/1+i1v9doNP/XKDU/1ic - 0f9eotb/YaXY/22nzdNFYGowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAHVXqOZmus2f9Rl87/UpjP/1ie0/9Pk8T/VZrN/1mh1f9ZodX/WaHV/1qh1f9aodX/WqHV/1qh - 1f9bodb/W6HW/1uh1f9aoNX/WqDV/1qg1f9aoNX/WqDV/1qg1f9aoNX/W6HW/1uh1v9codb/XKHW/1md - 0P9Ulsb/XqLW/1qf1P9VmdD/V5vR/3Gr0t1KZnQ3AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAGWH2TaIe+3v+f0uv/o9bt/6PW7f+j1uz/o9bt/6TX7f+k1+3/pNft/6TX - 7f+k1+7/pdfu/6XX7v+l1+7/pdfu/6XX7v+k1+3/pNbt/6TW7f+k1+3/ls3q/5PL6f+Vzer/lc3q/5XN - 6v+Vzer/ls3q/5XN6v+Vzen/ls7r/5fO6/+WzOr/i8Tk/3yx0uRIZ3k5AAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZY6jVoW+4v2Gv+L/lsPc/5TA2/+Vv9f/mMHY/5rE - 2v+ex9z/oMfc/6LI3f+jyd3/pcrd/6XL3v+nzN//qc3f/6jN3v+kyNj/qszc/6zP3/+rz+D/q8/g/6rO - 4P+pzt//qM3f/6fN3/+lzOD/n8rf/57I3/+cx93/nMjg/5rH4P+dyuT/i8Pj/4i9299ef5AuAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUXqRLIe+3duTyOf/UYWo/yhj - jv8gVHn/IFV5/yNYe/8qXoD/K1+A/ytfgP8rX4D/K1+A/ytfgP8rX4D/KFt8/yZYcv86bHn/JVdt/yZY - d/8qXn//K1+A/ytfgP8rX4D/K1+A/ytfgP8rX4D/K1+A/ytfgP8pXH7/MmyV/zJslP93p8T/j8Xl/4S5 - 1q5Mc38UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPFppEXiu - 0KWVy+j/eKnG/zBrlv8nXIH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/J12B/yddgP8jV3j/IlVw/2yf - nv/O5t//mcC9/yhccv8hU3P/JVt//yddgf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8lWn7/MGyW/zRv - mf+Ww9z/hr/g93aox3IAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAA2ecu2qNw+T1j7/a/z54n/8uZIn/L2aK/y9miv8vZor/L2aK/y9miv8vZor/LmWI/ypf - gP8rYnv/YqKb/8rz3f/C9Nf/xvPa/4vAtf8xan7/KFt7/yxihf8vZon/L2aK/y9miv8vZor/L2aK/y9m - iv8sYob/OHOb/1WLrv+UxuL/frjb5VKCmjUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEp1lTB2s9nikMTi/1qQsf83bpH/OHCT/zhwk/84cJP/OHCT/zhv - kv82bY//M2mK/zV1hv9ut6X/svHN/7fyz/+88tP/tvLP/67wyv+Ax7D/On2J/zJoiP80a4z/N2+R/zhw - k/84cJP/OHCT/zhwk/82a47/Qn6j/26iwf+RxuX/bajOswAVFQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXFwtmo8uygrve/3Glw/8/eJr/QXqb/0F6 - m/9Bepv/QHqb/z93mP8+dpb/PX2R/2jBof+Q6rb/me26/6Xvw/+r8Mf/pe/D/5jtuf+M67L/f9aw/z+L - kP89dZX/PnaW/0B5mf9Bepv/QXqb/0F6m/8+dpf/T4qs/4K00v+Lw+X/SHuiVQAAAAMAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM/dZ1Zerbd/4Cy - z/9Lg6P/S4Sk/0uEpP9LhKT/S4Sj/0qEov9Hipr/VseS/3XppP956aP/h+uu/5Hstf+W7bj/key1/4fr - rv946KP/a+ec/2PUnv9HlZn/SYSh/0qEo/9LhKP/S4Sk/0uEpP9If5//YJm4/5TE4P9vrdXgAAAAEQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAALFSoYZ6bS4Ia41v9bka7/V5Ct/1eQrf9XkK3/VpCs/0ubmv9FyYn/UuSN/1bkjP9n5pj/dOig/3zp - pv9/6qj/fOmm/3PooP9n5pf/VuSM/0rjh/9F04r/RqGV/1SQqf9XkK3/V5Ct/1eQrf9Ti6j/eazH/5HE - 5P9SjLaFAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAHSYi7koq+3v96rcX/dqvD/3Wrw/91q8P/VKSc/y/Lev8l3XD/Mt91/0Th - gP9T44r/X+WS/2bmlv9o55j/ZeaX/1/kkf9T44r/ROGA/zHfdf8e3mv/JtR4/0eulv9spb3/cafC/3Cn - wv9to7//mMPb/3ez2u5BcJM7AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARIKsMXWy2sqMxOTbi8Hf4YO81O9gu6z+Gspp/w3Z - Yf8Q22L/Jd1t/zbgd/9E4n//TuOG/1Pjiv9V5Iv/UeOJ/0rihP8+4Hz/Lt9z/xvdaP8G2l3/AddZ/xTQ - af9SvqP/grzS8om/3eOMwuPciMHi2W+r05g2a5QTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATdtfw4qQ08qFTArXwt/ - QMALwlv7JtRn/zbZcf883Xf/QuF9/0zihP9V44r/XOWP/1/lkf9f5ZH/W+WO/1Ljif9G4oH/M+B2/xzc - aP8I11v/ANJS/wHOUP8FyFj/DZNQ1RRCLHQqOUkxUXSLFlV/fwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA - ABkAAwBRAHEdyAW7Tfs0zmf/Ttd5/0/ZfP9P3H//T9+C/1Dhhf9T4oj/VuSL/1rljf9b5Y7/WuSN/1fj - i/9T44j/T+GE/0vfgP9G23v/NdVs/xPMVf8BxkX/AL9H/gCPNNYAIAVnAAAAIQAAAAUAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAACQAkA04AdBfSCr1N/zzJY/9a0nv/W9Z//1vYgv9b24T/W92G/1vfiP9b4Yr/W+KL/1vi - i/9b4oz/W+KM/1vii/9b4Yr/W9+I/1vdh/9b24T/W9iB/1rWfv9Fzm3/GsJM/wa5Q/8AhSLiACwFaAAA - ABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAA8AEQB7HJkTsUL9S8Zo/2XQf/9m0oL/ZtWF/2bYh/9m2on/ZtyL/2bd - jP9m343/Zt+P/2bgj/9m4ZD/ZuCP/2bgj/9m3o7/Zt6M/2bci/9m2on/ZtiH/2bVhf9m04L/Y899/0fE - Zf8bt0f/AIwh0QAVACUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAFC6WQaWK1Jf/pd+x/6bhsv+m4rT/peO1/4Lc - mv9s14r/ctuQ/3Lckf9y3ZL/ct6T/3LelP9y35T/ct6U/3Lek/9y3ZL/ctyR/3Lbj/9u2Iz/b9eL/6Pj - s/+m4rT/puGy/6XfsP+b2qb/Oa5Q4gApACwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAED6MRqCBwYv/i8mX/4vK - mf+LzJv/i86c/1vHe/9i0YD/e9mV/3vblv973Jf/e92Y/3vdmP973Zj/e92Y/3vdmP973Jf/e9uW/3va - lf9w1Yr/PcNk/4vOnf+LzJv/i8qZ/4vJl/+LxpX/RZtM4AAqACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMABSZ/ - K2pGmk7NSp1V0kqgV9JKoVjSSqNb0yqkR+pmzH//htma/4bbm/+G3Jz/htyd/4bdnf+G3Z7/ht2d/4bc - nf+G3Jz/htub/4bZmv961Y//GqxA8kihWtVKoVjSSqBW0kqdVdJKnFPRKoUunwA3AA4AAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAABmAAodfycaJoQmGyR/LhwmhC8bHGMjJAOCG5VsyX/8kdmg/5Hbof+R26L/kdyi/5Hc - o/+R3aP/kdyi/5Hcov+R26H/kduh/5HaoP+E1JT/AJslvxdRHSwkfy4cJoQvGyR/LhwmhCYbAHAAEAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQB9FYdzyIP8mtqm/5rb - p/+a3Kj/mtyo/5rdqP+a3an/mt2p/5rcqP+a3Kj/mtun/5rapv+N1Jn/AJMftwAAABIAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQB5 - EYd6yIb8pNut/6Tcrf+k3a7/pN2u/6Tdrv+k3a7/pN2u/6Tdrv+k3a7/pNyt/6TbrP+W1Z//AI8ZtwAA - ABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAACQB1C4eByIr8rt2z/67ds/+u3bT/rt20/67etf+u3rX/rt60/67etP+u3bT/rt2z/67d - s/+e1qT/AIoStwAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAACQBzCIeJyI78t966/7ffu/+337v/t+C7/7fgu/+34Lv/t+C7/7fg - u/+337v/t9+7/7feuv+n16r/AIQLtwAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQBvAoeRyJL8weHB/8Hhwv/B4cL/weLD/8Hi - w//B4sP/weLD/8Hiw//B4cL/weHC/8Hhwv+w2LH/AH8DtwAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQBsAIeezp782OvY/9jr - 2P/Y69j/2OzY/9js2f/Y7Nn/2OzZ/9js2P/Y7Nj/2OvY/9jr2P/B38H/AHwAtwAAABIAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACARn - BIWVxZX8xN7E/8TexP/E3sT/xN7E/8TexP/E3sT/xN7E/8TexP/E3sT/xN7E/8TexP+q0ar/A3ADtQAA - AA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAwxrDG5OmE73XZ9d/12fXf9dn13/XZ9d/12fXf9dn13/XZ9d/12fXf9dn13/XZ9d/12f - Xf9anlr/C24LngAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQVnBS8whDBwOIc4dziIOHY4iDh2OIc4dziIOHY4iDh2OIc4dziI - OHY4iDh2OIc4dziIOHYugy5vAGUAKwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////AAD/AAAAAf8AAP4AAAAA/wAA/gAAAAD/ - AAD+AAAAAP8AAP4AAAAA/wAA/gAAAAD/AAD+AAAAAP8AAP4AAAAA/wAA/gAAAAB/AAD+AAAAAH8AAP4A - AAAAfwAA/gAAAAB/AAD+AAAAAH8AAP4AAAAAfwAA/gAAAAB/AAD+AAAAAH8AAP4AAAAAfwAA/gAAAAB/ - AAD+AAAAAH8AAP4AAAAAfwAA/gAAAAB/AAD+AAAAAH8AAP4AAAAA/wAA/wAAAAD/AAD/AAAAAP8AAP8A - AAAB/wAA/4AAAAH/AAD/gAAAAf8AAP+AAAAD/wAA/8AAAAP/AAD/+AAAP/8AAP/wAAAf/wAA/+AAAA// - AAD/wAAAB/8AAP/AAAAH/wAA/8AAAAf/AAD/4AAAB/8AAP//AAH//wAA//8AAf//AAD//wAB//8AAP// - AAH//wAA//8AAf//AAD//wAB//8AAP//AAH//wAA//8AAf//AAD//4AB//8AAP///////wAAKAAAAEAA - AACAAAAAAQAgAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAQAAAANAAAAEwAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAA - ABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAA - ABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAA - ABMAAAANAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAXAAAAOQAAAE8AAABTAAAAUwAAAFMAAABTAAAAUwAA - AFMAAABTAAAAUwAAAFMAAABTAAAAUwAAAFMAAABTAAAAUwAAAFMAAABTAAAAUwAAAFMAAABTAAAAUwAA - AFMAAABTAAAAUwAAAFMAAABTAAAAUwAAAFMAAABTAAAAUwAAAFMAAABTAAAAUwAAAFMAAABTAAAAUwAA - AFMAAABTAAAAUwAAAFMAAABPAAAAOQAAABgAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICg8PMiJQdpwqXYfAKluFwypb - hcMqW4XDKluFwypbhcMqW4XDKluFwypbhcMqW4XDKluFwypbhcMqW4XDKluFwypbhcMqW4XDKluFwypb - hcMqW4XDKluFwypbhcMqW4XDKluFwypbhcMqW4XDKluFwypbhcMqW4XDKluFwypbhcMqW4XDKluFwypb - hcMqW4XDKluFwypbhcMqW4XDKluFwypbhcMqW4XDKl2HwCFKcJsAAAAzAAAACQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACxU3 - U1NAhcP/ZKXV/3Oz3v9zs97/c7Pe/2+v2P9ystz/c7Pe/3Oz3v9ztN7/c7Te/3i33/+BvOH/gbzh/4C7 - 4f9/u+H/frrh/3y64f98uuH/erjg/3W03/91tN//dbTf/3W13/91td//dbXf/3W13/91td//drXf/3a1 - 3/92td//drXf/3a13/92td//d7Xf/3e13/93td//crDY/3e13/93tt//d7bf/2Ok0/9Gisb/IUxtZQAA - AA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAwnVXlpYKTW/2yq1/9pqdX/ebjf/3m43/9hm73/cK3S/3m43/96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/4bA4/+OxeX/h8Dj/4fA4/+HwOP/hsDj/4bA4/+GwOP/hsDj/4fB - 4/+Oxub/jsbm/4XA4/+EwOP/g8Dj/4O/4/+Dv+P/g7/j/4K+4/98uuH/fLrh/1qRsP98uuH/fLng/2qo - 1P9zsdr/YqbX/ytfhnwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANKll+bWGm1/94tt//c7Lc/22r1/+Uyuj/lcro/5XK - 6P+Vyuj/lcvo/5XL6P+Vy+j/lcvo/5XL6P+Vy+j/lsvp/5bL6f+Wy+n/lsvp/5bL6f+Wy+n/lsvp/5bL - 6f+Wy+n/lsvp/5bL6f+Wy+n/lsvp/5bL6f+Wy+n/lsvp/5bL6f+Wy+n/lsvp/5bL6f+Wy+n/l8zp/5fM - 6f+XzOn/k8no/2up1f95t9//fLrh/2mr2v80Z5KIAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADytZe3BkqNj/dbTc/2Sg - w/+Fv+P/i8Hh/43D4v+TyOX/lMjl/5TI5f+UyOX/lMjl/5TI5f+UyOX/lMjl/5TI5f+UyOX/lMjl/5TI - 5f+UyOX/lMjl/5TI5f+UyOX/lMjl/5TI5f+UyOX/lMjl/5TI5f+UyOX/lMjl/5TI5f+UyOX/lMjl/5TI - 5f+UyOX/lMjl/5TI5f+UyOX/j8Xi/5fL5v96ueD/bqvQ/3Ct0v9qrdr/OHCakgAAABQAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - ABA3aZCBaKra/3Sz3P9joMX/hL7j/4K84f9xsNv/e7nf/3y64P98uuD/fLrg/3y64P98uuD/fLrg/3y6 - 4P98uuD/fLrg/3y64P98uuD/fLrg/3y64P98uuD/fLrg/3y64P98uuD/fLrg/3y64P98uuD/fLrg/3y6 - 4P98uuD/fLrg/3y64P98uuD/fLrg/3y64P98uuD/fLng/3Oy3P+YzOj/ebjf/3Ct0v9wrdL/cLHc/0N7 - p6AAAAAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAARPG2Xh2mr2v+Au+D/c7Pd/4K94v+Bu+D/b67b/3m33/95uN//ebjf/3m4 - 3/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m4 - 3/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/9xsNv/lsvo/3i3 - 3/93td7/eLff/3Gx3P9Hf6qpAAAAGgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEz1wlYlrrNv/frrh/3W03v+BvOL/gbrg/3Kw - 2/98uN//fbng/3254P99ueD/fbng/3254P99ueD/fbng/3254P99ueD/fbng/3254P99ueD/fbng/325 - 4P99ueD/fbng/3254P99ueD/fbng/3254P99ueD/fbng/3254P99ueD/fbng/3254P99ueD/fbng/325 - 4P99ueD/c7Lc/5TK5/93td7/c7Lc/3e13v9zs93/TYq3vAAAAB0AAAABAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRJfqiZa63b/2+w - 3f9/u+H/f7vi/3qy1v9fmcH/Zp7F/2efxf9nn8X/Z5/F/2efxf9nn8X/Z5/F/2efxf9nn8X/Z5/F/2ef - xf9nn8X/Z5/F/2efxf9nn8X/Z5/F/2efxf9nn8X/Z5/F/2efxf9nn8X/Z5/F/2efxf9nn8X/Z5/F/2ef - xf9nn8X/Z5/F/2efxf9nn8X/Z5/F/2Gbwv+Tyeb/dbTe/3Sz3f9wsNv/c7Pd/1KOu8MAAAAhAAAAAgAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAWUIetn2yt2/9ur9z/fbrg/3264f96td3/ZqjY/2+v3P9xsd3/cbHd/3Gx3f9xsd3/cbHd/3Gx - 3f9xsd3/cbHd/3Gx3f9xsd3/cbHd/3Gx3f9xsd3/cbHd/3Gx3f9xsd3/cbHd/3Gx3f9xsd3/cbHd/3Gx - 3f9xsd3/cbHd/3Gx3f91td7/dbTe/3Oy3f9xsd3/cbHd/3Gw3f9pqdn/kcjm/3Oz3f9zs93/ba3Z/3Sz - 3f9amMXUAAAAIwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAGFKFq6Jsrdv/ba7c/3q44P98ueD/eLTd/2Ol1v9srdv/ba7c/22u - 3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/2+v3P9zs97/c7Pe/3W03v95t9//eLbf/3Sz - 3v9zst3/drXf/3e23/92td//drXf/3a13/9yst3/crLd/3Ky3f9vsNz/ba7c/22u3P9trtz/ZqjX/4/G - 5v9yst3/crLd/2mq1/9yst3/XpzG2AAAACYAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABtak7u0bK3b/2yt2/93tt//e7jg/3ay - 3P9go9X/aava/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs - 2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs - 2/9qrNv/aqzb/2Kl1v+Oxeb/cLHd/3Cx3f9pqdf/cLHd/2ak0esAAAAqAAAABAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAcYZe/u2us - 2/9qrNv/c7Te/3m34P97tNr/bafP/3Ot0/90rtP/dK7T/3Su0/90rtP/dK7T/3Su0/90rtP/dK7T/3Su - 0/90rtP/dK7T/3Su0/90rtP/dK7T/3Su0/90rtP/dK7T/3Su0/90rtP/dK7T/3Su0/90rtP/dK7T/3Su - 0/90rtP/dK7T/3Su0/90rtP/dK7T/3Su0/9vqND/jMPk/2+v3f9vr93/aarY/26u3P9pp9PuAAAALQAA - AAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAACAAAAHmObvrxoq9r/ZajX/2ms2v94tt//banW/0+Rxv9VmMr/VpnL/1aZy/9Wmcv/VpnL/1aZ - y/9Wmcv/VpnL/1aZy/9Wmcv/VpnL/1aZy/9Wmcv/VpnL/1aZy/9Wmcv/VpnL/1aZy/9Wmcv/VpnL/1aZ - y/9Wmcv/VpnL/1aZy/9Wmcv/VpnL/1aZy/9Wmcv/VpnL/1aZy/9Wmcv/UZPG/4nB5P9srdv/ba7c/22t - 2/9rrNr/crLd/wAAADEAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAACFpo8bLZ6ra/2Kl1v9nqtr/d7Xf/3Cu2f9YnNL/YqbX/2ep - 2f9nqdn/ZqnZ/2ap2f9qrNr/aava/2iq2v9mqdn/Y6fY/2Wo2P9kp9j/YqbY/2Gl1/9gpdf/YKTX/2Cl - 1/9gpdf/YKXX/2Cl1/9gpdf/YKXX/2Cl1/9gpdf/YKXX/2Cl1/9gpdf/YKXX/2Cl1/9gpdf/YKXX/1qe - 0v+IweP/Z6nY/2yt2/9trtz/ba7c/3Oz3v8AAAA1AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAjbqjM1GWp2P9kp9f/YaXW/3W0 - 3v9tq9f/U5jO/2Gk1f9dodP/W6DT/1ug0/9boNP/W6DT/1ug0/9boNP/W6DT/1ug0/9boNP/W6DT/1ug - 0/9boNP/W6DT/1ug0/9boNP/W6DT/1ug0/9boNP/W6DT/1ug0/9boNP/W6DT/1ug0/9boNP/W6DT/1ug - 0/9boNP/W6DT/1ug0/9Vmc//hb/i/2Sm1v9qrNv/a6zb/2ut2/91tN7/M1BgUAAAAAoAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAJW6n - y9VkqNj/ZKjY/16h0/90tN3/aqjV/06Tyf9Vmc3/VprO/1aazv9Wms7/VprO/1aazv9Wms7/VprO/1aa - zv9Wms7/VprO/1aazv9Wms7/VprO/1aazv9Wms7/VprO/1aazv9Wms7/VprO/1aazv9Wms7/VprO/1aa - zv9Wms7/VprO/1aazv9Wms7/VprO/1aazv9Wms7/T5XK/4O84P9ipNX/aaza/2ms2v9prNr/dLTe/zFM - W1QAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAwAAACd2rtLiYqbY/2Km2P9bn9L/crLd/2ylzP9Ui7b/WJC5/1iQuf9YkLn/WJC5/1iQ - uf9YkLn/WJC5/1iQuf9YkLn/WJC5/1iQuf9YkLn/WJC5/1iQuf9YkLn/WJC5/1iQuf9YkLn/WJC5/1iQ - uf9YkLn/WJC5/1iQuf9YkLn/WJC5/1iQuf9YkLn/WJC5/1iQuf9YkLn/WJC5/1WNuP+But3/YaPV/2iq - 2v9oqtr/aKra/3a13v9Kb4RqAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAApd7HV62Cl1/9hptj/WZ7S/3Gx3f9koc//RYnA/0uQ - xP9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uR - xf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uR - xf9Hi8D/frfc/2ap2f9hpNX/ZqrZ/2aq2f9yst3/TXKGcAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAK3ex1etgpNf/YKTX/1ic - 0f9ur9v/YZ7M/0GFu/9IjcH/S5HE/06Txv9KkMT/SpHE/0ySxv9Lksb/S5DE/0yRxv9Mkcb/TJHG/0qR - xf9KkMX/SpDF/0mPxP9Jj8T/R4zB/0eMwf9HjMH/R4zB/0eMwf9HjMH/R4zB/0eMwf9HjMH/R4zB/0mP - w/9JjsP/SY7D/0iOw/9HjMH/Qoe9/3y12v9kqNj/XaHT/2Wp2P9lqdj/crLc/2CJoIQAAAARAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAA - AC6Bu9/3XqLW/12g1P9antH/aKnY/16ax/87frX/QIW4/0GGuP9Bhrj/QYa4/0GGuP9Bhrj/QYa4/0GG - uP9Bhrj/QYa4/0GGuP9Bhrj/QYa4/0GGuP9Firz/RIm8/0SJvP9IjL//SIy//0aLvv9Eibz/Rou+/0aL - vv9Gi77/RYq+/0SKvf9Dh7v/Q4e7/0OHu/9Chrr/QYa4/zx/tf95s9f/YqbY/1uezv9iptb/Y6fY/26w - 3P9ii5+KAAAAEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAUAAAAwf7vh/12h1v9SlMP/Som2/2mq2f9YlMD/NHSo/zh6rP85eqz/OXqs/zl6 - rP85eqz/OXqs/zl6rP85eqz/OXqs/zl6rP85eqz/OXqs/zl6rP85eqz/OXqs/zl6rP85eqz/OXqs/zl6 - rP85eqz/OXqs/zl6rP85eqz/OXqs/zl6rP85eqz/OXqs/zl6rP85eqz/OXqs/zl6rP80dan/bajO/2Gm - 2P9Iha7/Wp3L/2Km2P9srdv/cpuymgAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAM4G84v9bodX/W6HV/1uh1f9VmtH/VJnQ/1yh - 1v9an9T/V57T/1mf1P9YntT/WJ7U/1ie1P9YntT/WJ7U/1qf1P9ZntT/WZ7U/1me1P9ZntT/W6DU/1ug - 1P9boNX/XaLW/16i1v9eotb/XqLW/16i1v9fo9f/X6PX/1+j1/9fo9f/X6PX/2Ck1/9gpNf/YKTX/2Ck - 1/9gpNf/YKTX/12h1f9Tl83/XqLV/2Ck1/9gpNf/Z6rZ/3agtqIAAAAYAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCc2PkKBveL/WaDU/1ee - 0/9Mkcr/VZvR/1qh1f9IibX/UpbH/1qh1f9aodX/WqHV/1qh1f9bodX/W6HV/1uh1f9bodX/W6HV/1uh - 1f9codb/XKHW/1yh1v9boNX/W6DV/1ug1f9boNX/W6DV/1ug1f9boNX/W6DV/1ug1f9boNX/XaLW/12i - 1v9dotb/XqLW/16i1v9eotb/U5PD/0+Ou/9fo9b/X6PX/1GVzP9Wms//X6PX/2Om2P+Dsci1AAAAGwAA - AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAlFW2hOhsDj/0yRyv9Kj8n/V53T/1ie0/9YntP/U5jL/1ac0P9ZoNT/WaDU/1mg1P9ZoNT/WaDU/1mg - 1P9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqDU/1mf1P9Zn9T/WZ/U/1mf1P9ZoNT/WaDU/1mg - 1P9ZoNT/WqDV/1qg1f9an9X/Wp/V/1qf1f9boNX/W6DV/1md0P9YnM//XaHW/12h1v9dotb/VJjP/0yQ - yP9ipdf/ibbLvAAAAB4AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAHQVpnSnqx1f+h0+r/suHy/7Lh8v+y4fL/suHy/7Lh8v+y4fL/suHy/7Lh - 8v+z4fL/s+Hy/7Ph8v+z4fL/s+Hy/7Ph8v+z4fL/s+Hy/7Ph8v+z4fL/s+Hy/7Ph8v+z4fL/s+Hy/7Ph - 8v+z4fL/s+Hy/6PW7v+c0ez/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW - 7v+i1u//otbv/6LW7/+b0ev/gbja/3uryMkAAAAcAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEhmczyLxOX/fLfe/4W+4f+o0un/qtTq/6zU - 6/+u1uv/sdfr/7LZ7P+z2u7/tdvu/7bb7v+43O7/ud3v/7re7/+83+//vd/w/73g8P+/4fH/weLx/8Hj - 8v/C5PL/vuDu/8Tk8v/F5fL/xeXy/8Tk8v/E5PL/w+Ty/8Lj8v/B4/H/wOLx/77h8f+/4vL/vOHy/7be - 8f+03fH/s9zw/7Hb7/+w2u//rtnv/63X7v+m0+z/icHi/4nB4v+Iu9XIAAAAEwAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAXhbzd4JPJ - 5/+QxeX/RHqe/yZgjP8mYIz/HE5z/x5Sd/8eUnf/K1+A/zNmhv8zZob/M2aG/zNmhv8zZob/M2aG/zNm - hv8zZob/M2aG/zNmhv8yZIP/LFl0/yRQaf8pVm//MWOB/zNmhv8zZob/M2aG/zNmhv8zZob/M2aG/zNm - hv8zZob/M2aG/zNmhv8zZob/M2aG/zNmhv8yZIT/OnKY/zpymP86cpj/daTB/5XJ5/+Qx+f/eKfChgAA - AAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAC3Klw5GIweT/mczp/26du/8rZpH/K2aQ/yFUd/8jWHv/I1h7/yNYe/8jWHv/I1h7/yNY - e/8jWHv/I1h7/yNYe/8jWHv/I1h7/yNYe/8gU3X/Gkln/yNdav9Xj43/I1pq/xpIZf8eT3D/Ilh7/yNY - e/8jWHv/I1h7/yNYe/8jWHv/I1h7/yNYe/8jWHv/I1h7/yNYe/8jWHv/IVR3/ytmkf8rZpH/K2aR/5bB - 2f+JweL/jMTl/EBdbDQAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARHaoFBg7/j/5jN6f+LudP/Mm2Y/zFslf8mWn7/KF6C/yhe - gv8oXoL/KF6C/yhegv8oXoL/KF6C/yhegv8oXoL/KF6C/yhegf8jVXX/IFBu/zJxeP/H7Nv/7vv0/8no - 3f82b3r/IFBu/yFTcv8mXH//KF6C/yhegv8oXoL/KF6C/yhegv8oXoL/KF6C/yhegv8oXoL/KF6C/yZa - fv8xbZf/Mm2Y/zp1nf+u1+z/h8Di/32y08IAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAFHSu09GVyuj/ncrj/z95 - oP83cpr/K2CE/y5lif8uZYn/LmWJ/y5lif8uZYn/LmWJ/y5lif8uZYn/LmWJ/yxihP8oW3r/J1l4/zd/ - f//M8d//zfXe/8Dz1v/I9Nv/ye3c/zd9gP8nWXj/J1l4/ytfgf8uZYn/LmWJ/y5lif8uZYn/LmWJ/y5l - if8uZYn/LmWJ/y5lif8rYIT/N3Ka/zl0nP9rnbv/ns/p/4S+4f9cjqtxAAAABwAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAldkreGgbzh/6LS6/9glLP/Pnmf/zJniv81bI//NWyP/zVsj/81bI//NWyP/zVsj/81bI//NWyP/zFm - iP8uYoL/L2KC/0KSiP+/8df/vfLT/77y1f/A89b/vPLT/7Xxzv/B8dn/Qo6J/y5igv8uYoL/L2SF/zRr - jf81bI//NWyP/zVsj/81bI//NWyP/zVsj/81bI//MmeK/z55n/8/e6L/j7vT/47F5f93s9r2FiQzIwAA - AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAADK01lNXOy2/yKw+X/hLDK/0WBpv85bpH/PHSW/zx0lv88dJb/PHSW/zx0 - lv88dJb/O3KU/zdujv82bY3/N22M/0Ohif+v783/pO/C/6vwx/+18c7/uPHQ/7LxzP+m78T/nu6+/6nu - yv9Jn5D/N22N/zZtjf82bY3/OXGS/zx0lv88dJb/PHSW/zx0lv88dJb/PHSW/zlukf9Fgab/SoWq/6TN - 5f+Qx+f/ZqHHrQAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJlo83Je7fd/5rF3P9MiKz/PnaX/0J7 - nP9Ce5z/Qnuc/0J7nP9Ce5z/QHmZ/z93l/8/d5f/PneU/0SsiP+e7sP/iuuw/5Xst/+f7r//p+/E/6jv - xf+k78L/m+28/5Drs/+E6qz/mO2//0Wpi/8+d5b/P3eX/z93l/9AeJj/Qnub/0J7nP9Ce5z/Qnuc/0J7 - nP8+dpf/Soap/3Omw/+Vx+X/h8Hk/z5vlVcAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIRH2oeHaz - 3P+jz+f/WpO0/0Z9nf9Kg6P/SoOj/0qDo/9Kg6P/SoOi/0mCof9JgqH/SIKd/0m3if+E67L/ceee/33p - pv+I667/key1/5fsuf+Z7br/ley3/47rs/+E6qv/eOij/2vmmv+A67H/SrSP/0aDnf9JgqH/SYKh/0mC - of9Kg6L/SoOj/0qDo/9Kg6P/Rn2d/1KOr/+dxdr/iMDi/2+s1eYAAAAXAAAAAQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAhMsPiloqtf5jsLj/3mqw/9OhaT/U4uq/1OLqv9Ti6r/U4uq/1OLqv9Ti6r/Toyh/0G7 - gf9q6KL/VuOM/2Tmlv9x557/e+il/4Lpqv+H6q3/iOuu/4XqrP9/6aj/d+ii/2zmm/9f5ZL/UOKI/2Ln - nf9Gu4z/TIyh/1OLqv9Ti6r/U4uq/1OLqv9Ti6r/U4uq/06FpP9el7f/sNbq/4K84P9Pi7iYAAAACwAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARV5XFvHm03P+YwNX/Vo6q/1yUsP9clLD/XJSw/1yU - sP9clLD/UJSf/zu/fP9K5I7/POB6/0rihP9X44z/YuWU/2zmmv9y55//duei/3foov9156H/cOed/2jm - mP9e5ZH/UuOJ/0ThgP8133f/QuOJ/zy9g/9PlKD/XJSw/1yUsP9clLD/XJSw/1yUsP9Wjqr/gLDI/6HQ - 6v9wrtr/I05yQQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzBvpnBzsdv/oszi/3ir - xP97r8f/e6/H/3qvx/96r8f/WqGg/zDDdv8l33f/Hdxo/y7ecv884Hv/SOGD/1Pjiv9b5I//YeWT/2Xl - lf9l5pb/Y+WV/1/kkv9Z443/T+KH/0ThgP824Hj/J91v/xXcZP8e3nL/M8WB/1egpP91qsX/darF/3Sq - xf90qsX/cabC/5/H3P+JweP/WJvL1QAAABIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAETTHEbZ6fU3oS/4v+Px+f/kcjn/5HJ6P+Syej/armx/yDEbP8R2Wf/ANhZ/wzbYP8e3Gn/LN5x/zjg - ef9C4X7/SuKE/0/ih/9S44n/U+OK/1Hiif9N4ob/R+GC/z7gfP8033b/J91u/xfcZf8F2lz/ANdY/w7Y - ZP8jxnf/bbq7/5LJ5/+RyOf/j8fn/47G5v+MxeX/gLvf+0aFu20AAAAFAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAASBAYAhilrcnVXqVMDtTZEomOkVzF28/yRDGaP8K0lv/H9Zk/yna - a/8x3XL/OuB5/0fhgf9Q4of/V+OL/13kj/9g5ZL/YOWS/17kkf9Y5I3/UOOH/0ThgP8033b/Id1r/xTc - ZP8E2Vz/ANdY/wDUVf8A0FH/BdFY/w3DaP8cakbBKz1GcTxYakhcgpgvaZ23J2GSqhUAAAACAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAADAAAACsAAABbAGMZxADE - Xv8Jy1P/PdVv/0jYef9I3Hv/SN19/0jgf/9K4oL/T+KG/1bji/9b5I3/XuWQ/2Dlkf9g5ZH/YOWR/13k - j/9Z44z/VOOJ/0rig/8433f/Idpp/w3VW/8A0FH/AM1N/wDKSv8AyUz/A8Ng/wFdHbsAAABYAAAAKAAA - AAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAADAAA - AC8ABQBjAGoV0wC+VP8OxUz/R9Fx/1HWev9R2Hz/Udp+/1HcgP9R3oL/UeCE/1Hhhv9T4oj/VeOK/1nk - i/9a5I3/WuSN/1nkjP9X44v/VeOJ/1Lih/9R4YX/UeCE/1Hdgv9R3ID/RNd1/yfQYv8IyEv/AMRD/wDB - Qv8AvVH/AGkYygAFAF8AAAAsAAAACwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAABAAAACIADwBjAG8Q3wC7Tf8XwEr/U890/1rSe/9a1X7/WteA/1rZgv9a24T/Wt2F/1re - h/9a4Ij/WuGK/1riiv9a4ov/WuKL/1rii/9a4ov/WuKL/1rhiv9a4Yn/Wt+I/1reh/9a3IX/WtqD/1rY - gf9a13//V9R8/zvLZv8PwEX/ALk5/wC4Sf8AaxHUABAAYAAAACAAAAAEAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcADgA4AHsU4gC1Qv8ivEr/Xs15/2LRfv9i0oD/YtWC/2LX - hP9i2Ib/YtqI/2Lcif9i3Yr/Yt6L/2LfjP9i4I3/YuGN/2Lhjv9i4Y7/YuGO/2Lhjf9i4Iz/Yt+M/2Le - i/9i3Yr/YtyJ/2LZh/9i2IX/YtaD/2LUgf9i0n//YM98/z/EYf8JtTf/ALQ//wB2E9sABQA0AAAABwAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAC4ATgCsNP8vuk3/acx+/2vO - gf9r0YP/a9KF/2vUh/9r1oj/a9iK/2vZi/9r24z/a9yN/2vdj/9r3o//a96Q/2vfkf9r35H/a+CR/2vf - kf9r35H/a96Q/2vdj/9r3Y7/a9yN/2vai/9r2Yv/a9eJ/2vWiP9r04b/a9KE/2vQgv9rzYD/Zcp6/yq3 - SP8AqjL/AC4ATgAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAu - AE5LuVz/ruC2/7Hiuv+x47v/seS8/7Hlvf+x5r7/quW5/2HUgf9u14v/c9qQ/3Pbkf9z3JL/c92T/3Pd - lP9z3ZT/c96U/3PelP9z3pT/c92U/3PdlP9z3ZL/c9yS/3Pbkf9z2Y//bteL/2TUg/+q5bn/seW+/7Hl - vf+x5Lv/seO6/7Hhuf+u37b/Srlc/wAuAE4AAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAcAMwBGVade/5TMnv+Uzp//lM6g/5TPov+U0aP/lNKk/5TTpf8swVn/bdWI/3rZ - lP962pX/etuW/3rclv963Zf/et2X/3rdl/963Zf/et2X/3rdl/963Zf/etyW/3rblv962pX/etmT/23U - iP8wwlv/lNOl/5TSpP+U0KP/lM+h/5TOoP+UzZ//lMud/0yiVP8AMwBGAAAABgAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAEUAND2WRf9hrW3/Ya9v/2Gxcf9hs3P/YbR1/2G2 - dv9ht3j/IbZM/3TUjP+C2Zj/gtqY/4Lbmf+C3Jn/gtya/4Ldm/+C3Zv/gt2b/4Ldm/+C3Jv/gtya/4Lb - mf+C25j/gtqY/4LYl/901Iv/JLlO/2G3d/9htXb/YbN0/2Gycv9hsHD/Ya5u/2Gsbf86k0D/AEAAMAAA - AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYNcg95KIYvpCiF - LqUohjClKIgxpSiIMaUoiTOmIn8tswKeJfd704//itmc/4ranf+K257/ituf/4rcn/+K3J//it2g/4rd - oP+K3Z//ityf/4rcn/+K257/itqe/4rZnP+K2Jz/e9OP/wKlK+8jgS6wKIczpiiIMaUohjClKIYwpSiF - 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 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAoAIAC6q/Xr//E4cT/xOLE/8Tixf/E4sX/xOLF/8Ti - xf/E4sX/xOLF/8Tixf/E4sX/xOLF/8Tixf/E4sT/xOLE/8ThxP+v16//AIIB1AAAACIAAAACAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAKAB/AOq/37//2+zb/9vs - 2//b7Nv/2+3b/9vt2//b7dz/2+3c/9vt3P/b7dz/2+3c/9vt2//b7dv/2+zb/9vs2//b7Nv/v96//wCA - ANQAAAAiAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA - ACUDeQPqvdy9/9To1P/U6NT/1OjU/9To1P/U6NT/1OjU/9To1P/U6NT/1OjU/9To1P/U6NT/1OjU/9To - 1P/U6NT/1OjU/67Vrv8AdQDTAAAAHwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAIAAAAZFHcU5nWsdf91rHX/dax1/3Wsdf91rHX/dax1/3Wsdf91rHX/dax1/3Ws - df91rHX/dax1/3Wsdf91rHX/dax1/3Wsdf91rHX/FHIUzQAAABYAAAABAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQdxB7k/jz//RpNG/0aTRv9Gk0b/RpNG/0aT - Rv9Gk0b/RpNG/0aTRv9Gk0b/RpNG/0aTRv9Gk0b/RpNG/0aTRv9Gk0b/Po8+/wNuA6cAAAAIAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAJAAHAFwAJABe - ACYAXgAmAF4AJgBeACYAXgAmAF4AJgBeACYAXgAmAF4AJgBeACYAXgAmAF4AJgBeACYAXgAmAGAAJQBc - ACQAJAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////////8AAAAAA - B///wAAAAAAH///AAAAAAAf//8AAAAAAA///wAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAD//+A - AAAAAAP//4AAAAAAA///gAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAD//+AAAAAAAP//4AAAAAA - A///gAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAB//+AAAAAAAH//4AAAAAAAf//gAAAAAAB//+A - AAAAAAH//4AAAAAAAf//gAAAAAAB//+AAAAAAAH//4AAAAAAAf//gAAAAAAD///AAAAAAAP//8AAAAAA - B///wAAAAAAH///gAAAAAAf//+AAAAAAD///8AAAAAAP///wAAAAAA////AAAAAAH///+AAAAAAf///4 - AAAAAD/////AAAAH/////4AAAAP/////AAAAAf////4AAAAA/////AAAAAB////8AAAAAH////wAAAAA - f////AAAAAB////8AAAAAH////4AAAAA//////wAAH///////AAAf//////8AAB///////wAAH////// - /AAAf//////8AAB///////wAAH///////AAAf//////8AAB///////wAAH///////AAAf//////8AAB/ - /////////////ygAAACAAAAAAAEAAAEAIAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAEAAAABAAAAAwAAAAUAAAAHAAAACQAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA - AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA - AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA - AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA - AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA - AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACQAAAAcAAAAFAAAAAwAA - AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAUAAAAKAAAAEgAAABcAAAAcAAAAHwAA - AB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAA - AB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAA - AB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAA - AB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAA - AB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAA - AB8AAAAfAAAAHwAAAB4AAAAcAAAAFwAAABEAAAAKAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAEAAAAEAAAADAAAABcAAAAkAAAAMAAAADkAAAA9AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAA - AD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAA - AD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAA - AD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAA - AD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAA - AD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPQAAADkAAAAwAAAAJAAA - ABcAAAAMAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgAAAAUAAAAKAAAAD8AAABSAAAAYAAA - AGYAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAA - AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAA - AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAA - AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAA - AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAA - AGgAAABoAAAAaAAAAGgAAABmAAAAYAAAAFMAAAA/AAAAKAAAABUAAAAIAAAAAQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAACAAAADAAAAB4AAAA4AAAAVwAAAG8AAAB+AAAAhQAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAA - AIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAA - AIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAA - AIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAA - AIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAA - AIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIUAAAB/AAAAcAAA - AFkAAAA7AAAAIAAAAA0AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAPAAAAJR0mMFApXYu0O4fF90CN - zP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CN - zP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CN - zP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CN - zP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CN - zP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CN - zP9Ajcz/QI3M/0CNzP9Ajcz/QI3M/0CNzP87hML3JVF/rAAAAEoAAAAoAAAAEgAAAAUAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAABAAAABIAAAAqHUlxejBzuf80ebv/XqLV/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u - 3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22v3P9tr9z/ba/c/22v3P9tr9z/bq/c/26v - 3P9ur9z/bq/c/26v3P9ur9z/bq/d/26v3f9ur93/bq/d/26v3f9ur93/bq/d/26v3f9ur93/bq/d/26v - 3f9ur93/bq/d/26v3f9ur93/bq/d/26w3f9usN3/brDd/2+w3f9vsN3/b7Dd/2+w3f9vsN3/b7Dd/2+w - 3f9vsN3/b7Dd/2+w3f9vsN3/b7Dd/2+w3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cx - 3f9wsd3/cLHd/3Cx3f9wsd3/cLHd/3Cx3f9wsd3/cLHd/3Cx3f9wsd3/cLHd/3Cx3f9wsd3/XqHS/zB0 - t/80erz/JVd+iQAAAC8AAAAVAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFAAAAC0jTXJ9RY/N/1eZ - zP9Qkcb/d7Xd/3q54P96ueD/erng/3q54P96ueD/erng/3q54P9rp8v/d7Tb/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P+NxuX/lMnn/5TJ5/+Uyef/lMnn/5PI5v+SyOb/kcfm/5DH - 5v+Px+b/jcbm/4zG5v+LxuX/i8Xl/4rF5f+JxOX/g7/k/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y6 - 4f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f99uuH/fbrh/3264f99uuH/fbrh/326 - 4f99uuH/fbrh/3264f99uuH/fbrh/3664f9+uuH/frrh/3664f9+uuH/frrh/3664f92stb/c67S/366 - 4f9+uuH/f7vi/3+74v9/u+L/f7vi/3Gv2f9Pj8X/b67Z/0WPzf8ybp6sAAAAMwAAABcAAAAHAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAUAAAAUAAAALjBqmJ5Gkc7/ebjf/3Gv2v9Qkcb/ca/a/3q54P96ueD/erng/3q5 - 4P96ueD/a6fL/zhrgv9Zk7L/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P97ueD/e7ng/3u5 - 4P97ueD/e7ng/3u54P97ueD/e7ng/3u54P97ueD/e7ng/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y6 - 4f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/326 - 4f99uuH/fbrh/3264f99uuH/fbrh/0p/mf87bIL/fbrh/3264f99uuH/frrh/3664f9npdL/WpnK/3q5 - 3/9+uuH/RpHO/zJsna4AAAA1AAAAGQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAABUAAAAvNXGhqUmT - z/95t9//ebff/3a03f9Wl8n/ZqXT/3m43/95uN//ebjf/3m43/95uN//aaXJ/3Wy2f95uN//ebjf/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/k8jn/5PI5/+f0Or/ptTs/5PI5/+TyOf/k8jn/5PI5/+TyOf/k8jn/5PI5/+SyOf/ksjn/5LH - 5v+Rx+b/kcfm/5DH5v+Qx+b/kMfm/5TK5/+h0+z/odPs/6HS7P+g0uz/ksnn/43G5v+Mxub/jMbm/4vG - 5f+Lxub/i8bm/4vF5f+Lxeb/i8Xm/4rF5v+Kxeb/icTm/4fB5f98uuH/fLrh/3y64f98uuH/dLDV/3Cs - 0P98uuH/fLrh/3y64f96uN7/XJvM/2em0v99uuH/fbrh/3264f9Jk8//P4K51wAAADcAAAAbAAAACAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAFAAAAFQAAADA5c6KqSpXQ/3i33/94t9//eLff/3i33/9mpdP/W5vN/3m3 - 3/95t9//ebff/3m33/95t9//ebff/3m33/95t9//ebff/3m43/95uN//ebjf/3m43/95uN//ebjf/3m4 - 3/95uN//ebjf/3m43/95uN//erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P97ueD/e7ng/3u54P97ueD/e7ng/3u54P97ueD/e7ng/3u5 - 4P97ueD/e7ng/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/erfe/1yazP9zsdv/fLrh/3y6 - 4f98uuH/fLrh/1Sb0v9Dg7rXAAAAOQAAABsAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAWAAAAMTdz - oatMl9H/eLbf/3i23/94tt//eLbf/3i23/9vrtr/ca3W/63c8P+y3vL/st7y/7Le8v+y3vL/st7y/7Le - 8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le - 8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le - 8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le - 8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le8v+y3vL/st7y/7Le - 8v+y3vL/st7y/6TU7P9fns7/ebfe/3u54P97ueD/fLrh/3y64f98uuH/WZ/U/0KEuNgAAAA7AAAAHQAA - AAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAABcAAAAzOHOgrE6Y0v93tt7/d7be/3e23v93tt7/d7be/3e2 - 3v+Uyuj/jcTi/53P6f+t3PH/rt3x/7Dd8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He - 8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He - 8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He - 8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He - 8v+x3vL/sd7y/7He8v+x3vL/sd7y/7He8v+x3vL/r93x/63d8f+Xy+b/mMzn/3q54P96ueD/erng/3q5 - 4P96ueD/e7ng/3u54P9aodX/Q4a42QAAAD0AAAAeAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAGQAA - ADQ7dJ+tWJ7T/3a13v92td7/crHZ/0h+m/9alrf/drXe/5PK6P+dz+n/ZaLQ/2uo0v9xrdX/drLY/3iz - 2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz - 2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz - 2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz - 2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz2P94s9j/eLPY/3iz - 2P90sNb/bKrS/3242/+x3fH/erng/3q54P96ueD/TISg/1KKqf96ueD/erng/1yh1v9Mk8v2AAAAPwAA - ACAAAAALAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAZAAAANUOBsMJbodb/dbTe/3W03v9xsNn/SYCf/1yY - u/91tN7/k8ro/53Q6/9pqdb/b67a/3Wy3f96ud7/fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y6 - 3/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y6 - 3/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y6 - 3/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLrf/3y6 - 3/98ut//fLrf/3y63/98ut//fLrf/3y63/98ut//fLnf/3e13f9xsNv/gLvg/7Dd8f96ueD/erng/3q5 - 4P9UjKv/Vo6s/3q54P96ueD/Z6ra/1Ob0v8AAABBAAAAIQAAAAwAAAABAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAA - ABoAAAA3Soq81l2i1v91tN7/dbTe/3W03v91tN7/dbTe/3W03v+Tyej/ndDr/2io2P9urdr/dbPd/3q4 - 3/98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y6 - 4f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y6 - 4f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y6 - 4f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y6 - 4f98uuH/d7Xd/3Cv3P+Au+H/sN3x/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/9nqtr/VZvS/wAA - AEQAAAAjAAAADQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGwAAADdLir3XXqPX/3Sz3f90s93/h8Di/3Sz - 3f90s93/dLPd/5LJ5/+d0Ov/Z6fX/22s2v9zst3/ebff/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q5 - 4P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P92tN3/b67b/3664f+v3fH/ebff/3m3 - 3/95t9//ebff/3m33/95t9//ebff/2ir2v9XndP/AAAARgAAACUAAAAOAAAAAgAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAgAAAAbAAAAOU2MvddgpNf/c7Pd/3Oz3f+TyOb/c7Pd/3Oz3f9zs93/kcjn/5zP6/9mptb/a6vZ/3Kx - 3f94tt7/ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m4 - 3/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m4 - 3/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m4 - 3/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m4 - 3/95uN//ebjf/3Wz3f9trNr/fbng/67d8f94t9//eLff/3i33/90st3/eLff/3i33/94t9//a6zb/1mf - 1P8gOlBgAAAAJwAAABAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAB0AAAA7To6+2GKm2P9yst3/crLd/4vE - 5f9yst3/crLd/3Ky3f+Qx+f/m8/q/2Wl1v9qqtn/cK/c/3a03v94t9//eLff/3i33/94t9//eLff/3i3 - 3/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i3 - 3/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i3 - 3/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i3 - 3/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94tt//c7Ld/2us2v98ud//rt3x/3i2 - 3/94tt//eLbf/3Cw2/94tt//eLbf/3i23/9wsd3/W6HV/zBbeHkAAAApAAAAEQAAAAMAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAKAAAAHgAAADxPj7/YZ6ra/3Gx3f9xsd3/i8Tl/3664f9yst3/crLd/5DH5/+azur/aqjX/3ay - 3P97t97/gLrg/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O8 - 4v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O8 - 4v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O8 - 4v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O8 - 4v+DvOL/g7zi/4O84v99ud//dLHc/3q43v+t3PH/drXe/3e23v93tt7/b6/a/3W03f93tt7/d7be/3Cx - 3f9dotb/MFx5egAAACsAAAASAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAfAAAAPViZy+xoq9r/cLHd/3Cx - 3f9wsd3/isLk/3Gx3f9xsd3/j8fn/5jN6v9sn7//bJ66/2+hvP9zpL7/dKW//3Slv/90pb//dKW//3Sl - v/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Sl - v/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Sl - v/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Sl - v/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Slv/90pb//dKW//3Givf9tn7v/frnd/63d - 8f91tN7/dbTe/3a13v9yst3/bq7a/3a13v92td7/cLHd/2Ck1/8zWnl8AAAALQAAABQAAAAFAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAACgAAAB8AAAA+YaXY/2ir2v9vsN3/b7Dd/2+w3f+Tyef/cLHd/3Cx3f+Nxuf/mM3q/06P - x/9OkMf/VJXJ/1iYy/9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZ - zP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZ - zP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZ - zP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZzP9amcz/WpnM/1qZ - zP9amcz/WpnM/1qZzP9amcz/VpfK/1OUyf91stz/rdzx/3W03v91tN7/dbTe/3W03v9oqdb/dbTe/3W0 - 3v9yst3/YaXY/0BukpQAAAAuAAAAFQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAALAAAAIAAAAEBjp9j/aazb/2+v - 3f9vr93/b6/d/4XA4/9vr93/b7Dd/43G5/+XzOn/X6DT/2Wn1/9qq9n/b6/c/3Ky3f9yst3/crLd/3Ky - 3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky - 3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky - 3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky - 3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Ky3f9yst3/crLd/3Kx3f9trNr/Z6jY/3e1 - 3f+s3PH/dLPd/3Sz3f90s93/dLPd/2eo1f91tN7/dbTe/3W03v9jp9j/TIGoqgAAADAAAAAWAAAABgAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAQAAAAwAAAAhAAAAQWWp2P9qrNv/bq/c/26v3P9ur9z/lMrn/26v3P9ur9z/jMbm/5fM - 6P9en9L/Y6XX/2mq2f9trtz/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw - 3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw - 3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw - 3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/3m43/95uN//ebjf/3m33/95t9//cLDd/3Cw - 3f9wsN3/cLDd/3Cw3f9wsN3/cLDd/2us2v9lp9j/d7Td/6zb8P9zs93/c7Pd/3Oz3f9zs93/ZabU/3Sz - 3f90s93/dLPd/2Wp2P9KgKerAAAAMgAAABcAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAADQAAACMAAABEZ6ra/2yt - 2/9trtz/ba7c/22u3P+GweT/ba7c/22u3P+LxuX/lsvo/1ye0v9ipNb/Z6nY/2ys2/9ur9z/bq/c/26v - 3P9ur9z/bq/c/26v3P9ur9z/bq/c/26v3P9ur9z/bq/c/26v3P9ur9z/bq/c/26v3P9ur9z/bq/c/26v - 3P9ur9z/bq/c/26v3P9ur9z/dLPd/3q54P96uOD/erjg/3q44P95uN//gb7i/4XA4/+FwOP/hMDj/4S/ - 4/99uuH/ebff/3m33/95t9//fLrh/4O+4/+BvuP/gb7i/4G+4v+AveL/gL3i/4C94v+AveL/f7zi/3i2 - 3v93tt7/d7be/3e23v93tt7/d7be/3e23v9ur9z/bq/c/26v3P9ur9z/bq/c/26v3P9ur9z/aqzZ/2Ol - 1/92s93/q9vw/3Ky3f9yst3/crLd/3Ky3f9pqtj/a6vY/3Oz3f9zs93/Z6ra/02Apq0AAAA0AAAAGAAA - AAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAIAAAAOAAAAJAAAAEZprNr/bK7c/22u3P9trtz/ba7c/4nE5f9trtz/ba7c/4vF - 5f+Vy+j/W57S/2Ci1f9mqNj/a6zb/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u - 3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u - 3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u - 3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9trtz/ba7c/22u - 3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9pq9n/YqTW/3Sy3f+q2vD/crLd/3Ky3f9yst3/crLd/26u - 2/9lptT/crLd/3Ky3f9srdv/UoiutwAAADYAAAAZAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAA8AAAAmJkNTX2ut - 2/9srdv/ba7c/22u3P9trtz/fbvi/3W13/9trtz/i8Tl/5TK5/9anNL/X6HU/2Sm2P9pq9r/a63b/2ut - 2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut - 2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut - 2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut - 2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2ut2/9rrdv/a63b/2eq - 2P9gotX/c7Ld/6ra8P9xsd3/cbHd/3Gx3f9xsd3/cbHd/2Ki0v9xsd3/cbHd/22u3P9emcTXAAAAOAAA - ABsAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAADAAAAEAAAACc8Zn92ba7c/2yt2/9srdv/bK3b/2yt2/9vsN3/e7rh/2yt - 2/+KxOX/lMnn/1mc0v9doNP/Y6XX/2iq2f9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs - 2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs - 2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs - 2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs - 2/9qrNv/aqzb/2qs2/9qrNv/aqzb/2qs2/9qrNv/ZajY/1+h1P9ysd3/qdnw/3Cx3f9wsd3/cLHd/3Cx - 3f9wsd3/YaHS/3Cx3f9wsd3/ba/c/16ZxNgAAAA6AAAAHAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAQAAAAKD5i - gHdvr93/bK3b/2ut2/9rrdv/a63b/2ut2/+AwOT/a63b/4nD5f+Tyef/WJrS/1yf0/9hpNb/ZqnZ/2ir - 2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir - 2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir - 2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir - 2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir2v9oq9r/aKva/2ir - 2v9kp9j/XqHU/3Gw3P+o2e//b7Dd/2+w3f9vsN3/b7Dd/2+w3f9godL/b7Dd/2+w3f9vsN3/YZvE2AAA - ADwAAAAdAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABEAAAApQmZ/eHGx3f9rrNv/aqzb/2qs2/9qrNv/aqzb/3i5 - 4f9qrNv/iMLl/5LI5/9ypcj/eqvK/32uzP+Ascz/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gy - zf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gy - zf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gy - zf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gy - zf+Bss3/gbLN/4Gyzf+Bss3/gbLN/4Gyzf+Bss3/gbLN/3+vzP97rMr/ca7Y/6jY7/9vr93/b6/d/2+v - 3f9vr93/b6/d/2eo1/9rrNr/b6/d/3Cw3f9loMriAAAAPgAAAB8AAAAKAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEgAA - ACo/Zn16c7Pd/2ms2v9prNr/aaza/2Wn1/9qrNv/aqzb/2qs2/+IwuX/kcfn/0GCuv9Bgbn/Roa6/0mK - vP9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qL - vv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qL - vv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qL - vv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qLvv9Ki77/Sou+/0qL - vv9Ki77/R4i6/0SDuf9rqtj/p9jv/22u3P9ur9z/bq/c/26v3P9ur9z/bKza/2ao1v9ur9z/cbHd/3Oz - 3f8AAABAAAAAIQAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAATAAAALEBlfHt1tN7/aKva/2ir2v9oq9r/YaPU/2ms - 2v9prNr/aaza/4fB5f+Rx+f/VJfQ/1ic0v9dodT/YaXX/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On - 2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On - 2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On - 2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On - 2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9jp9j/Y6fY/2On2P9fo9X/Wp7S/22s2v+n2O//aqvZ/22u - 3P9trtz/ba7c/22u3P9trtz/ba7c/22u3P9xst3/dbTe/wAAAEIAAAAiAAAADAAAAAEAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAA - ABQAAAAuR3KLiHe23/9oqtr/aKra/2iq2v9fodP/aKra/2ir2v9oq9r/h8Hk/5DH5v9Sl8//V5vS/1yg - 1P9gpNf/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km - 2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km - 2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km - 2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km2P9iptj/YqbY/2Km - 2P9iptj/YqbY/16h1f9ZnNL/bKza/6bY7v9oqtj/aarZ/22u3P9trtz/ba7c/22u3P9trtz/ba7c/3Cx - 3f93tt//AAAARQAAACQAAAAOAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFQAAAC5cj62pebjf/2eq2v9nqtr/Z6ra/12g - 0v9nqtr/Z6ra/2iq2v+GwOT/j8bl/0+Uzf9VmdD/Wp7S/12i1P9rrNr/ba7b/22t2/9srdv/bK3b/2yt - 2/9rrNr/a6za/2yt2/90s93/crLd/3Gx3f9wsN3/b6/c/26u3P9srdv/aaza/2Wp2P9mqtn/aaza/2ir - 2f9nqtn/ZanY/2So2P9jp9j/YqbY/2Gl1/9gpdf/X6TW/1+j1v9fo9b/X6TW/1+k1v9fpNb/X6TW/1+k - 1v9fpNb/X6TW/1+k1v9fpNb/X6TW/1+k1v9fpNb/X6TW/1+k1v9fpNb/X6TW/1+k1v9fpNb/X6TW/1+k - 1v9fpNb/X6TW/1+k1v9fpNb/X6TW/1+k1v9fpNb/X6TW/1+k1v9fpNb/XKHT/1aa0f9qq9j/ptfu/2ep - 2P9nqdj/bK3b/22u3P9trtz/ba7c/22u3P9trtz/b7Dd/3m43/8AAABHAAAAJgAAAA8AAAACAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAUAAAAVAAAAMF6Qsap6ueD/ZqrZ/2aq2f9mqtn/YaPV/2Gk1f9mqtn/ZqrZ/4bA5P+PxuX/TZLM/1OX - zv9Xm9L/Z6nY/2us2f9kp9f/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h - 1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h - 1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h - 1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h1P9dodT/XaHU/12h - 1P9dodT/XaHU/12h1P9antL/VJjP/2ip1/+l1+7/aKvZ/2Gj0/9rrdv/a63b/2yt2/9srdv/bK3b/2yt - 2/9vsN3/erng/0Rrg3cAAAAoAAAAEAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAABYAAAAxYZOxqne23/9lqdj/ZanY/2Wp - 2P9kqNj/W5/S/2Wp2P9lqdj/hcDk/43F5f9LkMn/T5XM/1WZzv9YndH/Wp/S/1qf0v9an9L/Wp/S/1qf - 0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf - 0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf - 0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf - 0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1qf0v9an9L/Wp/S/1aaz/9Sl8z/ZqfV/6TW - 7v9qrNv/X6HS/2qs2/9qrNv/aqzb/2ut2/9rrdv/a63b/2+w3f98uuH/RWuAeQAAACoAAAASAAAAAwAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAHAAAAFwAAADJfj62rebff/2Wp2P9lqdj/ZanY/2Wp2P9Yms//ZanY/2Wp2P+FwOT/jMTk/0qO - x/9Nk8n/UpfM/1aazv9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ec - z/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ec - z/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ec - z/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ecz/9XnM//V5zP/1ec - z/9XnM//V5zP/1ecz/9XnM//VJnM/06Uyv9kpdP/pNXu/2qs2/9Ymc7/aqzb/2qs2/9qrNv/aqzb/2qs - 2/9qrNv/a63b/3664f9EaH57AAAALAAAABIAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAYAAAANGCPrq15uN//ZKjY/2So - 2P9kqNj/ZKjY/1eZzv9kqNj/ZKjY/4TA4/+LxOT/SIzG/0yQx/9Plcr/VJjM/1WZzf9Vmc3/VZnN/1WZ - zf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZ - zf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZ - zf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZ - zf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Vmc3/VZnN/1WZzf9Ql8v/TJHH/2Oj - 0v+j1e7/aaza/12g0v9prNr/aaza/2ms2v9prNr/aaza/2qs2/9qrNv/gL3i/0Vofn0AAAAuAAAAFAAA - AAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAABwAAABkAAAA1Z5a1t3q54P9jp9j/Y6fY/2On2P9jp9j/V5rP/2Gl1/9jp9j/g7/j/4vC - 4v9upMz/eKvO/3qs0P98sNL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x - 0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x - 0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x - 0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x0v99sdL/fbHS/32x - 0v99sdL/fbHS/32x0v99sdL/fbHS/3qu0f95rM//ZaTS/6HU7f9oq9r/WJnO/2ir2v9oq9r/aKva/2ir - 2v9oq9r/aKva/2ms2v+Dv+P/XYulnwAAADAAAAAVAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGgAAADZ4rMzWe7ng/2Km - 2P9iptj/YqbY/2Km2P9coNL/Wp7S/2Km2P+BvuP/isLi/zBso/8vaZ3/MGyf/zNvof80cKH/NHCh/zRw - of80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRw - of80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRw - of80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRw - of80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/NHCh/zRwof80cKH/Mm6g/zBs - of9dnMv/odTt/2iq2v9eodL/aKra/2iq2v9oqtr/aKra/2iq2v9oqtr/aKra/4bA5P9nlbCrAAAAMQAA - ABYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAgAAAAbAAAAN3itytd5uN//YabY/2Gm2P9iptj/YqbY/2Ck1/9Vmc7/YqbY/4G+ - 4/+JweL/QIS+/0WJwP9IjML/S5HF/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0yS - xv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0yS - xv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0yS - xv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9Mksb/TJLG/0yS - xv9Mksb/TJLG/0ySxv9Mksb/TJLG/0ySxv9KjsP/RorA/12dzP+h0+3/Z6ra/2Wp2P9go9T/Z6ra/2eq - 2v9nqtr/Z6ra/2eq2v9nqtr/frrh/2aUr6wAAAAzAAAAFwAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABsAAAA4ea7N13W0 - 3v9gpdf/YKXX/2Gm2P9hptj/YabY/1CVy/9hptj/gL3i/4nA4f8/gbz/Q4a//0eLwP9KjsP/S5HF/0uR - xf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uR - xf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uR - xf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uR - xf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0uRxf9LkcX/S5HF/0iM - wf9EiL//XJvM/6HT7f9mqtn/ZqrZ/1iaz/9mqtn/ZqrZ/2aq2f9mqtn/ZqrZ/2aq2f9/u+L/Z5WxrQAA - ADUAAAAZAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAJAAAAHAAAADp6rMvYdbTe/2Ck1/9gpNf/YKTX/2Cl1/9gpdf/T5PK/2Cl - 1/9/u+L/iL/g/z2Auv9AhLv/RIi+/0eMwP9JjsL/SY7C/0mOwv9JjsL/SY7C/0mOwv9JjsL/SY7C/0yT - xv9OlMf/TpTH/02Ux/9NlMf/TpXH/1KYzP9SmMz/UpjM/1KYzP9SmMz/UpjM/1SZz/9Ql8v/T5fL/0+X - y/9Olsv/TpbL/06Wy/9MlMf/TZXK/02Vyv9Lksf/SY7C/0mOwv9JjsL/SY7C/0mOwv9JjsL/SY7C/0mO - wv9JjsL/SY7C/0mOwv9JjsL/SY7C/0mOwv9JjsL/SY7C/0mOwv9JjsL/SY7C/0mOwv9JjsL/SY7C/0mO - wv9JjsL/SY7C/0mOwv9JjsL/SY7C/0mOwv9JjsL/RovA/0CGvP9amsr/oNLt/2Wp2P9lqdj/V5nO/2Wp - 2P9lqdj/ZanY/2Wp2P9lqdj/ZanY/4G+4v95q8fMAAAANwAAABoAAAAIAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAdAAAAPHuw - y9h3td7/YKTX/2Ck1/9gpNf/YKTX/2Ck1/9Tl8z/XaHU/3+74v+Gv9//O324/z+Cuv9Bhrz/RYu//0uR - xf9Nk8b/T5XH/1WZzP9Sl8n/TJLG/0ySxv9LksX/S5HF/0uRxf9LkcX/S5HF/0qRxf9Gi8D/RovA/0aL - wP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aL - wP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aLwP9Gi8D/RovA/0aL - wP9Gi8D/RovA/0aLwP9Gi8D/RovA/0qQxf9KkMX/So/F/0qPxf9Kj8X/SY/F/0mPxf9IjsP/RovA/0aL - wP9Eib7/P4O6/1iZyP+f0uz/ZKjY/2So2P9Wmc7/ZanY/2Wp2P9lqdj/ZanY/2Wp2P9lqdj/fbrh/3uv - zdcAAAA5AAAAGwAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAB8AAAA9grbT4ne13v9fo9f/X6PX/1+j1/9fo9f/X6PX/1md - 0v9XmtH/frvi/4a+3/86fLb/PX+5/z+Euv9DiLz/RYq9/0WKvf9Fir3/RYq9/0WKvf9Fir3/RYq9/0WK - vf9Fir3/RYq9/0WKvf9Fir3/RYq9/0WKvf9Fir3/RYq9/0WKvf9Fir3/RYq9/0WKvf9Fir3/RYq9/0WK - vf9Fir3/RYq9/0WKvf9Fir3/TJLF/0ySxf9MksX/S5HF/0uRxf9LkcX/U5jK/1OXyv9Sl8r/UpfK/1KX - yv9Mksb/SpDE/0qQxP9OlMf/T5bJ/0+Vyf9Olcj/TpXI/06UyP9NlMj/TZPI/02UyP9KkMb/SY3C/0iN - wv9IjML/SIzC/0iMwv9IjML/SIzC/0aLwP9Fir3/RYq9/0GGu/8+gLn/V5fG/5/S7P9jp9j/Y6fY/1ib - 0P9kqNj/ZKjY/2So2P9kqNj/ZKjY/2So2P96uOD/fbHM2AAAADsAAAAdAAAACQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAHwAA - AD6RyOf/eLbf/16i1v9eotb/XqLW/1iazP9Ul8b/XqLW/1CVzP99uuH/hLvd/zR2rf83eq//On2y/z2A - s/8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6C - tP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6C - tP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6C - tP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6CtP8+grT/PoK0/z6C - tP8+grT/PH6y/zd6sP9Sk8D/n9Ls/2Km2P9iptj/W5/S/1WWwf9go9L/Y6fY/2On2P9jp9j/Y6fY/3q5 - 4P9/ss3YAAAAPQAAAB4AAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAgAAAAP5PK6P9rrNv/XaLW/12i1v9dotb/O3ab/ypd - ev9antH/UJbM/3y64f+Butr/L22h/zJxo/80c6X/N3en/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4 - qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4 - qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4 - qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4 - qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP83eKj/N3io/zd4qP81dab/MnGk/02LuP+e0uz/YqbY/2Km - 2P9Mjbz/LV97/0mGrf9iptj/YqbY/2Km2P9iptj/erng/4q+2ewAAAA+AAAAHwAAAAoAAAABAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACwAA - ACEAAABAlcvo/2us2/9dodb/XaHW/12h1v9Ul8f/Sou4/12h1v9dodb/fLrh/4G63P8ycqr/NHWs/zd5 - rf86fLD/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9 - sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9 - sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9 - sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9sf87fbH/O32x/zt9 - sf87fbH/O32x/zd6rv81dqz/QYGz/4vD4v9hptj/YabY/16h0v9KirL/X6LS/2Gm2P9iptj/YqbY/2Km - 2P9yst3/lcvo/wAAAEEAAAAhAAAADAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAMAAAAIgAAAEKXzOn/a6zb/1yh1v9codb/XKHW/1yh - 1v9codb/XKHW/1yh1v9codb/TJHK/1WZ0P9dodb/XaHW/12h1v9YntP/WJ7T/1ie0/9dodb/XaHW/12h - 1v9dodb/XaLW/12i1v9dotb/XaLW/12i1v9dotb/XaLW/12i1v9dotb/XaLW/12i1v9eotb/XqLW/16i - 1v9eotb/XqLW/16i1v9eotb/XqLW/16i1v9eotb/XqLW/1+j1/9fo9f/X6PX/1+j1/9fo9f/X6PX/1+j - 1/9fo9f/X6PX/1+j1/9fo9f/YKTX/2Ck1/9gpNf/YKTX/2Ck1/9gpNf/YKTX/2Ck1/9gpNf/YKTX/2Ck - 1/9gpNf/YKTX/2Ck1/9gpNf/YKTX/2Ck1/9gpNf/YKTX/2Ck1/9gpNf/YKXX/2Cl1/9gpdf/VpnP/0uP - x/9eotX/YKXX/2Cl1/9gpdf/YKXX/2Cl1/9hptj/YabY/26v3P+XzOn/AAAARAAAACMAAAANAAAAAQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA - AA4AAAAkAAAARZjN6v9qrNv/W6HV/1uh1f9bodX/W6HV/1uh1f9bodX/VpvS/0iLxv9Wm9L/W6HV/1yh - 1v9codb/XKHW/1ee0/9XntP/V57T/1ee0/9WndP/VJvS/1Sb0v9Um9L/VJvS/1Ob0v9Tm9L/VJvS/1Sb - 0v9Um9L/VJvS/1ad0/9YntP/VZzS/1Sb0v9Um9L/VJvS/1Sb0v9Um9L/VJvS/1Sb0v9Yn9P/WJ7T/1ie - 0/9YntP/WJ7T/1ie0/9bodX/XqLW/16i1v9eotb/XqLW/16i1v9eotb/XqLW/16i1v9eotb/X6PX/1+j - 1/9fo9f/X6PX/1+j1/9fo9f/X6PX/1+j1/9fo9f/X6PX/2Ck1/9gpNf/YKTX/2Ck1/9gpNf/YKTX/2Ck - 1/9gpNf/YKTX/2Ck1/9gpNf/YKTX/2Ck1/9gpNf/XaHU/0iLxf9YnNH/YKTX/2Ck1/9gpNf/YKTX/2Ck - 1/9gpdf/bq/c/5jN6v8AAABGAAAAJQAAAA4AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADgAAACYAAABHm9Ds/2us2/9aodX/WqHV/1qh - 1f9aodX/WqHV/0eLxv9Hi8b/WqHV/1qh1f9aodX/WqHV/02RwP9XnND/W6HV/1uh1f9bodX/W6HV/1uh - 1f9bodX/W6HV/1uh1f9bodX/XKHW/1yh1v9codb/XKHW/1yh1v9codb/XKHW/1yh1v9codb/XKHW/1yh - 1v9dodb/XaHW/12h1v9dodb/XaHW/12h1v9dodb/XaHW/12h1v9dodb/XaHW/12i1v9dotb/XaLW/12i - 1v9dotb/XaLW/12i1v9dotb/XaLW/12i1v9eotb/XqLW/16i1v9eotb/XqLW/16i1v9eotb/XqLW/16i - 1v9eotb/XqLW/1+j1/9fo9f/X6PX/1+j1/9fo9f/X6PX/1+j1/9fo9f/WZvM/1WXxv9fo9f/YKTX/2Ck - 1/9gpNf/YKTX/0qOx/9Kjsf/YKTX/2Ck1/9gpNf/YKTX/2Ck1/9ur9z/m9Ds/zhRW18AAAAmAAAAEAAA - AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAMAAAAPAAAAJll5inad0uz/YabY/1mf1P9aodX/WqHV/0+Wzf8/g8D/U5jQ/1qh1f9aodX/WqHV/1qh - 1f9Slcb/Kl57/z56o/9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/W6HV/1uh - 1f9bodX/W6HV/1uh1f9bodX/W6HV/1uh1f9bodX/W6HV/1uh1f9codb/XKHW/1yh1v9codb/XKHW/1yh - 1v9bodb/WZ/U/1mf1P9Zn9T/WZ/U/1mf1P9Zn9T/WZ/U/1mf1P9Zn9T/WZ/U/1mf1P9Zn9T/WZ/U/1mf - 1P9Zn9T/WZ/U/1mf1P9Zn9T/WZ/U/12i1v9dotb/XaLW/12i1v9dotb/XaLW/16i1v9eotb/XqLW/16i - 1v9eotb/XqLW/16i1v83b5P/LF98/16i1v9eotb/X6PX/1+j1/9fo9f/X6PX/1KXzP8/gb7/Wp/S/1+j - 1/9fo9f/X6PX/1+j1/+d0uz/WXmIeAAAACgAAAAQAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABAAAAAnW3mKdp/S7P9mqtn/WJ7T/1ab - 0v9EiMT/RIfD/1ab0v9Zn9T/WZ/U/1mf1P9Zn9T/WZ/U/1mf1P9FhbL/UJTG/1qh1f9aodX/WqHV/1qh - 1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh - 1f9aodX/WqHV/1qh1f9bodX/W6HV/1uh1f9bodX/W6HV/1uh1f9ZoNT/WJ7T/1ie0/9YntP/WJ7T/1ie - 0/9YntP/WJ7T/1if1P9Yn9T/WJ/U/1if1P9Yn9T/WJ/U/1if1P9Yn9T/WJ/U/1if1P9Zn9T/WZ/U/1mf - 1P9ZntT/WZ7U/1me1P9ZntT/WZ7U/1mf1P9Zn9T/WZ/U/1mf1P9bodX/XaLW/1CTwf9Mj7z/XaLW/12i - 1v9dotb/XqLW/16i1v9eotb/XqLW/1md0v8/gL7/TJHI/16i1v9eotb/XqLW/5/S7P9aeYZ6AAAAKgAA - ABIAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAADAAAADwAAACZbeYp2oNPt/3Oz3f9Lksr/Ony7/0uRyv9YntP/WJ7T/1ie0/9YntP/WJ7T/1ie - 0/9YntP/WJ7T/1ie0/9YntP/WJ7T/1mf1P9Zn9T/WZ/U/1mf1P9Zn9T/WZ/U/1mf1P9Zn9T/WZ/U/1mf - 1P9Zn9T/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh - 1f9aodX/WqHV/1qh1f9aodX/WqHV/1qh1f9aodX/WqHV/1uh1f9bodX/W6HV/1uh1f9bodX/W6HV/1uh - 1f9bodX/W6HV/1uh1f9codb/XKHW/1yh1v9codb/XKHW/1yh1v9codb/XKHW/1yh1v9codb/XKHW/12h - 1v9dodb/XaHW/12h1v9dodb/XaHW/12h1v9dodb/XaHW/12h1v9dodb/XaLW/12i1v9dotb/XaLW/12i - 1v9GisT/QYXA/1ug1P9yst3/oNPt/1p5hnoAAAArAAAAEgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAOAAAAJF59jHSYy+b/mMbf/4nA - 3f+95/X/w+z3/8Ps9//D7Pf/w+z3/8Ps9//D7Pf/w+z3/8Ps9//D7Pf/w+z3/8Ps9//D7Pf/w+z3/8Ps - 9//D7Pf/w+z3/8Xs9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs - 9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs - 9//F7Pf/xez3/8Xs9//F7Pf/xez3/8Xs9/+l1+7/pdfu/6XX7v+m2O7/ptju/6bY7v+m2O7/ptju/6bY - 7v+m2O7/ptju/6bY7v+m2O7/ptju/6bY7v+m2O7/ptju/6bY7v+m2O7/ptju/6bY7v+m2O7/ptju/6bY - 7v+m2O7/p9jv/6fY7/+n2O//p9jv/6fY7/+n2O//p9jv/6fY7/+MxOH/Y6HN/6TS5/+n1ez/XYGVhAAA - ACoAAAASAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAQAAAAwAAAAhTW+GcFSRwv9mos3/nc/o/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW - 7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW - 7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW - 7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW7v+h1u7/odbu/6HW - 7v+h1u7/j8jo/5bP7P+c1O//nNTv/5zU7/+c1O//nNTv/5zU7/+c1O//nNTv/5zU7/+c1O//nNTv/5zU - 7/+c1O//nNTv/53U7/+d1O//ndTv/53U7/+d1O//ndTv/53U7/+d1O//ndTv/53U7/+d1O//ndXv/53V - 7/+d1e//ndXv/53V7/+bz+n/ZKHL/2eizP9xnbakAAAAJgAAABAAAAADAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACQAAABtgh5VqmM3q/366 - 4P90sdn/cq7Y/4O94v+Jw+X/i8Tl/4vF5f+Mxub/jcbn/5DH5/+RyOf/k8ro/5bM6f+XzOn/l8zp/5jN - 6v+az+v/m9Ds/5zR7P+d0ez/ntLs/5/S7P+f0uz/oNLs/6HT7f+h1O3/odTu/6TV7v+k1u7/ptfu/6fY - 7/+n2O//qdjv/6nZ8P+q2vD/q9vw/6zb8f+t3PH/rd3x/63d8f+u3fH/r93x/7Dd8f+x3fH/sd3y/7He - 8v+y3vL/st7y/7Pg8/+z4PP/st7y/7Le8v+y3vL/sd7y/7Hd8f+w3fH/sN3x/6/d8f+u3fH/rd3x/63d - 8f+t3PH/rNvx/6va8P+q2vD/qdnw/6jY7/+n2O//ptju/6XX7v+k1u7/pNXu/6HU7v+h1O3/oNPt/6DS - 7P+f0uz/n9Ls/57S7P+c0ez/nNHs/5rP6/+az+v/mM3q/5fM6f+XzOn/icHi/3653f+EvN//jMXj/3qk - t5QAAAAhAAAADAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAEAAAAGAAAAFVZ6i1aTyuj/hMDj/4bA5P+FwOP/erfd/5HE4v/G3+7/x+Hv/8fi - 7//I4u//yOLv/8ni7//J4u7/yeLu/8vj7v/L4+7/zOTv/8zk7//M5PD/zOXw/83l8f/N5fH/zuXx/87l - 8f/Q5vH/0Obx/9Hn8f/R5/H/0efx/9Ln8f/S5/H/0ufx/9Ln8f/S6PH/0ujx/9Lo8v/T6PL/0+ny/9Xp - 8v/V6fL/1erz/9bq8//W6/P/1uvz/9Ln8P/H3+f/1+vz/9fr8//Y7PP/2Ozz/9js8//Y7PP/2Ozz/9fr - 8//X6/P/1+vz/9fr8//W6/P/1uvz/9bq8//V6vP/1eny/9Xp8v/T6fP/0+nz/9Pp8//T6fP/2e73/9nu - 9//N6fX/yOb1/8fm9f/H5vX/xuX0/8bl9P/G5fT/xeTz/8Pk8//D4/P/wuLz/8Hi8v/A4vL/wODx/8Dh - 8f++3/H/q9Xs/4fA4v9/ud3/ksnn/5HH5/+Vy+j/eqe8jgAAABoAAAAIAAAAAQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAPAAAAJozA - 3+iFwOP/hsDk/6HS7P+HweT/mMjk/06Do/8mX4v/Jl+L/yZfi/8mX4v/Jl+L/xpJbv8eUHb/HlB2/x5Q - dv8eUHb/HlB2/yhcff9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5 - lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0d3kP8+an//Ml1y/zJd - cv82YXb/RHKJ/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5 - lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5lP9IeZT/SHmU/0h5 - lP9IeZT/SHmU/06Do/9Og6P/ToOj/06Do/9Og6P/ToOj/06Do/+bxt3/odHr/4vD5P+RyOf/kMfn/5PK - 6P8pQEk4AAAAEwAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAoAAAAdeafBnIjC5f+FwOP/odLs/4fB5P+dzen/d6S9/ydi - jf8nYo3/J2KN/ydijf8nYo3/G0xw/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9U - eP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9U - eP8fVHj/H1R4/x9UeP8bTG//FkNh/xZDYP8WQ2D/FkNg/xZDYP8WQ2D/GUdm/x5Tdv8fVHj/H1R4/x9U - eP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9U - eP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8fVHj/H1R4/x9UeP8bTHD/J2KN/ydijf8nYo3/J2KN/ydi - jf8nYo3/LmmU/73e8f+k0uz/hr/h/5HI5/+Qx+f/gbTRwwAAACEAAAAMAAAAAwAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAA - ABVAXG5IicPl/4XA4/+Rx+f/odLs/5DH5v+hxtn/KmWQ/yplkP8qZZD/KmWQ/yplj/8eT3L/Ild6/yJX - ev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJX - ev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iVnr/G0tr/xlGY/8ZRmP/HkBi/yA9 - Yf8eP2L/G0Ni/xlGY/8ZRmP/GkZl/x5Ocf8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJX - ev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJXev8iV3r/Ild6/yJX - ev8iV3r/Ild6/x5Pcv8qZZD/KmWQ/yplkP8qZZD/KmWQ/yplkP9blLX/w+Ly/5XL6P9/ut7/kcfn/43G - 5/9ql7GAAAAAGAAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACR8ttbchcDj/4bA5P+r2O7/iMLl/6nO - 4v9HfqH/LWiT/y1ok/8taJP/LGaO/yBSdf8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRa - ff8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRa - ff8kWn3/IlZ3/x1Laf8bSmf/G0pn/x9NZv84pID/keC6/5Dguv86m3//IEVm/xtKZ/8bSmf/G0pn/x5O - bv8jWXv/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRa - ff8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/JFp9/yRaff8kWn3/IFJ1/y1ok/8taJP/LWiT/y1o - k/8taJP/LWiT/4m30P+z2u7/ksnn/3653f+Qx+f/gbze9AAAACgAAAARAAAABAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAEAAAAJAAAAG2eZto+EwOP/hsDk/6jX7f+LxeX/qdLq/2OVsv8wbJf/MGyX/zBsl/8vaZL/IlV5/ydd - gf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/J12B/ydd - gf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/Jlx//yJTc/8eTWz/Hk1s/x5NbP8jUGv/RsCL//H7 - 9f/+/v7//v7+/+/69f9Ir4v/IlJr/x5NbP8eTWz/Hk1s/x9Obv8kWXr/J12B/yddgf8nXYH/J12B/ydd - gf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/J12B/yddgf8nXYH/J12B/ydd - gf8nXYH/J12B/yddgf8iVXn/MGyX/zBsl/8wbJf/MGyX/zBsl/8wbJf/udzt/6XS7P+Lw+T/hb7h/4zG - 5v90qMi2AAAAHgAAAAsAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAAUOlttRn+84v+FwOP/j8fn/6HS - 7P+ezun/hbDH/zRvmf80b5n/NG+Z/zJslP8mWHv/KmCE/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/ypg - hP8qYIT/KmCE/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/yhe - gP8iVHP/IlNx/yJTcf8jU3H/I2Ru/2XFnP/x+vX/9vz5/9/56v/e+Or/9fz5//n9+/9yyKT/JlZw/yJT - cf8iU3H/IlNx/yJTcf8kV3f/KV+D/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/ypg - hP8qYIT/KmCE/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/ypghP8qYIT/KmCE/yZYe/8zbpf/NG+Z/zRv - mf80b5n/NG+Z/1WOsP/G4/L/lcvo/4jA4v+HwOL/hcDk/0ZshFcAAAAWAAAABwAAAAEAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAwAAAA4AAAAjbKXIxIO/4/+GwOT/qNju/5HH5v+pzN3/N3Kb/zdym/83cpv/NW+X/yha - fv8tY4j/LWOI/y1jiP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1j - iP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1ih/8pXX7/Jld3/yZXd/8mV3f/JlZ3/ydmcv9u1aL/9/36//H8 - 9v/E9Nj/wPPW/8Dz1v/C9Nj/5fru//H89/9wxqL/KGB0/yZXd/8mV3f/Jld3/yZXd/8mWHf/KmCD/y1j - iP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1jiP8tY4j/LWOI/y1j - iP8tY4j/LWOI/y1jiP8tY4j/KFp+/zVvl/83cpv/N3Kb/zdym/83cpv/ibbO/7Xc7/+Syef/h8Di/4a/ - 4f90sNXoAAAAJQAAAA8AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACAAAABpWiamCfbrh/4XA - 4/+h0+z/i8Tl/7DS5v9Ui6z/O3ae/zt2nv83c5n/Kl6B/zBni/8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBn - i/8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBni/8uZYf/KV58/ylc - ev8pXHr/KVx6/ypbev8ncHT/atOg/+/89f/f+ev/v/PV/8Dz1v/A89b/wPPW/8Dz1v+68tL/2vjn/+n7 - 8/9o05//KGp2/ylcev8pXHr/KVx6/ylcev8pXHr/LGCA/y9niv8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBn - i/8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBni/8wZ4v/MGeL/zBni/8qXoH/N3OZ/zt2 - nv87dp7/O3ae/zt2nv+z1uj/odDp/5LJ5/99ud3/h8Hk/2CWt5wAAAAcAAAACgAAAAEAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAEAAAAFAAAAEyA3RDh1tN7/gb3i/4vE5f+c0ez/rtbt/2+guv8+eqH/Pnqh/zx3 - nP8uYoX/NGuO/zRrjv80a47/NGuO/zRrjv80a47/NGuO/zRrjv80a47/NGuO/zRrjv80a47/NGuO/zRr - jv80a47/NGuO/zRrjv8zao3/MGWH/yxgf/8sYH//LGB//yxgf/8uXn7/JoB0/37frP/m+vH/1/fl/7ny - 0f+/89X/wPPW/8Dz1v/A89b/wPPW/7ry0v+y8cz/yfXd/+D67v+X37z/KXR4/yxgf/8sYH//LGB//yxg - f/8sYH//LGGA/zJoi/80a47/NGuO/zRrjv80a47/NGuO/zRrjv80a47/NGuO/zRrjv80a47/NGuO/zRr - jv80a47/NGuO/zRrjv80a47/NGuO/y5ihf88d5z/Pnqh/z56of8+eqH/Toms/8fk8v+MxOT/kcjn/3q2 - 3P96ueD/MlNsRwAAABQAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAMAAAAIV+b - xMN+uuH/e7je/6DT7f+fzun/k7rQ/0B8o/9AfKP/P3qf/zBkh/83bpH/N26R/zdukf83bpH/N26R/zdu - kf83bpH/N26R/zdukf83bpH/N26R/zdukf83bpH/N26R/zdukf83bpH/NWyP/zJniP8wZYX/MGWF/zBl - hf8wZYX/NGOF/ySIdf+R5Ln/3Prs/7701f+v8cr/tvHP/7zy0//A89b/wPPW/8Dz1v++89T/uPLQ/7Dx - y/+p8Mb/uPPR/9f56f+N5Lf/J4J3/zBlhf8wZYX/MGWF/zBlhf8wZYX/MGWF/zNpi/82bpD/N26R/zdu - kf83bpH/N26R/zdukf83bpH/N26R/zdukf83bpH/N26R/zdukf83bpH/N26R/zdukf83bpH/MGSH/z96 - n/9AfKP/QHyj/0B8o/99rcf/rdPq/4vE5f+Rx+f/gLvg/2ajztsAAAAjAAAADgAAAAMAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgAAAAZToOpgHi23/93s9v/ls3q/5DG5v+00+T/RYCn/0WA - p/9DfqL/NGiL/ztylf87cpX/O3KV/ztylf87cpX/O3KV/ztylf87cpX/O3KV/ztylf87cpX/O3KV/zty - lf87cpX/O3KV/zdvj/81a4v/NWuL/zVri/81a4v/NWuL/zhoiv8dmm3/i+Kz/9L45/+z8s7/pO/C/6vw - x/+y8cz/t/HQ/7vy0v+989T/u/LT/7jy0f+y8cz/rPDI/6bvw/+f7r7/rvHL/8n34f+H4rL/J4p3/zVr - i/81a4v/NWuL/zVri/81a4v/NWuL/zZsi/84cJL/O3KV/ztylf87cpX/O3KV/ztylf87cpX/O3KV/zty - lf87cpX/O3KV/ztylf87cpX/O3KV/ztylf80aIv/Q36i/0WAp/9FgKf/RYCn/7DS5P+UxOL/kcfn/5DH - 5/96uN7/TYKogQAAABkAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAA - ABIAAAAqZqfU9Hq43f9/u+H/hsDk/7jY6v9il7b/SYWq/0aBpf83a43/PnaX/z52l/8+dpf/PnaX/z52 - l/8+dpf/PnaX/z52l/8+dpf/PnaX/z52l/8+dpf/PnaX/zx1lv86cZH/OHCP/zhwj/84cI//OHCP/zhw - j/86cIv/LJ92/47kt//E9t7/ne6//5ntuv+g7sD/pu/E/6zwx/+x8cv/s/HN/7Xxzv+08c3/svHM/63x - yP+o78X/oe7A/5rtu/+U7Lb/l+26/7/12/+f68X/Kp15/zpwj/84cI//OHCP/zhwj/84cI//OHCP/zhw - j/87c5P/PXaX/z52l/8+dpf/PnaX/z52l/8+dpf/PnaX/z52l/8+dpf/PnaX/z52l/8+dpf/PnaX/zdr - jf9GgaX/SYWq/0mFqv9XkLL/y+X0/4G63f+Qx+f/j8fn/26v3f8cM0U3AAAAEgAAAAUAAAABAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAAAACBTkL22fbrh/3Sx2f+GwOT/r9ft/3yr - xP9LiKz/SoWp/zhvkP9Aepv/QHqb/0B6m/9Aepv/QHqb/0B6m/9Aepv/QHqb/0B6m/9Aepv/QHqb/0B6 - m/8/eJj/PXWV/z11lf89dZX/PXWV/z11lf89dZX/P3SR/yCsav+a6sH/ufXY/5Lst/+N7LL/ley3/5vt - u/+h7sD/pe/D/6rwxv+s8Mj/rfHJ/6zwyP+q8Mb/pu/E/6HuwP+c7bz/luy4/4/ss/+I667/jOyz/7H0 - 0v+W6cD/LJ54/zt4kf89dZX/PXWV/z11lf89dZX/PXWV/z11lf8+dpf/QHmZ/0B6m/9Aepv/QHqb/0B6 - m/9Aepv/QHqb/0B6m/9Aepv/QHqb/0B6m/9Aepv/OG+Q/0aBpP9LiKz/S4is/4Oyy/+43fD/erTb/4/H - 5/+IwuX/U5C9tgAAACAAAAAMAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAEAAAAHAAAAFz90mnJvr93/cq/Y/4O+4v+gzur/nsTY/0+LsP9MiKv/PXOT/0V9nv9FfZ7/RX2e/0V9 - nv9FfZ7/RX2e/0V9nv9FfZ7/RX2e/0V9nv9FfZ3/Q3qZ/0F6mf9Bepn/QXqZ/0F6mf9Bepn/QXqZ/0B7 - kP8gqmj/kei9/6fyzP9/6qn/guqq/4nrr/+P7LP/ley4/5rtu/+f7r7/ou7A/6Tvwv+l78P/pO/C/6Lv - wf+g7r//m+28/5fsuf+Q7LT/i+uw/4Pqq/986ab/eumk/6Lxyf+N57r/IKpr/z97lf9Bepn/QXqZ/0F6 - mf9Bepn/QXqZ/0F6mf9Bepn/Q3ub/0V9nv9FfZ7/RX2e/0V9nv9FfZ7/RX2e/0V9nv9FfZ7/RX2e/0V9 - nv89c5P/SoSn/0+LsP9Pi7D/stPl/6nU7P98ud3/jcbn/3i33/8/dJpyAAAAFwAAAAcAAAABAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAKFmc0PR8ud//eLTc/5DG - 5v+92un/VI+y/1CMrv9Adpf/SYGh/0mBof9JgaH/SYGh/0mBof9JgaH/SYGh/0mBof9JgaH/SYGh/0d/ - n/9Hf5//R3+f/0d/n/9Hf5//R3+f/0d/n/9BgpH/LLlt/4jnuP+c8cb/c+eh/3boov996af/g+qr/4rr - r/+O7LP/lOy2/5ftuf+a7bv/nO69/53uvf+d7r3/m+27/5jtuf+V7Lf/kOy0/4vrsP+F6qz/fumo/3jo - o/9x557/beec/5PwwP+U7sT/NLJ5/0SAm/9Hf5//R3+f/0d/n/9Hf5//R3+f/0d/n/9Hf5//SICg/0mB - of9JgaH/SYGh/0mBof9JgaH/SYGh/0mBof9JgaH/SYGh/0B2l/9Niar/VI+y/2CYuP/M5fL/kMbl/4W/ - 4v+Nxuf/Wp3R9AAAACcAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAgAAAAsAAAAeRIOyqXq44P9sqtX/hcDj/73d7f9wo8D/VI6w/0R6mv9MhqX/TIal/0yG - pf9MhqX/TIal/0yGpf9MhqX/TIal/0yGpf9MhqT/TIak/0yGpP9MhqT/TIak/0yGpP9MhqT/R4aV/ym2 - af+O7cD/he21/2fnmP9q55n/ceee/3joov996af/g+qq/4jrrv+M7LL/kOy0/5Pstv+U7Lf/ley4/5Xs - t/+T7Lb/kOy0/43ssv+J66//hOqr/37pqP956KP/cuef/2vnmv9k5pb/XeSQ/3/ssv+K7L//KLVs/z6I - lf9MhqT/TIak/0yGpP9MhqT/TIak/0yGpP9MhqT/TIak/0yGpf9MhqX/TIal/0yGpf9MhqX/TIal/0yG - pf9MhqX/RHqa/1KMrP9YlLb/ibfP/8Hh8f+HwOL/hL7i/4G+4v9Eg7KpAAAAHgAAAAoAAAACAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwAAABYpVHdYZanY/3Ow - 2v98ud//sdft/4u5zv9XkLD/SH2d/1KKqf9Siqn/Uoqp/1KKqf9Siqn/Uoqp/1KKqf9Siqn/Uoqp/1KK - qf9Siqn/Uoqp/1KKqf9Siqn/U4qp/zyPhv8it2D/hOy7/3rsr/9W44z/XeWR/2Tmlv9r55r/cuef/3fo - ov986ab/geqq/4XqrP+I667/i+uw/4zssv+M7LL/jOyy/4vrsf+J66//huqs/4Lqqv996af/eOij/3Pn - oP9s55v/ZuaX/1/lkv9Y5I3/T+KI/3DqqP9/7Ln/J7Np/0OLmP9Siqn/Uoqp/1KKqf9Siqn/Uoqp/1KK - qf9Siqn/Uoqp/1KKqf9Siqn/Uoqp/1KKqf9Siqn/Uoqp/1KKqf9IfZ3/V5Cw/12Xuf+11eX/qdTs/365 - 3v+Gv+L/aaza/ypWelYAAAAVAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAADAAAAEAAAACZLksnofbrg/26s1/+gzun/qsze/1uVs/9LgaD/VY2r/1WN - q/9Vjav/VY2r/1WNq/9Vjav/VY2r/1WNq/9Vjav/VY2r/1WNq/9Vjav/VY2r/1WMq/8/kIf/Lr1r/3rr - tv9h55v/SeKD/1Diif9Y5I3/XuWS/2Xmlv9r55r/cOee/3Xoof966KT/femn/4Dpqf+C6qr/hOqr/4Tq - q/+E6qv/g+qq/4Dpqf996af/euik/3boof9x55//bOeb/2bml/9g5ZL/WeSO/1Ljiv9K4oT/Q+F//1fm - lP967rn/NMB2/zeRif9Vjav/VY2r/1WNq/9Vjav/VY2r/1WNq/9Vjav/VY2r/1WNq/9Vjav/VY2r/1WN - q/9Vjav/VY2r/0uBoP9blbP/bKPA/83l8f+Vyuf/erXc/4vF5f9Nk8noAAAAJQAAAA8AAAADAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAKAAAAHjl5 - sKl2td7/bKrV/4/F5f/F3uz/X5i3/0+Go/9ak6//WpOv/1qTr/9ak6//WpOv/1qTr/9ak6//WpOv/1qT - r/9ak6//WpOv/1qTr/9bkq//LZds/zK/bv917bf/T+WQ/zvgev9D4X//SuKE/1Ljif9Y5I3/XuWR/2Tm - lv9p5pj/buec/3Lnn/916KH/eOij/3ropP976aX/e+mm/3vppf966KX/eeij/3boof9z56D/b+ec/2rn - mf9l5pb/X+WS/1nkjv9T44r/S+KF/0XigP894Hv/NN93/0nkjP9v7bT/L75v/zqTi/9ak6//WpOv/1qT - r/9ak6//WpOv/1qTr/9ak6//WpOv/1qTr/9ak6//WpOv/1qTr/9ak6//T4aj/16Xtf+QvNL/w+Hx/4zG - 5v91sdn/dbTe/zNvo5AAAAAcAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAWGD9eSV2h1v9zsNr/drPc/8Lf7v96q8T/U4mm/16W - sv9elrL/Xpay/16Wsv9elrL/Xpay/16Wsv9elrL/Xpay/16Wsv9elrL/YJWy/y6XbP8svWr/ZOyt/zji - f/8t3nL/Nd93/z3ge/9E4YD/SuKF/1Ljif9X44z/XeSQ/2HllP9m5pf/aueZ/23nm/9w553/cuef/3Pn - oP9z56D/c+eg/3Lnn/9w557/buec/2vnmf9n5pf/YuWU/17lkf9Y5I3/U+OK/0zihf9F4oH/PuF8/zbf - eP8u3nP/Jt1u/y3fd/9f66r/Kbtr/yqWcv9elrL/Xpay/16Wsv9elrL/Xpay/16Wsv9elrL/Xpay/16W - sv9elrL/Xpay/16Wsv9Tiab/YZm2/7TU5P+q1Oz/i8Xl/3m03P9dodb/GUJiRgAAABQAAAAGAAAAAQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA - AA8AAAAjP4fB24C94v9urNf/stjt/5W+0v9Xi6r/Ypm2/2KZtv9imbb/Ypm2/2KZtv9imbb/Ypm2/2KZ - tv9imbb/Ypm2/16Xr/8bmFP/MMRz/1jqp/8k3nL/Hd1o/ybdbv8u3nP/Nd93/z3ge/9E4YD/SuKE/0/i - iP9V44v/WuSO/17lkf9i5ZT/ZeaW/2fml/9p5pj/aueZ/2rnmv9q55n/aeeY/2fml/9l5pf/YuWU/1/l - kv9b5I//VuOL/1Diif9L4oX/ReKA/z7hfP834Hj/L950/yfdb/8e3Wn/FNxk/x3ebv9T6aT/Ns2A/yyW - c/9imbb/Ypm2/2KZtv9imbb/Ypm2/2KZtv9imbb/Ypm2/2KZtv9imbb/Ypm2/1eLqv9robv/0efy/5TJ - 5/+LxeX/erfd/zqBucIAAAAgAAAADgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAABYvd7ivaqzb/3Sx2/+Rw+L/stfn/5TG - 2f+Uxdn/lMXZ/5TF2f+Uxdn/lMXZ/5TF2f+Txdn/k8XZ/5PF2f+Kvs//HpZO/zLMe/9D55f/ENxl/wvb - X/8U3GT/Ht1p/yfdbv8u3nP/Nd93/zzge/9B4X//SOKD/03ihv9S44n/VuOL/1nkjv9c5JD/XuWR/2Dl - k/9h5ZP/YeWU/2HllP9g5ZP/X+WS/1zkkP9a5I7/V+OM/1Pjiv9N4of/SeKD/0ThgP894Hv/NuB4/y/f - dP8o3W//H91q/xfcZf8N22D/Atpb/wjZXv8+5pb/Lct7/x2WXP99uMv/iLzV/4i81f+IvNT/iLzU/4i8 - 1P+Hu9T/h7vU/4e71P+Hu9T/hrvU/5DB2f+x1er/gLvg/4W+4v9rrdv/LXOulAAAABQAAAAIAAAAAQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAEAAAAFAAAADCJjm1JMk8z/bqzX/3y53/+XzOj/nNHs/53R7P+d0ez/ndLs/53S7P+d0uz/ntLs/57S - 7P+e0uz/h8bQ/xOYPv8oynf/OOWS/wjYXP8A2Fn/Atpb/w3bYP8W3GX/Ht1p/yfdbv8t3nL/NN92/zrg - ev8/4X3/ReKA/0nig/9N4ob/UOKI/1Pjiv9V44v/V+SM/1jkjf9Y5I3/WOSN/1fkjP9W44v/VOOL/1Di - if9N4of/SuKE/0bigf9A4X3/O+B6/zXfd/8v3nP/KN1v/yDdav8X3Gb/Dtth/wTaXP8A2Fr/ANdY/wbX - W/8z5JD/Jsl3/yecZv+NyOD/lszp/5XL6f+Vy+j/lMro/5PK6P+Tyuj/k8no/5LJ5/+SyOf/kcjn/4zG - 5v+Au+D/c7DY/0aLxv8ybJtCAAAACwAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAAC2GbxXt/u+L/f7vi/4C9 - 4v+DvuP/g7/j/4TA4/+GwOT/hsDk/4bA5P+HweT/iMLl/3S2yf8RmED/IM14/yfhhP8G1Vn/ANVW/wDX - WP8A2Fn/Atpc/w3bYP8W3GX/Ht1p/yTdbf8s3nH/Mt91/zfgeP884Hr/QOF9/0TigP9H4oL/SuKE/0zi - hf9N4of/TuKH/0/iiP9O4of/TeKH/0zihv9K4oT/SOKD/0XigP9B4X7/PeB7/zfgef8z33X/Ld5y/ybd - bv8f3Wr/F9xl/w7bYf8E2lz/ANla/wDYWP8A1lb/ANNV/wDSU/8f3n3/ItaD/x6ZW/92vMr/kcfn/5DH - 5/+Px+f/j8fn/43G5/+Mxub/i8Xl/4vF5f+LxOX/isPl/4nD5f+EveDxXZjDawAAAAoAAAAFAAAAAQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAEAAAADAAAABz1whRlpocRJaaDCS2qcuU1jlbFSXYukWld9mGZLb4d3Q2J2ijxZ - aZ0teWLVEJY8/xrWfv8a3Xr/ANBQ/wDSU/8A01X/ENdd/xTYYP8f3Gj/JN1s/yneb/864Hn/QeF9/0bi - gP9K4oT/TuKG/1Pjif9W44v/WeSN/1zkjv9e5JD/X+WS/17lkf9Y5Iz/WeSN/1bji/9O4of/SuKE/0Hh - fv8+4Xz/O+B6/zfgef8033b/L95z/ynecP8j3Wz/Hd1p/xbcZf8N22D/BNpc/wDZWv8A2Fj/ANZX/wDU - Vf8A0lP/ANFQ/wDPT/8W3Xn/FNR9/xSUSv8za2W/Ql1rmktneIhRc4d1W4OaZWSSqVlrmrZRcKK9TXKh - v0xypcRKc6jHSQAAAAkAAAAGAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAA - AAMAAAAGAAAADAAAABcAAAApAAAAQAAAAFoAAABzAEwStQCPKf8L1Hn/Ddhu/wDNTf8Q0Vf/O9hy/0Hb - d/9B3Hj/Qd16/0Heev9B4Hv/QeF9/0Xif/9K4oP/TuKG/1LjiP9W44v/WeSM/1zkj/9e5ZD/YeWS/2Lm - k/9k5pT/ZeaV/2bmlv9m5pb/ZuaW/2Xmlf9k5pT/Y+aT/17lkf9V44r/SeKD/z3he/8z33X/IN1q/xrd - Z/8T3GP/C9tf/wLaXP8A2Fr/ANhY/wDWV/8A1FX/ANJT/wDRUv8Az0//AM1N/wDMS/8G02P/CNJ4/wWH - NfgBTRyzAAAAcAAAAFcAAAA9AAAAJgAAABUAAAALAAAABQAAAAMAAAACAAAAAQAAAAEAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAAAAoAAAAXAAAAKQAAAEAAAABaAAAAcwBe - E8sAlzP/ANV4/wLSYf8Aykr/G89Z/0PXdP9G2Hj/Rtp5/0bcev9G3Xv/Rt18/0bfff9G4H7/RuF//0ji - gf9M4oT/T+KG/1Pjif9W5Iv/WeSM/1vkjv9d5Y//X+WQ/2Hlkv9i5ZP/YuWT/2Lmk/9i5ZP/YuWT/2Hl - kv9f5ZH/XuWQ/1zkjv9Z5Iz/V+SL/1Tjif9Q44f/P+F8/zDfc/8d3Gf/ANhZ/wDXWP8A1lb/ANRV/wDS - U/8A0VL/AM9P/wDNTf8AzEz/AMpK/wDISP8A0V//Atp9/wqWPv8BShizAAAAcQAAAFcAAAA9AAAAJgAA - ABUAAAAJAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA - AAUAAAAMAAAAGQAAACwAAABDAAAAXgAAAHYAYxPTAJQu/wDXdv8AzVn/AMZH/yLNWv9L1nf/S9h5/0vY - ev9L2Xr/S9t8/0vcff9L3X7/S95//0vfgP9L4IH/S+KC/0vig/9N4oX/UOOH/1Tjiv9X44v/WeSM/1vk - jf9c5Y//XuWQ/1/lkP9f5ZD/YOWQ/1/lkP9f5ZD/XuWQ/13lj/9b5I7/WeSM/1fji/9V44r/UuOI/07i - hv9M4oP/S+KC/0vhgf9L34D/PN12/yfYaP8N01n/ANFS/wDPT/8AzU7/AMxM/wDKSv8AyEn/AMZH/wDF - Rf8AylP/ANV0/wSVMv8BXRjLAAAAcwAAAFoAAABAAAAAKAAAABYAAAAKAAAABAAAAAEAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAADAAAABoAAAAuAAAARgAAAGEAEACBAGoQ4gCX - MP8A03H/AMZN/wDDQ/8ozFz/T9R4/0/Wev9P13r/T9h7/0/ZfP9P2n3/T9x//0/df/9P3YH/T96C/0/f - gv9P4YP/T+KE/0/ihf9P4ob/UuOI/1Tjif9W44v/WOSL/1rkjP9b5I3/XOSO/1zkjv9c5Y7/XOWO/1zk - jv9b5I7/WuSM/1jki/9W5Iv/VeOJ/1LjiP9Q4ob/T+KF/0/ihP9P4YT/T+CD/0/fgv9P3YH/T92A/0/c - f/9D2Hb/KNNj/w7NU/8Ay0r/AMlJ/wDHR/8AxkX/AMRE/wDCQf8AxUv/ANJv/wCSKv8AXxDTAAAAdgAA - AF0AAABCAAAAKwAAABcAAAALAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwAA - AAoAAAAYAAAALgAAAEgAAABjAA8AhABsBeoAmjT/AM5n/wDDSf8AwD//OMxk/1TSef9U1Hr/VNV6/1TX - fP9U2H3/VNh+/1Taf/9U24D/VNyB/1Tdgv9U3YP/VN+E/1Tfhf9U4IX/VOGG/1Tih/9U4oj/VOKI/1Tj - if9V44r/V+SL/1jki/9Y5Iz/WeSM/1nkjP9Z5Iz/WOSM/1jki/9X5Iv/VuOL/1Xjif9U44j/VOKI/1Ti - h/9U4of/VOGG/1Tghf9U34T/VN6D/1Tdgv9U3IL/VNuA/1Taf/9U2X7/VNh9/z3Sbv8gzFn/AMZG/wDE - RP8AwkH/AMA//wC/Pv8AwET/ANBo/wCfOP8AagniABAAgAAAAF8AAABEAAAAKwAAABYAAAAKAAAAAwAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAEgAAACcAAABEAAAAYgApAJUAawHxAKE7/wDN - Zf8AvT7/CL5A/zzKZP9Y0nr/WNJ6/1jUe/9Y1X3/WNZ+/1jYf/9Y2ID/WNmB/1jagv9Y24P/WN2E/1jd - hf9Y3oX/WN+G/1jfh/9Y4Ij/WOGI/1jiif9Y4or/WOKK/1jii/9Y44v/WOOL/1jji/9Y44v/WOOL/1jj - i/9Y44v/WOOL/1jji/9Y4ov/WOKK/1jiiv9Y4on/WOGI/1jgiP9Y4If/WN+H/1jehv9Y3YX/WN2E/1jc - g/9Y2oL/WNmB/1jYgP9Y2H//WNd+/1jVff9O0nb/Mstg/wjCRP8Avz7/AL08/wC7O/8Auzz/AMxj/wCb - NP8AaQPqABAAgQAAAF4AAABAAAAAJAAAABEAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA - AAoAAAAbAAAANQAAAFgAKgCQAG4A+ACfOP8AyF3/ALk6/wq6Pf9NzG//XNB6/1zRe/9c0nz/XNN+/1zV - fv9c1oD/XNeB/1zYgv9c2YP/XNqE/1zbhf9c3Ib/XN2G/1zdh/9c3oj/XN+I/1zfif9c4Ir/XOGL/1zh - i/9c4ov/XOKL/1zii/9c4oz/XOKM/1zijP9c4oz/XOKM/1zijP9c4oz/XOKL/1zii/9c4ov/XOGL/1zh - i/9c4Ir/XN+J/1zfif9c3oj/XN2H/1zdhv9c3Ib/XNuF/1zahP9c2YP/XNiC/1zXgf9c1oD/XNV//1zU - fv9c0nz/V9B5/zTHXf8KvT//ALk4/wC4Nv8AuDj/AMNV/wCdNf8AZwDpACsAjgAAAFUAAAAzAAAAGQAA - AAkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAAAACEAAABAAEIAlgBvAPcApz//AMFS/wC0 - M/8RuT7/Uspv/2DPe/9g0H3/YNJ+/2DSf/9g04D/YNWB/2DWgv9g14P/YNiE/2DYhf9g2Yb/YNqH/2Db - iP9g3Ij/YN2J/2Ddiv9g3ov/YN6L/2Dfi/9g4Iv/YOCM/2DhjP9g4Y3/YOKN/2Dijf9g4o3/YOKN/2Di - jf9g4o3/YOKN/2Dijf9g4o3/YOGN/2DhjP9g4Iz/YOCL/2Dfi/9g34v/YN6L/2Ddiv9g3Yn/YN2I/2Dc - iP9g2of/YNqG/2DYhf9g2IT/YNeD/2DWgv9g1YH/YNSA/2DSf/9g0n7/YNF9/1vOeP83w1v/Crg6/wC1 - M/8AsjD/AMBP/wCpQP8AbgD3AC0AgQAAAD4AAAAgAAAADAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAMAAAAOAAAAJQApAF0AdgT/AKxE/wC8Sf8AsS//GrhA/1/MeP9kzn3/ZM9+/2TQf/9k0oD/ZNKB/2TT - gv9k1IP/ZNWE/2TXhf9k2Ib/ZNiH/2TZiP9k2on/ZNuK/2Tciv9k3Yv/ZN2L/2Tdi/9k3oz/ZN6N/2Tf - jf9k4I3/ZOCO/2Tgjv9k4Y7/ZOGP/2Thj/9k4Y//ZOGP/2Thj/9k4Y//ZOGP/2Thjv9k4I7/ZOCO/2Tg - jf9k343/ZN6N/2TejP9k3Yv/ZN2L/2Tdi/9k3Ir/ZNuK/2Taif9k2Yj/ZNiH/2TYhv9k14b/ZNaE/2TU - hP9k04L/ZNKC/2TSgP9k0X//ZM9+/2TOff9aynT/J7tK/wCyL/8AsC3/ALhB/wCpQP8AbgD2ABYAUQAA - ACQAAAAOAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABAAAAAmAD8AdgCgNf8AtDz/AK4q/yK3 - Q/9jy3r/ac1+/2nOgP9pz4D/adCC/2nSg/9p0oT/adOF/2nUhv9p1Yb/adaH/2nYiP9p2In/adiK/2nZ - i/9p2ov/aduL/2ncjP9p3Y3/ad2N/2ndjv9p3o//ad6P/2nfj/9p35D/ad+Q/2ngkP9p4JH/aeCR/2ng - kf9p4JH/aeCR/2ngkf9p4JH/aeCR/2ngkP9p35D/ad+P/2nej/9p3o//ad2O/2ndjf9p3Y3/adyM/2nb - i/9p2ov/adqL/2nZiv9p2In/adiI/2nXiP9p1of/adSG/2nThf9p0oT/adKD/2nRgv9pz4H/ac6A/2nN - fv9pzH7/U8Vr/xOyNv8ArCn/ALI6/wCfNP8APwB2AAAAJgAAABAAAAADAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAADAAAAEAAAACcAQAB3ALI6/wCqJ/8wuEv/bct//23MgP9tzYH/bc6C/23Pg/9t0IT/bdKF/23S - hv9t04f/bdSI/23Vif9t1or/bdeK/23Yi/9t2Iv/bdmM/23ajP9t243/bduO/23cjv9t3Y//bd2Q/23d - kP9t3ZD/bd6R/23ekf9t35L/bd+S/23fkv9t35L/bd+S/23gkv9t4JL/bd+S/23fkv9t35L/bd+S/23e - kf9t3pH/bd6Q/23dkP9t3ZD/bd2P/23cjv9t247/bduN/23ajP9t2Yz/bdiL/23Yi/9t14v/bdaK/23V - if9t1Ij/bdOH/23Shv9t0oX/bdGE/23Pg/9tzoL/bc2B/23MgP9tzH//Z8h6/zC2Sv8AqSb/ALE3/wBA - AHcAAAAnAAAAEAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAQAAAAJwBAAHcNqir/iNKU/7rk - wf+65cH/uuXC/7rmwv+65sP/uufD/7rnxP+658T/uujF/7roxf+66cb/uunG/7rqxv+66sb/i96h/3HY - jf9x2Y7/cdmO/3Haj/9x25D/cdyQ/3Hckf9x3ZL/cd2S/3Hdkv9x3ZP/cd2T/3Hek/9x3pP/cd6T/3Hf - lP9x35T/cd+U/3HflP9x35T/cd6T/3Hek/9x3pP/cd2T/3Hdk/9x3ZL/cd2S/3Hdkv9x3JH/cdyQ/3Hb - kP9x2o//cdmO/3HZjv9x2I3/cdiM/5Xgqf+66sb/uunG/7rpxv+66cX/uujF/7roxf+658T/uufD/7rn - w/+65sL/uuXC/7rlwf+65MH/uuTA/4bQkv8NqCn/AD8AdgAAACcAAAAQAAAAAwAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAwAAAA8AAAAmAD8AdiOhNP90yYH/ntmn/6nesv+p3rL/qd+y/6ngs/+p4bT/qeG0/6ni - tf+p4rX/qeK2/6njt/+p5Lf/qeS4/4zdof9n1IX/JMZU/2LUgv912ZD/ddqR/3Xakv9125L/ddyT/3Xc - k/913ZP/dd2U/3XdlP913ZX/dd2V/3Xdlf913pX/dd6V/3Xelf913pX/dd6V/3Xelf913pX/dd2V/3Xd - lf913ZX/dd2V/3XdlP913ZP/ddyT/3Xck/9125L/dduS/3Xakf912ZD/ddiQ/2LTgf8kxVP/Z9OE/4zd - of+p5Lf/qeO3/6nitv+p4rX/qeK1/6nhtP+p4bT/qeCz/6nfs/+p3rL/qd6y/6ndsf+e2Kf/dMiA/yOn - Nv8AQQB1AAAAJgAAAA8AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADgAAACMARABxFIUg/5rS - ov+q27L/qtuz/6rcs/+q3bT/qt20/6rdtf+q3rX/qt62/6rft/+q4Lf/quC3/6rguP+q4bn/qOC3/03I - b/8AvT3/X9J+/3nZkv952ZP/edqU/3nblP9525X/edyV/3nclf953Zb/ed2W/3ndl/953Zf/ed2X/3nd - l/953Zf/ed2X/3ndl/953Zf/ed2X/3ndl/953Zf/ed2X/3ndl/953Zb/ed2W/3nclf953JX/eduV/3nb - lP952pT/edmT/3nZkv952JL/X9F9/wC8PP9czXr/qeC3/6rhuP+q4Lj/quC3/6rft/+q3rb/qt62/6rd - tf+q3bX/qt20/6rcs/+q27P/qtuy/6rasv+Tzpz/AH0L/wBEAHEAAAAjAAAADQAAAAIAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAIAAAALAAAAHQBGAGooizD/f7yJ/3+9iv9/vov/f7+L/3/AjP9/wI3/f8CN/3/B - jv9/wo//f8OQ/3/Ekf9/xJH/f8WS/3/Gk/9/xpT/ZMR+/wC7O/9i0n//fNiU/3zZlf982pb/fNqW/3zb - lv9825f/fNyX/3zcl/983Jf/fN2X/3zdmP983Zj/fN2Y/3zdmP983Zj/fN2Y/3zdmP983Zj/fN2Y/3zd - mP983Zj/fN2Y/3zdl/983Jf/fNyX/3zbl/9825f/fNqW/3zalv982ZX/fNmU/3zYlP9i0X7/ALo6/2TH - fv9/xpP/f8WS/3/Fkf9/xJH/f8OQ/3/Cj/9/wY7/f8CO/3/Ajf9/wIz/f7+L/3++i/9/vYr/f7yJ/3+7 - iP8fgiP/AEYAaQAAAB0AAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAVAEsAXyKI - Kv9rsXb/a7J3/2uzeP9rtHn/a7V6/2u2ev9rt3v/a7h8/2u5ff9ruX7/a7p//2u7gP9ru4D/a7yB/2u9 - gv9VvHH/ALk4/2XRgP+A2Jf/gNmX/4DZl/+A2pf/gNuX/4DbmP+A25j/gNyY/4Dcmf+A3Jn/gN2a/4Dd - mv+A3Zr/gN2a/4Ddmv+A3Zr/gN2a/4Ddmv+A3Zr/gN2a/4Ddmv+A3Zn/gNyZ/4DcmP+A25j/gNuY/4Db - l/+A2pf/gNqX/4DZl/+A2Jf/gNiW/2XQf/8AuTf/VcBx/2u8gf9rvIH/a7uA/2u6f/9ruX7/a7l9/2u4 - fP9rt3z/a7Z6/2u1ev9rtHn/a7N5/2uyeP9rsnf/a7F2/yKDJv8ATwBeAAAAFAAAAAcAAAABAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAABAAAABAAAAAwAVgBTEHwU/1emYv9Xp2P/V6hk/1eqZf9Xqmb/V6tn/1es - aP9XrWn/V65q/1eva/9XsGz/V7Ft/1eybv9Xsm//V7Nw/zKuVP8Atzb/aNCB/4TYmP+E2Zn/hNqZ/4Ta - mv+E2pr/hNua/4Tbm/+E3Jv/hNyb/4Tcm/+E3Jz/hN2c/4TdnP+E3Zz/hN2c/4TdnP+E3Zz/hN2c/4Td - nP+E3Zz/hNyc/4TcnP+E3Jv/hNyb/4Tbm/+E25r/hNua/4Tamv+E2pn/hNmZ/4TZmP+E2Jj/aNCB/wC2 - Nf87t1v/V7Jv/1eybv9XsW3/V7Bs/1eva/9Xrmv/V61p/1esaP9Xq2f/V6pm/1eqZf9XqWT/V6dj/1em - Yv9Tolz/CngL/wBQAEMAAAAMAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAA - AAwAawCnG38d/zWPO/81kT3/NZE9/zWSPv81kj//NZM//zWUQP81lED/NZVB/zWVQf81lkP/NZZD/zWX - RP8ulD3/CJMm/wC1M/9r0IP/iNib/4jZm/+I2Zv/iNqc/4janf+I253/iNud/4jcnv+I3J7/iNye/4jc - nv+I3Z7/iN2e/4jdn/+I3Z//iN2f/4jdn/+I3Z//iN2e/4jdnv+I3J7/iNye/4jcnv+I3J7/iNud/4jb - nf+I253/iNqc/4jZm/+I2Zv/iNib/4jYmv9rz4L/ALQz/wieKv8ukz3/NZZD/zWWQ/81lUH/NZVB/zWU - QP81lED/NZM//zWTP/81kj7/NZE9/zWRPf81kDz/NY87/xt/Hf8AawCnAAAADAAAAAUAAAACAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAABAAAAAcAWwA4AGAASgBfAEsAXgBMAF4ATABe - AEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAWABRAE8AXQBEAHEAewriALIw/2/PhP+M2J3/jNme/4za - nv+M2p7/jNqf/4zbn/+M25//jNug/4zcoP+M3KD/jNyg/4zcoP+M3aH/jN2h/4zdof+M3aH/jN2h/4zd - of+M3aH/jNyg/4zcoP+M3KD/jNyg/4zcoP+M25//jNuf/4zan/+M2p7/jNqe/4zZnv+M2Z3/jNid/2/P - g/8AsjD/AIkcwQBFAGsAVQBaAFoATwBeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABf - AEsAYABKAFEAKQAAAAcAAAAEAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAABAAAAAQAAAAEAAAACAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAA - AAoAAAAcAAAAOAB5DdcAsS7/cs+F/5DZoP+Q2aD/kNqg/5Daof+Q26H/kNuh/5Dbof+Q26H/kNyh/5Dc - of+Q3KL/kNyi/5Dcov+Q3aL/kN2i/5Ddov+Q3aL/kN2i/5Dcov+Q3KL/kNyi/5Dcof+Q3KH/kNuh/5Db - of+Q26H/kNuh/5Daof+Q2qD/kNmg/5DZoP+Q2J//cs6F/wCwLv8Ahx+qAAAAMQAAABcAAAAIAAAAAwAA - AAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAIAAAABAAAAAQAAAAEAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABoAAAA3AHgM1gCvLP91zof/lNmh/5TZ - of+U2qL/lNqi/5Tao/+U26P/lNuj/5Tbo/+U3KT/lNyk/5TcpP+U3KT/lNyk/5TcpP+U3KT/lNyk/5Tc - pP+U3KT/lNyk/5TcpP+U3KT/lNyk/5TcpP+U3KP/lNuj/5Tbo/+U26P/lNqi/5Taov+U2aH/lNmh/5TY - of91zob/AK4s/wCGHakAAAAvAAAAFQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAIAAAAGgAAADcAeArWAKwp/3jOiP+X2aP/l9qk/5fapP+X2qX/l9ul/5fbpf+X26X/l9ym/5fc - pv+X3Kb/l9ym/5fcpv+X3af/l92n/5fdp/+X3af/l92n/5fdp/+X3af/l9yn/5fcpv+X3Kb/l9ym/5fc - pv+X26b/l9ul/5fbpf+X2qX/l9qk/5fapP+X2aT/l9mj/3jNiP8Aqyj/AIMdqQAAAC8AAAAVAAAABQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAaAAAANwB4CtYAqif/es6K/5vZ - pv+b2qf/m9qn/5vbp/+b26f/m9uo/5vcqP+b3Kj/m9yo/5vcqf+b3Kn/m92p/5vdqf+b3an/m92p/5vd - qf+b3an/m92p/5vdqf+b3an/m9yp/5vcqf+b3Kj/m9yo/5vcqP+b26j/m9un/5vbp/+b2qf/m9qn/5vZ - pv+b2ab/es2J/wCqJv8AghqpAAAALwAAABUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAACAAAABoAAAA3AHgH1gCoJP99zYv/n9qp/5/aqf+f26n/n9uq/5/bqv+f3Kr/n9yq/5/c - qv+f3Kr/n9yq/5/dqv+f3ar/n92q/5/dqv+f3ar/n92r/5/dqv+f3ar/n92q/5/dqv+f3ar/n92q/5/c - qv+f3Kr/n9yq/5/cqv+f26r/n9uq/5/bqf+f2qn/n9qp/5/ZqP99zYv/AKcj/wCAGKkAAAAvAAAAFQAA - AAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGgAAADcAdwfWAKYi/4DN - jP+i2qv/otur/6Lbq/+i26v/otys/6LcrP+i3Kz/otys/6LdrP+i3a3/ot2t/6Ldrf+i3a3/ot2t/6Ld - rf+i3a3/ot2t/6Ldrf+i3a3/ot2t/6Ldrf+i3a3/ot2s/6LcrP+i3Kz/otys/6LcrP+i26v/otur/6Lb - q/+i2qv/otqq/4DNi/8ApSD/AH8VqQAAAC8AAAAVAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAgAAAAaAAAANwB2BtYAox//g82N/6bbrf+m263/ptuu/6bcrv+m3K7/pt2v/6bd - r/+m3a//pt2v/6bdr/+m3a//pt2w/6bdsP+m3bD/pt2w/6bdsP+m3bD/pt2w/6bdsP+m3bD/pt2v/6bd - r/+m3a//pt2v/6bdr/+m3a//ptyu/6bcrv+m3K7/ptut/6bbrf+m263/g8yN/wCjHv8AfRSpAAAALwAA - ABUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABoAAAA3AHUG1gCh - Hf+GzY//qtuw/6rcsP+q3LH/qt2x/6rdsf+q3bH/qt2y/6rdsv+q3bL/qt2y/6rdsv+q3bL/qt2y/6rd - sv+q3bL/qt2y/6rdsv+q3bL/qt2y/6rdsv+q3bL/qt2y/6rdsv+q3bL/qt2y/6rdsf+q3bH/qt2x/6rc - sf+q3LD/qtuw/6rbsP+GzI7/AKEb/wB6D6kAAAAvAAAAFQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAIAAAAGgAAADcAcgTWAJ8a/4nNkP+t3LL/rd2y/63dsv+t3bP/rd2z/63d - s/+t3bP/rd2z/63ds/+t3bT/rd60/63etP+t3rT/rd60/63etP+t3rT/rd60/63etP+t3rT/rd60/63e - tP+t3bT/rd20/63ds/+t3bP/rd2z/63ds/+t3bP/rd2z/63dsv+t3LL/rdyy/4nMkP8Anxn/AHkPqQAA - AC8AAAAVAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAaAAAANwBy - BNYAnRb/i82S/7Hdtf+x3bX/sd21/7Hdtv+x3bb/sd22/7Hdtv+x3rb/sd62/7Het/+x3rf/sd63/7He - t/+x37f/sd+3/7Hft/+x37f/sd+3/7Het/+x3rf/sd63/7Het/+x3rb/sd62/7Hdtv+x3bb/sd22/7Hd - tv+x3bX/sd21/7Hdtf+x3bX/i8yS/wCcFv8AeQupAAAALwAAABUAAAAFAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABoAAAA3AHIE1gCaE/+OzZT/tN24/7TduP+03bj/tN65/7Te - uf+03rn/tN65/7Teuf+03rn/tN+5/7Tfuf+037n/tN+5/7Tfuf+037n/tN+5/7Tfuf+037n/tN+5/7Tf - uf+037n/tN+5/7Tfuf+03rn/tN65/7Teuf+03rn/tN65/7TduP+03bj/tN24/7TduP+OzJP/AJoT/wB2 - C6kAAAAvAAAAFQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGgAA - ADcAcgHWAJgQ/5HNlf+43rr/uN66/7jeu/+437v/uN+7/7jfu/+437v/uN+7/7jgvP+44Lz/uOC8/7jg - vP+44Lz/uOC8/7jgvP+44Lz/uOC8/7jgvP+44Lz/uOC8/7jgvP+44Lz/uOC8/7jfu/+437v/uN+7/7jf - u/+437v/uN+7/7jeuv+43rr/uN66/5HNlf8AlxD/AHQFqQAAAC8AAAAVAAAABQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAaAAAANwBxANYAlg3/lM2X/7vfvf+7373/u9++/7vg - vv+74L7/u+C+/7vgvv+74L7/u+C+/7vhv/+74b//u+G//7vhv/+74b//u+G//7vhv/+74b//u+G//7vh - v/+74b//u+G//7vhv/+74L//u+C+/7vgvv+74L7/u+C+/7vgvv+7377/u9+9/7vfvf+7373/lM2X/wCW - C/8AcwWpAAAALwAAABUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAA - ABoAAAA3AHAA1gCUCv+XzZj/v+DA/7/gwP+/4MD/v+HA/7/hwP+/4cD/v+HB/7/hwf+/4sH/v+LB/7/i - wf+/4sH/v+LB/7/iwf+/4sH/v+LB/7/iwf+/4sH/v+LB/7/iwf+/4sH/v+LB/7/iwf+/4cH/v+HB/7/h - wP+/4cD/v+HA/7/hwP+/4MD/v+DA/7/gwP+XzZj/AJMI/wBwAKkAAAAvAAAAFQAAAAUAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGgAAADcAcADWAJEG/5nNmv/C4cP/wuHD/8Li - w//C4sP/wuLD/8LixP/C4sT/wuLE/8LixP/C4sT/wuLE/8LixP/C4sT/wuLE/8LixP/C4sT/wuLE/8Li - xP/C4sT/wuLE/8LixP/C4sT/wuLE/8LixP/C4sT/wuLE/8Liw//C4sP/wuLD/8Lhw//C4cP/wuHD/5nN - mv8AkQT/AHAAqQAAAC8AAAAVAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAgAAAAaAAAANwBvANYAjwL/nM6c/8bixv/G4sb/xuLG/8bixv/G4sb/xuLG/8bixv/G48b/xuPG/8bj - xv/G48b/xuPH/8bjx//G48f/xuPH/8bjx//G48f/xuPH/8bjx//G48f/xuPG/8bjxv/G48b/xuPG/8bj - xv/G4sb/xuLG/8bixv/G4sb/xuLG/8bixv/G4sb/nM6c/wCOAP8AbQCpAAAALwAAABUAAAAFAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABoAAAA3AG8A1gCOAP+ez57/yOPI/8jj - yP/I48j/yOPI/8jjyP/I48n/yOPJ/8jkyf/I5Mn/yOTJ/8jkyf/I5Mn/yOTJ/8jkyf/I5Mn/yOTJ/8jk - yf/I5Mn/yOTJ/8jkyf/I5Mn/yOTJ/8jkyf/I5Mn/yOTJ/8jjyf/I48n/yOPI/8jjyP/I48j/yOPI/8jj - yP+ez57/AI4A/wBtAKkAAAAvAAAAFQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAIAAAAGgAAADYAbwDWAI4A/6rVqv/u9u7/7vbu/+727v/u9u7/7vbu/+727v/u9u7/7vbu/+72 - 7v/u9u7/7vbu/+727//u9u//7vbv/+727//u9u//7vbv/+727//u9u//7vbv/+727//u9u7/7vbu/+72 - 7v/u9u7/7vbu/+727v/u9u7/7vbu/+727v/u9u7/7vbu/6jTqP8AjgD/AG0AqQAAAC8AAAAVAAAABQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAZAAAANQBsANYAjgD/rNas//7+ - /v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+ - /v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+ - /v/+/v7/iMSI/wCOAP8AYACpAAAALgAAABQAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAABwAAABcAAAAxAGcA1A6ADv+hzKH/qtKq/6rSqv+q0qr/qtKq/6rSqv+q0qr/qtKq/6rS - qv+q0qr/qtKq/6rSqv+q0qr/qtKq/6rSqv+q0qr/qtKq/6rSqv+q0qr/qtKq/6rSqv+q0qr/qtKq/6rS - qv+q0qr/qtKq/6rSqv+q0qr/qtKq/6rSqv+q0qr/qtKq/6rSqv+Lwov/AH4A/wBbAKYAAAAqAAAAEgAA - AAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEgAAACkAaADRKIQo/3+y - f/9/sn//f7J//3+yf/9/sn//f7J//3+yf/9/sn//f7J//3+yf/9/sn//f7J//3+yf/9/sn//f7J//3+y - f/9/sn//f7J//3+yf/9/sn//f7J//3+yf/9/sn//f7J//3+yf/9/sn//f7J//3+yf/9/sn//f7J//3+y - f/9/sn//f7J//3+yf/8ffx//AFsAoAAAACQAAAAPAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAMAAAANAAAAHgBrAMwigSL/bKds/2ynbP9sp2z/bKds/2ynbP9sp2z/bKds/2yn - bP9sp2z/bKds/2ynbP9sp2z/bKds/2ynbP9sp2z/bKds/2ynbP9sp2z/bKds/2ynbP9sp2z/bKds/2yn - bP9sp2z/bKds/2ynbP9sp2z/bKds/2ynbP9sp2z/bKds/2ynbP9sp2z/bKds/yKBIv8AYQCYAAAAGwAA - AAsAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAcAAAASAGsAuRZ7 - Fv9XnFf/V5xX/1ecV/9XnFf/V5xX/1ecV/9XnFf/V5xX/1ecV/9XnFf/V5xX/1ecV/9XnFf/V5xX/1ec - V/9XnFf/V5xX/1ecV/9XnFf/V5xX/1ecV/9XnFf/V5xX/1ecV/9XnFf/V5xX/1ecV/9XnFf/V5xX/1ec - V/9XnFf/V5xX/1ecV/9TmVP/CncK/wBmAI8AAAAQAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAgAWAA9AHAA8Rt9G/81ijX/NYo1/zWKNf81ijX/NYo1/zWK - Nf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWK - Nf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/xt9G/8AbgDiAFUALQAA - AAgAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwAA - AAUAQAAYAF4ASQBgAEoAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABe - AEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABe - AEwAXgBMAF4ATABfAEsAYABKAF4ASQBDABcAAAAFAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA//////////////////////////////////////////////////////////////////////// - /////////////////gAAAAAAAAAAAAH///////AAAAAAAAAAAAAAP//////wAAAAAAAAAAAAAB////// - 8AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAf - /////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAf/////+AAAAAAAAAA - AAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAA - AAAAAAAAAB//////4AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAA////// - 4AAAAAAAAAAAAAAP/////+AAAAAAAAAAAAAAD//////gAAAAAAAAAAAAAA//////4AAAAAAAAAAAAAAP - /////+AAAAAAAAAAAAAAD//////gAAAAAAAAAAAAAA//////4AAAAAAAAAAAAAAP/////+AAAAAAAAAA - AAAAD//////gAAAAAAAAAAAAAA//////4AAAAAAAAAAAAAAP/////8AAAAAAAAAAAAAAD//////AAAAA - AAAAAAAAAA//////wAAAAAAAAAAAAAAP/////8AAAAAAAAAAAAAAD//////AAAAAAAAAAAAAAA////// - wAAAAAAAAAAAAAAP/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH - /////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAA - AAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAA - AAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf///// - wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAP/////wAAAAAAAAAAAAAAD - /////8AAAAAAAAAAAAAAA//////AAAAAAAAAAAAAAAP/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAA - AAAAB//////gAAAAAAAAAAAAAAf/////4AAAAAAAAAAAAAAP/////+AAAAAAAAAAAAAAD//////wAAAA - AAAAAAAAAB//////8AAAAAAAAAAAAAAf//////AAAAAAAAAAAAAAH//////4AAAAAAAAAAAAAD////// - +AAAAAAAAAAAAAA///////gAAAAAAAAAAAAAP//////8AAAAAAAAAAAAAH///////AAAAAAAAAAAAAB/ - //////4AAAAAAAAAAAAA///////+AAAAAAAAAAAAAP///////gAAAAAAAAAAAAD///////8AAAAAAAAA - AAAB////////AAAAAAAAAAAAAf///////wAAAAAAAAAAAAH///////+AAAAAAAAAAAAD////////gAAA - AAAAAAAAA////////4AAAAAAAAAAAAP////////AAAAAAAAAAAAH////////4AAAAAAAAAAAD/////// - ///gAAAAAAAAH///////////8AAAAAAAAD///////////+AAAAAAAAAf///////////AAAAAAAAAD/// - ////////AAAAAAAAAAf//////////gAAAAAAAAAB//////////wAAAAAAAAAAP/////////4AAAAAAAA - AAB/////////8AAAAAAAAAAAP/////////AAAAAAAAAAAD/////////wAAAAAAAAAAA/////////8AAA - AAAAAAAAP/////////AAAAAAAAAAAD/////////wAAAAAAAAAAA/////////8AAAAAAAAAAAP/////// - //AAAAAAAAAAAD/////////wAAAAAAAAAAA/////////8AAAAAAAAAAAP/////////AAAAAAAAAAAD// - //////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAA - P//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////w - AAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD////////// - ////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///// - //////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAA - P//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////w - AAAAAD//////////////8AAAAAA///////////////gAAAAAf/////////////////////////////// - //////////////////8= - - - - - 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 - 71CQAAAAAElFTkSuQmCC - - - - - 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 - 71CQAAAAAElFTkSuQmCC - - - - - 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 - 71CQAAAAAElFTkSuQmCC - - - \ No newline at end of file diff --git a/NUS Downloader/Headers.cs b/NUS Downloader/Headers.cs deleted file mode 100644 index 7faa41a..0000000 --- a/NUS Downloader/Headers.cs +++ /dev/null @@ -1,747 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.IO; -using System.Security.Cryptography; - -namespace libWiiSharp -{ - public class Headers - { - private static uint imd5Magic = 0x494d4435; - private static uint imetMagic = 0x494d4554; - - /// - /// Convert HeaderType to int to get it's Length. - /// - public enum HeaderType - { - None = 0, - /// - /// Used in opening.bnr - /// - ShortIMET = 1536, - /// - /// Used in 00000000.app - /// - IMET = 1600, - /// - /// Used in banner.bin / icon.bin - /// - IMD5 = 32, - } - - #region Public Functions - /// - /// Checks a file for Headers. - /// - /// - /// - public static HeaderType DetectHeader(string pathToFile) - { - return DetectHeader(File.ReadAllBytes(pathToFile)); - } - - /// - /// Checks the byte array for Headers. - /// - /// - /// - public static HeaderType DetectHeader(byte[] file) - { - if (file.Length > 68) - if (Shared.Swap(BitConverter.ToUInt32(file, 64)) == imetMagic) - return HeaderType.ShortIMET; - if (file.Length > 132) - if (Shared.Swap(BitConverter.ToUInt32(file, 128)) == imetMagic) - return HeaderType.IMET; - if (file.Length > 4) - if (Shared.Swap(BitConverter.ToUInt32(file, 0)) == imd5Magic) - return HeaderType.IMD5; - - return HeaderType.None; - } - - /// - /// Checks the stream for Headers. - /// - /// - /// - public static HeaderType DetectHeader(Stream file) - { - byte[] tmp = new byte[4]; - - if (file.Length > 68) - { - file.Seek(64, SeekOrigin.Begin); - file.Read(tmp, 0, tmp.Length); - if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) == imetMagic) - return HeaderType.ShortIMET; - } - if (file.Length > 132) - { - file.Seek(128, SeekOrigin.Begin); - file.Read(tmp, 0, tmp.Length); - if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) == imetMagic) - return HeaderType.IMET; - } - if (file.Length > 4) - { - file.Seek(0, SeekOrigin.Begin); - file.Read(tmp, 0, tmp.Length); - if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) == imd5Magic) - return HeaderType.IMD5; - } - - return HeaderType.None; - } - #endregion - - public class IMET - { - private bool hashesMatch = true; - private bool isShortImet = false; - - private byte[] additionalPadding = new byte[64]; - private byte[] padding = new byte[64]; - private uint imetMagic = 0x494d4554; - private uint sizeOfHeader = 0x00000600; //Without additionalPadding - private uint unknown = 0x00000003; - private uint iconSize; - private uint bannerSize; - private uint soundSize; - private uint flags = 0x00000000; - private byte[] japaneseTitle = new byte[84]; - private byte[] englishTitle = new byte[84]; - private byte[] germanTitle = new byte[84]; - private byte[] frenchTitle = new byte[84]; - private byte[] spanishTitle = new byte[84]; - private byte[] italianTitle = new byte[84]; - private byte[] dutchTitle = new byte[84]; - private byte[] unknownTitle1 = new byte[84]; - private byte[] unknownTitle2 = new byte[84]; - private byte[] koreanTitle = new byte[84]; - private byte[] padding2 = new byte[588]; - private byte[] hash = new byte[16]; - - /// - /// Short IMET has a padding of 64 bytes at the beginning while Long IMET has 128. - /// - public bool IsShortIMET { get { return isShortImet; } set { isShortImet = value; } } - /// - /// The size of uncompressed icon.bin - /// - public uint IconSize { get { return iconSize; } set { iconSize = value; } } - /// - /// The size of uncompressed banner.bin - /// - public uint BannerSize { get { return bannerSize; } set { bannerSize = value; } } - /// - /// The size of uncompressed sound.bin - /// - public uint SoundSize { get { return soundSize; } set { soundSize = value; } } - /// - /// The japanese Title. - /// - public string JapaneseTitle { get { return returnTitleAsString(japaneseTitle); } set { setTitleFromString(value, 0); } } - /// - /// The english Title. - /// - public string EnglishTitle { get { return returnTitleAsString(englishTitle); } set { setTitleFromString(value, 1); } } - /// - /// The german Title. - /// - public string GermanTitle { get { return returnTitleAsString(germanTitle); } set { setTitleFromString(value, 2); } } - /// - /// The french Title. - /// - public string FrenchTitle { get { return returnTitleAsString(frenchTitle); } set { setTitleFromString(value, 3); } } - /// - /// The spanish Title. - /// - public string SpanishTitle { get { return returnTitleAsString(spanishTitle); } set { setTitleFromString(value, 4); } } - /// - /// The italian Title. - /// - public string ItalianTitle { get { return returnTitleAsString(italianTitle); } set { setTitleFromString(value, 5); } } - /// - /// The dutch Title. - /// - public string DutchTitle { get { return returnTitleAsString(dutchTitle); } set { setTitleFromString(value, 6); } } - /// - /// The korean Title. - /// - public string KoreanTitle { get { return returnTitleAsString(koreanTitle); } set { setTitleFromString(value, 7); } } - /// - /// All Titles as a string array. - /// - public string[] AllTitles { get { return new string[] { JapaneseTitle, EnglishTitle, GermanTitle, FrenchTitle, SpanishTitle, ItalianTitle, DutchTitle, KoreanTitle }; } } - /// - /// When parsing an IMET header, this value will turn false if the hash stored in the header doesn't match the headers hash. - /// - public bool HashesMatch { get { return hashesMatch; } } - - #region Public Functions - /// - /// Loads the IMET Header of a file. - /// - /// - /// - public static IMET Load(string pathToFile) - { - return Load(File.ReadAllBytes(pathToFile)); - } - - /// - /// Loads the IMET Header of a byte array. - /// - /// - /// - public static IMET Load(byte[] fileOrHeader) - { - HeaderType type = DetectHeader(fileOrHeader); - if (type != HeaderType.IMET && type != HeaderType.ShortIMET) - throw new Exception("No IMET Header found!"); - - IMET s = new IMET(); - if (type == HeaderType.ShortIMET) s.isShortImet = true; - - MemoryStream ms = new MemoryStream(fileOrHeader); - try { s.parseHeader(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - return s; - } - - /// - /// Loads the IMET Header of a stream. - /// - /// - /// - public static IMET Load(Stream fileOrHeader) - { - HeaderType type = DetectHeader(fileOrHeader); - if (type != HeaderType.IMET && type != HeaderType.ShortIMET) - throw new Exception("No IMET Header found!"); - - IMET s = new IMET(); - if (type == HeaderType.ShortIMET) s.isShortImet = true; - - s.parseHeader(fileOrHeader); - return s; - } - - /// - /// Creates a new IMET Header. - /// - /// - /// - /// - /// - /// - /// - public static IMET Create(bool isShortImet, int iconSize, int bannerSize, int soundSize, params string[] titles) - { - IMET s = new IMET(); - s.isShortImet = isShortImet; - - for (int i = 0; i < titles.Length; i++) - s.setTitleFromString(titles[i], i); - - for (int i = titles.Length; i < 8; i++) - s.setTitleFromString((titles.Length > 1) ? titles[1] : titles[0], i); - - s.iconSize = (uint)iconSize; - s.bannerSize = (uint)bannerSize; - s.soundSize = (uint)soundSize; - - return s; - } - - /// - /// Removes the IMET Header of a file. - /// - /// - public static void RemoveHeader(string pathToFile) - { - byte[] fileWithoutHeader = RemoveHeader(File.ReadAllBytes(pathToFile)); - File.Delete(pathToFile); - - File.WriteAllBytes(pathToFile, fileWithoutHeader); - } - - /// - /// Removes the IMET Header of a byte array. - /// - /// - /// - public static byte[] RemoveHeader(byte[] file) - { - HeaderType type = DetectHeader(file); - if (type != HeaderType.IMET && type != HeaderType.ShortIMET) - throw new Exception("No IMET Header found!"); - - byte[] fileWithoutHeader = new byte[file.Length - (int)type]; - Array.Copy(file, (int)type, fileWithoutHeader, 0, fileWithoutHeader.Length); - - return fileWithoutHeader; - } - - - - /// - /// Sets all title to the given string. - /// - /// - public void SetAllTitles(string newTitle) - { - for (int i = 0; i < 10; i++) - setTitleFromString(newTitle, i); - } - - /// - /// Returns the Header as a memory stream. - /// - /// - public MemoryStream ToMemoryStream() - { - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - return ms; - } - - /// - /// Returns the Header as a byte array. - /// - /// - public byte[] ToByteArray() - { - return ToMemoryStream().ToArray(); - } - - /// - /// Writes the Header to the given stream. - /// - /// - public void Write(Stream writeStream) - { - writeToStream(writeStream); - } - - /// - /// Changes the Titles. - /// - /// - public void ChangeTitles(params string[] newTitles) - { - for (int i = 0; i < newTitles.Length; i++) - setTitleFromString(newTitles[i], i); - - for (int i = newTitles.Length; i < 8; i++) - setTitleFromString((newTitles.Length > 1) ? newTitles[1] : newTitles[0], i); - } - - /// - /// Returns a string array with the Titles. - /// - /// - public string[] GetTitles() - { - return new string[] { JapaneseTitle, EnglishTitle, GermanTitle, FrenchTitle, SpanishTitle, ItalianTitle, DutchTitle, KoreanTitle }; - } - #endregion - - #region Private Functions - private void writeToStream(Stream writeStream) - { - writeStream.Seek(0, SeekOrigin.Begin); - - if (!isShortImet) writeStream.Write(additionalPadding, 0, additionalPadding.Length); - - writeStream.Write(padding, 0, padding.Length); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(imetMagic)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(sizeOfHeader)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(unknown)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(iconSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(bannerSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(soundSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(flags)), 0, 4); - - writeStream.Write(japaneseTitle, 0, japaneseTitle.Length); - writeStream.Write(englishTitle, 0, englishTitle.Length); - writeStream.Write(germanTitle, 0, germanTitle.Length); - writeStream.Write(frenchTitle, 0, frenchTitle.Length); - writeStream.Write(spanishTitle, 0, spanishTitle.Length); - writeStream.Write(italianTitle, 0, italianTitle.Length); - writeStream.Write(dutchTitle, 0, dutchTitle.Length); - writeStream.Write(unknownTitle1, 0, unknownTitle1.Length); - writeStream.Write(unknownTitle2, 0, unknownTitle2.Length); - writeStream.Write(koreanTitle, 0, koreanTitle.Length); - writeStream.Write(padding2, 0, padding2.Length); - - int hashPos = (int)writeStream.Position; - hash = new byte[16]; - writeStream.Write(hash, 0, hash.Length); - - byte[] toHash = new byte[writeStream.Position]; - writeStream.Seek(0, SeekOrigin.Begin); - writeStream.Read(toHash, 0, toHash.Length); - - computeHash(toHash, isShortImet ? 0 : 0x40); - - writeStream.Seek(hashPos, SeekOrigin.Begin); - writeStream.Write(hash, 0, hash.Length); - } - - private void computeHash(byte[] headerBytes, int hashPos) - { - MD5 md5 = MD5.Create(); - hash = md5.ComputeHash(headerBytes, hashPos, 0x600); - md5.Clear(); - } - - private void parseHeader(Stream headerStream) - { - headerStream.Seek(0, SeekOrigin.Begin); - byte[] tmp = new byte[4]; - - if (!isShortImet) headerStream.Read(additionalPadding, 0, additionalPadding.Length); - headerStream.Read(padding, 0, padding.Length); - - headerStream.Read(tmp, 0, 4); - if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) != imetMagic) - throw new Exception("Invalid Magic!"); - - headerStream.Read(tmp, 0, 4); - if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) != sizeOfHeader) - throw new Exception("Invalid Header Size!"); - - headerStream.Read(tmp, 0, 4); - unknown = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); - - headerStream.Read(tmp, 0, 4); - iconSize = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); - - headerStream.Read(tmp, 0, 4); - bannerSize = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); - - headerStream.Read(tmp, 0, 4); - soundSize = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); - - headerStream.Read(tmp, 0, 4); - flags = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); - - headerStream.Read(japaneseTitle, 0, japaneseTitle.Length); - headerStream.Read(englishTitle, 0, englishTitle.Length); - headerStream.Read(germanTitle, 0, germanTitle.Length); - headerStream.Read(frenchTitle, 0, frenchTitle.Length); - headerStream.Read(spanishTitle, 0, spanishTitle.Length); - headerStream.Read(italianTitle, 0, italianTitle.Length); - headerStream.Read(dutchTitle, 0, dutchTitle.Length); - headerStream.Read(unknownTitle1, 0, unknownTitle1.Length); - headerStream.Read(unknownTitle2, 0, unknownTitle2.Length); - headerStream.Read(koreanTitle, 0, koreanTitle.Length); - - headerStream.Read(padding2, 0, padding2.Length); - headerStream.Read(hash, 0, hash.Length); - - headerStream.Seek(-16, SeekOrigin.Current); - headerStream.Write(new byte[16], 0, 16); - - byte[] temp = new byte[headerStream.Length]; - headerStream.Seek(0, SeekOrigin.Begin); - headerStream.Read(temp, 0, temp.Length); - - MD5 m = MD5.Create(); - byte[] newHash = m.ComputeHash(temp, (isShortImet) ? 0 : 0x40, 0x600); - m.Clear(); - - hashesMatch = Shared.CompareByteArrays(newHash, hash); - } - - private string returnTitleAsString(byte[] title) - { - string tempStr = string.Empty; - - for (int i = 0; i < 84; i += 2) - { - char tempChar = BitConverter.ToChar(new byte[] { title[i + 1], title[i] }, 0); - if (tempChar != 0x00) tempStr += tempChar; - } - - return tempStr; - } - - private void setTitleFromString(string title, int titleIndex) - { - byte[] tempArray = new byte[84]; - - for (int i = 0; i < title.Length; i++) - { - byte[] tempBytes = BitConverter.GetBytes(title[i]); - tempArray[i * 2 + 1] = tempBytes[0]; - tempArray[i * 2] = tempBytes[1]; - } - - switch (titleIndex) - { - case 0: - japaneseTitle = tempArray; - break; - case 1: - englishTitle = tempArray; - break; - case 2: - germanTitle = tempArray; - break; - case 3: - frenchTitle = tempArray; - break; - case 4: - spanishTitle = tempArray; - break; - case 5: - italianTitle = tempArray; - break; - case 6: - dutchTitle = tempArray; - break; - case 7: - koreanTitle = tempArray; - break; - } - } - #endregion - } - - public class IMD5 - { - private uint imd5Magic = 0x494d4435; - private uint fileSize; - private byte[] padding = new byte[8]; - private byte[] hash = new byte[16]; - - /// - /// The size of the file without the IMD5 Header. - /// - public uint FileSize { get { return fileSize; } } - /// - /// The hash of the file without the IMD5 Header. - /// - public byte[] Hash { get { return hash; } } - - private IMD5() { } - - #region Public Functions - /// - /// Loads the IMD5 Header of a file. - /// - /// - /// - public static IMD5 Load(string pathToFile) - { - return Load(File.ReadAllBytes(pathToFile)); - } - - /// - /// Loads the IMD5 Header of a byte array. - /// - /// - /// - public static IMD5 Load(byte[] fileOrHeader) - { - HeaderType type = DetectHeader(fileOrHeader); - if (type != HeaderType.IMD5) - throw new Exception("No IMD5 Header found!"); - - IMD5 h = new IMD5(); - MemoryStream ms = new MemoryStream(fileOrHeader); - - try { h.parseHeader(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - return h; - } - - /// - /// Loads the IMD5 Header of a stream. - /// - /// - /// - public static IMD5 Load(Stream fileOrHeader) - { - HeaderType type = DetectHeader(fileOrHeader); - if (type != HeaderType.IMD5) - throw new Exception("No IMD5 Header found!"); - - IMD5 h = new IMD5(); - h.parseHeader(fileOrHeader); - return h; - } - - /// - /// Creates a new IMD5 Header. - /// - /// - /// - public static IMD5 Create(byte[] file) - { - IMD5 h = new IMD5(); - - h.fileSize = (uint)file.Length; - h.computeHash(file); - - return h; - } - - /// - /// Adds an IMD5 Header to a file. - /// - /// - public static void AddHeader(string pathToFile) - { - byte[] fileWithHeader = AddHeader(File.ReadAllBytes(pathToFile)); - File.Delete(pathToFile); - - using (FileStream fs = new FileStream(pathToFile, FileMode.Create)) - fs.Write(fileWithHeader, 0, fileWithHeader.Length); - } - - /// - /// Adds an IMD5 Header to a byte array. - /// - /// - /// - public static byte[] AddHeader(byte[] file) - { - IMD5 h = IMD5.Create(file); - - MemoryStream ms = new MemoryStream(); - h.writeToStream(ms); - ms.Write(file, 0, file.Length); - - byte[] res = ms.ToArray(); - ms.Dispose(); - return res; - } - - /// - /// Removes the IMD5 Header of a file. - /// - /// - public static void RemoveHeader(string pathToFile) - { - byte[] fileWithoutHeader = RemoveHeader(File.ReadAllBytes(pathToFile)); - File.Delete(pathToFile); - - using (FileStream fs = new FileStream(pathToFile, FileMode.Create)) - fs.Write(fileWithoutHeader, 0, fileWithoutHeader.Length); - } - - /// - /// Removes the IMD5 Header of a byte array. - /// - /// - /// - public static byte[] RemoveHeader(byte[] file) - { - MemoryStream ms = new MemoryStream(); - ms.Write(file, 32, file.Length - 32); - - byte[] ret = ms.ToArray(); - ms.Dispose(); - - return ret; - } - - - - /// - /// Returns the IMD5 Header as a memory stream. - /// - /// - public MemoryStream ToMemoryStream() - { - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - return ms; - } - - /// - /// Returns the IMD5 Header as a byte array. - /// - /// - public byte[] ToByteArray() - { - return ToMemoryStream().ToArray(); - } - - /// - /// Writes the IMD5 Header to the given stream. - /// - /// - public void Write(Stream writeStream) - { - writeToStream(writeStream); - } - #endregion - - #region Private Functions - private void writeToStream(Stream writeStream) - { - writeStream.Seek(0, SeekOrigin.Begin); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(imd5Magic)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(fileSize)), 0, 4); - writeStream.Write(padding, 0, padding.Length); - writeStream.Write(hash, 0, hash.Length); - } - - private void computeHash(byte[] bytesToHash) - { - MD5 md5 = MD5.Create(); - hash = md5.ComputeHash(bytesToHash); - md5.Clear(); - } - - private void parseHeader(Stream headerStream) - { - headerStream.Seek(0, SeekOrigin.Begin); - byte[] tmp = new byte[4]; - - headerStream.Read(tmp, 0, 4); - if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) != imd5Magic) - throw new Exception("Invalid Magic!"); - - headerStream.Read(tmp, 0, 4); - fileSize = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); - - headerStream.Read(padding, 0, padding.Length); - headerStream.Read(hash, 0, hash.Length); - } - #endregion - } - } -} diff --git a/NUS Downloader/IosPatcher.cs b/NUS Downloader/IosPatcher.cs deleted file mode 100644 index 00121fa..0000000 --- a/NUS Downloader/IosPatcher.cs +++ /dev/null @@ -1,313 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -//Patches based on Dop-Mii - Thanks to Arikado and Lunatik - -using System; -using System.ComponentModel; -using System.Text; - -namespace libWiiSharp -{ - /// - /// An IOS patcher which can patch fakesigning, es_identify and nand permissions. - /// - public class IosPatcher - { - private WAD wadFile; - private int esIndex = -1; - - #region Public Functions - /// - /// Loads an IOS wad to patch the es module. - /// - /// - public void LoadIOS(ref WAD iosWad) - { - if ((iosWad.TitleID >> 32) != 1 || - (iosWad.TitleID & 0xFFFFFFFF) < 3 || - (iosWad.TitleID & 0xFFFFFFFF) > 255) - throw new Exception("Only IOS WADs can be patched!"); - - wadFile = iosWad; - getEsIndex(); - } - - /// - /// Patches fakesigning. - /// Returns the number of applied patches. - /// - /// - public int PatchFakeSigning() - { - if (esIndex < 0) return -1; - return patchFakeSigning(ref wadFile.Contents[esIndex]); - } - - /// - /// Patches es_identify. - /// Returns the number of applied patches. - /// - /// - public int PatchEsIdentify() - { - if (esIndex < 0) return -1; - return patchEsIdentify(ref wadFile.Contents[esIndex]); - } - - /// - /// Patches nand permissions. - /// Returns the number of applied patches. - /// - /// - public int PatchNandPermissions() - { - if (esIndex < 0) return -1; - return patchNandPermissions(ref wadFile.Contents[esIndex]); - } - - /// - /// Patches fakesigning, es_identify and nand permissions. - /// Returns the number of applied patches. - /// - /// - public int PatchAll() - { - if (esIndex < 0) return -1; - return patchAll(ref wadFile.Contents[esIndex]); - } - - /// - /// Patches fakesigning. - /// Returns the number of applied patches. - /// - /// - public int PatchFakeSigning(ref byte[] esModule) - { - return patchFakeSigning(ref esModule); - } - - /// - /// Patches es_identify. - /// Returns the number of applied patches. - /// - /// - public int PatchEsIdentify(ref byte[] esModule) - { - return patchEsIdentify(ref esModule); - } - - /// - /// Patches nand permissions. - /// Returns the number of applied patches. - /// - /// - public int PatchNandPermissions(ref byte[] esModule) - { - return patchNandPermissions(ref esModule); - } - - /// - /// Patches fakesigning, es_identify and nand permissions. - /// Returns the number of applied patches. - /// - /// - public int PatchAll(ref byte[] esModule) - { - return patchAll(ref esModule); - } - #endregion - - #region Private Functions - private int patchFakeSigning(ref byte[] esModule) - { - fireDebug("Patching Fakesigning..."); - int patchCount = 0; - - byte[] oldHashCheck = { 0x20, 0x07, 0x23, 0xA2 }; - byte[] newHashCheck = { 0x20, 0x07, 0x4B, 0x0B }; - - for (int i = 0; i < esModule.Length - 4; i++) - { - fireProgress((i + 1) * 100 / esModule.Length); - - if (Shared.CompareByteArrays(esModule, i, oldHashCheck, 0, 4) || - Shared.CompareByteArrays(esModule, i, newHashCheck, 0, 4)) - { - fireDebug(" Patching at Offset: 0x{0}", i.ToString("x8").ToUpper()); - esModule[i + 1] = 0x00; - i += 4; - patchCount++; - } - } - - fireDebug("Patching Fakesigning Finished... (Patches applied: {0})", patchCount); - return patchCount; - } - - private int patchEsIdentify(ref byte[] esModule) - { - fireDebug("Patching ES_Identify..."); - int patchCount = 0; - - byte[] identifyCheck = { 0x28, 0x03, 0xD1, 0x23 }; - - for (int i = 0; i < esModule.Length - 4; i++) - { - fireProgress((i + 1) * 100 / esModule.Length); - - if (Shared.CompareByteArrays(esModule, i, identifyCheck, 0, 4)) - { - fireDebug(" Patching at Offset: 0x{0}", i.ToString("x8").ToUpper()); - esModule[i + 2] = 0x00; - esModule[i + 3] = 0x00; - i += 4; - patchCount++; - } - } - - fireDebug("Patching ES_Identify Finished... (Patches applied: {0})", patchCount); - return patchCount; - } - - private int patchNandPermissions(ref byte[] esModule) - { - fireDebug("Patching NAND Permissions..."); - int patchCount = 0; - - byte[] permissionTable = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 }; - - for (int i = 0; i < esModule.Length - 6; i++) - { - fireProgress((i + 1) * 100 / esModule.Length); - - if (Shared.CompareByteArrays(esModule, i, permissionTable, 0, 6)) - { - fireDebug(" Patching at Offset: 0x{0}", i.ToString("x8").ToUpper()); - esModule[i + 2] = 0xE0; - i += 6; - patchCount++; - } - } - - fireDebug("Patching NAND Permissions Finished... (Patches applied: {0})", patchCount); - return patchCount; - } - - private int patchAll(ref byte[] esModule) - { - fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions..."); - int patchCount = 0; - - byte[] oldHashCheck = { 0x20, 0x07, 0x23, 0xA2 }; - byte[] newHashCheck = { 0x20, 0x07, 0x4B, 0x0B }; - byte[] identifyCheck = { 0x28, 0x03, 0xD1, 0x23 }; - byte[] permissionTable = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 }; - - for (int i = 0; i < esModule.Length - 6; i++) - { - fireProgress((i + 1) * 100 / esModule.Length); - - if (Shared.CompareByteArrays(esModule, i, oldHashCheck, 0, 4) || - Shared.CompareByteArrays(esModule, i, newHashCheck, 0, 4)) - { - fireDebug(" Patching Fakesigning at Offset: 0x{0}", i.ToString("x8").ToUpper()); - esModule[i + 1] = 0x00; - i += 4; - patchCount++; - } - else if (Shared.CompareByteArrays(esModule, i, identifyCheck, 0, 4)) - { - fireDebug(" Patching ES_Identify at Offset: 0x{0}", i.ToString("x8").ToUpper()); - esModule[i + 2] = 0x00; - esModule[i + 3] = 0x00; - i += 4; - patchCount++; - } - else if (Shared.CompareByteArrays(esModule, i, permissionTable, 0, 6)) - { - fireDebug(" Patching NAND Permissions at Offset: 0x{0}", i.ToString("x8").ToUpper()); - esModule[i + 2] = 0xE0; - i += 6; - patchCount++; - } - } - - fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions Finished... (Patches applied: {0})", patchCount); - return patchCount; - } - - private void getEsIndex() - { - fireDebug("Scanning for ES Module..."); - string iosTag = "$IOSVersion:"; - - for (int i = wadFile.NumOfContents - 1; i >= 0; i--) - { - fireDebug(" Scanning Content #{0} of {1}...", i + 1, wadFile.NumOfContents); - fireProgress((i + 1) * 100 / wadFile.NumOfContents); - - for (int j = 0; j < wadFile.Contents[i].Length - 64; j++) - { - if (ASCIIEncoding.ASCII.GetString(wadFile.Contents[i], j, 12) == iosTag) - { - int curIndex = j + 12; - while (wadFile.Contents[i][curIndex] == ' ') { curIndex++; } - - if (ASCIIEncoding.ASCII.GetString(wadFile.Contents[i], curIndex, 3) == "ES:") - { - fireDebug(" -> ES Module found!"); - fireDebug("Scanning for ES Module Finished..."); - esIndex = i; - fireProgress(100); - return; - } - } - } - } - - fireDebug(@"/!\/!\/!\ ES Module wasn't found! /!\/!\/!\"); - throw new Exception("ES module wasn't found!"); - } - #endregion - - #region Events - /// - /// Fires the Progress of various operations - /// - public event EventHandler Progress; - /// - /// Fires debugging messages. You may write them into a log file or log textbox. - /// - public event EventHandler Debug; - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = Debug; - if (debug != null) - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - - private void fireProgress(int progressPercentage) - { - EventHandler progress = Progress; - if (progress != null) - progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); - } - #endregion - } -} diff --git a/NUS Downloader/Latest/NUS Downloader.exe b/NUS Downloader/Latest/NUS Downloader.exe deleted file mode 100644 index cb3590a..0000000 Binary files a/NUS Downloader/Latest/NUS Downloader.exe and /dev/null differ diff --git a/NUS Downloader/Lz77.cs b/NUS Downloader/Lz77.cs deleted file mode 100644 index 809ed6f..0000000 --- a/NUS Downloader/Lz77.cs +++ /dev/null @@ -1,400 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -//Lz77 (de-)compression algorithm based on gbalzss by Andre Perrot (Thanks!) - -using System; -using System.IO; - -namespace libWiiSharp -{ - public class Lz77 - { - private static uint lz77Magic = 0x4c5a3737; - private const int N = 4096; - private const int F = 18; - private const int threshold = 2; - private int[] leftSon = new int[N + 1]; - private int[] rightSon = new int[N + 257]; - private int[] dad = new int[N + 1]; - private ushort[] textBuffer = new ushort[N + 17]; - private int matchPosition = 0, matchLength = 0; - - /// - /// Lz77 Magic. - /// - public static uint Lz77Magic { get { return lz77Magic; } } - - #region Public Functions - /// - /// Checks whether a file is Lz77 compressed or not. - /// - /// - /// - public static bool IsLz77Compressed(string file) - { - return IsLz77Compressed(File.ReadAllBytes(file)); - } - - /// - /// Checks whether a file is Lz77 compressed or not. - /// - /// - /// - public static bool IsLz77Compressed(byte[] file) - { - Headers.HeaderType h = Headers.DetectHeader(file); - return (Shared.Swap(BitConverter.ToUInt32(file, (int)h)) == lz77Magic) ; - } - - /// - /// Checks whether a file is Lz77 compressed or not. - /// - /// - /// - public static bool IsLz77Compressed(Stream file) - { - Headers.HeaderType h = Headers.DetectHeader(file); - byte[] temp = new byte[4]; - file.Seek((long)h, SeekOrigin.Begin); - file.Read(temp, 0, temp.Length); - return (Shared.Swap(BitConverter.ToUInt32(temp, 0)) == lz77Magic); - } - - - - /// - /// Compresses a file using the Lz77 algorithm. - /// - /// - /// - public void Compress(string inFile, string outFile) - { - Stream compressedFile; - - using (FileStream fsIn = new FileStream(inFile, FileMode.Open)) - compressedFile = compress(fsIn); - - byte[] output = new byte[compressedFile.Length]; - compressedFile.Read(output, 0, output.Length); - - if (File.Exists(outFile)) File.Delete(outFile); - - using (FileStream fs = new FileStream(outFile, FileMode.Create)) - fs.Write(output, 0, output.Length); - } - - /// - /// Compresses the byte array using the Lz77 algorithm. - /// - /// - /// - public byte[] Compress(byte[] file) - { - return ((MemoryStream)compress(new MemoryStream(file))).ToArray(); - } - - /// - /// Compresses the stream using the Lz77 algorithm. - /// - /// - /// - public Stream Compress(Stream file) - { - return compress(file); - } - - /// - /// Decompresses a file using the Lz77 algorithm. - /// - /// - /// - public void Decompress(string inFile, string outFile) - { - Stream compressedFile; - - using (FileStream fsIn = new FileStream(inFile, FileMode.Open)) - compressedFile = decompress(fsIn); - - byte[] output = new byte[compressedFile.Length]; - compressedFile.Read(output, 0, output.Length); - - if (File.Exists(outFile)) File.Delete(outFile); - - using (FileStream fs = new FileStream(outFile, FileMode.Create)) - fs.Write(output, 0, output.Length); - } - - /// - /// Decompresses the byte array using the Lz77 algorithm. - /// - /// - /// - public byte[] Decompress(byte[] file) - { - return ((MemoryStream)decompress(new MemoryStream(file))).ToArray(); - } - - public Stream Decompress(Stream file) - { - return decompress(file); - } - #endregion - - #region Private Functions - private Stream decompress(Stream inFile) - { - if (!Lz77.IsLz77Compressed(inFile)) return inFile; - inFile.Seek(0, SeekOrigin.Begin); - - int i, j, k, r, c, z; - uint flags, decompressedSize, currentSize = 0; - - Headers.HeaderType h = Headers.DetectHeader(inFile); - - byte[] temp = new byte[8]; - inFile.Seek((int)h, SeekOrigin.Begin); - inFile.Read(temp, 0, 8); - - if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != lz77Magic) - { inFile.Dispose(); throw new Exception("Invaild Magic!"); } - if (temp[4] != 0x10) - { inFile.Dispose(); throw new Exception("Unsupported Compression Type!"); } - - decompressedSize = (BitConverter.ToUInt32(temp, 4)) >> 8; - - for (i = 0; i < N - F; i++) textBuffer[i] = 0xdf; - r = N - F; flags = 7; z = 7; - - MemoryStream outFile = new MemoryStream(); - while (true) - { - flags <<= 1; - z++; - - if (z == 8) - { - if ((c = inFile.ReadByte()) == -1) break; - - flags = (uint)c; - z = 0; - } - - if ((flags & 0x80) == 0) - { - if ((c = inFile.ReadByte()) == inFile.Length - 1) break; - if (currentSize < decompressedSize) outFile.WriteByte((byte)c); - - textBuffer[r++] = (byte)c; - r &= (N - 1); - currentSize++; - } - else - { - if ((i = inFile.ReadByte()) == -1) break; - if ((j = inFile.ReadByte()) == -1) break; - - j = j | ((i << 8) & 0xf00); - i = ((i >> 4) & 0x0f) + threshold; - for (k = 0; k <= i; k++) - { - c = textBuffer[(r - j - 1) & (N - 1)]; - if (currentSize < decompressedSize) outFile.WriteByte((byte)c); textBuffer[r++] = (byte)c; r &= (N - 1); currentSize++; - } - } - } - - return outFile; - } - - private Stream compress(Stream inFile) - { - if (Lz77.IsLz77Compressed(inFile)) return inFile; - inFile.Seek(0, SeekOrigin.Begin); - - int textSize = 0; - int codeSize = 0; - - int i, c, r, s, length, lastMatchLength, codeBufferPointer, mask; - int[] codeBuffer = new int[17]; - - uint fileSize = ((Convert.ToUInt32(inFile.Length)) << 8) + 0x10; - MemoryStream outFile = new MemoryStream(); - - outFile.Write(BitConverter.GetBytes(Shared.Swap(lz77Magic)), 0, 4); - outFile.Write(BitConverter.GetBytes(fileSize), 0, 4); - - InitTree(); - codeBuffer[0] = 0; - codeBufferPointer = 1; - mask = 0x80; - s = 0; - r = N - F; - - for (i = s; i < r; i++) textBuffer[i] = 0xffff; - - for (length = 0; length < F && (c = (int)inFile.ReadByte()) != -1; length++) - textBuffer[r + length] = (ushort)c; - - if ((textSize = length) == 0) return inFile; - - for (i = 1; i <= F; i++) InsertNode(r - i); - InsertNode(r); - - do - { - if (matchLength > length) matchLength = length; - - if (matchLength <= threshold) - { - matchLength = 1; - codeBuffer[codeBufferPointer++] = textBuffer[r]; - } - else - { - codeBuffer[0] |= mask; - - codeBuffer[codeBufferPointer++] = (char) - (((r - matchPosition - 1) >> 8) & 0x0f) | - ((matchLength - (threshold + 1)) << 4); - - codeBuffer[codeBufferPointer++] = (char)((r - matchPosition - 1) & 0xff); - } - - if ((mask >>= 1) == 0) - { - for (i = 0; i < codeBufferPointer; i++) - outFile.WriteByte((byte)codeBuffer[i]); - - codeSize += codeBufferPointer; - codeBuffer[0] = 0; codeBufferPointer = 1; - mask = 0x80; - } - - lastMatchLength = matchLength; - for (i = 0; i < lastMatchLength && (c = (int)inFile.ReadByte()) != -1; i++) - { - DeleteNode(s); - - textBuffer[s] = (ushort)c; - if (s < F - 1) textBuffer[s + N] = (ushort)c; - s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); - - InsertNode(r); - } - - while (i++ < lastMatchLength) - { - DeleteNode(s); - - s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); - if (--length != 0) InsertNode(r); - } - } while (length > 0); - - - if (codeBufferPointer > 1) - { - for (i = 0; i < codeBufferPointer; i++) outFile.WriteByte((byte)codeBuffer[i]); - codeSize += codeBufferPointer; - } - - if (codeSize % 4 != 0) - for (i = 0; i < 4 - (codeSize % 4); i++) - outFile.WriteByte(0x00); - - return outFile; - } - - private void InitTree() - { - int i; - for (i = N + 1; i <= N + 256; i++) rightSon[i] = N; - for (i = 0; i < N; i++) dad[i] = N; - } - - private void InsertNode(int r) - { - int i, p, cmp; - cmp = 1; - p = N + 1 + (textBuffer[r] == 0xffff ? 0 : (int)textBuffer[r]); - rightSon[r] = leftSon[r] = N; matchLength = 0; - - for (; ; ) - { - if (cmp >= 0) - { - if (rightSon[p] != N) p = rightSon[p]; - else { rightSon[p] = r; dad[r] = p; return; } - } - else - { - if (leftSon[p] != N) p = leftSon[p]; - else { leftSon[p] = r; dad[r] = p; return; } - } - - for (i = 1; i < F; i++) - if ((cmp = textBuffer[r + i] - textBuffer[p + i]) != 0) break; - - if (i > matchLength) - { - matchPosition = p; - if ((matchLength = i) >= F) break; - } - } - - dad[r] = dad[p]; leftSon[r] = leftSon[p]; rightSon[r] = rightSon[p]; - dad[leftSon[p]] = r; dad[rightSon[p]] = r; - - if (rightSon[dad[p]] == p) rightSon[dad[p]] = r; - else leftSon[dad[p]] = r; - - dad[p] = N; - } - - private void DeleteNode(int p) - { - int q; - - if (dad[p] == N) return; - - if (rightSon[p] == N) q = leftSon[p]; - else if (leftSon[p] == N) q = rightSon[p]; - else - { - q = leftSon[p]; - - if (rightSon[q] != N) - { - do { q = rightSon[q]; } while (rightSon[q] != N); - rightSon[dad[q]] = leftSon[q]; dad[leftSon[q]] = dad[q]; - leftSon[q] = leftSon[p]; dad[leftSon[p]] = q; - } - - rightSon[q] = rightSon[p]; dad[rightSon[p]] = q; - } - - dad[q] = dad[p]; - - if (rightSon[dad[p]] == p) rightSon[dad[p]] = q; - else leftSon[dad[p]] = q; - - dad[p] = N; - } - #endregion - } -} diff --git a/NUS Downloader/MessageEventArgs.cs b/NUS Downloader/MessageEventArgs.cs deleted file mode 100644 index 7191ea0..0000000 --- a/NUS Downloader/MessageEventArgs.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; - -namespace libWiiSharp -{ - public class MessageEventArgs : EventArgs - { - private string message; - public string Message { get { return message; } } - - public MessageEventArgs(string message) { this.message = message; } - } -} diff --git a/NUS Downloader/NUS Downloader.csproj b/NUS Downloader/NUS Downloader.csproj deleted file mode 100644 index d5415aa..0000000 --- a/NUS Downloader/NUS Downloader.csproj +++ /dev/null @@ -1,254 +0,0 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {DB1289FA-BA83-408F-A576-326E5EC4CC6D} - WinExe - Properties - NUS_Downloader - NUS Downloader - v2.0 - 512 - Crystal_Clear_app_ark2.ico - false - 1555E408E7D4078FB64D4CC67B4156C20E540209 - NUS Downloader_TemporaryKey.pfx - true - false - LocalIntranet - Properties\app.manifest - - - - - 3.5 - - C:\Users\Windows7\Documents\Visual Studio 2010\Projects\NUS Downloader\NUS Downloader\publish\ - true - Disk - false - Foreground - 7 - Days - false - false - false - false - 14 - 1.0.0.%2a - false - true - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - PreserveNewest - Form - - - Form1.cs - PreserveNewest - - - - - - - - - - Form1.cs - Designer - PreserveNewest - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - Designer - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - Component - - - Component - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - true - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - false - - - False - .NET Framework 3.5 SP1 - false - - - - - False - - - - - Exclude - True - File - - - False - - - - - Exclude - True - File - - - - - copy "$(TargetPath)" "$(ProjectDir)\Latest\" - - - \ No newline at end of file diff --git a/NUS Downloader/NusClient.cs b/NUS Downloader/NusClient.cs deleted file mode 100644 index 97de08e..0000000 --- a/NUS Downloader/NusClient.cs +++ /dev/null @@ -1,562 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.ComponentModel; -using System.IO; -using System.Net; -using System.Security.Cryptography; - -namespace libWiiSharp -{ - public enum StoreType - { - EncryptedContent = 0, - DecryptedContent = 1, - WAD = 2, - All = 3, - Empty = 4 - } - - public class NusClient : IDisposable - { - private const string WII_NUS_URL = "http://nus.cdn.shop.wii.com/ccs/download/"; - private const string DSI_NUS_URL = "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/"; - - private const string WII_USER_AGENT = "wii libnup/1.0"; - private const string DSI_USER_AGENT = "Opera/9.50 (Nintendo; Opera/154; U; Nintendo DS; en)"; - - private string nusUrl = WII_NUS_URL; - private WebClient wcNus = new WebClient(); - private bool useLocalFiles = false; - private bool continueWithoutTicket = false; - - private int titleversion; - - public int TitleVersion { get { return titleversion; } } - - /// - /// If true, existing local files will be used. - /// - public bool UseLocalFiles { get { return useLocalFiles; } set { useLocalFiles = value; } } - /// - /// If true, the download will be continued even if no ticket for the title is avaiable (WAD packaging and decryption are disabled). - /// - public bool ContinueWithoutTicket { get { return continueWithoutTicket; } set { continueWithoutTicket = value; } } - - #region IDisposable Members - private bool isDisposed = false; - - ~NusClient() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !isDisposed) - { - wcNus.Dispose(); - } - - isDisposed = true; - } - #endregion - - #region Public Functions - - public void ConfigureNusClient(WebClient wcReady) - { - wcNus = wcReady; - } - - public void SetToWiiServer() - { - nusUrl = WII_NUS_URL; - wcNus.Headers.Add("User-Agent", WII_USER_AGENT); - } - - public void SetToDSiServer() - { - nusUrl = DSI_NUS_URL; - wcNus.Headers.Add("User-Agent", DSI_USER_AGENT); - } - - /// - /// Grabs a title from NUS, you can define several store types. - /// Leave the title version empty for the latest. - /// - /// - /// - /// - /// - public void DownloadTitle(string titleId, string titleVersion, string outputDir, string wadName, params StoreType[] storeTypes) - { - if (titleId.Length != 16) throw new Exception("Title ID must be 16 characters long!"); - downloadTitle(titleId, titleVersion, outputDir, wadName, storeTypes); - } - - /// - /// Grabs a TMD from NUS. - /// Leave the title version empty for the latest. - /// - /// - /// - /// - public TMD DownloadTMD(string titleId, string titleVersion) - { - if (titleId.Length != 16) throw new Exception("Title ID must be 16 characters long!"); - return downloadTmd(titleId, titleVersion); - } - - /// - /// Grabs a Ticket from NUS. - /// - /// - /// - public Ticket DownloadTicket(string titleId) - { - if (titleId.Length != 16) throw new Exception("Title ID must be 16 characters long!"); - return downloadTicket(titleId); - } - - /// - /// Grabs a single content file and decrypts it. - /// Leave the title version empty for the latest. - /// - /// - /// - /// - /// - public byte[] DownloadSingleContent(string titleId, string titleVersion, string contentId) - { - if (titleId.Length != 16) throw new Exception("Title ID must be 16 characters long!"); - return downloadSingleContent(titleId, titleVersion, contentId); - } - - /// - /// Grabs a single content file and decrypts it. - /// Leave the title version empty for the latest. - /// - /// - /// - /// - /// - public void DownloadSingleContent(string titleId, string titleVersion, string contentId, string savePath) - { - if (titleId.Length != 16) throw new Exception("Title ID must be 16 characters long!"); - if (!Directory.Exists(Path.GetDirectoryName(savePath))) Directory.CreateDirectory(Path.GetDirectoryName(savePath)); - if (File.Exists(savePath)) File.Delete(savePath); - - byte[] content = downloadSingleContent(titleId, titleVersion, contentId); - File.WriteAllBytes(savePath, content); - } - #endregion - - #region Private Functions - private byte[] downloadSingleContent(string titleId, string titleVersion, string contentId) - { - uint cId = uint.Parse(contentId, System.Globalization.NumberStyles.HexNumber); - contentId = cId.ToString("x8"); - - fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2}...", contentId, titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); - - fireDebug(" Checking for Internet connection..."); - if (!CheckInet()) - { fireDebug(" Connection not found..."); throw new Exception("You're not connected to the internet!"); } - - fireProgress(0); - - string tmdFile = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", titleVersion)); - string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); - string contentIdString = string.Empty; - int cIndex = 0; - - //Download TMD - fireDebug(" Downloading TMD..."); - byte[] tmdArray = wcNus.DownloadData(titleUrl + tmdFile); - fireDebug(" Parsing TMD..."); - TMD tmd = TMD.Load(tmdArray); - - fireProgress(20); - - //Search for Content ID in TMD - fireDebug(" Looking for Content ID {0} in TMD...", contentId); - bool foundContentId = false; - for (int i = 0; i < tmd.Contents.Length; i++) - if (tmd.Contents[i].ContentID == cId) - { - fireDebug(" Content ID {0} found in TMD...", contentId); - foundContentId = true; - contentIdString = tmd.Contents[i].ContentID.ToString("x8"); - cIndex = i; - break; - } - - if (!foundContentId) - { fireDebug(" Content ID {0} wasn't found in TMD...", contentId); throw new Exception("Content ID wasn't found in the TMD!"); } - - //Download Ticket - fireDebug(" Downloading Ticket..."); - byte[] tikArray = wcNus.DownloadData(titleUrl + "cetk"); - fireDebug(" Parsing Ticket..."); - Ticket tik = Ticket.Load(tikArray); - - fireProgress(40); - - //Download and Decrypt Content - fireDebug(" Downloading Content... ({0} bytes)", tmd.Contents[cIndex].Size); - byte[] encryptedContent = wcNus.DownloadData(titleUrl + contentIdString); - - fireProgress(80); - - fireDebug(" Decrypting Content..."); - byte[] decryptedContent = decryptContent(encryptedContent, cIndex, tik, tmd); - Array.Resize(ref decryptedContent, (int)tmd.Contents[cIndex].Size); - - //Check SHA1 - SHA1 s = SHA1.Create(); - byte[] newSha = s.ComputeHash(decryptedContent); - - if (!Shared.CompareByteArrays(newSha, tmd.Contents[cIndex].Hash)) - { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); throw new Exception("Hashes do not match!"); } - - fireProgress(100); - - fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2} Finished...", contentId, titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); - return decryptedContent; - } - - private Ticket downloadTicket(string titleId) - { - if (!CheckInet()) - throw new Exception("You're not connected to the internet!"); - - string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); - byte[] tikArray = wcNus.DownloadData(titleUrl + "cetk"); - - return Ticket.Load(tikArray); - } - - private TMD downloadTmd(string titleId, string titleVersion) - { - if (!CheckInet()) - throw new Exception("You're not connected to the internet!"); - - string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); - string tmdFile = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", titleVersion)); - - byte[] tmdArray = wcNus.DownloadData(titleUrl + tmdFile); - - return TMD.Load(tmdArray); - } - - private void downloadTitle(string titleId, string titleVersion, string outputDir, string wadName, StoreType[] storeTypes) - { - fireDebug("Downloading Title {0} v{1}...", titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); - - if (storeTypes.Length < 1) - { fireDebug(" No store types were defined..."); throw new Exception("You must at least define one store type!"); } - - string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); - bool storeEncrypted = false; - bool storeDecrypted = false; - bool storeWad = false; - - fireProgress(0); - - foreach (StoreType st in storeTypes) - { - switch (st) - { - case StoreType.DecryptedContent: - fireDebug(" [=] Storing Decrypted Content..."); - storeDecrypted = true; - break; - case StoreType.EncryptedContent: - fireDebug(" [=] Storing Encrypted Content..."); - storeEncrypted = true; - break; - case StoreType.WAD: - fireDebug(" [=] Storing WAD..."); - storeWad = true; - break; - case StoreType.All: - fireDebug(" [=] Storing Decrypted Content..."); - fireDebug(" [=] Storing Encrypted Content..."); - fireDebug(" [=] Storing WAD..."); - storeDecrypted = true; - storeEncrypted = true; - storeWad = true; - break; - case StoreType.Empty: - break; - } - } - /* - fireDebug(" - Checking for Internet connection..."); - if (!CheckInet()) - { fireDebug(" + Connection not found..."); throw new Exception("You're not connected to the internet!"); } - */ - - if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir); - if (!Directory.Exists(Path.Combine(outputDir, titleId))) Directory.CreateDirectory(Path.Combine(outputDir, titleId)); - outputDir = Path.Combine(outputDir, titleId); - - string tmdFile = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", titleVersion)); - - //Download TMD - fireDebug(" - Downloading TMD..."); - TMD tmd; - byte[] tmdFileWithCerts; - try - { - tmdFileWithCerts = wcNus.DownloadData(titleUrl + tmdFile); - tmd = TMD.Load(tmdFileWithCerts); - } - catch (Exception ex) { fireDebug(" + Downloading TMD Failed..."); throw new Exception("Downloading TMD Failed:\n" + ex.Message); } - - //Parse TMD - fireDebug(" - Parsing TMD..."); - - if (string.IsNullOrEmpty(titleVersion)) { fireDebug(" + Title Version: {0}", tmd.TitleVersion); } - fireDebug(" + {0} Contents", tmd.NumOfContents); - - if (!Directory.Exists(Path.Combine(outputDir, tmd.TitleVersion.ToString()))) Directory.CreateDirectory(Path.Combine(outputDir, tmd.TitleVersion.ToString())); - outputDir = Path.Combine(outputDir, tmd.TitleVersion.ToString()); - - this.titleversion = tmd.TitleVersion; - - File.WriteAllBytes(Path.Combine(outputDir, tmdFile), tmd.ToByteArray()); - - fireProgress(5); - - //Download cetk - fireDebug(" - Downloading Ticket..."); - try - { - wcNus.DownloadFile(Path.Combine(titleUrl, "cetk"), Path.Combine(outputDir, "cetk")); - } - catch (Exception ex) - { - if (!continueWithoutTicket || !storeEncrypted) - { - fireDebug(" + Downloading Ticket Failed..."); - throw new Exception("Downloading Ticket Failed:\n" + ex.Message); - } - - if (!(File.Exists(Path.Combine(outputDir, "cetk")))) - { - storeDecrypted = false; - storeWad = false; - } - } - - fireProgress(10); - - // Parse Ticket - Ticket tik = new Ticket(); - - if (File.Exists(Path.Combine(outputDir, "cetk"))) - { - fireDebug(" + Parsing Ticket..."); - tik = Ticket.Load(Path.Combine(outputDir, "cetk")); - - // DSi ticket? Must make sure to use DSi Key :D - if (nusUrl == DSI_NUS_URL) - tik.DSiTicket = true; - } - else - { - fireDebug(" + Ticket Unavailable..."); - } - - string[] encryptedContents = new string[tmd.NumOfContents]; - - //Download Content - for (int i = 0; i < tmd.NumOfContents; i++) - { - fireDebug(" - Downloading Content #{0} of {1}... ({2} bytes)", i + 1, tmd.NumOfContents, tmd.Contents[i].Size); - fireProgress(((i + 1) * 60 / tmd.NumOfContents) + 10); - - if (useLocalFiles && File.Exists(Path.Combine(outputDir, tmd.Contents[i].ContentID.ToString("x8")))) - { fireDebug(" + Using Local File, Skipping..."); continue; } - - try - { - wcNus.DownloadFile(titleUrl + tmd.Contents[i].ContentID.ToString("x8"), - Path.Combine(outputDir, tmd.Contents[i].ContentID.ToString("x8"))); - - encryptedContents[i] = tmd.Contents[i].ContentID.ToString("x8"); - } - catch (Exception ex) { fireDebug(" - Downloading Content #{0} of {1} failed...", i + 1, tmd.NumOfContents); throw new Exception("Downloading Content Failed:\n" + ex.Message); } - } - - //Decrypt Content - if (storeDecrypted || storeWad) - { - SHA1 s = SHA1.Create(); - - for (int i = 0; i < tmd.NumOfContents; i++) - { - fireDebug(" - Decrypting Content #{0} of {1}...", i + 1, tmd.NumOfContents); - fireProgress(((i + 1) * 20 / tmd.NumOfContents) + 75); - - //Decrypt Content - byte[] decryptedContent = - decryptContent(File.ReadAllBytes(Path.Combine(outputDir, tmd.Contents[i].ContentID.ToString("x8"))), i, tik, tmd); - Array.Resize(ref decryptedContent, (int)tmd.Contents[i].Size); - - //Check SHA1 - byte[] newSha = s.ComputeHash(decryptedContent); - if (!Shared.CompareByteArrays(newSha, tmd.Contents[i].Hash)) - { - fireDebug(@" + Hashes do not match! (Invalid Output)"); - //throw new Exception(string.Format("Content #{0}: Hashes do not match!", i)); - } - - //Write Decrypted Content - File.WriteAllBytes(Path.Combine(outputDir, (tmd.Contents[i].ContentID.ToString("x8") + ".app")), decryptedContent); - } - - s.Clear(); - } - - //Pack Wad - if (storeWad) - { - fireDebug(" - Building Certificate Chain..."); - CertificateChain cert = CertificateChain.FromTikTmd(Path.Combine(outputDir, "cetk"), tmdFileWithCerts); - - byte[][] contents = new byte[tmd.NumOfContents][]; - - for (int i = 0; i < tmd.NumOfContents; i++) - contents[i] = File.ReadAllBytes(Path.Combine(outputDir, (tmd.Contents[i].ContentID.ToString("x8") + ".app"))); - - fireDebug(" - Creating WAD..."); - WAD wad = WAD.Create(cert, tik, tmd, contents); - wad.RemoveFooter(); - wadName = wadName.Replace("[v]", "v" + this.TitleVersion.ToString()); // fix by madri2 - if (Path.DirectorySeparatorChar.ToString() != "/" && Path.AltDirectorySeparatorChar.ToString() != "/") - wadName = wadName.Replace("/", ""); - if (wadName.Contains(Path.DirectorySeparatorChar.ToString()) || wadName.Contains(Path.AltDirectorySeparatorChar.ToString())) - wad.Save(wadName); - else - wad.Save(Path.Combine(outputDir, wadName)); - } - - //Delete not wanted files - if (!storeEncrypted) - { - fireDebug(" - Deleting Encrypted Contents..."); - for (int i = 0; i < encryptedContents.Length; i++) - if (File.Exists(Path.Combine(outputDir, encryptedContents[i]))) File.Delete(Path.Combine(outputDir, encryptedContents[i])); - } - - if (storeWad && !storeDecrypted) - { - fireDebug(" - Deleting Decrypted Contents..."); - for (int i = 0; i < encryptedContents.Length; i++) - if (File.Exists(Path.Combine(outputDir, (encryptedContents[i] + ".app")))) File.Delete(Path.Combine(outputDir, (encryptedContents[i] + ".app"))); - } - - if (!storeDecrypted && !storeEncrypted) - { - fireDebug(" - Deleting TMD and Ticket..."); - File.Delete(Path.Combine(outputDir, tmdFile)); - File.Delete(Path.Combine(outputDir, "cetk")); - } - - fireDebug("Downloading Title {0} v{1} Finished...", titleId, tmd.TitleVersion /*(string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion*/); - fireProgress(100); - } - - private byte[] decryptContent(byte[] content, int contentIndex, Ticket tik, TMD tmd) - { - Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); - byte[] titleKey = tik.TitleKey; - byte[] iv = new byte[16]; - - byte[] tmp = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); - iv[0] = tmp[1]; - iv[1] = tmp[0]; - - RijndaelManaged rm = new RijndaelManaged(); - rm.Mode = CipherMode.CBC; - rm.Padding = PaddingMode.None; - rm.KeySize = 128; - rm.BlockSize = 128; - rm.Key = titleKey; - rm.IV = iv; - - ICryptoTransform decryptor = rm.CreateDecryptor(); - - MemoryStream ms = new MemoryStream(content); - CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); - - byte[] decCont = new byte[content.Length]; - cs.Read(decCont, 0, decCont.Length); - - cs.Dispose(); - ms.Dispose(); - - return decCont; - } - - private bool CheckInet() - { - try - { - System.Net.IPHostEntry ipHost = System.Net.Dns.GetHostEntry("www.google.com"); - return true; - } - catch { return false; } - } - #endregion - - #region Events - /// - /// Fires the Progress of various operations - /// - public event EventHandler Progress; - /// - /// Fires debugging messages. You may write them into a log file or log textbox. - /// - public event EventHandler Debug; - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = Debug; - if (debug != null) - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - - private void fireProgress(int progressPercentage) - { - EventHandler progress = Progress; - if (progress != null) - progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); - } - #endregion - } -} diff --git a/NUS Downloader/Program.cs b/NUS Downloader/Program.cs deleted file mode 100644 index 9d7bd6e..0000000 --- a/NUS Downloader/Program.cs +++ /dev/null @@ -1,69 +0,0 @@ -/////////////////////////////////////////// -// NUS Downloader: Program.cs // -// $Rev:: $ // -// $Author:: $ // -// $Date:: $ // -/////////////////////////////////////////// - - -using System; -using System.Windows.Forms; -using System.Runtime.InteropServices; - -namespace NUS_Downloader -{ - static class Program - { - [DllImport("user32.dll")] - public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); - - [DllImport("user32.dll")] - static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); - - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main(string[] args) - { - //Console.Title = "NUSD"; - - // hide the console window - //setConsoleWindowVisibility(false, Console.Title); - - if (args.Length != 0) - { - // hide the console window - //setConsoleWindowVisibility(true, Console.Title); - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new Form1(args)); - } - else - { - // hide the console window - //setConsoleWindowVisibility(false, Console.Title); - - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new Form1()); - } - } - - public static void setConsoleWindowVisibility(bool visible, string title) - { - //Sometimes System.Windows.Forms.Application.ExecutablePath works for the caption depending on the system you are running under. - IntPtr hWnd = FindWindow(null, title); - - if (hWnd != IntPtr.Zero) - { - if (!visible) - //Hide the window - ShowWindow(hWnd, 0); // 0 = SW_HIDE - else - //Show window again - ShowWindow(hWnd, 1); //1 = SW_SHOWNORMA - } - } - } -} diff --git a/NUS Downloader/Properties/AssemblyInfo.cs b/NUS Downloader/Properties/AssemblyInfo.cs deleted file mode 100644 index c043efd..0000000 --- a/NUS Downloader/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NUS Downloader")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NUS Downloader")] -[assembly: AssemblyCopyright("Copyright © 2009")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("cb4ee0f5-7ba8-4ee6-a09e-7a09d4350582")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/NUS Downloader/Properties/Resources.Designer.cs b/NUS Downloader/Properties/Resources.Designer.cs deleted file mode 100644 index 5c5152d..0000000 --- a/NUS Downloader/Properties/Resources.Designer.cs +++ /dev/null @@ -1,329 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.1 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace NUS_Downloader.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NUS_Downloader.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - internal static System.Drawing.Bitmap arrow_ticker { - get { - object obj = ResourceManager.GetObject("arrow_ticker", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bin_closed { - get { - object obj = ResourceManager.GetObject("bin_closed", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap box { - get { - object obj = ResourceManager.GetObject("box", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bug_add { - get { - object obj = ResourceManager.GetObject("bug_add", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_green { - get { - object obj = ResourceManager.GetObject("bullet_green", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_green_blue { - get { - object obj = ResourceManager.GetObject("bullet_green_blue", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_orange { - get { - object obj = ResourceManager.GetObject("bullet_orange", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_orange_blue { - get { - object obj = ResourceManager.GetObject("bullet_orange_blue", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_red { - get { - object obj = ResourceManager.GetObject("bullet_red", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_redgreen { - get { - object obj = ResourceManager.GetObject("bullet_redgreen", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_redgreen_blue { - get { - object obj = ResourceManager.GetObject("bullet_redgreen_blue", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_redorange { - get { - object obj = ResourceManager.GetObject("bullet_redorange", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap bullet_redorange_blue { - get { - object obj = ResourceManager.GetObject("bullet_redorange_blue", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap connect { - get { - object obj = ResourceManager.GetObject("connect", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap database_save { - get { - object obj = ResourceManager.GetObject("database_save", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap disk { - get { - object obj = ResourceManager.GetObject("disk", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap drive_disk { - get { - object obj = ResourceManager.GetObject("drive_disk", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap dsi16x16 { - get { - object obj = ResourceManager.GetObject("dsi16x16", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap folder { - get { - object obj = ResourceManager.GetObject("folder", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap folder_table { - get { - object obj = ResourceManager.GetObject("folder_table", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap help { - get { - object obj = ResourceManager.GetObject("help", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap information { - get { - object obj = ResourceManager.GetObject("information", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap key { - get { - object obj = ResourceManager.GetObject("key", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap money { - get { - object obj = ResourceManager.GetObject("money", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap package { - get { - object obj = ResourceManager.GetObject("package", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap package_add { - get { - object obj = ResourceManager.GetObject("package_add", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap package_delete { - get { - object obj = ResourceManager.GetObject("package_delete", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap package_green { - get { - object obj = ResourceManager.GetObject("package_green", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap page_white_magnify { - get { - object obj = ResourceManager.GetObject("page_white_magnify", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap picture_empty { - get { - object obj = ResourceManager.GetObject("picture_empty", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap script_code { - get { - object obj = ResourceManager.GetObject("script_code", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap script_code_red { - get { - object obj = ResourceManager.GetObject("script_code_red", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap script_go { - get { - object obj = ResourceManager.GetObject("script_go", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap script_start { - get { - object obj = ResourceManager.GetObject("script_start", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap server_connect { - get { - object obj = ResourceManager.GetObject("server_connect", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap server_link { - get { - object obj = ResourceManager.GetObject("server_link", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap wii16x16 { - get { - object obj = ResourceManager.GetObject("wii16x16", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - internal static System.Drawing.Bitmap wrench { - get { - object obj = ResourceManager.GetObject("wrench", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} diff --git a/NUS Downloader/Properties/Resources.resx b/NUS Downloader/Properties/Resources.resx deleted file mode 100644 index 87be064..0000000 --- a/NUS Downloader/Properties/Resources.resx +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\server_connect.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\package_delete.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_redorange.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\wii16x16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_redgreen.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\folder.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\script_go.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\package_green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\help.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\key.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\page_white_magnify.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\money.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\script_code_red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\disk.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\server_link.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\arrow_ticker.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\script_start.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bin_closed.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_redorange-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\connect.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_redgreen-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\package.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\folder_table.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\database_save.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_orange.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\box.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\picture_empty.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_green-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bug_add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\wrench.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\script_code.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\bullet_orange-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\package_add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\drive_disk.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\information.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\dsi16x16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file diff --git a/NUS Downloader/Properties/Settings.Designer.cs b/NUS Downloader/Properties/Settings.Designer.cs deleted file mode 100644 index 3ef900c..0000000 --- a/NUS Downloader/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.1 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace NUS_Downloader.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/NUS Downloader/Properties/Settings.settings b/NUS Downloader/Properties/Settings.settings deleted file mode 100644 index abf36c5..0000000 --- a/NUS Downloader/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/NUS Downloader/Properties/app.manifest b/NUS Downloader/Properties/app.manifest deleted file mode 100644 index c0fffea..0000000 --- a/NUS Downloader/Properties/app.manifest +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NUS Downloader/Resources/arrow_down.png b/NUS Downloader/Resources/arrow_down.png deleted file mode 100644 index 2c4e279..0000000 Binary files a/NUS Downloader/Resources/arrow_down.png and /dev/null differ diff --git a/NUS Downloader/Resources/arrow_ticker.gif b/NUS Downloader/Resources/arrow_ticker.gif deleted file mode 100644 index be4449c..0000000 Binary files a/NUS Downloader/Resources/arrow_ticker.gif and /dev/null differ diff --git a/NUS Downloader/Resources/arrow_up.png b/NUS Downloader/Resources/arrow_up.png deleted file mode 100644 index 1ebb193..0000000 Binary files a/NUS Downloader/Resources/arrow_up.png and /dev/null differ diff --git a/NUS Downloader/Resources/bin_closed.png b/NUS Downloader/Resources/bin_closed.png deleted file mode 100644 index afe22ba..0000000 Binary files a/NUS Downloader/Resources/bin_closed.png and /dev/null differ diff --git a/NUS Downloader/Resources/box.png b/NUS Downloader/Resources/box.png deleted file mode 100644 index 8443c23..0000000 Binary files a/NUS Downloader/Resources/box.png and /dev/null differ diff --git a/NUS Downloader/Resources/bug_add.png b/NUS Downloader/Resources/bug_add.png deleted file mode 100644 index ced7817..0000000 Binary files a/NUS Downloader/Resources/bug_add.png and /dev/null differ diff --git a/NUS Downloader/Resources/bug_error.png b/NUS Downloader/Resources/bug_error.png deleted file mode 100644 index c4e8c28..0000000 Binary files a/NUS Downloader/Resources/bug_error.png and /dev/null differ diff --git a/NUS Downloader/Resources/bullet_green.png b/NUS Downloader/Resources/bullet_green.png deleted file mode 100644 index 058ad26..0000000 Binary files a/NUS Downloader/Resources/bullet_green.png and /dev/null differ diff --git a/NUS Downloader/Resources/bullet_orange.png b/NUS Downloader/Resources/bullet_orange.png deleted file mode 100644 index fa63024..0000000 Binary files a/NUS Downloader/Resources/bullet_orange.png and /dev/null differ diff --git a/NUS Downloader/Resources/bullet_red.png b/NUS Downloader/Resources/bullet_red.png deleted file mode 100644 index 0cd8031..0000000 Binary files a/NUS Downloader/Resources/bullet_red.png and /dev/null differ diff --git a/NUS Downloader/Resources/bullet_redgreen-blue.png b/NUS Downloader/Resources/bullet_redgreen-blue.png deleted file mode 100644 index 63b0f75..0000000 Binary files a/NUS Downloader/Resources/bullet_redgreen-blue.png and /dev/null differ diff --git a/NUS Downloader/Resources/bullet_redgreen.png b/NUS Downloader/Resources/bullet_redgreen.png deleted file mode 100644 index fb50ca8..0000000 Binary files a/NUS Downloader/Resources/bullet_redgreen.png and /dev/null differ diff --git a/NUS Downloader/Resources/bullet_redorange.png b/NUS Downloader/Resources/bullet_redorange.png deleted file mode 100644 index 339d374..0000000 Binary files a/NUS Downloader/Resources/bullet_redorange.png and /dev/null differ diff --git a/NUS Downloader/Resources/connect.png b/NUS Downloader/Resources/connect.png deleted file mode 100644 index 024138e..0000000 Binary files a/NUS Downloader/Resources/connect.png and /dev/null differ diff --git a/NUS Downloader/Resources/database_save.png b/NUS Downloader/Resources/database_save.png deleted file mode 100644 index 44c06dd..0000000 Binary files a/NUS Downloader/Resources/database_save.png and /dev/null differ diff --git a/NUS Downloader/Resources/disk.png b/NUS Downloader/Resources/disk.png deleted file mode 100644 index 99d532e..0000000 Binary files a/NUS Downloader/Resources/disk.png and /dev/null differ diff --git a/NUS Downloader/Resources/drive_disk.png b/NUS Downloader/Resources/drive_disk.png deleted file mode 100644 index 5a51e81..0000000 Binary files a/NUS Downloader/Resources/drive_disk.png and /dev/null differ diff --git a/NUS Downloader/Resources/dsi.png b/NUS Downloader/Resources/dsi.png deleted file mode 100644 index 5997b56..0000000 Binary files a/NUS Downloader/Resources/dsi.png and /dev/null differ diff --git a/NUS Downloader/Resources/dsi16x16.png b/NUS Downloader/Resources/dsi16x16.png deleted file mode 100644 index f4f88e7..0000000 Binary files a/NUS Downloader/Resources/dsi16x16.png and /dev/null differ diff --git a/NUS Downloader/Resources/folder.png b/NUS Downloader/Resources/folder.png deleted file mode 100644 index aad1646..0000000 Binary files a/NUS Downloader/Resources/folder.png and /dev/null differ diff --git a/NUS Downloader/Resources/folder_table.png b/NUS Downloader/Resources/folder_table.png deleted file mode 100644 index 473cee3..0000000 Binary files a/NUS Downloader/Resources/folder_table.png and /dev/null differ diff --git a/NUS Downloader/Resources/help.png b/NUS Downloader/Resources/help.png deleted file mode 100644 index 5c87017..0000000 Binary files a/NUS Downloader/Resources/help.png and /dev/null differ diff --git a/NUS Downloader/Resources/help1.png b/NUS Downloader/Resources/help1.png deleted file mode 100644 index 5c87017..0000000 Binary files a/NUS Downloader/Resources/help1.png and /dev/null differ diff --git a/NUS Downloader/Resources/information.png b/NUS Downloader/Resources/information.png deleted file mode 100644 index 12cd1ae..0000000 Binary files a/NUS Downloader/Resources/information.png and /dev/null differ diff --git a/NUS Downloader/Resources/key.png b/NUS Downloader/Resources/key.png deleted file mode 100644 index 4ec1a92..0000000 Binary files a/NUS Downloader/Resources/key.png and /dev/null differ diff --git a/NUS Downloader/Resources/link.png b/NUS Downloader/Resources/link.png deleted file mode 100644 index 25eacb7..0000000 Binary files a/NUS Downloader/Resources/link.png and /dev/null differ diff --git a/NUS Downloader/Resources/money.png b/NUS Downloader/Resources/money.png deleted file mode 100644 index 4e6773e..0000000 Binary files a/NUS Downloader/Resources/money.png and /dev/null differ diff --git a/NUS Downloader/Resources/package.png b/NUS Downloader/Resources/package.png deleted file mode 100644 index da3c2a2..0000000 Binary files a/NUS Downloader/Resources/package.png and /dev/null differ diff --git a/NUS Downloader/Resources/package_add.png b/NUS Downloader/Resources/package_add.png deleted file mode 100644 index 9c8a9da..0000000 Binary files a/NUS Downloader/Resources/package_add.png and /dev/null differ diff --git a/NUS Downloader/Resources/package_delete.png b/NUS Downloader/Resources/package_delete.png deleted file mode 100644 index 86f7fbc..0000000 Binary files a/NUS Downloader/Resources/package_delete.png and /dev/null differ diff --git a/NUS Downloader/Resources/package_green.png b/NUS Downloader/Resources/package_green.png deleted file mode 100644 index 25b28bb..0000000 Binary files a/NUS Downloader/Resources/package_green.png and /dev/null differ diff --git a/NUS Downloader/Resources/page_white_magnify.png b/NUS Downloader/Resources/page_white_magnify.png deleted file mode 100644 index f6b74cc..0000000 Binary files a/NUS Downloader/Resources/page_white_magnify.png and /dev/null differ diff --git a/NUS Downloader/Resources/pencil.png b/NUS Downloader/Resources/pencil.png deleted file mode 100644 index 0bfecd5..0000000 Binary files a/NUS Downloader/Resources/pencil.png and /dev/null differ diff --git a/NUS Downloader/Resources/picture_empty.png b/NUS Downloader/Resources/picture_empty.png deleted file mode 100644 index abd2b9b..0000000 Binary files a/NUS Downloader/Resources/picture_empty.png and /dev/null differ diff --git a/NUS Downloader/Resources/script_code.png b/NUS Downloader/Resources/script_code.png deleted file mode 100644 index 63fe6ce..0000000 Binary files a/NUS Downloader/Resources/script_code.png and /dev/null differ diff --git a/NUS Downloader/Resources/script_code_red.png b/NUS Downloader/Resources/script_code_red.png deleted file mode 100644 index 8fcf0f0..0000000 Binary files a/NUS Downloader/Resources/script_code_red.png and /dev/null differ diff --git a/NUS Downloader/Resources/script_go.png b/NUS Downloader/Resources/script_go.png deleted file mode 100644 index 8e154e2..0000000 Binary files a/NUS Downloader/Resources/script_go.png and /dev/null differ diff --git a/NUS Downloader/Resources/script_start.png b/NUS Downloader/Resources/script_start.png deleted file mode 100644 index 31c1e51..0000000 Binary files a/NUS Downloader/Resources/script_start.png and /dev/null differ diff --git a/NUS Downloader/Resources/server_connect.png b/NUS Downloader/Resources/server_connect.png deleted file mode 100644 index 49b2691..0000000 Binary files a/NUS Downloader/Resources/server_connect.png and /dev/null differ diff --git a/NUS Downloader/Resources/server_link.png b/NUS Downloader/Resources/server_link.png deleted file mode 100644 index e8821df..0000000 Binary files a/NUS Downloader/Resources/server_link.png and /dev/null differ diff --git a/NUS Downloader/Resources/telephone_add.png b/NUS Downloader/Resources/telephone_add.png deleted file mode 100644 index 5591cfc..0000000 Binary files a/NUS Downloader/Resources/telephone_add.png and /dev/null differ diff --git a/NUS Downloader/Resources/wii16x16.png b/NUS Downloader/Resources/wii16x16.png deleted file mode 100644 index 42b4dc4..0000000 Binary files a/NUS Downloader/Resources/wii16x16.png and /dev/null differ diff --git a/NUS Downloader/Resources/wilolgoi.png b/NUS Downloader/Resources/wilolgoi.png deleted file mode 100644 index d1e2810..0000000 Binary files a/NUS Downloader/Resources/wilolgoi.png and /dev/null differ diff --git a/NUS Downloader/Resources/wrench.png b/NUS Downloader/Resources/wrench.png deleted file mode 100644 index e8857d5..0000000 Binary files a/NUS Downloader/Resources/wrench.png and /dev/null differ diff --git a/NUS Downloader/Shared.cs b/NUS Downloader/Shared.cs deleted file mode 100644 index 6e01478..0000000 --- a/NUS Downloader/Shared.cs +++ /dev/null @@ -1,272 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.Collections.Generic; -using System.Net; - -namespace libWiiSharp -{ - public static class Shared - { - /// - /// Merges two string arrays into one without double entries. - /// - /// - /// - /// - public static string[] MergeStringArrays(string[] a, string[] b) - { - List sList = new List(a); - - foreach (string currentString in b) - if (!sList.Contains(currentString)) sList.Add(currentString); - - sList.Sort(); - return sList.ToArray(); - } - - /// - /// Compares two byte arrays. - /// - /// - /// - /// - /// - /// - /// - public static bool CompareByteArrays(byte[] first, int firstIndex, byte[] second, int secondIndex, int length) - { - if (first.Length < length || second.Length < length) return false; - - for (int i = 0; i < length; i++) - if (first[firstIndex + i] != second[secondIndex + i]) return false; - - return true; - } - - /// - /// Compares two byte arrays. - /// - /// - /// - /// - public static bool CompareByteArrays(byte[] first, byte[] second) - { - if (first.Length != second.Length) return false; - else - for (int i = 0; i < first.Length; i++) - if (first[i] != second[i]) return false; - - return true; - } - - /// - /// Turns a byte array into a string, default separator is a space. - /// - /// - /// - /// - public static string ByteArrayToString(byte[] byteArray, char separator = ' ') - { - string res = string.Empty; - - foreach (byte b in byteArray) - res += b.ToString("x2").ToUpper() + separator; - - return res.Remove(res.Length - 1); - } - - /// - /// Turns a hex string into a byte array. - /// - /// - /// - public static byte[] HexStringToByteArray(string hexString) - { - byte[] ba = new byte[hexString.Length / 2]; - - for (int i = 0; i < hexString.Length / 2; i++) - ba[i] = byte.Parse(hexString.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); - - return ba; - } - - /// - /// Counts how often the given char exists in the given string. - /// - /// - /// - /// - public static int CountCharsInString(string theString, char theChar) - { - int count = 0; - - foreach (char thisChar in theString) - if (thisChar == theChar) - count++; - - return count; - } - - /// - /// Pads the given value to a multiple of the given padding value, default padding value is 64. - /// - /// - /// - public static long AddPadding(long value) - { - return AddPadding(value, 64); - } - - /// - /// Pads the given value to a multiple of the given padding value, default padding value is 64. - /// - /// - /// - /// - public static long AddPadding(long value, int padding) - { - if (value % padding != 0) - { - value = value + (padding - (value % padding)); - } - - return value; - } - - /// - /// Pads the given value to a multiple of the given padding value, default padding value is 64. - /// - /// - /// - public static int AddPadding(int value) - { - return AddPadding(value, 64); - } - - /// - /// Pads the given value to a multiple of the given padding value, default padding value is 64. - /// - /// - /// - /// - public static int AddPadding(int value, int padding) - { - if (value % padding != 0) - { - value = value + (padding - (value % padding)); - } - - return value; - } - - /// - /// Swaps endianness. - /// - /// - /// - public static ushort Swap(ushort value) - { - return (ushort)IPAddress.HostToNetworkOrder((short)value); - } - - /// - /// Swaps endianness. - /// - /// - /// - public static uint Swap(uint value) - { - return (uint)IPAddress.HostToNetworkOrder((int)value); - } - - /// - /// Swaps endianness - /// - /// - /// - public static ulong Swap(ulong value) - { - return (ulong)IPAddress.HostToNetworkOrder((long)value); - } - - /// - /// Turns a ushort array into a byte array. - /// - /// - /// - public static byte[] UShortArrayToByteArray(ushort[] array) - { - List results = new List(); - foreach (ushort value in array) - { - byte[] converted = BitConverter.GetBytes(value); - results.AddRange(converted); - } - return results.ToArray(); - } - - /// - /// Turns a uint array into a byte array. - /// - /// - /// - public static byte[] UIntArrayToByteArray(uint[] array) - { - List results = new List(); - foreach (uint value in array) - { - byte[] converted = BitConverter.GetBytes(value); - results.AddRange(converted); - } - return results.ToArray(); - } - - /// - /// Turns a byte array into a uint array. - /// - /// - /// - public static uint[] ByteArrayToUIntArray(byte[] array) - { - UInt32[] converted = new UInt32[array.Length / 4]; - int j = 0; - - for (int i = 0; i < array.Length; i += 4) - converted[j++] = BitConverter.ToUInt32(array, i); - - return converted; - } - - /// - /// Turns a byte array into a ushort array. - /// - /// - /// - public static ushort[] ByteArrayToUShortArray(byte[] array) - { - ushort[] converted = new ushort[array.Length / 2]; - int j = 0; - - for (int i = 0; i < array.Length; i += 2) - converted[j++] = BitConverter.ToUInt16(array, i); - - return converted; - } - } -} diff --git a/NUS Downloader/TMD.cs b/NUS Downloader/TMD.cs deleted file mode 100644 index 32cbef5..0000000 --- a/NUS Downloader/TMD.cs +++ /dev/null @@ -1,659 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; - -namespace libWiiSharp -{ - public enum ContentType : ushort - { - Normal = 0x0001, - DLC = 0x4001, //Seen this in a DLC wad... - Shared = 0x8001, - } - - public enum Region : ushort - { - Japan = 0, - USA = 1, - Europe = 2, - Free = 3, - } - - public class TMD : IDisposable - { - private bool fakeSign = false; - - private uint signatureExponent = 0x00010001; - private byte[] signature = new byte[256]; - private byte[] padding = new byte[60]; - private byte[] issuer = new byte[64]; - private byte version; - private byte caCrlVersion; - private byte signerCrlVersion; - private byte paddingByte; - private ulong startupIos; - private ulong titleId; - private uint titleType; - private ushort groupId; - private ushort padding2; - private ushort region; - private byte[] reserved = new byte[58]; - private uint accessRights; - private ushort titleVersion; - private ushort numOfContents; - private ushort bootIndex; - private ushort padding3; - private List contents; - - /// - /// The region of the title. - /// - public Region Region { get { return (Region)region; } set { region = (ushort)value; } } - /// - /// The IOS the title is launched with. - /// - public ulong StartupIOS { get { return startupIos; } set { startupIos = value; } } - /// - /// The Title ID. - /// - public ulong TitleID { get { return titleId; } set { titleId = value; } } - /// - /// The Title Version. - /// - public ushort TitleVersion { get { return titleVersion; } set { titleVersion = value; } } - /// - /// The Number of Contents. - /// - public ushort NumOfContents { get { return numOfContents; } } - /// - /// The boot index. Represents the index of the nand loader. - /// - public ushort BootIndex { get { return bootIndex; } set { if (value <= numOfContents) bootIndex = value; } } - /// - /// The content descriptions in the TMD. - /// - public TMD_Content[] Contents { get { return contents.ToArray(); } set { contents = new List(value); numOfContents = (ushort)value.Length; } } - /// - /// If true, the TMD will be fakesigned while saving. - /// - public bool FakeSign { get { return fakeSign; } set { fakeSign = value; } } - - #region IDisposable Members - private bool isDisposed = false; - - ~TMD() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !isDisposed) - { - signature = null; - padding = null; - issuer = null; - reserved = null; - - contents.Clear(); - contents = null; - } - - isDisposed = true; - } - #endregion - - #region Public Functions - /// - /// Loads a tmd file. - /// - /// - /// - public static TMD Load(string pathToTmd) - { - return Load(File.ReadAllBytes(pathToTmd)); - } - - /// - /// Loads a tmd file. - /// - /// - /// - public static TMD Load(byte[] tmdFile) - { - TMD t = new TMD(); - MemoryStream ms = new MemoryStream(tmdFile); - - try { t.parseTmd(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - return t; - } - - /// - /// Loads a tmd file. - /// - /// - /// - public static TMD Load(Stream tmd) - { - TMD t = new TMD(); - t.parseTmd(tmd); - return t; - } - - - - /// - /// Loads a tmd file. - /// - /// - public void LoadFile(string pathToTmd) - { - LoadFile(File.ReadAllBytes(pathToTmd)); - } - - /// - /// Loads a tmd file. - /// - /// - public void LoadFile(byte[] tmdFile) - { - MemoryStream ms = new MemoryStream(tmdFile); - - try { parseTmd(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - } - - /// - /// Loads a tmd file. - /// - /// - public void LoadFile(Stream tmd) - { - parseTmd(tmd); - } - - - - /// - /// Saves the TMD. - /// - /// - public void Save(string savePath) - { - Save(savePath, false); - } - - /// - /// Saves the TMD. If fakeSign is true, the Ticket will be fakesigned. - /// - /// - /// - public void Save(string savePath, bool fakeSign) - { - if (fakeSign) this.fakeSign = true; - if (File.Exists(savePath)) File.Delete(savePath); - - using (FileStream fs = new FileStream(savePath, FileMode.Create)) - writeToStream(fs); - } - - /// - /// Returns the TMD as a memory stream. - /// - /// - public MemoryStream ToMemoryStream() - { - return ToMemoryStream(false); - } - - /// - /// Returns the TMD as a memory stream. If fakeSign is true, the Ticket will be fakesigned. - /// - /// - /// - public MemoryStream ToMemoryStream(bool fakeSign) - { - if (fakeSign) this.fakeSign = true; - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - return ms; - } - - /// - /// Returns the TMD as a byte array. - /// - /// - public byte[] ToByteArray() - { - return ToByteArray(false); - } - - /// - /// Returns the TMD as a byte array. If fakeSign is true, the Ticket will be fakesigned. - /// - /// - /// - public byte[] ToByteArray(bool fakeSign) - { - if (fakeSign) this.fakeSign = true; - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - byte[] res = ms.ToArray(); - ms.Dispose(); - return res; - } - - /// - /// Updates the content entries. - /// - /// - /// True if you use the content ID as name (e.g. 0000008a.app). - /// False if you use the index as name (e.g. 00000000.app) - public void UpdateContents(string contentDir) - { - bool namedContentId = true; - for (int i = 0; i < contents.Count; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + contents[i].ContentID.ToString("x8") + ".app")) - { namedContentId = false; break; } - - if (!namedContentId) - for (int i = 0; i < contents.Count; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + contents[i].ContentID.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); - - byte[][] conts = new byte[contents.Count][]; - - for (int i = 0; i < contents.Count; i++) - { - string file = contentDir + Path.DirectorySeparatorChar + ((namedContentId) ? contents[i].ContentID.ToString("x8") : contents[i].Index.ToString("x8")) + ".app"; - conts[i] = File.ReadAllBytes(file); - } - - updateContents(conts); - } - - /// - /// Updates the content entries. - /// - /// - /// True if you use the content ID as name (e.g. 0000008a.app). - /// False if you use the index as name (e.g. 00000000.app) - public void UpdateContents(byte[][] contents) - { - updateContents(contents); - } - - /// - /// Returns the Upper Title ID as a string. - /// - /// - public string GetUpperTitleID() - { - byte[] titleBytes = BitConverter.GetBytes(Shared.Swap((uint)titleId)); - return new string(new char[] { (char)titleBytes[0], (char)titleBytes[1], (char)titleBytes[2], (char)titleBytes[3] }); - } - - /// - /// The Number of memory blocks the content will take. - /// - /// - public string GetNandBlocks() - { - return calculateNandBlocks(); - } - - /// - /// Adds a TMD content. - /// - /// - public void AddContent(TMD_Content content) - { - contents.Add(content); - - numOfContents = (ushort)contents.Count; - } - - /// - /// Removes the content with the given index. - /// - /// - public void RemoveContent(int contentIndex) - { - for (int i = 0; i < numOfContents; i++) - if (contents[i].Index == contentIndex) - { contents.RemoveAt(i); break; } - - numOfContents = (ushort)contents.Count; - } - - /// - /// Removes the content with the given ID. - /// - /// - public void RemoveContentByID(int contentId) - { - for (int i = 0; i < numOfContents; i++) - if (contents[i].ContentID == contentId) - { contents.RemoveAt(i); break; } - - numOfContents = (ushort)contents.Count; - } - #endregion - - #region Private Functions - private void writeToStream(Stream writeStream) - { - fireDebug("Writing TMD..."); - - if (fakeSign) - { fireDebug(" Clearing Signature..."); signature = new byte[256]; } //Clear Signature if we fake Sign - - MemoryStream ms = new MemoryStream(); - ms.Seek(0, SeekOrigin.Begin); - - fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(signatureExponent)), 0, 4); - - fireDebug(" Writing Signature... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(signature, 0, signature.Length); - - fireDebug(" Writing Padding... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(padding, 0, padding.Length); - - fireDebug(" Writing Issuer... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(issuer, 0, issuer.Length); - - fireDebug(" Writing Version... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.WriteByte(version); - - fireDebug(" Writing CA Crl Version... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.WriteByte(caCrlVersion); - - fireDebug(" Writing Signer Crl Version... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.WriteByte(signerCrlVersion); - - fireDebug(" Writing Padding Byte... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.WriteByte(paddingByte); - - fireDebug(" Writing Startup IOS... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(startupIos)), 0, 8); - - fireDebug(" Writing Title ID... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(titleId)), 0, 8); - - fireDebug(" Writing Title Type... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(titleType)), 0, 4); - - fireDebug(" Writing Group ID... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(groupId)), 0, 2); - - fireDebug(" Writing Padding2... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(padding2)), 0, 2); - - fireDebug(" Writing Region... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(region)), 0, 2); - - fireDebug(" Writing Reserved... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(reserved, 0, reserved.Length); - - fireDebug(" Writing Access Rights... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(accessRights)), 0, 4); - - fireDebug(" Writing Title Version... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(titleVersion)), 0, 2); - - fireDebug(" Writing NumOfContents... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(numOfContents)), 0, 2); - - fireDebug(" Writing Boot Index... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(bootIndex)), 0, 2); - - fireDebug(" Writing Padding3... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(padding3)), 0, 2); - - //Write Contents - List contentList = new List(); - for (int i = 0; i < contents.Count; i++) - contentList.Add(new ContentIndices(i, contents[i].Index)); - - contentList.Sort(); - - for (int i = 0; i < contentList.Count; i++) - { - fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper().ToUpper(), i + 1, numOfContents); - - ms.Write(BitConverter.GetBytes(Shared.Swap(contents[contentList[i].Index].ContentID)), 0, 4); - ms.Write(BitConverter.GetBytes(Shared.Swap(contents[contentList[i].Index].Index)), 0, 2); - ms.Write(BitConverter.GetBytes(Shared.Swap((ushort)contents[contentList[i].Index].Type)), 0, 2); - ms.Write(BitConverter.GetBytes(Shared.Swap(contents[contentList[i].Index].Size)), 0, 8); - - ms.Write(contents[contentList[i].Index].Hash, 0, contents[contentList[i].Index].Hash.Length); - } - - //fake Sign - byte[] tmd = ms.ToArray(); - ms.Dispose(); - - if (fakeSign) - { - fireDebug(" Fakesigning TMD..."); - - byte[] hash = new byte[20]; - SHA1 s = SHA1.Create(); - - for (ushort i = 0; i < 0xFFFF; i++) - { - byte[] bytes = BitConverter.GetBytes(i); - tmd[482] = bytes[1]; tmd[483] = bytes[0]; - - hash = s.ComputeHash(tmd); - if (hash[0] == 0x00) - { fireDebug(" -> Signed ({0})", i); break; } //Win! It's signed... - - if (i == 0xFFFF - 1) - { fireDebug(" -> Signing Failed..."); throw new Exception("Fakesigning failed..."); } - } - - s.Clear(); - } - - writeStream.Seek(0, SeekOrigin.Begin); - writeStream.Write(tmd, 0, tmd.Length); - - fireDebug("Writing TMD Finished..."); - } - - private void updateContents(byte[][] conts) - { - SHA1 s = SHA1.Create(); - - for (int i = 0; i < contents.Count; i++) - { - contents[i].Size = (ulong)conts[i].Length; - contents[i].Hash = s.ComputeHash(conts[i]); - } - - s.Clear(); - } - - private void parseTmd(Stream tmdFile) - { - fireDebug("Pasing TMD..."); - - tmdFile.Seek(0, SeekOrigin.Begin); - byte[] temp = new byte[8]; - - fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 4); - signatureExponent = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - fireDebug(" Reading Signature... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(signature, 0, signature.Length); - - fireDebug(" Reading Padding... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(padding, 0, padding.Length); - - fireDebug(" Reading Issuer... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(issuer, 0, issuer.Length); - - fireDebug(" Reading Version... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading CA Crl Version... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading Signer Crl Version... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading Padding Byte... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 4); - version = temp[0]; - caCrlVersion = temp[1]; - signerCrlVersion = temp[2]; - paddingByte = temp[3]; - - fireDebug(" Reading Startup IOS... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 8); - startupIos = Shared.Swap(BitConverter.ToUInt64(temp, 0)); - - fireDebug(" Reading Title ID... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 8); - titleId = Shared.Swap(BitConverter.ToUInt64(temp, 0)); - - fireDebug(" Reading Title Type... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 4); - titleType = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - fireDebug(" Reading Group ID... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 2); - groupId = Shared.Swap(BitConverter.ToUInt16(temp, 0)); - - fireDebug(" Reading Padding2... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 2); - padding2 = Shared.Swap(BitConverter.ToUInt16(temp, 0)); - - fireDebug(" Reading Region... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 2); - region = Shared.Swap(BitConverter.ToUInt16(temp, 0)); - - fireDebug(" Reading Reserved... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(reserved, 0, reserved.Length); - - fireDebug(" Reading Access Rights... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 4); - accessRights = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - fireDebug(" Reading Title Version... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading NumOfContents... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading Boot Index... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading Padding3... (Offset: 0x{0})", tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(temp, 0, 8); - titleVersion = Shared.Swap(BitConverter.ToUInt16(temp, 0)); - numOfContents = Shared.Swap(BitConverter.ToUInt16(temp, 2)); - bootIndex = Shared.Swap(BitConverter.ToUInt16(temp, 4)); - padding3 = Shared.Swap(BitConverter.ToUInt16(temp, 6)); - - contents = new List(); - - //Read Contents - for (int i = 0; i < numOfContents; i++) - { - fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", i + 1, numOfContents, tmdFile.Position.ToString("x8").ToUpper().ToUpper()); - - TMD_Content tempContent = new TMD_Content(); - tempContent.Hash = new byte[20]; - - tmdFile.Read(temp, 0, 8); - tempContent.ContentID = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - tempContent.Index = Shared.Swap(BitConverter.ToUInt16(temp, 4)); - tempContent.Type = (ContentType)Shared.Swap(BitConverter.ToUInt16(temp, 6)); - - tmdFile.Read(temp, 0, 8); - tempContent.Size = Shared.Swap(BitConverter.ToUInt64(temp, 0)); - - tmdFile.Read(tempContent.Hash, 0, tempContent.Hash.Length); - - contents.Add(tempContent); - } - - fireDebug("Pasing TMD Finished..."); - } - - private string calculateNandBlocks() - { - int nandSizeMin = 0; - int nandSizeMax = 0; - - for (int i = 0; i < numOfContents; i++) - { - nandSizeMax += (int)contents[i].Size; - if (contents[i].Type == ContentType.Normal) nandSizeMin += (int)contents[i].Size; - } - - int blocksMin = (int)Math.Ceiling((double)((double)nandSizeMin / (128 * 1024))); - int blocksMax = (int)Math.Ceiling((double)((double)nandSizeMax / (128 * 1024))); - - if (blocksMin == blocksMax) return blocksMax.ToString(); - else return string.Format("{0} - {1}", blocksMin, blocksMax); - } - #endregion - - #region Events - /// - /// Fires debugging messages. You may write them into a log file or log textbox. - /// - public event EventHandler Debug; - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = Debug; - if (debug != null) - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - #endregion - } - - public class TMD_Content - { - private uint contentId; - private ushort index; - private ushort type; - private ulong size; - private byte[] hash = new byte[20]; - - public uint ContentID { get { return contentId; } set { contentId = value; } } - public ushort Index { get { return index; } set { index = value; } } - public ContentType Type { get { return (ContentType)type; } set { type = (ushort)value; } } - public ulong Size { get { return size; } set { size = value; } } - public byte[] Hash { get { return hash; } set { hash = value; } } - } -} diff --git a/NUS Downloader/TODO b/NUS Downloader/TODO deleted file mode 100644 index 5d608a1..0000000 --- a/NUS Downloader/TODO +++ /dev/null @@ -1,21 +0,0 @@ -/////////////////////////////////////////// -// NUS Downloader: TODO // -// $Rev:: $ // -// $Author:: $ // -// $Date:: $ // -/////////////////////////////////////////// - -Make more compatible with mono for Linux. -Broken stuff: -Working stuff: - - Downloading anything - - Displaying Form1 - - Loading database - - Generating update scripts - - - -Finish scripting improvements. - -Routine: -Verify version number before releases! \ No newline at end of file diff --git a/NUS Downloader/Ticket.cs b/NUS Downloader/Ticket.cs deleted file mode 100644 index e7b0189..0000000 --- a/NUS Downloader/Ticket.cs +++ /dev/null @@ -1,626 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.IO; -using System.Security.Cryptography; - -namespace libWiiSharp -{ - public enum CommonKeyType : byte - { - Standard = 0x00, - Korean = 0x01, - } - - public class Ticket : IDisposable - { - private byte newKeyIndex = (byte)CommonKeyType.Standard; - private byte[] decryptedTitleKey = new byte[16]; - private bool fakeSign = false; - private bool titleKeyChanged = false; - private byte[] newEncryptedTitleKey = new byte[0]; - private bool reDecrypt = false; - - private uint signatureExponent = 0x00010001; - private byte[] signature = new byte[256]; - private byte[] padding = new byte[60]; - private byte[] issuer = new byte[64]; - private byte[] unknown = new byte[63]; - private byte[] encryptedTitleKey = new byte[16]; - private byte unknown2; - private ulong ticketId; - private uint consoleId; - private ulong titleId; - private ushort unknown3 = 0xFFFF; - private ushort numOfDlc; - private ulong unknown4; - private byte padding2; - private byte commonKeyIndex = (byte)CommonKeyType.Standard; - private byte[] unknown5 = new byte[48]; - private byte[] unknown6 = new byte[32]; //0xFF - private ushort padding3; - private uint enableTimeLimit; - private uint timeLimit; - private byte[] padding4 = new byte[88]; - - private bool dsitik = false; - - /// - /// The Title Key the WADs content is encrypted with. - /// - public byte[] TitleKey { get { return decryptedTitleKey; } set { decryptedTitleKey = value; titleKeyChanged = true; reDecrypt = false; } } - /// - /// Defines which Common Key is used (Standard / Korean). - /// - public CommonKeyType CommonKeyIndex { get { return (CommonKeyType)newKeyIndex; } set { newKeyIndex = (byte)value; } } - /// - /// The Ticket ID. - /// - public ulong TicketID { get { return ticketId; } set { ticketId = value; } } - /// - /// The Console ID. - /// - public uint ConsoleID { get { return consoleId; } set { consoleId = value; } } - /// - /// The Title ID. - /// - public ulong TitleID { get { return titleId; } set { titleId = value; if (reDecrypt) reDecryptTitleKey(); } } - /// - /// Number of DLC. - /// - public ushort NumOfDLC { get { return numOfDlc; } set { numOfDlc = value; } } - /// - /// If true, the Ticket will be fakesigned while saving. - /// - public bool FakeSign { get { return fakeSign; } set { fakeSign = value; } } - /// - /// True if the Title Key was changed. - /// - public bool TitleKeyChanged { get { return titleKeyChanged; } } - - /// - /// If true, the Ticket will utilize the DSi CommonKey. - /// - public bool DSiTicket { get { return dsitik; } set { dsitik = value; decryptTitleKey(); } } - - #region IDisposable Members - private bool isDisposed = false; - - ~Ticket() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !isDisposed) - { - decryptedTitleKey = null; - newEncryptedTitleKey = null; - signature = null; - padding = null; - issuer = null; - unknown = null; - encryptedTitleKey = null; - unknown5 = null; - unknown6 = null; - padding4 = null; - } - - isDisposed = true; - } - #endregion - - #region Public Functions - /// - /// Loads a tik file. - /// - /// - /// - public static Ticket Load(string pathToTicket) - { - return Load(File.ReadAllBytes(pathToTicket)); - } - - /// - /// Loads a tik file. - /// - /// - /// - public static Ticket Load(byte[] ticket) - { - Ticket tik = new Ticket(); - MemoryStream ms = new MemoryStream(ticket); - - try { tik.parseTicket(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - return tik; - } - - /// - /// Loads a tik file. - /// - /// - /// - public static Ticket Load(Stream ticket) - { - Ticket tik = new Ticket(); - tik.parseTicket(ticket); - return tik; - } - - - - /// - /// Loads a tik file. - /// - /// - public void LoadFile(string pathToTicket) - { - LoadFile(File.ReadAllBytes(pathToTicket)); - } - - /// - /// Loads a tik file. - /// - /// - public void LoadFile(byte[] ticket) - { - MemoryStream ms = new MemoryStream(ticket); - - try { parseTicket(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - } - - /// - /// Loads a tik file. - /// - /// - public void LoadFile(Stream ticket) - { - parseTicket(ticket); - } - - - - /// - /// Saves the Ticket. - /// - /// - public void Save(string savePath) - { - Save(savePath, false); - } - - /// - /// Saves the Ticket. If fakeSign is true, the Ticket will be fakesigned. - /// - /// - /// - public void Save(string savePath, bool fakeSign) - { - if (fakeSign) this.fakeSign = true; - if (File.Exists(savePath)) File.Delete(savePath); - - using (FileStream fs = new FileStream(savePath, FileMode.Create)) - writeToStream(fs); - } - - /// - /// Returns the Ticket as a memory stream. - /// - /// - public MemoryStream ToMemoryStream() - { - return ToMemoryStream(false); - } - - /// - /// Returns the Ticket as a memory stream. If fakeSign is true, the Ticket will be fakesigned. - /// - /// - /// - public MemoryStream ToMemoryStream(bool fakeSign) - { - if (fakeSign) this.fakeSign = true; - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - return ms; - } - - /// - /// Returns the Ticket as a byte array. - /// - /// - public byte[] ToByteArray() - { - return ToByteArray(false); - } - - /// - /// Returns the Ticket as a byte array. If fakeSign is true, the Ticket will be fakesigned. - /// - /// - /// - public byte[] ToByteArray(bool fakeSign) - { - if (fakeSign) this.fakeSign = true; - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - byte[] res = ms.ToArray(); - ms.Dispose(); - return res; - } - - /// - /// This will set a new encrypted Title Key (i.e. the one that you can "read" in the Ticket). - /// - /// - public void SetTitleKey(string newTitleKey) - { - SetTitleKey(newTitleKey.ToCharArray()); - } - - /// - /// This will set a new encrypted Title Key (i.e. the one that you can "read" in the Ticket). - /// - /// - public void SetTitleKey(char[] newTitleKey) - { - if (newTitleKey.Length != 16) - throw new Exception("The title key must be 16 characters long!"); - - for (int i = 0; i < 16; i++) - encryptedTitleKey[i] = (byte)newTitleKey[i]; - - decryptTitleKey(); - titleKeyChanged = true; - - reDecrypt = true; - newEncryptedTitleKey = encryptedTitleKey; - } - - /// - /// This will set a new encrypted Title Key (i.e. the one that you can "read" in the Ticket). - /// - /// - public void SetTitleKey(byte[] newTitleKey) - { - if (newTitleKey.Length != 16) - throw new Exception("The title key must be 16 characters long!"); - - encryptedTitleKey = newTitleKey; - decryptTitleKey(); - titleKeyChanged = true; - - reDecrypt = true; - newEncryptedTitleKey = newTitleKey; - } - - /// - /// Returns the Upper Title ID as a string. - /// - /// - public string GetUpperTitleID() - { - byte[] titleBytes = BitConverter.GetBytes(Shared.Swap((uint)titleId)); - return new string(new char[] { (char)titleBytes[0], (char)titleBytes[1], (char)titleBytes[2], (char)titleBytes[3] }); - } - #endregion - - #region Private Functions - private void writeToStream(Stream writeStream) - { - fireDebug("Writing Ticket..."); - - fireDebug(" Encrypting Title Key..."); - encryptTitleKey(); - fireDebug(" -> Decrypted Title Key: {0}", Shared.ByteArrayToString(decryptedTitleKey)); - fireDebug(" -> Encrypted Title Key: {0}", Shared.ByteArrayToString(encryptedTitleKey)); - - if (fakeSign) - { fireDebug(" Clearing Signature..."); signature = new byte[256]; } //Clear Signature if we fake Sign - - MemoryStream ms = new MemoryStream(); - ms.Seek(0, SeekOrigin.Begin); - - fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(signatureExponent)), 0, 4); - - fireDebug(" Writing Signature... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(signature, 0, signature.Length); - - fireDebug(" Writing Padding... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(padding, 0, padding.Length); - - fireDebug(" Writing Issuer... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(issuer, 0, issuer.Length); - - fireDebug(" Writing Unknown... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(unknown, 0, unknown.Length); - - fireDebug(" Writing Title Key... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(encryptedTitleKey, 0, encryptedTitleKey.Length); - - fireDebug(" Writing Unknown2... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.WriteByte(unknown2); - - fireDebug(" Writing Ticket ID... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(ticketId)), 0, 8); - - fireDebug(" Writing Console ID... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(consoleId)), 0, 4); - - fireDebug(" Writing Title ID... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(titleId)), 0, 8); - - fireDebug(" Writing Unknwon3... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(unknown3)), 0, 2); - - fireDebug(" Writing NumOfDLC... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(numOfDlc)), 0, 2); - - fireDebug(" Writing Unknwon4... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(unknown4)), 0, 8); - - fireDebug(" Writing Padding2... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.WriteByte(padding2); - - fireDebug(" Writing Common Key Index... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.WriteByte(commonKeyIndex); - - fireDebug(" Writing Unknown5... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(unknown5, 0, unknown5.Length); - - fireDebug(" Writing Unknown6... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(unknown6, 0, unknown6.Length); - - fireDebug(" Writing Padding3... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(padding3)), 0, 2); - - fireDebug(" Writing Enable Time Limit... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(enableTimeLimit)), 0, 4); - - fireDebug(" Writing Time Limit... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(BitConverter.GetBytes(Shared.Swap(timeLimit)), 0, 4); - - fireDebug(" Writing Padding4... (Offset: 0x{0})", ms.Position.ToString("x8").ToUpper()); - ms.Write(padding4, 0, padding4.Length); - - byte[] tik = ms.ToArray(); - ms.Dispose(); - - //fake Sign - if (fakeSign) - { - fireDebug(" Fakesigning Ticket..."); - - byte[] hash = new byte[20]; - SHA1 s = SHA1.Create(); - - for (ushort i = 0; i < 0xFFFF; i++) - { - byte[] bytes = BitConverter.GetBytes(i); - tik[498] = bytes[1]; tik[499] = bytes[0]; - - hash = s.ComputeHash(tik); - if (hash[0] == 0x00) - { fireDebug(" -> Signed ({0})", i); break; } //Win! It's signed... - - if (i == 0xFFFF - 1) - { fireDebug(" -> Signing Failed..."); throw new Exception("Fakesigning failed..."); } - } - - s.Clear(); - } - - writeStream.Seek(0, SeekOrigin.Begin); - writeStream.Write(tik, 0, tik.Length); - - fireDebug("Writing Ticket Finished..."); - } - - private void parseTicket(Stream ticketFile) - { - fireDebug("Parsing Ticket..."); - - ticketFile.Seek(0, SeekOrigin.Begin); - byte[] temp = new byte[8]; - - fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 4); - signatureExponent = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - fireDebug(" Reading Signature... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(signature, 0, signature.Length); - - fireDebug(" Reading Padding... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(padding, 0, padding.Length); - - fireDebug(" Reading Issuer... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(issuer, 0, issuer.Length); - - fireDebug(" Reading Unknown... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(unknown, 0, unknown.Length); - - fireDebug(" Reading Title Key... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(encryptedTitleKey, 0, encryptedTitleKey.Length); - - fireDebug(" Reading Unknown2... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - unknown2 = (byte)ticketFile.ReadByte(); - - fireDebug(" Reading Ticket ID.. (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 8); - ticketId = Shared.Swap(BitConverter.ToUInt64(temp, 0)); - - fireDebug(" Reading Console ID... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 4); - consoleId = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - fireDebug(" Reading Title ID... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 8); - titleId = Shared.Swap(BitConverter.ToUInt64(temp, 0)); - - fireDebug(" Reading Unknown3... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading NumOfDLC... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 4); - unknown3 = Shared.Swap(BitConverter.ToUInt16(temp, 0)); - numOfDlc = Shared.Swap(BitConverter.ToUInt16(temp, 2)); - - fireDebug(" Reading Unknown4... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 8); - unknown4 = Shared.Swap(BitConverter.ToUInt64(temp, 0)); - - fireDebug(" Reading Padding2... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - padding2 = (byte)ticketFile.ReadByte(); - - fireDebug(" Reading Common Key Index... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - commonKeyIndex = (byte)ticketFile.ReadByte(); - - newKeyIndex = commonKeyIndex; - - fireDebug(" Reading Unknown5... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(unknown5, 0, unknown5.Length); - - fireDebug(" Reading Unknown6... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(unknown6, 0, unknown6.Length); - - fireDebug(" Reading Padding3... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 2); - padding3 = Shared.Swap(BitConverter.ToUInt16(temp, 0)); - - fireDebug(" Reading Enable Time Limit... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - fireDebug(" Reading Time Limit... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(temp, 0, 8); - enableTimeLimit = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - timeLimit = Shared.Swap(BitConverter.ToUInt32(temp, 4)); - - fireDebug(" Reading Padding4... (Offset: 0x{0})", ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(padding4, 0, padding4.Length); - - fireDebug(" Decrypting Title Key..."); - decryptTitleKey(); - fireDebug(" -> Encrypted Title Key: {0}", Shared.ByteArrayToString(encryptedTitleKey)); - fireDebug(" -> Decrypted Title Key: {0}", Shared.ByteArrayToString(decryptedTitleKey)); - - fireDebug("Parsing Ticket Finished..."); - } - - private void decryptTitleKey() - { - byte[] ckey; - if (dsitik) - { - ckey = CommonKey.GetDSiKey(); - } - else - ckey = (commonKeyIndex == 0x01) ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey(); - byte[] iv = BitConverter.GetBytes(Shared.Swap(titleId)); - Array.Resize(ref iv, 16); - - RijndaelManaged rm = new RijndaelManaged(); - rm.Mode = CipherMode.CBC; - rm.Padding = PaddingMode.None; - rm.KeySize = 128; - rm.BlockSize = 128; - rm.Key = ckey; - rm.IV = iv; - - ICryptoTransform decryptor = rm.CreateDecryptor(); - - MemoryStream ms = new MemoryStream(encryptedTitleKey); - CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); - - cs.Read(decryptedTitleKey, 0, decryptedTitleKey.Length); - - cs.Dispose(); - ms.Dispose(); - decryptor.Dispose(); - rm.Clear(); - } - - private void encryptTitleKey() - { - commonKeyIndex = newKeyIndex; - byte[] ckey; - if (dsitik) - ckey = CommonKey.GetDSiKey(); - else - ckey = (commonKeyIndex == 0x01) ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey(); - byte[] iv = BitConverter.GetBytes(Shared.Swap(titleId)); - Array.Resize(ref iv, 16); - - RijndaelManaged rm = new RijndaelManaged(); - rm.Mode = CipherMode.CBC; - rm.Padding = PaddingMode.None; - rm.KeySize = 128; - rm.BlockSize = 128; - rm.Key = ckey; - rm.IV = iv; - - ICryptoTransform encryptor = rm.CreateEncryptor(); - - MemoryStream ms = new MemoryStream(decryptedTitleKey); - CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Read); - - cs.Read(encryptedTitleKey, 0, encryptedTitleKey.Length); - - cs.Dispose(); - ms.Dispose(); - encryptor.Dispose(); - rm.Clear(); - } - - private void reDecryptTitleKey() - { - encryptedTitleKey = newEncryptedTitleKey; - decryptTitleKey(); - } - #endregion - - #region Events - /// - /// Fires debugging messages. You may write them into a log file or log textbox. - /// - public event EventHandler Debug; - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = Debug; - if (debug != null) - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - #endregion - } -} diff --git a/NUS Downloader/U8.cs b/NUS Downloader/U8.cs deleted file mode 100644 index 3d73107..0000000 --- a/NUS Downloader/U8.cs +++ /dev/null @@ -1,1120 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Security.Cryptography; - -namespace libWiiSharp -{ - public enum U8_NodeType : ushort - { - File = 0x0000, - Directory = 0x0100, - } - - public class U8 : IDisposable - { - private const int dataPadding = 32; - private Headers.HeaderType headerType = Headers.HeaderType.None; - private object header = null; - private U8_Header u8Header = new U8_Header(); - private U8_Node rootNode = new U8_Node(); - private List u8Nodes = new List(); - private List stringTable = new List(); - private List data = new List(); - private int iconSize = -1; - private int bannerSize = -1; - private int soundSize = -1; - private bool lz77 = false; - - /// - /// The type of the Header of the U8 file. - /// - public Headers.HeaderType HeaderType { get { return headerType; } } - /// - /// The Header of the U8 file as an object. Will be null if the file has no Header. - /// - public object Header { get { return header; } } - /// - /// The Rootnode of the U8 file. - /// - public U8_Node RootNode { get { return rootNode; } } - /// - /// The Nodes of the U8 file. - /// - public List Nodes { get { return u8Nodes; } } - /// - /// The string table of the U8 file. - /// - public string[] StringTable { get { return stringTable.ToArray(); } } - /// - /// The actual data (files) in the U8 file. Will be an empty byte array for directory entries. - /// - public byte[][] Data { get { return data.ToArray(); } } - - /// - /// The Number of Nodes WITHOUT the Rootnode. - /// - public int NumOfNodes { get { return (int)rootNode.SizeOfData - 1; } } - /// - /// The size of the icon.bin (if the U8 files contains an icon.bin). - /// - public int IconSize { get { return iconSize; } } - /// - /// The size of the banner.bin (if the U8 files contains an banner.bin). - /// - public int BannerSize { get { return bannerSize; } } - /// - /// The size of the sound.bin (if the U8 files contains an sound.bin). - /// - public int SoundSize { get { return soundSize; } } - /// - /// If true, the U8 file will be Lz77 compressed while saving. - /// - public bool Lz77Compress { get { return lz77; } set { lz77 = value; } } - - public U8() - { - rootNode.Type = U8_NodeType.Directory; - } - - #region IDisposable Members - private bool isDisposed = false; - - ~U8() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !isDisposed) - { - header = null; - u8Header = null; - rootNode = null; - - u8Nodes.Clear(); - u8Nodes = null; - - stringTable.Clear(); - stringTable = null; - - data.Clear(); - data = null; - } - - isDisposed = true; - } - #endregion - - #region Public Functions - /// - /// Checks whether a file is a U8 file or not. - /// - /// - /// - public static bool IsU8(string pathToFile) - { - return IsU8(File.ReadAllBytes(pathToFile)); - } - - /// - /// Checks whether a file is a U8 file or not. - /// - /// - /// - public static bool IsU8(byte[] file) - { - if (Lz77.IsLz77Compressed(file)) - { - byte[] partOfFile = new byte[(file.Length > 2000) ? 2000 : file.Length]; - - for (int i = 0; i < partOfFile.Length; i++) - partOfFile[i] = file[i]; - - Lz77 l = new Lz77(); - partOfFile = l.Decompress(partOfFile); - - return IsU8(partOfFile); - } - else - { - Headers.HeaderType h = Headers.DetectHeader(file); - return (Shared.Swap(BitConverter.ToUInt32(file, (int)h)) == 0x55AA382D); - } - } - - - - /// - /// Loads a U8 file. - /// - /// - /// - public static U8 Load(string pathToU8) - { - return Load(File.ReadAllBytes(pathToU8)); - } - - /// - /// Loads a U8 file. - /// - /// - /// - public static U8 Load(byte[] u8File) - { - U8 u = new U8(); - MemoryStream ms = new MemoryStream(u8File); - - try { u.parseU8(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - return u; - } - - /// - /// Loads a U8 file. - /// - /// - /// - public static U8 Load(Stream u8File) - { - U8 u = new U8(); - u.parseU8(u8File); - return u; - } - - /// - /// Creates a U8 file. - /// - /// - /// - public static U8 FromDirectory(string pathToDirectory) - { - U8 u = new U8(); - u.createFromDir(pathToDirectory); - return u; - } - - - - /// - /// Loads a U8 file. - /// - /// - public void LoadFile(string pathToU8) - { - LoadFile(File.ReadAllBytes(pathToU8)); - } - - /// - /// Loads a U8 file. - /// - /// - public void LoadFile(byte[] u8File) - { - MemoryStream ms = new MemoryStream(u8File); - - try { parseU8(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - } - - /// - /// Loads a U8 file. - /// - /// - public void LoadFile(Stream u8File) - { - parseU8(u8File); - } - - /// - /// Creates a U8 file. - /// - /// - public void CreateFromDirectory(string pathToDirectory) - { - createFromDir(pathToDirectory); - } - - - - /// - /// Saves the U8 file. - /// - /// - public void Save(string savePath) - { - if (File.Exists(savePath)) File.Delete(savePath); - - using (FileStream fs = new FileStream(savePath, FileMode.Create)) - writeToStream(fs); - } - - /// - /// Returns the U8 file as a memory stream. - /// - /// - public MemoryStream ToMemoryStream() - { - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - return ms; - } - - /// - /// Returns the U8 file as a byte array. - /// - /// - public byte[] ToByteArray() - { - return ToMemoryStream().ToArray(); - } - - /// - /// Unpacks the U8 file to given directory. - /// - /// - public void Unpack(string saveDir) - { - unpackToDir(saveDir); - } - - /// - /// Unpacks the U8 file to given directory. - /// - /// - public void Extract(string saveDir) - { - unpackToDir(saveDir); - } - - /// - /// Adds an IMET Header to the U8 file. - /// - /// - /// - public void AddHeaderImet(bool shortImet, params string[] titles) - { - if (iconSize == -1) - throw new Exception("icon.bin wasn't found!"); - else if (bannerSize == -1) - throw new Exception("banner.bin wasn't found!"); - else if (soundSize == -1) - throw new Exception("sound.bin wasn't found!"); - - header = Headers.IMET.Create(shortImet, iconSize, bannerSize, soundSize, titles); - headerType = (shortImet) ? Headers.HeaderType.ShortIMET : Headers.HeaderType.IMET; - } - - /// - /// Adds an IMD5 Header to the U8 file. - /// - public void AddHeaderImd5() - { - headerType = Headers.HeaderType.IMD5; - } - - /// - /// Replaces the file with the given index. - /// - /// - /// - public void ReplaceFile(int fileIndex, string pathToNewFile, bool changeFileName = false) - { - if (u8Nodes[fileIndex].Type == U8_NodeType.Directory) - throw new Exception("You can't replace a directory with a file!"); - - data[fileIndex] = File.ReadAllBytes(pathToNewFile); - if (changeFileName) stringTable[fileIndex] = Path.GetFileName(pathToNewFile); - - if (stringTable[fileIndex].ToLower() == "icon.bin") - iconSize = getRealSize(File.ReadAllBytes(pathToNewFile)); - else if (stringTable[fileIndex].ToLower() == "banner.bin") - bannerSize = getRealSize(File.ReadAllBytes(pathToNewFile)); - else if (stringTable[fileIndex].ToLower() == "sound.bin") - soundSize = getRealSize(File.ReadAllBytes(pathToNewFile)); - } - - /// - /// Replaces the file with the given index. - /// - /// - /// - public void ReplaceFile(int fileIndex, byte[] newData) - { - if (u8Nodes[fileIndex].Type == U8_NodeType.Directory) - throw new Exception("You can't replace a directory with a file!"); - - data[fileIndex] = newData; - - if (stringTable[fileIndex].ToLower() == "icon.bin") - iconSize = getRealSize(newData); - else if (stringTable[fileIndex].ToLower() == "banner.bin") - bannerSize = getRealSize(newData); - else if (stringTable[fileIndex].ToLower() == "sound.bin") - soundSize = getRealSize(newData); - } - - /// - /// Returns the index of the directory or file with the given name. - /// If no matching Node is found, -1 will be returned. - /// - /// - /// - public int GetNodeIndex(string fileOrDirName) - { - for (int i = 0; i < u8Nodes.Count; i++) - if (stringTable[i].ToLower() == fileOrDirName.ToLower()) return i; - - return -1; - } - - /// - /// Changes the name of a node. - /// - /// - /// - public void RenameNode(int index, string newName) - { - stringTable[index] = newName; - } - - /// - /// Changes the name of a node. - /// - /// - /// - public void RenameNode(string oldName, string newName) - { - stringTable[GetNodeIndex(oldName)] = newName; - } - - /// - /// Adds a directory to the U8 file. - /// Path must be like this: "/arc/timg/newFolder". - /// - /// - public void AddDirectory(string path) - { - addEntry(path, new byte[0]); - } - - /// - /// Adds a file to the U8 file. - /// Path must be like this: "/arc/timg/newFile.tpl". - /// - /// - /// - public void AddFile(string path, byte[] data) - { - addEntry(path, data); - } - - /// - /// Removes a directory from the U8 file. - /// If the directory contains files/dirs, they will also be deleted. - /// Path must be like this: "/arc/timg/folderToDelete". - /// - /// - public void RemoveDirectory(string path) - { - removeEntry(path); - } - - /// - /// Removes a file from the U8 file. - /// Path must be like this: "/arc/timg/fileToDelete.tpl". - /// - /// - public void RemoveFile(string path) - { - removeEntry(path); - } - #endregion - - #region Private Functions - private void writeToStream(Stream writeStream) - { - fireDebug("Writing U8 File..."); - - //Update Rootnode - fireDebug(" Updating Rootnode..."); - rootNode.SizeOfData = (uint)u8Nodes.Count + 1; - - MemoryStream u8Stream = new MemoryStream(); - - //Write Stringtable - u8Stream.Seek(u8Header.OffsetToRootNode + ((u8Nodes.Count + 1) * 12), SeekOrigin.Begin); - - fireDebug(" Writing String Table... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); - u8Stream.WriteByte(0x00); - - int stringTablePosition = (int)u8Stream.Position - 1; - for (int i = 0; i < u8Nodes.Count; i++) - { - fireDebug(" -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count, stringTable[i]); - - u8Nodes[i].OffsetToName = (ushort)(u8Stream.Position - stringTablePosition); - byte[] stringBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(stringTable[i]); - - u8Stream.Write(stringBytes, 0, stringBytes.Length); - u8Stream.WriteByte(0x00); - } - - u8Header.HeaderSize = (uint)(u8Stream.Position - u8Header.OffsetToRootNode); - u8Header.OffsetToData = 0; - - //Write Data - for (int i = 0; i < u8Nodes.Count; i++) - { - fireProgress((i + 1) * 100 / u8Nodes.Count); - - if (u8Nodes[i].Type == U8_NodeType.File) - { - u8Stream.Seek(Shared.AddPadding((int)u8Stream.Position, dataPadding), SeekOrigin.Begin); - - fireDebug(" Writing Data #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count); - - if (u8Header.OffsetToData == 0) u8Header.OffsetToData = (uint)u8Stream.Position; - u8Nodes[i].OffsetToData = (uint)u8Stream.Position; - u8Nodes[i].SizeOfData = (uint)data[i].Length; - - u8Stream.Write(data[i], 0, data[i].Length); - } - else fireDebug(" Node #{0} of {1} is a Directory...", i + 1, u8Nodes.Count); - } - - //Pad End to 16 bytes - while (u8Stream.Position % 16 != 0) - u8Stream.WriteByte(0x00); - - //Write Header + Nodes - u8Stream.Seek(0, SeekOrigin.Begin); - - fireDebug(" Writing Header... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); - u8Header.Write(u8Stream); - - fireDebug(" Writing Rootnode... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); - rootNode.Write(u8Stream); - - for (int i = 0; i < u8Nodes.Count; i++) - { - fireDebug(" Writing Node Entry #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count); - u8Nodes[i].Write(u8Stream); - } - - byte[] u8Array = u8Stream.ToArray(); - u8Stream.Dispose(); - - if (lz77) - { - fireDebug(" Lz77 Compressing U8 File..."); - - Lz77 l = new Lz77(); - u8Array = l.Compress(u8Array); - } - - //Write File Header - if (headerType == Headers.HeaderType.IMD5) - { - fireDebug(" Adding IMD5 Header..."); - - writeStream.Seek(0, SeekOrigin.Begin); - Headers.IMD5 h = Headers.IMD5.Create(u8Array); - h.Write(writeStream); - } - else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET) - { - fireDebug(" Adding IMET Header..."); - - ((Headers.IMET)header).IconSize = (uint)iconSize; - ((Headers.IMET)header).BannerSize = (uint)bannerSize; - ((Headers.IMET)header).SoundSize = (uint)soundSize; - - writeStream.Seek(0, SeekOrigin.Begin); - ((Headers.IMET)header).Write(writeStream); - } - - writeStream.Write(u8Array, 0, u8Array.Length); - - fireDebug("Writing U8 File Finished..."); - } - - private void unpackToDir(string saveDir) - { - fireDebug("Unpacking U8 File to: {0}", saveDir); - - if (!Directory.Exists(saveDir)) Directory.CreateDirectory(saveDir); - - string[] dirs = new string[u8Nodes.Count]; - dirs[0] = saveDir; - int[] dirCount = new int[u8Nodes.Count]; - int dirIndex = 0; - - for (int i = 0; i < u8Nodes.Count; i++) - { - fireDebug(" Unpacking Entry #{0} of {1}", i + 1, u8Nodes.Count); - fireProgress((i + 1) * 100 / u8Nodes.Count); - - switch (u8Nodes[i].Type) - { - case U8_NodeType.Directory: - fireDebug(" -> Directory: \"{0}\"", stringTable[i]); - - if (dirs[dirIndex][dirs[dirIndex].Length - 1] != Path.DirectorySeparatorChar) { dirs[dirIndex] = dirs[dirIndex] + Path.DirectorySeparatorChar; } - Directory.CreateDirectory(dirs[dirIndex] + stringTable[i]); - dirs[dirIndex + 1] = dirs[dirIndex] + stringTable[i]; - dirIndex++; - dirCount[dirIndex] = (int)u8Nodes[i].SizeOfData; - break; - default: - fireDebug(" -> File: \"{0}\"", stringTable[i]); - fireDebug(" -> Size: {0} bytes", data[i].Length); - - using (FileStream fs = new FileStream(dirs[dirIndex] + Path.DirectorySeparatorChar + stringTable[i], FileMode.Create)) - fs.Write(data[i], 0, data[i].Length); - break; - } - - while (dirIndex > 0 && dirCount[dirIndex] == i + 2) - { dirIndex--; } - } - - fireDebug("Unpacking U8 File Finished"); - } - - private void parseU8(Stream u8File) - { - fireDebug("Pasing U8 File..."); - - u8Header = new U8_Header(); - rootNode = new U8_Node(); - u8Nodes = new List(); - stringTable = new List(); - data = new List(); - - fireDebug(" Detecting Header..."); - headerType = Headers.DetectHeader(u8File); - Headers.HeaderType tempType = headerType; - - fireDebug(" -> {0}", headerType.ToString()); - - if (headerType == Headers.HeaderType.IMD5) - { - fireDebug(" Reading IMD5 Header..."); - header = Headers.IMD5.Load(u8File); - - byte[] file = new byte[u8File.Length]; - u8File.Read(file, 0, file.Length); - - MD5 m = MD5.Create(); - byte[] newHash = m.ComputeHash(file, (int)headerType, (int)u8File.Length - (int)headerType); - m.Clear(); - - if (!Shared.CompareByteArrays(newHash, ((Headers.IMD5)header).Hash)) - { - fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); - fireWarning(string.Format("Hashes of IMD5 header and file do not match! The content might be corrupted!")); - } - } - else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET) - { - fireDebug(" Reading IMET Header..."); - header = Headers.IMET.Load(u8File); - - if (!((Headers.IMET)header).HashesMatch) - { - fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); - fireWarning(string.Format("The hash stored in the IMET header doesn't match the headers hash! The header and/or file might be corrupted!")); - } - } - - fireDebug(" Checking for Lz77 Compression..."); - if (Lz77.IsLz77Compressed(u8File)) - { - fireDebug(" -> Lz77 Compression Found..."); - fireDebug(" Decompressing U8 Data..."); - - Lz77 l = new Lz77(); - Stream decompressedFile = l.Decompress(u8File); - - tempType = Headers.DetectHeader(decompressedFile); - u8File = decompressedFile; - - lz77 = true; - } - - u8File.Seek((int)tempType, SeekOrigin.Begin); - byte[] temp = new byte[4]; - - //Read U8 Header - fireDebug(" Reading U8 Header: Magic... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - u8File.Read(temp, 0, 4); - if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.U8Magic) - { fireDebug(" -> Invalid Magic!"); throw new Exception("U8 Header: Invalid Magic!"); } - - fireDebug(" Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - u8File.Read(temp, 0, 4); - if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.OffsetToRootNode) - { fireDebug(" -> Invalid Offset to Rootnode"); throw new Exception("U8 Header: Invalid Offset to Rootnode!"); } - - fireDebug(" Reading U8 Header: Header Size... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - u8File.Read(temp, 0, 4); - u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - fireDebug(" Reading U8 Header: Offset to Data... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - u8File.Read(temp, 0, 4); - u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - u8File.Seek(16, SeekOrigin.Current); - - //Read Rootnode - fireDebug(" Reading Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - u8File.Read(temp, 0, 4); - rootNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); - rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); - - u8File.Read(temp, 0, 4); - rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - u8File.Read(temp, 0, 4); - rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - int stringTablePosition = (int)((int)tempType + u8Header.OffsetToRootNode + rootNode.SizeOfData * 12); - int nodePosition = (int)u8File.Position; - - //Read Nodes - for (int i = 0; i < rootNode.SizeOfData - 1; i++) - { - fireDebug(" Reading Node #{1} of {2}... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper(), i + 1, rootNode.SizeOfData - 1); - fireProgress((int)((i + 1) * 100 / (rootNode.SizeOfData - 1))); - - U8_Node tempNode = new U8_Node(); - string tempName = string.Empty; - byte[] tempData = new byte[0]; - - //Read Node Entry - u8File.Seek(nodePosition, SeekOrigin.Begin); - - fireDebug(" -> Reading Node Entry... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - u8File.Read(temp, 0, 4); - tempNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); - tempNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); - - u8File.Read(temp, 0, 4); - tempNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - u8File.Read(temp, 0, 4); - tempNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - nodePosition = (int)u8File.Position; - - fireDebug(" -> {0}", tempNode.Type.ToString()); - - //Read Node Name - u8File.Seek(stringTablePosition + tempNode.OffsetToName, SeekOrigin.Begin); - - fireDebug(" -> Reading Node Name... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - for (;;) - { - char tempChar = (char)u8File.ReadByte(); - if (tempChar == 0x00) break; - - tempName += tempChar; - - if (tempName.Length > 255) break; - } - - fireDebug(" -> {0}", tempName); - - //Read Node Data - if (tempNode.Type == U8_NodeType.File) - { - u8File.Seek((int)tempType + tempNode.OffsetToData, SeekOrigin.Begin); - - fireDebug(" -> Reading Node Data (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); - - tempData = new byte[tempNode.SizeOfData]; - u8File.Read(tempData, 0, tempData.Length); - } - - if (tempName.ToLower() == "icon.bin") iconSize = getRealSize(tempData); - else if (tempName.ToLower() == "banner.bin") bannerSize = getRealSize(tempData); - else if (tempName.ToLower() == "sound.bin") soundSize = getRealSize(tempData); - - u8Nodes.Add(tempNode); - stringTable.Add(tempName); - data.Add(tempData); - } - - fireDebug("Pasing U8 File Finished..."); - } - - private void createFromDir(string path) - { - fireDebug("Creating U8 File from: {0}", path); - - if (path[path.Length - 1] != Path.DirectorySeparatorChar) path += Path.DirectorySeparatorChar; - - fireDebug(" Collecting Content..."); - string[] dirEntries = getDirContent(path, true); - int offsetToName = 1; - int offsetToData = 0; - - fireDebug(" Creating U8 Header..."); - u8Header = new U8_Header(); - rootNode = new U8_Node(); - u8Nodes = new List(); - stringTable = new List(); - data = new List(); - - //Create Rootnode - fireDebug(" Creating Rootnode..."); - rootNode.Type = U8_NodeType.Directory; - rootNode.OffsetToName = 0; - rootNode.OffsetToData = 0; - rootNode.SizeOfData = (uint)dirEntries.Length + 1; - - //Create Nodes - for (int i = 0; i < dirEntries.Length; i++) - { - fireDebug(" Creating Node #{0} of {1}", i + 1, dirEntries.Length); - fireProgress((i + 1) * 100 / dirEntries.Length); - - U8_Node tempNode = new U8_Node(); - byte[] tempData = new byte[0]; - - string tempDirEntry = dirEntries[i].Remove(0, path.Length - 1); - - if (Directory.Exists(dirEntries[i])) //It's a dir - { - fireDebug(" -> Directory"); - - tempNode.Type = U8_NodeType.Directory; - tempNode.OffsetToData = (uint)Shared.CountCharsInString(tempDirEntry, Path.DirectorySeparatorChar); //Recursion - - int size = u8Nodes.Count + 2; - for (int j = 0; j < dirEntries.Length; j++) - if (dirEntries[j].Contains(dirEntries[i] + System.IO.Path.DirectorySeparatorChar.ToString())) size++; - - tempNode.SizeOfData = (uint)size; - } - else //It's a file - { - fireDebug(" -> File"); - fireDebug(" -> Reading File Data..."); - - tempData = File.ReadAllBytes(dirEntries[i]); - tempNode.Type = U8_NodeType.File; - tempNode.OffsetToData = (uint)offsetToData; - tempNode.SizeOfData = (uint)tempData.Length; - - offsetToData += Shared.AddPadding(offsetToData + tempData.Length, dataPadding); - } - - tempNode.OffsetToName = (ushort)offsetToName; - offsetToName += (Path.GetFileName(dirEntries[i])).Length + 1; - - fireDebug(" -> Reading Name..."); - string tempName = Path.GetFileName(dirEntries[i]); - - if (tempName.ToLower() == "icon.bin") iconSize = getRealSize(tempData); - else if (tempName.ToLower() == "banner.bin") bannerSize = getRealSize(tempData); - else if (tempName.ToLower() == "sound.bin") soundSize = getRealSize(tempData); - - u8Nodes.Add(tempNode); - stringTable.Add(tempName); - data.Add(tempData); - } - - //Update U8 Header - fireDebug(" Updating U8 Header..."); - u8Header.HeaderSize = (uint)(((u8Nodes.Count + 1) * 12) + offsetToName); - u8Header.OffsetToData = (uint)Shared.AddPadding((int)u8Header.OffsetToRootNode + (int)u8Header.HeaderSize, dataPadding); - - //Update dataOffsets - fireDebug(" Calculating Data Offsets..."); - - for (int i = 0; i < u8Nodes.Count; i++) - { - fireDebug(" -> Node #{0} of {1}...", i + 1, u8Nodes.Count); - - int tempOffset = (int)u8Nodes[i].OffsetToData; - u8Nodes[i].OffsetToData = (uint)(u8Header.OffsetToData + tempOffset); - } - - fireDebug("Creating U8 File Finished..."); - } - - private string[] getDirContent(string dir, bool root) - { - string[] files = Directory.GetFiles(dir); - string[] dirs = Directory.GetDirectories(dir); - string all = ""; - - if (!root) - all += dir + "\n"; - - for (int i = 0; i < files.Length; i++) - all += files[i] + "\n"; - - foreach (string thisDir in dirs) - { - string[] temp = getDirContent(thisDir, false); - - foreach (string thisTemp in temp) - all += thisTemp + "\n"; - } - - return all.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); - } - - private int getRealSize(byte[] data) - { - if (data[0] == 'I' && data[1] == 'M' && data[2] == 'D' && data[3] == '5') - if (data[0x20] == 'L' && data[0x21] == 'Z' && data[0x22] == '7' && data[0x23] == '7') - return (BitConverter.ToInt32(data, 0x24)) >> 8; - else - return data.Length - 32; - - return data.Length; - } - - private void addEntry(string nodePath, byte[] fileData) - { - //Parse path - if (nodePath.StartsWith("/")) nodePath = nodePath.Remove(0, 1); - string[] path = nodePath.Split('/'); //Last entry is the filename - - int nodeIndex = -1; - int maxIndex = (u8Nodes.Count > 0) ? u8Nodes.Count - 1 : 0; - int currentIndex = 0; - List pathIndices = new List(); - - for (int i = 0; i < path.Length - 1; i++) - { - for (int j = currentIndex; j <= maxIndex; j++) - { - if (stringTable[j].ToLower() == path[i].ToLower()) - { - if (i == path.Length - 2) nodeIndex = j; - - maxIndex = (int)u8Nodes[j].SizeOfData - 1; - currentIndex = j + 1; - pathIndices.Add(j); - - break; - } - - if (j == maxIndex - 1) throw new Exception("Path wasn't found!"); - } - } - - //Get last entry in current dir - int lastEntry; - - if (nodeIndex > -1) lastEntry = (int)u8Nodes[nodeIndex].SizeOfData - 2; - else lastEntry = (rootNode.SizeOfData > 1) ? (int)rootNode.SizeOfData - 2 : -1; - - //Create and insert node + data - U8_Node tempNode = new U8_Node(); - tempNode.Type = (fileData.Length == 0) ? U8_NodeType.Directory : U8_NodeType.File; - tempNode.SizeOfData = (uint)((fileData.Length == 0) ? lastEntry + 2 : fileData.Length); - tempNode.OffsetToData = (uint)((fileData.Length == 0) ? Shared.CountCharsInString(nodePath, '/') : 0); - - stringTable.Insert(lastEntry + 1, path[path.Length - 1]); - u8Nodes.Insert(lastEntry + 1, tempNode); - data.Insert(lastEntry + 1, fileData); - - //Update rootnode and path sizes (+1) - rootNode.SizeOfData += 1; - - foreach (int index in pathIndices) - if (u8Nodes[index].Type == U8_NodeType.Directory) - u8Nodes[index].SizeOfData += 1; - - for (int i = lastEntry + 1; i < u8Nodes.Count; i++) - if (u8Nodes[i].Type == U8_NodeType.Directory) - u8Nodes[i].SizeOfData += 1; - } - - private void removeEntry(string nodePath) - { - //Parse path - if (nodePath.StartsWith("/")) nodePath = nodePath.Remove(0, 1); - string[] path = nodePath.Split('/'); //Last entry is the filename - - int nodeIndex = -1; - int maxIndex = u8Nodes.Count - 1; - int currentIndex = 0; - List pathIndices = new List(); - - for (int i = 0; i < path.Length; i++) - { - for (int j = currentIndex; j < maxIndex; j++) - { - if (stringTable[j].ToLower() == path[i].ToLower()) - { - if (i == path.Length - 1) nodeIndex = j; - else pathIndices.Add(j); - - maxIndex = (int)u8Nodes[j].SizeOfData - 1; - currentIndex = j + 1; - - break; - } - - if (j == maxIndex - 1) throw new Exception("Path wasn't found!"); - } - } - - //Remove Node (and subnodes if node is dir) - int removed = 0; - - if (u8Nodes[nodeIndex].Type == U8_NodeType.Directory) - { - for (int i = (int)u8Nodes[nodeIndex].SizeOfData - 2; i >= nodeIndex; i--) - { - stringTable.RemoveAt(i); - u8Nodes.RemoveAt(i); - data.RemoveAt(i); - - removed++; - } - } - else - { - stringTable.RemoveAt(nodeIndex); - u8Nodes.RemoveAt(nodeIndex); - data.RemoveAt(nodeIndex); - - removed++; - } - - //Update rootnode and path sizes - rootNode.SizeOfData -= (uint)removed; - - foreach (int index in pathIndices) - if (u8Nodes[index].Type == U8_NodeType.Directory) - u8Nodes[index].SizeOfData -= (uint)removed; - - for (int i = nodeIndex + 1; i < u8Nodes.Count; i++) - if (u8Nodes[i].Type == U8_NodeType.Directory) - u8Nodes[i].SizeOfData -= (uint)removed; - } - #endregion - - #region Events - /// - /// Fires the Progress of various operations - /// - public event EventHandler Progress; - /// - /// Fires warnings (e.g. when hashes do not match) - /// - public event EventHandler Warning; - /// - /// Fires debugging messages. You may write them into a log file or log textbox. - /// - public event EventHandler Debug; - - - private void fireWarning(string warningMessage) - { - EventHandler warning = Warning; - if (warning != null) - warning(new object(), new MessageEventArgs(warningMessage)); - } - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = Debug; - if (debug != null) - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - - private void fireProgress(int progressPercentage) - { - EventHandler progress = Progress; - if (progress != null) - progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); - } - #endregion - } - - public class U8_Header - { - private uint u8Magic = 0x55AA382D; - private uint offsetToRootNode = 0x20; - private uint headerSize; - private uint offsetToData; - private byte[] padding = new byte[16]; - - public uint U8Magic { get { return u8Magic; } } - public uint OffsetToRootNode { get { return offsetToRootNode; } } - public uint HeaderSize { get { return headerSize; } set { headerSize = value; } } - public uint OffsetToData { get { return offsetToData; } set { offsetToData = value; } } - public byte[] Padding { get { return padding; } } - - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(u8Magic)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToRootNode)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(headerSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToData)), 0, 4); - writeStream.Write(padding, 0, 16); - } - } - - public class U8_Node - { - private ushort type; - private ushort offsetToName; - private uint offsetToData; - private uint sizeOfData; - - public U8_NodeType Type { get { return (U8_NodeType)type; } set { type = (ushort)value; } } - public ushort OffsetToName { get { return offsetToName; } set { offsetToName = value; } } - public uint OffsetToData { get { return offsetToData; } set { offsetToData = value; } } - public uint SizeOfData { get { return sizeOfData; } set { sizeOfData = value; } } - - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(type)), 0, 2); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToName)), 0, 2); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToData)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(sizeOfData)), 0, 4); - } - } -} diff --git a/NUS Downloader/WAD.cs b/NUS Downloader/WAD.cs deleted file mode 100644 index 93e1e71..0000000 --- a/NUS Downloader/WAD.cs +++ /dev/null @@ -1,1269 +0,0 @@ -/* This file is part of libWiiSharp - * Copyright (C) 2009 Leathl - * - * libWiiSharp 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. - * - * libWiiSharp 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 . - */ - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Security.Cryptography; - -namespace libWiiSharp -{ - public enum LowerTitleID : uint - { - SystemTitles = 0x00000001, - SystemChannels = 0x00010002, - Channel = 0x00010001, - GameChannel = 0x00010004, - DLC = 0x00010005, - HiddenChannels = 0x00010008, - } - - public class WAD : IDisposable - { - private SHA1 sha = SHA1.Create(); - private DateTime creationTimeUTC = new DateTime(1970, 1, 1); - private bool hasBanner = false; - private bool lz77CompressBannerAndIcon = true; - private bool lz77DecompressBannerAndIcon = false; - private bool keepOriginalFooter = false; - - private WAD_Header wadHeader; - private CertificateChain cert = new CertificateChain(); - private Ticket tik = new Ticket(); - private TMD tmd = new TMD(); - private List contents; - private U8 bannerApp = new U8(); - private byte[] footer = new byte[0]; - - /// - /// The region of the title. - /// - public Region Region { get { return tmd.Region; } set { tmd.Region = value; } } - /// - /// The Number of contents. - /// - public int NumOfContents { get { return tmd.NumOfContents; } } - /// - /// The content of the WAD. - /// - public byte[][] Contents { get { return contents.ToArray(); } } - /// - /// If true, the Ticket and TMD will be fakesigned. - /// - public bool FakeSign { get { return (tik.FakeSign && tmd.FakeSign); } set { tik.FakeSign = value; tmd.FakeSign = value; } } - /// - /// The banner app file (aka 00000000.app). Will be empty if HasBanner is false. - /// - public U8 BannerApp { get { return bannerApp; } set { bannerApp = value; } } - /// - /// The IOS the Title is launched with. - /// - public ulong StartupIOS { get { return tmd.StartupIOS; } set { tmd.StartupIOS = value; } } - /// - /// The Title ID. - /// - public ulong TitleID { get { return tik.TitleID; } set { tik.TitleID = value; tmd.TitleID = value; } } - /// - /// The upper Title ID as string. - /// - public string UpperTitleID { get { return tik.GetUpperTitleID(); } } - /// - /// The Title Version. - /// - public ushort TitleVersion { get { return tmd.TitleVersion; } set { tmd.TitleVersion = value; } } - /// - /// The boot index. Represents the index of the nand loader. - /// - public ushort BootIndex { get { return tmd.BootIndex; } set { tmd.BootIndex = value; } } - /// - /// The creation time of the Title. Will be 1/1/1970 if no Timestamp footer was found. - /// - public DateTime CreationTimeUTC { get { return creationTimeUTC; } } - /// - /// True if the WAD has a banner. - /// - public bool HasBanner { get { return hasBanner; } } - /// - /// If true, the banner.bin and icon.bin files will be Lz77 compressed while saving the WAD. - /// - public bool Lz77CompressBannerAndIcon { get { return lz77CompressBannerAndIcon; } set { lz77CompressBannerAndIcon = value; if (value) lz77DecompressBannerAndIcon = false; } } - /// - /// If true, the banner.bin and icon.bin files will be Lz77 decompressed while saving the WAD. - /// - public bool Lz77DecompressBannerAndIcon { get { return lz77DecompressBannerAndIcon; } set { lz77DecompressBannerAndIcon = value; if (value) lz77CompressBannerAndIcon = false; } } - /// - /// The Number of memory blocks the content will take. - /// Might be inaccurate due to Lz77 (de)compression while saving. - /// - public string NandBlocks { get { return tmd.GetNandBlocks(); } } - /// - /// All Channel Titles as a string array. Will be empty if HasBanner is false. - /// - public string[] ChannelTitles { get { if (hasBanner) return ((Headers.IMET)bannerApp.Header).AllTitles; else return new string[0]; } set { ChangeChannelTitles(value); } } - /// - /// If false, a timestamp will be added as footer (64 bytes). - /// Else, the original footer will be kept or the one you provided. - /// - public bool KeepOriginalFooter { get { return keepOriginalFooter; } set { keepOriginalFooter = value; } } - /// - /// The TMDs content entries. - /// - public TMD_Content[] TmdContents { get { return tmd.Contents; } } - - public WAD() - { - cert.Debug += new EventHandler(cert_Debug); - tik.Debug += new EventHandler(tik_Debug); - tmd.Debug += new EventHandler(tmd_Debug); - bannerApp.Debug += new EventHandler(bannerApp_Debug); - bannerApp.Warning += new EventHandler(bannerApp_Warning); - } - - #region IDisposable Members - private bool isDisposed = false; - - ~WAD() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !isDisposed) - { - sha.Clear(); - sha = null; - - wadHeader = null; - - cert.Dispose(); - tik.Dispose(); - tmd.Dispose(); - - contents.Clear(); - contents = null; - - bannerApp.Dispose(); - - footer = null; - } - - isDisposed = true; - } - #endregion - - #region Public Functions - /// - /// Loads a WAD file. - /// - /// - /// - public static WAD Load(string pathToWad) - { - return Load(File.ReadAllBytes(pathToWad)); - } - - /// - /// Loads a WAD file. - /// - /// - /// - public static WAD Load(byte[] wadFile) - { - WAD w = new WAD(); - MemoryStream ms = new MemoryStream(wadFile); - - try { w.parseWad(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - return w; - } - - /// - /// Loads a WAD file. - /// - /// - /// - public static WAD Load(Stream wad) - { - WAD w = new WAD(); - w.parseWad(wad); - return w; - } - - /// - /// Creates a WAD file from contents. - /// - /// - /// - public static WAD Create(string contentDir) - { - string[] certPath = Directory.GetFiles(contentDir, "*cert*"); - string[] tikPath = Directory.GetFiles(contentDir, "*tik*"); - string[] tmdPath = Directory.GetFiles(contentDir, "*tmd*"); - - CertificateChain _cert = CertificateChain.Load(certPath[0]); - Ticket _tik = Ticket.Load(tikPath[0]); - TMD _tmd = TMD.Load(tmdPath[0]); - - bool namedContentId = true; - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].ContentID.ToString("x8") + ".app")) - { namedContentId = false; break; } - - if (!namedContentId) - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); - - byte[][] contents = new byte[_tmd.Contents.Length][]; - - for (int i = 0; i < _tmd.Contents.Length; i++) - { - string file = contentDir + Path.DirectorySeparatorChar + ((namedContentId) ? _tmd.Contents[i].ContentID.ToString("x8") : _tmd.Contents[i].Index.ToString("x8")) + ".app"; - contents[i] = File.ReadAllBytes(file); - } - - return Create(_cert, _tik, _tmd, contents); - } - - /// - /// Creates a WAD file from contents. - /// - /// - /// - /// - /// - /// - public static WAD Create(string pathToCert, string pathToTik, string pathToTmd, string contentDir) - { - CertificateChain _cert = CertificateChain.Load(pathToCert); - Ticket _tik = Ticket.Load(pathToTik); - TMD _tmd = TMD.Load(pathToTmd); - - bool namedContentId = true; - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].ContentID.ToString("x8") + ".app")) - { namedContentId = false; break; } - - if (!namedContentId) - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); - - byte[][] contents = new byte[_tmd.Contents.Length][]; - - for (int i = 0; i < _tmd.Contents.Length; i++) - { - string file = contentDir + Path.DirectorySeparatorChar + ((namedContentId) ? _tmd.Contents[i].ContentID.ToString("x8") : _tmd.Contents[i].Index.ToString("x8")) + ".app"; - contents[i] = File.ReadAllBytes(file); - } - - return Create(_cert, _tik, _tmd, contents); - } - - /// - /// Creates a WAD file from contents. - /// - /// - /// - /// - /// - /// - public static WAD Create(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) - { - CertificateChain _cert = CertificateChain.Load(cert); - Ticket _tik = Ticket.Load(tik); - TMD _tmd = TMD.Load(tmd); - - return Create(_cert, _tik, _tmd, contents); - } - - /// - /// Creates a WAD file from contents. - /// - /// - /// - /// - /// - /// - public static WAD Create(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) - { - WAD w = new WAD(); - w.cert = cert; - w.tik = tik; - w.tmd = tmd; - w.contents = new List(contents); - - w.wadHeader = new WAD_Header(); - w.wadHeader.TmdSize = (uint)(484 + (tmd.Contents.Length * 36)); - - int contentSize = 0; - for (int i = 0; i < contents.Length - 1; i++) - contentSize += Shared.AddPadding(contents[i].Length); - - contentSize += contents[contents.Length - 1].Length; - - w.wadHeader.ContentSize = (uint)contentSize; - - for (int i = 0; i < w.tmd.Contents.Length; i++) - if (w.tmd.Contents[i].Index == 0x0000) - { - try { w.bannerApp.LoadFile(contents[i]); w.hasBanner = true; } - catch { w.hasBanner = false; } //Probably System Wad => No Banner App... - break; - } - - return w; - } - - - - /// - /// Loads a WAD file. - /// - /// - public void LoadFile(string pathToWad) - { - LoadFile(File.ReadAllBytes(pathToWad)); - } - - /// - /// Loads a WAD file. - /// - /// - public void LoadFile(byte[] wadFile) - { - MemoryStream ms = new MemoryStream(wadFile); - - try { parseWad(ms); } - catch { ms.Dispose(); throw; } - - ms.Dispose(); - } - - /// - /// Loads a WAD file. - /// - /// - public void LoadFile(Stream wad) - { - parseWad(wad); - } - - /// - /// Creates a WAD file from contents. - /// - /// - public void CreateNew(string contentDir) - { - string[] certPath = Directory.GetFiles(contentDir, "*cert*"); - string[] tikPath = Directory.GetFiles(contentDir, "*tik*"); - string[] tmdPath = Directory.GetFiles(contentDir, "*tmd*"); - - CertificateChain _cert = CertificateChain.Load(certPath[0]); - Ticket _tik = Ticket.Load(tikPath[0]); - TMD _tmd = TMD.Load(tmdPath[0]); - - bool namedContentId = true; - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].ContentID.ToString("x8") + ".app")) - { namedContentId = false; break; } - - if (!namedContentId) - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); - - byte[][] contents = new byte[_tmd.Contents.Length][]; - - for (int i = 0; i < _tmd.Contents.Length; i++) - { - string file = contentDir + Path.DirectorySeparatorChar + ((namedContentId) ? _tmd.Contents[i].ContentID.ToString("x8") : _tmd.Contents[i].Index.ToString("x8")) + ".app"; - contents[i] = File.ReadAllBytes(file); - } - - CreateNew(_cert, _tik, _tmd, contents); - } - - /// - /// Creates a WAD file from contents. - /// - /// - /// - /// - /// - public void CreateNew(string pathToCert, string pathToTik, string pathToTmd, string contentDir) - { - CertificateChain _cert = CertificateChain.Load(pathToCert); - Ticket _tik = Ticket.Load(pathToTik); - TMD _tmd = TMD.Load(pathToTmd); - - bool namedContentId = true; - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].ContentID.ToString("x8") + ".app")) - { namedContentId = false; break; } - - if (!namedContentId) - for (int i = 0; i < _tmd.Contents.Length; i++) - if (!File.Exists(contentDir + Path.DirectorySeparatorChar + _tmd.Contents[i].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); - - byte[][] contents = new byte[_tmd.Contents.Length][]; - - for (int i = 0; i < _tmd.Contents.Length; i++) - { - string file = contentDir + Path.DirectorySeparatorChar + ((namedContentId) ? _tmd.Contents[i].ContentID.ToString("x8") : _tmd.Contents[i].Index.ToString("x8")) + ".app"; - contents[i] = File.ReadAllBytes(file); - } - - CreateNew(_cert, _tik, _tmd, contents); - } - - /// - /// Creates a WAD file from contents. - /// - /// - /// - /// - /// - public void CreateNew(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) - { - CertificateChain _cert = CertificateChain.Load(cert); - Ticket _tik = Ticket.Load(tik); - TMD _tmd = TMD.Load(tmd); - - CreateNew(_cert, _tik, _tmd, contents); - } - - /// - /// Creates a WAD file from contents. - /// - /// - /// - /// - /// - public void CreateNew(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) - { - this.cert = cert; - this.tik = tik; - this.tmd = tmd; - this.contents = new List(contents); - - this.wadHeader = new WAD_Header(); - this.wadHeader.TmdSize = (uint)(484 + (tmd.Contents.Length * 36)); - - int contentSize = 0; - for (int i = 0; i < contents.Length - 1; i++) - contentSize += Shared.AddPadding(contents[i].Length); - - contentSize += contents[contents.Length - 1].Length; - - this.wadHeader.ContentSize = (uint)contentSize; - - for (int i = 0; i < this.tmd.Contents.Length; i++) - if (this.tmd.Contents[i].Index == 0x0000) - { - try { this.bannerApp.LoadFile(contents[i]); hasBanner = true; } - catch { hasBanner = false; } //Probably System Wad => No Banner App... - break; - } - } - - - /// - /// Saves the WAD file to the given location. - /// - /// - public void Save(string savePath) - { - if (File.Exists(savePath)) File.Delete(savePath); - - using (FileStream fs = new FileStream(savePath, FileMode.Create)) - writeToStream(fs); - } - - /// - /// Returns the WAD file as a memory stream. - /// - /// - public MemoryStream ToMemoryStream() - { - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - return ms; - } - - /// - /// Returns the WAD file as a byte array. - /// - /// - public byte[] ToByteArray() - { - MemoryStream ms = new MemoryStream(); - - try { writeToStream(ms); } - catch { ms.Dispose(); throw; } - - byte[] res = ms.ToArray(); - ms.Dispose(); - return res; - } - - /// - /// Changes the Title ID of the WAD file. - /// - /// - /// - public void ChangeTitleID(LowerTitleID lowerID, string upperID) - { - if (upperID.Length != 4) throw new Exception("Upper Title ID must be 4 characters long!"); - - byte[] temp = new byte[4]; - temp[0] = (byte)upperID[3]; - temp[1] = (byte)upperID[2]; - temp[2] = (byte)upperID[1]; - temp[3] = (byte)upperID[0]; - uint upper = BitConverter.ToUInt32(temp, 0); - - ulong newId = ((ulong)lowerID << 32) | upper; - - tik.TitleID = newId; - tmd.TitleID = newId; - } - - /// - /// Changes the IOS the Title is launched with. - /// - /// - public void ChangeStartupIOS(int newIos) - { - StartupIOS = ((ulong)0x00000001 << 32) | (uint)newIos; - } - - /// - /// Changes the Title Key in the Ticket. - /// The given value will be the encrypted Key (i.e. what you can "read" in the Ticket). - /// - /// - public void ChangeTitleKey(string newTitleKey) - { - tik.SetTitleKey(newTitleKey); - } - - /// - /// Changes the Title Key in the Ticket. - /// The given value will be the encrypted Key (i.e. what you can "read" in the Ticket). - /// - /// - public void ChangeTitleKey(char[] newTitleKey) - { - tik.SetTitleKey(newTitleKey); - } - - /// - /// Changes the Title Key in the Ticket. - /// The given value will be the encrypted Key (i.e. what you can "read" in the Ticket). - /// - /// - public void ChangeTitleKey(byte[] newTitleKey) - { - tik.SetTitleKey(newTitleKey); - } - - /// - /// Returns a content by it's TMD index. - /// - /// - /// - public byte[] GetContentByIndex(int index) - { - for (int i = 0; i < tmd.NumOfContents; i++) - if (tmd.Contents[i].Index == index) - return contents[i]; - - throw new Exception(string.Format("Content with index {0} not found!", index)); - } - - /// - /// Returns a content by it's content ID. - /// - /// - /// - public byte[] GetContentByID(int contentID) - { - for (int i = 0; i < tmd.NumOfContents; i++) - if (tmd.Contents[i].Index == contentID) - return contents[i]; - - throw new Exception(string.Format("Content with content ID {0} not found!", contentID)); - } - - /// - /// Changes the Channel Titles (Only if HasBanner is true). - /// 0: Japanese, - /// 1: English, - /// 2: German, - /// 3: French, - /// 4: Spanish, - /// 5: Italian, - /// 6: Dutch, - /// 7: Korean - /// - /// - public void ChangeChannelTitles(params string[] newTitles) - { - if (hasBanner) - ((Headers.IMET)bannerApp.Header).ChangeTitles(newTitles); - } - - /// - /// Adds a content to the WAD. - /// - /// - /// - /// - /// - public void AddContent(byte[] newContent, int contentID, int index, ContentType type = ContentType.Normal) - { - TMD_Content temp = new TMD_Content(); - temp.ContentID = (uint)contentID; - temp.Index = (ushort)index; - temp.Type = type; - temp.Size = (ulong)newContent.Length; - temp.Hash = sha.ComputeHash(newContent); - - tmd.AddContent(temp); - contents.Add(newContent); - - wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); - } - - /// - /// Removes a content from the WAD. - /// - /// - public void RemoveContent(int index) - { - for (int i = 0; i < tmd.Contents.Length; i++) - if (tmd.Contents[i].Index == index) - { tmd.RemoveContent(index); contents.RemoveAt(i); wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); return; } - - throw new Exception(string.Format("Content with index {0} not found!", index)); - } - - /// - /// Removes a content by it's content ID. - /// - /// - public void RemoveContentByID(int contentID) - { - for (int i = 0; i < tmd.Contents.Length; i++) - if (tmd.Contents[i].Index == contentID) - { tmd.RemoveContentByID(contentID); contents.RemoveAt(i); wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); return; } - - throw new Exception(string.Format("Content with content ID {0} not found!", contentID)); - } - - /// - /// Removes all contents from the WAD. If HasBanner is true, the banner content (Index 0) won't be removed! - /// - public void RemoveAllContents() - { - if (!hasBanner) - { - tmd.Contents = new TMD_Content[0]; - contents = new List(); - - wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); - } - else - { - for (int i=0;i(); - - tmd.AddContent(tmpTmdCont); - contents.Add(tmpCont); - - wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); - break; - } - } - } - - /// - /// Unpacks the WAD to the given directory. - /// If nameContentID is true, contents are named after their content ID, else after their index. - /// - /// - /// - public void Unpack(string unpackDir, bool nameContentID = false) - { - unpackAll(unpackDir, nameContentID); - } - - /// - /// Removes the footer. - /// - public void RemoveFooter() - { - this.footer = new byte[0]; - wadHeader.FooterSize = 0; - - this.keepOriginalFooter = true; - } - - /// - /// Adds a footer. - /// - /// - public void AddFooter(byte[] footer) - { - ChangeFooter(footer); - } - - /// - /// Changes the footer. - /// - /// - public void ChangeFooter(byte[] newFooter) - { - if (newFooter.Length % 64 != 0) - Array.Resize(ref newFooter, Shared.AddPadding(newFooter.Length)); - - this.footer = newFooter; - wadHeader.FooterSize = (uint)newFooter.Length; - - this.keepOriginalFooter = true; - } - #endregion - - #region Private Functions - private void writeToStream(Stream writeStream) - { - fireDebug("Writing Wad..."); - - //Create Footer Timestamp - if (!keepOriginalFooter) - { - fireDebug(" Building Footer Timestamp..."); - createFooterTimestamp(); - } - - //Save Banner App - if (hasBanner) - { - //Compress icon.bin and banner.bin - if (lz77CompressBannerAndIcon || lz77DecompressBannerAndIcon) - { - for (int i = 0; i < bannerApp.Nodes.Count; i++) - { - if (bannerApp.StringTable[i].ToLower() == "icon.bin" || - bannerApp.StringTable[i].ToLower() == "banner.bin") - { - if (!Lz77.IsLz77Compressed(bannerApp.Data[i]) && lz77CompressBannerAndIcon) - { - fireDebug(" Compressing {0}...", bannerApp.StringTable[i]); - - //Get the data without the IMD5 Header - byte[] fileData = new byte[bannerApp.Data[i].Length - 32]; - Array.Copy(bannerApp.Data[i], 32, fileData, 0, fileData.Length); - - //Compress the data - Lz77 l = new Lz77(); - fileData = l.Compress(fileData); - - //Add a new IMD5 Header - fileData = Headers.IMD5.AddHeader(fileData); - bannerApp.Data[i] = fileData; - - //Update the node - bannerApp.Nodes[i].SizeOfData = (uint)fileData.Length; - } - else if (Lz77.IsLz77Compressed(bannerApp.Data[i]) && lz77DecompressBannerAndIcon) - { - fireDebug(" Decompressing {0}...", bannerApp.StringTable[i]); - - //Get the data without the IMD5 Header - byte[] fileData = new byte[bannerApp.Data[i].Length - 32]; - Array.Copy(bannerApp.Data[i], 32, fileData, 0, fileData.Length); - - //Decompress the data - Lz77 l = new Lz77(); - fileData = l.Decompress(fileData); - - //Add a new IMD5 Header - fileData = Headers.IMD5.AddHeader(fileData); - bannerApp.Data[i] = fileData; - - //Update the node - bannerApp.Nodes[i].SizeOfData = (uint)fileData.Length; - } - } - } - } - - for (int i = 0; i < contents.Count; i++) - if (tmd.Contents[i].Index == 0x0000) - { fireDebug(" Saving Banner App..."); contents[i] = bannerApp.ToByteArray(); break; } - } - - //Update Header (Content Size) - fireDebug(" Updating Header..."); - int contentSize = 0; - for (int i = 0; i < contents.Count - 1; i++) - contentSize += Shared.AddPadding(contents[i].Length); - - contentSize += contents[contents.Count - 1].Length; - - wadHeader.ContentSize = (uint)contentSize; - wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); - - //Update Contents - fireDebug(" Updating TMD Contents..."); - tmd.UpdateContents(contents.ToArray()); - - //Write Header - fireDebug(" Writing Wad Header... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek(0, SeekOrigin.Begin); - wadHeader.Write(writeStream); - - //Write Cert - fireDebug(" Writing Certificate Chain... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); - byte[] temp = cert.ToByteArray(); - writeStream.Write(temp, 0, temp.Length); - - //Write Tik - fireDebug(" Writing Ticket... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); - temp = tik.ToByteArray(); - writeStream.Write(temp, 0, temp.Length); - - //Write TMD - fireDebug(" Writing TMD... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); - temp = tmd.ToByteArray(); - writeStream.Write(temp, 0, temp.Length); - - //Write Contents - List contentList = new List(); - for (int i = 0; i < tmd.Contents.Length; i++) - contentList.Add(new ContentIndices(i, tmd.Contents[i].Index)); - - contentList.Sort(); - - for (int i = 0; i < contentList.Count; i++) - { - writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); - - fireProgress((i + 1) * 100 / contents.Count); - - fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper(), i + 1, contents.Count); - fireDebug(" -> Content ID: 0x{0}", tmd.Contents[contentList[i].Index].ContentID.ToString("x8")); - fireDebug(" -> Index: 0x{0}", tmd.Contents[contentList[i].Index].Index.ToString("x4")); - fireDebug(" -> Type: 0x{0} ({1})", ((ushort)tmd.Contents[contentList[i].Index].Type).ToString("x4"), tmd.Contents[contentList[i].Index].Type.ToString()); - fireDebug(" -> Size: {0} bytes", tmd.Contents[contentList[i].Index].Size); - fireDebug(" -> Hash: {0}", Shared.ByteArrayToString(tmd.Contents[contentList[i].Index].Hash)); - - temp = encryptContent(contents[contentList[i].Index], contentList[i].Index); - writeStream.Write(temp, 0, temp.Length); - } - - //Write Footer - if (wadHeader.FooterSize > 0) - { - fireDebug(" Writing Footer... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); - writeStream.Write(footer, 0, footer.Length); - } - - //Padding - while (writeStream.Position % 64 != 0) - writeStream.WriteByte(0x00); - - fireDebug("Writing Wad Finished... (Written Bytes: {0})", writeStream.Position); - } - - private void unpackAll(string unpackDir, bool nameContentId) - { - fireDebug("Unpacking Wad to: {0}", unpackDir); - - if (!Directory.Exists(unpackDir)) Directory.CreateDirectory(unpackDir); - string titleID = tik.TitleID.ToString("x16"); - - //Save Cert - fireDebug(" Saving Certificate Chain: {0}.cert", titleID); - cert.Save(unpackDir + Path.DirectorySeparatorChar + titleID + ".cert"); - - //Save Tik - fireDebug(" Saving Ticket: {0}.tik", titleID); - tik.Save(unpackDir + Path.DirectorySeparatorChar + titleID + ".tik"); - - //Save TMD - fireDebug(" Saving TMD: {0}.tmd", titleID); - tmd.Save(unpackDir + Path.DirectorySeparatorChar + titleID + ".tmd"); - - //Save Contents - for (int i = 0; i < tmd.NumOfContents; i++) - { - fireProgress((i + 1) * 100 / tmd.NumOfContents); - - fireDebug(" Saving Content #{0} of {1}: {2}.app", i + 1, tmd.NumOfContents, (nameContentId ? tmd.Contents[i].ContentID.ToString("x8") : tmd.Contents[i].Index.ToString("x8"))); - fireDebug(" -> Content ID: 0x{0}", tmd.Contents[i].ContentID.ToString("x8")); - fireDebug(" -> Index: 0x{0}", tmd.Contents[i].Index.ToString("x4")); - fireDebug(" -> Type: 0x{0} ({1})", ((ushort)tmd.Contents[i].Type).ToString("x4"), tmd.Contents[i].Type.ToString()); - fireDebug(" -> Size: {0} bytes", tmd.Contents[i].Size); - fireDebug(" -> Hash: {0}", Shared.ByteArrayToString(tmd.Contents[i].Hash)); - - using (FileStream fs = new FileStream(unpackDir + Path.DirectorySeparatorChar + - (nameContentId ? tmd.Contents[i].ContentID.ToString("x8") : tmd.Contents[i].Index.ToString("x8")) + ".app", - FileMode.Create)) - fs.Write(contents[i], 0, contents[i].Length); - } - - //Save Footer - fireDebug(" Saving Footer: {0}.footer", titleID); - using (FileStream fs = new FileStream(unpackDir + Path.DirectorySeparatorChar + titleID + ".footer", FileMode.Create)) - fs.Write(footer, 0, footer.Length); - - fireDebug("Unpacking Wad Finished..."); - } - - private void parseWad(Stream wadFile) - { - fireDebug("Parsing Wad..."); - - wadFile.Seek(0, SeekOrigin.Begin); - byte[] temp = new byte[4]; - - wadHeader = new WAD_Header(); - contents = new List(); - - //Read Header - fireDebug(" Parsing Header... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); - wadFile.Read(temp, 0, 4); - if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != wadHeader.HeaderSize) - throw new Exception("Invalid Headersize!"); - - wadFile.Read(temp, 0, 4); - wadHeader.WadType = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - wadFile.Seek(12, SeekOrigin.Current); - - wadFile.Read(temp, 0, 4); - wadHeader.TmdSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - wadFile.Read(temp, 0, 4); - wadHeader.ContentSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - wadFile.Read(temp, 0, 4); - wadHeader.FooterSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); - - //Read Cert - fireDebug(" Parsing Certificate Chain... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); - wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); - - temp = new byte[wadHeader.CertSize]; - wadFile.Read(temp, 0, temp.Length); - cert.LoadFile(temp); - - //Read Tik - fireDebug(" Parsing Ticket... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); - wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); - - temp = new byte[wadHeader.TicketSize]; - wadFile.Read(temp, 0, temp.Length); - tik.LoadFile(temp); - - //Read Tmd - fireDebug(" Parsing TMD... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); - wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); - - temp = new byte[wadHeader.TmdSize]; - wadFile.Read(temp, 0, temp.Length); - tmd.LoadFile(temp); - - if (tmd.TitleID != tik.TitleID) - fireWarning("The Title ID in the Ticket doesn't match the one in the TMD!"); - - //Read Content - for (int i = 0; i < tmd.NumOfContents; i++) - { - fireProgress((i + 1) * 100 / tmd.NumOfContents); - - fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", i + 1, tmd.NumOfContents, wadFile.Position.ToString("x8").ToUpper()); - fireDebug(" -> Content ID: 0x{0}", tmd.Contents[i].ContentID.ToString("x8")); - fireDebug(" -> Index: 0x{0}", tmd.Contents[i].Index.ToString("x4")); - fireDebug(" -> Type: 0x{0} ({1})", ((ushort)tmd.Contents[i].Type).ToString("x4"), tmd.Contents[i].Type.ToString()); - fireDebug(" -> Size: {0} bytes", tmd.Contents[i].Size); - fireDebug(" -> Hash: {0}", Shared.ByteArrayToString(tmd.Contents[i].Hash)); - - wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); - - temp = new byte[Shared.AddPadding((int)tmd.Contents[i].Size, 16)]; - wadFile.Read(temp, 0, temp.Length); - - //Decrypt Content - temp = decryptContent(temp, i); - Array.Resize(ref temp, (int)tmd.Contents[i].Size); - - byte[] tmdHash = tmd.Contents[i].Hash; - byte[] newHash = sha.ComputeHash(temp, 0, (int)tmd.Contents[i].Size); - - if (!Shared.CompareByteArrays(tmdHash, newHash)) - { - fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); - fireWarning(string.Format("Content #{0} (Content ID: 0x{1}; Index: 0x{2}): Hashes do not match! The content might be corrupted!", i + 1, tmd.Contents[i].ContentID.ToString("x8"), tmd.Contents[i].Index.ToString("x4"))); - } - - contents.Add(temp); - - if (tmd.Contents[i].Index == 0x0000) - { - try { bannerApp.LoadFile(temp); hasBanner = true; } - catch { hasBanner = false; } //Probably System Wad => No Banner App... - } - } - - //Read Footer - if (wadHeader.FooterSize > 0) - { - fireDebug(" Reading Footer... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); - footer = new byte[wadHeader.FooterSize]; - - wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); - wadFile.Read(footer, 0, footer.Length); - - parseFooterTimestamp(); - } - - fireDebug("Parsing Wad Finished..."); - } - - private byte[] decryptContent(byte[] content, int contentIndex) - { - int originalLength = content.Length; - Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); - byte[] titleKey = tik.TitleKey; - byte[] iv = new byte[16]; - - byte[] tmp = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); - iv[0] = tmp[1]; - iv[1] = tmp[0]; - - RijndaelManaged rm = new RijndaelManaged(); - rm.Mode = CipherMode.CBC; - rm.Padding = PaddingMode.None; - rm.KeySize = 128; - rm.BlockSize = 128; - rm.Key = titleKey; - rm.IV = iv; - - ICryptoTransform decryptor = rm.CreateDecryptor(); - - MemoryStream ms = new MemoryStream(content); - CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); - - byte[] decCont = new byte[originalLength]; - cs.Read(decCont, 0, decCont.Length); - - cs.Dispose(); - ms.Dispose(); - - return decCont; - } - - private byte[] encryptContent(byte[] content, int contentIndex) - { - Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); - byte[] titleKey = tik.TitleKey; - byte[] iv = new byte[16]; - - byte[] tmp = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); - iv[0] = tmp[1]; - iv[1] = tmp[0]; - - RijndaelManaged encrypt = new RijndaelManaged(); - encrypt.Mode = CipherMode.CBC; - encrypt.Padding = PaddingMode.None; - encrypt.KeySize = 128; - encrypt.BlockSize = 128; - encrypt.Key = titleKey; - encrypt.IV = iv; - - ICryptoTransform encryptor = encrypt.CreateEncryptor(); - - MemoryStream ms = new MemoryStream(content); - CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Read); - - byte[] encCont = new byte[content.Length]; - cs.Read(encCont, 0, encCont.Length); - - cs.Dispose(); - ms.Dispose(); - - return encCont; - } - - private void createFooterTimestamp() - { - DateTime dtNow = DateTime.UtcNow; - TimeSpan tsTimestamp = (dtNow - new DateTime(1970, 1, 1, 0, 0, 0)); - - int timeStamp = (int)tsTimestamp.TotalSeconds; - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - - byte[] timeStampBytes = enc.GetBytes("TmStmp" + timeStamp.ToString()); - Array.Resize(ref timeStampBytes, 64); - - wadHeader.FooterSize = (uint)timeStampBytes.Length; - footer = timeStampBytes; - } - - private void parseFooterTimestamp() - { - creationTimeUTC = new DateTime(1970, 1, 1); - - if ((footer[0] == 'C' && footer[1] == 'M' && footer[2] == 'i' && - footer[3] == 'i' && footer[4] == 'U' && footer[5] == 'T') || - (footer[0] == 'T' && footer[1] == 'm' && footer[2] == 'S' && - footer[3] == 't' && footer[4] == 'm' && footer[5] == 'p')) - { - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - string stringSeconds = enc.GetString(footer, 6, 10); - int seconds = 0; - - if (int.TryParse(stringSeconds, out seconds)) - creationTimeUTC = creationTimeUTC.AddSeconds((double)seconds); - } - } - #endregion - - #region Events - /// - /// Fires the Progress of various operations - /// - public event EventHandler Progress; - /// - /// Fires warnings (e.g. when hashes don't match) - /// - public event EventHandler Warning; - /// - /// Fires debugging messages. You may write them into a log file or log textbox. - /// - public event EventHandler Debug; - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = Debug; - if (debug != null) - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - - private void fireWarning(string warningMessage) - { - EventHandler warning = Warning; - if (warning != null) - warning(new object(), new MessageEventArgs(warningMessage)); - } - - private void fireProgress(int progressPercentage) - { - EventHandler progress = Progress; - if (progress != null) - progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); - } - - private void cert_Debug(object sender, MessageEventArgs e) - { - fireDebug(" Certificate Chain: {0}", e.Message); - } - - private void tik_Debug(object sender, MessageEventArgs e) - { - fireDebug(" Ticket: {0}", e.Message); - } - - private void tmd_Debug(object sender, MessageEventArgs e) - { - fireDebug(" TMD: {0}", e.Message); - } - - void bannerApp_Debug(object sender, MessageEventArgs e) - { - fireDebug(" BannerApp: {0}", e.Message); - } - - void bannerApp_Warning(object sender, MessageEventArgs e) - { - fireWarning(e.Message); - } - #endregion - } - - public class WAD_Header - { - private uint headerSize = 0x20; - private uint wadType = 0x49730000; - private uint certSize = 0xA00; - private uint reserved = 0x00; - private uint tikSize = 0x2A4; - private uint tmdSize; - private uint contentSize; - private uint footerSize = 0x00; - - public uint HeaderSize { get { return headerSize; } } - public uint WadType { get { return wadType; } set { wadType = value; } } - public uint CertSize { get { return certSize; } } - public uint Reserved { get { return reserved; } } - public uint TicketSize { get { return tikSize; } } - public uint TmdSize { get { return tmdSize; } set { tmdSize = value; } } - public uint ContentSize { get { return contentSize; } set { contentSize = value; } } - public uint FooterSize { get { return footerSize; } set { footerSize = value; } } - - public void Write(Stream writeStream) - { - writeStream.Seek(0, SeekOrigin.Begin); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(headerSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(wadType)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(certSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(reserved)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(tikSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(tmdSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(contentSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(footerSize)), 0, 4); - } - } -} diff --git a/NUS Downloader/WaterMarkTextBox.cs b/NUS Downloader/WaterMarkTextBox.cs deleted file mode 100644 index fffa865..0000000 --- a/NUS Downloader/WaterMarkTextBox.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows.Forms; -using System.Drawing; - -namespace wmgCMS -{ - class WaterMarkTextBox : TextBox - { - private Font oldFont = null; - private Boolean waterMarkTextEnabled = false; - - #region Attributes - private Color _waterMarkColor = Color.Gray; - public Color WaterMarkColor - { - get { return _waterMarkColor; } - set { _waterMarkColor = value; Invalidate();/*thanks to Bernhard Elbl for Invalidate()*/ } - } - - private string _waterMarkText = "Water Mark"; - public string WaterMarkText - { - get { return _waterMarkText; } - set { _waterMarkText = value; Invalidate(); } - } - #endregion - - //Default constructor - public WaterMarkTextBox() - { - JoinEvents(true); - } - - //Override OnCreateControl ... thanks to "lpgray .. codeproject guy" - protected override void OnCreateControl() - { - base.OnCreateControl(); - //WaterMark_Toggel(null, null); - EnableWaterMark(); - } - - //Override OnPaint - protected override void OnPaint(PaintEventArgs args) - { - // Use the same font that was defined in base class - System.Drawing.Font drawFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit); - //Create new brush with gray color or - SolidBrush drawBrush = new SolidBrush(WaterMarkColor);//use Water mark color - //Draw Text or WaterMark - float xpoint = ((float)args.ClipRectangle.Width / 2.0F) - ((float)TextRenderer.MeasureText(WaterMarkText, Font).Width / 2.0F); - ; - PointF centeredtext = new PointF(xpoint, 0.0F); - args.Graphics.DrawString((waterMarkTextEnabled ? WaterMarkText : Text), drawFont, drawBrush, centeredtext); - base.OnPaint(args); - } - - private void JoinEvents(Boolean join) - { - if (join) - { - this.TextChanged += new System.EventHandler(this.WaterMark_Toggel); - this.LostFocus += new System.EventHandler(this.WaterMark_Toggel); - this.GotFocus += new System.EventHandler(this.WaterMark_Toggel); - this.MouseCaptureChanged += new System.EventHandler(this.WaterMark_Toggel); - this.FontChanged += new System.EventHandler(this.WaterMark_FontChanged); - //No one of the above events will start immeddiatlly - //TextBox control still in constructing, so, - //Font object (for example) couldn't be catched from within WaterMark_Toggle - //So, call WaterMark_Toggel through OnCreateControl after TextBox is totally created - //No doupt, it will be only one time call - - //Old solution uses Timer.Tick event to check Create property - } - } - - private void WaterMark_Toggel(object sender, EventArgs args) - { - /*if (this.Text.Length <= 0) - EnableWaterMark(); - else - DisbaleWaterMark(); */ - - /*if (this.Text.Length > 0) - { - System.Diagnostics.Debug.WriteLine(sender.ToString() + " disabled watermark"); - DisbaleWaterMark(); - }*/ - DisbaleWaterMark(); - } - - private void EnableWaterMark() - { - //Save current font until returning the UserPaint style to false (NOTE: It is a try and error advice) - oldFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit); - //Enable OnPaint event handler - this.SetStyle(ControlStyles.UserPaint, true); - this.waterMarkTextEnabled = true; - //Triger OnPaint immediatly - Refresh(); - } - - private void DisbaleWaterMark() - { - //Disbale OnPaint event handler - this.waterMarkTextEnabled = false; - this.SetStyle(ControlStyles.UserPaint, false); - //Return back oldFont if existed - if (oldFont != null) - this.Font = new System.Drawing.Font(oldFont.FontFamily, oldFont.Size, oldFont.Style, oldFont.Unit); - } - - private void WaterMark_FontChanged(object sender, EventArgs args) - { - if (waterMarkTextEnabled) - { - oldFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit); - Refresh(); - } - } - } -} diff --git a/NUS Downloader/Windows7ProgressBar.cs b/NUS Downloader/Windows7ProgressBar.cs deleted file mode 100644 index 1153831..0000000 --- a/NUS Downloader/Windows7ProgressBar.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System.ComponentModel; -using System.ComponentModel.Design; -using System.Drawing; -using System.Windows.Forms; - -//Windows7ProgressBar v1.0, created by Wyatt O'Day -//Visit: http://wyday.com/windows-7-progress-bar/ - -namespace wyDay.Controls -{ - /// - /// A Windows progress bar control with Windows Vista & 7 functionality. - /// - [ToolboxBitmap(typeof(ProgressBar))] - public class Windows7ProgressBar : ProgressBar - { - bool showInTaskbar; - private ProgressBarState m_State = ProgressBarState.Normal; - ContainerControl ownerForm; - - public Windows7ProgressBar () {} - - public Windows7ProgressBar(ContainerControl parentControl) - { - ContainerControl = parentControl; - } - public ContainerControl ContainerControl - { - get { return ownerForm; } - set - { - ownerForm = value; - - if(!ownerForm.Visible) - ((Form)ownerForm).Shown += Windows7ProgressBar_Shown; - } - } - public override ISite Site - { - set - { - // Runs at design time, ensures designer initializes ContainerControl - base.Site = value; - if (value == null) return; - IDesignerHost service = value.GetService(typeof(IDesignerHost)) as IDesignerHost; - if (service == null) return; - IComponent rootComponent = service.RootComponent; - - ContainerControl = rootComponent as ContainerControl; - } - } - - void Windows7ProgressBar_Shown(object sender, System.EventArgs e) - { - if (ShowInTaskbar) - { - if (Style != ProgressBarStyle.Marquee) - SetValueInTB(); - - SetStateInTB(); - } - - ((Form)ownerForm).Shown -= Windows7ProgressBar_Shown; - } - - - - /// - /// Show progress in taskbar - /// - [DefaultValue(false)] - public bool ShowInTaskbar - { - get - { - return showInTaskbar; - } - set - { - if (showInTaskbar != value) - { - showInTaskbar = value; - - // send signal to the taskbar. - if (ownerForm != null) - { - if (Style != ProgressBarStyle.Marquee) - SetValueInTB(); - - SetStateInTB(); - } - } - } - } - - - /// - /// Gets or sets the current position of the progress bar. - /// - /// The position within the range of the progress bar. The default is 0. - public new int Value - { - get - { - return base.Value; - } - set - { - base.Value = value; - - // send signal to the taskbar. - SetValueInTB(); - } - } - - /// - /// Gets or sets the manner in which progress should be indicated on the progress bar. - /// - /// One of the ProgressBarStyle values. The default is ProgressBarStyle.Blocks - public new ProgressBarStyle Style - { - get - { - return base.Style; - } - set - { - base.Style = value; - - // set the style of the progress bar - if (showInTaskbar && ownerForm != null) - { - SetStateInTB(); - } - } - } - - - /// - /// The progress bar state for Windows Vista & 7 - /// - [DefaultValue(ProgressBarState.Normal)] - public ProgressBarState State - { - get { return m_State; } - set - { - m_State = value; - - bool wasMarquee = Style == ProgressBarStyle.Marquee; - - if(wasMarquee) - // sets the state to normal (and implicity calls SetStateInTB() ) - Style = ProgressBarStyle.Blocks; - - // set the progress bar state (Normal, Error, Paused) - Windows7Taskbar.SendMessage(Handle, 0x410, (int)value, 0); - - - if (wasMarquee) - // the Taskbar PB value needs to be reset - SetValueInTB(); - else - // there wasn't a marquee, thus we need to update the taskbar - SetStateInTB(); - } - } - - /// - /// Advances the current position of the progress bar by the specified amount. - /// - /// The amount by which to increment the progress bar's current position. - public new void Increment(int value) - { - base.Increment(value); - - // send signal to the taskbar. - SetValueInTB(); - } - - /// - /// Advances the current position of the progress bar by the amount of the System.Windows.Forms.ProgressBar.Step property. - /// - public new void PerformStep() - { - base.PerformStep(); - - // send signal to the taskbar. - SetValueInTB(); - } - - private void SetValueInTB() - { - if (showInTaskbar) - { - ulong maximum = (ulong) (Maximum - Minimum); - ulong progress = (ulong) (Value - Minimum); - - Windows7Taskbar.SetProgressValue(ownerForm.Handle, progress, maximum); - } - } - - private void SetStateInTB() - { - if (ownerForm == null) return; - - ThumbnailProgressState thmState = ThumbnailProgressState.Normal; - - if (!showInTaskbar) - thmState = ThumbnailProgressState.NoProgress; - else if (Style == ProgressBarStyle.Marquee) - thmState = ThumbnailProgressState.Indeterminate; - else if (m_State == ProgressBarState.Error) - thmState = ThumbnailProgressState.Error; - else if (m_State == ProgressBarState.Pause) - thmState = ThumbnailProgressState.Paused; - - Windows7Taskbar.SetProgressState(ownerForm.Handle, thmState); - } - } - - /// - /// The progress bar state for Windows Vista & 7 - /// - public enum ProgressBarState - { - /// - /// Indicates normal progress - /// - Normal = 1, - - /// - /// Indicates an error in the progress - /// - Error = 2, - - /// - /// Indicates paused progress - /// - Pause = 3 - } -} \ No newline at end of file diff --git a/NUS Downloader/Windows7Taskbar.cs b/NUS Downloader/Windows7Taskbar.cs deleted file mode 100644 index 4f98787..0000000 --- a/NUS Downloader/Windows7Taskbar.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using System; -using System.Runtime.InteropServices; - -namespace wyDay.Controls -{ - /// - /// The primary coordinator of the Windows 7 taskbar-related activities. - /// - public static class Windows7Taskbar - { - private static ITaskbarList3 _taskbarList; - internal static ITaskbarList3 TaskbarList - { - get - { - if (_taskbarList == null) - { - lock (typeof(Windows7Taskbar)) - { - if (_taskbarList == null) - { - _taskbarList = (ITaskbarList3)new CTaskbarList(); - _taskbarList.HrInit(); - } - } - } - return _taskbarList; - } - } - - static readonly OperatingSystem osInfo = Environment.OSVersion; - - internal static bool Windows7OrGreater - { - get - { - return (osInfo.Version.Major == 6 && osInfo.Version.Minor >= 1) - || (osInfo.Version.Major > 6); - } - } - - /// - /// Sets the progress state of the specified window's - /// taskbar button. - /// - /// The window handle. - /// The progress state. - public static void SetProgressState(IntPtr hwnd, ThumbnailProgressState state) - { - if(Windows7OrGreater) - TaskbarList.SetProgressState(hwnd, state); - } - /// - /// Sets the progress value of the specified window's - /// taskbar button. - /// - /// The window handle. - /// The current value. - /// The maximum value. - public static void SetProgressValue(IntPtr hwnd, ulong current, ulong maximum) - { - if(Windows7OrGreater) - TaskbarList.SetProgressValue(hwnd, current, maximum); - } - - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - internal static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam); - } -} \ No newline at end of file diff --git a/NUS Downloader/app.config b/NUS Downloader/app.config deleted file mode 100644 index 8494f72..0000000 --- a/NUS Downloader/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/NUS_Downloader/Database.cs b/NUS_Downloader/Database.cs new file mode 100644 index 0000000..6f5a02c --- /dev/null +++ b/NUS_Downloader/Database.cs @@ -0,0 +1,600 @@ +// Decompiled with JetBrains decompiler +// Type: NUS_Downloader.Database +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using NUS_Downloader.Properties; +using System; +using System.Drawing; +using System.IO; +using System.Windows.Forms; +using System.Xml; + +namespace NUS_Downloader +{ + internal class Database + { + private string SystemTag = "SYS"; + private string IosTag = "IOS"; + private string VcTag = "VC"; + private string WwTag = "WW"; + private string UpdateTag = "UPD"; + private string DSiSystemTag = "DSISYSTEM"; + private string DSiWareTag = "DSIWARE"; + private string[] VcConsoles = new string[11] + { + "C64", + "GEN", + "MSX", + "N64", + "NEO", + "NES", + "SMS", + "SNES", + "TG16", + "TGCD", + "ARC" + }; + private string databaseString; + public static Image green = (Image) Resources.bullet_green; + public static Image orange = (Image) Resources.bullet_orange; + public static Image redgreen = (Image) Resources.bullet_redgreen; + public static Image redorange = (Image) Resources.bullet_redorange; + public static Image green_blue = (Image) Resources.bullet_green_blue; + public static Image orange_blue = (Image) Resources.bullet_orange_blue; + public static Image redgreen_blue = (Image) Resources.bullet_redgreen_blue; + public static Image redorange_blue = (Image) Resources.bullet_redorange_blue; + + public void LoadDatabaseToStream(string databaseFile) => this.databaseString = File.Exists(databaseFile) ? File.ReadAllText(databaseFile) : throw new FileNotFoundException("I couldn't find the database file!", "database.xml"); + + public string GetDatabaseVersion() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + return xmlDocument.GetElementsByTagName("database")[0].Attributes[0].Value; + } + + public static string GetDatabaseVersion(string databaseString) + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(databaseString); + return xmlDocument.GetElementsByTagName("database")[0].Attributes[0].Value; + } + + public ToolStripMenuItem[] LoadSystemTitles() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.SystemTag); + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count]; + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + XmlAttributeCollection attributes = elementsByTagName[i1].Attributes; + string str1 = ""; + string str2 = ""; + bool danger = false; + bool ticket = true; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "name": + str2 = childNodes[i2].InnerText; + break; + case "titleID": + str1 = childNodes[i2].InnerText; + break; + case "version": + string[] strArray1 = childNodes[i2].InnerText.Split(','); + if (toolStripMenuItem.DropDownItems.Count > 0) + { + for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1) + { + if (childNodes[i2].InnerText != "") + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1]; + dropDownItem.DropDownItems.Add("Latest Version"); + for (int index2 = 0; index2 < strArray1.Length; ++index2) + dropDownItem.DropDownItems.Add("v" + strArray1[index2]); + } + } + break; + } + toolStripMenuItem.DropDownItems.Add("Latest Version"); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray1.Length; ++index) + toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]); + break; + } + break; + case "region": + string[] strArray2 = childNodes[i2].InnerText.Split(','); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray2.Length; ++index) + toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index]))); + break; + } + break; + case "ticket": + ticket = Convert.ToBoolean(childNodes[i2].InnerText); + break; + case "danger": + danger = true; + toolStripMenuItem.ToolTipText = childNodes[i2].InnerText; + break; + } + toolStripMenuItem.Image = this.SelectItemImage(ticket, danger); + if (str1 != "") + toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2); + else + toolStripMenuItem.Text = str2; + } + toolStripMenuItemArray[i1] = toolStripMenuItem; + } + return toolStripMenuItemArray; + } + + public ToolStripMenuItem[] LoadIosTitles() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.IosTag); + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count]; + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + XmlAttributeCollection attributes = elementsByTagName[i1].Attributes; + string str1 = ""; + string str2 = ""; + bool danger = false; + bool ticket = true; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "name": + str2 = childNodes[i2].InnerText; + break; + case "titleID": + str1 = childNodes[i2].InnerText; + break; + case "version": + string[] strArray = childNodes[i2].InnerText.Split(','); + toolStripMenuItem.DropDownItems.Add("Latest Version"); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray.Length; ++index) + toolStripMenuItem.DropDownItems.Add("v" + strArray[index]); + break; + } + break; + case "ticket": + ticket = Convert.ToBoolean(childNodes[i2].InnerText); + break; + case "danger": + danger = true; + toolStripMenuItem.ToolTipText = childNodes[i2].InnerText; + break; + } + toolStripMenuItem.Image = this.SelectItemImage(ticket, danger); + if (str1 != "") + toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2); + else + toolStripMenuItem.Text = str2; + } + toolStripMenuItemArray[i1] = toolStripMenuItem; + } + return toolStripMenuItemArray; + } + + public ToolStripMenuItem[][] LoadVirtualConsoleTitles() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.VcTag); + ToolStripMenuItem[][] toolStripMenuItemArray = new ToolStripMenuItem[this.VcConsoles.Length][]; + for (int index = 0; index < toolStripMenuItemArray.Length; ++index) + toolStripMenuItemArray[index] = new ToolStripMenuItem[0]; + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + XmlAttributeCollection attributes = elementsByTagName[i1].Attributes; + string str1 = ""; + string str2 = ""; + bool danger = false; + bool ticket = true; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "name": + str2 = childNodes[i2].InnerText; + break; + case "titleID": + str1 = childNodes[i2].InnerText; + break; + case "version": + string[] strArray1 = childNodes[i2].InnerText.Split(','); + if (toolStripMenuItem.DropDownItems.Count > 0) + { + for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1) + { + if (childNodes[i2].InnerText != "") + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1]; + dropDownItem.DropDownItems.Add("Latest Version"); + for (int index2 = 0; index2 < strArray1.Length; ++index2) + dropDownItem.DropDownItems.Add("v" + strArray1[index2]); + } + } + break; + } + toolStripMenuItem.DropDownItems.Add("Latest Version"); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray1.Length; ++index) + toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]); + break; + } + break; + case "region": + string[] strArray2 = childNodes[i2].InnerText.Split(','); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray2.Length; ++index) + toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index]))); + break; + } + break; + case "ticket": + ticket = Convert.ToBoolean(childNodes[i2].InnerText); + break; + case "danger": + danger = true; + toolStripMenuItem.ToolTipText = childNodes[i2].InnerText; + break; + } + toolStripMenuItem.Image = this.SelectItemImage(ticket, danger); + if (str1 != "") + toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2); + else + toolStripMenuItem.Text = str2; + } + for (int index = 0; index < this.VcConsoles.Length; ++index) + { + if (attributes[0].Value == this.VcConsoles[index]) + { + Array.Resize(ref toolStripMenuItemArray[index], toolStripMenuItemArray[index].Length + 1); + toolStripMenuItemArray[index][toolStripMenuItemArray[index].Length - 1] = toolStripMenuItem; + } + } + } + return toolStripMenuItemArray; + } + + public ToolStripMenuItem[] LoadWiiWareTitles() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.WwTag); + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count]; + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + XmlAttributeCollection attributes = elementsByTagName[i1].Attributes; + string str1 = ""; + string str2 = ""; + bool danger = false; + bool ticket = true; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "name": + str2 = childNodes[i2].InnerText; + break; + case "titleID": + str1 = childNodes[i2].InnerText; + break; + case "version": + string[] strArray1 = childNodes[i2].InnerText.Split(','); + if (toolStripMenuItem.DropDownItems.Count > 0) + { + for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1) + { + if (childNodes[i2].InnerText != "") + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1]; + dropDownItem.DropDownItems.Add("Latest Version"); + for (int index2 = 0; index2 < strArray1.Length; ++index2) + dropDownItem.DropDownItems.Add("v" + strArray1[index2]); + } + } + break; + } + toolStripMenuItem.DropDownItems.Add("Latest Version"); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray1.Length; ++index) + toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]); + break; + } + break; + case "region": + string[] strArray2 = childNodes[i2].InnerText.Split(','); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray2.Length; ++index) + toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index]))); + break; + } + break; + case "ticket": + ticket = Convert.ToBoolean(childNodes[i2].InnerText); + break; + case "danger": + danger = true; + toolStripMenuItem.ToolTipText = childNodes[i2].InnerText; + break; + } + toolStripMenuItem.Image = this.SelectItemImage(ticket, danger); + if (str1 != "") + toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2); + else + toolStripMenuItem.Text = str2; + } + toolStripMenuItemArray[i1] = toolStripMenuItem; + } + return toolStripMenuItemArray; + } + + private string RegionFromIndex(int index) + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList childNodes = xmlDocument.GetElementsByTagName("REGIONS")[0].ChildNodes; + for (int i = 0; i < childNodes.Count; ++i) + { + if (Convert.ToInt32(childNodes[i].Attributes[0].Value) == index) + return childNodes[i].InnerText; + } + return "XX (Error)"; + } + + private Image SelectItemImage(bool ticket, bool danger) + { + if (ticket && !danger) + return Database.green; + if (!ticket && !danger) + return Database.orange; + if (ticket && danger) + return Database.redgreen; + return !ticket && danger ? Database.redorange : (Image) null; + } + + public ToolStripMenuItem[] LoadRegionCodes() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList childNodes = xmlDocument.GetElementsByTagName("REGIONS")[0].ChildNodes; + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[childNodes.Count]; + for (int i = 0; i < childNodes.Count; ++i) + { + toolStripMenuItemArray[i] = new ToolStripMenuItem(); + toolStripMenuItemArray[i].Text = childNodes[i].InnerText; + } + return toolStripMenuItemArray; + } + + public ToolStripMenuItem[] LoadScripts() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.UpdateTag); + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count]; + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + XmlAttributeCollection attributes = elementsByTagName[i1].Attributes; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "name": + toolStripMenuItem.Text = childNodes[i2].InnerText; + break; + case "script": + toolStripMenuItem.ToolTipText = childNodes[i2].InnerText; + break; + } + toolStripMenuItem.Image = (Image) Resources.script_start; + } + toolStripMenuItemArray[i1] = toolStripMenuItem; + } + return toolStripMenuItemArray; + } + + public ToolStripMenuItem[] LoadDSiSystemTitles() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.DSiSystemTag); + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count]; + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + XmlAttributeCollection attributes = elementsByTagName[i1].Attributes; + string str1 = ""; + string str2 = ""; + bool danger = false; + bool ticket = true; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "name": + str2 = childNodes[i2].InnerText; + break; + case "titleID": + str1 = childNodes[i2].InnerText; + break; + case "version": + string[] strArray1 = childNodes[i2].InnerText.Split(','); + if (toolStripMenuItem.DropDownItems.Count > 0) + { + for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1) + { + if (childNodes[i2].InnerText != "") + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1]; + dropDownItem.DropDownItems.Add("Latest Version"); + for (int index2 = 0; index2 < strArray1.Length; ++index2) + dropDownItem.DropDownItems.Add("v" + strArray1[index2]); + } + } + break; + } + toolStripMenuItem.DropDownItems.Add("Latest Version"); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray1.Length; ++index) + toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]); + break; + } + break; + case "region": + string[] strArray2 = childNodes[i2].InnerText.Split(','); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray2.Length; ++index) + toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index]))); + break; + } + break; + case "ticket": + ticket = Convert.ToBoolean(childNodes[i2].InnerText); + break; + case "danger": + danger = true; + toolStripMenuItem.ToolTipText = childNodes[i2].InnerText; + break; + } + toolStripMenuItem.Image = this.SelectItemImage(ticket, danger); + if (str1 != "") + toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2); + else + toolStripMenuItem.Text = str2; + } + toolStripMenuItemArray[i1] = toolStripMenuItem; + } + return toolStripMenuItemArray; + } + + public ToolStripMenuItem[] LoadDsiWareTitles() + { + if (this.databaseString.Length < 1) + throw new Exception("Load the database into a memory stream first!"); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(this.databaseString); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.DSiWareTag); + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count]; + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + XmlAttributeCollection attributes = elementsByTagName[i1].Attributes; + string str1 = ""; + string str2 = ""; + bool danger = false; + bool ticket = true; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "name": + str2 = childNodes[i2].InnerText; + break; + case "titleID": + str1 = childNodes[i2].InnerText; + break; + case "version": + string[] strArray1 = childNodes[i2].InnerText.Split(','); + if (toolStripMenuItem.DropDownItems.Count > 0) + { + for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1) + { + if (childNodes[i2].InnerText != "") + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1]; + dropDownItem.DropDownItems.Add("Latest Version"); + for (int index2 = 0; index2 < strArray1.Length; ++index2) + dropDownItem.DropDownItems.Add("v" + strArray1[index2]); + } + } + break; + } + toolStripMenuItem.DropDownItems.Add("Latest Version"); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray1.Length; ++index) + toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]); + break; + } + break; + case "region": + string[] strArray2 = childNodes[i2].InnerText.Split(','); + if (childNodes[i2].InnerText != "") + { + for (int index = 0; index < strArray2.Length; ++index) + toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index]))); + break; + } + break; + case "ticket": + ticket = Convert.ToBoolean(childNodes[i2].InnerText); + break; + case "danger": + danger = true; + toolStripMenuItem.ToolTipText = childNodes[i2].InnerText; + break; + } + toolStripMenuItem.Image = this.SelectItemImage(ticket, danger); + if (str1 != "") + toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2); + else + toolStripMenuItem.Text = str2; + } + toolStripMenuItemArray[i1] = toolStripMenuItem; + } + return toolStripMenuItemArray; + } + } +} diff --git a/NUS_Downloader/Form1.cs b/NUS_Downloader/Form1.cs new file mode 100644 index 0000000..a6b74c2 --- /dev/null +++ b/NUS_Downloader/Form1.cs @@ -0,0 +1,2923 @@ +// Decompiled with JetBrains decompiler +// Type: NUS_Downloader.Form1 +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using libWiiSharp; +using NUS_Downloader.Properties; +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Windows.Forms; +using System.Windows.Forms.Layout; +using System.Xml; +using wmgCMS; +using wyDay.Controls; + +namespace NUS_Downloader +{ + internal class Form1 : Form + { + private const string _chars = "abcdefghijklmnopqrstuvwxyz"; + private IContainer components; + private Button Extrasbtn; + private Button downloadstartbtn; + private RichTextBox statusbox; + private CheckBox packbox; + private CheckBox localuse; + private BackgroundWorker NUSDownloader; + private Label label1; + private TextBox wadnamebox; + private CheckBox decryptbox; + private Button databaseButton; + private ContextMenuStrip databaseStrip; + private ToolStripMenuItem SystemMenuList; + private ToolStripMenuItem IOSMenuList; + private ToolStripMenuItem VCMenuList; + private ToolStripMenuItem WiiWareMenuList; + private ToolStripMenuItem C64MenuList; + private ToolStripMenuItem NeoGeoMenuList; + private ToolStripMenuItem NESMenuList; + private ToolStripMenuItem SNESMenuList; + private ToolStripMenuItem N64MenuList; + private ToolStripMenuItem MSXMenuList; + private ToolStripMenuItem TurboGrafx16MenuList; + private ToolStripMenuItem SegaMSMenuList; + private ToolStripMenuItem GenesisMenuList; + private ToolStripMenuItem VCArcadeMenuList; + private ToolStripMenuItem TurboGrafxCDMenuList; + private ToolStripSeparator toolStripSeparator1; + private ToolStripMenuItem RegionCodesList; + private Button clearButton; + private ContextMenuStrip extrasStrip; + private ToolStripMenuItem loadInfoFromTMDToolStripMenuItem; + private ToolStripSeparator toolStripSeparator3; + private ToolStripMenuItem proxySettingsToolStripMenuItem; + private GroupBox proxyBox; + private TextBox ProxyUser; + private Button SaveProxyBtn; + private Button ProxyAssistBtn; + private TextBox ProxyURL; + private Label label13; + private Label label12; + private GroupBox ProxyVerifyBox; + private Button SaveProxyPwdBtn; + private Label label14; + private TextBox ProxyPwdBox; + private Windows7ProgressBar dlprogress; + private ToolStripSeparator toolStripSeparator6; + private WaterMarkTextBox titleidbox; + private WaterMarkTextBox titleversion; + private Button scriptsbutton; + private ContextMenuStrip scriptsStrip; + private ToolStripMenuItem loadNUSScriptToolStripMenuItem; + private ToolStripMenuItem emulateUpdate; + private ToolStripMenuItem uSANTSCToolStripMenuItem; + private ToolStripMenuItem europePALToolStripMenuItem; + private ToolStripMenuItem japanNTSCJToolStripMenuItem; + private ToolStripMenuItem koreaToolStripMenuItem; + private ToolStripSeparator toolStripSeparator4; + private ToolStripMenuItem updateDatabaseToolStripMenuItem; + private ToolStripMenuItem scriptsLocalMenuEntry; + private ToolStripSeparator toolStripSeparator2; + private ToolStripMenuItem scriptsDatabaseToolStripMenuItem; + private ToolStripMenuItem aboutNUSDToolStripMenuItem; + private CheckBox checkBox1; + private Button SaveProxyPwdPermanentBtn; + private CheckBox keepenccontents; + private Button saveaswadbtn; + private CheckBox iosPatchCheckbox; + private GroupBox iosPatchGroupBox; + private CheckedListBox iosPatchesListBox; + private Button iosPatchGroupBoxOKbtn; + private Label label2; + private Panel richPanel; + private ToolStripMenuItem systemFakeMenuItem; + private ToolStripMenuItem iosFakeMenuItem; + private ToolStripMenuItem vcFakeMenuItem; + private ToolStripMenuItem wwFakeMenuItem; + private ToolStripMenuItem openNUSDDirectoryToolStripMenuItem; + private ToolStripMenuItem moreExtrasToolStripMenuItem; + private ToolStripMenuItem runFolderFixToolStripMenuItem; + private ToolStripMenuItem wiiBrewToolStripMenuItem; + private ToolStripMenuItem mainPageToolStripMenuItem; + private ToolStripMenuItem databasePageToolStripMenuItem; + private ToolStripMenuItem removeNUSDFilesFoldersToolStripMenuItem; + private ToolStripMenuItem databaseToolStripMenuItem; + private ToolStripMenuItem localTicketInventoryToolStripMenuItem; + private ToolStripMenuItem donateToolStripMenuItem; + private ToolStripSeparator toolStripSeparator5; + private ToolStripMenuItem dsiSystemToolStripMenu; + private ToolStripMenuItem dsiFakeSystemToolStripMenu; + private ToolStripMenuItem dSiWareToolStripMenu; + private ToolStripMenuItem dSiWareFakeToolStripMenu; + private ToolStripMenuItem wiiRegionCodesMenu; + private ToolStripMenuItem dsiRegionCodesMenu; + private Label serverLbl; + private ToolStripSeparator toolStripSeparator7; + private CheckBox pathbox; + private readonly string CURRENT_DIR = Directory.GetCurrentDirectory(); + private string version = "v1.9 mod"; + private string WAD_Saveas_Filename; + private string proxy_url; + private string proxy_usr; + private string proxy_pwd; + private BackgroundWorker databaseWorker; + private BackgroundWorker dsiDatabaseWorker; + private BackgroundWorker scriptsWorker; + private Color normalcolor = Color.FromName("Black"); + private Color warningcolor = Color.FromName("DarkGoldenrod"); + private Color errorcolor = Color.FromName("Crimson"); + private Color infocolor = Color.FromName("RoyalBlue"); + private bool[] disabledStorage = new bool[14]; + private readonly Random _rng = new Random(); + + protected override void Dispose(bool disposing) + { + if (disposing && this.components != null) + this.components.Dispose(); + base.Dispose(disposing); + } + + private void InitializeComponent() + { + this.components = (IContainer) new Container(); + ComponentResourceManager componentResourceManager = new ComponentResourceManager(typeof (Form1)); + this.Extrasbtn = new Button(); + this.downloadstartbtn = new Button(); + this.statusbox = new RichTextBox(); + this.NUSDownloader = new BackgroundWorker(); + this.label1 = new Label(); + this.wadnamebox = new TextBox(); + this.databaseStrip = new ContextMenuStrip(this.components); + this.SystemMenuList = new ToolStripMenuItem(); + this.systemFakeMenuItem = new ToolStripMenuItem(); + this.IOSMenuList = new ToolStripMenuItem(); + this.iosFakeMenuItem = new ToolStripMenuItem(); + this.VCMenuList = new ToolStripMenuItem(); + this.C64MenuList = new ToolStripMenuItem(); + this.GenesisMenuList = new ToolStripMenuItem(); + this.MSXMenuList = new ToolStripMenuItem(); + this.N64MenuList = new ToolStripMenuItem(); + this.NeoGeoMenuList = new ToolStripMenuItem(); + this.NESMenuList = new ToolStripMenuItem(); + this.SegaMSMenuList = new ToolStripMenuItem(); + this.SNESMenuList = new ToolStripMenuItem(); + this.TurboGrafx16MenuList = new ToolStripMenuItem(); + this.TurboGrafxCDMenuList = new ToolStripMenuItem(); + this.VCArcadeMenuList = new ToolStripMenuItem(); + this.vcFakeMenuItem = new ToolStripMenuItem(); + this.WiiWareMenuList = new ToolStripMenuItem(); + this.wwFakeMenuItem = new ToolStripMenuItem(); + this.toolStripSeparator5 = new ToolStripSeparator(); + this.dsiSystemToolStripMenu = new ToolStripMenuItem(); + this.dsiFakeSystemToolStripMenu = new ToolStripMenuItem(); + this.dSiWareToolStripMenu = new ToolStripMenuItem(); + this.dSiWareFakeToolStripMenu = new ToolStripMenuItem(); + this.toolStripSeparator1 = new ToolStripSeparator(); + this.RegionCodesList = new ToolStripMenuItem(); + this.wiiRegionCodesMenu = new ToolStripMenuItem(); + this.dsiRegionCodesMenu = new ToolStripMenuItem(); + this.toolStripSeparator4 = new ToolStripSeparator(); + this.updateDatabaseToolStripMenuItem = new ToolStripMenuItem(); + this.extrasStrip = new ContextMenuStrip(this.components); + this.loadInfoFromTMDToolStripMenuItem = new ToolStripMenuItem(); + this.toolStripSeparator3 = new ToolStripSeparator(); + this.proxySettingsToolStripMenuItem = new ToolStripMenuItem(); + this.toolStripSeparator6 = new ToolStripSeparator(); + this.openNUSDDirectoryToolStripMenuItem = new ToolStripMenuItem(); + this.moreExtrasToolStripMenuItem = new ToolStripMenuItem(); + this.runFolderFixToolStripMenuItem = new ToolStripMenuItem(); + this.wiiBrewToolStripMenuItem = new ToolStripMenuItem(); + this.mainPageToolStripMenuItem = new ToolStripMenuItem(); + this.databasePageToolStripMenuItem = new ToolStripMenuItem(); + this.removeNUSDFilesFoldersToolStripMenuItem = new ToolStripMenuItem(); + this.databaseToolStripMenuItem = new ToolStripMenuItem(); + this.localTicketInventoryToolStripMenuItem = new ToolStripMenuItem(); + this.donateToolStripMenuItem = new ToolStripMenuItem(); + this.toolStripSeparator7 = new ToolStripSeparator(); + this.aboutNUSDToolStripMenuItem = new ToolStripMenuItem(); + this.proxyBox = new GroupBox(); + this.label13 = new Label(); + this.label12 = new Label(); + this.ProxyUser = new TextBox(); + this.SaveProxyBtn = new Button(); + this.ProxyAssistBtn = new Button(); + this.ProxyURL = new TextBox(); + this.ProxyVerifyBox = new GroupBox(); + this.SaveProxyPwdPermanentBtn = new Button(); + this.checkBox1 = new CheckBox(); + this.SaveProxyPwdBtn = new Button(); + this.label14 = new Label(); + this.ProxyPwdBox = new TextBox(); + this.scriptsbutton = new Button(); + this.scriptsStrip = new ContextMenuStrip(this.components); + this.scriptsLocalMenuEntry = new ToolStripMenuItem(); + this.scriptsDatabaseToolStripMenuItem = new ToolStripMenuItem(); + this.loadNUSScriptToolStripMenuItem = new ToolStripMenuItem(); + this.toolStripSeparator2 = new ToolStripSeparator(); + this.emulateUpdate = new ToolStripMenuItem(); + this.uSANTSCToolStripMenuItem = new ToolStripMenuItem(); + this.europePALToolStripMenuItem = new ToolStripMenuItem(); + this.japanNTSCJToolStripMenuItem = new ToolStripMenuItem(); + this.koreaToolStripMenuItem = new ToolStripMenuItem(); + this.iosPatchGroupBox = new GroupBox(); + this.label2 = new Label(); + this.iosPatchesListBox = new CheckedListBox(); + this.iosPatchGroupBoxOKbtn = new Button(); + this.richPanel = new Panel(); + this.databaseButton = new Button(); + this.saveaswadbtn = new Button(); + this.iosPatchCheckbox = new CheckBox(); + this.keepenccontents = new CheckBox(); + this.clearButton = new Button(); + this.packbox = new CheckBox(); + this.decryptbox = new CheckBox(); + this.localuse = new CheckBox(); + this.serverLbl = new Label(); + this.titleidbox = new WaterMarkTextBox(); + this.dlprogress = new Windows7ProgressBar(); + this.titleversion = new WaterMarkTextBox(); + this.pathbox = new CheckBox(); + this.databaseStrip.SuspendLayout(); + this.extrasStrip.SuspendLayout(); + this.proxyBox.SuspendLayout(); + this.ProxyVerifyBox.SuspendLayout(); + this.scriptsStrip.SuspendLayout(); + this.iosPatchGroupBox.SuspendLayout(); + this.richPanel.SuspendLayout(); + this.SuspendLayout(); + this.Extrasbtn.FlatStyle = FlatStyle.Popup; + this.Extrasbtn.Location = new Point(194, 5); + this.Extrasbtn.Name = "Extrasbtn"; + this.Extrasbtn.Size = new Size(68, 27); + this.Extrasbtn.TabIndex = 2; + this.Extrasbtn.Text = "Extras..."; + this.Extrasbtn.UseVisualStyleBackColor = true; + this.Extrasbtn.Click += new EventHandler(this.extrasMenuButton_Click); + this.downloadstartbtn.FlatStyle = FlatStyle.Popup; + this.downloadstartbtn.Location = new Point(12, 64); + this.downloadstartbtn.Name = "downloadstartbtn"; + this.downloadstartbtn.Size = new Size(250, 25); + this.downloadstartbtn.TabIndex = 5; + this.downloadstartbtn.Text = "Start NUS Download!"; + this.downloadstartbtn.UseVisualStyleBackColor = true; + this.downloadstartbtn.Click += new EventHandler(this.DownloadBtn_Click); + this.statusbox.BackColor = SystemColors.ControlLightLight; + this.statusbox.BorderStyle = BorderStyle.FixedSingle; + this.statusbox.Location = new Point(-2, -2); + this.statusbox.Name = "statusbox"; + this.statusbox.ReadOnly = true; + this.statusbox.ScrollBars = RichTextBoxScrollBars.None; + this.statusbox.Size = new Size(252, 269); + this.statusbox.TabIndex = 0; + this.statusbox.Text = ""; + this.NUSDownloader.DoWork += new DoWorkEventHandler(this.NUSDownloader_DoWork); + this.NUSDownloader.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.NUSDownloader_RunWorkerCompleted); + this.label1.AutoSize = true; + this.label1.BackColor = Color.Transparent; + this.label1.Location = new Point(159, 45); + this.label1.Name = "label1"; + this.label1.Size = new Size(13, 13); + this.label1.TabIndex = 0; + this.label1.Text = "v"; + this.wadnamebox.BorderStyle = BorderStyle.FixedSingle; + this.wadnamebox.Enabled = false; + this.wadnamebox.Location = new Point(102, 390); + this.wadnamebox.MaxLength = 99999; + this.wadnamebox.Name = "wadnamebox"; + this.wadnamebox.Size = new Size(161, 20); + this.wadnamebox.TabIndex = 17; + this.databaseStrip.Font = new Font("Tahoma", 8.25f, FontStyle.Regular, GraphicsUnit.Point, (byte) 0); + this.databaseStrip.Items.AddRange(new ToolStripItem[17] + { + (ToolStripItem) this.SystemMenuList, + (ToolStripItem) this.systemFakeMenuItem, + (ToolStripItem) this.IOSMenuList, + (ToolStripItem) this.iosFakeMenuItem, + (ToolStripItem) this.VCMenuList, + (ToolStripItem) this.vcFakeMenuItem, + (ToolStripItem) this.WiiWareMenuList, + (ToolStripItem) this.wwFakeMenuItem, + (ToolStripItem) this.toolStripSeparator5, + (ToolStripItem) this.dsiSystemToolStripMenu, + (ToolStripItem) this.dsiFakeSystemToolStripMenu, + (ToolStripItem) this.dSiWareToolStripMenu, + (ToolStripItem) this.dSiWareFakeToolStripMenu, + (ToolStripItem) this.toolStripSeparator1, + (ToolStripItem) this.RegionCodesList, + (ToolStripItem) this.toolStripSeparator4, + (ToolStripItem) this.updateDatabaseToolStripMenuItem + }); + this.databaseStrip.Name = "databaseStrip"; + this.databaseStrip.ShowItemToolTips = false; + this.databaseStrip.Size = new Size(164, 330); + this.databaseStrip.Text = "Hidden"; + this.databaseStrip.Closed += new ToolStripDropDownClosedEventHandler(this.anyStrip_Closed); + this.SystemMenuList.AutoSize = false; + this.SystemMenuList.Image = (Image) componentResourceManager.GetObject("SystemMenuList.Image"); + this.SystemMenuList.Name = "SystemMenuList"; + this.SystemMenuList.Size = new Size(158, 22); + this.SystemMenuList.Text = "System"; + this.systemFakeMenuItem.Image = (Image) Resources.arrow_ticker; + this.systemFakeMenuItem.Name = "systemFakeMenuItem"; + this.systemFakeMenuItem.Size = new Size(163, 22); + this.systemFakeMenuItem.Text = "System"; + this.systemFakeMenuItem.Visible = false; + this.IOSMenuList.Image = (Image) componentResourceManager.GetObject("IOSMenuList.Image"); + this.IOSMenuList.Name = "IOSMenuList"; + this.IOSMenuList.Size = new Size(163, 22); + this.IOSMenuList.Text = "IOS"; + this.iosFakeMenuItem.Image = (Image) Resources.arrow_ticker; + this.iosFakeMenuItem.Name = "iosFakeMenuItem"; + this.iosFakeMenuItem.Size = new Size(163, 22); + this.iosFakeMenuItem.Text = "IOS"; + this.iosFakeMenuItem.Visible = false; + this.VCMenuList.DropDownItems.AddRange(new ToolStripItem[11] + { + (ToolStripItem) this.C64MenuList, + (ToolStripItem) this.GenesisMenuList, + (ToolStripItem) this.MSXMenuList, + (ToolStripItem) this.N64MenuList, + (ToolStripItem) this.NeoGeoMenuList, + (ToolStripItem) this.NESMenuList, + (ToolStripItem) this.SegaMSMenuList, + (ToolStripItem) this.SNESMenuList, + (ToolStripItem) this.TurboGrafx16MenuList, + (ToolStripItem) this.TurboGrafxCDMenuList, + (ToolStripItem) this.VCArcadeMenuList + }); + this.VCMenuList.Image = (Image) componentResourceManager.GetObject("VCMenuList.Image"); + this.VCMenuList.Name = "VCMenuList"; + this.VCMenuList.Size = new Size(163, 22); + this.VCMenuList.Text = "Virtual Console"; + this.C64MenuList.Name = "C64MenuList"; + this.C64MenuList.Size = new Size(182, 22); + this.C64MenuList.Text = "Commodore 64"; + this.GenesisMenuList.Name = "GenesisMenuList"; + this.GenesisMenuList.Size = new Size(182, 22); + this.GenesisMenuList.Text = "Mega Drive/Genesis"; + this.MSXMenuList.Name = "MSXMenuList"; + this.MSXMenuList.Size = new Size(182, 22); + this.MSXMenuList.Text = "MSX"; + this.N64MenuList.Name = "N64MenuList"; + this.N64MenuList.Size = new Size(182, 22); + this.N64MenuList.Text = "Nintendo 64"; + this.NeoGeoMenuList.Name = "NeoGeoMenuList"; + this.NeoGeoMenuList.Size = new Size(182, 22); + this.NeoGeoMenuList.Text = "NeoGeo"; + this.NESMenuList.Name = "NESMenuList"; + this.NESMenuList.Size = new Size(182, 22); + this.NESMenuList.Text = "NES"; + this.SegaMSMenuList.Name = "SegaMSMenuList"; + this.SegaMSMenuList.Size = new Size(182, 22); + this.SegaMSMenuList.Text = "Sega Master System"; + this.SNESMenuList.Name = "SNESMenuList"; + this.SNESMenuList.Size = new Size(182, 22); + this.SNESMenuList.Text = "SNES"; + this.TurboGrafx16MenuList.Name = "TurboGrafx16MenuList"; + this.TurboGrafx16MenuList.Size = new Size(182, 22); + this.TurboGrafx16MenuList.Text = "TruboGrafx-16"; + this.TurboGrafxCDMenuList.Name = "TurboGrafxCDMenuList"; + this.TurboGrafxCDMenuList.Size = new Size(182, 22); + this.TurboGrafxCDMenuList.Text = "TurboGrafx-CD"; + this.VCArcadeMenuList.Name = "VCArcadeMenuList"; + this.VCArcadeMenuList.Size = new Size(182, 22); + this.VCArcadeMenuList.Text = "Virtual Console Arcade"; + this.vcFakeMenuItem.Image = (Image) Resources.arrow_ticker; + this.vcFakeMenuItem.Name = "vcFakeMenuItem"; + this.vcFakeMenuItem.Size = new Size(163, 22); + this.vcFakeMenuItem.Text = "Virtual Console"; + this.vcFakeMenuItem.Visible = false; + this.WiiWareMenuList.Image = (Image) componentResourceManager.GetObject("WiiWareMenuList.Image"); + this.WiiWareMenuList.Name = "WiiWareMenuList"; + this.WiiWareMenuList.Size = new Size(163, 22); + this.WiiWareMenuList.Text = "WiiWare"; + this.wwFakeMenuItem.Image = (Image) Resources.arrow_ticker; + this.wwFakeMenuItem.Name = "wwFakeMenuItem"; + this.wwFakeMenuItem.Size = new Size(163, 22); + this.wwFakeMenuItem.Text = "WiiWare"; + this.wwFakeMenuItem.Visible = false; + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new Size(160, 6); + this.dsiSystemToolStripMenu.Image = (Image) Resources.dsi16x16; + this.dsiSystemToolStripMenu.Name = "dsiSystemToolStripMenu"; + this.dsiSystemToolStripMenu.Size = new Size(163, 22); + this.dsiSystemToolStripMenu.Text = "System"; + this.dsiFakeSystemToolStripMenu.Image = (Image) Resources.arrow_ticker; + this.dsiFakeSystemToolStripMenu.Name = "dsiFakeSystemToolStripMenu"; + this.dsiFakeSystemToolStripMenu.Size = new Size(163, 22); + this.dsiFakeSystemToolStripMenu.Text = "System"; + this.dsiFakeSystemToolStripMenu.Visible = false; + this.dSiWareToolStripMenu.Image = (Image) Resources.dsi16x16; + this.dSiWareToolStripMenu.Name = "dSiWareToolStripMenu"; + this.dSiWareToolStripMenu.Size = new Size(163, 22); + this.dSiWareToolStripMenu.Text = "DSiWare"; + this.dSiWareFakeToolStripMenu.Image = (Image) Resources.arrow_ticker; + this.dSiWareFakeToolStripMenu.Name = "dSiWareFakeToolStripMenu"; + this.dSiWareFakeToolStripMenu.Size = new Size(163, 22); + this.dSiWareFakeToolStripMenu.Text = "DSiWare"; + this.dSiWareFakeToolStripMenu.Visible = false; + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new Size(160, 6); + this.RegionCodesList.DropDownItems.AddRange(new ToolStripItem[2] + { + (ToolStripItem) this.wiiRegionCodesMenu, + (ToolStripItem) this.dsiRegionCodesMenu + }); + this.RegionCodesList.Name = "RegionCodesList"; + this.RegionCodesList.Size = new Size(163, 22); + this.RegionCodesList.Text = "Region Codes"; + this.wiiRegionCodesMenu.Name = "wiiRegionCodesMenu"; + this.wiiRegionCodesMenu.Size = new Size(89, 22); + this.wiiRegionCodesMenu.Text = "Wii"; + this.wiiRegionCodesMenu.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.wiiRegionCodesMenu_DropDownItemClicked); + this.dsiRegionCodesMenu.Name = "dsiRegionCodesMenu"; + this.dsiRegionCodesMenu.Size = new Size(89, 22); + this.dsiRegionCodesMenu.Text = "DSi"; + this.dsiRegionCodesMenu.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.dsiRegionCodesMenu_DropDownItemClicked); + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new Size(160, 6); + this.updateDatabaseToolStripMenuItem.Image = (Image) Resources.database_save; + this.updateDatabaseToolStripMenuItem.Name = "updateDatabaseToolStripMenuItem"; + this.updateDatabaseToolStripMenuItem.Size = new Size(163, 22); + this.updateDatabaseToolStripMenuItem.Text = "Update Databases"; + this.updateDatabaseToolStripMenuItem.Click += new EventHandler(this.updateDatabaseToolStripMenuItem_Click); + this.extrasStrip.AllowMerge = false; + this.extrasStrip.Font = new Font("Tahoma", 8.25f, FontStyle.Regular, GraphicsUnit.Point, (byte) 0); + this.extrasStrip.Items.AddRange(new ToolStripItem[9] + { + (ToolStripItem) this.loadInfoFromTMDToolStripMenuItem, + (ToolStripItem) this.toolStripSeparator3, + (ToolStripItem) this.proxySettingsToolStripMenuItem, + (ToolStripItem) this.toolStripSeparator6, + (ToolStripItem) this.openNUSDDirectoryToolStripMenuItem, + (ToolStripItem) this.moreExtrasToolStripMenuItem, + (ToolStripItem) this.donateToolStripMenuItem, + (ToolStripItem) this.toolStripSeparator7, + (ToolStripItem) this.aboutNUSDToolStripMenuItem + }); + this.extrasStrip.Name = "extrasStrip"; + this.extrasStrip.Size = new Size(178, 154); + this.extrasStrip.Text = "Hidden"; + this.extrasStrip.Closed += new ToolStripDropDownClosedEventHandler(this.anyStrip_Closed); + this.extrasStrip.Opening += new CancelEventHandler(this.extrasStrip_Opening); + this.loadInfoFromTMDToolStripMenuItem.Image = (Image) Resources.page_white_magnify; + this.loadInfoFromTMDToolStripMenuItem.Name = "loadInfoFromTMDToolStripMenuItem"; + this.loadInfoFromTMDToolStripMenuItem.Size = new Size(177, 22); + this.loadInfoFromTMDToolStripMenuItem.Text = "Load Info from TMD"; + this.loadInfoFromTMDToolStripMenuItem.Click += new EventHandler(this.loadInfoFromTMDToolStripMenuItem_Click); + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new Size(174, 6); + this.proxySettingsToolStripMenuItem.Image = (Image) Resources.server_link; + this.proxySettingsToolStripMenuItem.Name = "proxySettingsToolStripMenuItem"; + this.proxySettingsToolStripMenuItem.Size = new Size(177, 22); + this.proxySettingsToolStripMenuItem.Text = "Proxy Settings"; + this.proxySettingsToolStripMenuItem.Click += new EventHandler(this.proxySettingsToolStripMenuItem_Click); + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new Size(174, 6); + this.openNUSDDirectoryToolStripMenuItem.Image = (Image) Resources.folder; + this.openNUSDDirectoryToolStripMenuItem.Name = "openNUSDDirectoryToolStripMenuItem"; + this.openNUSDDirectoryToolStripMenuItem.Size = new Size(177, 22); + this.openNUSDDirectoryToolStripMenuItem.Text = "Open NUSD Directory"; + this.openNUSDDirectoryToolStripMenuItem.Click += new EventHandler(this.openNUSDDirectoryToolStripMenuItem_Click); + this.moreExtrasToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[4] + { + (ToolStripItem) this.runFolderFixToolStripMenuItem, + (ToolStripItem) this.wiiBrewToolStripMenuItem, + (ToolStripItem) this.removeNUSDFilesFoldersToolStripMenuItem, + (ToolStripItem) this.databaseToolStripMenuItem + }); + this.moreExtrasToolStripMenuItem.Image = (Image) Resources.wrench; + this.moreExtrasToolStripMenuItem.Name = "moreExtrasToolStripMenuItem"; + this.moreExtrasToolStripMenuItem.Size = new Size(177, 22); + this.moreExtrasToolStripMenuItem.Text = "More Extras..."; + this.moreExtrasToolStripMenuItem.Visible = false; + this.runFolderFixToolStripMenuItem.Name = "runFolderFixToolStripMenuItem"; + this.runFolderFixToolStripMenuItem.Size = new Size(206, 22); + this.runFolderFixToolStripMenuItem.Text = "Run 'FolderFix'"; + this.runFolderFixToolStripMenuItem.Click += new EventHandler(this.runFolderFixToolStripMenuItem_Click); + this.wiiBrewToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[2] + { + (ToolStripItem) this.mainPageToolStripMenuItem, + (ToolStripItem) this.databasePageToolStripMenuItem + }); + this.wiiBrewToolStripMenuItem.Name = "wiiBrewToolStripMenuItem"; + this.wiiBrewToolStripMenuItem.Size = new Size(206, 22); + this.wiiBrewToolStripMenuItem.Text = "WiiBrew"; + this.mainPageToolStripMenuItem.Name = "mainPageToolStripMenuItem"; + this.mainPageToolStripMenuItem.Size = new Size(147, 22); + this.mainPageToolStripMenuItem.Text = "Main Page"; + this.mainPageToolStripMenuItem.Click += new EventHandler(this.mainPageToolStripMenuItem_Click); + this.databasePageToolStripMenuItem.Name = "databasePageToolStripMenuItem"; + this.databasePageToolStripMenuItem.Size = new Size(147, 22); + this.databasePageToolStripMenuItem.Text = "Database Page"; + this.databasePageToolStripMenuItem.Click += new EventHandler(this.databasePageToolStripMenuItem_Click); + this.removeNUSDFilesFoldersToolStripMenuItem.Name = "removeNUSDFilesFoldersToolStripMenuItem"; + this.removeNUSDFilesFoldersToolStripMenuItem.Size = new Size(206, 22); + this.removeNUSDFilesFoldersToolStripMenuItem.Text = "Remove NUSD Files\\Folders"; + this.removeNUSDFilesFoldersToolStripMenuItem.Click += new EventHandler(this.removeNUSDFilesFoldersToolStripMenuItem_Click); + this.databaseToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[1] + { + (ToolStripItem) this.localTicketInventoryToolStripMenuItem + }); + this.databaseToolStripMenuItem.Name = "databaseToolStripMenuItem"; + this.databaseToolStripMenuItem.Size = new Size(206, 22); + this.databaseToolStripMenuItem.Text = "Database"; + this.localTicketInventoryToolStripMenuItem.Name = "localTicketInventoryToolStripMenuItem"; + this.localTicketInventoryToolStripMenuItem.Size = new Size(180, 22); + this.localTicketInventoryToolStripMenuItem.Text = "Local Ticket Inventory"; + this.localTicketInventoryToolStripMenuItem.Click += new EventHandler(this.localTicketInventoryToolStripMenuItem_Click); + this.donateToolStripMenuItem.Image = (Image) Resources.money; + this.donateToolStripMenuItem.Name = "donateToolStripMenuItem"; + this.donateToolStripMenuItem.Size = new Size(177, 22); + this.donateToolStripMenuItem.Text = "Donate!"; + this.donateToolStripMenuItem.Visible = false; + this.donateToolStripMenuItem.Click += new EventHandler(this.donateToolStripMenuItem_Click); + this.toolStripSeparator7.Name = "toolStripSeparator7"; + this.toolStripSeparator7.Size = new Size(174, 6); + this.aboutNUSDToolStripMenuItem.Image = (Image) Resources.information; + this.aboutNUSDToolStripMenuItem.Name = "aboutNUSDToolStripMenuItem"; + this.aboutNUSDToolStripMenuItem.Size = new Size(177, 22); + this.aboutNUSDToolStripMenuItem.Text = "About NUSD"; + this.aboutNUSDToolStripMenuItem.Click += new EventHandler(this.aboutNUSDToolStripMenuItem_Click); + this.proxyBox.BackColor = Color.White; + this.proxyBox.Controls.Add((Control) this.label13); + this.proxyBox.Controls.Add((Control) this.label12); + this.proxyBox.Controls.Add((Control) this.ProxyUser); + this.proxyBox.Controls.Add((Control) this.SaveProxyBtn); + this.proxyBox.Controls.Add((Control) this.ProxyAssistBtn); + this.proxyBox.Controls.Add((Control) this.ProxyURL); + this.proxyBox.Location = new Point(31, 250); + this.proxyBox.Name = "proxyBox"; + this.proxyBox.Size = new Size(212, 114); + this.proxyBox.TabIndex = 45; + this.proxyBox.TabStop = false; + this.proxyBox.Text = "Proxy Settings"; + this.proxyBox.Visible = false; + this.label13.AutoSize = true; + this.label13.Location = new Point(6, 55); + this.label13.Name = "label13"; + this.label13.Size = new Size(32, 13); + this.label13.TabIndex = 32; + this.label13.Text = "User:"; + this.label12.AutoSize = true; + this.label12.Location = new Point(6, 29); + this.label12.Name = "label12"; + this.label12.Size = new Size(36, 13); + this.label12.TabIndex = 31; + this.label12.Text = "Proxy:"; + this.ProxyUser.BorderStyle = BorderStyle.FixedSingle; + this.ProxyUser.Location = new Point(55, 53); + this.ProxyUser.Name = "ProxyUser"; + this.ProxyUser.Size = new Size(151, 20); + this.ProxyUser.TabIndex = 30; + this.SaveProxyBtn.FlatStyle = FlatStyle.Popup; + this.SaveProxyBtn.Location = new Point(6, 79); + this.SaveProxyBtn.Name = "SaveProxyBtn"; + this.SaveProxyBtn.Size = new Size(161, 26); + this.SaveProxyBtn.TabIndex = 29; + this.SaveProxyBtn.Text = "Save Proxy Settings"; + this.SaveProxyBtn.UseVisualStyleBackColor = true; + this.SaveProxyBtn.Click += new EventHandler(this.SaveProxyBtn_Click); + this.ProxyAssistBtn.FlatStyle = FlatStyle.Popup; + this.ProxyAssistBtn.Image = (Image) Resources.help; + this.ProxyAssistBtn.Location = new Point(177, 79); + this.ProxyAssistBtn.Name = "ProxyAssistBtn"; + this.ProxyAssistBtn.Size = new Size(29, 26); + this.ProxyAssistBtn.TabIndex = 28; + this.ProxyAssistBtn.UseVisualStyleBackColor = true; + this.ProxyAssistBtn.Click += new EventHandler(this.ProxyAssistBtn_Click); + this.ProxyURL.BorderStyle = BorderStyle.FixedSingle; + this.ProxyURL.Location = new Point(55, 27); + this.ProxyURL.Name = "ProxyURL"; + this.ProxyURL.Size = new Size(151, 20); + this.ProxyURL.TabIndex = 0; + this.ProxyVerifyBox.BackColor = SystemColors.Control; + this.ProxyVerifyBox.Controls.Add((Control) this.SaveProxyPwdPermanentBtn); + this.ProxyVerifyBox.Controls.Add((Control) this.checkBox1); + this.ProxyVerifyBox.Controls.Add((Control) this.SaveProxyPwdBtn); + this.ProxyVerifyBox.Controls.Add((Control) this.label14); + this.ProxyVerifyBox.Controls.Add((Control) this.ProxyPwdBox); + this.ProxyVerifyBox.Location = new Point(31, 222); + this.ProxyVerifyBox.Name = "ProxyVerifyBox"; + this.ProxyVerifyBox.Size = new Size(212, 133); + this.ProxyVerifyBox.TabIndex = 46; + this.ProxyVerifyBox.TabStop = false; + this.ProxyVerifyBox.Text = "Verify Credentials"; + this.ProxyVerifyBox.Visible = false; + this.SaveProxyPwdPermanentBtn.Enabled = false; + this.SaveProxyPwdPermanentBtn.FlatStyle = FlatStyle.Popup; + this.SaveProxyPwdPermanentBtn.Location = new Point(9, 104); + this.SaveProxyPwdPermanentBtn.Name = "SaveProxyPwdPermanentBtn"; + this.SaveProxyPwdPermanentBtn.Size = new Size(197, 23); + this.SaveProxyPwdPermanentBtn.TabIndex = 36; + this.SaveProxyPwdPermanentBtn.Text = "Save (To File)"; + this.SaveProxyPwdPermanentBtn.UseVisualStyleBackColor = true; + this.SaveProxyPwdPermanentBtn.Click += new EventHandler(this.SaveProxyPwdPermanentBtn_Click); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new Point(9, 72); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new Size(199, 30); + this.checkBox1.TabIndex = 35; + this.checkBox1.Text = "I understand that NUSD stores proxy\r\npasswords in plain text."; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new EventHandler(this.checkBox1_CheckedChanged); + this.SaveProxyPwdBtn.FlatStyle = FlatStyle.Popup; + this.SaveProxyPwdBtn.Location = new Point(9, 43); + this.SaveProxyPwdBtn.Name = "SaveProxyPwdBtn"; + this.SaveProxyPwdBtn.Size = new Size(197, 23); + this.SaveProxyPwdBtn.TabIndex = 34; + this.SaveProxyPwdBtn.Text = "Save (This Session Only)"; + this.SaveProxyPwdBtn.UseVisualStyleBackColor = true; + this.SaveProxyPwdBtn.Click += new EventHandler(this.SaveProxyPwdButton_Click); + this.label14.AutoSize = true; + this.label14.Location = new Point(6, 21); + this.label14.Name = "label14"; + this.label14.Size = new Size(62, 13); + this.label14.TabIndex = 33; + this.label14.Text = "Proxy Pass:"; + this.ProxyPwdBox.BorderStyle = BorderStyle.FixedSingle; + this.ProxyPwdBox.Location = new Point(71, 19); + this.ProxyPwdBox.Name = "ProxyPwdBox"; + this.ProxyPwdBox.Size = new Size(135, 20); + this.ProxyPwdBox.TabIndex = 32; + this.ProxyPwdBox.UseSystemPasswordChar = true; + this.ProxyPwdBox.KeyPress += new KeyPressEventHandler(this.ProxyPwdBox_KeyPress); + this.scriptsbutton.FlatStyle = FlatStyle.Popup; + this.scriptsbutton.Location = new Point(103, 5); + this.scriptsbutton.Name = "scriptsbutton"; + this.scriptsbutton.Size = new Size(85, 27); + this.scriptsbutton.TabIndex = 1; + this.scriptsbutton.Text = "Scripts..."; + this.scriptsbutton.UseVisualStyleBackColor = true; + this.scriptsbutton.Click += new EventHandler(this.scriptsbutton_Click); + this.scriptsStrip.Font = new Font("Tahoma", 8.25f, FontStyle.Regular, GraphicsUnit.Point, (byte) 0); + this.scriptsStrip.Items.AddRange(new ToolStripItem[5] + { + (ToolStripItem) this.scriptsLocalMenuEntry, + (ToolStripItem) this.scriptsDatabaseToolStripMenuItem, + (ToolStripItem) this.loadNUSScriptToolStripMenuItem, + (ToolStripItem) this.toolStripSeparator2, + (ToolStripItem) this.emulateUpdate + }); + this.scriptsStrip.Name = "scriptsStrip"; + this.scriptsStrip.ShowItemToolTips = false; + this.scriptsStrip.Size = new Size(206, 98); + this.scriptsStrip.Text = "Hidden"; + this.scriptsStrip.Closed += new ToolStripDropDownClosedEventHandler(this.anyStrip_Closed); + this.scriptsLocalMenuEntry.Enabled = false; + this.scriptsLocalMenuEntry.Image = (Image) Resources.script_code; + this.scriptsLocalMenuEntry.Name = "scriptsLocalMenuEntry"; + this.scriptsLocalMenuEntry.Overflow = ToolStripItemOverflow.AsNeeded; + this.scriptsLocalMenuEntry.Size = new Size(205, 22); + this.scriptsLocalMenuEntry.Text = "Scripts (Local)"; + this.scriptsDatabaseToolStripMenuItem.Enabled = false; + this.scriptsDatabaseToolStripMenuItem.Image = (Image) Resources.script_code_red; + this.scriptsDatabaseToolStripMenuItem.Name = "scriptsDatabaseToolStripMenuItem"; + this.scriptsDatabaseToolStripMenuItem.Size = new Size(205, 22); + this.scriptsDatabaseToolStripMenuItem.Text = "Scripts (Database)"; + this.loadNUSScriptToolStripMenuItem.Image = (Image) Resources.script_go; + this.loadNUSScriptToolStripMenuItem.Name = "loadNUSScriptToolStripMenuItem"; + this.loadNUSScriptToolStripMenuItem.Size = new Size(205, 22); + this.loadNUSScriptToolStripMenuItem.Text = "Load NUS Script"; + this.loadNUSScriptToolStripMenuItem.Click += new EventHandler(this.loadNUSScriptToolStripMenuItem_Click); + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new Size(202, 6); + this.emulateUpdate.DropDownItems.AddRange(new ToolStripItem[4] + { + (ToolStripItem) this.uSANTSCToolStripMenuItem, + (ToolStripItem) this.europePALToolStripMenuItem, + (ToolStripItem) this.japanNTSCJToolStripMenuItem, + (ToolStripItem) this.koreaToolStripMenuItem + }); + this.emulateUpdate.Image = (Image) Resources.server_connect; + this.emulateUpdate.Name = "emulateUpdate"; + this.emulateUpdate.Size = new Size(205, 22); + this.emulateUpdate.Text = "Emulate Wii System Update"; + this.emulateUpdate.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.emulateUpdate_DropDownItemClicked); + this.uSANTSCToolStripMenuItem.Name = "uSANTSCToolStripMenuItem"; + this.uSANTSCToolStripMenuItem.Size = new Size(114, 22); + this.uSANTSCToolStripMenuItem.Text = "USA"; + this.europePALToolStripMenuItem.Name = "europePALToolStripMenuItem"; + this.europePALToolStripMenuItem.Size = new Size(114, 22); + this.europePALToolStripMenuItem.Text = "EUROPE"; + this.japanNTSCJToolStripMenuItem.Name = "japanNTSCJToolStripMenuItem"; + this.japanNTSCJToolStripMenuItem.Size = new Size(114, 22); + this.japanNTSCJToolStripMenuItem.Text = "JAPAN"; + this.koreaToolStripMenuItem.Name = "koreaToolStripMenuItem"; + this.koreaToolStripMenuItem.Size = new Size(114, 22); + this.koreaToolStripMenuItem.Text = "KOREA"; + this.iosPatchGroupBox.Controls.Add((Control) this.label2); + this.iosPatchGroupBox.Controls.Add((Control) this.iosPatchesListBox); + this.iosPatchGroupBox.Controls.Add((Control) this.iosPatchGroupBoxOKbtn); + this.iosPatchGroupBox.Location = new Point(31, 187); + this.iosPatchGroupBox.Name = "iosPatchGroupBox"; + this.iosPatchGroupBox.Size = new Size(212, 115); + this.iosPatchGroupBox.TabIndex = 55; + this.iosPatchGroupBox.TabStop = false; + this.iosPatchGroupBox.Text = "IOS Patches"; + this.iosPatchGroupBox.Visible = false; + this.label2.AutoSize = true; + this.label2.Location = new Point(9, 16); + this.label2.Name = "label2"; + this.label2.Size = new Size(184, 26); + this.label2.TabIndex = 2; + this.label2.Text = "Patch the following bugs into any IOS\r\nI download:"; + this.iosPatchesListBox.BackColor = SystemColors.Menu; + this.iosPatchesListBox.BorderStyle = BorderStyle.None; + this.iosPatchesListBox.CheckOnClick = true; + this.iosPatchesListBox.FormattingEnabled = true; + this.iosPatchesListBox.Items.AddRange(new object[3] + { + (object) "Trucha bug", + (object) "ES_Identify", + (object) "NAND permissions" + }); + this.iosPatchesListBox.Location = new Point(6, 62); + this.iosPatchesListBox.Name = "iosPatchesListBox"; + this.iosPatchesListBox.Size = new Size(115, 45); + this.iosPatchesListBox.TabIndex = 1; + this.iosPatchGroupBoxOKbtn.FlatStyle = FlatStyle.Popup; + this.iosPatchGroupBoxOKbtn.Location = new Point((int) sbyte.MaxValue, 84); + this.iosPatchGroupBoxOKbtn.Name = "iosPatchGroupBoxOKbtn"; + this.iosPatchGroupBoxOKbtn.Size = new Size(75, 23); + this.iosPatchGroupBoxOKbtn.TabIndex = 0; + this.iosPatchGroupBoxOKbtn.Text = "OK"; + this.iosPatchGroupBoxOKbtn.UseVisualStyleBackColor = true; + this.iosPatchGroupBoxOKbtn.Click += new EventHandler(this.iosPatchGroupBoxOKbtn_Click); + this.richPanel.BorderStyle = BorderStyle.FixedSingle; + this.richPanel.Controls.Add((Control) this.statusbox); + this.richPanel.Location = new Point(12, 116); + this.richPanel.Name = "richPanel"; + this.richPanel.Size = new Size(250, 268); + this.richPanel.TabIndex = 56; + this.databaseButton.FlatStyle = FlatStyle.Popup; + this.databaseButton.Location = new Point(12, 5); + this.databaseButton.Name = "databaseButton"; + this.databaseButton.Size = new Size(85, 27); + this.databaseButton.TabIndex = 0; + this.databaseButton.Text = "Database..."; + this.databaseButton.TextImageRelation = TextImageRelation.ImageBeforeText; + this.databaseButton.UseVisualStyleBackColor = true; + this.databaseButton.Click += new EventHandler(this.DatabaseButton_Click); + this.saveaswadbtn.Anchor = AnchorStyles.Top | AnchorStyles.Right; + this.saveaswadbtn.AutoSize = true; + this.saveaswadbtn.AutoSizeMode = AutoSizeMode.GrowAndShrink; + this.saveaswadbtn.BackColor = Color.Transparent; + this.saveaswadbtn.Enabled = false; + this.saveaswadbtn.FlatStyle = FlatStyle.Flat; + this.saveaswadbtn.Image = (Image) Resources.disk; + this.saveaswadbtn.Location = new Point(239, 409); + this.saveaswadbtn.MaximumSize = new Size(0, 24); + this.saveaswadbtn.MinimumSize = new Size(0, 24); + this.saveaswadbtn.Name = "saveaswadbtn"; + this.saveaswadbtn.Size = new Size(24, 24); + this.saveaswadbtn.TabIndex = 11; + this.saveaswadbtn.TextAlign = ContentAlignment.MiddleLeft; + this.saveaswadbtn.TextImageRelation = TextImageRelation.ImageBeforeText; + this.saveaswadbtn.UseVisualStyleBackColor = false; + this.saveaswadbtn.Click += new EventHandler(this.saveaswadbtn_Click); + this.saveaswadbtn.MouseEnter += new EventHandler(this.saveaswadbtn_MouseEnter); + this.saveaswadbtn.MouseLeave += new EventHandler(this.saveaswadbtn_MouseLeave); + this.iosPatchCheckbox.Enabled = false; + this.iosPatchCheckbox.Image = (Image) Resources.bug_add; + this.iosPatchCheckbox.ImageAlign = ContentAlignment.MiddleLeft; + this.iosPatchCheckbox.Location = new Point(11, 480); + this.iosPatchCheckbox.Name = "iosPatchCheckbox"; + this.iosPatchCheckbox.Size = new Size(104, 22); + this.iosPatchCheckbox.TabIndex = 10; + this.iosPatchCheckbox.Text = "Patch IOS..."; + this.iosPatchCheckbox.TextImageRelation = TextImageRelation.ImageBeforeText; + this.iosPatchCheckbox.UseVisualStyleBackColor = true; + this.iosPatchCheckbox.CheckedChanged += new EventHandler(this.iosPatchCheckbox_CheckedChanged); + this.keepenccontents.Checked = true; + this.keepenccontents.CheckState = CheckState.Checked; + this.keepenccontents.Image = (Image) Resources.package; + this.keepenccontents.ImageAlign = ContentAlignment.MiddleLeft; + this.keepenccontents.Location = new Point(10, 414); + this.keepenccontents.Name = "keepenccontents"; + this.keepenccontents.Size = new Size(177, 22); + this.keepenccontents.TabIndex = 8; + this.keepenccontents.Text = "Keep Encrypted Contents"; + this.keepenccontents.TextImageRelation = TextImageRelation.ImageBeforeText; + this.keepenccontents.UseVisualStyleBackColor = true; + this.clearButton.Anchor = AnchorStyles.Top | AnchorStyles.Right; + this.clearButton.AutoSize = true; + this.clearButton.AutoSizeMode = AutoSizeMode.GrowAndShrink; + this.clearButton.BackColor = Color.Transparent; + this.clearButton.FlatStyle = FlatStyle.Flat; + this.clearButton.Image = (Image) Resources.bin_closed; + this.clearButton.ImageAlign = ContentAlignment.MiddleRight; + this.clearButton.Location = new Point(238, 360); + this.clearButton.MaximumSize = new Size(0, 24); + this.clearButton.MinimumSize = new Size(0, 24); + this.clearButton.Name = "clearButton"; + this.clearButton.Size = new Size(24, 24); + this.clearButton.TabIndex = 12; + this.clearButton.TextAlign = ContentAlignment.MiddleRight; + this.clearButton.TextImageRelation = TextImageRelation.ImageBeforeText; + this.clearButton.UseVisualStyleBackColor = false; + this.clearButton.Click += new EventHandler(this.ClearStatusbox); + this.clearButton.MouseEnter += new EventHandler(this.clearButton_MouseEnter); + this.clearButton.MouseLeave += new EventHandler(this.clearButton_MouseLeave); + this.packbox.Image = (Image) Resources.box; + this.packbox.ImageAlign = ContentAlignment.MiddleLeft; + this.packbox.Location = new Point(10, 392); + this.packbox.Name = "packbox"; + this.packbox.Size = new Size(98, 22); + this.packbox.TabIndex = 7; + this.packbox.Text = "Pack WAD"; + this.packbox.TextImageRelation = TextImageRelation.ImageBeforeText; + this.packbox.UseVisualStyleBackColor = true; + this.packbox.CheckedChanged += new EventHandler(this.packbox_CheckedChanged); + this.packbox.EnabledChanged += new EventHandler(this.packbox_EnabledChanged); + this.decryptbox.Image = (Image) Resources.package_green; + this.decryptbox.ImageAlign = ContentAlignment.MiddleLeft; + this.decryptbox.Location = new Point(11, 436); + this.decryptbox.Name = "decryptbox"; + this.decryptbox.Size = new Size(231, 22); + this.decryptbox.TabIndex = 9; + this.decryptbox.Text = "Create Decrypted Contents (*.app)"; + this.decryptbox.TextImageRelation = TextImageRelation.ImageBeforeText; + this.decryptbox.UseVisualStyleBackColor = true; + this.localuse.Checked = true; + this.localuse.CheckState = CheckState.Checked; + this.localuse.Image = (Image) Resources.drive_disk; + this.localuse.ImageAlign = ContentAlignment.MiddleLeft; + this.localuse.Location = new Point(11, 458); + this.localuse.MinimumSize = new Size(0, 22); + this.localuse.Name = "localuse"; + this.localuse.Size = new Size(162, 22); + this.localuse.TabIndex = 12; + this.localuse.Text = "Use Local Files If Present"; + this.localuse.TextImageRelation = TextImageRelation.ImageBeforeText; + this.localuse.UseVisualStyleBackColor = true; + this.serverLbl.BorderStyle = BorderStyle.FixedSingle; + this.serverLbl.Location = new Point(233, 38); + this.serverLbl.Name = "serverLbl"; + this.serverLbl.Size = new Size(29, 20); + this.serverLbl.TabIndex = 57; + this.serverLbl.Text = "Wii"; + this.serverLbl.TextAlign = ContentAlignment.MiddleCenter; + this.serverLbl.TextChanged += new EventHandler(this.serverLbl_TextChanged); + this.serverLbl.Click += new EventHandler(this.serverLbl_Click); + this.serverLbl.MouseEnter += new EventHandler(this.serverLbl_MouseEnter); + this.serverLbl.MouseLeave += new EventHandler(this.serverLbl_MouseLeave); + this.titleidbox.Font = new Font("Tahoma", 8.25f); + this.titleidbox.Location = new Point(12, 38); + this.titleidbox.MaxLength = 16; + this.titleidbox.Name = "titleidbox"; + this.titleidbox.Size = new Size(141, 21); + this.titleidbox.TabIndex = 3; + this.titleidbox.TextAlign = HorizontalAlignment.Center; + this.titleidbox.WaterMarkColor = Color.Silver; + this.titleidbox.WaterMarkText = "Title ID"; + this.titleidbox.TextChanged += new EventHandler(this.titleidbox_TextChanged); + this.dlprogress.ContainerControl = (ContainerControl) this; + this.dlprogress.Location = new Point(12, 95); + this.dlprogress.Name = "dlprogress"; + this.dlprogress.Size = new Size(250, 15); + this.dlprogress.TabIndex = 47; + this.titleversion.Font = new Font("Tahoma", 8.25f); + this.titleversion.Location = new Point(169, 38); + this.titleversion.MaxLength = 8; + this.titleversion.Name = "titleversion"; + this.titleversion.Size = new Size(58, 21); + this.titleversion.TabIndex = 4; + this.titleversion.TextAlign = HorizontalAlignment.Center; + this.titleversion.WaterMarkColor = Color.Silver; + this.titleversion.WaterMarkText = "Version"; + this.titleversion.TextChanged += new EventHandler(this.titleversion_TextChanged); + this.pathbox.Location = new Point(11, 502); + this.pathbox.Name = "pathbox"; + this.pathbox.Size = new Size(161, 22); + this.pathbox.TabIndex = 58; + this.pathbox.Text = "Directory of NUSD v1.5"; + this.pathbox.UseVisualStyleBackColor = true; + this.AutoScaleMode = AutoScaleMode.None; + this.ClientSize = new Size(274, 527); + this.Controls.Add((Control) this.pathbox); + this.Controls.Add((Control) this.serverLbl); + this.Controls.Add((Control) this.iosPatchGroupBox); + this.Controls.Add((Control) this.ProxyVerifyBox); + this.Controls.Add((Control) this.proxyBox); + this.Controls.Add((Control) this.scriptsbutton); + this.Controls.Add((Control) this.titleidbox); + this.Controls.Add((Control) this.dlprogress); + this.Controls.Add((Control) this.titleversion); + this.Controls.Add((Control) this.databaseButton); + this.Controls.Add((Control) this.iosPatchCheckbox); + this.Controls.Add((Control) this.downloadstartbtn); + this.Controls.Add((Control) this.clearButton); + this.Controls.Add((Control) this.keepenccontents); + this.Controls.Add((Control) this.label1); + this.Controls.Add((Control) this.Extrasbtn); + this.Controls.Add((Control) this.wadnamebox); + this.Controls.Add((Control) this.richPanel); + this.Controls.Add((Control) this.decryptbox); + this.Controls.Add((Control) this.packbox); + this.Controls.Add((Control) this.saveaswadbtn); + this.Controls.Add((Control) this.localuse); + this.FormBorderStyle = FormBorderStyle.FixedSingle; + this.Icon = (Icon) componentResourceManager.GetObject("$this.Icon"); + this.MaximizeBox = false; + this.Name = nameof (Form1); + this.Text = " "; + this.FormClosing += new FormClosingEventHandler(this.Form1_FormClosing); + this.Load += new EventHandler(this.Form1_Load); + this.MouseWheel += new MouseEventHandler(this.Form1_MouseWheel); + this.databaseStrip.ResumeLayout(false); + this.extrasStrip.ResumeLayout(false); + this.proxyBox.ResumeLayout(false); + this.proxyBox.PerformLayout(); + this.ProxyVerifyBox.ResumeLayout(false); + this.ProxyVerifyBox.PerformLayout(); + this.scriptsStrip.ResumeLayout(false); + this.iosPatchGroupBox.ResumeLayout(false); + this.iosPatchGroupBox.PerformLayout(); + this.richPanel.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + } + + public Form1() + { + this.InitializeComponent(); + this.GUISetup(); + this.BootChecks(); + } + + public Form1(string[] args) + { + this.InitializeComponent(); + this.GUISetup(); + if (args.Length == 1 && System.IO.File.Exists(args[0])) + { + this.BootChecks(); + string str1 = System.IO.File.ReadAllText(args[0]); + FileInfo fileInfo = new FileInfo(args[0]); + string str2 = str1 + string.Format(";{0}", (object) fileInfo.Name.Replace("." + fileInfo.Extension, "")); + BackgroundWorker backgroundWorker = new BackgroundWorker(); + backgroundWorker.DoWork += new DoWorkEventHandler(this.RunScriptBg); + backgroundWorker.RunWorkerAsync((object) str2); + } + else if (args.Length >= 2) + { + this.RunCommandMode(args); + Environment.Exit(0); + } + else + this.BootChecks(); + } + + private void RunCommandMode(string[] args) + { + this.packbox.Checked = false; + this.localuse.Checked = true; + this.decryptbox.Checked = false; + this.keepenccontents.Checked = false; + this.iosPatchCheckbox.Checked = false; + this.iosPatchesListBox.SetItemChecked(0, false); + this.iosPatchesListBox.SetItemChecked(1, false); + this.iosPatchesListBox.SetItemChecked(2, false); + Console.WriteLine("NUS Downloader - v{0}", (object) this.version); + if (args.Length < 2) + { + Console.WriteLine("Usage:"); + Console.WriteLine(" nusd [optionalArgs]"); + Console.WriteLine("\nWhere:"); + Console.WriteLine(" titleID = The ID of the title to be downloaded"); + Console.WriteLine(" titleVersion = The version of the title to be downloaded"); + Console.WriteLine(" Use \"*\" (no quotes) to get the latest version"); + Console.WriteLine(" OptionalArgs:"); + Console.WriteLine(" packwad = A wad file will be generated"); + Console.WriteLine(" localuse = Use local contents if available"); + Console.WriteLine(" decrypt = Create decrypted contents"); + Console.WriteLine(" keepencrypt = Keep encrypted contents"); + } + else + { + for (int index = 0; index < args.Length; ++index) + { + Console.WriteLine("{0}", (object) args[index]); + switch (index) + { + case 0: + this.titleidbox.Text = args[index]; + break; + case 1: + if (args[index] == "*") + { + this.titleversion.Text = ""; + break; + } + this.titleversion.Text = args[index]; + break; + default: + if (args[index] == "packwad") + { + this.packbox.Checked = true; + break; + } + if (args[index] == "localuse") + { + this.localuse.Checked = true; + break; + } + if (args[index] == "decrypt") + { + this.decryptbox.Checked = true; + break; + } + if (args[index] == "keepencrypt") + { + this.keepenccontents.Checked = true; + break; + } + Console.WriteLine("\n>>>> Warning: Unrecognized command line argument: {0}. This option is ignored...", (object) args[index]); + break; + } + } + this.UpdatePackedName(); + this.NUSDownloader_DoWork((object) null, (DoWorkEventArgs) null); + Console.WriteLine("\nSuccessfully downloaded the title {0} version {1}", (object) args[0], (object) args[1]); + } + } + + private void GUISetup() + { + this.Font = new Font("Tahoma", 8f); + this.MaximumSize = this.MinimumSize = this.Size; + if (System.Type.GetType("Mono.Runtime") != null) + { + this.saveaswadbtn.Text = "Save As"; + this.clearButton.Text = "Clear"; + this.keepenccontents.Text = "Keep Enc. Contents"; + this.clearButton.Left -= 41; + } + else + this.statusbox.Font = new Font("Microsoft Sans Serif", 7f); + this.statusbox.SelectionColor = this.statusbox.ForeColor = this.normalcolor; + if (this.version.StartsWith("SVN")) + { + this.WriteStatus("!!!!! THIS IS A DEBUG BUILD FROM SVN !!!!!"); + this.WriteStatus("Features CAN and WILL be broken in this build!"); + this.WriteStatus("Devs: REMEMBER TO CHANGE TO THE RELEASE CONFIGURATION AND CHANGE VERSION NUMBER BEFORE BUILDING!"); + this.WriteStatus("\r\n"); + } + this.databaseWorker = new BackgroundWorker(); + this.databaseWorker.DoWork += new DoWorkEventHandler(this.DoAllDatabaseyStuff); + this.databaseWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.DoAllDatabaseyStuff_Completed); + this.databaseWorker.ProgressChanged += new ProgressChangedEventHandler(this.DoAllDatabaseyStuff_ProgressChanged); + this.databaseWorker.WorkerReportsProgress = true; + this.dsiDatabaseWorker = new BackgroundWorker(); + this.dsiDatabaseWorker.DoWork += new DoWorkEventHandler(this.DSiDatabaseWork); + this.dsiDatabaseWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.DSiDatabaseWork_Completed); + this.dsiDatabaseWorker.ProgressChanged += new ProgressChangedEventHandler(this.DSiDatabaseWork_ProgressChanged); + this.dsiDatabaseWorker.WorkerReportsProgress = true; + this.scriptsWorker = new BackgroundWorker(); + this.scriptsWorker.DoWork += new DoWorkEventHandler(this.OrganizeScripts); + this.scriptsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.scriptsWorker_RunWorkerCompleted); + } + + private void Form1_Load(object sender, EventArgs e) + { + this.Text = string.Format("NUSD - {0}", (object) this.version); + this.Size = this.MinimumSize; + this.serverLbl.Text = "Wii"; + } + + private bool NUSDFileExists(string filename) => System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, filename)); + + private void BootChecks() + { + if (this.InvokeRequired) + { + this.Invoke((Delegate) new Form1.BootChecksCallback(this.BootChecks)); + } + else + { + if (this.NUSDFileExists("database.xml")) + { + Database database = new Database(); + database.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, "database.xml")); + string databaseVersion = database.GetDatabaseVersion(); + this.WriteStatus("Database.xml detected."); + this.WriteStatus(" - Version: " + databaseVersion); + this.updateDatabaseToolStripMenuItem.Text = "Update Database"; + this.databaseButton.Text = " [ ]"; + this.databaseButton.Image = (Image) Resources.arrow_ticker; + this.databaseWorker.RunWorkerAsync(); + } + if (this.NUSDFileExists("dsidatabase.xml")) + { + Database database = new Database(); + database.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, "dsidatabase.xml")); + string databaseVersion = database.GetDatabaseVersion(); + this.WriteStatus("DSiDatabase.xml detected."); + this.WriteStatus(" - Version: " + databaseVersion); + this.updateDatabaseToolStripMenuItem.Text = "Update Database"; + this.databaseButton.Text = " [ ]"; + this.databaseButton.Image = (Image) Resources.arrow_ticker; + this.dsiDatabaseWorker.RunWorkerAsync(); + } + this.RunScriptOrganizer(); + if (!this.NUSDFileExists("proxy.txt")) + return; + this.WriteStatus("Proxy settings detected."); + string[] strArray = System.IO.File.ReadAllLines(Path.Combine(this.CURRENT_DIR, "proxy.txt")); + this.proxy_url = strArray[0]; + if (strArray.Length > 2) + { + this.proxy_usr = strArray[1]; + this.proxy_pwd = strArray[2]; + } + else + { + if (strArray.Length <= 1) + return; + this.proxy_usr = strArray[1]; + this.SetAllEnabled(false); + this.ProxyVerifyBox.Visible = true; + this.ProxyVerifyBox.Enabled = true; + this.ProxyPwdBox.Enabled = true; + this.SaveProxyBtn.Enabled = true; + this.ProxyVerifyBox.Select(); + } + } + } + + private void DoAllDatabaseyStuff(object sender, DoWorkEventArgs e) + { + BackgroundWorker worker = sender as BackgroundWorker; + this.ClearDatabaseStrip(); + this.FillDatabaseStrip(worker); + this.LoadRegionCodes(); + this.FillDatabaseScripts(); + this.ShowInnerToolTips(false); + } + + private void DoAllDatabaseyStuff_Completed(object sender, RunWorkerCompletedEventArgs e) + { + this.databaseButton.Text = "Database..."; + this.databaseButton.Image = (Image) null; + } + + private void DoAllDatabaseyStuff_ProgressChanged(object sender, ProgressChangedEventArgs e) + { + if (e.ProgressPercentage == 25) + this.databaseButton.Text = " [. ]"; + else if (e.ProgressPercentage == 50) + this.databaseButton.Text = " [.. ]"; + else if (e.ProgressPercentage == 75) + { + this.databaseButton.Text = " [... ]"; + } + else + { + if (e.ProgressPercentage != 100) + return; + this.databaseButton.Text = " [....]"; + } + } + + private void RunScriptOrganizer() => this.scriptsWorker.RunWorkerAsync(); + + private void SetAllEnabled(bool enabled) + { + for (int index = 0; index < this.Controls.Count; ++index) + { + try + { + this.Controls[index].Enabled = enabled; + } + catch + { + } + } + } + + private void extrasMenuButton_Click(object sender, EventArgs e) + { + this.extrasStrip.Text = "Showing"; + this.extrasStrip.Show((Control) this.Extrasbtn, 2, 2 + this.Extrasbtn.Height); + System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); + timer.Interval = 52; + timer.Tick += new EventHandler(this.contextmenusTimer_Tick); + timer.Start(); + } + + private void LoadTitleFromTMD() + { + OpenFileDialog openFileDialog = new OpenFileDialog(); + openFileDialog.Filter = "TMD Files|*tmd*"; + openFileDialog.Title = "Open TMD"; + if (openFileDialog.ShowDialog() == DialogResult.Cancel) + return; + TMD tmd = new TMD(); + tmd.LoadFile(openFileDialog.FileName); + this.WriteStatus(string.Format("TMD Loaded ({0} blocks)", (object) tmd.GetNandBlocks())); + this.titleidbox.Text = tmd.TitleID.ToString("X16"); + this.WriteStatus("Title ID: " + tmd.TitleID.ToString("X16")); + this.titleversion.Text = tmd.TitleVersion.ToString(); + this.WriteStatus("Version: " + (object) tmd.TitleVersion); + if (tmd.StartupIOS.ToString("X") != "0") + this.WriteStatus("Requires: IOS" + (object) int.Parse(tmd.StartupIOS.ToString("X").Substring(7, 2).ToString(), NumberStyles.HexNumber)); + this.WriteStatus("Content Count: " + (object) tmd.NumOfContents); + for (int index = 0; index < tmd.Contents.Length; ++index) + { + this.WriteStatus(string.Format(" Content {0}: {1} ({2} bytes)", (object) index, (object) tmd.Contents[index].ContentID.ToString("X8"), (object) tmd.Contents[index].Size.ToString())); + this.WriteStatus(string.Format(" - Index: {0}", (object) tmd.Contents[index].Index.ToString())); + this.WriteStatus(string.Format(" - Type: {0}", (object) tmd.Contents[index].Type.ToString())); + this.WriteStatus(string.Format(" - Hash: {0}...", (object) this.DisplayBytes(tmd.Contents[index].Hash, string.Empty).Substring(0, 8))); + } + this.WriteStatus("TMD information parsed!"); + } + + public void WriteStatus(string Update, Color writecolor) + { + if (this.statusbox.InvokeRequired) + { + this.Invoke((Delegate) new Form1.WriteStatusCallback(this.WriteStatus), (object) Update, (object) writecolor); + } + else + { + int textLength1 = this.statusbox.TextLength; + if (this.statusbox.Text == "") + this.statusbox.Text = Update; + else + this.statusbox.AppendText("\r\n" + Update); + int textLength2 = this.statusbox.TextLength; + this.statusbox.Select(textLength1, textLength2 - textLength1); + this.statusbox.SelectionColor = writecolor; + this.statusbox.SelectionStart = this.statusbox.TextLength; + this.statusbox.SelectionLength = 0; + this.statusbox.ScrollToCaret(); + Console.WriteLine(Update); + } + } + + public void WriteStatus(string Update) => this.WriteStatus(Update, this.normalcolor); + + private void ReadIDType(string ttlid) + { + if (ttlid.Substring(0, 8) == "00000001") + this.WriteStatus("ID Type: System Title. BE CAREFUL!", this.warningcolor); + else if (ttlid.Substring(0, 8) == "00010000" || ttlid.Substring(0, 8) == "00010004") + this.WriteStatus("ID Type: Disc-Based Game. Unlikely NUS Content!"); + else if (ttlid.Substring(0, 8) == "00010001") + this.WriteStatus("ID Type: Downloaded Channel. Possible NUS Content."); + else if (ttlid.Substring(0, 8) == "00010002") + this.WriteStatus("ID Type: System Channel. BE CAREFUL!", this.warningcolor); + else if (ttlid.Substring(0, 8) == "00010004") + this.WriteStatus("ID Type: Game Channel. Unlikely NUS Content!"); + else if (ttlid.Substring(0, 8) == "00010005") + this.WriteStatus("ID Type: Downloaded Game Content. Unlikely NUS Content!"); + else if (ttlid.Substring(0, 8) == "00010008") + this.WriteStatus("ID Type: 'Hidden' Channel. Unlikely NUS Content!"); + else + this.WriteStatus("ID Type: Unknown. Unlikely NUS Content!"); + } + + private void DownloadBtn_Click(object sender, EventArgs e) + { + if (this.titleidbox.Text == string.Empty) + this.WriteStatus("Please enter a Title ID!", this.errorcolor); + else if (!this.packbox.Checked && !this.decryptbox.Checked && !this.keepenccontents.Checked) + { + this.WriteStatus("Running with your current settings will produce no output!", this.errorcolor); + this.WriteStatus(" - To amend this, look below and check an output type.", this.errorcolor); + } + else + this.NUSDownloader.RunWorkerAsync(); + } + + private void SetTextThreadSafe(Control what, string setto) => this.SetPropertyThreadSafe((Component) what, (object) "Name", setto); + + private void SetPropertyThreadSafe(Component what, object setto, string property) + { + if (this.InvokeRequired) + { + Form1.SetPropertyThreadSafeCallback method = new Form1.SetPropertyThreadSafeCallback(this.SetPropertyThreadSafe); + try + { + this.Invoke((Delegate) method, (object) what, setto, (object) property); + } + catch (Exception ex) + { + } + } + else + what.GetType().GetProperty(property).SetValue((object) what, setto, (object[]) null); + } + + private void NUSDownloader_DoWork(object sender, DoWorkEventArgs e) + { + Control.CheckForIllegalCrossThreadCalls = false; + this.WriteStatus("Starting NUS Download. Please be patient!", this.infocolor); + this.SetEnableforDownload(false); + this.downloadstartbtn.Text = "Starting NUS Download!"; + WebClient wcReady = this.ConfigureWithProxy(new WebClient()); + NusClient nusClient = new NusClient(); + nusClient.ConfigureNusClient(wcReady); + nusClient.UseLocalFiles = this.localuse.Checked; + nusClient.ContinueWithoutTicket = true; + if (this.serverLbl.Text == "Wii") + nusClient.SetToWiiServer(); + else if (this.serverLbl.Text == "DSi") + nusClient.SetToDSiServer(); + nusClient.Debug += new EventHandler(this.nusClient_Debug); + nusClient.Progress += new EventHandler(this.nusClient_Progress); + StoreType[] storeTypeArray = new StoreType[3] + { + !this.packbox.Checked ? StoreType.Empty : StoreType.WAD, + !this.decryptbox.Checked ? StoreType.Empty : StoreType.DecryptedContent, + !this.keepenccontents.Checked ? StoreType.Empty : StoreType.EncryptedContent + }; + string wadName = !string.IsNullOrEmpty(this.WAD_Saveas_Filename) ? this.WAD_Saveas_Filename : this.wadnamebox.Text; + try + { + Console.Write(this.packbox.Checked); + nusClient.DownloadTitle(this.titleidbox.Text, this.titleversion.Text, Path.Combine(this.CURRENT_DIR, "titles"), this.pathbox.Checked, wadName, storeTypeArray); + } + catch (Exception ex) + { + this.WriteStatus("Download failed: \"" + ex.Message + " ):\"", this.errorcolor); + } + if (this.iosPatchCheckbox.Checked) + { + bool flag = false; + IosPatcher iosPatcher = new IosPatcher(); + WAD iosWad = new WAD(); + string str1 = wadName.Replace("[v]", nusClient.TitleVersion.ToString()); + if (str1.Contains(Path.DirectorySeparatorChar.ToString()) || str1.Contains(Path.AltDirectorySeparatorChar.ToString())) + iosWad.LoadFile(str1); + else + iosWad.LoadFile(Path.Combine(Path.Combine(Path.Combine(Path.Combine(this.CURRENT_DIR, "titles"), this.titleidbox.Text), nusClient.TitleVersion.ToString()), str1)); + try + { + iosPatcher.LoadIOS(ref iosWad); + } + catch (Exception ex) + { + this.WriteStatus("NUS Download Finished.", this.infocolor); + return; + } + foreach (object checkedItem in this.iosPatchesListBox.CheckedItems) + { + if (this.iosPatchesListBox.GetItemCheckState(this.iosPatchesListBox.Items.IndexOf(checkedItem)).ToString() == "Checked") + { + switch (checkedItem.ToString()) + { + case "Trucha bug": + int num1 = iosPatcher.PatchFakeSigning(); + if (num1 > 0) + { + this.WriteStatus(" - Patched in fake-signing:", this.infocolor); + string str2 = num1 <= 1 ? "" : "es"; + this.WriteStatus(string.Format(" {0} patch{1} applied.", (object) num1, (object) str2)); + flag = true; + continue; + } + this.WriteStatus(" - Could not patch fake-signing", this.errorcolor); + continue; + case "ES_Identify": + int num2 = iosPatcher.PatchEsIdentify(); + if (num2 > 0) + { + this.WriteStatus(" - Patched in ES_Identify:", this.infocolor); + string str3 = num2 <= 1 ? "" : "es"; + this.WriteStatus(string.Format(" {0} patch{1} applied.", (object) num2, (object) str3)); + flag = true; + continue; + } + this.WriteStatus(" - Could not patch ES_Identify", this.errorcolor); + continue; + case "NAND permissions": + int num3 = iosPatcher.PatchNandPermissions(); + if (num3 > 0) + { + this.WriteStatus(" - Patched in NAND permissions:", this.infocolor); + string str4 = num3 <= 1 ? "" : "es"; + this.WriteStatus(string.Format(" {0} patch{1} applied.", (object) num3, (object) str4)); + flag = true; + continue; + } + this.WriteStatus(" - Could not patch NAND permissions", this.errorcolor); + continue; + default: + continue; + } + } + } + if (flag) + { + string str5 = str1.Replace(".wad", ".patched.wad"); + try + { + if (str5.Contains(Path.DirectorySeparatorChar.ToString()) || str5.Contains(Path.AltDirectorySeparatorChar.ToString())) + iosWad.Save(str5); + else + iosWad.Save(Path.Combine(Path.Combine(Path.Combine(Path.Combine(this.CURRENT_DIR, "titles"), this.titleidbox.Text), nusClient.TitleVersion.ToString()), str5)); + this.WriteStatus(string.Format("Patched WAD saved as: {0}", (object) Path.GetFileName(str5)), this.infocolor); + } + catch (Exception ex) + { + this.WriteStatus(string.Format("Couldn't save patched WAD: \"{0}\" :(", (object) ex.Message), this.errorcolor); + } + } + } + this.WriteStatus("NUS Download Finished."); + } + + private void nusClient_Progress(object sender, ProgressChangedEventArgs e) => this.dlprogress.Value = e.ProgressPercentage; + + private void nusClient_Debug(object sender, MessageEventArgs e) => this.WriteStatus(e.Message); + + private void NUSDownloader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + { + this.WAD_Saveas_Filename = string.Empty; + this.SetEnableforDownload(true); + this.downloadstartbtn.Text = "Start NUS Download!"; + this.dlprogress.Value = 0; + if (!Form1.IsWin7()) + return; + this.dlprogress.ShowInTaskbar = false; + } + + private void packbox_CheckedChanged(object sender, EventArgs e) + { + if (this.packbox.Checked) + { + this.wadnamebox.Enabled = true; + this.saveaswadbtn.Enabled = true; + this.UpdatePackedName(); + } + else + { + this.wadnamebox.Enabled = false; + this.saveaswadbtn.Enabled = false; + this.wadnamebox.Text = string.Empty; + if (!this.iosPatchCheckbox.Checked) + return; + this.iosPatchCheckbox.Checked = false; + } + } + + private void titleidbox_TextChanged(object sender, EventArgs e) + { + this.UpdatePackedName(); + this.EnablePatchIOSBox(); + } + + private void titleversion_TextChanged(object sender, EventArgs e) => this.UpdatePackedName(); + + private void EnablePatchIOSBox() + { + this.iosPatchCheckbox.Enabled = this.TitleIsIOS(this.titleidbox.Text); + if (this.iosPatchCheckbox.Enabled) + return; + this.iosPatchCheckbox.Checked = false; + } + + private bool TitleIsIOS(string titleid) => titleid.Length == 16 && !(titleid == "0000000100000001") && !(titleid == "0000000100000002") && titleid.Substring(0, 14) == "00000001000000"; + + public string DisplayBytes(byte[] bytes, string spacer) + { + string str = ""; + for (int index = 0; index < bytes.Length; ++index) + str = str + bytes[index].ToString("X2") + spacer; + return str; + } + + private void DatabaseButton_Click(object sender, EventArgs e) + { + this.databaseStrip.Text = "Showing"; + this.databaseStrip.Show((Control) this.databaseButton, 2, 2 + this.databaseButton.Height); + System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); + timer.Interval = 50; + timer.Tick += new EventHandler(this.contextmenusTimer_Tick); + timer.Start(); + } + + private void contextmenusTimer_Tick(object sender, EventArgs e) + { + if (this.SystemMenuList.Pressed || this.IOSMenuList.Pressed || this.VCMenuList.Pressed || this.WiiWareMenuList.Pressed || this.RegionCodesList.Pressed || this.scriptsLocalMenuEntry.Pressed || this.scriptsDatabaseToolStripMenuItem.Pressed || this.emulateUpdate.Pressed) + return; + if (this.databaseButton.ClientRectangle.Contains(this.databaseButton.PointToClient(Control.MousePosition)) && ((System.Windows.Forms.Timer) sender).Interval != 50) + { + this.databaseStrip.Close(); + this.scriptsStrip.Close(); + this.extrasStrip.Close(); + this.DatabaseButton_Click(sender, EventArgs.Empty); + ((System.Windows.Forms.Timer) sender).Stop(); + } + if (this.scriptsbutton.ClientRectangle.Contains(this.scriptsbutton.PointToClient(Control.MousePosition)) && ((System.Windows.Forms.Timer) sender).Interval != 51) + { + this.databaseStrip.Close(); + this.scriptsStrip.Close(); + this.extrasStrip.Close(); + this.scriptsbutton_Click(sender, EventArgs.Empty); + ((System.Windows.Forms.Timer) sender).Stop(); + } + if (this.Extrasbtn.ClientRectangle.Contains(this.Extrasbtn.PointToClient(Control.MousePosition)) && ((System.Windows.Forms.Timer) sender).Interval != 52) + { + this.databaseStrip.Close(); + this.scriptsStrip.Close(); + this.extrasStrip.Close(); + this.extrasMenuButton_Click(sender, EventArgs.Empty); + ((System.Windows.Forms.Timer) sender).Stop(); + } + if (this.databaseStrip.Visible || this.extrasStrip.Visible || this.scriptsStrip.Visible) + return; + ((System.Windows.Forms.Timer) sender).Stop(); + } + + private void ClearDatabaseStrip() + { + Control.CheckForIllegalCrossThreadCalls = false; + object[] objArray = new object[17] + { + (object) this.SystemMenuList, + (object) this.IOSMenuList, + (object) this.WiiWareMenuList, + (object) this.VCMenuList, + (object) this.C64MenuList, + (object) this.NeoGeoMenuList, + (object) this.NESMenuList, + (object) this.SNESMenuList, + (object) this.N64MenuList, + (object) this.TurboGrafx16MenuList, + (object) this.TurboGrafxCDMenuList, + (object) this.MSXMenuList, + (object) this.SegaMSMenuList, + (object) this.GenesisMenuList, + (object) this.VCArcadeMenuList, + (object) this.dsiSystemToolStripMenu, + (object) this.dSiWareToolStripMenu + }; + foreach (ToolStripMenuItem toolStripMenuItem in objArray) + { + if (toolStripMenuItem.Name != "VCMenuList") + toolStripMenuItem.DropDownItems.Clear(); + } + } + + private void FillDatabaseStrip(BackgroundWorker worker) + { + this.SetPropertyThreadSafe((Component) this.SystemMenuList, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.IOSMenuList, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.VCMenuList, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.WiiWareMenuList, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.systemFakeMenuItem, (object) true, "Visible"); + this.SetPropertyThreadSafe((Component) this.iosFakeMenuItem, (object) true, "Visible"); + this.SetPropertyThreadSafe((Component) this.vcFakeMenuItem, (object) true, "Visible"); + this.SetPropertyThreadSafe((Component) this.wwFakeMenuItem, (object) true, "Visible"); + Database database = new Database(); + database.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, "database.xml")); + ToolStripMenuItem[] toolStripMenuItemArray1 = database.LoadSystemTitles(); + for (int index1 = 0; index1 < toolStripMenuItemArray1.Length; ++index1) + { + toolStripMenuItemArray1[index1].DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + for (int index2 = 0; index2 < toolStripMenuItemArray1[index1].DropDownItems.Count; ++index2) + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItemArray1[index1].DropDownItems[index2]; + if (dropDownItem.DropDownItems.Count > 0) + dropDownItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + } + } + Array.Sort(toolStripMenuItemArray1, (Comparison) ((tsmi1, tsmi2) => tsmi1.Text.Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)))); + this.AddToolStripItemToStrip(this.SystemMenuList, toolStripMenuItemArray1); + this.SetPropertyThreadSafe((Component) this.systemFakeMenuItem, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.SystemMenuList, (object) true, "Visible"); + worker.ReportProgress(25); + ToolStripMenuItem[] additionitems = database.LoadIosTitles(); + for (int index = 0; index < additionitems.Length; ++index) + additionitems[index].DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + this.AddToolStripItemToStrip(this.IOSMenuList, additionitems); + this.SetPropertyThreadSafe((Component) this.iosFakeMenuItem, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.IOSMenuList, (object) true, "Visible"); + worker.ReportProgress(50); + ToolStripMenuItem[][] toolStripMenuItemArray2 = database.LoadVirtualConsoleTitles(); + for (int index3 = 0; index3 < toolStripMenuItemArray2.Length; ++index3) + { + for (int index4 = 0; index4 < toolStripMenuItemArray2[index3].Length; ++index4) + { + toolStripMenuItemArray2[index3][index4].DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + for (int index5 = 0; index5 < toolStripMenuItemArray2[index3][index4].DropDownItems.Count; ++index5) + ((ToolStripDropDownItem) toolStripMenuItemArray2[index3][index4].DropDownItems[index5]).DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + } + Array.Sort(toolStripMenuItemArray2[index3], (Comparison) ((tsmi1, tsmi2) => tsmi1.Text.Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)))); + this.AddToolStripItemToStrip((ToolStripMenuItem) this.VCMenuList.DropDownItems[index3], toolStripMenuItemArray2[index3]); + } + this.SetPropertyThreadSafe((Component) this.vcFakeMenuItem, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.VCMenuList, (object) true, "Visible"); + worker.ReportProgress(75); + ToolStripMenuItem[] toolStripMenuItemArray3 = database.LoadWiiWareTitles(); + for (int index6 = 0; index6 < toolStripMenuItemArray3.Length; ++index6) + { + toolStripMenuItemArray3[index6].DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + for (int index7 = 0; index7 < toolStripMenuItemArray3[index6].DropDownItems.Count; ++index7) + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItemArray3[index6].DropDownItems[index7]; + if (dropDownItem.DropDownItems.Count > 0) + dropDownItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + } + } + Array.Sort(toolStripMenuItemArray3, (Comparison) ((tsmi1, tsmi2) => tsmi1.Text.Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)))); + this.AddToolStripItemToStrip(this.WiiWareMenuList, toolStripMenuItemArray3); + this.SetPropertyThreadSafe((Component) this.wwFakeMenuItem, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.WiiWareMenuList, (object) true, "Visible"); + worker.ReportProgress(100); + } + + private void FillDSiDatabaseStrip(BackgroundWorker worker) + { + this.SetPropertyThreadSafe((Component) this.dsiSystemToolStripMenu, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.dSiWareToolStripMenu, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.dsiFakeSystemToolStripMenu, (object) true, "Visible"); + this.SetPropertyThreadSafe((Component) this.dSiWareFakeToolStripMenu, (object) true, "Visible"); + Database database = new Database(); + database.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, "dsidatabase.xml")); + ToolStripMenuItem[] toolStripMenuItemArray1 = database.LoadDSiSystemTitles(); + for (int index1 = 0; index1 < toolStripMenuItemArray1.Length; ++index1) + { + toolStripMenuItemArray1[index1].DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + for (int index2 = 0; index2 < toolStripMenuItemArray1[index1].DropDownItems.Count; ++index2) + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItemArray1[index1].DropDownItems[index2]; + if (dropDownItem.DropDownItems.Count > 0) + dropDownItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + } + } + Array.Sort(toolStripMenuItemArray1, (Comparison) ((tsmi1, tsmi2) => tsmi1.Text.Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)))); + this.AddToolStripItemToStrip(this.dsiSystemToolStripMenu, toolStripMenuItemArray1); + this.SetPropertyThreadSafe((Component) this.dsiFakeSystemToolStripMenu, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.dsiSystemToolStripMenu, (object) true, "Visible"); + worker.ReportProgress(50); + ToolStripMenuItem[] toolStripMenuItemArray2 = database.LoadDsiWareTitles(); + for (int index3 = 0; index3 < toolStripMenuItemArray2.Length; ++index3) + { + toolStripMenuItemArray2[index3].DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + for (int index4 = 0; index4 < toolStripMenuItemArray2[index3].DropDownItems.Count; ++index4) + { + ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItemArray2[index3].DropDownItems[index4]; + if (dropDownItem.DropDownItems.Count > 0) + dropDownItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.DatabaseItem_Clicked); + } + } + Array.Sort(toolStripMenuItemArray2, (Comparison) ((tsmi1, tsmi2) => tsmi1.Text.Substring(18, tsmi1.Text.Length - 19).CompareTo(tsmi2.Text.Substring(18, tsmi2.Text.Length - 19)))); + this.AddToolStripItemToStrip(this.dSiWareToolStripMenu, toolStripMenuItemArray2); + this.SetPropertyThreadSafe((Component) this.dSiWareFakeToolStripMenu, (object) false, "Visible"); + this.SetPropertyThreadSafe((Component) this.dSiWareToolStripMenu, (object) true, "Visible"); + worker.ReportProgress(100); + } + + private void AddToolStripItemToStrip( + ToolStripMenuItem menulist, + ToolStripMenuItem[] additionitems) + { + if (this.InvokeRequired) + this.Invoke((Delegate) new Form1.AddToolStripItemToStripCallback(this.AddToolStripItemToStrip), (object) menulist, (object) additionitems); + else + menulist.DropDownItems.AddRange((ToolStripItem[]) additionitems); + } + + public string OfficialWADNaming(string titlename) + { + titlename = !(titlename == "MIOS") ? (!titlename.Contains("IOS") ? (!titlename.Contains("System Menu") ? (!titlename.Contains("System Menu") ? (!(titlename == "BC") ? (!titlename.Contains("Mii Channel") ? (!titlename.Contains("Shopping Channel") ? (!titlename.Contains("Weather Channel") ? titlename + "-NUS-[v].wad" : "RVL-Weather-[v].wad") : "RVL-Shopping-[v].wad") : "RVL-NigaoeNR-[v].wad") : "RVL-bc-[v].wad") : "RVL-WiiSystemmenu-[v].wad") : "RVL-WiiSystemmenu-[v].wad") : titlename + "-64-[v].wad") : "RVL-mios-[v].wad"; + if (this.wadnamebox.InvokeRequired) + { + this.wadnamebox.Invoke((Delegate) new Form1.OfficialWADNamingCallback(this.OfficialWADNaming), (object) titlename); + return titlename; + } + this.wadnamebox.Text = titlename; + if (this.titleversion.Text != "") + this.wadnamebox.Text = this.wadnamebox.Text.Replace("[v]", "v" + this.titleversion.Text); + return titlename; + } + + public void DatabaseItem_Clicked(object sender, ToolStripItemClickedEventArgs e) + { + Regex regex1 = new Regex("[0-9A-Z]*\\s-\\s.*"); + Regex regex2 = new Regex("[0-9A-Z][0-9A-Z] \\(.*\\)"); + Regex regex3 = new Regex("v[0-9]*.*"); + object[] objArray1 = new object[4] + { + (object) this.SystemMenuList, + (object) this.IOSMenuList, + (object) this.WiiWareMenuList, + (object) this.VCMenuList + }; + object[] objArray2 = new object[2] + { + (object) this.dsiSystemToolStripMenu, + (object) this.dSiWareToolStripMenu + }; + if (regex1.IsMatch(e.ClickedItem.Text)) + { + string[] strArray = e.ClickedItem.Text.Replace(" - ", "~").Split('~'); + this.titleidbox.Text = strArray[0]; + this.statusbox.Text = string.Format(" --- {0} ---", (object) strArray[1]); + this.titleversion.Text = string.Empty; + if (e.ClickedItem.Image == Database.orange || e.ClickedItem.Image == Database.redorange) + { + this.WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); + this.packbox.Checked = false; + this.decryptbox.Checked = false; + } + if (e.ClickedItem.Image == Database.redgreen || e.ClickedItem.Image == Database.redorange) + this.WriteStatus("\n" + e.ClickedItem.ToolTipText); + foreach (ToolStripItem toolStripItem in objArray1) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.Name) + this.serverLbl.Text = "Wii"; + } + foreach (ToolStripItem toolStripItem in objArray2) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.Name) + this.serverLbl.Text = "DSi"; + } + } + if (regex2.IsMatch(e.ClickedItem.Text)) + { + string[] strArray = e.ClickedItem.OwnerItem.Text.Replace(" - ", "~").Split('~'); + this.titleidbox.Text = strArray[0]; + this.statusbox.Text = string.Format(" --- {0} ---", (object) strArray[1]); + this.titleversion.Text = string.Empty; + this.titleidbox.Text = this.titleidbox.Text.Replace("XX", e.ClickedItem.Text.Substring(0, 2)); + if (e.ClickedItem.OwnerItem.Image == Database.orange || e.ClickedItem.OwnerItem.Image == Database.redorange) + { + this.WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); + this.packbox.Checked = false; + this.decryptbox.Checked = false; + } + if (e.ClickedItem.OwnerItem.Image == Database.redgreen || e.ClickedItem.OwnerItem.Image == Database.redorange) + this.WriteStatus("\n" + e.ClickedItem.OwnerItem.ToolTipText); + foreach (ToolStripItem toolStripItem in objArray1) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) + this.serverLbl.Text = "Wii"; + } + foreach (ToolStripItem toolStripItem in objArray2) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) + this.serverLbl.Text = "DSi"; + } + } + if (!regex3.IsMatch(e.ClickedItem.Text) && !(e.ClickedItem.Text == "Latest Version")) + return; + if (regex2.IsMatch(e.ClickedItem.OwnerItem.Text)) + { + string[] strArray = e.ClickedItem.OwnerItem.OwnerItem.Text.Replace(" - ", "~").Split('~'); + this.titleidbox.Text = strArray[0]; + this.statusbox.Text = string.Format(" --- {0} ---", (object) strArray[1]); + this.titleidbox.Text = this.titleidbox.Text.Replace("XX", e.ClickedItem.OwnerItem.Text.Substring(0, 2)); + } + else + { + string[] strArray = e.ClickedItem.OwnerItem.Text.Replace(" - ", "~").Split('~'); + this.titleidbox.Text = strArray[0]; + this.statusbox.Text = string.Format(" --- {0} ---", (object) strArray[1]); + } + if (e.ClickedItem.Text == "Latest Version") + this.titleversion.Text = string.Empty; + else + this.titleversion.Text = e.ClickedItem.Text.Replace("v", "").Split(' ')[0]; + if (regex2.IsMatch(e.ClickedItem.OwnerItem.Text)) + { + if (e.ClickedItem.OwnerItem.OwnerItem.Image == Database.orange || e.ClickedItem.OwnerItem.OwnerItem.Image == Database.redorange) + { + this.WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); + this.packbox.Checked = false; + this.decryptbox.Checked = false; + } + if (e.ClickedItem.OwnerItem.OwnerItem.Image == Database.redgreen || e.ClickedItem.OwnerItem.OwnerItem.Image == Database.redorange) + this.WriteStatus("\n" + e.ClickedItem.OwnerItem.OwnerItem.ToolTipText); + foreach (ToolStripItem toolStripItem in objArray1) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.OwnerItem.OwnerItem.Name) + this.serverLbl.Text = "Wii"; + } + foreach (ToolStripItem toolStripItem in objArray2) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.OwnerItem.OwnerItem.Name) + this.serverLbl.Text = "DSi"; + } + } + else + { + if (e.ClickedItem.OwnerItem.Image == Database.orange || e.ClickedItem.OwnerItem.Image == Database.redorange) + { + this.WriteStatus("Note: This title has no ticket and cannot be packed/decrypted!"); + this.packbox.Checked = false; + this.decryptbox.Checked = false; + } + if (e.ClickedItem.OwnerItem.Image == Database.redgreen || e.ClickedItem.OwnerItem.Image == Database.redorange) + this.WriteStatus("\n" + e.ClickedItem.OwnerItem.ToolTipText); + foreach (ToolStripItem toolStripItem in objArray1) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) + this.serverLbl.Text = "Wii"; + } + foreach (ToolStripItem toolStripItem in objArray2) + { + if (toolStripItem.Name == e.ClickedItem.OwnerItem.OwnerItem.Name) + this.serverLbl.Text = "DSi"; + } + } + } + + private string RegionFromIndex(int index, XmlDocument databasexml) + { + XmlNodeList childNodes = databasexml.GetElementsByTagName("REGIONS")[0].ChildNodes; + for (int i = 0; i < childNodes.Count; ++i) + { + if (Convert.ToInt32(childNodes[i].Attributes[0].Value) == index) + return childNodes[i].InnerText; + } + return "XX (Error)"; + } + + private void LoadRegionCodes() + { + if (this.InvokeRequired) + { + this.Invoke((Delegate) new Form1.BootChecksCallback(this.LoadRegionCodes)); + } + else + { + this.wiiRegionCodesMenu.DropDownItems.Clear(); + this.dsiRegionCodesMenu.DropDownItems.Clear(); + Database database1 = new Database(); + database1.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, "database.xml")); + foreach (ToolStripItem loadRegionCode in database1.LoadRegionCodes()) + this.wiiRegionCodesMenu.DropDownItems.Add(loadRegionCode.Text); + Database database2 = new Database(); + database2.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, "dsidatabase.xml")); + foreach (ToolStripItem loadRegionCode in database2.LoadRegionCodes()) + this.dsiRegionCodesMenu.DropDownItems.Add(loadRegionCode.Text); + } + } + + private static string RemoveIllegalCharacters(string databasestr) + { + foreach (char invalidFileNameChar in Path.GetInvalidFileNameChars()) + { + if (databasestr.Contains(invalidFileNameChar.ToString())) + databasestr = databasestr.Replace(invalidFileNameChar, '-'); + } + return databasestr; + } + + private void ClearStatusbox(object sender, EventArgs e) => this.statusbox.Text = ""; + + private void SetEnableforDownload(bool enabled) + { + if (this.InvokeRequired) + this.Invoke((Delegate) new Form1.SetEnableForDownloadCallback(this.SetEnableforDownload), (object) enabled); + else if (enabled) + { + this.downloadstartbtn.Enabled = this.disabledStorage[0]; + this.titleidbox.Enabled = this.disabledStorage[1]; + this.titleversion.Enabled = this.disabledStorage[2]; + this.Extrasbtn.Enabled = this.disabledStorage[3]; + this.databaseButton.Enabled = this.disabledStorage[4]; + this.packbox.Enabled = this.disabledStorage[5]; + this.localuse.Enabled = this.disabledStorage[6]; + this.saveaswadbtn.Enabled = this.disabledStorage[7]; + this.decryptbox.Enabled = this.disabledStorage[8]; + this.keepenccontents.Enabled = this.disabledStorage[9]; + this.scriptsbutton.Enabled = this.disabledStorage[10]; + this.serverLbl.Enabled = this.disabledStorage[11]; + this.iosPatchCheckbox.Enabled = this.disabledStorage[12]; + this.pathbox.Enabled = this.disabledStorage[13]; + } + else + { + this.disabledStorage[0] = this.downloadstartbtn.Enabled; + this.disabledStorage[1] = this.titleidbox.Enabled; + this.disabledStorage[2] = this.titleversion.Enabled; + this.disabledStorage[3] = this.Extrasbtn.Enabled; + this.disabledStorage[4] = this.databaseButton.Enabled; + this.disabledStorage[5] = this.packbox.Enabled; + this.disabledStorage[6] = this.localuse.Enabled; + this.disabledStorage[7] = this.saveaswadbtn.Enabled; + this.disabledStorage[8] = this.decryptbox.Enabled; + this.disabledStorage[9] = this.keepenccontents.Enabled; + this.disabledStorage[10] = this.scriptsbutton.Enabled; + this.disabledStorage[11] = this.serverLbl.Enabled; + this.disabledStorage[12] = this.iosPatchCheckbox.Enabled; + this.disabledStorage[13] = this.pathbox.Enabled; + this.downloadstartbtn.Enabled = enabled; + this.titleidbox.Enabled = enabled; + this.titleversion.Enabled = enabled; + this.Extrasbtn.Enabled = enabled; + this.databaseButton.Enabled = enabled; + this.packbox.Enabled = enabled; + this.localuse.Enabled = enabled; + this.saveaswadbtn.Enabled = enabled; + this.decryptbox.Enabled = enabled; + this.keepenccontents.Enabled = enabled; + this.scriptsbutton.Enabled = enabled; + this.serverLbl.Enabled = enabled; + this.iosPatchCheckbox.Enabled = enabled; + this.pathbox.Enabled = enabled; + } + } + + private void ShowInnerToolTips(bool enabled) + { + foreach (ToolStripItem toolStripItem in (ArrangedElementCollection) this.databaseStrip.Items) + { + try + { + ((ToolStripDropDownItem) toolStripItem).DropDown.ShowItemToolTips = false; + } + catch (Exception ex) + { + } + } + foreach (ToolStripItem toolStripItem in (ArrangedElementCollection) this.scriptsStrip.Items) + { + try + { + ((ToolStripDropDownItem) toolStripItem).DropDown.ShowItemToolTips = false; + } + catch (Exception ex) + { + } + } + } + + private void UpdatePackedName() + { + string str = (string) null; + if (this.titleidbox.Enabled && this.packbox.Checked) + { + if (this.titleversion.Text != "") + this.wadnamebox.Text = this.titleidbox.Text + "-NUS-v" + this.titleversion.Text + ".wad"; + else + this.wadnamebox.Text = this.titleidbox.Text + "-NUS-[v]" + this.titleversion.Text + ".wad"; + if (System.IO.File.Exists("database.xml") && this.titleidbox.Text.Length == 16) + str = this.NameFromDatabase(this.titleidbox.Text); + if (str != null) + { + this.wadnamebox.Text = this.wadnamebox.Text.Replace(this.titleidbox.Text, str); + this.OfficialWADNaming(str); + } + } + this.wadnamebox.Text = Form1.RemoveIllegalCharacters(this.wadnamebox.Text); + } + + private static bool IsWin7() => Environment.OSVersion.VersionString.Contains("6.1"); + + private byte[] NewIntegertoByteArray(int theInt, int arrayLen) + { + byte[] numArray = new byte[arrayLen]; + for (int index = arrayLen - 1; index >= 0; --index) + numArray[index] = (byte) (theInt >> 8 * index & (int) byte.MaxValue); + Array.Reverse((Array) numArray); + if (arrayLen > 4) + { + for (int index = 0; index < arrayLen - 4; ++index) + numArray[index] = (byte) 0; + } + return numArray; + } + + private WebClient ConfigureWithProxy(WebClient client) + { + if (!string.IsNullOrEmpty(this.proxy_url)) + { + WebProxy webProxy = new WebProxy(); + webProxy.Address = new Uri(this.proxy_url); + if (string.IsNullOrEmpty(this.proxy_usr)) + { + webProxy.UseDefaultCredentials = true; + } + else + { + NetworkCredential networkCredential = new NetworkCredential(); + networkCredential.UserName = this.proxy_usr; + if (!string.IsNullOrEmpty(this.proxy_pwd)) + networkCredential.Password = this.proxy_pwd; + webProxy.Credentials = (ICredentials) networkCredential; + } + client.Proxy = (IWebProxy) webProxy; + this.WriteStatus(" - Custom proxy settings applied!"); + } + else + { + try + { + client.Proxy = WebRequest.GetSystemWebProxy(); + client.UseDefaultCredentials = true; + } + catch (NotImplementedException ex) + { + this.WriteStatus("This operating system does not support automatic system proxy usage. Operating without a proxy..."); + } + } + return client; + } + + private void RetrieveNewDatabase(object sender, DoWorkEventArgs e) + { + string str1 = Regex.Replace(new WebClient().DownloadString(e.Argument.ToString() + "?cachesmash=" + DateTime.Now.ToString()), "<(.|\\n)*?>", ""); + string str2 = "<database v"; + string str3 = "</database>"; + string str4 = str1.Substring(str1.IndexOf(str2), str1.Length - str1.IndexOf(str2)); + string str5 = str4.Substring(0, str4.IndexOf(str3) + str3.Length).Replace("<", "<").Replace(">", ">").Replace(""", '"'.ToString()).Replace(" ", " "); + e.Result = (object) str5; + } + + private void RetrieveNewDatabase_Completed(object sender, RunWorkerCompletedEventArgs e) + { + string str1 = e.Result.ToString(); + string str2 = ""; + if (str1.Contains("DSISYSTEM")) + str2 = "dsidatabase.xml"; + else if (str1.Contains("0000000100000002")) + str2 = "database.xml"; + try + { + Database database = new Database(); + database.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, str2)); + string databaseVersion1 = database.GetDatabaseVersion(); + string databaseVersion2 = Database.GetDatabaseVersion(str1); + this.WriteStatus(string.Format(" - Database successfully parsed! ({0})", (object) str2)); + this.WriteStatus(" - Current Database Version: " + databaseVersion1); + this.WriteStatus(" - Online Database Version: " + databaseVersion2); + if (databaseVersion1 == databaseVersion2) + { + this.WriteStatus(" - You have the latest database version!"); + return; + } + } + catch (FileNotFoundException ex) + { + this.WriteStatus(" - Database does not yet exist."); + this.WriteStatus(" - Online Database Version: " + Database.GetDatabaseVersion(str1)); + } + bool flag = false; + if (System.IO.File.Exists(str2)) + { + this.WriteStatus(" - Overwriting your current database..."); + this.WriteStatus(string.Format(" - The old database will become 'old{0}' in case the new one is faulty.", (object) str2)); + string contents = System.IO.File.ReadAllText(str2); + System.IO.File.WriteAllText("old" + str2, contents); + System.IO.File.Delete(str2); + System.IO.File.WriteAllText(str2, str1); + } + else + { + this.WriteStatus(string.Format(" - {0} has been created.", (object) str2)); + System.IO.File.WriteAllText(str2, str1); + flag = true; + } + this.databaseWorker.RunWorkerAsync(); + if (flag) + { + this.WriteStatus("Database successfully created!"); + this.databaseButton.Visible = true; + this.updateDatabaseToolStripMenuItem.Text = "Download Database"; + } + else + this.WriteStatus("Database successfully updated!"); + } + + private void updateDatabaseToolStripMenuItem_Click(object sender, EventArgs e) + { + this.statusbox.Text = ""; + this.WriteStatus("Updating your databases from Wiibrew/DSibrew"); + string[] strArray = new string[2] + { + "http://www.wiibrew.org/wiki/NUS_Downloader/database", + "http://www.dsibrew.org/wiki/NUS_Downloader/database" + }; + BackgroundWorker backgroundWorker1 = new BackgroundWorker(); + backgroundWorker1.DoWork += new DoWorkEventHandler(this.RetrieveNewDatabase); + backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.RetrieveNewDatabase_Completed); + backgroundWorker1.RunWorkerAsync((object) strArray[0]); + BackgroundWorker backgroundWorker2 = new BackgroundWorker(); + backgroundWorker2.DoWork += new DoWorkEventHandler(this.RetrieveNewDatabase); + backgroundWorker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.RetrieveNewDatabase_Completed); + backgroundWorker2.RunWorkerAsync((object) strArray[1]); + } + + private void loadInfoFromTMDToolStripMenuItem_Click(object sender, EventArgs e) => this.LoadTitleFromTMD(); + + public string SendSOAPRequest(string soap_xml) + { + HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create("http://nus.shop.wii.com/nus/services/NetUpdateSOAP"); + httpWebRequest.Method = "POST"; + httpWebRequest.UserAgent = "wii libnup/1.0"; + httpWebRequest.Headers.Add("SOAPAction", '"'.ToString() + "urn:nus.wsapi.broadon.com/GetSystemUpdate" + (object) '"'); + if (!string.IsNullOrEmpty(this.proxy_url)) + { + WebProxy webProxy = new WebProxy(); + webProxy.Address = new Uri(this.proxy_url); + if (string.IsNullOrEmpty(this.proxy_usr)) + { + webProxy.UseDefaultCredentials = true; + } + else + { + NetworkCredential networkCredential = new NetworkCredential(); + networkCredential.UserName = this.proxy_usr; + if (!string.IsNullOrEmpty(this.proxy_pwd)) + networkCredential.Password = this.proxy_pwd; + webProxy.Credentials = (ICredentials) networkCredential; + } + httpWebRequest.Proxy = (IWebProxy) webProxy; + this.WriteStatus(" - Custom proxy settings applied!"); + } + else + { + httpWebRequest.Proxy = WebRequest.GetSystemWebProxy(); + httpWebRequest.UseDefaultCredentials = true; + } + byte[] bytes = new UTF8Encoding().GetBytes(soap_xml); + httpWebRequest.ContentType = "text/xml; charset=utf-8"; + httpWebRequest.ContentLength = (long) bytes.Length; + Stream requestStream = httpWebRequest.GetRequestStream(); + requestStream.Write(bytes, 0, bytes.Length); + requestStream.Close(); + Application.DoEvents(); + try + { + string end; + using (Stream responseStream = httpWebRequest.GetResponse().GetResponseStream()) + { + using (StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8)) + end = streamReader.ReadToEnd(); + } + httpWebRequest.Abort(); + Application.DoEvents(); + return end; + } + catch (Exception ex) + { + httpWebRequest.Abort(); + this.WriteStatus(" --- An Error Occurred: " + ex.Message.ToString()); + return (string) null; + } + } + + private void emulateUpdate_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) + { + this.statusbox.Text = ""; + this.WriteStatus("Starting Wii System Update..."); + this.scriptsStrip.Close(); + string str1 = "4362227770"; + string str2 = "13198105123219038"; + string str3 = "1"; + string str4 = e.ClickedItem.Text.Substring(0, 3); + if (str4 == "JAP") + str4 = "JPN"; + string str5 = str4.Substring(0, 2); + string soap_xml = "\n\n\n\n1.0\n" + str2 + "\n" + str1 + "\n" + str4 + "\n" + str5 + "\n\n0000000100000001\n2\n\n\n0000000100000002\n33\n\n\n0000000100000009\n516\n\n" + str3 + "\n\n\n\n"; + this.WriteStatus(" - Sending SOAP Request to NUS..."); + this.WriteStatus(" - Region: " + str4); + string xml = this.SendSOAPRequest(soap_xml); + if (xml != null) + { + this.WriteStatus(" - Recieved Update Info!"); + this.WriteStatus(" - Title information:"); + string contents = ""; + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(xml); + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName("TitleVersion"); + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + string titleid = ""; + string str6 = ""; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "TitleId": + titleid = childNodes[i2].InnerText; + break; + case "Version": + str6 = childNodes[i2].InnerText; + break; + } + } + this.WriteStatus(string.Format(" - {0} [v{1}]", (object) titleid, (object) str6)); + if (this.NUSDFileExists("database.xml") && !string.IsNullOrEmpty(this.NameFromDatabase(titleid))) + this.WriteStatus(string.Format(" [{0}]", (object) this.NameFromDatabase(titleid))); + contents += string.Format("{0} {1}\n", (object) titleid, (object) this.DisplayBytes(this.NewIntegertoByteArray(Convert.ToInt32(str6), 2), "")); + } + this.WriteStatus(" - Outputting results to NUS script..."); + if (!Directory.Exists(Path.Combine(this.CURRENT_DIR, "scripts"))) + { + Directory.CreateDirectory(Path.Combine(this.CURRENT_DIR, "scripts")); + this.WriteStatus(" - Created 'scripts' directory."); + } + string str7 = Form1.RemoveIllegalCharacters(DateTime.Now.ToShortTimeString()); + System.IO.File.WriteAllText(string.Format(Path.Combine(this.CURRENT_DIR, Path.Combine("scripts", "{0}_Update_{1}_{2}_{3} at {4}.nus")), (object) str4, (object) DateTime.Now.Month, (object) DateTime.Now.Day, (object) DateTime.Now.Year, (object) str7), contents); + this.WriteStatus(" - Script written!"); + this.scriptsLocalMenuEntry.Enabled = false; + this.scriptsWorker.RunWorkerAsync(); + this.WriteStatus(" - Run this script if you feel like downloading the update!"); + } + else + this.WriteStatus(" - Fail."); + } + + private string NameFromDatabase(string titleid) + { + if (titleid == "0000000100000101") + return "MIOS"; + if (titleid == "0000000100000100") + return "BC"; + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load("database.xml"); + string[] strArray = new string[4] + { + "SYS", + "IOS", + "VC", + "WW" + }; + foreach (string name in strArray) + { + XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(name); + for (int i1 = 0; i1 < elementsByTagName.Count; ++i1) + { + bool flag = false; + XmlNodeList childNodes = elementsByTagName[i1].ChildNodes; + for (int i2 = 0; i2 < childNodes.Count; ++i2) + { + switch (childNodes[i2].Name) + { + case "titleID": + flag = childNodes[i2].InnerText == titleid || childNodes[i2].InnerText.Substring(0, 14) + "XX" == titleid.Substring(0, 14) + "XX" && titleid.Substring(0, 14) != "00000001000000"; + break; + } + } + if (flag) + { + for (int i3 = 0; i3 < childNodes.Count; ++i3) + { + switch (childNodes[i3].Name) + { + case "name": + return childNodes[i3].InnerText; + default: + continue; + } + } + } + } + } + return (string) null; + } + + private void packbox_EnabledChanged(object sender, EventArgs e) => this.saveaswadbtn.Enabled = this.packbox.Enabled; + + private void SaveProxyBtn_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(this.ProxyURL.Text) && string.IsNullOrEmpty(this.ProxyUser.Text) && System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "proxy.txt"))) + { + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "proxy.txt")); + this.proxyBox.Visible = false; + this.proxy_usr = ""; + this.proxy_url = ""; + this.proxy_pwd = ""; + this.WriteStatus("Proxy settings deleted!"); + } + else if (string.IsNullOrEmpty(this.ProxyURL.Text) && string.IsNullOrEmpty(this.ProxyUser.Text) && !System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "proxy.txt"))) + { + this.proxyBox.Visible = false; + this.WriteStatus("No proxy settings saved!"); + } + else + { + string contents = ""; + if (!string.IsNullOrEmpty(this.ProxyURL.Text)) + { + contents = contents + this.ProxyURL.Text + "\n"; + this.proxy_url = this.ProxyURL.Text; + } + if (!string.IsNullOrEmpty(this.ProxyUser.Text)) + { + contents += this.ProxyUser.Text; + this.proxy_usr = this.ProxyUser.Text; + } + if (!string.IsNullOrEmpty(contents)) + { + System.IO.File.WriteAllText(Path.Combine(this.CURRENT_DIR, "proxy.txt"), contents); + this.WriteStatus("Proxy settings saved!"); + } + this.proxyBox.Visible = false; + this.SetAllEnabled(false); + this.ProxyVerifyBox.Visible = true; + this.ProxyVerifyBox.Enabled = true; + this.ProxyPwdBox.Enabled = true; + this.SaveProxyBtn.Enabled = true; + this.ProxyVerifyBox.Select(); + } + } + + private void proxySettingsToolStripMenuItem_Click(object sender, EventArgs e) + { + if (System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "proxy.txt"))) + { + string[] strArray = System.IO.File.ReadAllLines(Path.Combine(this.CURRENT_DIR, "proxy.txt")); + this.ProxyURL.Text = strArray[0]; + if (strArray.Length > 1) + this.ProxyUser.Text = strArray[1]; + } + this.proxyBox.Visible = true; + } + + private void SaveProxyPwdButton_Click(object sender, EventArgs e) + { + this.proxy_pwd = this.ProxyPwdBox.Text; + this.ProxyVerifyBox.Visible = false; + this.SetAllEnabled(true); + } + + private void ProxyPwdBox_KeyPress(object sender, KeyPressEventArgs e) + { + if ((int) e.KeyChar != (int) Convert.ToChar((object) Keys.Return)) + return; + this.SaveProxyPwdButton_Click((object) "LOLWUT", EventArgs.Empty); + } + + private void ProxyAssistBtn_Click(object sender, EventArgs e) + { + int num = (int) 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) + { + OpenFileDialog openFileDialog = new OpenFileDialog(); + openFileDialog.Multiselect = false; + openFileDialog.Filter = "NUS Scripts|*.nus|All Files|*.*"; + if (Directory.Exists(Path.Combine(this.CURRENT_DIR, "scripts"))) + openFileDialog.InitialDirectory = Path.Combine(this.CURRENT_DIR, "scripts"); + openFileDialog.Title = "Load a NUS/Wiimpersonator script."; + if (openFileDialog.ShowDialog() == DialogResult.Cancel) + return; + string str1 = System.IO.File.ReadAllText(openFileDialog.FileName); + FileInfo fileInfo = new FileInfo(openFileDialog.FileName); + string str2 = str1 + string.Format(";{0}", (object) fileInfo.Name.Replace("." + fileInfo.Extension, "")); + BackgroundWorker backgroundWorker = new BackgroundWorker(); + backgroundWorker.DoWork += new DoWorkEventHandler(this.RunScriptBg); + backgroundWorker.RunWorkerAsync((object) str2); + } + + private void RunScriptBg(object sender, DoWorkEventArgs e) + { + char ch = ';'; + string[] strArray = e.Argument.ToString().Split(ch); + if (strArray.Length < 2) + this.RunScript(strArray[0], "random"); + else + this.RunScript(strArray[0], Form1.RemoveIllegalCharacters(strArray[1])); + } + + private void scriptsbutton_Click(object sender, EventArgs e) + { + this.scriptsStrip.Text = "Showing"; + this.scriptsStrip.Show((Control) this.scriptsbutton, 2, 2 + this.scriptsbutton.Height); + System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); + timer.Interval = 51; + timer.Tick += new EventHandler(this.contextmenusTimer_Tick); + timer.Start(); + } + + private void DatabaseEnabled(bool enabled) + { + for (int index = 0; index < this.databaseStrip.Items.Count; ++index) + { + this.databaseStrip.Items[index].Enabled = enabled; + this.databaseStrip.Items[index].Visible = enabled; + } + for (int index = 0; index < this.VCMenuList.DropDownItems.Count; ++index) + { + this.VCMenuList.DropDownItems[index].Enabled = true; + this.VCMenuList.DropDownItems[index].Visible = true; + } + } + + private void scriptsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) => this.scriptsLocalMenuEntry.Enabled = true; + + private void OrganizeScripts(object sender, DoWorkEventArgs e) + { + if (!Directory.Exists(Path.Combine(this.CURRENT_DIR, "scripts"))) + { + this.WriteStatus("Scripts directory not found..."); + this.WriteStatus("- Creating it."); + Directory.CreateDirectory(Path.Combine(this.CURRENT_DIR, "scripts")); + } + if (this.scriptsLocalMenuEntry.DropDownItems.Count > 0) + { + Control.CheckForIllegalCrossThreadCalls = false; + this.scriptsLocalMenuEntry.DropDownItems.Clear(); + } + foreach (string directory in Directory.GetDirectories(Path.Combine(this.CURRENT_DIR, "scripts"), "*", SearchOption.TopDirectoryOnly)) + { + if (Directory.GetFiles(directory, "*.nus", SearchOption.TopDirectoryOnly).Length > 0) + { + DirectoryInfo directoryInfo = new DirectoryInfo(directory); + ToolStripMenuItem toolStripMenuItem1 = new ToolStripMenuItem(); + toolStripMenuItem1.Text = directoryInfo.Name + (object) Path.DirectorySeparatorChar; + toolStripMenuItem1.Image = (Image) Resources.folder_table; + foreach (string file in Directory.GetFiles(directory, "*.nus", SearchOption.TopDirectoryOnly)) + { + FileInfo fileInfo = new FileInfo(file); + ToolStripMenuItem toolStripMenuItem2 = new ToolStripMenuItem(); + toolStripMenuItem2.Text = fileInfo.Name; + toolStripMenuItem2.Image = (Image) Resources.script_start; + toolStripMenuItem1.DropDownItems.Add((ToolStripItem) toolStripMenuItem2); + toolStripMenuItem2.Click += new EventHandler(this.nus_script_item_Click); + } + this.scriptsLocalMenuEntry.DropDownItems.Add((ToolStripItem) toolStripMenuItem1); + } + } + foreach (string file in Directory.GetFiles(Path.Combine(this.CURRENT_DIR, "scripts"), "*.nus", SearchOption.TopDirectoryOnly)) + { + FileInfo fileInfo = new FileInfo(file); + ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(); + toolStripMenuItem.Text = fileInfo.Name; + toolStripMenuItem.Image = (Image) Resources.script_start; + this.scriptsLocalMenuEntry.DropDownItems.Add((ToolStripItem) toolStripMenuItem); + toolStripMenuItem.Click += new EventHandler(this.nus_script_item_Click); + } + } + + private void aboutNUSDToolStripMenuItem_Click(object sender, EventArgs e) + { + this.statusbox.Text = ""; + this.WriteStatus("NUS Downloader (NUSD)"); + this.WriteStatus("You are running version: " + this.version); + if (this.version.StartsWith("SVN")) + this.WriteStatus("SVN BUILD: DO NOT REPORT BROKEN FEATURES!"); + this.WriteStatus("This application created by WB3000"); + this.WriteStatus("Various contributions by lukegb"); + this.WriteStatus(string.Empty); + if (this.NUSDFileExists("key.bin")) + this.WriteStatus("Wii Decryption: Local (key.bin)"); + if (this.NUSDFileExists("kkey.bin")) + this.WriteStatus("Wii Korea Decryption: Local (kkey.bin)"); + if (this.NUSDFileExists("dsikey.bin")) + this.WriteStatus("DSi Decryption: Local (dsikey.bin)"); + if (!this.NUSDFileExists("database.xml")) + this.WriteStatus("Database (Wii): Need (database.xml)"); + else + this.WriteStatus("Database (Wii): OK"); + if (!this.NUSDFileExists("dsidatabase.xml")) + this.WriteStatus("Database (DSi): Need (dsidatabase.xml)"); + else + this.WriteStatus("Database (DSi): OK"); + if (Form1.IsWin7()) + this.WriteStatus("Windows 7 Features: Enabled"); + this.WriteStatus(""); + this.WriteStatus("Special thanks to:"); + this.WriteStatus(" * Crediar for his wadmaker tool + source, and for the advice!"); + this.WriteStatus(" * Leathl for libWiiSharp."); + this.WriteStatus(" * SquidMan/Galaxy/comex/Xuzz/#WiiDev for advice."); + this.WriteStatus(" * Pasta for impressive database contributions."); + this.WriteStatus(" * Napo7 for testing proxy settings."); + this.WriteStatus(" * Wyatt O'Day for the Windows7ProgressBar Control."); + this.WriteStatus(" * Famfamfam for the Silk Icon Set."); + this.WriteStatus(" * Anyone who has helped beta test!"); + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) => this.SaveProxyPwdPermanentBtn.Enabled = this.checkBox1.Checked; + + private void SaveProxyPwdPermanentBtn_Click(object sender, EventArgs e) + { + this.proxy_pwd = this.ProxyPwdBox.Text; + string contents = System.IO.File.ReadAllText(Path.Combine(this.CURRENT_DIR, "proxy.txt")) + string.Format("\n{0}", (object) this.proxy_pwd); + System.IO.File.WriteAllText(Path.Combine(this.CURRENT_DIR, "proxy.txt"), contents); + this.ProxyVerifyBox.Visible = false; + this.SetAllEnabled(true); + this.WriteStatus("To delete all traces of proxy settings, delete the proxy.txt file!"); + } + + private void clearButton_MouseEnter(object sender, EventArgs e) => this.clearButton.Text = "Clear"; + + private void clearButton_MouseLeave(object sender, EventArgs e) + { + if (System.Type.GetType("Mono.Runtime") != null) + return; + this.clearButton.Text = string.Empty; + } + + private void saveaswadbtn_MouseEnter(object sender, EventArgs e) => this.saveaswadbtn.Text = "Save As"; + + private void saveaswadbtn_MouseLeave(object sender, EventArgs e) + { + if (System.Type.GetType("Mono.Runtime") != null) + return; + this.saveaswadbtn.Text = string.Empty; + } + + private void nus_script_item_Click(object sender, EventArgs e) + { + ToolStripMenuItem toolStripMenuItem = (ToolStripMenuItem) sender; + string str1 = ""; + if (!toolStripMenuItem.OwnerItem.Equals((object) this.scriptsLocalMenuEntry)) + str1 = Path.Combine(toolStripMenuItem.OwnerItem.Text, str1); + string str2 = System.IO.File.ReadAllText(Path.Combine(this.CURRENT_DIR, Path.Combine("scripts", Path.Combine(str1, toolStripMenuItem.Text)))) + string.Format(";{0}", (object) toolStripMenuItem.Text.Replace(".nus", "")); + BackgroundWorker backgroundWorker = new BackgroundWorker(); + backgroundWorker.DoWork += new DoWorkEventHandler(this.RunScriptBg); + backgroundWorker.RunWorkerAsync((object) str2); + } + + private void saveaswadbtn_Click(object sender, EventArgs e) + { + SaveFileDialog saveFileDialog = new SaveFileDialog(); + saveFileDialog.Title = "Save WAD File..."; + saveFileDialog.Filter = "WAD Files|*.wad|All Files|*.*"; + saveFileDialog.AddExtension = true; + if (saveFileDialog.ShowDialog() == DialogResult.Cancel) + return; + this.WAD_Saveas_Filename = saveFileDialog.FileName; + } + + private void Form1_FormClosing(object sender, FormClosingEventArgs e) => Environment.Exit(0); + + private void iosPatchCheckbox_CheckedChanged(object sender, EventArgs e) + { + if (!this.iosPatchCheckbox.Checked) + return; + this.packbox.Checked = true; + this.SetAllEnabled(false); + this.iosPatchGroupBox.Visible = true; + this.iosPatchGroupBox.Enabled = true; + this.iosPatchesListBox.Enabled = true; + this.iosPatchGroupBoxOKbtn.Enabled = true; + } + + private void iosPatchGroupBoxOKbtn_Click(object sender, EventArgs e) + { + this.SetAllEnabled(true); + this.iosPatchGroupBox.Visible = false; + if (this.iosPatchesListBox.CheckedIndices.Count != 0) + return; + this.iosPatchCheckbox.Checked = false; + } + + private void FillDatabaseScripts() + { + this.SetPropertyThreadSafe((Component) this.scriptsDatabaseToolStripMenuItem, (object) false, "Visible"); + Database database = new Database(); + database.LoadDatabaseToStream(Path.Combine(this.CURRENT_DIR, "database.xml")); + ToolStripMenuItem[] additionitems = database.LoadScripts(); + for (int index = 0; index < additionitems.Length; ++index) + additionitems[index].Click += new EventHandler(this.ScriptItem_Clicked); + this.AddToolStripItemToStrip(this.scriptsDatabaseToolStripMenuItem, additionitems); + this.SetPropertyThreadSafe((Component) this.scriptsDatabaseToolStripMenuItem, (object) true, "Enabled"); + this.SetPropertyThreadSafe((Component) this.scriptsDatabaseToolStripMenuItem, (object) true, "Visible"); + } + + public void ScriptItem_Clicked(object sender, EventArgs e) + { + ToolStripMenuItem toolStripMenuItem = (ToolStripMenuItem) sender; + string str = toolStripMenuItem.ToolTipText + string.Format(";{0}", (object) toolStripMenuItem.Text); + BackgroundWorker backgroundWorker = new BackgroundWorker(); + backgroundWorker.DoWork += new DoWorkEventHandler(this.RunScriptBg); + backgroundWorker.RunWorkerAsync((object) str); + } + + private void ReorganizePreviousFolderStructure(object sender, DoWorkEventArgs e) + { + Regex regex = new Regex("[a-zA-Z0-9]{16}v?([0-9]*)?"); + if (!Directory.Exists(Path.Combine(this.CURRENT_DIR, "titles"))) + Directory.CreateDirectory(Path.Combine(this.CURRENT_DIR, "titles")); + foreach (string directory in Directory.GetDirectories(this.CURRENT_DIR, "*", SearchOption.TopDirectoryOnly)) + { + DirectoryInfo directoryInfo = new DirectoryInfo(directory); + if (regex.IsMatch(directoryInfo.Name.ToString()) && directoryInfo.Name.Contains("v")) + { + string[] strArray = directoryInfo.Name.Split('v'); + this.WriteStatus("Bitte einen Text eingeben: "); + string str1 = Path.Combine(Path.Combine(this.CURRENT_DIR, "titles"), strArray[0]); + string str2 = Path.Combine(str1, string.Format("{0}", (object) strArray[1])); + if (!Directory.Exists(str1)) + Directory.CreateDirectory(str1); + if (!Directory.Exists(str2)) + Directory.CreateDirectory(str2); + foreach (string file in Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly)) + { + FileInfo fileInfo = new FileInfo(file); + if (!System.IO.File.Exists(Path.Combine(str2, fileInfo.Name))) + fileInfo.MoveTo(Path.Combine(str2, fileInfo.Name)); + } + if (directoryInfo.GetFiles().Length <= 0 && directoryInfo.GetDirectories().Length <= 0) + Directory.Delete(directory); + } + else if (regex.IsMatch(directoryInfo.Name.ToString())) + { + string str3 = Path.Combine(Path.Combine(this.CURRENT_DIR, "titles"), directoryInfo.Name.ToString()); + TMD tmd = new TMD(); + int num = 0; + string[] files = Directory.GetFiles(directory, "*tmd*", SearchOption.TopDirectoryOnly); + if (files.Length <= 1) + { + foreach (string pathToTmd in files) + { + if (pathToTmd.Contains("tmd")) + { + tmd.LoadFile(pathToTmd); + ++num; + } + } + if (num != 0) + { + string str4 = tmd.TitleVersion.ToString(); + string str5 = Path.Combine(str3, string.Format("{0}", (object) str4)); + if (!Directory.Exists(str3)) + Directory.CreateDirectory(str3); + if (!Directory.Exists(str5)) + Directory.CreateDirectory(str5); + foreach (string file in Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly)) + { + FileInfo fileInfo = new FileInfo(file); + if (!System.IO.File.Exists(Path.Combine(str5, fileInfo.Name))) + fileInfo.MoveTo(Path.Combine(str5, fileInfo.Name)); + } + if (directoryInfo.GetFiles().Length <= 0 && directoryInfo.GetDirectories().Length <= 0) + Directory.Delete(directory); + } + } + } + } + } + + private void ReorganizePreviousFolderStructure_Completed( + object sender, + RunWorkerCompletedEventArgs e) + { + this.WriteStatus(" - Operation complete!"); + } + + private void RunScript(string scriptstr, string scriptname) + { + this.SetTextThreadSafe((Control) this.statusbox, ""); + this.WriteStatus("Starting script download. Please be patient!"); + string str = !(scriptname == "random") ? Path.Combine(Path.Combine(this.CURRENT_DIR, "scripts"), scriptname + "_output") : Path.Combine(Path.Combine(this.CURRENT_DIR, "scripts"), this.RandomString(7) + "_output"); + if (!System.IO.File.Exists(str)) + Directory.CreateDirectory(str); + string[] strArray1 = scriptstr.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + this.WriteStatus(string.Format(" - Script loaded ({0} Titles)", (object) strArray1.Length)); + this.WriteStatus(" - Output: " + str.Replace(this.CURRENT_DIR, "")); + for (int index = 0; index < strArray1.Length; ++index) + { + this.WriteStatus(string.Format("===== Running Download ({0}/{1}) =====", (object) (index + 1), (object) strArray1.Length)); + string[] strArray2 = strArray1[index].Split(' '); + if (!string.IsNullOrEmpty(strArray2[0])) + { + WebClient wcReady = this.ConfigureWithProxy(new WebClient()); + wcReady.Headers.Add("User-Agent", "wii libnup/1.0"); + NusClient nusClient = new NusClient(); + nusClient.ConfigureNusClient(wcReady); + nusClient.UseLocalFiles = this.localuse.Checked; + nusClient.ContinueWithoutTicket = true; + nusClient.Debug += new EventHandler(this.nusClient_Debug); + StoreType[] storeTypeArray = new StoreType[1] + { + StoreType.All + }; + int num = int.Parse(strArray2[1], NumberStyles.HexNumber); + string titlename = this.NameFromDatabase(strArray2[0]); + string wadName; + if (titlename != null) + wadName = this.OfficialWADNaming(titlename); + else + wadName = strArray2[0] + "-NUS-v" + (object) num + ".wad"; + nusClient.DownloadTitle(strArray2[0], num.ToString(), str, this.pathbox.Checked, wadName, storeTypeArray); + } + } + this.WriteStatus("Script completed!"); + } + + private string RandomString(int size) + { + char[] chArray = new char[size]; + for (int index = 0; index < size; ++index) + chArray[index] = "abcdefghijklmnopqrstuvwxyz"[this._rng.Next("abcdefghijklmnopqrstuvwxyz".Length)]; + return new string(chArray); + } + + private void Form1_MouseWheel(object sender, MouseEventArgs e) + { + if (!this.SystemMenuList.DropDown.DisplayRectangle.Contains(e.Location) && !this.SystemMenuList.DropDown.Bounds.Contains(e.Location) && !this.WiiWareMenuList.DropDown.DisplayRectangle.Contains(e.Location) && !this.WiiWareMenuList.DropDown.Bounds.Contains(e.Location) && !this.VCMenuList.DropDown.DisplayRectangle.Contains(e.Location) && !this.VCMenuList.DropDown.Bounds.Contains(e.Location) && !this.IOSMenuList.DropDown.DisplayRectangle.Contains(e.Location) && !this.IOSMenuList.DropDown.Bounds.Contains(e.Location)) + return; + if (e.Delta > 0) + { + SendKeys.Send("{UP}"); + SendKeys.Send("{UP}"); + SendKeys.Send("{UP}"); + SendKeys.Send("{UP}"); + SendKeys.Send("{UP}"); + } + else + { + SendKeys.Send("{DOWN}"); + SendKeys.Send("{DOWN}"); + SendKeys.Send("{DOWN}"); + SendKeys.Send("{DOWN}"); + SendKeys.Send("{DOWN}"); + } + } + + private void openNUSDDirectoryToolStripMenuItem_Click(object sender, EventArgs e) => Process.Start(this.CURRENT_DIR); + + private void mainPageToolStripMenuItem_Click(object sender, EventArgs e) => Process.Start("http://www.wiibrew.org/wiki/NUS_Downloader"); + + private void databasePageToolStripMenuItem_Click(object sender, EventArgs e) => Process.Start("http://www.wiibrew.org/wiki/NUS_Downloader/database"); + + private void extrasStrip_Opening(object sender, CancelEventArgs e) => this.moreExtrasToolStripMenuItem.Visible = Control.ModifierKeys == Keys.Control; + + private void runFolderFixToolStripMenuItem_Click(object sender, EventArgs e) + { + BackgroundWorker backgroundWorker = new BackgroundWorker(); + backgroundWorker.DoWork += new DoWorkEventHandler(this.ReorganizePreviousFolderStructure); + backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.ReorganizePreviousFolderStructure_Completed); + this.WriteStatus("Organizing your old folder structure..."); + backgroundWorker.RunWorkerAsync(); + } + + private void removeNUSDFilesFoldersToolStripMenuItem_Click(object sender, EventArgs e) + { + if (MessageBox.Show("This will delete all the files\folders you have downloaded from NUS! Are you sure you want to do this?", "Wait a second!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) != DialogResult.Yes) + return; + if (Directory.Exists(Path.Combine(this.CURRENT_DIR, "titles"))) + Directory.Delete(Path.Combine(this.CURRENT_DIR, "titles"), true); + if (Directory.Exists(Path.Combine(this.CURRENT_DIR, "scripts"))) + Directory.Delete(Path.Combine(this.CURRENT_DIR, "scripts"), true); + if (System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "database.xml"))) + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "database.xml")); + if (System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "dsidatabase.xml"))) + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "dsidatabase.xml")); + if (System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "olddatabase.xml"))) + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "olddatabase.xml")); + if (System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "proxy.txt"))) + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "proxy.txt")); + if (System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "key.bin"))) + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "key.bin")); + if (System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "kkey.bin"))) + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "kkey.bin")); + if (!System.IO.File.Exists(Path.Combine(this.CURRENT_DIR, "dsikey.bin"))) + return; + System.IO.File.Delete(Path.Combine(this.CURRENT_DIR, "dsikey.bin")); + } + + private void anyStrip_Closed(object sender, ToolStripDropDownClosedEventArgs e) => ((Control) sender).Text = "Hidden"; + + private void localTicketInventoryToolStripMenuItem_Click(object sender, EventArgs e) + { + this.WriteStatus("Adding ticket information to database entries..."); + ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[6] + { + this.SystemMenuList, + this.IOSMenuList, + this.VCMenuList, + this.WiiWareMenuList, + this.dsiSystemToolStripMenu, + this.dSiWareToolStripMenu + }; + for (int index1 = 0; index1 < toolStripMenuItemArray.Length; ++index1) + { + for (int index2 = 0; index2 < toolStripMenuItemArray[index1].DropDownItems.Count; ++index2) + { + if (toolStripMenuItemArray[index1].DropDownItems[index2].Text.Length >= 16) + { + string path2 = toolStripMenuItemArray[index1].DropDownItems[index2].Text.Substring(0, 16); + string path = Path.Combine(Path.Combine(this.CURRENT_DIR, "titles"), path2); + if (Directory.Exists(path) && Directory.GetFiles(path, "cetk", SearchOption.AllDirectories).Length > 0) + { + if (toolStripMenuItemArray[index1].DropDownItems[index2].Image == Database.green) + toolStripMenuItemArray[index1].DropDownItems[index2].Image = Database.green_blue; + if (toolStripMenuItemArray[index1].DropDownItems[index2].Image == Database.orange) + toolStripMenuItemArray[index1].DropDownItems[index2].Image = Database.orange_blue; + if (toolStripMenuItemArray[index1].DropDownItems[index2].Image == Database.redorange) + toolStripMenuItemArray[index1].DropDownItems[index2].Image = Database.redorange_blue; + if (toolStripMenuItemArray[index1].DropDownItems[index2].Image == Database.redgreen) + toolStripMenuItemArray[index1].DropDownItems[index2].Image = Database.redgreen_blue; + } + } + } + } + this.WriteStatus(" - Operation completed!"); + } + + private void donateToolStripMenuItem_Click(object sender, EventArgs e) => Process.Start("http://wb3000.atspace.name/donations.html"); + + private void DSiDatabaseWork(object sender, DoWorkEventArgs e) + { + while (this.databaseWorker.IsBusy) + Thread.Sleep(1000); + this.FillDSiDatabaseStrip(sender as BackgroundWorker); + this.LoadRegionCodes(); + this.ShowInnerToolTips(false); + } + + private void DSiDatabaseWork_Completed(object sender, RunWorkerCompletedEventArgs e) + { + this.databaseButton.Text = "Database..."; + this.databaseButton.Image = (Image) null; + } + + private void DSiDatabaseWork_ProgressChanged(object sender, ProgressChangedEventArgs e) + { + if (e.ProgressPercentage == 50) + { + this.databaseButton.Text = " [. ]"; + } + else + { + if (e.ProgressPercentage != 100) + return; + this.databaseButton.Text = " [..]"; + } + } + + private void wiiRegionCodesMenu_DropDownItemClicked( + object sender, + ToolStripItemClickedEventArgs e) + { + if (this.titleidbox.Text.Length != 16) + return; + this.titleidbox.Text = this.titleidbox.Text.Substring(0, 14) + e.ClickedItem.Text.Substring(0, 2); + } + + private void dsiRegionCodesMenu_DropDownItemClicked( + object sender, + ToolStripItemClickedEventArgs e) + { + if (this.titleidbox.Text.Length != 16) + return; + this.titleidbox.Text = this.titleidbox.Text.Substring(0, 14) + e.ClickedItem.Text.Substring(0, 2); + } + + private void serverLbl_MouseEnter(object sender, EventArgs e) => this.serverLbl.Font = new Font(this.serverLbl.Font, FontStyle.Underline); + + private void serverLbl_MouseLeave(object sender, EventArgs e) => this.serverLbl.Font = new Font(this.serverLbl.Font, FontStyle.Regular); + + private void serverLbl_TextChanged(object sender, EventArgs e) + { + if (this.serverLbl.Text == "Wii") + this.packbox.Enabled = true; + if (!(this.serverLbl.Text == "DSi")) + return; + this.packbox.Checked = false; + this.packbox.Enabled = false; + this.wadnamebox.Enabled = false; + this.wadnamebox.Text = ""; + } + + private void serverLbl_Click(object sender, EventArgs e) + { + string[] strArray = new string[2]{ "Wii", "DSi" }; + for (int index = 0; index < strArray.Length; ++index) + { + if (this.serverLbl.Text == strArray[index]) + { + if (strArray.Length == index + 1) + { + this.serverLbl.Text = strArray[0]; + break; + } + this.serverLbl.Text = strArray[index + 1]; + break; + } + } + } + + private delegate void AddToolStripItemToStripCallback( + ToolStripMenuItem menulist, + ToolStripMenuItem[] additionitems); + + private delegate void WriteStatusCallback(string Update, Color writecolor); + + private delegate void BootChecksCallback(); + + private delegate void SetEnableForDownloadCallback(bool enabled); + + private delegate void SetPropertyThreadSafeCallback( + Component what, + object setto, + string property); + + private delegate string OfficialWADNamingCallback(string whut); + } +} diff --git a/NUS_Downloader/Form1.resx b/NUS_Downloader/Form1.resx new file mode 100644 index 0000000..e9953c8 --- /dev/null +++ b/NUS_Downloader/Form1.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////////8AAAAAAB///wAAAAAAH///AAAAAAAf//8AAAAAAA///wAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAD//+AAAAAAAP//4AAAAAAA///gAAAAAAB//+AAAAAAAH//4AAAAAAAf//gAAAAAAB//+AAAAAAAH//4AAAAAAAf//gAAAAAAB//+AAAAAAAH//4AAAAAAAf//gAAAAAAD///AAAAAAAP//8AAAAAAB///wAAAAAAH///gAAAAAAf//+AAAAAAD///8AAAAAAP///wAAAAAA////AAAAAAH///+AAAAAAf///4AAAAAD/////AAAAH/////4AAAAP/////AAAAAf////4AAAAA/////AAAAAB////8AAAAAH////wAAAAAf////AAAAAB////8AAAAAH////4AAAAA//////wAAH///////AAAf//////8AAB///////wAAH///////AAAf//////8AAB///////wAAH///////AAAf//////8AAB///////wAAH///////AAAf//////8AAB//////////////ygAAACAAAAAAAEAAAEAIAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAwAAAAUAAAAHAAAACQAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACQAAAAcAAAAFAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAUAAAAKAAAAEgAAABcAAAAcAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB8AAAAfAAAAHwAAAB4AAAAcAAAAFwAAABEAAAAKAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAADAAAABcAAAAkAAAAMAAAADkAAAA9AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPQAAADkAAAAwAAAAJAAAABcAAAAMAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgAAAAUAAAAKAAAAD8AAABSAAAAYAAAAGYAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABmAAAAYAAAAFMAAAA/AAAAKAAAABUAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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/3264f99uuH/fbrh/3264f99uuH/fbrh/3264f99uuH/fbrh/3664f9+uuH/frrh/3664f9+uuH/frrh/3664f92stb/c67S/3664f9+uuH/f7vi/3+74v9/u+L/f7vi/3Gv2f9Pj8X/b67Z/0WPzf8ybp6sAAAAMwAAABcAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAUAAAALjBqmJ5Gkc7/ebjf/3Gv2v9Qkcb/ca/a/3q54P96ueD/erng/3q54P96ueD/a6fL/zhrgv9Zk7L/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P97ueD/e7ng/3u54P97ueD/e7ng/3u54P97ueD/e7ng/3u54P97ueD/e7ng/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3y64f98uuH/fLrh/3264f99uuH/fbrh/3264f99uuH/fbrh/0p/mf87bIL/fbrh/3264f99uuH/frrh/3664f9npdL/WpnK/3q53/9+uuH/RpHO/zJsna4AAAA1AAAAGQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAABUAAAAvNXGhqUmTz/95t9//ebff/3a03f9Wl8n/ZqXT/3m43/95uN//ebjf/3m43/95uN//aaXJ/3Wy2f95uN//ebjf/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng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/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P96ueD/erng/3q54P92tN3/b67b/3664f+v3fH/ebff/3m33/95t9//ebff/3m33/95t9//ebff/2ir2v9XndP/AAAARgAAACUAAAAOAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAbAAAAOU2MvddgpNf/c7Pd/3Oz3f+TyOb/c7Pd/3Oz3f9zs93/kcjn/5zP6/9mptb/a6vZ/3Kx3f94tt7/ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3m43/95uN//ebjf/3Wz3f9trNr/fbng/67d8f94t9//eLff/3i33/90st3/eLff/3i33/94t9//a6zb/1mf1P8gOlBgAAAAJwAAABAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAB0AAAA7To6+2GKm2P9yst3/crLd/4vE5f9yst3/crLd/3Ky3f+Qx+f/m8/q/2Wl1v9qqtn/cK/c/3a03v94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94t9//eLff/3i33/94tt//c7Ld/2us2v98ud//rt3x/3i23/94tt//eLbf/3Cw2/94tt//eLbf/3i23/9wsd3/W6HV/zBbeHkAAAApAAAAEQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAHgAAADxPj7/YZ6ra/3Gx3f9xsd3/i8Tl/3664f9yst3/crLd/5DH5/+azur/aqjX/3ay3P97t97/gLrg/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v+DvOL/g7zi/4O84v99ud//dLHc/3q43v+t3PH/drXe/3e23v93tt7/b6/a/3W03f93tt7/d7be/3Cx3f9dotb/MFx5egAAACsAAAASAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/zWKNf81ijX/NYo1/xt9G/8AbgDiAFUALQAAAAgAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAUAQAAYAF4ASQBgAEoAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABeAEwAXgBMAF4ATABfAEsAYABKAF4ASQBDABcAAAAFAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////////////////////////////////////////////////////////////////////////////////gAAAAAAAAAAAAH///////AAAAAAAAAAAAAAP//////wAAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////gAAAAAAAAAAAAAA//////4AAAAAAAAAAAAAAP/////+AAAAAAAAAAAAAAD//////gAAAAAAAAAAAAAA//////4AAAAAAAAAAAAAAP/////+AAAAAAAAAAAAAAD//////gAAAAAAAAAAAAAA//////4AAAAAAAAAAAAAAP/////+AAAAAAAAAAAAAAD//////gAAAAAAAAAAAAAA//////4AAAAAAAAAAAAAAP/////8AAAAAAAAAAAAAAD//////AAAAAAAAAAAAAAA//////wAAAAAAAAAAAAAAP/////8AAAAAAAAAAAAAAD//////AAAAAAAAAAAAAAA//////wAAAAAAAAAAAAAAP/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAP/////wAAAAAAAAAAAAAAD/////8AAAAAAAAAAAAAAA//////AAAAAAAAAAAAAAAP/////wAAAAAAAAAAAAAAH/////8AAAAAAAAAAAAAAB//////gAAAAAAAAAAAAAAf/////4AAAAAAAAAAAAAAP/////+AAAAAAAAAAAAAAD//////wAAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAf//////AAAAAAAAAAAAAAH//////4AAAAAAAAAAAAAD//////+AAAAAAAAAAAAAA///////gAAAAAAAAAAAAAP//////8AAAAAAAAAAAAAH///////AAAAAAAAAAAAAB///////4AAAAAAAAAAAAA///////+AAAAAAAAAAAAAP///////gAAAAAAAAAAAAD///////8AAAAAAAAAAAAB////////AAAAAAAAAAAAAf///////wAAAAAAAAAAAAH///////+AAAAAAAAAAAAD////////gAAAAAAAAAAAA////////4AAAAAAAAAAAAP////////AAAAAAAAAAAAH////////4AAAAAAAAAAAD//////////gAAAAAAAAH///////////8AAAAAAAAD///////////+AAAAAAAAAf///////////AAAAAAAAAD///////////AAAAAAAAAAf//////////gAAAAAAAAAB//////////wAAAAAAAAAAP/////////4AAAAAAAAAAB/////////8AAAAAAAAAAAP/////////AAAAAAAAAAAD/////////wAAAAAAAAAAA/////////8AAAAAAAAAAAP/////////AAAAAAAAAAAD/////////wAAAAAAAAAAA/////////8AAAAAAAAAAAP/////////AAAAAAAAAAAD/////////wAAAAAAAAAAA/////////8AAAAAAAAAAAP/////////AAAAAAAAAAAD////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////AAAAAAP//////////////wAAAAAD//////////////8AAAAAA///////////////gAAAAAf/////////////////////////////////////////////////8L + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAApw0AAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAsY58+1GTAAAAIGNIUk0AAIcPAACMDwAA/VIAAIFAAAB9eQAA6YsAADzlAAAZzHM8hXcAAAo5aUNDUFBob3Rvc2hvcCBJQ0MgcHJvZmlsZQAASMedlndUVNcWh8+9d3qhzTACUobeu8AA0nuTXkVhmBlgKAMOMzSxIaICEUVEmiJIUMSA0VAkVkSxEBRUsAckCCgxGEVULG9G1ouurLz38vL746xv7bP3ufvsvc9aFwCSpy+XlwZLAZDKE/CDPJzpEZFRdOwAgAEeYIApAExWRrpfsHsIEMnLzYWeIXICXwQB8HpYvAJw09AzgE4H/5+kWel8geiYABGbszkZLBEXiDglS5Auts+KmBqXLGYYJWa+KEERy4k5YZENPvsssqOY2ak8tojFOaezU9li7hXxtkwhR8SIr4gLM7mcLBHfErFGijCVK+I34thUDjMDABRJbBdwWIkiNhExiR8S5CLi5QDgSAlfcdxXLOBkC8SXcklLz+FzExIFdB2WLt3U2ppB9+RkpXAEAsMAJiuZyWfTXdJS05m8HAAW7/xZMuLa0kVFtjS1trQ0NDMy/apQ/3Xzb0rc20V6Gfi5ZxCt/4vtr/zSGgBgzIlqs/OLLa4KgM4tAMjd+2LTOACApKhvHde/ug9NPC+JAkG6jbFxVlaWEZfDMhIX9A/9T4e/oa++ZyQ+7o/y0F058UxhioAurhsrLSVNyKdnpDNZHLrhn4f4Hwf+dR4GQZx4Dp/DE0WEiaaMy0sQtZvH5gq4aTw6l/efmvgPw/6kxbkWidL4EVBjjIDUdSpAfu0HKAoRINH7xV3/o2+++DAgfnnhKpOLc//vN/1nwaXiJYOb8DnOJSiEzhLyMxf3xM8SoAEBSAIqkAfKQB3oAENgBqyALXAEbsAb+IMQEAlWAxZIBKmAD7JAHtgECkEx2An2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 + + \ No newline at end of file diff --git a/NUS_Downloader/Program.cs b/NUS_Downloader/Program.cs new file mode 100644 index 0000000..2ec4db3 --- /dev/null +++ b/NUS_Downloader/Program.cs @@ -0,0 +1,49 @@ +// Decompiled with JetBrains decompiler +// Type: NUS_Downloader.Program +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace NUS_Downloader +{ + internal static class Program + { + [DllImport("user32.dll")] + public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("user32.dll")] + private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + + [STAThread] + private static void Main(string[] args) + { + if (args.Length != 0) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run((Form) new Form1(args)); + } + else + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run((Form) new Form1()); + } + } + + public static void setConsoleWindowVisibility(bool visible, string title) + { + IntPtr window = Program.FindWindow((string) null, title); + if (!(window != IntPtr.Zero)) + return; + if (!visible) + Program.ShowWindow(window, 0); + else + Program.ShowWindow(window, 1); + } + } +} diff --git a/NUS_Downloader/Properties/Resources.cs b/NUS_Downloader/Properties/Resources.cs new file mode 100644 index 0000000..5c2a602 --- /dev/null +++ b/NUS_Downloader/Properties/Resources.cs @@ -0,0 +1,123 @@ +// Decompiled with JetBrains decompiler +// Type: NUS_Downloader.Properties.Resources +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.Resources; +using System.Runtime.CompilerServices; + +namespace NUS_Downloader.Properties +{ + [CompilerGenerated] + [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [DebuggerNonUserCode] + internal class Resources + { + private static ResourceManager resourceMan; + private static CultureInfo resourceCulture; + + internal Resources() + { + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + internal static ResourceManager ResourceManager + { + get + { + if (object.ReferenceEquals((object) NUS_Downloader.Properties.Resources.resourceMan, (object) null)) + NUS_Downloader.Properties.Resources.resourceMan = new ResourceManager("NUS_Downloader.Properties.Resources", typeof (NUS_Downloader.Properties.Resources).Assembly); + return NUS_Downloader.Properties.Resources.resourceMan; + } + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + internal static CultureInfo Culture + { + get => NUS_Downloader.Properties.Resources.resourceCulture; + set => NUS_Downloader.Properties.Resources.resourceCulture = value; + } + + internal static Bitmap arrow_ticker => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (arrow_ticker), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bin_closed => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bin_closed), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap box => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (box), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bug_add => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bug_add), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_green => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_green), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_green_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_green_blue), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_orange => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_orange), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_orange_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_orange_blue), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_red => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_red), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_redgreen => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redgreen), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_redgreen_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redgreen_blue), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_redorange => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redorange), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap bullet_redorange_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redorange_blue), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap connect => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (connect), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap database_save => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (database_save), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap disk => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (disk), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap drive_disk => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (drive_disk), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap dsi16x16 => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (dsi16x16), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap folder => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (folder), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap folder_table => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (folder_table), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap help => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (help), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap information => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (information), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap key => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (key), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap money => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (money), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap package => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap package_add => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package_add), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap package_delete => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package_delete), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap package_green => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package_green), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap page_white_magnify => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (page_white_magnify), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap picture_empty => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (picture_empty), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap script_code => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_code), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap script_code_red => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_code_red), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap script_go => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_go), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap script_start => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_start), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap server_connect => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (server_connect), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap server_link => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (server_link), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap wii16x16 => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (wii16x16), NUS_Downloader.Properties.Resources.resourceCulture); + + internal static Bitmap wrench => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (wrench), NUS_Downloader.Properties.Resources.resourceCulture); + } +} diff --git a/NUS_Downloader/Properties/Resources.resx b/NUS_Downloader/Properties/Resources.resx new file mode 100644 index 0000000..60e32bc --- /dev/null +++ b/NUS_Downloader/Properties/Resources.resx @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + \ No newline at end of file diff --git a/NUS_Downloader/Properties/Settings.cs b/NUS_Downloader/Properties/Settings.cs new file mode 100644 index 0000000..d55da69 --- /dev/null +++ b/NUS_Downloader/Properties/Settings.cs @@ -0,0 +1,21 @@ +// Decompiled with JetBrains decompiler +// Type: NUS_Downloader.Properties.Settings +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System.CodeDom.Compiler; +using System.Configuration; +using System.Runtime.CompilerServices; + +namespace NUS_Downloader.Properties +{ + [CompilerGenerated] + [GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed class Settings : ApplicationSettingsBase + { + private static Settings defaultInstance = (Settings) SettingsBase.Synchronized((SettingsBase) new Settings()); + + public static Settings Default => Settings.defaultInstance; + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..d7baa3c --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# NUS Downloader + +This is v1.9 Mod of the NUS Downloader by [hamachi-mp](https://forum.wii-homebrew.com/index.php/Thread/31411-NUS-Downloader-v1-9-mod/). The original version was made by [WB3000](https://github.com/WB3000/nusdownloader). The mod's source code was never made public so the EXE has been decompiled with [dotPeek](https://www.jetbrains.com/decompiler/). + +NUS Downloader is licensed under the GNU GPL v3. + +## Changelog +### v1.9 Mod +* Based on NUS r122 +* Checkbox to use the folder structure of NUSD v1.5 +* Fixed script creation on "Emulate Update" + +### Older versions +See [WiiBrew](https://wiibrew.org/wiki/NUS_Downloader#Update_History). diff --git a/libWiiSharp/CertificateChain.cs b/libWiiSharp/CertificateChain.cs new file mode 100644 index 0000000..3a001ae --- /dev/null +++ b/libWiiSharp/CertificateChain.cs @@ -0,0 +1,433 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.CertificateChain +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace libWiiSharp +{ + public class CertificateChain : IDisposable + { + private const string certCaHash = "5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318"; + private const string certCpHash = "6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C"; + private const string certXsHash = "09787045037121477824BC6A3E5E076156573F8A"; + private SHA1 sha = SHA1.Create(); + private bool[] certsComplete = new bool[3]; + private byte[] certCa = new byte[1024]; + private byte[] certCp = new byte[768]; + private byte[] certXs = new byte[768]; + private bool isDisposed; + + public bool CertsComplete => this.certsComplete[0] && this.certsComplete[1] && this.certsComplete[2]; + + ~CertificateChain() => this.Dispose(false); + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize((object) this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !this.isDisposed) + { + this.sha.Clear(); + this.sha = (SHA1) null; + this.certsComplete = (bool[]) null; + this.certCa = (byte[]) null; + this.certCp = (byte[]) null; + this.certXs = (byte[]) null; + } + this.isDisposed = true; + } + + public static CertificateChain Load(string pathToCert) => CertificateChain.Load(File.ReadAllBytes(pathToCert)); + + public static CertificateChain Load(byte[] certFile) + { + CertificateChain certificateChain = new CertificateChain(); + MemoryStream certFile1 = new MemoryStream(certFile); + try + { + certificateChain.parseCert((Stream) certFile1); + } + catch + { + certFile1.Dispose(); + throw; + } + certFile1.Dispose(); + return certificateChain; + } + + public static CertificateChain Load(Stream cert) + { + CertificateChain certificateChain = new CertificateChain(); + certificateChain.parseCert(cert); + return certificateChain; + } + + public static CertificateChain FromTikTmd(string pathToTik, string pathToTmd) => CertificateChain.FromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); + + public static CertificateChain FromTikTmd(string pathToTik, byte[] tmdFile) => CertificateChain.FromTikTmd(File.ReadAllBytes(pathToTik), tmdFile); + + public static CertificateChain FromTikTmd(byte[] tikFile, byte[] tmdFile) + { + CertificateChain certificateChain = new CertificateChain(); + MemoryStream tik = new MemoryStream(tikFile); + try + { + certificateChain.grabFromTik((Stream) tik); + } + catch + { + tik.Dispose(); + throw; + } + MemoryStream tmd = new MemoryStream(tmdFile); + try + { + certificateChain.grabFromTmd((Stream) tmd); + } + catch + { + tmd.Dispose(); + throw; + } + tmd.Dispose(); + return certificateChain.CertsComplete ? certificateChain : throw new Exception("Couldn't locate all certs!"); + } + + public static CertificateChain FromTikTmd(Stream tik, Stream tmd) + { + CertificateChain certificateChain = new CertificateChain(); + certificateChain.grabFromTik(tik); + certificateChain.grabFromTmd(tmd); + return certificateChain; + } + + public void LoadFile(string pathToCert) => this.LoadFile(File.ReadAllBytes(pathToCert)); + + public void LoadFile(byte[] certFile) + { + MemoryStream certFile1 = new MemoryStream(certFile); + try + { + this.parseCert((Stream) certFile1); + } + catch + { + certFile1.Dispose(); + throw; + } + certFile1.Dispose(); + } + + public void LoadFile(Stream cert) => this.parseCert(cert); + + public void LoadFromTikTmd(string pathToTik, string pathToTmd) => this.LoadFromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); + + public void LoadFromTikTmd(string pathToTik, byte[] tmdFile) => this.LoadFromTikTmd(File.ReadAllBytes(pathToTik), tmdFile); + + public void LoadFromTikTmd(byte[] tikFile, byte[] tmdFile) + { + MemoryStream tik = new MemoryStream(tikFile); + try + { + this.grabFromTik((Stream) tik); + } + catch + { + tik.Dispose(); + throw; + } + MemoryStream tmd = new MemoryStream(tmdFile); + try + { + this.grabFromTmd((Stream) tmd); + } + catch + { + tmd.Dispose(); + throw; + } + tmd.Dispose(); + if (!this.CertsComplete) + throw new Exception("Couldn't locate all certs!"); + } + + public void LoadFromTikTmd(Stream tik, Stream tmd) + { + this.grabFromTik(tik); + this.grabFromTmd(tmd); + } + + public void Save(string savePath) + { + if (File.Exists(savePath)) + File.Delete(savePath); + using (FileStream writeStream = new FileStream(savePath, FileMode.Create)) + this.writeToStream((Stream) writeStream); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + return writeStream; + } + + public byte[] ToByteArray() + { + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + byte[] array = writeStream.ToArray(); + writeStream.Dispose(); + return array; + } + + private void writeToStream(Stream writeStream) + { + this.fireDebug("Writing Certificate Chain..."); + if (!this.CertsComplete) + { + this.fireDebug(" Certificate Chain incomplete..."); + throw new Exception("At least one certificate is missing!"); + } + writeStream.Seek(0L, SeekOrigin.Begin); + this.fireDebug(" Writing Certificate CA... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8")); + writeStream.Write(this.certCa, 0, this.certCa.Length); + this.fireDebug(" Writing Certificate CP... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8")); + writeStream.Write(this.certCp, 0, this.certCp.Length); + this.fireDebug(" Writing Certificate XS... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8")); + writeStream.Write(this.certXs, 0, this.certXs.Length); + this.fireDebug("Writing Certificate Chain Finished..."); + } + + private void parseCert(Stream certFile) + { + this.fireDebug("Parsing Certificate Chain..."); + int offset = 0; + for (int index = 0; index < 3; ++index) + { + this.fireDebug(" Scanning at Offset 0x{0}:", (object) offset.ToString("x8")); + try + { + certFile.Seek((long) offset, SeekOrigin.Begin); + byte[] array = new byte[1024]; + certFile.Read(array, 0, array.Length); + this.fireDebug(" Checking for Certificate CA..."); + if (this.isCertCa(array) && !this.certsComplete[1]) + { + this.fireDebug(" Certificate CA detected..."); + this.certCa = array; + this.certsComplete[1] = true; + offset += 1024; + continue; + } + this.fireDebug(" Checking for Certificate CP..."); + if (this.isCertCp(array) && !this.certsComplete[2]) + { + this.fireDebug(" Certificate CP detected..."); + Array.Resize(ref array, 768); + this.certCp = array; + this.certsComplete[2] = true; + offset += 768; + continue; + } + this.fireDebug(" Checking for Certificate XS..."); + if (this.isCertXs(array)) + { + if (!this.certsComplete[0]) + { + this.fireDebug(" Certificate XS detected..."); + Array.Resize(ref array, 768); + this.certXs = array; + this.certsComplete[0] = true; + offset += 768; + continue; + } + } + } + catch (Exception ex) + { + this.fireDebug("Error: {0}", (object) ex.Message); + } + offset += 768; + } + if (!this.CertsComplete) + { + this.fireDebug(" Couldn't locate all Certificates..."); + throw new Exception("Couldn't locate all certs!"); + } + this.fireDebug("Parsing Certificate Chain Finished..."); + } + + private void grabFromTik(Stream tik) + { + this.fireDebug("Scanning Ticket for Certificates..."); + int offset = 676; + for (int index = 0; index < 3; ++index) + { + this.fireDebug(" Scanning at Offset 0x{0}:", (object) offset.ToString("x8")); + try + { + tik.Seek((long) offset, SeekOrigin.Begin); + byte[] array = new byte[1024]; + tik.Read(array, 0, array.Length); + this.fireDebug(" Checking for Certificate CA..."); + if (this.isCertCa(array) && !this.certsComplete[1]) + { + this.fireDebug(" Certificate CA detected..."); + this.certCa = array; + this.certsComplete[1] = true; + offset += 1024; + continue; + } + this.fireDebug(" Checking for Certificate CP..."); + if (this.isCertCp(array) && !this.certsComplete[2]) + { + this.fireDebug(" Certificate CP detected..."); + Array.Resize(ref array, 768); + this.certCp = array; + this.certsComplete[2] = true; + offset += 768; + continue; + } + this.fireDebug(" Checking for Certificate XS..."); + if (this.isCertXs(array)) + { + if (!this.certsComplete[0]) + { + this.fireDebug(" Certificate XS detected..."); + Array.Resize(ref array, 768); + this.certXs = array; + this.certsComplete[0] = true; + offset += 768; + continue; + } + } + } + catch + { + } + offset += 768; + } + this.fireDebug("Scanning Ticket for Certificates Finished..."); + } + + private void grabFromTmd(Stream tmd) + { + this.fireDebug("Scanning TMD for Certificates..."); + byte[] buffer = new byte[2]; + tmd.Seek(478L, SeekOrigin.Begin); + tmd.Read(buffer, 0, 2); + int offset = 484 + (int) Shared.Swap(BitConverter.ToUInt16(buffer, 0)) * 36; + for (int index = 0; index < 3; ++index) + { + this.fireDebug(" Scanning at Offset 0x{0}:", (object) offset.ToString("x8")); + try + { + tmd.Seek((long) offset, SeekOrigin.Begin); + byte[] array = new byte[1024]; + tmd.Read(array, 0, array.Length); + this.fireDebug(" Checking for Certificate CA..."); + if (this.isCertCa(array) && !this.certsComplete[1]) + { + this.fireDebug(" Certificate CA detected..."); + this.certCa = array; + this.certsComplete[1] = true; + offset += 1024; + continue; + } + this.fireDebug(" Checking for Certificate CP..."); + if (this.isCertCp(array) && !this.certsComplete[2]) + { + this.fireDebug(" Certificate CP detected..."); + Array.Resize(ref array, 768); + this.certCp = array; + this.certsComplete[2] = true; + offset += 768; + continue; + } + this.fireDebug(" Checking for Certificate XS..."); + if (this.isCertXs(array)) + { + if (!this.certsComplete[0]) + { + this.fireDebug(" Certificate XS detected..."); + Array.Resize(ref array, 768); + this.certXs = array; + this.certsComplete[0] = true; + offset += 768; + continue; + } + } + } + catch + { + } + offset += 768; + } + this.fireDebug("Scanning TMD for Certificates Finished..."); + } + + private bool isCertXs(byte[] part) + { + if (part.Length < 768) + return false; + if (part.Length > 768) + Array.Resize(ref part, 768); + return part[388] == (byte) 88 && part[389] == (byte) 83 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("09787045037121477824BC6A3E5E076156573F8A")); + } + + private bool isCertCa(byte[] part) + { + if (part.Length < 1024) + return false; + if (part.Length > 1024) + Array.Resize(ref part, 1024); + return part[644] == (byte) 67 && part[645] == (byte) 65 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318")); + } + + private bool isCertCp(byte[] part) + { + if (part.Length < 768) + return false; + if (part.Length > 768) + Array.Resize(ref part, 768); + return part[388] == (byte) 67 && part[389] == (byte) 80 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C")); + } + + public event EventHandler Debug; + + private void fireDebug(string debugMessage, params object[] args) + { + EventHandler debug = this.Debug; + if (debug == null) + return; + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + } +} diff --git a/libWiiSharp/CommonKey.cs b/libWiiSharp/CommonKey.cs new file mode 100644 index 0000000..cdb71f8 --- /dev/null +++ b/libWiiSharp/CommonKey.cs @@ -0,0 +1,27 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.CommonKey +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System.IO; + +namespace libWiiSharp +{ + public class CommonKey + { + private static string standardKey = "ebe42a225e8593e448d9c5457381aaf7"; + private static string koreanKey = "63b82bb4f4614e2e13f2fefbba4c9b7e"; + private static string dsiKey = "af1bf516a807d21aea45984f04742861"; + private static string currentDir = Directory.GetCurrentDirectory(); + private static string standardKeyName = "key.bin"; + private static string koreanKeyName = "kkey.bin"; + private static string dsiKeyName = "dsikey.bin"; + + public static byte[] GetStandardKey() => File.Exists(Path.Combine(CommonKey.currentDir, CommonKey.standardKeyName)) ? File.ReadAllBytes(Path.Combine(CommonKey.currentDir, CommonKey.standardKeyName)) : Shared.HexStringToByteArray(CommonKey.standardKey); + + public static byte[] GetKoreanKey() => File.Exists(Path.Combine(CommonKey.currentDir, CommonKey.koreanKeyName)) ? File.ReadAllBytes(Path.Combine(CommonKey.currentDir, CommonKey.koreanKeyName)) : Shared.HexStringToByteArray(CommonKey.koreanKey); + + public static byte[] GetDSiKey() => File.Exists(Path.Combine(CommonKey.currentDir, CommonKey.dsiKeyName)) ? File.ReadAllBytes(Path.Combine(CommonKey.currentDir, CommonKey.dsiKeyName)) : Shared.HexStringToByteArray(CommonKey.dsiKey); + } +} diff --git a/libWiiSharp/CommonKeyType.cs b/libWiiSharp/CommonKeyType.cs new file mode 100644 index 0000000..33878d6 --- /dev/null +++ b/libWiiSharp/CommonKeyType.cs @@ -0,0 +1,14 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.CommonKeyType +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace libWiiSharp +{ + public enum CommonKeyType : byte + { + Standard, + Korean, + } +} diff --git a/libWiiSharp/ContentIndices.cs b/libWiiSharp/ContentIndices.cs new file mode 100644 index 0000000..396ecd1 --- /dev/null +++ b/libWiiSharp/ContentIndices.cs @@ -0,0 +1,33 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.ContentIndices +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; + +namespace libWiiSharp +{ + internal struct ContentIndices : IComparable + { + private int index; + private int contentIndex; + + public int Index => this.index; + + public int ContentIndex => this.contentIndex; + + public ContentIndices(int index, int contentIndex) + { + this.index = index; + this.contentIndex = contentIndex; + } + + public int CompareTo(object obj) + { + if (obj is ContentIndices contentIndices) + return this.contentIndex.CompareTo(contentIndices.contentIndex); + throw new ArgumentException(); + } + } +} diff --git a/libWiiSharp/ContentType.cs b/libWiiSharp/ContentType.cs new file mode 100644 index 0000000..3542ed3 --- /dev/null +++ b/libWiiSharp/ContentType.cs @@ -0,0 +1,15 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.ContentType +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace libWiiSharp +{ + public enum ContentType : ushort + { + Normal = 1, + DLC = 16385, // 0x4001 + Shared = 32769, // 0x8001 + } +} diff --git a/libWiiSharp/Headers.cs b/libWiiSharp/Headers.cs new file mode 100644 index 0000000..963bf92 --- /dev/null +++ b/libWiiSharp/Headers.cs @@ -0,0 +1,589 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.Headers +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace libWiiSharp +{ + public class Headers + { + private static uint imd5Magic = 1229800501; + private static uint imetMagic = 1229800788; + + public static Headers.HeaderType DetectHeader(string pathToFile) => Headers.DetectHeader(File.ReadAllBytes(pathToFile)); + + public static Headers.HeaderType DetectHeader(byte[] file) + { + if (file.Length > 68 && (int) Shared.Swap(BitConverter.ToUInt32(file, 64)) == (int) Headers.imetMagic) + return Headers.HeaderType.ShortIMET; + if (file.Length > 132 && (int) Shared.Swap(BitConverter.ToUInt32(file, 128)) == (int) Headers.imetMagic) + return Headers.HeaderType.IMET; + return file.Length > 4 && (int) Shared.Swap(BitConverter.ToUInt32(file, 0)) == (int) Headers.imd5Magic ? Headers.HeaderType.IMD5 : Headers.HeaderType.None; + } + + public static Headers.HeaderType DetectHeader(Stream file) + { + byte[] buffer = new byte[4]; + if (file.Length > 68L) + { + file.Seek(64L, SeekOrigin.Begin); + file.Read(buffer, 0, buffer.Length); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imetMagic) + return Headers.HeaderType.ShortIMET; + } + if (file.Length > 132L) + { + file.Seek(128L, SeekOrigin.Begin); + file.Read(buffer, 0, buffer.Length); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imetMagic) + return Headers.HeaderType.IMET; + } + if (file.Length > 4L) + { + file.Seek(0L, SeekOrigin.Begin); + file.Read(buffer, 0, buffer.Length); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imd5Magic) + return Headers.HeaderType.IMD5; + } + return Headers.HeaderType.None; + } + + public enum HeaderType + { + None = 0, + IMD5 = 32, // 0x00000020 + ShortIMET = 1536, // 0x00000600 + IMET = 1600, // 0x00000640 + } + + public class IMET + { + private bool hashesMatch = true; + private bool isShortImet; + private byte[] additionalPadding = new byte[64]; + private byte[] padding = new byte[64]; + private uint imetMagic = 1229800788; + private uint sizeOfHeader = 1536; + private uint unknown = 3; + private uint iconSize; + private uint bannerSize; + private uint soundSize; + private uint flags; + private byte[] japaneseTitle = new byte[84]; + private byte[] englishTitle = new byte[84]; + private byte[] germanTitle = new byte[84]; + private byte[] frenchTitle = new byte[84]; + private byte[] spanishTitle = new byte[84]; + private byte[] italianTitle = new byte[84]; + private byte[] dutchTitle = new byte[84]; + private byte[] unknownTitle1 = new byte[84]; + private byte[] unknownTitle2 = new byte[84]; + private byte[] koreanTitle = new byte[84]; + private byte[] padding2 = new byte[588]; + private byte[] hash = new byte[16]; + + public bool IsShortIMET + { + get => this.isShortImet; + set => this.isShortImet = value; + } + + public uint IconSize + { + get => this.iconSize; + set => this.iconSize = value; + } + + public uint BannerSize + { + get => this.bannerSize; + set => this.bannerSize = value; + } + + public uint SoundSize + { + get => this.soundSize; + set => this.soundSize = value; + } + + public string JapaneseTitle + { + get => this.returnTitleAsString(this.japaneseTitle); + set => this.setTitleFromString(value, 0); + } + + public string EnglishTitle + { + get => this.returnTitleAsString(this.englishTitle); + set => this.setTitleFromString(value, 1); + } + + public string GermanTitle + { + get => this.returnTitleAsString(this.germanTitle); + set => this.setTitleFromString(value, 2); + } + + public string FrenchTitle + { + get => this.returnTitleAsString(this.frenchTitle); + set => this.setTitleFromString(value, 3); + } + + public string SpanishTitle + { + get => this.returnTitleAsString(this.spanishTitle); + set => this.setTitleFromString(value, 4); + } + + public string ItalianTitle + { + get => this.returnTitleAsString(this.italianTitle); + set => this.setTitleFromString(value, 5); + } + + public string DutchTitle + { + get => this.returnTitleAsString(this.dutchTitle); + set => this.setTitleFromString(value, 6); + } + + public string KoreanTitle + { + get => this.returnTitleAsString(this.koreanTitle); + set => this.setTitleFromString(value, 7); + } + + public string[] AllTitles => new string[8] + { + this.JapaneseTitle, + this.EnglishTitle, + this.GermanTitle, + this.FrenchTitle, + this.SpanishTitle, + this.ItalianTitle, + this.DutchTitle, + this.KoreanTitle + }; + + public bool HashesMatch => this.hashesMatch; + + public static Headers.IMET Load(string pathToFile) => Headers.IMET.Load(File.ReadAllBytes(pathToFile)); + + public static Headers.IMET Load(byte[] fileOrHeader) + { + Headers.HeaderType headerType = Headers.DetectHeader(fileOrHeader); + switch (headerType) + { + case Headers.HeaderType.ShortIMET: + case Headers.HeaderType.IMET: + Headers.IMET imet = new Headers.IMET(); + if (headerType == Headers.HeaderType.ShortIMET) + imet.isShortImet = true; + MemoryStream headerStream = new MemoryStream(fileOrHeader); + try + { + imet.parseHeader((Stream) headerStream); + } + catch + { + headerStream.Dispose(); + throw; + } + headerStream.Dispose(); + return imet; + default: + throw new Exception("No IMET Header found!"); + } + } + + public static Headers.IMET Load(Stream fileOrHeader) + { + Headers.HeaderType headerType = Headers.DetectHeader(fileOrHeader); + switch (headerType) + { + case Headers.HeaderType.ShortIMET: + case Headers.HeaderType.IMET: + Headers.IMET imet = new Headers.IMET(); + if (headerType == Headers.HeaderType.ShortIMET) + imet.isShortImet = true; + imet.parseHeader(fileOrHeader); + return imet; + default: + throw new Exception("No IMET Header found!"); + } + } + + public static Headers.IMET Create( + bool isShortImet, + int iconSize, + int bannerSize, + int soundSize, + params string[] titles) + { + Headers.IMET imet = new Headers.IMET(); + imet.isShortImet = isShortImet; + for (int titleIndex = 0; titleIndex < titles.Length; ++titleIndex) + imet.setTitleFromString(titles[titleIndex], titleIndex); + for (int length = titles.Length; length < 8; ++length) + imet.setTitleFromString(titles.Length > 1 ? titles[1] : titles[0], length); + imet.iconSize = (uint) iconSize; + imet.bannerSize = (uint) bannerSize; + imet.soundSize = (uint) soundSize; + return imet; + } + + public static void RemoveHeader(string pathToFile) + { + byte[] bytes = Headers.IMET.RemoveHeader(File.ReadAllBytes(pathToFile)); + File.Delete(pathToFile); + File.WriteAllBytes(pathToFile, bytes); + } + + public static byte[] RemoveHeader(byte[] file) + { + Headers.HeaderType sourceIndex = Headers.DetectHeader(file); + switch (sourceIndex) + { + case Headers.HeaderType.ShortIMET: + case Headers.HeaderType.IMET: + byte[] destinationArray = new byte[(int) (file.Length - sourceIndex)]; + Array.Copy((Array) file, (int) sourceIndex, (Array) destinationArray, 0, destinationArray.Length); + return destinationArray; + default: + throw new Exception("No IMET Header found!"); + } + } + + public void SetAllTitles(string newTitle) + { + for (int titleIndex = 0; titleIndex < 10; ++titleIndex) + this.setTitleFromString(newTitle, titleIndex); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + return writeStream; + } + + public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); + + public void Write(Stream writeStream) => this.writeToStream(writeStream); + + public void ChangeTitles(params string[] newTitles) + { + for (int titleIndex = 0; titleIndex < newTitles.Length; ++titleIndex) + this.setTitleFromString(newTitles[titleIndex], titleIndex); + for (int length = newTitles.Length; length < 8; ++length) + this.setTitleFromString(newTitles.Length > 1 ? newTitles[1] : newTitles[0], length); + } + + public string[] GetTitles() => new string[8] + { + this.JapaneseTitle, + this.EnglishTitle, + this.GermanTitle, + this.FrenchTitle, + this.SpanishTitle, + this.ItalianTitle, + this.DutchTitle, + this.KoreanTitle + }; + + private void writeToStream(Stream writeStream) + { + writeStream.Seek(0L, SeekOrigin.Begin); + if (!this.isShortImet) + writeStream.Write(this.additionalPadding, 0, this.additionalPadding.Length); + writeStream.Write(this.padding, 0, this.padding.Length); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.imetMagic)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.sizeOfHeader)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.iconSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.bannerSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.soundSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.flags)), 0, 4); + writeStream.Write(this.japaneseTitle, 0, this.japaneseTitle.Length); + writeStream.Write(this.englishTitle, 0, this.englishTitle.Length); + writeStream.Write(this.germanTitle, 0, this.germanTitle.Length); + writeStream.Write(this.frenchTitle, 0, this.frenchTitle.Length); + writeStream.Write(this.spanishTitle, 0, this.spanishTitle.Length); + writeStream.Write(this.italianTitle, 0, this.italianTitle.Length); + writeStream.Write(this.dutchTitle, 0, this.dutchTitle.Length); + writeStream.Write(this.unknownTitle1, 0, this.unknownTitle1.Length); + writeStream.Write(this.unknownTitle2, 0, this.unknownTitle2.Length); + writeStream.Write(this.koreanTitle, 0, this.koreanTitle.Length); + writeStream.Write(this.padding2, 0, this.padding2.Length); + int position = (int) writeStream.Position; + this.hash = new byte[16]; + writeStream.Write(this.hash, 0, this.hash.Length); + byte[] numArray = new byte[writeStream.Position]; + writeStream.Seek(0L, SeekOrigin.Begin); + writeStream.Read(numArray, 0, numArray.Length); + this.computeHash(numArray, this.isShortImet ? 0 : 64); + writeStream.Seek((long) position, SeekOrigin.Begin); + writeStream.Write(this.hash, 0, this.hash.Length); + } + + private void computeHash(byte[] headerBytes, int hashPos) + { + MD5 md5 = MD5.Create(); + this.hash = md5.ComputeHash(headerBytes, hashPos, 1536); + md5.Clear(); + } + + private void parseHeader(Stream headerStream) + { + headerStream.Seek(0L, SeekOrigin.Begin); + byte[] buffer1 = new byte[4]; + if (!this.isShortImet) + headerStream.Read(this.additionalPadding, 0, this.additionalPadding.Length); + headerStream.Read(this.padding, 0, this.padding.Length); + headerStream.Read(buffer1, 0, 4); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.imetMagic) + throw new Exception("Invalid Magic!"); + headerStream.Read(buffer1, 0, 4); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.sizeOfHeader) + throw new Exception("Invalid Header Size!"); + headerStream.Read(buffer1, 0, 4); + this.unknown = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + headerStream.Read(buffer1, 0, 4); + this.iconSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + headerStream.Read(buffer1, 0, 4); + this.bannerSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + headerStream.Read(buffer1, 0, 4); + this.soundSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + headerStream.Read(buffer1, 0, 4); + this.flags = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + headerStream.Read(this.japaneseTitle, 0, this.japaneseTitle.Length); + headerStream.Read(this.englishTitle, 0, this.englishTitle.Length); + headerStream.Read(this.germanTitle, 0, this.germanTitle.Length); + headerStream.Read(this.frenchTitle, 0, this.frenchTitle.Length); + headerStream.Read(this.spanishTitle, 0, this.spanishTitle.Length); + headerStream.Read(this.italianTitle, 0, this.italianTitle.Length); + headerStream.Read(this.dutchTitle, 0, this.dutchTitle.Length); + headerStream.Read(this.unknownTitle1, 0, this.unknownTitle1.Length); + headerStream.Read(this.unknownTitle2, 0, this.unknownTitle2.Length); + headerStream.Read(this.koreanTitle, 0, this.koreanTitle.Length); + headerStream.Read(this.padding2, 0, this.padding2.Length); + headerStream.Read(this.hash, 0, this.hash.Length); + headerStream.Seek(-16L, SeekOrigin.Current); + headerStream.Write(new byte[16], 0, 16); + byte[] buffer2 = new byte[headerStream.Length]; + headerStream.Seek(0L, SeekOrigin.Begin); + headerStream.Read(buffer2, 0, buffer2.Length); + MD5 md5 = MD5.Create(); + byte[] hash = md5.ComputeHash(buffer2, this.isShortImet ? 0 : 64, 1536); + md5.Clear(); + this.hashesMatch = Shared.CompareByteArrays(hash, this.hash); + } + + private string returnTitleAsString(byte[] title) + { + string empty = string.Empty; + for (int index = 0; index < 84; index += 2) + { + char ch = BitConverter.ToChar(new byte[2] + { + title[index + 1], + title[index] + }, 0); + if (ch != char.MinValue) + empty += (string) (object) ch; + } + return empty; + } + + private void setTitleFromString(string title, int titleIndex) + { + byte[] numArray = new byte[84]; + for (int index = 0; index < title.Length; ++index) + { + byte[] bytes = BitConverter.GetBytes(title[index]); + numArray[index * 2 + 1] = bytes[0]; + numArray[index * 2] = bytes[1]; + } + switch (titleIndex) + { + case 0: + this.japaneseTitle = numArray; + break; + case 1: + this.englishTitle = numArray; + break; + case 2: + this.germanTitle = numArray; + break; + case 3: + this.frenchTitle = numArray; + break; + case 4: + this.spanishTitle = numArray; + break; + case 5: + this.italianTitle = numArray; + break; + case 6: + this.dutchTitle = numArray; + break; + case 7: + this.koreanTitle = numArray; + break; + } + } + } + + public class IMD5 + { + private uint imd5Magic = 1229800501; + private uint fileSize; + private byte[] padding = new byte[8]; + private byte[] hash = new byte[16]; + + public uint FileSize => this.fileSize; + + public byte[] Hash => this.hash; + + private IMD5() + { + } + + public static Headers.IMD5 Load(string pathToFile) => Headers.IMD5.Load(File.ReadAllBytes(pathToFile)); + + public static Headers.IMD5 Load(byte[] fileOrHeader) + { + if (Headers.DetectHeader(fileOrHeader) != Headers.HeaderType.IMD5) + throw new Exception("No IMD5 Header found!"); + Headers.IMD5 imD5 = new Headers.IMD5(); + MemoryStream headerStream = new MemoryStream(fileOrHeader); + try + { + imD5.parseHeader((Stream) headerStream); + } + catch + { + headerStream.Dispose(); + throw; + } + headerStream.Dispose(); + return imD5; + } + + public static Headers.IMD5 Load(Stream fileOrHeader) + { + if (Headers.DetectHeader(fileOrHeader) != Headers.HeaderType.IMD5) + throw new Exception("No IMD5 Header found!"); + Headers.IMD5 imD5 = new Headers.IMD5(); + imD5.parseHeader(fileOrHeader); + return imD5; + } + + public static Headers.IMD5 Create(byte[] file) + { + Headers.IMD5 imD5 = new Headers.IMD5(); + imD5.fileSize = (uint) file.Length; + imD5.computeHash(file); + return imD5; + } + + public static void AddHeader(string pathToFile) + { + byte[] buffer = Headers.IMD5.AddHeader(File.ReadAllBytes(pathToFile)); + File.Delete(pathToFile); + using (FileStream fileStream = new FileStream(pathToFile, FileMode.Create)) + fileStream.Write(buffer, 0, buffer.Length); + } + + public static byte[] AddHeader(byte[] file) + { + Headers.IMD5 imD5 = Headers.IMD5.Create(file); + MemoryStream writeStream = new MemoryStream(); + imD5.writeToStream((Stream) writeStream); + writeStream.Write(file, 0, file.Length); + byte[] array = writeStream.ToArray(); + writeStream.Dispose(); + return array; + } + + public static void RemoveHeader(string pathToFile) + { + byte[] buffer = Headers.IMD5.RemoveHeader(File.ReadAllBytes(pathToFile)); + File.Delete(pathToFile); + using (FileStream fileStream = new FileStream(pathToFile, FileMode.Create)) + fileStream.Write(buffer, 0, buffer.Length); + } + + public static byte[] RemoveHeader(byte[] file) + { + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Write(file, 32, file.Length - 32); + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + return array; + } + + public MemoryStream ToMemoryStream() + { + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + return writeStream; + } + + public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); + + public void Write(Stream writeStream) => this.writeToStream(writeStream); + + private void writeToStream(Stream writeStream) + { + writeStream.Seek(0L, SeekOrigin.Begin); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.imd5Magic)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.fileSize)), 0, 4); + writeStream.Write(this.padding, 0, this.padding.Length); + writeStream.Write(this.hash, 0, this.hash.Length); + } + + private void computeHash(byte[] bytesToHash) + { + MD5 md5 = MD5.Create(); + this.hash = md5.ComputeHash(bytesToHash); + md5.Clear(); + } + + private void parseHeader(Stream headerStream) + { + headerStream.Seek(0L, SeekOrigin.Begin); + byte[] buffer = new byte[4]; + headerStream.Read(buffer, 0, 4); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) this.imd5Magic) + throw new Exception("Invalid Magic!"); + headerStream.Read(buffer, 0, 4); + this.fileSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + headerStream.Read(this.padding, 0, this.padding.Length); + headerStream.Read(this.hash, 0, this.hash.Length); + } + } + } +} diff --git a/libWiiSharp/IosPatcher.cs b/libWiiSharp/IosPatcher.cs new file mode 100644 index 0000000..4bd9f98 --- /dev/null +++ b/libWiiSharp/IosPatcher.cs @@ -0,0 +1,244 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.IosPatcher +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.ComponentModel; +using System.Text; + +namespace libWiiSharp +{ + public class IosPatcher + { + private WAD wadFile; + private int esIndex = -1; + + public void LoadIOS(ref WAD iosWad) + { + if (iosWad.TitleID >> 32 != 1UL || (iosWad.TitleID & (ulong) uint.MaxValue) < 3UL || (iosWad.TitleID & (ulong) uint.MaxValue) > (ulong) byte.MaxValue) + throw new Exception("Only IOS WADs can be patched!"); + this.wadFile = iosWad; + this.getEsIndex(); + } + + public int PatchFakeSigning() => this.esIndex < 0 ? -1 : this.patchFakeSigning(ref this.wadFile.Contents[this.esIndex]); + + public int PatchEsIdentify() => this.esIndex < 0 ? -1 : this.patchEsIdentify(ref this.wadFile.Contents[this.esIndex]); + + public int PatchNandPermissions() => this.esIndex < 0 ? -1 : this.patchNandPermissions(ref this.wadFile.Contents[this.esIndex]); + + public int PatchAll() => this.esIndex < 0 ? -1 : this.patchAll(ref this.wadFile.Contents[this.esIndex]); + + public int PatchFakeSigning(ref byte[] esModule) => this.patchFakeSigning(ref esModule); + + public int PatchEsIdentify(ref byte[] esModule) => this.patchEsIdentify(ref esModule); + + public int PatchNandPermissions(ref byte[] esModule) => this.patchNandPermissions(ref esModule); + + public int PatchAll(ref byte[] esModule) => this.patchAll(ref esModule); + + private int patchFakeSigning(ref byte[] esModule) + { + this.fireDebug("Patching Fakesigning..."); + int num = 0; + byte[] second1 = new byte[4] + { + (byte) 32, + (byte) 7, + (byte) 35, + (byte) 162 + }; + byte[] second2 = new byte[4] + { + (byte) 32, + (byte) 7, + (byte) 75, + (byte) 11 + }; + for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) + { + this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4)) + { + this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 1] = (byte) 0; + firstIndex += 4; + ++num; + } + } + this.fireDebug("Patching Fakesigning Finished... (Patches applied: {0})", (object) num); + return num; + } + + private int patchEsIdentify(ref byte[] esModule) + { + this.fireDebug("Patching ES_Identify..."); + int num = 0; + byte[] second = new byte[4] + { + (byte) 40, + (byte) 3, + (byte) 209, + (byte) 35 + }; + for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) + { + this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 4)) + { + this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = (byte) 0; + esModule[firstIndex + 3] = (byte) 0; + firstIndex += 4; + ++num; + } + } + this.fireDebug("Patching ES_Identify Finished... (Patches applied: {0})", (object) num); + return num; + } + + private int patchNandPermissions(ref byte[] esModule) + { + this.fireDebug("Patching NAND Permissions..."); + int num = 0; + byte[] second = new byte[6] + { + (byte) 66, + (byte) 139, + (byte) 208, + (byte) 1, + (byte) 37, + (byte) 102 + }; + for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex) + { + this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 6)) + { + this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = (byte) 224; + firstIndex += 6; + ++num; + } + } + this.fireDebug("Patching NAND Permissions Finished... (Patches applied: {0})", (object) num); + return num; + } + + private int patchAll(ref byte[] esModule) + { + this.fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions..."); + int num = 0; + byte[] second1 = new byte[4] + { + (byte) 32, + (byte) 7, + (byte) 35, + (byte) 162 + }; + byte[] second2 = new byte[4] + { + (byte) 32, + (byte) 7, + (byte) 75, + (byte) 11 + }; + byte[] second3 = new byte[4] + { + (byte) 40, + (byte) 3, + (byte) 209, + (byte) 35 + }; + byte[] second4 = new byte[6] + { + (byte) 66, + (byte) 139, + (byte) 208, + (byte) 1, + (byte) 37, + (byte) 102 + }; + for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex) + { + this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4)) + { + this.fireDebug(" Patching Fakesigning at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 1] = (byte) 0; + firstIndex += 4; + ++num; + } + else if (Shared.CompareByteArrays(esModule, firstIndex, second3, 0, 4)) + { + this.fireDebug(" Patching ES_Identify at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = (byte) 0; + esModule[firstIndex + 3] = (byte) 0; + firstIndex += 4; + ++num; + } + else if (Shared.CompareByteArrays(esModule, firstIndex, second4, 0, 6)) + { + this.fireDebug(" Patching NAND Permissions at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = (byte) 224; + firstIndex += 6; + ++num; + } + } + this.fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions Finished... (Patches applied: {0})", (object) num); + return num; + } + + private void getEsIndex() + { + this.fireDebug("Scanning for ES Module..."); + string str = "$IOSVersion:"; + for (int index1 = this.wadFile.NumOfContents - 1; index1 >= 0; --index1) + { + this.fireDebug(" Scanning Content #{0} of {1}...", (object) (index1 + 1), (object) this.wadFile.NumOfContents); + this.fireProgress((index1 + 1) * 100 / this.wadFile.NumOfContents); + for (int index2 = 0; index2 < this.wadFile.Contents[index1].Length - 64; ++index2) + { + if (Encoding.ASCII.GetString(this.wadFile.Contents[index1], index2, 12) == str) + { + int index3 = index2 + 12; + while (this.wadFile.Contents[index1][index3] == (byte) 32) + ++index3; + if (Encoding.ASCII.GetString(this.wadFile.Contents[index1], index3, 3) == "ES:") + { + this.fireDebug(" -> ES Module found!"); + this.fireDebug("Scanning for ES Module Finished..."); + this.esIndex = index1; + this.fireProgress(100); + return; + } + } + } + } + this.fireDebug("/!\\/!\\/!\\ ES Module wasn't found! /!\\/!\\/!\\"); + throw new Exception("ES module wasn't found!"); + } + + public event EventHandler Progress; + + public event EventHandler Debug; + + private void fireDebug(string debugMessage, params object[] args) + { + EventHandler debug = this.Debug; + if (debug == null) + return; + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + + private void fireProgress(int progressPercentage) + { + EventHandler progress = this.Progress; + if (progress == null) + return; + progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); + } + } +} diff --git a/libWiiSharp/LowerTitleID.cs b/libWiiSharp/LowerTitleID.cs new file mode 100644 index 0000000..17a0bd2 --- /dev/null +++ b/libWiiSharp/LowerTitleID.cs @@ -0,0 +1,18 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.LowerTitleID +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace libWiiSharp +{ + public enum LowerTitleID : uint + { + SystemTitles = 1, + Channel = 65537, // 0x00010001 + SystemChannels = 65538, // 0x00010002 + GameChannel = 65540, // 0x00010004 + DLC = 65541, // 0x00010005 + HiddenChannels = 65544, // 0x00010008 + } +} diff --git a/libWiiSharp/Lz77.cs b/libWiiSharp/Lz77.cs new file mode 100644 index 0000000..b051409 --- /dev/null +++ b/libWiiSharp/Lz77.cs @@ -0,0 +1,363 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.Lz77 +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.IO; + +namespace libWiiSharp +{ + public class Lz77 + { + private const int N = 4096; + private const int F = 18; + private const int threshold = 2; + private static uint lz77Magic = 1280980791; + private int[] leftSon = new int[4097]; + private int[] rightSon = new int[4353]; + private int[] dad = new int[4097]; + private ushort[] textBuffer = new ushort[4113]; + private int matchPosition; + private int matchLength; + + public static uint Lz77Magic => Lz77.lz77Magic; + + public static bool IsLz77Compressed(string file) => Lz77.IsLz77Compressed(File.ReadAllBytes(file)); + + public static bool IsLz77Compressed(byte[] file) + { + Headers.HeaderType startIndex = Headers.DetectHeader(file); + return (int) Shared.Swap(BitConverter.ToUInt32(file, (int) startIndex)) == (int) Lz77.lz77Magic; + } + + public static bool IsLz77Compressed(Stream file) + { + Headers.HeaderType offset = Headers.DetectHeader(file); + byte[] buffer = new byte[4]; + file.Seek((long) offset, SeekOrigin.Begin); + file.Read(buffer, 0, buffer.Length); + return (int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Lz77.lz77Magic; + } + + public void Compress(string inFile, string outFile) + { + Stream stream; + using (FileStream inFile1 = new FileStream(inFile, FileMode.Open)) + stream = this.compress((Stream) inFile1); + byte[] buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + if (File.Exists(outFile)) + File.Delete(outFile); + using (FileStream fileStream = new FileStream(outFile, FileMode.Create)) + fileStream.Write(buffer, 0, buffer.Length); + } + + public byte[] Compress(byte[] file) => ((MemoryStream) this.compress((Stream) new MemoryStream(file))).ToArray(); + + public Stream Compress(Stream file) => this.compress(file); + + public void Decompress(string inFile, string outFile) + { + Stream stream; + using (FileStream inFile1 = new FileStream(inFile, FileMode.Open)) + stream = this.decompress((Stream) inFile1); + byte[] buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + if (File.Exists(outFile)) + File.Delete(outFile); + using (FileStream fileStream = new FileStream(outFile, FileMode.Create)) + fileStream.Write(buffer, 0, buffer.Length); + } + + public byte[] Decompress(byte[] file) => ((MemoryStream) this.decompress((Stream) new MemoryStream(file))).ToArray(); + + public Stream Decompress(Stream file) => this.decompress(file); + + private Stream decompress(Stream inFile) + { + if (!Lz77.IsLz77Compressed(inFile)) + return inFile; + inFile.Seek(0L, SeekOrigin.Begin); + uint num1 = 0; + Headers.HeaderType offset = Headers.DetectHeader(inFile); + byte[] buffer = new byte[8]; + inFile.Seek((long) offset, SeekOrigin.Begin); + inFile.Read(buffer, 0, 8); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) Lz77.lz77Magic) + { + inFile.Dispose(); + throw new Exception("Invaild Magic!"); + } + if (buffer[4] != (byte) 16) + { + inFile.Dispose(); + throw new Exception("Unsupported Compression Type!"); + } + uint num2 = BitConverter.ToUInt32(buffer, 4) >> 8; + for (int index = 0; index < 4078; ++index) + this.textBuffer[index] = (ushort) 223; + int num3 = 4078; + uint num4 = 7; + int num5 = 7; + MemoryStream memoryStream = new MemoryStream(); +label_10: + while (true) + { + num4 <<= 1; + ++num5; + if (num5 == 8) + { + int num6; + if ((num6 = inFile.ReadByte()) != -1) + { + num4 = (uint) num6; + num5 = 0; + } + else + goto label_24; + } + if (((int) num4 & 128) == 0) + { + int num7; + if ((long) (num7 = inFile.ReadByte()) != inFile.Length - 1L) + { + if (num1 < num2) + memoryStream.WriteByte((byte) num7); + ushort[] textBuffer = this.textBuffer; + int index = num3; + int num8 = index + 1; + int num9 = (int) (byte) num7; + textBuffer[index] = (ushort) num9; + num3 = num8 & 4095; + ++num1; + } + else + goto label_24; + } + else + break; + } + int num10; + int num11; + if ((num10 = inFile.ReadByte()) != -1 && (num11 = inFile.ReadByte()) != -1) + { + int num12 = num11 | num10 << 8 & 3840; + int num13 = (num10 >> 4 & 15) + 2; + for (int index1 = 0; index1 <= num13; ++index1) + { + int num14 = (int) this.textBuffer[num3 - num12 - 1 & 4095]; + if (num1 < num2) + memoryStream.WriteByte((byte) num14); + ushort[] textBuffer = this.textBuffer; + int index2 = num3; + int num15 = index2 + 1; + int num16 = (int) (byte) num14; + textBuffer[index2] = (ushort) num16; + num3 = num15 & 4095; + ++num1; + } + goto label_10; + } +label_24: + return (Stream) memoryStream; + } + + private Stream compress(Stream inFile) + { + if (Lz77.IsLz77Compressed(inFile)) + return inFile; + inFile.Seek(0L, SeekOrigin.Begin); + int num1 = 0; + int[] numArray1 = new int[17]; + uint num2 = (uint) (((int) Convert.ToUInt32(inFile.Length) << 8) + 16); + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(Lz77.lz77Magic)), 0, 4); + memoryStream.Write(BitConverter.GetBytes(num2), 0, 4); + this.InitTree(); + numArray1[0] = 0; + int num3 = 1; + int num4 = 128; + int p = 0; + int r = 4078; + for (int index = p; index < r; ++index) + this.textBuffer[index] = ushort.MaxValue; + int num5; + int num6; + for (num5 = 0; num5 < 18 && (num6 = inFile.ReadByte()) != -1; ++num5) + this.textBuffer[r + num5] = (ushort) num6; + if (num5 == 0) + return inFile; + for (int index = 1; index <= 18; ++index) + this.InsertNode(r - index); + this.InsertNode(r); + do + { + if (this.matchLength > num5) + this.matchLength = num5; + if (this.matchLength <= 2) + { + this.matchLength = 1; + numArray1[num3++] = (int) this.textBuffer[r]; + } + else + { + numArray1[0] |= num4; + int[] numArray2 = numArray1; + int index1 = num3; + int num7 = index1 + 1; + int num8 = (int) (ushort) (r - this.matchPosition - 1 >> 8 & 15) | this.matchLength - 3 << 4; + numArray2[index1] = num8; + int[] numArray3 = numArray1; + int index2 = num7; + num3 = index2 + 1; + int num9 = (int) (ushort) (r - this.matchPosition - 1 & (int) byte.MaxValue); + numArray3[index2] = num9; + } + if ((num4 >>= 1) == 0) + { + for (int index = 0; index < num3; ++index) + memoryStream.WriteByte((byte) numArray1[index]); + num1 += num3; + numArray1[0] = 0; + num3 = 1; + num4 = 128; + } + int matchLength = this.matchLength; + int num10; + int num11; + for (num10 = 0; num10 < matchLength && (num11 = inFile.ReadByte()) != -1; ++num10) + { + this.DeleteNode(p); + this.textBuffer[p] = (ushort) num11; + if (p < 17) + this.textBuffer[p + 4096] = (ushort) num11; + p = p + 1 & 4095; + r = r + 1 & 4095; + this.InsertNode(r); + } + while (num10++ < matchLength) + { + this.DeleteNode(p); + p = p + 1 & 4095; + r = r + 1 & 4095; + if (--num5 != 0) + this.InsertNode(r); + } + } + while (num5 > 0); + if (num3 > 1) + { + for (int index = 0; index < num3; ++index) + memoryStream.WriteByte((byte) numArray1[index]); + num1 += num3; + } + if (num1 % 4 != 0) + { + for (int index = 0; index < 4 - num1 % 4; ++index) + memoryStream.WriteByte((byte) 0); + } + return (Stream) memoryStream; + } + + private void InitTree() + { + for (int index = 4097; index <= 4352; ++index) + this.rightSon[index] = 4096; + for (int index = 0; index < 4096; ++index) + this.dad[index] = 4096; + } + + private void InsertNode(int r) + { + int num1 = 1; + int index = 4097 + (this.textBuffer[r] == ushort.MaxValue ? 0 : (int) this.textBuffer[r]); + this.rightSon[r] = this.leftSon[r] = 4096; + this.matchLength = 0; + int num2; + do + { + do + { + if (num1 >= 0) + { + if (this.rightSon[index] != 4096) + { + index = this.rightSon[index]; + } + else + { + this.rightSon[index] = r; + this.dad[r] = index; + return; + } + } + else if (this.leftSon[index] != 4096) + { + index = this.leftSon[index]; + } + else + { + this.leftSon[index] = r; + this.dad[r] = index; + return; + } + num2 = 1; + while (num2 < 18 && (num1 = (int) this.textBuffer[r + num2] - (int) this.textBuffer[index + num2]) == 0) + ++num2; + } + while (num2 <= this.matchLength); + this.matchPosition = index; + } + while ((this.matchLength = num2) < 18); + this.dad[r] = this.dad[index]; + this.leftSon[r] = this.leftSon[index]; + this.rightSon[r] = this.rightSon[index]; + this.dad[this.leftSon[index]] = r; + this.dad[this.rightSon[index]] = r; + if (this.rightSon[this.dad[index]] == index) + this.rightSon[this.dad[index]] = r; + else + this.leftSon[this.dad[index]] = r; + this.dad[index] = 4096; + } + + private void DeleteNode(int p) + { + if (this.dad[p] == 4096) + return; + int index; + if (this.rightSon[p] == 4096) + index = this.leftSon[p]; + else if (this.leftSon[p] == 4096) + { + index = this.rightSon[p]; + } + else + { + index = this.leftSon[p]; + if (this.rightSon[index] != 4096) + { + do + { + index = this.rightSon[index]; + } + while (this.rightSon[index] != 4096); + this.rightSon[this.dad[index]] = this.leftSon[index]; + this.dad[this.leftSon[index]] = this.dad[index]; + this.leftSon[index] = this.leftSon[p]; + this.dad[this.leftSon[p]] = index; + } + this.rightSon[index] = this.rightSon[p]; + this.dad[this.rightSon[p]] = index; + } + this.dad[index] = this.dad[p]; + if (this.rightSon[this.dad[p]] == p) + this.rightSon[this.dad[p]] = index; + else + this.leftSon[this.dad[p]] = index; + this.dad[p] = 4096; + } + } +} diff --git a/libWiiSharp/MessageEventArgs.cs b/libWiiSharp/MessageEventArgs.cs new file mode 100644 index 0000000..47055ae --- /dev/null +++ b/libWiiSharp/MessageEventArgs.cs @@ -0,0 +1,19 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.MessageEventArgs +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; + +namespace libWiiSharp +{ + public class MessageEventArgs : EventArgs + { + private string message; + + public string Message => this.message; + + public MessageEventArgs(string message) => this.message = message; + } +} diff --git a/libWiiSharp/NusClient.cs b/libWiiSharp/NusClient.cs new file mode 100644 index 0000000..9897ff1 --- /dev/null +++ b/libWiiSharp/NusClient.cs @@ -0,0 +1,444 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.NusClient +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Net; +using System.Security.Cryptography; + +namespace libWiiSharp +{ + public class NusClient : IDisposable + { + private const string WII_NUS_URL = "http://nus.cdn.shop.wii.com/ccs/download/"; + private const string DSI_NUS_URL = "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/"; + private const string WII_USER_AGENT = "wii libnup/1.0"; + private const string DSI_USER_AGENT = "Opera/9.50 (Nintendo; Opera/154; U; Nintendo DS; en)"; + private string nusUrl = "http://nus.cdn.shop.wii.com/ccs/download/"; + private WebClient wcNus = new WebClient(); + private bool useLocalFiles; + private bool continueWithoutTicket; + private int titleversion; + private bool isDisposed; + + public int TitleVersion => this.titleversion; + + public bool UseLocalFiles + { + get => this.useLocalFiles; + set => this.useLocalFiles = value; + } + + public bool ContinueWithoutTicket + { + get => this.continueWithoutTicket; + set => this.continueWithoutTicket = value; + } + + ~NusClient() => this.Dispose(false); + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize((object) this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !this.isDisposed) + this.wcNus.Dispose(); + this.isDisposed = true; + } + + public void ConfigureNusClient(WebClient wcReady) => this.wcNus = wcReady; + + public void SetToWiiServer() + { + this.nusUrl = "http://nus.cdn.shop.wii.com/ccs/download/"; + this.wcNus.Headers.Add("User-Agent", "wii libnup/1.0"); + } + + public void SetToDSiServer() + { + this.nusUrl = "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/"; + this.wcNus.Headers.Add("User-Agent", "Opera/9.50 (Nintendo; Opera/154; U; Nintendo DS; en)"); + } + + public void DownloadTitle( + string titleId, + string titleVersion, + string outputDir, + bool alternative_path, + string wadName, + params StoreType[] storeTypes) + { + if (titleId.Length != 16) + throw new Exception("Title ID must be 16 characters long!"); + this.downloadTitle(titleId, titleVersion, outputDir, alternative_path, wadName, storeTypes); + } + + public TMD DownloadTMD(string titleId, string titleVersion) => titleId.Length == 16 ? this.downloadTmd(titleId, titleVersion) : throw new Exception("Title ID must be 16 characters long!"); + + public Ticket DownloadTicket(string titleId) => titleId.Length == 16 ? this.downloadTicket(titleId) : throw new Exception("Title ID must be 16 characters long!"); + + public byte[] DownloadSingleContent(string titleId, string titleVersion, string contentId) + { + if (titleId.Length != 16) + throw new Exception("Title ID must be 16 characters long!"); + return this.downloadSingleContent(titleId, titleVersion, contentId); + } + + public void DownloadSingleContent( + string titleId, + string titleVersion, + string contentId, + string savePath) + { + if (titleId.Length != 16) + throw new Exception("Title ID must be 16 characters long!"); + if (!Directory.Exists(Path.GetDirectoryName(savePath))) + Directory.CreateDirectory(Path.GetDirectoryName(savePath)); + if (System.IO.File.Exists(savePath)) + System.IO.File.Delete(savePath); + byte[] bytes = this.downloadSingleContent(titleId, titleVersion, contentId); + System.IO.File.WriteAllBytes(savePath, bytes); + } + + private byte[] downloadSingleContent(string titleId, string titleVersion, string contentId) + { + uint num = uint.Parse(contentId, NumberStyles.HexNumber); + contentId = num.ToString("x8"); + this.fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2}...", (object) contentId, (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion); + this.fireDebug(" Checking for Internet connection..."); + if (!this.CheckInet()) + { + this.fireDebug(" Connection not found..."); + throw new Exception("You're not connected to the internet!"); + } + this.fireProgress(0); + string str1 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", (object) titleVersion)); + string str2 = string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId); + string empty = string.Empty; + int contentIndex = 0; + this.fireDebug(" Downloading TMD..."); + byte[] tmdFile = this.wcNus.DownloadData(str2 + str1); + this.fireDebug(" Parsing TMD..."); + TMD tmd = TMD.Load(tmdFile); + this.fireProgress(20); + this.fireDebug(" Looking for Content ID {0} in TMD...", (object) contentId); + bool flag = false; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if ((int) tmd.Contents[index].ContentID == (int) num) + { + this.fireDebug(" Content ID {0} found in TMD...", (object) contentId); + flag = true; + empty = tmd.Contents[index].ContentID.ToString("x8"); + contentIndex = index; + break; + } + } + if (!flag) + { + this.fireDebug(" Content ID {0} wasn't found in TMD...", (object) contentId); + throw new Exception("Content ID wasn't found in the TMD!"); + } + this.fireDebug(" Downloading Ticket..."); + byte[] ticket = this.wcNus.DownloadData(str2 + "cetk"); + this.fireDebug(" Parsing Ticket..."); + Ticket tik = Ticket.Load(ticket); + this.fireProgress(40); + this.fireDebug(" Downloading Content... ({0} bytes)", (object) tmd.Contents[contentIndex].Size); + byte[] content = this.wcNus.DownloadData(str2 + empty); + this.fireProgress(80); + this.fireDebug(" Decrypting Content..."); + byte[] array = this.decryptContent(content, contentIndex, tik, tmd); + Array.Resize(ref array, (int) tmd.Contents[contentIndex].Size); + if (!Shared.CompareByteArrays(SHA1.Create().ComputeHash(array), tmd.Contents[contentIndex].Hash)) + { + this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + throw new Exception("Hashes do not match!"); + } + this.fireProgress(100); + this.fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2} Finished...", (object) contentId, (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion); + return array; + } + + private Ticket downloadTicket(string titleId) + { + if (!this.CheckInet()) + throw new Exception("You're not connected to the internet!"); + return Ticket.Load(this.wcNus.DownloadData(string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId) + "cetk")); + } + + private TMD downloadTmd(string titleId, string titleVersion) + { + if (!this.CheckInet()) + throw new Exception("You're not connected to the internet!"); + return TMD.Load(this.wcNus.DownloadData(string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId) + ("tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", (object) titleVersion))))); + } + + private void downloadTitle( + string titleId, + string titleVersion, + string outputDir, + bool alternative_path, + string wadName, + StoreType[] storeTypes) + { + this.fireDebug("Downloading Title {0} v{1}...", (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion); + if (storeTypes.Length < 1) + { + this.fireDebug(" No store types were defined..."); + throw new Exception("You must at least define one store type!"); + } + string path1 = string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId); + bool flag1 = false; + bool flag2 = false; + bool flag3 = false; + this.fireProgress(0); + foreach (int storeType in storeTypes) + { + switch (storeType) + { + case 0: + this.fireDebug(" [=] Storing Encrypted Content..."); + flag1 = true; + break; + case 1: + this.fireDebug(" [=] Storing Decrypted Content..."); + flag2 = true; + break; + case 2: + this.fireDebug(" [=] Storing WAD..."); + flag3 = true; + break; + case 3: + this.fireDebug(" [=] Storing Decrypted Content..."); + this.fireDebug(" [=] Storing Encrypted Content..."); + this.fireDebug(" [=] Storing WAD..."); + flag2 = true; + flag1 = true; + flag3 = true; + break; + } + } + if (!Directory.Exists(outputDir)) + Directory.CreateDirectory(outputDir); + string path2 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", (object) titleVersion)); + this.fireDebug(" - Downloading TMD..."); + byte[] tmdFile; + TMD tmd; + try + { + tmdFile = this.wcNus.DownloadData(path1 + path2); + tmd = TMD.Load(tmdFile); + } + catch (Exception ex) + { + this.fireDebug(" + Downloading TMD Failed..."); + throw new Exception("Downloading TMD Failed:\n" + ex.Message); + } + if (alternative_path) + { + if (!Directory.Exists(Path.Combine(outputDir, titleId + "v" + (object) tmd.TitleVersion))) + Directory.CreateDirectory(Path.Combine(outputDir, titleId + "v" + (object) tmd.TitleVersion)); + outputDir = Path.Combine(outputDir, titleId + "v" + (object) tmd.TitleVersion); + } + else + { + if (!Directory.Exists(Path.Combine(outputDir, titleId))) + Directory.CreateDirectory(Path.Combine(outputDir, titleId)); + outputDir = Path.Combine(outputDir, titleId); + } + this.fireDebug(" - Parsing TMD..."); + if (string.IsNullOrEmpty(titleVersion)) + this.fireDebug(" + Title Version: {0}", (object) tmd.TitleVersion); + this.fireDebug(" + {0} Contents", (object) tmd.NumOfContents); + if (!alternative_path) + { + if (!Directory.Exists(Path.Combine(outputDir, tmd.TitleVersion.ToString()))) + Directory.CreateDirectory(Path.Combine(outputDir, tmd.TitleVersion.ToString())); + outputDir = Path.Combine(outputDir, tmd.TitleVersion.ToString()); + } + this.titleversion = (int) tmd.TitleVersion; + System.IO.File.WriteAllBytes(Path.Combine(outputDir, path2), tmd.ToByteArray()); + this.fireProgress(5); + this.fireDebug(" - Downloading Ticket..."); + try + { + this.wcNus.DownloadFile(Path.Combine(path1, "cetk"), Path.Combine(outputDir, "cetk")); + } + catch (Exception ex) + { + if (!this.continueWithoutTicket || !flag1) + { + this.fireDebug(" + Downloading Ticket Failed..."); + throw new Exception("Downloading Ticket Failed:\n" + ex.Message); + } + if (!System.IO.File.Exists(Path.Combine(outputDir, "cetk"))) + { + flag2 = false; + flag3 = false; + } + } + this.fireProgress(10); + Ticket tik = new Ticket(); + if (System.IO.File.Exists(Path.Combine(outputDir, "cetk"))) + { + this.fireDebug(" + Parsing Ticket..."); + tik = Ticket.Load(Path.Combine(outputDir, "cetk")); + if (this.nusUrl == "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/") + tik.DSiTicket = true; + } + else + this.fireDebug(" + Ticket Unavailable..."); + string[] strArray = new string[(int) tmd.NumOfContents]; + for (int index = 0; index < (int) tmd.NumOfContents; ++index) + { + this.fireDebug(" - Downloading Content #{0} of {1}... ({2} bytes)", (object) (index + 1), (object) tmd.NumOfContents, (object) tmd.Contents[index].Size); + this.fireProgress((index + 1) * 60 / (int) tmd.NumOfContents + 10); + if (this.useLocalFiles) + { + if (System.IO.File.Exists(Path.Combine(outputDir, tmd.Contents[index].ContentID.ToString("x8")))) + { + this.fireDebug(" + Using Local File, Skipping..."); + continue; + } + } + try + { + this.wcNus.DownloadFile(path1 + tmd.Contents[index].ContentID.ToString("x8"), Path.Combine(outputDir, tmd.Contents[index].ContentID.ToString("x8"))); + strArray[index] = tmd.Contents[index].ContentID.ToString("x8"); + } + catch (Exception ex) + { + this.fireDebug(" - Downloading Content #{0} of {1} failed...", (object) (index + 1), (object) tmd.NumOfContents); + throw new Exception("Downloading Content Failed:\n" + ex.Message); + } + } + if (flag2 || flag3) + { + SHA1 shA1 = SHA1.Create(); + for (int contentIndex = 0; contentIndex < (int) tmd.NumOfContents; ++contentIndex) + { + this.fireDebug(" - Decrypting Content #{0} of {1}...", (object) (contentIndex + 1), (object) tmd.NumOfContents); + this.fireProgress((contentIndex + 1) * 20 / (int) tmd.NumOfContents + 75); + byte[] array = this.decryptContent(System.IO.File.ReadAllBytes(Path.Combine(outputDir, tmd.Contents[contentIndex].ContentID.ToString("x8"))), contentIndex, tik, tmd); + Array.Resize(ref array, (int) tmd.Contents[contentIndex].Size); + if (!Shared.CompareByteArrays(shA1.ComputeHash(array), tmd.Contents[contentIndex].Hash)) + this.fireDebug(" + Hashes do not match! (Invalid Output)"); + System.IO.File.WriteAllBytes(Path.Combine(outputDir, tmd.Contents[contentIndex].ContentID.ToString("x8") + ".app"), array); + } + shA1.Clear(); + } + if (flag3) + { + this.fireDebug(" - Building Certificate Chain..."); + CertificateChain cert = CertificateChain.FromTikTmd(Path.Combine(outputDir, "cetk"), tmdFile); + byte[][] contents = new byte[(int) tmd.NumOfContents][]; + for (int index = 0; index < (int) tmd.NumOfContents; ++index) + contents[index] = System.IO.File.ReadAllBytes(Path.Combine(outputDir, tmd.Contents[index].ContentID.ToString("x8") + ".app")); + this.fireDebug(" - Creating WAD..."); + WAD wad = WAD.Create(cert, tik, tmd, contents); + wad.RemoveFooter(); + wadName = wadName.Replace("[v]", "v" + this.TitleVersion.ToString()); + if (Path.DirectorySeparatorChar.ToString() != "/" && Path.AltDirectorySeparatorChar.ToString() != "/") + wadName = wadName.Replace("/", ""); + if (wadName.Contains(Path.DirectorySeparatorChar.ToString()) || wadName.Contains(Path.AltDirectorySeparatorChar.ToString())) + wad.Save(wadName); + else + wad.Save(Path.Combine(outputDir, wadName)); + } + if (!flag1) + { + this.fireDebug(" - Deleting Encrypted Contents..."); + for (int index = 0; index < strArray.Length; ++index) + { + if (System.IO.File.Exists(Path.Combine(outputDir, strArray[index]))) + System.IO.File.Delete(Path.Combine(outputDir, strArray[index])); + } + } + if (flag3 && !flag2) + { + this.fireDebug(" - Deleting Decrypted Contents..."); + for (int index = 0; index < strArray.Length; ++index) + { + if (System.IO.File.Exists(Path.Combine(outputDir, strArray[index] + ".app"))) + System.IO.File.Delete(Path.Combine(outputDir, strArray[index] + ".app")); + } + } + if (!flag2 && !flag1) + { + this.fireDebug(" - Deleting TMD and Ticket..."); + System.IO.File.Delete(Path.Combine(outputDir, path2)); + System.IO.File.Delete(Path.Combine(outputDir, "cetk")); + } + this.fireDebug("Downloading Title {0} v{1} Finished...", (object) titleId, (object) tmd.TitleVersion); + this.fireProgress(100); + } + + private byte[] decryptContent(byte[] content, int contentIndex, Ticket tik, TMD tmd) + { + Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); + byte[] titleKey = tik.TitleKey; + byte[] numArray = new byte[16]; + byte[] bytes = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); + numArray[0] = bytes[1]; + numArray[1] = bytes[0]; + RijndaelManaged rijndaelManaged = new RijndaelManaged(); + rijndaelManaged.Mode = CipherMode.CBC; + rijndaelManaged.Padding = PaddingMode.None; + rijndaelManaged.KeySize = 128; + rijndaelManaged.BlockSize = 128; + rijndaelManaged.Key = titleKey; + rijndaelManaged.IV = numArray; + ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); + MemoryStream memoryStream = new MemoryStream(content); + CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read); + byte[] buffer = new byte[content.Length]; + cryptoStream.Read(buffer, 0, buffer.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + return buffer; + } + + private bool CheckInet() + { + try + { + Dns.GetHostEntry("www.google.com"); + return true; + } + catch + { + return false; + } + } + + public event EventHandler Progress; + + public event EventHandler Debug; + + private void fireDebug(string debugMessage, params object[] args) + { + EventHandler debug = this.Debug; + if (debug == null) + return; + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + + private void fireProgress(int progressPercentage) + { + EventHandler progress = this.Progress; + if (progress == null) + return; + progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); + } + } +} diff --git a/libWiiSharp/Region.cs b/libWiiSharp/Region.cs new file mode 100644 index 0000000..a2a24a7 --- /dev/null +++ b/libWiiSharp/Region.cs @@ -0,0 +1,16 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.Region +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace libWiiSharp +{ + public enum Region : ushort + { + Japan, + USA, + Europe, + Free, + } +} diff --git a/libWiiSharp/Shared.cs b/libWiiSharp/Shared.cs new file mode 100644 index 0000000..8219879 --- /dev/null +++ b/libWiiSharp/Shared.cs @@ -0,0 +1,148 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.Shared +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Net; + +namespace libWiiSharp +{ + public static class Shared + { + public static string[] MergeStringArrays(string[] a, string[] b) + { + List stringList = new List((IEnumerable) a); + foreach (string str in b) + { + if (!stringList.Contains(str)) + stringList.Add(str); + } + stringList.Sort(); + return stringList.ToArray(); + } + + public static bool CompareByteArrays( + byte[] first, + int firstIndex, + byte[] second, + int secondIndex, + int length) + { + if (first.Length < length || second.Length < length) + return false; + for (int index = 0; index < length; ++index) + { + if ((int) first[firstIndex + index] != (int) second[secondIndex + index]) + return false; + } + return true; + } + + public static bool CompareByteArrays(byte[] first, byte[] second) + { + if (first.Length != second.Length) + return false; + for (int index = 0; index < first.Length; ++index) + { + if ((int) first[index] != (int) second[index]) + return false; + } + return true; + } + + public static string ByteArrayToString(byte[] byteArray, char separator = ' ') + { + string str = string.Empty; + foreach (byte num in byteArray) + str = str + num.ToString("x2").ToUpper() + (object) separator; + return str.Remove(str.Length - 1); + } + + public static byte[] HexStringToByteArray(string hexString) + { + byte[] byteArray = new byte[hexString.Length / 2]; + for (int index = 0; index < hexString.Length / 2; ++index) + byteArray[index] = byte.Parse(hexString.Substring(index * 2, 2), NumberStyles.HexNumber); + return byteArray; + } + + public static int CountCharsInString(string theString, char theChar) + { + int num1 = 0; + foreach (int num2 in theString) + { + if (num2 == (int) theChar) + ++num1; + } + return num1; + } + + public static long AddPadding(long value) => Shared.AddPadding(value, 64); + + public static long AddPadding(long value, int padding) + { + if (value % (long) padding != 0L) + value += (long) padding - value % (long) padding; + return value; + } + + public static int AddPadding(int value) => Shared.AddPadding(value, 64); + + public static int AddPadding(int value, int padding) + { + if (value % padding != 0) + value += padding - value % padding; + return value; + } + + public static ushort Swap(ushort value) => (ushort) IPAddress.HostToNetworkOrder((short) value); + + public static uint Swap(uint value) => (uint) IPAddress.HostToNetworkOrder((int) value); + + public static ulong Swap(ulong value) => (ulong) IPAddress.HostToNetworkOrder((long) value); + + public static byte[] UShortArrayToByteArray(ushort[] array) + { + List byteList = new List(); + foreach (ushort num in array) + { + byte[] bytes = BitConverter.GetBytes(num); + byteList.AddRange((IEnumerable) bytes); + } + return byteList.ToArray(); + } + + public static byte[] UIntArrayToByteArray(uint[] array) + { + List byteList = new List(); + foreach (uint num in array) + { + byte[] bytes = BitConverter.GetBytes(num); + byteList.AddRange((IEnumerable) bytes); + } + return byteList.ToArray(); + } + + public static uint[] ByteArrayToUIntArray(byte[] array) + { + uint[] uintArray = new uint[array.Length / 4]; + int num = 0; + for (int startIndex = 0; startIndex < array.Length; startIndex += 4) + uintArray[num++] = BitConverter.ToUInt32(array, startIndex); + return uintArray; + } + + public static ushort[] ByteArrayToUShortArray(byte[] array) + { + ushort[] ushortArray = new ushort[array.Length / 2]; + int num = 0; + for (int startIndex = 0; startIndex < array.Length; startIndex += 2) + ushortArray[num++] = BitConverter.ToUInt16(array, startIndex); + return ushortArray; + } + } +} diff --git a/libWiiSharp/StoreType.cs b/libWiiSharp/StoreType.cs new file mode 100644 index 0000000..bfddac2 --- /dev/null +++ b/libWiiSharp/StoreType.cs @@ -0,0 +1,17 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.StoreType +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace libWiiSharp +{ + public enum StoreType + { + EncryptedContent, + DecryptedContent, + WAD, + All, + Empty, + } +} diff --git a/libWiiSharp/TMD.cs b/libWiiSharp/TMD.cs new file mode 100644 index 0000000..c7ef129 --- /dev/null +++ b/libWiiSharp/TMD.cs @@ -0,0 +1,490 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.TMD +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; + +namespace libWiiSharp +{ + public class TMD : IDisposable + { + private bool fakeSign; + private uint signatureExponent = 65537; + private byte[] signature = new byte[256]; + private byte[] padding = new byte[60]; + private byte[] issuer = new byte[64]; + private byte version; + private byte caCrlVersion; + private byte signerCrlVersion; + private byte paddingByte; + private ulong startupIos; + private ulong titleId; + private uint titleType; + private ushort groupId; + private ushort padding2; + private ushort region; + private byte[] reserved = new byte[58]; + private uint accessRights; + private ushort titleVersion; + private ushort numOfContents; + private ushort bootIndex; + private ushort padding3; + private List contents; + private bool isDisposed; + + public Region Region + { + get => (Region) this.region; + set => this.region = (ushort) value; + } + + public ulong StartupIOS + { + get => this.startupIos; + set => this.startupIos = value; + } + + public ulong TitleID + { + get => this.titleId; + set => this.titleId = value; + } + + public ushort TitleVersion + { + get => this.titleVersion; + set => this.titleVersion = value; + } + + public ushort NumOfContents => this.numOfContents; + + public ushort BootIndex + { + get => this.bootIndex; + set + { + if ((int) value > (int) this.numOfContents) + return; + this.bootIndex = value; + } + } + + public TMD_Content[] Contents + { + get => this.contents.ToArray(); + set + { + this.contents = new List((IEnumerable) value); + this.numOfContents = (ushort) value.Length; + } + } + + public bool FakeSign + { + get => this.fakeSign; + set => this.fakeSign = value; + } + + ~TMD() => this.Dispose(false); + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize((object) this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !this.isDisposed) + { + this.signature = (byte[]) null; + this.padding = (byte[]) null; + this.issuer = (byte[]) null; + this.reserved = (byte[]) null; + this.contents.Clear(); + this.contents = (List) null; + } + this.isDisposed = true; + } + + public static TMD Load(string pathToTmd) => TMD.Load(File.ReadAllBytes(pathToTmd)); + + public static TMD Load(byte[] tmdFile) + { + TMD tmd = new TMD(); + MemoryStream tmdFile1 = new MemoryStream(tmdFile); + try + { + tmd.parseTmd((Stream) tmdFile1); + } + catch + { + tmdFile1.Dispose(); + throw; + } + tmdFile1.Dispose(); + return tmd; + } + + public static TMD Load(Stream tmd) + { + TMD tmd1 = new TMD(); + tmd1.parseTmd(tmd); + return tmd1; + } + + public void LoadFile(string pathToTmd) => this.LoadFile(File.ReadAllBytes(pathToTmd)); + + public void LoadFile(byte[] tmdFile) + { + MemoryStream tmdFile1 = new MemoryStream(tmdFile); + try + { + this.parseTmd((Stream) tmdFile1); + } + catch + { + tmdFile1.Dispose(); + throw; + } + tmdFile1.Dispose(); + } + + public void LoadFile(Stream tmd) => this.parseTmd(tmd); + + public void Save(string savePath) => this.Save(savePath, false); + + public void Save(string savePath, bool fakeSign) + { + if (fakeSign) + this.fakeSign = true; + if (File.Exists(savePath)) + File.Delete(savePath); + using (FileStream writeStream = new FileStream(savePath, FileMode.Create)) + this.writeToStream((Stream) writeStream); + } + + public MemoryStream ToMemoryStream() => this.ToMemoryStream(false); + + public MemoryStream ToMemoryStream(bool fakeSign) + { + if (fakeSign) + this.fakeSign = true; + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + return writeStream; + } + + public byte[] ToByteArray() => this.ToByteArray(false); + + public byte[] ToByteArray(bool fakeSign) + { + if (fakeSign) + this.fakeSign = true; + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + byte[] array = writeStream.ToArray(); + writeStream.Dispose(); + return array; + } + + public void UpdateContents(string contentDir) + { + bool flag = true; + for (int index = 0; index < this.contents.Count; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + this.contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < this.contents.Count; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + this.contents[index].ContentID.ToString("x8") + ".app")) + throw new Exception("Couldn't find all content files!"); + } + } + byte[][] conts = new byte[this.contents.Count][]; + for (int index = 0; index < this.contents.Count; ++index) + { + string path = contentDir + (object) Path.DirectorySeparatorChar + (flag ? (object) this.contents[index].ContentID.ToString("x8") : (object) this.contents[index].Index.ToString("x8")) + ".app"; + conts[index] = File.ReadAllBytes(path); + } + this.updateContents(conts); + } + + public void UpdateContents(byte[][] contents) => this.updateContents(contents); + + public string GetUpperTitleID() + { + byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint) this.titleId)); + return new string(new char[4] + { + (char) bytes[0], + (char) bytes[1], + (char) bytes[2], + (char) bytes[3] + }); + } + + public string GetNandBlocks() => this.calculateNandBlocks(); + + public void AddContent(TMD_Content content) + { + this.contents.Add(content); + this.numOfContents = (ushort) this.contents.Count; + } + + public void RemoveContent(int contentIndex) + { + for (int index = 0; index < (int) this.numOfContents; ++index) + { + if ((int) this.contents[index].Index == contentIndex) + { + this.contents.RemoveAt(index); + break; + } + } + this.numOfContents = (ushort) this.contents.Count; + } + + public void RemoveContentByID(int contentId) + { + for (int index = 0; index < (int) this.numOfContents; ++index) + { + if ((long) this.contents[index].ContentID == (long) contentId) + { + this.contents.RemoveAt(index); + break; + } + } + this.numOfContents = (ushort) this.contents.Count; + } + + private void writeToStream(Stream writeStream) + { + this.fireDebug("Writing TMD..."); + if (this.fakeSign) + { + this.fireDebug(" Clearing Signature..."); + this.signature = new byte[256]; + } + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Seek(0L, SeekOrigin.Begin); + this.fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.signatureExponent)), 0, 4); + this.fireDebug(" Writing Signature... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.signature, 0, this.signature.Length); + this.fireDebug(" Writing Padding... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.padding, 0, this.padding.Length); + this.fireDebug(" Writing Issuer... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.issuer, 0, this.issuer.Length); + this.fireDebug(" Writing Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(this.version); + this.fireDebug(" Writing CA Crl Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(this.caCrlVersion); + this.fireDebug(" Writing Signer Crl Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(this.signerCrlVersion); + this.fireDebug(" Writing Padding Byte... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(this.paddingByte); + this.fireDebug(" Writing Startup IOS... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.startupIos)), 0, 8); + this.fireDebug(" Writing Title ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleId)), 0, 8); + this.fireDebug(" Writing Title Type... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleType)), 0, 4); + this.fireDebug(" Writing Group ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.groupId)), 0, 2); + this.fireDebug(" Writing Padding2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding2)), 0, 2); + this.fireDebug(" Writing Region... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.region)), 0, 2); + this.fireDebug(" Writing Reserved... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.reserved, 0, this.reserved.Length); + this.fireDebug(" Writing Access Rights... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.accessRights)), 0, 4); + this.fireDebug(" Writing Title Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleVersion)), 0, 2); + this.fireDebug(" Writing NumOfContents... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.numOfContents)), 0, 2); + this.fireDebug(" Writing Boot Index... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.bootIndex)), 0, 2); + this.fireDebug(" Writing Padding3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding3)), 0, 2); + List contentIndicesList = new List(); + for (int index = 0; index < this.contents.Count; ++index) + contentIndicesList.Add(new ContentIndices(index, (int) this.contents[index].Index)); + contentIndicesList.Sort(); + for (int index = 0; index < contentIndicesList.Count; ++index) + { + this.fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper().ToUpper(), (object) (index + 1), (object) this.numOfContents); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].ContentID)), 0, 4); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].Index)), 0, 2); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap((ushort) this.contents[contentIndicesList[index].Index].Type)), 0, 2); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].Size)), 0, 8); + memoryStream.Write(this.contents[contentIndicesList[index].Index].Hash, 0, this.contents[contentIndicesList[index].Index].Hash.Length); + } + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + if (this.fakeSign) + { + this.fireDebug(" Fakesigning TMD..."); + byte[] numArray = new byte[20]; + SHA1 shA1 = SHA1.Create(); + for (ushort index = 0; index < ushort.MaxValue; ++index) + { + byte[] bytes = BitConverter.GetBytes(index); + array[482] = bytes[1]; + array[483] = bytes[0]; + if (shA1.ComputeHash(array)[0] == (byte) 0) + { + this.fireDebug(" -> Signed ({0})", (object) index); + break; + } + if (index == (ushort) 65534) + { + this.fireDebug(" -> Signing Failed..."); + throw new Exception("Fakesigning failed..."); + } + } + shA1.Clear(); + } + writeStream.Seek(0L, SeekOrigin.Begin); + writeStream.Write(array, 0, array.Length); + this.fireDebug("Writing TMD Finished..."); + } + + private void updateContents(byte[][] conts) + { + SHA1 shA1 = SHA1.Create(); + for (int index = 0; index < this.contents.Count; ++index) + { + this.contents[index].Size = (ulong) conts[index].Length; + this.contents[index].Hash = shA1.ComputeHash(conts[index]); + } + shA1.Clear(); + } + + private void parseTmd(Stream tmdFile) + { + this.fireDebug("Pasing TMD..."); + tmdFile.Seek(0L, SeekOrigin.Begin); + byte[] buffer = new byte[8]; + this.fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + this.signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + this.fireDebug(" Reading Signature... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(this.signature, 0, this.signature.Length); + this.fireDebug(" Reading Padding... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(this.padding, 0, this.padding.Length); + this.fireDebug(" Reading Issuer... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(this.issuer, 0, this.issuer.Length); + this.fireDebug(" Reading Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading CA Crl Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading Signer Crl Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading Padding Byte... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + this.version = buffer[0]; + this.caCrlVersion = buffer[1]; + this.signerCrlVersion = buffer[2]; + this.paddingByte = buffer[3]; + this.fireDebug(" Reading Startup IOS... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 8); + this.startupIos = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + this.fireDebug(" Reading Title ID... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 8); + this.titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + this.fireDebug(" Reading Title Type... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + this.titleType = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + this.fireDebug(" Reading Group ID... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 2); + this.groupId = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + this.fireDebug(" Reading Padding2... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 2); + this.padding2 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + this.fireDebug(" Reading Region... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 2); + this.region = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + this.fireDebug(" Reading Reserved... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(this.reserved, 0, this.reserved.Length); + this.fireDebug(" Reading Access Rights... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + this.accessRights = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + this.fireDebug(" Reading Title Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading NumOfContents... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading Boot Index... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading Padding3... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 8); + this.titleVersion = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + this.numOfContents = Shared.Swap(BitConverter.ToUInt16(buffer, 2)); + this.bootIndex = Shared.Swap(BitConverter.ToUInt16(buffer, 4)); + this.padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 6)); + this.contents = new List(); + for (int index = 0; index < (int) this.numOfContents; ++index) + { + this.fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", (object) (index + 1), (object) this.numOfContents, (object) tmdFile.Position.ToString("x8").ToUpper().ToUpper()); + TMD_Content tmdContent = new TMD_Content(); + tmdContent.Hash = new byte[20]; + tmdFile.Read(buffer, 0, 8); + tmdContent.ContentID = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + tmdContent.Index = Shared.Swap(BitConverter.ToUInt16(buffer, 4)); + tmdContent.Type = (ContentType) Shared.Swap(BitConverter.ToUInt16(buffer, 6)); + tmdFile.Read(buffer, 0, 8); + tmdContent.Size = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + tmdFile.Read(tmdContent.Hash, 0, tmdContent.Hash.Length); + this.contents.Add(tmdContent); + } + this.fireDebug("Pasing TMD Finished..."); + } + + private string calculateNandBlocks() + { + int num1 = 0; + int num2 = 0; + for (int index = 0; index < (int) this.numOfContents; ++index) + { + num2 += (int) this.contents[index].Size; + if (this.contents[index].Type == ContentType.Normal) + num1 += (int) this.contents[index].Size; + } + int num3 = (int) Math.Ceiling((double) num1 / 131072.0); + int num4 = (int) Math.Ceiling((double) num2 / 131072.0); + return num3 == num4 ? num4.ToString() : string.Format("{0} - {1}", (object) num3, (object) num4); + } + + public event EventHandler Debug; + + private void fireDebug(string debugMessage, params object[] args) + { + EventHandler debug = this.Debug; + if (debug == null) + return; + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + } +} diff --git a/libWiiSharp/TMD_Content.cs b/libWiiSharp/TMD_Content.cs new file mode 100644 index 0000000..c0b9038 --- /dev/null +++ b/libWiiSharp/TMD_Content.cs @@ -0,0 +1,47 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.TMD_Content +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace libWiiSharp +{ + public class TMD_Content + { + private uint contentId; + private ushort index; + private ushort type; + private ulong size; + private byte[] hash = new byte[20]; + + public uint ContentID + { + get => this.contentId; + set => this.contentId = value; + } + + public ushort Index + { + get => this.index; + set => this.index = value; + } + + public ContentType Type + { + get => (ContentType) this.type; + set => this.type = (ushort) value; + } + + public ulong Size + { + get => this.size; + set => this.size = value; + } + + public byte[] Hash + { + get => this.hash; + set => this.hash = value; + } + } +} diff --git a/libWiiSharp/Ticket.cs b/libWiiSharp/Ticket.cs new file mode 100644 index 0000000..107cbd8 --- /dev/null +++ b/libWiiSharp/Ticket.cs @@ -0,0 +1,478 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.Ticket +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace libWiiSharp +{ + public class Ticket : IDisposable + { + private byte newKeyIndex; + private byte[] decryptedTitleKey = new byte[16]; + private bool fakeSign; + private bool titleKeyChanged; + private byte[] newEncryptedTitleKey = new byte[0]; + private bool reDecrypt; + private uint signatureExponent = 65537; + private byte[] signature = new byte[256]; + private byte[] padding = new byte[60]; + private byte[] issuer = new byte[64]; + private byte[] unknown = new byte[63]; + private byte[] encryptedTitleKey = new byte[16]; + private byte unknown2; + private ulong ticketId; + private uint consoleId; + private ulong titleId; + private ushort unknown3 = ushort.MaxValue; + private ushort numOfDlc; + private ulong unknown4; + private byte padding2; + private byte commonKeyIndex; + private byte[] unknown5 = new byte[48]; + private byte[] unknown6 = new byte[32]; + private ushort padding3; + private uint enableTimeLimit; + private uint timeLimit; + private byte[] padding4 = new byte[88]; + private bool dsitik; + private bool isDisposed; + + public byte[] TitleKey + { + get => this.decryptedTitleKey; + set + { + this.decryptedTitleKey = value; + this.titleKeyChanged = true; + this.reDecrypt = false; + } + } + + public CommonKeyType CommonKeyIndex + { + get => (CommonKeyType) this.newKeyIndex; + set => this.newKeyIndex = (byte) value; + } + + public ulong TicketID + { + get => this.ticketId; + set => this.ticketId = value; + } + + public uint ConsoleID + { + get => this.consoleId; + set => this.consoleId = value; + } + + public ulong TitleID + { + get => this.titleId; + set + { + this.titleId = value; + if (!this.reDecrypt) + return; + this.reDecryptTitleKey(); + } + } + + public ushort NumOfDLC + { + get => this.numOfDlc; + set => this.numOfDlc = value; + } + + public bool FakeSign + { + get => this.fakeSign; + set => this.fakeSign = value; + } + + public bool TitleKeyChanged => this.titleKeyChanged; + + public bool DSiTicket + { + get => this.dsitik; + set + { + this.dsitik = value; + this.decryptTitleKey(); + } + } + + ~Ticket() => this.Dispose(false); + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize((object) this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !this.isDisposed) + { + this.decryptedTitleKey = (byte[]) null; + this.newEncryptedTitleKey = (byte[]) null; + this.signature = (byte[]) null; + this.padding = (byte[]) null; + this.issuer = (byte[]) null; + this.unknown = (byte[]) null; + this.encryptedTitleKey = (byte[]) null; + this.unknown5 = (byte[]) null; + this.unknown6 = (byte[]) null; + this.padding4 = (byte[]) null; + } + this.isDisposed = true; + } + + public static Ticket Load(string pathToTicket) => Ticket.Load(File.ReadAllBytes(pathToTicket)); + + public static Ticket Load(byte[] ticket) + { + Ticket ticket1 = new Ticket(); + MemoryStream ticketFile = new MemoryStream(ticket); + try + { + ticket1.parseTicket((Stream) ticketFile); + } + catch + { + ticketFile.Dispose(); + throw; + } + ticketFile.Dispose(); + return ticket1; + } + + public static Ticket Load(Stream ticket) + { + Ticket ticket1 = new Ticket(); + ticket1.parseTicket(ticket); + return ticket1; + } + + public void LoadFile(string pathToTicket) => this.LoadFile(File.ReadAllBytes(pathToTicket)); + + public void LoadFile(byte[] ticket) + { + MemoryStream ticketFile = new MemoryStream(ticket); + try + { + this.parseTicket((Stream) ticketFile); + } + catch + { + ticketFile.Dispose(); + throw; + } + ticketFile.Dispose(); + } + + public void LoadFile(Stream ticket) => this.parseTicket(ticket); + + public void Save(string savePath) => this.Save(savePath, false); + + public void Save(string savePath, bool fakeSign) + { + if (fakeSign) + this.fakeSign = true; + if (File.Exists(savePath)) + File.Delete(savePath); + using (FileStream writeStream = new FileStream(savePath, FileMode.Create)) + this.writeToStream((Stream) writeStream); + } + + public MemoryStream ToMemoryStream() => this.ToMemoryStream(false); + + public MemoryStream ToMemoryStream(bool fakeSign) + { + if (fakeSign) + this.fakeSign = true; + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + return writeStream; + } + + public byte[] ToByteArray() => this.ToByteArray(false); + + public byte[] ToByteArray(bool fakeSign) + { + if (fakeSign) + this.fakeSign = true; + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + byte[] array = writeStream.ToArray(); + writeStream.Dispose(); + return array; + } + + public void SetTitleKey(string newTitleKey) => this.SetTitleKey(newTitleKey.ToCharArray()); + + public void SetTitleKey(char[] newTitleKey) + { + if (newTitleKey.Length != 16) + throw new Exception("The title key must be 16 characters long!"); + for (int index = 0; index < 16; ++index) + this.encryptedTitleKey[index] = (byte) newTitleKey[index]; + this.decryptTitleKey(); + this.titleKeyChanged = true; + this.reDecrypt = true; + this.newEncryptedTitleKey = this.encryptedTitleKey; + } + + public void SetTitleKey(byte[] newTitleKey) + { + this.encryptedTitleKey = newTitleKey.Length == 16 ? newTitleKey : throw new Exception("The title key must be 16 characters long!"); + this.decryptTitleKey(); + this.titleKeyChanged = true; + this.reDecrypt = true; + this.newEncryptedTitleKey = newTitleKey; + } + + public string GetUpperTitleID() + { + byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint) this.titleId)); + return new string(new char[4] + { + (char) bytes[0], + (char) bytes[1], + (char) bytes[2], + (char) bytes[3] + }); + } + + private void writeToStream(Stream writeStream) + { + this.fireDebug("Writing Ticket..."); + this.fireDebug(" Encrypting Title Key..."); + this.encryptTitleKey(); + this.fireDebug(" -> Decrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.decryptedTitleKey)); + this.fireDebug(" -> Encrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.encryptedTitleKey)); + if (this.fakeSign) + { + this.fireDebug(" Clearing Signature..."); + this.signature = new byte[256]; + } + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Seek(0L, SeekOrigin.Begin); + this.fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.signatureExponent)), 0, 4); + this.fireDebug(" Writing Signature... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.signature, 0, this.signature.Length); + this.fireDebug(" Writing Padding... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.padding, 0, this.padding.Length); + this.fireDebug(" Writing Issuer... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.issuer, 0, this.issuer.Length); + this.fireDebug(" Writing Unknown... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.unknown, 0, this.unknown.Length); + this.fireDebug(" Writing Title Key... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length); + this.fireDebug(" Writing Unknown2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(this.unknown2); + this.fireDebug(" Writing Ticket ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.ticketId)), 0, 8); + this.fireDebug(" Writing Console ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.consoleId)), 0, 4); + this.fireDebug(" Writing Title ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleId)), 0, 8); + this.fireDebug(" Writing Unknwon3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown3)), 0, 2); + this.fireDebug(" Writing NumOfDLC... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.numOfDlc)), 0, 2); + this.fireDebug(" Writing Unknwon4... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown4)), 0, 8); + this.fireDebug(" Writing Padding2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(this.padding2); + this.fireDebug(" Writing Common Key Index... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(this.commonKeyIndex); + this.fireDebug(" Writing Unknown5... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.unknown5, 0, this.unknown5.Length); + this.fireDebug(" Writing Unknown6... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.unknown6, 0, this.unknown6.Length); + this.fireDebug(" Writing Padding3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding3)), 0, 2); + this.fireDebug(" Writing Enable Time Limit... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.enableTimeLimit)), 0, 4); + this.fireDebug(" Writing Time Limit... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.timeLimit)), 0, 4); + this.fireDebug(" Writing Padding4... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(this.padding4, 0, this.padding4.Length); + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + if (this.fakeSign) + { + this.fireDebug(" Fakesigning Ticket..."); + byte[] numArray = new byte[20]; + SHA1 shA1 = SHA1.Create(); + for (ushort index = 0; index < ushort.MaxValue; ++index) + { + byte[] bytes = BitConverter.GetBytes(index); + array[498] = bytes[1]; + array[499] = bytes[0]; + if (shA1.ComputeHash(array)[0] == (byte) 0) + { + this.fireDebug(" -> Signed ({0})", (object) index); + break; + } + if (index == (ushort) 65534) + { + this.fireDebug(" -> Signing Failed..."); + throw new Exception("Fakesigning failed..."); + } + } + shA1.Clear(); + } + writeStream.Seek(0L, SeekOrigin.Begin); + writeStream.Write(array, 0, array.Length); + this.fireDebug("Writing Ticket Finished..."); + } + + private void parseTicket(Stream ticketFile) + { + this.fireDebug("Parsing Ticket..."); + ticketFile.Seek(0L, SeekOrigin.Begin); + byte[] buffer = new byte[8]; + this.fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 4); + this.signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + this.fireDebug(" Reading Signature... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.signature, 0, this.signature.Length); + this.fireDebug(" Reading Padding... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.padding, 0, this.padding.Length); + this.fireDebug(" Reading Issuer... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.issuer, 0, this.issuer.Length); + this.fireDebug(" Reading Unknown... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.unknown, 0, this.unknown.Length); + this.fireDebug(" Reading Title Key... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length); + this.fireDebug(" Reading Unknown2... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + this.unknown2 = (byte) ticketFile.ReadByte(); + this.fireDebug(" Reading Ticket ID.. (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + this.ticketId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + this.fireDebug(" Reading Console ID... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 4); + this.consoleId = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + this.fireDebug(" Reading Title ID... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + this.titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + this.fireDebug(" Reading Unknown3... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading NumOfDLC... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 4); + this.unknown3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + this.numOfDlc = Shared.Swap(BitConverter.ToUInt16(buffer, 2)); + this.fireDebug(" Reading Unknown4... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + this.unknown4 = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + this.fireDebug(" Reading Padding2... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + this.padding2 = (byte) ticketFile.ReadByte(); + this.fireDebug(" Reading Common Key Index... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + this.commonKeyIndex = (byte) ticketFile.ReadByte(); + this.newKeyIndex = this.commonKeyIndex; + this.fireDebug(" Reading Unknown5... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.unknown5, 0, this.unknown5.Length); + this.fireDebug(" Reading Unknown6... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.unknown6, 0, this.unknown6.Length); + this.fireDebug(" Reading Padding3... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 2); + this.padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + this.fireDebug(" Reading Enable Time Limit... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" Reading Time Limit... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + this.enableTimeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + this.timeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 4)); + this.fireDebug(" Reading Padding4... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(this.padding4, 0, this.padding4.Length); + this.fireDebug(" Decrypting Title Key..."); + this.decryptTitleKey(); + this.fireDebug(" -> Encrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.encryptedTitleKey)); + this.fireDebug(" -> Decrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.decryptedTitleKey)); + this.fireDebug("Parsing Ticket Finished..."); + } + + private void decryptTitleKey() + { + byte[] numArray = !this.dsitik ? (this.commonKeyIndex == (byte) 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey()) : CommonKey.GetDSiKey(); + byte[] bytes = BitConverter.GetBytes(Shared.Swap(this.titleId)); + Array.Resize(ref bytes, 16); + RijndaelManaged rijndaelManaged = new RijndaelManaged(); + rijndaelManaged.Mode = CipherMode.CBC; + rijndaelManaged.Padding = PaddingMode.None; + rijndaelManaged.KeySize = 128; + rijndaelManaged.BlockSize = 128; + rijndaelManaged.Key = numArray; + rijndaelManaged.IV = bytes; + ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); + MemoryStream memoryStream = new MemoryStream(this.encryptedTitleKey); + CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read); + cryptoStream.Read(this.decryptedTitleKey, 0, this.decryptedTitleKey.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + decryptor.Dispose(); + rijndaelManaged.Clear(); + } + + private void encryptTitleKey() + { + this.commonKeyIndex = this.newKeyIndex; + byte[] numArray = !this.dsitik ? (this.commonKeyIndex == (byte) 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey()) : CommonKey.GetDSiKey(); + byte[] bytes = BitConverter.GetBytes(Shared.Swap(this.titleId)); + Array.Resize(ref bytes, 16); + RijndaelManaged rijndaelManaged = new RijndaelManaged(); + rijndaelManaged.Mode = CipherMode.CBC; + rijndaelManaged.Padding = PaddingMode.None; + rijndaelManaged.KeySize = 128; + rijndaelManaged.BlockSize = 128; + rijndaelManaged.Key = numArray; + rijndaelManaged.IV = bytes; + ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(); + MemoryStream memoryStream = new MemoryStream(this.decryptedTitleKey); + CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Read); + cryptoStream.Read(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + encryptor.Dispose(); + rijndaelManaged.Clear(); + } + + private void reDecryptTitleKey() + { + this.encryptedTitleKey = this.newEncryptedTitleKey; + this.decryptTitleKey(); + } + + public event EventHandler Debug; + + private void fireDebug(string debugMessage, params object[] args) + { + EventHandler debug = this.Debug; + if (debug == null) + return; + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + } +} diff --git a/libWiiSharp/U8.cs b/libWiiSharp/U8.cs new file mode 100644 index 0000000..78e6392 --- /dev/null +++ b/libWiiSharp/U8.cs @@ -0,0 +1,735 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.U8 +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace libWiiSharp +{ + public class U8 : IDisposable + { + private const int dataPadding = 32; + private Headers.HeaderType headerType; + private object header; + private U8_Header u8Header = new U8_Header(); + private U8_Node rootNode = new U8_Node(); + private List u8Nodes = new List(); + private List stringTable = new List(); + private List data = new List(); + private int iconSize = -1; + private int bannerSize = -1; + private int soundSize = -1; + private bool lz77; + private bool isDisposed; + + public Headers.HeaderType HeaderType => this.headerType; + + public object Header => this.header; + + public U8_Node RootNode => this.rootNode; + + public List Nodes => this.u8Nodes; + + public string[] StringTable => this.stringTable.ToArray(); + + public byte[][] Data => this.data.ToArray(); + + public int NumOfNodes => (int) this.rootNode.SizeOfData - 1; + + public int IconSize => this.iconSize; + + public int BannerSize => this.bannerSize; + + public int SoundSize => this.soundSize; + + public bool Lz77Compress + { + get => this.lz77; + set => this.lz77 = value; + } + + public U8() => this.rootNode.Type = U8_NodeType.Directory; + + ~U8() => this.Dispose(false); + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize((object) this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !this.isDisposed) + { + this.header = (object) null; + this.u8Header = (U8_Header) null; + this.rootNode = (U8_Node) null; + this.u8Nodes.Clear(); + this.u8Nodes = (List) null; + this.stringTable.Clear(); + this.stringTable = (List) null; + this.data.Clear(); + this.data = (List) null; + } + this.isDisposed = true; + } + + public static bool IsU8(string pathToFile) => U8.IsU8(File.ReadAllBytes(pathToFile)); + + public static bool IsU8(byte[] file) + { + if (Lz77.IsLz77Compressed(file)) + { + byte[] file1 = new byte[file.Length > 2000 ? 2000 : file.Length]; + for (int index = 0; index < file1.Length; ++index) + file1[index] = file[index]; + return U8.IsU8(new Lz77().Decompress(file1)); + } + Headers.HeaderType startIndex = Headers.DetectHeader(file); + return Shared.Swap(BitConverter.ToUInt32(file, (int) startIndex)) == 1437218861U; + } + + public static U8 Load(string pathToU8) => U8.Load(File.ReadAllBytes(pathToU8)); + + public static U8 Load(byte[] u8File) + { + U8 u8 = new U8(); + MemoryStream u8File1 = new MemoryStream(u8File); + try + { + u8.parseU8((Stream) u8File1); + } + catch + { + u8File1.Dispose(); + throw; + } + u8File1.Dispose(); + return u8; + } + + public static U8 Load(Stream u8File) + { + U8 u8 = new U8(); + u8.parseU8(u8File); + return u8; + } + + public static U8 FromDirectory(string pathToDirectory) + { + U8 u8 = new U8(); + u8.createFromDir(pathToDirectory); + return u8; + } + + public void LoadFile(string pathToU8) => this.LoadFile(File.ReadAllBytes(pathToU8)); + + public void LoadFile(byte[] u8File) + { + MemoryStream u8File1 = new MemoryStream(u8File); + try + { + this.parseU8((Stream) u8File1); + } + catch + { + u8File1.Dispose(); + throw; + } + u8File1.Dispose(); + } + + public void LoadFile(Stream u8File) => this.parseU8(u8File); + + public void CreateFromDirectory(string pathToDirectory) => this.createFromDir(pathToDirectory); + + public void Save(string savePath) + { + if (File.Exists(savePath)) + File.Delete(savePath); + using (FileStream writeStream = new FileStream(savePath, FileMode.Create)) + this.writeToStream((Stream) writeStream); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + return writeStream; + } + + public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); + + public void Unpack(string saveDir) => this.unpackToDir(saveDir); + + public void Extract(string saveDir) => this.unpackToDir(saveDir); + + public void AddHeaderImet(bool shortImet, params string[] titles) + { + if (this.iconSize == -1) + throw new Exception("icon.bin wasn't found!"); + if (this.bannerSize == -1) + throw new Exception("banner.bin wasn't found!"); + if (this.soundSize == -1) + throw new Exception("sound.bin wasn't found!"); + this.header = (object) Headers.IMET.Create(shortImet, this.iconSize, this.bannerSize, this.soundSize, titles); + this.headerType = shortImet ? Headers.HeaderType.ShortIMET : Headers.HeaderType.IMET; + } + + public void AddHeaderImd5() => this.headerType = Headers.HeaderType.IMD5; + + public void ReplaceFile(int fileIndex, string pathToNewFile, bool changeFileName = false) + { + if (this.u8Nodes[fileIndex].Type == U8_NodeType.Directory) + throw new Exception("You can't replace a directory with a file!"); + this.data[fileIndex] = File.ReadAllBytes(pathToNewFile); + if (changeFileName) + this.stringTable[fileIndex] = Path.GetFileName(pathToNewFile); + if (this.stringTable[fileIndex].ToLower() == "icon.bin") + this.iconSize = this.getRealSize(File.ReadAllBytes(pathToNewFile)); + else if (this.stringTable[fileIndex].ToLower() == "banner.bin") + { + this.bannerSize = this.getRealSize(File.ReadAllBytes(pathToNewFile)); + } + else + { + if (!(this.stringTable[fileIndex].ToLower() == "sound.bin")) + return; + this.soundSize = this.getRealSize(File.ReadAllBytes(pathToNewFile)); + } + } + + public void ReplaceFile(int fileIndex, byte[] newData) + { + if (this.u8Nodes[fileIndex].Type == U8_NodeType.Directory) + throw new Exception("You can't replace a directory with a file!"); + this.data[fileIndex] = newData; + if (this.stringTable[fileIndex].ToLower() == "icon.bin") + this.iconSize = this.getRealSize(newData); + else if (this.stringTable[fileIndex].ToLower() == "banner.bin") + { + this.bannerSize = this.getRealSize(newData); + } + else + { + if (!(this.stringTable[fileIndex].ToLower() == "sound.bin")) + return; + this.soundSize = this.getRealSize(newData); + } + } + + public int GetNodeIndex(string fileOrDirName) + { + for (int index = 0; index < this.u8Nodes.Count; ++index) + { + if (this.stringTable[index].ToLower() == fileOrDirName.ToLower()) + return index; + } + return -1; + } + + public void RenameNode(int index, string newName) => this.stringTable[index] = newName; + + public void RenameNode(string oldName, string newName) => this.stringTable[this.GetNodeIndex(oldName)] = newName; + + public void AddDirectory(string path) => this.addEntry(path, new byte[0]); + + public void AddFile(string path, byte[] data) => this.addEntry(path, data); + + public void RemoveDirectory(string path) => this.removeEntry(path); + + public void RemoveFile(string path) => this.removeEntry(path); + + private void writeToStream(Stream writeStream) + { + this.fireDebug("Writing U8 File..."); + this.fireDebug(" Updating Rootnode..."); + this.rootNode.SizeOfData = (uint) (this.u8Nodes.Count + 1); + MemoryStream writeStream1 = new MemoryStream(); + writeStream1.Seek((long) this.u8Header.OffsetToRootNode + (long) ((this.u8Nodes.Count + 1) * 12), SeekOrigin.Begin); + this.fireDebug(" Writing String Table... (Offset: 0x{0})", (object) writeStream1.Position.ToString("x8").ToUpper()); + writeStream1.WriteByte((byte) 0); + int num = (int) writeStream1.Position - 1; + for (int index = 0; index < this.u8Nodes.Count; ++index) + { + this.fireDebug(" -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", (object) writeStream1.Position.ToString("x8").ToUpper(), (object) (index + 1), (object) this.u8Nodes.Count, (object) this.stringTable[index]); + this.u8Nodes[index].OffsetToName = (ushort) ((ulong) writeStream1.Position - (ulong) num); + byte[] bytes = Encoding.ASCII.GetBytes(this.stringTable[index]); + writeStream1.Write(bytes, 0, bytes.Length); + writeStream1.WriteByte((byte) 0); + } + this.u8Header.HeaderSize = (uint) ((ulong) writeStream1.Position - (ulong) this.u8Header.OffsetToRootNode); + this.u8Header.OffsetToData = 0U; + for (int index = 0; index < this.u8Nodes.Count; ++index) + { + this.fireProgress((index + 1) * 100 / this.u8Nodes.Count); + if (this.u8Nodes[index].Type == U8_NodeType.File) + { + writeStream1.Seek((long) Shared.AddPadding((int) writeStream1.Position, 32), SeekOrigin.Begin); + this.fireDebug(" Writing Data #{1} of {2}... (Offset: 0x{0})", (object) writeStream1.Position.ToString("x8").ToUpper(), (object) (index + 1), (object) this.u8Nodes.Count); + if (this.u8Header.OffsetToData == 0U) + this.u8Header.OffsetToData = (uint) writeStream1.Position; + this.u8Nodes[index].OffsetToData = (uint) writeStream1.Position; + this.u8Nodes[index].SizeOfData = (uint) this.data[index].Length; + writeStream1.Write(this.data[index], 0, this.data[index].Length); + } + else + this.fireDebug(" Node #{0} of {1} is a Directory...", (object) (index + 1), (object) this.u8Nodes.Count); + } + while (writeStream1.Position % 16L != 0L) + writeStream1.WriteByte((byte) 0); + writeStream1.Seek(0L, SeekOrigin.Begin); + this.fireDebug(" Writing Header... (Offset: 0x{0})", (object) writeStream1.Position.ToString("x8").ToUpper()); + this.u8Header.Write((Stream) writeStream1); + this.fireDebug(" Writing Rootnode... (Offset: 0x{0})", (object) writeStream1.Position.ToString("x8").ToUpper()); + this.rootNode.Write((Stream) writeStream1); + for (int index = 0; index < this.u8Nodes.Count; ++index) + { + this.fireDebug(" Writing Node Entry #{1} of {2}... (Offset: 0x{0})", (object) writeStream1.Position.ToString("x8").ToUpper(), (object) (index + 1), (object) this.u8Nodes.Count); + this.u8Nodes[index].Write((Stream) writeStream1); + } + byte[] numArray = writeStream1.ToArray(); + writeStream1.Dispose(); + if (this.lz77) + { + this.fireDebug(" Lz77 Compressing U8 File..."); + numArray = new Lz77().Compress(numArray); + } + if (this.headerType == Headers.HeaderType.IMD5) + { + this.fireDebug(" Adding IMD5 Header..."); + writeStream.Seek(0L, SeekOrigin.Begin); + Headers.IMD5.Create(numArray).Write(writeStream); + } + else if (this.headerType == Headers.HeaderType.IMET || this.headerType == Headers.HeaderType.ShortIMET) + { + this.fireDebug(" Adding IMET Header..."); + ((Headers.IMET) this.header).IconSize = (uint) this.iconSize; + ((Headers.IMET) this.header).BannerSize = (uint) this.bannerSize; + ((Headers.IMET) this.header).SoundSize = (uint) this.soundSize; + writeStream.Seek(0L, SeekOrigin.Begin); + ((Headers.IMET) this.header).Write(writeStream); + } + writeStream.Write(numArray, 0, numArray.Length); + this.fireDebug("Writing U8 File Finished..."); + } + + private void unpackToDir(string saveDir) + { + this.fireDebug("Unpacking U8 File to: {0}", (object) saveDir); + if (!Directory.Exists(saveDir)) + Directory.CreateDirectory(saveDir); + string[] strArray = new string[this.u8Nodes.Count]; + strArray[0] = saveDir; + int[] numArray = new int[this.u8Nodes.Count]; + int index1 = 0; + for (int index2 = 0; index2 < this.u8Nodes.Count; ++index2) + { + this.fireDebug(" Unpacking Entry #{0} of {1}", (object) (index2 + 1), (object) this.u8Nodes.Count); + this.fireProgress((index2 + 1) * 100 / this.u8Nodes.Count); + if (this.u8Nodes[index2].Type == U8_NodeType.Directory) + { + this.fireDebug(" -> Directory: \"{0}\"", (object) this.stringTable[index2]); + if ((int) strArray[index1][strArray[index1].Length - 1] != (int) Path.DirectorySeparatorChar) + strArray[index1] = strArray[index1] + (object) Path.DirectorySeparatorChar; + Directory.CreateDirectory(strArray[index1] + this.stringTable[index2]); + strArray[index1 + 1] = strArray[index1] + this.stringTable[index2]; + ++index1; + numArray[index1] = (int) this.u8Nodes[index2].SizeOfData; + } + else + { + this.fireDebug(" -> File: \"{0}\"", (object) this.stringTable[index2]); + this.fireDebug(" -> Size: {0} bytes", (object) this.data[index2].Length); + using (FileStream fileStream = new FileStream(strArray[index1] + (object) Path.DirectorySeparatorChar + this.stringTable[index2], FileMode.Create)) + fileStream.Write(this.data[index2], 0, this.data[index2].Length); + } + while (index1 > 0 && numArray[index1] == index2 + 2) + --index1; + } + this.fireDebug("Unpacking U8 File Finished"); + } + + private void parseU8(Stream u8File) + { + this.fireDebug("Pasing U8 File..."); + this.u8Header = new U8_Header(); + this.rootNode = new U8_Node(); + this.u8Nodes = new List(); + this.stringTable = new List(); + this.data = new List(); + this.fireDebug(" Detecting Header..."); + this.headerType = Headers.DetectHeader(u8File); + Headers.HeaderType offset = this.headerType; + this.fireDebug(" -> {0}", (object) this.headerType.ToString()); + if (this.headerType == Headers.HeaderType.IMD5) + { + this.fireDebug(" Reading IMD5 Header..."); + this.header = (object) Headers.IMD5.Load(u8File); + byte[] buffer = new byte[u8File.Length]; + u8File.Read(buffer, 0, buffer.Length); + MD5 md5 = MD5.Create(); + byte[] hash = md5.ComputeHash(buffer, (int) this.headerType, (int) ((int) u8File.Length - this.headerType)); + md5.Clear(); + if (!Shared.CompareByteArrays(hash, ((Headers.IMD5) this.header).Hash)) + { + this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + this.fireWarning(string.Format("Hashes of IMD5 header and file do not match! The content might be corrupted!")); + } + } + else if (this.headerType == Headers.HeaderType.IMET || this.headerType == Headers.HeaderType.ShortIMET) + { + this.fireDebug(" Reading IMET Header..."); + this.header = (object) Headers.IMET.Load(u8File); + if (!((Headers.IMET) this.header).HashesMatch) + { + this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + this.fireWarning(string.Format("The hash stored in the IMET header doesn't match the headers hash! The header and/or file might be corrupted!")); + } + } + this.fireDebug(" Checking for Lz77 Compression..."); + if (Lz77.IsLz77Compressed(u8File)) + { + this.fireDebug(" -> Lz77 Compression Found..."); + this.fireDebug(" Decompressing U8 Data..."); + Stream file = new Lz77().Decompress(u8File); + offset = Headers.DetectHeader(file); + u8File = file; + this.lz77 = true; + } + u8File.Seek((long) offset, SeekOrigin.Begin); + byte[] buffer1 = new byte[4]; + this.fireDebug(" Reading U8 Header: Magic... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.u8Header.U8Magic) + { + this.fireDebug(" -> Invalid Magic!"); + throw new Exception("U8 Header: Invalid Magic!"); + } + this.fireDebug(" Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.u8Header.OffsetToRootNode) + { + this.fireDebug(" -> Invalid Offset to Rootnode"); + throw new Exception("U8 Header: Invalid Offset to Rootnode!"); + } + this.fireDebug(" Reading U8 Header: Header Size... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + this.u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + this.fireDebug(" Reading U8 Header: Offset to Data... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + this.u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + u8File.Seek(16L, SeekOrigin.Current); + this.fireDebug(" Reading Rootnode... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + this.rootNode.Type = (U8_NodeType) Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); + this.rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); + u8File.Read(buffer1, 0, 4); + this.rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + u8File.Read(buffer1, 0, 4); + this.rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + int num = (int) ((long) offset + (long) this.u8Header.OffsetToRootNode + (long) (this.rootNode.SizeOfData * 12U)); + int position = (int) u8File.Position; + for (int index = 0; (long) index < (long) (this.rootNode.SizeOfData - 1U); ++index) + { + this.fireDebug(" Reading Node #{1} of {2}... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper(), (object) (index + 1), (object) (uint) ((int) this.rootNode.SizeOfData - 1)); + this.fireProgress((int) ((long) ((index + 1) * 100) / (long) (this.rootNode.SizeOfData - 1U))); + U8_Node u8Node = new U8_Node(); + string empty = string.Empty; + byte[] numArray = new byte[0]; + u8File.Seek((long) position, SeekOrigin.Begin); + this.fireDebug(" -> Reading Node Entry... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + u8Node.Type = (U8_NodeType) Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); + u8Node.OffsetToName = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); + u8File.Read(buffer1, 0, 4); + u8Node.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + u8File.Read(buffer1, 0, 4); + u8Node.SizeOfData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + position = (int) u8File.Position; + this.fireDebug(" -> {0}", (object) u8Node.Type.ToString()); + u8File.Seek((long) (num + (int) u8Node.OffsetToName), SeekOrigin.Begin); + this.fireDebug(" -> Reading Node Name... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + do + { + char ch = (char) u8File.ReadByte(); + if (ch != char.MinValue) + empty += (string) (object) ch; + else + break; + } + while (empty.Length <= (int) byte.MaxValue); + this.fireDebug(" -> {0}", (object) empty); + if (u8Node.Type == U8_NodeType.File) + { + u8File.Seek((long) offset + (long) u8Node.OffsetToData, SeekOrigin.Begin); + this.fireDebug(" -> Reading Node Data (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); + numArray = new byte[(IntPtr) u8Node.SizeOfData]; + u8File.Read(numArray, 0, numArray.Length); + } + if (empty.ToLower() == "icon.bin") + this.iconSize = this.getRealSize(numArray); + else if (empty.ToLower() == "banner.bin") + this.bannerSize = this.getRealSize(numArray); + else if (empty.ToLower() == "sound.bin") + this.soundSize = this.getRealSize(numArray); + this.u8Nodes.Add(u8Node); + this.stringTable.Add(empty); + this.data.Add(numArray); + } + this.fireDebug("Pasing U8 File Finished..."); + } + + private void createFromDir(string path) + { + this.fireDebug("Creating U8 File from: {0}", (object) path); + if ((int) path[path.Length - 1] != (int) Path.DirectorySeparatorChar) + path += (string) (object) Path.DirectorySeparatorChar; + this.fireDebug(" Collecting Content..."); + string[] dirContent = this.getDirContent(path, true); + int num1 = 1; + int num2 = 0; + this.fireDebug(" Creating U8 Header..."); + this.u8Header = new U8_Header(); + this.rootNode = new U8_Node(); + this.u8Nodes = new List(); + this.stringTable = new List(); + this.data = new List(); + this.fireDebug(" Creating Rootnode..."); + this.rootNode.Type = U8_NodeType.Directory; + this.rootNode.OffsetToName = (ushort) 0; + this.rootNode.OffsetToData = 0U; + this.rootNode.SizeOfData = (uint) (dirContent.Length + 1); + for (int index1 = 0; index1 < dirContent.Length; ++index1) + { + this.fireDebug(" Creating Node #{0} of {1}", (object) (index1 + 1), (object) dirContent.Length); + this.fireProgress((index1 + 1) * 100 / dirContent.Length); + U8_Node u8Node = new U8_Node(); + byte[] data = new byte[0]; + string theString = dirContent[index1].Remove(0, path.Length - 1); + if (Directory.Exists(dirContent[index1])) + { + this.fireDebug(" -> Directory"); + u8Node.Type = U8_NodeType.Directory; + u8Node.OffsetToData = (uint) Shared.CountCharsInString(theString, Path.DirectorySeparatorChar); + int num3 = this.u8Nodes.Count + 2; + for (int index2 = 0; index2 < dirContent.Length; ++index2) + { + if (dirContent[index2].Contains(dirContent[index1] + Path.DirectorySeparatorChar.ToString())) + ++num3; + } + u8Node.SizeOfData = (uint) num3; + } + else + { + this.fireDebug(" -> File"); + this.fireDebug(" -> Reading File Data..."); + data = File.ReadAllBytes(dirContent[index1]); + u8Node.Type = U8_NodeType.File; + u8Node.OffsetToData = (uint) num2; + u8Node.SizeOfData = (uint) data.Length; + num2 += Shared.AddPadding(num2 + data.Length, 32); + } + u8Node.OffsetToName = (ushort) num1; + num1 += Path.GetFileName(dirContent[index1]).Length + 1; + this.fireDebug(" -> Reading Name..."); + string fileName = Path.GetFileName(dirContent[index1]); + if (fileName.ToLower() == "icon.bin") + this.iconSize = this.getRealSize(data); + else if (fileName.ToLower() == "banner.bin") + this.bannerSize = this.getRealSize(data); + else if (fileName.ToLower() == "sound.bin") + this.soundSize = this.getRealSize(data); + this.u8Nodes.Add(u8Node); + this.stringTable.Add(fileName); + this.data.Add(data); + } + this.fireDebug(" Updating U8 Header..."); + this.u8Header.HeaderSize = (uint) ((this.u8Nodes.Count + 1) * 12 + num1); + this.u8Header.OffsetToData = (uint) Shared.AddPadding((int) this.u8Header.OffsetToRootNode + (int) this.u8Header.HeaderSize, 32); + this.fireDebug(" Calculating Data Offsets..."); + for (int index = 0; index < this.u8Nodes.Count; ++index) + { + this.fireDebug(" -> Node #{0} of {1}...", (object) (index + 1), (object) this.u8Nodes.Count); + int offsetToData = (int) this.u8Nodes[index].OffsetToData; + this.u8Nodes[index].OffsetToData = (uint) ((ulong) this.u8Header.OffsetToData + (ulong) offsetToData); + } + this.fireDebug("Creating U8 File Finished..."); + } + + private string[] getDirContent(string dir, bool root) + { + string[] files = Directory.GetFiles(dir); + string[] directories = Directory.GetDirectories(dir); + string str1 = ""; + if (!root) + str1 = str1 + dir + "\n"; + for (int index = 0; index < files.Length; ++index) + str1 = str1 + files[index] + "\n"; + foreach (string dir1 in directories) + { + foreach (string str2 in this.getDirContent(dir1, false)) + str1 = str1 + str2 + "\n"; + } + return str1.Split(new char[1]{ '\n' }, StringSplitOptions.RemoveEmptyEntries); + } + + private int getRealSize(byte[] data) + { + if (data[0] != (byte) 73 || data[1] != (byte) 77 || data[2] != (byte) 68 || data[3] != (byte) 53) + return data.Length; + return data[32] == (byte) 76 && data[33] == (byte) 90 && data[34] == (byte) 55 && data[35] == (byte) 55 ? BitConverter.ToInt32(data, 36) >> 8 : data.Length - 32; + } + + private void addEntry(string nodePath, byte[] fileData) + { + if (nodePath.StartsWith("/")) + nodePath = nodePath.Remove(0, 1); + string[] strArray = nodePath.Split('/'); + int index1 = -1; + int num1 = this.u8Nodes.Count > 0 ? this.u8Nodes.Count - 1 : 0; + int num2 = 0; + List intList = new List(); + for (int index2 = 0; index2 < strArray.Length - 1; ++index2) + { + for (int index3 = num2; index3 <= num1; ++index3) + { + if (this.stringTable[index3].ToLower() == strArray[index2].ToLower()) + { + if (index2 == strArray.Length - 2) + index1 = index3; + num1 = (int) this.u8Nodes[index3].SizeOfData - 1; + num2 = index3 + 1; + intList.Add(index3); + break; + } + if (index3 == num1 - 1) + throw new Exception("Path wasn't found!"); + } + } + int num3 = index1 <= -1 ? (this.rootNode.SizeOfData > 1U ? (int) this.rootNode.SizeOfData - 2 : -1) : (int) this.u8Nodes[index1].SizeOfData - 2; + U8_Node u8Node = new U8_Node(); + u8Node.Type = fileData.Length == 0 ? U8_NodeType.Directory : U8_NodeType.File; + u8Node.SizeOfData = fileData.Length == 0 ? (uint) (num3 + 2) : (uint) fileData.Length; + u8Node.OffsetToData = fileData.Length == 0 ? (uint) Shared.CountCharsInString(nodePath, '/') : 0U; + this.stringTable.Insert(num3 + 1, strArray[strArray.Length - 1]); + this.u8Nodes.Insert(num3 + 1, u8Node); + this.data.Insert(num3 + 1, fileData); + ++this.rootNode.SizeOfData; + foreach (int index4 in intList) + { + if (this.u8Nodes[index4].Type == U8_NodeType.Directory) + ++this.u8Nodes[index4].SizeOfData; + } + for (int index5 = num3 + 1; index5 < this.u8Nodes.Count; ++index5) + { + if (this.u8Nodes[index5].Type == U8_NodeType.Directory) + ++this.u8Nodes[index5].SizeOfData; + } + } + + private void removeEntry(string nodePath) + { + if (nodePath.StartsWith("/")) + nodePath = nodePath.Remove(0, 1); + string[] strArray = nodePath.Split('/'); + int index1 = -1; + int num1 = this.u8Nodes.Count - 1; + int num2 = 0; + List intList = new List(); + for (int index2 = 0; index2 < strArray.Length; ++index2) + { + for (int index3 = num2; index3 < num1; ++index3) + { + if (this.stringTable[index3].ToLower() == strArray[index2].ToLower()) + { + if (index2 == strArray.Length - 1) + index1 = index3; + else + intList.Add(index3); + num1 = (int) this.u8Nodes[index3].SizeOfData - 1; + num2 = index3 + 1; + break; + } + if (index3 == num1 - 1) + throw new Exception("Path wasn't found!"); + } + } + int num3 = 0; + if (this.u8Nodes[index1].Type == U8_NodeType.Directory) + { + for (int index4 = (int) this.u8Nodes[index1].SizeOfData - 2; index4 >= index1; --index4) + { + this.stringTable.RemoveAt(index4); + this.u8Nodes.RemoveAt(index4); + this.data.RemoveAt(index4); + ++num3; + } + } + else + { + this.stringTable.RemoveAt(index1); + this.u8Nodes.RemoveAt(index1); + this.data.RemoveAt(index1); + ++num3; + } + this.rootNode.SizeOfData -= (uint) num3; + foreach (int index5 in intList) + { + if (this.u8Nodes[index5].Type == U8_NodeType.Directory) + this.u8Nodes[index5].SizeOfData -= (uint) num3; + } + for (int index6 = index1 + 1; index6 < this.u8Nodes.Count; ++index6) + { + if (this.u8Nodes[index6].Type == U8_NodeType.Directory) + this.u8Nodes[index6].SizeOfData -= (uint) num3; + } + } + + public event EventHandler Progress; + + public event EventHandler Warning; + + public event EventHandler Debug; + + private void fireWarning(string warningMessage) + { + EventHandler warning = this.Warning; + if (warning == null) + return; + warning(new object(), new MessageEventArgs(warningMessage)); + } + + private void fireDebug(string debugMessage, params object[] args) + { + EventHandler debug = this.Debug; + if (debug == null) + return; + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + + private void fireProgress(int progressPercentage) + { + EventHandler progress = this.Progress; + if (progress == null) + return; + progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); + } + } +} diff --git a/libWiiSharp/U8_Header.cs b/libWiiSharp/U8_Header.cs new file mode 100644 index 0000000..526ac8d --- /dev/null +++ b/libWiiSharp/U8_Header.cs @@ -0,0 +1,47 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.U8_Header +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.IO; + +namespace libWiiSharp +{ + public class U8_Header + { + private uint u8Magic = 1437218861; + private uint offsetToRootNode = 32; + private uint headerSize; + private uint offsetToData; + private byte[] padding = new byte[16]; + + public uint U8Magic => this.u8Magic; + + public uint OffsetToRootNode => this.offsetToRootNode; + + public uint HeaderSize + { + get => this.headerSize; + set => this.headerSize = value; + } + + public uint OffsetToData + { + get => this.offsetToData; + set => this.offsetToData = value; + } + + public byte[] Padding => this.padding; + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.u8Magic)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToRootNode)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.headerSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToData)), 0, 4); + writeStream.Write(this.padding, 0, 16); + } + } +} diff --git a/libWiiSharp/U8_Node.cs b/libWiiSharp/U8_Node.cs new file mode 100644 index 0000000..afe4909 --- /dev/null +++ b/libWiiSharp/U8_Node.cs @@ -0,0 +1,51 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.U8_Node +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.IO; + +namespace libWiiSharp +{ + public class U8_Node + { + private ushort type; + private ushort offsetToName; + private uint offsetToData; + private uint sizeOfData; + + public U8_NodeType Type + { + get => (U8_NodeType) this.type; + set => this.type = (ushort) value; + } + + public ushort OffsetToName + { + get => this.offsetToName; + set => this.offsetToName = value; + } + + public uint OffsetToData + { + get => this.offsetToData; + set => this.offsetToData = value; + } + + public uint SizeOfData + { + get => this.sizeOfData; + set => this.sizeOfData = value; + } + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.type)), 0, 2); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToName)), 0, 2); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToData)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.sizeOfData)), 0, 4); + } + } +} diff --git a/libWiiSharp/U8_NodeType.cs b/libWiiSharp/U8_NodeType.cs new file mode 100644 index 0000000..5c41a72 --- /dev/null +++ b/libWiiSharp/U8_NodeType.cs @@ -0,0 +1,14 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.U8_NodeType +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace libWiiSharp +{ + public enum U8_NodeType : ushort + { + File = 0, + Directory = 256, // 0x0100 + } +} diff --git a/libWiiSharp/WAD.cs b/libWiiSharp/WAD.cs new file mode 100644 index 0000000..7b1010e --- /dev/null +++ b/libWiiSharp/WAD.cs @@ -0,0 +1,922 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.WAD +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace libWiiSharp +{ + public class WAD : IDisposable + { + private SHA1 sha = SHA1.Create(); + private DateTime creationTimeUTC = new DateTime(1970, 1, 1); + private bool hasBanner; + private bool lz77CompressBannerAndIcon = true; + private bool lz77DecompressBannerAndIcon; + private bool keepOriginalFooter; + private WAD_Header wadHeader; + private CertificateChain cert = new CertificateChain(); + private Ticket tik = new Ticket(); + private TMD tmd = new TMD(); + private List contents; + private U8 bannerApp = new U8(); + private byte[] footer = new byte[0]; + private bool isDisposed; + + public Region Region + { + get => this.tmd.Region; + set => this.tmd.Region = value; + } + + public int NumOfContents => (int) this.tmd.NumOfContents; + + public byte[][] Contents => this.contents.ToArray(); + + public bool FakeSign + { + get => this.tik.FakeSign && this.tmd.FakeSign; + set + { + this.tik.FakeSign = value; + this.tmd.FakeSign = value; + } + } + + public U8 BannerApp + { + get => this.bannerApp; + set => this.bannerApp = value; + } + + public ulong StartupIOS + { + get => this.tmd.StartupIOS; + set => this.tmd.StartupIOS = value; + } + + public ulong TitleID + { + get => this.tik.TitleID; + set + { + this.tik.TitleID = value; + this.tmd.TitleID = value; + } + } + + public string UpperTitleID => this.tik.GetUpperTitleID(); + + public ushort TitleVersion + { + get => this.tmd.TitleVersion; + set => this.tmd.TitleVersion = value; + } + + public ushort BootIndex + { + get => this.tmd.BootIndex; + set => this.tmd.BootIndex = value; + } + + public DateTime CreationTimeUTC => this.creationTimeUTC; + + public bool HasBanner => this.hasBanner; + + public bool Lz77CompressBannerAndIcon + { + get => this.lz77CompressBannerAndIcon; + set + { + this.lz77CompressBannerAndIcon = value; + if (!value) + return; + this.lz77DecompressBannerAndIcon = false; + } + } + + public bool Lz77DecompressBannerAndIcon + { + get => this.lz77DecompressBannerAndIcon; + set + { + this.lz77DecompressBannerAndIcon = value; + if (!value) + return; + this.lz77CompressBannerAndIcon = false; + } + } + + public string NandBlocks => this.tmd.GetNandBlocks(); + + public string[] ChannelTitles + { + get => this.hasBanner ? ((Headers.IMET) this.bannerApp.Header).AllTitles : new string[0]; + set => this.ChangeChannelTitles(value); + } + + public bool KeepOriginalFooter + { + get => this.keepOriginalFooter; + set => this.keepOriginalFooter = value; + } + + public TMD_Content[] TmdContents => this.tmd.Contents; + + public WAD() + { + this.cert.Debug += new EventHandler(this.cert_Debug); + this.tik.Debug += new EventHandler(this.tik_Debug); + this.tmd.Debug += new EventHandler(this.tmd_Debug); + this.bannerApp.Debug += new EventHandler(this.bannerApp_Debug); + this.bannerApp.Warning += new EventHandler(this.bannerApp_Warning); + } + + ~WAD() => this.Dispose(false); + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize((object) this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !this.isDisposed) + { + this.sha.Clear(); + this.sha = (SHA1) null; + this.wadHeader = (WAD_Header) null; + this.cert.Dispose(); + this.tik.Dispose(); + this.tmd.Dispose(); + this.contents.Clear(); + this.contents = (List) null; + this.bannerApp.Dispose(); + this.footer = (byte[]) null; + } + this.isDisposed = true; + } + + public static WAD Load(string pathToWad) => WAD.Load(File.ReadAllBytes(pathToWad)); + + public static WAD Load(byte[] wadFile) + { + WAD wad = new WAD(); + MemoryStream wadFile1 = new MemoryStream(wadFile); + try + { + wad.parseWad((Stream) wadFile1); + } + catch + { + wadFile1.Dispose(); + throw; + } + wadFile1.Dispose(); + return wad; + } + + public static WAD Load(Stream wad) + { + WAD wad1 = new WAD(); + wad1.parseWad(wad); + return wad1; + } + + public static WAD Create(string contentDir) + { + string[] files1 = Directory.GetFiles(contentDir, "*cert*"); + string[] files2 = Directory.GetFiles(contentDir, "*tik*"); + string[] files3 = Directory.GetFiles(contentDir, "*tmd*"); + CertificateChain cert = CertificateChain.Load(files1[0]); + Ticket tik = Ticket.Load(files2[0]); + TMD tmd = TMD.Load(files3[0]); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].Index.ToString("x8") + ".app")) + throw new Exception("Couldn't find all content files!"); + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + (object) Path.DirectorySeparatorChar + (flag ? (object) tmd.Contents[index].ContentID.ToString("x8") : (object) tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + return WAD.Create(cert, tik, tmd, contents); + } + + public static WAD Create( + string pathToCert, + string pathToTik, + string pathToTmd, + string contentDir) + { + CertificateChain cert = CertificateChain.Load(pathToCert); + Ticket tik = Ticket.Load(pathToTik); + TMD tmd = TMD.Load(pathToTmd); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].Index.ToString("x8") + ".app")) + throw new Exception("Couldn't find all content files!"); + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + (object) Path.DirectorySeparatorChar + (flag ? (object) tmd.Contents[index].ContentID.ToString("x8") : (object) tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + return WAD.Create(cert, tik, tmd, contents); + } + + public static WAD Create(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) => WAD.Create(CertificateChain.Load(cert), Ticket.Load(tik), TMD.Load(tmd), contents); + + public static WAD Create(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) + { + WAD wad = new WAD() + { + cert = cert, + tik = tik, + tmd = tmd, + contents = new List((IEnumerable) contents), + wadHeader = new WAD_Header() + }; + wad.wadHeader.TmdSize = (uint) (484 + tmd.Contents.Length * 36); + int num1 = 0; + for (int index = 0; index < contents.Length - 1; ++index) + num1 += Shared.AddPadding(contents[index].Length); + int num2 = num1 + contents[contents.Length - 1].Length; + wad.wadHeader.ContentSize = (uint) num2; + for (int index = 0; index < wad.tmd.Contents.Length; ++index) + { + if (wad.tmd.Contents[index].Index == (ushort) 0) + { + try + { + wad.bannerApp.LoadFile(contents[index]); + wad.hasBanner = true; + break; + } + catch + { + wad.hasBanner = false; + break; + } + } + } + return wad; + } + + public void LoadFile(string pathToWad) => this.LoadFile(File.ReadAllBytes(pathToWad)); + + public void LoadFile(byte[] wadFile) + { + MemoryStream wadFile1 = new MemoryStream(wadFile); + try + { + this.parseWad((Stream) wadFile1); + } + catch + { + wadFile1.Dispose(); + throw; + } + wadFile1.Dispose(); + } + + public void LoadFile(Stream wad) => this.parseWad(wad); + + public void CreateNew(string contentDir) + { + string[] files1 = Directory.GetFiles(contentDir, "*cert*"); + string[] files2 = Directory.GetFiles(contentDir, "*tik*"); + string[] files3 = Directory.GetFiles(contentDir, "*tmd*"); + CertificateChain cert = CertificateChain.Load(files1[0]); + Ticket tik = Ticket.Load(files2[0]); + TMD tmd = TMD.Load(files3[0]); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].Index.ToString("x8") + ".app")) + throw new Exception("Couldn't find all content files!"); + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + (object) Path.DirectorySeparatorChar + (flag ? (object) tmd.Contents[index].ContentID.ToString("x8") : (object) tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + this.CreateNew(cert, tik, tmd, contents); + } + + public void CreateNew( + string pathToCert, + string pathToTik, + string pathToTmd, + string contentDir) + { + CertificateChain cert = CertificateChain.Load(pathToCert); + Ticket tik = Ticket.Load(pathToTik); + TMD tmd = TMD.Load(pathToTmd); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + tmd.Contents[index].Index.ToString("x8") + ".app")) + throw new Exception("Couldn't find all content files!"); + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + (object) Path.DirectorySeparatorChar + (flag ? (object) tmd.Contents[index].ContentID.ToString("x8") : (object) tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + this.CreateNew(cert, tik, tmd, contents); + } + + public void CreateNew(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) => this.CreateNew(CertificateChain.Load(cert), Ticket.Load(tik), TMD.Load(tmd), contents); + + public void CreateNew(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) + { + this.cert = cert; + this.tik = tik; + this.tmd = tmd; + this.contents = new List((IEnumerable) contents); + this.wadHeader = new WAD_Header(); + this.wadHeader.TmdSize = (uint) (484 + tmd.Contents.Length * 36); + int num = 0; + for (int index = 0; index < contents.Length - 1; ++index) + num += Shared.AddPadding(contents[index].Length); + this.wadHeader.ContentSize = (uint) (num + contents[contents.Length - 1].Length); + for (int index = 0; index < this.tmd.Contents.Length; ++index) + { + if (this.tmd.Contents[index].Index == (ushort) 0) + { + try + { + this.bannerApp.LoadFile(contents[index]); + this.hasBanner = true; + break; + } + catch + { + this.hasBanner = false; + break; + } + } + } + } + + public void Save(string savePath) + { + if (File.Exists(savePath)) + File.Delete(savePath); + using (FileStream writeStream = new FileStream(savePath, FileMode.Create)) + this.writeToStream((Stream) writeStream); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + return writeStream; + } + + public byte[] ToByteArray() + { + MemoryStream writeStream = new MemoryStream(); + try + { + this.writeToStream((Stream) writeStream); + } + catch + { + writeStream.Dispose(); + throw; + } + byte[] array = writeStream.ToArray(); + writeStream.Dispose(); + return array; + } + + public void ChangeTitleID(LowerTitleID lowerID, string upperID) + { + uint num1 = upperID.Length == 4 ? BitConverter.ToUInt32(new byte[4] + { + (byte) upperID[3], + (byte) upperID[2], + (byte) upperID[1], + (byte) upperID[0] + }, 0) : throw new Exception("Upper Title ID must be 4 characters long!"); + ulong num2 = (ulong) lowerID << 32 | (ulong) num1; + this.tik.TitleID = num2; + this.tmd.TitleID = num2; + } + + public void ChangeStartupIOS(int newIos) => this.StartupIOS = 4294967296UL | (ulong) (uint) newIos; + + public void ChangeTitleKey(string newTitleKey) => this.tik.SetTitleKey(newTitleKey); + + public void ChangeTitleKey(char[] newTitleKey) => this.tik.SetTitleKey(newTitleKey); + + public void ChangeTitleKey(byte[] newTitleKey) => this.tik.SetTitleKey(newTitleKey); + + public byte[] GetContentByIndex(int index) + { + for (int index1 = 0; index1 < (int) this.tmd.NumOfContents; ++index1) + { + if ((int) this.tmd.Contents[index1].Index == index) + return this.contents[index1]; + } + throw new Exception(string.Format("Content with index {0} not found!", (object) index)); + } + + public byte[] GetContentByID(int contentID) + { + for (int index = 0; index < (int) this.tmd.NumOfContents; ++index) + { + if ((int) this.tmd.Contents[index].Index == contentID) + return this.contents[index]; + } + throw new Exception(string.Format("Content with content ID {0} not found!", (object) contentID)); + } + + public void ChangeChannelTitles(params string[] newTitles) + { + if (!this.hasBanner) + return; + ((Headers.IMET) this.bannerApp.Header).ChangeTitles(newTitles); + } + + public void AddContent(byte[] newContent, int contentID, int index, ContentType type = ContentType.Normal) + { + this.tmd.AddContent(new TMD_Content() + { + ContentID = (uint) contentID, + Index = (ushort) index, + Type = type, + Size = (ulong) newContent.Length, + Hash = this.sha.ComputeHash(newContent) + }); + this.contents.Add(newContent); + this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); + } + + public void RemoveContent(int index) + { + for (int index1 = 0; index1 < this.tmd.Contents.Length; ++index1) + { + if ((int) this.tmd.Contents[index1].Index == index) + { + this.tmd.RemoveContent(index); + this.contents.RemoveAt(index1); + this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); + return; + } + } + throw new Exception(string.Format("Content with index {0} not found!", (object) index)); + } + + public void RemoveContentByID(int contentID) + { + for (int index = 0; index < this.tmd.Contents.Length; ++index) + { + if ((int) this.tmd.Contents[index].Index == contentID) + { + this.tmd.RemoveContentByID(contentID); + this.contents.RemoveAt(index); + this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); + return; + } + } + throw new Exception(string.Format("Content with content ID {0} not found!", (object) contentID)); + } + + public void RemoveAllContents() + { + if (!this.hasBanner) + { + this.tmd.Contents = new TMD_Content[0]; + this.contents = new List(); + this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); + } + else + { + for (int index = 0; index < (int) this.tmd.NumOfContents; ++index) + { + if (this.tmd.Contents[index].Index == (ushort) 0) + { + byte[] content1 = this.contents[index]; + TMD_Content content2 = this.tmd.Contents[index]; + this.tmd.Contents = new TMD_Content[0]; + this.contents = new List(); + this.tmd.AddContent(content2); + this.contents.Add(content1); + this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); + break; + } + } + } + } + + public void Unpack(string unpackDir, bool nameContentID = false) => this.unpackAll(unpackDir, nameContentID); + + public void RemoveFooter() + { + this.footer = new byte[0]; + this.wadHeader.FooterSize = 0U; + this.keepOriginalFooter = true; + } + + public void AddFooter(byte[] footer) => this.ChangeFooter(footer); + + public void ChangeFooter(byte[] newFooter) + { + if (newFooter.Length % 64 != 0) + Array.Resize(ref newFooter, Shared.AddPadding(newFooter.Length)); + this.footer = newFooter; + this.wadHeader.FooterSize = (uint) newFooter.Length; + this.keepOriginalFooter = true; + } + + private void writeToStream(Stream writeStream) + { + this.fireDebug("Writing Wad..."); + if (!this.keepOriginalFooter) + { + this.fireDebug(" Building Footer Timestamp..."); + this.createFooterTimestamp(); + } + if (this.hasBanner) + { + if (this.lz77CompressBannerAndIcon || this.lz77DecompressBannerAndIcon) + { + for (int index = 0; index < this.bannerApp.Nodes.Count; ++index) + { + if (this.bannerApp.StringTable[index].ToLower() == "icon.bin" || this.bannerApp.StringTable[index].ToLower() == "banner.bin") + { + if (!Lz77.IsLz77Compressed(this.bannerApp.Data[index]) && this.lz77CompressBannerAndIcon) + { + this.fireDebug(" Compressing {0}...", (object) this.bannerApp.StringTable[index]); + byte[] numArray1 = new byte[this.bannerApp.Data[index].Length - 32]; + Array.Copy((Array) this.bannerApp.Data[index], 32, (Array) numArray1, 0, numArray1.Length); + byte[] numArray2 = Headers.IMD5.AddHeader(new Lz77().Compress(numArray1)); + this.bannerApp.Data[index] = numArray2; + this.bannerApp.Nodes[index].SizeOfData = (uint) numArray2.Length; + } + else if (Lz77.IsLz77Compressed(this.bannerApp.Data[index]) && this.lz77DecompressBannerAndIcon) + { + this.fireDebug(" Decompressing {0}...", (object) this.bannerApp.StringTable[index]); + byte[] numArray3 = new byte[this.bannerApp.Data[index].Length - 32]; + Array.Copy((Array) this.bannerApp.Data[index], 32, (Array) numArray3, 0, numArray3.Length); + byte[] numArray4 = Headers.IMD5.AddHeader(new Lz77().Decompress(numArray3)); + this.bannerApp.Data[index] = numArray4; + this.bannerApp.Nodes[index].SizeOfData = (uint) numArray4.Length; + } + } + } + } + for (int index = 0; index < this.contents.Count; ++index) + { + if (this.tmd.Contents[index].Index == (ushort) 0) + { + this.fireDebug(" Saving Banner App..."); + this.contents[index] = this.bannerApp.ToByteArray(); + break; + } + } + } + this.fireDebug(" Updating Header..."); + int num = 0; + for (int index = 0; index < this.contents.Count - 1; ++index) + num += Shared.AddPadding(this.contents[index].Length); + this.wadHeader.ContentSize = (uint) (num + this.contents[this.contents.Count - 1].Length); + this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); + this.fireDebug(" Updating TMD Contents..."); + this.tmd.UpdateContents(this.contents.ToArray()); + this.fireDebug(" Writing Wad Header... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek(0L, SeekOrigin.Begin); + this.wadHeader.Write(writeStream); + this.fireDebug(" Writing Certificate Chain... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); + byte[] byteArray1 = this.cert.ToByteArray(); + writeStream.Write(byteArray1, 0, byteArray1.Length); + this.fireDebug(" Writing Ticket... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); + byte[] byteArray2 = this.tik.ToByteArray(); + writeStream.Write(byteArray2, 0, byteArray2.Length); + this.fireDebug(" Writing TMD... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); + byte[] byteArray3 = this.tmd.ToByteArray(); + writeStream.Write(byteArray3, 0, byteArray3.Length); + List contentIndicesList = new List(); + for (int index = 0; index < this.tmd.Contents.Length; ++index) + contentIndicesList.Add(new ContentIndices(index, (int) this.tmd.Contents[index].Index)); + contentIndicesList.Sort(); + for (int index = 0; index < contentIndicesList.Count; ++index) + { + writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); + this.fireProgress((index + 1) * 100 / this.contents.Count); + this.fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper(), (object) (index + 1), (object) this.contents.Count); + this.fireDebug(" -> Content ID: 0x{0}", (object) this.tmd.Contents[contentIndicesList[index].Index].ContentID.ToString("x8")); + this.fireDebug(" -> Index: 0x{0}", (object) this.tmd.Contents[contentIndicesList[index].Index].Index.ToString("x4")); + this.fireDebug(" -> Type: 0x{0} ({1})", (object) ((ushort) this.tmd.Contents[contentIndicesList[index].Index].Type).ToString("x4"), (object) this.tmd.Contents[contentIndicesList[index].Index].Type.ToString()); + this.fireDebug(" -> Size: {0} bytes", (object) this.tmd.Contents[contentIndicesList[index].Index].Size); + this.fireDebug(" -> Hash: {0}", (object) Shared.ByteArrayToString(this.tmd.Contents[contentIndicesList[index].Index].Hash)); + byte[] buffer = this.encryptContent(this.contents[contentIndicesList[index].Index], contentIndicesList[index].Index); + writeStream.Write(buffer, 0, buffer.Length); + } + if (this.wadHeader.FooterSize > 0U) + { + this.fireDebug(" Writing Footer... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); + writeStream.Write(this.footer, 0, this.footer.Length); + } + while (writeStream.Position % 64L != 0L) + writeStream.WriteByte((byte) 0); + this.fireDebug("Writing Wad Finished... (Written Bytes: {0})", (object) writeStream.Position); + } + + private void unpackAll(string unpackDir, bool nameContentId) + { + this.fireDebug("Unpacking Wad to: {0}", (object) unpackDir); + if (!Directory.Exists(unpackDir)) + Directory.CreateDirectory(unpackDir); + string str = this.tik.TitleID.ToString("x16"); + this.fireDebug(" Saving Certificate Chain: {0}.cert", (object) str); + this.cert.Save(unpackDir + (object) Path.DirectorySeparatorChar + str + ".cert"); + this.fireDebug(" Saving Ticket: {0}.tik", (object) str); + this.tik.Save(unpackDir + (object) Path.DirectorySeparatorChar + str + ".tik"); + this.fireDebug(" Saving TMD: {0}.tmd", (object) str); + this.tmd.Save(unpackDir + (object) Path.DirectorySeparatorChar + str + ".tmd"); + for (int index = 0; index < (int) this.tmd.NumOfContents; ++index) + { + this.fireProgress((index + 1) * 100 / (int) this.tmd.NumOfContents); + this.fireDebug(" Saving Content #{0} of {1}: {2}.app", (object) (index + 1), (object) this.tmd.NumOfContents, nameContentId ? (object) this.tmd.Contents[index].ContentID.ToString("x8") : (object) this.tmd.Contents[index].Index.ToString("x8")); + this.fireDebug(" -> Content ID: 0x{0}", (object) this.tmd.Contents[index].ContentID.ToString("x8")); + this.fireDebug(" -> Index: 0x{0}", (object) this.tmd.Contents[index].Index.ToString("x4")); + this.fireDebug(" -> Type: 0x{0} ({1})", (object) ((ushort) this.tmd.Contents[index].Type).ToString("x4"), (object) this.tmd.Contents[index].Type.ToString()); + this.fireDebug(" -> Size: {0} bytes", (object) this.tmd.Contents[index].Size); + this.fireDebug(" -> Hash: {0}", (object) Shared.ByteArrayToString(this.tmd.Contents[index].Hash)); + using (FileStream fileStream = new FileStream(unpackDir + (object) Path.DirectorySeparatorChar + (nameContentId ? (object) this.tmd.Contents[index].ContentID.ToString("x8") : (object) this.tmd.Contents[index].Index.ToString("x8")) + ".app", FileMode.Create)) + fileStream.Write(this.contents[index], 0, this.contents[index].Length); + } + this.fireDebug(" Saving Footer: {0}.footer", (object) str); + using (FileStream fileStream = new FileStream(unpackDir + (object) Path.DirectorySeparatorChar + str + ".footer", FileMode.Create)) + fileStream.Write(this.footer, 0, this.footer.Length); + this.fireDebug("Unpacking Wad Finished..."); + } + + private void parseWad(Stream wadFile) + { + this.fireDebug("Parsing Wad..."); + wadFile.Seek(0L, SeekOrigin.Begin); + byte[] buffer = new byte[4]; + this.wadHeader = new WAD_Header(); + this.contents = new List(); + this.fireDebug(" Parsing Header... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); + wadFile.Read(buffer, 0, 4); + if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) this.wadHeader.HeaderSize) + throw new Exception("Invalid Headersize!"); + wadFile.Read(buffer, 0, 4); + this.wadHeader.WadType = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + wadFile.Seek(12L, SeekOrigin.Current); + wadFile.Read(buffer, 0, 4); + this.wadHeader.TmdSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + wadFile.Read(buffer, 0, 4); + this.wadHeader.ContentSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + wadFile.Read(buffer, 0, 4); + this.wadHeader.FooterSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + this.fireDebug(" Parsing Certificate Chain... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); + wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); + byte[] numArray1 = new byte[(IntPtr) this.wadHeader.CertSize]; + wadFile.Read(numArray1, 0, numArray1.Length); + this.cert.LoadFile(numArray1); + this.fireDebug(" Parsing Ticket... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); + wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); + byte[] numArray2 = new byte[(IntPtr) this.wadHeader.TicketSize]; + wadFile.Read(numArray2, 0, numArray2.Length); + this.tik.LoadFile(numArray2); + this.fireDebug(" Parsing TMD... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); + wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); + byte[] numArray3 = new byte[(IntPtr) this.wadHeader.TmdSize]; + wadFile.Read(numArray3, 0, numArray3.Length); + this.tmd.LoadFile(numArray3); + if ((long) this.tmd.TitleID != (long) this.tik.TitleID) + this.fireWarning("The Title ID in the Ticket doesn't match the one in the TMD!"); + for (int contentIndex = 0; contentIndex < (int) this.tmd.NumOfContents; ++contentIndex) + { + this.fireProgress((contentIndex + 1) * 100 / (int) this.tmd.NumOfContents); + this.fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", (object) (contentIndex + 1), (object) this.tmd.NumOfContents, (object) wadFile.Position.ToString("x8").ToUpper()); + this.fireDebug(" -> Content ID: 0x{0}", (object) this.tmd.Contents[contentIndex].ContentID.ToString("x8")); + this.fireDebug(" -> Index: 0x{0}", (object) this.tmd.Contents[contentIndex].Index.ToString("x4")); + this.fireDebug(" -> Type: 0x{0} ({1})", (object) ((ushort) this.tmd.Contents[contentIndex].Type).ToString("x4"), (object) this.tmd.Contents[contentIndex].Type.ToString()); + this.fireDebug(" -> Size: {0} bytes", (object) this.tmd.Contents[contentIndex].Size); + this.fireDebug(" -> Hash: {0}", (object) Shared.ByteArrayToString(this.tmd.Contents[contentIndex].Hash)); + wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); + byte[] array = new byte[Shared.AddPadding((int) this.tmd.Contents[contentIndex].Size, 16)]; + wadFile.Read(array, 0, array.Length); + array = this.decryptContent(array, contentIndex); + Array.Resize(ref array, (int) this.tmd.Contents[contentIndex].Size); + if (!Shared.CompareByteArrays(this.tmd.Contents[contentIndex].Hash, this.sha.ComputeHash(array, 0, (int) this.tmd.Contents[contentIndex].Size))) + { + this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + this.fireWarning(string.Format("Content #{0} (Content ID: 0x{1}; Index: 0x{2}): Hashes do not match! The content might be corrupted!", (object) (contentIndex + 1), (object) this.tmd.Contents[contentIndex].ContentID.ToString("x8"), (object) this.tmd.Contents[contentIndex].Index.ToString("x4"))); + } + this.contents.Add(array); + if (this.tmd.Contents[contentIndex].Index == (ushort) 0) + { + try + { + this.bannerApp.LoadFile(array); + this.hasBanner = true; + } + catch + { + this.hasBanner = false; + } + } + } + if (this.wadHeader.FooterSize > 0U) + { + this.fireDebug(" Reading Footer... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); + this.footer = new byte[(IntPtr) this.wadHeader.FooterSize]; + wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); + wadFile.Read(this.footer, 0, this.footer.Length); + this.parseFooterTimestamp(); + } + this.fireDebug("Parsing Wad Finished..."); + } + + private byte[] decryptContent(byte[] content, int contentIndex) + { + int length = content.Length; + Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); + byte[] titleKey = this.tik.TitleKey; + byte[] numArray = new byte[16]; + byte[] bytes = BitConverter.GetBytes(this.tmd.Contents[contentIndex].Index); + numArray[0] = bytes[1]; + numArray[1] = bytes[0]; + RijndaelManaged rijndaelManaged = new RijndaelManaged(); + rijndaelManaged.Mode = CipherMode.CBC; + rijndaelManaged.Padding = PaddingMode.None; + rijndaelManaged.KeySize = 128; + rijndaelManaged.BlockSize = 128; + rijndaelManaged.Key = titleKey; + rijndaelManaged.IV = numArray; + ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); + MemoryStream memoryStream = new MemoryStream(content); + CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read); + byte[] buffer = new byte[length]; + cryptoStream.Read(buffer, 0, buffer.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + return buffer; + } + + private byte[] encryptContent(byte[] content, int contentIndex) + { + Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); + byte[] titleKey = this.tik.TitleKey; + byte[] numArray = new byte[16]; + byte[] bytes = BitConverter.GetBytes(this.tmd.Contents[contentIndex].Index); + numArray[0] = bytes[1]; + numArray[1] = bytes[0]; + RijndaelManaged rijndaelManaged = new RijndaelManaged(); + rijndaelManaged.Mode = CipherMode.CBC; + rijndaelManaged.Padding = PaddingMode.None; + rijndaelManaged.KeySize = 128; + rijndaelManaged.BlockSize = 128; + rijndaelManaged.Key = titleKey; + rijndaelManaged.IV = numArray; + ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(); + MemoryStream memoryStream = new MemoryStream(content); + CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Read); + byte[] buffer = new byte[content.Length]; + cryptoStream.Read(buffer, 0, buffer.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + return buffer; + } + + private void createFooterTimestamp() + { + byte[] bytes = new ASCIIEncoding().GetBytes("TmStmp" + ((int) (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds).ToString()); + Array.Resize(ref bytes, 64); + this.wadHeader.FooterSize = (uint) bytes.Length; + this.footer = bytes; + } + + private void parseFooterTimestamp() + { + this.creationTimeUTC = new DateTime(1970, 1, 1); + if ((this.footer[0] != (byte) 67 || this.footer[1] != (byte) 77 || this.footer[2] != (byte) 105 || this.footer[3] != (byte) 105 || this.footer[4] != (byte) 85 || this.footer[5] != (byte) 84) && (this.footer[0] != (byte) 84 || this.footer[1] != (byte) 109 || this.footer[2] != (byte) 83 || this.footer[3] != (byte) 116 || this.footer[4] != (byte) 109 || this.footer[5] != (byte) 112)) + return; + string s = new ASCIIEncoding().GetString(this.footer, 6, 10); + int result = 0; + if (!int.TryParse(s, out result)) + return; + this.creationTimeUTC = this.creationTimeUTC.AddSeconds((double) result); + } + + public event EventHandler Progress; + + public event EventHandler Warning; + + public event EventHandler Debug; + + private void fireDebug(string debugMessage, params object[] args) + { + EventHandler debug = this.Debug; + if (debug == null) + return; + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + + private void fireWarning(string warningMessage) + { + EventHandler warning = this.Warning; + if (warning == null) + return; + warning(new object(), new MessageEventArgs(warningMessage)); + } + + private void fireProgress(int progressPercentage) + { + EventHandler progress = this.Progress; + if (progress == null) + return; + progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); + } + + private void cert_Debug(object sender, MessageEventArgs e) => this.fireDebug(" Certificate Chain: {0}", (object) e.Message); + + private void tik_Debug(object sender, MessageEventArgs e) => this.fireDebug(" Ticket: {0}", (object) e.Message); + + private void tmd_Debug(object sender, MessageEventArgs e) => this.fireDebug(" TMD: {0}", (object) e.Message); + + private void bannerApp_Debug(object sender, MessageEventArgs e) => this.fireDebug(" BannerApp: {0}", (object) e.Message); + + private void bannerApp_Warning(object sender, MessageEventArgs e) => this.fireWarning(e.Message); + } +} diff --git a/libWiiSharp/WAD_Header.cs b/libWiiSharp/WAD_Header.cs new file mode 100644 index 0000000..b2a8bef --- /dev/null +++ b/libWiiSharp/WAD_Header.cs @@ -0,0 +1,68 @@ +// Decompiled with JetBrains decompiler +// Type: libWiiSharp.WAD_Header +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.IO; + +namespace libWiiSharp +{ + public class WAD_Header + { + private uint headerSize = 32; + private uint wadType = 1232273408; + private uint certSize = 2560; + private uint reserved; + private uint tikSize = 676; + private uint tmdSize; + private uint contentSize; + private uint footerSize; + + public uint HeaderSize => this.headerSize; + + public uint WadType + { + get => this.wadType; + set => this.wadType = value; + } + + public uint CertSize => this.certSize; + + public uint Reserved => this.reserved; + + public uint TicketSize => this.tikSize; + + public uint TmdSize + { + get => this.tmdSize; + set => this.tmdSize = value; + } + + public uint ContentSize + { + get => this.contentSize; + set => this.contentSize = value; + } + + public uint FooterSize + { + get => this.footerSize; + set => this.footerSize = value; + } + + public void Write(Stream writeStream) + { + writeStream.Seek(0L, SeekOrigin.Begin); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.headerSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.wadType)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.certSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.reserved)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.tikSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.tmdSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.contentSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.footerSize)), 0, 4); + } + } +} diff --git a/wmgCMS/WaterMarkTextBox.cs b/wmgCMS/WaterMarkTextBox.cs new file mode 100644 index 0000000..1e9597f --- /dev/null +++ b/wmgCMS/WaterMarkTextBox.cs @@ -0,0 +1,95 @@ +// Decompiled with JetBrains decompiler +// Type: wmgCMS.WaterMarkTextBox +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace wmgCMS +{ + internal class WaterMarkTextBox : TextBox + { + private Font oldFont; + private bool waterMarkTextEnabled; + private Color _waterMarkColor = Color.Gray; + private string _waterMarkText = "Water Mark"; + + public Color WaterMarkColor + { + get => this._waterMarkColor; + set + { + this._waterMarkColor = value; + this.Invalidate(); + } + } + + public string WaterMarkText + { + get => this._waterMarkText; + set + { + this._waterMarkText = value; + this.Invalidate(); + } + } + + public WaterMarkTextBox() => this.JoinEvents(true); + + protected override void OnCreateControl() + { + base.OnCreateControl(); + this.EnableWaterMark(); + } + + protected override void OnPaint(PaintEventArgs args) + { + Font font = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style, this.Font.Unit); + SolidBrush solidBrush = new SolidBrush(this.WaterMarkColor); + PointF point = new PointF((float) ((double) args.ClipRectangle.Width / 2.0 - (double) TextRenderer.MeasureText(this.WaterMarkText, this.Font).Width / 2.0), 0.0f); + args.Graphics.DrawString(this.waterMarkTextEnabled ? this.WaterMarkText : this.Text, font, (Brush) solidBrush, point); + base.OnPaint(args); + } + + private void JoinEvents(bool join) + { + if (!join) + return; + this.TextChanged += new EventHandler(this.WaterMark_Toggel); + this.LostFocus += new EventHandler(this.WaterMark_Toggel); + this.GotFocus += new EventHandler(this.WaterMark_Toggel); + this.MouseCaptureChanged += new EventHandler(this.WaterMark_Toggel); + this.FontChanged += new EventHandler(this.WaterMark_FontChanged); + } + + private void WaterMark_Toggel(object sender, EventArgs args) => this.DisbaleWaterMark(); + + private void EnableWaterMark() + { + this.oldFont = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style, this.Font.Unit); + this.SetStyle(ControlStyles.UserPaint, true); + this.waterMarkTextEnabled = true; + this.Refresh(); + } + + private void DisbaleWaterMark() + { + this.waterMarkTextEnabled = false; + this.SetStyle(ControlStyles.UserPaint, false); + if (this.oldFont == null) + return; + this.Font = new Font(this.oldFont.FontFamily, this.oldFont.Size, this.oldFont.Style, this.oldFont.Unit); + } + + private void WaterMark_FontChanged(object sender, EventArgs args) + { + if (!this.waterMarkTextEnabled) + return; + this.oldFont = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style, this.Font.Unit); + this.Refresh(); + } + } +} diff --git a/wyDay/Controls/CTaskbarList.cs b/wyDay/Controls/CTaskbarList.cs new file mode 100644 index 0000000..e5c3e19 --- /dev/null +++ b/wyDay/Controls/CTaskbarList.cs @@ -0,0 +1,20 @@ +// Decompiled with JetBrains decompiler +// Type: wyDay.Controls.CTaskbarList +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace wyDay.Controls +{ + [ClassInterface(ClassInterfaceType.None)] + [Guid("56FDF344-FD6D-11d0-958A-006097C9A090")] + [ComImport] + internal class CTaskbarList + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public extern CTaskbarList(); + } +} diff --git a/wyDay/Controls/ITaskbarList3.cs b/wyDay/Controls/ITaskbarList3.cs new file mode 100644 index 0000000..0cf4705 --- /dev/null +++ b/wyDay/Controls/ITaskbarList3.cs @@ -0,0 +1,40 @@ +// Decompiled with JetBrains decompiler +// Type: wyDay.Controls.ITaskbarList3 +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace wyDay.Controls +{ + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")] + [ComImport] + internal interface ITaskbarList3 + { + [MethodImpl(MethodImplOptions.PreserveSig)] + void HrInit(); + + [MethodImpl(MethodImplOptions.PreserveSig)] + void AddTab(IntPtr hwnd); + + [MethodImpl(MethodImplOptions.PreserveSig)] + void DeleteTab(IntPtr hwnd); + + [MethodImpl(MethodImplOptions.PreserveSig)] + void ActivateTab(IntPtr hwnd); + + [MethodImpl(MethodImplOptions.PreserveSig)] + void SetActiveAlt(IntPtr hwnd); + + [MethodImpl(MethodImplOptions.PreserveSig)] + void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen); + + void SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal); + + void SetProgressState(IntPtr hwnd, ThumbnailProgressState tbpFlags); + } +} diff --git a/wyDay/Controls/ProgressBarState.cs b/wyDay/Controls/ProgressBarState.cs new file mode 100644 index 0000000..a5c34a5 --- /dev/null +++ b/wyDay/Controls/ProgressBarState.cs @@ -0,0 +1,15 @@ +// Decompiled with JetBrains decompiler +// Type: wyDay.Controls.ProgressBarState +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace wyDay.Controls +{ + public enum ProgressBarState + { + Normal = 1, + Error = 2, + Pause = 3, + } +} diff --git a/wyDay/Controls/ThumbnailProgressState.cs b/wyDay/Controls/ThumbnailProgressState.cs new file mode 100644 index 0000000..e01edb0 --- /dev/null +++ b/wyDay/Controls/ThumbnailProgressState.cs @@ -0,0 +1,17 @@ +// Decompiled with JetBrains decompiler +// Type: wyDay.Controls.ThumbnailProgressState +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +namespace wyDay.Controls +{ + public enum ThumbnailProgressState + { + NoProgress = 0, + Indeterminate = 1, + Normal = 2, + Error = 4, + Paused = 8, + } +} diff --git a/wyDay/Controls/Windows7ProgressBar.cs b/wyDay/Controls/Windows7ProgressBar.cs new file mode 100644 index 0000000..0b0ae59 --- /dev/null +++ b/wyDay/Controls/Windows7ProgressBar.cs @@ -0,0 +1,154 @@ +// Decompiled with JetBrains decompiler +// Type: wyDay.Controls.Windows7ProgressBar +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Windows.Forms; + +namespace wyDay.Controls +{ + [ToolboxBitmap(typeof (ProgressBar))] + public class Windows7ProgressBar : ProgressBar + { + private bool showInTaskbar; + private ProgressBarState m_State = ProgressBarState.Normal; + private ContainerControl ownerForm; + + public Windows7ProgressBar() + { + } + + public Windows7ProgressBar(ContainerControl parentControl) => this.ContainerControl = parentControl; + + public ContainerControl ContainerControl + { + get => this.ownerForm; + set + { + this.ownerForm = value; + if (this.ownerForm.Visible) + return; + ((Form) this.ownerForm).Shown += new EventHandler(this.Windows7ProgressBar_Shown); + } + } + + public override ISite Site + { + set + { + base.Site = value; + if (value == null || !(value.GetService(typeof (IDesignerHost)) is IDesignerHost service)) + return; + this.ContainerControl = service.RootComponent as ContainerControl; + } + } + + private void Windows7ProgressBar_Shown(object sender, EventArgs e) + { + if (this.ShowInTaskbar) + { + if (this.Style != ProgressBarStyle.Marquee) + this.SetValueInTB(); + this.SetStateInTB(); + } + ((Form) this.ownerForm).Shown -= new EventHandler(this.Windows7ProgressBar_Shown); + } + + [DefaultValue(false)] + public bool ShowInTaskbar + { + get => this.showInTaskbar; + set + { + if (this.showInTaskbar == value) + return; + this.showInTaskbar = value; + if (this.ownerForm == null) + return; + if (this.Style != ProgressBarStyle.Marquee) + this.SetValueInTB(); + this.SetStateInTB(); + } + } + + public new int Value + { + get => base.Value; + set + { + base.Value = value; + this.SetValueInTB(); + } + } + + public new ProgressBarStyle Style + { + get => base.Style; + set + { + base.Style = value; + if (!this.showInTaskbar || this.ownerForm == null) + return; + this.SetStateInTB(); + } + } + + [DefaultValue(ProgressBarState.Normal)] + public ProgressBarState State + { + get => this.m_State; + set + { + this.m_State = value; + bool flag = this.Style == ProgressBarStyle.Marquee; + if (flag) + this.Style = ProgressBarStyle.Blocks; + Windows7Taskbar.SendMessage(this.Handle, 1040, (int) value, 0); + if (flag) + this.SetValueInTB(); + else + this.SetStateInTB(); + } + } + + public new void Increment(int value) + { + base.Increment(value); + this.SetValueInTB(); + } + + public new void PerformStep() + { + base.PerformStep(); + this.SetValueInTB(); + } + + private void SetValueInTB() + { + if (!this.showInTaskbar) + return; + Windows7Taskbar.SetProgressValue(this.ownerForm.Handle, (ulong) (this.Value - this.Minimum), (ulong) (this.Maximum - this.Minimum)); + } + + private void SetStateInTB() + { + if (this.ownerForm == null) + return; + ThumbnailProgressState state = ThumbnailProgressState.Normal; + if (!this.showInTaskbar) + state = ThumbnailProgressState.NoProgress; + else if (this.Style == ProgressBarStyle.Marquee) + state = ThumbnailProgressState.Indeterminate; + else if (this.m_State == ProgressBarState.Error) + state = ThumbnailProgressState.Error; + else if (this.m_State == ProgressBarState.Pause) + state = ThumbnailProgressState.Paused; + Windows7Taskbar.SetProgressState(this.ownerForm.Handle, state); + } + } +} diff --git a/wyDay/Controls/Windows7Taskbar.cs b/wyDay/Controls/Windows7Taskbar.cs new file mode 100644 index 0000000..49810d0 --- /dev/null +++ b/wyDay/Controls/Windows7Taskbar.cs @@ -0,0 +1,55 @@ +// Decompiled with JetBrains decompiler +// Type: wyDay.Controls.Windows7Taskbar +// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6 +// Assembly location: C:\dotpeek\NUS Downloader.exe + +using System; +using System.Runtime.InteropServices; + +namespace wyDay.Controls +{ + public static class Windows7Taskbar + { + private static ITaskbarList3 _taskbarList; + private static readonly OperatingSystem osInfo = Environment.OSVersion; + + internal static ITaskbarList3 TaskbarList + { + get + { + if (Windows7Taskbar._taskbarList == null) + { + lock (typeof (Windows7Taskbar)) + { + if (Windows7Taskbar._taskbarList == null) + { + Windows7Taskbar._taskbarList = (ITaskbarList3) new CTaskbarList(); + Windows7Taskbar._taskbarList.HrInit(); + } + } + } + return Windows7Taskbar._taskbarList; + } + } + + internal static bool Windows7OrGreater => Windows7Taskbar.osInfo.Version.Major == 6 && Windows7Taskbar.osInfo.Version.Minor >= 1 || Windows7Taskbar.osInfo.Version.Major > 6; + + public static void SetProgressState(IntPtr hwnd, ThumbnailProgressState state) + { + if (!Windows7Taskbar.Windows7OrGreater) + return; + Windows7Taskbar.TaskbarList.SetProgressState(hwnd, state); + } + + public static void SetProgressValue(IntPtr hwnd, ulong current, ulong maximum) + { + if (!Windows7Taskbar.Windows7OrGreater) + return; + Windows7Taskbar.TaskbarList.SetProgressValue(hwnd, current, maximum); + } + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + internal static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam); + } +}