// TODO: real processing. Currently we are ignoring everything except the hashes public static WUDPartitionHeader parseHeader(byte[] header) { WUDPartitionHeader result = new WUDPartitionHeader(); result.rawData = (header); 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); }