Decompiled v1.9 Mod with dotPeek

This commit is contained in:
Andreas Bielawski 2022-03-23 17:04:52 +01:00
parent 3ed87d8ea1
commit 30dde55ace
Signed by: Brawl
GPG Key ID: 851D5FF3B79056CA
122 changed files with 9835 additions and 15334 deletions

14
AssemblyInfo.cs Normal file
View File

@ -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")]

View File

@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. 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. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail. 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, 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. 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 For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>. <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with 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 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 Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>. <https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestRunConfiguration name="Local Test Run" id="913cc7e8-5ef9-4d00-9a8b-e0e799870251" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
<Description>This is a default test run configuration for a local test run.</Description>
<TestTypeSpecific />
</TestRunConfiguration>

82
NUS Downloader.csproj Normal file
View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--Project was exported from assembly: C:\dotpeek\NUS Downloader.exe-->
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AssemblyName>NUS Downloader</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<ApplicationVersion>1.0.0.0</ApplicationVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="libWiiSharp\LowerTitleID.cs" />
<Compile Include="libWiiSharp\WAD.cs" />
<Compile Include="libWiiSharp\WAD_Header.cs" />
<Compile Include="libWiiSharp\CommonKeyType.cs" />
<Compile Include="libWiiSharp\Ticket.cs" />
<Compile Include="libWiiSharp\StoreType.cs" />
<Compile Include="libWiiSharp\NusClient.cs" />
<Compile Include="libWiiSharp\U8_NodeType.cs" />
<Compile Include="libWiiSharp\U8.cs" />
<Compile Include="libWiiSharp\U8_Header.cs" />
<Compile Include="libWiiSharp\U8_Node.cs" />
<Compile Include="libWiiSharp\CommonKey.cs" />
<Compile Include="libWiiSharp\Shared.cs" />
<Compile Include="libWiiSharp\MessageEventArgs.cs" />
<Compile Include="libWiiSharp\IosPatcher.cs" />
<Compile Include="libWiiSharp\Headers.cs" />
<Compile Include="libWiiSharp\Lz77.cs" />
<Compile Include="libWiiSharp\CertificateChain.cs" />
<Compile Include="libWiiSharp\ContentType.cs" />
<Compile Include="libWiiSharp\Region.cs" />
<Compile Include="libWiiSharp\TMD.cs" />
<Compile Include="libWiiSharp\TMD_Content.cs" />
<Compile Include="libWiiSharp\ContentIndices.cs" />
<Compile Include="NUS_Downloader\Form1.cs" />
<Compile Include="NUS_Downloader\Database.cs" />
<Compile Include="NUS_Downloader\Program.cs" />
<Compile Include="NUS_Downloader\Properties\Resources.cs" />
<Compile Include="NUS_Downloader\Properties\Settings.cs" />
<Compile Include="wyDay\Controls\ThumbnailProgressState.cs" />
<Compile Include="wyDay\Controls\ITaskbarList3.cs" />
<Compile Include="wyDay\Controls\CTaskbarList.cs" />
<Compile Include="wyDay\Controls\Windows7ProgressBar.cs" />
<Compile Include="wyDay\Controls\ProgressBarState.cs" />
<Compile Include="wyDay\Controls\Windows7Taskbar.cs" />
<Compile Include="wmgCMS\WaterMarkTextBox.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="NUS_Downloader\Form1.resx" />
<EmbeddedResource Include="NUS_Downloader\Properties\Resources.resx" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

BIN
NUS Downloader.pdb Normal file

Binary file not shown.

View File

@ -1,27 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00 Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2010 # Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUS Downloader", "NUS Downloader\NUS Downloader.csproj", "{DB1289FA-BA83-408F-A576-326E5EC4CC6D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUS Downloader", "NUS Downloader.csproj", "{9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}"
EndProject EndProject
Global Global
GlobalSection(SubversionScc) = preSolution
Svn-Managed = True
Manager = AnkhSVN - Subversion Support for Visual Studio
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DB1289FA-BA83-408F-A576-326E5EC4CC6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB1289FA-BA83-408F-A576-326E5EC4CC6D}.Debug|Any CPU.Build.0 = Debug|Any CPU {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB1289FA-BA83-408F-A576-326E5EC4CC6D}.Release|Any CPU.ActiveCfg = Release|Any CPU {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.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}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
VisualSVNWorkingCopyRoot = .
EndGlobalSection
EndGlobal EndGlobal

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
<TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
<RunConfiguration id="913cc7e8-5ef9-4d00-9a8b-e0e799870251" name="Local Test Run" storage="localtestrun.testrunconfig" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, PublicKeyToken=b03f5f7f11d50a3a" />
</TestList>
</TestLists>

View File

@ -1,70 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Runtime.InteropServices;
namespace wyDay.Controls
{
/// <summary>
/// Represents the thumbnail progress bar state.
/// </summary>
public enum ThumbnailProgressState
{
/// <summary>
/// No progress is displayed.
/// </summary>
NoProgress = 0,
/// <summary>
/// The progress is indeterminate (marquee).
/// </summary>
Indeterminate = 0x1,
/// <summary>
/// Normal progress is displayed.
/// </summary>
Normal = 0x2,
/// <summary>
/// An error occurred (red).
/// </summary>
Error = 0x4,
/// <summary>
/// The operation is paused (yellow).
/// </summary>
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 { }
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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];
/// <summary>
/// If false, the Certificate Chain is not complete (i.e. at least one certificate is missing).
/// </summary>
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
/// <summary>
/// Loads a cert file.
/// </summary>
/// <param name="pathToCert"></param>
/// <returns></returns>
public static CertificateChain Load(string pathToCert)
{
return Load(File.ReadAllBytes(pathToCert));
}
/// <summary>
/// Loads a cert file.
/// </summary>
/// <param name="certFile"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Loads a cert file.
/// </summary>
/// <param name="cert"></param>
/// <returns></returns>
public static CertificateChain Load(Stream cert)
{
CertificateChain c = new CertificateChain();
c.parseCert(cert);
return c;
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="pathToTik"></param>
/// <param name="pathToTmd"></param>
/// <returns></returns>
public static CertificateChain FromTikTmd(string pathToTik, string pathToTmd)
{
return FromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd));
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="pathToTik"></param>
/// <param name="pathToTmd"></param>
/// <returns></returns>
public static CertificateChain FromTikTmd(string pathToTik, byte[] tmdFile)
{
return FromTikTmd(File.ReadAllBytes(pathToTik), tmdFile);
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="tikFile"></param>
/// <param name="tmdFile"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="tik"></param>
/// <param name="tmd"></param>
/// <returns></returns>
public static CertificateChain FromTikTmd(Stream tik, Stream tmd)
{
CertificateChain c = new CertificateChain();
c.grabFromTik(tik);
c.grabFromTmd(tmd);
return c;
}
/// <summary>
/// Loads a cert file.
/// </summary>
/// <param name="pathToCert"></param>
public void LoadFile(string pathToCert)
{
LoadFile(File.ReadAllBytes(pathToCert));
}
/// <summary>
/// Loads a cert file.
/// </summary>
/// <param name="certFile"></param>
public void LoadFile(byte[] certFile)
{
MemoryStream ms = new MemoryStream(certFile);
try { parseCert(ms); }
catch { ms.Dispose(); throw; }
ms.Dispose();
}
/// <summary>
/// Loads a cert file.
/// </summary>
/// <param name="cert"></param>
public void LoadFile(Stream cert)
{
parseCert(cert);
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="pathToTik"></param>
/// <param name="pathToTmd"></param>
/// <returns></returns>
public void LoadFromTikTmd(string pathToTik, string pathToTmd)
{
LoadFromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd));
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="pathToTik"></param>
/// <param name="tmdFile"></param>
/// <returns></returns>
public void LoadFromTikTmd(string pathToTik, byte[] tmdFile)
{
LoadFromTikTmd(File.ReadAllBytes(pathToTik), tmdFile);
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="tikFile"></param>
/// <param name="tmdFile"></param>
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!");
}
/// <summary>
/// Grabs certificates from Ticket and Tmd.
/// Ticket and Tmd must contain certs! (They do when they're downloaded from NUS!)
/// </summary>
/// <param name="tik"></param>
/// <param name="tmd"></param>
public void LoadFromTikTmd(Stream tik, Stream tmd)
{
grabFromTik(tik);
grabFromTmd(tmd);
}
/// <summary>
/// Saves the Certificate Chain.
/// </summary>
/// <param name="savePath"></param>
public void Save(string savePath)
{
if (File.Exists(savePath)) File.Delete(savePath);
using (FileStream fs = new FileStream(savePath, FileMode.Create))
writeToStream(fs);
}
/// <summary>
/// Returns the Certificate Chain as a memory stream.
/// </summary>
/// <returns></returns>
public MemoryStream ToMemoryStream()
{
MemoryStream ms = new MemoryStream();
try { writeToStream(ms); }
catch { ms.Dispose(); throw; }
return ms;
}
/// <summary>
/// Returns the Certificate Chain as a byte array.
/// </summary>
/// <returns></returns>
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
/// <summary>
/// Fires debugging messages. You may write them into a log file or log textbox.
/// </summary>
public event EventHandler<MessageEventArgs> Debug;
private void fireDebug(string debugMessage, params object[] args)
{
EventHandler<MessageEventArgs> debug = Debug;
if (debug != null)
debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
}
#endregion
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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();
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

View File

@ -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;
}
/// <summary>
/// Gathers the region based on index
/// </summary>
/// <param name="index">The index.</param>
/// <param name="databasexml">XmlDocument with database inside</param>
/// <returns>Region desc</returns>
private string RegionFromIndex(int index)
{
/* Typical Region XML
* <REGIONS>
<region index="0">41 (All/System)</region>
<region index=1>44 (German)</region>
<region index=2>45 (USA/NTSC)</region>
<region index=3>46 (French)</region>
<region index=4>4A (Japan)</region>
<region index=5>4B (Korea)</region>
<region index=6>4C (Japanese Import to Europe/Australia/PAL)</region>
<region index=7>4D (American Import to Europe/Australia/PAL)</region>
<region index=8>4E (Japanese Import to USA/NTSC)</region>
<region index=9>50 (Europe/PAL)</region>
<region index=10>51 (Korea w/ Japanese Language)</region>
<region index=11>54 (Korea w/ English Language)</region>
<region index=12>58 (Some Homebrew)</region>
</REGIONS>
*/
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)";
}
/// <summary>
/// Selects the database item image.
/// </summary>
/// <param name="ticket">if set to <c>true</c> [ticket].</param>
/// <param name="danger">if set to <c>true</c> [danger].</param>
/// <returns>Correct Image</returns>
private System.Drawing.Image SelectItemImage(bool ticket, bool danger)
{
// All is good, go green...
if ((ticket) && (!danger))
return green;
// There's no ticket, but danger is clear...
if ((!ticket) && (!danger))
return orange;
// DANGER WILL ROBINSON...
if ((ticket) && (danger))
return redgreen;
// Double bad...
if ((!ticket) && (danger))
return redorange;
return null;
}
/// <summary>
/// Loads the region codes.
/// </summary>
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;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.IO;
using System.Security.Cryptography;
namespace libWiiSharp
{
public class Headers
{
private static uint imd5Magic = 0x494d4435;
private static uint imetMagic = 0x494d4554;
/// <summary>
/// Convert HeaderType to int to get it's Length.
/// </summary>
public enum HeaderType
{
None = 0,
/// <summary>
/// Used in opening.bnr
/// </summary>
ShortIMET = 1536,
/// <summary>
/// Used in 00000000.app
/// </summary>
IMET = 1600,
/// <summary>
/// Used in banner.bin / icon.bin
/// </summary>
IMD5 = 32,
}
#region Public Functions
/// <summary>
/// Checks a file for Headers.
/// </summary>
/// <param name="pathToFile"></param>
/// <returns></returns>
public static HeaderType DetectHeader(string pathToFile)
{
return DetectHeader(File.ReadAllBytes(pathToFile));
}
/// <summary>
/// Checks the byte array for Headers.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Checks the stream for Headers.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
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];
/// <summary>
/// Short IMET has a padding of 64 bytes at the beginning while Long IMET has 128.
/// </summary>
public bool IsShortIMET { get { return isShortImet; } set { isShortImet = value; } }
/// <summary>
/// The size of uncompressed icon.bin
/// </summary>
public uint IconSize { get { return iconSize; } set { iconSize = value; } }
/// <summary>
/// The size of uncompressed banner.bin
/// </summary>
public uint BannerSize { get { return bannerSize; } set { bannerSize = value; } }
/// <summary>
/// The size of uncompressed sound.bin
/// </summary>
public uint SoundSize { get { return soundSize; } set { soundSize = value; } }
/// <summary>
/// The japanese Title.
/// </summary>
public string JapaneseTitle { get { return returnTitleAsString(japaneseTitle); } set { setTitleFromString(value, 0); } }
/// <summary>
/// The english Title.
/// </summary>
public string EnglishTitle { get { return returnTitleAsString(englishTitle); } set { setTitleFromString(value, 1); } }
/// <summary>
/// The german Title.
/// </summary>
public string GermanTitle { get { return returnTitleAsString(germanTitle); } set { setTitleFromString(value, 2); } }
/// <summary>
/// The french Title.
/// </summary>
public string FrenchTitle { get { return returnTitleAsString(frenchTitle); } set { setTitleFromString(value, 3); } }
/// <summary>
/// The spanish Title.
/// </summary>
public string SpanishTitle { get { return returnTitleAsString(spanishTitle); } set { setTitleFromString(value, 4); } }
/// <summary>
/// The italian Title.
/// </summary>
public string ItalianTitle { get { return returnTitleAsString(italianTitle); } set { setTitleFromString(value, 5); } }
/// <summary>
/// The dutch Title.
/// </summary>
public string DutchTitle { get { return returnTitleAsString(dutchTitle); } set { setTitleFromString(value, 6); } }
/// <summary>
/// The korean Title.
/// </summary>
public string KoreanTitle { get { return returnTitleAsString(koreanTitle); } set { setTitleFromString(value, 7); } }
/// <summary>
/// All Titles as a string array.
/// </summary>
public string[] AllTitles { get { return new string[] { JapaneseTitle, EnglishTitle, GermanTitle, FrenchTitle, SpanishTitle, ItalianTitle, DutchTitle, KoreanTitle }; } }
/// <summary>
/// When parsing an IMET header, this value will turn false if the hash stored in the header doesn't match the headers hash.
/// </summary>
public bool HashesMatch { get { return hashesMatch; } }
#region Public Functions
/// <summary>
/// Loads the IMET Header of a file.
/// </summary>
/// <param name="pathToFile"></param>
/// <returns></returns>
public static IMET Load(string pathToFile)
{
return Load(File.ReadAllBytes(pathToFile));
}
/// <summary>
/// Loads the IMET Header of a byte array.
/// </summary>
/// <param name="fileOrHeader"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Loads the IMET Header of a stream.
/// </summary>
/// <param name="fileOrHeader"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Creates a new IMET Header.
/// </summary>
/// <param name="isShortImet"></param>
/// <param name="iconSize"></param>
/// <param name="bannerSize"></param>
/// <param name="soundSize"></param>
/// <param name="titles"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Removes the IMET Header of a file.
/// </summary>
/// <param name="pathToFile"></param>
public static void RemoveHeader(string pathToFile)
{
byte[] fileWithoutHeader = RemoveHeader(File.ReadAllBytes(pathToFile));
File.Delete(pathToFile);
File.WriteAllBytes(pathToFile, fileWithoutHeader);
}
/// <summary>
/// Removes the IMET Header of a byte array.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Sets all title to the given string.
/// </summary>
/// <param name="newTitle"></param>
public void SetAllTitles(string newTitle)
{
for (int i = 0; i < 10; i++)
setTitleFromString(newTitle, i);
}
/// <summary>
/// Returns the Header as a memory stream.
/// </summary>
/// <returns></returns>
public MemoryStream ToMemoryStream()
{
MemoryStream ms = new MemoryStream();
try { writeToStream(ms); }
catch { ms.Dispose(); throw; }
return ms;
}
/// <summary>
/// Returns the Header as a byte array.
/// </summary>
/// <returns></returns>
public byte[] ToByteArray()
{
return ToMemoryStream().ToArray();
}
/// <summary>
/// Writes the Header to the given stream.
/// </summary>
/// <param name="writeStream"></param>
public void Write(Stream writeStream)
{
writeToStream(writeStream);
}
/// <summary>
/// Changes the Titles.
/// </summary>
/// <param name="newTitles"></param>
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);
}
/// <summary>
/// Returns a string array with the Titles.
/// </summary>
/// <returns></returns>
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];
/// <summary>
/// The size of the file without the IMD5 Header.
/// </summary>
public uint FileSize { get { return fileSize; } }
/// <summary>
/// The hash of the file without the IMD5 Header.
/// </summary>
public byte[] Hash { get { return hash; } }
private IMD5() { }
#region Public Functions
/// <summary>
/// Loads the IMD5 Header of a file.
/// </summary>
/// <param name="pathToFile"></param>
/// <returns></returns>
public static IMD5 Load(string pathToFile)
{
return Load(File.ReadAllBytes(pathToFile));
}
/// <summary>
/// Loads the IMD5 Header of a byte array.
/// </summary>
/// <param name="fileOrHeader"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Loads the IMD5 Header of a stream.
/// </summary>
/// <param name="fileOrHeader"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Creates a new IMD5 Header.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static IMD5 Create(byte[] file)
{
IMD5 h = new IMD5();
h.fileSize = (uint)file.Length;
h.computeHash(file);
return h;
}
/// <summary>
/// Adds an IMD5 Header to a file.
/// </summary>
/// <param name="pathToFile"></param>
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);
}
/// <summary>
/// Adds an IMD5 Header to a byte array.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Removes the IMD5 Header of a file.
/// </summary>
/// <param name="pathToFile"></param>
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);
}
/// <summary>
/// Removes the IMD5 Header of a byte array.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Returns the IMD5 Header as a memory stream.
/// </summary>
/// <returns></returns>
public MemoryStream ToMemoryStream()
{
MemoryStream ms = new MemoryStream();
try { writeToStream(ms); }
catch { ms.Dispose(); throw; }
return ms;
}
/// <summary>
/// Returns the IMD5 Header as a byte array.
/// </summary>
/// <returns></returns>
public byte[] ToByteArray()
{
return ToMemoryStream().ToArray();
}
/// <summary>
/// Writes the IMD5 Header to the given stream.
/// </summary>
/// <param name="writeStream"></param>
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
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
//Patches based on Dop-Mii - Thanks to Arikado and Lunatik
using System;
using System.ComponentModel;
using System.Text;
namespace libWiiSharp
{
/// <summary>
/// An IOS patcher which can patch fakesigning, es_identify and nand permissions.
/// </summary>
public class IosPatcher
{
private WAD wadFile;
private int esIndex = -1;
#region Public Functions
/// <summary>
/// Loads an IOS wad to patch the es module.
/// </summary>
/// <param name="iosWad"></param>
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();
}
/// <summary>
/// Patches fakesigning.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
public int PatchFakeSigning()
{
if (esIndex < 0) return -1;
return patchFakeSigning(ref wadFile.Contents[esIndex]);
}
/// <summary>
/// Patches es_identify.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
public int PatchEsIdentify()
{
if (esIndex < 0) return -1;
return patchEsIdentify(ref wadFile.Contents[esIndex]);
}
/// <summary>
/// Patches nand permissions.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
public int PatchNandPermissions()
{
if (esIndex < 0) return -1;
return patchNandPermissions(ref wadFile.Contents[esIndex]);
}
/// <summary>
/// Patches fakesigning, es_identify and nand permissions.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
public int PatchAll()
{
if (esIndex < 0) return -1;
return patchAll(ref wadFile.Contents[esIndex]);
}
/// <summary>
/// Patches fakesigning.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
public int PatchFakeSigning(ref byte[] esModule)
{
return patchFakeSigning(ref esModule);
}
/// <summary>
/// Patches es_identify.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
public int PatchEsIdentify(ref byte[] esModule)
{
return patchEsIdentify(ref esModule);
}
/// <summary>
/// Patches nand permissions.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
public int PatchNandPermissions(ref byte[] esModule)
{
return patchNandPermissions(ref esModule);
}
/// <summary>
/// Patches fakesigning, es_identify and nand permissions.
/// Returns the number of applied patches.
/// </summary>
/// <returns></returns>
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
/// <summary>
/// Fires the Progress of various operations
/// </summary>
public event EventHandler<ProgressChangedEventArgs> Progress;
/// <summary>
/// Fires debugging messages. You may write them into a log file or log textbox.
/// </summary>
public event EventHandler<MessageEventArgs> Debug;
private void fireDebug(string debugMessage, params object[] args)
{
EventHandler<MessageEventArgs> debug = Debug;
if (debug != null)
debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
}
private void fireProgress(int progressPercentage)
{
EventHandler<ProgressChangedEventArgs> progress = Progress;
if (progress != null)
progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty));
}
#endregion
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
//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;
/// <summary>
/// Lz77 Magic.
/// </summary>
public static uint Lz77Magic { get { return lz77Magic; } }
#region Public Functions
/// <summary>
/// Checks whether a file is Lz77 compressed or not.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static bool IsLz77Compressed(string file)
{
return IsLz77Compressed(File.ReadAllBytes(file));
}
/// <summary>
/// Checks whether a file is Lz77 compressed or not.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static bool IsLz77Compressed(byte[] file)
{
Headers.HeaderType h = Headers.DetectHeader(file);
return (Shared.Swap(BitConverter.ToUInt32(file, (int)h)) == lz77Magic) ;
}
/// <summary>
/// Checks whether a file is Lz77 compressed or not.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
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);
}
/// <summary>
/// Compresses a file using the Lz77 algorithm.
/// </summary>
/// <param name="inFile"></param>
/// <param name="outFile"></param>
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);
}
/// <summary>
/// Compresses the byte array using the Lz77 algorithm.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public byte[] Compress(byte[] file)
{
return ((MemoryStream)compress(new MemoryStream(file))).ToArray();
}
/// <summary>
/// Compresses the stream using the Lz77 algorithm.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public Stream Compress(Stream file)
{
return compress(file);
}
/// <summary>
/// Decompresses a file using the Lz77 algorithm.
/// </summary>
/// <param name="inFile"></param>
/// <param name="outFile"></param>
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);
}
/// <summary>
/// Decompresses the byte array using the Lz77 algorithm.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
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
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace libWiiSharp
{
public class MessageEventArgs : EventArgs
{
private string message;
public string Message { get { return message; } }
public MessageEventArgs(string message) { this.message = message; }
}
}

