From 270033b3f9d12e7f83105fb94878ce4f1bb9ef38 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Wed, 29 Apr 2020 18:07:30 +0300 Subject: [PATCH] RomFs support --- README.md | 2 +- .../konogonka/Controllers/MainController.java | 8 ++++---- .../Controllers/RFS/RomFsController.java | 10 +++++++++- .../konogonka/Tools/RomFs/IRomFsProvider.java | 1 + .../Tools/RomFs/RomFsDecryptedProvider.java | 16 +++++++++++----- .../Tools/RomFs/RomFsEncryptedProvider.java | 2 ++ src/main/java/konogonka/Workers/Analyzer.java | 4 ++-- .../Workers/DumbNCA3ContentExtractor.java | 8 ++++++-- 8 files changed, 36 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 828351a..a0615c8 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,6 @@ JRE/JDK 8u60 or higher. * [ ] CERT support * [ ] CNMT support * [ ] NSO support -* [ ] RomFS deep-dive +* [x] RomFS * [ ] LogPrinter to singleton implementation. * [x] 'Save to folder' option \ No newline at end of file diff --git a/src/main/java/konogonka/Controllers/MainController.java b/src/main/java/konogonka/Controllers/MainController.java index be53c08..267cb45 100644 --- a/src/main/java/konogonka/Controllers/MainController.java +++ b/src/main/java/konogonka/Controllers/MainController.java @@ -110,7 +110,7 @@ public class MainController implements Initializable { fileChooser.setInitialDirectory(new File(System.getProperty("user.home"))); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NS files", - "*.nsp", "*.nsz", "*.xci", "*.nca", "*.tik", "*.xml", "*.npdm", "*.romfs")); + "*.nsp", "*.nsz", "*.xci", "*.nca", "*.tik", "*.xml", "*.npdm", "*.bin")); this.selectedFile = fileChooser.showOpenDialog(analyzeBtn.getScene().getWindow()); @@ -156,7 +156,7 @@ public class MainController implements Initializable { case "npdm": tabPane.getSelectionModel().select(5); break; - case "romfs": + case "bin": tabPane.getSelectionModel().select(6); } } @@ -185,7 +185,7 @@ public class MainController implements Initializable { case "npdm": NPDMTabController.analyze(selectedFile); break; - case "romfs": + case "bin": RFSTabController.analyze(selectedFile); } } @@ -198,7 +198,7 @@ public class MainController implements Initializable { case "tik": case "xml": case "npdm": - case "romfs": + case "bin": return false; default: return true; diff --git a/src/main/java/konogonka/Controllers/RFS/RomFsController.java b/src/main/java/konogonka/Controllers/RFS/RomFsController.java index 6a61f74..72e7971 100644 --- a/src/main/java/konogonka/Controllers/RFS/RomFsController.java +++ b/src/main/java/konogonka/Controllers/RFS/RomFsController.java @@ -147,7 +147,15 @@ public class RomFsController implements ITabController { @Override public void analyze(File file) { - Task analyzer = Analyzer.analyzeRomFS(file); + long lv6offset = -1; + try{ + System.out.println(file.getName().replaceAll("(^.*lv6\\s)|(]\\.bin)", "")); + lv6offset = Long.parseLong(file.getName().replaceAll("(^.*lv6\\s)|(]\\.bin)", "")); + } + catch (Exception e){ + e.printStackTrace(); + } + Task analyzer = Analyzer.analyzeRomFS(file, lv6offset); analyzer.setOnSucceeded(e->{ RomFsDecryptedProvider provider = analyzer.getValue(); this.setData(provider); diff --git a/src/main/java/konogonka/Tools/RomFs/IRomFsProvider.java b/src/main/java/konogonka/Tools/RomFs/IRomFsProvider.java index 6c5eb4c..b80d8d5 100644 --- a/src/main/java/konogonka/Tools/RomFs/IRomFsProvider.java +++ b/src/main/java/konogonka/Tools/RomFs/IRomFsProvider.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.PipedInputStream; public interface IRomFsProvider { + long getLevel6Offset(); Level6Header getHeader(); FileSystemEntry getRootEntry(); PipedInputStream getContent(FileSystemEntry entry) throws Exception; diff --git a/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java b/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java index 6f7a7b0..5142efb 100644 --- a/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java +++ b/src/main/java/konogonka/Tools/RomFs/RomFsDecryptedProvider.java @@ -23,20 +23,24 @@ import java.io.*; public class RomFsDecryptedProvider implements IRomFsProvider{ - private static final long LEVEL_6_DEFAULT_OFFSET = 0x14000; // TODO: FIX incorrect + private long level6Offset; private File file; private Level6Header header; private FileSystemEntry rootEntry; - // TODO: FIX. LEVEL 6 OFFSET MUST be provided - public RomFsDecryptedProvider(File decryptedFsImageFile) throws Exception{ // TODO: add default setup AND using meta-data headers from NCA RomFs section (?) + public RomFsDecryptedProvider(File decryptedFsImageFile, long level6Offset) throws Exception{ + if (level6Offset < 0) + throw new Exception("Incorrect Level 6 Offset"); + this.file = decryptedFsImageFile; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(decryptedFsImageFile)); - skipBytes(bis, LEVEL_6_DEFAULT_OFFSET); + this.level6Offset = level6Offset; + + skipBytes(bis, level6Offset); byte[] rawDataChunk = new byte[0x50]; @@ -98,6 +102,8 @@ public class RomFsDecryptedProvider implements IRomFsProvider{ } } @Override + public long getLevel6Offset() { return level6Offset; } + @Override public Level6Header getHeader() { return header; } @Override public FileSystemEntry getRootEntry() { return rootEntry; } @@ -114,7 +120,7 @@ public class RomFsDecryptedProvider implements IRomFsProvider{ workerThread = new Thread(() -> { System.out.println("RomFsDecryptedProvider -> getContent(): Executing thread"); try { - long subFileRealPosition = LEVEL_6_DEFAULT_OFFSET + header.getFileDataOffset() + entry.getFileOffset(); + long subFileRealPosition = level6Offset + header.getFileDataOffset() + entry.getFileOffset(); BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); skipBytes(bis, subFileRealPosition); diff --git a/src/main/java/konogonka/Tools/RomFs/RomFsEncryptedProvider.java b/src/main/java/konogonka/Tools/RomFs/RomFsEncryptedProvider.java index d143382..a8d53f5 100644 --- a/src/main/java/konogonka/Tools/RomFs/RomFsEncryptedProvider.java +++ b/src/main/java/konogonka/Tools/RomFs/RomFsEncryptedProvider.java @@ -176,6 +176,8 @@ public class RomFsEncryptedProvider implements IRomFsProvider{ return metadataTable; } + @Override + public long getLevel6Offset() { return level6Offset; } @Override public Level6Header getHeader() { return header; } @Override diff --git a/src/main/java/konogonka/Workers/Analyzer.java b/src/main/java/konogonka/Workers/Analyzer.java index a61c44e..083c5ea 100644 --- a/src/main/java/konogonka/Workers/Analyzer.java +++ b/src/main/java/konogonka/Workers/Analyzer.java @@ -161,14 +161,14 @@ public class Analyzer { }; } - public static Task analyzeRomFS(File file){ + public static Task analyzeRomFS(File file, long lv6offset){ LogPrinter logPrinter = new LogPrinter(); return new Task() { @Override protected RomFsDecryptedProvider call() { logPrinter.print("\tStart chain: RomFS", EMsgType.INFO); try { - return new RomFsDecryptedProvider(file); + return new RomFsDecryptedProvider(file, lv6offset); } catch (Exception e) { logPrinter.print(e.getMessage(), EMsgType.FAIL); return null; diff --git a/src/main/java/konogonka/Workers/DumbNCA3ContentExtractor.java b/src/main/java/konogonka/Workers/DumbNCA3ContentExtractor.java index 6cbf935..e6ffc85 100644 --- a/src/main/java/konogonka/Workers/DumbNCA3ContentExtractor.java +++ b/src/main/java/konogonka/Workers/DumbNCA3ContentExtractor.java @@ -26,8 +26,12 @@ public class DumbNCA3ContentExtractor extends Task { @Override protected Void call() { - logPrinter.print("\tStart dummy extracting: \n"+filesDestPath+"NCAContent_"+ncaNumberInFile+".bin", EMsgType.INFO); - File contentFile = new File(filesDestPath + "NCAContent_"+ncaNumberInFile+".bin"); + String lv6mark = ""; + if (ncaContent.getRomfs() != null){ + lv6mark = " [lv6 "+ncaContent.getRomfs().getLevel6Offset()+"]"; + } + logPrinter.print("\tStart dummy extracting: \n"+filesDestPath+"NCAContent_"+ncaNumberInFile+lv6mark+".bin", EMsgType.INFO); + File contentFile = new File(filesDestPath + "NCAContent_"+ncaNumberInFile+lv6mark+".bin"); try { BufferedOutputStream extractedFileBOS = new BufferedOutputStream(new FileOutputStream(contentFile)); PipedInputStream pis = ncaContent.getRawDataContentPipedInpStream();