Compare commits

...

1 commit

Author SHA1 Message Date
Dmitry Isaenko
77ae860396 DarkMatterCore/nxdumptool support
Hotfix within adding DarkMatterCore/nxdumptool support: fix 'Stop' button functionality

Update NxdtUsbAbi1.java

Rename method isInvalidCommand() -> isInvalidCommand()

A bit more renames and debug things

More refactoring

Typos fixes

He just told me that 'NXDT_COMMAND_HEADER_SIZE was added to reflect the UsbCommandHeader struct from my codebase. No received command should ever be smaller than this. NXDT_COMMAND_SIZE was renamed to NXDT_MAX_COMMAND_SIZE for this reason.'

Some bug fixes

With debug

Few more fixes

Copy-paste Windows10 workaround fix

Add NXDT_FILE_PROPERTIES_MAX_NAME_LENGTH validation

Fix NXDT_FILE_PROPERTIES_MAX_NAME_LENGTH validation

If fileSize == 0 only one success reply sent

Add debug

rewrite timeouts

One more rewrite timeouts
2020-05-13 02:25:37 +03:00
18 changed files with 726 additions and 143 deletions

View file

@ -1,135 +0,0 @@
# NS-USBloader
NS-USBloader는 PC-side **[Adubbz/TinFoil](https://github.com/Adubbz/Tinfoil/)** (버전 0.2.1; USB와 네트워크)와 **GoldLeaf** (USB) NSP 설치 프로그램 입니다. 기본 **usb_install_pc.py**, **remote_install_pc.py** *(당신이 용감할지라도 사용하지 마십시오. 왜 작동하는지 모르겠음)* 와 **GoldTree**를 대체할 수 있습니다.
GUI와 쿠키. Windows, macOS, Linux에서 작동합니다.
가끔씩 이 프로젝트에 대한 새로운 게시물을 [내 홈페이지](https://developersu.blogspot.com/search/label/NS-USBloader). 에 추가합니다.
![스크린샷](https://farm8.staticflickr.com/7809/46703921964_53f60f04ed_o.png)
### 라이센스
[GNU 일반 공개 라이센스 v3](https://github.com/developersu/ns-usbloader/blob/master/LICENSE)
### 사용된 라이브러리 & 리소스
* [OpenJFX](https://wiki.openjdk.java.net/display/OpenJFX/Main)
* [usb4java](https://mvnrepository.com/artifact/org.usb4java/usb4java)
* [materialdesignicons.com](http://materialdesignicons.com/) 에서 가져온 아이콘은 거의 없습니다.
### 시스템 요구사항
JRE/JDK 8u60 또는 이상.
### 사용법
#### 그것을 시작하는 방법.
##### Linux:
1. JRE/JDK 8u60 이상을 설치하십시오 (openJDK는 좋습니다. 오라클의 것도 좋습니다). JavaFX는 필요하지 않습니다 (내장되어 있습니다).
2. `root # java -jar /path/to/NS-USBloader.jar`
##### macOS
다운로드 한 .jar 파일을 더블 클릭하십시오. 지시를 따릅니다. 또는 'Linux' 섹션을 참조하십시오.
필요한 경우 '보안 & 개인 정보' 설정을 지정하십시오.
##### Windows:
* Zadig 다운로드: [https://zadig.akeo.ie/](https://zadig.akeo.ie/)
* TinFoil 열기. '타이틀 관리' -> 'Usb 설치 NSP' 설정
* NS를 PC에 연결
* Zadig 열기
* '옵션'을 클릭하고 '모든 장치 나열' 선택
* 드롭다운에서 NS를 선택하고 'libusbK (v3.0.7.0)'(버전이 다를 수 있음)을 선택하고 'WCID 드라이버 설치' 클릭.
* 시스템의 장치 목록에서 'libusbK USB Devices' 폴더가 있고 그 안에 NS가 있는지 확인.
* [Java JRE 다운로드 및 설치](http://java.com/download/) (8u60 또는 이상)
* 이 응용 프로그램 (JAR 파일)을 두 번 클릭합니다 (또는 'cmd'를 열고 'java -jar thisAppName.jar'을 통해 jar이 위치한 곳으로 이동).
* 즐거운 시간을 보내십시오!
#### 어떻게 사용합니까?
가장 먼저해야 할 일은 NS에 TinFoil ([Adubbz] (https://github.com/Adubbz/Tinfoil/)) 또는 GoldLeaf ([XorTroll] (https://github.com/XorTroll/Goldleaf)) 를 설치하는 것입니다. 나는 TinFoil을 사용하는 것을 권하지만, 그것은 당신에게 달려있습니다. 앱을보고 USB 및/또는 네트워크에서 설치할 수 있는 옵션을 찾으십시오. 아마 [이 게시물] (https://developersu.blogspot.com/2019/02/ns-usbloader-en.html) 이 도움이 될 것입니다.
여기에 '완벽하지 않지만 어쨌든' [내가 사용하는 tinfoil](https://cloud.mail.ru/public/DwbX/H8d2p3aYR) 이 있습니다.
좋아, 나는 이 버전에 버그가 있다는 것을 거의 확신합니다. 나는 그것을 어디에서 다운로드했는지 기억하지 않지만, 그것은 어떻게든 나를 위해 작동합니다.
TinFoil의 작업 버전을 가지고 있다면 이것을 **사용하지 마십시오**. 좋아요. 시작합니다.
세 개의 탭이 있습니다. 첫번째 것은 메인입니다.
##### 첫 번째 탭.
상단에서 드롭 다운 응용 프로그램과 프로토콜을 선택하여 사용할 것입니다. GoldLeaf의 경우 USB 만 사용할 수 있습니다. 램프 아이콘은 테마 전환 (밝은 색 또는 어두운 색)을 의미합니다.
그런 다음 NSP 또는 파일이 있는 폴더를 응용 프로그램으로 끌어다 놓거나 'NSP 파일 선택' 버튼을 사용할 수 있습니다. 사용 가능한 파일을 여러 번 선택할 수 있습니다. 다시 클릭하고 원하는 다른 폴더에서 파일을 선택하면 테이블에 추가됩니다.
테이블.
여기에서 신청서 (TF/GL)로 보낼 파일에 대한 확인란을 선택할 수 있습니다. GoldLeaf는 시간당 하나의 파일 전송만을 허용하기 때문에 하나의 파일만 선택할 수 있습니다. 또한 공간을 사용하여 파일을 선택/선택 취소하고 삭제를 위해 '삭제' 버튼을 사용할 수 있습니다. 마우스 오른쪽 버튼을 클릭하면 컨텍스트 메뉴가 표시되어 테이블에서 하나 또는 모든 항목을 삭제할 수 있습니다.
##### 두 번째 탭.
네트워크 파일 전송 설정을 구성 할 수 있습니다. 보통 아무것도 바꾸면 안되지만 당신은 멋진 해커이기에 나아가세요! 가장 흥미로운 옵션은 '요청하지 마십시오' 입니다. TinFoil의 NET 부분 아키텍처가 흥미로운 방식으로 작동하고 있습니다. TF 네트워크 NSP 전송을 선택하면 응용 프로그램은 포트 2000에서 파일을 가져 오는 위치에 대한 정보를 기다립니다. '192.168.1.5:6060/my file.nsp'와 같습니다. 일반적으로 NS-USBloader는 단순화 된 HTTP 서버를 구현하고 이를 가져오는 등 요청을 처리하지만, 이 옵션을 선택하면 파일의 원격 위치에 대한 경로를 정의할 수 있습니다. 예를 들어 '192.168.4.2:80/ROMS/NS/' 설정을 지정하고 'my file.nsp' 테이블 파일을 추가하면 NS-USBloader는 TinFoil에 "'192.168.4.2:80/ROMS/NS/my%20file.nsp'에서 파일 가져오기"로 간단히 언급합니다. 물론 당신은 '192.168.4.2' 호스트를 가져와서 그런 주소에서 파일에 접근 할 수 있게해야 합니다 (그냥 nginx를 설치하십시오). 제가 말했듯이, 이 기능은 재미있지만, 인기가 없을 것입니다.
또한 여기에서 '업데이트 자동 확인'을 선택하거나 버튼을 클릭하여 새 버전의 출시 여부를 확인할 수 있습니다.
##### 세 번째 탭.
그것이 모든 로그가 삭제된 곳입니다. 전송에 대한 자세한 정보는 여기에 있습니다.
왜 'NET'이 한 번 시작되면 결코 끝나지 않습니까?
응용 프로그램 내부에 HTTP 서버가 있기 때문입니다. 모든 전송이 (실패하지 않는 한) 끝나는 순간을 결정할 수는 없습니다. 그래서 당신은 당신의 NS 화면을 보아야만 합니다.
### 팁&트릭
#### Linux: NS-from-root-account를 사용하려면 'udev'규칙에 사용자 추가
```
root # vim /etc/udev/rules.d/99-NS.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="3000", GROUP="plugdev"
root # udevadm control --reload-rules && udevadm trigger
```
### 알려진 버그
* 읽기 이벤트를 기다리는 libusb (사용자가 NSP 목록을 보냈지만 NS에서 아무 것도 선택하지 않은 경우)를 기다릴 때 전송을 방해할 수 없습니다. 때때로 이 문제는 네트워크 전송이 시작되고 NS로부터 아무것도 수신되지 않은 경우에도 나타납니다.
### 다른 참조
표에 'Status' = 'Uploaded'라고 표시되었다고해서 파일이 설치되었다는 의미는 아닙니다. 그것은 어떤 문제없이 NS에 보냈다는 것을 의미합니다! 그것이 바로 이 앱의 특징입니다.
설치 성공/실패 처리는 상대방 응용 프로그램의 목적입니다: TinFoil 또는 GoldLeaf. 그리고 그들은 피드백 인터페이스를 제공하지 않기 때문에 성공/실패를 감지할 수 없습니다.
NS-USBloader-v0.2.3이 1.3.0 대신 1.2.0으로 전환된 이후 usb4java. 이것은 이전 버전의 NS-USBloader가 작동하지 않는 macOS 하이 시에라 (및 시에라, 엘 캐피탄) 사용자를 제외한 모든 사용자에게 영향을 주지 않습니다.
### Translators! Traductores! Übersetzer! Թարգմանիչներ! 번역가!
이 앱을 귀하의 언어로 번역하려면 [이 파일](https://github.com/developersu/ns-usbloader/blob/master/src/main/resources/locale.properties) 클릭하고 번역하십시오.
어딘가에 업로드 (페이스트빈? 구글 드라이브? 그 밖의 무엇이든지). [새로운 이슈 생성](https://github.com/developersu/ns-usbloader/issues) 와 링크를 게시하십시오. 검토하여 추가할 것 입니다.
참고: 사실 우리가 연락을 해야하기 때문에 실제로 작동하지 않을 것입니다. 번역해야 할 것을 추가할 때 필요합니다. =(
### 번역가가 해준 위대한 일에 감사드립니다!
프랑스어 [Stephane Meden (JackFromNice)](https://github.com/JackFromNice)
이탈리아어 [unbranched](https://github.com/unbranched)
#### (아마도) 할 일:
- [x] macOS QA v0.1 (모하비)
- [x] macOS QA v0.2.2 (모하비)
- [x] macOS QA v0.2.3-DEV (하이 시에라)
- [x] macOS QA v0.3
- [x] 윈도우 지원
- [x] 코드 리팩터링
- [x] GoldLeaf 지원
- [ ] XCI 지원
- [ ] 파일 순서 정렬 (중요하지 않음)
- [ ] 업로드 전 더 심오하게 파일 분석.
- [x] TinFoil에 대한 네트워크 모드 지원
- [x] '응용 프로그램 업데이트 확인' 기능
#### 감사
Vitaliy과 Konstantin의 도움과 지원에 감사드립니다. 당신들 없이는 이 모든 마법은 일어나지 않았을 겁니다.
[Konstanin Kelemen](https://github.com/konstantin-kelemen)
[Vitaliy Natarov](https://github.com/SebastianUA)

View file

@ -8,7 +8,7 @@
<name>NS-USBloader</name>
<artifactId>ns-usbloader</artifactId>
<version>2.2.1-SNAPSHOT</version>
<version>3.0-SNAPSHOT</version>
<url>https://github.com/developersu/ns-usbloader/</url>
<description>

View file

@ -152,4 +152,7 @@ public class AppPreferences {
// RCM //
public String getRecentRcm(int num){ return preferences.get(String.format("RCM_%02d", num), ""); }
public void setRecentRcm(int num, String value){ preferences.put(String.format("RCM_%02d", num), value); }
// NXDT //
public String getNXDTSaveToLocation(){ return preferences.get("nxdt_saveto", System.getProperty("user.home")); }
public void setNXDTSaveToLocation(String value){ preferences.put("nxdt_saveto", value); }
}

View file

@ -48,6 +48,8 @@ public class NSLMainController implements Initializable {
private SplitMergeController SplitMergeTabController;
@FXML
private RcmController RcmTabController;
@FXML
private NxdtController NXDTabController;
@Override
public void initialize(URL url, ResourceBundle rb) {
@ -110,6 +112,8 @@ public class NSLMainController implements Initializable {
}
public RcmController getRcmCtrlr(){ return RcmTabController; }
public NxdtController getNXDTabController(){ return NXDTabController; }
/**
* Save preferences before exit
* */
@ -135,5 +139,6 @@ public class NSLMainController implements Initializable {
SplitMergeTabController.updatePreferencesOnExit(); // NOTE: This shit above should be re-written to similar pattern
RcmTabController.updatePreferencesOnExit();
NXDTabController.updatePreferencesOnExit();
}
}

View file

@ -0,0 +1,139 @@
/*
Copyright 2019-2020 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 <https://www.gnu.org/licenses/>.
*/
package nsusbloader.Controllers;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Region;
import javafx.stage.DirectoryChooser;
import nsusbloader.AppPreferences;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.Utilities.NxdtTask;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
public class NxdtController implements Initializable {
@FXML
private Label saveToLocationLbl, statusLbl;
@FXML
private Button injectPldBtn;
private ResourceBundle rb;
private Region btnDumpStopImage;
private Task<Boolean> NxdtTask;
private Thread workThread;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
this.rb = resourceBundle;
File saveToValidator = new File(AppPreferences.getInstance().getNXDTSaveToLocation());
if (saveToValidator.exists())
saveToLocationLbl.setText(saveToValidator.getAbsolutePath());
else
saveToLocationLbl.setText(System.getProperty("user.home"));
btnDumpStopImage = new Region();
btnDumpStopImage.getStyleClass().add("regionDump");
injectPldBtn.getStyleClass().add("buttonUp");
injectPldBtn.setGraphic(btnDumpStopImage);
injectPldBtn.setOnAction(event -> startDumpProcess());
}
@FXML
private void bntSelectSaveTo(){
DirectoryChooser dc = new DirectoryChooser();
dc.setTitle(rb.getString("tabSplMrg_Btn_SelectFolder"));
dc.setInitialDirectory(new File(saveToLocationLbl.getText()));
File saveToDir = dc.showDialog(saveToLocationLbl.getScene().getWindow());
if (saveToDir != null)
saveToLocationLbl.setText(saveToDir.getAbsolutePath());
}
/**
* Start reading commands from NXDT button handler
* */
private void startDumpProcess(){
if ((workThread == null || ! workThread.isAlive())){
MediatorControl.getInstance().getContoller().logArea.clear();
NxdtTask = new NxdtTask(saveToLocationLbl.getText());
NxdtTask.setOnSucceeded(event -> {
if (NxdtTask.getValue())
statusLbl.setText(rb.getString("done_txt"));
else
statusLbl.setText(rb.getString("failure_txt"));
});
workThread = new Thread(NxdtTask);
workThread.setDaemon(true);
workThread.start();
}
}
/**
* Interrupt thread NXDT button handler
* */
private void stopBtnAction(){
if (workThread != null && workThread.isAlive()){
NxdtTask.cancel(false);
}
}
public void notifyThreadStarted(boolean isActive, EModule type){
if (! type.equals(EModule.NXDT)){
injectPldBtn.setDisable(isActive);
return;
}
if (isActive) {
btnDumpStopImage.getStyleClass().clear();
btnDumpStopImage.getStyleClass().add("regionStop");
injectPldBtn.setOnAction(e-> stopBtnAction());
injectPldBtn.setText(rb.getString("btn_Stop"));
injectPldBtn.getStyleClass().remove("buttonUp");
injectPldBtn.getStyleClass().add("buttonStop");
return;
}
btnDumpStopImage.getStyleClass().clear();
btnDumpStopImage.getStyleClass().add("regionDump");
injectPldBtn.setOnAction(e-> startDumpProcess());
injectPldBtn.setText(rb.getString("tabNXDT_Btn_Start"));
injectPldBtn.getStyleClass().remove("buttonStop");
injectPldBtn.getStyleClass().add("buttonUp");
}
/**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
AppPreferences.getInstance().setNXDTSaveToLocation(saveToLocationLbl.getText());
}
}

View file

@ -44,6 +44,7 @@ public class MediatorControl {
mainCtrler.getFrontCtrlr().notifyTransmThreadStarted(isActive, appModuleType);
mainCtrler.getSmCtrlr().notifySmThreadStarted(isActive, appModuleType);
mainCtrler.getRcmCtrlr().notifySmThreadStarted(isActive, appModuleType);
mainCtrler.getNXDTabController().notifyThreadStarted(isActive, appModuleType);
}
public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
}

View file

@ -21,5 +21,6 @@ package nsusbloader.NSLDataTypes;
public enum EModule {
USB_NET_TRANSFERS,
SPLIT_MERGE_TOOL,
RCM
RCM,
NXDT
}

View file

@ -26,12 +26,14 @@ import javafx.scene.image.Image;
import javafx.stage.Stage;
import nsusbloader.Controllers.NSLMainController;
import java.io.File;
import java.nio.file.Paths;
import java.util.Locale;
import java.util.ResourceBundle;
public class NSLMain extends Application {
public static final String appVersion = "v2.2.1";
public static final String appVersion = "v3.0";
@Override
public void start(Stage primaryStage) throws Exception{

View file

@ -41,12 +41,23 @@ public class RainbowHexDump {
System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET);
for (byte b: byteArray)
System.out.print(String.format("%02x ", b));
//System.out.println();
System.out.println();
System.out.print("\t\t\t"
+ new String(byteArray, StandardCharsets.UTF_8)
+ "\n");
}
public static void hexDumpUTF8ForWin(byte[] byteArray){
for (int i=0; i < byteArray.length; i++)
System.out.print(String.format("%02d-", i%100));
System.out.println(">"+byteArray.length);
for (byte b: byteArray)
System.out.print(String.format("%02x ", b));
System.out.println();
System.out.print(new String(byteArray, StandardCharsets.UTF_8)
+ "\n");
}
public static void hexDumpUTF16LE(byte[] byteArray){
System.out.print(ANSI_BLUE);
for (int i=0; i < byteArray.length; i++)
@ -54,8 +65,7 @@ public class RainbowHexDump {
System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET);
for (byte b: byteArray)
System.out.print(String.format("%02x ", b));
System.out.print("\t\t\t"
+ new String(byteArray, StandardCharsets.UTF_16LE)
System.out.print(new String(byteArray, StandardCharsets.UTF_16LE)
+ "\n");
}
}

View file

@ -0,0 +1,60 @@
/*
Copyright 2019-2020 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 <https://www.gnu.org/licenses/>.
*/
package nsusbloader.Utilities;
import javafx.concurrent.Task;
import nsusbloader.COM.USB.UsbConnect;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import org.usb4java.DeviceHandle;
public class NxdtTask extends Task<Boolean> {
private LogPrinter logPrinter;
private String saveToLocation;
public NxdtTask(String saveToLocation){
this.logPrinter = new LogPrinter(EModule.NXDT);
this.saveToLocation = saveToLocation;
}
@Override
protected Boolean call() {
logPrinter.print("Save to location: "+ saveToLocation, EMsgType.INFO);
logPrinter.print("=============== nxdumptool ===============", EMsgType.INFO);
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
if (! usbConnect.isConnected()){
logPrinter.close();
return false;
}
DeviceHandle handler = usbConnect.getNsHandler();
new NxdtUsbAbi1(handler, this, logPrinter, saveToLocation);
logPrinter.print(".:: Complete ::.", EMsgType.PASS);
usbConnect.close();
logPrinter.close();
return true;
}
}

View file

@ -0,0 +1,391 @@
/*
Copyright 2019-2020 Dmitry Isaenko, DarkMatterCore
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 <https://www.gnu.org/licenses/>.
*/
package nsusbloader.Utilities;
import javafx.concurrent.Task;
import nsusbloader.COM.USB.UsbErrorCodes;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EMsgType;
import org.usb4java.DeviceHandle;
import org.usb4java.LibUsb;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
class NxdtUsbAbi1 {
private LogPrinter logPrinter;
private DeviceHandle handlerNS;
private Task<Boolean> task;
private String saveToPath;
private boolean isWindows;
private boolean isWindows10;
private static final int NXDT_MAX_DIRECTIVE_SIZE = 0x1000;
private static final int NXDT_FILE_CHUNK_SIZE = 0x800000;
private static final int NXDT_FILE_PROPERTIES_MAX_NAME_LENGTH = 0x300;
private static final byte ABI_VERSION = 1;
private static final byte[] MAGIC_NXDT = { 0x4e, 0x58, 0x44, 0x54 };
private static final int CMD_HANDSHAKE = 0;
private static final int CMD_SEND_FILE_PROPERTIES = 1;
private static final int CMD_ENDSESSION = 3;
// Standard set of possible replies
private static final byte[] USBSTATUS_SUCCESS = { 0x4e, 0x58, 0x44, 0x54,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
private static final byte[] USBSTATUS_INVALID_MAGIC = { 0x4e, 0x58, 0x44, 0x54,
0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
private static final byte[] USBSTATUS_UNSUPPORTED_CMD = { 0x4e, 0x58, 0x44, 0x54,
0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
private static final byte[] USBSTATUS_UNSUPPORTED_ABI = { 0x4e, 0x58, 0x44, 0x54,
0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
private static final byte[] USBSTATUS_MALFORMED_REQUEST = { 0x4e, 0x58, 0x44, 0x54,
0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
private static final byte[] USBSTATUS_HOSTIOERROR = { 0x4e, 0x58, 0x44, 0x54,
0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
public NxdtUsbAbi1(DeviceHandle handler,
Task<Boolean> task,
LogPrinter logPrinter,
String saveToPath
){
this.handlerNS = handler;
this.task = task;
this.logPrinter = logPrinter;
this.isWindows = System.getProperty("os.name").toLowerCase().contains("windows");
if (isWindows)
isWindows10 = System.getProperty("os.name").toLowerCase().contains("windows 10");
if (! saveToPath.endsWith(File.separator))
this.saveToPath = saveToPath + File.separator;
else
this.saveToPath = saveToPath;
readLoop();
}
private void readLoop(){
logPrinter.print("Awaiting for handshake", EMsgType.INFO);
try {
byte[] directive;
int command;
while (true){
directive = readUsbDirective();
if (isInvalidDirective(directive))
continue;
command = getLEint(directive, 4);
switch (command){
case CMD_HANDSHAKE:
performHandshake(directive);
break;
case CMD_SEND_FILE_PROPERTIES:
handleSendFileProperties(directive);
break;
case CMD_ENDSESSION:
logPrinter.print("Session successfully ended.", EMsgType.PASS);
return;
default:
writeUsb(USBSTATUS_UNSUPPORTED_CMD);
logPrinter.print(String.format("Unsupported command 0x%08x", command), EMsgType.FAIL);
}
}
}
catch (InterruptedException ie){
logPrinter.print("Execution interrupted", EMsgType.INFO);
}
catch (Exception e){
e.printStackTrace();
logPrinter.print(e.getMessage(), EMsgType.INFO);
logPrinter.print("Terminating now", EMsgType.FAIL);
}
};
private boolean isInvalidDirective(byte[] message) throws Exception{
if (message.length < 0x10){
writeUsb(USBSTATUS_MALFORMED_REQUEST);
logPrinter.print("Directive is too small. Only "+message.length+" bytes received.", EMsgType.FAIL);
return true;
}
if (! Arrays.equals(Arrays.copyOfRange(message, 0,4), MAGIC_NXDT)){
writeUsb(USBSTATUS_INVALID_MAGIC);
logPrinter.print("Invalid 'MAGIC'", EMsgType.FAIL);
return true;
}
int payloadSize = getLEint(message, 0x8);
if (payloadSize + 0x10 != message.length){
writeUsb(USBSTATUS_MALFORMED_REQUEST);
logPrinter.print("Invalid directive info block size. "+message.length+" bytes received while "+payloadSize+" expected.", EMsgType.FAIL);
return true;
}
return false;
}
private void performHandshake(byte[] message) throws Exception{
final byte versionMajor = message[0x10];
final byte versionMinor = message[0x11];
final byte versionMicro = message[0x12];
final byte versionABI = message[0x13];
logPrinter.print("nxdumptool v"+versionMajor+"."+versionMinor+"."+versionMicro+" ABI v"+versionABI, EMsgType.INFO);
if (ABI_VERSION != versionABI){
writeUsb(USBSTATUS_UNSUPPORTED_ABI);
throw new Exception("ABI v"+versionABI+" is not supported in current version.");
}
writeUsb(USBSTATUS_SUCCESS);
}
private void handleSendFileProperties(byte[] message) throws Exception{
final long fileSize = getLElong(message, 0x10);
final int fileNameLen = getLEint(message, 0x18);
String filename = new String(message, 0x20, fileNameLen, StandardCharsets.UTF_8);
if (fileNameLen <= 0 || fileNameLen > NXDT_FILE_PROPERTIES_MAX_NAME_LENGTH){
writeUsb(USBSTATUS_MALFORMED_REQUEST);
logPrinter.print("Invalid filename length!", EMsgType.FAIL);
return;
}
// If RomFs related
if (isRomFs(filename)) {
if (isWindows)
filename = saveToPath + filename.replaceAll("/", "\\\\");
else
filename = saveToPath + filename;
createPath(filename);
}
else {
logPrinter.print("Receiving: '"+filename+"' ("+fileSize+" b)", EMsgType.INFO);
filename = saveToPath + filename;
}
File fileToDump = new File(filename);
// Check if enough space
if (fileToDump.getParentFile().getFreeSpace() <= fileSize){
writeUsb(USBSTATUS_HOSTIOERROR);
logPrinter.print("Not enough space on selected volume. Need: "+fileSize+
" while available: "+fileToDump.getParentFile().getFreeSpace(), EMsgType.FAIL);
return;
}
// Check if FS is NOT read-only
if (! (fileToDump.canWrite() || fileToDump.createNewFile()) ){
writeUsb(USBSTATUS_HOSTIOERROR);
logPrinter.print("Unable to write into selected volume: "+fileToDump.getAbsolutePath(), EMsgType.FAIL);
return;
}
writeUsb(USBSTATUS_SUCCESS);
if (fileSize == 0)
return;
if (isWindows10)
dumpFileOnWindowsTen(fileToDump, fileSize);
else
dumpFile(fileToDump, fileSize);
writeUsb(USBSTATUS_SUCCESS);
}
private int getLEint(byte[] bytes, int fromOffset){
return ByteBuffer.wrap(bytes, fromOffset, 0x4).order(ByteOrder.LITTLE_ENDIAN).getInt();
}
private long getLElong(byte[] bytes, int fromOffset){
return ByteBuffer.wrap(bytes, fromOffset, 0x8).order(ByteOrder.LITTLE_ENDIAN).getLong();
}
private boolean isRomFs(String filename){
return filename.startsWith("/");
}
private void createPath(String path) throws Exception{
File resultingFile = new File(path);
File folderForTheFile = resultingFile.getParentFile();
if (folderForTheFile.exists())
return;
if (folderForTheFile.mkdirs())
return;
writeUsb(USBSTATUS_HOSTIOERROR);
throw new Exception("Unable to create dir(s) for file in "+folderForTheFile);
}
private void dumpFile(File file, long size) throws Exception{
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file, false));
byte[] readBuffer;
long received = 0;
int bufferSize;
while (received < size){
readBuffer = readUsbFile();
bos.write(readBuffer);
bufferSize = readBuffer.length;
received += bufferSize;
logPrinter.updateProgress((received + bufferSize) / (size / 100.0) / 100.0);
}
logPrinter.updateProgress(1.0);
bos.close();
}
// @see https://bugs.openjdk.java.net/browse/JDK-8146538
private void dumpFileOnWindowsTen(File file, long size) throws Exception{
FileOutputStream fos = new FileOutputStream(file, true);
BufferedOutputStream bos = new BufferedOutputStream(fos);
FileDescriptor fd = fos.getFD();
byte[] readBuffer;
long received = 0;
int bufferSize;
while (received < size){
readBuffer = readUsbFile();
bos.write(readBuffer);
fd.sync(); // Fixes flushing under Windows (unharmful for other OS)
bufferSize = readBuffer.length;
received += bufferSize;
logPrinter.updateProgress((received + bufferSize) / (size / 100.0) / 100.0);
}
logPrinter.updateProgress(1.0);
bos.close();
}
/**
* Sending any byte array to USB device
* @return 'false' if no issues
* 'true' if errors happened
* */
private void writeUsb(byte[] message) throws Exception{
ByteBuffer writeBuffer = ByteBuffer.allocateDirect(message.length);
writeBuffer.put(message);
IntBuffer writeBufTransferred = IntBuffer.allocate(1);
if ( task.isCancelled())
throw new InterruptedException("Execution interrupted");
int result = LibUsb.bulkTransfer(handlerNS, (byte) 0x01, writeBuffer, writeBufTransferred, 5050);
switch (result){
case LibUsb.SUCCESS:
if (writeBufTransferred.get() == message.length)
return;
throw new Exception("Data transfer issue [write]" +
"\n Requested: "+message.length+
"\n Transferred: "+writeBufTransferred.get());
default:
throw new Exception("Data transfer issue [write]" +
"\n Returned: "+ UsbErrorCodes.getErrCode(result) +
"\n (execution stopped)");
}
}
/**
* Reading what USB device responded (command).
* @return byte array if data read successful
* 'null' if read failed
* */
private byte[] readUsbDirective() throws Exception{
ByteBuffer readBuffer = ByteBuffer.allocateDirect(NXDT_MAX_DIRECTIVE_SIZE);
// We can limit it to 32 bytes, but there is a non-zero chance to got OVERFLOW from libusb.
IntBuffer readBufTransferred = IntBuffer.allocate(1);
int result;
while (! task.isCancelled()) {
result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000); // last one is TIMEOUT. 0 stands for unlimited. Endpoint IN = 0x81
switch (result) {
case LibUsb.SUCCESS:
int trans = readBufTransferred.get();
byte[] receivedBytes = new byte[trans];
readBuffer.get(receivedBytes);
return receivedBytes;
case LibUsb.ERROR_TIMEOUT:
break;
default:
throw new Exception("Data transfer issue [read command]" +
"\n Returned: " + UsbErrorCodes.getErrCode(result)+
"\n (execution stopped)");
}
}
throw new InterruptedException();
}
/**
* Reading what USB device responded (file).
* @return byte array if data read successful
* 'null' if read failed
* */
private byte[] readUsbFile() throws Exception{
ByteBuffer readBuffer = ByteBuffer.allocateDirect(NXDT_FILE_CHUNK_SIZE);
IntBuffer readBufTransferred = IntBuffer.allocate(1);
int result;
int countDown = 0;
while (! task.isCancelled() && countDown < 5) {
result = LibUsb.bulkTransfer(handlerNS, (byte) 0x81, readBuffer, readBufTransferred, 1000);
switch (result) {
case LibUsb.SUCCESS:
int trans = readBufTransferred.get();
byte[] receivedBytes = new byte[trans];
readBuffer.get(receivedBytes);
return receivedBytes;
case LibUsb.ERROR_TIMEOUT:
countDown++;
break;
default:
throw new Exception("Data transfer issue [read file]" +
"\n Returned: " + UsbErrorCodes.getErrCode(result)+
"\n (execution stopped)");
}
}
throw new InterruptedException();
}
}

View file

@ -31,6 +31,14 @@
<SVGPath content="M 5.2753906 0.9453125 C 3.4702091 0.94491305 2.0128532 1.7453477 1.0566406 2.9082031 C 0.10042811 4.0710585 -0.40065633 5.5585011 -0.55664062 7.0488281 C -0.71262492 8.5391552 -0.52822452 10.042928 0.0078125 11.292969 C 0.54008474 12.534229 1.4899019 13.5834 2.8300781 13.826172 L 2.828125 13.837891 L 4.2050781 13.837891 L 4.6484375 11.080078 L 5.3496094 11.080078 L 5.9257812 13.837891 L 7.4042969 13.837891 L 7.4042969 13.753906 L 6.703125 10.685547 C 7.49408 10.281262 7.9297095 9.5624699 8.0097656 8.5292969 C 8.0610016 7.8485775 7.9209243 7.3118876 7.5878906 6.9179688 C 7.254857 6.5240499 6.7748288 6.3176076 6.1503906 6.296875 L 4.0371094 6.2910156 L 3.0976562 12.150391 C 2.4734416 12.023142 1.945837 11.518943 1.5625 10.625 C 1.1696133 9.7087867 0.99863233 8.4506302 1.1269531 7.2246094 C 1.2552739 5.9985885 1.6798073 4.8135983 2.3632812 3.9824219 C 3.0467553 3.1512454 3.9413986 2.6383771 5.2734375 2.6386719 L 20.007812 2.640625 C 20.496454 2.6407331 20.818797 2.788345 21.136719 3.0976562 C 21.454641 3.4069676 21.743658 3.910529 21.949219 4.5761719 C 22.36034 5.9074576 22.421621 7.8407685 22.128906 9.7714844 C 21.836191 11.7022 21.195943 13.639966 20.339844 15.023438 C 19.483744 16.406908 18.498727 17.154297 17.46875 17.154297 L -0.59375 17.154297 L -0.59375 18.845703 L 17.46875 18.845703 C 19.298148 18.845703 20.755291 17.568872 21.779297 15.914062 C 22.803302 14.259253 23.481257 12.145818 23.802734 10.025391 C 24.124212 7.904966 24.093647 5.7854271 23.566406 4.078125 C 23.302786 3.2244739 22.911503 2.4618437 22.318359 1.8847656 C 21.725216 1.3076876 20.907952 0.94941793 20.007812 0.94921875 L 5.2753906 0.9453125 z M 11.574219 6.1875 C 10.831297 6.1702229 10.207831 6.4450285 9.7050781 7.0117188 C 9.2055276 7.578409 8.8809744 8.3951633 8.7304688 9.4628906 L 8.5527344 10.712891 C 8.5207119 10.975503 8.5072674 11.234984 8.5136719 11.494141 C 8.5328854 12.254335 8.7132962 12.848871 9.0527344 13.277344 C 9.3921725 13.705817 9.8729047 13.927585 10.494141 13.941406 C 11.217848 13.962139 11.814426 13.735112 12.285156 13.261719 C 12.759089 12.78487 13.038539 12.137296 13.125 11.318359 L 11.775391 11.328125 C 11.698537 11.846439 11.565182 12.208239 11.373047 12.412109 C 11.180912 12.612524 10.923036 12.704777 10.599609 12.6875 C 10.080845 12.663312 9.8371182 12.277623 9.8691406 11.53125 C 9.8723429 11.403399 9.8965748 11.131448 9.9414062 10.716797 L 10.113281 9.4160156 C 10.190135 8.7145637 10.339592 8.209426 10.560547 7.8984375 C 10.781502 7.5839935 11.081823 7.4334439 11.462891 7.4472656 C 11.956037 7.4645428 12.209143 7.763238 12.21875 8.34375 L 12.208984 8.8574219 L 13.595703 8.8613281 C 13.595703 7.9974711 13.421311 7.3393799 13.072266 6.8867188 C 12.723221 6.4306022 12.224275 6.1978663 11.574219 6.1875 z M 14.869141 6.2910156 L 13.658203 13.837891 L 15.037109 13.837891 L 15.353516 11.847656 L 15.753906 8.5976562 L 16.28125 13.837891 L 17.21875 13.837891 L 19.361328 8.7675781 L 18.755859 11.748047 L 18.419922 13.837891 L 19.802734 13.837891 L 21.017578 6.2910156 L 19.201172 6.2910156 L 17.054688 11.716797 L 16.646484 6.2910156 L 14.869141 6.2910156 z M 5.2148438 7.5605469 L 6.09375 7.5664062 C 6.4491994 7.5940497 6.6336754 7.8344483 6.6464844 8.2871094 C 6.6496866 8.7466813 6.5554161 9.1146416 6.3632812 9.3945312 C 6.1711464 9.6709655 5.9072524 9.8134016 5.5742188 9.8203125 L 4.8496094 9.8105469 L 5.2148438 7.5605469 z" />
</graphic>
</Tab>
<Tab closable="false">
<content>
<fx:include fx:id="NXDTab" source="NXDTab.fxml" VBox.vgrow="ALWAYS" />
</content>
<graphic>
<SVGPath content="M 7 0 L 0 4 C -0.02484618 7.6613523 4.6259293e-18 7.3229335 0 10.984375 C 0 10.993031 0.015625 7 0.015625 8 L 13 0 L 7 0 z M 17.966797 6.46875 L 17.966797 10.673828 C 17.715715 10.211268 17.396999 9.8685131 17.011719 9.6464844 C 16.630766 9.4198301 16.171566 9.3066406 15.634766 9.3066406 C 14.755976 9.3066406 14.040441 9.682293 13.486328 10.431641 C 12.936542 11.180987 12.660156 12.165561 12.660156 13.386719 C 12.660156 14.607877 12.936542 15.59245 13.486328 16.341797 C 14.040441 17.091144 14.755976 17.466797 15.634766 17.466797 C 16.171566 17.466797 16.630766 17.354841 17.011719 17.132812 C 17.396999 16.90616 17.715715 16.562169 17.966797 16.099609 L 17.966797 17.265625 L 19.160156 17.265625 L 19.160156 6.46875 L 17.966797 6.46875 z M 20.572266 7.3652344 L 20.572266 9.5546875 L 19.800781 9.5546875 L 19.800781 10.539062 L 20.572266 10.539062 L 20.572266 14.724609 C 20.572266 15.688531 20.728201 16.353495 21.037109 16.720703 C 21.346016 17.083321 21.906432 17.265625 22.71875 17.265625 L 23.800781 17.265625 L 23.800781 16.205078 L 22.71875 16.205078 C 22.280176 16.205078 21.98867 16.114559 21.84375 15.935547 C 21.702645 15.756534 21.630859 15.353453 21.630859 14.724609 L 21.630859 10.539062 L 23.800781 10.539062 L 23.800781 9.5546875 L 21.630859 9.5546875 L 21.630859 7.3652344 L 20.572266 7.3652344 z M 3.6386719 9.3066406 C 3.1397071 9.3066406 2.6982722 9.4230165 2.3144531 9.6542969 C 1.9348986 9.8855772 1.6037331 10.233986 1.3222656 10.701172 L 1.3222656 9.4941406 L 0.13867188 9.4941406 L 0.13867188 17.265625 L 1.3222656 17.265625 L 1.3222656 12.873047 C 1.3222656 12.114448 1.5062865 11.515605 1.8730469 11.076172 C 2.2398077 10.636739 2.7395664 10.417969 3.375 10.417969 C 3.9038175 10.417969 4.3000442 10.599421 4.5644531 10.964844 C 4.8288618 11.330266 4.9609375 11.881715 4.9609375 12.617188 L 4.9609375 17.265625 L 6.1386719 17.265625 L 6.1386719 12.576172 C 6.1386719 11.503031 5.9280604 10.691072 5.5058594 10.140625 C 5.0836585 9.5855522 4.4617505 9.3066406 3.6386719 9.3066406 z M 6.984375 9.4941406 L 9.2207031 13.199219 L 6.7773438 17.265625 L 7.9960938 17.265625 L 9.828125 14.212891 L 11.658203 17.265625 L 12.878906 17.265625 L 10.484375 13.275391 L 12.759766 9.4941406 L 11.541016 9.4941406 L 9.8730469 12.263672 L 8.2050781 9.4941406 L 6.984375 9.4941406 z M 15.927734 10.375 C 16.559769 10.375 17.056283 10.643118 17.419922 11.179688 C 17.783557 11.711631 17.966797 12.447722 17.966797 13.386719 C 17.966797 14.325715 17.783557 15.06304 17.419922 15.599609 C 17.056283 16.131553 16.559769 16.398437 15.927734 16.398438 C 15.295699 16.398438 14.797233 16.131553 14.433594 15.599609 C 14.074286 15.06304 13.894531 14.325715 13.894531 13.386719 C 13.894531 12.447722 14.074286 11.711631 14.433594 11.179688 C 14.797233 10.643118 15.295699 10.375 15.927734 10.375 z M 24 18.400391 C 24.0056 21.386719 23.984375 22 23.984375 19 L 15 23.982422 L 23.984375 23.996094 C 23.993075 23.996094 24 23.990492 24 23.982422 L 24 18.400391 z" />
</graphic>
</Tab>
<Tab closable="false">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">

View file

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.SVGPath?>
<?import javafx.scene.text.Font?>
<VBox spacing="15.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NxdtController">
<HBox alignment="CENTER">
<children>
<Label styleClass="nxdt" text="nx">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Label>
<Label text="dumptool">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Label>
</children>
</HBox>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" />
<ColumnConstraints hgrow="SOMETIMES" percentWidth="90.0" />
<ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Separator prefWidth="200.0" styleClass="strangeSeparator" GridPane.columnIndex="1" />
</children>
</GridPane>
<BorderPane>
<left>
<Label text="%tabSplMrg_Lbl_SaveToLocation" BorderPane.alignment="CENTER" />
</left>
<center>
<Label fx:id="saveToLocationLbl" BorderPane.alignment="CENTER_LEFT" />
</center>
<right>
<Button mnemonicParsing="false" onAction="#bntSelectSaveTo" styleClass="buttonSelect" BorderPane.alignment="CENTER">
<graphic>
<SVGPath content="M3,4C1.89,4 1,4.89 1,6V18A2,2 0 0,0 3,20H11V18.11L21,8.11V8C21,6.89 20.1,6 19,6H11L9,4H3M21.04,11.13C20.9,11.13 20.76,11.19 20.65,11.3L19.65,12.3L21.7,14.35L22.7,13.35C22.92,13.14 22.92,12.79 22.7,12.58L21.42,11.3C21.31,11.19 21.18,11.13 21.04,11.13M19.07,12.88L13,18.94V21H15.06L21.12,14.93L19.07,12.88Z" fill="#289de8" />
</graphic>
</Button>
</right>
<VBox.margin>
<Insets left="15.0" right="15.0" />
</VBox.margin>
</BorderPane>
<Pane VBox.vgrow="ALWAYS" />
<HBox alignment="CENTER">
<children>
<Label fx:id="statusLbl" alignment="CENTER" />
</children>
</HBox>
<Pane />
<HBox alignment="CENTER">
<children>
<Button fx:id="injectPldBtn" contentDisplay="TOP" minWidth="100.0" mnemonicParsing="false" styleClass="buttonUp" text="%tabNXDT_Btn_Start" />
</children>
</HBox>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>

View file

@ -62,3 +62,4 @@ done_txt=Done!
failure_txt=Failed
btn_Select=Select
btn_InjectPayloader=Inject payload
tabNXDT_Btn_Start=Start!

View file

@ -62,4 +62,5 @@ done_txt=\u0413\u043E\u0442\u043E\u0432\u043E!
failure_txt=\u041D\u0435\u0443\u0434\u0430\u0447\u0430
btn_Select=\u0412\u044B\u0431\u0440\u0430\u0442\u044C
btn_InjectPayloader=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C payload
tabNXDT_Btn_Start=\u0421\u0442\u0430\u0440\u0442!

View file

@ -62,3 +62,4 @@ done_txt=\u0413\u043E\u0442\u043E\u0432\u043E!
failure_txt=\u041D\u0435\u0432\u0434\u0430\u0447\u0430
btn_Select=\u0412\u0438\u0431\u0440\u0430\u0442\u0438
btn_InjectPayloader=\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 payload
tabNXDT_Btn_Start=\u0421\u0442\u0430\u0440\u0442!

View file

@ -373,6 +373,12 @@
-fx-min-height: 24;
-fx-min-width: 36;
}
.regionDump{
-fx-shape: "M 4.0078125 0 C 1.5078125 0 0 1.4882812 0 3.984375 L 0 15.988281 C 0 18.417969 1.4927148 20 4.0078125 20 L 6.5 20 L 6.5 0 L 4.0078125 0 z M 23.5 0 L 23.5 20 C 24.504057 19.999294 25.159942 20 25.992188 20 C 28.414062 20 30 18.496094 30 15.996094 L 30 3.9765625 C 30 1.5195311 28.508726 0 26.003906 0 L 23.5 0 z M 11.990234 2.8886719 L 11.990234 9.9003906 L 6.9902344 9.9003906 L 14.990234 20 L 22.990234 9.9003906 L 17.990234 9.9003906 C 17.990234 8.2387016 17.9999 3.6538029 18 2.8886719 L 11.990234 2.8886719 z M 3.1015625 2.9570312 C 4.1485235 2.9562481 4.9977514 3.8046013 4.9980469 4.8515625 C 4.998831 5.8992865 4.1492865 6.7488309 3.1015625 6.7480469 C 2.0546013 6.7477509 1.2062483 5.8985235 1.2070312 4.8515625 C 1.2073268 3.8053642 2.0553642 2.9573267 3.1015625 2.9570312 z M 26.865234 11.148438 C 27.912958 11.147652 28.762503 11.997198 28.761719 13.044922 C 28.761423 14.091883 27.912195 14.940236 26.865234 14.939453 C 25.819036 14.939158 24.970999 14.09112 24.970703 13.044922 C 24.96992 11.997961 25.818273 11.148733 26.865234 11.148438 z ";
-fx-background-color: #71e016;
-fx-min-height: 24;
-fx-min-width: 36;
}
.regionStop{
-fx-shape: "M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z";
-fx-background-color: #fb582c;
@ -394,6 +400,9 @@
-size: 17.5;
-fx-min-width: 20;
}
.nxdt.label .text {
-fx-fill: #cb0010;
}
//
//.lineGradient {
// -fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #00c8fc 30%, transparent 45%);

View file

@ -291,7 +291,12 @@
-fx-min-height: 24;
-fx-min-width: 36;
}
.regionDump{
-fx-shape: "M 4.0078125 0 C 1.5078125 0 0 1.4882812 0 3.984375 L 0 15.988281 C 0 18.417969 1.4927148 20 4.0078125 20 L 6.5 20 L 6.5 0 L 4.0078125 0 z M 23.5 0 L 23.5 20 C 24.504057 19.999294 25.159942 20 25.992188 20 C 28.414062 20 30 18.496094 30 15.996094 L 30 3.9765625 C 30 1.5195311 28.508726 0 26.003906 0 L 23.5 0 z M 11.990234 2.8886719 L 11.990234 9.9003906 L 6.9902344 9.9003906 L 14.990234 20 L 22.990234 9.9003906 L 17.990234 9.9003906 C 17.990234 8.2387016 17.9999 3.6538029 18 2.8886719 L 11.990234 2.8886719 z M 3.1015625 2.9570312 C 4.1485235 2.9562481 4.9977514 3.8046013 4.9980469 4.8515625 C 4.998831 5.8992865 4.1492865 6.7488309 3.1015625 6.7480469 C 2.0546013 6.7477509 1.2062483 5.8985235 1.2070312 4.8515625 C 1.2073268 3.8053642 2.0553642 2.9573267 3.1015625 2.9570312 z M 26.865234 11.148438 C 27.912958 11.147652 28.762503 11.997198 28.761719 13.044922 C 28.761423 14.091883 27.912195 14.940236 26.865234 14.939453 C 25.819036 14.939158 24.970999 14.09112 24.970703 13.044922 C 24.96992 11.997961 25.818273 11.148733 26.865234 11.148438 z ";
-fx-background-color: #71e016;
-fx-min-height: 24;
-fx-min-width: 36;
}
.regionStop{
-fx-shape: "M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z";
-fx-background-color: #fb582c;
@ -313,3 +318,6 @@
-size: 17.5;
-fx-min-width: 20;
}
.nxdt.label .text {
-fx-fill: #9d010e;
}