From 0cb945a7f4c8af82a3b5eec8fd6d81a5c9093ad7 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Wed, 28 Oct 2020 15:59:45 +0300 Subject: [PATCH] Cosmetic updates of GL code and working prototype of NXDT --- .../Utilities/nxdumptool/NxdtUsbAbi1.java | 45 ++++--- .../java/nsusbloader/com/usb/GoldLeaf_08.java | 114 +++++++++--------- 2 files changed, 83 insertions(+), 76 deletions(-) diff --git a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java index 097563f..e003a99 100644 --- a/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java +++ b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java @@ -45,7 +45,7 @@ class NxdtUsbAbi1 { private final boolean isWindows; private boolean isWindows10; - private static final int NXDT_MAX_DIRECTIVE_SIZE = 0x1000; + private static final int NXDT_MAX_DIRECTIVE_SIZE = 0x800000;//0x1000; private static final int NXDT_FILE_CHUNK_SIZE = 0x800000; private static final int NXDT_FILE_PROPERTIES_MAX_NAME_LENGTH = 0x300; @@ -212,8 +212,6 @@ class NxdtUsbAbi1 { String absoluteFilePath = getAbsoluteFilePath(filename); File fileToDump = new File(absoluteFilePath); - boolean nspTransferMode = false; - if (checkSizes(fullSize, headerSize)) return; @@ -225,14 +223,9 @@ class NxdtUsbAbi1 { return; if (headerSize > 0){ // if NSP - logPrinter.print("Receiving NSP file entry: '"+filename+"' ("+fullSize+" b)", EMsgType.INFO); - if (filename.equals(nspFile.getName())){ - nspTransferMode = true; - } - else { - createNewNsp(filename, headerSize, fullSize, fileToDump); - return; - } + logPrinter.print("Receiving NSP file: '"+filename+"' ("+formatByteSize(fullSize)+")", EMsgType.PASS); + createNewNsp(filename, headerSize, fullSize, fileToDump); + return; } else { // TODO: Note, in case of a big amount of small files performance decreases dramatically. It's better to handle this only in case of 1-big-file-transfer @@ -244,7 +237,7 @@ class NxdtUsbAbi1 { if (fullSize == 0) return; - if (nspTransferMode) + if (isNspTransfer()) dumpNspFile(nspFile, fullSize); else dumpFile(fileToDump, fullSize); @@ -261,8 +254,8 @@ class NxdtUsbAbi1 { return false; } private boolean checkSizes(long fileSize, int headerSize) throws Exception{ - if (fileSize >= headerSize){ - logPrinter.print("File size should not be equal to header size for NSP files!", EMsgType.FAIL); + if (headerSize >= fileSize){ + logPrinter.print(String.format("File size (%d) should not be less or equal to header size (%d)!", fileSize, headerSize), EMsgType.FAIL); resetNsp(); writeUsb(USBSTATUS_MALFORMED_REQUEST); return true; @@ -275,7 +268,6 @@ class NxdtUsbAbi1 { } return false; } - private boolean checkFileSystem(File fileToDump, long fileSize) throws Exception{ // Check if enough space if (fileToDump.getParentFile().getFreeSpace() <= fileSize){ @@ -297,7 +289,8 @@ class NxdtUsbAbi1 { nspFile = new NxdtNspFile(filename, headerSize, fileSize, fileToDump); } catch (Exception e){ - logPrinter.print(e.getMessage(), EMsgType.FAIL); + logPrinter.print("Unable to create new file for: "+filename+" :"+e.getMessage(), EMsgType.FAIL); + e.printStackTrace(); writeUsb(USBSTATUS_HOSTIOERROR); return; } @@ -310,6 +303,9 @@ class NxdtUsbAbi1 { private long getLElong(byte[] bytes, int fromOffset){ return ByteBuffer.wrap(bytes, fromOffset, 0x8).order(ByteOrder.LITTLE_ENDIAN).getLong(); } + private boolean isNspTransfer(){ + return nspFile != null; + } private String getAbsoluteFilePath(String filename) throws Exception{ if (isRomFs(filename) && isWindows) // Since RomFS entry starts from '/' it should be replaced to '\'. @@ -367,9 +363,10 @@ class NxdtUsbAbi1 { private void dumpNspFile(NxdtNspFile nsp, long size) throws Exception{ FileOutputStream fos = new FileOutputStream(nsp.getFile(), true); long nspSize = nsp.getFullSize(); - long nspRemainingSize = nsp.getNspRemainingSize(); try (BufferedOutputStream bos = new BufferedOutputStream(fos)) { + long nspRemainingSize = nsp.getNspRemainingSize(); + FileDescriptor fd = fos.getFD(); byte[] readBuffer; long received = 0; @@ -393,8 +390,6 @@ class NxdtUsbAbi1 { if (isWindows10) fd.sync(); nspRemainingSize -= (lastChunkSize - 1); - } - finally { nsp.setNspRemainingSize(nspRemainingSize); } } @@ -427,7 +422,8 @@ class NxdtUsbAbi1 { raf.seek(0); raf.write(headerData); } - + logPrinter.print("NSP file: '"+nsp.getName()+"' successfully received!", EMsgType.PASS); + logPrinter.updateProgress(1.0); writeUsb(USBSTATUS_SUCCESS); } private void resetNsp(){ @@ -534,4 +530,13 @@ class NxdtUsbAbi1 { "\n Returned: " + UsbErrorCodes.getErrCode(result) + "\n (execution stopped)"); } + + private String formatByteSize(double length) { + final String[] unitNames = { "bytes", "KiB", "MiB", "GiB", "TiB"}; + int i; + for (i = 0; length > 1024 && i < unitNames.length - 1; i++) { + length = length / 1024; + } + return String.format("%,.2f %s", length, unitNames[i]); + } } diff --git a/src/main/java/nsusbloader/com/usb/GoldLeaf_08.java b/src/main/java/nsusbloader/com/usb/GoldLeaf_08.java index 8e6171f..f6a29ac 100644 --- a/src/main/java/nsusbloader/com/usb/GoldLeaf_08.java +++ b/src/main/java/nsusbloader/com/usb/GoldLeaf_08.java @@ -64,14 +64,19 @@ class GoldLeaf_08 extends TransferModule { private long virtDriveSize; private HashMap splitFileSize; - private boolean isWindows; - private String homePath; + private final boolean isWindows; + private final String homePath; // For using in CMD_SelectFile with SPEC:/ prefix private File selectedFile; - private CancellableRunnable task; + private final CancellableRunnable task; - GoldLeaf_08(DeviceHandle handler, LinkedHashMap nspMap, CancellableRunnable task, ILogPrinter logPrinter, boolean nspFilter){ + GoldLeaf_08(DeviceHandle handler, + LinkedHashMap nspMap, + CancellableRunnable task, + ILogPrinter logPrinter, + boolean nspFilter) + { super(handler, nspMap, task, logPrinter); this.task = task; @@ -890,43 +895,42 @@ class GoldLeaf_08 extends TransferModule { if (fileName.startsWith("VIRT:/")){ return writeGL_FAIL("GL Handle 'WriteFile' command [not supported for virtual drive]"); } - else { - fileName = updateHomePath(fileName); - // Check if we didn't see this (or any) file during this session - if (writeFilesMap.size() == 0 || (! writeFilesMap.containsKey(fileName))){ - // Open what we have to open - File writeFile = new File(fileName); - // If this file exists GL will take care - // Otherwise, let's add it - try{ - BufferedOutputStream writeFileBufOutStream = new BufferedOutputStream(new FileOutputStream(writeFile, true)); - writeFilesMap.put(fileName, writeFileBufOutStream); - } catch (IOException ioe){ - return writeGL_FAIL("GL Handle 'WriteFile' command [IOException]\n\t"+ioe.getMessage()); - } - } - // Now we have stream - BufferedOutputStream myStream = writeFilesMap.get(fileName); - byte[] transferredData; - - if ((transferredData = readGL_file()) == null){ - logPrinter.print("GL Handle 'WriteFile' command [1/1]", EMsgType.FAIL); - return true; - } + fileName = updateHomePath(fileName); + // Check if we didn't see this (or any) file during this session + if (writeFilesMap.size() == 0 || (! writeFilesMap.containsKey(fileName))){ + // Open what we have to open + File writeFile = new File(fileName); + // If this file exists GL will take care + // Otherwise, let's add it try{ - myStream.write(transferredData, 0, transferredData.length); + BufferedOutputStream writeFileBufOutStream = new BufferedOutputStream(new FileOutputStream(writeFile, true)); + writeFilesMap.put(fileName, writeFileBufOutStream); + } catch (IOException ioe){ + return writeGL_FAIL("GL Handle 'WriteFile' command [IOException]\n\t"+ioe.getMessage()); } - catch (IOException ioe){ - return writeGL_FAIL("GL Handle 'WriteFile' command [1/1]\n\t"+ioe.getMessage()); - } - // Report we're good - if (writeGL_PASS()) { - logPrinter.print("GL Handle 'WriteFile' command", EMsgType.FAIL); - return true; - } - return false; } + // Now we have stream + BufferedOutputStream myStream = writeFilesMap.get(fileName); + + byte[] transferredData; + + if ((transferredData = readGL_file()) == null){ + logPrinter.print("GL Handle 'WriteFile' command [1/1]", EMsgType.FAIL); + return true; + } + try{ + myStream.write(transferredData, 0, transferredData.length); + } + catch (IOException ioe){ + return writeGL_FAIL("GL Handle 'WriteFile' command [1/1]\n\t"+ioe.getMessage()); + } + // Report we're good + if (writeGL_PASS()) { + logPrinter.print("GL Handle 'WriteFile' command", EMsgType.FAIL); + return true; + } + return false; } /** @@ -938,27 +942,27 @@ class GoldLeaf_08 extends TransferModule { File selectedFile = CompletableFuture.supplyAsync(() -> { FileChooser fChooser = new FileChooser(); fChooser.setTitle(MediatorControl.getInstance().getContoller().getResourceBundle().getString("btn_OpenFile")); // TODO: FIX BAD IMPLEMENTATION - fChooser.setInitialDirectory(new File(System.getProperty("user.home"))); // TODO: Consider fixing; not a prio. + fChooser.setInitialDirectory(new File(System.getProperty("user.home")));// TODO: Consider fixing; not a prio. fChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("*", "*")); return fChooser.showOpenDialog(null); // Leave as is for now. }, Platform::runLater).join(); - if (selectedFile != null){ - List command = new LinkedList<>(); - byte[] selectedFileNameBytes = ("SPEC:/"+selectedFile.getName()).getBytes(StandardCharsets.UTF_16LE); - command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7 - command.add(selectedFileNameBytes); - if (writeGL_PASS(command)) { - logPrinter.print("GL Handle 'SelectFile' command", EMsgType.FAIL); - this.selectedFile = null; - return true; - } - this.selectedFile = selectedFile; - return false; + if (selectedFile == null){ // Nothing selected + this.selectedFile = null; + return writeGL_FAIL("GL Handle 'SelectFile' command: Nothing selected"); } - // Nothing selected; Report failure. - this.selectedFile = null; - return writeGL_FAIL("GL Handle 'SelectFile' command: Nothing selected"); + + List command = new LinkedList<>(); + byte[] selectedFileNameBytes = ("SPEC:/"+selectedFile.getName()).getBytes(StandardCharsets.UTF_16LE); + command.add(intToArrLE(selectedFileNameBytes.length / 2)); // since GL 0.7 + command.add(selectedFileNameBytes); + if (writeGL_PASS(command)) { + logPrinter.print("GL Handle 'SelectFile' command", EMsgType.FAIL); + this.selectedFile = null; + return true; + } + this.selectedFile = selectedFile; + return false; } /*----------------------------------------------------*/ @@ -1039,9 +1043,7 @@ class GoldLeaf_08 extends TransferModule { return null; } private byte[] readGL_file(){ - ByteBuffer readBuffer; - readBuffer = ByteBuffer.allocateDirect(8388608); // Just don't ask.. - + ByteBuffer readBuffer = ByteBuffer.allocateDirect(8388608); // Just don't ask.. IntBuffer readBufTransferred = IntBuffer.allocate(1); int result;