diff --git a/.drone.yml b/.drone.yml index db885a8..7d3a283 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,6 +17,7 @@ steps: commands: - mkdir -p /builds/ns-usbloader - cp target/ns-usbloader-*jar /builds/ns-usbloader/ + - cp target/ns-usbloader-*exe /builds/ns-usbloader/ volumes: - name: builds path: /builds @@ -27,6 +28,7 @@ steps: - . ./.make_legacy - mvn -B -DskipTests clean package - cp target/ns-usbloader-*jar /builds/ns-usbloader/ + - cp target/ns-usbloader-*exe /builds/ns-usbloader/ volumes: - name: m2 path: /root/.m2 diff --git a/.make_legacy b/.make_legacy index a7c3a6f..f0f75ee 100644 --- a/.make_legacy +++ b/.make_legacy @@ -1,2 +1,3 @@ sed -z -i -e 's/org.usb4java<\/groupId>\n\s*usb4java<\/artifactId>\s*1.3.0<\/version>/org.usb4java<\/groupId>\nusb4java<\/artifactId>\n1.2.0<\/version>/g' pom.xml sed -z -i -e 's/${project.artifactId}-${project.version}-${maven.build.timestamp}<\/finalName>/${project.artifactId}-${project.version}-legacy-${maven.build.timestamp}<\/finalName>/g' pom.xml +sed -z -i -e 's/target\/NS-USBloader-${project.version}-${maven.build.timestamp}.exe<\/outfile>/target\/NS-USBloader-${project.version}-legacy-${maven.build.timestamp}.exe<\/outfile>/g' pom.xml diff --git a/README.md b/README.md index 1ebcd95..3bfb3f1 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# NS-USBloader +

NS-USBloader

