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); }
private static byte[] getFSTEntryAsByte(String filename, WUDPartition partition, FST fst, WUDDiscReader discReader, byte[] key) { FSTEntry entry = getEntryByName(fst.root, filename); ContentFSTInfo info = fst.contentFSTInfos[((int)entry.contentFSTID)]; // Calculating the IV ByteBuffer byteBuffer = ByteBuffer.allocate(0x10); byteBuffer.position(0x08); long l = entry.fileOffset >> 16; byte[] ar = BitConverter.GetBytes(l); byte[] IV = new byte[0x10];//= copybyteBuffer.putLong(entry.fileOffset >> 16).ToArray(); Array.ConstrainedCopy(ar, 0, IV, 0x08, 0x08); return(discReader.readDecryptedToByteArray(Settings.WIIU_DECRYPTED_AREA_OFFSET + (long)partition.partitionOffset + (long)info.getOffset(), entry.fileOffset, (int)entry.fileSize, key, IV)); }