mirror of
https://github.com/Maschell/JNUSLib.git
synced 2024-11-25 09:26:55 +01:00
Add support for titles without FST.
This commit is contained in:
parent
1698acb3f6
commit
151ad6e2a6
@ -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,12 +66,22 @@ 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()));
|
||||||
|
|
||||||
byte[] fstBytes = StreamUtils.getBytesFromStream(fstContentEncryptedStream, (int) fstContent.getEncryptedFileSize());
|
byte[] fstBytes = StreamUtils.getBytesFromStream(fstContentEncryptedStream, (int) fstContent.getEncryptedFileSize());
|
||||||
|
|
||||||
if (fstContent.isEncrypted()) {
|
if (fstContent.isEncrypted()) {
|
||||||
AESDecryption aesDecryption = new AESDecryption(ticket.getDecryptedKey(), new byte[0x10]);
|
AESDecryption aesDecryption = new AESDecryption(ticket.getDecryptedKey(), new byte[0x10]);
|
||||||
if (fstBytes.length % 0x10 != 0) {
|
if (fstBytes.length % 0x10 != 0) {
|
||||||
|
@ -88,6 +88,16 @@ public class FSTEntry {
|
|||||||
param.setDir(true);
|
param.setDir(true);
|
||||||
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) {
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user