public NUSTitle loadNusTitle(NUSTitleConfig config) { NUSTitle result = new NUSTitle(); NUSDataProvider dataProvider = getDataProvider(result, config); result.dataProvider = (dataProvider); TMD tmd = TMD.parseTMD(dataProvider.getRawTMD()); result.TMD = (tmd); if (tmd == null) { //MessageBox.Show("TMD not found."); throw new Exception(); } Ticket ticket = config.ticket; if (ticket == null) { ticket = Ticket.parseTicket(dataProvider.getRawTicket()); } result.ticket = ticket; // System.out.println(ticket); Content fstContent = tmd.getContentByIndex(0); MemoryStream fstContentEncryptedStream = dataProvider.getInputStreamFromContent(fstContent, 0); if (fstContentEncryptedStream == null) { return(null); } byte[] fstBytes = fstContentEncryptedStream.ToArray();// StreamUtils.getBytesFromStream(fstContentEncryptedStream, (int)fstContent.getEncryptedFileSize()); if (fstContent.isEncrypted()) { AESDecryption aesDecryption = new AESDecryption(ticket.decryptedKey, new byte[0x10]); fstBytes = aesDecryption.decrypt(fstBytes); } Dictionary <int, Content> contents = tmd.getAllContents(); FST fst = FST.parseFST(fstBytes, contents); result.FST = (fst); return(result); }
private static Dictionary <string, WUDPartition> readPartitions(WUDInfo wudInfo, byte[] partitionTocBlock) { byte[] buffer = new byte[partitionTocBlock.Length]; int partitionCount = (int)SwapEndianness(BitConverter.ToUInt32(partitionTocBlock, 0x1C)); Dictionary <string, WUDPartition> partitions = new Dictionary <string, WUDPartition>(); byte[] gamePartitionTMD = new byte[0]; byte[] gamePartitionTicket = new byte[0]; byte[] gamePartitionCert = new byte[0]; String realGamePartitionName = ""; // populate partition information from decrypted TOC for (int i = 0; i < partitionCount; i++) { int offset = (PARTITION_TOC_OFFSET + (i * PARTITION_TOC_ENTRY_SIZE)); byte[] partitionIdentifier = new byte[0x19]; Array.ConstrainedCopy(partitionTocBlock, offset, partitionIdentifier, 0, 0x19); int j = 0; for (j = 0; j < partitionIdentifier.Length; j++) { if (partitionIdentifier[j] == 0) { break; } } byte[] partitionNameArray = new byte[j]; Array.ConstrainedCopy(partitionIdentifier, 0, partitionNameArray, 0, j); String partitionName = Encoding.ASCII.GetString(partitionNameArray); // calculate partition offset (relative from WIIU_DECRYPTED_AREA_OFFSET) from decrypted TOC long tmp = SwapEndianness(BitConverter.ToUInt32(partitionTocBlock, (PARTITION_TOC_OFFSET + (i * PARTITION_TOC_ENTRY_SIZE) + 0x20))); long partitionOffset = ((tmp * (long)0x8000) - 0x10000); WUDPartition partition = new WUDPartition(partitionName, partitionOffset); if (partitionName.StartsWith("SI")) { byte[] fileTableBlock = wudInfo.WUDDiscReader.readDecryptedToByteArray(Settings.WIIU_DECRYPTED_AREA_OFFSET + partitionOffset, 0, 0x8000, wudInfo.titleKey, null); byte[] copy = new byte[4]; Array.ConstrainedCopy(fileTableBlock, 0, copy, 0, 4); if (!ArraysEqual(copy, PARTITION_FILE_TABLE_SIGNATURE)) { //MessageBox.Show("FST Decrpytion failed"); continue; } //if (!Arrays.equals(Arrays.copyOfRange(fileTableBlock, 0, 4), PARTITION_FILE_TABLE_SIGNATURE)) //{ // log.info("FST Decrpytion failed"); // continue; //} FST fst = FST.parseFST(fileTableBlock, null); byte[] rawTIK = getFSTEntryAsByte(WUD_TICKET_FILENAME, partition, fst, wudInfo.WUDDiscReader, wudInfo.titleKey); byte[] rawTMD = getFSTEntryAsByte(WUD_TMD_FILENAME, partition, fst, wudInfo.WUDDiscReader, wudInfo.titleKey); byte[] rawCert = getFSTEntryAsByte(WUD_CERT_FILENAME, partition, fst, wudInfo.WUDDiscReader, wudInfo.titleKey); gamePartitionTMD = rawTMD; gamePartitionTicket = rawTIK; gamePartitionCert = rawCert; // We want to use the real game partition realGamePartitionName = partitionName = "GM" + Utils.ByteArrayToString(Arrays.copyOfRange(rawTIK, 0x1DC, 0x1DC + 0x08)); } else if (partitionName.StartsWith(realGamePartitionName)) { wudInfo.gamePartitionName = partitionName; partition = new WUDGamePartition(partitionName, partitionOffset, gamePartitionTMD, gamePartitionCert, gamePartitionTicket); } byte[] header = wudInfo.WUDDiscReader.readEncryptedToByteArray(partition.partitionOffset + 0x10000, 0, 0x8000); WUDPartitionHeader partitionHeader = WUDPartitionHeader.parseHeader(header); partition.partitionHeader = (partitionHeader); partitions.Add(partitionName, partition); } return(partitions); }