View File

@ -1,254 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{DB1289FA-BA83-408F-A576-326E5EC4CC6D}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NUS_Downloader</RootNamespace>
<AssemblyName>NUS Downloader</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ApplicationIcon>Crystal_Clear_app_ark2.ico</ApplicationIcon>
<IsWebBootstrapper>false</IsWebBootstrapper>
<ManifestCertificateThumbprint>1555E408E7D4078FB64D4CC67B4156C20E540209</ManifestCertificateThumbprint>
<ManifestKeyFile>NUS Downloader_TemporaryKey.pfx</ManifestKeyFile>
<GenerateManifests>true</GenerateManifests>
<SignManifests>false</SignManifests>
<TargetZone>LocalIntranet</TargetZone>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile />
<PublishUrl>C:\Users\Windows7\Documents\Visual Studio 2010\Projects\NUS Downloader\NUS Downloader\publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>false</MapFileExtensions>
<OpenBrowserOnPublish>false</OpenBrowserOnPublish>
<ApplicationRevision>14</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CertificateChain.cs" />
<Compile Include="CommonKey.cs" />
<Compile Include="COMTypes.cs" />
<Compile Include="ContentIndices.cs" />
<Compile Include="Database.cs" />
<Compile Include="Form1.cs">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Compile>
<Compile Include="Headers.cs" />
<Compile Include="IosPatcher.cs" />
<Compile Include="Lz77.cs" />
<Compile Include="MessageEventArgs.cs" />
<Compile Include="NusClient.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config">
<SubType>Designer</SubType>
</None>
<None Include="COPYING" />
<None Include="NUS Downloader_TemporaryKey.pfx" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="Shared.cs" />
<Compile Include="Ticket.cs" />
<Compile Include="TMD.cs" />
<Compile Include="U8.cs" />
<Compile Include="WAD.cs" />
<Compile Include="WaterMarkTextBox.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Windows7ProgressBar.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Windows7Taskbar.cs" />
<None Include="TODO" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\wilolgoi.png" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\app.manifest" />
<None Include="Resources\dsi.png" />
</ItemGroup>
<ItemGroup>
<Content Include="Crystal_Clear_app_ark2.ico" />
<None Include="Resources\wii16x16.png" />
<None Include="Resources\money.png" />
<None Include="Resources\wrench.png" />
<None Include="Resources\script_start.png" />
<None Include="Resources\package_green.png" />
<None Include="Resources\package.png" />
<None Include="Resources\picture_empty.png" />
<None Include="Resources\telephone_add.png" />
<None Include="Resources\script_code_red.png" />
<None Include="Resources\script_code.png" />
<None Include="Resources\database_save.png" />
<None Include="Resources\folder_table.png" />
<None Include="Resources\help1.png" />
<None Include="Resources\information.png" />
<None Include="Resources\box.png" />
<None Include="Resources\disk.png" />
<None Include="Resources\drive_disk.png" />
<None Include="Resources\bin_closed.png" />
<None Include="Resources\arrow_ticker.gif" />
<None Include="Resources\folder.png" />
<None Include="Resources\bullet_green-blue.png" />
<None Include="Resources\bullet_orange-blue.png" />
<None Include="Resources\bullet_redgreen-blue.png" />
<None Include="Resources\bullet_redorange-blue.png" />
<None Include="Resources\dsi16x16.png" />
<Content Include="Resources\key.png" />
<None Include="Resources\page_white_magnify.png" />
<None Include="Resources\server_link.png" />
<None Include="Resources\server_connect.png" />
<None Include="Resources\script_go.png" />
<None Include="Resources\bug_error.png" />
<None Include="Resources\help.png" />
<None Include="Resources\link.png" />
<None Include="Resources\bug_add.png" />
<None Include="Resources\arrow_down.png" />
<None Include="Resources\arrow_up.png" />
<None Include="Resources\connect.png" />
<None Include="Resources\package_add.png" />
<None Include="Resources\package_delete.png" />
<None Include="Resources\pencil.png" />
<None Include="Resources\bullet_redgreen.png" />
<None Include="Resources\bullet_green.png" />
<None Include="Resources\bullet_redorange.png" />
<None Include="Resources\bullet_orange.png" />
<None Include="Resources\bullet_red.png" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
<Visible>False</Visible>
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
<Visible>False</Visible>
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<PublishFile Include="Crystal_Clear_app_ark2.ico">
<Visible>False</Visible>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>File</FileType>
</PublishFile>
<PublishFile Include="Resources\key.png">
<Visible>False</Visible>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>File</FileType>
</PublishFile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy "$(TargetPath)" "$(ProjectDir)\Latest\"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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; } }
/// <summary>
/// If true, existing local files will be used.
/// </summary>
public bool UseLocalFiles { get { return useLocalFiles; } set { useLocalFiles = value; } }
/// <summary>
/// If true, the download will be continued even if no ticket for the title is avaiable (WAD packaging and decryption are disabled).
/// </summary>
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);
}
/// <summary>
/// Grabs a title from NUS, you can define several store types.
/// Leave the title version empty for the latest.
/// </summary>
/// <param name="titleId"></param>
/// <param name="titleVersion"></param>
/// <param name="outputDir"></param>
/// <param name="storeTypes"></param>
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);
}
/// <summary>
/// Grabs a TMD from NUS.
/// Leave the title version empty for the latest.
/// </summary>
/// <param name="titleId"></param>
/// <param name="titleVersion"></param>
/// <returns></returns>
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);
}
/// <summary>
/// Grabs a Ticket from NUS.
/// </summary>
/// <param name="titleId"></param>
/// <returns></returns>
public Ticket DownloadTicket(string titleId)
{
if (titleId.Length != 16) throw new Exception("Title ID must be 16 characters long!");
return downloadTicket(titleId);
}
/// <summary>
/// Grabs a single content file and decrypts it.
/// Leave the title version empty for the latest.
/// </summary>
/// <param name="titleId"></param>
/// <param name="titleVersion"></param>
/// <param name="contentId"></param>
/// <returns></returns>
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);
}
/// <summary>
/// Grabs a single content file and decrypts it.
/// Leave the title version empty for the latest.
/// </summary>
/// <param name="titleId"></param>
/// <param name="titleVersion"></param>
/// <param name="contentId"></param>
/// <param name="savePath"></param>
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
/// <summary>
/// Fires the Progress of various operations
/// </summary>
public event EventHandler<ProgressChangedEventArgs> Progress;
/// <summary>
/// Fires debugging messages. You may write them into a log file or log textbox.
/// </summary>
public event EventHandler<MessageEventArgs> Debug;
private void fireDebug(string debugMessage, params object[] args)
{
EventHandler<MessageEventArgs> debug = Debug;
if (debug != null)
debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
}
private void fireProgress(int progressPercentage)
{
EventHandler<ProgressChangedEventArgs> progress = Progress;
if (progress != null)
progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty));
}
#endregion
}
}

View File

@ -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);
/// <summary>
/// The main entry point for the application.
/// </summary>
[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
}
}
}
}

View File

@ -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")]

View File

@ -1,329 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace NUS_Downloader.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[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));
}
}
}
}

View File

