++ NPDM implementation, UI updates

This commit is contained in:
Dmitry Isaenko 2019-08-24 07:29:56 +03:00
parent bd70a7db78
commit 5dcbaff8ac
20 changed files with 2630 additions and 1459 deletions

View file

@ -15,7 +15,7 @@ import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class ChildWindow { public class ChildWindow {
public ChildWindow(ISuperProvider provider, IRowModel model) throws IOException{ public ChildWindow(ISuperProvider provider, IRowModel model) throws IOException {
Stage stageSettings = new Stage(); Stage stageSettings = new Stage();
stageSettings.setMinWidth(570); stageSettings.setMinWidth(570);
@ -23,21 +23,22 @@ public class ChildWindow {
FXMLLoader loaderSettings; FXMLLoader loaderSettings;
if (model.getFileName().endsWith(".nca")){ if (model.getFileName().endsWith(".nca")) {
loaderSettings = new FXMLLoader(getClass().getResource("/FXML/NCA/NCATab.fxml")); loaderSettings = new FXMLLoader(getClass().getResource("/FXML/NCA/NCATab.fxml"));
} } else if (model.getFileName().endsWith(".tik")) {
else if(model.getFileName().endsWith(".tik")){
loaderSettings = new FXMLLoader(getClass().getResource("/FXML/TIK/TIKTab.fxml")); loaderSettings = new FXMLLoader(getClass().getResource("/FXML/TIK/TIKTab.fxml"));
} } else if (model.getFileName().endsWith(".xml")) {
else if(model.getFileName().endsWith(".xml")){
loaderSettings = new FXMLLoader(getClass().getResource("/FXML/XML/XMLTab.fxml")); loaderSettings = new FXMLLoader(getClass().getResource("/FXML/XML/XMLTab.fxml"));
} }
else if(model.getFileName().endsWith(".npdm")){
loaderSettings = new FXMLLoader(getClass().getResource("/FXML/NPDM/NPDMTab.fxml"));
}
else if(model.getFileName().endsWith(".cert")){ else if(model.getFileName().endsWith(".cert")){
// TODO: IMPLEMENT // TODO: IMPLEMENT
return; return;
} }
else if(model.getFileName().endsWith(".cnmt")){ else if(model.getFileName().endsWith(".cnmt")){
// TODO: IMPLEMENT // todo: implement
return; return;
} }
else // TODO: Dynamic detection function else // TODO: Dynamic detection function
@ -53,6 +54,15 @@ public class ChildWindow {
XMLController myController = loaderSettings.<XMLController>getController(); XMLController myController = loaderSettings.<XMLController>getController();
myController.analyze(provider.getFile(), provider.getRawFileDataStart()+model.getFileOffset(), model.getFileSize()); myController.analyze(provider.getFile(), provider.getRawFileDataStart()+model.getFileOffset(), model.getFileSize());
} }
else if (model.getFileName().endsWith(".npdm")){
ITabController myController = loaderSettings.<ITabController>getController();
try {
myController.analyze(provider, model.getNumber());
}
catch (Exception e){
System.out.println("ERR"+e.getMessage());
}
}
else { else {
ITabController myController = loaderSettings.<ITabController>getController(); ITabController myController = loaderSettings.<ITabController>getController();
myController.analyze(provider.getFile(), provider.getRawFileDataStart()+model.getFileOffset()); myController.analyze(provider.getFile(), provider.getRawFileDataStart()+model.getFileOffset());

View file

@ -8,5 +8,6 @@ import java.io.File;
public interface ITabController extends Initializable { public interface ITabController extends Initializable {
void analyze(File file); void analyze(File file);
void analyze(File file, long offset); void analyze(File file, long offset);
void analyze(ISuperProvider parentProvider, int fileNo) throws Exception;
void resetTab(); void resetTab();
} }

View file

@ -5,6 +5,7 @@ import javafx.scene.control.Label;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import konogonka.AppPreferences; import konogonka.AppPreferences;
import konogonka.Controllers.ITabController; import konogonka.Controllers.ITabController;
import konogonka.Tools.ISuperProvider;
import konogonka.Tools.NCA.NCAContentPFS0; import konogonka.Tools.NCA.NCAContentPFS0;
import konogonka.Tools.NCA.NCAProvider; import konogonka.Tools.NCA.NCAProvider;
import konogonka.Workers.AnalyzerNCA; import konogonka.Workers.AnalyzerNCA;
@ -105,7 +106,10 @@ public class NCAController implements ITabController {
public void analyze(File file) { public void analyze(File file) {
analyze(file, 0); analyze(file, 0);
} }
@Override
public void analyze(ISuperProvider parentProvider, int fileNo) throws Exception {
throw new Exception("Not supported for NCA");
}
@Override @Override
public void resetTab() { public void resetTab() {
// Header // Header

View file

@ -1,4 +0,0 @@
package konogonka.Controllers.NPDM;
public class ACI0Provider {
}

View file

@ -1,4 +0,0 @@
package konogonka.Controllers.NPDM;
public class ACIDProvider {
}

View file

@ -4,12 +4,14 @@ import javafx.fxml.FXML;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import konogonka.Controllers.ITabController; import konogonka.Controllers.ITabController;
import konogonka.Tools.ISuperProvider;
import konogonka.Tools.NPDM.ACI0Provider;
import konogonka.Tools.NPDM.ACIDProvider;
import konogonka.Tools.NPDM.NPDMProvider; import konogonka.Tools.NPDM.NPDMProvider;
import konogonka.Workers.AnalyzerNPDM; import konogonka.Workers.AnalyzerNPDM;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;
import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import static konogonka.LoperConverter.byteArrToHexString; import static konogonka.LoperConverter.byteArrToHexString;
@ -38,21 +40,65 @@ public class NPDMController implements ITabController {
productCodeTf, productCodeTf,
reserved4Tf; reserved4Tf;
// ACI0
@FXML
private Label aci0MagicNumLbl,
aci0Reserved1Lbl,
aci0TitleIDLbl,
aci0Reserved2Lbl,
aci0FsAccessHeaderOffsetLbl,
aci0FsAccessHeaderSizeLbl,
aci0ServiceAccessControlOffsetLbl,
aci0ServiceAccessControlSizeLbl,
aci0KernelAccessControlOffsetLbl,
aci0KernelAccessControlSizeLbl,
aci0Reserved3Lbl;
// ACID
@FXML TextField acidRsa2048signatureTf,
acidRsa2048publicKeyTf;
@FXML
private Label acidMagicNumLbl,
acidDataSizeLbl,
acidReserved1Lbl,
acidFlag1Lbl,
acidFlag2Lbl,
acidFlag3Lbl,
acidFlag4Lbl,
acidTitleRangeMinLbl,
acidTitleRangeMaxLbl,
acidFsAccessControlOffsetLbl,
acidFsAccessControlSizeLbl,
acidServiceAccessControlOffsetLbl,
acidServiceAccessControlSizeLbl,
acidKernelAccessControlOffsetLbl,
acidKernelAccessControlSizeLbl,
acidReserved2Lbl;
@Override @Override
public void initialize(URL url, ResourceBundle resourceBundle) { } public void initialize(URL url, ResourceBundle resourceBundle) { }
@Override @Override
public void analyze(File file) { analyze(file, 0); } public void analyze(File file) { analyze(file, 0); }
@Override
public void analyze(ISuperProvider parentProvider, int fileNo) throws Exception {
AnalyzerNPDM analyzerNPDM = new AnalyzerNPDM(parentProvider, fileNo);
analyzerNPDM.setOnSucceeded(e->{
NPDMProvider npdm = analyzerNPDM.getValue();
setData(npdm, null);
});
Thread workThread = new Thread(analyzerNPDM);
workThread.setDaemon(true);
workThread.start();
}
@Override @Override
public void analyze(File file, long offset) { public void analyze(File file, long offset) {
AnalyzerNPDM analyzerNPDM = new AnalyzerNPDM(file, offset); AnalyzerNPDM analyzerNPDM = new AnalyzerNPDM(file, offset);
analyzerNPDM.setOnSucceeded(e->{ analyzerNPDM.setOnSucceeded(e->{
NPDMProvider tik = analyzerNPDM.getValue(); NPDMProvider npdm = analyzerNPDM.getValue();
if (offset == 0) if (offset == 0)
setData(tik, file); setData(npdm, file);
else else
setData(tik, null); setData(npdm, null);
}); });
Thread workThread = new Thread(analyzerNPDM); Thread workThread = new Thread(analyzerNPDM);
workThread.setDaemon(true); workThread.setDaemon(true);
@ -79,6 +125,38 @@ public class NPDMController implements ITabController {
productCodeTf.setText("-"); productCodeTf.setText("-");
reserved4Tf.setText("-"); reserved4Tf.setText("-");
npdmFileSize.setText("-"); npdmFileSize.setText("-");
// ACI0
aci0MagicNumLbl.setText("-");
aci0Reserved1Lbl.setText("-");
aci0TitleIDLbl.setText("-");
aci0Reserved2Lbl.setText("-");
aci0FsAccessHeaderOffsetLbl.setText("-");
aci0FsAccessHeaderSizeLbl.setText("-");
aci0ServiceAccessControlOffsetLbl.setText("-");
aci0ServiceAccessControlSizeLbl.setText("-");
aci0KernelAccessControlOffsetLbl.setText("-");
aci0KernelAccessControlSizeLbl.setText("-");
aci0Reserved3Lbl.setText("-");
// ACID
acidRsa2048signatureTf.setText("-");
acidRsa2048publicKeyTf.setText("-");
acidMagicNumLbl.setText("-");
acidDataSizeLbl.setText("-");
acidReserved1Lbl.setText("-");
acidFlag1Lbl.setText("-");
acidFlag2Lbl.setText("-");
acidFlag3Lbl.setText("-");
acidFlag4Lbl.setText("-");
acidTitleRangeMinLbl.setText("-");
acidTitleRangeMaxLbl.setText("-");
acidFsAccessControlOffsetLbl.setText("-");
acidFsAccessControlSizeLbl.setText("-");
acidServiceAccessControlOffsetLbl.setText("-");
acidServiceAccessControlSizeLbl.setText("-");
acidKernelAccessControlOffsetLbl.setText("-");
acidKernelAccessControlSizeLbl.setText("-");
acidReserved2Lbl.setText("-");
} }
private void setData(NPDMProvider npdmProvider, File file) { private void setData(NPDMProvider npdmProvider, File file) {
if (npdmProvider == null) if (npdmProvider == null)
@ -101,10 +179,42 @@ public class NPDMController implements ITabController {
titleNameTf.setText(npdmProvider.getTitleName()); titleNameTf.setText(npdmProvider.getTitleName());
productCodeTf.setText(byteArrToHexString(npdmProvider.getProductCode())); productCodeTf.setText(byteArrToHexString(npdmProvider.getProductCode()));
reserved4Tf.setText(byteArrToHexString(npdmProvider.getReserved4())); reserved4Tf.setText(byteArrToHexString(npdmProvider.getReserved4()));
aci0offsetLbl.setText(Long.toString(npdmProvider.getAci0offset())); aci0offsetLbl.setText(Integer.toString(npdmProvider.getAci0offset()));
aci0sizeLbl.setText(Long.toString(npdmProvider.getAci0size())); aci0sizeLbl.setText(Integer.toString(npdmProvider.getAci0size()));
acidOffsetLbl.setText(Long.toString(npdmProvider.getAcidOffset())); acidOffsetLbl.setText(Integer.toString(npdmProvider.getAcidOffset()));
acidSizeLbl.setText(Long.toString(npdmProvider.getAcidSize())); acidSizeLbl.setText(Integer.toString(npdmProvider.getAcidSize()));
// ACI0
ACI0Provider aci0 = npdmProvider.getAci0();
aci0MagicNumLbl.setText(aci0.getMagicNum());
aci0Reserved1Lbl.setText(byteArrToHexString(aci0.getReserved1()));
aci0TitleIDLbl.setText(byteArrToHexString(aci0.getTitleID()));
aci0Reserved2Lbl.setText(byteArrToHexString(aci0.getReserved2()));
aci0FsAccessHeaderOffsetLbl.setText(Integer.toString(aci0.getFsAccessHeaderOffset()));
aci0FsAccessHeaderSizeLbl.setText(Integer.toString(aci0.getFsAccessHeaderSize()));
aci0ServiceAccessControlOffsetLbl.setText(Integer.toString(aci0.getServiceAccessControlOffset()));
aci0ServiceAccessControlSizeLbl.setText(Integer.toString(aci0.getServiceAccessControlSize()));
aci0KernelAccessControlOffsetLbl.setText(Integer.toString(aci0.getKernelAccessControlOffset()));
aci0KernelAccessControlSizeLbl.setText(Integer.toString(aci0.getKernelAccessControlSize()));
aci0Reserved3Lbl.setText(byteArrToHexString(aci0.getReserved3()));
// ACID
ACIDProvider acid = npdmProvider.getAcid();
acidRsa2048signatureTf.setText(byteArrToHexString(acid.getRsa2048signature()));
acidRsa2048publicKeyTf.setText(byteArrToHexString(acid.getRsa2048publicKey()));
acidMagicNumLbl.setText(acid.getMagicNum());
acidDataSizeLbl.setText(Integer.toString(acid.getDataSize()));
acidReserved1Lbl.setText(byteArrToHexString(acid.getReserved1()));
acidFlag1Lbl.setText(String.format("0x%02x", acid.getFlag1()));
acidFlag2Lbl.setText(String.format("0x%02x", acid.getFlag2()));
acidFlag3Lbl.setText(String.format("0x%02x", acid.getFlag3()));
acidFlag4Lbl.setText(String.format("0x%02x", acid.getFlag4()));
acidTitleRangeMinLbl.setText(Long.toString(acid.getTitleRangeMin()));
acidTitleRangeMaxLbl.setText(Long.toString(acid.getTitleRangeMax()));
acidFsAccessControlOffsetLbl.setText(Integer.toString(acid.getFsAccessControlOffset()));
acidFsAccessControlSizeLbl.setText(Integer.toString(acid.getFsAccessControlSize()));
acidServiceAccessControlOffsetLbl.setText(Integer.toString(acid.getServiceAccessControlOffset()));
acidServiceAccessControlSizeLbl.setText(Integer.toString(acid.getServiceAccessControlSize()));
acidKernelAccessControlOffsetLbl.setText(Integer.toString(acid.getKernelAccessControlOffset()));
acidKernelAccessControlSizeLbl.setText(Integer.toString(acid.getKernelAccessControlSize()));
acidReserved2Lbl.setText(byteArrToHexString(acid.getReserved2()));
} }
}
}

View file

@ -108,6 +108,10 @@ public class NSPController implements ITabController {
workThread.setDaemon(true); workThread.setDaemon(true);
workThread.start(); workThread.start();
} }
@Override
public void analyze(ISuperProvider parentProvider, int fileNo) throws Exception {
throw new Exception("Not supported for NSP");
}
/** /**
* Just populate fields by already analyzed PFS0 * Just populate fields by already analyzed PFS0
* */ * */

View file

@ -6,6 +6,7 @@ import javafx.scene.control.Label;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import konogonka.AppPreferences; import konogonka.AppPreferences;
import konogonka.Controllers.ITabController; import konogonka.Controllers.ITabController;
import konogonka.Tools.ISuperProvider;
import konogonka.Tools.TIK.TIKProvider; import konogonka.Tools.TIK.TIKProvider;
import konogonka.Workers.AnalyzerTIK; import konogonka.Workers.AnalyzerTIK;
@ -61,7 +62,10 @@ public class TIKController implements ITabController {
@Override @Override
public void analyze(File file) { analyze(file, 0); } public void analyze(File file) { analyze(file, 0); }
@Override
public void analyze(ISuperProvider parentProvider, int fileNo) throws Exception {
throw new Exception("Not supported for TIK");
}
@Override @Override
public void analyze(File file, long offset) { public void analyze(File file, long offset) {
AnalyzerTIK analyzerTIK = new AnalyzerTIK(file, offset); AnalyzerTIK analyzerTIK = new AnalyzerTIK(file, offset);

View file

@ -107,6 +107,10 @@ public class XCIController implements ITabController {
workThread.start(); workThread.start();
} }
@Override @Override
public void analyze(ISuperProvider parentProvider, int fileNo) throws Exception {
throw new Exception("Not supported for XCI");
}
@Override
public void resetTab(){ public void resetTab(){
HFSBlockController.setSelectedFile(null); HFSBlockController.setSelectedFile(null);
/* Header */ /* Header */

View file

@ -4,6 +4,7 @@ import javafx.fxml.FXML;
import javafx.scene.control.TextArea; import javafx.scene.control.TextArea;
import konogonka.Controllers.ITabController; import konogonka.Controllers.ITabController;
import konogonka.MediatorControl; import konogonka.MediatorControl;
import konogonka.Tools.ISuperProvider;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
@ -14,7 +15,6 @@ import java.util.ResourceBundle;
public class XMLController implements ITabController { public class XMLController implements ITabController {
@FXML @FXML
private TextArea mainTa; private TextArea mainTa;
@Override @Override
@ -47,6 +47,7 @@ public class XMLController implements ITabController {
MediatorControl.getInstance().getContoller().logArea.appendText("XMLController -> analyze(): \n"+e.getMessage()); MediatorControl.getInstance().getContoller().logArea.appendText("XMLController -> analyze(): \n"+e.getMessage());
} }
} }
/** /**
* Read from offset to length * Read from offset to length
* */ * */
@ -68,6 +69,10 @@ public class XMLController implements ITabController {
} }
} }
@Override @Override
public void analyze(ISuperProvider parentProvider, int fileNo) throws Exception {
throw new Exception("Not supported for XML");
}
@Override
public void resetTab() { public void resetTab() {
mainTa.setText(null); mainTa.setText(null);
} }

View file

@ -0,0 +1,23 @@
package konogonka.Tools;
import java.io.IOException;
import java.io.PipedInputStream;
/**
* Create prototype of the provider that created and works with pipes only
* */
public abstract class ASuperInFileProvider {
protected byte[] readFromStream(PipedInputStream pis, int size) throws IOException {
byte[] buffer = new byte[size];
int startingPos = 0;
int readCnt;
while (size > 0){
readCnt = pis.read(buffer, startingPos, size);
if (readCnt == -1)
return null;
startingPos += readCnt;
size -= readCnt;
}
return buffer;
}
}

View file

@ -163,7 +163,7 @@ public class NCAProvider {
else else
cryptoTypeReal = cryptoType1; cryptoTypeReal = cryptoType1;
if (cryptoTypeReal > 0) // TODO: CLARIFY WHY THEH FUCK IS IT FAIR???? if (cryptoTypeReal > 0) // TODO: CLARIFY WHY THE FUCK IS IT FAIR????
cryptoTypeReal -= 1; cryptoTypeReal -= 1;
//todo: if nca3 proceed //todo: if nca3 proceed
@ -193,6 +193,8 @@ public class NCAProvider {
decryptedKey2 = cipher.doFinal(encryptedKey2); decryptedKey2 = cipher.doFinal(encryptedKey2);
decryptedKey3 = cipher.doFinal(encryptedKey3); decryptedKey3 = cipher.doFinal(encryptedKey3);
} }
else
throw new Exception("key_are_key_[UNKNOWN] requested ("+keyIndex+"). Not supported.");
} }
tableEntry0 = new NCAHeaderTableEntry(tableBytes); tableEntry0 = new NCAHeaderTableEntry(tableBytes);
@ -244,6 +246,7 @@ public class NCAProvider {
public NCASectionBlock getSectionBlock1() { return sectionBlock1; } public NCASectionBlock getSectionBlock1() { return sectionBlock1; }
public NCASectionBlock getSectionBlock2() { return sectionBlock2; } public NCASectionBlock getSectionBlock2() { return sectionBlock2; }
public NCASectionBlock getSectionBlock3() { return sectionBlock3; } public NCASectionBlock getSectionBlock3() { return sectionBlock3; }
public boolean isKeyAvailable(){ // TODO: USE public boolean isKeyAvailable(){ // TODO: USE
if (Arrays.equals(rightsId, new byte[0x10])) if (Arrays.equals(rightsId, new byte[0x10]))
return true; return true;

View file

@ -0,0 +1,48 @@
package konogonka.Tools.NPDM;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import static konogonka.LoperConverter.getLEint;
public class ACI0Provider {
private String magicNum;
private byte[] reserved1;
private byte[] titleID;
private byte[] reserved2;
private int fsAccessHeaderOffset;
private int fsAccessHeaderSize;
private int serviceAccessControlOffset;
private int serviceAccessControlSize;
private int kernelAccessControlOffset;
private int kernelAccessControlSize;
private byte[] reserved3;
public ACI0Provider(byte[] aci0bytes) throws Exception{
if (aci0bytes.length < 0x40)
throw new Exception("ACI0 size is too short");
magicNum = new String(aci0bytes, 0, 0x4, StandardCharsets.UTF_8);
reserved1 = Arrays.copyOfRange(aci0bytes, 0x4, 0x10);
titleID = Arrays.copyOfRange(aci0bytes, 0x10, 0x18);
reserved2 = Arrays.copyOfRange(aci0bytes, 0x18, 0x20);
fsAccessHeaderOffset = getLEint(aci0bytes, 0x20);
fsAccessHeaderSize = getLEint(aci0bytes, 0x24);
serviceAccessControlOffset = getLEint(aci0bytes, 0x28);
serviceAccessControlSize = getLEint(aci0bytes, 0x2C);
kernelAccessControlOffset = getLEint(aci0bytes, 0x30);
kernelAccessControlSize = getLEint(aci0bytes, 0x34);
reserved3 = Arrays.copyOfRange(aci0bytes, 0x38, 0x40);
}
public String getMagicNum() { return magicNum; }
public byte[] getReserved1() { return reserved1; }
public byte[] getTitleID() { return titleID; }
public byte[] getReserved2() { return reserved2; }
public int getFsAccessHeaderOffset() { return fsAccessHeaderOffset; }
public int getFsAccessHeaderSize() { return fsAccessHeaderSize; }
public int getServiceAccessControlOffset() { return serviceAccessControlOffset; }
public int getServiceAccessControlSize() { return serviceAccessControlSize; }
public int getKernelAccessControlOffset() { return kernelAccessControlOffset; }
public int getKernelAccessControlSize() { return kernelAccessControlSize; }
public byte[] getReserved3() { return reserved3; }
}

View file

@ -0,0 +1,70 @@
package konogonka.Tools.NPDM;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import static konogonka.LoperConverter.*;
public class ACIDProvider {
private byte[] rsa2048signature;
private byte[] rsa2048publicKey;
private String magicNum;
private int dataSize;
private byte[] reserved1;
private byte flag1;
private byte flag2;
private byte flag3;
private byte flag4;
private long titleRangeMin;
private long titleRangeMax;
private int fsAccessControlOffset;
private int fsAccessControlSize;
private int serviceAccessControlOffset;
private int serviceAccessControlSize;
private int kernelAccessControlOffset;
private int kernelAccessControlSize;
private byte[] reserved2;
public ACIDProvider(byte[] acidBytes) throws Exception{
if (acidBytes.length < 0x240)
throw new Exception("ACI0 size is too short");
rsa2048signature = Arrays.copyOfRange(acidBytes, 0, 0x100);
rsa2048publicKey = Arrays.copyOfRange(acidBytes, 0x100, 0x200);
magicNum = new String(acidBytes, 0x200, 0x4, StandardCharsets.UTF_8);
dataSize = getLEint(acidBytes, 0x204);
reserved1 = Arrays.copyOfRange(acidBytes, 0x208, 0x20C);
flag1 = acidBytes[0x20C];
flag2 = acidBytes[0x20D];
flag3 = acidBytes[0x20E];
flag4 = acidBytes[0x20F];
titleRangeMin = getLElong(acidBytes, 0x210);
titleRangeMax = getLElong(acidBytes, 0x218);
fsAccessControlOffset = getLEint(acidBytes, 0x220);
fsAccessControlSize = getLEint(acidBytes, 0x224);
serviceAccessControlOffset = getLEint(acidBytes, 0x228);
serviceAccessControlSize = getLEint(acidBytes, 0x22C);
kernelAccessControlOffset = getLEint(acidBytes, 0x230);
kernelAccessControlSize = getLEint(acidBytes, 0x234);
reserved2 = Arrays.copyOfRange(acidBytes, 0x238, 0x240);
}
public byte[] getRsa2048signature() { return rsa2048signature; }
public byte[] getRsa2048publicKey() { return rsa2048publicKey; }
public String getMagicNum() { return magicNum; }
public int getDataSize() { return dataSize; }
public byte[] getReserved1() { return reserved1; }
public byte getFlag1() { return flag1; }
public byte getFlag2() { return flag2; }
public byte getFlag3() { return flag3; }
public byte getFlag4() { return flag4; }
public long getTitleRangeMin() { return titleRangeMin; }
public long getTitleRangeMax() { return titleRangeMax; }
public int getFsAccessControlOffset() { return fsAccessControlOffset; }
public int getFsAccessControlSize() { return fsAccessControlSize; }
public int getServiceAccessControlOffset() { return serviceAccessControlOffset; }
public int getServiceAccessControlSize() { return serviceAccessControlSize; }
public int getKernelAccessControlOffset() { return kernelAccessControlOffset; }
public int getKernelAccessControlSize() { return kernelAccessControlSize; }
public byte[] getReserved2() { return reserved2; }
}

View file

@ -1,13 +1,14 @@
package konogonka.Tools.NPDM; package konogonka.Tools.NPDM;
import java.io.File; import konogonka.Tools.ASuperInFileProvider;
import java.io.RandomAccessFile;
import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import static konogonka.LoperConverter.*; import static konogonka.LoperConverter.*;
public class NPDMProvider { public class NPDMProvider extends ASuperInFileProvider {
private String magicNum; private String magicNum;
private byte[] reserved1; private byte[] reserved1;
@ -22,12 +23,63 @@ public class NPDMProvider {
private String titleName; private String titleName;
private byte[] productCode; private byte[] productCode;
private byte[] reserved4; private byte[] reserved4;
private long aci0offset; // originally 4-bytes (u-int) private int aci0offset; // originally 4-bytes (u-int)
private long aci0size; // originally 4-bytes (u-int) private int aci0size; // originally 4-bytes (u-int)
private long acidOffset; // originally 4-bytes (u-int) private int acidOffset; // originally 4-bytes (u-int)
private long acidSize; // originally 4-bytes (u-int) private int acidSize; // originally 4-bytes (u-int)
public NPDMProvider(File file) throws Exception { this(file, 0); } private ACI0Provider aci0;
private ACIDProvider acid;
public NPDMProvider(PipedInputStream pis) throws Exception{
byte[] mainBuf = new byte[0x80];
if(pis.read(mainBuf) != 0x80)
throw new Exception("NPDMProvider: Failed to read 'META'");
aci0offset = getLEint(mainBuf, 0x70);
aci0size = getLEint(mainBuf, 0x74);
acidOffset = getLEint(mainBuf, 0x78);
acidSize = getLEint(mainBuf, 0x7C);
byte[] aci0Buf;
byte[] acidBuf;
if (aci0offset < acidOffset){
if (pis.skip(aci0offset - 0x80) != (aci0offset - 0x80))
throw new Exception("NPDMProvider: Failed to skip bytes till 'ACI0'");
if ((aci0Buf = readFromStream(pis, aci0size)) == null)
throw new Exception("NPDMProvider: Failed to read 'ACI0'");
if (pis.skip(acidOffset - aci0offset - aci0size) != (acidOffset - aci0offset - aci0size))
throw new Exception("NPDMProvider: Failed to skip bytes till 'ACID'");
if ((acidBuf = readFromStream(pis, acidSize)) == null)
throw new Exception("NPDMProvider: Failed to read 'ACID'");
}
else {
if (pis.skip(acidOffset - 0x80) != (acidOffset - 0x80))
throw new Exception("NPDMProvider: Failed to skip bytes till 'ACID'");
if ((acidBuf = readFromStream(pis, acidSize)) == null)
throw new Exception("NPDMProvider: Failed to read 'ACID'");
if (pis.skip(aci0offset - acidOffset - acidSize) != (aci0offset - acidOffset - acidSize))
throw new Exception("NPDMProvider: Failed to skip bytes till 'ACI0'");
if ((aci0Buf = readFromStream(pis, aci0size)) == null)
throw new Exception("NPDMProvider: Failed to read 'ACI0'");
}
magicNum = new String(mainBuf, 0, 4, StandardCharsets.UTF_8);
reserved1 = Arrays.copyOfRange(mainBuf, 0x4, 0xC);
MMUFlags = mainBuf[0xC];
reserved2 = mainBuf[0xD];
mainThreadPrio = mainBuf[0xE];
mainThreadCoreNum = mainBuf[0xF];
reserved3 = Arrays.copyOfRange(mainBuf, 0x10, 0x14);
personalMmHeapSize = getLEint(mainBuf, 0x14);
version = getLEint(mainBuf, 0x18);
mainThreadStackSize = getLElongOfInt(mainBuf, 0x1C);
titleName = new String(mainBuf, 0x20, 0x10, StandardCharsets.UTF_8);
productCode = Arrays.copyOfRange(mainBuf, 0x30, 0x40);
reserved4 = Arrays.copyOfRange(mainBuf, 0x40, 0x70);
aci0 = new ACI0Provider(aci0Buf);
acid = new ACIDProvider(acidBuf);
}
public NPDMProvider(File file) throws Exception { this(file, 0); }
public NPDMProvider(File file, long offset) throws Exception { public NPDMProvider(File file, long offset) throws Exception {
if (file.length() - offset < 0x80) // Header's size if (file.length() - offset < 0x80) // Header's size
@ -51,10 +103,23 @@ public class NPDMProvider {
titleName = new String(metaBuf, 0x20, 0x10, StandardCharsets.UTF_8); titleName = new String(metaBuf, 0x20, 0x10, StandardCharsets.UTF_8);
productCode = Arrays.copyOfRange(metaBuf, 0x30, 0x40); productCode = Arrays.copyOfRange(metaBuf, 0x30, 0x40);
reserved4 = Arrays.copyOfRange(metaBuf, 0x40, 0x70); reserved4 = Arrays.copyOfRange(metaBuf, 0x40, 0x70);
aci0offset = getLElongOfInt(metaBuf, 0x70); aci0offset = getLEint(metaBuf, 0x70);
aci0size = getLElongOfInt(metaBuf, 0x74); aci0size = getLEint(metaBuf, 0x74);
acidOffset = getLElongOfInt(metaBuf, 0x78); acidOffset = getLEint(metaBuf, 0x78);
acidSize = getLElongOfInt(metaBuf, 0x7C); acidSize = getLEint(metaBuf, 0x7C);
// Get ACI0
raf.seek(aci0offset);
metaBuf = new byte[aci0size]; // TODO: NOTE: we read all size but need only header
if (raf.read(metaBuf) != aci0size)
throw new Exception("NPDMProvider: Failed to read 'ACI0'");
aci0 = new ACI0Provider(metaBuf);
// Get ACID
raf.seek(acidOffset);
metaBuf = new byte[acidSize]; // TODO: NOTE: we read all size but need only header
if (raf.read(metaBuf) != acidSize)
throw new Exception("NPDMProvider: Failed to read 'ACID'");
acid = new ACIDProvider(metaBuf);
raf.close();
} }
public String getMagicNum() { return magicNum; } public String getMagicNum() { return magicNum; }
@ -70,8 +135,11 @@ public class NPDMProvider {
public String getTitleName() { return titleName; } public String getTitleName() { return titleName; }
public byte[] getProductCode() { return productCode; } public byte[] getProductCode() { return productCode; }
public byte[] getReserved4() { return reserved4; } public byte[] getReserved4() { return reserved4; }
public long getAci0offset() { return aci0offset; } public int getAci0offset() { return aci0offset; }
public long getAci0size() { return aci0size; } public int getAci0size() { return aci0size; }
public long getAcidOffset() { return acidOffset; } public int getAcidOffset() { return acidOffset; }
public long getAcidSize() { return acidSize; } public int getAcidSize() { return acidSize; }
public ACI0Provider getAci0() { return aci0; }
public ACIDProvider getAcid() { return acid; }
} }

View file

@ -245,7 +245,7 @@ public class PFS0EncryptedProvider implements IPFS0Provider{
streamOut.write(dectyptedBlock, 0, extraData); streamOut.write(dectyptedBlock, 0, extraData);
} }
else { else {
System.out.println("PFS0EncryptedProvider -> getProviderSubFilePipedInpStream(): Unable to get 512 bytes from 1st bock"); System.out.println("PFS0EncryptedProvider -> getProviderSubFilePipedInpStream(): Unable to get 512 bytes from bock");
return; return;
} }
} }
@ -256,7 +256,7 @@ public class PFS0EncryptedProvider implements IPFS0Provider{
streamOut.write(dectyptedBlock, 0, 0x200 + extraData); streamOut.write(dectyptedBlock, 0, 0x200 + extraData);
} }
else { else {
System.out.println("PFS0EncryptedProvider -> getProviderSubFilePipedInpStream(): Unable to get 512 bytes from 1st bock"); System.out.println("PFS0EncryptedProvider -> getProviderSubFilePipedInpStream(): Unable to get 512 bytes from last bock");
return; return;
} }
} }

View file

@ -3,6 +3,7 @@ package konogonka.Workers;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import konogonka.ModelControllers.EMsgType; import konogonka.ModelControllers.EMsgType;
import konogonka.ModelControllers.LogPrinter; import konogonka.ModelControllers.LogPrinter;
import konogonka.Tools.ISuperProvider;
import konogonka.Tools.NPDM.NPDMProvider; import konogonka.Tools.NPDM.NPDMProvider;
import java.io.File; import java.io.File;
@ -13,6 +14,15 @@ public class AnalyzerNPDM extends Task<NPDMProvider> {
private long offset; private long offset;
private LogPrinter logPrinter; private LogPrinter logPrinter;
private ISuperProvider parentProvider;
private int fileNo;
public AnalyzerNPDM(ISuperProvider parentProvider, int fileNo){
this.parentProvider = parentProvider;
this.fileNo = fileNo;
this.logPrinter = new LogPrinter();
}
public AnalyzerNPDM(File file){ public AnalyzerNPDM(File file){
this(file, 0); this(file, 0);
} }
@ -27,7 +37,10 @@ public class AnalyzerNPDM extends Task<NPDMProvider> {
protected NPDMProvider call() { protected NPDMProvider call() {
logPrinter.print("\tStart chain: NPDM", EMsgType.INFO); logPrinter.print("\tStart chain: NPDM", EMsgType.INFO);
try{ try{
return new NPDMProvider(file, offset); if (parentProvider != null)
return new NPDMProvider(parentProvider.getProviderSubFilePipedInpStream(fileNo));
else
return new NPDMProvider(file, offset);
} }
catch (Exception e){ catch (Exception e){
logPrinter.print("\tException: "+e.getMessage(), EMsgType.FAIL); logPrinter.print("\tException: "+e.getMessage(), EMsgType.FAIL);

View file

@ -44,6 +44,7 @@ public class NspXciExtractor extends Task<Void> {
readBuf = new byte[0x800000]; readBuf = new byte[0x800000];
//*** PROGRESS BAR DECORCATIONS START //*** PROGRESS BAR DECORCATIONS START
progressHandleFRead += readSize; progressHandleFRead += readSize;
System.out.println(readSize);
try { try {
logPrinter.updateProgress((progressHandleFRead)/(progressHandleFSize/100.0) / 100.0); logPrinter.updateProgress((progressHandleFRead)/(progressHandleFSize/100.0) / 100.0);
}catch (InterruptedException ie){ }catch (InterruptedException ie){

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff