├── 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 | --------------------------------------------------------------------------------