diff --git a/src/main/java/konogonka/Controllers/NSP/NSPController.java b/src/main/java/konogonka/Controllers/NSP/NSPController.java index 590f57c..c7998a1 100644 --- a/src/main/java/konogonka/Controllers/NSP/NSPController.java +++ b/src/main/java/konogonka/Controllers/NSP/NSPController.java @@ -51,7 +51,8 @@ public class NSPController implements ITabController { ISuperProvider provider = tableFilesListController.getProvider(); if (models != null && !models.isEmpty() && (provider != null)){ - File dir = new File(System.getProperty("user.dir")+File.separator+selectedFile.getName()+" extracted"); // todo: move option to settings + //File dir = new File(System.getProperty("user.dir")+File.separator+selectedFile.getName()+" extracted"); // todo: move option to settings + File dir = new File(System.getProperty("user.dir")+File.separator+provider.getFile().getName()+" extracted"); // todo: move option to settings try { dir.mkdir(); } diff --git a/src/main/java/konogonka/Controllers/TIK/TIKController.java b/src/main/java/konogonka/Controllers/TIK/TIKController.java index 88d367a..d9cb518 100644 --- a/src/main/java/konogonka/Controllers/TIK/TIKController.java +++ b/src/main/java/konogonka/Controllers/TIK/TIKController.java @@ -1,9 +1,12 @@ package konogonka.Controllers.TIK; import javafx.fxml.FXML; +import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; +import konogonka.AppPreferences; import konogonka.Controllers.ITabController; +import konogonka.MediatorControl; import konogonka.Tools.TIK.TIKProvider; import konogonka.Workers.AnalyzerTIK; @@ -14,7 +17,8 @@ import java.util.ResourceBundle; import static konogonka.LoperConverter.byteArrToHexString; public class TIKController implements ITabController { - + @FXML + private Button btnImport; @FXML private Label sigTypeLbl, sigTypeStrLbl, @@ -35,11 +39,28 @@ public class TIKController implements ITabController { @FXML private TextField signatureTF, issuerTf, - titleKeyBlockTf, + titleKeyBlockStartTf, + titleKeyBlockEndTf, rightsIdTf; @Override - public void initialize(URL url, ResourceBundle resourceBundle) { } + public void initialize(URL url, ResourceBundle resourceBundle) { + btnImport.setOnAction(e -> { + String key = rightsIdTf.getText(); + String value = titleKeyBlockStartTf.getText(); + int titleKeysCnt = AppPreferences.getInstance().getTitleKeysCount(); + System.out.println(key+" "+value+" "+titleKeysCnt); + if (key.length() > 16 && ! (key.length() > 32) && value.length() == 32){ + System.out.println("OK"); + for (int i = 0; i < titleKeysCnt; i++){ + if (AppPreferences.getInstance().getTitleKeyPair(i)[0].equals(key)) + return; + } + AppPreferences.getInstance().setTitleKey(titleKeysCnt, key+" = "+value); + AppPreferences.getInstance().setTitleKeysCount(titleKeysCnt+1); + } + }); + } @Override public void analyze(File file) { analyze(file, 0); } @@ -115,8 +136,9 @@ public class TIKController implements ITabController { } signatureTF.setText(byteArrToHexString(tikProvider.getSignature())); - issuerTf.setText(byteArrToHexString(tikProvider.getIssuer())); - titleKeyBlockTf.setText(byteArrToHexString(tikProvider.getTitleKeyBlock())); + issuerTf.setText(tikProvider.getIssuer()); + titleKeyBlockStartTf.setText(byteArrToHexString(tikProvider.getTitleKeyBlockStartingBytes())); + titleKeyBlockEndTf.setText(byteArrToHexString(tikProvider.getTitleKeyBlockEndingBytes())); unknown1Lbl.setText(String.format("0x%02x", tikProvider.getUnknown1())); titleKeyTypeLbl.setText(String.format("0x%02x", tikProvider.getTitleKeyType())); unknown2Lbl.setText(byteArrToHexString(tikProvider.getUnknown2())); @@ -127,9 +149,11 @@ public class TIKController implements ITabController { rightsIdTf.setText(byteArrToHexString(tikProvider.getRightsId())); accountIdLbl.setText(byteArrToHexString(tikProvider.getAccountId())); unknown4Lbl.setText(byteArrToHexString(tikProvider.getUnknown4())); + btnImport.setDisable(false); } @Override public void resetTab() { + btnImport.setDisable(true); sigTypeLbl.setText("-"); sigTypeStrLbl.setText("-"); tikSizeLbl.setText("-"); @@ -139,7 +163,8 @@ public class TIKController implements ITabController { signatureTF.setText("-"); issuerTf.setText("-"); - titleKeyBlockTf.setText("-"); + titleKeyBlockStartTf.setText("-"); + titleKeyBlockEndTf.setText("-"); unknown1Lbl.setText("-"); titleKeyTypeLbl.setText("-"); unknown2Lbl.setText("-"); diff --git a/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java b/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java index bcfce2a..12a09dd 100644 --- a/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java +++ b/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java @@ -1,10 +1,12 @@ package konogonka.Controllers.XCI; +import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; @@ -17,6 +19,7 @@ import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.util.Callback; import konogonka.Controllers.IRowModel; +import konogonka.MediatorControl; import konogonka.Tools.ISuperProvider; import konogonka.Tools.XCI.HFS0Provider; @@ -152,6 +155,22 @@ public class Hfs0TableViewController implements Initializable { @Override public TableRow call(TableView nslHfs0RowModelTableView) { final TableRow row = new TableRow<>(); + ContextMenu contextMenu = new ContextMenu(); + + MenuItem openMenuItem = new MenuItem("Open"); + openMenuItem.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent actionEvent) { + MediatorControl.getInstance().getContoller().showContentWindow(provider, row.getItem()); // TODO: change to something better + } + }); + + contextMenu.getItems().addAll(openMenuItem); + + row.setContextMenu(contextMenu); + row.contextMenuProperty().bind( + Bindings.when(Bindings.isNotNull(row.itemProperty())).then(contextMenu).otherwise((ContextMenu)null) + ); row.setOnMouseClicked(new EventHandler() { // Just.. don't ask.. @Override public void handle(MouseEvent mouseEvent) { diff --git a/src/main/java/konogonka/Tools/PFS0/PFS0EncryptedProvider.java b/src/main/java/konogonka/Tools/PFS0/PFS0EncryptedProvider.java index 0f3e20f..4848fe5 100644 --- a/src/main/java/konogonka/Tools/PFS0/PFS0EncryptedProvider.java +++ b/src/main/java/konogonka/Tools/PFS0/PFS0EncryptedProvider.java @@ -163,10 +163,10 @@ public class PFS0EncryptedProvider implements IPFS0Provider{ try { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); // Let's store what we're about to skip - int skipBytes = (int) (offsetPositionInFile + (mediaStartOffset * 0x200)); + long skipInitL = offsetPositionInFile + (mediaStartOffset * 0x200); // NOTE: NEVER cast to int. // Check if skip was successful - if (bis.skip(skipBytes) != skipBytes) { - System.out.println("PFS0EncryptedProvider -> getPfs0subFilePipedInpStream(): Failed to skip range "+skipBytes); + if (bis.skip(skipInitL) != skipInitL) { + System.out.println("PFS0EncryptedProvider -> getPfs0subFilePipedInpStream(): Failed to skip range "+skipInitL); return; } @@ -178,6 +178,7 @@ public class PFS0EncryptedProvider implements IPFS0Provider{ //----------------------------- Pre-set: skip non-necessary data -------------------------------- long startBlock = (rawBlockDataStart + pfs0subFiles[subFileNumber].getOffset()) / 0x200; // <- pointing to place where actual data starts + int skipBytes; if (startBlock > 0) { aesCtrDecryptSimple.skipNext(startBlock); diff --git a/src/main/java/konogonka/Tools/TIK/TIKProvider.java b/src/main/java/konogonka/Tools/TIK/TIKProvider.java index 0906caa..18d4c94 100644 --- a/src/main/java/konogonka/Tools/TIK/TIKProvider.java +++ b/src/main/java/konogonka/Tools/TIK/TIKProvider.java @@ -1,11 +1,9 @@ package konogonka.Tools.TIK; -import konogonka.RainbowHexDump; - import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; -import java.lang.reflect.Array; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import static konogonka.LoperConverter.*; @@ -54,8 +52,9 @@ public class TIKProvider { private byte[] sigType; private byte[] signature; // Ticket - private byte[] Issuer; - private byte[] TitleKeyBlock; // Actually 32 bytes. Check against WIKI + private String Issuer; + private byte[] TitleKeyBlockStartingBytes; // Actually 32 bytes. + private byte[] TitleKeyBlockEndingBytes; // Anything else private byte Unknown1; private byte TitleKeyType; private byte[] Unknown2; @@ -64,6 +63,7 @@ public class TIKProvider { private byte[] TicketId; private byte[] DeviceId; private byte[] RightsId; + private byte[] RightsIdEndingBytes; private byte[] AccountId; private byte[] Unknown4; @@ -129,8 +129,9 @@ public class TIKProvider { } bis.close(); - Issuer = Arrays.copyOfRange(readChunk, 0, 0x40); - TitleKeyBlock = Arrays.copyOfRange(readChunk, 0x40, 0x140); + Issuer = new String(readChunk, 0, 0x40, StandardCharsets.UTF_8); + TitleKeyBlockStartingBytes = Arrays.copyOfRange(readChunk, 0x40, 0x50); + TitleKeyBlockEndingBytes = Arrays.copyOfRange(readChunk, 0x50, 0x140); Unknown1 = readChunk[0x140]; TitleKeyType = readChunk[0x141]; Unknown2 = Arrays.copyOfRange(readChunk, 0x142, 0x145); @@ -146,8 +147,9 @@ public class TIKProvider { public byte[] getSigType() { return sigType; } public byte[] getSignature() { return signature; } - public byte[] getIssuer() { return Issuer; } - public byte[] getTitleKeyBlock() { return TitleKeyBlock; } + public String getIssuer() { return Issuer; } + public byte[] getTitleKeyBlockStartingBytes() { return TitleKeyBlockStartingBytes; } + public byte[] getTitleKeyBlockEndingBytes() { return TitleKeyBlockEndingBytes; } public byte getUnknown1() { return Unknown1; } public byte getTitleKeyType() { return TitleKeyType; } public byte[] getUnknown2() { return Unknown2; } diff --git a/src/main/java/konogonka/Workers/NspXciExtractor.java b/src/main/java/konogonka/Workers/NspXciExtractor.java index 144da85..1ba3415 100644 --- a/src/main/java/konogonka/Workers/NspXciExtractor.java +++ b/src/main/java/konogonka/Workers/NspXciExtractor.java @@ -67,93 +67,4 @@ public class NspXciExtractor extends Task { } return null; } - /* - private long rawDataStartPos; - private List models; - private String filesDestPath; - private LogPrinter logPrinter; - private File NspXciFile; - - - - public NspXciExtractor(long rawDataStartPos, List models, String filesDestPath, File NspXciFile){ - this.rawDataStartPos = rawDataStartPos; - this.models = models; - this.filesDestPath = filesDestPath; - this.NspXciFile = NspXciFile; - this.logPrinter = new LogPrinter(); - } - - @Override - protected Void call() { - logPrinter.print("\tStart extracting", EMsgType.INFO); - for (IRowModel model: models){ - logPrinter.print(filesDestPath+model.getFileName(), EMsgType.INFO); - File contentFile = new File(filesDestPath+model.getFileName()); - - long realFileOffset = rawDataStartPos + model.getFileOffset(); - long realFileSize = model.getFileSize(); - - long readFrom = 0; - - int readPice = 8388608; // 8mb NOTE: consider switching to 1mb 1048576 - byte[] readBuf; - - try{ - BufferedOutputStream extractedFileOS = new BufferedOutputStream(new FileOutputStream(contentFile)); - - BufferedInputStream bufferedInStream = new BufferedInputStream(new FileInputStream(NspXciFile)); // TODO: refactor? - if (bufferedInStream.skip(realFileOffset) != realFileOffset) { - logPrinter.print("File length is less than offset noted", EMsgType.FAIL); - return null; - } - - while (readFrom < realFileSize){ - - // if (isCancelled()) // Check if user interrupted process. - // return false; - - if (realFileSize - readFrom < readPice) - readPice = Math.toIntExact(realFileSize - readFrom); // it's safe, I guarantee - readBuf = new byte[readPice]; - if (bufferedInStream.read(readBuf) != readPice) { - logPrinter.print("Can't read required chunk from file", EMsgType.FAIL); - return null; - } - - extractedFileOS.write(readBuf, 0, readPice); - //-----------------------------------------/ - try { - logPrinter.updateProgress((readFrom+readPice)/(realFileSize/100.0) / 100.0); - }catch (InterruptedException ie){ - getException().printStackTrace(); // TODO: Do something with this - } - //-----------------------------------------/ - readFrom += readPice; - } - bufferedInStream.close(); - extractedFileOS.close(); - //-----------------------------------------/ - try{ - logPrinter.updateProgress(1.0); - } - catch (InterruptedException ie){ - getException().printStackTrace(); // TODO: Do something with this - } - //-----------------------------------------/ - } - catch (IOException ioe){ - logPrinter.print("\tRead/Write error\n\t"+ioe.getMessage(), EMsgType.INFO); - return null; - } - } - close(); - return null; - } - - private void close(){ - logPrinter.print("\tEnd extracting", EMsgType.INFO); - logPrinter.close(); - } - */ } \ No newline at end of file diff --git a/src/main/resources/FXML/TIK/TIKTab.fxml b/src/main/resources/FXML/TIK/TIKTab.fxml index 014c2d2..a291d36 100644 --- a/src/main/resources/FXML/TIK/TIKTab.fxml +++ b/src/main/resources/FXML/TIK/TIKTab.fxml @@ -1,15 +1,18 @@ + + + @@ -206,7 +209,7 @@ - + @@ -215,6 +218,7 @@ + @@ -225,7 +229,7 @@ - + - + - + - + - + - + - + - + - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + - - - - - + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + @@ -698,6 +725,15 @@ + +
+ +
+