├── NUS Downloader.pdb
├── libWiiSharp
├── CommonKeyType.cs
├── Region.cs
├── U8_NodeType.cs
├── StoreType.cs
├── ContentType.cs
├── MessageEventArgs.cs
├── LowerTitleID.cs
├── ContentIndices.cs
├── TMD_Content.cs
├── U8_Node.cs
├── U8_Header.cs
├── CommonKey.cs
├── WAD_Header.cs
├── Shared.cs
├── IosPatcher.cs
├── Lz77.cs
├── CertificateChain.cs
├── NusClient.cs
├── Ticket.cs
├── TMD.cs
└── Headers.cs
├── wyDay
└── Controls
│ ├── ProgressBarState.cs
│ ├── ThumbnailProgressState.cs
│ ├── CTaskbarList.cs
│ ├── ITaskbarList3.cs
│ ├── Windows7Taskbar.cs
│ └── Windows7ProgressBar.cs
├── AssemblyInfo.cs
├── README.md
├── NUS_Downloader
├── Properties
│ ├── Settings.cs
│ └── Resources.cs
├── Program.cs
└── Database.cs
├── NUS Downloader.sln
├── wmgCMS
└── WaterMarkTextBox.cs
└── NUS Downloader.csproj
/NUS Downloader.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WiiDatabase/nusdownloader/HEAD/NUS Downloader.pdb
--------------------------------------------------------------------------------
/libWiiSharp/CommonKeyType.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.CommonKeyType
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace libWiiSharp
8 | {
9 | public enum CommonKeyType : byte
10 | {
11 | Standard,
12 | Korean,
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/libWiiSharp/Region.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.Region
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace libWiiSharp
8 | {
9 | public enum Region : ushort
10 | {
11 | Japan,
12 | USA,
13 | Europe,
14 | Free,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/libWiiSharp/U8_NodeType.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.U8_NodeType
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace libWiiSharp
8 | {
9 | public enum U8_NodeType : ushort
10 | {
11 | File = 0,
12 | Directory = 256, // 0x0100
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/wyDay/Controls/ProgressBarState.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: wyDay.Controls.ProgressBarState
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace wyDay.Controls
8 | {
9 | public enum ProgressBarState
10 | {
11 | Normal = 1,
12 | Error = 2,
13 | Pause = 3,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/libWiiSharp/StoreType.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.StoreType
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace libWiiSharp
8 | {
9 | public enum StoreType
10 | {
11 | EncryptedContent,
12 | DecryptedContent,
13 | WAD,
14 | All,
15 | Empty,
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/libWiiSharp/ContentType.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.ContentType
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace libWiiSharp
8 | {
9 | public enum ContentType : ushort
10 | {
11 | Normal = 1,
12 | DLC = 16385, // 0x4001
13 | Shared = 32769, // 0x8001
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/wyDay/Controls/ThumbnailProgressState.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: wyDay.Controls.ThumbnailProgressState
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace wyDay.Controls
8 | {
9 | public enum ThumbnailProgressState
10 | {
11 | NoProgress = 0,
12 | Indeterminate = 1,
13 | Normal = 2,
14 | Error = 4,
15 | Paused = 8,
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | [assembly: AssemblyTitle("NUS Downloader")]
5 | [assembly: AssemblyFileVersion("1.0.0.0")]
6 | [assembly: AssemblyDescription("")]
7 | [assembly: AssemblyConfiguration("")]
8 | [assembly: AssemblyCompany("")]
9 | [assembly: AssemblyProduct("NUS Downloader")]
10 | [assembly: AssemblyCopyright("Copyright © 2009")]
11 | [assembly: AssemblyTrademark("")]
12 | [assembly: ComVisible(false)]
13 | [assembly: Guid("cb4ee0f5-7ba8-4ee6-a09e-7a09d4350582")]
14 | [assembly: AssemblyVersion("1.0.0.0")]
15 |
--------------------------------------------------------------------------------
/libWiiSharp/MessageEventArgs.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.MessageEventArgs
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 |
9 | namespace libWiiSharp
10 | {
11 | public class MessageEventArgs : EventArgs
12 | {
13 | private string message;
14 |
15 | public string Message => this.message;
16 |
17 | public MessageEventArgs(string message) => this.message = message;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/libWiiSharp/LowerTitleID.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.LowerTitleID
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace libWiiSharp
8 | {
9 | public enum LowerTitleID : uint
10 | {
11 | SystemTitles = 1,
12 | Channel = 65537, // 0x00010001
13 | SystemChannels = 65538, // 0x00010002
14 | GameChannel = 65540, // 0x00010004
15 | DLC = 65541, // 0x00010005
16 | HiddenChannels = 65544, // 0x00010008
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/wyDay/Controls/CTaskbarList.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: wyDay.Controls.CTaskbarList
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System.Runtime.CompilerServices;
8 | using System.Runtime.InteropServices;
9 |
10 | namespace wyDay.Controls
11 | {
12 | [ClassInterface(ClassInterfaceType.None)]
13 | [Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
14 | [ComImport]
15 | internal class CTaskbarList
16 | {
17 | [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
18 | public extern CTaskbarList();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NUS Downloader
2 |
3 | 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/).
4 |
5 | NUS Downloader is licensed under the GNU GPL v3.
6 |
7 | ## Changelog
8 | ### v1.9 Mod NUS-Fix (by WiiDatabase.de)
9 | * Switch to Wii U CDN for Wii titles since NUS is down
10 | * Modified from the decompiled EXE
11 |
12 | ### v1.9 Mod (by hamachi-mp)
13 | * Based on NUS r122
14 | * Checkbox to use the folder structure of NUSD v1.5
15 | * Fixed script creation on "Emulate Update"
16 |
17 | ### Older versions
18 | See [WiiBrew](https://wiibrew.org/wiki/NUS_Downloader#Update_History).
19 |
--------------------------------------------------------------------------------
/NUS_Downloader/Properties/Settings.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: NUS_Downloader.Properties.Settings
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System.CodeDom.Compiler;
8 | using System.Configuration;
9 | using System.Runtime.CompilerServices;
10 |
11 | namespace NUS_Downloader.Properties
12 | {
13 | [CompilerGenerated]
14 | [GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
15 | internal sealed class Settings : ApplicationSettingsBase
16 | {
17 | private static Settings defaultInstance = (Settings) SettingsBase.Synchronized((SettingsBase) new Settings());
18 |
19 | public static Settings Default => Settings.defaultInstance;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/NUS Downloader.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 10.00
3 | # Visual Studio 2008
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUS Downloader", "NUS Downloader.csproj", "{9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/libWiiSharp/ContentIndices.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.ContentIndices
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 |
9 | namespace libWiiSharp
10 | {
11 | internal struct ContentIndices : IComparable
12 | {
13 | private int index;
14 | private int contentIndex;
15 |
16 | public int Index => this.index;
17 |
18 | public int ContentIndex => this.contentIndex;
19 |
20 | public ContentIndices(int index, int contentIndex)
21 | {
22 | this.index = index;
23 | this.contentIndex = contentIndex;
24 | }
25 |
26 | public int CompareTo(object obj)
27 | {
28 | if (obj is ContentIndices contentIndices)
29 | return this.contentIndex.CompareTo(contentIndices.contentIndex);
30 | throw new ArgumentException();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/libWiiSharp/TMD_Content.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.TMD_Content
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | namespace libWiiSharp
8 | {
9 | public class TMD_Content
10 | {
11 | private uint contentId;
12 | private ushort index;
13 | private ushort type;
14 | private ulong size;
15 | private byte[] hash = new byte[20];
16 |
17 | public uint ContentID
18 | {
19 | get => this.contentId;
20 | set => this.contentId = value;
21 | }
22 |
23 | public ushort Index
24 | {
25 | get => this.index;
26 | set => this.index = value;
27 | }
28 |
29 | public ContentType Type
30 | {
31 | get => (ContentType) this.type;
32 | set => this.type = (ushort) value;
33 | }
34 |
35 | public ulong Size
36 | {
37 | get => this.size;
38 | set => this.size = value;
39 | }
40 |
41 | public byte[] Hash
42 | {
43 | get => this.hash;
44 | set => this.hash = value;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/wyDay/Controls/ITaskbarList3.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: wyDay.Controls.ITaskbarList3
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.Runtime.CompilerServices;
9 | using System.Runtime.InteropServices;
10 |
11 | namespace wyDay.Controls
12 | {
13 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
14 | [Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
15 | [ComImport]
16 | internal interface ITaskbarList3
17 | {
18 | [MethodImpl(MethodImplOptions.PreserveSig)]
19 | void HrInit();
20 |
21 | [MethodImpl(MethodImplOptions.PreserveSig)]
22 | void AddTab(IntPtr hwnd);
23 |
24 | [MethodImpl(MethodImplOptions.PreserveSig)]
25 | void DeleteTab(IntPtr hwnd);
26 |
27 | [MethodImpl(MethodImplOptions.PreserveSig)]
28 | void ActivateTab(IntPtr hwnd);
29 |
30 | [MethodImpl(MethodImplOptions.PreserveSig)]
31 | void SetActiveAlt(IntPtr hwnd);
32 |
33 | [MethodImpl(MethodImplOptions.PreserveSig)]
34 | void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
35 |
36 | void SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal);
37 |
38 | void SetProgressState(IntPtr hwnd, ThumbnailProgressState tbpFlags);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/libWiiSharp/U8_Node.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.U8_Node
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.IO;
9 |
10 | namespace libWiiSharp
11 | {
12 | public class U8_Node
13 | {
14 | private ushort type;
15 | private ushort offsetToName;
16 | private uint offsetToData;
17 | private uint sizeOfData;
18 |
19 | public U8_NodeType Type
20 | {
21 | get => (U8_NodeType) this.type;
22 | set => this.type = (ushort) value;
23 | }
24 |
25 | public ushort OffsetToName
26 | {
27 | get => this.offsetToName;
28 | set => this.offsetToName = value;
29 | }
30 |
31 | public uint OffsetToData
32 | {
33 | get => this.offsetToData;
34 | set => this.offsetToData = value;
35 | }
36 |
37 | public uint SizeOfData
38 | {
39 | get => this.sizeOfData;
40 | set => this.sizeOfData = value;
41 | }
42 |
43 | public void Write(Stream writeStream)
44 | {
45 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.type)), 0, 2);
46 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToName)), 0, 2);
47 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToData)), 0, 4);
48 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.sizeOfData)), 0, 4);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/libWiiSharp/U8_Header.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.U8_Header
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.IO;
9 |
10 | namespace libWiiSharp
11 | {
12 | public class U8_Header
13 | {
14 | private uint u8Magic = 1437218861;
15 | private uint offsetToRootNode = 32;
16 | private uint headerSize;
17 | private uint offsetToData;
18 | private byte[] padding = new byte[16];
19 |
20 | public uint U8Magic => this.u8Magic;
21 |
22 | public uint OffsetToRootNode => this.offsetToRootNode;
23 |
24 | public uint HeaderSize
25 | {
26 | get => this.headerSize;
27 | set => this.headerSize = value;
28 | }
29 |
30 | public uint OffsetToData
31 | {
32 | get => this.offsetToData;
33 | set => this.offsetToData = value;
34 | }
35 |
36 | public byte[] Padding => this.padding;
37 |
38 | public void Write(Stream writeStream)
39 | {
40 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.u8Magic)), 0, 4);
41 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToRootNode)), 0, 4);
42 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.headerSize)), 0, 4);
43 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToData)), 0, 4);
44 | writeStream.Write(this.padding, 0, 16);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/NUS_Downloader/Program.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: NUS_Downloader.Program
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.Runtime.InteropServices;
9 | using System.Windows.Forms;
10 |
11 | namespace NUS_Downloader
12 | {
13 | internal static class Program
14 | {
15 | [DllImport("user32.dll")]
16 | public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
17 |
18 | [DllImport("user32.dll")]
19 | private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
20 |
21 | [STAThread]
22 | private static void Main(string[] args)
23 | {
24 | if (args.Length != 0)
25 | {
26 | Application.EnableVisualStyles();
27 | Application.SetCompatibleTextRenderingDefault(false);
28 | Application.Run((Form) new Form1(args));
29 | }
30 | else
31 | {
32 | Application.EnableVisualStyles();
33 | Application.SetCompatibleTextRenderingDefault(false);
34 | Application.Run((Form) new Form1());
35 | }
36 | }
37 |
38 | public static void setConsoleWindowVisibility(bool visible, string title)
39 | {
40 | IntPtr window = Program.FindWindow((string) null, title);
41 | if (!(window != IntPtr.Zero))
42 | return;
43 | if (!visible)
44 | Program.ShowWindow(window, 0);
45 | else
46 | Program.ShowWindow(window, 1);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/libWiiSharp/CommonKey.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.CommonKey
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System.IO;
8 |
9 | namespace libWiiSharp
10 | {
11 | public class CommonKey
12 | {
13 | private static string standardKey = "ebe42a225e8593e448d9c5457381aaf7";
14 | private static string koreanKey = "63b82bb4f4614e2e13f2fefbba4c9b7e";
15 | private static string dsiKey = "af1bf516a807d21aea45984f04742861";
16 | private static string currentDir = Directory.GetCurrentDirectory();
17 | private static string standardKeyName = "key.bin";
18 | private static string koreanKeyName = "kkey.bin";
19 | private static string dsiKeyName = "dsikey.bin";
20 |
21 | public static byte[] GetStandardKey() => File.Exists(Path.Combine(CommonKey.currentDir, CommonKey.standardKeyName)) ? File.ReadAllBytes(Path.Combine(CommonKey.currentDir, CommonKey.standardKeyName)) : Shared.HexStringToByteArray(CommonKey.standardKey);
22 |
23 | public static byte[] GetKoreanKey() => File.Exists(Path.Combine(CommonKey.currentDir, CommonKey.koreanKeyName)) ? File.ReadAllBytes(Path.Combine(CommonKey.currentDir, CommonKey.koreanKeyName)) : Shared.HexStringToByteArray(CommonKey.koreanKey);
24 |
25 | public static byte[] GetDSiKey() => File.Exists(Path.Combine(CommonKey.currentDir, CommonKey.dsiKeyName)) ? File.ReadAllBytes(Path.Combine(CommonKey.currentDir, CommonKey.dsiKeyName)) : Shared.HexStringToByteArray(CommonKey.dsiKey);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/wyDay/Controls/Windows7Taskbar.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: wyDay.Controls.Windows7Taskbar
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.Runtime.InteropServices;
9 |
10 | namespace wyDay.Controls
11 | {
12 | public static class Windows7Taskbar
13 | {
14 | private static ITaskbarList3 _taskbarList;
15 | private static readonly OperatingSystem osInfo = Environment.OSVersion;
16 |
17 | internal static ITaskbarList3 TaskbarList
18 | {
19 | get
20 | {
21 | if (Windows7Taskbar._taskbarList == null)
22 | {
23 | lock (typeof (Windows7Taskbar))
24 | {
25 | if (Windows7Taskbar._taskbarList == null)
26 | {
27 | Windows7Taskbar._taskbarList = (ITaskbarList3) new CTaskbarList();
28 | Windows7Taskbar._taskbarList.HrInit();
29 | }
30 | }
31 | }
32 | return Windows7Taskbar._taskbarList;
33 | }
34 | }
35 |
36 | internal static bool Windows7OrGreater => Windows7Taskbar.osInfo.Version.Major == 6 && Windows7Taskbar.osInfo.Version.Minor >= 1 || Windows7Taskbar.osInfo.Version.Major > 6;
37 |
38 | public static void SetProgressState(IntPtr hwnd, ThumbnailProgressState state)
39 | {
40 | if (!Windows7Taskbar.Windows7OrGreater)
41 | return;
42 | Windows7Taskbar.TaskbarList.SetProgressState(hwnd, state);
43 | }
44 |
45 | public static void SetProgressValue(IntPtr hwnd, ulong current, ulong maximum)
46 | {
47 | if (!Windows7Taskbar.Windows7OrGreater)
48 | return;
49 | Windows7Taskbar.TaskbarList.SetProgressValue(hwnd, current, maximum);
50 | }
51 |
52 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
53 | internal static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/libWiiSharp/WAD_Header.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.WAD_Header
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.IO;
9 |
10 | namespace libWiiSharp
11 | {
12 | public class WAD_Header
13 | {
14 | private uint headerSize = 32;
15 | private uint wadType = 1232273408;
16 | private uint certSize = 2560;
17 | private uint reserved;
18 | private uint tikSize = 676;
19 | private uint tmdSize;
20 | private uint contentSize;
21 | private uint footerSize;
22 |
23 | public uint HeaderSize => this.headerSize;
24 |
25 | public uint WadType
26 | {
27 | get => this.wadType;
28 | set => this.wadType = value;
29 | }
30 |
31 | public uint CertSize => this.certSize;
32 |
33 | public uint Reserved => this.reserved;
34 |
35 | public uint TicketSize => this.tikSize;
36 |
37 | public uint TmdSize
38 | {
39 | get => this.tmdSize;
40 | set => this.tmdSize = value;
41 | }
42 |
43 | public uint ContentSize
44 | {
45 | get => this.contentSize;
46 | set => this.contentSize = value;
47 | }
48 |
49 | public uint FooterSize
50 | {
51 | get => this.footerSize;
52 | set => this.footerSize = value;
53 | }
54 |
55 | public void Write(Stream writeStream)
56 | {
57 | writeStream.Seek(0L, SeekOrigin.Begin);
58 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.headerSize)), 0, 4);
59 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.wadType)), 0, 4);
60 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.certSize)), 0, 4);
61 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.reserved)), 0, 4);
62 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.tikSize)), 0, 4);
63 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.tmdSize)), 0, 4);
64 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.contentSize)), 0, 4);
65 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.footerSize)), 0, 4);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/wmgCMS/WaterMarkTextBox.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: wmgCMS.WaterMarkTextBox
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.Drawing;
9 | using System.Windows.Forms;
10 |
11 | namespace wmgCMS
12 | {
13 | internal class WaterMarkTextBox : TextBox
14 | {
15 | private Font oldFont;
16 | private bool waterMarkTextEnabled;
17 | private Color _waterMarkColor = Color.Gray;
18 | private string _waterMarkText = "Water Mark";
19 |
20 | public Color WaterMarkColor
21 | {
22 | get => this._waterMarkColor;
23 | set
24 | {
25 | this._waterMarkColor = value;
26 | this.Invalidate();
27 | }
28 | }
29 |
30 | public string WaterMarkText
31 | {
32 | get => this._waterMarkText;
33 | set
34 | {
35 | this._waterMarkText = value;
36 | this.Invalidate();
37 | }
38 | }
39 |
40 | public WaterMarkTextBox() => this.JoinEvents(true);
41 |
42 | protected override void OnCreateControl()
43 | {
44 | base.OnCreateControl();
45 | this.EnableWaterMark();
46 | }
47 |
48 | protected override void OnPaint(PaintEventArgs args)
49 | {
50 | Font font = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style, this.Font.Unit);
51 | SolidBrush solidBrush = new SolidBrush(this.WaterMarkColor);
52 | PointF point = new PointF((float) ((double) args.ClipRectangle.Width / 2.0 - (double) TextRenderer.MeasureText(this.WaterMarkText, this.Font).Width / 2.0), 0.0f);
53 | args.Graphics.DrawString(this.waterMarkTextEnabled ? this.WaterMarkText : this.Text, font, (Brush) solidBrush, point);
54 | base.OnPaint(args);
55 | }
56 |
57 | private void JoinEvents(bool join)
58 | {
59 | if (!join)
60 | return;
61 | this.TextChanged += new EventHandler(this.WaterMark_Toggel);
62 | this.LostFocus += new EventHandler(this.WaterMark_Toggel);
63 | this.GotFocus += new EventHandler(this.WaterMark_Toggel);
64 | this.MouseCaptureChanged += new EventHandler(this.WaterMark_Toggel);
65 | this.FontChanged += new EventHandler(this.WaterMark_FontChanged);
66 | }
67 |
68 | private void WaterMark_Toggel(object sender, EventArgs args) => this.DisbaleWaterMark();
69 |
70 | private void EnableWaterMark()
71 | {
72 | this.oldFont = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style, this.Font.Unit);
73 | this.SetStyle(ControlStyles.UserPaint, true);
74 | this.waterMarkTextEnabled = true;
75 | this.Refresh();
76 | }
77 |
78 | private void DisbaleWaterMark()
79 | {
80 | this.waterMarkTextEnabled = false;
81 | this.SetStyle(ControlStyles.UserPaint, false);
82 | if (this.oldFont == null)
83 | return;
84 | this.Font = new Font(this.oldFont.FontFamily, this.oldFont.Size, this.oldFont.Style, this.oldFont.Unit);
85 | }
86 |
87 | private void WaterMark_FontChanged(object sender, EventArgs args)
88 | {
89 | if (!this.waterMarkTextEnabled)
90 | return;
91 | this.oldFont = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style, this.Font.Unit);
92 | this.Refresh();
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/NUS Downloader.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {9DFC0D36-D4CB-4FE3-A1A2-C21B1665D4E1}
8 | WinExe
9 | NUS Downloader
10 | v3.5
11 | 1.0.0.0
12 | 512
13 |
14 |
15 | AnyCPU
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | AnyCPU
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/wyDay/Controls/Windows7ProgressBar.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: wyDay.Controls.Windows7ProgressBar
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using System.ComponentModel.Design;
10 | using System.Drawing;
11 | using System.Windows.Forms;
12 |
13 | namespace wyDay.Controls
14 | {
15 | [ToolboxBitmap(typeof (ProgressBar))]
16 | public class Windows7ProgressBar : ProgressBar
17 | {
18 | private bool showInTaskbar;
19 | private ProgressBarState m_State = ProgressBarState.Normal;
20 | private ContainerControl ownerForm;
21 |
22 | public Windows7ProgressBar()
23 | {
24 | }
25 |
26 | public Windows7ProgressBar(ContainerControl parentControl) => this.ContainerControl = parentControl;
27 |
28 | public ContainerControl ContainerControl
29 | {
30 | get => this.ownerForm;
31 | set
32 | {
33 | this.ownerForm = value;
34 | if (this.ownerForm.Visible)
35 | return;
36 | ((Form) this.ownerForm).Shown += new EventHandler(this.Windows7ProgressBar_Shown);
37 | }
38 | }
39 |
40 | public override ISite Site
41 | {
42 | set
43 | {
44 | base.Site = value;
45 | if (value == null || !(value.GetService(typeof (IDesignerHost)) is IDesignerHost service))
46 | return;
47 | this.ContainerControl = service.RootComponent as ContainerControl;
48 | }
49 | }
50 |
51 | private void Windows7ProgressBar_Shown(object sender, EventArgs e)
52 | {
53 | if (this.ShowInTaskbar)
54 | {
55 | if (this.Style != ProgressBarStyle.Marquee)
56 | this.SetValueInTB();
57 | this.SetStateInTB();
58 | }
59 | ((Form) this.ownerForm).Shown -= new EventHandler(this.Windows7ProgressBar_Shown);
60 | }
61 |
62 | [DefaultValue(false)]
63 | public bool ShowInTaskbar
64 | {
65 | get => this.showInTaskbar;
66 | set
67 | {
68 | if (this.showInTaskbar == value)
69 | return;
70 | this.showInTaskbar = value;
71 | if (this.ownerForm == null)
72 | return;
73 | if (this.Style != ProgressBarStyle.Marquee)
74 | this.SetValueInTB();
75 | this.SetStateInTB();
76 | }
77 | }
78 |
79 | public new int Value
80 | {
81 | get => base.Value;
82 | set
83 | {
84 | base.Value = value;
85 | this.SetValueInTB();
86 | }
87 | }
88 |
89 | public new ProgressBarStyle Style
90 | {
91 | get => base.Style;
92 | set
93 | {
94 | base.Style = value;
95 | if (!this.showInTaskbar || this.ownerForm == null)
96 | return;
97 | this.SetStateInTB();
98 | }
99 | }
100 |
101 | [DefaultValue(ProgressBarState.Normal)]
102 | public ProgressBarState State
103 | {
104 | get => this.m_State;
105 | set
106 | {
107 | this.m_State = value;
108 | bool flag = this.Style == ProgressBarStyle.Marquee;
109 | if (flag)
110 | this.Style = ProgressBarStyle.Blocks;
111 | Windows7Taskbar.SendMessage(this.Handle, 1040, (int) value, 0);
112 | if (flag)
113 | this.SetValueInTB();
114 | else
115 | this.SetStateInTB();
116 | }
117 | }
118 |
119 | public new void Increment(int value)
120 | {
121 | base.Increment(value);
122 | this.SetValueInTB();
123 | }
124 |
125 | public new void PerformStep()
126 | {
127 | base.PerformStep();
128 | this.SetValueInTB();
129 | }
130 |
131 | private void SetValueInTB()
132 | {
133 | if (!this.showInTaskbar)
134 | return;
135 | Windows7Taskbar.SetProgressValue(this.ownerForm.Handle, (ulong) (this.Value - this.Minimum), (ulong) (this.Maximum - this.Minimum));
136 | }
137 |
138 | private void SetStateInTB()
139 | {
140 | if (this.ownerForm == null)
141 | return;
142 | ThumbnailProgressState state = ThumbnailProgressState.Normal;
143 | if (!this.showInTaskbar)
144 | state = ThumbnailProgressState.NoProgress;
145 | else if (this.Style == ProgressBarStyle.Marquee)
146 | state = ThumbnailProgressState.Indeterminate;
147 | else if (this.m_State == ProgressBarState.Error)
148 | state = ThumbnailProgressState.Error;
149 | else if (this.m_State == ProgressBarState.Pause)
150 | state = ThumbnailProgressState.Paused;
151 | Windows7Taskbar.SetProgressState(this.ownerForm.Handle, state);
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/libWiiSharp/Shared.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.Shared
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Globalization;
10 | using System.Net;
11 |
12 | namespace libWiiSharp
13 | {
14 | public static class Shared
15 | {
16 | public static string[] MergeStringArrays(string[] a, string[] b)
17 | {
18 | List stringList = new List((IEnumerable) a);
19 | foreach (string str in b)
20 | {
21 | if (!stringList.Contains(str))
22 | stringList.Add(str);
23 | }
24 | stringList.Sort();
25 | return stringList.ToArray();
26 | }
27 |
28 | public static bool CompareByteArrays(
29 | byte[] first,
30 | int firstIndex,
31 | byte[] second,
32 | int secondIndex,
33 | int length)
34 | {
35 | if (first.Length < length || second.Length < length)
36 | return false;
37 | for (int index = 0; index < length; ++index)
38 | {
39 | if ((int) first[firstIndex + index] != (int) second[secondIndex + index])
40 | return false;
41 | }
42 | return true;
43 | }
44 |
45 | public static bool CompareByteArrays(byte[] first, byte[] second)
46 | {
47 | if (first.Length != second.Length)
48 | return false;
49 | for (int index = 0; index < first.Length; ++index)
50 | {
51 | if ((int) first[index] != (int) second[index])
52 | return false;
53 | }
54 | return true;
55 | }
56 |
57 | public static string ByteArrayToString(byte[] byteArray, char separator = ' ')
58 | {
59 | string str = string.Empty;
60 | foreach (byte num in byteArray)
61 | str = str + num.ToString("x2").ToUpper() + (object) separator;
62 | return str.Remove(str.Length - 1);
63 | }
64 |
65 | public static byte[] HexStringToByteArray(string hexString)
66 | {
67 | byte[] byteArray = new byte[hexString.Length / 2];
68 | for (int index = 0; index < hexString.Length / 2; ++index)
69 | byteArray[index] = byte.Parse(hexString.Substring(index * 2, 2), NumberStyles.HexNumber);
70 | return byteArray;
71 | }
72 |
73 | public static int CountCharsInString(string theString, char theChar)
74 | {
75 | int num1 = 0;
76 | foreach (int num2 in theString)
77 | {
78 | if (num2 == (int) theChar)
79 | ++num1;
80 | }
81 | return num1;
82 | }
83 |
84 | public static long AddPadding(long value) => Shared.AddPadding(value, 64);
85 |
86 | public static long AddPadding(long value, int padding)
87 | {
88 | if (value % (long) padding != 0L)
89 | value += (long) padding - value % (long) padding;
90 | return value;
91 | }
92 |
93 | public static int AddPadding(int value) => Shared.AddPadding(value, 64);
94 |
95 | public static int AddPadding(int value, int padding)
96 | {
97 | if (value % padding != 0)
98 | value += padding - value % padding;
99 | return value;
100 | }
101 |
102 | public static ushort Swap(ushort value) => (ushort) IPAddress.HostToNetworkOrder((short) value);
103 |
104 | public static uint Swap(uint value) => (uint) IPAddress.HostToNetworkOrder((int) value);
105 |
106 | public static ulong Swap(ulong value) => (ulong) IPAddress.HostToNetworkOrder((long) value);
107 |
108 | public static byte[] UShortArrayToByteArray(ushort[] array)
109 | {
110 | List byteList = new List();
111 | foreach (ushort num in array)
112 | {
113 | byte[] bytes = BitConverter.GetBytes(num);
114 | byteList.AddRange((IEnumerable) bytes);
115 | }
116 | return byteList.ToArray();
117 | }
118 |
119 | public static byte[] UIntArrayToByteArray(uint[] array)
120 | {
121 | List byteList = new List();
122 | foreach (uint num in array)
123 | {
124 | byte[] bytes = BitConverter.GetBytes(num);
125 | byteList.AddRange((IEnumerable) bytes);
126 | }
127 | return byteList.ToArray();
128 | }
129 |
130 | public static uint[] ByteArrayToUIntArray(byte[] array)
131 | {
132 | uint[] uintArray = new uint[array.Length / 4];
133 | int num = 0;
134 | for (int startIndex = 0; startIndex < array.Length; startIndex += 4)
135 | uintArray[num++] = BitConverter.ToUInt32(array, startIndex);
136 | return uintArray;
137 | }
138 |
139 | public static ushort[] ByteArrayToUShortArray(byte[] array)
140 | {
141 | ushort[] ushortArray = new ushort[array.Length / 2];
142 | int num = 0;
143 | for (int startIndex = 0; startIndex < array.Length; startIndex += 2)
144 | ushortArray[num++] = BitConverter.ToUInt16(array, startIndex);
145 | return ushortArray;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/NUS_Downloader/Properties/Resources.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: NUS_Downloader.Properties.Resources
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System.CodeDom.Compiler;
8 | using System.ComponentModel;
9 | using System.Diagnostics;
10 | using System.Drawing;
11 | using System.Globalization;
12 | using System.Resources;
13 | using System.Runtime.CompilerServices;
14 |
15 | namespace NUS_Downloader.Properties
16 | {
17 | [CompilerGenerated]
18 | [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
19 | [DebuggerNonUserCode]
20 | internal class Resources
21 | {
22 | private static ResourceManager resourceMan;
23 | private static CultureInfo resourceCulture;
24 |
25 | internal Resources()
26 | {
27 | }
28 |
29 | [EditorBrowsable(EditorBrowsableState.Advanced)]
30 | internal static ResourceManager ResourceManager
31 | {
32 | get
33 | {
34 | if (object.ReferenceEquals((object) NUS_Downloader.Properties.Resources.resourceMan, (object) null))
35 | NUS_Downloader.Properties.Resources.resourceMan = new ResourceManager("NUS_Downloader.Properties.Resources", typeof (NUS_Downloader.Properties.Resources).Assembly);
36 | return NUS_Downloader.Properties.Resources.resourceMan;
37 | }
38 | }
39 |
40 | [EditorBrowsable(EditorBrowsableState.Advanced)]
41 | internal static CultureInfo Culture
42 | {
43 | get => NUS_Downloader.Properties.Resources.resourceCulture;
44 | set => NUS_Downloader.Properties.Resources.resourceCulture = value;
45 | }
46 |
47 | internal static Bitmap arrow_ticker => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (arrow_ticker), NUS_Downloader.Properties.Resources.resourceCulture);
48 |
49 | internal static Bitmap bin_closed => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bin_closed), NUS_Downloader.Properties.Resources.resourceCulture);
50 |
51 | internal static Bitmap box => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (box), NUS_Downloader.Properties.Resources.resourceCulture);
52 |
53 | internal static Bitmap bug_add => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bug_add), NUS_Downloader.Properties.Resources.resourceCulture);
54 |
55 | internal static Bitmap bullet_green => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_green), NUS_Downloader.Properties.Resources.resourceCulture);
56 |
57 | internal static Bitmap bullet_green_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_green_blue), NUS_Downloader.Properties.Resources.resourceCulture);
58 |
59 | internal static Bitmap bullet_orange => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_orange), NUS_Downloader.Properties.Resources.resourceCulture);
60 |
61 | internal static Bitmap bullet_orange_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_orange_blue), NUS_Downloader.Properties.Resources.resourceCulture);
62 |
63 | internal static Bitmap bullet_red => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_red), NUS_Downloader.Properties.Resources.resourceCulture);
64 |
65 | internal static Bitmap bullet_redgreen => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redgreen), NUS_Downloader.Properties.Resources.resourceCulture);
66 |
67 | internal static Bitmap bullet_redgreen_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redgreen_blue), NUS_Downloader.Properties.Resources.resourceCulture);
68 |
69 | internal static Bitmap bullet_redorange => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redorange), NUS_Downloader.Properties.Resources.resourceCulture);
70 |
71 | internal static Bitmap bullet_redorange_blue => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (bullet_redorange_blue), NUS_Downloader.Properties.Resources.resourceCulture);
72 |
73 | internal static Bitmap connect => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (connect), NUS_Downloader.Properties.Resources.resourceCulture);
74 |
75 | internal static Bitmap database_save => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (database_save), NUS_Downloader.Properties.Resources.resourceCulture);
76 |
77 | internal static Bitmap disk => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (disk), NUS_Downloader.Properties.Resources.resourceCulture);
78 |
79 | internal static Bitmap drive_disk => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (drive_disk), NUS_Downloader.Properties.Resources.resourceCulture);
80 |
81 | internal static Bitmap dsi16x16 => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (dsi16x16), NUS_Downloader.Properties.Resources.resourceCulture);
82 |
83 | internal static Bitmap folder => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (folder), NUS_Downloader.Properties.Resources.resourceCulture);
84 |
85 | internal static Bitmap folder_table => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (folder_table), NUS_Downloader.Properties.Resources.resourceCulture);
86 |
87 | internal static Bitmap help => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (help), NUS_Downloader.Properties.Resources.resourceCulture);
88 |
89 | internal static Bitmap information => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (information), NUS_Downloader.Properties.Resources.resourceCulture);
90 |
91 | internal static Bitmap key => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (key), NUS_Downloader.Properties.Resources.resourceCulture);
92 |
93 | internal static Bitmap money => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (money), NUS_Downloader.Properties.Resources.resourceCulture);
94 |
95 | internal static Bitmap package => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package), NUS_Downloader.Properties.Resources.resourceCulture);
96 |
97 | internal static Bitmap package_add => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package_add), NUS_Downloader.Properties.Resources.resourceCulture);
98 |
99 | internal static Bitmap package_delete => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package_delete), NUS_Downloader.Properties.Resources.resourceCulture);
100 |
101 | internal static Bitmap package_green => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (package_green), NUS_Downloader.Properties.Resources.resourceCulture);
102 |
103 | internal static Bitmap page_white_magnify => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (page_white_magnify), NUS_Downloader.Properties.Resources.resourceCulture);
104 |
105 | internal static Bitmap picture_empty => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (picture_empty), NUS_Downloader.Properties.Resources.resourceCulture);
106 |
107 | internal static Bitmap script_code => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_code), NUS_Downloader.Properties.Resources.resourceCulture);
108 |
109 | internal static Bitmap script_code_red => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_code_red), NUS_Downloader.Properties.Resources.resourceCulture);
110 |
111 | internal static Bitmap script_go => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_go), NUS_Downloader.Properties.Resources.resourceCulture);
112 |
113 | internal static Bitmap script_start => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (script_start), NUS_Downloader.Properties.Resources.resourceCulture);
114 |
115 | internal static Bitmap server_connect => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (server_connect), NUS_Downloader.Properties.Resources.resourceCulture);
116 |
117 | internal static Bitmap server_link => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (server_link), NUS_Downloader.Properties.Resources.resourceCulture);
118 |
119 | internal static Bitmap wii16x16 => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (wii16x16), NUS_Downloader.Properties.Resources.resourceCulture);
120 |
121 | internal static Bitmap wrench => (Bitmap) NUS_Downloader.Properties.Resources.ResourceManager.GetObject(nameof (wrench), NUS_Downloader.Properties.Resources.resourceCulture);
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/libWiiSharp/IosPatcher.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.IosPatcher
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using System.Text;
10 |
11 | namespace libWiiSharp
12 | {
13 | public class IosPatcher
14 | {
15 | private WAD wadFile;
16 | private int esIndex = -1;
17 |
18 | public void LoadIOS(ref WAD iosWad)
19 | {
20 | if (iosWad.TitleID >> 32 != 1UL || (iosWad.TitleID & (ulong) uint.MaxValue) < 3UL || (iosWad.TitleID & (ulong) uint.MaxValue) > (ulong) byte.MaxValue)
21 | throw new Exception("Only IOS WADs can be patched!");
22 | this.wadFile = iosWad;
23 | this.getEsIndex();
24 | }
25 |
26 | public int PatchFakeSigning() => this.esIndex < 0 ? -1 : this.patchFakeSigning(ref this.wadFile.Contents[this.esIndex]);
27 |
28 | public int PatchEsIdentify() => this.esIndex < 0 ? -1 : this.patchEsIdentify(ref this.wadFile.Contents[this.esIndex]);
29 |
30 | public int PatchNandPermissions() => this.esIndex < 0 ? -1 : this.patchNandPermissions(ref this.wadFile.Contents[this.esIndex]);
31 |
32 | public int PatchAll() => this.esIndex < 0 ? -1 : this.patchAll(ref this.wadFile.Contents[this.esIndex]);
33 |
34 | public int PatchFakeSigning(ref byte[] esModule) => this.patchFakeSigning(ref esModule);
35 |
36 | public int PatchEsIdentify(ref byte[] esModule) => this.patchEsIdentify(ref esModule);
37 |
38 | public int PatchNandPermissions(ref byte[] esModule) => this.patchNandPermissions(ref esModule);
39 |
40 | public int PatchAll(ref byte[] esModule) => this.patchAll(ref esModule);
41 |
42 | private int patchFakeSigning(ref byte[] esModule)
43 | {
44 | this.fireDebug("Patching Fakesigning...");
45 | int num = 0;
46 | byte[] second1 = new byte[4]
47 | {
48 | (byte) 32,
49 | (byte) 7,
50 | (byte) 35,
51 | (byte) 162
52 | };
53 | byte[] second2 = new byte[4]
54 | {
55 | (byte) 32,
56 | (byte) 7,
57 | (byte) 75,
58 | (byte) 11
59 | };
60 | for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex)
61 | {
62 | this.fireProgress((firstIndex + 1) * 100 / esModule.Length);
63 | if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4))
64 | {
65 | this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper());
66 | esModule[firstIndex + 1] = (byte) 0;
67 | firstIndex += 4;
68 | ++num;
69 | }
70 | }
71 | this.fireDebug("Patching Fakesigning Finished... (Patches applied: {0})", (object) num);
72 | return num;
73 | }
74 |
75 | private int patchEsIdentify(ref byte[] esModule)
76 | {
77 | this.fireDebug("Patching ES_Identify...");
78 | int num = 0;
79 | byte[] second = new byte[4]
80 | {
81 | (byte) 40,
82 | (byte) 3,
83 | (byte) 209,
84 | (byte) 35
85 | };
86 | for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex)
87 | {
88 | this.fireProgress((firstIndex + 1) * 100 / esModule.Length);
89 | if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 4))
90 | {
91 | this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper());
92 | esModule[firstIndex + 2] = (byte) 0;
93 | esModule[firstIndex + 3] = (byte) 0;
94 | firstIndex += 4;
95 | ++num;
96 | }
97 | }
98 | this.fireDebug("Patching ES_Identify Finished... (Patches applied: {0})", (object) num);
99 | return num;
100 | }
101 |
102 | private int patchNandPermissions(ref byte[] esModule)
103 | {
104 | this.fireDebug("Patching NAND Permissions...");
105 | int num = 0;
106 | byte[] second = new byte[6]
107 | {
108 | (byte) 66,
109 | (byte) 139,
110 | (byte) 208,
111 | (byte) 1,
112 | (byte) 37,
113 | (byte) 102
114 | };
115 | for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex)
116 | {
117 | this.fireProgress((firstIndex + 1) * 100 / esModule.Length);
118 | if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 6))
119 | {
120 | this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper());
121 | esModule[firstIndex + 2] = (byte) 224;
122 | firstIndex += 6;
123 | ++num;
124 | }
125 | }
126 | this.fireDebug("Patching NAND Permissions Finished... (Patches applied: {0})", (object) num);
127 | return num;
128 | }
129 |
130 | private int patchAll(ref byte[] esModule)
131 | {
132 | this.fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions...");
133 | int num = 0;
134 | byte[] second1 = new byte[4]
135 | {
136 | (byte) 32,
137 | (byte) 7,
138 | (byte) 35,
139 | (byte) 162
140 | };
141 | byte[] second2 = new byte[4]
142 | {
143 | (byte) 32,
144 | (byte) 7,
145 | (byte) 75,
146 | (byte) 11
147 | };
148 | byte[] second3 = new byte[4]
149 | {
150 | (byte) 40,
151 | (byte) 3,
152 | (byte) 209,
153 | (byte) 35
154 | };
155 | byte[] second4 = new byte[6]
156 | {
157 | (byte) 66,
158 | (byte) 139,
159 | (byte) 208,
160 | (byte) 1,
161 | (byte) 37,
162 | (byte) 102
163 | };
164 | for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex)
165 | {
166 | this.fireProgress((firstIndex + 1) * 100 / esModule.Length);
167 | if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4))
168 | {
169 | this.fireDebug(" Patching Fakesigning at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper());
170 | esModule[firstIndex + 1] = (byte) 0;
171 | firstIndex += 4;
172 | ++num;
173 | }
174 | else if (Shared.CompareByteArrays(esModule, firstIndex, second3, 0, 4))
175 | {
176 | this.fireDebug(" Patching ES_Identify at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper());
177 | esModule[firstIndex + 2] = (byte) 0;
178 | esModule[firstIndex + 3] = (byte) 0;
179 | firstIndex += 4;
180 | ++num;
181 | }
182 | else if (Shared.CompareByteArrays(esModule, firstIndex, second4, 0, 6))
183 | {
184 | this.fireDebug(" Patching NAND Permissions at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper());
185 | esModule[firstIndex + 2] = (byte) 224;
186 | firstIndex += 6;
187 | ++num;
188 | }
189 | }
190 | this.fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions Finished... (Patches applied: {0})", (object) num);
191 | return num;
192 | }
193 |
194 | private void getEsIndex()
195 | {
196 | this.fireDebug("Scanning for ES Module...");
197 | string str = "$IOSVersion:";
198 | for (int index1 = this.wadFile.NumOfContents - 1; index1 >= 0; --index1)
199 | {
200 | this.fireDebug(" Scanning Content #{0} of {1}...", (object) (index1 + 1), (object) this.wadFile.NumOfContents);
201 | this.fireProgress((index1 + 1) * 100 / this.wadFile.NumOfContents);
202 | for (int index2 = 0; index2 < this.wadFile.Contents[index1].Length - 64; ++index2)
203 | {
204 | if (Encoding.ASCII.GetString(this.wadFile.Contents[index1], index2, 12) == str)
205 | {
206 | int index3 = index2 + 12;
207 | while (this.wadFile.Contents[index1][index3] == (byte) 32)
208 | ++index3;
209 | if (Encoding.ASCII.GetString(this.wadFile.Contents[index1], index3, 3) == "ES:")
210 | {
211 | this.fireDebug(" -> ES Module found!");
212 | this.fireDebug("Scanning for ES Module Finished...");
213 | this.esIndex = index1;
214 | this.fireProgress(100);
215 | return;
216 | }
217 | }
218 | }
219 | }
220 | this.fireDebug("/!\\/!\\/!\\ ES Module wasn't found! /!\\/!\\/!\\");
221 | throw new Exception("ES module wasn't found!");
222 | }
223 |
224 | public event EventHandler Progress;
225 |
226 | public event EventHandler Debug;
227 |
228 | private void fireDebug(string debugMessage, params object[] args)
229 | {
230 | EventHandler debug = this.Debug;
231 | if (debug == null)
232 | return;
233 | debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
234 | }
235 |
236 | private void fireProgress(int progressPercentage)
237 | {
238 | EventHandler progress = this.Progress;
239 | if (progress == null)
240 | return;
241 | progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty));
242 | }
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/libWiiSharp/Lz77.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.Lz77
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.IO;
9 |
10 | namespace libWiiSharp
11 | {
12 | public class Lz77
13 | {
14 | private const int N = 4096;
15 | private const int F = 18;
16 | private const int threshold = 2;
17 | private static uint lz77Magic = 1280980791;
18 | private int[] leftSon = new int[4097];
19 | private int[] rightSon = new int[4353];
20 | private int[] dad = new int[4097];
21 | private ushort[] textBuffer = new ushort[4113];
22 | private int matchPosition;
23 | private int matchLength;
24 |
25 | public static uint Lz77Magic => Lz77.lz77Magic;
26 |
27 | public static bool IsLz77Compressed(string file) => Lz77.IsLz77Compressed(File.ReadAllBytes(file));
28 |
29 | public static bool IsLz77Compressed(byte[] file)
30 | {
31 | Headers.HeaderType startIndex = Headers.DetectHeader(file);
32 | return (int) Shared.Swap(BitConverter.ToUInt32(file, (int) startIndex)) == (int) Lz77.lz77Magic;
33 | }
34 |
35 | public static bool IsLz77Compressed(Stream file)
36 | {
37 | Headers.HeaderType offset = Headers.DetectHeader(file);
38 | byte[] buffer = new byte[4];
39 | file.Seek((long) offset, SeekOrigin.Begin);
40 | file.Read(buffer, 0, buffer.Length);
41 | return (int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Lz77.lz77Magic;
42 | }
43 |
44 | public void Compress(string inFile, string outFile)
45 | {
46 | Stream stream;
47 | using (FileStream inFile1 = new FileStream(inFile, FileMode.Open))
48 | stream = this.compress((Stream) inFile1);
49 | byte[] buffer = new byte[stream.Length];
50 | stream.Read(buffer, 0, buffer.Length);
51 | if (File.Exists(outFile))
52 | File.Delete(outFile);
53 | using (FileStream fileStream = new FileStream(outFile, FileMode.Create))
54 | fileStream.Write(buffer, 0, buffer.Length);
55 | }
56 |
57 | public byte[] Compress(byte[] file) => ((MemoryStream) this.compress((Stream) new MemoryStream(file))).ToArray();
58 |
59 | public Stream Compress(Stream file) => this.compress(file);
60 |
61 | public void Decompress(string inFile, string outFile)
62 | {
63 | Stream stream;
64 | using (FileStream inFile1 = new FileStream(inFile, FileMode.Open))
65 | stream = this.decompress((Stream) inFile1);
66 | byte[] buffer = new byte[stream.Length];
67 | stream.Read(buffer, 0, buffer.Length);
68 | if (File.Exists(outFile))
69 | File.Delete(outFile);
70 | using (FileStream fileStream = new FileStream(outFile, FileMode.Create))
71 | fileStream.Write(buffer, 0, buffer.Length);
72 | }
73 |
74 | public byte[] Decompress(byte[] file) => ((MemoryStream) this.decompress((Stream) new MemoryStream(file))).ToArray();
75 |
76 | public Stream Decompress(Stream file) => this.decompress(file);
77 |
78 | private Stream decompress(Stream inFile)
79 | {
80 | if (!Lz77.IsLz77Compressed(inFile))
81 | return inFile;
82 | inFile.Seek(0L, SeekOrigin.Begin);
83 | uint num1 = 0;
84 | Headers.HeaderType offset = Headers.DetectHeader(inFile);
85 | byte[] buffer = new byte[8];
86 | inFile.Seek((long) offset, SeekOrigin.Begin);
87 | inFile.Read(buffer, 0, 8);
88 | if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) Lz77.lz77Magic)
89 | {
90 | inFile.Dispose();
91 | throw new Exception("Invaild Magic!");
92 | }
93 | if (buffer[4] != (byte) 16)
94 | {
95 | inFile.Dispose();
96 | throw new Exception("Unsupported Compression Type!");
97 | }
98 | uint num2 = BitConverter.ToUInt32(buffer, 4) >> 8;
99 | for (int index = 0; index < 4078; ++index)
100 | this.textBuffer[index] = (ushort) 223;
101 | int num3 = 4078;
102 | uint num4 = 7;
103 | int num5 = 7;
104 | MemoryStream memoryStream = new MemoryStream();
105 | label_10:
106 | while (true)
107 | {
108 | num4 <<= 1;
109 | ++num5;
110 | if (num5 == 8)
111 | {
112 | int num6;
113 | if ((num6 = inFile.ReadByte()) != -1)
114 | {
115 | num4 = (uint) num6;
116 | num5 = 0;
117 | }
118 | else
119 | goto label_24;
120 | }
121 | if (((int) num4 & 128) == 0)
122 | {
123 | int num7;
124 | if ((long) (num7 = inFile.ReadByte()) != inFile.Length - 1L)
125 | {
126 | if (num1 < num2)
127 | memoryStream.WriteByte((byte) num7);
128 | ushort[] textBuffer = this.textBuffer;
129 | int index = num3;
130 | int num8 = index + 1;
131 | int num9 = (int) (byte) num7;
132 | textBuffer[index] = (ushort) num9;
133 | num3 = num8 & 4095;
134 | ++num1;
135 | }
136 | else
137 | goto label_24;
138 | }
139 | else
140 | break;
141 | }
142 | int num10;
143 | int num11;
144 | if ((num10 = inFile.ReadByte()) != -1 && (num11 = inFile.ReadByte()) != -1)
145 | {
146 | int num12 = num11 | num10 << 8 & 3840;
147 | int num13 = (num10 >> 4 & 15) + 2;
148 | for (int index1 = 0; index1 <= num13; ++index1)
149 | {
150 | int num14 = (int) this.textBuffer[num3 - num12 - 1 & 4095];
151 | if (num1 < num2)
152 | memoryStream.WriteByte((byte) num14);
153 | ushort[] textBuffer = this.textBuffer;
154 | int index2 = num3;
155 | int num15 = index2 + 1;
156 | int num16 = (int) (byte) num14;
157 | textBuffer[index2] = (ushort) num16;
158 | num3 = num15 & 4095;
159 | ++num1;
160 | }
161 | goto label_10;
162 | }
163 | label_24:
164 | return (Stream) memoryStream;
165 | }
166 |
167 | private Stream compress(Stream inFile)
168 | {
169 | if (Lz77.IsLz77Compressed(inFile))
170 | return inFile;
171 | inFile.Seek(0L, SeekOrigin.Begin);
172 | int num1 = 0;
173 | int[] numArray1 = new int[17];
174 | uint num2 = (uint) (((int) Convert.ToUInt32(inFile.Length) << 8) + 16);
175 | MemoryStream memoryStream = new MemoryStream();
176 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(Lz77.lz77Magic)), 0, 4);
177 | memoryStream.Write(BitConverter.GetBytes(num2), 0, 4);
178 | this.InitTree();
179 | numArray1[0] = 0;
180 | int num3 = 1;
181 | int num4 = 128;
182 | int p = 0;
183 | int r = 4078;
184 | for (int index = p; index < r; ++index)
185 | this.textBuffer[index] = ushort.MaxValue;
186 | int num5;
187 | int num6;
188 | for (num5 = 0; num5 < 18 && (num6 = inFile.ReadByte()) != -1; ++num5)
189 | this.textBuffer[r + num5] = (ushort) num6;
190 | if (num5 == 0)
191 | return inFile;
192 | for (int index = 1; index <= 18; ++index)
193 | this.InsertNode(r - index);
194 | this.InsertNode(r);
195 | do
196 | {
197 | if (this.matchLength > num5)
198 | this.matchLength = num5;
199 | if (this.matchLength <= 2)
200 | {
201 | this.matchLength = 1;
202 | numArray1[num3++] = (int) this.textBuffer[r];
203 | }
204 | else
205 | {
206 | numArray1[0] |= num4;
207 | int[] numArray2 = numArray1;
208 | int index1 = num3;
209 | int num7 = index1 + 1;
210 | int num8 = (int) (ushort) (r - this.matchPosition - 1 >> 8 & 15) | this.matchLength - 3 << 4;
211 | numArray2[index1] = num8;
212 | int[] numArray3 = numArray1;
213 | int index2 = num7;
214 | num3 = index2 + 1;
215 | int num9 = (int) (ushort) (r - this.matchPosition - 1 & (int) byte.MaxValue);
216 | numArray3[index2] = num9;
217 | }
218 | if ((num4 >>= 1) == 0)
219 | {
220 | for (int index = 0; index < num3; ++index)
221 | memoryStream.WriteByte((byte) numArray1[index]);
222 | num1 += num3;
223 | numArray1[0] = 0;
224 | num3 = 1;
225 | num4 = 128;
226 | }
227 | int matchLength = this.matchLength;
228 | int num10;
229 | int num11;
230 | for (num10 = 0; num10 < matchLength && (num11 = inFile.ReadByte()) != -1; ++num10)
231 | {
232 | this.DeleteNode(p);
233 | this.textBuffer[p] = (ushort) num11;
234 | if (p < 17)
235 | this.textBuffer[p + 4096] = (ushort) num11;
236 | p = p + 1 & 4095;
237 | r = r + 1 & 4095;
238 | this.InsertNode(r);
239 | }
240 | while (num10++ < matchLength)
241 | {
242 | this.DeleteNode(p);
243 | p = p + 1 & 4095;
244 | r = r + 1 & 4095;
245 | if (--num5 != 0)
246 | this.InsertNode(r);
247 | }
248 | }
249 | while (num5 > 0);
250 | if (num3 > 1)
251 | {
252 | for (int index = 0; index < num3; ++index)
253 | memoryStream.WriteByte((byte) numArray1[index]);
254 | num1 += num3;
255 | }
256 | if (num1 % 4 != 0)
257 | {
258 | for (int index = 0; index < 4 - num1 % 4; ++index)
259 | memoryStream.WriteByte((byte) 0);
260 | }
261 | return (Stream) memoryStream;
262 | }
263 |
264 | private void InitTree()
265 | {
266 | for (int index = 4097; index <= 4352; ++index)
267 | this.rightSon[index] = 4096;
268 | for (int index = 0; index < 4096; ++index)
269 | this.dad[index] = 4096;
270 | }
271 |
272 | private void InsertNode(int r)
273 | {
274 | int num1 = 1;
275 | int index = 4097 + (this.textBuffer[r] == ushort.MaxValue ? 0 : (int) this.textBuffer[r]);
276 | this.rightSon[r] = this.leftSon[r] = 4096;
277 | this.matchLength = 0;
278 | int num2;
279 | do
280 | {
281 | do
282 | {
283 | if (num1 >= 0)
284 | {
285 | if (this.rightSon[index] != 4096)
286 | {
287 | index = this.rightSon[index];
288 | }
289 | else
290 | {
291 | this.rightSon[index] = r;
292 | this.dad[r] = index;
293 | return;
294 | }
295 | }
296 | else if (this.leftSon[index] != 4096)
297 | {
298 | index = this.leftSon[index];
299 | }
300 | else
301 | {
302 | this.leftSon[index] = r;
303 | this.dad[r] = index;
304 | return;
305 | }
306 | num2 = 1;
307 | while (num2 < 18 && (num1 = (int) this.textBuffer[r + num2] - (int) this.textBuffer[index + num2]) == 0)
308 | ++num2;
309 | }
310 | while (num2 <= this.matchLength);
311 | this.matchPosition = index;
312 | }
313 | while ((this.matchLength = num2) < 18);
314 | this.dad[r] = this.dad[index];
315 | this.leftSon[r] = this.leftSon[index];
316 | this.rightSon[r] = this.rightSon[index];
317 | this.dad[this.leftSon[index]] = r;
318 | this.dad[this.rightSon[index]] = r;
319 | if (this.rightSon[this.dad[index]] == index)
320 | this.rightSon[this.dad[index]] = r;
321 | else
322 | this.leftSon[this.dad[index]] = r;
323 | this.dad[index] = 4096;
324 | }
325 |
326 | private void DeleteNode(int p)
327 | {
328 | if (this.dad[p] == 4096)
329 | return;
330 | int index;
331 | if (this.rightSon[p] == 4096)
332 | index = this.leftSon[p];
333 | else if (this.leftSon[p] == 4096)
334 | {
335 | index = this.rightSon[p];
336 | }
337 | else
338 | {
339 | index = this.leftSon[p];
340 | if (this.rightSon[index] != 4096)
341 | {
342 | do
343 | {
344 | index = this.rightSon[index];
345 | }
346 | while (this.rightSon[index] != 4096);
347 | this.rightSon[this.dad[index]] = this.leftSon[index];
348 | this.dad[this.leftSon[index]] = this.dad[index];
349 | this.leftSon[index] = this.leftSon[p];
350 | this.dad[this.leftSon[p]] = index;
351 | }
352 | this.rightSon[index] = this.rightSon[p];
353 | this.dad[this.rightSon[p]] = index;
354 | }
355 | this.dad[index] = this.dad[p];
356 | if (this.rightSon[this.dad[p]] == p)
357 | this.rightSon[this.dad[p]] = index;
358 | else
359 | this.leftSon[this.dad[p]] = index;
360 | this.dad[p] = 4096;
361 | }
362 | }
363 | }
364 |
--------------------------------------------------------------------------------
/libWiiSharp/CertificateChain.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.CertificateChain
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.IO;
9 | using System.Security.Cryptography;
10 |
11 | namespace libWiiSharp
12 | {
13 | public class CertificateChain : IDisposable
14 | {
15 | private const string certCaHash = "5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318";
16 | private const string certCpHash = "6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C";
17 | private const string certXsHash = "09787045037121477824BC6A3E5E076156573F8A";
18 | private SHA1 sha = SHA1.Create();
19 | private bool[] certsComplete = new bool[3];
20 | private byte[] certCa = new byte[1024];
21 | private byte[] certCp = new byte[768];
22 | private byte[] certXs = new byte[768];
23 | private bool isDisposed;
24 |
25 | public bool CertsComplete => this.certsComplete[0] && this.certsComplete[1] && this.certsComplete[2];
26 |
27 | ~CertificateChain() => this.Dispose(false);
28 |
29 | public void Dispose()
30 | {
31 | this.Dispose(true);
32 | GC.SuppressFinalize((object) this);
33 | }
34 |
35 | protected virtual void Dispose(bool disposing)
36 | {
37 | if (disposing && !this.isDisposed)
38 | {
39 | this.sha.Clear();
40 | this.sha = (SHA1) null;
41 | this.certsComplete = (bool[]) null;
42 | this.certCa = (byte[]) null;
43 | this.certCp = (byte[]) null;
44 | this.certXs = (byte[]) null;
45 | }
46 | this.isDisposed = true;
47 | }
48 |
49 | public static CertificateChain Load(string pathToCert) => CertificateChain.Load(File.ReadAllBytes(pathToCert));
50 |
51 | public static CertificateChain Load(byte[] certFile)
52 | {
53 | CertificateChain certificateChain = new CertificateChain();
54 | MemoryStream certFile1 = new MemoryStream(certFile);
55 | try
56 | {
57 | certificateChain.parseCert((Stream) certFile1);
58 | }
59 | catch
60 | {
61 | certFile1.Dispose();
62 | throw;
63 | }
64 | certFile1.Dispose();
65 | return certificateChain;
66 | }
67 |
68 | public static CertificateChain Load(Stream cert)
69 | {
70 | CertificateChain certificateChain = new CertificateChain();
71 | certificateChain.parseCert(cert);
72 | return certificateChain;
73 | }
74 |
75 | public static CertificateChain FromTikTmd(string pathToTik, string pathToTmd) => CertificateChain.FromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd));
76 |
77 | public static CertificateChain FromTikTmd(string pathToTik, byte[] tmdFile) => CertificateChain.FromTikTmd(File.ReadAllBytes(pathToTik), tmdFile);
78 |
79 | public static CertificateChain FromTikTmd(byte[] tikFile, byte[] tmdFile)
80 | {
81 | CertificateChain certificateChain = new CertificateChain();
82 | MemoryStream tik = new MemoryStream(tikFile);
83 | try
84 | {
85 | certificateChain.grabFromTik((Stream) tik);
86 | }
87 | catch
88 | {
89 | tik.Dispose();
90 | throw;
91 | }
92 | MemoryStream tmd = new MemoryStream(tmdFile);
93 | try
94 | {
95 | certificateChain.grabFromTmd((Stream) tmd);
96 | }
97 | catch
98 | {
99 | tmd.Dispose();
100 | throw;
101 | }
102 | tmd.Dispose();
103 | return certificateChain.CertsComplete ? certificateChain : throw new Exception("Couldn't locate all certs!");
104 | }
105 |
106 | public static CertificateChain FromTikTmd(Stream tik, Stream tmd)
107 | {
108 | CertificateChain certificateChain = new CertificateChain();
109 | certificateChain.grabFromTik(tik);
110 | certificateChain.grabFromTmd(tmd);
111 | return certificateChain;
112 | }
113 |
114 | public void LoadFile(string pathToCert) => this.LoadFile(File.ReadAllBytes(pathToCert));
115 |
116 | public void LoadFile(byte[] certFile)
117 | {
118 | MemoryStream certFile1 = new MemoryStream(certFile);
119 | try
120 | {
121 | this.parseCert((Stream) certFile1);
122 | }
123 | catch
124 | {
125 | certFile1.Dispose();
126 | throw;
127 | }
128 | certFile1.Dispose();
129 | }
130 |
131 | public void LoadFile(Stream cert) => this.parseCert(cert);
132 |
133 | public void LoadFromTikTmd(string pathToTik, string pathToTmd) => this.LoadFromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd));
134 |
135 | public void LoadFromTikTmd(string pathToTik, byte[] tmdFile) => this.LoadFromTikTmd(File.ReadAllBytes(pathToTik), tmdFile);
136 |
137 | public void LoadFromTikTmd(byte[] tikFile, byte[] tmdFile)
138 | {
139 | MemoryStream tik = new MemoryStream(tikFile);
140 | try
141 | {
142 | this.grabFromTik((Stream) tik);
143 | }
144 | catch
145 | {
146 | tik.Dispose();
147 | throw;
148 | }
149 | MemoryStream tmd = new MemoryStream(tmdFile);
150 | try
151 | {
152 | this.grabFromTmd((Stream) tmd);
153 | }
154 | catch
155 | {
156 | tmd.Dispose();
157 | throw;
158 | }
159 | tmd.Dispose();
160 | if (!this.CertsComplete)
161 | throw new Exception("Couldn't locate all certs!");
162 | }
163 |
164 | public void LoadFromTikTmd(Stream tik, Stream tmd)
165 | {
166 | this.grabFromTik(tik);
167 | this.grabFromTmd(tmd);
168 | }
169 |
170 | public void Save(string savePath)
171 | {
172 | if (File.Exists(savePath))
173 | File.Delete(savePath);
174 | using (FileStream writeStream = new FileStream(savePath, FileMode.Create))
175 | this.writeToStream((Stream) writeStream);
176 | }
177 |
178 | public MemoryStream ToMemoryStream()
179 | {
180 | MemoryStream writeStream = new MemoryStream();
181 | try
182 | {
183 | this.writeToStream((Stream) writeStream);
184 | }
185 | catch
186 | {
187 | writeStream.Dispose();
188 | throw;
189 | }
190 | return writeStream;
191 | }
192 |
193 | public byte[] ToByteArray()
194 | {
195 | MemoryStream writeStream = new MemoryStream();
196 | try
197 | {
198 | this.writeToStream((Stream) writeStream);
199 | }
200 | catch
201 | {
202 | writeStream.Dispose();
203 | throw;
204 | }
205 | byte[] array = writeStream.ToArray();
206 | writeStream.Dispose();
207 | return array;
208 | }
209 |
210 | private void writeToStream(Stream writeStream)
211 | {
212 | this.fireDebug("Writing Certificate Chain...");
213 | if (!this.CertsComplete)
214 | {
215 | this.fireDebug(" Certificate Chain incomplete...");
216 | throw new Exception("At least one certificate is missing!");
217 | }
218 | writeStream.Seek(0L, SeekOrigin.Begin);
219 | this.fireDebug(" Writing Certificate CA... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8"));
220 | writeStream.Write(this.certCa, 0, this.certCa.Length);
221 | this.fireDebug(" Writing Certificate CP... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8"));
222 | writeStream.Write(this.certCp, 0, this.certCp.Length);
223 | this.fireDebug(" Writing Certificate XS... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8"));
224 | writeStream.Write(this.certXs, 0, this.certXs.Length);
225 | this.fireDebug("Writing Certificate Chain Finished...");
226 | }
227 |
228 | private void parseCert(Stream certFile)
229 | {
230 | this.fireDebug("Parsing Certificate Chain...");
231 | int offset = 0;
232 | for (int index = 0; index < 3; ++index)
233 | {
234 | this.fireDebug(" Scanning at Offset 0x{0}:", (object) offset.ToString("x8"));
235 | try
236 | {
237 | certFile.Seek((long) offset, SeekOrigin.Begin);
238 | byte[] array = new byte[1024];
239 | certFile.Read(array, 0, array.Length);
240 | this.fireDebug(" Checking for Certificate CA...");
241 | if (this.isCertCa(array) && !this.certsComplete[1])
242 | {
243 | this.fireDebug(" Certificate CA detected...");
244 | this.certCa = array;
245 | this.certsComplete[1] = true;
246 | offset += 1024;
247 | continue;
248 | }
249 | this.fireDebug(" Checking for Certificate CP...");
250 | if (this.isCertCp(array) && !this.certsComplete[2])
251 | {
252 | this.fireDebug(" Certificate CP detected...");
253 | Array.Resize(ref array, 768);
254 | this.certCp = array;
255 | this.certsComplete[2] = true;
256 | offset += 768;
257 | continue;
258 | }
259 | this.fireDebug(" Checking for Certificate XS...");
260 | if (this.isCertXs(array))
261 | {
262 | if (!this.certsComplete[0])
263 | {
264 | this.fireDebug(" Certificate XS detected...");
265 | Array.Resize(ref array, 768);
266 | this.certXs = array;
267 | this.certsComplete[0] = true;
268 | offset += 768;
269 | continue;
270 | }
271 | }
272 | }
273 | catch (Exception ex)
274 | {
275 | this.fireDebug("Error: {0}", (object) ex.Message);
276 | }
277 | offset += 768;
278 | }
279 | if (!this.CertsComplete)
280 | {
281 | this.fireDebug(" Couldn't locate all Certificates...");
282 | throw new Exception("Couldn't locate all certs!");
283 | }
284 | this.fireDebug("Parsing Certificate Chain Finished...");
285 | }
286 |
287 | private void grabFromTik(Stream tik)
288 | {
289 | this.fireDebug("Scanning Ticket for Certificates...");
290 | int offset = 676;
291 | for (int index = 0; index < 3; ++index)
292 | {
293 | this.fireDebug(" Scanning at Offset 0x{0}:", (object) offset.ToString("x8"));
294 | try
295 | {
296 | tik.Seek((long) offset, SeekOrigin.Begin);
297 | byte[] array = new byte[1024];
298 | tik.Read(array, 0, array.Length);
299 | this.fireDebug(" Checking for Certificate CA...");
300 | if (this.isCertCa(array) && !this.certsComplete[1])
301 | {
302 | this.fireDebug(" Certificate CA detected...");
303 | this.certCa = array;
304 | this.certsComplete[1] = true;
305 | offset += 1024;
306 | continue;
307 | }
308 | this.fireDebug(" Checking for Certificate CP...");
309 | if (this.isCertCp(array) && !this.certsComplete[2])
310 | {
311 | this.fireDebug(" Certificate CP detected...");
312 | Array.Resize(ref array, 768);
313 | this.certCp = array;
314 | this.certsComplete[2] = true;
315 | offset += 768;
316 | continue;
317 | }
318 | this.fireDebug(" Checking for Certificate XS...");
319 | if (this.isCertXs(array))
320 | {
321 | if (!this.certsComplete[0])
322 | {
323 | this.fireDebug(" Certificate XS detected...");
324 | Array.Resize(ref array, 768);
325 | this.certXs = array;
326 | this.certsComplete[0] = true;
327 | offset += 768;
328 | continue;
329 | }
330 | }
331 | }
332 | catch
333 | {
334 | }
335 | offset += 768;
336 | }
337 | this.fireDebug("Scanning Ticket for Certificates Finished...");
338 | }
339 |
340 | private void grabFromTmd(Stream tmd)
341 | {
342 | this.fireDebug("Scanning TMD for Certificates...");
343 | byte[] buffer = new byte[2];
344 | tmd.Seek(478L, SeekOrigin.Begin);
345 | tmd.Read(buffer, 0, 2);
346 | int offset = 484 + (int) Shared.Swap(BitConverter.ToUInt16(buffer, 0)) * 36;
347 | for (int index = 0; index < 3; ++index)
348 | {
349 | this.fireDebug(" Scanning at Offset 0x{0}:", (object) offset.ToString("x8"));
350 | try
351 | {
352 | tmd.Seek((long) offset, SeekOrigin.Begin);
353 | byte[] array = new byte[1024];
354 | tmd.Read(array, 0, array.Length);
355 | this.fireDebug(" Checking for Certificate CA...");
356 | if (this.isCertCa(array) && !this.certsComplete[1])
357 | {
358 | this.fireDebug(" Certificate CA detected...");
359 | this.certCa = array;
360 | this.certsComplete[1] = true;
361 | offset += 1024;
362 | continue;
363 | }
364 | this.fireDebug(" Checking for Certificate CP...");
365 | if (this.isCertCp(array) && !this.certsComplete[2])
366 | {
367 | this.fireDebug(" Certificate CP detected...");
368 | Array.Resize(ref array, 768);
369 | this.certCp = array;
370 | this.certsComplete[2] = true;
371 | offset += 768;
372 | continue;
373 | }
374 | this.fireDebug(" Checking for Certificate XS...");
375 | if (this.isCertXs(array))
376 | {
377 | if (!this.certsComplete[0])
378 | {
379 | this.fireDebug(" Certificate XS detected...");
380 | Array.Resize(ref array, 768);
381 | this.certXs = array;
382 | this.certsComplete[0] = true;
383 | offset += 768;
384 | continue;
385 | }
386 | }
387 | }
388 | catch
389 | {
390 | }
391 | offset += 768;
392 | }
393 | this.fireDebug("Scanning TMD for Certificates Finished...");
394 | }
395 |
396 | private bool isCertXs(byte[] part)
397 | {
398 | if (part.Length < 768)
399 | return false;
400 | if (part.Length > 768)
401 | Array.Resize(ref part, 768);
402 | return part[388] == (byte) 88 && part[389] == (byte) 83 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("09787045037121477824BC6A3E5E076156573F8A"));
403 | }
404 |
405 | private bool isCertCa(byte[] part)
406 | {
407 | if (part.Length < 1024)
408 | return false;
409 | if (part.Length > 1024)
410 | Array.Resize(ref part, 1024);
411 | return part[644] == (byte) 67 && part[645] == (byte) 65 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318"));
412 | }
413 |
414 | private bool isCertCp(byte[] part)
415 | {
416 | if (part.Length < 768)
417 | return false;
418 | if (part.Length > 768)
419 | Array.Resize(ref part, 768);
420 | return part[388] == (byte) 67 && part[389] == (byte) 80 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C"));
421 | }
422 |
423 | public event EventHandler Debug;
424 |
425 | private void fireDebug(string debugMessage, params object[] args)
426 | {
427 | EventHandler debug = this.Debug;
428 | if (debug == null)
429 | return;
430 | debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
431 | }
432 | }
433 | }
434 |
--------------------------------------------------------------------------------
/libWiiSharp/NusClient.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.NusClient
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using System.Globalization;
10 | using System.IO;
11 | using System.Net;
12 | using System.Security.Cryptography;
13 |
14 | namespace libWiiSharp
15 | {
16 | public class NusClient : IDisposable
17 | {
18 | private const string WII_NUS_URL = "http://ccs.cdn.wup.shop.nintendo.net/ccs/download/";
19 | private const string DSI_NUS_URL = "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/";
20 | private const string WII_USER_AGENT = "wii libnup/1.0";
21 | private const string DSI_USER_AGENT = "Opera/9.50 (Nintendo; Opera/154; U; Nintendo DS; en)";
22 | private string nusUrl = "http://ccs.cdn.wup.shop.nintendo.net/ccs/download/";
23 | private WebClient wcNus = new WebClient();
24 | private bool useLocalFiles;
25 | private bool continueWithoutTicket;
26 | private int titleversion;
27 | private bool isDisposed;
28 |
29 | public int TitleVersion => this.titleversion;
30 |
31 | public bool UseLocalFiles
32 | {
33 | get => this.useLocalFiles;
34 | set => this.useLocalFiles = value;
35 | }
36 |
37 | public bool ContinueWithoutTicket
38 | {
39 | get => this.continueWithoutTicket;
40 | set => this.continueWithoutTicket = value;
41 | }
42 |
43 | ~NusClient() => this.Dispose(false);
44 |
45 | public void Dispose()
46 | {
47 | this.Dispose(true);
48 | GC.SuppressFinalize((object) this);
49 | }
50 |
51 | protected virtual void Dispose(bool disposing)
52 | {
53 | if (disposing && !this.isDisposed)
54 | this.wcNus.Dispose();
55 | this.isDisposed = true;
56 | }
57 |
58 | public void ConfigureNusClient(WebClient wcReady) => this.wcNus = wcReady;
59 |
60 | public void SetToWiiServer()
61 | {
62 | this.nusUrl = "http://ccs.cdn.wup.shop.nintendo.net/ccs/download/";
63 | this.wcNus.Headers.Add("User-Agent", "wii libnup/1.0");
64 | }
65 |
66 | public void SetToDSiServer()
67 | {
68 | this.nusUrl = "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/";
69 | this.wcNus.Headers.Add("User-Agent", "Opera/9.50 (Nintendo; Opera/154; U; Nintendo DS; en)");
70 | }
71 |
72 | public void DownloadTitle(
73 | string titleId,
74 | string titleVersion,
75 | string outputDir,
76 | bool alternative_path,
77 | string wadName,
78 | params StoreType[] storeTypes)
79 | {
80 | if (titleId.Length != 16)
81 | throw new Exception("Title ID must be 16 characters long!");
82 | this.downloadTitle(titleId, titleVersion, outputDir, alternative_path, wadName, storeTypes);
83 | }
84 |
85 | public TMD DownloadTMD(string titleId, string titleVersion) => titleId.Length == 16 ? this.downloadTmd(titleId, titleVersion) : throw new Exception("Title ID must be 16 characters long!");
86 |
87 | public Ticket DownloadTicket(string titleId) => titleId.Length == 16 ? this.downloadTicket(titleId) : throw new Exception("Title ID must be 16 characters long!");
88 |
89 | public byte[] DownloadSingleContent(string titleId, string titleVersion, string contentId)
90 | {
91 | if (titleId.Length != 16)
92 | throw new Exception("Title ID must be 16 characters long!");
93 | return this.downloadSingleContent(titleId, titleVersion, contentId);
94 | }
95 |
96 | public void DownloadSingleContent(
97 | string titleId,
98 | string titleVersion,
99 | string contentId,
100 | string savePath)
101 | {
102 | if (titleId.Length != 16)
103 | throw new Exception("Title ID must be 16 characters long!");
104 | if (!Directory.Exists(Path.GetDirectoryName(savePath)))
105 | Directory.CreateDirectory(Path.GetDirectoryName(savePath));
106 | if (System.IO.File.Exists(savePath))
107 | System.IO.File.Delete(savePath);
108 | byte[] bytes = this.downloadSingleContent(titleId, titleVersion, contentId);
109 | System.IO.File.WriteAllBytes(savePath, bytes);
110 | }
111 |
112 | private byte[] downloadSingleContent(string titleId, string titleVersion, string contentId)
113 | {
114 | uint num = uint.Parse(contentId, NumberStyles.HexNumber);
115 | contentId = num.ToString("x8");
116 | this.fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2}...", (object) contentId, (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion);
117 | this.fireDebug(" Checking for Internet connection...");
118 | if (!this.CheckInet())
119 | {
120 | this.fireDebug(" Connection not found...");
121 | throw new Exception("You're not connected to the internet!");
122 | }
123 | this.fireProgress(0);
124 | string str1 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", (object) titleVersion));
125 | string str2 = string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId);
126 | string empty = string.Empty;
127 | int contentIndex = 0;
128 | this.fireDebug(" Downloading TMD...");
129 | byte[] tmdFile = this.wcNus.DownloadData(str2 + str1);
130 | this.fireDebug(" Parsing TMD...");
131 | TMD tmd = TMD.Load(tmdFile);
132 | this.fireProgress(20);
133 | this.fireDebug(" Looking for Content ID {0} in TMD...", (object) contentId);
134 | bool flag = false;
135 | for (int index = 0; index < tmd.Contents.Length; ++index)
136 | {
137 | if ((int) tmd.Contents[index].ContentID == (int) num)
138 | {
139 | this.fireDebug(" Content ID {0} found in TMD...", (object) contentId);
140 | flag = true;
141 | empty = tmd.Contents[index].ContentID.ToString("x8");
142 | contentIndex = index;
143 | break;
144 | }
145 | }
146 | if (!flag)
147 | {
148 | this.fireDebug(" Content ID {0} wasn't found in TMD...", (object) contentId);
149 | throw new Exception("Content ID wasn't found in the TMD!");
150 | }
151 | this.fireDebug(" Downloading Ticket...");
152 | byte[] ticket = this.wcNus.DownloadData(str2 + "cetk");
153 | this.fireDebug(" Parsing Ticket...");
154 | Ticket tik = Ticket.Load(ticket);
155 | this.fireProgress(40);
156 | this.fireDebug(" Downloading Content... ({0} bytes)", (object) tmd.Contents[contentIndex].Size);
157 | byte[] content = this.wcNus.DownloadData(str2 + empty);
158 | this.fireProgress(80);
159 | this.fireDebug(" Decrypting Content...");
160 | byte[] array = this.decryptContent(content, contentIndex, tik, tmd);
161 | Array.Resize(ref array, (int) tmd.Contents[contentIndex].Size);
162 | if (!Shared.CompareByteArrays(SHA1.Create().ComputeHash(array), tmd.Contents[contentIndex].Hash))
163 | {
164 | this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\");
165 | throw new Exception("Hashes do not match!");
166 | }
167 | this.fireProgress(100);
168 | this.fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2} Finished...", (object) contentId, (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion);
169 | return array;
170 | }
171 |
172 | private Ticket downloadTicket(string titleId)
173 | {
174 | if (!this.CheckInet())
175 | throw new Exception("You're not connected to the internet!");
176 | return Ticket.Load(this.wcNus.DownloadData(string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId) + "cetk"));
177 | }
178 |
179 | private TMD downloadTmd(string titleId, string titleVersion)
180 | {
181 | if (!this.CheckInet())
182 | throw new Exception("You're not connected to the internet!");
183 | return TMD.Load(this.wcNus.DownloadData(string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId) + ("tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", (object) titleVersion)))));
184 | }
185 |
186 | private void downloadTitle(
187 | string titleId,
188 | string titleVersion,
189 | string outputDir,
190 | bool alternative_path,
191 | string wadName,
192 | StoreType[] storeTypes)
193 | {
194 | this.fireDebug("Downloading Title {0} v{1}...", (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion);
195 | if (storeTypes.Length < 1)
196 | {
197 | this.fireDebug(" No store types were defined...");
198 | throw new Exception("You must at least define one store type!");
199 | }
200 | string path1 = string.Format("{0}{1}/", (object) this.nusUrl, (object) titleId);
201 | bool flag1 = false;
202 | bool flag2 = false;
203 | bool flag3 = false;
204 | this.fireProgress(0);
205 | foreach (int storeType in storeTypes)
206 | {
207 | switch (storeType)
208 | {
209 | case 0:
210 | this.fireDebug(" [=] Storing Encrypted Content...");
211 | flag1 = true;
212 | break;
213 | case 1:
214 | this.fireDebug(" [=] Storing Decrypted Content...");
215 | flag2 = true;
216 | break;
217 | case 2:
218 | this.fireDebug(" [=] Storing WAD...");
219 | flag3 = true;
220 | break;
221 | case 3:
222 | this.fireDebug(" [=] Storing Decrypted Content...");
223 | this.fireDebug(" [=] Storing Encrypted Content...");
224 | this.fireDebug(" [=] Storing WAD...");
225 | flag2 = true;
226 | flag1 = true;
227 | flag3 = true;
228 | break;
229 | }
230 | }
231 | if (!Directory.Exists(outputDir))
232 | Directory.CreateDirectory(outputDir);
233 | string path2 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", (object) titleVersion));
234 | this.fireDebug(" - Downloading TMD...");
235 | byte[] tmdFile;
236 | TMD tmd;
237 | try
238 | {
239 | tmdFile = this.wcNus.DownloadData(path1 + path2);
240 | tmd = TMD.Load(tmdFile);
241 | }
242 | catch (Exception ex)
243 | {
244 | this.fireDebug(" + Downloading TMD Failed...");
245 | throw new Exception("Downloading TMD Failed:\n" + ex.Message);
246 | }
247 | if (alternative_path)
248 | {
249 | if (!Directory.Exists(Path.Combine(outputDir, titleId + "v" + (object) tmd.TitleVersion)))
250 | Directory.CreateDirectory(Path.Combine(outputDir, titleId + "v" + (object) tmd.TitleVersion));
251 | outputDir = Path.Combine(outputDir, titleId + "v" + (object) tmd.TitleVersion);
252 | }
253 | else
254 | {
255 | if (!Directory.Exists(Path.Combine(outputDir, titleId)))
256 | Directory.CreateDirectory(Path.Combine(outputDir, titleId));
257 | outputDir = Path.Combine(outputDir, titleId);
258 | }
259 | this.fireDebug(" - Parsing TMD...");
260 | if (string.IsNullOrEmpty(titleVersion))
261 | this.fireDebug(" + Title Version: {0}", (object) tmd.TitleVersion);
262 | this.fireDebug(" + {0} Contents", (object) tmd.NumOfContents);
263 | if (!alternative_path)
264 | {
265 | if (!Directory.Exists(Path.Combine(outputDir, tmd.TitleVersion.ToString())))
266 | Directory.CreateDirectory(Path.Combine(outputDir, tmd.TitleVersion.ToString()));
267 | outputDir = Path.Combine(outputDir, tmd.TitleVersion.ToString());
268 | }
269 | this.titleversion = (int) tmd.TitleVersion;
270 | System.IO.File.WriteAllBytes(Path.Combine(outputDir, path2), tmd.ToByteArray());
271 | this.fireProgress(5);
272 | this.fireDebug(" - Downloading Ticket...");
273 | try
274 | {
275 | this.wcNus.DownloadFile(Path.Combine(path1, "cetk"), Path.Combine(outputDir, "cetk"));
276 | }
277 | catch (Exception ex)
278 | {
279 | if (!this.continueWithoutTicket || !flag1)
280 | {
281 | this.fireDebug(" + Downloading Ticket Failed...");
282 | throw new Exception("Downloading Ticket Failed:\n" + ex.Message);
283 | }
284 | if (!System.IO.File.Exists(Path.Combine(outputDir, "cetk")))
285 | {
286 | flag2 = false;
287 | flag3 = false;
288 | }
289 | }
290 | this.fireProgress(10);
291 | Ticket tik = new Ticket();
292 | if (System.IO.File.Exists(Path.Combine(outputDir, "cetk")))
293 | {
294 | this.fireDebug(" + Parsing Ticket...");
295 | tik = Ticket.Load(Path.Combine(outputDir, "cetk"));
296 | if (this.nusUrl == "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/")
297 | tik.DSiTicket = true;
298 | }
299 | else
300 | this.fireDebug(" + Ticket Unavailable...");
301 | string[] strArray = new string[(int) tmd.NumOfContents];
302 | for (int index = 0; index < (int) tmd.NumOfContents; ++index)
303 | {
304 | this.fireDebug(" - Downloading Content #{0} of {1}... ({2} bytes)", (object) (index + 1), (object) tmd.NumOfContents, (object) tmd.Contents[index].Size);
305 | this.fireProgress((index + 1) * 60 / (int) tmd.NumOfContents + 10);
306 | if (this.useLocalFiles)
307 | {
308 | if (System.IO.File.Exists(Path.Combine(outputDir, tmd.Contents[index].ContentID.ToString("x8"))))
309 | {
310 | this.fireDebug(" + Using Local File, Skipping...");
311 | continue;
312 | }
313 | }
314 | try
315 | {
316 | this.wcNus.DownloadFile(path1 + tmd.Contents[index].ContentID.ToString("x8"), Path.Combine(outputDir, tmd.Contents[index].ContentID.ToString("x8")));
317 | strArray[index] = tmd.Contents[index].ContentID.ToString("x8");
318 | }
319 | catch (Exception ex)
320 | {
321 | this.fireDebug(" - Downloading Content #{0} of {1} failed...", (object) (index + 1), (object) tmd.NumOfContents);
322 | throw new Exception("Downloading Content Failed:\n" + ex.Message);
323 | }
324 | }
325 | if (flag2 || flag3)
326 | {
327 | SHA1 shA1 = SHA1.Create();
328 | for (int contentIndex = 0; contentIndex < (int) tmd.NumOfContents; ++contentIndex)
329 | {
330 | this.fireDebug(" - Decrypting Content #{0} of {1}...", (object) (contentIndex + 1), (object) tmd.NumOfContents);
331 | this.fireProgress((contentIndex + 1) * 20 / (int) tmd.NumOfContents + 75);
332 | byte[] array = this.decryptContent(System.IO.File.ReadAllBytes(Path.Combine(outputDir, tmd.Contents[contentIndex].ContentID.ToString("x8"))), contentIndex, tik, tmd);
333 | Array.Resize(ref array, (int) tmd.Contents[contentIndex].Size);
334 | if (!Shared.CompareByteArrays(shA1.ComputeHash(array), tmd.Contents[contentIndex].Hash))
335 | this.fireDebug(" + Hashes do not match! (Invalid Output)");
336 | System.IO.File.WriteAllBytes(Path.Combine(outputDir, tmd.Contents[contentIndex].ContentID.ToString("x8") + ".app"), array);
337 | }
338 | shA1.Clear();
339 | }
340 | if (flag3)
341 | {
342 | this.fireDebug(" - Building Certificate Chain...");
343 | CertificateChain cert = CertificateChain.FromTikTmd(Path.Combine(outputDir, "cetk"), tmdFile);
344 | byte[][] contents = new byte[(int) tmd.NumOfContents][];
345 | for (int index = 0; index < (int) tmd.NumOfContents; ++index)
346 | contents[index] = System.IO.File.ReadAllBytes(Path.Combine(outputDir, tmd.Contents[index].ContentID.ToString("x8") + ".app"));
347 | this.fireDebug(" - Creating WAD...");
348 | WAD wad = WAD.Create(cert, tik, tmd, contents);
349 | wad.RemoveFooter();
350 | wadName = wadName.Replace("[v]", "v" + this.TitleVersion.ToString());
351 | if (Path.DirectorySeparatorChar.ToString() != "/" && Path.AltDirectorySeparatorChar.ToString() != "/")
352 | wadName = wadName.Replace("/", "");
353 | if (wadName.Contains(Path.DirectorySeparatorChar.ToString()) || wadName.Contains(Path.AltDirectorySeparatorChar.ToString()))
354 | wad.Save(wadName);
355 | else
356 | wad.Save(Path.Combine(outputDir, wadName));
357 | }
358 | if (!flag1)
359 | {
360 | this.fireDebug(" - Deleting Encrypted Contents...");
361 | for (int index = 0; index < strArray.Length; ++index)
362 | {
363 | if (System.IO.File.Exists(Path.Combine(outputDir, strArray[index])))
364 | System.IO.File.Delete(Path.Combine(outputDir, strArray[index]));
365 | }
366 | }
367 | if (flag3 && !flag2)
368 | {
369 | this.fireDebug(" - Deleting Decrypted Contents...");
370 | for (int index = 0; index < strArray.Length; ++index)
371 | {
372 | if (System.IO.File.Exists(Path.Combine(outputDir, strArray[index] + ".app")))
373 | System.IO.File.Delete(Path.Combine(outputDir, strArray[index] + ".app"));
374 | }
375 | }
376 | if (!flag2 && !flag1)
377 | {
378 | this.fireDebug(" - Deleting TMD and Ticket...");
379 | System.IO.File.Delete(Path.Combine(outputDir, path2));
380 | System.IO.File.Delete(Path.Combine(outputDir, "cetk"));
381 | }
382 | this.fireDebug("Downloading Title {0} v{1} Finished...", (object) titleId, (object) tmd.TitleVersion);
383 | this.fireProgress(100);
384 | }
385 |
386 | private byte[] decryptContent(byte[] content, int contentIndex, Ticket tik, TMD tmd)
387 | {
388 | Array.Resize(ref content, Shared.AddPadding(content.Length, 16));
389 | byte[] titleKey = tik.TitleKey;
390 | byte[] numArray = new byte[16];
391 | byte[] bytes = BitConverter.GetBytes(tmd.Contents[contentIndex].Index);
392 | numArray[0] = bytes[1];
393 | numArray[1] = bytes[0];
394 | RijndaelManaged rijndaelManaged = new RijndaelManaged();
395 | rijndaelManaged.Mode = CipherMode.CBC;
396 | rijndaelManaged.Padding = PaddingMode.None;
397 | rijndaelManaged.KeySize = 128;
398 | rijndaelManaged.BlockSize = 128;
399 | rijndaelManaged.Key = titleKey;
400 | rijndaelManaged.IV = numArray;
401 | ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor();
402 | MemoryStream memoryStream = new MemoryStream(content);
403 | CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read);
404 | byte[] buffer = new byte[content.Length];
405 | cryptoStream.Read(buffer, 0, buffer.Length);
406 | cryptoStream.Dispose();
407 | memoryStream.Dispose();
408 | return buffer;
409 | }
410 |
411 | private bool CheckInet()
412 | {
413 | try
414 | {
415 | Dns.GetHostEntry("www.google.com");
416 | return true;
417 | }
418 | catch
419 | {
420 | return false;
421 | }
422 | }
423 |
424 | public event EventHandler Progress;
425 |
426 | public event EventHandler Debug;
427 |
428 | private void fireDebug(string debugMessage, params object[] args)
429 | {
430 | EventHandler debug = this.Debug;
431 | if (debug == null)
432 | return;
433 | debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
434 | }
435 |
436 | private void fireProgress(int progressPercentage)
437 | {
438 | EventHandler progress = this.Progress;
439 | if (progress == null)
440 | return;
441 | progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty));
442 | }
443 | }
444 | }
445 |
--------------------------------------------------------------------------------
/libWiiSharp/Ticket.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.Ticket
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.IO;
9 | using System.Security.Cryptography;
10 |
11 | namespace libWiiSharp
12 | {
13 | public class Ticket : IDisposable
14 | {
15 | private byte newKeyIndex;
16 | private byte[] decryptedTitleKey = new byte[16];
17 | private bool fakeSign;
18 | private bool titleKeyChanged;
19 | private byte[] newEncryptedTitleKey = new byte[0];
20 | private bool reDecrypt;
21 | private uint signatureExponent = 65537;
22 | private byte[] signature = new byte[256];
23 | private byte[] padding = new byte[60];
24 | private byte[] issuer = new byte[64];
25 | private byte[] unknown = new byte[63];
26 | private byte[] encryptedTitleKey = new byte[16];
27 | private byte unknown2;
28 | private ulong ticketId;
29 | private uint consoleId;
30 | private ulong titleId;
31 | private ushort unknown3 = ushort.MaxValue;
32 | private ushort numOfDlc;
33 | private ulong unknown4;
34 | private byte padding2;
35 | private byte commonKeyIndex;
36 | private byte[] unknown5 = new byte[48];
37 | private byte[] unknown6 = new byte[32];
38 | private ushort padding3;
39 | private uint enableTimeLimit;
40 | private uint timeLimit;
41 | private byte[] padding4 = new byte[88];
42 | private bool dsitik;
43 | private bool isDisposed;
44 |
45 | public byte[] TitleKey
46 | {
47 | get => this.decryptedTitleKey;
48 | set
49 | {
50 | this.decryptedTitleKey = value;
51 | this.titleKeyChanged = true;
52 | this.reDecrypt = false;
53 | }
54 | }
55 |
56 | public CommonKeyType CommonKeyIndex
57 | {
58 | get => (CommonKeyType) this.newKeyIndex;
59 | set => this.newKeyIndex = (byte) value;
60 | }
61 |
62 | public ulong TicketID
63 | {
64 | get => this.ticketId;
65 | set => this.ticketId = value;
66 | }
67 |
68 | public uint ConsoleID
69 | {
70 | get => this.consoleId;
71 | set => this.consoleId = value;
72 | }
73 |
74 | public ulong TitleID
75 | {
76 | get => this.titleId;
77 | set
78 | {
79 | this.titleId = value;
80 | if (!this.reDecrypt)
81 | return;
82 | this.reDecryptTitleKey();
83 | }
84 | }
85 |
86 | public ushort NumOfDLC
87 | {
88 | get => this.numOfDlc;
89 | set => this.numOfDlc = value;
90 | }
91 |
92 | public bool FakeSign
93 | {
94 | get => this.fakeSign;
95 | set => this.fakeSign = value;
96 | }
97 |
98 | public bool TitleKeyChanged => this.titleKeyChanged;
99 |
100 | public bool DSiTicket
101 | {
102 | get => this.dsitik;
103 | set
104 | {
105 | this.dsitik = value;
106 | this.decryptTitleKey();
107 | }
108 | }
109 |
110 | ~Ticket() => this.Dispose(false);
111 |
112 | public void Dispose()
113 | {
114 | this.Dispose(true);
115 | GC.SuppressFinalize((object) this);
116 | }
117 |
118 | protected virtual void Dispose(bool disposing)
119 | {
120 | if (disposing && !this.isDisposed)
121 | {
122 | this.decryptedTitleKey = (byte[]) null;
123 | this.newEncryptedTitleKey = (byte[]) null;
124 | this.signature = (byte[]) null;
125 | this.padding = (byte[]) null;
126 | this.issuer = (byte[]) null;
127 | this.unknown = (byte[]) null;
128 | this.encryptedTitleKey = (byte[]) null;
129 | this.unknown5 = (byte[]) null;
130 | this.unknown6 = (byte[]) null;
131 | this.padding4 = (byte[]) null;
132 | }
133 | this.isDisposed = true;
134 | }
135 |
136 | public static Ticket Load(string pathToTicket) => Ticket.Load(File.ReadAllBytes(pathToTicket));
137 |
138 | public static Ticket Load(byte[] ticket)
139 | {
140 | Ticket ticket1 = new Ticket();
141 | MemoryStream ticketFile = new MemoryStream(ticket);
142 | try
143 | {
144 | ticket1.parseTicket((Stream) ticketFile);
145 | }
146 | catch
147 | {
148 | ticketFile.Dispose();
149 | throw;
150 | }
151 | ticketFile.Dispose();
152 | return ticket1;
153 | }
154 |
155 | public static Ticket Load(Stream ticket)
156 | {
157 | Ticket ticket1 = new Ticket();
158 | ticket1.parseTicket(ticket);
159 | return ticket1;
160 | }
161 |
162 | public void LoadFile(string pathToTicket) => this.LoadFile(File.ReadAllBytes(pathToTicket));
163 |
164 | public void LoadFile(byte[] ticket)
165 | {
166 | MemoryStream ticketFile = new MemoryStream(ticket);
167 | try
168 | {
169 | this.parseTicket((Stream) ticketFile);
170 | }
171 | catch
172 | {
173 | ticketFile.Dispose();
174 | throw;
175 | }
176 | ticketFile.Dispose();
177 | }
178 |
179 | public void LoadFile(Stream ticket) => this.parseTicket(ticket);
180 |
181 | public void Save(string savePath) => this.Save(savePath, false);
182 |
183 | public void Save(string savePath, bool fakeSign)
184 | {
185 | if (fakeSign)
186 | this.fakeSign = true;
187 | if (File.Exists(savePath))
188 | File.Delete(savePath);
189 | using (FileStream writeStream = new FileStream(savePath, FileMode.Create))
190 | this.writeToStream((Stream) writeStream);
191 | }
192 |
193 | public MemoryStream ToMemoryStream() => this.ToMemoryStream(false);
194 |
195 | public MemoryStream ToMemoryStream(bool fakeSign)
196 | {
197 | if (fakeSign)
198 | this.fakeSign = true;
199 | MemoryStream writeStream = new MemoryStream();
200 | try
201 | {
202 | this.writeToStream((Stream) writeStream);
203 | }
204 | catch
205 | {
206 | writeStream.Dispose();
207 | throw;
208 | }
209 | return writeStream;
210 | }
211 |
212 | public byte[] ToByteArray() => this.ToByteArray(false);
213 |
214 | public byte[] ToByteArray(bool fakeSign)
215 | {
216 | if (fakeSign)
217 | this.fakeSign = true;
218 | MemoryStream writeStream = new MemoryStream();
219 | try
220 | {
221 | this.writeToStream((Stream) writeStream);
222 | }
223 | catch
224 | {
225 | writeStream.Dispose();
226 | throw;
227 | }
228 | byte[] array = writeStream.ToArray();
229 | writeStream.Dispose();
230 | return array;
231 | }
232 |
233 | public void SetTitleKey(string newTitleKey) => this.SetTitleKey(newTitleKey.ToCharArray());
234 |
235 | public void SetTitleKey(char[] newTitleKey)
236 | {
237 | if (newTitleKey.Length != 16)
238 | throw new Exception("The title key must be 16 characters long!");
239 | for (int index = 0; index < 16; ++index)
240 | this.encryptedTitleKey[index] = (byte) newTitleKey[index];
241 | this.decryptTitleKey();
242 | this.titleKeyChanged = true;
243 | this.reDecrypt = true;
244 | this.newEncryptedTitleKey = this.encryptedTitleKey;
245 | }
246 |
247 | public void SetTitleKey(byte[] newTitleKey)
248 | {
249 | this.encryptedTitleKey = newTitleKey.Length == 16 ? newTitleKey : throw new Exception("The title key must be 16 characters long!");
250 | this.decryptTitleKey();
251 | this.titleKeyChanged = true;
252 | this.reDecrypt = true;
253 | this.newEncryptedTitleKey = newTitleKey;
254 | }
255 |
256 | public string GetUpperTitleID()
257 | {
258 | byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint) this.titleId));
259 | return new string(new char[4]
260 | {
261 | (char) bytes[0],
262 | (char) bytes[1],
263 | (char) bytes[2],
264 | (char) bytes[3]
265 | });
266 | }
267 |
268 | private void writeToStream(Stream writeStream)
269 | {
270 | this.fireDebug("Writing Ticket...");
271 | this.fireDebug(" Encrypting Title Key...");
272 | this.encryptTitleKey();
273 | this.fireDebug(" -> Decrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.decryptedTitleKey));
274 | this.fireDebug(" -> Encrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.encryptedTitleKey));
275 | if (this.fakeSign)
276 | {
277 | this.fireDebug(" Clearing Signature...");
278 | this.signature = new byte[256];
279 | }
280 | MemoryStream memoryStream = new MemoryStream();
281 | memoryStream.Seek(0L, SeekOrigin.Begin);
282 | this.fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
283 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.signatureExponent)), 0, 4);
284 | this.fireDebug(" Writing Signature... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
285 | memoryStream.Write(this.signature, 0, this.signature.Length);
286 | this.fireDebug(" Writing Padding... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
287 | memoryStream.Write(this.padding, 0, this.padding.Length);
288 | this.fireDebug(" Writing Issuer... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
289 | memoryStream.Write(this.issuer, 0, this.issuer.Length);
290 | this.fireDebug(" Writing Unknown... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
291 | memoryStream.Write(this.unknown, 0, this.unknown.Length);
292 | this.fireDebug(" Writing Title Key... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
293 | memoryStream.Write(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length);
294 | this.fireDebug(" Writing Unknown2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
295 | memoryStream.WriteByte(this.unknown2);
296 | this.fireDebug(" Writing Ticket ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
297 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.ticketId)), 0, 8);
298 | this.fireDebug(" Writing Console ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
299 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.consoleId)), 0, 4);
300 | this.fireDebug(" Writing Title ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
301 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleId)), 0, 8);
302 | this.fireDebug(" Writing Unknwon3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
303 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown3)), 0, 2);
304 | this.fireDebug(" Writing NumOfDLC... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
305 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.numOfDlc)), 0, 2);
306 | this.fireDebug(" Writing Unknwon4... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
307 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown4)), 0, 8);
308 | this.fireDebug(" Writing Padding2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
309 | memoryStream.WriteByte(this.padding2);
310 | this.fireDebug(" Writing Common Key Index... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
311 | memoryStream.WriteByte(this.commonKeyIndex);
312 | this.fireDebug(" Writing Unknown5... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
313 | memoryStream.Write(this.unknown5, 0, this.unknown5.Length);
314 | this.fireDebug(" Writing Unknown6... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
315 | memoryStream.Write(this.unknown6, 0, this.unknown6.Length);
316 | this.fireDebug(" Writing Padding3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
317 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding3)), 0, 2);
318 | this.fireDebug(" Writing Enable Time Limit... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
319 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.enableTimeLimit)), 0, 4);
320 | this.fireDebug(" Writing Time Limit... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
321 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.timeLimit)), 0, 4);
322 | this.fireDebug(" Writing Padding4... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
323 | memoryStream.Write(this.padding4, 0, this.padding4.Length);
324 | byte[] array = memoryStream.ToArray();
325 | memoryStream.Dispose();
326 | if (this.fakeSign)
327 | {
328 | this.fireDebug(" Fakesigning Ticket...");
329 | byte[] numArray = new byte[20];
330 | SHA1 shA1 = SHA1.Create();
331 | for (ushort index = 0; index < ushort.MaxValue; ++index)
332 | {
333 | byte[] bytes = BitConverter.GetBytes(index);
334 | array[498] = bytes[1];
335 | array[499] = bytes[0];
336 | if (shA1.ComputeHash(array)[0] == (byte) 0)
337 | {
338 | this.fireDebug(" -> Signed ({0})", (object) index);
339 | break;
340 | }
341 | if (index == (ushort) 65534)
342 | {
343 | this.fireDebug(" -> Signing Failed...");
344 | throw new Exception("Fakesigning failed...");
345 | }
346 | }
347 | shA1.Clear();
348 | }
349 | writeStream.Seek(0L, SeekOrigin.Begin);
350 | writeStream.Write(array, 0, array.Length);
351 | this.fireDebug("Writing Ticket Finished...");
352 | }
353 |
354 | private void parseTicket(Stream ticketFile)
355 | {
356 | this.fireDebug("Parsing Ticket...");
357 | ticketFile.Seek(0L, SeekOrigin.Begin);
358 | byte[] buffer = new byte[8];
359 | this.fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
360 | ticketFile.Read(buffer, 0, 4);
361 | this.signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
362 | this.fireDebug(" Reading Signature... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
363 | ticketFile.Read(this.signature, 0, this.signature.Length);
364 | this.fireDebug(" Reading Padding... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
365 | ticketFile.Read(this.padding, 0, this.padding.Length);
366 | this.fireDebug(" Reading Issuer... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
367 | ticketFile.Read(this.issuer, 0, this.issuer.Length);
368 | this.fireDebug(" Reading Unknown... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
369 | ticketFile.Read(this.unknown, 0, this.unknown.Length);
370 | this.fireDebug(" Reading Title Key... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
371 | ticketFile.Read(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length);
372 | this.fireDebug(" Reading Unknown2... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
373 | this.unknown2 = (byte) ticketFile.ReadByte();
374 | this.fireDebug(" Reading Ticket ID.. (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
375 | ticketFile.Read(buffer, 0, 8);
376 | this.ticketId = Shared.Swap(BitConverter.ToUInt64(buffer, 0));
377 | this.fireDebug(" Reading Console ID... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
378 | ticketFile.Read(buffer, 0, 4);
379 | this.consoleId = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
380 | this.fireDebug(" Reading Title ID... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
381 | ticketFile.Read(buffer, 0, 8);
382 | this.titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0));
383 | this.fireDebug(" Reading Unknown3... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
384 | this.fireDebug(" Reading NumOfDLC... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
385 | ticketFile.Read(buffer, 0, 4);
386 | this.unknown3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0));
387 | this.numOfDlc = Shared.Swap(BitConverter.ToUInt16(buffer, 2));
388 | this.fireDebug(" Reading Unknown4... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
389 | ticketFile.Read(buffer, 0, 8);
390 | this.unknown4 = Shared.Swap(BitConverter.ToUInt64(buffer, 0));
391 | this.fireDebug(" Reading Padding2... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
392 | this.padding2 = (byte) ticketFile.ReadByte();
393 | this.fireDebug(" Reading Common Key Index... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
394 | this.commonKeyIndex = (byte) ticketFile.ReadByte();
395 | this.newKeyIndex = this.commonKeyIndex;
396 | this.fireDebug(" Reading Unknown5... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
397 | ticketFile.Read(this.unknown5, 0, this.unknown5.Length);
398 | this.fireDebug(" Reading Unknown6... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
399 | ticketFile.Read(this.unknown6, 0, this.unknown6.Length);
400 | this.fireDebug(" Reading Padding3... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
401 | ticketFile.Read(buffer, 0, 2);
402 | this.padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0));
403 | this.fireDebug(" Reading Enable Time Limit... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
404 | this.fireDebug(" Reading Time Limit... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
405 | ticketFile.Read(buffer, 0, 8);
406 | this.enableTimeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
407 | this.timeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 4));
408 | this.fireDebug(" Reading Padding4... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper());
409 | ticketFile.Read(this.padding4, 0, this.padding4.Length);
410 | this.fireDebug(" Decrypting Title Key...");
411 | this.decryptTitleKey();
412 | this.fireDebug(" -> Encrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.encryptedTitleKey));
413 | this.fireDebug(" -> Decrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.decryptedTitleKey));
414 | this.fireDebug("Parsing Ticket Finished...");
415 | }
416 |
417 | private void decryptTitleKey()
418 | {
419 | byte[] numArray = !this.dsitik ? (this.commonKeyIndex == (byte) 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey()) : CommonKey.GetDSiKey();
420 | byte[] bytes = BitConverter.GetBytes(Shared.Swap(this.titleId));
421 | Array.Resize(ref bytes, 16);
422 | RijndaelManaged rijndaelManaged = new RijndaelManaged();
423 | rijndaelManaged.Mode = CipherMode.CBC;
424 | rijndaelManaged.Padding = PaddingMode.None;
425 | rijndaelManaged.KeySize = 128;
426 | rijndaelManaged.BlockSize = 128;
427 | rijndaelManaged.Key = numArray;
428 | rijndaelManaged.IV = bytes;
429 | ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor();
430 | MemoryStream memoryStream = new MemoryStream(this.encryptedTitleKey);
431 | CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read);
432 | cryptoStream.Read(this.decryptedTitleKey, 0, this.decryptedTitleKey.Length);
433 | cryptoStream.Dispose();
434 | memoryStream.Dispose();
435 | decryptor.Dispose();
436 | rijndaelManaged.Clear();
437 | }
438 |
439 | private void encryptTitleKey()
440 | {
441 | this.commonKeyIndex = this.newKeyIndex;
442 | byte[] numArray = !this.dsitik ? (this.commonKeyIndex == (byte) 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey()) : CommonKey.GetDSiKey();
443 | byte[] bytes = BitConverter.GetBytes(Shared.Swap(this.titleId));
444 | Array.Resize(ref bytes, 16);
445 | RijndaelManaged rijndaelManaged = new RijndaelManaged();
446 | rijndaelManaged.Mode = CipherMode.CBC;
447 | rijndaelManaged.Padding = PaddingMode.None;
448 | rijndaelManaged.KeySize = 128;
449 | rijndaelManaged.BlockSize = 128;
450 | rijndaelManaged.Key = numArray;
451 | rijndaelManaged.IV = bytes;
452 | ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor();
453 | MemoryStream memoryStream = new MemoryStream(this.decryptedTitleKey);
454 | CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Read);
455 | cryptoStream.Read(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length);
456 | cryptoStream.Dispose();
457 | memoryStream.Dispose();
458 | encryptor.Dispose();
459 | rijndaelManaged.Clear();
460 | }
461 |
462 | private void reDecryptTitleKey()
463 | {
464 | this.encryptedTitleKey = this.newEncryptedTitleKey;
465 | this.decryptTitleKey();
466 | }
467 |
468 | public event EventHandler Debug;
469 |
470 | private void fireDebug(string debugMessage, params object[] args)
471 | {
472 | EventHandler debug = this.Debug;
473 | if (debug == null)
474 | return;
475 | debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
476 | }
477 | }
478 | }
479 |
--------------------------------------------------------------------------------
/libWiiSharp/TMD.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.TMD
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.IO;
10 | using System.Security.Cryptography;
11 |
12 | namespace libWiiSharp
13 | {
14 | public class TMD : IDisposable
15 | {
16 | private bool fakeSign;
17 | private uint signatureExponent = 65537;
18 | private byte[] signature = new byte[256];
19 | private byte[] padding = new byte[60];
20 | private byte[] issuer = new byte[64];
21 | private byte version;
22 | private byte caCrlVersion;
23 | private byte signerCrlVersion;
24 | private byte paddingByte;
25 | private ulong startupIos;
26 | private ulong titleId;
27 | private uint titleType;
28 | private ushort groupId;
29 | private ushort padding2;
30 | private ushort region;
31 | private byte[] reserved = new byte[58];
32 | private uint accessRights;
33 | private ushort titleVersion;
34 | private ushort numOfContents;
35 | private ushort bootIndex;
36 | private ushort padding3;
37 | private List contents;
38 | private bool isDisposed;
39 |
40 | public Region Region
41 | {
42 | get => (Region) this.region;
43 | set => this.region = (ushort) value;
44 | }
45 |
46 | public ulong StartupIOS
47 | {
48 | get => this.startupIos;
49 | set => this.startupIos = value;
50 | }
51 |
52 | public ulong TitleID
53 | {
54 | get => this.titleId;
55 | set => this.titleId = value;
56 | }
57 |
58 | public ushort TitleVersion
59 | {
60 | get => this.titleVersion;
61 | set => this.titleVersion = value;
62 | }
63 |
64 | public ushort NumOfContents => this.numOfContents;
65 |
66 | public ushort BootIndex
67 | {
68 | get => this.bootIndex;
69 | set
70 | {
71 | if ((int) value > (int) this.numOfContents)
72 | return;
73 | this.bootIndex = value;
74 | }
75 | }
76 |
77 | public TMD_Content[] Contents
78 | {
79 | get => this.contents.ToArray();
80 | set
81 | {
82 | this.contents = new List((IEnumerable) value);
83 | this.numOfContents = (ushort) value.Length;
84 | }
85 | }
86 |
87 | public bool FakeSign
88 | {
89 | get => this.fakeSign;
90 | set => this.fakeSign = value;
91 | }
92 |
93 | ~TMD() => this.Dispose(false);
94 |
95 | public void Dispose()
96 | {
97 | this.Dispose(true);
98 | GC.SuppressFinalize((object) this);
99 | }
100 |
101 | protected virtual void Dispose(bool disposing)
102 | {
103 | if (disposing && !this.isDisposed)
104 | {
105 | this.signature = (byte[]) null;
106 | this.padding = (byte[]) null;
107 | this.issuer = (byte[]) null;
108 | this.reserved = (byte[]) null;
109 | this.contents.Clear();
110 | this.contents = (List) null;
111 | }
112 | this.isDisposed = true;
113 | }
114 |
115 | public static TMD Load(string pathToTmd) => TMD.Load(File.ReadAllBytes(pathToTmd));
116 |
117 | public static TMD Load(byte[] tmdFile)
118 | {
119 | TMD tmd = new TMD();
120 | MemoryStream tmdFile1 = new MemoryStream(tmdFile);
121 | try
122 | {
123 | tmd.parseTmd((Stream) tmdFile1);
124 | }
125 | catch
126 | {
127 | tmdFile1.Dispose();
128 | throw;
129 | }
130 | tmdFile1.Dispose();
131 | return tmd;
132 | }
133 |
134 | public static TMD Load(Stream tmd)
135 | {
136 | TMD tmd1 = new TMD();
137 | tmd1.parseTmd(tmd);
138 | return tmd1;
139 | }
140 |
141 | public void LoadFile(string pathToTmd) => this.LoadFile(File.ReadAllBytes(pathToTmd));
142 |
143 | public void LoadFile(byte[] tmdFile)
144 | {
145 | MemoryStream tmdFile1 = new MemoryStream(tmdFile);
146 | try
147 | {
148 | this.parseTmd((Stream) tmdFile1);
149 | }
150 | catch
151 | {
152 | tmdFile1.Dispose();
153 | throw;
154 | }
155 | tmdFile1.Dispose();
156 | }
157 |
158 | public void LoadFile(Stream tmd) => this.parseTmd(tmd);
159 |
160 | public void Save(string savePath) => this.Save(savePath, false);
161 |
162 | public void Save(string savePath, bool fakeSign)
163 | {
164 | if (fakeSign)
165 | this.fakeSign = true;
166 | if (File.Exists(savePath))
167 | File.Delete(savePath);
168 | using (FileStream writeStream = new FileStream(savePath, FileMode.Create))
169 | this.writeToStream((Stream) writeStream);
170 | }
171 |
172 | public MemoryStream ToMemoryStream() => this.ToMemoryStream(false);
173 |
174 | public MemoryStream ToMemoryStream(bool fakeSign)
175 | {
176 | if (fakeSign)
177 | this.fakeSign = true;
178 | MemoryStream writeStream = new MemoryStream();
179 | try
180 | {
181 | this.writeToStream((Stream) writeStream);
182 | }
183 | catch
184 | {
185 | writeStream.Dispose();
186 | throw;
187 | }
188 | return writeStream;
189 | }
190 |
191 | public byte[] ToByteArray() => this.ToByteArray(false);
192 |
193 | public byte[] ToByteArray(bool fakeSign)
194 | {
195 | if (fakeSign)
196 | this.fakeSign = true;
197 | MemoryStream writeStream = new MemoryStream();
198 | try
199 | {
200 | this.writeToStream((Stream) writeStream);
201 | }
202 | catch
203 | {
204 | writeStream.Dispose();
205 | throw;
206 | }
207 | byte[] array = writeStream.ToArray();
208 | writeStream.Dispose();
209 | return array;
210 | }
211 |
212 | public void UpdateContents(string contentDir)
213 | {
214 | bool flag = true;
215 | for (int index = 0; index < this.contents.Count; ++index)
216 | {
217 | if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + this.contents[index].ContentID.ToString("x8") + ".app"))
218 | {
219 | flag = false;
220 | break;
221 | }
222 | }
223 | if (!flag)
224 | {
225 | for (int index = 0; index < this.contents.Count; ++index)
226 | {
227 | if (!File.Exists(contentDir + (object) Path.DirectorySeparatorChar + this.contents[index].ContentID.ToString("x8") + ".app"))
228 | throw new Exception("Couldn't find all content files!");
229 | }
230 | }
231 | byte[][] conts = new byte[this.contents.Count][];
232 | for (int index = 0; index < this.contents.Count; ++index)
233 | {
234 | string path = contentDir + (object) Path.DirectorySeparatorChar + (flag ? (object) this.contents[index].ContentID.ToString("x8") : (object) this.contents[index].Index.ToString("x8")) + ".app";
235 | conts[index] = File.ReadAllBytes(path);
236 | }
237 | this.updateContents(conts);
238 | }
239 |
240 | public void UpdateContents(byte[][] contents) => this.updateContents(contents);
241 |
242 | public string GetUpperTitleID()
243 | {
244 | byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint) this.titleId));
245 | return new string(new char[4]
246 | {
247 | (char) bytes[0],
248 | (char) bytes[1],
249 | (char) bytes[2],
250 | (char) bytes[3]
251 | });
252 | }
253 |
254 | public string GetNandBlocks() => this.calculateNandBlocks();
255 |
256 | public void AddContent(TMD_Content content)
257 | {
258 | this.contents.Add(content);
259 | this.numOfContents = (ushort) this.contents.Count;
260 | }
261 |
262 | public void RemoveContent(int contentIndex)
263 | {
264 | for (int index = 0; index < (int) this.numOfContents; ++index)
265 | {
266 | if ((int) this.contents[index].Index == contentIndex)
267 | {
268 | this.contents.RemoveAt(index);
269 | break;
270 | }
271 | }
272 | this.numOfContents = (ushort) this.contents.Count;
273 | }
274 |
275 | public void RemoveContentByID(int contentId)
276 | {
277 | for (int index = 0; index < (int) this.numOfContents; ++index)
278 | {
279 | if ((long) this.contents[index].ContentID == (long) contentId)
280 | {
281 | this.contents.RemoveAt(index);
282 | break;
283 | }
284 | }
285 | this.numOfContents = (ushort) this.contents.Count;
286 | }
287 |
288 | private void writeToStream(Stream writeStream)
289 | {
290 | this.fireDebug("Writing TMD...");
291 | if (this.fakeSign)
292 | {
293 | this.fireDebug(" Clearing Signature...");
294 | this.signature = new byte[256];
295 | }
296 | MemoryStream memoryStream = new MemoryStream();
297 | memoryStream.Seek(0L, SeekOrigin.Begin);
298 | this.fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
299 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.signatureExponent)), 0, 4);
300 | this.fireDebug(" Writing Signature... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
301 | memoryStream.Write(this.signature, 0, this.signature.Length);
302 | this.fireDebug(" Writing Padding... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
303 | memoryStream.Write(this.padding, 0, this.padding.Length);
304 | this.fireDebug(" Writing Issuer... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
305 | memoryStream.Write(this.issuer, 0, this.issuer.Length);
306 | this.fireDebug(" Writing Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
307 | memoryStream.WriteByte(this.version);
308 | this.fireDebug(" Writing CA Crl Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
309 | memoryStream.WriteByte(this.caCrlVersion);
310 | this.fireDebug(" Writing Signer Crl Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
311 | memoryStream.WriteByte(this.signerCrlVersion);
312 | this.fireDebug(" Writing Padding Byte... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
313 | memoryStream.WriteByte(this.paddingByte);
314 | this.fireDebug(" Writing Startup IOS... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
315 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.startupIos)), 0, 8);
316 | this.fireDebug(" Writing Title ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
317 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleId)), 0, 8);
318 | this.fireDebug(" Writing Title Type... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
319 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleType)), 0, 4);
320 | this.fireDebug(" Writing Group ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
321 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.groupId)), 0, 2);
322 | this.fireDebug(" Writing Padding2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
323 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding2)), 0, 2);
324 | this.fireDebug(" Writing Region... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
325 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.region)), 0, 2);
326 | this.fireDebug(" Writing Reserved... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
327 | memoryStream.Write(this.reserved, 0, this.reserved.Length);
328 | this.fireDebug(" Writing Access Rights... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
329 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.accessRights)), 0, 4);
330 | this.fireDebug(" Writing Title Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
331 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleVersion)), 0, 2);
332 | this.fireDebug(" Writing NumOfContents... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
333 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.numOfContents)), 0, 2);
334 | this.fireDebug(" Writing Boot Index... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
335 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.bootIndex)), 0, 2);
336 | this.fireDebug(" Writing Padding3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper());
337 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding3)), 0, 2);
338 | List contentIndicesList = new List();
339 | for (int index = 0; index < this.contents.Count; ++index)
340 | contentIndicesList.Add(new ContentIndices(index, (int) this.contents[index].Index));
341 | contentIndicesList.Sort();
342 | for (int index = 0; index < contentIndicesList.Count; ++index)
343 | {
344 | this.fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper().ToUpper(), (object) (index + 1), (object) this.numOfContents);
345 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].ContentID)), 0, 4);
346 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].Index)), 0, 2);
347 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap((ushort) this.contents[contentIndicesList[index].Index].Type)), 0, 2);
348 | memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].Size)), 0, 8);
349 | memoryStream.Write(this.contents[contentIndicesList[index].Index].Hash, 0, this.contents[contentIndicesList[index].Index].Hash.Length);
350 | }
351 | byte[] array = memoryStream.ToArray();
352 | memoryStream.Dispose();
353 | if (this.fakeSign)
354 | {
355 | this.fireDebug(" Fakesigning TMD...");
356 | byte[] numArray = new byte[20];
357 | SHA1 shA1 = SHA1.Create();
358 | for (ushort index = 0; index < ushort.MaxValue; ++index)
359 | {
360 | byte[] bytes = BitConverter.GetBytes(index);
361 | array[482] = bytes[1];
362 | array[483] = bytes[0];
363 | if (shA1.ComputeHash(array)[0] == (byte) 0)
364 | {
365 | this.fireDebug(" -> Signed ({0})", (object) index);
366 | break;
367 | }
368 | if (index == (ushort) 65534)
369 | {
370 | this.fireDebug(" -> Signing Failed...");
371 | throw new Exception("Fakesigning failed...");
372 | }
373 | }
374 | shA1.Clear();
375 | }
376 | writeStream.Seek(0L, SeekOrigin.Begin);
377 | writeStream.Write(array, 0, array.Length);
378 | this.fireDebug("Writing TMD Finished...");
379 | }
380 |
381 | private void updateContents(byte[][] conts)
382 | {
383 | SHA1 shA1 = SHA1.Create();
384 | for (int index = 0; index < this.contents.Count; ++index)
385 | {
386 | this.contents[index].Size = (ulong) conts[index].Length;
387 | this.contents[index].Hash = shA1.ComputeHash(conts[index]);
388 | }
389 | shA1.Clear();
390 | }
391 |
392 | private void parseTmd(Stream tmdFile)
393 | {
394 | this.fireDebug("Pasing TMD...");
395 | tmdFile.Seek(0L, SeekOrigin.Begin);
396 | byte[] buffer = new byte[8];
397 | this.fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
398 | tmdFile.Read(buffer, 0, 4);
399 | this.signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
400 | this.fireDebug(" Reading Signature... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
401 | tmdFile.Read(this.signature, 0, this.signature.Length);
402 | this.fireDebug(" Reading Padding... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
403 | tmdFile.Read(this.padding, 0, this.padding.Length);
404 | this.fireDebug(" Reading Issuer... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
405 | tmdFile.Read(this.issuer, 0, this.issuer.Length);
406 | this.fireDebug(" Reading Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
407 | this.fireDebug(" Reading CA Crl Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
408 | this.fireDebug(" Reading Signer Crl Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
409 | this.fireDebug(" Reading Padding Byte... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
410 | tmdFile.Read(buffer, 0, 4);
411 | this.version = buffer[0];
412 | this.caCrlVersion = buffer[1];
413 | this.signerCrlVersion = buffer[2];
414 | this.paddingByte = buffer[3];
415 | this.fireDebug(" Reading Startup IOS... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
416 | tmdFile.Read(buffer, 0, 8);
417 | this.startupIos = Shared.Swap(BitConverter.ToUInt64(buffer, 0));
418 | this.fireDebug(" Reading Title ID... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
419 | tmdFile.Read(buffer, 0, 8);
420 | this.titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0));
421 | this.fireDebug(" Reading Title Type... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
422 | tmdFile.Read(buffer, 0, 4);
423 | this.titleType = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
424 | this.fireDebug(" Reading Group ID... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
425 | tmdFile.Read(buffer, 0, 2);
426 | this.groupId = Shared.Swap(BitConverter.ToUInt16(buffer, 0));
427 | this.fireDebug(" Reading Padding2... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
428 | tmdFile.Read(buffer, 0, 2);
429 | this.padding2 = Shared.Swap(BitConverter.ToUInt16(buffer, 0));
430 | this.fireDebug(" Reading Region... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
431 | tmdFile.Read(buffer, 0, 2);
432 | this.region = Shared.Swap(BitConverter.ToUInt16(buffer, 0));
433 | this.fireDebug(" Reading Reserved... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
434 | tmdFile.Read(this.reserved, 0, this.reserved.Length);
435 | this.fireDebug(" Reading Access Rights... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
436 | tmdFile.Read(buffer, 0, 4);
437 | this.accessRights = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
438 | this.fireDebug(" Reading Title Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
439 | this.fireDebug(" Reading NumOfContents... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
440 | this.fireDebug(" Reading Boot Index... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
441 | this.fireDebug(" Reading Padding3... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper());
442 | tmdFile.Read(buffer, 0, 8);
443 | this.titleVersion = Shared.Swap(BitConverter.ToUInt16(buffer, 0));
444 | this.numOfContents = Shared.Swap(BitConverter.ToUInt16(buffer, 2));
445 | this.bootIndex = Shared.Swap(BitConverter.ToUInt16(buffer, 4));
446 | this.padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 6));
447 | this.contents = new List();
448 | for (int index = 0; index < (int) this.numOfContents; ++index)
449 | {
450 | this.fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", (object) (index + 1), (object) this.numOfContents, (object) tmdFile.Position.ToString("x8").ToUpper().ToUpper());
451 | TMD_Content tmdContent = new TMD_Content();
452 | tmdContent.Hash = new byte[20];
453 | tmdFile.Read(buffer, 0, 8);
454 | tmdContent.ContentID = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
455 | tmdContent.Index = Shared.Swap(BitConverter.ToUInt16(buffer, 4));
456 | tmdContent.Type = (ContentType) Shared.Swap(BitConverter.ToUInt16(buffer, 6));
457 | tmdFile.Read(buffer, 0, 8);
458 | tmdContent.Size = Shared.Swap(BitConverter.ToUInt64(buffer, 0));
459 | tmdFile.Read(tmdContent.Hash, 0, tmdContent.Hash.Length);
460 | this.contents.Add(tmdContent);
461 | }
462 | this.fireDebug("Pasing TMD Finished...");
463 | }
464 |
465 | private string calculateNandBlocks()
466 | {
467 | int num1 = 0;
468 | int num2 = 0;
469 | for (int index = 0; index < (int) this.numOfContents; ++index)
470 | {
471 | num2 += (int) this.contents[index].Size;
472 | if (this.contents[index].Type == ContentType.Normal)
473 | num1 += (int) this.contents[index].Size;
474 | }
475 | int num3 = (int) Math.Ceiling((double) num1 / 131072.0);
476 | int num4 = (int) Math.Ceiling((double) num2 / 131072.0);
477 | return num3 == num4 ? num4.ToString() : string.Format("{0} - {1}", (object) num3, (object) num4);
478 | }
479 |
480 | public event EventHandler Debug;
481 |
482 | private void fireDebug(string debugMessage, params object[] args)
483 | {
484 | EventHandler debug = this.Debug;
485 | if (debug == null)
486 | return;
487 | debug(new object(), new MessageEventArgs(string.Format(debugMessage, args)));
488 | }
489 | }
490 | }
491 |
--------------------------------------------------------------------------------
/libWiiSharp/Headers.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: libWiiSharp.Headers
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using System;
8 | using System.IO;
9 | using System.Security.Cryptography;
10 |
11 | namespace libWiiSharp
12 | {
13 | public class Headers
14 | {
15 | private static uint imd5Magic = 1229800501;
16 | private static uint imetMagic = 1229800788;
17 |
18 | public static Headers.HeaderType DetectHeader(string pathToFile) => Headers.DetectHeader(File.ReadAllBytes(pathToFile));
19 |
20 | public static Headers.HeaderType DetectHeader(byte[] file)
21 | {
22 | if (file.Length > 68 && (int) Shared.Swap(BitConverter.ToUInt32(file, 64)) == (int) Headers.imetMagic)
23 | return Headers.HeaderType.ShortIMET;
24 | if (file.Length > 132 && (int) Shared.Swap(BitConverter.ToUInt32(file, 128)) == (int) Headers.imetMagic)
25 | return Headers.HeaderType.IMET;
26 | return file.Length > 4 && (int) Shared.Swap(BitConverter.ToUInt32(file, 0)) == (int) Headers.imd5Magic ? Headers.HeaderType.IMD5 : Headers.HeaderType.None;
27 | }
28 |
29 | public static Headers.HeaderType DetectHeader(Stream file)
30 | {
31 | byte[] buffer = new byte[4];
32 | if (file.Length > 68L)
33 | {
34 | file.Seek(64L, SeekOrigin.Begin);
35 | file.Read(buffer, 0, buffer.Length);
36 | if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imetMagic)
37 | return Headers.HeaderType.ShortIMET;
38 | }
39 | if (file.Length > 132L)
40 | {
41 | file.Seek(128L, SeekOrigin.Begin);
42 | file.Read(buffer, 0, buffer.Length);
43 | if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imetMagic)
44 | return Headers.HeaderType.IMET;
45 | }
46 | if (file.Length > 4L)
47 | {
48 | file.Seek(0L, SeekOrigin.Begin);
49 | file.Read(buffer, 0, buffer.Length);
50 | if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imd5Magic)
51 | return Headers.HeaderType.IMD5;
52 | }
53 | return Headers.HeaderType.None;
54 | }
55 |
56 | public enum HeaderType
57 | {
58 | None = 0,
59 | IMD5 = 32, // 0x00000020
60 | ShortIMET = 1536, // 0x00000600
61 | IMET = 1600, // 0x00000640
62 | }
63 |
64 | public class IMET
65 | {
66 | private bool hashesMatch = true;
67 | private bool isShortImet;
68 | private byte[] additionalPadding = new byte[64];
69 | private byte[] padding = new byte[64];
70 | private uint imetMagic = 1229800788;
71 | private uint sizeOfHeader = 1536;
72 | private uint unknown = 3;
73 | private uint iconSize;
74 | private uint bannerSize;
75 | private uint soundSize;
76 | private uint flags;
77 | private byte[] japaneseTitle = new byte[84];
78 | private byte[] englishTitle = new byte[84];
79 | private byte[] germanTitle = new byte[84];
80 | private byte[] frenchTitle = new byte[84];
81 | private byte[] spanishTitle = new byte[84];
82 | private byte[] italianTitle = new byte[84];
83 | private byte[] dutchTitle = new byte[84];
84 | private byte[] unknownTitle1 = new byte[84];
85 | private byte[] unknownTitle2 = new byte[84];
86 | private byte[] koreanTitle = new byte[84];
87 | private byte[] padding2 = new byte[588];
88 | private byte[] hash = new byte[16];
89 |
90 | public bool IsShortIMET
91 | {
92 | get => this.isShortImet;
93 | set => this.isShortImet = value;
94 | }
95 |
96 | public uint IconSize
97 | {
98 | get => this.iconSize;
99 | set => this.iconSize = value;
100 | }
101 |
102 | public uint BannerSize
103 | {
104 | get => this.bannerSize;
105 | set => this.bannerSize = value;
106 | }
107 |
108 | public uint SoundSize
109 | {
110 | get => this.soundSize;
111 | set => this.soundSize = value;
112 | }
113 |
114 | public string JapaneseTitle
115 | {
116 | get => this.returnTitleAsString(this.japaneseTitle);
117 | set => this.setTitleFromString(value, 0);
118 | }
119 |
120 | public string EnglishTitle
121 | {
122 | get => this.returnTitleAsString(this.englishTitle);
123 | set => this.setTitleFromString(value, 1);
124 | }
125 |
126 | public string GermanTitle
127 | {
128 | get => this.returnTitleAsString(this.germanTitle);
129 | set => this.setTitleFromString(value, 2);
130 | }
131 |
132 | public string FrenchTitle
133 | {
134 | get => this.returnTitleAsString(this.frenchTitle);
135 | set => this.setTitleFromString(value, 3);
136 | }
137 |
138 | public string SpanishTitle
139 | {
140 | get => this.returnTitleAsString(this.spanishTitle);
141 | set => this.setTitleFromString(value, 4);
142 | }
143 |
144 | public string ItalianTitle
145 | {
146 | get => this.returnTitleAsString(this.italianTitle);
147 | set => this.setTitleFromString(value, 5);
148 | }
149 |
150 | public string DutchTitle
151 | {
152 | get => this.returnTitleAsString(this.dutchTitle);
153 | set => this.setTitleFromString(value, 6);
154 | }
155 |
156 | public string KoreanTitle
157 | {
158 | get => this.returnTitleAsString(this.koreanTitle);
159 | set => this.setTitleFromString(value, 7);
160 | }
161 |
162 | public string[] AllTitles => new string[8]
163 | {
164 | this.JapaneseTitle,
165 | this.EnglishTitle,
166 | this.GermanTitle,
167 | this.FrenchTitle,
168 | this.SpanishTitle,
169 | this.ItalianTitle,
170 | this.DutchTitle,
171 | this.KoreanTitle
172 | };
173 |
174 | public bool HashesMatch => this.hashesMatch;
175 |
176 | public static Headers.IMET Load(string pathToFile) => Headers.IMET.Load(File.ReadAllBytes(pathToFile));
177 |
178 | public static Headers.IMET Load(byte[] fileOrHeader)
179 | {
180 | Headers.HeaderType headerType = Headers.DetectHeader(fileOrHeader);
181 | switch (headerType)
182 | {
183 | case Headers.HeaderType.ShortIMET:
184 | case Headers.HeaderType.IMET:
185 | Headers.IMET imet = new Headers.IMET();
186 | if (headerType == Headers.HeaderType.ShortIMET)
187 | imet.isShortImet = true;
188 | MemoryStream headerStream = new MemoryStream(fileOrHeader);
189 | try
190 | {
191 | imet.parseHeader((Stream) headerStream);
192 | }
193 | catch
194 | {
195 | headerStream.Dispose();
196 | throw;
197 | }
198 | headerStream.Dispose();
199 | return imet;
200 | default:
201 | throw new Exception("No IMET Header found!");
202 | }
203 | }
204 |
205 | public static Headers.IMET Load(Stream fileOrHeader)
206 | {
207 | Headers.HeaderType headerType = Headers.DetectHeader(fileOrHeader);
208 | switch (headerType)
209 | {
210 | case Headers.HeaderType.ShortIMET:
211 | case Headers.HeaderType.IMET:
212 | Headers.IMET imet = new Headers.IMET();
213 | if (headerType == Headers.HeaderType.ShortIMET)
214 | imet.isShortImet = true;
215 | imet.parseHeader(fileOrHeader);
216 | return imet;
217 | default:
218 | throw new Exception("No IMET Header found!");
219 | }
220 | }
221 |
222 | public static Headers.IMET Create(
223 | bool isShortImet,
224 | int iconSize,
225 | int bannerSize,
226 | int soundSize,
227 | params string[] titles)
228 | {
229 | Headers.IMET imet = new Headers.IMET();
230 | imet.isShortImet = isShortImet;
231 | for (int titleIndex = 0; titleIndex < titles.Length; ++titleIndex)
232 | imet.setTitleFromString(titles[titleIndex], titleIndex);
233 | for (int length = titles.Length; length < 8; ++length)
234 | imet.setTitleFromString(titles.Length > 1 ? titles[1] : titles[0], length);
235 | imet.iconSize = (uint) iconSize;
236 | imet.bannerSize = (uint) bannerSize;
237 | imet.soundSize = (uint) soundSize;
238 | return imet;
239 | }
240 |
241 | public static void RemoveHeader(string pathToFile)
242 | {
243 | byte[] bytes = Headers.IMET.RemoveHeader(File.ReadAllBytes(pathToFile));
244 | File.Delete(pathToFile);
245 | File.WriteAllBytes(pathToFile, bytes);
246 | }
247 |
248 | public static byte[] RemoveHeader(byte[] file)
249 | {
250 | Headers.HeaderType sourceIndex = Headers.DetectHeader(file);
251 | switch (sourceIndex)
252 | {
253 | case Headers.HeaderType.ShortIMET:
254 | case Headers.HeaderType.IMET:
255 | byte[] destinationArray = new byte[(int) (file.Length - sourceIndex)];
256 | Array.Copy((Array) file, (int) sourceIndex, (Array) destinationArray, 0, destinationArray.Length);
257 | return destinationArray;
258 | default:
259 | throw new Exception("No IMET Header found!");
260 | }
261 | }
262 |
263 | public void SetAllTitles(string newTitle)
264 | {
265 | for (int titleIndex = 0; titleIndex < 10; ++titleIndex)
266 | this.setTitleFromString(newTitle, titleIndex);
267 | }
268 |
269 | public MemoryStream ToMemoryStream()
270 | {
271 | MemoryStream writeStream = new MemoryStream();
272 | try
273 | {
274 | this.writeToStream((Stream) writeStream);
275 | }
276 | catch
277 | {
278 | writeStream.Dispose();
279 | throw;
280 | }
281 | return writeStream;
282 | }
283 |
284 | public byte[] ToByteArray() => this.ToMemoryStream().ToArray();
285 |
286 | public void Write(Stream writeStream) => this.writeToStream(writeStream);
287 |
288 | public void ChangeTitles(params string[] newTitles)
289 | {
290 | for (int titleIndex = 0; titleIndex < newTitles.Length; ++titleIndex)
291 | this.setTitleFromString(newTitles[titleIndex], titleIndex);
292 | for (int length = newTitles.Length; length < 8; ++length)
293 | this.setTitleFromString(newTitles.Length > 1 ? newTitles[1] : newTitles[0], length);
294 | }
295 |
296 | public string[] GetTitles() => new string[8]
297 | {
298 | this.JapaneseTitle,
299 | this.EnglishTitle,
300 | this.GermanTitle,
301 | this.FrenchTitle,
302 | this.SpanishTitle,
303 | this.ItalianTitle,
304 | this.DutchTitle,
305 | this.KoreanTitle
306 | };
307 |
308 | private void writeToStream(Stream writeStream)
309 | {
310 | writeStream.Seek(0L, SeekOrigin.Begin);
311 | if (!this.isShortImet)
312 | writeStream.Write(this.additionalPadding, 0, this.additionalPadding.Length);
313 | writeStream.Write(this.padding, 0, this.padding.Length);
314 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.imetMagic)), 0, 4);
315 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.sizeOfHeader)), 0, 4);
316 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown)), 0, 4);
317 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.iconSize)), 0, 4);
318 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.bannerSize)), 0, 4);
319 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.soundSize)), 0, 4);
320 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.flags)), 0, 4);
321 | writeStream.Write(this.japaneseTitle, 0, this.japaneseTitle.Length);
322 | writeStream.Write(this.englishTitle, 0, this.englishTitle.Length);
323 | writeStream.Write(this.germanTitle, 0, this.germanTitle.Length);
324 | writeStream.Write(this.frenchTitle, 0, this.frenchTitle.Length);
325 | writeStream.Write(this.spanishTitle, 0, this.spanishTitle.Length);
326 | writeStream.Write(this.italianTitle, 0, this.italianTitle.Length);
327 | writeStream.Write(this.dutchTitle, 0, this.dutchTitle.Length);
328 | writeStream.Write(this.unknownTitle1, 0, this.unknownTitle1.Length);
329 | writeStream.Write(this.unknownTitle2, 0, this.unknownTitle2.Length);
330 | writeStream.Write(this.koreanTitle, 0, this.koreanTitle.Length);
331 | writeStream.Write(this.padding2, 0, this.padding2.Length);
332 | int position = (int) writeStream.Position;
333 | this.hash = new byte[16];
334 | writeStream.Write(this.hash, 0, this.hash.Length);
335 | byte[] numArray = new byte[writeStream.Position];
336 | writeStream.Seek(0L, SeekOrigin.Begin);
337 | writeStream.Read(numArray, 0, numArray.Length);
338 | this.computeHash(numArray, this.isShortImet ? 0 : 64);
339 | writeStream.Seek((long) position, SeekOrigin.Begin);
340 | writeStream.Write(this.hash, 0, this.hash.Length);
341 | }
342 |
343 | private void computeHash(byte[] headerBytes, int hashPos)
344 | {
345 | MD5 md5 = MD5.Create();
346 | this.hash = md5.ComputeHash(headerBytes, hashPos, 1536);
347 | md5.Clear();
348 | }
349 |
350 | private void parseHeader(Stream headerStream)
351 | {
352 | headerStream.Seek(0L, SeekOrigin.Begin);
353 | byte[] buffer1 = new byte[4];
354 | if (!this.isShortImet)
355 | headerStream.Read(this.additionalPadding, 0, this.additionalPadding.Length);
356 | headerStream.Read(this.padding, 0, this.padding.Length);
357 | headerStream.Read(buffer1, 0, 4);
358 | if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.imetMagic)
359 | throw new Exception("Invalid Magic!");
360 | headerStream.Read(buffer1, 0, 4);
361 | if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.sizeOfHeader)
362 | throw new Exception("Invalid Header Size!");
363 | headerStream.Read(buffer1, 0, 4);
364 | this.unknown = Shared.Swap(BitConverter.ToUInt32(buffer1, 0));
365 | headerStream.Read(buffer1, 0, 4);
366 | this.iconSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0));
367 | headerStream.Read(buffer1, 0, 4);
368 | this.bannerSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0));
369 | headerStream.Read(buffer1, 0, 4);
370 | this.soundSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0));
371 | headerStream.Read(buffer1, 0, 4);
372 | this.flags = Shared.Swap(BitConverter.ToUInt32(buffer1, 0));
373 | headerStream.Read(this.japaneseTitle, 0, this.japaneseTitle.Length);
374 | headerStream.Read(this.englishTitle, 0, this.englishTitle.Length);
375 | headerStream.Read(this.germanTitle, 0, this.germanTitle.Length);
376 | headerStream.Read(this.frenchTitle, 0, this.frenchTitle.Length);
377 | headerStream.Read(this.spanishTitle, 0, this.spanishTitle.Length);
378 | headerStream.Read(this.italianTitle, 0, this.italianTitle.Length);
379 | headerStream.Read(this.dutchTitle, 0, this.dutchTitle.Length);
380 | headerStream.Read(this.unknownTitle1, 0, this.unknownTitle1.Length);
381 | headerStream.Read(this.unknownTitle2, 0, this.unknownTitle2.Length);
382 | headerStream.Read(this.koreanTitle, 0, this.koreanTitle.Length);
383 | headerStream.Read(this.padding2, 0, this.padding2.Length);
384 | headerStream.Read(this.hash, 0, this.hash.Length);
385 | headerStream.Seek(-16L, SeekOrigin.Current);
386 | headerStream.Write(new byte[16], 0, 16);
387 | byte[] buffer2 = new byte[headerStream.Length];
388 | headerStream.Seek(0L, SeekOrigin.Begin);
389 | headerStream.Read(buffer2, 0, buffer2.Length);
390 | MD5 md5 = MD5.Create();
391 | byte[] hash = md5.ComputeHash(buffer2, this.isShortImet ? 0 : 64, 1536);
392 | md5.Clear();
393 | this.hashesMatch = Shared.CompareByteArrays(hash, this.hash);
394 | }
395 |
396 | private string returnTitleAsString(byte[] title)
397 | {
398 | string empty = string.Empty;
399 | for (int index = 0; index < 84; index += 2)
400 | {
401 | char ch = BitConverter.ToChar(new byte[2]
402 | {
403 | title[index + 1],
404 | title[index]
405 | }, 0);
406 | if (ch != char.MinValue)
407 | empty += (string) (object) ch;
408 | }
409 | return empty;
410 | }
411 |
412 | private void setTitleFromString(string title, int titleIndex)
413 | {
414 | byte[] numArray = new byte[84];
415 | for (int index = 0; index < title.Length; ++index)
416 | {
417 | byte[] bytes = BitConverter.GetBytes(title[index]);
418 | numArray[index * 2 + 1] = bytes[0];
419 | numArray[index * 2] = bytes[1];
420 | }
421 | switch (titleIndex)
422 | {
423 | case 0:
424 | this.japaneseTitle = numArray;
425 | break;
426 | case 1:
427 | this.englishTitle = numArray;
428 | break;
429 | case 2:
430 | this.germanTitle = numArray;
431 | break;
432 | case 3:
433 | this.frenchTitle = numArray;
434 | break;
435 | case 4:
436 | this.spanishTitle = numArray;
437 | break;
438 | case 5:
439 | this.italianTitle = numArray;
440 | break;
441 | case 6:
442 | this.dutchTitle = numArray;
443 | break;
444 | case 7:
445 | this.koreanTitle = numArray;
446 | break;
447 | }
448 | }
449 | }
450 |
451 | public class IMD5
452 | {
453 | private uint imd5Magic = 1229800501;
454 | private uint fileSize;
455 | private byte[] padding = new byte[8];
456 | private byte[] hash = new byte[16];
457 |
458 | public uint FileSize => this.fileSize;
459 |
460 | public byte[] Hash => this.hash;
461 |
462 | private IMD5()
463 | {
464 | }
465 |
466 | public static Headers.IMD5 Load(string pathToFile) => Headers.IMD5.Load(File.ReadAllBytes(pathToFile));
467 |
468 | public static Headers.IMD5 Load(byte[] fileOrHeader)
469 | {
470 | if (Headers.DetectHeader(fileOrHeader) != Headers.HeaderType.IMD5)
471 | throw new Exception("No IMD5 Header found!");
472 | Headers.IMD5 imD5 = new Headers.IMD5();
473 | MemoryStream headerStream = new MemoryStream(fileOrHeader);
474 | try
475 | {
476 | imD5.parseHeader((Stream) headerStream);
477 | }
478 | catch
479 | {
480 | headerStream.Dispose();
481 | throw;
482 | }
483 | headerStream.Dispose();
484 | return imD5;
485 | }
486 |
487 | public static Headers.IMD5 Load(Stream fileOrHeader)
488 | {
489 | if (Headers.DetectHeader(fileOrHeader) != Headers.HeaderType.IMD5)
490 | throw new Exception("No IMD5 Header found!");
491 | Headers.IMD5 imD5 = new Headers.IMD5();
492 | imD5.parseHeader(fileOrHeader);
493 | return imD5;
494 | }
495 |
496 | public static Headers.IMD5 Create(byte[] file)
497 | {
498 | Headers.IMD5 imD5 = new Headers.IMD5();
499 | imD5.fileSize = (uint) file.Length;
500 | imD5.computeHash(file);
501 | return imD5;
502 | }
503 |
504 | public static void AddHeader(string pathToFile)
505 | {
506 | byte[] buffer = Headers.IMD5.AddHeader(File.ReadAllBytes(pathToFile));
507 | File.Delete(pathToFile);
508 | using (FileStream fileStream = new FileStream(pathToFile, FileMode.Create))
509 | fileStream.Write(buffer, 0, buffer.Length);
510 | }
511 |
512 | public static byte[] AddHeader(byte[] file)
513 | {
514 | Headers.IMD5 imD5 = Headers.IMD5.Create(file);
515 | MemoryStream writeStream = new MemoryStream();
516 | imD5.writeToStream((Stream) writeStream);
517 | writeStream.Write(file, 0, file.Length);
518 | byte[] array = writeStream.ToArray();
519 | writeStream.Dispose();
520 | return array;
521 | }
522 |
523 | public static void RemoveHeader(string pathToFile)
524 | {
525 | byte[] buffer = Headers.IMD5.RemoveHeader(File.ReadAllBytes(pathToFile));
526 | File.Delete(pathToFile);
527 | using (FileStream fileStream = new FileStream(pathToFile, FileMode.Create))
528 | fileStream.Write(buffer, 0, buffer.Length);
529 | }
530 |
531 | public static byte[] RemoveHeader(byte[] file)
532 | {
533 | MemoryStream memoryStream = new MemoryStream();
534 | memoryStream.Write(file, 32, file.Length - 32);
535 | byte[] array = memoryStream.ToArray();
536 | memoryStream.Dispose();
537 | return array;
538 | }
539 |
540 | public MemoryStream ToMemoryStream()
541 | {
542 | MemoryStream writeStream = new MemoryStream();
543 | try
544 | {
545 | this.writeToStream((Stream) writeStream);
546 | }
547 | catch
548 | {
549 | writeStream.Dispose();
550 | throw;
551 | }
552 | return writeStream;
553 | }
554 |
555 | public byte[] ToByteArray() => this.ToMemoryStream().ToArray();
556 |
557 | public void Write(Stream writeStream) => this.writeToStream(writeStream);
558 |
559 | private void writeToStream(Stream writeStream)
560 | {
561 | writeStream.Seek(0L, SeekOrigin.Begin);
562 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.imd5Magic)), 0, 4);
563 | writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.fileSize)), 0, 4);
564 | writeStream.Write(this.padding, 0, this.padding.Length);
565 | writeStream.Write(this.hash, 0, this.hash.Length);
566 | }
567 |
568 | private void computeHash(byte[] bytesToHash)
569 | {
570 | MD5 md5 = MD5.Create();
571 | this.hash = md5.ComputeHash(bytesToHash);
572 | md5.Clear();
573 | }
574 |
575 | private void parseHeader(Stream headerStream)
576 | {
577 | headerStream.Seek(0L, SeekOrigin.Begin);
578 | byte[] buffer = new byte[4];
579 | headerStream.Read(buffer, 0, 4);
580 | if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) this.imd5Magic)
581 | throw new Exception("Invalid Magic!");
582 | headerStream.Read(buffer, 0, 4);
583 | this.fileSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0));
584 | headerStream.Read(this.padding, 0, this.padding.Length);
585 | headerStream.Read(this.hash, 0, this.hash.Length);
586 | }
587 | }
588 | }
589 | }
590 |
--------------------------------------------------------------------------------
/NUS_Downloader/Database.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: NUS_Downloader.Database
3 | // Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
4 | // MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
5 | // Assembly location: C:\dotpeek\NUS Downloader.exe
6 |
7 | using NUS_Downloader.Properties;
8 | using System;
9 | using System.Drawing;
10 | using System.IO;
11 | using System.Windows.Forms;
12 | using System.Xml;
13 |
14 | namespace NUS_Downloader
15 | {
16 | internal class Database
17 | {
18 | private string SystemTag = "SYS";
19 | private string IosTag = "IOS";
20 | private string VcTag = "VC";
21 | private string WwTag = "WW";
22 | private string UpdateTag = "UPD";
23 | private string DSiSystemTag = "DSISYSTEM";
24 | private string DSiWareTag = "DSIWARE";
25 | private string[] VcConsoles = new string[11]
26 | {
27 | "C64",
28 | "GEN",
29 | "MSX",
30 | "N64",
31 | "NEO",
32 | "NES",
33 | "SMS",
34 | "SNES",
35 | "TG16",
36 | "TGCD",
37 | "ARC"
38 | };
39 | private string databaseString;
40 | public static Image green = (Image) Resources.bullet_green;
41 | public static Image orange = (Image) Resources.bullet_orange;
42 | public static Image redgreen = (Image) Resources.bullet_redgreen;
43 | public static Image redorange = (Image) Resources.bullet_redorange;
44 | public static Image green_blue = (Image) Resources.bullet_green_blue;
45 | public static Image orange_blue = (Image) Resources.bullet_orange_blue;
46 | public static Image redgreen_blue = (Image) Resources.bullet_redgreen_blue;
47 | public static Image redorange_blue = (Image) Resources.bullet_redorange_blue;
48 |
49 | 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");
50 |
51 | public string GetDatabaseVersion()
52 | {
53 | if (this.databaseString.Length < 1)
54 | throw new Exception("Load the database into a memory stream first!");
55 | XmlDocument xmlDocument = new XmlDocument();
56 | xmlDocument.LoadXml(this.databaseString);
57 | return xmlDocument.GetElementsByTagName("database")[0].Attributes[0].Value;
58 | }
59 |
60 | public static string GetDatabaseVersion(string databaseString)
61 | {
62 | XmlDocument xmlDocument = new XmlDocument();
63 | xmlDocument.LoadXml(databaseString);
64 | return xmlDocument.GetElementsByTagName("database")[0].Attributes[0].Value;
65 | }
66 |
67 | public ToolStripMenuItem[] LoadSystemTitles()
68 | {
69 | if (this.databaseString.Length < 1)
70 | throw new Exception("Load the database into a memory stream first!");
71 | XmlDocument xmlDocument = new XmlDocument();
72 | xmlDocument.LoadXml(this.databaseString);
73 | XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.SystemTag);
74 | ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count];
75 | for (int i1 = 0; i1 < elementsByTagName.Count; ++i1)
76 | {
77 | ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
78 | XmlAttributeCollection attributes = elementsByTagName[i1].Attributes;
79 | string str1 = "";
80 | string str2 = "";
81 | bool danger = false;
82 | bool ticket = true;
83 | XmlNodeList childNodes = elementsByTagName[i1].ChildNodes;
84 | for (int i2 = 0; i2 < childNodes.Count; ++i2)
85 | {
86 | switch (childNodes[i2].Name)
87 | {
88 | case "name":
89 | str2 = childNodes[i2].InnerText;
90 | break;
91 | case "titleID":
92 | str1 = childNodes[i2].InnerText;
93 | break;
94 | case "version":
95 | string[] strArray1 = childNodes[i2].InnerText.Split(',');
96 | if (toolStripMenuItem.DropDownItems.Count > 0)
97 | {
98 | for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1)
99 | {
100 | if (childNodes[i2].InnerText != "")
101 | {
102 | ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1];
103 | dropDownItem.DropDownItems.Add("Latest Version");
104 | for (int index2 = 0; index2 < strArray1.Length; ++index2)
105 | dropDownItem.DropDownItems.Add("v" + strArray1[index2]);
106 | }
107 | }
108 | break;
109 | }
110 | toolStripMenuItem.DropDownItems.Add("Latest Version");
111 | if (childNodes[i2].InnerText != "")
112 | {
113 | for (int index = 0; index < strArray1.Length; ++index)
114 | toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]);
115 | break;
116 | }
117 | break;
118 | case "region":
119 | string[] strArray2 = childNodes[i2].InnerText.Split(',');
120 | if (childNodes[i2].InnerText != "")
121 | {
122 | for (int index = 0; index < strArray2.Length; ++index)
123 | toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index])));
124 | break;
125 | }
126 | break;
127 | case "ticket":
128 | ticket = Convert.ToBoolean(childNodes[i2].InnerText);
129 | break;
130 | case "danger":
131 | danger = true;
132 | toolStripMenuItem.ToolTipText = childNodes[i2].InnerText;
133 | break;
134 | }
135 | toolStripMenuItem.Image = this.SelectItemImage(ticket, danger);
136 | if (str1 != "")
137 | toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2);
138 | else
139 | toolStripMenuItem.Text = str2;
140 | }
141 | toolStripMenuItemArray[i1] = toolStripMenuItem;
142 | }
143 | return toolStripMenuItemArray;
144 | }
145 |
146 | public ToolStripMenuItem[] LoadIosTitles()
147 | {
148 | if (this.databaseString.Length < 1)
149 | throw new Exception("Load the database into a memory stream first!");
150 | XmlDocument xmlDocument = new XmlDocument();
151 | xmlDocument.LoadXml(this.databaseString);
152 | XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.IosTag);
153 | ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count];
154 | for (int i1 = 0; i1 < elementsByTagName.Count; ++i1)
155 | {
156 | ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
157 | XmlAttributeCollection attributes = elementsByTagName[i1].Attributes;
158 | string str1 = "";
159 | string str2 = "";
160 | bool danger = false;
161 | bool ticket = true;
162 | XmlNodeList childNodes = elementsByTagName[i1].ChildNodes;
163 | for (int i2 = 0; i2 < childNodes.Count; ++i2)
164 | {
165 | switch (childNodes[i2].Name)
166 | {
167 | case "name":
168 | str2 = childNodes[i2].InnerText;
169 | break;
170 | case "titleID":
171 | str1 = childNodes[i2].InnerText;
172 | break;
173 | case "version":
174 | string[] strArray = childNodes[i2].InnerText.Split(',');
175 | toolStripMenuItem.DropDownItems.Add("Latest Version");
176 | if (childNodes[i2].InnerText != "")
177 | {
178 | for (int index = 0; index < strArray.Length; ++index)
179 | toolStripMenuItem.DropDownItems.Add("v" + strArray[index]);
180 | break;
181 | }
182 | break;
183 | case "ticket":
184 | ticket = Convert.ToBoolean(childNodes[i2].InnerText);
185 | break;
186 | case "danger":
187 | danger = true;
188 | toolStripMenuItem.ToolTipText = childNodes[i2].InnerText;
189 | break;
190 | }
191 | toolStripMenuItem.Image = this.SelectItemImage(ticket, danger);
192 | if (str1 != "")
193 | toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2);
194 | else
195 | toolStripMenuItem.Text = str2;
196 | }
197 | toolStripMenuItemArray[i1] = toolStripMenuItem;
198 | }
199 | return toolStripMenuItemArray;
200 | }
201 |
202 | public ToolStripMenuItem[][] LoadVirtualConsoleTitles()
203 | {
204 | if (this.databaseString.Length < 1)
205 | throw new Exception("Load the database into a memory stream first!");
206 | XmlDocument xmlDocument = new XmlDocument();
207 | xmlDocument.LoadXml(this.databaseString);
208 | XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.VcTag);
209 | ToolStripMenuItem[][] toolStripMenuItemArray = new ToolStripMenuItem[this.VcConsoles.Length][];
210 | for (int index = 0; index < toolStripMenuItemArray.Length; ++index)
211 | toolStripMenuItemArray[index] = new ToolStripMenuItem[0];
212 | for (int i1 = 0; i1 < elementsByTagName.Count; ++i1)
213 | {
214 | ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
215 | XmlAttributeCollection attributes = elementsByTagName[i1].Attributes;
216 | string str1 = "";
217 | string str2 = "";
218 | bool danger = false;
219 | bool ticket = true;
220 | XmlNodeList childNodes = elementsByTagName[i1].ChildNodes;
221 | for (int i2 = 0; i2 < childNodes.Count; ++i2)
222 | {
223 | switch (childNodes[i2].Name)
224 | {
225 | case "name":
226 | str2 = childNodes[i2].InnerText;
227 | break;
228 | case "titleID":
229 | str1 = childNodes[i2].InnerText;
230 | break;
231 | case "version":
232 | string[] strArray1 = childNodes[i2].InnerText.Split(',');
233 | if (toolStripMenuItem.DropDownItems.Count > 0)
234 | {
235 | for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1)
236 | {
237 | if (childNodes[i2].InnerText != "")
238 | {
239 | ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1];
240 | dropDownItem.DropDownItems.Add("Latest Version");
241 | for (int index2 = 0; index2 < strArray1.Length; ++index2)
242 | dropDownItem.DropDownItems.Add("v" + strArray1[index2]);
243 | }
244 | }
245 | break;
246 | }
247 | toolStripMenuItem.DropDownItems.Add("Latest Version");
248 | if (childNodes[i2].InnerText != "")
249 | {
250 | for (int index = 0; index < strArray1.Length; ++index)
251 | toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]);
252 | break;
253 | }
254 | break;
255 | case "region":
256 | string[] strArray2 = childNodes[i2].InnerText.Split(',');
257 | if (childNodes[i2].InnerText != "")
258 | {
259 | for (int index = 0; index < strArray2.Length; ++index)
260 | toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index])));
261 | break;
262 | }
263 | break;
264 | case "ticket":
265 | ticket = Convert.ToBoolean(childNodes[i2].InnerText);
266 | break;
267 | case "danger":
268 | danger = true;
269 | toolStripMenuItem.ToolTipText = childNodes[i2].InnerText;
270 | break;
271 | }
272 | toolStripMenuItem.Image = this.SelectItemImage(ticket, danger);
273 | if (str1 != "")
274 | toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2);
275 | else
276 | toolStripMenuItem.Text = str2;
277 | }
278 | for (int index = 0; index < this.VcConsoles.Length; ++index)
279 | {
280 | if (attributes[0].Value == this.VcConsoles[index])
281 | {
282 | Array.Resize(ref toolStripMenuItemArray[index], toolStripMenuItemArray[index].Length + 1);
283 | toolStripMenuItemArray[index][toolStripMenuItemArray[index].Length - 1] = toolStripMenuItem;
284 | }
285 | }
286 | }
287 | return toolStripMenuItemArray;
288 | }
289 |
290 | public ToolStripMenuItem[] LoadWiiWareTitles()
291 | {
292 | if (this.databaseString.Length < 1)
293 | throw new Exception("Load the database into a memory stream first!");
294 | XmlDocument xmlDocument = new XmlDocument();
295 | xmlDocument.LoadXml(this.databaseString);
296 | XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.WwTag);
297 | ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count];
298 | for (int i1 = 0; i1 < elementsByTagName.Count; ++i1)
299 | {
300 | ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
301 | XmlAttributeCollection attributes = elementsByTagName[i1].Attributes;
302 | string str1 = "";
303 | string str2 = "";
304 | bool danger = false;
305 | bool ticket = true;
306 | XmlNodeList childNodes = elementsByTagName[i1].ChildNodes;
307 | for (int i2 = 0; i2 < childNodes.Count; ++i2)
308 | {
309 | switch (childNodes[i2].Name)
310 | {
311 | case "name":
312 | str2 = childNodes[i2].InnerText;
313 | break;
314 | case "titleID":
315 | str1 = childNodes[i2].InnerText;
316 | break;
317 | case "version":
318 | string[] strArray1 = childNodes[i2].InnerText.Split(',');
319 | if (toolStripMenuItem.DropDownItems.Count > 0)
320 | {
321 | for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1)
322 | {
323 | if (childNodes[i2].InnerText != "")
324 | {
325 | ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1];
326 | dropDownItem.DropDownItems.Add("Latest Version");
327 | for (int index2 = 0; index2 < strArray1.Length; ++index2)
328 | dropDownItem.DropDownItems.Add("v" + strArray1[index2]);
329 | }
330 | }
331 | break;
332 | }
333 | toolStripMenuItem.DropDownItems.Add("Latest Version");
334 | if (childNodes[i2].InnerText != "")
335 | {
336 | for (int index = 0; index < strArray1.Length; ++index)
337 | toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]);
338 | break;
339 | }
340 | break;
341 | case "region":
342 | string[] strArray2 = childNodes[i2].InnerText.Split(',');
343 | if (childNodes[i2].InnerText != "")
344 | {
345 | for (int index = 0; index < strArray2.Length; ++index)
346 | toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index])));
347 | break;
348 | }
349 | break;
350 | case "ticket":
351 | ticket = Convert.ToBoolean(childNodes[i2].InnerText);
352 | break;
353 | case "danger":
354 | danger = true;
355 | toolStripMenuItem.ToolTipText = childNodes[i2].InnerText;
356 | break;
357 | }
358 | toolStripMenuItem.Image = this.SelectItemImage(ticket, danger);
359 | if (str1 != "")
360 | toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2);
361 | else
362 | toolStripMenuItem.Text = str2;
363 | }
364 | toolStripMenuItemArray[i1] = toolStripMenuItem;
365 | }
366 | return toolStripMenuItemArray;
367 | }
368 |
369 | private string RegionFromIndex(int index)
370 | {
371 | if (this.databaseString.Length < 1)
372 | throw new Exception("Load the database into a memory stream first!");
373 | XmlDocument xmlDocument = new XmlDocument();
374 | xmlDocument.LoadXml(this.databaseString);
375 | XmlNodeList childNodes = xmlDocument.GetElementsByTagName("REGIONS")[0].ChildNodes;
376 | for (int i = 0; i < childNodes.Count; ++i)
377 | {
378 | if (Convert.ToInt32(childNodes[i].Attributes[0].Value) == index)
379 | return childNodes[i].InnerText;
380 | }
381 | return "XX (Error)";
382 | }
383 |
384 | private Image SelectItemImage(bool ticket, bool danger)
385 | {
386 | if (ticket && !danger)
387 | return Database.green;
388 | if (!ticket && !danger)
389 | return Database.orange;
390 | if (ticket && danger)
391 | return Database.redgreen;
392 | return !ticket && danger ? Database.redorange : (Image) null;
393 | }
394 |
395 | public ToolStripMenuItem[] LoadRegionCodes()
396 | {
397 | if (this.databaseString.Length < 1)
398 | throw new Exception("Load the database into a memory stream first!");
399 | XmlDocument xmlDocument = new XmlDocument();
400 | xmlDocument.LoadXml(this.databaseString);
401 | XmlNodeList childNodes = xmlDocument.GetElementsByTagName("REGIONS")[0].ChildNodes;
402 | ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[childNodes.Count];
403 | for (int i = 0; i < childNodes.Count; ++i)
404 | {
405 | toolStripMenuItemArray[i] = new ToolStripMenuItem();
406 | toolStripMenuItemArray[i].Text = childNodes[i].InnerText;
407 | }
408 | return toolStripMenuItemArray;
409 | }
410 |
411 | public ToolStripMenuItem[] LoadScripts()
412 | {
413 | if (this.databaseString.Length < 1)
414 | throw new Exception("Load the database into a memory stream first!");
415 | XmlDocument xmlDocument = new XmlDocument();
416 | xmlDocument.LoadXml(this.databaseString);
417 | XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.UpdateTag);
418 | ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count];
419 | for (int i1 = 0; i1 < elementsByTagName.Count; ++i1)
420 | {
421 | ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
422 | XmlAttributeCollection attributes = elementsByTagName[i1].Attributes;
423 | XmlNodeList childNodes = elementsByTagName[i1].ChildNodes;
424 | for (int i2 = 0; i2 < childNodes.Count; ++i2)
425 | {
426 | switch (childNodes[i2].Name)
427 | {
428 | case "name":
429 | toolStripMenuItem.Text = childNodes[i2].InnerText;
430 | break;
431 | case "script":
432 | toolStripMenuItem.ToolTipText = childNodes[i2].InnerText;
433 | break;
434 | }
435 | toolStripMenuItem.Image = (Image) Resources.script_start;
436 | }
437 | toolStripMenuItemArray[i1] = toolStripMenuItem;
438 | }
439 | return toolStripMenuItemArray;
440 | }
441 |
442 | public ToolStripMenuItem[] LoadDSiSystemTitles()
443 | {
444 | if (this.databaseString.Length < 1)
445 | throw new Exception("Load the database into a memory stream first!");
446 | XmlDocument xmlDocument = new XmlDocument();
447 | xmlDocument.LoadXml(this.databaseString);
448 | XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.DSiSystemTag);
449 | ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count];
450 | for (int i1 = 0; i1 < elementsByTagName.Count; ++i1)
451 | {
452 | ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
453 | XmlAttributeCollection attributes = elementsByTagName[i1].Attributes;
454 | string str1 = "";
455 | string str2 = "";
456 | bool danger = false;
457 | bool ticket = true;
458 | XmlNodeList childNodes = elementsByTagName[i1].ChildNodes;
459 | for (int i2 = 0; i2 < childNodes.Count; ++i2)
460 | {
461 | switch (childNodes[i2].Name)
462 | {
463 | case "name":
464 | str2 = childNodes[i2].InnerText;
465 | break;
466 | case "titleID":
467 | str1 = childNodes[i2].InnerText;
468 | break;
469 | case "version":
470 | string[] strArray1 = childNodes[i2].InnerText.Split(',');
471 | if (toolStripMenuItem.DropDownItems.Count > 0)
472 | {
473 | for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1)
474 | {
475 | if (childNodes[i2].InnerText != "")
476 | {
477 | ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1];
478 | dropDownItem.DropDownItems.Add("Latest Version");
479 | for (int index2 = 0; index2 < strArray1.Length; ++index2)
480 | dropDownItem.DropDownItems.Add("v" + strArray1[index2]);
481 | }
482 | }
483 | break;
484 | }
485 | toolStripMenuItem.DropDownItems.Add("Latest Version");
486 | if (childNodes[i2].InnerText != "")
487 | {
488 | for (int index = 0; index < strArray1.Length; ++index)
489 | toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]);
490 | break;
491 | }
492 | break;
493 | case "region":
494 | string[] strArray2 = childNodes[i2].InnerText.Split(',');
495 | if (childNodes[i2].InnerText != "")
496 | {
497 | for (int index = 0; index < strArray2.Length; ++index)
498 | toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index])));
499 | break;
500 | }
501 | break;
502 | case "ticket":
503 | ticket = Convert.ToBoolean(childNodes[i2].InnerText);
504 | break;
505 | case "danger":
506 | danger = true;
507 | toolStripMenuItem.ToolTipText = childNodes[i2].InnerText;
508 | break;
509 | }
510 | toolStripMenuItem.Image = this.SelectItemImage(ticket, danger);
511 | if (str1 != "")
512 | toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2);
513 | else
514 | toolStripMenuItem.Text = str2;
515 | }
516 | toolStripMenuItemArray[i1] = toolStripMenuItem;
517 | }
518 | return toolStripMenuItemArray;
519 | }
520 |
521 | public ToolStripMenuItem[] LoadDsiWareTitles()
522 | {
523 | if (this.databaseString.Length < 1)
524 | throw new Exception("Load the database into a memory stream first!");
525 | XmlDocument xmlDocument = new XmlDocument();
526 | xmlDocument.LoadXml(this.databaseString);
527 | XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName(this.DSiWareTag);
528 | ToolStripMenuItem[] toolStripMenuItemArray = new ToolStripMenuItem[elementsByTagName.Count];
529 | for (int i1 = 0; i1 < elementsByTagName.Count; ++i1)
530 | {
531 | ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
532 | XmlAttributeCollection attributes = elementsByTagName[i1].Attributes;
533 | string str1 = "";
534 | string str2 = "";
535 | bool danger = false;
536 | bool ticket = true;
537 | XmlNodeList childNodes = elementsByTagName[i1].ChildNodes;
538 | for (int i2 = 0; i2 < childNodes.Count; ++i2)
539 | {
540 | switch (childNodes[i2].Name)
541 | {
542 | case "name":
543 | str2 = childNodes[i2].InnerText;
544 | break;
545 | case "titleID":
546 | str1 = childNodes[i2].InnerText;
547 | break;
548 | case "version":
549 | string[] strArray1 = childNodes[i2].InnerText.Split(',');
550 | if (toolStripMenuItem.DropDownItems.Count > 0)
551 | {
552 | for (int index1 = 0; index1 < toolStripMenuItem.DropDownItems.Count; ++index1)
553 | {
554 | if (childNodes[i2].InnerText != "")
555 | {
556 | ToolStripMenuItem dropDownItem = (ToolStripMenuItem) toolStripMenuItem.DropDownItems[index1];
557 | dropDownItem.DropDownItems.Add("Latest Version");
558 | for (int index2 = 0; index2 < strArray1.Length; ++index2)
559 | dropDownItem.DropDownItems.Add("v" + strArray1[index2]);
560 | }
561 | }
562 | break;
563 | }
564 | toolStripMenuItem.DropDownItems.Add("Latest Version");
565 | if (childNodes[i2].InnerText != "")
566 | {
567 | for (int index = 0; index < strArray1.Length; ++index)
568 | toolStripMenuItem.DropDownItems.Add("v" + strArray1[index]);
569 | break;
570 | }
571 | break;
572 | case "region":
573 | string[] strArray2 = childNodes[i2].InnerText.Split(',');
574 | if (childNodes[i2].InnerText != "")
575 | {
576 | for (int index = 0; index < strArray2.Length; ++index)
577 | toolStripMenuItem.DropDownItems.Add(this.RegionFromIndex(Convert.ToInt32(strArray2[index])));
578 | break;
579 | }
580 | break;
581 | case "ticket":
582 | ticket = Convert.ToBoolean(childNodes[i2].InnerText);
583 | break;
584 | case "danger":
585 | danger = true;
586 | toolStripMenuItem.ToolTipText = childNodes[i2].InnerText;
587 | break;
588 | }
589 | toolStripMenuItem.Image = this.SelectItemImage(ticket, danger);
590 | if (str1 != "")
591 | toolStripMenuItem.Text = string.Format("{0} - {1}", (object) str1, (object) str2);
592 | else
593 | toolStripMenuItem.Text = str2;
594 | }
595 | toolStripMenuItemArray[i1] = toolStripMenuItem;
596 | }
597 | return toolStripMenuItemArray;
598 | }
599 | }
600 | }
601 |
--------------------------------------------------------------------------------