/// <summary> /// Creates a WAD file from contents. /// </summary> /// <param name="cert"></param> /// <param name="tik"></param> /// <param name="tmd"></param> /// <param name="contents"></param> public void CreateNew(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) { this.cert = cert; this.tik = tik; this.tmd = tmd; this.contents = new List<byte[]>(contents); this.wadHeader = new WAD_Header(); this.wadHeader.TmdSize = (uint)(484 + (tmd.Contents.Length * 36)); int contentSize = 0; for (int i = 0; i < contents.Length - 1; i++) contentSize += Shared.AddPadding(contents[i].Length); contentSize += contents[contents.Length - 1].Length; this.wadHeader.ContentSize = (uint)contentSize; for (int i = 0; i < this.tmd.Contents.Length; i++) if (this.tmd.Contents[i].Index == 0x0000) { try { this.bannerApp.LoadFile(contents[i]); hasBanner = true; } catch { hasBanner = false; } //Probably System Wad => No Banner App... break; } }
protected virtual void Dispose(bool disposing) { if (disposing && !isDisposed) { sha.Clear(); sha = null; wadHeader = null; cert.Dispose(); tik.Dispose(); tmd.Dispose(); contents.Clear(); contents = null; bannerApp.Dispose(); footer = null; } isDisposed = true; }
private void parseWad(Stream wadFile) { fireDebug("Parsing Wad..."); wadFile.Seek(0, SeekOrigin.Begin); byte[] temp = new byte[4]; wadHeader = new WAD_Header(); contents = new List<byte[]>(); //Read Header fireDebug(" Parsing Header... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); wadFile.Read(temp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != wadHeader.HeaderSize) throw new Exception("Invalid Headersize!"); wadFile.Read(temp, 0, 4); wadHeader.WadType = Shared.Swap(BitConverter.ToUInt32(temp, 0)); wadFile.Seek(12, SeekOrigin.Current); wadFile.Read(temp, 0, 4); wadHeader.TmdSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); wadFile.Read(temp, 0, 4); wadHeader.ContentSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); wadFile.Read(temp, 0, 4); wadHeader.FooterSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); //Read Cert fireDebug(" Parsing Certificate Chain... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); temp = new byte[wadHeader.CertSize]; wadFile.Read(temp, 0, temp.Length); cert.LoadFile(temp); //Read Tik fireDebug(" Parsing Ticket... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); temp = new byte[wadHeader.TicketSize]; wadFile.Read(temp, 0, temp.Length); tik.LoadFile(temp); //Read Tmd fireDebug(" Parsing TMD... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); temp = new byte[wadHeader.TmdSize]; wadFile.Read(temp, 0, temp.Length); tmd.LoadFile(temp); if (tmd.TitleID != tik.TitleID) fireWarning("The Title ID in the Ticket doesn't match the one in the TMD!"); //Read Content for (int i = 0; i < tmd.NumOfContents; i++) { fireProgress((i + 1) * 100 / tmd.NumOfContents); fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", i + 1, tmd.NumOfContents, wadFile.Position.ToString("x8").ToUpper()); fireDebug(" -> Content ID: 0x{0}", tmd.Contents[i].ContentID.ToString("x8")); fireDebug(" -> Index: 0x{0}", tmd.Contents[i].Index.ToString("x4")); fireDebug(" -> Type: 0x{0} ({1})", ((ushort)tmd.Contents[i].Type).ToString("x4"), tmd.Contents[i].Type.ToString()); fireDebug(" -> Size: {0} bytes", tmd.Contents[i].Size); fireDebug(" -> Hash: {0}", Shared.ByteArrayToString(tmd.Contents[i].Hash)); wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); temp = new byte[Shared.AddPadding((int)tmd.Contents[i].Size, 16)]; wadFile.Read(temp, 0, temp.Length); //Decrypt Content temp = decryptContent(temp, i); Array.Resize(ref temp, (int)tmd.Contents[i].Size); byte[] tmdHash = tmd.Contents[i].Hash; byte[] newHash = sha.ComputeHash(temp, 0, (int)tmd.Contents[i].Size); if (!Shared.CompareByteArrays(tmdHash, newHash)) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); fireWarning(string.Format("Content #{0} (Content ID: 0x{1}; Index: 0x{2}): Hashes do not match! The content might be corrupted!", i + 1, tmd.Contents[i].ContentID.ToString("x8"), tmd.Contents[i].Index.ToString("x4"))); } contents.Add(temp); if (tmd.Contents[i].Index == 0x0000) { try { bannerApp.LoadFile(temp); hasBanner = true; } catch { hasBanner = false; } //Probably System Wad => No Banner App... } } //Read Footer if (wadHeader.FooterSize > 0) { fireDebug(" Reading Footer... (Offset: 0x{0})", wadFile.Position.ToString("x8").ToUpper()); footer = new byte[wadHeader.FooterSize]; wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); wadFile.Read(footer, 0, footer.Length); parseFooterTimestamp(); } fireDebug("Parsing Wad Finished..."); }