mirror of
https://github.com/Maschell/JWUDTool.git
synced 2024-11-16 21:19:19 +01:00
Using the newest JNUSLib as a backend:
- Support for extracting and decrypting all partitions - Common key can be read from ~/.wii/common.key
This commit is contained in:
parent
2341b55271
commit
1c8673b416
2
pom.xml
2
pom.xml
@ -49,7 +49,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.Maschell</groupId>
|
<groupId>com.github.Maschell</groupId>
|
||||||
<artifactId>JNUSLib</artifactId>
|
<artifactId>JNUSLib</artifactId>
|
||||||
<version>8124bb2</version>
|
<version>3eb299d</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||||
|
@ -4,6 +4,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
@ -17,10 +18,11 @@ import org.apache.commons.cli.UnrecognizedOptionException;
|
|||||||
import de.mas.wiiu.jnus.DecryptionService;
|
import de.mas.wiiu.jnus.DecryptionService;
|
||||||
import de.mas.wiiu.jnus.ExtractionService;
|
import de.mas.wiiu.jnus.ExtractionService;
|
||||||
import de.mas.wiiu.jnus.NUSTitle;
|
import de.mas.wiiu.jnus.NUSTitle;
|
||||||
import de.mas.wiiu.jnus.NUSTitleLoaderWUD;
|
import de.mas.wiiu.jnus.WUDLoader;
|
||||||
import de.mas.wiiu.jnus.Settings;
|
|
||||||
import de.mas.wiiu.jnus.WUDService;
|
import de.mas.wiiu.jnus.WUDService;
|
||||||
import de.mas.wiiu.jnus.implementations.wud.WUDImage;
|
import de.mas.wiiu.jnus.implementations.wud.WUDImage;
|
||||||
|
import de.mas.wiiu.jnus.implementations.wud.parser.WUDInfo;
|
||||||
|
import de.mas.wiiu.jnus.interfaces.FSTDataProvider;
|
||||||
import de.mas.wiiu.jnus.utils.Utils;
|
import de.mas.wiiu.jnus.utils.Utils;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
|
||||||
@ -39,6 +41,9 @@ public class Main {
|
|||||||
private static final String OPTION_DECRYPT_FILE = "decryptFile";
|
private static final String OPTION_DECRYPT_FILE = "decryptFile";
|
||||||
private static final String OPTION_EXTRACT = "extract";
|
private static final String OPTION_EXTRACT = "extract";
|
||||||
private static final String OPTION_DEVMODE = "dev";
|
private static final String OPTION_DEVMODE = "dev";
|
||||||
|
private static byte[] commonKey;
|
||||||
|
|
||||||
|
private static final String HOMEPATH = System.getProperty("user.home") + File.separator + ".wiiu";
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
System.out.println("JWUDTool 0.2a - Maschell");
|
System.out.println("JWUDTool 0.2a - Maschell");
|
||||||
@ -69,7 +74,8 @@ public class Main {
|
|||||||
boolean devMode = false;
|
boolean devMode = false;
|
||||||
byte[] titlekey = null;
|
byte[] titlekey = null;
|
||||||
|
|
||||||
readKey();
|
readKey(new File(HOMEPATH + File.separator + "common.key")).ifPresent(key -> Main.commonKey = key);
|
||||||
|
readKey(new File("common.key")).ifPresent(key -> Main.commonKey = key);
|
||||||
|
|
||||||
if (cmd.hasOption(OPTION_HELP)) {
|
if (cmd.hasOption(OPTION_HELP)) {
|
||||||
showHelp(options);
|
showHelp(options);
|
||||||
@ -87,7 +93,7 @@ public class Main {
|
|||||||
String commonKey = cmd.getOptionValue(OPTION_COMMON_KEY);
|
String commonKey = cmd.getOptionValue(OPTION_COMMON_KEY);
|
||||||
byte[] key = Utils.StringToByteArray(commonKey);
|
byte[] key = Utils.StringToByteArray(commonKey);
|
||||||
if (key.length == 0x10) {
|
if (key.length == 0x10) {
|
||||||
Settings.commonKey = key;
|
Main.commonKey = key;
|
||||||
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key));
|
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,15 +202,19 @@ public class Main {
|
|||||||
|
|
||||||
System.out.println("Extracting: " + inputFile.getAbsolutePath());
|
System.out.println("Extracting: " + inputFile.getAbsolutePath());
|
||||||
|
|
||||||
List<NUSTitle> titles = null;
|
WUDInfo wudInfo = null;
|
||||||
if (!devMode) {
|
if (!devMode) {
|
||||||
titles = NUSTitleLoaderWUD.loadNUSTitle(inputFile.getAbsolutePath(), titlekey);
|
wudInfo = WUDLoader.load(inputFile.getAbsolutePath(), titlekey);
|
||||||
} else {
|
} else {
|
||||||
titles = NUSTitleLoaderWUD.loadNUSTitleDev(inputFile.getAbsolutePath());
|
wudInfo = WUDLoader.loadDev(inputFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
if (titles == null || titles.isEmpty()) {
|
|
||||||
|
if (wudInfo == null) {
|
||||||
|
System.out.println("Failed to load WUX " + inputFile.getAbsolutePath());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<NUSTitle> titles = WUDLoader.getGamePartionsAsNUSTitles(wudInfo, Main.commonKey);
|
||||||
System.out.println("Found " + titles.size() + " titles on the Disc.");
|
System.out.println("Found " + titles.size() + " titles on the Disc.");
|
||||||
for (val title : titles) {
|
for (val title : titles) {
|
||||||
String newOutput = output;
|
String newOutput = output;
|
||||||
@ -241,34 +251,36 @@ public class Main {
|
|||||||
|
|
||||||
System.out.println("Decrypting: " + inputFile.getAbsolutePath());
|
System.out.println("Decrypting: " + inputFile.getAbsolutePath());
|
||||||
|
|
||||||
List<NUSTitle> titles = null;
|
WUDInfo wudInfo = null;
|
||||||
if (!devMode) {
|
if (!devMode) {
|
||||||
titles = NUSTitleLoaderWUD.loadNUSTitle(inputFile.getAbsolutePath(), titlekey);
|
wudInfo = WUDLoader.load(inputFile.getAbsolutePath(), titlekey);
|
||||||
} else {
|
} else {
|
||||||
titles = NUSTitleLoaderWUD.loadNUSTitleDev(inputFile.getAbsolutePath());
|
wudInfo = WUDLoader.loadDev(inputFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (titles == null || titles.isEmpty()) {
|
if (wudInfo == null) {
|
||||||
|
System.out.println("Failed to load Wii U Disc Image " + inputFile.getAbsolutePath());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
System.out.println("Found " + titles.size() + " titles on the Disc.");
|
|
||||||
|
List<FSTDataProvider> partitions = WUDLoader.getPartitonsAsFSTDataProvider(wudInfo, Main.commonKey);
|
||||||
for (val title : titles) {
|
System.out.println("Found " + partitions.size() + " titles on the Disc.");
|
||||||
|
|
||||||
|
for (val dp : partitions) {
|
||||||
String newOutput = output;
|
String newOutput = output;
|
||||||
System.out.println("Decrypting files in Title " + String.format("%016X", title.getTMD().getTitleID()));
|
System.out.println("Decrypting files in partition " + dp.getName());
|
||||||
if (newOutput == null) {
|
if (newOutput == null) {
|
||||||
newOutput = String.format("%016X", title.getTMD().getTitleID());
|
newOutput = dp.getName();
|
||||||
} else {
|
} else {
|
||||||
newOutput += File.separator + String.format("%016X", title.getTMD().getTitleID());
|
newOutput += File.separator + dp.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
File outputFolder = new File(newOutput);
|
File outputFolder = new File(newOutput);
|
||||||
|
|
||||||
System.out.println("To the folder: " + outputFolder.getAbsolutePath());
|
System.out.println("To the folder: " + outputFolder.getAbsolutePath());
|
||||||
title.setSkipExistingFiles(!overwrite);
|
DecryptionService decryption = DecryptionService.getInstance(dp);
|
||||||
DecryptionService decryption = DecryptionService.getInstance(title);
|
|
||||||
|
|
||||||
decryption.decryptFSTEntriesTo(regex, outputFolder.getAbsolutePath());
|
decryption.decryptFSTEntriesTo(regex, outputFolder.getAbsolutePath(), !overwrite);
|
||||||
}
|
}
|
||||||
System.out.println("Decryption done");
|
System.out.println("Decryption done");
|
||||||
}
|
}
|
||||||
@ -302,22 +314,22 @@ public class Main {
|
|||||||
}
|
}
|
||||||
System.out.println("Parsing WUD image.");
|
System.out.println("Parsing WUD image.");
|
||||||
WUDImage image = new WUDImage(inputImage);
|
WUDImage image = new WUDImage(inputImage);
|
||||||
File outputFile = null;
|
Optional<File> outputFile = Optional.empty();
|
||||||
if (!decompress) {
|
if (!decompress) {
|
||||||
outputFile = WUDService.compressWUDToWUX(image, output, overwrite);
|
outputFile = WUDService.compressWUDToWUX(image, output, overwrite);
|
||||||
if (outputFile != null) {
|
if (outputFile.isPresent()) {
|
||||||
System.out.println("Compression successful!");
|
System.out.println("Compression successful!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outputFile = WUDService.decompressWUX(image, output, overwrite);
|
outputFile = WUDService.decompressWUX(image, output, overwrite);
|
||||||
if (outputFile != null) {
|
if (outputFile.isPresent()) {
|
||||||
System.out.println("Decompression successful!");
|
System.out.println("Decompression successful!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
if (outputFile != null) {
|
if (outputFile.isPresent()) {
|
||||||
WUDImage image2 = new WUDImage(outputFile);
|
WUDImage image2 = new WUDImage(outputFile.get());
|
||||||
if (WUDService.compareWUDImage(image, image2)) {
|
if (WUDService.compareWUDImage(image, image2)) {
|
||||||
System.out.println("Compressed files is valid.");
|
System.out.println("Compressed files is valid.");
|
||||||
} else {
|
} else {
|
||||||
@ -329,13 +341,18 @@ public class Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void readKey() throws IOException {
|
private static Optional<byte[]> readKey(File file) {
|
||||||
File file = new File("common.key");
|
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
byte[] key = Files.readAllBytes(file.toPath());
|
byte[] key;
|
||||||
Settings.commonKey = key;
|
try {
|
||||||
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key));
|
key = Files.readAllBytes(file.toPath());
|
||||||
|
if (key != null && key.length == 16) {
|
||||||
|
return Optional.of(key);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Options getOptions() {
|
private static Options getOptions() {
|
||||||
|
Loading…
Reference in New Issue
Block a user