Compare commits

..

13 commits

Author SHA1 Message Date
Dmitry Isaenko
2e0d583963 Add drag-n-drop for Split'n'merge tab. Fix minor issues. 2020-02-11 00:42:43 +03:00
Dmitry Isaenko
8eb05bb1b5 Fix drag-n-drop for app. Add drag-n-drop for RCM tab 2020-02-11 00:15:19 +03:00
Dmitry Isaenko
6b6bf8320f Fix RCM for MacOS 2020-02-10 14:34:07 +03:00
Dmitry Isaenko
aff6044cdb Cosmetic updates 2020-02-10 04:16:29 +03:00
Dmitry Isaenko
bbb71e2a53 Update README.md #2 2020-02-10 04:14:02 +03:00
Dmitry Isaenko
fe673c0ace Update README.md 2020-02-10 04:12:21 +03:00
Dmitry Isaenko
ec4362ebc7 RCM bugfix 2020-02-10 02:52:59 +03:00
Dmitry Isaenko
010c33c593 RCM (Fusée Gelée) support, numerous UI updates and a lot of things for version 2. 2020-02-10 02:19:39 +03:00
Dmitry Isaenko
3d3fb56f9e A lot of small updates. Finishing split-merge functions. 2020-01-24 23:44:21 +03:00
Dmitry Isaenko
ca061cd1f2 UI refactoring 2020-01-24 01:08:16 +03:00
Dmitry Isaenko
98155bc1f8 Finish split-merge files backend functionality 2020-01-24 00:02:47 +03:00
Dmitry Isaenko
d00b914214 A bit more for split-merge files functionality 2020-01-21 03:22:22 +03:00
Dmitry Isaenko
4dc6d0ae0c Add Split/Merge functions 2020-01-19 21:35:44 +03:00
43 changed files with 2633 additions and 358 deletions

45
BUILD.md Normal file
View file

@ -0,0 +1,45 @@
### How to build this app
Java application:
* Install Maven
* Execute
`# mvn -B -DskipTests clean package`
**Building JNI libraries section**
First of all install JDK, GCC, make, kernel headers and whatever else (or use Gentoo <3 ).
Generate header (Optional! Already generated.):
```
$ cp NS-USBloader/src/main/java/nsusbloader/Utilities/RcmSmash.java .
$ javac -h . RcmSmash.java
```
**Build for Linux (amd64 Linux host):**
```
$ cd 'NS-USBloader/JNI sources/linux'
$ make install clean
```
**Build for Windows (on x86_64 host):**
[ This part should be updated ]
Install MinGW, msys (?) MinGW-w64 and JDK. Set JAVA_HOME, set PATH to match MinGW, MSYS, JDK/bin (and other?) environment variables.
x86: Install MinGw to C:\MinGW\
Update sources: set (uncomment) line 'BUILD_FOR_X86'
Set environment variables for MinGw:
* C:\MinGW\bin
* C:\MinGW\msys\1.0\bin
```
$ cd 'NS-USBloader/JNI sources/windows'
$ make x86
```
amd64: Install MinGw-w64
Update sources: remove line 'BUILD_FOR_X86'
```
$ make amd64
```

View file

@ -0,0 +1,33 @@
# Compiler
CC=gcc
# Flags
CFLAGS=-O2
MKDIR_P = mkdir -p
APP_NAME = smashlib.so
all: x86 amd64
x86:
$(MKDIR_P) ./x86
$(CC) ${CFLAGS} -m32 -c -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" smashlib.c -o smashlib_x86.o
$(CC) ${CFLAGS} -m32 -shared -fPIC -o ./x86/${APP_NAME} smashlib_x86.o -lc
amd64:
$(MKDIR_P) ./amd64
$(CC) ${CFLAGS} -m64 -c -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" smashlib.c -o smashlib_amd64.o
$(CC) ${CFLAGS} -m64 -shared -fPIC -o ./amd64/${APP_NAME} smashlib_amd64.o -lc
clean:
rm -rf \
smashlib_amd64.o \
smashlib_x86.o \
./x86 \
./amd64
install: x86 amd64
install ./x86/${APP_NAME} ../../src/main/resources/native/linux/x86/
install ./amd64/${APP_NAME} ../../src/main/resources/native/linux/amd64/
uninstall:
rm ../../src/main/resources/native/linux/x86/${APP_NAME}
rm ../../src/main/resources/native/linux/amd64/${APP_NAME}

View file

@ -0,0 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class nsusbloader_Utilities_RcmSmash */
#ifndef _Included_nsusbloader_Utilities_RcmSmash
#define _Included_nsusbloader_Utilities_RcmSmash
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nsusbloader_Utilities_RcmSmash
* Method: smashLinux
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashLinux
(JNIEnv *, jclass, jint, jint);
/*
* Class: nsusbloader_Utilities_RcmSmash
* Method: smashWindows
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashWindows
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif

88
JNI sources/linux/smashlib.c Executable file
View file

@ -0,0 +1,88 @@
/* NS-USBloader - native libraries for 'special purposes'
* Copyright (C) 2020 Dmitry Isaenko
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/ch9.h>
#include <errno.h>
#include "nsusbloader_Utilities_RcmSmash.h"
struct usbdevfs_urb urb;
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashLinux
(JNIEnv * jni_env, jclass this_class, jint bus_id, jint device_addr){
int ret_value;
char *usb_path = (char*)malloc(24 * sizeof(char));
sprintf(usb_path, "/dev/bus/usb/%03d/%03d", bus_id, device_addr);
int fd = open(usb_path, O_RDWR);
if (fd == -1)
return -1;
struct usb_ctrlrequest* ctrl_req;
__u8* buf[0x7000+sizeof(ctrl_req)];
ctrl_req = (struct usb_ctrlrequest *) buf;
ctrl_req->bRequestType = 0x82;
ctrl_req->bRequest = USB_REQ_GET_STATUS;
ctrl_req->wValue = 0;
ctrl_req->wIndex = 0;
ctrl_req->wLength = 0x7000;
memset(&urb, 0, sizeof(urb));
urb.type = USBDEVFS_URB_TYPE_CONTROL;
urb.endpoint = USB_DIR_IN | 0;
urb.buffer = buf;
urb.buffer_length = sizeof(buf);
//Submit request
ret_value = ioctl(fd, USBDEVFS_SUBMITURB, &urb);
// If we failed on this step, it's a VERY bad sign. Nothing to do, let's report failure.
if (ret_value != 0)
return ret_value;
// Wait 1/4 sec
usleep(250000);
struct usbdevfs_urb urb1;
// Let's pick reply (everybody does it, right? In non-blocking manner.)
ret_value = ioctl(fd, USBDEVFS_REAPURBNDELAY, &urb1);
if (ret_value < 0){
if (errno == EAGAIN){ // In case of resource temporarily unavailable
// Wired.. so much time left. Let's cancel it!
ret_value = ioctl(fd, USBDEVFS_DISCARDURB, &urb);
// And wait a bit more..
usleep(40000);
// And try to pick reply. Yes, it's still possible. See /usr/src/linux/drivers/usb/core/devio.c
ret_value = ioctl(fd, USBDEVFS_REAPURBNDELAY, &urb1);
}
}
// Leftovers.
free(usb_path);
// Let's try to close device, but even if we fail with this, nvm.
close(fd); // So we won't even write returned value somewhere.
return 0;
}
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashWindows
(JNIEnv * jni_env, jclass this_class){
return -1;
}

View file

@ -0,0 +1,34 @@
# Compiler
CC32='C:/MinGW/bin/gcc'
CC64='C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/bin/gcc'
# Flags
CFLAGS=-O2
MKDIR_P=mkdir
APP_NAME=smashlib.dll
all: x86 amd64
#$(CC) ${CFLAGS} -m32 -c -fPIC -I "C:/MinGW/include/ddk" -I "${JAVA_HOME}/include" -I "${JAVA_HOME}/include/win32" smashlib.c -o ./x86/smashlib.o # MinGw-32 version
x86:
$(MKDIR_P) ./x86
export PATH="C/MinGW/bin/:${PATH}"
$(CC32) ${CFLAGS} -m32 -c -fPIC -I "C:/MinGW/include/ddk" -I "${JAVA_HOME}/include" -I "${JAVA_HOME}/include/win32" smashlib.c -o ./smashlib_x86.o
$(CC32) ${CFLAGS} -shared -o ./x86/${APP_NAME} ./smashlib_x86.o -lsetupapi -lhid -Wl,--add-stdcall-alias
#$(CC) ${CFLAGS} -m64 -c -fPIC -I "C:/MinGW/include/ddk" -I "${JAVA_HOME}/include" -I "${JAVA_HOME}/include/win32" smashlib.c -o ./amd64/smashlib.o # MinGw-32 version
amd64:
$(MKDIR_P) ./amd64
export PATH="C/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/bin/:${PATH}"
$(CC64) ${CFLAGS} -m64 -c -fPIC -I "${JAVA_HOME}/include" -I "${JAVA_HOME}/include/win32" smashlib.c -o ./smashlib_amd64.o
$(CC64) ${CFLAGS} -shared -o ./amd64/${APP_NAME} ./smashlib_amd64.o -lsetupapi -lhid -Wl,--add-stdcall-alias
clean:
rm -rf ./smashlib_x86.o ./smashlib_amd64.o ./x86 ./amd64
install: x86 amd64
install ./x86/${APP_NAME} ../../src/main/resources/native/windows/x86/
install ./amd64/${APP_NAME} ../../src/main/resources/native/windows/amd64/
uninstall:
rm ../../src/main/resources/native/windows/x86/${APP_NAME}
rm ../../src/main/resources/native/windows/amd64/${APP_NAME}

View file

@ -0,0 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class nsusbloader_Utilities_RcmSmash */
#ifndef _Included_nsusbloader_Utilities_RcmSmash
#define _Included_nsusbloader_Utilities_RcmSmash
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nsusbloader_Utilities_RcmSmash
* Method: smashLinux
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashLinux
(JNIEnv *, jclass, jint, jint);
/*
* Class: nsusbloader_Utilities_RcmSmash
* Method: smashWindows
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashWindows
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,168 @@
/*
* Derivative & modified code based on awesome example from here: https://www.velleman.eu/images/tmp/usbfind.c
* And MSDN documentation :)
*
* return
* -2 device not connected
* -1 Unable to open handler
* 0 maybe we're all set
*/
#ifdef __cplusplus
extern "C" {
#endif
#define _DEBUG
#define _BUILD_FOR_X86
#include <windows.h>
#include <tchar.h>
#include <setupapi.h>
#ifdef DEBUG
#include <stdio.h>
#endif
#ifdef BUILD_FOR_X86
#include <ntddser.h>
#endif
#include "nsusbloader_Utilities_RcmSmash.h"
#define LIBUSB_IOCTL_GET_STATUS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS)
static GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10L, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
// NOTE: CHANGE TO NV DEVICE!
//static TCHAR VID_PID_PAIR[] = _T("vid_1a86&pid_7523"); // UNCOMMENT FOR TESTS
static TCHAR VID_PID_PAIR[] = _T("vid_0955&pid_7321"); // UNCOMMENT ON RELEASE
typedef struct
{
unsigned int timeout;
unsigned int recipient;
unsigned int index;
unsigned int status;
unsigned int ___zeroes_hold_0; // made it for better understanding. Literally useless.
unsigned int ___zeroes_hold_1; // Just consider each int as 4 bytes and calculate size =)
} simple_status_req;
int win32_magic(LPCSTR lpFileName){
unsigned char reqBuf[24] = {0};
simple_status_req* request;
request = (simple_status_req *) &reqBuf;
request->timeout = 1000;
request->recipient = 0x02;
request->index = 0;
request->status = 0;
#ifdef DEBUG
printf("Device path: %s\nStatus: %x\nIn buffer size: %d\nIn buffer content: ",
lpFileName,
LIBUSB_IOCTL_GET_STATUS,
sizeof(reqBuf) ); // Path and what is our IOCTL request looks like
for (int i = 0; i < sizeof(reqBuf); i++)
printf("%x ", reqBuf[i]);
printf("\n");
#endif
unsigned char outBuffer[28672];
OVERLAPPED ovrlpd;
memset(&ovrlpd, 0, sizeof(ovrlpd));
// Fucking finally let's open this
HANDLE handler = CreateFile(
lpFileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if ( handler == INVALID_HANDLE_VALUE )
return -1;
BOOL ret_val = DeviceIoControl(
handler,
LIBUSB_IOCTL_GET_STATUS,
(LPVOID) &reqBuf,
24,
(LPVOID) &outBuffer,
28672,
NULL,
&ovrlpd
);
#ifdef DEBUG
printf("\nDeviceIoControl reports: %d\nLast Error Code: %d\n", ret_val, GetLastError());
#endif
Sleep(250);
DWORD bReceived = 0;
ret_val = GetOverlappedResult(handler, &ovrlpd, &bReceived, FALSE);
#ifdef DEBUG
if (! ret_val) {
// we won't report any issues since there is no workaround.
printf("\nLast Error Code: %d\n\n", GetLastError());
}
#endif
CloseHandle(handler);
return 0;
}
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashWindows
(JNIEnv * jnie_enb, jclass this_class) {
int found = 0;
int ret_val = -2;
HDEVINFO hDevInfo;
SP_DEVICE_INTERFACE_DATA DevIntfData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DevIntfDetailData;
SP_DEVINFO_DATA DevData;
DWORD dwSize, dwType, dwMemberIdx;
HKEY hKey;
BYTE lpData[1024];
hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hDevInfo != INVALID_HANDLE_VALUE){
DevIntfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
dwMemberIdx = 0;
SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, dwMemberIdx, &DevIntfData);
while(GetLastError() != ERROR_NO_MORE_ITEMS) {
DevData.cbSize = sizeof(DevData);
SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, NULL, 0, &dwSize, NULL);
DevIntfDetailData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
DevIntfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, DevIntfDetailData, dwSize, &dwSize, &DevData)) {
if (NULL != _tcsstr((TCHAR*)DevIntfDetailData->DevicePath, VID_PID_PAIR)) {
found = 1;
ret_val = win32_magic(DevIntfDetailData->DevicePath);
}
}
HeapFree(GetProcessHeap(), 0, DevIntfDetailData);
if (found)
break;
// Continue looping
SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, ++dwMemberIdx, &DevIntfData);
}
SetupDiDestroyDeviceInfoList(hDevInfo);
}
#ifdef DEBUG
printf("Returning value: %d\n", ret_val);
#endif
return ret_val;
}
JNIEXPORT jint JNICALL Java_nsusbloader_Utilities_RcmSmash_smashLinux
(JNIEnv * jnie_env, jclass this_class, jint bus_id, jint device_addr){
return -1;
}

View file