@ -1,235 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="server_connect" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\server_connect.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="package_delete" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\package_delete.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_redorange" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_redorange.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="wii16x16" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\wii16x16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_redgreen" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_redgreen.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="folder" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\folder.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="script_go" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\script_go.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="package_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\package_green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="help" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\help.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="key" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\key.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="page_white_magnify" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\page_white_magnify.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="money" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\money.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="script_code_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\script_code_red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="disk" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\disk.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="server_link" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\server_link.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="arrow_ticker" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\arrow_ticker.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="script_start" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\script_start.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bin_closed" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bin_closed.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_redorange_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_redorange-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="connect" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\connect.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_redgreen_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_redgreen-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="package" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\package.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="folder_table" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\folder_table.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="database_save" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\database_save.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_orange" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_orange.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="box" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\box.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="picture_empty" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\picture_empty.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_green_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_green-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bug_add" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bug_add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="wrench" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\wrench.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="script_code" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\script_code.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="bullet_orange_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bullet_orange-blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="package_add" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\package_add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="drive_disk" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\drive_disk.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="information" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\information.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="dsi16x16" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\dsi16x16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
If you want to utilize File and Registry Virtualization for backward
compatibility then delete the requestedExecutionLevel node.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
<applicationRequestMinimum>
<defaultAssemblyRequest permissionSetReference="Custom" />
<PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" />
</applicationRequestMinimum>
</security>
</trustInfo>
</asmv1:assembly>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 896 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 617 B

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Net;
namespace libWiiSharp
{
public static class Shared
{
/// <summary>
/// Merges two string arrays into one without double entries.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static string[] MergeStringArrays(string[] a, string[] b)
{
List<string> sList = new List<string>(a);
foreach (string currentString in b)
if (!sList.Contains(currentString)) sList.Add(currentString);
sList.Sort();
return sList.ToArray();
}
/// <summary>
/// Compares two byte arrays.
/// </summary>
/// <param name="first"></param>
/// <param name="firstIndex"></param>
/// <param name="second"></param>
/// <param name="secondIndex"></param>
/// <param name="length"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Compares two byte arrays.
/// </summary>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Turns a byte array into a string, default separator is a space.
/// </summary>
/// <param name="byteArray"></param>
/// <param name="separator"></param>
/// <returns></returns>
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);
}
/// <summary>
/// Turns a hex string into a byte array.
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Counts how often the given char exists in the given string.
/// </summary>
/// <param name="theString"></param>
/// <param name="theChar"></param>
/// <returns></returns>
public static int CountCharsInString(string theString, char theChar)
{
int count = 0;
foreach (char thisChar in theString)
if (thisChar == theChar)
count++;
return count;
}
/// <summary>
/// Pads the given value to a multiple of the given padding value, default padding value is 64.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static long AddPadding(long value)
{
return AddPadding(value, 64);
}
/// <summary>
/// Pads the given value to a multiple of the given padding value, default padding value is 64.
/// </summary>
/// <param name="value"></param>
/// <param name="padding"></param>
/// <returns></returns>
public static long AddPadding(long value, int padding)
{
if (value % padding != 0)
{
value = value + (padding - (value % padding));
}
return value;
}
/// <summary>
/// Pads the given value to a multiple of the given padding value, default padding value is 64.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static int AddPadding(int value)
{
return AddPadding(value, 64);
}
/// <summary>
/// Pads the given value to a multiple of the given padding value, default padding value is 64.
/// </summary>
/// <param name="value"></param>
/// <param name="padding"></param>
/// <returns></returns>
public static int AddPadding(int value, int padding)
{
if (value % padding != 0)
{
value = value + (padding - (value % padding));
}
return value;
}
/// <summary>
/// Swaps endianness.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static ushort Swap(ushort value)
{
return (ushort)IPAddress.HostToNetworkOrder((short)value);
}
/// <summary>
/// Swaps endianness.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static uint Swap(uint value)
{
return (uint)IPAddress.HostToNetworkOrder((int)value);
}
/// <summary>
/// Swaps endianness
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static ulong Swap(ulong value)
{
return (ulong)IPAddress.HostToNetworkOrder((long)value);
}
/// <summary>
/// Turns a ushort array into a byte array.
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public static byte[] UShortArrayToByteArray(ushort[] array)
{
List<byte> results = new List<byte>();
foreach (ushort value in array)
{
byte[] converted = BitConverter.GetBytes(value);
results.AddRange(converted);
}
return results.ToArray();
}
/// <summary>
/// Turns a uint array into a byte array.
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public static byte[] UIntArrayToByteArray(uint[] array)
{
List<byte> results = new List<byte>();
foreach (uint value in array)
{
byte[] converted = BitConverter.GetBytes(value);
results.AddRange(converted);
}
return results.ToArray();
}
/// <summary>
/// Turns a byte array into a uint array.
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Turns a byte array into a ushort array.
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
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;
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<TMD_Content> contents;
/// <summary>
/// The region of the title.
/// </summary>
public Region Region { get { return (Region)region; } set { region = (ushort)value; } }
/// <summary>
/// The IOS the title is launched with.
/// </summary>
public ulong StartupIOS { get { return startupIos; } set { startupIos = value; } }
/// <summary>
/// The Title ID.
/// </summary>
public ulong TitleID { get { return titleId; } set { titleId = value; } }
/// <summary>
/// The Title Version.
/// </summary>
public ushort TitleVersion { get { return titleVersion; } set { titleVersion = value; } }
/// <summary>
/// The Number of Contents.
/// </summary>
public ushort NumOfContents { get { return numOfContents; } }
/// <summary>
/// The boot index. Represents the index of the nand loader.
/// </summary>
public ushort BootIndex { get { return bootIndex; } set { if (value <= numOfContents) bootIndex = value; } }
/// <summary>
/// The content descriptions in the TMD.
/// </summary>
public TMD_Content[] Contents { get { return contents.ToArray(); } set { contents = new List<TMD_Content>(value); numOfContents = (ushort)value.Length; } }
/// <summary>
/// If true, the TMD will be fakesigned while saving.
/// </summary>
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
/// <summary>
/// Loads a tmd file.
/// </summary>
/// <param name="pathToTmd"></param>
/// <returns></returns>
public static TMD Load(string pathToTmd)
{
return Load(File.ReadAllBytes(pathToTmd));
}
/// <summary>
/// Loads a tmd file.
/// </summary>
/// <param name="tmdFile"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Loads a tmd file.
/// </summary>
/// <param name="tmd"></param>
/// <returns></returns>
public static TMD Load(Stream tmd)
{
TMD t = new TMD();
t.parseTmd(tmd);
return t;
}
/// <summary>
/// Loads a tmd file.
/// </summary>
/// <param name="pathToTmd"></param>
public void LoadFile(string pathToTmd)
{
LoadFile(File.ReadAllBytes(pathToTmd));
}
/// <summary>
/// Loads a tmd file.
/// </summary>
/// <param name="tmdFile"></param>
public void LoadFile(byte[] tmdFile)
{
MemoryStream ms = new MemoryStream(tmdFile);
try { parseTmd(ms); }
catch { ms.Dispose(); throw; }
ms.Dispose();
}
/// <summary>
/// Loads a tmd file.
/// </summary>
/// <param name="tmd"></param>
public void LoadFile(Stream tmd)
{
parseTmd(tmd);
}
/// <summary>
/// Saves the TMD.
/// </summary>
/// <param name="savePath"></param>
public void Save(string savePath)
{
Save(savePath, false);
}
/// <summary>
/// Saves the TMD. If fakeSign is true, the Ticket will be fakesigned.
/// </summary>
/// <param name="savePath"></param>
/// <param name="fakeSign"></param>
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);
}
/// <summary>
/// Returns the TMD as a memory stream.
/// </summary>
/// <returns></returns>
public MemoryStream ToMemoryStream()
{
return ToMemoryStream(false);
}
/// <summary>
/// Returns the TMD as a memory stream. If fakeSign is true, the Ticket will be fakesigned.
/// </summary>
/// <param name="fakeSign"></param>
/// <returns></returns>
public MemoryStream ToMemoryStream(bool fakeSign)
{
if (fakeSign) this.fakeSign = true;
MemoryStream ms = new MemoryStream();
try { writeToStream(ms); }
catch { ms.Dispose(); throw; }
return ms;
}
/// <summary>
/// Returns the TMD as a byte array.
/// </summary>
/// <returns></returns>
public byte[] ToByteArray()
{
return ToByteArray(false);
}
/// <summary>
/// Returns the TMD as a byte array. If fakeSign is true, the Ticket will be fakesigned.
/// </summary>
/// <param name="fakeSign"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Updates the content entries.
/// </summary>
/// <param name="contentDir"></param>
/// <param name="namedContentId">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)</param>
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);
}
/// <summary>
/// Updates the content entries.
/// </summary>
/// <param name="contentDir"></param>
/// <param name="namedContentId">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)</param>
public void UpdateContents(byte[][] contents)
{
updateContents(contents);
}
/// <summary>
/// Returns the Upper Title ID as a string.
/// </summary>
/// <returns></returns>
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] });
}
/// <summary>
/// The Number of memory blocks the content will take.
/// </summary>
/// <returns></returns>
public string GetNandBlocks()
{
return calculateNandBlocks();
}
/// <summary>
/// Adds a TMD content.
/// </summary>
/// <param name="content"></param>
public void AddContent(TMD_Content content)
{
contents.Add(content);
numOfContents = (ushort)contents.Count;
}
/// <summary>
/// Removes the content with the given index.
/// </summary>
/// <param name="contentIndex"></param>
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;
}
/// <summary>
/// Removes the content with the given ID.
/// </summary>
/// <param name="contentId"></param>
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<ContentIndices> contentList = new List<ContentIndices>();
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<TMD_Content>();
//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
/// <summary>
/// Fires debugging messages. You may write them into a log file or log textbox.
/// </summary>
public event EventHandler<MessageEventArgs> Debug;
private void fireDebug(string debugMessage, params object[] args)
{
EventHandler<MessageEventArgs> 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; } }
}
}

View File

@ -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!

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
/// <summary>
/// The Title Key the WADs content is encrypted with.
/// </summary>
public byte[] TitleKey { get { return decryptedTitleKey; } set { decryptedTitleKey = value; titleKeyChanged = true; reDecrypt = false; } }
/// <summary>
/// Defines which Common Key is used (Standard / Korean).
/// </summary>
public CommonKeyType CommonKeyIndex { get { return (CommonKeyType)newKeyIndex; } set { newKeyIndex = (byte)value; } }
/// <summary>
/// The Ticket ID.
/// </summary>
public ulong TicketID { get { return ticketId; } set { ticketId = value; } }
/// <summary>
/// The Console ID.
/// </summary>
public uint ConsoleID { get { return consoleId; } set { consoleId = value; } }
/// <summary>
/// The Title ID.
/// </summary>
public ulong TitleID { get { return titleId; } set { titleId = value; if (reDecrypt) reDecryptTitleKey(); } }
/// <summary>
/// Number of DLC.
/// </summary>
public ushort NumOfDLC { get { return numOfDlc; } set { numOfDlc = value; } }
/// <summary>
/// If true, the Ticket will be fakesigned while saving.
/// </summary>
public bool FakeSign { get { return fakeSign; } set { fakeSign = value; } }
/// <summary>
/// True if the Title Key was changed.
/// </summary>
public bool TitleKeyChanged { get { return titleKeyChanged; } }
/// <summary>
/// If true, the Ticket will utilize the DSi CommonKey.
/// </summary>
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
/// <summary>
/// Loads a tik file.
/// </summary>
/// <param name="pathToTicket"></param>
/// <returns></returns>
public static Ticket Load(string pathToTicket)
{
return Load(File.ReadAllBytes(pathToTicket));
}
/// <summary>
/// Loads a tik file.
/// </summary>
/// <param name="ticket"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Loads a tik file.
/// </summary>
/// <param name="ticket"></param>
/// <returns></returns>
public static Ticket Load(Stream ticket)
{
Ticket tik = new Ticket();
tik.parseTicket(ticket);
return tik;
}
/// <summary>
/// Loads a tik file.
/// </summary>
/// <param name="pathToTicket"></param>
public void LoadFile(string pathToTicket)
{
LoadFile(File.ReadAllBytes(pathToTicket));
}
/// <summary>
/// Loads a tik file.
/// </summary>
/// <param name="ticket"></param>
public void LoadFile(byte[] ticket)
{
MemoryStream ms = new MemoryStream(ticket);
try { parseTicket(ms); }
catch { ms.Dispose(); throw; }
ms.Dispose();
}
/// <summary>
/// Loads a tik file.
/// </summary>
/// <param name="ticket"></param>
public void LoadFile(Stream ticket)
{
parseTicket(ticket);
}
/// <summary>
/// Saves the Ticket.
/// </summary>
/// <param name="savePath"></param>
public void Save(string savePath)
{
Save(savePath, false);
}
/// <summary>
/// Saves the Ticket. If fakeSign is true, the Ticket will be fakesigned.
/// </summary>
/// <param name="savePath"></param>
/// <param name="fakeSign"></param>
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);
}
/// <summary>
/// Returns the Ticket as a memory stream.
/// </summary>
/// <returns></returns>
public MemoryStream ToMemoryStream()
{
return ToMemoryStream(false);
}
/// <summary>
/// Returns the Ticket as a memory stream. If fakeSign is true, the Ticket will be fakesigned.
/// </summary>
/// <param name="fakeSign"></param>
/// <returns></returns>
public MemoryStream ToMemoryStream(bool fakeSign)
{
if (fakeSign) this.fakeSign = true;
MemoryStream ms = new MemoryStream();
try { writeToStream(ms); }
catch { ms.Dispose(); throw; }
return ms;
}
/// <summary>
/// Returns the Ticket as a byte array.
/// </summary>
/// <returns></returns>
public byte[] ToByteArray()
{
return ToByteArray(false);
}
/// <summary>
/// Returns the Ticket as a byte array. If fakeSign is true, the Ticket will be fakesigned.
/// </summary>
/// <param name="fakeSign"></param>
/// <returns></returns>
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;
}
/// <summary>
/// This will set a new encrypted Title Key (i.e. the one that you can "read" in the Ticket).
/// </summary>
/// <param name="newTitleKey"></param>
public void SetTitleKey(string newTitleKey)
{
SetTitleKey(newTitleKey.ToCharArray());
}
/// <summary>
/// This will set a new encrypted Title Key (i.e. the one that you can "read" in the Ticket).
/// </summary>
/// <param name="newTitleKey"></param>
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;
}
/// <summary>
/// This will set a new encrypted Title Key (i.e. the one that you can "read" in the Ticket).
/// </summary>
/// <param name="newTitleKey"></param>
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;
}
/// <summary>
/// Returns the Upper Title ID as a string.
/// </summary>
/// <returns></returns>
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
/// <summary>
/// Fires debugging messages. You may write them into a log file or log textbox.
/// </summary>
public event EventHandler<MessageEventArgs> Debug;
private void fireDebug(string debugMessage, params object[] args)
{
EventHandler<MessageEventArgs> debug = Debug;
if (debug != null)
debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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();
}
}
}
}

View File

