Add support for titles without FST.

This commit is contained in:
Maschell 2019-04-14 14:50:01 +02:00
parent 1698acb3f6
commit 151ad6e2a6
3 changed files with 41 additions and 2 deletions

View File

@ -27,6 +27,9 @@ import de.mas.wiiu.jnus.entities.TMD;
import de.mas.wiiu.jnus.entities.Ticket; import de.mas.wiiu.jnus.entities.Ticket;
import de.mas.wiiu.jnus.entities.content.Content; import de.mas.wiiu.jnus.entities.content.Content;
import de.mas.wiiu.jnus.entities.fst.FST; import de.mas.wiiu.jnus.entities.fst.FST;
import de.mas.wiiu.jnus.entities.fst.FSTEntry;
import de.mas.wiiu.jnus.implementations.FSTDataProviderNUSTitle;
import de.mas.wiiu.jnus.interfaces.FSTDataProvider;
import de.mas.wiiu.jnus.interfaces.NUSDataProvider; import de.mas.wiiu.jnus.interfaces.NUSDataProvider;
import de.mas.wiiu.jnus.utils.StreamUtils; import de.mas.wiiu.jnus.utils.StreamUtils;
import de.mas.wiiu.jnus.utils.cryptography.AESDecryption; import de.mas.wiiu.jnus.utils.cryptography.AESDecryption;
@ -63,6 +66,16 @@ public class NUSTitleLoader {
} }
result.setTicket(ticket); result.setTicket(ticket);
// If we have just content, we don't have a FST.
if (tmd.getAllContents().size() == 1) {
// The only way to check if the key is right, is by trying to decrypt the whole thing.
FSTDataProvider dp = new FSTDataProviderNUSTitle(result);
for (FSTEntry children : dp.getRoot().getChildren()) {
dp.readFile(children);
}
return result;
}
// If we have more than one content, the index 0 is the FST.
Content fstContent = tmd.getContentByIndex(0); Content fstContent = tmd.getContentByIndex(0);
InputStream fstContentEncryptedStream = dataProvider.getInputStreamFromContent(fstContent, 0, Optional.of(fstContent.getEncryptedFileSize())); InputStream fstContentEncryptedStream = dataProvider.getInputStreamFromContent(fstContent, 0, Optional.of(fstContent.getEncryptedFileSize()));

View File

@ -89,6 +89,16 @@ public class FSTEntry {
return new FSTEntry(param); return new FSTEntry(param);
} }
public static FSTEntry createFSTEntry(FSTEntry parent, String filename, Content content) {
FSTEntryParam param = new FSTEntryParam();
param.setFileNameSupplier(() -> filename);
param.setFileSize(content.getDecryptedFileSize());
param.setContent(content);
param.setDir(false);
param.setParent(parent);
return new FSTEntry(param);
}
public String getFilename() { public String getFilename() {
if (filename == null) { if (filename == null) {
filename = filenameSupplier.get(); filename = filenameSupplier.get();

View File

@ -21,9 +21,11 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
import de.mas.wiiu.jnus.NUSTitle; import de.mas.wiiu.jnus.NUSTitle;
import de.mas.wiiu.jnus.entities.content.Content; import de.mas.wiiu.jnus.entities.content.Content;
import de.mas.wiiu.jnus.entities.fst.FST;
import de.mas.wiiu.jnus.entities.fst.FSTEntry; import de.mas.wiiu.jnus.entities.fst.FSTEntry;
import de.mas.wiiu.jnus.interfaces.FSTDataProvider; import de.mas.wiiu.jnus.interfaces.FSTDataProvider;
import de.mas.wiiu.jnus.interfaces.HasNUSTitle; import de.mas.wiiu.jnus.interfaces.HasNUSTitle;
@ -38,16 +40,30 @@ import lombok.extern.java.Log;
@Log @Log
public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle { public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
private final NUSTitle title; private final NUSTitle title;
private final FSTEntry rootEntry;
@Getter @Setter private String name; @Getter @Setter private String name;
public FSTDataProviderNUSTitle(NUSTitle title) { public FSTDataProviderNUSTitle(NUSTitle title) {
this.title = title; this.title = title;
this.name = String.format("%016X", title.getTMD().getTitleID()); this.name = String.format("%016X", title.getTMD().getTitleID());
FST fst = title.getFST();
if (fst != null) {
rootEntry = title.getFST().getRoot();
} else if (title.getTMD().getContentCount() == 1) {
// If the tmd has only one content file, it has not FST. We have to create our own FST.
Content c = title.getTMD().getAllContents().values().stream().collect(Collectors.toList()).get(0);
FSTEntry root = FSTEntry.getRootFSTEntry();
FSTEntry.createFSTEntry(root, "data.bin", c); // Will add this title root.
rootEntry = root;
} else {
rootEntry = null;
}
} }
@Override @Override
public FSTEntry getRoot() { public FSTEntry getRoot() {
return title.getFST().getRoot(); return rootEntry;
} }
@Override @Override