@ -4,8 +4,12 @@
[Support author](#support-this-app)
NS-USBloader is a PC-side installer for **[Adubbz/TinFoil (v0.2.1)](https://github.com/Adubbz/Tinfoil/)**, **[Huntereb/Awoo-Installer](https://github.com/Huntereb/Awoo-Installer)** (USB and Network supported) and **[XorTroll/GoldLeaf](https://github.com/XorTroll/Goldleaf)** (USB) NSP installer.
NS-USBloader is:
* A PC-side installer for **[Adubbz/TinFoil (v0.2.1)](https://github.com/Adubbz/Tinfoil/)**, **[Huntereb/Awoo-Installer](https://github.com/Huntereb/Awoo-Installer)** (USB and Network supported) and **[XorTroll/GoldLeaf](https://github.com/XorTroll/Goldleaf)** (USB) NSP installer.
Replacement for default **usb_install_pc.py**, **remote_install_pc.py**, **GoldTree**/**Quark**.
* This application also could be used as RCM payload on Windows, MacOS and Linux (supported arch: x86, x86_64).
* And of course it's a tool for split files!
* And also for merging split-files into one :)
[Click here for Android version ;)](https://github.com/developersu/ns-usbloader-mobile)
@ -13,7 +17,9 @@ With GUI and cookies. Works on Windows, macOS and Linux.
Sometimes I add new posts about this project [on my home page](https://developersu.blogspot.com/search/label/NS-USBloader).
![Screenshot](https://live.staticflickr.com/65535/48962978677_4c3913e8a9_o.png)
![Application screenshot](https://live.staticflickr.com/65535/49513701961_2b41747a9f_o.png)
<img src="https://live.staticflickr.com/65535/49513701841_e09c86b944_o.png" alt="screenshot" width="250"/> <img src="https://live.staticflickr.com/65535/49513701896_c4d0a905c0_o.png" alt="screenshot" width="250"/>
<img src="https://live.staticflickr.com/65535/49513184138_688ee551f8_o.png" alt="screenshot" width="250"/> <img src="https://live.staticflickr.com/65535/49513924407_212988e0e9_o.png" alt="screenshot" width="250"/>
#### License
@ -23,6 +29,7 @@ Sometimes I add new posts about this project [on my home page](https://developer
* [OpenJFX](https://wiki.openjdk.java.net/display/OpenJFX/Main)
* [usb4java](https://mvnrepository.com/artifact/org.usb4java/usb4java)
* Few icons taken from: [materialdesignicons.com](http://materialdesignicons.com/)
* Information, ideas and data from ['fusee-launcher'](https://github.com/reswitched/fusee-launcher) application
#### List of awesome contributors!
@ -73,6 +80,12 @@ 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
```
4. For RCM part
```
root # vim /etc/udev/rules.d/99-NS-RCM.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="0955", ATTRS{idProduct}=="7321", GROUP="plugdev"
root # udevadm control --reload-rules && udevadm trigger
```
Please note: you may have to change 'plugdev' group from example above to the different one. It's depends on you linux distro.
@ -155,7 +168,6 @@ Upload somewhere (create PR, use pastebin/google drive/whatever else). [Create n
To convert files of any locale to readable format (and vise-versa) you can use this site [https://itpro.cz/juniconv/](https://itpro.cz/juniconv/)
#### TODO (maybe):
- [x] [Android support](https://github.com/developersu/ns-usbloader-mobile)
- [ ] File order sort (non-critical)

View file

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

View file

@ -123,6 +123,15 @@ public class AppPreferences {
public double getSceneWidth(){ return preferences.getDouble("WIND_WIDTH", 850.0); }
public void setSceneWidth(double value){ preferences.putDouble("WIND_WIDTH", value); }
public double getSceneHeight(){ return preferences.getDouble("WIND_HEIGHT", 475.0); }
public double getSceneHeight(){ return preferences.getDouble("WIND_HEIGHT", 525.0); }
public void setSceneHeight(double value){ preferences.putDouble("WIND_HEIGHT", value); }
// Split and Merge //
public int getSplitMergeType(){ return preferences.getInt("SM_TYPE", 0); }
public void setSplitMergeType(int value){ preferences.putInt("SM_TYPE", value); }
public String getSplitMergeRecent(){ return preferences.get("SM_RECENT", System.getProperty("user.home")); }
public void setSplitMergeRecent(String value){ preferences.put("SM_RECENT", value); }
// 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); }
}

View file

@ -3,6 +3,7 @@ package nsusbloader.COM.NET;
import javafx.concurrent.Task;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import nsusbloader.COM.Helpers.NSSplitReader;
@ -42,7 +43,7 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
else
this.extras = "";
this.switchIP = switchIP;
this.logPrinter = new LogPrinter();
this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
this.nspMap = new HashMap<>();
this.nspFileSizes = new HashMap<>();
// Filter and remove empty/incorrect split-files

View file

@ -3,6 +3,7 @@ package nsusbloader.COM.USB;
import javafx.concurrent.Task;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import org.usb4java.*;
@ -34,21 +35,21 @@ public class UsbCommunications extends Task<Void> {
this.nspMap = new LinkedHashMap<>();
for (File f: nspList)
nspMap.put(f.getName(), f);
this.logPrinter = new LogPrinter();
this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
}
@Override
protected Void call() {
logPrinter.print("\tStart chain", EMsgType.INFO);
UsbConnect usbConnect = new UsbConnect(logPrinter);
UsbConnect usbConnect = new UsbConnect(logPrinter, false);
if (! usbConnect.isConnected()){
close(EFileStatus.FAILED);
return null;
}
DeviceHandle handler = usbConnect.getHandlerNS();
DeviceHandle handler = usbConnect.getNsHandler();
TransferModule module;

View file

@ -4,20 +4,38 @@ import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EMsgType;
import org.usb4java.*;
class UsbConnect {
private final int DEFAULT_INTERFACE = 0;
public class UsbConnect {
private int DEFAULT_INTERFACE = 0;
private Context contextNS;
private DeviceHandle handlerNS;
private Device deviceNS;
private LogPrinter logPrinter;
private boolean connected;
private boolean connected; // TODO: replace to 'connectionFailure' and invert requests everywhere
UsbConnect(LogPrinter logPrinter){
public UsbConnect(LogPrinter logPrinter, boolean initForRCM){
this.logPrinter = logPrinter;
this.connected = false;
short VENDOR_ID;
short PRODUCT_ID;
if (initForRCM){
// CORRECT NV:
VENDOR_ID = 0x0955;
PRODUCT_ID = 0x7321;
/* // QA:
VENDOR_ID = 0x1a86;
PRODUCT_ID = 0x7523;
*/
}
else {
VENDOR_ID = 0x057E;
PRODUCT_ID = 0x3000;
}
int result;
// Creating Context required by libusb. Optional. TODO: Consider removing.
@ -28,8 +46,7 @@ class UsbConnect {
close();
return;
}
else
logPrinter.print("libusb initialization", EMsgType.PASS);
logPrinter.print("libusb initialization", EMsgType.PASS);
// Searching for NS in devices: obtain list of all devices
DeviceList deviceList = new DeviceList();
@ -39,11 +56,10 @@ class UsbConnect {
close();
return;
}
else
logPrinter.print("Get device list", EMsgType.PASS);
logPrinter.print("Get device list", EMsgType.PASS);
// Searching for NS in devices: looking for NS
DeviceDescriptor descriptor;
Device deviceNS = null;
deviceNS = null;
for (Device device: deviceList){
descriptor = new DeviceDescriptor(); // mmm.. leave it as is.
result = LibUsb.getDeviceDescriptor(device, descriptor);
@ -53,21 +69,20 @@ class UsbConnect {
close();
return;
}
if ((descriptor.idVendor() == 0x057E) && descriptor.idProduct() == 0x3000){
if ((descriptor.idVendor() == VENDOR_ID) && descriptor.idProduct() == PRODUCT_ID){
deviceNS = device;
logPrinter.print("Read file descriptors for USB devices", EMsgType.PASS);
break;
}
}
// Free device list.
if (deviceNS != null){
logPrinter.print("NS in connected USB devices found", EMsgType.PASS);
}
else {
if (deviceNS == null){
logPrinter.print("NS in connected USB devices not found", EMsgType.FAIL);
close();
return;
}
logPrinter.print("NS in connected USB devices found", EMsgType.PASS);
// Handle NS device
handlerNS = new DeviceHandle();
result = LibUsb.open(deviceNS, handlerNS);
@ -75,10 +90,11 @@ class UsbConnect {
logPrinter.print("Open NS USB device\n Returned: "+UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
if (result == LibUsb.ERROR_ACCESS)
logPrinter.print("Double check that you have administrator privileges (you're 'root') or check 'udev' rules set for this user (linux only)!\n\n" +
"Steps to set 'udev' rules:\n" +
"root # vim /etc/udev/rules.d/99-NS.rules\n" +
"SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"057e\", ATTRS{idProduct}==\"3000\", GROUP=\"plugdev\"\n" +
"root # udevadm control --reload-rules && udevadm trigger\n", EMsgType.INFO);
String.format("Steps to set 'udev' rules:\n" +
"root # vim /etc/udev/rules.d/99-NS"+(initForRCM?"RCM":"")+".rules\n" +
"SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", GROUP=\"plugdev\"\n" +
"root # udevadm control --reload-rules && udevadm trigger\n", VENDOR_ID, PRODUCT_ID)
, EMsgType.INFO);
// Let's make a bit dirty workaround since such shit happened
logPrinter.print("Requested context close", EMsgType.INFO);
LibUsb.exit(contextNS);
@ -107,25 +123,24 @@ class UsbConnect {
return;
}
*/
// Set configuration (soft reset if needed)
result = LibUsb.setConfiguration(handlerNS, 1); // 1 - configuration all we need
if (result != LibUsb.SUCCESS){
logPrinter.print("Set active configuration to device\n Returned: "+UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
close();
return;
}
else
if ( ! initForRCM){
// Set configuration (soft reset if needed)
result = LibUsb.setConfiguration(handlerNS, 1); // 1 - configuration all we need
if (result != LibUsb.SUCCESS){
logPrinter.print("Set active configuration to device\n Returned: "+UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
close();
return;
}
logPrinter.print("Set active configuration to device.", EMsgType.PASS);
}
// Claim interface
result = LibUsb.claimInterface(handlerNS, DEFAULT_INTERFACE);
if (result != LibUsb.SUCCESS) {
logPrinter.print("Claim interface\n Returned: "+UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
logPrinter.print("Claim interface\n Returned: "+UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
close();
return;
}
else
logPrinter.print("Claim interface", EMsgType.PASS);
logPrinter.print("Claim interface", EMsgType.PASS);
this.connected = true;
}
@ -134,23 +149,36 @@ class UsbConnect {
* Get USB status
* @return status of connection
*/
boolean isConnected() { return connected; }
public boolean isConnected() { return connected; }
/**
* Getter for handler
* @return DeviceHandle of NS
*/
DeviceHandle getHandlerNS(){ return handlerNS; }
public DeviceHandle getNsHandler(){ return handlerNS; }
/**
* Getter for 'Bus ID' where NS located found
*/
public int getNsBus(){
return LibUsb.getBusNumber(deviceNS);
}
/**
* Getter for 'Device address' where NS located at
*/
public int getNsAddress(){
return LibUsb.getDeviceAddress(deviceNS);
}
/**
* Correct exit
* */
void close(){
public void close(){
// Close handler in the end
if (handlerNS != null) {
// Try to release interface
int result = LibUsb.releaseInterface(handlerNS, DEFAULT_INTERFACE);
if (result != LibUsb.SUCCESS)
logPrinter.print("Release interface\n Returned: "+result+" (sometimes it's not an issue)", EMsgType.WARNING);
logPrinter.print("Release interface" +
"\n Returned: "+result+" (sometimes it's not an issue)", EMsgType.WARNING);
else
logPrinter.print("Release interface", EMsgType.PASS);

View file

@ -2,8 +2,8 @@ package nsusbloader.COM.USB;
import org.usb4java.LibUsb;
class UsbErrorCodes {
static String getErrCode(int value){
public class UsbErrorCodes {
public static String getErrCode(int value){
switch (value){
case LibUsb.ERROR_ACCESS:
return "ERROR_ACCESS";

View file

@ -2,20 +2,32 @@ package nsusbloader.Controllers;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.Pane;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Region;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import nsusbloader.AppPreferences;
import nsusbloader.COM.NET.NETCommunications;
import nsusbloader.COM.USB.UsbCommunications;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.ServiceWindow;
import java.io.File;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
public class FrontController implements Initializable {
@FXML
private Pane specialPane;
private AnchorPane usbNetPane;
@FXML
private ChoiceBox<String> choiceProtocol, choiceNetUsb;
@ -26,11 +38,19 @@ public class FrontController implements Initializable {
@FXML
private Button switchThemeBtn;
@FXML
public NSTableViewController tableFilesListController; // Accessible from Mediator
public NSTableViewController tableFilesListController; // Accessible from Mediator (for drag-n-drop support)
@FXML
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
private String previouslyOpenedPath;
private Region btnUpStopImage;
private ResourceBundle resourceBundle;
private Task<Void> usbNetCommunications;
private Thread workThread;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
specialPane.getStyleClass().add("special-pane-as-border"); // UI hacks
this.resourceBundle = resourceBundle;
ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf");
choiceProtocol.setItems(choiceProtocolList);
@ -52,9 +72,9 @@ public class FrontController implements Initializable {
}
// Really bad disable-enable upload button function
if (tableFilesListController.isFilesForUploadListEmpty())
MediatorControl.getInstance().getContoller().disableUploadStopBtn(true);
disableUploadStopBtn(true);
else
MediatorControl.getInstance().getContoller().disableUploadStopBtn(false);
disableUploadStopBtn(false);
}); // Add listener to notify tableView controller
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller
@ -92,6 +112,28 @@ public class FrontController implements Initializable {
btnSwitchImage.getStyleClass().add("regionLamp");
switchThemeBtn.setGraphic(btnSwitchImage);
this.switchThemeBtn.setOnAction(e->switchTheme());
if (getSelectedProtocol().equals("TinFoil"))
uploadStopBtn.setDisable(true);
else
uploadStopBtn.setDisable(false);
selectNspBtn.setOnAction(e-> selectFilesBtnAction());
selectSplitNspBtn.setOnAction(e-> selectSplitBtnAction());
selectSplitNspBtn.getStyleClass().add("buttonSelect");
uploadStopBtn.setOnAction(e-> uploadBtnAction());
selectNspBtn.getStyleClass().add("buttonSelect");
this.btnUpStopImage = new Region();
btnUpStopImage.getStyleClass().add("regionUpload");
uploadStopBtn.getStyleClass().add("buttonUp");
uploadStopBtn.setGraphic(btnUpStopImage);
this.previouslyOpenedPath = AppPreferences.getInstance().getRecent();
}
/**
* Changes UI theme on the go
@ -125,4 +167,200 @@ public class FrontController implements Initializable {
String getNsIp(){
return nsIpTextField.getText();
}
/*-****************************************************************************************************************-*/
/**
* Functionality for selecting NSP button.
* */
private void selectFilesBtnAction(){
List<File> filesList;
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(resourceBundle.getString("btn_OpenFile"));
File validator = new File(previouslyOpenedPath);
if (validator.exists())
fileChooser.setInitialDirectory(validator);
else
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));
if (getSelectedProtocol().equals("TinFoil") && MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTfXciNszXczSupport())
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP/XCI/NSZ/XCZ", "*.nsp", "*.xci", "*.nsz", "*.xcz"));
else if (getSelectedProtocol().equals("GoldLeaf") && (! MediatorControl.getInstance().getContoller().getSettingsCtrlr().getNSPFileFilterForGL()))
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Any file", "*.*"),
new FileChooser.ExtensionFilter("NSP ROM", "*.nsp")
);
else
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP ROM", "*.nsp"));
filesList = fileChooser.showOpenMultipleDialog(usbNetPane.getScene().getWindow());
if (filesList != null && !filesList.isEmpty()) {
tableFilesListController.setFiles(filesList);
uploadStopBtn.setDisable(false);
previouslyOpenedPath = filesList.get(0).getParent();
}
}
/**
* Functionality for selecting Split NSP button.
* */
private void selectSplitBtnAction(){
File splitFile;
DirectoryChooser dirChooser = new DirectoryChooser();
dirChooser.setTitle(resourceBundle.getString("btn_OpenFile"));
File validator = new File(previouslyOpenedPath);
if (validator.exists())
dirChooser.setInitialDirectory(validator);
else
dirChooser.setInitialDirectory(new File(System.getProperty("user.home")));
splitFile = dirChooser.showDialog(usbNetPane.getScene().getWindow());
if (splitFile != null && splitFile.getName().toLowerCase().endsWith(".nsp")) {
tableFilesListController.setFile(splitFile);
uploadStopBtn.setDisable(false); // Is it useful?
previouslyOpenedPath = splitFile.getParent();
}
}
/**
* It's button listener when no transmission executes
* */
private void uploadBtnAction(){
if ((workThread == null || !workThread.isAlive())){
// Collect files
List<File> nspToUpload;
if (tableFilesListController.getFilesForUpload() == null && getSelectedProtocol().equals("TinFoil")) {
MediatorControl.getInstance().getContoller().logArea.setText(resourceBundle.getString("tab3_Txt_NoFolderOrFileSelected"));
return;
}
else {
if ((nspToUpload = tableFilesListController.getFilesForUpload()) != null){
MediatorControl.getInstance().getContoller().logArea.setText(resourceBundle.getString("tab3_Txt_FilesToUploadTitle")+"\n");
for (File item: nspToUpload)
MediatorControl.getInstance().getContoller().logArea.appendText(" "+item.getAbsolutePath()+"\n");
}
else {
MediatorControl.getInstance().getContoller().logArea.clear();
nspToUpload = new LinkedList<>();
}
}
// If USB selected
if (getSelectedProtocol().equals("GoldLeaf") ||
( getSelectedProtocol().equals("TinFoil") && getSelectedNetUsb().equals("USB") )
){
usbNetCommunications = new UsbCommunications(nspToUpload, getSelectedProtocol()+MediatorControl.getInstance().getContoller().getSettingsCtrlr().getGlOldVer(), MediatorControl.getInstance().getContoller().getSettingsCtrlr().getNSPFileFilterForGL());
workThread = new Thread(usbNetCommunications);
workThread.setDaemon(true);
workThread.start();
}
else { // NET INSTALL OVER TINFOIL
if (MediatorControl.getInstance().getContoller().getSettingsCtrlr().isNsIpValidate() && ! getNsIp().matches("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"))
if (!ServiceWindow.getConfirmationWindow(resourceBundle.getString("windowTitleBadIp"),resourceBundle.getString("windowBodyBadIp")))
return;
String nsIP = getNsIp();
if (! MediatorControl.getInstance().getContoller().getSettingsCtrlr().getExpertModeSelected())
usbNetCommunications = new NETCommunications(nspToUpload, nsIP, false, "", "", "");
else {
usbNetCommunications = new NETCommunications(
nspToUpload,
nsIP,
MediatorControl.getInstance().getContoller().getSettingsCtrlr().getNotServeSelected(),
MediatorControl.getInstance().getContoller().getSettingsCtrlr().getAutoIpSelected()?"":MediatorControl.getInstance().getContoller().getSettingsCtrlr().getHostIp(),
MediatorControl.getInstance().getContoller().getSettingsCtrlr().getRandPortSelected()?"":MediatorControl.getInstance().getContoller().getSettingsCtrlr().getHostPort(),
MediatorControl.getInstance().getContoller().getSettingsCtrlr().getNotServeSelected()?MediatorControl.getInstance().getContoller().getSettingsCtrlr().getHostExtra():""
);
}
workThread = new Thread(usbNetCommunications);
workThread.setDaemon(true);
workThread.start();
}
}
}
/**
* It's button listener when transmission in progress
* */
private void stopBtnAction(){
if (workThread != null && workThread.isAlive()){
usbNetCommunications.cancel(false);
}
}
/**
* Drag-n-drop support (dragOver consumer)
* */
@FXML
private void handleDragOver(DragEvent event){
if (event.getDragboard().hasFiles() && ! MediatorControl.getInstance().getTransferActive())
event.acceptTransferModes(TransferMode.ANY);
event.consume();
}
/**
* Drag-n-drop support (drop consumer)
* */
@FXML
private void handleDrop(DragEvent event){
List<File> filesDropped = event.getDragboard().getFiles();
if (getSelectedProtocol().equals("TinFoil") && MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTfXciNszXczSupport())
filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches("(.*\\.nsp$)|(.*\\.xci$)|(.*\\.nsz$)|(.*\\.xcz$)"));
else if (getSelectedProtocol().equals("GoldLeaf") && (! MediatorControl.getInstance().getContoller().getSettingsCtrlr().getNSPFileFilterForGL()))
filesDropped.removeIf(file -> (file.isDirectory() && ! file.getName().toLowerCase().matches(".*\\.nsp$")));
else
filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches(".*\\.nsp$"));
if ( ! filesDropped.isEmpty() )
tableFilesListController.setFiles(filesDropped);
event.setDropCompleted(true);
event.consume();
}
/**
* This thing modify UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission"
* Called from mediator
* TODO: remove shitcoding practices
* */
public void notifyTransmThreadStarted(boolean isActive, EModule type){
if (! type.equals(EModule.USB_NET_TRANSFERS)){
usbNetPane.setDisable(isActive);
return;
}
if (isActive) {
selectNspBtn.setDisable(true);
selectSplitNspBtn.setDisable(true);
btnUpStopImage.getStyleClass().clear();
btnUpStopImage.getStyleClass().add("regionStop");
uploadStopBtn.setOnAction(e-> stopBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
uploadStopBtn.getStyleClass().remove("buttonUp");
uploadStopBtn.getStyleClass().add("buttonStop");
return;
}
selectNspBtn.setDisable(false);
selectSplitNspBtn.setDisable(false);
btnUpStopImage.getStyleClass().clear();
btnUpStopImage.getStyleClass().add("regionUpload");
uploadStopBtn.setOnAction(e-> uploadBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
uploadStopBtn.getStyleClass().remove("buttonStop");
uploadStopBtn.getStyleClass().add("buttonUp");
}
/**
* Crunch. This function called from NSTableViewController
* */
public void disableUploadStopBtn(boolean disable){
if (getSelectedProtocol().equals("TinFoil"))
uploadStopBtn.setDisable(disable);
else
uploadStopBtn.setDisable(false);
}
/**
* Get 'Recent' path
*/
public String getRecentPath(){
return previouslyOpenedPath;
}
}

View file

@ -5,19 +5,10 @@ import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Region;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import nsusbloader.*;
import nsusbloader.ModelControllers.UpdatesChecker;
import nsusbloader.COM.NET.NETCommunications;
import nsusbloader.COM.USB.UsbCommunications;
import java.io.File;
import java.net.*;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
@ -27,22 +18,18 @@ public class NSLMainController implements Initializable {
@FXML
public TextArea logArea; // Accessible from Mediator
@FXML
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
private Region btnUpStopImage;
@FXML
public ProgressBar progressBar; // Accessible from Mediator
@FXML
public FrontController FrontTabController; // Accessible from Mediator | todo: incapsulate
@FXML
private SettingsController SettingsTabController;
@FXML
public FrontController FrontTabController; // Accessible from Mediator | todo: incapsulate
private Task<Void> usbNetCommunications;
private Thread workThread;
private String previouslyOpenedPath;
private SplitMergeController SplitMergeTabController;
@FXML
private RcmController RcmTabController;
@Override
public void initialize(URL url, ResourceBundle rb) {
@ -56,27 +43,6 @@ public class NSLMainController implements Initializable {
MediatorControl.getInstance().setController(this);
if (FrontTabController.getSelectedProtocol().equals("TinFoil"))
uploadStopBtn.setDisable(true);
else
uploadStopBtn.setDisable(false);
selectNspBtn.setOnAction(e-> selectFilesBtnAction());
selectSplitNspBtn.setOnAction(e-> selectSplitBtnAction());
selectSplitNspBtn.getStyleClass().add("buttonSelect");
uploadStopBtn.setOnAction(e-> uploadBtnAction());
selectNspBtn.getStyleClass().add("buttonSelect");
this.btnUpStopImage = new Region();
btnUpStopImage.getStyleClass().add("regionUpload");
uploadStopBtn.getStyleClass().add("buttonUp");
uploadStopBtn.setGraphic(btnUpStopImage);
this.previouslyOpenedPath = AppPreferences.getInstance().getRecent();
if (AppPreferences.getInstance().getAutoCheckUpdates()){
Task<List<String>> updTask = new UpdatesChecker();
updTask.setOnSucceeded(event->{
@ -110,201 +76,29 @@ public class NSLMainController implements Initializable {
public void setHostServices(HostServices hs ){ SettingsTabController.registerHostServices(hs);}
/**
* Functionality for selecting NSP button.
* Get 'Settings' controller
* Used by FrontController
* */
private void selectFilesBtnAction(){
List<File> filesList;
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(resourceBundle.getString("btn_OpenFile"));
File validator = new File(previouslyOpenedPath);
if (validator.exists())
fileChooser.setInitialDirectory(validator);
else
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));
if (FrontTabController.getSelectedProtocol().equals("TinFoil") && SettingsTabController.getTfXciNszXczSupport())
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP/XCI/NSZ/XCZ", "*.nsp", "*.xci", "*.nsz", "*.xcz"));
else if (FrontTabController.getSelectedProtocol().equals("GoldLeaf") && (! SettingsTabController.getNSPFileFilterForGL()))
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Any file", "*.*"),
new FileChooser.ExtensionFilter("NSP ROM", "*.nsp")
);
else
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP ROM", "*.nsp"));
filesList = fileChooser.showOpenMultipleDialog(logArea.getScene().getWindow());
if (filesList != null && !filesList.isEmpty()) {
FrontTabController.tableFilesListController.setFiles(filesList);
uploadStopBtn.setDisable(false);
previouslyOpenedPath = filesList.get(0).getParent();
}
public SettingsController getSettingsCtrlr(){
return SettingsTabController;
}
/**
* Functionality for selecting Split NSP button.
* */
private void selectSplitBtnAction(){
File splitFile;
DirectoryChooser dirChooser = new DirectoryChooser();
dirChooser.setTitle(resourceBundle.getString("btn_OpenFile"));
File validator = new File(previouslyOpenedPath);
if (validator.exists())
dirChooser.setInitialDirectory(validator);
else
dirChooser.setInitialDirectory(new File(System.getProperty("user.home")));
splitFile = dirChooser.showDialog(logArea.getScene().getWindow());
if (splitFile != null && splitFile.getName().toLowerCase().endsWith(".nsp")) {
FrontTabController.tableFilesListController.setFile(splitFile);
uploadStopBtn.setDisable(false); // Is it useful?
previouslyOpenedPath = splitFile.getParent();
}
public FrontController getFrontCtrlr(){
return FrontTabController;
}
/**
* It's button listener when no transmission executes
* */
private void uploadBtnAction(){
if ((workThread == null || !workThread.isAlive())){
// Collect files
List<File> nspToUpload;
if (FrontTabController.tableFilesListController.getFilesForUpload() == null && FrontTabController.getSelectedProtocol().equals("TinFoil")) {
logArea.setText(resourceBundle.getString("tab3_Txt_NoFolderOrFileSelected"));
return;
}
else {
if ((nspToUpload = FrontTabController.tableFilesListController.getFilesForUpload()) != null){
logArea.setText(resourceBundle.getString("tab3_Txt_FilesToUploadTitle")+"\n");
for (File item: nspToUpload)
logArea.appendText(" "+item.getAbsolutePath()+"\n");
}
else {
logArea.clear();
nspToUpload = new LinkedList<>();
}
}
// If USB selected
if (FrontTabController.getSelectedProtocol().equals("GoldLeaf") ||
( FrontTabController.getSelectedProtocol().equals("TinFoil") && FrontTabController.getSelectedNetUsb().equals("USB") )
){
usbNetCommunications = new UsbCommunications(nspToUpload, FrontTabController.getSelectedProtocol()+SettingsTabController.getGlOldVer(), SettingsTabController.getNSPFileFilterForGL());
workThread = new Thread(usbNetCommunications);
workThread.setDaemon(true);
workThread.start();
}
else { // NET INSTALL OVER TINFOIL
if (SettingsTabController.isNsIpValidate() && ! FrontTabController.getNsIp().matches("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"))
if (!ServiceWindow.getConfirmationWindow(resourceBundle.getString("windowTitleBadIp"),resourceBundle.getString("windowBodyBadIp")))
return;
String nsIP = FrontTabController.getNsIp();
if (!SettingsTabController.getExpertModeSelected())
usbNetCommunications = new NETCommunications(nspToUpload, nsIP, false, "", "", "");
else {
usbNetCommunications = new NETCommunications(
nspToUpload,
nsIP,
SettingsTabController.getNotServeSelected(),
SettingsTabController.getAutoIpSelected()?"":SettingsTabController.getHostIp(),
SettingsTabController.getRandPortSelected()?"":SettingsTabController.getHostPort(),
SettingsTabController.getNotServeSelected()?SettingsTabController.getHostExtra():""
);
}
workThread = new Thread(usbNetCommunications);
workThread.setDaemon(true);
workThread.start();
}
}
public SplitMergeController getSmCtrlr(){
return SplitMergeTabController;
}
/**
* It's button listener when transmission in progress
* */
private void stopBtnAction(){
if (workThread != null && workThread.isAlive()){
usbNetCommunications.cancel(false);
}
}
/**
* This thing modify UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission"
* Called from mediator
* */
public void notifyTransmissionStarted(boolean isTransmissionStarted){
if (isTransmissionStarted) {
selectNspBtn.setDisable(true);
selectSplitNspBtn.setDisable(true);
uploadStopBtn.setOnAction(e-> stopBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
btnUpStopImage.getStyleClass().remove("regionUpload");
btnUpStopImage.getStyleClass().add("regionStop");
uploadStopBtn.getStyleClass().remove("buttonUp");
uploadStopBtn.getStyleClass().add("buttonStop");
}
else {
selectNspBtn.setDisable(false);
selectSplitNspBtn.setDisable(false);
uploadStopBtn.setOnAction(e-> uploadBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
btnUpStopImage.getStyleClass().remove("regionStop");
btnUpStopImage.getStyleClass().add("regionUpload");
uploadStopBtn.getStyleClass().remove("buttonStop");
uploadStopBtn.getStyleClass().add("buttonUp");
}
}
/**
* Crunch. Now you see that I'm not a programmer.. This function called from NSTableViewController
* */
public void disableUploadStopBtn(boolean disable){
if (FrontTabController.getSelectedProtocol().equals("TinFoil"))
uploadStopBtn.setDisable(disable);
else
uploadStopBtn.setDisable(false);
}
/**
* Drag-n-drop support (dragOver consumer)
* */
@FXML
private void handleDragOver(DragEvent event){
if (event.getDragboard().hasFiles())
event.acceptTransferModes(TransferMode.ANY);
}
/**
* Drag-n-drop support (drop consumer)
* */
@FXML
private void handleDrop(DragEvent event){
if (MediatorControl.getInstance().getTransferActive()) {
event.setDropCompleted(true);
return;
}
List<File> filesDropped = event.getDragboard().getFiles();
if (FrontTabController.getSelectedProtocol().equals("TinFoil") && SettingsTabController.getTfXciNszXczSupport())
filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches("(.*\\.nsp$)|(.*\\.xci$)|(.*\\.nsz$)|(.*\\.xcz$)"));
else if (FrontTabController.getSelectedProtocol().equals("GoldLeaf") && (! SettingsTabController.getNSPFileFilterForGL()))
filesDropped.removeIf(file -> (file.isDirectory() && ! file.getName().toLowerCase().matches(".*\\.nsp$")));
else
filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches(".*\\.nsp$"));
if ( ! filesDropped.isEmpty() )
FrontTabController.tableFilesListController.setFiles(filesDropped);
event.setDropCompleted(true);
}
public RcmController getRcmCtrlr(){ return RcmTabController; }
/**
* Save preferences before exit
* */
public void exit(){
AppPreferences.getInstance().setAll(
FrontTabController.getSelectedProtocol(),
previouslyOpenedPath,
FrontTabController.getRecentPath(),
FrontTabController.getSelectedNetUsb(),
FrontTabController.getNsIp(),
SettingsTabController.isNsIpValidate(),
@ -320,5 +114,8 @@ public class NSLMainController implements Initializable {
SettingsTabController.getNSPFileFilterForGL(),
SettingsTabController.getGlOldVer()
);
SplitMergeTabController.updatePreferencesOnExit(); // NOTE: This shit above should be re-written to similar pattern
RcmTabController.updatePreferencesOnExit();
}
}

View file

@ -17,7 +17,6 @@ import nsusbloader.NSLDataTypes.EFileStatus;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
@ -39,7 +38,7 @@ public class NSTableViewController implements Initializable {
if (keyEvent.getCode() == KeyCode.DELETE && !MediatorControl.getInstance().getTransferActive()) {
rowsObsLst.removeAll(table.getSelectionModel().getSelectedItems());
if (rowsObsLst.isEmpty())
MediatorControl.getInstance().getContoller().disableUploadStopBtn(true); // TODO: change to something better
MediatorControl.getInstance().getContoller().getFrontCtrlr().disableUploadStopBtn(true); // TODO: change to something better
table.refresh();
} else if (keyEvent.getCode() == KeyCode.SPACE) {
for (NSLRowModel item : table.getSelectionModel().getSelectedItems()) {
@ -112,13 +111,13 @@ public class NSTableViewController implements Initializable {
deleteMenuItem.setOnAction(actionEvent -> {
rowsObsLst.remove(row.getItem());
if (rowsObsLst.isEmpty())
MediatorControl.getInstance().getContoller().disableUploadStopBtn(true); // TODO: change to something better
MediatorControl.getInstance().getContoller().getFrontCtrlr().disableUploadStopBtn(true); // TODO: change to something better
table.refresh();
});
MenuItem deleteAllMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_DeleteAll"));
deleteAllMenuItem.setOnAction(actionEvent -> {
rowsObsLst.clear();
MediatorControl.getInstance().getContoller().disableUploadStopBtn(true); // TODO: change to something better
MediatorControl.getInstance().getContoller().getFrontCtrlr().disableUploadStopBtn(true); // TODO: change to something better
table.refresh();
});
contextMenu.getItems().addAll(deleteMenuItem, deleteAllMenuItem);
@ -163,7 +162,7 @@ public class NSTableViewController implements Initializable {
}
else {
rowsObsLst.add(new NSLRowModel(file, true));
MediatorControl.getInstance().getContoller().disableUploadStopBtn(false);
MediatorControl.getInstance().getContoller().getFrontCtrlr().disableUploadStopBtn(false); // TODO: change to something better
}
table.refresh();
}
@ -183,7 +182,7 @@ public class NSTableViewController implements Initializable {
else {
for (File file: newFiles)
rowsObsLst.add(new NSLRowModel(file, true));
MediatorControl.getInstance().getContoller().disableUploadStopBtn(false);
MediatorControl.getInstance().getContoller().getFrontCtrlr().disableUploadStopBtn(false); // TODO: change to something better
}
//rowsObsLst.get(0).setMarkForUpload(true);
table.refresh();

View file

@ -0,0 +1,329 @@
package nsusbloader.Controllers;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.DragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import nsusbloader.AppPreferences;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.ServiceWindow;
import nsusbloader.Utilities.RcmTask;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
public class RcmController implements Initializable {
@FXML
private ToggleGroup rcmToggleGrp;
@FXML
private VBox rcmToolPane;
@FXML
private RadioButton pldrRadio1,
pldrRadio2,
pldrRadio3,
pldrRadio4,
pldrRadio5;
@FXML
private Button injectPldBtn;
@FXML
private Label payloadFNameLbl1, payloadFPathLbl1,
payloadFNameLbl2, payloadFPathLbl2,
payloadFNameLbl3, payloadFPathLbl3,
payloadFNameLbl4, payloadFPathLbl4,
payloadFNameLbl5, payloadFPathLbl5;
@FXML
private Label statusLbl;
private ResourceBundle rb;
private String myRegexp;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
this.rb = resourceBundle;
rcmToggleGrp.selectToggle(pldrRadio1);
pldrRadio1.setOnAction(e -> statusLbl.setText(""));
pldrRadio2.setOnAction(e -> statusLbl.setText(""));
pldrRadio3.setOnAction(e -> statusLbl.setText(""));
pldrRadio4.setOnAction(e -> statusLbl.setText(""));
pldrRadio5.setOnAction(e -> statusLbl.setText(""));
String recentRcm1 = AppPreferences.getInstance().getRecentRcm(1);
String recentRcm2 = AppPreferences.getInstance().getRecentRcm(2);
String recentRcm3 = AppPreferences.getInstance().getRecentRcm(3);
String recentRcm4 = AppPreferences.getInstance().getRecentRcm(4);
String recentRcm5 = AppPreferences.getInstance().getRecentRcm(5);
if (File.separator.equals("/"))
this.myRegexp = "^.+/";
else
this.myRegexp = "^.+\\\\";
if (! recentRcm1.isEmpty()) {
payloadFNameLbl1.setText(recentRcm1.replaceAll(myRegexp, ""));
payloadFPathLbl1.setText(recentRcm1);
}
if (! recentRcm2.isEmpty()) {
payloadFNameLbl2.setText(recentRcm2.replaceAll(myRegexp, ""));
payloadFPathLbl2.setText(recentRcm2);
}
if (! recentRcm3.isEmpty()) {
payloadFNameLbl3.setText(recentRcm3.replaceAll(myRegexp, ""));
payloadFPathLbl3.setText(recentRcm3);
}
if (! recentRcm4.isEmpty()) {
payloadFNameLbl4.setText(recentRcm4.replaceAll(myRegexp, ""));
payloadFPathLbl4.setText(recentRcm4);
}
if (! recentRcm5.isEmpty()) {
payloadFNameLbl5.setText(recentRcm5.replaceAll(myRegexp, ""));
payloadFPathLbl5.setText(recentRcm5);
}
// TODO: write logic ?? Like in case PAYLOADER exist, button active. If not: not active?
injectPldBtn.setOnAction(actionEvent -> smash());
}
/**
* 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){
Node sourceNode = (Node) event.getSource();
File fileDrpd = event.getDragboard().getFiles().get(0);
if (fileDrpd.isDirectory()){
event.setDropCompleted(true);
event.consume();
return;
}
String fileNameDrpd = fileDrpd.getAbsolutePath();
switch (sourceNode.getId()){
case "plHbox1":
setPayloadFile( 1, fileNameDrpd);
break;
case "plHbox2":
setPayloadFile( 2, fileNameDrpd);
break;
case "plHbox3":
setPayloadFile( 3, fileNameDrpd);
break;
case "plHbox4":
setPayloadFile( 4, fileNameDrpd);
break;
case "plHbox5":
setPayloadFile( 5, fileNameDrpd);
}
event.setDropCompleted(true);
event.consume();
}
private void setPayloadFile(int RcmBoxNo, String fileName){
String fileNameShort = fileName.replaceAll(myRegexp, "");
switch (RcmBoxNo){
case 1:
payloadFNameLbl1.setText(fileNameShort);
payloadFPathLbl1.setText(fileName);
rcmToggleGrp.selectToggle(pldrRadio1);
break;
case 2:
payloadFNameLbl2.setText(fileNameShort);
payloadFPathLbl2.setText(fileName);
rcmToggleGrp.selectToggle(pldrRadio2);
break;
case 3:
payloadFNameLbl3.setText(fileNameShort);
payloadFPathLbl3.setText(fileName);
rcmToggleGrp.selectToggle(pldrRadio3);
break;
case 4:
payloadFNameLbl4.setText(fileNameShort);
payloadFPathLbl4.setText(fileName);
rcmToggleGrp.selectToggle(pldrRadio4);
break;
case 5:
payloadFNameLbl5.setText(fileNameShort);
payloadFPathLbl5.setText(fileName);
rcmToggleGrp.selectToggle(pldrRadio5);
}
}
private void smash(){
statusLbl.setText("");
if (MediatorControl.getInstance().getTransferActive()) {
ServiceWindow.getErrorNotification(rb.getString("windowTitleError"), rb.getString("windowBodyPleaseFinishTransfersFirst"));
return;
}
Task<Boolean> RcmTask;
RadioButton selectedRadio = (RadioButton)rcmToggleGrp.getSelectedToggle();
switch (selectedRadio.getId()){
case "pldrRadio1":
RcmTask = new RcmTask(payloadFPathLbl1.getText());
break;
case "pldrRadio2":
RcmTask = new RcmTask(payloadFPathLbl2.getText());
break;
case "pldrRadio3":
RcmTask = new RcmTask(payloadFPathLbl3.getText());
break;
case "pldrRadio4":
RcmTask = new RcmTask(payloadFPathLbl4.getText());
break;
case "pldrRadio5":
RcmTask = new RcmTask(payloadFPathLbl5.getText());
break;
default:
return;
}
RcmTask.setOnSucceeded(event -> {
if (RcmTask.getValue())
statusLbl.setText(rb.getString("done_txt"));
else
statusLbl.setText(rb.getString("failure_txt"));
});
Thread RcmThread = new Thread(RcmTask);
RcmThread.setDaemon(true);
RcmThread.start();
}
@FXML
private void bntSelectPayloader(ActionEvent event){
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(rb.getString("btn_Select"));
File validator = new File(payloadFPathLbl1.getText()).getParentFile();
if (validator != null && validator.exists())
fileChooser.setInitialDirectory(validator);
else
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("bin", "*.bin"),
new FileChooser.ExtensionFilter("Any file", "*.*")
);
File payloadFile = fileChooser.showOpenDialog(payloadFPathLbl1.getScene().getWindow());
if (payloadFile == null)
return;
final String fullFileName = payloadFile.getAbsolutePath();
final Node btn = (Node)event.getSource();
switch (btn.getId()){
case "selPldBtn1":
setPayloadFile(1, fullFileName);
break;
case "selPldBtn2":
setPayloadFile(2, fullFileName);
break;
case "selPldBtn3":
setPayloadFile(3, fullFileName);
break;
case "selPldBtn4":
setPayloadFile(4, fullFileName);
break;
case "selPldBtn5":
setPayloadFile(5, fullFileName);
}
}
@FXML
private void bntResetPayloader(ActionEvent event){
final Node btn = (Node)event.getSource();
switch (btn.getId()){
case "resPldBtn1":
payloadFNameLbl1.setText("");
payloadFPathLbl1.setText("");
statusLbl.setText("");
break;
case "resPldBtn2":
payloadFNameLbl2.setText("");
payloadFPathLbl2.setText("");
statusLbl.setText("");
break;
case "resPldBtn3":
payloadFNameLbl3.setText("");
payloadFPathLbl3.setText("");
statusLbl.setText("");
break;
case "resPldBtn4":
payloadFNameLbl4.setText("");
payloadFPathLbl4.setText("");
statusLbl.setText("");
break;
case "resPldBtn5":
payloadFNameLbl5.setText("");
payloadFPathLbl5.setText("");
statusLbl.setText("");
}
}
@FXML
public void selectPldrPane(MouseEvent mouseEvent) {
final Node selectedPane = (Node)mouseEvent.getSource();
switch (selectedPane.getId()){
case "pldPane1":
pldrRadio1.fire();
break;
case "pldPane2":
pldrRadio2.fire();
break;
case "pldPane3":
pldrRadio3.fire();
break;
case "pldPane4":
pldrRadio4.fire();
break;
case "pldPane5":
pldrRadio5.fire();
break;
}
}
public void notifySmThreadStarted(boolean isStart, EModule type){
rcmToolPane.setDisable(isStart);
if (type.equals(EModule.RCM) && isStart){
MediatorControl.getInstance().getContoller().logArea.clear();
}
}
/**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
AppPreferences.getInstance().setRecentRcm(1, payloadFPathLbl1.getText());
AppPreferences.getInstance().setRecentRcm(2, payloadFPathLbl2.getText());
AppPreferences.getInstance().setRecentRcm(3, payloadFPathLbl3.getText());
AppPreferences.getInstance().setRecentRcm(4, payloadFPathLbl4.getText());
AppPreferences.getInstance().setRecentRcm(5, payloadFPathLbl5.getText());
}
}

View file

@ -0,0 +1,240 @@
package nsusbloader.Controllers;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import nsusbloader.AppPreferences;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.ServiceWindow;
import nsusbloader.Utilities.SplitMergeTool;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
public class SplitMergeController implements Initializable {
@FXML
private ToggleGroup splitMergeTogGrp;
@FXML
private VBox smToolPane;
@FXML
private RadioButton splitRad, mergeRad;
@FXML
private Button selectFileFolderBtn,
changeSaveToBtn,
convertBtn;
@FXML
private Label fileFolderLabelLbl,
fileFolderActualPathLbl,
saveToPathLbl,
statusLbl;
private ResourceBundle resourceBundle;
private Region convertRegion;
private Task<Boolean> smTask;
private Thread smThread;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
convertRegion = new Region();
convertBtn.setGraphic(convertRegion);
splitRad.setOnAction((actionEvent -> {
statusLbl.setText("");
convertRegion.getStyleClass().clear();
convertRegion.getStyleClass().add("regionSplitToOne");
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_File"));
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
fileFolderActualPathLbl.setText("");
convertBtn.setDisable(true);
}));
mergeRad.setOnAction((actionEvent -> {
statusLbl.setText("");
convertRegion.getStyleClass().clear();
convertRegion.getStyleClass().add("regionOneToSplit");
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_Folder"));
selectFileFolderBtn.setText(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
fileFolderActualPathLbl.setText("");
convertBtn.setDisable(true);
}));
if (AppPreferences.getInstance().getSplitMergeType() == 0)
splitRad.fire();
else
mergeRad.fire();
saveToPathLbl.setText(AppPreferences.getInstance().getSplitMergeRecent());
changeSaveToBtn.setOnAction((actionEvent -> {
DirectoryChooser dc = new DirectoryChooser();
dc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
dc.setInitialDirectory(new File(saveToPathLbl.getText()));
File saveToDir = dc.showDialog(changeSaveToBtn.getScene().getWindow());
if (saveToDir != null)
saveToPathLbl.setText(saveToDir.getAbsolutePath());
}));
selectFileFolderBtn.setOnAction(actionEvent -> {
statusLbl.setText("");
if (splitRad.isSelected()) {
FileChooser fc = new FileChooser();
fc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
if (! fileFolderActualPathLbl.getText().isEmpty()){
File temporaryFile = new File(fileFolderActualPathLbl.getText()).getParentFile();
if (temporaryFile != null && temporaryFile.exists())
fc.setInitialDirectory(temporaryFile);
else
fc.setInitialDirectory(new File(System.getProperty("user.home")));
}
else
fc.setInitialDirectory(new File(System.getProperty("user.home")));
File fileFile = fc.showOpenDialog(changeSaveToBtn.getScene().getWindow());
if (fileFile == null)
return;
fileFolderActualPathLbl.setText(fileFile.getAbsolutePath());
}
else{
DirectoryChooser dc = new DirectoryChooser();
dc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
if (! fileFolderActualPathLbl.getText().isEmpty()){
File temporaryFile = new File(fileFolderActualPathLbl.getText());
if (temporaryFile.exists())
dc.setInitialDirectory(temporaryFile);
else
dc.setInitialDirectory(new File(System.getProperty("user.home")));
}
else
dc.setInitialDirectory(new File(System.getProperty("user.home")));
File folderFile = dc.showDialog(changeSaveToBtn.getScene().getWindow());
if (folderFile == null)
return;
fileFolderActualPathLbl.setText(folderFile.getAbsolutePath());
}
convertBtn.setDisable(false);
});
convertBtn.setOnAction(actionEvent -> setConvertBtnAction());
}
public void notifySmThreadStarted(boolean isStart, EModule type){ // todo: refactor: remove everything, place to separate container and just disable.
if (! type.equals(EModule.SPLIT_MERGE_TOOL)){
smToolPane.setDisable(isStart);
return;
}
if (isStart){
MediatorControl.getInstance().getContoller().logArea.clear();
splitRad.setDisable(true);
mergeRad.setDisable(true);
selectFileFolderBtn.setDisable(true);
changeSaveToBtn.setDisable(true);
convertBtn.setOnAction(e -> stopBtnAction());
convertBtn.setText(resourceBundle.getString("btn_Stop"));
convertRegion.getStyleClass().clear();
convertRegion.getStyleClass().add("regionStop");
convertBtn.getStyleClass().remove("buttonUp");
convertBtn.getStyleClass().add("buttonStop");
return;
}
splitRad.setDisable(false);
mergeRad.setDisable(false);
selectFileFolderBtn.setDisable(false);
changeSaveToBtn.setDisable(false);
convertBtn.setOnAction(e -> setConvertBtnAction());
convertBtn.setText(resourceBundle.getString("tabSplMrg_Btn_Convert"));
convertRegion.getStyleClass().clear();
convertBtn.getStyleClass().remove("buttonStop");
convertBtn.getStyleClass().add("buttonUp");
if (splitRad.isSelected())
convertRegion.getStyleClass().add("regionSplitToOne");
else
convertRegion.getStyleClass().add("regionOneToSplit");
}
/**
* It's button listener when convert-process in progress
* */
private void stopBtnAction(){
if (smThread != null && smThread.isAlive())
smTask.cancel(false);
}
/**
* It's button listener when convert-process NOT in progress
* */
private void setConvertBtnAction(){
statusLbl.setText("");
if (MediatorControl.getInstance().getTransferActive()) {
ServiceWindow.getErrorNotification(
resourceBundle.getString("windowTitleError"),
resourceBundle.getString("windowBodyPleaseFinishTransfersFirst")
);
return;
}
if (splitRad.isSelected())
smTask = SplitMergeTool.splitFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
else
smTask = SplitMergeTool.mergeFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
smTask.setOnCancelled(event -> statusLbl.setText(resourceBundle.getString("failure_txt")));
smTask.setOnSucceeded(event -> {
if (smTask.getValue())
statusLbl.setText(resourceBundle.getString("done_txt"));
else
statusLbl.setText(resourceBundle.getString("failure_txt"));
});
smThread = new Thread(smTask);
smThread.setDaemon(true);
smThread.start();
}
/**
* Drag-n-drop support (dragOver consumer)
* */
@FXML
private void handleDragOver(DragEvent event){
if (event.getDragboard().hasFiles() && ! MediatorControl.getInstance().getTransferActive())
event.acceptTransferModes(TransferMode.ANY);
event.consume();
}
/**
* Drag-n-drop support (drop consumer)
* */
@FXML
private void handleDrop(DragEvent event) {
Node sourceNode = (Node) event.getSource();
File fileDrpd = event.getDragboard().getFiles().get(0);
if (fileDrpd.isDirectory())
mergeRad.fire();
else
splitRad.fire();
fileFolderActualPathLbl.setText(fileDrpd.getAbsolutePath());
convertBtn.setDisable(false);
event.setDropCompleted(true);
event.consume();
}
/**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
if (splitRad.isSelected())
AppPreferences.getInstance().setSplitMergeType(0);
else
AppPreferences.getInstance().setSplitMergeType(1);
AppPreferences.getInstance().setSplitMergeRecent(saveToPathLbl.getText());
}
}

View file

@ -1,12 +1,13 @@
package nsusbloader;
import nsusbloader.Controllers.NSLMainController;
import nsusbloader.NSLDataTypes.EModule;
import java.util.concurrent.atomic.AtomicBoolean;
public class MediatorControl {
private AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure
private NSLMainController applicationController;
private NSLMainController mainCtrler;
public static MediatorControl getInstance(){
return MediatorControlHold.INSTANCE;
@ -16,13 +17,15 @@ public class MediatorControl {
private static final MediatorControl INSTANCE = new MediatorControl();
}
public void setController(NSLMainController controller){
this.applicationController = controller;
this.mainCtrler = controller;
}
public NSLMainController getContoller(){ return this.applicationController; }
public NSLMainController getContoller(){ return this.mainCtrler; }
public synchronized void setTransferActive(boolean state) {
isTransferActive.set(state);
applicationController.notifyTransmissionStarted(state);
public synchronized void setBgThreadActive(boolean isActive, EModule appModuleType) {
isTransferActive.set(isActive);
mainCtrler.getFrontCtrlr().notifyTransmThreadStarted(isActive, appModuleType);
mainCtrler.getSmCtrlr().notifySmThreadStarted(isActive, appModuleType);
mainCtrler.getRcmCtrlr().notifySmThreadStarted(isActive, appModuleType);
}
public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
}

View file

@ -1,6 +1,7 @@
package nsusbloader.ModelControllers;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import java.io.File;
@ -14,11 +15,11 @@ public class LogPrinter {
private BlockingQueue<Double> progressQueue;
private HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
public LogPrinter(){
public LogPrinter(EModule whoIsAsking){
this.msgQueue = new LinkedBlockingQueue<>();
this.progressQueue = new LinkedBlockingQueue<>();
this.statusMap = new HashMap<>();
this.msgConsumer = new MessagesConsumer(this.msgQueue, this.progressQueue, this.statusMap);
this.msgConsumer = new MessagesConsumer(whoIsAsking, this.msgQueue, this.progressQueue, this.statusMap);
this.msgConsumer.start();
}
/**
@ -42,7 +43,8 @@ public class LogPrinter {
default:
msgQueue.put(message);
}
}catch (InterruptedException ie){
}
catch (InterruptedException ie){
ie.printStackTrace();
}
}

View file

@ -7,6 +7,7 @@ import javafx.scene.control.TextArea;
import nsusbloader.Controllers.NSTableViewController;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EModule;
import java.util.ArrayList;
import java.util.HashMap;
@ -20,10 +21,12 @@ public class MessagesConsumer extends AnimationTimer {
private final ProgressBar progressBar;
private final HashMap<String, EFileStatus> statusMap;
private final NSTableViewController tableViewController;
private final EModule appModuleType;
private boolean isInterrupted;
MessagesConsumer(BlockingQueue<String> msgQueue, BlockingQueue<Double> progressQueue, HashMap<String, EFileStatus> statusMap){
MessagesConsumer(EModule appModuleType, BlockingQueue<String> msgQueue, BlockingQueue<Double> progressQueue, HashMap<String, EFileStatus> statusMap){
this.appModuleType = appModuleType;
this.isInterrupted = false;
this.msgQueue = msgQueue;
@ -38,7 +41,7 @@ public class MessagesConsumer extends AnimationTimer {
progressBar.setProgress(0.0);
progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
MediatorControl.getInstance().setTransferActive(true);
MediatorControl.getInstance().setBgThreadActive(true, appModuleType);
}
@Override
@ -60,7 +63,7 @@ public class MessagesConsumer extends AnimationTimer {
}
if (isInterrupted) { // It's safe 'cuz it's could't be interrupted while HashMap populating
MediatorControl.getInstance().setTransferActive(false);
MediatorControl.getInstance().setBgThreadActive(false, appModuleType);
progressBar.setProgress(0.0);
if (statusMap.size() > 0)

View file

@ -0,0 +1,7 @@
package nsusbloader.NSLDataTypes;
public enum EModule {
USB_NET_TRANSFERS,
SPLIT_MERGE_TOOL,
RCM
}

View file

@ -12,7 +12,9 @@ import java.util.Locale;
import java.util.ResourceBundle;
public class NSLMain extends Application {
public static final String appVersion = "v1.0";
public static final String appVersion = "v2.0";
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/NSLMain.fxml"));

View file

@ -0,0 +1,105 @@
package nsusbloader.Utilities;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
public class JNIRcmLoader {
private JNIRcmLoader(){}
public static boolean load(){
String osName = System.getProperty("os.name").toLowerCase().replace(" ", "");
String osArch = System.getProperty("os.arch").toLowerCase().replace(" ", "");
String libPostfix;
if (osName.equals("linux")){
switch (osArch){
case "i386":
case "i586":
case "i686":
osArch = "x86";
break;
case "x86_64":
case "amd64":
osArch = "amd64";
break;
default:
return false;
}
libPostfix = "so";
}
else if (osName.contains("windows")){
osName = "windows";
libPostfix = "dll";
switch (osArch){
case "x86":
case "i386":
case "i586":
case "i686":
osArch = "x86";
break;
case "x86_64":
case "amd64":
osArch = "amd64";
break;
default:
return false;
}
}
else
return false;
final URL url_ = RcmSmash.class.getResource("/native/"+osName+"/"+osArch+"/smashlib."+libPostfix);
if (url_ == null)
return false;
String proto = url_.getProtocol();
File libraryFile;
if (proto.equals("file")){
// We can pick file from disk as is.
try {
libraryFile = new File(url_.toURI());
}
catch (URISyntaxException e){
e.printStackTrace();
return false;
}
}
else if (proto.equals("jar")){
// We have to export file to temp dir.
InputStream inStream = RcmSmash.class.getResourceAsStream("/native/"+osName+"/"+osArch+"/smashlib."+libPostfix);
if (inStream == null)
return false;
// Create temp folder
try{
File tmpDirFile = File.createTempFile("jni", null);
if (! tmpDirFile.delete())
return false;
if (! tmpDirFile.mkdirs())
return false;
libraryFile = new File(tmpDirFile, "smashlib."+libPostfix);
byte[] ioBuffer = new byte[8192];
FileOutputStream foStream = new FileOutputStream(libraryFile);
while (inStream.read(ioBuffer) != -1)
foStream.write(ioBuffer);
foStream.close();
inStream.close();
libraryFile.deleteOnExit();
tmpDirFile.deleteOnExit();
}
catch (IOException ioe){
ioe.printStackTrace();
return false;
}
}
else
return false;
//System.out.println("LIB LOCATION: "+libraryFile);
System.load(libraryFile.getAbsolutePath());
//System.out.println("LIB LOADED");
return true;
}
}

View file

@ -0,0 +1,17 @@
package nsusbloader.Utilities;
public class RcmSmash {
private static final boolean supported;
static {
supported = JNIRcmLoader.load();
}
private RcmSmash(){}
public static native int smashLinux(final int bus_id, final int device_addr);
public static native int smashWindows();
public static boolean isSupported() { return supported; }
}

View file

@ -0,0 +1,316 @@
package nsusbloader.Utilities;
/*
* Implementation of the 'Fusée Gelée' RCM payload that is inspired by 'fusee-launcher' application by ktemkin.
* Definitely uses ideas and even some code.
* Check original project: https://github.com/reswitched/fusee-launcher
*
* This code is not political. It could be used by anyone.
* Find details in LICENSE file in the root directory of this project.
**/
import javafx.concurrent.Task;
import nsusbloader.COM.USB.UsbConnect;
import nsusbloader.COM.USB.UsbErrorCodes;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import org.usb4java.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;
public class RcmTask extends Task<Boolean> {
private enum ECurrentOS {
win, lin, mac, unsupported
}
private LogPrinter logPrinter;
private String filePath;
private DeviceHandle handler;
private byte[] fullPayload;
private static final byte[] initSeq = { (byte) 0x98, (byte) 0x02, (byte) 0x03 };
private static final byte[] mezzo = {
(byte) 0x5c, (byte) 0x00, (byte) 0x9f, (byte) 0xe5, (byte) 0x5c, (byte) 0x10, (byte) 0x9f, (byte) 0xe5, (byte) 0x5c, (byte) 0x20, (byte) 0x9f, (byte) 0xe5, (byte) 0x01, (byte) 0x20, (byte) 0x42, (byte) 0xe0,
(byte) 0x0e, (byte) 0x00, (byte) 0x00, (byte) 0xeb, (byte) 0x48, (byte) 0x00, (byte) 0x9f, (byte) 0xe5, (byte) 0x10, (byte) 0xff, (byte) 0x2f, (byte) 0xe1, (byte) 0x00, (byte) 0x00, (byte) 0xa0, (byte) 0xe1,
(byte) 0x48, (byte) 0x00, (byte) 0x9f, (byte) 0xe5, (byte) 0x48, (byte) 0x10, (byte) 0x9f, (byte) 0xe5, (byte) 0x01, (byte) 0x29, (byte) 0xa0, (byte) 0xe3, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0xeb,
(byte) 0x38, (byte) 0x00, (byte) 0x9f, (byte) 0xe5, (byte) 0x01, (byte) 0x19, (byte) 0xa0, (byte) 0xe3, (byte) 0x01, (byte) 0x00, (byte) 0x80, (byte) 0xe0, (byte) 0x34, (byte) 0x10, (byte) 0x9f, (byte) 0xe5,
(byte) 0x03, (byte) 0x28, (byte) 0xa0, (byte) 0xe3, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0xeb, (byte) 0x20, (byte) 0x00, (byte) 0x9f, (byte) 0xe5, (byte) 0x10, (byte) 0xff, (byte) 0x2f, (byte) 0xe1,
(byte) 0x04, (byte) 0x30, (byte) 0x91, (byte) 0xe4, (byte) 0x04, (byte) 0x30, (byte) 0x80, (byte) 0xe4, (byte) 0x04, (byte) 0x20, (byte) 0x52, (byte) 0xe2, (byte) 0xfb, (byte) 0xff, (byte) 0xff, (byte) 0x1a,
(byte) 0x1e, (byte) 0xff, (byte) 0x2f, (byte) 0xe1, (byte) 0x00, (byte) 0xf0, (byte) 0x00, (byte) 0x40, (byte) 0x20, (byte) 0x00, (byte) 0x01, (byte) 0x40, (byte) 0x7c, (byte) 0x00, (byte) 0x01, (byte) 0x40,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x40, (byte) 0x40, (byte) 0x0e, (byte) 0x01, (byte) 0x40, (byte) 0x00, (byte) 0x70, (byte) 0x01, (byte) 0x40
}; // 124 bytes
private static final byte[] sprayPttrn = { 0x00, 0x00, 0x01, 0x40};
public RcmTask(String filePath){
this.logPrinter = new LogPrinter(EModule.RCM);
this.filePath = filePath;
}
@Override
protected Boolean call() {
logPrinter.print("Selected: "+filePath, EMsgType.INFO);
logPrinter.print("=============== RCM ===============", EMsgType.INFO);
ECurrentOS ecurrentOS;
String realOsName = System.getProperty("os.name").toLowerCase().replace(" ", "");
if (realOsName.equals("macos") || realOsName.equals("macosx") || realOsName.equals("freebsd"))
ecurrentOS = ECurrentOS.mac;
else if (realOsName.contains("windows"))
ecurrentOS = ECurrentOS.win;
else if (realOsName.equals("linux"))
ecurrentOS = ECurrentOS.lin;
else
ecurrentOS = ECurrentOS.unsupported;
logPrinter.print("Found your OS: "+System.getProperty("os.name"), EMsgType.PASS);
if (! ecurrentOS.equals(ECurrentOS.mac)){
if (! RcmSmash.isSupported()){
logPrinter.print("Unfortunately your platform '"+System.getProperty("os.name")+
"' of '"+System.getProperty("os.arch")+"' is not supported :("+
"\n But you could file a bug with request."+
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
logPrinter.close();
return false;
}
}
if (preparePayload()){
logPrinter.close();
return false;
}
// === TEST THIS ===
// writeTestFile();
// =================
// Bring up USB connection
UsbConnect usbConnect = new UsbConnect(logPrinter, true);
if (! usbConnect.isConnected()){
logPrinter.close();
return false;
}
this.handler = usbConnect.getNsHandler();
// Get device ID and show it.
if (readUsbDeviceID()){
usbConnect.close();
logPrinter.close();
return false;
}
// Send payload
for (int i=0; i < fullPayload.length / 4096 ; i++){
if (writeUsb(Arrays.copyOfRange(fullPayload, i*4096, (i+1)*4096))){
logPrinter.print("Failed to sent payload ["+i+"]"+
"\n\n Execution stopped.", EMsgType.FAIL);
usbConnect.close();
logPrinter.close();
return false;
}
}
logPrinter.print("Information sent to NS.", EMsgType.PASS);
if (ecurrentOS.equals(ECurrentOS.mac)){
if (smashMacOS()){
usbConnect.close();
logPrinter.close();
return false;
}
}
else {
// JNI MAGIC HERE
int retval;
if (ecurrentOS.equals(ECurrentOS.lin))
retval = RcmSmash.smashLinux(usbConnect.getNsBus(), usbConnect.getNsAddress());
else if (ecurrentOS.equals(ECurrentOS.win))
retval = RcmSmash.smashWindows();
else {
// ( ?_?)
logPrinter.print("Failed to smash the stack since your OS is not supported. Please report this issue."+
"\n\n Execution stopped and failed. And it's strange.", EMsgType.FAIL);
usbConnect.close();
logPrinter.close();
return false;
}
if (retval != 0){
logPrinter.print("Failed to smash the stack ("+retval+")"+
"\n\n Execution stopped and failed.", EMsgType.FAIL);
usbConnect.close();
logPrinter.close();
return false;
}
logPrinter.print(".:: Payload complete ::.", EMsgType.PASS);
}
usbConnect.close();
logPrinter.close();
return true;
}
/**
* Prepare the 'big' or full-size byte-buffer that is actually is a payload that we're about to use.
* @return false for issues
* true for good result
* */
private boolean preparePayload(){
File pldrFile = new File(filePath);
// 126296 b <- biggest size per CTCaer; 16384 selected randomly as minimum threshold. It's probably wrong.
if (pldrFile.length() > 126296 || pldrFile.length() < 16384) {
logPrinter.print("File size of this payload looks wired. It's "+pldrFile.length()+" bytes."+
"\n 1. Double-check that you're using the right payload." +
"\n 2. Please report this issue in case you're sure that you're doing everything right." +
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
return true;
}
// Get payload file size
int pldFileSize = (int) pldrFile.length();
// Get full payload array size
int totalSize = 4328 + pldFileSize + 8640;
totalSize += 4096 - (totalSize % 4096);
if ((totalSize / 4096 % 2) == 0) // Flip buffer story to get 0x40009000 (hi) buf to always smash with 0x7000 (dec: 28672)
totalSize += 4096;
// Double-check
if (totalSize > 0x30298){
logPrinter.print("File size of the payload is too big. Comparing to maximum size, it's greater to "+(totalSize - 0x30298)+" bytes!"+
"\n 1. Double-check that you're using the right payload." +
"\n 2. Please report this issue in case you're sure that you're doing everything right." +
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL); // Occurs: never. I'm too lazy to check.
return true;
}
// Define holder of 'everything payload'
fullPayload = new byte[totalSize];
// Prepare array to store file payload.
byte[] dataPldFile = new byte[pldFileSize];
try{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pldrFile));
int readSize;
if ((readSize = bis.read(dataPldFile)) != pldFileSize){
logPrinter.print("Failed to retrieve data from payload file." +
"\n Got only "+readSize+" bytes while "+pldFileSize+" expected." +
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
bis.close();
return true;
}
bis.close();
}
catch (Exception e){
logPrinter.print("Failed to retrieve data from payload file: " +e.getMessage()+
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
return true;
}
// Trust me
System.arraycopy(initSeq, 0, fullPayload, 0, 3);
System.arraycopy(mezzo, 0, fullPayload, 680, 124);
System.arraycopy(dataPldFile, 0, fullPayload, 4328, 16384);
for (int i = 0; i < 2160; i++)
System.arraycopy(sprayPttrn, 0, fullPayload, 20712+i*4, 4);
System.arraycopy(dataPldFile, 16384, fullPayload, 29352, pldFileSize-16384);
return false;
}
/**
* Read device ID in the early beginning
* @return false if NO issues
* true if issues
* */
private boolean readUsbDeviceID(){
ByteBuffer readBuffer = ByteBuffer.allocateDirect(16);
IntBuffer readBufTransferred = IntBuffer.allocate(1);
int result = LibUsb.bulkTransfer(handler, (byte) 0x81, readBuffer, readBufTransferred, 1000);
if (result != LibUsb.SUCCESS) {
logPrinter.print("Unable to get device ID" +
"\n\n Nothing has been sent to NS. Execution stopped.", EMsgType.FAIL);
return true;
}
int trans = readBufTransferred.get();
byte[] receivedBytes = new byte[trans];
readBuffer.get(receivedBytes);
StringBuilder idStrBld = new StringBuilder("Found device with ID: ");
for (byte b: receivedBytes)
idStrBld.append(String.format("%02x ", b));
logPrinter.print(idStrBld.toString(), EMsgType.PASS);
return false;
}
/**
* Sending byte array to USB device
* @return 'false' if no issues
* 'true' if errors happened
* */
private boolean writeUsb(byte[] message){
ByteBuffer writeBuffer = ByteBuffer.allocateDirect(4096);
writeBuffer.put(message);
IntBuffer writeBufTransferred = IntBuffer.allocate(1);
int result = LibUsb.bulkTransfer(handler, (byte) 0x01, writeBuffer, writeBufTransferred, 5050);
if (result == LibUsb.SUCCESS) {
if (writeBufTransferred.get() == 4096)
return false;
logPrinter.print("RCM Data transfer issue [write]" +
"\n Requested: " + message.length +
"\n Transferred: " + writeBufTransferred.get()+
"\n\n Execution stopped.", EMsgType.FAIL);
return true;
}
logPrinter.print("RCM Data transfer issue [write]" +
"\n Returned: " + UsbErrorCodes.getErrCode(result) +
"\n\n Execution stopped.", EMsgType.FAIL);
return true;
}
/**
* MacOS version of RcmSmash class
* */
boolean smashMacOS(){
int result;
ByteBuffer writeBuffer = ByteBuffer.allocateDirect(28672); //writeBuffer.order() equals BIG_ENDIAN; 28672
result = LibUsb.controlTransfer(handler, (byte) 0x82, LibUsb.REQUEST_GET_STATUS, (short) 0, (short) 0, writeBuffer, 1000);
if (result < 0){
logPrinter.print("Failed to smash the stack ("+UsbErrorCodes.getErrCode(result)+")"+
"\n\n Execution stopped and failed.", EMsgType.FAIL);
return true;
}
logPrinter.print("Payload complete!", EMsgType.PASS);
return false;
}
//*****************************************************************************************************************/
/*
private void writeTestFile(){
try {
File testFile = new File("/tmp/dmTests.bin");
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(testFile)
);
bos.write(fullPayload);
bos.close();
}
catch (Exception e){ e.printStackTrace(); }
// ------------------ TEST THIS p.2 ----------------------
writeUsbTest(fullPayload);
}
private boolean writeUsbTest(byte[] message){
for (int i=0; i < message.length / 0x1000 ;i++){
try {
File testFile = new File(String.format("/tmp/cnk_%02d.bin", i));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(testFile)
);
bos.write(Arrays.copyOfRange(message, i*4096, (i+1)*4096));
bos.close();
}
catch (Exception e){ e.printStackTrace(); }
}
return false;
}
*/
}

View file

@ -0,0 +1,285 @@
package nsusbloader.Utilities;
import javafx.concurrent.Task;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import java.io.*;
import java.util.Arrays;
public class SplitMergeTool {
public static Task<Boolean> splitFile(String filePath, String saveToPath){
return new SplitTask(filePath, saveToPath);
};
public static Task<Boolean> mergeFile(String filePath, String saveToPath){
return new MergeTask(filePath, saveToPath);
}
}
class SplitTask extends Task<Boolean>{
private LogPrinter logPrinter;
private String saveToPath;
private String filePath;
SplitTask(String filePath, String saveToPath){
this.filePath = filePath;
this.saveToPath = saveToPath;
logPrinter = new LogPrinter(EModule.SPLIT_MERGE_TOOL);
}
@Override
protected Boolean call() {
File file = new File(filePath);
File folder = new File(saveToPath+File.separator+"!_"+file.getName());
logPrinter.print("Split file: "+filePath, EMsgType.INFO);
for (int i = 0; ; i++){
if (this.isCancelled()){
logPrinter.print("Split task interrupted!", EMsgType.PASS);
logPrinter.close();
return false;
}
if (! folder.mkdir()){
if (folder.exists()){
if (i >= 50){
logPrinter.print("Can't create new file.", EMsgType.FAIL);
logPrinter.close();
return false;
}
logPrinter.print("Trying to create a good new folder...", EMsgType.WARNING);
folder = new File(saveToPath+File.separator+"!_"+i+"_"+file.getName());
continue;
}
else { // folder not created and not exists - return
logPrinter.print("Folder "+folder.getAbsolutePath()+" could not be created. Not enough rights or something like that?", EMsgType.FAIL);
logPrinter.close();
return false;
}
}
logPrinter.print("Save results to: "+folder.getAbsolutePath(), EMsgType.INFO);
break;
}
try{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream fragmentBos;
long counter;
long originalFileLen = file.length();
double chunkPercent = (4194240.0 / (originalFileLen / 100.0) / 100.0);
long totalSizeCnt = 0;
byte[] chunk;
int readBytesCnt;
main_loop:
for (int i = 0; ; i++){
fragmentBos = new BufferedOutputStream(
new FileOutputStream(new File(folder.getAbsolutePath()+File.separator+String.format("%02d", i)))
);
counter = 0;
while (counter < 1024){ // 0xffff0000 total
if (this.isCancelled()){
fragmentBos.close();
bis.close();
boolean isDeleted = folder.delete();
File[] chArrToDel = folder.listFiles();
if (! isDeleted && chArrToDel != null){
isDeleted = true;
for (File chunkFile : chArrToDel)
isDeleted &= chunkFile.delete();
isDeleted &= folder.delete();
}
logPrinter.print("Split task interrupted and folder "+(isDeleted?"deleted.":"is not deleted."), EMsgType.PASS);
logPrinter.close();
return false;
}
chunk = new byte[4194240];
if ((readBytesCnt = bis.read(chunk)) < 4194240){
if (readBytesCnt > 0)
fragmentBos.write(chunk, 0, readBytesCnt);
fragmentBos.close();
logPrinter.updateProgress(1.0);
break main_loop;
}
fragmentBos.write(chunk);
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
counter++; // NOTE: here we have some redundancy of variables. It has to be fixed one day.
totalSizeCnt++;
}
fragmentBos.close();
}
bis.close();
//=============== let's check what we have ==============
logPrinter.print("Original file size: "+originalFileLen, EMsgType.INFO);
long totalChunksSize = 0;
File[] chunkFileArr = folder.listFiles();
if (chunkFileArr == null) {
logPrinter.print("Unable to check results. It means that something went wrong.", EMsgType.FAIL);
return false;
}
else {
Arrays.sort(chunkFileArr);
for (File chunkFile : chunkFileArr) {
logPrinter.print("Chunk " + chunkFile.getName() + " size: " + chunkFile.length(), EMsgType.INFO);
totalChunksSize += chunkFile.length();
}
logPrinter.print("Total chunks size: " + totalChunksSize, EMsgType.INFO);
if (originalFileLen != totalChunksSize)
logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL);
else
logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS);
}
}
catch (Exception e){
e.printStackTrace();
logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL);
}
logPrinter.print("Split task complete!", EMsgType.INFO);
logPrinter.close();
return true;
}
}
class MergeTask extends Task<Boolean> {
private LogPrinter logPrinter;
private String saveToPath;
private String filePath;
MergeTask(String filePath, String saveToPath) {
this.filePath = filePath;
this.saveToPath = saveToPath;
logPrinter = new LogPrinter(EModule.SPLIT_MERGE_TOOL);
}
@Override
protected Boolean call() {
logPrinter.print("Merge file: "+filePath, EMsgType.INFO);
File folder = new File(filePath);
long cnkTotalSize = 0;
File[] chunkFiles = folder.listFiles((file, s) -> s.matches("^[0-9][0-9]$"));
if (chunkFiles == null || chunkFiles.length == 0){
logPrinter.print("Selected folder doesn't have any chunks. Nothing to do here.", EMsgType.FAIL);
logPrinter.close();
return false;
}
Arrays.sort(chunkFiles);
logPrinter.print("Next files will be merged in following order: ", EMsgType.INFO);
for (File cnk : chunkFiles){
logPrinter.print(" "+cnk.getName(), EMsgType.INFO);
cnkTotalSize += cnk.length();
}
double chunkPercent = (4194240.0 / (cnkTotalSize / 100.0) / 100.0);
long totalSizeCnt = 0;
File resultFile = new File(saveToPath+File.separator+"!_"+folder.getName());
//*******
for (int i = 0; ; i++){
if (this.isCancelled()){
logPrinter.print("Split task interrupted!", EMsgType.PASS);
logPrinter.close();
return false;
}
if (resultFile.exists()){
if (i >= 50){
logPrinter.print("Can't create new file.", EMsgType.FAIL);
logPrinter.close();
return false;
}
logPrinter.print("Trying to create a good new file...", EMsgType.WARNING);
resultFile = new File(saveToPath+File.separator+"!_"+i+"_"+folder.getName());
continue;
}
logPrinter.print("Save results to: "+resultFile.getAbsolutePath(), EMsgType.INFO);
break;
}
//*******
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(resultFile));
BufferedInputStream bis;
byte[] chunk;
int readBytesCnt;
for (File cnk : chunkFiles){
bis = new BufferedInputStream(new FileInputStream(cnk));
while (true){
if (this.isCancelled()){
bos.close();
bis.close();
boolean isDeleted = resultFile.delete();
logPrinter.print("Split task interrupted and file "+(isDeleted?"deleted.":"is not deleted."), EMsgType.PASS);
logPrinter.close();
return false;
}
chunk = new byte[4194240];
readBytesCnt = bis.read(chunk);
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
totalSizeCnt++;
if (readBytesCnt < 4194240){
if (readBytesCnt > 0)
bos.write(chunk, 0, readBytesCnt);
break;
}
bos.write(chunk);
}
bis.close();
}
bos.close();
//=============== let's check what we have ==============
long resultFileSize = resultFile.length();
logPrinter.print("Total chunks size: " + cnkTotalSize, EMsgType.INFO);
logPrinter.print("Merged file size: " + resultFileSize, EMsgType.INFO);
if (cnkTotalSize != resultFileSize){
logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL);
return false;
}
logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS);
}
catch (Exception e){
e.printStackTrace();
logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL);
}
logPrinter.print("Merge task complete!", EMsgType.INFO);
logPrinter.close();
return true;
}
}

View file

@ -4,6 +4,7 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.AnchorPane?>
@ -13,8 +14,9 @@
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.SVGPath?>
<AnchorPane xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.FrontController">
<AnchorPane fx:id="usbNetPane" onDragDropped="#handleDrop" onDragOver="#handleDragOver" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.FrontController">
<children>
<VBox layoutX="10.0" layoutY="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
@ -38,13 +40,40 @@
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Pane fx:id="specialPane" GridPane.columnIndex="1" />
<Separator prefWidth="200.0" styleClass="strangeSeparator" GridPane.columnIndex="1" />
</children>
<VBox.margin>
<Insets bottom="2.0" />
</VBox.margin>
</GridPane>
<fx:include fx:id="tableFilesList" source="TableView.fxml" VBox.vgrow="ALWAYS" />
<HBox alignment="TOP_CENTER" spacing="3.0" VBox.vgrow="NEVER">
<children>
<Button fx:id="selectNspBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_OpenFile">
<HBox.margin>
<Insets />
</HBox.margin>
<graphic>
<SVGPath content="M 8,0 C 6.8954305,0 6,0.8954305 6,2 v 16 c 0,1.1 0.89,2 2,2 h 12 c 1.104569,0 2,-0.895431 2,-2 V 2 C 22,0.90484721 21.089844,0 20,0 Z m 2.1,1.2 h 7.8 C 18,1.20208 18,1.2002604 18,1.3 v 0.1 c 0,0.095833 0,0.097917 -0.1,0.1 H 10.1 C 10,1.5057292 10,1.5036458 10,1.4 V 1.3 C 10,1.20026 10,1.1981771 10.1,1.2 Z M 8,2 h 12 c 0.303385,0 0.5,0.2044271 0.5,0.5 v 12 C 20.5,14.789959 20.29836,15 20,15 H 8 C 7.7044271,15 7.5,14.803385 7.5,14.5 V 2.5 C 7.5,2.2083333 7.7122396,2 8,2 Z M 2,4 v 18 c 0,1.104569 0.8954305,2 2,2 H 20 V 22 H 4 V 4 Z m 8,12 h 8 l -4,3 z" fill="#289de8" />
</graphic>
</Button>
<Button fx:id="selectSplitNspBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_OpenSplitFile">
<graphic>
<SVGPath content="M 2.4003906 2 C 1.0683906 2 0 3.1125 0 4.5 L 0 19.5 A 2.4 2.5 0 0 0 2.4003906 22 L 21.599609 22 A 2.4 2.5 0 0 0 24 19.5 L 24 7 C 24 5.6125 22.919609 4.5 21.599609 4.5 L 12 4.5 L 9.5996094 2 L 2.4003906 2 z M 13.193359 10.962891 C 14.113498 10.962891 14.814236 11.348741 15.296875 12.123047 C 15.779514 12.89388 16.021484 13.935113 16.021484 15.244141 C 16.021484 16.556641 15.779514 17.598741 15.296875 18.373047 C 14.814236 19.14388 14.113498 19.529297 13.193359 19.529297 C 12.276693 19.529297 11.575955 19.14388 11.089844 18.373047 C 10.607205 17.598741 10.365234 16.556641 10.365234 15.244141 C 10.365234 13.935113 10.607205 12.89388 11.089844 12.123047 C 11.575955 11.348741 12.276693 10.962891 13.193359 10.962891 z M 19.589844 10.962891 C 20.509983 10.962891 21.21072 11.348741 21.693359 12.123047 C 22.175998 12.89388 22.417969 13.935113 22.417969 15.244141 C 22.417969 16.556641 22.175998 17.598741 21.693359 18.373047 C 21.21072 19.14388 20.509983 19.529297 19.589844 19.529297 C 18.673177 19.529297 17.970486 19.14388 17.484375 18.373047 C 17.001736 17.598741 16.761719 16.556641 16.761719 15.244141 C 16.761719 13.935113 17.001736 12.89388 17.484375 12.123047 C 17.970486 11.348741 18.673177 10.962891 19.589844 10.962891 z M 13.193359 11.769531 C 12.613498 11.769531 12.173177 12.092448 11.871094 12.738281 C 11.56901 13.380642 11.417969 14.195964 11.417969 15.185547 C 11.417969 15.411241 11.423611 15.655599 11.4375 15.916016 C 11.451389 16.176432 11.511068 16.528212 11.615234 16.972656 L 14.412109 12.591797 C 14.235026 12.26888 14.042318 12.052517 13.833984 11.941406 C 13.629123 11.826823 13.415582 11.769531 13.193359 11.769531 z M 19.589844 11.769531 C 19.009983 11.769531 18.567708 12.092448 18.265625 12.738281 C 17.963542 13.380642 17.8125 14.195964 17.8125 15.185547 C 17.8125 15.411241 17.820095 15.655599 17.833984 15.916016 C 17.847873 16.176432 17.907552 16.528212 18.011719 16.972656 L 20.808594 12.591797 C 20.63151 12.26888 20.438802 12.052517 20.230469 11.941406 C 20.025608 11.826823 19.812066 11.769531 19.589844 11.769531 z M 14.761719 13.556641 L 11.984375 17.962891 C 12.133681 18.216363 12.305556 18.406684 12.5 18.535156 C 12.694444 18.660156 12.91276 18.722656 13.152344 18.722656 C 13.812066 18.722656 14.280816 18.355252 14.558594 17.619141 C 14.836372 16.879557 14.974609 16.059462 14.974609 15.160156 C 14.974609 14.604601 14.90408 14.07053 14.761719 13.556641 z M 21.15625 13.556641 L 18.380859 17.962891 C 18.530165 18.216363 18.70204 18.406684 18.896484 18.535156 C 19.090929 18.660156 19.307292 18.722656 19.546875 18.722656 C 20.206597 18.722656 20.675347 18.355252 20.953125 17.619141 C 21.230903 16.879557 21.371094 16.059462 21.371094 15.160156 C 21.371094 14.604601 21.298611 14.07053 21.15625 13.556641 z" fill="#289de8" />
</graphic></Button>
<Pane HBox.hgrow="ALWAYS" />
<Button fx:id="uploadStopBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_Upload">
<HBox.margin>
<Insets />
</HBox.margin>
</Button>
</children>
<VBox.margin>
<Insets left="5.0" right="5.0" top="5.0" />
</VBox.margin>
</HBox>
</children>
</VBox>
</children>

View file

@ -1,18 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.SVGPath?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onDragDropped="#handleDrop" onDragOver="#handleDragOver" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NSLMainController">
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NSLMainController">
<children>
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
@ -26,6 +23,24 @@
<SVGPath content="M21,19V17H8V19H21M21,13V11H8V13H21M8,7H21V5H8V7M4,5V7H6V5H4M3,5A1,1 0 0,1 4,4H6A1,1 0 0,1 7,5V7A1,1 0 0,1 6,8H4A1,1 0 0,1 3,7V5M4,11V13H6V11H4M3,11A1,1 0 0,1 4,10H6A1,1 0 0,1 7,11V13A1,1 0 0,1 6,14H4A1,1 0 0,1 3,13V11M4,17V19H6V17H4M3,17A1,1 0 0,1 4,16H6A1,1 0 0,1 7,17V19A1,1 0 0,1 6,20H4A1,1 0 0,1 3,19V17Z" />
</graphic>
</Tab>
<Tab closable="false">
<content>
<fx:include fx:id="RcmTab" source="RcmTab.fxml" VBox.vgrow="ALWAYS" />
</content>
<graphic>
<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>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<fx:include fx:id="SplitMergeTab" source="SplitMergeTab.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" VBox.vgrow="ALWAYS" />
</AnchorPane>
</content>
<graphic>
<SVGPath content="M 2.4003906 2 C 1.0683906 2 2.9605947e-16 3.1125 0 4.5 L 0 19.5 A 2.4 2.5 0 0 0 2.4003906 22 L 21.599609 22 A 2.4 2.5 0 0 0 24 19.5 L 24 7 C 24 5.6125 22.919609 4.5 21.599609 4.5 L 12 4.5 L 9.5996094 2 L 2.4003906 2 z M 9 5 L 13 8.5 L 9 12 L 9 10 L 6 10 L 6 7 L 9 7 L 9 5 z M 5 9 L 5 11 L 8 11 L 8 14 L 5 14 L 5 16 L 1 12.5 L 5 9 z M 13.193359 10.962891 C 14.113498 10.962891 14.814236 11.348741 15.296875 12.123047 C 15.779514 12.89388 16.021484 13.935113 16.021484 15.244141 C 16.021484 16.556641 15.779514 17.598741 15.296875 18.373047 C 14.814236 19.14388 14.113498 19.529297 13.193359 19.529297 C 12.276693 19.529297 11.575955 19.14388 11.089844 18.373047 C 10.607205 17.598741 10.365234 16.556641 10.365234 15.244141 C 10.365234 13.935113 10.607205 12.89388 11.089844 12.123047 C 11.575955 11.348741 12.276693 10.962891 13.193359 10.962891 z M 19.589844 10.962891 C 20.509983 10.962891 21.21072 11.348741 21.693359 12.123047 C 22.175998 12.89388 22.417969 13.935113 22.417969 15.244141 C 22.417969 16.556641 22.175998 17.598741 21.693359 18.373047 C 21.21072 19.14388 20.509983 19.529297 19.589844 19.529297 C 18.673177 19.529297 17.970486 19.14388 17.484375 18.373047 C 17.001736 17.598741 16.761719 16.556641 16.761719 15.244141 C 16.761719 13.935113 17.001736 12.89388 17.484375 12.123047 C 17.970486 11.348741 18.673177 10.962891 19.589844 10.962891 z M 13.193359 11.769531 C 12.613498 11.769531 12.173177 12.092448 11.871094 12.738281 C 11.56901 13.380642 11.417969 14.195964 11.417969 15.185547 C 11.417969 15.411241 11.423611 15.655599 11.4375 15.916016 C 11.451389 16.176432 11.511068 16.528212 11.615234 16.972656 L 14.412109 12.591797 C 14.235026 12.26888 14.042318 12.052517 13.833984 11.941406 C 13.629123 11.826823 13.415582 11.769531 13.193359 11.769531 z M 19.589844 11.769531 C 19.009983 11.769531 18.567708 12.092448 18.265625 12.738281 C 17.963542 13.380642 17.8125 14.195964 17.8125 15.185547 C 17.8125 15.411241 17.820095 15.655599 17.833984 15.916016 C 17.847873 16.176432 17.907552 16.528212 18.011719 16.972656 L 20.808594 12.591797 C 20.63151 12.26888 20.438802 12.052517 20.230469 11.941406 C 20.025608 11.826823 19.812066 11.769531 19.589844 11.769531 z M 14.761719 13.556641 L 11.984375 17.962891 C 12.133681 18.216363 12.305556 18.406684 12.5 18.535156 C 12.694444 18.660156 12.91276 18.722656 13.152344 18.722656 C 13.812066 18.722656 14.280816 18.355252 14.558594 17.619141 C 14.836372 16.879557 14.974609 16.059462 14.974609 15.160156 C 14.974609 14.604601 14.90408 14.07053 14.761719 13.556641 z M 21.15625 13.556641 L 18.380859 17.962891 C 18.530165 18.216363 18.70204 18.406684 18.896484 18.535156 C 19.090929 18.660156 19.307292 18.722656 19.546875 18.722656 C 20.206597 18.722656 20.675347 18.355252 20.953125 17.619141 C 21.230903 16.879557 21.371094 16.059462 21.371094 15.160156 C 21.371094 14.604601 21.298611 14.07053 21.15625 13.556641 z" />
</graphic>
</Tab>
<Tab closable="false">
<content>
<fx:include fx:id="SettingsTab" source="SettingsTab.fxml" VBox.vgrow="ALWAYS" />
@ -54,34 +69,9 @@
</TabPane>
<ProgressBar fx:id="progressBar" prefWidth="Infinity" progress="0.0">
<VBox.margin>
<Insets left="5.0" right="5.0" top="2.0" />
<Insets bottom="2.0" left="5.0" right="5.0" top="2.0" />
</VBox.margin>
</ProgressBar>
<HBox alignment="TOP_CENTER" spacing="3.0" VBox.vgrow="NEVER">
<children>
<Button fx:id="selectNspBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_OpenFile">
<HBox.margin>
<Insets />
</HBox.margin>
<graphic>
<SVGPath content="M 8,0 C 6.8954305,0 6,0.8954305 6,2 v 16 c 0,1.1 0.89,2 2,2 h 12 c 1.104569,0 2,-0.895431 2,-2 V 2 C 22,0.90484721 21.089844,0 20,0 Z m 2.1,1.2 h 7.8 C 18,1.20208 18,1.2002604 18,1.3 v 0.1 c 0,0.095833 0,0.097917 -0.1,0.1 H 10.1 C 10,1.5057292 10,1.5036458 10,1.4 V 1.3 C 10,1.20026 10,1.1981771 10.1,1.2 Z M 8,2 h 12 c 0.303385,0 0.5,0.2044271 0.5,0.5 v 12 C 20.5,14.789959 20.29836,15 20,15 H 8 C 7.7044271,15 7.5,14.803385 7.5,14.5 V 2.5 C 7.5,2.2083333 7.7122396,2 8,2 Z M 2,4 v 18 c 0,1.104569 0.8954305,2 2,2 H 20 V 22 H 4 V 4 Z m 8,12 h 8 l -4,3 z" fill="#289de8" />
</graphic>
</Button>
<Button fx:id="selectSplitNspBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_OpenSplitFile">
<graphic>
<SVGPath content="M 2.4003906 2 C 1.0683906 2 0 3.1125 0 4.5 L 0 19.5 A 2.4 2.5 0 0 0 2.4003906 22 L 21.599609 22 A 2.4 2.5 0 0 0 24 19.5 L 24 7 C 24 5.6125 22.919609 4.5 21.599609 4.5 L 12 4.5 L 9.5996094 2 L 2.4003906 2 z M 13.193359 10.962891 C 14.113498 10.962891 14.814236 11.348741 15.296875 12.123047 C 15.779514 12.89388 16.021484 13.935113 16.021484 15.244141 C 16.021484 16.556641 15.779514 17.598741 15.296875 18.373047 C 14.814236 19.14388 14.113498 19.529297 13.193359 19.529297 C 12.276693 19.529297 11.575955 19.14388 11.089844 18.373047 C 10.607205 17.598741 10.365234 16.556641 10.365234 15.244141 C 10.365234 13.935113 10.607205 12.89388 11.089844 12.123047 C 11.575955 11.348741 12.276693 10.962891 13.193359 10.962891 z M 19.589844 10.962891 C 20.509983 10.962891 21.21072 11.348741 21.693359 12.123047 C 22.175998 12.89388 22.417969 13.935113 22.417969 15.244141 C 22.417969 16.556641 22.175998 17.598741 21.693359 18.373047 C 21.21072 19.14388 20.509983 19.529297 19.589844 19.529297 C 18.673177 19.529297 17.970486 19.14388 17.484375 18.373047 C 17.001736 17.598741 16.761719 16.556641 16.761719 15.244141 C 16.761719 13.935113 17.001736 12.89388 17.484375 12.123047 C 17.970486 11.348741 18.673177 10.962891 19.589844 10.962891 z M 13.193359 11.769531 C 12.613498 11.769531 12.173177 12.092448 11.871094 12.738281 C 11.56901 13.380642 11.417969 14.195964 11.417969 15.185547 C 11.417969 15.411241 11.423611 15.655599 11.4375 15.916016 C 11.451389 16.176432 11.511068 16.528212 11.615234 16.972656 L 14.412109 12.591797 C 14.235026 12.26888 14.042318 12.052517 13.833984 11.941406 C 13.629123 11.826823 13.415582 11.769531 13.193359 11.769531 z M 19.589844 11.769531 C 19.009983 11.769531 18.567708 12.092448 18.265625 12.738281 C 17.963542 13.380642 17.8125 14.195964 17.8125 15.185547 C 17.8125 15.411241 17.820095 15.655599 17.833984 15.916016 C 17.847873 16.176432 17.907552 16.528212 18.011719 16.972656 L 20.808594 12.591797 C 20.63151 12.26888 20.438802 12.052517 20.230469 11.941406 C 20.025608 11.826823 19.812066 11.769531 19.589844 11.769531 z M 14.761719 13.556641 L 11.984375 17.962891 C 12.133681 18.216363 12.305556 18.406684 12.5 18.535156 C 12.694444 18.660156 12.91276 18.722656 13.152344 18.722656 C 13.812066 18.722656 14.280816 18.355252 14.558594 17.619141 C 14.836372 16.879557 14.974609 16.059462 14.974609 15.160156 C 14.974609 14.604601 14.90408 14.07053 14.761719 13.556641 z M 21.15625 13.556641 L 18.380859 17.962891 C 18.530165 18.216363 18.70204 18.406684 18.896484 18.535156 C 19.090929 18.660156 19.307292 18.722656 19.546875 18.722656 C 20.206597 18.722656 20.675347 18.355252 20.953125 17.619141 C 21.230903 16.879557 21.371094 16.059462 21.371094 15.160156 C 21.371094 14.604601 21.298611 14.07053 21.15625 13.556641 z" fill="#289de8" />
</graphic></Button>
<Pane HBox.hgrow="ALWAYS" />
<Button fx:id="uploadStopBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_Upload">
<HBox.margin>
<Insets />
</HBox.margin>
</Button>
</children>
<VBox.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="2.0" />
</VBox.margin>
</HBox>
</children>
</VBox>
</children>

View file

@ -0,0 +1,218 @@
<?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.RadioButton?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.ToggleGroup?>
<?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?>
<ScrollPane fitToWidth="true" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.RcmController">
<VBox fx:id="rcmToolPane" spacing="15.0">
<Pane minHeight="-Infinity" prefHeight="10.0" style="-fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #ff1515 40%, transparent 45%);" />
<HBox alignment="CENTER">
<children>
<Label text="Fusée Gelée RCM">
<font>
<Font name="System Bold" size="15.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>
<VBox spacing="8.0">
<children>
<Label text="Payload: " />
<HBox fx:id="plHbox1" alignment="CENTER_LEFT" onDragDropped="#handleDrop" onDragOver="#handleDragOver" spacing="5.0">
<children>
<RadioButton fx:id="pldrRadio1" mnemonicParsing="false">
<toggleGroup>
<ToggleGroup fx:id="rcmToggleGrp" />
</toggleGroup></RadioButton>
<VBox fx:id="pldPane1" onMouseClicked="#selectPldrPane" HBox.hgrow="ALWAYS">
<children>
<HBox>
<children>
<Label fx:id="payloadFNameLbl1" />
</children>
</HBox>
<Label fx:id="payloadFPathLbl1" disable="true">
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children>
</VBox>
<Button fx:id="selPldBtn1" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
<graphic>
<SVGPath content="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" fill="#289de8" />
</graphic></Button>
<Button fx:id="resPldBtn1" mnemonicParsing="false" onAction="#bntResetPayloader" styleClass="buttonStop">
<graphic>
<SVGPath content="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" fill="#fb582c" />
</graphic>
</Button>
</children>
</HBox>
<Separator prefWidth="200.0" />
<HBox fx:id="plHbox2" alignment="CENTER_LEFT" onDragDropped="#handleDrop" onDragOver="#handleDragOver" spacing="5.0">
<children>
<RadioButton fx:id="pldrRadio2" mnemonicParsing="false" toggleGroup="$rcmToggleGrp" />
<VBox fx:id="pldPane2" onMouseClicked="#selectPldrPane" HBox.hgrow="ALWAYS">
<children>
<HBox>
<children>
<Label fx:id="payloadFNameLbl2" />
</children>
</HBox>
<Label fx:id="payloadFPathLbl2" disable="true">
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children>
</VBox>
<Button fx:id="selPldBtn2" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
<graphic>
<SVGPath content="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" fill="#289de8" />
</graphic></Button>
<Button fx:id="resPldBtn2" mnemonicParsing="false" onAction="#bntResetPayloader" styleClass="buttonStop">
<graphic>
<SVGPath content="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" fill="#fb582c" />
</graphic>
</Button>
</children>
</HBox>
<Separator prefWidth="200.0" />
<HBox fx:id="plHbox3" alignment="CENTER_LEFT" onDragDropped="#handleDrop" onDragOver="#handleDragOver" spacing="5.0">
<children>
<RadioButton fx:id="pldrRadio3" mnemonicParsing="false" toggleGroup="$rcmToggleGrp" />
<VBox fx:id="pldPane3" onMouseClicked="#selectPldrPane" HBox.hgrow="ALWAYS">
<children>
<HBox>
<children>
<Label fx:id="payloadFNameLbl3" />
</children>
</HBox>
<Label fx:id="payloadFPathLbl3" disable="true">
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children>
</VBox>
<Button fx:id="selPldBtn3" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
<graphic>
<SVGPath content="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" fill="#289de8" />
</graphic></Button>
<Button fx:id="resPldBtn3" mnemonicParsing="false" onAction="#bntResetPayloader" styleClass="buttonStop">
<graphic>
<SVGPath content="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" fill="#fb582c" />
</graphic>
</Button>
</children>
</HBox>
<Separator prefWidth="200.0" />
<HBox fx:id="plHbox4" alignment="CENTER_LEFT" onDragDropped="#handleDrop" onDragOver="#handleDragOver" spacing="5.0">
<children>
<RadioButton fx:id="pldrRadio4" mnemonicParsing="false" toggleGroup="$rcmToggleGrp" />
<VBox fx:id="pldPane4" onMouseClicked="#selectPldrPane" HBox.hgrow="ALWAYS">
<children>
<HBox>
<children>
<Label fx:id="payloadFNameLbl4" />
</children>
</HBox>
<Label fx:id="payloadFPathLbl4" disable="true">
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children>
</VBox>
<Button fx:id="selPldBtn4" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
<graphic>
<SVGPath content="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" fill="#289de8" />
</graphic></Button>
<Button fx:id="resPldBtn4" mnemonicParsing="false" onAction="#bntResetPayloader" styleClass="buttonStop">
<graphic>
<SVGPath content="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" fill="#fb582c" />
</graphic>
</Button>
</children>
</HBox>
<Separator prefWidth="200.0" />
<HBox fx:id="plHbox5" alignment="CENTER_LEFT" onDragDropped="#handleDrop" onDragOver="#handleDragOver" spacing="5.0">
<children>
<RadioButton fx:id="pldrRadio5" mnemonicParsing="false" toggleGroup="$rcmToggleGrp" />
<VBox fx:id="pldPane5" onMouseClicked="#selectPldrPane" HBox.hgrow="ALWAYS">
<children>
<HBox>
<children>
<Label fx:id="payloadFNameLbl5" />
</children>
</HBox>
<Label fx:id="payloadFPathLbl5" disable="true">
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children>
</VBox>
<Button fx:id="selPldBtn5" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
<graphic>
<SVGPath content="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" fill="#289de8" />
</graphic></Button>
<Button fx:id="resPldBtn5" mnemonicParsing="false" onAction="#bntResetPayloader" styleClass="buttonStop">
<graphic>
<SVGPath content="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" fill="#fb582c" />
</graphic>
</Button>
</children>
</HBox>
<Separator prefWidth="200.0" />
</children>
<VBox.margin>
<Insets left="15.0" right="15.0" />
</VBox.margin>
</VBox>
<HBox alignment="CENTER">
<children>
<Label fx:id="statusLbl" />
</children>
</HBox>
<Pane VBox.vgrow="ALWAYS" />
<HBox alignment="CENTER">
<children>
<Button fx:id="injectPldBtn" contentDisplay="TOP" mnemonicParsing="false" styleClass="buttonUp" text="%btn_InjectPayloader">
<graphic>
<SVGPath content="M 1 1 L 1 13.5 L 21 13.5 L 21 1 L 1 1 z M 26.226562 1.0683594 L 22 5.2949219 L 26.226562 9.5214844 L 27.226562 8.5214844 L 24.697266 6 L 31.158203 6 L 31.158203 20 L 32.566406 20 L 32.566406 4.5917969 L 24.697266 4.5917969 L 27.226562 2.0683594 L 26.226562 1.0683594 z M 2.515625 2.25 L 12.984375 2.25 C 12.993075 2.25 13 2.256995 13 2.265625 L 13 3.984375 C 12.999995 3.993026 12.993031 4 12.984375 4 L 2.515625 4 C 2.5069687 4 2.5 3.993031 2.5 3.984375 L 2.5 2.265625 C 2.5 2.256925 2.50697 2.25 2.515625 2.25 z M 2.515625 5.25 L 17.962891 5.25 C 17.971591 5.25 17.978516 5.256995 17.978516 5.265625 L 17.978516 6.984375 C 17.978516 6.993075 17.971521 7 17.962891 7 L 2.515625 7 C 2.5069687 6.99999 2.5 6.993031 2.5 6.984375 L 2.5 5.265625 C 2.5 5.256925 2.50697 5.25 2.515625 5.25 z M 2.515625 8.25 L 15.421875 8.25 C 15.430575 8.25 15.4375 8.256995 15.4375 8.265625 L 15.4375 9.984375 C 15.4375 9.993075 15.430505 10 15.421875 10 L 2.515625 10 C 2.5069687 9.99999 2.5 9.993031 2.5 9.984375 L 2.5 8.265625 C 2.5 8.256969 2.5069687 8.25 2.515625 8.25 z M 1 14.5 L 1 18 C 1 20 2 21 4 21 L 18 21 C 20 21 21 20 21 18 L 21 14.5 L 1 14.5 z M 5.8515625 16.001953 A 1.8950667 1.8950667 0 0 1 7.7480469 17.898438 A 1.8950667 1.8950667 0 0 1 5.8515625 19.792969 A 1.8950667 1.8950667 0 0 1 3.9570312 17.898438 A 1.8950667 1.8950667 0 0 1 5.8515625 16.001953 z" fill="#71e016" />
</graphic></Button>
</children>
</HBox>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>
</ScrollPane>

View file

@ -127,7 +127,7 @@
</VBox>
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
<Insets bottom="5.0" left="15.0" right="15.0" top="5.0" />
</padding>
</VBox>
</ScrollPane>

View file

@ -0,0 +1,107 @@
<?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.RadioButton?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.ToggleGroup?>
<?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.text.Font?>
<VBox fx:id="smToolPane" onDragDropped="#handleDrop" onDragOver="#handleDragOver" spacing="20.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.SplitMergeController">
<VBox spacing="15.0">
<children>
<Pane minHeight="-Infinity" prefHeight="10.0" style="-fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #00c8fc 40%, transparent 45%);" />
<HBox alignment="CENTER">
<children>
<Label text="%tabSplMrg_Lbl_SplitNMergeTitle">
<font>
<Font name="System Bold" size="15.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>
</children>
</VBox>
<VBox fillWidth="false" spacing="5.0">
<children>
<RadioButton fx:id="splitRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Split">
<toggleGroup>
<ToggleGroup fx:id="splitMergeTogGrp" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="mergeRad" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_RadioBtn_Merge" toggleGroup="$splitMergeTogGrp" />
</children>
<VBox.margin>
<Insets left="15.0" right="15.0" />
</VBox.margin>
</VBox>
<VBox spacing="5.0">
<children>
<HBox>
<children>
<Label fx:id="fileFolderLabelLbl" />
<Label fx:id="fileFolderActualPathLbl" />
</children>
</HBox>
<Button fx:id="selectFileFolderBtn" contentDisplay="TOP" mnemonicParsing="false" />
</children>
<VBox.margin>
<Insets left="15.0" right="15.0" />
</VBox.margin>
</VBox>
<VBox spacing="5.0">
<children>
<HBox>
<children>
<Label text="%tabSplMrg_Lbl_SaveToLocation" />
<Label fx:id="saveToPathLbl" />
</children>
</HBox>
<Button fx:id="changeSaveToBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_ChangeSaveToLocation" />
</children>
<VBox.margin>
<Insets left="15.0" right="15.0" />
</VBox.margin>
</VBox>
<HBox alignment="CENTER">
<children>
<Label fx:id="statusLbl" />
</children>
<VBox.margin>
<Insets left="15.0" right="15.0" />
</VBox.margin>
</HBox>
<Pane VBox.vgrow="ALWAYS" />
<VBox>
<children>
<HBox alignment="CENTER">
<children>
<Button fx:id="convertBtn" contentDisplay="TOP" mnemonicParsing="false" styleClass="buttonUp" text="%tabSplMrg_Btn_Convert" />
</children>
</HBox>
</children>
</VBox>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>

View file

@ -39,10 +39,26 @@ windowTitleNewVersionUnknown=Unable to check for new versions
windowBodyNewVersionUnknown=Something went wrong\nMaybe internet unavailable, or GitHub is down
windowBodyNewVersionNOTAval=You're using the latest version
tab2_Cb_AllowXciNszXcz=Allow XCI / NSZ / XCZ files selection for Tinfoil
tab2_Lbl_AllowXciNszXczDesc=Used by applications that support XCI/NSZ/XCZ and utilizes Tinfoil transfer protocol. Don't change if not sure.
tab2_Lbl_AllowXciNszXczDesc=Used by applications that support XCI/NSZ/XCZ and utilizes Tinfoil transfer protocol. Don't change if not sure. Enable for Awoo Installer.
tab2_Lbl_Language=Language
windowBodyRestartToApplyLang=Please restart application to apply changes.
tab2_Cb_GLshowNspOnly=Show only *.nsp in GoldLeaf.
tab2_Cb_UseOldGlVersion=Use old GoldLeaf version
btn_OpenSplitFile=Select split NSP
tab2_Lbl_ApplicationSettings=Main settings
tabSplMrg_Lbl_SplitNMergeTitle=Split & merge files tool
tabSplMrg_RadioBtn_Split=Split
tabSplMrg_RadioBtn_Merge=Merge
tabSplMrg_Txt_File=File:
tabSplMrg_Txt_Folder=Split file (folder):
tabSplMrg_Btn_SelectFile=Select File
tabSplMrg_Btn_SelectFolder=Select Folder
tabSplMrg_Lbl_SaveToLocation=Save to:
tabSplMrg_Btn_ChangeSaveToLocation=Change
tabSplMrg_Btn_Convert=Convert
windowTitleError=Error
windowBodyPleaseFinishTransfersFirst=Unable to split/merge files when application USB/Network process active. Please interrupt active transfers first.
done_txt=Done!
failure_txt=Failed
btn_Select=Select
btn_InjectPayloader=Inject payload

View file

@ -39,11 +39,27 @@ windowTitleNewVersionUnknown=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u0
windowBodyNewVersionNOTAval=\u0412\u044B \u0443\u0436\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0435 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044E\u044E \u0432\u0435\u0440\u0441\u0438\u044E
windowBodyNewVersionUnknown=\u0427\u0442\u043E-\u0442\u043E \u043F\u043E\u0448\u043B\u043E \u043D\u0435 \u0442\u0430\u043A.\n\u041C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043D\u0435\u0442 \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442\u0430 \u0438\u043B\u0438 GitHub \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D.
tab2_Cb_AllowXciNszXcz=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044C \u0432\u044B\u0431\u043E\u0440 XCI, NSZ \u0438 XCZ \u0444\u0430\u0439\u043B\u043E\u0432 \u0434\u043B\u044F Tinfoil
tab2_Lbl_AllowXciNszXczDesc=\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F\u043C\u0438, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442 XCI, NSZ, XCZ \u0438 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044E\u0442 \u043F\u0440\u043E\u0442\u043E\u043A\u043E\u043B \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 Tinfoil. \u041D\u0435 \u043C\u0435\u043D\u044F\u0439\u0442\u0435 \u0435\u0441\u043B\u0438 \u043D\u0435 \u0443\u0432\u0435\u0440\u0435\u043D\u044B.
tab2_Lbl_AllowXciNszXczDesc=\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F\u043C\u0438, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442 XCI, NSZ, XCZ \u0438 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044E\u0442 \u043F\u0440\u043E\u0442\u043E\u043A\u043E\u043B \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 Tinfoil. \u041D\u0435 \u043C\u0435\u043D\u044F\u0439\u0442\u0435 \u0435\u0441\u043B\u0438 \u043D\u0435 \u0443\u0432\u0435\u0440\u0435\u043D\u044B. \u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u043F\u0440\u0438 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0438 Awoo Installer.
tab2_Lbl_Language=\u042F\u0437\u044B\u043A
windowBodyRestartToApplyLang=\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443.
tab2_Cb_GLshowNspOnly=\u041E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u044C \u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0444\u0430\u0439\u043B\u044B *.nsp \u0432 GoldLeaf.
tab2_Cb_UseOldGlVersion=\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0441\u0442\u0430\u0440\u0443\u044E \u0432\u0435\u0440\u0441\u0438\u044E GoldLeaf
btn_OpenSplitFile=\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0440\u0430\u0437\u0431\u0438\u0442\u044B\u0439 NSP
tab2_Lbl_ApplicationSettings=\u041E\u0441\u043D\u043E\u0432\u043D\u044B\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438
tabSplMrg_Lbl_SplitNMergeTitle=\u0423\u0442\u0438\u043B\u0438\u0442\u0430 \u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0438 \u0438 \u0441\u043B\u0438\u044F\u043D\u0438\u044F \u0444\u0430\u0439\u043B\u043E\u0432
tabSplMrg_Btn_Convert=\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C
tabSplMrg_RadioBtn_Split=\u0420\u0430\u0437\u0431\u0438\u0442\u044C
tabSplMrg_RadioBtn_Merge=\u041E\u0431\u044A\u0435\u0434\u0438\u043D\u0438\u0442\u044C
tabSplMrg_Txt_File=\u0424\u0430\u0439\u043B:
tabSplMrg_Txt_Folder=\u0420\u0430\u0437\u0431\u0438\u0442\u044B\u0439 \u0444\u0430\u0439\u043B (\u043F\u0430\u043F\u043A\u0430):
tabSplMrg_Lbl_SaveToLocation=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u0432:
tabSplMrg_Btn_ChangeSaveToLocation=\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C
tabSplMrg_Btn_SelectFile=\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B
tabSplMrg_Btn_SelectFolder=\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u043F\u0430\u043F\u043A\u0443
windowTitleError=\u041E\u0448\u0438\u0431\u043A\u0430
windowBodyPleaseFinishTransfersFirst=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u044C \u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0443 \u0438\u043B\u0438 \u0441\u043B\u0438\u044F\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u0430 \u0432 \u0442\u043E\u0442 \u043C\u043E\u043C\u0435\u043D\u0442, \u043A\u043E\u0433\u0434\u0430 \u0430\u043A\u0442\u0438\u0432\u0435\u043D \u043F\u0440\u043E\u0446\u0435\u0441\u0441 USB \u0438\u043B\u0438 \u0421\u0435\u0442\u0435\u0432\u043E\u0439 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438. \u0421\u043F\u0435\u0440\u0432\u0430 \u043F\u0440\u0435\u0440\u0432\u0438\u0442\u0435 \u0435\u0433\u043E.
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

View file

@ -39,10 +39,26 @@ windowTitleNewVersionUnknown=\u041D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u0
windowBodyNewVersionNOTAval=\u0412\u0438 \u0432\u0436\u0435 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0454\u0442\u0435 \u043E\u0441\u0442\u0430\u043D\u043D\u044E \u0432\u0435\u0440\u0441\u0456\u044E
windowBodyNewVersionUnknown=\u0429\u043E\u0441\u044C \u043F\u0456\u0448\u043B\u043E \u043D\u0435 \u0442\u0430\u043A.\n\u041C\u043E\u0436\u043B\u0438\u0432\u043E, \u0456\u043D\u0442\u0435\u0440\u043D\u0435\u0442 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439, \u0430\u0431\u043E GitHub \u043D\u0435 \u043F\u0440\u0430\u0446\u044E\u0454.
tab2_Cb_AllowXciNszXcz=\u0414\u043E\u0437\u0432\u043E\u043B\u0438\u0442\u0438 \u0432\u0438\u0431\u0456\u0440 XCI, NSZ \u0442\u0430 XCZ \u0444\u0430\u0439\u043B\u0456\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u0443 Tinfoil
tab2_Lbl_AllowXciNszXczDesc=\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0454\u0442\u044C\u0441\u044F \u0434\u043E\u0434\u0430\u0442\u043A\u0430\u043C\u0438, \u0449\u043E \u043C\u0430\u044E\u0442\u044C \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u043A\u0443 XCI, NSZ, XCZ \u0456 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0442\u044C \u043F\u0440\u043E\u0442\u043E\u043A\u043E\u043B \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 Tinfoil. \u041D\u0435 \u0437\u043C\u0456\u043D\u044E\u0439\u0442\u0435, \u044F\u043A\u0449\u043E \u043D\u0435 \u0432\u043F\u0435\u0432\u043D\u0435\u043D\u0456.
tab2_Lbl_AllowXciNszXczDesc=\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0454\u0442\u044C\u0441\u044F \u0434\u043E\u0434\u0430\u0442\u043A\u0430\u043C\u0438, \u0449\u043E \u043C\u0430\u044E\u0442\u044C \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u043A\u0443 XCI, NSZ, XCZ \u0456 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0442\u044C \u043F\u0440\u043E\u0442\u043E\u043A\u043E\u043B \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 Tinfoil. \u041D\u0435 \u0437\u043C\u0456\u043D\u044E\u0439\u0442\u0435, \u044F\u043A\u0449\u043E \u043D\u0435 \u0432\u043F\u0435\u0432\u043D\u0435\u043D\u0456. \u0423\u0432\u0456\u043C\u043A\u043D\u0456\u0442\u044C \u044F\u043A\u0449\u043E \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0454\u0442\u0435 Awoo Installer
tab2_Lbl_Language=\u041C\u043E\u0432\u0430
windowBodyRestartToApplyLang=\u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0456\u0442\u044C \u0434\u043E\u0434\u0430\u0442\u043E\u043A \u0449\u043E\u0431 \u0437\u043C\u0456\u043D\u0438 \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443.
tab2_Cb_GLshowNspOnly=\u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u0432\u0438\u043A\u043B\u044E\u0447\u043D\u043E *.nsp \u0444\u0430\u0439\u043B\u0438 \u0443 GoldLeaf.
tab2_Cb_UseOldGlVersion=\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0440\u0443 \u0432\u0435\u0440\u0441\u0456\u044E GoldLeaf
btn_OpenSplitFile=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0440\u043E\u0437\u0431\u0438\u0442\u0438\u0439 NSP
tab2_Lbl_ApplicationSettings=\u041E\u0441\u043D\u043E\u0432\u043D\u0456 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F
tabSplMrg_Lbl_SplitNMergeTitle=\u041F\u043E\u043C\u0456\u0447\u043D\u0438\u043A \u0440\u043E\u0437\u0431\u0432\u043A\u0438 \u0442\u0430 \u043E\u0431'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0444\u0430\u0439\u043B\u0456\u0432
tabSplMrg_Btn_Convert=\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0443\u0432\u0430\u0442\u0438
tabSplMrg_RadioBtn_Split=\u0420\u043E\u0437\u0431\u0438\u0442\u0438
tabSplMrg_RadioBtn_Merge=\u041E\u0431'\u0454\u0434\u043D\u0430\u0442\u0438
tabSplMrg_Txt_File=\u0424\u0430\u0439\u043B:
tabSplMrg_Txt_Folder=\u0420\u043E\u0437\u0431\u0438\u0442\u0438\u0439 \u0444\u0430\u0439\u043B (\u043F\u0430\u043F\u043A\u0430):
tabSplMrg_Lbl_SaveToLocation=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0432:
tabSplMrg_Btn_ChangeSaveToLocation=\u0417\u043C\u0456\u043D\u0438\u0442\u0438
tabSplMrg_Btn_SelectFile=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0444\u0430\u0439\u043B
tabSplMrg_Btn_SelectFolder=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043F\u0430\u043F\u043A\u0443
windowTitleError=\u041F\u043E\u043C\u0438\u043B\u043A\u0430
windowBodyPleaseFinishTransfersFirst=\u041D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u0434\u0456\u0439\u0441\u043D\u044E\u0432\u0430\u0442\u0438 \u0440\u043E\u0437\u0431\u0438\u0432\u043A\u0443 \u0430\u0431\u043E \u0437'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0444\u0430\u0439\u043B\u0443 \u0443 \u0442\u043E\u0439 \u043C\u043E\u043C\u0435\u043D\u0442, \u044F\u043A \u043F\u0440\u043E\u0446\u0435\u0441 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0447\u0435\u0440\u0435\u0437 USB \u0447\u0438 \u0442\u043E \u0447\u0435\u0440\u0435\u0437 \u043C\u0435\u0440\u0435\u0436\u0443 \u0449\u0435 \u0430\u043A\u0442\u0438\u0432\u043D\u0438\u0439. \u0421\u043F\u043E\u0447\u0430\u0442\u043A\u0443 \u043F\u0440\u0438\u043F\u0438\u043D\u0456\u0442\u044C \u0439\u043E\u0433\u043E.
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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -92,11 +92,6 @@
.tool-bar{
-fx-background-color: transparent;
}
.special-pane-as-border{
-fx-background-color: #f7fafa;
-fx-min-height: 1;
}
// -======================== Choice box =========================-
.choice-box {
-fx-background-color: #4f4f4f;
@ -144,16 +139,16 @@
-fx-fill: #7effff;
}
.tab-pane .tab{
-fx-background-color: #424242;
-fx-background-color: transparent;
-fx-focus-color: transparent;
-fx-faint-focus-color: transparent;
-fx-border-radius: 0 0 0 0;
-fx-border-width: 3 0 0 0;
-fx-border-color: #424242;
-fx-border-color: transparent;
}
.tab-pane .tab:selected{
-fx-background-color: #2d2d2d;
-fx-background-color: transparent;
-fx-focus-color: transparent;
-fx-faint-focus-color: transparent;
-fx-border-radius: 0 0 0 0;
@ -168,8 +163,7 @@
.tab-pane > .tab-header-area > .tab-header-background
{
-fx-background-color: #424242;
-fx-background-color: linear-gradient(to right, #2d2d2d 0%, #343434 7.5%, #343434 100%); //#424242; //
}
.tab-pane > .tab-header-area > .headers-region > .tab {
-fx-padding: 10;
@ -255,8 +249,18 @@
-fx-background-radius : 0.0em;
-fx-border-radius :2.0em;
}
// -========================== Scroll =====================-
/* -========================= Separator ===================- */
.separator *.line {
-fx-border-style: solid;
-fx-border-width: 0 0 1 0;
-fx-border-color: #3a3738;
}
.strangeSeparator *.line {
-fx-border-style: solid;
-fx-border-width: 0 0 1 0;
-fx-border-color: #f7fafa;
}
/* -========================== Scroll =====================- */
.scroll-bar .increment-arrow,
.scroll-bar .decrement-arrow {
-fx-background-color: #71e016;
@ -307,7 +311,6 @@
-fx-background-radius: 5;
-fx-border-color: #2d2d2d;
-fx-border-radius: 3;
}
.check-box:hover .box {
@ -324,7 +327,46 @@
.check-box:selected .mark, .check-box:selected:hover .mark{
-fx-background-color: #4f4f4f;
}
/*-======================= Radio Button =====================-*/
.radio-button .radio, .radio-button:selected .radio {
-fx-background-color: #4f4f4f;
-fx-background-insets: 0 0 0 0, 0, 1, 1;
-fx-background-radius: 45;
-fx-border-color: transparent;
-fx-border-radius: 45;
}
.radio-button:hover .radio {
-fx-background-color: #4f4f4f;
-fx-background-insets: 0 0 0 0, 0, 1, 1;
-fx-background-radius: 45;
-fx-border-color: #a4ffff;
-fx-border-radius: 45;
}
.radio-button:selected .radio, .radio-button:selected:hover .radio {
-fx-background-color: #71e016;
}
.radio-button:selected .dot, .radio-button:selected:hover .dot{
-fx-background-color: #2d2d2d;
-fx-shape: "M9,20.42L2.79,14.21L5.62,11.38L9,14.77L18.88,4.88L21.71,7.71L9,20.42Z";
-fx-scale-x: 1.2;
-fx-scale-y: 1.2;
}
/***********************************************************/
.regionSplitToOne {
-fx-shape: "m 3,23 c -1.104569,0 -2,0.895431 -2,2 v 16 c 0,1.1 0.89,2 2,2 h 12 c 1.104569,0 2,-0.895431 2,-2 V 25 c 0,-1.095153 -0.910156,-2 -2,-2 z m 39.400391,0 C 41.068391,23 40,24.1125 40,25.5 v 15 A 2.4,2.5 0 0 0 42.400391,43 H 61.599609 A 2.4,2.5 0 0 0 64,40.5 V 28 c 0,-1.3875 -1.080391,-2.5 -2.400391,-2.5 H 52 L 49.599609,23 Z M 5.099609,24.199219 h 7.800782 c 0.1,0.0021 0.09961,0.0018 0.09961,0.101562 v 0.09961 c -10e-7,0.09583 3.91e-4,0.09753 -0.09961,0.09961 H 5.099609 c -0.1,0.0057 -0.09961,0.004 -0.09961,-0.09961 v -0.09961 c 0,-0.09974 -3.91e-4,-0.103386 0.09961,-0.101562 z M 29,24.75 v 4 h -8 v 8 h 8 v 4 l 8,-8 z M 3,25 h 12 c 0.303385,0 0.5,0.204427 0.5,0.5 v 13 C 15.5,38.789959 15.29836,39 15,39 H 3 C 2.704427,39 2.5,38.803385 2.5,38.5 v -13 C 2.5,25.208333 2.71224,25 3,25 Z m 50.193359,6.962891 c 0.920139,0 1.620877,0.38585 2.103516,1.160156 0.482639,0.770833 0.724609,1.812066 0.724609,3.121094 0,1.3125 -0.24197,2.3546 -0.724609,3.128906 -0.482639,0.770833 -1.183377,1.15625 -2.103516,1.15625 -0.916666,0 -1.617404,-0.385417 -2.103515,-1.15625 -0.482639,-0.774306 -0.72461,-1.816406 -0.72461,-3.128906 0,-1.309028 0.241971,-2.350261 0.72461,-3.121094 0.486111,-0.774306 1.186849,-1.160156 2.103515,-1.160156 z m 6.396485,0 c 0.920139,0 1.620876,0.38585 2.103515,1.160156 0.482639,0.770833 0.72461,1.812066 0.72461,3.121094 0,1.3125 -0.241971,2.3546 -0.72461,3.128906 -0.482639,0.770833 -1.183376,1.15625 -2.103515,1.15625 -0.916667,0 -1.619358,-0.385417 -2.105469,-1.15625 -0.482639,-0.774306 -0.722656,-1.816406 -0.722656,-3.128906 0,-1.309028 0.240017,-2.350261 0.722656,-3.121094 0.486111,-0.774306 1.188802,-1.160156 2.105469,-1.160156 z m -10.025391,0.52539 h 0.01953 l -0.01953,0.01758 z m 3.628906,0.28125 c -0.579861,0 -1.020182,0.322917 -1.322265,0.96875 -0.302084,0.642361 -0.453125,1.457683 -0.453125,2.447266 0,0.225694 0.0056,0.470052 0.01953,0.730469 0.01389,0.260416 0.07357,0.612196 0.177734,1.05664 l 2.796875,-4.380859 c -0.177083,-0.322917 -0.369791,-0.53928 -0.578125,-0.650391 -0.204861,-0.114583 -0.418402,-0.171875 -0.640624,-0.171875 z m 6.396485,0 c -0.579861,0 -1.022136,0.322917 -1.324219,0.96875 -0.302083,0.642361 -0.453125,1.457683 -0.453125,2.447266 0,0.225694 0.0076,0.470052 0.02148,0.730469 0.01389,0.260416 0.07357,0.612196 0.177735,1.05664 l 2.796875,-4.380859 c -0.17708,-0.322917 -0.369788,-0.53928 -0.578121,-0.650391 -0.204861,-0.114583 -0.418403,-0.171875 -0.640625,-0.171875 z m -4.828125,1.78711 -2.777344,4.40625 c 0.149306,0.253472 0.321181,0.443793 0.515625,0.572265 0.194444,0.125 0.41276,0.1875 0.652344,0.1875 0.659722,0 1.128472,-0.367404 1.40625,-1.103515 0.277778,-0.739584 0.416015,-1.559679 0.416015,-2.458985 0,-0.555555 -0.07053,-1.089626 -0.21289,-1.603515 z m 6.394531,0 -2.775391,4.40625 c 0.149306,0.253472 0.321181,0.443793 0.515625,0.572265 0.194445,0.125 0.410808,0.1875 0.650391,0.1875 0.659722,0 1.128472,-0.367404 1.40625,-1.103515 0.277778,-0.739584 0.417969,-1.559679 0.417969,-2.458985 0,-0.555555 -0.07248,-1.089626 -0.214844,-1.603515 z M 6,40 h 6 l -3,2 z";
-fx-min-height: 20;
-fx-min-width: 64;
-fx-background-color: #71e016;
}
.regionOneToSplit {
-fx-shape: "M 50 1 C 48.895431 1 48 1.895431 48 3 L 48 19 C 48 20.1 48.89 21 50 21 L 62 21 C 63.104569 21 64 20.104569 64 19 L 64 3 C 64 1.904847 63.089844 1 62 1 L 50 1 z M 3.4160156 1.0371094 C 2.0840156 1.0371094 1.015625 2.1496094 1.015625 3.5371094 L 1.015625 18.537109 A 2.4 2.5 0 0 0 3.4160156 21.037109 L 22.615234 21.037109 A 2.4 2.5 0 0 0 25.015625 18.537109 L 25.015625 6.0371094 C 25.015625 4.6496094 23.935234 3.5371094 22.615234 3.5371094 L 13.015625 3.5371094 L 10.615234 1.0371094 L 3.4160156 1.0371094 z M 52.099609 2.1992188 L 59.900391 2.1992188 C 60.000391 2.2013185 60 2.2010194 60 2.3007812 L 60 2.4003906 C 59.999999 2.4962206 60.000391 2.49792 59.900391 2.5 L 52.099609 2.5 C 51.999609 2.5057 52 2.5040006 52 2.4003906 L 52 2.3007812 C 52 2.2010414 51.999609 2.1973947 52.099609 2.1992188 z M 37 3 L 37 7 L 29 7 L 29 15 L 37 15 L 37 19 L 45 11 L 37 3 z M 50 3 L 62 3 C 62.303385 3 62.5 3.204427 62.5 3.5 L 62.5 16.5 C 62.5 16.789959 62.29836 17 62 17 L 50 17 C 49.704427 17 49.5 16.803385 49.5 16.5 L 49.5 3.5 C 49.5 3.208333 49.71224 3 50 3 z M 14.208984 10 C 15.129123 10 15.829861 10.38585 16.3125 11.160156 C 16.795139 11.930989 17.037109 12.972222 17.037109 14.28125 C 17.037109 15.59375 16.795139 16.63585 16.3125 17.410156 C 15.829861 18.180989 15.129123 18.566406 14.208984 18.566406 C 13.292318 18.566406 12.59158 18.180989 12.105469 17.410156 C 11.62283 16.63585 11.380859 15.59375 11.380859 14.28125 C 11.380859 12.972222 11.62283 11.930989 12.105469 11.160156 C 12.59158 10.38585 13.292318 10 14.208984 10 z M 20.605469 10 C 21.525608 10 22.226345 10.38585 22.708984 11.160156 C 23.191623 11.930989 23.433594 12.972222 23.433594 14.28125 C 23.433594 15.59375 23.191623 16.63585 22.708984 17.410156 C 22.226345 18.180989 21.525608 18.566406 20.605469 18.566406 C 19.688802 18.566406 18.986111 18.180989 18.5 17.410156 C 18.017361 16.63585 17.777344 15.59375 17.777344 14.28125 C 17.777344 12.972222 18.017361 11.930989 18.5 11.160156 C 18.986111 10.38585 19.688802 10 20.605469 10 z M 14.208984 10.806641 C 13.629123 10.806641 13.188802 11.129558 12.886719 11.775391 C 12.584635 12.417752 12.433594 13.233073 12.433594 14.222656 C 12.433594 14.44835 12.439195 14.692708 12.453125 14.953125 C 12.467015 15.213541 12.526695 15.565322 12.630859 16.009766 L 15.427734 11.628906 C 15.250651 11.305989 15.057943 11.089627 14.849609 10.978516 C 14.644748 10.863933 14.431206 10.806641 14.208984 10.806641 z M 20.605469 10.806641 C 20.025608 10.806641 19.583333 11.129558 19.28125 11.775391 C 18.979167 12.417752 18.828125 13.233073 18.828125 14.222656 C 18.828125 14.44835 18.835729 14.692708 18.849609 14.953125 C 18.863499 15.213541 18.923179 15.565322 19.027344 16.009766 L 21.824219 11.628906 C 21.647139 11.305989 21.454427 11.089627 21.246094 10.978516 C 21.041233 10.863933 20.827691 10.806641 20.605469 10.806641 z M 15.777344 12.59375 L 13 17 C 13.149306 17.253472 13.321181 17.443794 13.515625 17.572266 C 13.710069 17.697266 13.928385 17.759766 14.167969 17.759766 C 14.827691 17.759766 15.296441 17.392361 15.574219 16.65625 C 15.851997 15.916666 15.990234 15.096572 15.990234 14.197266 C 15.990234 13.641711 15.919704 13.107639 15.777344 12.59375 z M 22.171875 12.59375 L 19.396484 17 C 19.54579 17.253472 19.717665 17.443794 19.912109 17.572266 C 20.106554 17.697266 20.322917 17.759766 20.5625 17.759766 C 21.222222 17.759766 21.690972 17.392361 21.96875 16.65625 C 22.246528 15.916666 22.386719 15.096572 22.386719 14.197266 C 22.386719 13.641711 22.314239 13.107639 22.171875 12.59375 z M 53 18 L 59 18 L 56 20 L 53 18 z";
-fx-min-height: 20;
-fx-min-width: 64;
-fx-background-color: #71e016;
}
.regionUpload{
-fx-shape: "M 4.0078125,0 C 1.5078125,0 0,1.4882812 0,3.984375 V 15.988281 C 0,18.417969 1.4927148,20 4.0078125,20 H 6.5 V 0 Z M 15,2.9 7,13 h 5 c 0,1.661689 -0.0097,6.246588 -0.0098,7.011719 H 18 V 13 h 5 z M 23.5,0 v 20 c 1.004057,-7.06e-4 1.659943,0 2.492187,0 C 28.414063,20 30,18.496094 30,15.996094 V 3.9765625 C 30,1.5195311 28.508727,0 26.003907,0 Z M 3.1015625,2.9570312 C 4.1485235,2.9562481 4.9977514,3.8046013 4.9980469,4.8515625 4.998831,5.8992865 4.1492865,6.748831 3.1015625,6.7480469 2.0546013,6.7477514 1.2062481,5.8985235 1.2070312,4.8515625 1.2073268,3.8053642 2.0553642,2.9573267 3.1015625,2.9570312 Z M 26.865234,11.148438 c 1.047724,-7.85e-4 1.897269,0.84876 1.896485,1.896484 -2.96e-4,1.046961 -0.849524,1.895314 -1.896485,1.894531 -1.046198,-2.95e-4 -1.894235,-0.848333 -1.894531,-1.894531 -7.83e-4,-1.046961 0.84757,-1.896189 1.894531,-1.896484 z";
-fx-background-color: #71e016;
@ -352,3 +394,7 @@
-size: 17.5;
-fx-min-width: 20;
}
//
//.lineGradient {
// -fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #00c8fc 30%, transparent 45%);
//}

View file

@ -109,12 +109,7 @@
.tool-bar{
-fx-background-color: transparent;
}
.special-pane-as-border{
-fx-background-color: #2c2c2c;
-fx-min-height: 1;
}
// -======================== Choice box =========================-
/* -======================== Choice box =========================- */
.choice-box {
-fx-background-color: #fefefe;
-fx-border-color: #fefefe;
@ -150,7 +145,7 @@
-fx-text-fill: #2c2c2c;
}
// -======================== TAB PANE =========================-
/* -======================== TAB PANE =========================- */
.tab-pane .tab SVGPath{
-fx-fill: #2c2c2c;
}
@ -161,16 +156,16 @@
-fx-fill: #1c6fa2;
}
.tab-pane .tab{
-fx-background-color: #fefefe;
-fx-background-color: transparent;
-fx-focus-color: transparent;
-fx-faint-focus-color: transparent;
-fx-border-radius: 0 0 0 0;
-fx-border-width: 3 0 0 0;
-fx-border-color: #fefefe;
-fx-border-color: transparent;
}
.tab-pane .tab:selected{
-fx-background-color: #ebebeb;
-fx-background-color: #fefefe;
-fx-focus-color: transparent;
-fx-faint-focus-color: transparent;
-fx-border-radius: 0 0 0 0;
@ -185,13 +180,13 @@
.tab-pane > .tab-header-area > .tab-header-background
{
-fx-background-color: #fefefe;
-fx-background-color: #ebebeb;
}
.tab-pane > .tab-header-area > .headers-region > .tab {
-fx-padding: 10;
}
// -=========================== TABLE ======================-
/* -=========================== TABLE ======================- */
.table-view {
-fx-background-color: #fefefe;
-fx-background-image: url(app_logo.png);
@ -240,7 +235,18 @@
-fx-padding: 0.0em; /* 0 */
-fx-table-cell-border-color: #b0b0b0;
}
// -========================== Context menu =====================-
/* -========================= Separator ===================- */
.separator *.line {
-fx-border-style: solid;
-fx-border-width: 0 0 1 0;
-fx-border-color: #a7a7a7;
}
.strangeSeparator *.line {
-fx-border-style: solid;
-fx-border-width: 0 0 1 0;
-fx-border-color: #2c2c2c;
}
/* -========================== Context menu =====================- */
.context-menu {
-fx-background-color: #fefefe;
-fx-cursor: hand;
@ -251,7 +257,7 @@
.context-menu .menu-item:focused .label {
-fx-text-fill: white;
}
// -========================== Text Field =====================-
/* -========================== Text Field =====================- */
.text-field {
-fx-border-color: #289de8;
-fx-border-width: 0 0 1 0;
@ -265,8 +271,19 @@
-fx-text-fill: #e82382;
}
.regionSplitToOne {
-fx-shape: "m 3,23 c -1.104569,0 -2,0.895431 -2,2 v 16 c 0,1.1 0.89,2 2,2 h 12 c 1.104569,0 2,-0.895431 2,-2 V 25 c 0,-1.095153 -0.910156,-2 -2,-2 z m 39.400391,0 C 41.068391,23 40,24.1125 40,25.5 v 15 A 2.4,2.5 0 0 0 42.400391,43 H 61.599609 A 2.4,2.5 0 0 0 64,40.5 V 28 c 0,-1.3875 -1.080391,-2.5 -2.400391,-2.5 H 52 L 49.599609,23 Z M 5.099609,24.199219 h 7.800782 c 0.1,0.0021 0.09961,0.0018 0.09961,0.101562 v 0.09961 c -10e-7,0.09583 3.91e-4,0.09753 -0.09961,0.09961 H 5.099609 c -0.1,0.0057 -0.09961,0.004 -0.09961,-0.09961 v -0.09961 c 0,-0.09974 -3.91e-4,-0.103386 0.09961,-0.101562 z M 29,24.75 v 4 h -8 v 8 h 8 v 4 l 8,-8 z M 3,25 h 12 c 0.303385,0 0.5,0.204427 0.5,0.5 v 13 C 15.5,38.789959 15.29836,39 15,39 H 3 C 2.704427,39 2.5,38.803385 2.5,38.5 v -13 C 2.5,25.208333 2.71224,25 3,25 Z m 50.193359,6.962891 c 0.920139,0 1.620877,0.38585 2.103516,1.160156 0.482639,0.770833 0.724609,1.812066 0.724609,3.121094 0,1.3125 -0.24197,2.3546 -0.724609,3.128906 -0.482639,0.770833 -1.183377,1.15625 -2.103516,1.15625 -0.916666,0 -1.617404,-0.385417 -2.103515,-1.15625 -0.482639,-0.774306 -0.72461,-1.816406 -0.72461,-3.128906 0,-1.309028 0.241971,-2.350261 0.72461,-3.121094 0.486111,-0.774306 1.186849,-1.160156 2.103515,-1.160156 z m 6.396485,0 c 0.920139,0 1.620876,0.38585 2.103515,1.160156 0.482639,0.770833 0.72461,1.812066 0.72461,3.121094 0,1.3125 -0.241971,2.3546 -0.72461,3.128906 -0.482639,0.770833 -1.183376,1.15625 -2.103515,1.15625 -0.916667,0 -1.619358,-0.385417 -2.105469,-1.15625 -0.482639,-0.774306 -0.722656,-1.816406 -0.722656,-3.128906 0,-1.309028 0.240017,-2.350261 0.722656,-3.121094 0.486111,-0.774306 1.188802,-1.160156 2.105469,-1.160156 z m -10.025391,0.52539 h 0.01953 l -0.01953,0.01758 z m 3.628906,0.28125 c -0.579861,0 -1.020182,0.322917 -1.322265,0.96875 -0.302084,0.642361 -0.453125,1.457683 -0.453125,2.447266 0,0.225694 0.0056,0.470052 0.01953,0.730469 0.01389,0.260416 0.07357,0.612196 0.177734,1.05664 l 2.796875,-4.380859 c -0.177083,-0.322917 -0.369791,-0.53928 -0.578125,-0.650391 -0.204861,-0.114583 -0.418402,-0.171875 -0.640624,-0.171875 z m 6.396485,0 c -0.579861,0 -1.022136,0.322917 -1.324219,0.96875 -0.302083,0.642361 -0.453125,1.457683 -0.453125,2.447266 0,0.225694 0.0076,0.470052 0.02148,0.730469 0.01389,0.260416 0.07357,0.612196 0.177735,1.05664 l 2.796875,-4.380859 c -0.17708,-0.322917 -0.369788,-0.53928 -0.578121,-0.650391 -0.204861,-0.114583 -0.418403,-0.171875 -0.640625,-0.171875 z m -4.828125,1.78711 -2.777344,4.40625 c 0.149306,0.253472 0.321181,0.443793 0.515625,0.572265 0.194444,0.125 0.41276,0.1875 0.652344,0.1875 0.659722,0 1.128472,-0.367404 1.40625,-1.103515 0.277778,-0.739584 0.416015,-1.559679 0.416015,-2.458985 0,-0.555555 -0.07053,-1.089626 -0.21289,-1.603515 z m 6.394531,0 -2.775391,4.40625 c 0.149306,0.253472 0.321181,0.443793 0.515625,0.572265 0.194445,0.125 0.410808,0.1875 0.650391,0.1875 0.659722,0 1.128472,-0.367404 1.40625,-1.103515 0.277778,-0.739584 0.417969,-1.559679 0.417969,-2.458985 0,-0.555555 -0.07248,-1.089626 -0.214844,-1.603515 z M 6,40 h 6 l -3,2 z";
-fx-min-height: 20;
-fx-min-width: 64;
-fx-background-color: #71e016;
}
.regionOneToSplit {
-fx-shape: "M 50 1 C 48.895431 1 48 1.895431 48 3 L 48 19 C 48 20.1 48.89 21 50 21 L 62 21 C 63.104569 21 64 20.104569 64 19 L 64 3 C 64 1.904847 63.089844 1 62 1 L 50 1 z M 3.4160156 1.0371094 C 2.0840156 1.0371094 1.015625 2.1496094 1.015625 3.5371094 L 1.015625 18.537109 A 2.4 2.5 0 0 0 3.4160156 21.037109 L 22.615234 21.037109 A 2.4 2.5 0 0 0 25.015625 18.537109 L 25.015625 6.0371094 C 25.015625 4.6496094 23.935234 3.5371094 22.615234 3.5371094 L 13.015625 3.5371094 L 10.615234 1.0371094 L 3.4160156 1.0371094 z M 52.099609 2.1992188 L 59.900391 2.1992188 C 60.000391 2.2013185 60 2.2010194 60 2.3007812 L 60 2.4003906 C 59.999999 2.4962206 60.000391 2.49792 59.900391 2.5 L 52.099609 2.5 C 51.999609 2.5057 52 2.5040006 52 2.4003906 L 52 2.3007812 C 52 2.2010414 51.999609 2.1973947 52.099609 2.1992188 z M 37 3 L 37 7 L 29 7 L 29 15 L 37 15 L 37 19 L 45 11 L 37 3 z M 50 3 L 62 3 C 62.303385 3 62.5 3.204427 62.5 3.5 L 62.5 16.5 C 62.5 16.789959 62.29836 17 62 17 L 50 17 C 49.704427 17 49.5 16.803385 49.5 16.5 L 49.5 3.5 C 49.5 3.208333 49.71224 3 50 3 z M 14.208984 10 C 15.129123 10 15.829861 10.38585 16.3125 11.160156 C 16.795139 11.930989 17.037109 12.972222 17.037109 14.28125 C 17.037109 15.59375 16.795139 16.63585 16.3125 17.410156 C 15.829861 18.180989 15.129123 18.566406 14.208984 18.566406 C 13.292318 18.566406 12.59158 18.180989 12.105469 17.410156 C 11.62283 16.63585 11.380859 15.59375 11.380859 14.28125 C 11.380859 12.972222 11.62283 11.930989 12.105469 11.160156 C 12.59158 10.38585 13.292318 10 14.208984 10 z M 20.605469 10 C 21.525608 10 22.226345 10.38585 22.708984 11.160156 C 23.191623 11.930989 23.433594 12.972222 23.433594 14.28125 C 23.433594 15.59375 23.191623 16.63585 22.708984 17.410156 C 22.226345 18.180989 21.525608 18.566406 20.605469 18.566406 C 19.688802 18.566406 18.986111 18.180989 18.5 17.410156 C 18.017361 16.63585 17.777344 15.59375 17.777344 14.28125 C 17.777344 12.972222 18.017361 11.930989 18.5 11.160156 C 18.986111 10.38585 19.688802 10 20.605469 10 z M 14.208984 10.806641 C 13.629123 10.806641 13.188802 11.129558 12.886719 11.775391 C 12.584635 12.417752 12.433594 13.233073 12.433594 14.222656 C 12.433594 14.44835 12.439195 14.692708 12.453125 14.953125 C 12.467015 15.213541 12.526695 15.565322 12.630859 16.009766 L 15.427734 11.628906 C 15.250651 11.305989 15.057943 11.089627 14.849609 10.978516 C 14.644748 10.863933 14.431206 10.806641 14.208984 10.806641 z M 20.605469 10.806641 C 20.025608 10.806641 19.583333 11.129558 19.28125 11.775391 C 18.979167 12.417752 18.828125 13.233073 18.828125 14.222656 C 18.828125 14.44835 18.835729 14.692708 18.849609 14.953125 C 18.863499 15.213541 18.923179 15.565322 19.027344 16.009766 L 21.824219 11.628906 C 21.647139 11.305989 21.454427 11.089627 21.246094 10.978516 C 21.041233 10.863933 20.827691 10.806641 20.605469 10.806641 z M 15.777344 12.59375 L 13 17 C 13.149306 17.253472 13.321181 17.443794 13.515625 17.572266 C 13.710069 17.697266 13.928385 17.759766 14.167969 17.759766 C 14.827691 17.759766 15.296441 17.392361 15.574219 16.65625 C 15.851997 15.916666 15.990234 15.096572 15.990234 14.197266 C 15.990234 13.641711 15.919704 13.107639 15.777344 12.59375 z M 22.171875 12.59375 L 19.396484 17 C 19.54579 17.253472 19.717665 17.443794 19.912109 17.572266 C 20.106554 17.697266 20.322917 17.759766 20.5625 17.759766 C 21.222222 17.759766 21.690972 17.392361 21.96875 16.65625 C 22.246528 15.916666 22.386719 15.096572 22.386719 14.197266 C 22.386719 13.641711 22.314239 13.107639 22.171875 12.59375 z M 53 18 L 59 18 L 56 20 L 53 18 z";
-fx-min-height: 20;
-fx-min-width: 64;
-fx-background-color: #71e016;
}
.regionUpload{
-fx-shape: "M 4.0078125,0 C 1.5078125,0 0,1.4882812 0,3.984375 V 15.988281 C 0,18.417969 1.4927148,20 4.0078125,20 H 6.5 V 0 Z M 15,2.9 7,13 h 5 c 0,1.661689 -0.0097,6.246588 -0.0098,7.011719 H 18 V 13 h 5 z M 23.5,0 v 20 c 1.004057,-7.06e-4 1.659943,0 2.492187,0 C 28.414063,20 30,18.496094 30,15.996094 V 3.9765625 C 30,1.5195311 28.508727,0 26.003907,0 Z M 3.1015625,2.9570312 C 4.1485235,2.9562481 4.9977514,3.8046013 4.9980469,4.8515625 4.998831,5.8992865 4.1492865,6.748831 3.1015625,6.7480469 2.0546013,6.7477514 1.2062481,5.8985235 1.2070312,4.8515625 1.2073268,3.8053642 2.0553642,2.9573267 3.1015625,2.9570312 Z M 26.865234,11.148438 c 1.047724,-7.85e-4 1.897269,0.84876 1.896485,1.896484 -2.96e-4,1.046961 -0.849524,1.895314 -1.896485,1.894531 -1.046198,-2.95e-4 -1.894235,-0.848333 -1.894531,-1.894531 -7.83e-4,-1.046961 0.84757,-1.896189 1.894531,-1.896484 z";