@ -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
{
/// <summary>
/// A Windows progress bar control with Windows Vista & 7 functionality.
/// </summary>
[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;
}
/// <summary>
/// Show progress in taskbar
/// </summary>
[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();
}
}
}
}
/// <summary>
/// Gets or sets the current position of the progress bar.
/// </summary>
/// <returns>The position within the range of the progress bar. The default is 0.</returns>
public new int Value
{
get
{
return base.Value;
}
set
{
base.Value = value;
// send signal to the taskbar.
SetValueInTB();
}
}
/// <summary>
/// Gets or sets the manner in which progress should be indicated on the progress bar.
/// </summary>
/// <returns>One of the ProgressBarStyle values. The default is ProgressBarStyle.Blocks</returns>
public new ProgressBarStyle Style
{
get
{
return base.Style;
}
set
{
base.Style = value;
// set the style of the progress bar
if (showInTaskbar && ownerForm != null)
{
SetStateInTB();
}
}
}
/// <summary>
/// The progress bar state for Windows Vista & 7
/// </summary>
[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();
}
}
/// <summary>
/// Advances the current position of the progress bar by the specified amount.
/// </summary>
/// <param name="value">The amount by which to increment the progress bar's current position.</param>
public new void Increment(int value)
{
base.Increment(value);
// send signal to the taskbar.
SetValueInTB();
}
/// <summary>
/// Advances the current position of the progress bar by the amount of the System.Windows.Forms.ProgressBar.Step property.
/// </summary>
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);
}
}
/// <summary>
/// The progress bar state for Windows Vista & 7
/// </summary>
public enum ProgressBarState
{
/// <summary>
/// Indicates normal progress
/// </summary>
Normal = 1,
/// <summary>
/// Indicates an error in the progress
/// </summary>
Error = 2,
/// <summary>
/// Indicates paused progress
/// </summary>
Pause = 3
}
}

View File

@ -1,72 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Runtime.InteropServices;
namespace wyDay.Controls
{
/// <summary>
/// The primary coordinator of the Windows 7 taskbar-related activities.
/// </summary>
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);
}
}
/// <summary>
/// Sets the progress state of the specified window's
/// taskbar button.
/// </summary>
/// <param name="hwnd">The window handle.</param>
/// <param name="state">The progress state.</param>
public static void SetProgressState(IntPtr hwnd, ThumbnailProgressState state)
{
if(Windows7OrGreater)
TaskbarList.SetProgressState(hwnd, state);
}
/// <summary>
/// Sets the progress value of the specified window's
/// taskbar button.
/// </summary>
/// <param name="hwnd">The window handle.</param>
/// <param name="current">The current value.</param>
/// <param name="maximum">The maximum value.</param>
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);
}
}

View File

@ -1,3 +0,0 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

600
NUS_Downloader/Database.cs Normal file
View File

@ -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<ToolStripMenuItem>(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;
}
}
}

2923
NUS_Downloader/Form1.cs Normal file

File diff suppressed because it is too large Load Diff

135
NUS_Downloader/Form1.resx Normal file

File diff suppressed because one or more lines are too long

