diff --git a/README.md b/README.md
index 75a78d4..59aa9e4 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,14 @@ JRE/JDK 8u60 or higher.
### Checklist
+* [X] NSP (PFS0)
+* [X] XCI (+HFS0)
+* [X] TIK
+* [X] XML
+
* [ ] LogPrinter to singleton implementation
* [ ] NPDM support
* [ ] CNMT support
-* [ ] NSO support
\ No newline at end of file
+* [ ] NSO support
+* [ ] RomFS deep-dive
+* [ ] 'Save to folder' option
\ No newline at end of file
diff --git a/src/main/java/konogonka/Controllers/NPDM/FSAccessControlController.java b/src/main/java/konogonka/Controllers/NPDM/FSAccessControlController.java
new file mode 100644
index 0000000..b94e238
--- /dev/null
+++ b/src/main/java/konogonka/Controllers/NPDM/FSAccessControlController.java
@@ -0,0 +1,188 @@
+package konogonka.Controllers.NPDM;
+
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import konogonka.Tools.NPDM.FSAccessControlProvider;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+import static konogonka.LoperConverter.byteArrToHexString;
+
+public class FSAccessControlController implements Initializable {
+ @FXML
+ private Label ACID_FSAcccessControlVersionLbl,
+ ACID_FSAcccessControlPaddingLbl,
+ ACID_FSAcccessControlBitbaskLbl;
+ @FXML
+ private TextField ACID_FSAcccessControlReservedTf;
+
+ @FXML
+ private Label mask0,
+ mask1,
+ mask2,
+ mask3,
+ mask4,
+ mask5,
+ mask6,
+ mask7,
+ mask8,
+ mask9,
+ mask10,
+ mask11,
+ mask12,
+ mask13,
+ mask14,
+ mask15,
+ mask16,
+ mask17,
+ mask18,
+ mask19,
+ mask20,
+ mask21,
+ mask22,
+ mask23,
+ mask24,
+ mask25,
+ mask26,
+ mask27,
+ mask28,
+ mask29,
+ mask30,
+ mask31,
+ mask32,
+ mask33,
+ mask34,
+ mask35,
+ mask36,
+ mask37,
+ mask38,
+ mask39,
+ mask40,
+ mask41,
+ mask42,
+ mask43,
+ mask44,
+ mask45,
+ mask46,
+ mask47,
+ mask48,
+ mask49,
+ mask50,
+ mask51,
+ mask52,
+ mask53,
+ mask54,
+ mask55,
+ mask56,
+ mask57,
+ mask58,
+ mask59,
+ mask60,
+ mask61,
+ mask62,
+ mask63;
+
+ private Label[] masksArr;
+ @Override
+ public void initialize(URL url, ResourceBundle resourceBundle) {
+ masksArr = new Label[64];
+ masksArr[0] = mask0;
+ masksArr[1] = mask1;
+ masksArr[2] = mask2;
+ masksArr[3] = mask3;
+ masksArr[4] = mask4;
+ masksArr[5] = mask5;
+ masksArr[6] = mask6;
+ masksArr[7] = mask7;
+ masksArr[8] = mask8;
+ masksArr[9] = mask9;
+ masksArr[10] = mask10;
+ masksArr[11] = mask11;
+ masksArr[12] = mask12;
+ masksArr[13] = mask13;
+ masksArr[14] = mask14;
+ masksArr[15] = mask15;
+ masksArr[16] = mask16;
+ masksArr[17] = mask17;
+ masksArr[18] = mask18;
+ masksArr[19] = mask19;
+ masksArr[20] = mask20;
+ masksArr[21] = mask21;
+ masksArr[22] = mask22;
+ masksArr[23] = mask23;
+ masksArr[24] = mask24;
+ masksArr[25] = mask25;
+ masksArr[26] = mask26;
+ masksArr[27] = mask27;
+ masksArr[28] = mask28;
+ masksArr[29] = mask29;
+ masksArr[30] = mask30;
+ masksArr[31] = mask31;
+ masksArr[32] = mask32;
+ masksArr[33] = mask33;
+ masksArr[34] = mask34;
+ masksArr[35] = mask35;
+ masksArr[36] = mask36;
+ masksArr[37] = mask37;
+ masksArr[38] = mask38;
+ masksArr[39] = mask39;
+ masksArr[40] = mask40;
+ masksArr[41] = mask41;
+ masksArr[42] = mask42;
+ masksArr[43] = mask43;
+ masksArr[44] = mask44;
+ masksArr[45] = mask45;
+ masksArr[46] = mask46;
+ masksArr[47] = mask47;
+ masksArr[48] = mask48;
+ masksArr[49] = mask49;
+ masksArr[50] = mask50;
+ masksArr[51] = mask51;
+ masksArr[52] = mask52;
+ masksArr[53] = mask53;
+ masksArr[54] = mask54;
+ masksArr[55] = mask55;
+ masksArr[56] = mask56;
+ masksArr[57] = mask57;
+ masksArr[58] = mask58;
+ masksArr[59] = mask59;
+ masksArr[60] = mask60;
+ masksArr[61] = mask61;
+ masksArr[62] = mask62;
+ masksArr[63] = mask63;
+ }
+
+ public void resetTab() {
+ ACID_FSAcccessControlVersionLbl.setText("-");
+ ACID_FSAcccessControlPaddingLbl.setText("-");
+ ACID_FSAcccessControlBitbaskLbl.setText("-");
+ ACID_FSAcccessControlReservedTf.setText("-");
+
+ for (int i = 0; i < 64; i++)
+ masksArr[i].setText("-");
+ }
+
+ public void populateFields(FSAccessControlProvider provider){
+ ACID_FSAcccessControlVersionLbl.setText(String.format("0x%02x", provider.getVersion()));
+ ACID_FSAcccessControlPaddingLbl.setText(byteArrToHexString(provider.getPadding()));
+ ACID_FSAcccessControlBitbaskLbl.setText(byteArrToHexString(provider.getPermissionsBitmask()));
+ ACID_FSAcccessControlReservedTf.setText(byteArrToHexString(provider.getReserved()));
+
+ byte[] permissionsBitmask = provider.getPermissionsBitmask();
+ String mask =
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[7] & 0xFF)).replace(' ', '0')+
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[6] & 0xFF)).replace(' ', '0')+
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[5] & 0xFF)).replace(' ', '0')+
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[4] & 0xFF)).replace(' ', '0')+
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[3] & 0xFF)).replace(' ', '0')+
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[2] & 0xFF)).replace(' ', '0')+
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[1] & 0xFF)).replace(' ', '0')+
+ String.format("%8s", Integer.toBinaryString(permissionsBitmask[0] & 0xFF)).replace(' ', '0');
+
+ for (int i = 0; i < 64; i++)
+ masksArr[i].setText(mask.substring(i, i+1));
+ }
+}
diff --git a/src/main/java/konogonka/Controllers/NPDM/NPDMController.java b/src/main/java/konogonka/Controllers/NPDM/NPDMController.java
index 2224100..21a8ddb 100644
--- a/src/main/java/konogonka/Controllers/NPDM/NPDMController.java
+++ b/src/main/java/konogonka/Controllers/NPDM/NPDMController.java
@@ -55,7 +55,8 @@ public class NPDMController implements ITabController {
aci0KernelAccessControlSizeLbl,
aci0Reserved3Lbl;
// ACID
- @FXML TextField acidRsa2048signatureTf,
+ @FXML
+ TextField acidRsa2048signatureTf,
acidRsa2048publicKeyTf;
@FXML
private Label acidMagicNumLbl,
@@ -74,6 +75,8 @@ public class NPDMController implements ITabController {
acidKernelAccessControlOffsetLbl,
acidKernelAccessControlSizeLbl,
acidReserved2Lbl;
+ @FXML
+ private FSAccessControlController FSAccessControlTableController;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) { }
@@ -158,6 +161,8 @@ public class NPDMController implements ITabController {
acidKernelAccessControlOffsetLbl.setText("-");
acidKernelAccessControlSizeLbl.setText("-");
acidReserved2Lbl.setText("-");
+
+ FSAccessControlTableController.resetTab();
}
private void setData(NPDMProvider npdmProvider, File file) {
if (npdmProvider == null)
@@ -217,5 +222,7 @@ public class NPDMController implements ITabController {
acidKernelAccessControlOffsetLbl.setText(Integer.toString(acid.getKernelAccessControlOffset()));
acidKernelAccessControlSizeLbl.setText(Integer.toString(acid.getKernelAccessControlSize()));
acidReserved2Lbl.setText(byteArrToHexString(acid.getReserved2()));
+
+ FSAccessControlTableController.populateFields(acid.getFSAccessControlProvider());
}
}
\ No newline at end of file
diff --git a/src/main/java/konogonka/Tools/ASuperInFileProvider.java b/src/main/java/konogonka/Tools/ASuperInFileProvider.java
index 7813a09..79fc333 100644
--- a/src/main/java/konogonka/Tools/ASuperInFileProvider.java
+++ b/src/main/java/konogonka/Tools/ASuperInFileProvider.java
@@ -4,8 +4,9 @@ import java.io.IOException;
import java.io.PipedInputStream;
/**
- * Create prototype of the provider that created and works with pipes only
+ * Any class of this type must be able to accept data from stream (and file as any other).
* */
+
public abstract class ASuperInFileProvider {
protected byte[] readFromStream(PipedInputStream pis, int size) throws IOException {
byte[] buffer = new byte[size];
diff --git a/src/main/java/konogonka/Tools/ISuperProvider.java b/src/main/java/konogonka/Tools/ISuperProvider.java
index 730bc30..aad2ef6 100644
--- a/src/main/java/konogonka/Tools/ISuperProvider.java
+++ b/src/main/java/konogonka/Tools/ISuperProvider.java
@@ -2,7 +2,9 @@ package konogonka.Tools;
import java.io.File;
import java.io.PipedInputStream;
-
+/**
+ * Any class of this type must provide streams
+ * */
public interface ISuperProvider {
PipedInputStream getProviderSubFilePipedInpStream(String subFileName) throws Exception;
PipedInputStream getProviderSubFilePipedInpStream(int subFileNumber) throws Exception;
diff --git a/src/main/java/konogonka/Tools/NPDM/ACI0Provider.java b/src/main/java/konogonka/Tools/NPDM/ACI0Provider.java
index 4c8bd0f..6acd59a 100644
--- a/src/main/java/konogonka/Tools/NPDM/ACI0Provider.java
+++ b/src/main/java/konogonka/Tools/NPDM/ACI0Provider.java
@@ -18,7 +18,7 @@ public class ACI0Provider {
private int kernelAccessControlSize;
private byte[] reserved3;
- public ACI0Provider(byte[] aci0bytes) throws Exception{
+ 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);
diff --git a/src/main/java/konogonka/Tools/NPDM/ACIDProvider.java b/src/main/java/konogonka/Tools/NPDM/ACIDProvider.java
index c1f68fe..bed9327 100644
--- a/src/main/java/konogonka/Tools/NPDM/ACIDProvider.java
+++ b/src/main/java/konogonka/Tools/NPDM/ACIDProvider.java
@@ -26,9 +26,12 @@ public class ACIDProvider {
private int kernelAccessControlSize;
private byte[] reserved2;
+ private FSAccessControlProvider fsAccessControlProvider;
+
+
public ACIDProvider(byte[] acidBytes) throws Exception{
if (acidBytes.length < 0x240)
- throw new Exception("ACI0 size is too short");
+ throw new Exception("ACIDProvider -> 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);
@@ -47,6 +50,9 @@ public class ACIDProvider {
kernelAccessControlOffset = getLEint(acidBytes, 0x230);
kernelAccessControlSize = getLEint(acidBytes, 0x234);
reserved2 = Arrays.copyOfRange(acidBytes, 0x238, 0x240);
+ if (fsAccessControlOffset > serviceAccessControlOffset || serviceAccessControlOffset > kernelAccessControlOffset )
+ throw new Exception("ACIDProvider -> blocks inside the ACID are not sorted in ascending order. Only ascending order supported.");
+ fsAccessControlProvider = new FSAccessControlProvider(Arrays.copyOfRange(acidBytes, fsAccessControlOffset, fsAccessControlOffset+fsAccessControlSize));
}
public byte[] getRsa2048signature() { return rsa2048signature; }
@@ -67,4 +73,7 @@ public class ACIDProvider {
public int getKernelAccessControlOffset() { return kernelAccessControlOffset; }
public int getKernelAccessControlSize() { return kernelAccessControlSize; }
public byte[] getReserved2() { return reserved2; }
+
+ public FSAccessControlProvider getFSAccessControlProvider() { return fsAccessControlProvider; }
+
}
\ No newline at end of file
diff --git a/src/main/java/konogonka/Tools/NPDM/FSAccessControlProvider.java b/src/main/java/konogonka/Tools/NPDM/FSAccessControlProvider.java
new file mode 100644
index 0000000..543e1ed
--- /dev/null
+++ b/src/main/java/konogonka/Tools/NPDM/FSAccessControlProvider.java
@@ -0,0 +1,26 @@
+package konogonka.Tools.NPDM;
+
+import java.util.Arrays;
+
+/**
+ * For ACID Provider
+ * */
+public class FSAccessControlProvider {
+
+ private byte version;
+ private byte[] padding;
+ private byte[] permissionsBitmask; // ??? Where each byte representing 255-long bit-bask of the thing it representing. Like 0x01 bit-mask for ApplicationInfo
+ private byte[] reserved;
+
+ public FSAccessControlProvider(byte[] bytes) {
+ version = bytes[0];
+ padding = Arrays.copyOfRange(bytes, 1, 0x4);
+ permissionsBitmask = Arrays.copyOfRange(bytes, 0x4, 0xC);
+ reserved = Arrays.copyOfRange(bytes, 0xC, 0x2C);
+ }
+
+ public byte getVersion() { return version; }
+ public byte[] getPadding() { return padding; }
+ public byte[] getPermissionsBitmask() { return permissionsBitmask; }
+ public byte[] getReserved() { return reserved; }
+}
diff --git a/src/main/resources/FXML/NPDM/FSAccessControlTable.fxml b/src/main/resources/FXML/NPDM/FSAccessControlTable.fxml
new file mode 100644
index 0000000..9113685
--- /dev/null
+++ b/src/main/resources/FXML/NPDM/FSAccessControlTable.fxml
@@ -0,0 +1,1317 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/FXML/NPDM/NPDMTab.fxml b/src/main/resources/FXML/NPDM/NPDMTab.fxml
index 7c79b0d..7196e98 100644
--- a/src/main/resources/FXML/NPDM/NPDMTab.fxml
+++ b/src/main/resources/FXML/NPDM/NPDMTab.fxml
@@ -439,447 +439,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1175,6 +734,449 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+