├── .gitignore ├── .gitattributes ├── .github └── workflows │ └── maven.yml ├── pom.xml ├── README.md └── src └── main └── java └── de └── mas └── jwudtool └── Main.java /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /target/ 3 | .classpath 4 | .project 5 | .settings/ 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Build with Maven 24 | run: mvn -B package --file pom.xml 25 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | de.mas 6 | jwudtool 7 | 0.5 8 | 9 | 10 | 11 | normal-build 12 | 13 | true 14 | 15 | 16 | ./target 17 | 18 | 19 | 20 | ci-build 21 | 22 | 23 | ci-build 24 | true 25 | 26 | 27 | 28 | ./ci 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | maven-compiler-plugin 37 | 3.7.0 38 | 39 | 1.8 40 | 1.8 41 | 42 | 43 | 44 | maven-assembly-plugin 45 | 46 | 47 | make-assembly 48 | 49 | 50 | 51 | de.mas.jwudtool.Main 52 | 53 | 54 | 55 | jar-with-dependencies 56 | 57 | 58 | ${jar_dir} 59 | JWUDTool-${project.version}-nightly 60 | 61 | package 62 | 63 | attached 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | jitpack.io 74 | https://jitpack.io 75 | 76 | 77 | 78 | 79 | 80 | com.github.Maschell 81 | JNUSLib 82 | 822cf2d 83 | 84 | 85 | 86 | 87 | org.projectlombok 88 | lombok 89 | 1.18.4 90 | provided 91 | 92 | 93 | 94 | 95 | commons-cli 96 | commons-cli 97 | 1.4 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JWUDTool 2 | 3 | Here is just a simple program that uses the (http://gbatemp.net/threads/jnuslib-java-nus-library.452954/). 4 | The usage should be pretty self explaining. 5 | 6 | **STILL EXPERIMENTAL. Bugs may occur, please report them!** 7 | 8 | ## Features 9 | 10 | * Compressing .wud and splitted wud files into .wux 11 | * Decompressing a .wux back to .wud 12 | * Extracting titles from the GI or GM partition 13 | * Extracting .app/-h3/.tmd/.cert/.tik files from a .wud/.wux or splitted .wud 14 | * Extracting just the contents/hashes/ticket. 15 | * Decrypting the full partitions from a .wud/.wux or splitted .wud 16 | * Decrypting specific files any partition from a .wud/.wux or splitted .wud 17 | * Verify a image / Compare two images (for example a .wud with .wux to make sure its legit) 18 | 19 | ## Usage 20 | 21 | Optional: 22 | - Copy the common.key into the folder next to the .jar or provide the key via the command line 23 | - Copy the game.key into the folder next to the wud image or provide the key via the command line 24 | 25 | ``` 26 | usage: 27 | -commonkey Optional. HexString. Will be used if no "common.key" in the 28 | folder of this .jar is found 29 | -dev Required when using discs without a titlekey. 30 | -compress Compresses the input to a .wux file. 31 | -decompress Decompresses the input to a .wud file. 32 | -decrypt Decrypts full the game partition of the given wud. 33 | -decryptFile Decrypts files of the game partition that match the regular 34 | expression of the given wud. 35 | -extract Extracts files from the game partition of the given wud 36 | (Arguments optional) 37 | -help shows this text 38 | -in Input file. Can be a .wux, .wud or a game_part1.wud 39 | -noVerify Disables verification after (de)compressing 40 | -out The path where the result will be saved 41 | -overwrite Optional. Overwrites existing files 42 | -titleKey Optional. HexString. Will be used if no "game.key" in the 43 | folder of the wud image is found 44 | -verify Compares two WUD images to find differences 45 | ``` 46 | # Examples 47 | ## Getting .app files from an Wii U Image: 48 | ### Extract .app etc. from a WUD: 49 | Get .app files from "game.wud" to the folder "extracted" with game.key in the same folder 50 | ``` 51 | java -jar JWUDTool.jar -in "game.wud" -out "extracted" -extract all 52 | ``` 53 | 54 | ### Extract .app etc. from a WUX (compressed WUD): 55 | Get .app files from "game.wux" to the folder "extracted" with game.key in the same folder 56 | ``` 57 | java -jar JWUDTool.jar -in "game.wux" -out "extracted" -extract all 58 | ``` 59 | 60 | ### Extract .app etc. from a splitted WUD (dump with wudump): 61 | Get .app files from "game_part1.wud" to the folder "extracted" with game.key in the same folder 62 | ``` 63 | java -jar JWUDTool.jar -in "game_part1.wud" -out "extracted" -extract all 64 | ``` 65 | 66 | ## Compressing into .wux examples: 67 | ### Compress a .wud to .wux:[/B] 68 | Compress a "game.wud" to "game.wux" 69 | ``` 70 | java -jar JWUDTool.jar -in "game.wud" -compress 71 | ``` 72 | 73 | ### Compress a splitted game_part1.wud to .wux: 74 | Compress a "game_part1.wud" from a wudump dump to "game.wux" 75 | ``` 76 | java -jar JWUDTool.jar -in "game_part1.wud" -compress 77 | ``` 78 | 79 | ## Decryption game files examples: 80 | ### Decrypt a WUD image to game files 81 | Input can be a .wud, game_part1.wud or a .wux. This decrypted the full game partition. 82 | Given a game.key and common.key in the same folder. 83 | ``` 84 | java -jar JWUDTool.jar -in "game.wud" -decrypt //WUD 85 | java -jar JWUDTool.jar -in "game.wux" -decrypt //WUX 86 | java -jar JWUDTool.jar -in "game_part1.wud" -decrypt //game_part1 87 | ``` 88 | 89 | ### Decrypt a single file from an WUD 90 | Input can be a .wud, game_part1.wud or a .wux. This decrypted the full game partition. 91 | Given a game.key and common.key in the same folder. 92 | 93 | Extracting the code/app.xml file. 94 | ``` 95 | java -jar JWUDTool.jar -in "game.wud" -decryptFile /code/app.xml 96 | java -jar JWUDTool.jar -in "game.wux" -decryptFile /code/app.xml 97 | java -jar JWUDTool.jar -in "game_part1.wud" -decryptFile /code/app.xml 98 | ``` 99 | 100 | Extracting all .bfstm files. 101 | ``` 102 | java -jar JWUDTool.jar -in "game.wud" -decryptFile /.*.bfstm 103 | java -jar JWUDTool.jar -in "game.wux" -decryptFile /.*.bfstm 104 | java -jar JWUDTool.jar -in "game_part1.wud" -decryptFile /.*.bfstm 105 | ``` 106 | 107 | Extracting the folder /content/Sound 108 | ``` 109 | java -jar JWUDTool.jar -in "game.wud" -decryptFile /content/Sound/.* 110 | java -jar JWUDTool.jar -in "game.wux" -decryptFile /content/Sound/.* 111 | java -jar JWUDTool.jar -in "game_part1.wud" -decryptFile /content/Sound/.* 112 | ``` 113 | 114 | ## Compiling 115 | `mvn clean package` 116 | 117 | ## Credits 118 | Maschell 119 | 120 | Thanks to: 121 | Crediar for CDecrypt (https://github.com/crediar/cdecrypt) 122 | All people who have contributed to vgmtoolbox (https://sourceforge.net/projects/vgmtoolbox/) 123 | Exzap for the .wux file format (https://gbatemp.net/threads/wii-u-image-wud-compression-tool.397901/) 124 | FIX94 for wudump (https://gbatemp.net/threads/wudump-dump-raw-images-from-a-wiiu-game-disc.451736/) 125 | The creators of lombok for lombok https://projectlombok.org/index.html 126 | -------------------------------------------------------------------------------- /src/main/java/de/mas/jwudtool/Main.java: -------------------------------------------------------------------------------- 1 | package de.mas.jwudtool; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.util.List; 7 | import java.util.Optional; 8 | import java.util.Set; 9 | import java.util.TreeSet; 10 | 11 | import org.apache.commons.cli.CommandLine; 12 | import org.apache.commons.cli.CommandLineParser; 13 | import org.apache.commons.cli.DefaultParser; 14 | import org.apache.commons.cli.HelpFormatter; 15 | import org.apache.commons.cli.MissingArgumentException; 16 | import org.apache.commons.cli.Option; 17 | import org.apache.commons.cli.Options; 18 | import org.apache.commons.cli.UnrecognizedOptionException; 19 | 20 | import de.mas.wiiu.jnus.DecryptionService; 21 | import de.mas.wiiu.jnus.ExtractionService; 22 | import de.mas.wiiu.jnus.NUSTitle; 23 | import de.mas.wiiu.jnus.WUDLoader; 24 | import de.mas.wiiu.jnus.WUDService; 25 | import de.mas.wiiu.jnus.implementations.wud.WUDImage; 26 | import de.mas.wiiu.jnus.implementations.wud.WiiUDisc; 27 | import de.mas.wiiu.jnus.interfaces.FSTDataProvider; 28 | import de.mas.wiiu.jnus.utils.Utils; 29 | import lombok.val; 30 | 31 | public class Main { 32 | private final static String OPTION_IN = "in"; 33 | private final static String OPTION_HELP = "help"; 34 | private static final String OPTION_OUT = "out"; 35 | private static final String OPTION_DECOMPRESS = "decompress"; 36 | private static final String OPTION_COMPRESS = "compress"; 37 | private static final String OPTION_COMMON_KEY = "commonkey"; 38 | private static final String OPTION_NO_VERIFY = "noVerify"; 39 | private static final String OPTION_VERIFY = "verify"; 40 | private static final String OPTION_OVERWRITE = "overwrite"; 41 | private static final String OPTION_DECRYPT = "decrypt"; 42 | private static final String OPTION_TITLEKEY = "titleKey"; 43 | private static final String OPTION_DECRYPT_FILE = "decryptFile"; 44 | private static final String OPTION_EXTRACT = "extract"; 45 | private static final String OPTION_DEVMODE = "dev"; 46 | private static byte[] commonKey; 47 | 48 | private static final String HOMEPATH = System.getProperty("user.home") + File.separator + ".wiiu"; 49 | 50 | public static void main(String[] args) throws Exception { 51 | System.out.println("JWUDTool 0.4 - Maschell"); 52 | System.out.println(); 53 | Options options = getOptions(); 54 | 55 | if (args.length == 0) { 56 | showHelp(options); 57 | return; 58 | } 59 | 60 | CommandLineParser parser = new DefaultParser(); 61 | CommandLine cmd; 62 | try { 63 | cmd = parser.parse(options, args); 64 | } catch (MissingArgumentException e) { 65 | System.out.println(e.getMessage()); 66 | return; 67 | } catch (UnrecognizedOptionException e) { 68 | System.out.println(e.getMessage()); 69 | showHelp(options); 70 | return; 71 | } 72 | 73 | String input = null; 74 | String output = null; 75 | boolean overwrite = false; 76 | boolean devMode = false; 77 | byte[] titlekey = null; 78 | 79 | if (cmd.hasOption(OPTION_HELP)) { 80 | showHelp(options); 81 | return; 82 | } 83 | 84 | if (cmd.hasOption(OPTION_DEVMODE)) { 85 | devMode = true; 86 | } 87 | 88 | readKey(new File(HOMEPATH + File.separator + (devMode ? "devcommon.key" : "common.key"))).ifPresent(key -> Main.commonKey = key); 89 | readKey(new File("common.key")).ifPresent(key -> Main.commonKey = key); 90 | 91 | if (cmd.hasOption(OPTION_IN)) { 92 | input = cmd.getOptionValue(OPTION_IN); 93 | } 94 | if (cmd.hasOption(OPTION_OUT)) { 95 | output = cmd.getOptionValue(OPTION_OUT); 96 | } 97 | 98 | if (cmd.hasOption(OPTION_COMMON_KEY)) { 99 | String commonKey = cmd.getOptionValue(OPTION_COMMON_KEY); 100 | byte[] key = Utils.StringToByteArray(commonKey); 101 | if (key.length == 0x10) { 102 | Main.commonKey = key; 103 | System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key)); 104 | } 105 | } 106 | 107 | if (cmd.hasOption(OPTION_TITLEKEY)) { 108 | String titlekey_string = cmd.getOptionValue(OPTION_TITLEKEY); 109 | titlekey = Utils.StringToByteArray(titlekey_string); 110 | if (titlekey.length != 0x10) { 111 | titlekey = null; 112 | } else { 113 | System.out.println("Titlekey was set to: " + Utils.ByteArrayToString(titlekey)); 114 | } 115 | } 116 | 117 | if (cmd.hasOption(OPTION_OVERWRITE)) { 118 | overwrite = true; 119 | } 120 | 121 | if (cmd.hasOption(OPTION_COMPRESS)) { 122 | boolean verify = true; 123 | System.out.println("Compressing: " + input); 124 | if (cmd.hasOption(OPTION_NO_VERIFY)) { 125 | System.out.println("Verification disabled."); 126 | verify = false; 127 | } 128 | compressDecompressWUD(input, output, verify, overwrite, false); 129 | return; 130 | } else if (cmd.hasOption(OPTION_DECOMPRESS)) { 131 | boolean verify = true; 132 | System.out.println("Decompressing: " + input); 133 | if (cmd.hasOption(OPTION_NO_VERIFY)) { 134 | System.out.println("Verification disabled."); 135 | verify = false; 136 | } 137 | compressDecompressWUD(input, output, verify, overwrite, true); 138 | return; 139 | } else if (cmd.hasOption(OPTION_VERIFY)) { 140 | System.out.println("Comparing images."); 141 | String[] verifyArgs = cmd.getOptionValues(OPTION_VERIFY); 142 | 143 | File input1 = new File(verifyArgs[0]); 144 | File input2 = new File(verifyArgs[1]); 145 | 146 | verifyImages(input1, input2); 147 | 148 | return; 149 | } else { 150 | if (cmd.hasOption(OPTION_DECRYPT)) { 151 | System.out.println("Decrypting full game partition."); 152 | 153 | decrypt(input, output, devMode, overwrite, titlekey); 154 | 155 | return; 156 | } else if (cmd.hasOption(OPTION_DECRYPT_FILE)) { 157 | String regex = cmd.getOptionValue(OPTION_DECRYPT_FILE); 158 | System.out.println("Decrypting files matching \"" + regex + "\""); 159 | 160 | decryptFile(input, output, regex, devMode, overwrite, titlekey); 161 | 162 | return; 163 | } else if (cmd.hasOption(OPTION_EXTRACT)) { 164 | System.out.println("Extracting WUD"); 165 | String arg = cmd.getOptionValue(OPTION_EXTRACT); 166 | if (arg == null) { 167 | arg = "all"; 168 | } 169 | extract(input, output, devMode, overwrite, titlekey, arg); 170 | 171 | return; 172 | } 173 | } 174 | System.out.println("Done!"); 175 | } 176 | 177 | private static void extract(String input, String output, boolean devMode, boolean overwrite, byte[] titlekey, String arg) throws Exception { 178 | if (input == null) { 179 | System.out.println("You need to provide an input file"); 180 | } 181 | boolean extractAll = false; 182 | boolean extractContent = false; 183 | boolean extractTicket = false; 184 | boolean extractHashes = false; 185 | 186 | switch (arg) { 187 | case "all": 188 | extractAll = true; 189 | break; 190 | case "content": 191 | extractContent = true; 192 | break; 193 | case "ticket": 194 | extractTicket = true; 195 | break; 196 | case "hashes": 197 | extractHashes = true; 198 | break; 199 | default: 200 | System.out.println("Argument not found:" + arg); 201 | return; 202 | } 203 | 204 | assert input != null; 205 | File inputFile = new File(input); 206 | 207 | System.out.println("Extracting: " + inputFile.getAbsolutePath()); 208 | 209 | WiiUDisc wudInfo; 210 | if (!devMode) { 211 | wudInfo = WUDLoader.load(inputFile.getAbsolutePath(), titlekey); 212 | } else { 213 | wudInfo = WUDLoader.loadDev(inputFile.getAbsolutePath()); 214 | } 215 | 216 | List titles = WUDLoader.getGamePartionsAsNUSTitles(wudInfo, Main.commonKey); 217 | System.out.println("Found " + titles.size() + " titles on the Disc."); 218 | for (val title : titles) { 219 | String newOutput = output; 220 | System.out.println("Extract files of Title " + String.format("%016X", title.getTMD().getTitleID())); 221 | if (newOutput == null) { 222 | newOutput = String.format("%016X", title.getTMD().getTitleID()); 223 | } else { 224 | newOutput += File.separator + String.format("%016X", title.getTMD().getTitleID()); 225 | } 226 | 227 | File outputFolder = new File(newOutput); 228 | System.out.println("To the folder: " + outputFolder.getAbsolutePath()); 229 | 230 | ExtractionService extractionService = ExtractionService.getInstance(title); 231 | if (extractAll) { 232 | extractionService.extractAll(outputFolder.getAbsolutePath()); 233 | } else if (extractTicket) { 234 | extractionService.extractTicketTo(outputFolder.getAbsolutePath()); 235 | } else if (extractContent) { 236 | extractionService.extractAllEncryptedContentFilesWithoutHashesTo(outputFolder.getAbsolutePath()); 237 | } else if (extractHashes) { 238 | extractionService.extractAllEncrpytedContentFileHashes(outputFolder.getAbsolutePath()); 239 | } 240 | System.out.println("Extraction done!"); 241 | } 242 | 243 | } 244 | 245 | private static void decryptFile(String input, String output, String regex, boolean devMode, boolean overwrite, byte[] titlekey) throws Exception { 246 | if (input == null) { 247 | System.out.println("You need to provide an input file"); 248 | return; 249 | } 250 | File inputFile = new File(input); 251 | 252 | System.out.println("Decrypting: " + inputFile.getAbsolutePath()); 253 | 254 | WiiUDisc wudInfo; 255 | if (!devMode) { 256 | wudInfo = WUDLoader.load(inputFile.getAbsolutePath(), titlekey); 257 | } else { 258 | wudInfo = WUDLoader.loadDev(inputFile.getAbsolutePath()); 259 | } 260 | 261 | List partitions = WUDLoader.getPartitonsAsFSTDataProvider(wudInfo, Main.commonKey); 262 | System.out.println("Found " + partitions.size() + " titles on the Disc."); 263 | 264 | Set paritionNames = new TreeSet<>(); 265 | for (val dp : partitions) { 266 | String partitionName = dp.getName(); 267 | 268 | int i = 0; 269 | while (paritionNames.contains(partitionName)) { 270 | partitionName = dp.getName() + "_" + i++; 271 | } 272 | 273 | paritionNames.add(partitionName); 274 | 275 | String newOutput = output; 276 | System.out.println("Decrypting files in partition " + partitionName); 277 | if (newOutput == null) { 278 | newOutput = partitionName; 279 | } else { 280 | newOutput += File.separator + partitionName; 281 | } 282 | 283 | File outputFolder = new File(newOutput); 284 | 285 | System.out.println("To the folder: " + outputFolder.getAbsolutePath()); 286 | DecryptionService decryption = DecryptionService.getInstance(dp); 287 | 288 | decryption.decryptFSTEntriesTo(regex, outputFolder.getAbsolutePath(), !overwrite); 289 | } 290 | System.out.println("Decryption done"); 291 | } 292 | 293 | private static void decrypt(String input, String output, boolean devMode, boolean overwrite, byte[] titlekey) throws Exception { 294 | decryptFile(input, output, ".*", devMode, overwrite, titlekey); 295 | } 296 | 297 | private static void verifyImages(File input1, File input2) throws IOException { 298 | System.out.println("Input 1: " + input1.getAbsolutePath()); 299 | WUDImage image1 = new WUDImage(input1); 300 | 301 | System.out.println("Input 2: " + input2.getAbsolutePath()); 302 | WUDImage image2 = new WUDImage(input2); 303 | if (WUDService.compareWUDImage(image1, image2)) { 304 | System.out.println("Both images have the same data"); 305 | } else { 306 | System.out.println("The images are different!"); 307 | } 308 | } 309 | 310 | private static void compressDecompressWUD(String input, String output, boolean verify, boolean overwrite, boolean decompress) throws IOException { 311 | if (input == null) { 312 | System.out.println("-" + OPTION_IN + " was null"); 313 | return; 314 | } 315 | File inputImage = new File(input); 316 | if (inputImage.isDirectory() || !inputImage.exists()) { 317 | System.out.println(inputImage.getAbsolutePath() + " is no file or does not exist"); 318 | return; 319 | } 320 | System.out.println("Parsing WUD image."); 321 | WUDImage image = new WUDImage(inputImage); 322 | Optional outputFile; 323 | if (!decompress) { 324 | outputFile = WUDService.compressWUDToWUX(image, output, overwrite); 325 | if (outputFile.isPresent()) { 326 | System.out.println("Compression successful!"); 327 | } 328 | } else { 329 | outputFile = WUDService.decompressWUX(image, output, overwrite); 330 | if (outputFile.isPresent()) { 331 | System.out.println("Decompression successful!"); 332 | } 333 | } 334 | 335 | if (verify) { 336 | if (outputFile.isPresent()) { 337 | WUDImage image2 = new WUDImage(outputFile.get()); 338 | if (WUDService.compareWUDImage(image, image2)) { 339 | System.out.println("Compressed files is valid."); 340 | } else { 341 | System.out.println("Warning! (De)Compressed file is INVALID!"); 342 | } 343 | } 344 | } else { 345 | System.out.println("Verfication skipped"); 346 | } 347 | } 348 | 349 | private static Optional readKey(File file) { 350 | if (file.isFile()) { 351 | byte[] key; 352 | try { 353 | key = Files.readAllBytes(file.toPath()); 354 | if (key.length == 16) { 355 | return Optional.of(key); 356 | } 357 | } catch (IOException ignored) { 358 | } 359 | } 360 | return Optional.empty(); 361 | } 362 | 363 | private static Options getOptions() { 364 | Options options = new Options(); 365 | options.addOption(Option.builder(OPTION_IN).argName("input file").hasArg().desc("Input file. Can be a .wux, .wud or a game_part1.wud").build()); 366 | options.addOption(Option.builder(OPTION_OUT).argName("output path").hasArg().desc("The path where the result will be saved").build()); 367 | options.addOption(Option.builder(OPTION_DEVMODE).argName("dev mode").desc("Allows you to handle Kiosk Discs").build()); 368 | options.addOption(Option.builder(OPTION_COMPRESS).desc("Compresses the input to a .wux file.").build()); 369 | options.addOption(Option.builder(OPTION_DECOMPRESS).desc("Decompresses the input back to a .wud file.").build()); 370 | options.addOption(Option.builder(OPTION_NO_VERIFY).desc("Disables verification after compressing").build()); 371 | options.addOption(Option.builder(OPTION_VERIFY).argName("wudimage1|wudimage2").hasArg().numberOfArgs(2) 372 | .desc("Compares two WUD images to find differences").build()); 373 | options.addOption(Option.builder(OPTION_OVERWRITE).desc("Optional. Overwrites existing files").build()); 374 | options.addOption(Option.builder(OPTION_COMMON_KEY).argName("WiiU common key").hasArg() 375 | .desc("Optional. HexString. Will be used if no \"common.key\" in the folder of this .jar is found").build()); 376 | options.addOption(Option.builder(OPTION_DECRYPT).desc("Decrypts full the game partition of the given wud.").build()); 377 | options.addOption(Option.builder(OPTION_TITLEKEY).argName("WUD title key").hasArg() 378 | .desc("Optional. HexString. Will be used if no \"game.key\" in the folder of the wud image is found").build()); 379 | options.addOption( 380 | Option.builder(OPTION_DECRYPT_FILE).argName("regular expression").hasArg().desc("Decrypts full the game partition of the given wud.").build()); 381 | options.addOption(Option.builder(OPTION_EXTRACT).argName("all|content|ticket|hashes").hasArg().optionalArg(true) 382 | .desc("Extracts files from the game partition of the given wud (Arguments optional)").build()); 383 | 384 | options.addOption(OPTION_HELP, false, "shows this text"); 385 | 386 | return options; 387 | } 388 | 389 | private static void showHelp(Options options) { 390 | HelpFormatter formatter = new HelpFormatter(); 391 | formatter.setWidth(100); 392 | formatter.printHelp(" ", options); 393 | } 394 | 395 | } 396 | --------------------------------------------------------------------------------