49
NUS_Downloader/Program.cs Normal file
View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,234 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="package_add" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAnwMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAzFJREFUOE91k+tPm2UYh/tFE/+BJfPDPhlDZFNnjCeyDHGDznHQmGyJn9gimukSjNGwxM1Fw0aRspJKF6MjW8yKhImjlYMUCmMWaBkMVmhLKUw6KKdS+sIsUArv5d3qNHHzTe48eZ/cv+s+PhpA8ygba8pLH7Mevu5rfLPD+7N27//5PST2t+TvEHGpz3o4uui5xNyADs9PB++P1h/Qj/yY9eR/Qf8AxlsLHhNx0VhTbiA0ZGRrYxZ1bZrVyeusz1gJ3viEO1f3Tw3/sO/k0JWMJx6AUgB/a0G2vzn/5lTvF6wv35GrNVAVEpFbjDe8xbqvgniwnlWviYD1OLdrXnUOfvdSXlKbFF/2N+epEb+ZWNhN5G4nd13i+Fs53l8/ZrLtBDFfFbGhs2wEaticrmepvxRP7dvcMr1Qq5F6E+pGkHh4kIjbSHiglFBXMQHLEZzVGWwu3YaYHxbbUH83gacEZswkJkpxGZ9LaKRZyvbGPbg/yuZMIytD54kNnxU7xYwlN3XHQgsEv0f1niJmz2SheR8rniqchj2Kxtt4SNleE8Af4wLxQNjOuqecmOsEC025JMYrYUJP3KFlqeUV5ru0zLcXoAzr6atMVzSehhxlKwXwwaqkG3UKxEYiYGSl+wjxm1oUewZLPTks2A8y25zFrCWH5X4dvV+nKRqZ718AKQHFBZFOqfcXmGtA9Z8m2qdl0fEGDfX5fHrxKO9fKKDwfCY1V96lp+xpRTNSlxVXE3MyuUmJ3i3RW2H+mjTqKmrwIuFeLXW1h/jy2jGaRk0Mz9owtH/IUcMePivZtaVxmzPbJ+wlrIW6BBKAZYGEzDB9WQDVLHZnc0x3AMtIFRavUUYP+o4iDB0f8NrJndsa2azHZbOKZDkCUzfOsLXcJ70YkCzqUKeqmbO9Tu7ne2kZvZQSP/isbhMvf7Tz34ckm7Vj4NsXz8lyREOOr6SpAok6WHFXsL94FxW245TZClP6srbCVAYCWH/oMfV/83y6q+pZs/PCbjU8aOBeazFnTu/mHX0albb3SEZOnsl/Aegf+ZSTO95b8Ux2T3lap3Ta4Tj3VJ4468RWk2n/feqSfn8CIS/31E+22i0AAAAASUVORK5CYIIL</value>
</data>
<data name="package" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAkwMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyVJREFUOE91k91Pm3UUx58bTfQP2IXe6KZmGb4uRucIWWUCdYOhMeHWxGQXi5oZY7Jd6Gage+FtIwhq1AVj6DbZkJfx4jYLayml7XgbW1tKAVtoy0tp+wAWWsqejweMizq8ODcnv+/n/M4536MAylYx2laQMdp6sMnTfOA39y/6V/7v3UNib8ehbSI2eFoPxuddPzDTfxbX1Zzlew1vVdy9lP3Ef0EPAGOdhY+I+PBoW74vNFTNejKMtjLN0kQTq8FWArc+5U79Pv/wT1kfDf2Y+djfoE2At7Mw19t+yOK3nWA1dkdSK6CppKO3GWt8h1VPOalAA0vuWnytHzB44Q37wHevFWxoN8R13vYCLeo1koiMEJ3sYtIhD3tKcf/6CRPXj5DwVJEYOknSd4G16QYWnAZcF9/ldu3ui4r0m9aSAVKRAaIj1UT6DYS6j+JrKcJek8nawiAkvDB/He33WnAdg6CR9LgBR/VLaUWGpd5PTsHyPdaCzSwOnSYxfFLiOMGW/M0ccx0Q+B7NfZyEScdcexaLrirs519QFXfz2+r9FQH8MSYQF0RMrLpKSTiOMNeWT3qsEsYrSFn1LHTsYbZbz+zNQtThCvoqM1TF1Zinrm8CPLAk343bBXKDtK+aRXMRKYse1ZTJQm8ec6Ycwu3ZhFvyiDnPYivbqSqy378A0gKqA6Jd0u81mGlE835OvE/PvHU/s137RbyP6St7CVzSCbCE3jPPqcrdy9kpLT0jm5uQ6map3gmzV2RQ9WiBr4nY9FJZR7gti6mf9zBZt5twx4fErCVYTz2TVEaMupvjpmOshLoF4oOYQEJGmK4TQA3z5lypvJephtcJNRURtZ0heO0znFUH6CnZblbEWY+Ksw6LOXz+W1+wHuuTWfTLLy6j+WuYufGmbCOHuLOMiLmY4W/eo8eww28p3v6x5cunHn9gZXHWtv5vXz0l5oiHrMUyVIHErSyOlKMOluGpfx/r6WeXRVxpKX76yX9Z+Z8H4vzq5QxH1YtG+7nntcjAeaY6j2I/p9vo92pPyY6HrnLLU94A2sp35faW7uySSVtFvOn7reJPpm0BFOUXvxMAAAAASUVORK5CYIIL</value>
</data>
<data name="script_code_red" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAkwMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyVJREFUOE9lk/1PE3cYwNkP+3mJ8W9Y9pOJ2WJmXOY2IybiXoLy0rGuMkiUZYS9SNSwJQ5xsoypMbBkLDAjzDg3dZtzGtEJgkXBIgLVQpHOo6XQ0pejtNe76/HZ0xKbLLvkc7k8eZ7PPfd9nisACrI4flU2CM4vr4fYf2We2j/m2PubH4nFhVnhvnBP6BHOCkXCs7niLPazM7UtvSF5/O+1rFuEEiaT4TTjc2mcviRnhheQ/Ihgzwsquqea2p3hXLUSyxCMW4RVi2jSQk1baIaFkVmVa+YKvVPLSE0oLyj/0X3y3MAspgXuBQtP2OLxbBJfxEIRmV9k/viq4eNT/6CbcPSqb7X9LNVtzp/n6z9He9/B0BMDvX4f6uFm3DNLIjTxLGTwhjKIn086xuibjFLSPhrIFeu7HWu8VbXxxMHPWHJUSXs6y/UHSB1uILL/C1yeKC7FYDRgYK3Au8eHKW4dUoWtBbrdXq6VlmmJA5+ivrcb93iQ6yK4NTJPfM9HZOOJHe8wcaaHO0/M3CeWtd7hrWMDa7IvL9B2lajxlkbUwu2oDx4x6NO5Ma1zc9pg+G8PiW1FRKWT2KtbGZpO5Q5y57d9FDXfeC4nSG7fUZ54o1CL7alm6c1inHf9UpzmtmuOxVI72Xjs5c2MnbrMsGKS1DNsa7xiCs/kBNlbc2XTOteWXURsNoKbCrnpTbO4s4JYdSWB0g+4PRqm/7HBRNBEiSTZ0vC7/+nh5wSv1Z97wXHoImqxjdDz63PtRzcXEiipZGAsQq/XoF9iMzJa1/Qikj+UF7xS171W+KXlgpuAzPv0oMb5+xqX3XIWU2luzcj2yVjv+Q0WZamujShI/qW8YGNNZ5mQsh35k4afJqnr9PDhD4+o+s6D/eRDbMcnKDs2Tk2HwoNZg9M9HiS/My/YUP3910e6B//3D2Rk3tmVVTUhtcJXF/x45w3aLo4gNd/kBS86WvfWnrhK17WHXHL66J8IMu6LooSSxJZNUvIPZJfHFzaZi5kc6uhDaurygvUVJ9YKTUKX8JdwV5gSwoKxsbKN12vaeXtfF47G80hsUnjpqeBfqmcIWpg8ay0AAAAASUVORK5CYIIL</value>
</data>
<data name="script_code" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAgQMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAxNJREFUOE9lk9tLFHEUx+2h50D8H+rJiEIQeuhCBAkFhq26mGYKKohpWYQvWdrVVESjvKzhejevlYoaatZu3lN3bVdt1x133d2Z9bLk3mZ2/HZmxIVo4DMMh3M+v9/vnN+EAQiTSP7ARBGawhEWDwYcyO7bREaPFRTbJTaIeWKGGCZaiRjiqFwskdRqyi4ZY+nz32cvIIL9I8DI+bG06YfG7EHztBOUv0UkhQTKxpWiag0nVzM7Qdh3RXBuEdseEW6/CB8vgg8eyH3CPsZW9kA1bEgQX6+vUGlYCCKgd4owcCJWWRHmLREMyawks+4eGO68X0dAAJ4Nmg+2LxH7dqEtpc2OW10OTFl4pPW7kNnLYdISIKEAgzNIwiDIj9y6RYwbtxFX/dMmF598agq/Ur2+m9fPIbXFQdsLILWHw/1hF9LaWYyu+jHL8Php4yHuA4ll04itnHITl8Iii0zxyg6nL/czi5RGO8aMXoyQoHPRi5ttTkhxJUlLB7bxwyLIR1RU/sDV0m/h0uJhiha7++GgC/FNNmipMVpzAF/WAhhd46HW7iGxeRP5fU4o6qz4/puXG3n99Thinn85JguO3zXGx9XbfFntDiTXWtEz76FiP7oXPEhU2SDF42o28LLXhWlGgCcQxOXHAwJxRBZIr6i80cgLhTqkq22IK7PIZ06otSGj1Q5lFYN+nRcTtLrOLoDZ8uBiQa/1sPmy4Fx++4nrTwaRXmVBbOm6vP0bbxkkVjAY0PswtspjgmImGu3smguUPxUSnM1pjCA6Srr0sNG8G7Q+dM778FlPvVjx46uJbh+NdcbKw0WXamiOAeV/DAmiM1UKwptQ/AkFTUbkqAzIqvmF228MSKpYRkKZDorSJWTWMVjY4NEwbADlq0KCqLR3L4obtf/9A0Gat3Rl3T7Cu4+nXVasOnhUdc+Bal6FBKeTKzOyywehHlrGR40ZEzo7lszbYFgPdvYEeOkfkC6PmROwuSPgUd04qCYnJDilLI8gigg10U9MEisER/DRt6pwPrMa1+6pkfy4ExQzEmcOBX8B47oRPHT8jXgAAAAASUVORK5CYIIL</value>
</data>
<data name="bug_add" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAMgMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAsRJREFUOE99k+1PUmEYh/03yjYLFBWFUkAOoCjOdE3B14VsviCFmkqpmC/prHxDF4o5yXK+hIopQgRiJjpN+2BbrVq5+tDHtj60tanVZK78dY5LEs3Odvbs7Nz39fyu55zbD4DfUXfsrBCxLoGEeh/zkJ8RbY3aOljr0yyZF9H3F4idBGLsfGdJl4wmmuSphePczf8C4qgdZwRVe0XRNr5HZIn6Wng90ZzWJtwSDnJ2sitEHfshPgnE08R6jIPw7Ea2EhvCCR4EZi4EJi4aVyqx8smOWn0+pOrIq3sQHwDpKYmeioJ4klhPtp6FbW0ITz6MoetZK1iGEOTPpsLyvA8RneE40xEGdisTfmIHsUF6et1Jz51YswATr7rRMqdCvTMb1U4lxH0EWB2hUI3JkZDG+OhNQHpuk54QPuCNiM3El/O2NJhfduLGTB60tlTkjsZDYUnH5It+GJe6wG4OhUgRZPdREIxxVwkTB8QQB9bXvWh05aDSKkOuSQL5uAx3l1uhnZDj3mIbWI1MMOsY30OrgzQUxHsGxADHo5jMgH5Bg3KLFDnD8cgaScGdpWZoRtNxYTCJBHSAWcNAiDZwJ7icDkYZ7e9PxDdG/ii2qXB7sQa59xOQOZwMvasWJSMyqAaScG1UjctGBQq7UqFoift2rpbdQC882eBNIOzh6SL1LDTN1CBrSAr9dB1KTFIo+xNRPVyAm1MFcK0Z8eazG4b5EsgNLPBLj+l9PiNHd3qZXnUSg0970WQvQxEJanlUjrz2RDjedcPxvofUBqmphmGhiAJsHZoDdj1zmV3HxBVTMbQjpWBXMJFSH4HHawO7zXuX862RAvx7kMK0DFOwhvYz8NIpkJ4gyvx/3XKroHMrd/t1c8qjExwcFlpBwGq42h+Z+hB0ui+C2plaqedDZ3DUWAcoTmyHq457yIZNKvaftZ2q/w2XNXnDBjBEpAAAAABJRU5ErkJgggs=</value>
</data>
<data name="bullet_redorange" mimetype="application/x-microsoft.net.object.binary.base64">
<value>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</value>
</data>
<data name="bullet_redorange_blue" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAnAwAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/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+IMQEAlWAxZIBKmAD7JAHtgECkEx2An2gGpQBxpBM2gFx0EnOAXOg0vgGrgBboP7YBRMgGdgFrwGCxAEYSEyRIHkIRVIE9KHzCAGZA+5Qb5QEBQJxUIJEA8SQnnQZqgYKoOqoXqoGfoeOgmdh65Ag9BdaAyahn6H3sEITIKpsBKsBRvDDNgJ9oFD4FVwArwGzoUL4B1wJdwAH4U74PPwNfg2PAo/g+cQgBARGqKKGCIMxAXxR6KQeISPrEeKkAqkAWlFupE+5CYyiswgb1EYFAVFRxmibFGeqFAUC7UGtR5VgqpGHUZ1oHpRN1FjqFnURzQZrYjWR9ugvdAR6AR0FroQXYFuQrejL6JvoyfQrzEYDA2jjbHCeGIiMUmYtZgSzD5MG+YcZhAzjpnDYrHyWH2sHdYfy8QKsIXYKuxR7FnsEHYC+wZHxKngzHDuuCgcD5ePq8AdwZ3BDeEmcQt4Kbwm3gbvj2fjc/Cl+EZ8N/46fgK/QJAmaBPsCCGEJMImQiWhlXCR8IDwkkgkqhGtiYFELnEjsZJ4jHiZOEZ8S5Ih6ZFcSNEkIWkH6RDpHOku6SWZTNYiO5KjyALyDnIz+QL5EfmNBEXCSMJLgi2xQaJGokNiSOK5JF5SU9JJcrVkrmSF5AnJ65IzUngpLSkXKabUeqkaqZNSI1Jz0hRpU2l/6VTpEukj0lekp2SwMloybjJsmQKZgzIXZMYpCEWd4kJhUTZTGikXKRNUDFWb6kVNohZTv6MOUGdlZWSXyYbJZsvWyJ6WHaUhNC2aFy2FVko7ThumvVuitMRpCWfJ9iWtS4aWzMstlXOU48gVybXJ3ZZ7J0+Xd5NPlt8l3yn/UAGloKcQqJClsF/hosLMUupS26WspUVLjy+9pwgr6ikGKa5VPKjYrzinpKzkoZSuVKV0QWlGmabsqJykXK58RnlahaJir8JVKVc5q/KULkt3oqfQK+m99FlVRVVPVaFqveqA6oKatlqoWr5am9pDdYI6Qz1evVy9R31WQ0XDTyNPo0XjniZek6GZqLlXs09zXktbK1xrq1an1pS2nLaXdq52i/YDHbKOg84anQadW7oYXYZusu4+3Rt6sJ6FXqJejd51fVjfUp+rv09/0ABtYG3AM2gwGDEkGToZZhq2GI4Z0Yx8jfKNOo2eG2sYRxnvMu4z/mhiYZJi0mhy31TG1Ns037Tb9HczPTOWWY3ZLXOyubv5BvMu8xfL9Jdxlu1fdseCYuFnsdWix+KDpZUl37LVctpKwyrWqtZqhEFlBDBKGJet0dbO1husT1m/tbG0Edgct/nN1tA22faI7dRy7eWc5Y3Lx+3U7Jh29Xaj9nT7WPsD9qMOqg5MhwaHx47qjmzHJsdJJ12nJKejTs+dTZz5zu3O8y42Lutczrkirh6uRa4DbjJuoW7Vbo/c1dwT3FvcZz0sPNZ6nPNEe/p47vIc8VLyYnk1e816W3mv8+71IfkE+1T7PPbV8+X7dvvBft5+u/0erNBcwVvR6Q/8vfx3+z8M0A5YE/BjICYwILAm8EmQaVBeUF8wJTgm+Ejw6xDnkNKQ+6E6ocLQnjDJsOiw5rD5cNfwsvDRCOOIdRHXIhUiuZFdUdiosKimqLmVbiv3rJyItogujB5epb0qe9WV1QqrU1afjpGMYcaciEXHhsceiX3P9Gc2MOfivOJq42ZZLqy9rGdsR3Y5e5pjxynjTMbbxZfFTyXYJexOmE50SKxInOG6cKu5L5I8k+qS5pP9kw8lf0oJT2lLxaXGpp7kyfCSeb1pymnZaYPp+umF6aNrbNbsWTPL9+E3ZUAZqzK6BFTRz1S/UEe4RTiWaZ9Zk/kmKyzrRLZ0Ni+7P0cvZ3vOZK577rdrUWtZa3vyVPM25Y2tc1pXvx5aH7e+Z4P6hoINExs9Nh7eRNiUvOmnfJP8svxXm8M3dxcoFWwsGN/isaWlUKKQXziy1XZr3TbUNu62ge3m26u2fyxiF10tNimuKH5fwiq5+o3pN5XffNoRv2Og1LJ0/07MTt7O4V0Ouw6XSZfllo3v9tvdUU4vLyp/tSdmz5WKZRV1ewl7hXtHK30ru6o0qnZWva9OrL5d41zTVqtYu712fh9739B+x/2tdUp1xXXvDnAP3Kn3qO9o0GqoOIg5mHnwSWNYY9+3jG+bmxSaips+HOIdGj0cdLi32aq5+YjikdIWuEXYMn00+uiN71y/62o1bK1vo7UVHwPHhMeefh/7/fBxn+M9JxgnWn/Q/KG2ndJe1AF15HTMdiZ2jnZFdg2e9D7Z023b3f6j0Y+HTqmeqjkte7r0DOFMwZlPZ3PPzp1LPzdzPuH8eE9Mz/0LERdu9Qb2Dlz0uXj5kvulC31OfWcv210+dcXmysmrjKud1yyvdfRb9Lf/ZPFT+4DlQMd1q+tdN6xvdA8uHzwz5DB0/qbrzUu3vG5du73i9uBw6PCdkeiR0TvsO1N3U+6+uJd5b+H+xgfoB0UPpR5WPFJ81PCz7s9to5ajp8dcx/ofBz++P84af/ZLxi/vJwqekJ9UTKpMNk+ZTZ2adp++8XTl04ln6c8WZgp/lf619rnO8x9+c/ytfzZiduIF/8Wn30teyr889GrZq565gLlHr1NfL8wXvZF/c/gt423fu/B3kwtZ77HvKz/ofuj+6PPxwafUT5/+BQOY8/y6xOjTAAAACXBIWXMAAAsPAAALDwGS+QOlAAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJTUUH2wYaDQ4mQJ8/NwAAAahJREFUOE+lk01LW0EUhl8TLSiFLlwoF3+G+EPqbyhakFux2gj5YNAm0aI0foAbKVpXQii4MChcISr1W6nCwaqgRmtX1QbiYOKlvB0i7q5wg4uzm/c5c54zA5J4Tj2ER5ssU4qfG4XD9cLkS8W+oOUH/AhQXBsic0vkaYbMxngXhvIPSDUIcw65nTDhHnJnnH+6IP4Bg6+EP9Pkcoh0bPL7AM/aKwF8rFFcCpvOY+Rakpx/x5nWunO3GqKDkOsA1CXg6aTsoBSG9bcb6rcNOX4DmXpde54LvaXrLPJ+fo75aJSHqPJ04rnCkunsOgssJmLU3Tb1+Ai3EPR04gnIByDF9Cx1qJO3HW0sDCTo4IV/wJWZ+SYSoR5LmXCcu9EkW+xvWcy4giktmLxWmLgsO/G8wREC1h4CahU1kjGdm01YHfzj4oXLudN7RjfzROqw7MTXM8bXkizkXMbWi7RXNEf2NfFpqzySP8CXvMyeFNlpwm3ZWyZ2C0S/UwFg4kpFNm6Y+qEZ3y6wd/kX8WG6ghFGjywM7SkkVwUqI3g/qdAef1qinz/weOY/mjjOrXfVqDIAAAAASUVORK5CYIIL</value>
</data>
<data name="package_green" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAoAMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAzJJREFUOE91k9tP22UYx383mugfsAu9UYZmE6fziISQ4XCs22CbMe7WxIQYjWbGLNkupptQEDZgtYoadWrMmKxpOZ9kFEYpUKBACz1ShhzaFWgLLbXQw/b7+ELiog4vvjdP3u/3zfM8n0cCpJ3kai3McDUfa3A2Hu121Cte+L93D5jd7cd3CbPS2XxsbcX+I35zOXbtoahN80bl1G8HH/tv0P2A6Y4TDwlzkau1wOObUHM3fgd5Y5H12w1sepuZv/UJ1msH5iy/5nw48Uv2I38HbQe4O07ku9uOG+YGP2Nz1SpKGyCHSYVGmdadZNN5mcS8hnVHDZ7mdxm/mmUa+/7Vwi3vlvlnd1uhHHLXEgtMEprtYXZYPOyvwNH5MbNdHxBzqohNXCDuuUpyUUNwRIn9+puM1rx4XRL9puT4PInAGKFJNQGzEl/vaTxNpzB9nU0yOA4xN6z8jvxHDdjPgreW1IySYfXzKUkMK3wvvgBRG0lvI5GJMmKWC0Ln8DYVbNdYbof5H5Ad54jpc1luyyFiV2G6si8sORqPxOMbHhEgfonaIaBn015BbPh9llsLSE1XwUwlCaOCYPtrLPUq8HcqiEypGKrKSEp23eGUza/G5bvIvYgJ1oQCXaQ8aiJ9p0gYFIT12QQHDrOsP8SdtjxsuizMk+UMXtqDJPa7uRCqo8XxOl2uI3i9laLfFvDrkN3nWRtSsGLMY6knj5mWHG7U76O8aS83p0oZ+OJpWZqqO5iQU34SUQudznzqbVn0u0+yvlCNPP8NgUEFi90HaGrYj1Kbzue6dAy97xE0lmAsTY9Lk7W5N2f0Z9nw9Yr1ewgs/YR2KhPtZCZW19t0d2ZSqknnvCaNGx2FIrAMb8sZRlRH6S9J65MEWQ8LsooEHJ65W59yd3UIeX0Uy+0i6qwvbRu/bHyFpdEKAn3FWL59i37l7jlDcdpHhotPPHofZUHWLvN3L5cKONZ8xmL400xytRuvtZzw+CWc197BWPZUVJirDMVPPv4vlP95ICNf7c8YVj1Xa6p+Vg6MXWGh4zSm6tytfrX9JbsfuModT3krcPDyM/kDFXt6xKSNwrzN/U76C5r08l+6Z9+nAAAAAElFTkSuQmCCCw==</value>
</data>
<data name="bullet_redgreen" mimetype="application/x-microsoft.net.object.binary.base64">
<value>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</value>
</data>
<data name="server_connect" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAASwMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAt1JREFUOE+lk9tPkgEYxrlobV71H/gPdNHWcmantVoHu3CVzU7WLI95mGx+NhDDZm54HPOAohlkAuYwRFHw8+PwIYgiIBgooCApacqs62YXT98nF11ka62L5/L3e9733V4OAM7/5K+wx+ORO53OH3a7HTRNg6Io6PV6aLVaqNXqoT8KfD7fMbfbrY5EIojHtxFZ30AkEsMam7V17O19g1KpPHx8r9d73eVyfY7FYkgkEnAueDHrcMFmX4DVNg+rdQ6hcAQymexwAQNjd3f3IBsbm7AzcE+PFBJJNzo7u9De3oGV4BqkUunvggF6L1Wj0YAkSQbeQDQaxQzbOjMPi9UBs2UWlMmG5ZVVRtT+S6C0fU2RmxOjfaOL3w0GA4xGI0ZGRpi9o6CZkdlWsViMtrY2NDc3I7AcRktLS1LAtB7pp76sDtI7GLRsoeXNJNgpVCoVQqEwTOZZGM12UEYbSMqKKZKG3x9EQ0NDUiCd2k7tnIjjg2MHKjoOsXYNhHgSFmfwYE+CqAY5TTOxQjH/FjnDN7HECIRCYVLQqvmU0aqJQmHeRJM6hC5dGDVyLx7WKJijdWJ4eBgFBYWYNJhwaeAs0rvS4VtaAY/HSwrqlMGselUQvfoIXgz4UNXnQr3CC6J3DvfKmyASiVD9nIcJvQm6CQpjOgpeXwBVVVVJAVe6SNQyoFgTRGWPE0ViG3IbTShopfGk0YgL2Q3Qjk1jnIXHpzE6RmLRG0BFRQU4pRLP0bxWx/4r1RIEcjcEMtdBc3mHDYVtZlx59h6CRg10kyZGQkLDZtQAz6IfJSUl4DxotO+XdDjw8p0H3O5ZZAv0uFqqxvnHg0i73Y9r9yWw0Hb4A+GDVhZks7W1w9ylAJwbtdOGXJEFOUISZ54O7afdlRMnb73OOpEpyTh+WZzKF9Rl8vn8jwRBgMvloqysDMXFxcjPz0deXl6Qc7FSm3KuSG04/Uixf+qO7Oi/vvZPxDTnf9/GJ/8AAAAASUVORK5CYIIL</value>
</data>
<data name="bullet_redgreen_blue" mimetype="application/x-microsoft.net.object.binary.base64">
<value>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</value>
</data>
<data name="arrow_ticker" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAATwMAAAJHSUY4OWEQABAA9AAA////b21t+vr6joyMubi4cnBwhIKC5+fnzczMe3l5sbCwqKen7+/vxMPD3t7el5aWn56eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIf8LTkVUU0NBUEUyLjADAQAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAkKAAAALAAAAAAQABAAAAVQICCOZGmepTAUbCEqhGCqrZgUxpEaNYDwBtmIgFuNBDwCaYVQkRCFAYmFoo6sKSyASVr4oiRi8LpIkpA4hKg1Jh14iTVrIDwTFPJ5HcXvj0IAIfkECQoAAAAsAAAAABAAEAAABWggIIpH0oxoKhrF4KioQCRFfcDAwdbFAgiMlIBlaBQSDMHAIEARCkzAgPBjUUeDAkK05bZQNZggPKo1VWRRtivoIr6jZ5QwqBauoqGPQWsQzyNBAAs8UDcwBzwJBIAwDlkGOCoNCYcjIQAh+QQJCgAAACwAAAAAEAAQAAAFYCAgjiPzkCjaFEgqCsRQFAktpIcx7zOBCjpDyzFLtEiEguEGSC6YJNmxeQAIEL7RzAXYagsugVdEQNwOWQCiMEgJFoUsMI5C1AqOaxBK5u0MVT81dwMEfCRrDVwpDwyLIQAh+QQJCgAAACwAAAAAEAAQAAAFUiAgjmRpnoAglAIxFMVAqINDHgasF8Zri4KcASFC5GA/AIG3Ar6QI0WCOHpCUViAY7ttonYLEiKhIOnCo2CBYIYNVUamGXLcGQ6lcOsp82b/gCEAIfkECQoAAAAsAAAAABAAEAAABWAgII5kaZ6oQAxFMRDCyRhtXRjHuRhIjNCG2CgHEIoENAIg5ygsGKZGIWFIAFhTmAiBbTWktQFiREi0BgCquWFiLAqOJYBwMxZjxCOwJ/gN7CIHNDY3UCYqWC+AKIyNJCEAIfkECQoAAAAsAAAAABAAEAAABV8gII5kaZ6oSBTFQAimQDQAwrLGQSJJkQiwmqFgCD5uhQVJMCSIGI0eSzeyDUgsB8GJLXSDKoKDRRoUEKTDLdFgqIhgwAL5EDGJCBiwl0CPDkM3aAgvMQRmBVwpi4wmIQA7AAAAAAAAAAAACw==</value>
</data>
<data name="connect" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAADgMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqBJREFUOE+Vk91PkmEYxjnwxL+gMw77MNey5ZKtVKYrdYusg5huzmXO1MUQM3SKkSYkwngVId9eFRRInKCAyjTxA/MjPwh1fqNlmdhqHbsltqsXWi6atnnwnD33b9f9e66HAYBxkiPp2IwVtS75C6j5vZy6maT/Dre6voc1Ob8w1Q4fS961xakwrasrTWuQW1ZRZVrEXcno3rEA3fC3cLJ/d7K+9zOU9i3IzF4oOr0gHZuota6iqNGNxJK+/WMBGodP2DywA/P4LozD22h6/QH13esQGxYgaVvAbbETsfldcUcCSOfGaWnPxE8DPUj1bUHavozy1nk8ombxVO9BlnwEV3PNmoC7EEAgNtW/a1V1D/yonChGhc0BlW0NRNcq+A3TyCHGIGycQorAjivpek4IQDv0Nayhz+fVOXcQOJK2lgPxqBDphO2A/+ItyrSzSJMM4qFqDHH32xCVSrFCAKpeH5Owf/y988g2lJ1rEKjb97k15uKkEuNBRpUTeYQL92oGEX2nCZGJdcwQQHXne5bMvAH90Cc871iBumcdpToPMmUav2iQh+v8etx6bAM7y4jzCYT3LFseFgIQ6Vc4TwxLwWcKCCui3HhmnIOQmkK2ohyl/fmITlX4I9hK65n46vA/5TuUyCM9dmn7IpSWFQjIaeTWjiOzZgQPiDfIpq3fyBX7L3Gk5/5tbRCQp3YXCps9UFiWacuzELW4g7b5mong3kk8C6JuksKjKs+g+ywQvHSjwjAfjFymnUEGbTtZYEV8tgkxXC0upjRMRiYQh7H/BjHSqsdQrp+jC/IOOQoXkgttiMl4pbnM1XGiUknWhWQ1MyKBCAo7MkFK2QBt2oUsGb0nzxooCPskv5PBLrCfupZnBivTtBfN1cWdZDhw9xfIGbpCZGflsAAAAABJRU5ErkJgggs=</value>
</data>
<data name="bullet_orange_blue" mimetype="application/x-microsoft.net.object.binary.base64">
<value>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</value>
</data>
<data name="bullet_red" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAKwEAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAL1JREFUOE/dkqELwlAYxM/NWQz2/YMWEYOgwibPsGFUNFqMgsWgKKzZDLaHmNWoDPTBdMj57Asbawtf+eB+xx0HkshzucR/48ICLNi0IOIypDIh7wbEBfqXUHhyB1r8HQjGwY6f9Yqh6/KEkkgNeGvnONgy8vtU7SbVdMwDTJkaEBqQ0XJB1Wnx1ajzOfQZoJIecNOZH45DNRlpscdrt8c5qukjnGHYRxhiD0tutPNMiz3UMpSYYd6FXWKGDn7xfN6LQf68lwAAAABJRU5ErkJgggs=</value>
</data>
<data name="page_white_magnify" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAQwIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdVJREFUOE+Nk0tLG1EUx62fw4J7d1b8Dl0ILly48RPYdcGldCN1pSZIRESwtPGxamvwQZBIHPERXwFpNeapM+Rlkpm5mRsz5u89YybxSWbgz1y45/zO457TBqBNfB1Cn4R6W6hT3LeTjy3rQM6c82K1Wr03TRNvSdzD5XJNCNtnEBvQS866roMx1lCpVEKhUEA6nbagiqLA7XY/g1D0D5Q2GRiGgUqlYv1JmqahWCwik8lYgHK5DAri8XgsSD37JoCcbRGAHFRVRTabfVVWvVcUvAkQZTQM6Ux1U0lUSi6XszKRZdmyeRPwsnlPIZQJ9SOfzzsHmGYVgXASK9IF5rcS+BW8gS+Uwl2FOctg+yyBv6E0LhWGWI5j70rF2kkW/uOkM8CSJOP8WsN+vAwpyrAjFJY5vNvx1gCqf84fRyTDIV3pCEZ0+P9pCCU5fgSunQG8oubzG4bAxaMz6TDFMeP73xpALxIIK9iLqDgSTrtxAwci+p9TDZ6F3xgb6h6tj0BjDmovn/FW4zi4vMWy6MXijozZzRimF3wIr81CmhpiP790Ddq70CMmkAnAu8tkw6P7q7XDueFadH0Svm+fmQ34KNLpcbDO1rp/7esY2RwfMDa+9+MBN5GpoorUyG8AAAAASUVORK5CYIIL</value>
</data>
<data name="money" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA5wIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnlJREFUOE+Fk0lPU1EYhrvQrYlLtybGuNT4BzQQMRCmRhSVWKNIEEONRRA60oEaRttCZ2gpCFpqSy/QgUqhLVEqYNwog5SiMXHnxhSJoK/nnkYiMnRxNvee9/me833ncABwMq2WWFNKPSU/ste+jOHmqDJlmddDFZZBEqzfBTkQ8DiiSJnnO+H/PALjrA4ifx1qmPs7IPsCiHLKNMeGGThX+uBbG4b2VSsE3mpUDd3ZhuwJaJpsTBnndPB/8uL5xz44Fi2oGxVgNOlBa0yNSmc5bvaXUcgugCosTRlmtfCRcHNMBVVEBvuCCbYFI54u2cAkXWgMiXHdfmV9F0AxIVnXv9EQXS8S35ewsfUDg+/6oZySpMOrLshCQly1lWz+nQg10MXbT8hfin92xZ/QszZHVTRsiHYh+S0BdVQO7+oQpONCtjLKektx2co9RA108TaxnCh1znTQ8LNlB9GW0spsWBGQpcPBBrYyZr5OQxR4hGJTvpICWCXdTDvGSIMGl3vpWXs+GKAg2uqIHMOJIYiD9ahw36Lh6S8RhNeC4JoLcFGbfZSjnJDayYL1rQEjyReoGeGj+70efYvdJOyk1WrHH5BwDGPLDKoDlRulPSXI0WQLsjrOneEow9JjrAV7SQyzGqrrWLCmw+RbuYsHZtENzXQLCg15wbzOHE2OJuv4jiY2+B5a7PNWCBg+tK/b4FlxQuirxSVLEYQEwjUXJgr0uedzdRdO/f8e6BRqGP7JxpBoK7Tqxz1XBQgQRcb836TTAa6poOGgx0YB1e67h8nt8pQP8H7x3VWs6maJtfgs6fS26n6Q7Zt4e4B3+obj2hwZVW6m5/3v/z84vMwbgzo2GQAAAABJRU5ErkJgggs=</value>
</data>
<data name="box" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAANQMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAsdJREFUOE+lk9sz1GEcxvcP6MpYm8PavW26Kam2I6oZHSxWu1iLPUQYQxSWtdaytA5rF7GtIYQ2kYgaNek0TQ1CTCrHJevcpJ+2+6f3tzPNdOPKxTPvze953s/7fL8/BgDGbrQrM32xM8ByhbvntoLbZlZwts1yjqOWqEbGcVRLvR1Vsd6Oyhi2wxTNdlRIvBwGiddaWZSn+h81bXYh5q12lR8GbskwUCMnpxwvqmV4XiVDf6UMT00y9Bml6DFI0VkSBUsKD/oID52TgJhnO9QBeGWOg/XaftxN5KIpnouGOC7qFBzUyjioknrDFOONMjEbljQ/WIskqEnmoUjk3s0g2NT0YyXaUvehXs5CXSwL5mgWqiVuMIqZKA9nQi90RaHAFZpgF6iCXGBIPIYeYwIKhe5gkPdSWyMm/CH6/V6P7Xc6/HqtxdZAHn48U2HzSSbWe9Kx2pmKlftJsLdexfdGBexdWhRc3gsGKYv6OVhBPo7HRq8Ea4/EWHkQAfs9IZaaBbDVh2DOHISZqguYMgTiq/4sJgv9sdiuQX4YCSBNU5sfyrHRp8BqRySWrSIstYRhsSEE8xY+ZqsvYroiEN9Kz+GLLgCf8/0wnnsSttZcaAQsMMiYqPW3JVh9GEvwhAQvFLY6PuZqLmHGdB5TZcRYfAaTWn9MqE/hk/IERm/wMN+UDXUoCTDFsKnVl8Wwt4l3xJ3IO41x1UmMZfAwkn4UH1N9MVufhdwQNzCM0WxqpV+HhTuiHXHHso5j9DptPIzh5EMYSvTBjCUTqmASQDaLsvdqCbJgR9yRtCMYTvHFUJIPBhMOYjD+AAnIQA6fBJRHeVGLXRosdxdgqTPf2e6CVQ1biwrzzTmYa1Q6cWfqMp2m/5XNZ4JRKvbsL4n0xM1wDxSLPKAjy0EviJbMmB4T3XQeKYt+L42cQ4vcTJuVQcw3u/4b/wJ+v5Cv68UEAwAAAABJRU5ErkJgggs=</value>
</data>
<data name="key" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAcwIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAgVJREFUOE+Nk01PE1EUhht/TZu60OFDRoXEolEXEv+ASxau3LlBRUqqpRNMTaQh8ZOwIjSGkBgNJRIMmFKkBoPTBsFaAY2tzrSdzkxLx76ee7G1agtdnN08z/vec+/YANj2m62p0wEa/J7Av982BVuFj2BTT9JQUEm29CiK6Uco5V5SeJlLEpOuB5UmdQW1cOHrMIrfxyrpxAGJMRHhEXGOSRoJeGUGm9s3UPh2j2Z2TxJ0oWwp2BwVuKShgFVmMJ+dAS4pZWehrUvQN8/jZ2Ee6/4j9W+AJVnme2ow9EfCRW7k5LPIRDtg6U8hX3P8LyD4ENtBauEKATeRXe2E/uESjMRlaLGLUFdaUVI9kPsdmLnVGq8eoXrf02eQWryKXSVIaSLBF6hFL3LRk1CXBA7HBpwIedvW/loiq122snTOEIztPmTe2aGvHYPxaRBbE12wtCdUewIxtxNzUtvb6jXWvrRiahJavIeSnNDkTphJHyI+QXkx2LIhX3cg7jmM+Tvty7Wv0baXnKHKU8jHu6GE7cjHTsH8PIRlSfgx7e0Y3++pM0FuVw3RskQoi3YYGz0EexCRBOWZJN4/6F/hDUr518jK3bSwc9CTboS9RzPPh8XRg2C+xGTQtWKmF2Ak+2F+eYwln6DO+I/fbQbmgsjDrr7VQPvOG39Lmp351ciJ283C7Ltf3aj/RBYgBxEAAAAASUVORK5CYIIL</value>
</data>
<data name="bin_closed" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAFgIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAahJREFUOE+lk7tqQkEQhvMAeYm8lJaChQgKitqoYKEiWmghnFrkiIjH+xVstFE7L4iEHIwX8NZodwJJ8PzZWTAE4kogxc8OOzvfzM7sPgB4+I9uBne73adCoSAxqfV6/aPVaqHdbqPT6eiKorzm83mJzlDim4BSqTTv9/sYj8eQZZkrl8uhUqnwPfIx+FwIKBaLl8VigdVqxYNpJVEVtJKPAS5CQDqd1s/nM06nE/b7PTabDRfZtEc+dobFC64Qi8WQzWYxGo1wPB6haRoX2bRHvnA4LAYkEgnUajVIkoRgMAi/3w+fz4dQKIR4PI5MJsPtuxWs1+vvu6uqyu3BYMCz01QCgYAYQFkOhwMPGg6HfJ3NZphMJkgmk2g2m/B6vfcruAUgCMEbjQY8Ho8YEIlEsNvtflVAgGg0imq1CofDIQZQ4649+HmF6XTKu18ul2Gz2cQAt9v91uv1LtcqqInXHlB1qVRKNxqNmnAKFotFYSNU6ckShLTdbrFcLvkE2Dt5N5vNshBADgZ5ZtJdLhecTifsdjusVisMBsMnC34xmUyPdwF//eJfB2UIPj9zcm8AAAAASUVORK5CYIIL</value>
</data>
<data name="information" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAFgMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqhJREFUOE+lk91PUmEcx/1b9E/onG5am14012aDJO0is4ZporbSVZgNVikm4huggA3BUPOF8g1KUoQEjmSEvISmnhyYQVtb3UDWsvz2QAu1Whd18bk65/v5Pd/nJQNAxv/wWzhfs5J1TBUS5SmC7JEWbzxH5olnyxbYbJlbdPg2k/XrsH0CjnqZd1QeiFX0+tFrj2CU2Uyht4bBVz8FLZqN0WIrb68kLSBTebmtvkTL5Cos3hh6piOQGF/i1vAy5KZVGB0baBwNga6cSNAXJ9KSlCBPGczMbVuMJsOmZzGISOjaQABDrtcYcm7gqsEPYX8Ahtl1SO77QZcZo3TpcGYymxLkyhfF5VovzJ63qBsIQUgqXNb58PHzdopqnQfVPR4I73ox8CSMU82PQRX1i9OCnDYPq7dGoDSxuNLrQ43Oi2qtB332dRgIld3MDzQuUisA9fQK6EIdmxYckjBb4wtvUNfnJ5Oeo+qOm/zMkO/ADkGgcqK8c47gwAWNE0YmDIrXtZUW0GL71ph7M9U1OalC7SIhF0KRD0h82kZZhx2l7TacIwgUNozMEwFXsVdgZbVWFtIHS6jSuCHocuK8cg4vwu+J4AtKZDMoIb35zRbU9jBQWoKgj3fsVqBrLeJiuR1DjgiqVAwEcgcsng18/baTquB/9Q7FEjPBhO6HIRReHyWC9t1NpC+NZdICY/TmiA8G6xrK5DbwW6ZxRjqF4gYTTtdPoKh+HK0jXnK882T50ijNle4eY3IzKP4g70CBPiEa9EA/swKh1kmW/AhnG82oUdmgNgUg7GNAcxoSJLz/Iv28mlShnkcVdMdO3piEcmoJ95wsYQ0d5iDy64ygOI0xmtv056v8U0KfUGdRvE4Rla9gKW5znOI0xclEliA6yG34+2P6l2f9HTiGy+y2ZQFvAAAAAElFTkSuQmCCCw==</value>
</data>
<data name="bullet_green_blue" mimetype="application/x-microsoft.net.object.binary.base64">
<value>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</value>
</data>
<data name="folder_table" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA8gIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAoRJREFUOE+FkttP02AYxvvXeCXe6Ga89cZrDcYY4wH1RqPBEKOBKALBgUgguAlEFJzAFBwHAUUxIGMOgXkAARkdDLYxdmJsbbe2dGsfv9bABSebPunF29/vffqlFABqe5pH4oWvbHF/03AML4aiMPYHUdmzgvIuH0qtyyhqW8T91gUUNNMTO2BVZratR5NCGv/L7Zdz4q6Cxi9rGtw6+xzm6XoYnY/xaLQEpfZCFNkKcG/ojjbPbZjZWV9t0DAY1V7Y71Ln1+umdhfUD4Q1gcUe3jPq/KrxJ6j5viOT3pELks9+aSsmcmibArWF9VtoR5koI+BitRMU3asXFUUmLyjkViOjui8AlpfQPhqGVQ0RqOkeD6N7LIT330PwBFmcrRgjgi5dQskIEFeqkPLUILXchMp3fjBE0Dke0Tbv1sAdYHDaMEoE7XpWlhgCm5BcMIKdLUZd2zBWbDWgTbo94/IlkG34SgRvdVKaDyHiKIS/8xy8b05iqSMHAh8Dn4qBiwexvhZALPovcU7UpKrgfIVDpmjLUUn7flkk4YFMClNuDxwTHRh2WDBob8GHwUb0DtSh5+MT9Du9muBUqR3H737upmizfkPJ8MiwY0jHP0Fas5LzqITor4DgLYGwlA9+8SZSdA6Sc2fInqAm2Pz9KfqZXpQlFlKsFxvhFoirTyH4HhK4GMJyAYFzCXwZ3J9ssNMnIG+EtglMOkGR4gQ2QwzUaCDvySPQFbIxGxyB2MljYH4cQsJ5AGl2QhUIWw3mqw6vSomFRHLxtZx0N4Kja8G5qsDNGcDOPCBb88H8zgMzeQPMr2sQIyMKYRJbApfh4C1XeZbFVZYVIU9h35Rpc4Ywxk3BX4qEPVGmSS+cAAAAAElFTkSuQmCCCw==</value>
</data>
<data name="database_save" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAARgMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAthJREFUOE+FU99PUmEYZuuiq/6Cbuq2i7bW1kUXXbUuunPpajVXtrVpU9O5lmZplvZDtFrNKc4gJCTCHyiCim6QVEgTBAOE4DARQfocPxQE4tfTd06zi2jrbO++9zvne573vM/zfjwAvIWFhYPz8/MVWq12fHZ21jkzM5PTaDQ/p6enzSqVSj45OXluYmLiAHv272DBxyjYZrVaEQ6HkUgkUCgUkM/nEYlEsL6+jsXFRYyNjRlGR0cPlxDQqjq/349isUi//fvJ5XJYWVmBXC4XlxDMzc2RTCbzXwJCCGQyGSkhoP2SdDqNra0txGIxpFIpsBWz2Szi8Th8Ph8MBgNCoRCkUmkpgVqtJixoe3ubO+x0OuFwOGCz2Tgg1Qh6vR7BYBASiaSUgCpN9vb2EI1GuSobGxvcWt9vR6vQjsYBKx6+c6L6uRk1L824PWhFk8CG6/wlHLk8doo3NTVFkskk2B5ZMRmGQSAQwI3eZSjNCU5VlTFQoq5YR3DtmQk8pVJJWOtYDViw2+3mrLvy2AihPsYB618v/yFI54CdDNAzsYmqbiN44+PjZHd3l/t1l8vF9e/1elH5dAliXQzZfAG5fJHORhF5Gtkcuy+g6z2DC+0fwaPDQfbVttvtWF1dhcfjoS18hWCWoE3K4MEIg3sSD+6+daOFRrPIhWahC5WdOvDocBBWfbYNFrhPUMU34ZU6hA7ZBg0/7kt8aBV70SLy4I7QjaZBOy62zYNHh+M89TdpsVi40WUFZV0p7/iEfg0BFQihnQiNGELxGII0j+wl0DLkwNkG5e/LQf09KhaL34hEojhdoVAoUNZuwKAmhnCCoFNXhgHTLQhMjTQvx4/kJlqHGJyu+VB6uwQCwaG+vr4TFY++QGthXWBgjD7BWnIYa6lhmvfQd+voGmZw5qailGB/1k9Waz9f6jSgmv8NDS/8qO31oo7/HfXda6jlm3G2ToHjV0fwC5QBPCf+f5H0AAAAAElFTkSuQmCCCw==</value>
</data>
<data name="bullet_orange" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAJwEAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALlJREFUOE/dkrEKQWEYhr+STRkMdDpX4x64A2U6SmQ4pT/JoYgOlyEbE0VyDKx/yUBnMSmjTA9nN/izneEb3+fte3oFkH/ur3BUHFuAb1v4tmKY0wwyGi+laCWsb7K/O4jCQR/CFVwWsG7ydEX9DhhlNeESDp1PuA7HCfeq6N8BvbTmNIVNA5YO7LpcyyaAdlKxcj/NYwg8mFfYFw1eeLliPWqibo7oc0n0tiBqlhcDiQbzju0SDRy8AYzt7sj8fh4AAAAAAElFTkSuQmCCCw==</value>
</data>
<data name="script_start" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAkgMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAAB7AAAAewAERLra3AAAAB3RJTUUH1wsQECs0r8RKFQAAAyFJREFUOE9lk11IU2EYx3fTRVdBdN111EVkJBmShn1cCCuitDIxK8EisQ/6oEymuTkr1MwyjSxzamVWLsvUmTNt083YcK3mpi6Xnxvqpvs65+z479kZDaIDPzgcnv/vPM/z8ooAiMJkvHbEEpoClRNX22eRo5xG9rtJ0Dc38ZswEENEF/GCSCZWCeEw6S/Gc+6qnfT67+NleDiXOYy4gjBNB6Gx+9ConwPVzxPpUUGawlpUo3EJacdiCDNuHi4PjwUfD0+QR4DlwYYi8gC3ArXVC8o4o4IjT80VDToXOB4wz/GwuHjYnDzs8zwcJJsk2aQ7Yjj/7BcYDij+ZI+0H+ZwjVGhNM7D7Qd0EyyGfnMwEqZpjoQcLHMhEoZAflx4MozekQVQZioqOFip6+odcWNinqP2GHwZZfB1nIH2Fwudg8U3wjjFgl8BjpXpQfUeYk9UIC7tt1pmfBimIhUJVDYGPTYWvWMR+scYDExwwoiplQOg+rXhzqOCZHk34/aHoLUz6Ka/94xSkAR9FP5gHkV5txyFbbkoU0lwrLIZVL8mKthX2L46WdohbLdXCAcF1LYg6nVKtJqb0DfZBeX3FrSONUH++SYyag/IooKkG63rD8o6wIRWKBhuncIk+GCy4Y2pDn1T3ShQXRFOoEpzB4of1bjWlh0QV+yKE0ZIvPxqQ4qsnRa0gi/jrNC+mnZQqirG+/GXeDRcirzOc2AYBn6/H9LPJ/FAL8O+0niDKD5XsY5ovvvGjCk67+faAFoMAZqbQX7rOdT9rIJcn4f8npNYXl6Gx+OBz+dD1isxEkpi/aK4M7WphP+otA03GkaQW2vB2cc/ceqhBeebruChoQS3tJdw4u1uIby0tITrHWJUfJVgu3SzQRR7urpEqtD+dwdoHbDMWlHYeRFPjGU43pgAr9dL4f14rL+NrIbUQIxkY5xoa0Zldk75J9R3/sB7jR1932dgsi/A4fRh0cuhcbAO15TZuK+9hSp1Pu71S3CqPoWNkWyKnMKWtPJ1RBFRT3wkBgkr4SLYuMwHSLoow95iMRLlO7Atb2cw5sKhzL9X4A9Osg9mtv1ymAAAAABJRU5ErkJgggs=</value>
</data>
<data name="package_delete" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAqwMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAz1JREFUOE91k21Mm1UYhl/DtsT90xhiTPyxRM0ibs7FmC1kEVGgbnTMaGb8q1uyJUtmSBQ0KolhcwzYSAVjVDJj1klQNkDK11YKs0DLx/gYbSmFjY6WjxbaF7a2lLL38inGmbj5Jk/e5OTc13nO/dxHAZRH1XiTPm288cAVV/3+a87Lulf+b99DYnfzwVQRF7saD4QDjp+YGziD4/esu2O1b5Xd/DXzmf+CHgAmWvI2i/joeFOuxz9kYH11Fi06w8rUFWK+Rryd+YxcfH16+Jd9J4Z+Tn/8H9AGwN2Sl+02Hbw+3fMVsdCILEVBU0ks9TNRd4iYq5S4t5YVZxWexg+5Ub3XNvjDa/qkNim+4DbptSW3kUhwlKVbHdyyy8Y/S3C2fsxU23EirgoiQ0WseqpZm6llsa8Yx6V36K/afUmR+ya0VS/x4CBLowaCA8X4LSfxNBzGVpnO2uINiLgh0IZ2uwocBeAzkpgsxm54OaGIWer91Ttwd4w1Xz3LQ6eJDBdJFeJryN1YY6EZvD+iOQuJmDNYMO1j2VGB7fwOVXHWv63ejwrg3oRAHBA0E3OUELEfZ6Epl8REOUyWEbfqWGzew7xFx/zVPNThMnrL01TFUZejrm8AXLAi7YZtAmkn4TGw3HWY+HUdqjmdxe4cFsxZzJoymW3IIdR3hp6z21VF5vs3QK6AaoelDrnvHzBXh+b+gnCvjoD1TVzndmP94CmuZW6i49BWxkpy6P7mBVW5WZMZ1xJzMrkpOb1LTm+B+d/EqIto3u8I9ugYL9/FyCd7iJnKxYdWIjX59J/YSeex1IQyasy4OmkuIOq3CMQDIYH4jTBzQQCVBLqysby7laiIMcjoC56A09sIns2gff+WmCLJ2iLJOirh8Ex3fsl6qFe8GJAuatCmK5lrf2OjbW3wsuTm3y9c9HRyXXsQZUlW6sD3r56ScIT91q/FVIGErSyPlmJ570nuVX8EIlr9VCEk5T2WQltWiu+hx9T37a40e8VOo+3cS1pw8Dx3Wk7Snb8D+5HntdmCbQQ+28zUkccw6zett2alfP7Ip5zMeE/pi9ndJds7xGmr9dRzeuv7zxbKibeTbct/JilO7vsLiHz2eBEua0gAAAAASUVORK5CYIIL</value>
</data>
<data name="wii16x16" mimetype="application/x-microsoft.net.object.binary.base64">
<value>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</value>
</data>
<data name="picture_empty" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAARwIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdlJREFUOE+lk0lTGlEUhf3bMYmV0SkCRlScAmgiJqDibKLu3Aq9dEiiothIQdMPaGlWHu95UO3QVLlwcRbdVe/r7553uwtA10uiD8+uZwOxVeN6LJVRwYUOSci7BwknM2o6nQnxrAbE1oxiqVy+rTsOnBsXdUlNonSasJ0mKvUmyjouinYNkaWs7QH45VrdwfjmJcJrFwitnGNo6Qz9yf/4tPAP7+dP0DN3jNfxI7yKHqJUczGaMpQHCIk2vxzZzCO8foHhlZwH+PyzDfh+jDezR+iOHaKoOgCoTMBoGxBYPsNA6hS9AviY+It3P07wViwIuVYNMcg+NuC8E1t5jG1c4utqDsH0Ob4snqKvPcaH+RakR0wK9o0fYDsuJrevvB44RkB6GBSLvl+tLmjCPgqVDgYVaXfq9xUibYsRsQiJBcvUEDHhOOzEB+DdW9LszB/Ts2AXHIUQmnAcdsKbMZ8aEFCuuvi2Y2JaLCa383oUQmjCcdgJi6WRDxBIHChLANHdgg/CUrkbtCGIMa0GwskHtxDUgAbie4UnkFYntCGIRtwT03IfA8ZTmZxlV1GVIquytkpH1liebV+aKOlVNu5XeSadHZxaNva5HFR7LvIfKDkz7K3yS37nO+liK/bAYIsPAAAAAElFTkSuQmCCCw==</value>
</data>
<data name="folder" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAeQIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAgtJREFUOE+tk0trE1EYhrtw786f4CoV0WZEdCmIKzeiG28ggrVZSJRCRdAuegEhUBpFRCyFUqEtFo0ILq2LamrbsYlmMklr00togs3cb2cur19SzcSNmxTm4cxheJ/3OwOnA0BHO7QVrhfvjyD/rosvzV1lG5+ut3CNFd6fXhXeRg4RB/8hRftU5EBzAjHF2UHg0z6gp87eu2tVsTXf42zO99h/KS/2Wdvpe6X8m2MXQ8FsVA48C/ZWAsbaCIz1MZilGQSuRC4dgacRyt7erQE+c8RZLhsKpjjVZwqFk9CLo1C/92M3fRvVhRikzACklUeQ+PuoLfcScZqsAvF1lxYKpqPMNXcgZZOoLQ2j8vEuzMoXalX/tNdXOZyAjidOc1YomDzBGuf3bcIEPKMR9EwBdjkJa3MA5s9eGIVb0IXL8PQcxIloi2CccwLPhKd+hit9APs1A2fnBQUfw1x/ALMYg5G/Av3HeWiZM/A0HuJYq+A5Z/tMBdtNwalMUOsTWBvUulZvvQk9dwla9hzUb6egLB2Fq36F+KxVkIxaAZMoPA57ewRWqZ/CcRjiDQpfoNazUPmTUBaPQF44TII0RMo0/0E+cbzM5KKsr77y9cJLaOJTaEICWm4QavYh1EwflJU4FD4GZbkbdnUuoIzcFAiDkTvCcOekMNRZpdX6L0ON7wplRvfvLrRznX8DjdEbMp2PN+cAAAAASUVORK5CYIIL</value>
</data>
<data name="script_go" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAiAMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAxpJREFUOE9lkwtIU2EYhk9ENwqskCgK6UKQRZCVhqFUdCWhwChLM9EuzkItMEJULG3Z3RVmZaStuTDNMi3voZu62dQUzfK+nLfc0CY53Tlnx7dvRxpEBx44/Hzv83//jQHA2Al6Y/AgNNfKjbhS9BPh+YOQ5PWDxsxEH9FI1BNlRBbhQ8wSw3YCs3rC71Ya6fffb5wVYPzNo91kRcugFRq9Ba/qhkH1I0SgQxCQ2XE9TWMS04ZfNgyZBZjGBIxaBIxZBUxyAjjbtHySn0JlxzgoY3QIjme0PlTqTOAFoHVYQJtJQKdRgH5EgIFk/STrN08bLr74AZYHkor10+3bOZrWlJnfNALzBKDr5VDfx6OJaBnkScijbdhGQhvIj0vPm6FqHwVlBhwC3xRdmardjN4Rntpjoe5iUdPDQvuDg87AoYFoGuAgTAH+yXWg+jFir0Nw6H51R9uQBc1UVE6C8k4WFZ0cVN3TVHezqO3lxSX6pdSC6hfbO3cIfG5+Ys0TNmj1LD7R7BVdFCRBFYXVRIRyB85muMHCWnHkngpU7+QQ7E8omucjLRF3VyWGrSKVnQTNbCdU7olrBf7we7IO+xPzecrMcAh2x7x38b1RAtY2RUF761ZEKr0RofCERO6OkHQ3xL47iuy6B4jKOYy9yUvhfWfRAodg5+XsdcduFNEGTUHdw4ntX1BsQ96XVOQ2pIjBrDoZZOVRkGtvQ6LcB/ekOcLGxBlOjFdkpjORc/dtKwbovF9qJ5HbOInTtF57+H5pJG4VX4C08ByuFgQj4WMonqgTcfKFF9bGMzbGMyzdj5g4If2AGGU7ItPbcP7ZdwQ8c8VrnQzK2nuQa24jveYmSc7jsToB55QHsCqOMS6PZjYxHmee3pJmav97A76PV+PggxXYk7wEXncW4lTGdqSqriJEsQ8rY+eOL4tm1ot7sCUoRRIuK4ai9BsKNHpUfR1Ci34UBqMFv8Z5TNAbsF+ezUnzESTfDdd4Z2wIlUj/3mDGLUDmTFwnFEQh8ZnoIEwE5xn8CLvC0rAmbjZcYmZiY1BMD41v/Sv4A2kn7q14K034AAAAAElFTkSuQmCCCw==</value>
</data>
<data name="dsi16x16" mimetype="application/x-microsoft.net.object.binary.base64">
<value>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</value>
</data>
<data name="server_link" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAABAMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApZJREFUOE+lk99LU2EYx4Xu6qL/Quiuv2CimYSbmLtIr/JmQ9iubK0URUI21G1iztSFYCFptjFniKN5nO6czencz1huHj3bnEboXG5UIJXw7X3fC8HaXQceeHje5/k8P08VgKr/kX+Co9Hoq1Ao9DsQCMDn84HjOLjdbiwuLsLhcLz9O9klIJFI3IxEIg5JknB09AVSNg9JymGfyn4WxeIZZmdnSfzVihkgHo/fC4fDn3O5HAqFAkLbcWwEw/AHtsH7t8Dzm9gVJUxPT1cGkGCcnJwwyecPESDBk5M2jI9PYGzsBUZHrUil92Gz2SoDgsEgSqUSCc4jk8lAoFmFLazzQaytb4Dz+rGT2iOg0coAOqxisYiDgwPSdwY+UjLNOjIyguHhYZhMJnzaEWE2mysD6KQpgM5AFPdI1iBW1wLgVv3wcDw+eHxIJtMwGAyVAcvLywyQzWaxuyuyklc4AZ4VHm+2XuPBu/v4SAB9fX2VAS6XC6enp6z/WCyB8YmXGBwcYlPXP3uMOnMdNjcj6OnpYTaj0Xim0Wj0MpnsBlvj/Pw8W58oiqRfMxvW8fExA/I8j4GBITKP50ilUsxGj4z6KBQKEwPMzMygXC7Dbreju7sbsWQSj3R66gC1Wg2r1crsVJfL5RdtbW1uCtHpdGUGmJqaCi0tLaG3t5eWxwCu9x7U19+F1+slbcUgCAKcTidqamq+Nzc3X6eA/v7+88tTJiuTt7e357VaLQPonzwlgHo0NDSgpaWFCdVra2t/KZVKDwV0dHSUrvxMt8hH6IcWi+Vibm4OCwsL5CIn0dnZia6uLqZTG2n1K7mPUlNTU/oKoLq6+hop8XZjY2NOpVL9INWcE/nZ2tr6kMgdon+jNvpGfajvHyC+39hZLhMbAAAAAElFTkSuQmCCCw==</value>
</data>
<data name="bullet_green" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAMgEAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAMRJREFUOE9j+P//PwMlmCLNIIuHqwEOu6ykgLjBfrvlVfvNFldt15o12CwzkcIW2FjDAKR59rXp/w89Ovh/9/1d/6eemfTfYq5hA9EG2G+zvHrg4YH/Uy9N/d95puP/kiuL/ptP0btKtAF2G8yvbr2z5X/3ma7/raea/8+9MOu/SZc28QZYLzdpmHp64v/FVxb+n31h5v8Jh3r+65epEu8Fy3mGUhbT9RtM+3SuGrVqXtUtUm7QSpQjPhBJSdrDNSWSEgYAFyLiA2JoJbgAAAAASUVORK5CYIIL</value>
</data>
<data name="drive_disk" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAAgMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApRJREFUOE+lU+1PUlEcvn9RX/rWh9ya/4DLVluzsq1Nm5LOtTRJs5AKBBI+qMwhalHLaTqEUsQLQl2IF0FehPAikCkwiRj2MhWfzrmbrNb85N2end+9u8/L+f3OYQAwp8GpyNS4KhCLxayRSARra2vw+/1wu91wOp1gWRYLCwswGo2Ynp6GwWCAXq+3HqcWBAi5JplMolwuo1Ao/Ifd3V0co1QqYW5uDmq1+kI1QTgctmazWSQSCWQyGQHpdBqpVKqKzc1NOBwOBINBIaVMJhNSMKFQqCYejwsONAVJI/zg9XrhcrnAcZywejweBAIB8DwPaka2AbFYfIFZXV0V3Hd2dv5xFQ2F0a0Lo304gEcvomhS+tD83Ie72gA6RoK4KXfhmkjiYUizrFSVutjtdthsNiwvL+OWwotZX5mkBIzcF2H9+xln87jxzA2G7osKrKysCMTBwUHaIFyVctDZigJHpPFWub8OgNJvYODtFhplHJilpSXQHlCyxWKBUqmESqVCw1MXxtki9g8rODg8QqVyhEOC/QP6XkH/ax4Xe+1gTCYTotGoQKbzNpvNmJ+fJ1v4hJH3efS85PHQwEM8mcB9fRxdBJ1jMXTqYmiQsGBmZmaQy+VApiF0n46JdrtR7obatI2+VxmCNB5MJtE9voGusQTu6eLo0IZxuccChpysd3QkWq0WGo0GCoUCUqkU9X1ODJnzyJPDtV0qEBSx/b2Ir6Qu/CijazSC2rbZky9SXa8DWnMR2XIeErYOw+47GHG3k7oeub0tdI/yONf85mSBS48/YtFPp8CD+/YE63sTWP85QeoB8i2F/gke529PnSxwtmnxwxWJA03yENpUabQoNtAq/wyRbB0tch9qW6dw5roBfwDVdCmix4FHNgAAAABJRU5ErkJgggs=</value>
</data>
<data name="wrench" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAaQIAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAftJREFUOE+Vk81v0mAcx/lf/FuMGmOMJ08ePYvRg2RZllKgFAvEMrDYwg664BybMQw3KmpteTOpklVefINlyEDQ1dPioWbfPeUwNW50Hppe+vn8vr/v89QFwOX0pNNptyRJLVEUrWQyaf35vSOcSqXcBNzr9/swTROJRILwv4c6Cgjc6vV6GA6HKBQKiMVi/ycQBMGyp9frdfA8r9rTI5EIOI5DKBSyHBOQyL86nQ7K5TKi0eircDisZbNZtNttMAwzXRCPx8+SyPuNRgO1Wg3FYhGyLENVVZRKJfj9/taRCW6vfOGDmY91EtmqVqvQdR32u1KpQNM0KIoCn8+35/V63f8I2KVtXioMITwdgFt6D8MwkM/nwbLsvh2ZTLVomm5RFOW2+/hLwNjw+gDF+g/Ib01wqz3MiAaCweDPQCBw6qj7cijwZ7b5JIGfETCjjHD/+Vfkat9BPdjCFdZ4fdxlmwjoxS1eWBtAfmNi8eUIibUdpMgaq5Vv8Cx0cYluPjpWMEfg+dwAGzqBX4wwn9uBSJKslMa4le7iIvUuO+2quzwLHazru5PI/JM+7pHystoYN6UuLsxNhyclXrv7iey6C3GDNE/WWCbwDQKfm9187PSTTQRX73zQ7aKW1TEeKmNcT37GmZmTwYfHeJlpNklROD+7idOek8O24AByavlRgSfdiAAAAABJRU5ErkJgggs=</value>
</data>
<data name="disk" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAABQMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApdJREFUOE+NkltPE0EYhvuXgC6eEn+F14ZTgVIwgIhA0WjihRpBotHIQapAoIAoigXsAhoUoVCxYDDlUGiLUAr0DN3ttt3Xb6bKJeHiyaTbfZ/v3ZnR5BomqogWwk4ECSXXIKoEcssyXCifwKVrk7hYIeK8QQxdrhQXBP3oFQAaDQXal9xxLLklyEkVEhFPpBE+TmE/rCAQTfLfkpLGQSSJLb+sTjoOk1cf2A4FvaWQCZxLW3HcGfAjrlCYXix6NIdgLIl9CkTjKS6O0Oo9TGDdJ8PqCIIkoCYyE4QdJLht3uMvMZjAH1EQPEryyazBHrVx7clY35XQ0O3B15UQBP2YygSK3XVMAh9/iVHcZIOf1pichkytQkcpqs6mS1jdkVDX5Ub/tA9C6ShIIKq2jSPc6vPBQxUZ24EETU/x6TEpjZ2AchJ27sRx89Umeqb+QFvykQswu0qC3l1eXUfTS5ptKH+ygApC3zIPHT1n//2npmMNJqsH2uIREtAxzTijMPZs07cRtBp7vDB2Mzyo7/LQxC3UmjZR0+lCdcc6al5uoM3iglb3PiOYXolmwkQmSJCEheteu3nlG50koOD19jViFc+G15BT9C4jmFoOU9j7D8/JdB6mybUmFw9XU7Cq1YnK1t9oHlxBTuEQE1ghOkJo6PLy8z4LFc9/4WHfMrILBqGhq4nxxRCvK9GR3f9ScCrsTpQ9/Yl73YvIzh8gQbmIUXuQGmQE0xufT4UJSlt+4G6nnQRmaM4ZrOrIfIAE7jM30DXNo7Hdhqy8PlUjlFk3h74fYGhm/0zfz/aosW0O9S9mmSDANvGxoP9kEfTjQaF0jK6nhd8wbfEH5OiG6ajeIrvwDW3YAFXup5CZT87K641k5Zu//QWbzBTtXs2KnAAAAABJRU5ErkJgggs=</value>
</data>
<data name="help" mimetype="application/x-microsoft.net.object.binary.base64">
<value>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAHAMAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAEZ0FNQQAAr8g3BYrpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAq5JREFUOE+lk99PUmEcxv1b9E9oreZq1Wrd1da46KILp+ZPoKnlahksZ+kwp1lSamY6FdTUORUFTgIiiCaKgCBwMJFfyoGBcOCo2faELCGrdVEXn7v3+bx73vf7zQKQ9T/8FtaQhzlqxwFPZdsnFRsM/ckSp2VmmpwxRnlThr2cXy87JVDaGNasNeF3Bg6xucvA4aNTOHcSsHoTGFkM+ocWAqyfJWkBsR5nSU2x+Ba1j7UvYYjnPBCM2VA/soEuYhM6axB2P40PCk+8i9hOS1ICyVo0e3I14tsMMFiwhVCbDHUSTnhCDNyhBMYWvagRmyBf9cPijqJ1kvQ1j9uzj7MpwehSkL/uiWPFGQF/0IKHPWtIHBwl+faDI9QOGlHTb8C8hYJ6nUKd2MRPC/rm/KQ92bWb2EJ1jwFV3SvwBBOYWvZCad4Bk5QpzT6w2zVonbLC5ArjUbeeTAs6ZC7G4YuBLzKi8r0enE5d8rAW03o3wvQBdsMMemftKG1To/KdFlb3HjhCLZMWtIzbGbs3hscDRrA7tCh/q0HZGw1izFdsUzS4QjWKWhS4m4QrVMHiiSC/SZkRPBObSfN2BEKJHZx2HcqE8yh5PYfil8oUhS8IFDbKUNAoRb14GXonhdt10kyFZB++TO+F1kqhskOXDoai+6D2GOQJZlIUCiQgVt0QJevcqJnIPCJXuJBd/mret2SjIF/xgN2mQkGTHG3jhhTH4fyGCQyrHFAZvbhePea7en80843Hj5EnmGXdaSDiGssOlCYfnouWUNIsRVHjNJ72aiHXu6BY8+Byxcf4xXtDpwfpZDRv8SWsm08m/X3EBj47AjC6QikWbbvokpiRyxH7z5eL/jzKJ5JrD0ZzrlSN8C5VDJMXuIN0LltMnysbIM+W9vPOFPf9fZn+Za2/A9evBaJ0QokTAAAAAElFTkSuQmCCCw==</value>
</data>
</root>