![License](https://img.shields.io/badge/License-GPLv3-blue.svg) ![Releases](https://img.shields.io/github/downloads/developersu/ns-usbloader/total.svg) ![LatestVer](https://img.shields.io/github/release/developersu/ns-usbloader.svg) [![Build Status](https://ci.redrise.ru/api/badges/desu/ns-usbloader/status.svg)](https://ci.redrise.ru/desu/ns-usbloader) NS-USBloader is: -* A PC-side installer for **[Huntereb/Awoo-Installer](https://github.com/Huntereb/Awoo-Installer)** / other compatible installers (USB and Network supported) and **[XorTroll/GoldLeaf](https://github.com/XorTroll/Goldleaf)** (USB) NSP installer. +* A PC-side installer for **[Huntereb/Awoo-Installer](https://github.com/Huntereb/Awoo-Installer)** / other compatible installers (USB and Network supported) and **[XorTroll/Goldleaf](https://github.com/XorTroll/Goldleaf)** (USB) NSP installer. Alternative to default **usb_install_pc.py**, **remote_install_pc.py**, **GoldTree**/**Quark**. * RCM payload tool that works on Windows, macOS (Intel and Apple Silicon) and Linux (x86, amd64 and Raspberry Pi ARM). * It's a tool for creating split files! @@ -59,14 +59,16 @@ Sometimes I add new posts about this project [on my blog page](https://developer * Japanese by [kuragehime](https://github.com/kuragehimekurara1) * Ryukyuan languages by [kuragehime](https://github.com/kuragehimekurara1) +* angelodalzotto makes packages in AUR + ### System requirements JRE/JDK 8u60 or higher for Windows JDK 11 for MacOS and Linux -### Supported GoldLeaf versions -| GoldLeaf version | NS-USBloader version | +### Supported Goldleaf versions +| Goldleaf version | NS-USBloader version | |------------------|----------------------| | v0.5 | v0.4 - v0.5.2, v0.8+ | | v0.6 | none | @@ -136,7 +138,7 @@ Set 'Security & Privacy' settings if needed. #### And how to use it? -The first thing you should do it install Awoo ([Huntereb](https://github.com/Huntereb/Awoo-Installer)) or GoldLeaf ([XorTroll](https://github.com/XorTroll/Goldleaf)) on your NS. +The first thing you should do it install Awoo ([Huntereb](https://github.com/Huntereb/Awoo-Installer)) or Goldleaf ([XorTroll](https://github.com/XorTroll/Goldleaf)) on your NS. Take a look on app, find where is the option to install from USB and/or Network. Maybe (very old) [this article (about TinFoil)](https://developersu.blogspot.com/2019/02/ns-usbloader-en.html) will be helpful. @@ -146,19 +148,19 @@ There are three tabs. First one is main. ##### 'Gamepad' tab. -At the top of you selecting from drop-down application and protocol that you're going to use. For GoldLeaf only USB is available. Lamp icon stands for switching themes (light or dark). +At the top of you selecting from drop-down application and protocol that you're going to use. For Goldleaf only USB is available. Lamp icon stands for switching themes (light or dark). Then you may drag-n-drop files (split-files aka folders) to application or use 'Select NSP files' button. Multiple selection for files available. Click it again and select files from another folder it you want, it will be added into the table. Table. -There you can select checkbox for files that will be sent to application (AW/GL). ~~Since GoldLeaf v0.5 allow you only one file transmission per time, only one file is available for selection.~~ +There you can select checkbox for files that will be sent to application (AW/GL). ~~Since Goldleaf v0.5 allow you only one file transmission per time, only one file is available for selection.~~ Also you can use space to select/un-select files and 'delete' button for deleting. By right-mouse-click you can see context menu where you can delete one OR all items from the table. -For GoldLeaf v0.6.1 and NS-USBloader v0.6 (and higher) you will have to use 'Explore content' -> 'Remote PC (via USB)' You will see two drives HOME:/ and VIRT:/. First drive is pointing to your home directory. Second one is reflection of what you've added to table (first application tab). Also VIRT:/ drive have limited functionality in comparison to HOME:/. E.g. you can't write files to this drive since it's not a drive. But don't worry, it won't make any impact on GoldLeaf or your NS if you try. +For Goldleaf v0.6.1 and NS-USBloader v0.6 (and higher) you will have to use 'Explore content' -> 'Remote PC (via USB)' You will see two drives HOME:/ and VIRT:/. First drive is pointing to your home directory. Second one is reflection of what you've added to table (first application tab). Also VIRT:/ drive have limited functionality in comparison to HOME:/. E.g. you can't write files to this drive since it's not a drive. But don't worry, it won't make any impact on Goldleaf or your NS if you try. -Also, for GoldLeaf write files (from NS to PC): You have to 'Stop execution' properly before accessing files transferred from GL. Usually you have to wait 5sec or less. It will guarantee that your files properly written to PC. +Also, for Goldleaf write files (from NS to PC): You have to 'Stop execution' properly before accessing files transferred from GL. Usually you have to wait 5sec or less. It will guarantee that your files properly written to PC. ##### 'RCM' tab @@ -174,7 +176,7 @@ Here you can configure settings for network file transmission. Usually you shoul Also here you can: * Set 'Auto-check for updates' for checking for updates when application starts, or click button to verify if new version released immediately. -* Set 'Show only *.nsp in GoldLeaf' to filter all files displayed at HOME:/ drive. So only NSP files will appear. +* Set 'Show only *.nsp in Goldleaf' to filter all files displayed at HOME:/ drive. So only NSP files will appear. ##### 'Dialog with three dots' tab. @@ -187,7 +189,7 @@ To get help run ``$ java -jar ns-usbloader-4.0.jar --help`` ``` -c,--clean Remove/reset settings and exit - -g,--goldleaf <...> Install via GoldLeaf mode. Check '-g help' for information. + -g,--Goldleaf <...> Install via Goldleaf mode. Check '-g help' for information. -h,--help Show this help -m,--merge <...> Merge files. Check '-m help' for information. -n,--tfn <...> Install via Awoo Network mode. Check '-n help' for information. @@ -218,7 +220,7 @@ Send RCM payload: $ java -jar ns-usbloader-4.0.jar -r C:\Users\Superhero\hekate.bin Send files to Awoo Installer via Net-install: $ java -jar ns-usbloader-4.0.jar -n nsip=192.168.0.1 ./file.nsz ./file.nsp ~/*.xci -Send files to GoldLeaf v0.8: +Send files to Goldleaf v0.8: $ java -jar ns-usbloader-4.0.jar -g ver=v0.8 ./* Split files: $ java -jar ns-usbloader-4.0.jar -s /tmp/ ~/*.nsp @@ -229,7 +231,7 @@ $ java -jar ns-usbloader-4.0.jar -m /tmp/ ~/*.nsp ### Other notes 'Status' = 'Uploaded' that appears in the table does not mean that file has been installed. It means that it has been sent to NS without any issues! That's what this app about. -Handling successful/failed installation is a purpose of the other side application: Awoo/Awoo-like or GoldLeaf. And they don't provide any feedback interfaces so I can't detect success/failure. +Handling successful/failed installation is a purpose of the other side application: Awoo/Awoo-like or Goldleaf. And they don't provide any feedback interfaces so I can't detect success/failure. #### What is this '-legacy' jar?! diff --git a/misc/freedesktop_entry/ns-usbloader.desktop b/misc/freedesktop_entry/ns-usbloader.desktop new file mode 100755 index 0000000..d402210 --- /dev/null +++ b/misc/freedesktop_entry/ns-usbloader.desktop @@ -0,0 +1,9 @@ +#!/usr/bin/env xdg-open +[Desktop Entry] +Type=Application +Name=NS-USBloader +Exec=ns-usbloader +Comment=NS multi tool +Terminal=false +Icon=ns-usbloader.svg +Categories=Game; diff --git a/misc/freedesktop_entry/ns-usbloader.svg b/misc/freedesktop_entry/ns-usbloader.svg new file mode 100644 index 0000000..75a45a7 --- /dev/null +++ b/misc/freedesktop_entry/ns-usbloader.svg @@ -0,0 +1,118 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index b3c4607..346cec4 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ https://redrise.ru - NS multi-tool + NS multi tool 2019 @@ -61,28 +61,28 @@ org.openjfx javafx-controls - 18.0.1 + 19 linux compile org.openjfx javafx-media - 18.0.1 + 19 linux compile org.openjfx javafx-fxml - 18.0.1 + 19 linux compile org.openjfx javafx-graphics - 18.0.1 + 19 linux compile @@ -90,28 +90,28 @@ org.openjfx javafx-controls - 18.0.1 + 19 win compile org.openjfx javafx-media - 18.0.1 + 19 win compile org.openjfx javafx-fxml - 18.0.1 + 19 win compile org.openjfx javafx-graphics - 18.0.1 + 19 win compile @@ -119,31 +119,60 @@ org.openjfx javafx-controls - 18.0.1 + 19 mac compile org.openjfx javafx-media - 18.0.1 + 19 mac compile org.openjfx javafx-fxml - 18.0.1 + 19 mac compile org.openjfx javafx-graphics - 18.0.1 + 19 mac compile + + + org.openjfx + javafx-controls + 19 + mac-aarch64 + compile + + + org.openjfx + javafx-media + 19 + mac-aarch64 + compile + + + org.openjfx + javafx-fxml + 19 + mac-aarch64 + compile + + + org.openjfx + javafx-graphics + 19 + mac-aarch64 + compile + org.usb4java @@ -170,6 +199,13 @@ 5.9.0 test + + + ru.redrise + libKonogonka + 0.1-SNAPSHOT + compile + ${project.artifactId}-${project.version}-${maven.build.timestamp} @@ -243,10 +279,10 @@ - com.akathist.maven.plugins.launch4j - 1.7.25 + 2.2.0 launch4j-maven-plugin @@ -258,8 +294,8 @@ gui appicon.ico - target/NS-USBloader-${project.version}.exe - target/ns-usbloader-${project.version}-jar-with-dependencies.jar + target/NS-USBloader-${project.version}-${maven.build.timestamp}.exe + target/${project.artifactId}-${project.version}-${maven.build.timestamp}.jar NS-USBloader nsusbloader.Main @@ -267,13 +303,14 @@ anything - 1.8 + 1.8.0 + %JAVA_HOME%;%PATH% 1.0.0.0 ${project.version} - Awoo and GoldLeaf installer for your NS - GNU General Public License v3, 2019 ${project.organization.name}. Russia/LPR. + NS multi tool + GNU General Public License v3, 2019 ${project.organization.name}, Russia. 1.0.0.0 ${project.version} ${project.organization.name} @@ -285,7 +322,6 @@ - --> \ No newline at end of file diff --git a/screenshots/ApplicationLogo.svg b/screenshots/ApplicationLogo.svg index 222de82..852045a 100644 --- a/screenshots/ApplicationLogo.svg +++ b/screenshots/ApplicationLogo.svg @@ -1,19 +1,19 @@ + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + sodipodi:docname="Application Logo.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + inkscape:document-rotation="0" + inkscape:showpageshadow="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1"> + originx="-40.99399" + originy="-37.999752" /> @@ -54,7 +57,6 @@ image/svg+xml - @@ -114,145 +116,65 @@ inkscape:connector-curvature="0" style="fill:#ffffff;stroke-width:0.0680452" inkscape:label="usb_logo" /> - NS-USBloader + id="text982" + style="font-size:1.43163px;line-height:1.25;font-family:Play;-inkscape-font-specification:'Play, Normal';letter-spacing:0px;word-spacing:0px;fill:#ffffff;stroke-width:0.357908" + inkscape:label="ns-usbloader"> + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Dmitry Isaenko diff --git a/src/main/java/nsusbloader/AppPreferences.java b/src/main/java/nsusbloader/AppPreferences.java index 363f9ba..d774ae0 100644 --- a/src/main/java/nsusbloader/AppPreferences.java +++ b/src/main/java/nsusbloader/AppPreferences.java @@ -88,6 +88,8 @@ public class AppPreferences { public String getHostIp(){ return preferences.get("HOSTIP", "0.0.0.0").replaceAll("(\\s)|(\t)", "");} // who the hell said 'paranoid'? public void setHostIp(String ip){preferences.put("HOSTIP", ip);} + public void give(){preferences.putBoolean("man", true);} + public boolean take(){return preferences.getBoolean("man", false);} public String getHostPort(){ String value = preferences.get("HOSTPORT", "6042"); if (!value.matches("^[0-9]{1,5}$")) @@ -138,4 +140,10 @@ public class AppPreferences { public String getLastOpenedTab(){ return preferences.get("recent_tab", ""); } public void setLastOpenedTab(String tabId){ preferences.put("recent_tab", tabId); } + // Patches + public String getKeysLocation(){ return preferences.get("keys", ""); } + public void setKeysLocation(String path){ preferences.put("keys", path); } + + public String getPatchesSaveToLocation(){ return FilesHelper.getRealFolder(preferences.get("patches_saveto", System.getProperty("user.home"))); } + public void setPatchesSaveToLocation(String value){ preferences.put("patches_saveto", value); } } diff --git a/src/main/java/nsusbloader/Controllers/NSLMainController.java b/src/main/java/nsusbloader/Controllers/NSLMainController.java index 99fa2d0..cc051b3 100644 --- a/src/main/java/nsusbloader/Controllers/NSLMainController.java +++ b/src/main/java/nsusbloader/Controllers/NSLMainController.java @@ -43,7 +43,7 @@ public class NSLMainController implements Initializable { @FXML private TabPane mainTabPane; @FXML - private Tab GamesTabHolder, RCMTabHolder, SMTabHolder; + private Tab GamesTabHolder, RCMTabHolder, SMTabHolder, PatchesTabHolder; @FXML private GamesController GamesTabController; @@ -55,6 +55,8 @@ public class NSLMainController implements Initializable { private RcmController RcmTabController; @FXML private NxdtController NXDTabController; + @FXML + private PatchesController PatchesTabController; @Override public void initialize(URL url, ResourceBundle rb) { @@ -71,7 +73,7 @@ public class NSLMainController implements Initializable { if (AppPreferences.getInstance().getAutoCheckUpdates()){ checkForUpdates(); } - + if (! AppPreferences.getInstance().take()) mainTabPane.getTabs().remove(3); openLastOpenedTab(); } private void checkForUpdates(){ @@ -127,6 +129,8 @@ public class NSLMainController implements Initializable { public RcmController getRcmCtrlr(){ return RcmTabController; } public NxdtController getNXDTabController(){ return NXDTabController; } + + public PatchesController getPatchesTabController(){ return PatchesTabController; } /** * Save preferences before exit * */ @@ -136,7 +140,7 @@ public class NSLMainController implements Initializable { SplitMergeTabController.updatePreferencesOnExit(); // NOTE: This shit above should be re-written to similar pattern RcmTabController.updatePreferencesOnExit(); NXDTabController.updatePreferencesOnExit(); - + PatchesTabController.updatePreferencesOnExit(); saveLastOpenedTab(); } @@ -152,6 +156,9 @@ public class NSLMainController implements Initializable { case "SMTabHolder": mainTabPane.getSelectionModel().select(SMTabHolder); break; + case "PatchesTabHolder": + mainTabPane.getSelectionModel().select(PatchesTabHolder); + break; } } private void saveLastOpenedTab(){ diff --git a/src/main/java/nsusbloader/Controllers/PatchesController.java b/src/main/java/nsusbloader/Controllers/PatchesController.java new file mode 100644 index 0000000..66aaaf7 --- /dev/null +++ b/src/main/java/nsusbloader/Controllers/PatchesController.java @@ -0,0 +1,225 @@ +/* + Copyright 2018-2022 Dmitry Isaenko + + This file is part of NS-USBloader. + + NS-USBloader 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. + + NS-USBloader 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 NS-USBloader. If not, see . + */ +package nsusbloader.Controllers; + +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.input.DragEvent; +import javafx.scene.input.TransferMode; + +import java.io.File; +import java.net.URL; +import java.util.List; +import java.util.ResourceBundle; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; +import javafx.stage.DirectoryChooser; +import javafx.stage.FileChooser; +import nsusbloader.AppPreferences; +import nsusbloader.FilesHelper; +import nsusbloader.MediatorControl; +import nsusbloader.NSLDataTypes.EModule; +import nsusbloader.ServiceWindow; +import nsusbloader.Utilities.patches.es.EsPatchMaker; + +// TODO: CLI SUPPORT +public class PatchesController implements Initializable { + @FXML + private VBox patchesToolPane; + @FXML + private Button selFwFolderBtn, selProdKeysBtn, makeEsBtn; + @FXML + private Label shortNameFirmwareLbl, locationFirmwareLbl, saveToLbl, shortNameKeysLbl, locationKeysLbl, statusLbl; + private Thread workThread; + + private String previouslyOpenedPath; + private ResourceBundle resourceBundle; + private Region convertRegion; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + this.resourceBundle = resourceBundle; + this.previouslyOpenedPath = System.getProperty("user.home"); + + String myRegexp; + if (File.separator.equals("/")) + myRegexp = "^.+/"; + else + myRegexp = "^.+\\\\"; + locationFirmwareLbl.textProperty().addListener((observableValue, currentText, updatedText) -> + shortNameFirmwareLbl.setText(updatedText.replaceAll(myRegexp, ""))); + + locationKeysLbl.textProperty().addListener((observableValue, currentText, updatedText) -> + shortNameKeysLbl.setText(updatedText.replaceAll(myRegexp, ""))); + + convertRegion = new Region(); + convertRegion.getStyleClass().add("regionCake"); + makeEsBtn.setGraphic(convertRegion); + + AppPreferences preferences = AppPreferences.getInstance(); + String keysLocation = preferences.getKeysLocation(); + File keysFile = new File(keysLocation); + + if (keysFile.exists() && keysFile.isFile()) { + locationKeysLbl.setText(keysLocation); + } + + saveToLbl.setText(preferences.getPatchesSaveToLocation()); + //makeEsBtn.disableProperty().bind(Bindings.isEmpty(locationFirmwareLbl.textProperty())); + makeEsBtn.setOnAction(actionEvent -> makeEs()); + } + + /** + * Drag-n-drop support (dragOver consumer) + * */ + @FXML + private void handleDragOver(DragEvent event){ + if (event.getDragboard().hasFiles()) + event.acceptTransferModes(TransferMode.ANY); + event.consume(); + } + /** + * Drag-n-drop support (drop consumer) + * */ + @FXML + private void handleDrop(DragEvent event){ + List filesDropped = event.getDragboard().getFiles(); + for (File file : filesDropped){ + if (file.isDirectory()) { + locationFirmwareLbl.setText(file.getAbsolutePath()); + continue; + } + String fileName = file.getName().toLowerCase(); + if ((fileName.endsWith(".dat")) || + (fileName.endsWith(".keys") && + ! fileName.equals("dev.keys") && + ! fileName.equals("title.keys"))) + locationKeysLbl.setText(file.getAbsolutePath()); + } + event.setDropCompleted(true); + event.consume(); + } + @FXML + private void selectFirmware(){ + DirectoryChooser directoryChooser = new DirectoryChooser(); + directoryChooser.setTitle(resourceBundle.getString("tabPatches_Lbl_Firmware")); + directoryChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); + File firmware = directoryChooser.showDialog(patchesToolPane.getScene().getWindow()); + if (firmware == null) + return; + locationFirmwareLbl.setText(firmware.getAbsolutePath()); + } + @FXML + private void selectSaveTo(){ + DirectoryChooser directoryChooser = new DirectoryChooser(); + directoryChooser.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFolder")); + directoryChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); + File saveToDir = directoryChooser.showDialog(patchesToolPane.getScene().getWindow()); + if (saveToDir == null) + return; + saveToLbl.setText(saveToDir.getAbsolutePath()); + } + @FXML + private void selectProdKeys(){ + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle(resourceBundle.getString("tabPatches_Lbl_Keys")); + fileChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("keys", "*.dat", "*.keys")); + File keys = fileChooser.showOpenDialog(patchesToolPane.getScene().getWindow()); + + if (keys != null && keys.exists()) { + locationKeysLbl.setText(keys.getAbsolutePath()); + } + } + + private void makeEs(){ + if (locationFirmwareLbl.getText().isEmpty() || locationKeysLbl.getText().isEmpty()){ + ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"), + resourceBundle.getString("tabPatches_ServiceWindowMessage")); + return; + } + + if (workThread != null && workThread.isAlive()) + return; + statusLbl.setText(""); + + if (MediatorControl.getInstance().getTransferActive()) { + ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"), + resourceBundle.getString("windowBodyPleaseStopOtherProcessFirst")); + return; + } + + EsPatchMaker esPatchMaker = new EsPatchMaker(locationFirmwareLbl.getText(), locationKeysLbl.getText(), + saveToLbl.getText()); + workThread = new Thread(esPatchMaker); + + workThread.setDaemon(true); + workThread.start(); + } + private void interruptProcessOfPatchMaking(){ + if (workThread == null || ! workThread.isAlive()) + return; + + workThread.interrupt(); + } + + public void notifyThreadStarted(boolean isActive, EModule type) { + if (! type.equals(EModule.PATCHES)) { + patchesToolPane.setDisable(isActive); + return; + } + + convertRegion.getStyleClass().clear(); + + if (isActive) { + MediatorControl.getInstance().getContoller().logArea.clear(); + convertRegion.getStyleClass().add("regionStop"); + + makeEsBtn.setOnAction(e-> interruptProcessOfPatchMaking()); + makeEsBtn.setText(resourceBundle.getString("btn_Stop")); + makeEsBtn.getStyleClass().remove("buttonUp"); + makeEsBtn.getStyleClass().add("buttonStop"); + } + else { + convertRegion.getStyleClass().add("regionCake"); + + makeEsBtn.setOnAction(actionEvent -> makeEs()); + makeEsBtn.setText(resourceBundle.getString("tabPatches_Btn_MakeEs")); + makeEsBtn.getStyleClass().remove("buttonStop"); + makeEsBtn.getStyleClass().add("buttonUp"); + } + } + + public void setOneLineStatus(boolean statusSuccess){ + if (statusSuccess) + statusLbl.setText(resourceBundle.getString("done_txt")); + else + statusLbl.setText(resourceBundle.getString("failure_txt")); + } + + void updatePreferencesOnExit(){ + AppPreferences.getInstance().setPatchesSaveToLocation(saveToLbl.getText()); + if (locationKeysLbl.getText().isEmpty()) + return; + AppPreferences.getInstance().setKeysLocation(locationKeysLbl.getText()); + } + +} \ No newline at end of file diff --git a/src/main/java/nsusbloader/MediatorControl.java b/src/main/java/nsusbloader/MediatorControl.java index 3717ad2..b15b409 100644 --- a/src/main/java/nsusbloader/MediatorControl.java +++ b/src/main/java/nsusbloader/MediatorControl.java @@ -40,11 +40,12 @@ public class MediatorControl { } public NSLMainController getContoller(){ return mainController; } - public GamesController getGamesController(){ return mainController.getGamesCtrlr(); }; - public SettingsController getSettingsController(){ return mainController.getSettingsCtrlr(); }; - public SplitMergeController getSplitMergeController(){ return mainController.getSmCtrlr(); }; - public RcmController getRcmController(){ return mainController.getRcmCtrlr(); }; - public NxdtController getNxdtController(){ return mainController.getNXDTabController(); }; + public GamesController getGamesController(){ return mainController.getGamesCtrlr(); } + public SettingsController getSettingsController(){ return mainController.getSettingsCtrlr(); } + public SplitMergeController getSplitMergeController(){ return mainController.getSmCtrlr(); } + public RcmController getRcmController(){ return mainController.getRcmCtrlr(); } + public NxdtController getNxdtController(){ return mainController.getNXDTabController(); } + public PatchesController getPatchesController(){ return mainController.getPatchesTabController(); } public ResourceBundle getResourceBundle(){ return mainController.getResourceBundle(); @@ -56,6 +57,7 @@ public class MediatorControl { getSplitMergeController().notifyThreadStarted(isActive, appModuleType); getRcmController().notifyThreadStarted(isActive, appModuleType); getNxdtController().notifyThreadStarted(isActive, appModuleType); + getPatchesController().notifyThreadStarted(isActive, appModuleType); } public synchronized boolean getTransferActive() { return this.isTransferActive.get(); } } diff --git a/src/main/java/nsusbloader/ModelControllers/MessagesConsumer.java b/src/main/java/nsusbloader/ModelControllers/MessagesConsumer.java index ba4b294..08add56 100644 --- a/src/main/java/nsusbloader/ModelControllers/MessagesConsumer.java +++ b/src/main/java/nsusbloader/ModelControllers/MessagesConsumer.java @@ -112,6 +112,8 @@ public class MessagesConsumer extends AnimationTimer { case SPLIT_MERGE_TOOL: MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get()); break; + case PATCHES: + MediatorControl.getInstance().getPatchesController().setOneLineStatus(oneLinerStatus.get()); } this.stop(); } diff --git a/src/main/java/nsusbloader/NSLDataTypes/EModule.java b/src/main/java/nsusbloader/NSLDataTypes/EModule.java index b8331a0..b144d7b 100644 --- a/src/main/java/nsusbloader/NSLDataTypes/EModule.java +++ b/src/main/java/nsusbloader/NSLDataTypes/EModule.java @@ -22,5 +22,6 @@ public enum EModule { USB_NET_TRANSFERS, SPLIT_MERGE_TOOL, RCM, - NXDT + NXDT, + PATCHES } diff --git a/src/main/java/nsusbloader/NSLMain.java b/src/main/java/nsusbloader/NSLMain.java index aa03af7..bd70c80 100644 --- a/src/main/java/nsusbloader/NSLMain.java +++ b/src/main/java/nsusbloader/NSLMain.java @@ -28,6 +28,7 @@ import nsusbloader.Controllers.NSLMainController; import nsusbloader.cli.CommandLineInterface; import java.util.Locale; +import java.util.Objects; import java.util.ResourceBundle; public class NSLMain extends Application { @@ -47,10 +48,10 @@ public class NSLMain extends Application { Parent root = loader.load(); primaryStage.getIcons().addAll( - new Image(getClass().getResourceAsStream("/res/app_icon32x32.png")), - new Image(getClass().getResourceAsStream("/res/app_icon48x48.png")), - new Image(getClass().getResourceAsStream("/res/app_icon64x64.png")), - new Image(getClass().getResourceAsStream("/res/app_icon128x128.png")) + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon32x32.png"))), + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon48x48.png"))), + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon64x64.png"))), + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon128x128.png"))) ); primaryStage.setTitle("NS-USBloader "+appVersion); diff --git a/src/main/java/nsusbloader/Utilities/patches/es/BinToAsmPrinter.java b/src/main/java/nsusbloader/Utilities/patches/es/BinToAsmPrinter.java new file mode 100644 index 0000000..d3e2024 --- /dev/null +++ b/src/main/java/nsusbloader/Utilities/patches/es/BinToAsmPrinter.java @@ -0,0 +1,526 @@ +/* + Copyright 2018-2022 Dmitry Isaenko + + This file is part of NS-USBloader. + + NS-USBloader 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. + + NS-USBloader 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 NS-USBloader. If not, see . + */ +package nsusbloader.Utilities.patches.es; + +import libKonogonka.Converter; +import nsusbloader.Main; +import nsusbloader.NSLMain; + +public class BinToAsmPrinter { + static { + boolean notWindows = ! System.getProperty("os.name").toLowerCase().contains("windows"); + + if(notWindows && NSLMain.isCli){ + ANSI_RESET = "\u001B[0m"; + ANSI_GREEN = "\u001B[32m"; + ANSI_BLUE = "\u001B[34m"; + ANSI_YELLOW = "\u001B[33m"; + ANSI_PURPLE = "\u001B[35m"; + ANSI_CYAN = "\u001B[36m"; + ANSI_RED = "\u001B[31m"; + } + else { + ANSI_RESET = ANSI_RED = ANSI_GREEN = ANSI_BLUE = ANSI_YELLOW = ANSI_PURPLE = ANSI_CYAN = ""; + } + } + private static final String ANSI_RESET; + private static final String ANSI_RED; + private static final String ANSI_GREEN; + private static final String ANSI_BLUE; + private static final String ANSI_YELLOW; + private static final String ANSI_PURPLE; + private static final String ANSI_CYAN; + + public static String print(int instructionExpression, int offset){ + if (instructionExpression == 0xd503201f) + return printNOP(instructionExpression); + + if ((instructionExpression & 0x7FE0FFE0) == 0x2A0003E0) { + return printMOVRegister(instructionExpression); + } + + switch ((instructionExpression >> 23 & 0b011111111)){ + case 0xA5: + return printMOV(instructionExpression); + case 0x62: + if (((instructionExpression & 0x1f) == 0x1f)){ + return printCMN(instructionExpression, offset); + } + } + + switch (instructionExpression >> 24 & 0xff) { + case 0x34: + case 0xb4: + return printCBZ(instructionExpression, offset); + case 0xb5: + case 0x35: + return printCBNZ(instructionExpression, offset); + case 0x36: + case 0xb6: + return printTBZ(instructionExpression, offset); + case 0x54: + return printBConditional(instructionExpression, offset); + } + switch ((instructionExpression >> 26 & 0b111111)) { + case 0x5: + return printB(instructionExpression, offset); + case 0x25: + return printBL(instructionExpression, offset); + } + + return printUnknown(instructionExpression); + } + public static String printSimplified(int instructionExpression, int offset){ + if (instructionExpression == 0xd503201f) + return printNOPSimplified(instructionExpression, offset); + + if ((instructionExpression & 0x7FE0FFE0) == 0x2A0003E0) { + return printMOVRegisterSimplified(instructionExpression, offset); + } + + switch (instructionExpression >> 22 & 0b1011111111) { + case 0x2e5: + return printLRDImmUnsignSimplified(instructionExpression, offset); + case 0xe5: + return printLRDBImmUnsignSimplified(instructionExpression, offset); + } + + if ((instructionExpression >> 21 & 0x7FF) == 0x1C2) + return printLDURBSimplified(instructionExpression, offset); + + // same to (afterJumpExpression >> 23 & 0x1F9) != 0xA1 + switch (instructionExpression >> 22 & 0x1FF){ + case 0xA3: // 0b10100011 + case 0xA7: // 0b10100111 + case 0xA5: // 0b10100101 + return printLDPSimplified(instructionExpression, offset); + } + + switch ((instructionExpression >> 23 & 0xff)){ + case 0xA5: + return printMOVSimplified(instructionExpression, offset); + case 0x22: + return printADDSimplified(instructionExpression, offset); + case 0x62: + if (((instructionExpression & 0x1f) == 0x1f)){ + return printCMNSimplified(instructionExpression, offset); + } + case 0xA2: + return printSUBSimplified(instructionExpression, offset); + } + + switch (instructionExpression >> 24 & 0xff) { + case 0x34: + case 0xb4: + return printCBZSimplified(instructionExpression, offset); + case 0xb5: + case 0x35: + return printCBNZSimplified(instructionExpression, offset); + case 0x36: + case 0xb6: + return printTBZSimplified(instructionExpression, offset); + case 0x54: + return printBConditionalSimplified(instructionExpression, offset); + } + + switch ((instructionExpression >> 26 & 0b111111)) { + case 0x5: + return printBSimplified(instructionExpression, offset); + case 0x25: + return printBLSimplified(instructionExpression, offset); + } + return printUnknownSimplified(instructionExpression, offset); + } + + private static String printCBZ(int instructionExpression, int offset){ + int conditionalJumpLocation = ((instructionExpression >> 5 & 0x7FFFF) * 4 + offset) & 0xfffff; + + return String.format(ANSI_YELLOW + "sf == 0 ? else \n" + + "CBZ ,