Decompiled v1.9 Mod with dotPeek
14
AssemblyInfo.cs
Normal 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")]
|
@ -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>.
|
@ -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
@ -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
@ -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
|
||||||
|
@ -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>
|
|
@ -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 { }
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 100 KiB |
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
1199
NUS Downloader/Form1.Designer.cs
generated
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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")]
|
|
329
NUS Downloader/Properties/Resources.Designer.cs
generated
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
26
NUS Downloader/Properties/Settings.Designer.cs
generated
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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>
|
|
Before Width: | Height: | Size: 379 B |
Before Width: | Height: | Size: 847 B |
Before Width: | Height: | Size: 372 B |
Before Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 555 B |
Before Width: | Height: | Size: 806 B |
Before Width: | Height: | Size: 841 B |
Before Width: | Height: | Size: 295 B |
Before Width: | Height: | Size: 283 B |
Before Width: | Height: | Size: 287 B |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 748 B |
Before Width: | Height: | Size: 755 B |
Before Width: | Height: | Size: 620 B |
Before Width: | Height: | Size: 695 B |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 633 B |
Before Width: | Height: | Size: 675 B |
Before Width: | Height: | Size: 786 B |
Before Width: | Height: | Size: 786 B |
Before Width: | Height: | Size: 778 B |
Before Width: | Height: | Size: 612 B |
Before Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 743 B |
Before Width: | Height: | Size: 853 B |
Before Width: | Height: | Size: 899 B |
Before Width: | Height: | Size: 891 B |
Before Width: | Height: | Size: 896 B |
Before Width: | Height: | Size: 554 B |
Before Width: | Height: | Size: 450 B |
Before Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 859 B |
Before Width: | Height: | Size: 868 B |
Before Width: | Height: | Size: 839 B |
Before Width: | Height: | Size: 887 B |
Before Width: | Height: | Size: 755 B |
Before Width: | Height: | Size: 706 B |
Before Width: | Height: | Size: 860 B |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 617 B |
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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; } }
|
|
||||||
}
|
|
||||||
}
|
|
@ -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!
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
1120
NUS Downloader/U8.cs
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<configuration>
|
|
||||||
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>
|
|
600
NUS_Downloader/Database.cs
Normal 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
135
NUS_Downloader/Form1.resx
Normal file
49
NUS_Downloader/Program.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
123
NUS_Downloader/Properties/Resources.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
234
NUS_Downloader/Properties/Resources.resx
Normal 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>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</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>AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAMgwAAAKJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/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/y6xOjTAAAACXBIWXMAAAsSAAALEgHS3X78AAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJTUUH2wYaDRItMTq74gAAAT5JREFUOE+tk8lKw1AUhg+KO6ELF0roY4gPkfcQXaXiDNFyUduoVIxVcFPEYSWI4MKikEKr3DpURYWLE1TitHIo1GBrkN90ZzYlNV2c5fed8597DwEgP+ULrjSusyAelBAPMsy2Ccy0CGjNDGONUrWI7gkqcDYGmCkgnwTSYXypxLwL9FYB0wByUQceAE4W8NpLwrtgKiBwvQFkhgBDAfgk7rtrEUw0MaRUp/M8kNWA7RA6lM0QrdmCli1OiTf5kdyLd+2grJL00U/sRSFx20mi3YHZ5Q92H2xs5b8xelQA6Vfy30hVn5FWy3zHtBE+KEHZszB3YYGmj7l3wVKBr9+V0OPAXelPRE+LoHGjBsHiszxy+A793EIkV8Rw5gk0uOI9wg01EMXOZNL2BbEkp76EHKGAK3adv/I/LtP3BL8PE+DmhtdNCgAAAABJRU5ErkJgggs=</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>
|
21
NUS_Downloader/Properties/Settings.cs
Normal 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
@ -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).
|
433
libWiiSharp/CertificateChain.cs
Normal 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
@ -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);
|
||||||
|
}
|
||||||
|
}
|
14
libWiiSharp/CommonKeyType.cs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
33
libWiiSharp/ContentIndices.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
libWiiSharp/ContentType.cs
Normal 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
@ -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
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
libWiiSharp/LowerTitleID.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|