View File

@ -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;
}
}

14
README.md Normal file
View File

@ -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).

View File

@ -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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(ref part, 768);
return part[388] == (byte) 67 && part[389] == (byte) 80 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C"));
}
public event EventHandler<MessageEventArgs> Debug;
private void fireDebug(string debugMessage, params object[] args)
{
EventHandler<MessageEventArgs> debug = this.Debug;
if (debug == null)
return;
debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
}
}
}

27
libWiiSharp/CommonKey.cs Normal file
View File

@ -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);
}
}

View File

@ -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,
}
}

View File

@ -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();
}
}
}

View File

@ -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
}
}

589
libWiiSharp/Headers.cs Normal file
View File

@ -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);
}
}
}
}

244
libWiiSharp/IosPatcher.cs Normal file
View File

@ -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<ProgressChangedEventArgs> Progress;
public event EventHandler<MessageEventArgs> Debug;
private void fireDebug(string debugMessage, params object[] args)
{
EventHandler<MessageEventArgs> debug = this.Debug;
if (debug == null)
return;
debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
}
private void fireProgress(int progressPercentage)
{
EventHandler<ProgressChangedEventArgs> progress = this.Progress;
if (progress == null)
return;
progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty));
}
}
}

View File

@ -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
}
}

Some files were not shown because too many files have changed in this diff Show More