diff --git a/pom.xml b/pom.xml
index c8a5a5b..fa5f880 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
konogonka
konogonka
- 0.0.2-SNAPSHOT
+ 0.0.3-SNAPSHOT
https://github.com/developersu/${project.name}}/
diff --git a/src/main/java/konogonka/Controllers/MainController.java b/src/main/java/konogonka/Controllers/MainController.java
index bd112c4..2c92c43 100644
--- a/src/main/java/konogonka/Controllers/MainController.java
+++ b/src/main/java/konogonka/Controllers/MainController.java
@@ -21,6 +21,8 @@ package konogonka.Controllers;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
+import javafx.scene.input.DragEvent;
+import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import konogonka.AppPreferences;
@@ -35,10 +37,10 @@ import konogonka.Controllers.XML.XMLController;
import konogonka.MediatorControl;
import konogonka.Settings.SettingsWindow;
import konogonka.Tools.ISuperProvider;
-import konogonka.Tools.TIK.TIKProvider;
import java.io.*;
import java.net.URL;
+import java.util.List;
import java.util.ResourceBundle;
public class MainController implements Initializable {
@@ -187,6 +189,21 @@ public class MainController implements Initializable {
RFSTabController.analyze(selectedFile);
}
}
+ private boolean isNotSupportedFileFormat(String fileExtension){
+ switch (fileExtension){
+ case "nsp":
+ case "nsz":
+ case "xci":
+ case "nca":
+ case "tic":
+ case "xml":
+ case "npdm":
+ case "romfs":
+ return false;
+ default:
+ return true;
+ }
+ }
@FXML
private void showHideLogs(){
if (splitPane.getItems().size() == 2)
@@ -194,6 +211,50 @@ public class MainController implements Initializable {
else
splitPane.getItems().add(logPane);
}
+ /**
+ * Drag-n-drop support (dragOver consumer)
+ * */
+ @FXML
+ private void handleDragOver(DragEvent event){
+ event.acceptTransferModes(TransferMode.ANY);
+
+ event.consume();
+ }
+ /**
+ * Drag-n-drop support (drop consumer)
+ * */
+ @FXML
+ private void handleDrop(DragEvent event){
+ List filesDropped = event.getDragboard().getFiles();
+
+ if ( filesDropped.isEmpty() ) {
+ event.setDropCompleted(true);
+ event.consume();
+ return;
+ }
+
+ File droppedFile = filesDropped.get(0);
+
+ String fileExtension = droppedFile.getName().toLowerCase().replaceAll("^.*\\.", "");
+
+ if (isNotSupportedFileFormat(fileExtension)) {
+ event.setDropCompleted(true);
+ event.consume();
+ return;
+ }
+
+ selectedFile = droppedFile;
+
+ resetAllTabsContent();
+ filenameSelected.setText(selectedFile.getAbsolutePath());
+ previouslyOpenedPath = selectedFile.getParent();
+ analyzeBtn.setDisable(false);
+ setFocusOnPane(fileExtension);
+
+ event.setDropCompleted(true);
+ event.consume();
+ }
+
public void showContentWindow(ISuperProvider provider, IRowModel model){
try{
new ChildWindow(provider, model);
diff --git a/src/main/java/konogonka/Controllers/NSP/Pfs0TableViewController.java b/src/main/java/konogonka/Controllers/NSP/Pfs0TableViewController.java
index 31ca473..a0cdd86 100644
--- a/src/main/java/konogonka/Controllers/NSP/Pfs0TableViewController.java
+++ b/src/main/java/konogonka/Controllers/NSP/Pfs0TableViewController.java
@@ -18,11 +18,8 @@
*/
package konogonka.Controllers.NSP;
-import javafx.beans.Observable;
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;
@@ -35,8 +32,6 @@ import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
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;
@@ -44,7 +39,6 @@ import konogonka.Tools.PFS0.IPFS0Provider;
import java.net.URL;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
@@ -82,13 +76,13 @@ public class Pfs0TableViewController implements Initializable {
TableColumn fileNameColumn = new TableColumn<>(resourceBundle.getString("tableFileNameLbl"));
TableColumn fileOffsetColumn = new TableColumn<>(resourceBundle.getString("tableOffsetLbl"));
TableColumn fileSizeColumn = new TableColumn<>(resourceBundle.getString("tableSizeLbl"));
- TableColumn uploadColumn = new TableColumn<>(resourceBundle.getString("tableUploadLbl"));
+ TableColumn checkBoxColumn = new TableColumn<>(resourceBundle.getString("tableUploadLbl"));
numberColumn.setEditable(false);
fileNameColumn.setEditable(false);
fileOffsetColumn.setEditable(false);
fileSizeColumn.setEditable(false);
- uploadColumn.setEditable(true);
+ checkBoxColumn.setEditable(true);
// See https://bugs.openjdk.java.net/browse/JDK-8157687
numberColumn.setMinWidth(30.0);
@@ -108,17 +102,17 @@ public class Pfs0TableViewController implements Initializable {
fileSizeColumn.setMaxWidth(120.0);
fileSizeColumn.setResizable(false);
- uploadColumn.setMinWidth(120.0);
- uploadColumn.setPrefWidth(120.0);
- uploadColumn.setMaxWidth(120.0);
- uploadColumn.setResizable(false);
+ checkBoxColumn.setMinWidth(120.0);
+ checkBoxColumn.setPrefWidth(120.0);
+ checkBoxColumn.setMaxWidth(120.0);
+ checkBoxColumn.setResizable(false);
numberColumn.setCellValueFactory(new PropertyValueFactory<>("number"));
fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("fileName"));
fileSizeColumn.setCellValueFactory(new PropertyValueFactory<>("fileSize"));
fileOffsetColumn.setCellValueFactory(new PropertyValueFactory<>("fileOffset"));
// ><
- uploadColumn.setCellValueFactory(paramFeatures -> {
+ checkBoxColumn.setCellValueFactory(paramFeatures -> {
Pfs0RowModel model = paramFeatures.getValue();
SimpleBooleanProperty booleanProperty = new SimpleBooleanProperty(model.isMarkSelected());
@@ -130,7 +124,7 @@ public class Pfs0TableViewController implements Initializable {
return booleanProperty;
});
- uploadColumn.setCellFactory(paramFeatures -> new CheckBoxTableCell<>());
+ checkBoxColumn.setCellFactory(paramFeatures -> new CheckBoxTableCell<>());
table.setRowFactory( // this shit is made to implement context menu. It's such a pain..
Pfs0RowModelTableView -> {
final TableRow row = new TableRow<>();
@@ -167,6 +161,7 @@ public class Pfs0TableViewController implements Initializable {
table.getColumns().add(fileNameColumn);
table.getColumns().add(fileOffsetColumn);
table.getColumns().add(fileSizeColumn);
+ table.getColumns().add(checkBoxColumn);
}
/**
* Add files when user selected them
diff --git a/src/main/java/konogonka/Controllers/RFS/RFSEntry.java b/src/main/java/konogonka/Controllers/RFS/RFSEntry.java
new file mode 100644
index 0000000..e72e2d0
--- /dev/null
+++ b/src/main/java/konogonka/Controllers/RFS/RFSEntry.java
@@ -0,0 +1,59 @@
+/*
+ Copyright 2019-2020 Dmitry Isaenko
+
+ This file is part of Konogonka.
+
+ Konogonka is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Konogonka is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Konogonka. If not, see .
+*/
+package konogonka.Controllers.RFS;
+
+import konogonka.Controllers.IRowModel;
+import konogonka.Tools.RomFs.FileSystemEntry;
+
+public class RFSEntry implements IRowModel {
+ private FileSystemEntry fileSystemEntry;
+ private boolean check;
+
+ public RFSEntry(FileSystemEntry fileSystemEntry){
+ this.fileSystemEntry = fileSystemEntry;
+ }
+
+ public boolean isDirectory(){
+ return fileSystemEntry.isDirectory();
+ }
+
+ @Override
+ public String toString(){
+ return fileSystemEntry.getName();
+ }
+
+
+ @Override
+ public int getNumber() { return 0; }
+
+ @Override
+ public String getFileName() { return fileSystemEntry.getName(); }
+
+ @Override
+ public long getFileSize() { return fileSystemEntry.getFileSize(); }
+
+ @Override
+ public long getFileOffset() { return fileSystemEntry.getFileOffset(); }
+
+ @Override
+ public boolean isMarkSelected() { return check; }
+
+ @Override
+ public void setMarkSelected(boolean value) { check = value; }
+}
\ No newline at end of file
diff --git a/src/main/java/konogonka/Controllers/RFS/RFSFolderEntry.java b/src/main/java/konogonka/Controllers/RFS/RFSFolderEntry.java
deleted file mode 100644
index bfcea98..0000000
--- a/src/main/java/konogonka/Controllers/RFS/RFSFolderEntry.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- Copyright 2019-2020 Dmitry Isaenko
-
- This file is part of Konogonka.
-
- Konogonka is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Konogonka is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Konogonka. If not, see .
-*/
-package konogonka.Controllers.RFS;
-
-public class RFSFolderEntry {
- private String name;
-
- public RFSFolderEntry(String name){
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public String toString(){
- return name;
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/konogonka/Controllers/RFS/RFSFolderTableViewController.java b/src/main/java/konogonka/Controllers/RFS/RFSFolderTableViewController.java
new file mode 100644
index 0000000..b793539
--- /dev/null
+++ b/src/main/java/konogonka/Controllers/RFS/RFSFolderTableViewController.java
@@ -0,0 +1,172 @@
+/*
+ Copyright 2019-2020 Dmitry Isaenko
+
+ This file is part of Konogonka.
+
+ Konogonka is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Konogonka is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Konogonka. If not, see .
+*/
+package konogonka.Controllers.RFS;
+
+import javafx.beans.binding.Bindings;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.*;
+import javafx.scene.control.cell.CheckBoxTableCell;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.MouseButton;
+import konogonka.Controllers.IRowModel;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+public class RFSFolderTableViewController implements Initializable {
+ @FXML
+ private TableView table;
+ private ObservableList rowsObsLst;
+
+ @Override
+ public void initialize(URL url, ResourceBundle resourceBundle) {
+ rowsObsLst = FXCollections.observableArrayList();
+
+ table.setPlaceholder(new Label());
+ table.setEditable(false); // At least with hacks it works as expected. Otherwise - null pointer exception
+ table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
+ table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
+ table.setOnKeyPressed(keyEvent -> {
+ if (!rowsObsLst.isEmpty()) {
+ if (keyEvent.getCode() == KeyCode.SPACE) {
+ for (RFSEntry item : table.getSelectionModel().getSelectedItems()) {
+ item.setMarkSelected( ! item.isMarkSelected());
+ }
+ table.refresh();
+ }
+ }
+ keyEvent.consume();
+ });
+
+ TableColumn numberColumn = new TableColumn<>(resourceBundle.getString("tableNumberLbl"));
+ TableColumn fileNameColumn = new TableColumn<>(resourceBundle.getString("tableFileNameLbl"));
+ TableColumn fileOffsetColumn = new TableColumn<>(resourceBundle.getString("tableOffsetLbl"));
+ TableColumn fileSizeColumn = new TableColumn<>(resourceBundle.getString("tableSizeLbl"));
+ TableColumn checkBoxColumn = new TableColumn<>(resourceBundle.getString("tableUploadLbl"));
+
+ numberColumn.setEditable(false);
+ fileNameColumn.setEditable(false);
+ fileOffsetColumn.setEditable(false);
+ fileSizeColumn.setEditable(false);
+ checkBoxColumn.setEditable(true);
+
+ // See https://bugs.openjdk.java.net/browse/JDK-8157687
+ numberColumn.setMinWidth(30.0);
+ numberColumn.setPrefWidth(30.0);
+ numberColumn.setMaxWidth(30.0);
+ numberColumn.setResizable(false);
+
+ fileNameColumn.setMinWidth(25.0);
+
+ fileOffsetColumn.setMinWidth(130.0);
+ fileOffsetColumn.setPrefWidth(130.0);
+ fileOffsetColumn.setMaxWidth(130.0);
+ fileOffsetColumn.setResizable(false);
+
+ fileSizeColumn.setMinWidth(120.0);
+ fileSizeColumn.setPrefWidth(120.0);
+ fileSizeColumn.setMaxWidth(120.0);
+ fileSizeColumn.setResizable(false);
+
+ checkBoxColumn.setMinWidth(120.0);
+ checkBoxColumn.setPrefWidth(120.0);
+ checkBoxColumn.setMaxWidth(120.0);
+ checkBoxColumn.setResizable(false);
+
+ numberColumn.setCellValueFactory(new PropertyValueFactory<>("number"));
+ fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("fileName"));
+ fileSizeColumn.setCellValueFactory(new PropertyValueFactory<>("fileSize"));
+ fileOffsetColumn.setCellValueFactory(new PropertyValueFactory<>("fileOffset"));
+
+ // ><
+ checkBoxColumn.setCellValueFactory(paramFeatures -> {
+ RFSEntry model = paramFeatures.getValue();
+
+ SimpleBooleanProperty booleanProperty = new SimpleBooleanProperty(model.isMarkSelected());
+
+ booleanProperty.addListener((observableValue, oldValue, newValue) -> {
+ model.setMarkSelected(newValue);
+ table.refresh();
+ });
+ return booleanProperty;
+ });
+
+ checkBoxColumn.setCellFactory(paramFeatures -> new CheckBoxTableCell<>());
+ table.setRowFactory( // this shit is made to implement context menu. It's such a pain..
+ RFSEntryTableView -> {
+ final TableRow row = new TableRow<>();
+ ContextMenu contextMenu = new ContextMenu();
+ /* // TODO: CHANGE TO 'Export' or something
+ MenuItem openMenuItem = new MenuItem("Open");
+ openMenuItem.setOnAction(new EventHandler() {
+ @Override
+ public void handle(ActionEvent actionEvent) {
+ MediatorControl.getInstance().getContoller().showContentWindow(provider, row.getItem());
+ }
+ });
+
+ contextMenu.getItems().addAll(openMenuItem);
+ */
+ row.setContextMenu(contextMenu);
+ row.contextMenuProperty().bind(
+ Bindings.when(Bindings.isNotNull(row.itemProperty())).then(contextMenu).otherwise((ContextMenu)null)
+ );
+ // Just.. don't ask..
+ row.setOnMouseClicked(mouseEvent -> {
+ if (!row.isEmpty() && mouseEvent.getButton() == MouseButton.PRIMARY){
+ RFSEntry thisItem = row.getItem();
+ thisItem.setMarkSelected(!thisItem.isMarkSelected());
+ table.refresh();
+ }
+ mouseEvent.consume();
+ });
+ return row;
+ }
+ );
+ table.setItems(rowsObsLst);
+ table.getColumns().add(numberColumn);
+ table.getColumns().add(fileNameColumn);
+ table.getColumns().add(fileOffsetColumn);
+ table.getColumns().add(fileSizeColumn);
+ table.getColumns().add(checkBoxColumn);
+ }
+ /**
+ * Add files when user selected them on left-hand tree
+ * */
+ public void setContent(TreeItem containerTreeItem){
+ rowsObsLst.clear();
+
+ if (containerTreeItem == null) {
+ table.refresh();
+ return;
+ }
+
+ for (TreeItem childTreeItem : containerTreeItem.getChildren())
+ rowsObsLst.add(childTreeItem.getValue());
+
+ table.refresh();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/konogonka/Controllers/RFS/RomFsController.java b/src/main/java/konogonka/Controllers/RFS/RomFsController.java
index f4bff08..8a664ce 100644
--- a/src/main/java/konogonka/Controllers/RFS/RomFsController.java
+++ b/src/main/java/konogonka/Controllers/RFS/RomFsController.java
@@ -19,12 +19,14 @@
package konogonka.Controllers.RFS;
import javafx.fxml.FXML;
-import javafx.scene.control.TreeItem;
-import javafx.scene.control.TreeView;
+import javafx.scene.control.*;
+import javafx.scene.input.MouseButton;
import javafx.scene.layout.Region;
-import javafx.scene.layout.VBox;
+import javafx.util.Callback;
import konogonka.Controllers.ITabController;
import konogonka.Tools.ISuperProvider;
+import konogonka.Tools.RomFs.FileSystemEntry;
+import konogonka.Tools.RomFs.Level6Header;
import konogonka.Tools.RomFs.RomFsDecryptedProvider;
import java.io.File;
@@ -34,20 +36,48 @@ import java.util.ResourceBundle;
public class RomFsController implements ITabController {
@FXML
- private TreeView filesTreeView;
+ private Label headerHeaderLengthLbl,
+ headerDirectoryHashTableOffsetLbl,
+ headerDirectoryHashTableLengthLbl,
+ headerDirectoryMetadataTableOffsetLbl,
+ headerDirectoryMetadataTableLengthLbl,
+ headerFileHashTableOffsetLbl,
+ headerFileHashTableLengthLbl,
+ headerFileMetadataTableOffsetLbl,
+ headerFileMetadataTableLengthLbl,
+ headerFileDataOffsetLbl;
@FXML
- private VBox folderContentVBox;
+ private Label headerHeaderLengthHexLbl,
+ headerDirectoryHashTableOffsetHexLbl,
+ headerDirectoryHashTableLengthHexLbl,
+ headerDirectoryMetadataTableOffsetHexLbl,
+ headerDirectoryMetadataTableLengthHexLbl,
+ headerFileHashTableOffsetHexLbl,
+ headerFileHashTableLengthHexLbl,
+ headerFileMetadataTableOffsetHexLbl,
+ headerFileMetadataTableLengthHexLbl,
+ headerFileDataOffsetHexLbl;
+
+ @FXML
+ private TreeView filesTreeView;
private RomFsDecryptedProvider RomFsProvider;
+ @FXML
+ private RFSFolderTableViewController RFSTableViewController;
+
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
- TreeItem rootTest = getEmptyRoot();
- TreeItem test = new TreeItem<>(new RFSFolderEntry("WIP"), getFolderImage());
+ filesTreeView.setOnMouseClicked(mouseEvent -> {
+ TreeItem item = filesTreeView.getSelectionModel().getSelectedItem();
+ if (item != null && item.getValue().isDirectory())
+ RFSTableViewController.setContent(item);
+ mouseEvent.consume();
+ });
+ }
- rootTest.getChildren().add(test);
+ private final class RFSTreeCell extends TreeCell{
- filesTreeView.setRoot(rootTest);
}
@Override
@@ -59,22 +89,96 @@ public class RomFsController implements ITabController {
public void analyze(File file, long offset) {
try {
this.RomFsProvider = new RomFsDecryptedProvider(file);
+ Level6Header header = RomFsProvider.getHeader();
+ long tempValue;
+ tempValue = header.getHeaderLength();
+ headerHeaderLengthLbl.setText(Long.toString(tempValue));
+ headerHeaderLengthHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getDirectoryHashTableOffset();
+ headerDirectoryHashTableOffsetLbl.setText(Long.toString(tempValue));
+ headerDirectoryHashTableOffsetHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getDirectoryHashTableLength();
+ headerDirectoryHashTableLengthLbl.setText(Long.toString(tempValue));
+ headerDirectoryHashTableLengthHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getDirectoryMetadataTableOffset();
+ headerDirectoryMetadataTableOffsetLbl.setText(Long.toString(tempValue));
+ headerDirectoryMetadataTableOffsetHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getDirectoryMetadataTableLength();
+ headerDirectoryMetadataTableLengthLbl.setText(Long.toString(tempValue));
+ headerDirectoryMetadataTableLengthHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getFileHashTableOffset();
+ headerFileHashTableOffsetLbl.setText(Long.toString(tempValue));
+ headerFileHashTableOffsetHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getFileHashTableLength();
+ headerFileHashTableLengthLbl.setText(Long.toString(tempValue));
+ headerFileHashTableLengthHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getFileMetadataTableOffset();
+ headerFileMetadataTableOffsetLbl.setText(Long.toString(tempValue));
+ headerFileMetadataTableOffsetHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getFileMetadataTableLength();
+ headerFileMetadataTableLengthLbl.setText(Long.toString(tempValue));
+ headerFileMetadataTableLengthHexLbl.setText(getHexString(tempValue));
+ tempValue = header.getFileDataOffset();
+ headerFileDataOffsetLbl.setText(Long.toString(tempValue));
+ headerFileDataOffsetHexLbl.setText(getHexString(tempValue));
+
+ TreeItem rootItem = getTreeFolderItem(RomFsProvider.getRootEntry());
+
+ filesTreeView.setRoot(rootItem);
+
+ RFSTableViewController.setContent(rootItem);
}
catch (Exception e){ // TODO: FIX
e.printStackTrace();
}
- TreeItem rootItem = getEmptyRoot();
+ }
- filesTreeView.setRoot(rootItem);
+ private TreeItem getTreeFolderItem(FileSystemEntry childEntry){
+ TreeItem entryTreeItem = new TreeItem<>(new RFSEntry(childEntry), getFolderImage());
+ for (FileSystemEntry entry : childEntry.getContent()){
+ if (entry.isDirectory()) {
+ entryTreeItem.getChildren().add(getTreeFolderItem(entry));
+ }
+ else
+ entryTreeItem.getChildren().add( getTreeFileItem(entry) );;
+ }
+ entryTreeItem.setExpanded(true);
+
+ return entryTreeItem;
+ }
+ private TreeItem getTreeFileItem(FileSystemEntry childEntry) {
+ return new TreeItem<>(new RFSEntry(childEntry), getFileImage());
}
@Override
public void analyze(ISuperProvider parentProvider, int fileNo) throws Exception {
-
+ throw new Exception("NOT IMPLEMENTED: analyze(ISuperProvider parentProvider, int fileNo)");
}
@Override
public void resetTab() {
+ headerHeaderLengthLbl.setText("");
+ headerDirectoryHashTableOffsetLbl.setText("");
+ headerDirectoryHashTableLengthLbl.setText("");
+ headerDirectoryMetadataTableOffsetLbl.setText("");
+ headerDirectoryMetadataTableLengthLbl.setText("");
+ headerFileHashTableOffsetLbl.setText("");
+ headerFileHashTableLengthLbl.setText("");
+ headerFileMetadataTableOffsetLbl.setText("");
+ headerFileMetadataTableLengthLbl.setText("");
+ headerFileDataOffsetLbl.setText("");
+
+ headerHeaderLengthHexLbl.setText("");
+ headerDirectoryHashTableOffsetHexLbl.setText("");
+ headerDirectoryHashTableLengthHexLbl.setText("");
+ headerDirectoryMetadataTableOffsetHexLbl.setText("");
+ headerDirectoryMetadataTableLengthHexLbl.setText("");
+ headerFileHashTableOffsetHexLbl.setText("");
+ headerFileHashTableLengthHexLbl.setText("");
+ headerFileMetadataTableOffsetHexLbl.setText("");
+ headerFileMetadataTableLengthHexLbl.setText("");
+ headerFileDataOffsetHexLbl.setText("");
+
filesTreeView.setRoot(null);
}
@@ -83,8 +187,13 @@ public class RomFsController implements ITabController {
folderImage.getStyleClass().add("regionFolder");
return folderImage;
}
+ private Region getFileImage(){
+ final Region folderImage = new Region();
+ folderImage.getStyleClass().add("regionFile");
+ return folderImage;
+ }
- private TreeItem getEmptyRoot(){
- return new TreeItem<>(new RFSFolderEntry("/"));
+ private String getHexString(long value){
+ return String.format("0x%x", value);
}
}
diff --git a/src/main/java/konogonka/Controllers/TIK/TIKController.java b/src/main/java/konogonka/Controllers/TIK/TIKController.java
index 3558f36..039bb82 100644
--- a/src/main/java/konogonka/Controllers/TIK/TIKController.java
+++ b/src/main/java/konogonka/Controllers/TIK/TIKController.java
@@ -87,9 +87,9 @@ public class TIKController implements ITabController {
}
@Override
public void analyze(File file, long offset) {
- Task analyzer = Analyzer.analyzeTIK(file, offset);
+ Task analyzer = Analyzer.analyzeTIK(file, offset);
analyzer.setOnSucceeded(e->{
- TIKProvider tik = (TIKProvider) analyzer.getValue();
+ TIKProvider tik = analyzer.getValue();
if (offset == 0)
setData(tik, file);
else
diff --git a/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java b/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java
index 6569ee3..2f1516f 100644
--- a/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java
+++ b/src/main/java/konogonka/Controllers/XCI/Hfs0TableViewController.java
@@ -42,12 +42,8 @@ import konogonka.Tools.ISuperProvider;
import konogonka.Tools.XCI.HFS0Provider;
-import java.lang.reflect.Array;
import java.net.URL;
-import java.nio.IntBuffer;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
diff --git a/src/main/java/konogonka/MainFx.java b/src/main/java/konogonka/MainFx.java
index 0f55cb0..a3de8e2 100644
--- a/src/main/java/konogonka/MainFx.java
+++ b/src/main/java/konogonka/MainFx.java
@@ -30,7 +30,7 @@ import java.util.Locale;
import java.util.ResourceBundle;
public class MainFx extends Application {
- public static final String appVersion = "v0.0.2";
+ public static final String appVersion = "v0.0.3";
@Override
public void start(Stage primaryStage) throws Exception{
diff --git a/src/main/java/konogonka/Tools/RomFs/FileMeta.java b/src/main/java/konogonka/Tools/RomFs/FileMeta.java
deleted file mode 100644
index e4f4d0d..0000000
--- a/src/main/java/konogonka/Tools/RomFs/FileMeta.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Copyright 2019-2020 Dmitry Isaenko
-
- This file is part of Konogonka.
-
- Konogonka is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Konogonka is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Konogonka. If not, see .
-*/
-package konogonka.Tools.RomFs;
-
-public class FileMeta {
- private int containingDirectoryOffset;
- private int nextSiblingFileOffset;
- private long fileDataOffset;
- private long fileDataLength;
- private int nextFileOffset;
- private int fileNameLength;
- private String fileName;
-}
diff --git a/src/main/java/konogonka/Tools/RomFs/FileMeta4Debug.java b/src/main/java/konogonka/Tools/RomFs/FileMeta4Debug.java
new file mode 100644
index 0000000..6287cd4
--- /dev/null
+++ b/src/main/java/konogonka/Tools/RomFs/FileMeta4Debug.java
@@ -0,0 +1,88 @@
+/*
+ Copyright 2019-2020 Dmitry Isaenko
+
+ This file is part of Konogonka.
+
+ Konogonka is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Konogonka is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Konogonka. If not, see .
+*/
+package konogonka.Tools.RomFs;
+
+import konogonka.LoperConverter;
+import konogonka.ModelControllers.LogPrinter;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static konogonka.RainbowDump.formatDecHexString;
+
+public class FileMeta4Debug {
+
+ List allFiles;
+
+ FileMeta4Debug(long fileMetadataTableLength, byte[] fileMetadataTable) {
+ allFiles = new ArrayList<>();
+ int i = 0;
+ while (i < fileMetadataTableLength) {
+ FileMeta fileMeta = new FileMeta();
+ fileMeta.containingDirectoryOffset = LoperConverter.getLEint(fileMetadataTable, i);
+ i += 4;
+ fileMeta.nextSiblingFileOffset = LoperConverter.getLEint(fileMetadataTable, i);
+ i += 4;
+ fileMeta.fileDataOffset = LoperConverter.getLElong(fileMetadataTable, i);
+ i += 8;
+ fileMeta.fileDataLength = LoperConverter.getLElong(fileMetadataTable, i);
+ i += 8;
+ fileMeta.nextFileOffset = LoperConverter.getLEint(fileMetadataTable, i);
+ i += 4;
+ fileMeta.fileNameLength = LoperConverter.getLEint(fileMetadataTable, i);
+ i += 4;
+ fileMeta.fileName = new String(Arrays.copyOfRange(fileMetadataTable, i, i + fileMeta.fileNameLength), StandardCharsets.UTF_8);
+ ;
+ i += getRealNameSize(fileMeta.fileNameLength);
+
+ allFiles.add(fileMeta);
+ }
+
+ for (FileMeta fileMeta : allFiles){
+ System.out.println(
+ "-------------------------FILE--------------------------------\n" +
+ "Offset of Containing Directory " + formatDecHexString(fileMeta.containingDirectoryOffset) + "\n" +
+ "Offset of next Sibling File " + formatDecHexString(fileMeta.nextSiblingFileOffset) + "\n" +
+ "Offset of File's Data " + formatDecHexString(fileMeta.fileDataOffset) + "\n" +
+ "Length of File's Data " + formatDecHexString(fileMeta.fileDataLength) + "\n" +
+ "Offset of next File in the same Hash Table bucket " + formatDecHexString(fileMeta.nextFileOffset) + "\n" +
+ "Name Length " + formatDecHexString(fileMeta.fileNameLength) + "\n" +
+ "Name Length (rounded up to multiple of 4) " + fileMeta.fileName + "\n"
+ );
+ }
+ }
+
+ private int getRealNameSize(int value){
+ if (value % 4 == 0)
+ return value;
+ return value + 4 - value % 4;
+ }
+
+ private static class FileMeta{
+ int containingDirectoryOffset;
+ int nextSiblingFileOffset;
+ long fileDataOffset;
+ long fileDataLength;
+ int nextFileOffset;
+ int fileNameLength;
+ String fileName;
+ }
+}
diff --git a/src/main/java/konogonka/Tools/RomFs/FileSystemEntry.java b/src/main/java/konogonka/Tools/RomFs/FileSystemEntry.java
new file mode 100644
index 0000000..98470b0
--- /dev/null
+++ b/src/main/java/konogonka/Tools/RomFs/FileSystemEntry.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2019-2020 Dmitry Isaenko
+ *
+ * This file is part of Konogonka.
+ *
+ * Konogonka is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Konogonka is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Konogonka. If not, see .
+ */
+
+package konogonka.Tools.RomFs;
+
+import konogonka.LoperConverter;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+public class FileSystemEntry {
+ private boolean directoryFlag;
+ private String name;
+ private List content;
+
+ private static byte[] dirsMetadataTable;
+ private static byte[] filesMetadataTable;
+
+ private long fileOffset;
+ private long fileSize;
+
+ public FileSystemEntry(byte[] dirsMetadataTable, byte[] filesMetadataTable) throws Exception{
+ FileSystemEntry.dirsMetadataTable = dirsMetadataTable;
+ FileSystemEntry.filesMetadataTable = filesMetadataTable;
+ this.content = new ArrayList<>();
+ this.directoryFlag = true;
+ DirectoryMetaData rootDirectoryMetaData = new DirectoryMetaData();
+ if (rootDirectoryMetaData.dirName.isEmpty())
+ this.name = "/";
+ else
+ this.name = rootDirectoryMetaData.dirName;
+ if (rootDirectoryMetaData.parentDirectoryOffset != 0)
+ throw new Exception("Offset of Parent Directory is incorrect. Expected 0 for root, received value is "+ rootDirectoryMetaData.parentDirectoryOffset);
+ if (rootDirectoryMetaData.nextSiblingDirectoryOffset != -1)
+ throw new Exception("Offset of next Sibling Directory is incorrect. Expected -1 for root, received value is "+ rootDirectoryMetaData.nextSiblingDirectoryOffset);
+ if (rootDirectoryMetaData.firstSubdirectoryOffset != -1)
+ content.add(getDirectory(rootDirectoryMetaData.firstSubdirectoryOffset));
+ if (rootDirectoryMetaData.firstFileOffset != -1)
+ content.add(getFile(this, rootDirectoryMetaData.firstFileOffset));
+ content.sort(Comparator.comparingLong(FileSystemEntry::getFileOffset));
+ }
+
+ private FileSystemEntry(){
+ this.content = new ArrayList<>();
+ }
+
+ private FileSystemEntry getDirectory(int childDirMetaPosition){
+ FileSystemEntry fileSystemEntry = new FileSystemEntry();
+ fileSystemEntry.directoryFlag = true;
+
+ DirectoryMetaData directoryMetaData = new DirectoryMetaData(childDirMetaPosition);
+ fileSystemEntry.name = directoryMetaData.dirName;
+
+ if (directoryMetaData.nextSiblingDirectoryOffset != -1)
+ this.content.add(getDirectory(directoryMetaData.nextSiblingDirectoryOffset));
+
+ if (directoryMetaData.firstSubdirectoryOffset != -1)
+ fileSystemEntry.content.add(getDirectory(directoryMetaData.firstSubdirectoryOffset));
+
+ if (directoryMetaData.firstFileOffset != -1)
+ fileSystemEntry.content.add(getFile(fileSystemEntry, directoryMetaData.firstFileOffset));
+
+ fileSystemEntry.content.sort(Comparator.comparingLong(FileSystemEntry::getFileOffset));
+
+ return fileSystemEntry;
+ }
+
+ private FileSystemEntry getFile(FileSystemEntry directoryContainer, int childFileMetaPosition){
+ FileSystemEntry fileSystemEntry = new FileSystemEntry();
+ fileSystemEntry.directoryFlag = false;
+
+ FileMetaData fileMetaData = new FileMetaData(childFileMetaPosition);
+ fileSystemEntry.name = fileMetaData.fileName;
+ fileSystemEntry.fileOffset = fileMetaData.fileDataRealOffset;
+ fileSystemEntry.fileSize = fileMetaData.fileDataRealLength;
+ if (fileMetaData.nextSiblingFileOffset != -1)
+ directoryContainer.content.add( getFile(directoryContainer, fileMetaData.nextSiblingFileOffset) );
+
+ return fileSystemEntry;
+ }
+
+ public boolean isDirectory() { return directoryFlag; }
+ public boolean isFile() { return ! directoryFlag; }
+ public long getFileOffset() { return fileOffset; }
+ public long getFileSize() { return fileSize; }
+ public List getContent() { return content; }
+ public String getName(){ return name; }
+
+
+ private static class DirectoryMetaData {
+ private int parentDirectoryOffset;
+ private int nextSiblingDirectoryOffset;
+ private int firstSubdirectoryOffset;
+ private int firstFileOffset;
+
+ private String dirName;
+
+ private DirectoryMetaData(){
+ this(0);
+ }
+ private DirectoryMetaData(int childDirMetaPosition){
+ int i = childDirMetaPosition;
+ parentDirectoryOffset = LoperConverter.getLEint(dirsMetadataTable, i);
+ i += 4;
+ nextSiblingDirectoryOffset = LoperConverter.getLEint(dirsMetadataTable, i);
+ i += 4;
+ firstSubdirectoryOffset = LoperConverter.getLEint(dirsMetadataTable, i);
+ i += 4;
+ firstFileOffset = LoperConverter.getLEint(dirsMetadataTable, i);
+ i += 4;
+ // int nextHashTableBucketDirectoryOffset = LoperConverter.getLEint(dirsMetadataTable, i);
+ i += 4;
+ int dirNameLength = LoperConverter.getLEint(dirsMetadataTable, i);
+ i += 4;
+ dirName = new String(Arrays.copyOfRange(dirsMetadataTable, i, i + dirNameLength), StandardCharsets.UTF_8);
+ //i += getRealNameSize(dirNameLength);
+ }
+
+ private int getRealNameSize(int value){
+ if (value % 4 == 0)
+ return value;
+ return value + 4 - value % 4;
+ }
+ }
+ private static class FileMetaData {
+
+ private int nextSiblingFileOffset;
+ private long fileDataRealOffset;
+ private long fileDataRealLength;
+
+ private String fileName;
+
+ private FileMetaData(){
+ this(0);
+ }
+
+ private FileMetaData(int childFileMetaPosition){
+ int i = childFileMetaPosition;
+ // int containingDirectoryOffset = LoperConverter.getLEint(filesMetadataTable, i); // never used
+ i += 4;
+ nextSiblingFileOffset = LoperConverter.getLEint(filesMetadataTable, i);
+ i += 4;
+ fileDataRealOffset = LoperConverter.getLElong(filesMetadataTable, i);
+ i += 8;
+ fileDataRealLength = LoperConverter.getLElong(filesMetadataTable, i);
+ i += 8;
+ //int nextHashTableBucketFileOffset = LoperConverter.getLEint(filesMetadataTable, i);
+ i += 4;
+ int fileNameLength = LoperConverter.getLEint(filesMetadataTable, i);
+ i += 4;
+ fileName = new String(Arrays.copyOfRange(filesMetadataTable, i, i + fileNameLength), StandardCharsets.UTF_8);;
+ //i += getRealNameSize(fileNameLength);
+ }
+ }
+
+ public void printTreeForDebug(){
+ System.out.println("/");
+ for (FileSystemEntry entry: content)
+ printEntry(2, entry);
+ }
+ private void printEntry(int cnt, FileSystemEntry entry) {
+ for (int i = 0; i < cnt; i++)
+ System.out.print(" ");
+
+ if (entry.isDirectory()){
+ System.out.println("|-" + entry.getName());
+ for (FileSystemEntry e : entry.content)
+ printEntry(cnt+2, e);
+ }
+ else
+ System.out.println("|-" + entry.getName() + String.format(" 0x%-10x 0x%-10x", entry.fileOffset, entry.fileSize));
+ }
+}
diff --git a/src/main/java/konogonka/Tools/RomFs/FolderMeta.java b/src/main/java/konogonka/Tools/RomFs/FolderMeta.java
deleted file mode 100644
index 0c6cd7e..0000000
--- a/src/main/java/konogonka/Tools/RomFs/FolderMeta.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Copyright 2019-2020 Dmitry Isaenko
-
- This file is part of Konogonka.
-
- Konogonka is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Konogonka is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Konogonka. If not, see .
-*/
-package konogonka.Tools.RomFs;
-
-public class FolderMeta {
- private int parentDirectoryOffset;
- private int nextSiblingDirectoryOffset;
- private int firstSubdirectoryOffset;
- private int firstFileOffset;
- private int nextDirectoryOffset;
- private int dirNameLength;
- private String dirName;
-}
diff --git a/src/main/java/konogonka/Tools/RomFs/FolderMeta4Debug.java b/src/main/java/konogonka/Tools/RomFs/FolderMeta4Debug.java
new file mode 100644
index 0000000..48d5b97
--- /dev/null
+++ b/src/main/java/konogonka/Tools/RomFs/FolderMeta4Debug.java
@@ -0,0 +1,85 @@
+/*
+ Copyright 2019-2020 Dmitry Isaenko
+
+ This file is part of Konogonka.
+
+ Konogonka is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Konogonka is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Konogonka. If not, see .
+*/
+package konogonka.Tools.RomFs;
+
+import konogonka.LoperConverter;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static konogonka.RainbowDump.formatDecHexString;
+
+public class FolderMeta4Debug {
+
+ List allFolders;
+
+ FolderMeta4Debug(long directoryMetadataTableLength, byte[] directoryMetadataTable){
+ allFolders = new ArrayList<>();
+ int i = 0;
+ while (i < directoryMetadataTableLength){
+ FolderMeta folderMeta = new FolderMeta();
+ folderMeta.parentDirectoryOffset = LoperConverter.getLEint(directoryMetadataTable, i);
+ i += 4;
+ folderMeta.nextSiblingDirectoryOffset = LoperConverter.getLEint(directoryMetadataTable, i);
+ i += 4;
+ folderMeta.firstSubdirectoryOffset = LoperConverter.getLEint(directoryMetadataTable, i);
+ i += 4;
+ folderMeta.firstFileOffset = LoperConverter.getLEint(directoryMetadataTable, i);
+ i += 4;
+ folderMeta.nextDirectoryOffset = LoperConverter.getLEint(directoryMetadataTable, i);
+ i += 4;
+ folderMeta.dirNameLength = LoperConverter.getLEint(directoryMetadataTable, i);
+ i += 4;
+ folderMeta.dirName = new String(Arrays.copyOfRange(directoryMetadataTable, i, i + folderMeta.dirNameLength), StandardCharsets.UTF_8);
+ i += getRealNameSize(folderMeta.dirNameLength);
+
+ allFolders.add(folderMeta);
+ }
+
+ for (FolderMeta headersDirectory : allFolders)
+ System.out.println(
+ "---------------------------DIRECTORY------------------------\n" +
+ "Offset of Parent Directory (self if Root) " + formatDecHexString(headersDirectory.parentDirectoryOffset ) +"\n" +
+ "Offset of next Sibling Directory " + formatDecHexString(headersDirectory.nextSiblingDirectoryOffset) +"\n" +
+ "Offset of first Child Directory (Subdirectory) " + formatDecHexString(headersDirectory.firstSubdirectoryOffset ) +"\n" +
+ "Offset of first File (in File Metadata Table) " + formatDecHexString(headersDirectory.firstFileOffset ) +"\n" +
+ "Offset of next Directory in the same Hash Table bucket " + formatDecHexString(headersDirectory.nextDirectoryOffset ) +"\n" +
+ "Name Length " + formatDecHexString(headersDirectory.dirNameLength ) +"\n" +
+ "Name Length (rounded up to multiple of 4) " + headersDirectory.dirName + "\n"
+ );
+ }
+
+ private int getRealNameSize(int value){
+ if (value % 4 == 0)
+ return value;
+ return value + 4 - value % 4;
+ }
+
+ private static class FolderMeta {
+ int parentDirectoryOffset;
+ int nextSiblingDirectoryOffset;
+ int firstSubdirectoryOffset;
+ int firstFileOffset;
+ int nextDirectoryOffset;
+ int dirNameLength;
+ String dirName;
+ }
+}
diff --git a/src/main/java/konogonka/Tools/RomFs/Level6Header.java b/src/main/java/konogonka/Tools/RomFs/Level6Header.java
index c73921a..6ae0171 100644
--- a/src/main/java/konogonka/Tools/RomFs/Level6Header.java
+++ b/src/main/java/konogonka/Tools/RomFs/Level6Header.java
@@ -20,49 +20,34 @@
package konogonka.Tools.RomFs;
import konogonka.LoperConverter;
-import konogonka.RainbowDump;
public class Level6Header {
- private long headerHeaderLength;
- private long headerDirectoryHashTableOffset;
- private long headerDirectoryHashTableLength;
- private long headerDirectoryMetadataTableOffset;
- private long headerDirectoryMetadataTableLength;
- private long headerFileHashTableOffset;
- private long headerFileHashTableLength;
- private long headerFileMetadataTableOffset;
- private long headerFileMetadataTableLength;
- private long headerFileDataOffset;
+ private long headerLength;
+ private long directoryHashTableOffset;
+ private long directoryHashTableLength;
+ private long directoryMetadataTableOffset;
+ private long directoryMetadataTableLength;
+ private long fileHashTableOffset;
+ private long fileHashTableLength;
+ private long fileMetadataTableOffset;
+ private long fileMetadataTableLength;
+ private long fileDataOffset;
private byte[] headerBytes;
private int i;
Level6Header(byte[] headerBytes){
this.headerBytes = headerBytes;
- headerHeaderLength = getNext();
- headerDirectoryHashTableOffset = getNext();
- headerDirectoryHashTableLength = getNext();
- headerDirectoryMetadataTableOffset = getNext();
- headerDirectoryMetadataTableLength = getNext();
- headerFileHashTableOffset = getNext();
- headerFileHashTableLength = getNext();
- headerFileMetadataTableOffset = getNext();
- headerFileMetadataTableLength = getNext();
- headerFileDataOffset = getNext();
-
- System.out.println("== Level 6 Header ==\n" +
- "Header Length (always 0x50 ?) "+ RainbowDump.formatDecHexString(headerHeaderLength)+" (size of this structure within first 0x200 block of LEVEL 6 part)\n" +
- "Directory Hash Table Offset "+ RainbowDump.formatDecHexString(headerDirectoryHashTableOffset)+" (against THIS block where HEADER contains)\n" +
- "Directory Hash Table Length "+ RainbowDump.formatDecHexString(headerDirectoryHashTableLength) + "\n" +
- "Directory Metadata Table Offset "+ RainbowDump.formatDecHexString(headerDirectoryMetadataTableOffset) + "\n" +
- "Directory Metadata Table Length "+ RainbowDump.formatDecHexString(headerDirectoryMetadataTableLength) + "\n" +
- "File Hash Table Offset "+ RainbowDump.formatDecHexString(headerFileHashTableOffset) + "\n" +
- "File Hash Table Length "+ RainbowDump.formatDecHexString(headerFileHashTableLength) + "\n" +
- "File Metadata Table Offset "+ RainbowDump.formatDecHexString(headerFileMetadataTableOffset) + "\n" +
- "File Metadata Table Length "+ RainbowDump.formatDecHexString(headerFileMetadataTableLength) + "\n" +
- "File Data Offset "+ RainbowDump.formatDecHexString(headerFileDataOffset) + "\n" +
- "-------------------------------------------------------------"
- );
+ headerLength = getNext();
+ directoryHashTableOffset = getNext();
+ directoryHashTableLength = getNext();
+ directoryMetadataTableOffset = getNext();
+ directoryMetadataTableLength = getNext();
+ fileHashTableOffset = getNext();
+ fileHashTableLength = getNext();
+ fileMetadataTableOffset = getNext();
+ fileMetadataTableLength = getNext();
+ fileDataOffset = getNext();
}
private long getNext(){
@@ -71,14 +56,14 @@ public class Level6Header {
return result;
}
- public long getHeaderHeaderLength() { return headerHeaderLength; }
- public long getHeaderDirectoryHashTableOffset() { return headerDirectoryHashTableOffset; }
- public long getHeaderDirectoryHashTableLength() { return headerDirectoryHashTableLength; }
- public long getHeaderDirectoryMetadataTableOffset() { return headerDirectoryMetadataTableOffset; }
- public long getHeaderDirectoryMetadataTableLength() { return headerDirectoryMetadataTableLength; }
- public long getHeaderFileHashTableOffset() { return headerFileHashTableOffset; }
- public long getHeaderFileHashTableLength() { return headerFileHashTableLength; }
- public long getHeaderFileMetadataTableOffset() { return headerFileMetadataTableOffset; }
- public long getHeaderFileMetadataTableLength() { return headerFileMetadataTableLength; }
- public long getHeaderFileDataOffset() { return headerFileDataOffset; }
+ public long getHeaderLength() { return headerLength; }
+ public long getDirectoryHashTableOffset() { return directoryHashTableOffset; }
+ public long getDirectoryHashTableLength() { return directoryHashTableLength; }
+ public long getDirectoryMetadataTableOffset() { return directoryMetadataTableOffset; }
+ public long getDirectoryMetadataTableLength() { return directoryMetadataTableLength; }
+ public long getFileHashTableOffset() { return fileHashTableOffset; }
+ public long getFileHashTableLength() { return fileHashTableLength; }
+ public long getFileMetadataTableOffset() { return fileMetadataTableOffset; }
+ public long getFileMetadataTableLength() { return fileMetadataTableLength; }
+ public long getFileDataOffset() { return fileDataOffset; }
}
diff --git a/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java b/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java
index ff57205..d0586b0 100644
--- a/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java
+++ b/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java
@@ -19,12 +19,19 @@
package konogonka.Tools.RomFs;
+import konogonka.LoperConverter;
import konogonka.Tools.ISuperProvider;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.PipedInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import static konogonka.RainbowDump.formatDecHexString;
public class RomFsDecryptedProvider implements ISuperProvider {
@@ -33,12 +40,14 @@ public class RomFsDecryptedProvider implements ISuperProvider {
private File decryptedFSImage;
private Level6Header header;
+ private FileSystemEntry rootEntry;
+
public RomFsDecryptedProvider(File decryptedFSImage) throws Exception{ // TODO: add default setup AND using meta-data headers from NCA RomFs section (?)
this.decryptedFSImage = decryptedFSImage;
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(decryptedFSImage));
- skipTo(bis, LEVEL_6_DEFAULT_OFFSET);
+ skipBytes(bis, LEVEL_6_DEFAULT_OFFSET);
byte[] rawDataChunk = new byte[0x50];
@@ -46,10 +55,52 @@ public class RomFsDecryptedProvider implements ISuperProvider {
throw new Exception("Failed to read header (0x50)");
this.header = new Level6Header(rawDataChunk);
+ /*
+ // Print Dir Hash table as is:
+ long seekTo = header.getDirectoryHashTableOffset() - 0x50;
+ rawDataChunk = new byte[(int) header.getDirectoryHashTableLength()];
+ skipTo(bis, seekTo);
+ if (bis.read(rawDataChunk) != (int) header.getDirectoryHashTableLength())
+ throw new Exception("Failed to read Dir hash table");
+ RainbowDump.hexDumpUTF8(rawDataChunk);
+ // Print Files Hash table as is:
+ seekTo = header.getFileHashTableOffset() - header.getDirectoryMetadataTableOffset();
+ rawDataChunk = new byte[(int) header.getFileHashTableLength()];
+ skipTo(bis, seekTo);
+ if (bis.read(rawDataChunk) != (int) header.getFileHashTableLength())
+ throw new Exception("Failed to read Files hash table");
+ RainbowDump.hexDumpUTF8(rawDataChunk);
+ */
+ // Read directories metadata
+ long locationInFile = header.getDirectoryMetadataTableOffset() - 0x50;
+ skipBytes(bis, locationInFile);
+
+ if (header.getDirectoryMetadataTableLength() < 0)
+ throw new Exception("Not supported operation.");
+
+ byte[] directoryMetadataTable = new byte[(int) header.getDirectoryMetadataTableLength()];
+
+ if (bis.read(directoryMetadataTable) != (int) header.getDirectoryMetadataTableLength())
+ throw new Exception("Failed to read "+header.getDirectoryMetadataTableLength());
+ // Read files metadata
+ locationInFile = header.getFileMetadataTableOffset() - header.getFileHashTableOffset(); // TODO: replace to 'CurrentPosition'?
+
+ skipBytes(bis, locationInFile);
+
+ if (header.getFileMetadataTableLength() < 0)
+ throw new Exception("Not supported operation.");
+
+ byte[] fileMetadataTable = new byte[(int) header.getFileMetadataTableLength()];
+
+ if (bis.read(fileMetadataTable) != (int) header.getFileMetadataTableLength())
+ throw new Exception("Failed to read "+header.getFileMetadataTableLength());
+
+ rootEntry = new FileSystemEntry(directoryMetadataTable, fileMetadataTable);
+ //printDebug(directoryMetadataTable, fileMetadataTable);
bis.close();
}
- private void skipTo(BufferedInputStream bis, long size) throws Exception{
+ private void skipBytes(BufferedInputStream bis, long size) throws Exception{
long mustSkip = size;
long skipped = 0;
while (mustSkip > 0){
@@ -57,13 +108,9 @@ public class RomFsDecryptedProvider implements ISuperProvider {
mustSkip = size - skipped;
}
}
- private int getRealNameSize(int value){
- if (value % 4 == 0)
- return value;
- return value + 4 - value % 4;
- }
public Level6Header getHeader() { return header; }
+ public FileSystemEntry getRootEntry() { return rootEntry; }
@Override
public PipedInputStream getProviderSubFilePipedInpStream(String subFileName) throws Exception {
@@ -72,7 +119,7 @@ public class RomFsDecryptedProvider implements ISuperProvider {
@Override
public PipedInputStream getProviderSubFilePipedInpStream(int subFileNumber) throws Exception {
- return null;
+ throw new Exception("RomFsDecryptedProvider -> getProviderSubFilePipedInpStream(): Get files by number is not supported.");
}
@Override
@@ -84,4 +131,10 @@ public class RomFsDecryptedProvider implements ISuperProvider {
public long getRawFileDataStart() {
return 0;
}
+
+ private void printDebug(byte[] directoryMetadataTable, byte[] fileMetadataTable){
+ new FolderMeta4Debug(header.getDirectoryMetadataTableLength(), directoryMetadataTable);
+ new FileMeta4Debug(header.getFileMetadataTableLength(), fileMetadataTable);
+ rootEntry.printTreeForDebug();
+ }
}
diff --git a/src/main/resources/FXML/NSP/TableView.fxml b/src/main/resources/FXML/NSP/TableView.fxml
index 5b8c2b8..843949a 100644
--- a/src/main/resources/FXML/NSP/TableView.fxml
+++ b/src/main/resources/FXML/NSP/TableView.fxml
@@ -3,6 +3,25 @@
+
+
diff --git a/src/main/resources/FXML/RomFS/RFSTab.fxml b/src/main/resources/FXML/RomFS/RFSTab.fxml
index bd209f1..0f7a327 100644
--- a/src/main/resources/FXML/RomFS/RFSTab.fxml
+++ b/src/main/resources/FXML/RomFS/RFSTab.fxml
@@ -1,15 +1,366 @@
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/FXML/RomFS/RFSTableView.fxml b/src/main/resources/FXML/RomFS/RFSTableView.fxml
new file mode 100644
index 0000000..d180775
--- /dev/null
+++ b/src/main/resources/FXML/RomFS/RFSTableView.fxml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/FXML/landingPage.fxml b/src/main/resources/FXML/landingPage.fxml
index 3e2f2a0..8c8496f 100644
--- a/src/main/resources/FXML/landingPage.fxml
+++ b/src/main/resources/FXML/landingPage.fxml
@@ -43,7 +43,7 @@
-
+
diff --git a/src/main/resources/res/app_light.css b/src/main/resources/res/app_light.css
index 7375d8c..124270d 100644
--- a/src/main/resources/res/app_light.css
+++ b/src/main/resources/res/app_light.css
@@ -433,4 +433,10 @@
-fx-background-color: #ffbf00;
-fx-min-height: 17.0;
-fx-min-width: 17.5;
+}
+.regionFile {
+ -fx-shape: "M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z";
+ -fx-background-color: #e54d1e;
+ -fx-min-height: 17.0;
+ -fx-min-width: 13;
}
\ No newline at end of file