Compare commits
	
		
			13 commits
		
	
	
		
			ea97bcd2eb
			...
			2e0d583963
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
							 | 
						2e0d583963 | ||
| 
							 | 
						8eb05bb1b5 | ||
| 
							 | 
						6b6bf8320f | ||
| 
							 | 
						aff6044cdb | ||
| 
							 | 
						bbb71e2a53 | ||
| 
							 | 
						fe673c0ace | ||
| 
							 | 
						ec4362ebc7 | ||
| 
							 | 
						010c33c593 | ||
| 
							 | 
						3d3fb56f9e | ||
| 
							 | 
						ca061cd1f2 | ||
| 
							 | 
						98155bc1f8 | ||
| 
							 | 
						d00b914214 | ||
| 
							 | 
						4dc6d0ae0c | 
					 43 changed files with 2633 additions and 358 deletions
				
			
		
							
								
								
									
										45
									
								
								BUILD.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								BUILD.md
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										33
									
								
								JNI sources/linux/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								JNI sources/linux/Makefile
									
									
									
									
									
										Normal 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}
 | 
				
			||||||
							
								
								
									
										29
									
								
								JNI sources/linux/nsusbloader_Utilities_RcmSmash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								JNI sources/linux/nsusbloader_Utilities_RcmSmash.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										88
									
								
								JNI sources/linux/smashlib.c
									
									
									
									
									
										Executable 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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
							
								
								
									
										34
									
								
								JNI sources/windows/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								JNI sources/windows/Makefile
									
									
									
									
									
										Normal 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}
 | 
				
			||||||
							
								
								
									
										29
									
								
								JNI sources/windows/nsusbloader_Utilities_RcmSmash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								JNI sources/windows/nsusbloader_Utilities_RcmSmash.h
									
									
									
									
									
										Normal 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
 | 
				
			||||||
							
								
								
									
										168
									
								
								JNI sources/windows/smashlib.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								JNI sources/windows/smashlib.c
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							| 
						 | 
					@ -4,8 +4,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[Support author](#support-this-app)
 | 
					[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**. 
 | 
					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)
 | 
					[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).
 | 
					Sometimes I add new posts about this project [on my home page](https://developersu.blogspot.com/search/label/NS-USBloader).
 | 
				
			||||||
 | 
					
 | 
				
			||||||

 | 
					  
 | 
				
			||||||
 | 
					<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
 | 
					#### 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)
 | 
					* [OpenJFX](https://wiki.openjdk.java.net/display/OpenJFX/Main)
 | 
				
			||||||
* [usb4java](https://mvnrepository.com/artifact/org.usb4java/usb4java)
 | 
					* [usb4java](https://mvnrepository.com/artifact/org.usb4java/usb4java)
 | 
				
			||||||
* Few icons taken from: [materialdesignicons.com](http://materialdesignicons.com/)
 | 
					* 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!
 | 
					#### 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"
 | 
					SUBSYSTEM=="usb", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="3000", GROUP="plugdev"
 | 
				
			||||||
root # udevadm control --reload-rules && udevadm trigger
 | 
					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.
 | 
					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/)
 | 
					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):
 | 
					#### TODO (maybe):
 | 
				
			||||||
- [x] [Android support](https://github.com/developersu/ns-usbloader-mobile)
 | 
					- [x] [Android support](https://github.com/developersu/ns-usbloader-mobile)
 | 
				
			||||||
- [ ] File order sort (non-critical)
 | 
					- [ ] File order sort (non-critical)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							| 
						 | 
					@ -8,7 +8,7 @@
 | 
				
			||||||
    <name>NS-USBloader</name>
 | 
					    <name>NS-USBloader</name>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <artifactId>ns-usbloader</artifactId>
 | 
					    <artifactId>ns-usbloader</artifactId>
 | 
				
			||||||
    <version>1.0.0-SNAPSHOT</version>
 | 
					    <version>2.0-SNAPSHOT</version>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <url>https://github.com/developersu/ns-usbloader/</url>
 | 
					    <url>https://github.com/developersu/ns-usbloader/</url>
 | 
				
			||||||
    <description>
 | 
					    <description>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,6 +123,15 @@ public class AppPreferences {
 | 
				
			||||||
    public double getSceneWidth(){ return preferences.getDouble("WIND_WIDTH", 850.0); }
 | 
					    public double getSceneWidth(){ return preferences.getDouble("WIND_WIDTH", 850.0); }
 | 
				
			||||||
    public void setSceneWidth(double value){ preferences.putDouble("WIND_WIDTH", value); }
 | 
					    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); }
 | 
					    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); }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ package nsusbloader.COM.NET;
 | 
				
			||||||
import javafx.concurrent.Task;
 | 
					import javafx.concurrent.Task;
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EFileStatus;
 | 
					import nsusbloader.NSLDataTypes.EFileStatus;
 | 
				
			||||||
import nsusbloader.ModelControllers.LogPrinter;
 | 
					import nsusbloader.ModelControllers.LogPrinter;
 | 
				
			||||||
 | 
					import nsusbloader.NSLDataTypes.EModule;
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EMsgType;
 | 
					import nsusbloader.NSLDataTypes.EMsgType;
 | 
				
			||||||
import nsusbloader.COM.Helpers.NSSplitReader;
 | 
					import nsusbloader.COM.Helpers.NSSplitReader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +43,7 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            this.extras = "";
 | 
					            this.extras = "";
 | 
				
			||||||
        this.switchIP = switchIP;
 | 
					        this.switchIP = switchIP;
 | 
				
			||||||
        this.logPrinter = new LogPrinter();
 | 
					        this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
 | 
				
			||||||
        this.nspMap = new HashMap<>();
 | 
					        this.nspMap = new HashMap<>();
 | 
				
			||||||
        this.nspFileSizes = new HashMap<>();
 | 
					        this.nspFileSizes = new HashMap<>();
 | 
				
			||||||
        // Filter and remove empty/incorrect split-files
 | 
					        // Filter and remove empty/incorrect split-files
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ package nsusbloader.COM.USB;
 | 
				
			||||||
import javafx.concurrent.Task;
 | 
					import javafx.concurrent.Task;
 | 
				
			||||||
import nsusbloader.ModelControllers.LogPrinter;
 | 
					import nsusbloader.ModelControllers.LogPrinter;
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EFileStatus;
 | 
					import nsusbloader.NSLDataTypes.EFileStatus;
 | 
				
			||||||
 | 
					import nsusbloader.NSLDataTypes.EModule;
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EMsgType;
 | 
					import nsusbloader.NSLDataTypes.EMsgType;
 | 
				
			||||||
import org.usb4java.*;
 | 
					import org.usb4java.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,21 +35,21 @@ public class UsbCommunications extends Task<Void> {
 | 
				
			||||||
        this.nspMap = new LinkedHashMap<>();
 | 
					        this.nspMap = new LinkedHashMap<>();
 | 
				
			||||||
        for (File f: nspList)
 | 
					        for (File f: nspList)
 | 
				
			||||||
            nspMap.put(f.getName(), f);
 | 
					            nspMap.put(f.getName(), f);
 | 
				
			||||||
        this.logPrinter = new LogPrinter();
 | 
					        this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    protected Void call() {
 | 
					    protected Void call() {
 | 
				
			||||||
        logPrinter.print("\tStart chain", EMsgType.INFO);
 | 
					        logPrinter.print("\tStart chain", EMsgType.INFO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        UsbConnect usbConnect = new UsbConnect(logPrinter);
 | 
					        UsbConnect usbConnect = new UsbConnect(logPrinter, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! usbConnect.isConnected()){
 | 
					        if (! usbConnect.isConnected()){
 | 
				
			||||||
            close(EFileStatus.FAILED);
 | 
					            close(EFileStatus.FAILED);
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        DeviceHandle handler = usbConnect.getHandlerNS();
 | 
					        DeviceHandle handler = usbConnect.getNsHandler();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TransferModule module;
 | 
					        TransferModule module;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,20 +4,38 @@ import nsusbloader.ModelControllers.LogPrinter;
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EMsgType;
 | 
					import nsusbloader.NSLDataTypes.EMsgType;
 | 
				
			||||||
import org.usb4java.*;
 | 
					import org.usb4java.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UsbConnect {
 | 
					public class UsbConnect {
 | 
				
			||||||
    private final int DEFAULT_INTERFACE = 0;
 | 
					    private int DEFAULT_INTERFACE = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Context contextNS;
 | 
					    private Context contextNS;
 | 
				
			||||||
    private DeviceHandle handlerNS;
 | 
					    private DeviceHandle handlerNS;
 | 
				
			||||||
 | 
					    private Device deviceNS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private LogPrinter logPrinter;
 | 
					    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.logPrinter = logPrinter;
 | 
				
			||||||
        this.connected = false;
 | 
					        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;
 | 
					        int result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Creating Context required by libusb. Optional. TODO: Consider removing.
 | 
					        // Creating Context required by libusb. Optional. TODO: Consider removing.
 | 
				
			||||||
| 
						 | 
					@ -28,7 +46,6 @@ class UsbConnect {
 | 
				
			||||||
            close();
 | 
					            close();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        logPrinter.print("libusb initialization", EMsgType.PASS);
 | 
					        logPrinter.print("libusb initialization", EMsgType.PASS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Searching for NS in devices: obtain list of all devices
 | 
					        // Searching for NS in devices: obtain list of all devices
 | 
				
			||||||
| 
						 | 
					@ -39,11 +56,10 @@ class UsbConnect {
 | 
				
			||||||
            close();
 | 
					            close();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        logPrinter.print("Get device list", EMsgType.PASS);
 | 
					        logPrinter.print("Get device list", EMsgType.PASS);
 | 
				
			||||||
        // Searching for NS in devices: looking for NS
 | 
					        // Searching for NS in devices: looking for NS
 | 
				
			||||||
        DeviceDescriptor descriptor;
 | 
					        DeviceDescriptor descriptor;
 | 
				
			||||||
        Device deviceNS = null;
 | 
					        deviceNS = null;
 | 
				
			||||||
        for (Device device: deviceList){
 | 
					        for (Device device: deviceList){
 | 
				
			||||||
            descriptor = new DeviceDescriptor();                // mmm.. leave it as is.
 | 
					            descriptor = new DeviceDescriptor();                // mmm.. leave it as is.
 | 
				
			||||||
            result = LibUsb.getDeviceDescriptor(device, descriptor);
 | 
					            result = LibUsb.getDeviceDescriptor(device, descriptor);
 | 
				
			||||||
| 
						 | 
					@ -53,21 +69,20 @@ class UsbConnect {
 | 
				
			||||||
                close();
 | 
					                close();
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if ((descriptor.idVendor() == 0x057E) && descriptor.idProduct() == 0x3000){
 | 
					            if ((descriptor.idVendor() == VENDOR_ID) && descriptor.idProduct() == PRODUCT_ID){
 | 
				
			||||||
                deviceNS = device;
 | 
					                deviceNS = device;
 | 
				
			||||||
                logPrinter.print("Read file descriptors for USB devices", EMsgType.PASS);
 | 
					                logPrinter.print("Read file descriptors for USB devices", EMsgType.PASS);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Free device list.
 | 
					        // Free device list.
 | 
				
			||||||
        if (deviceNS != null){
 | 
					        if (deviceNS == null){
 | 
				
			||||||
            logPrinter.print("NS in connected USB devices found", EMsgType.PASS);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            logPrinter.print("NS in connected USB devices not found", EMsgType.FAIL);
 | 
					            logPrinter.print("NS in connected USB devices not found", EMsgType.FAIL);
 | 
				
			||||||
            close();
 | 
					            close();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        logPrinter.print("NS in connected USB devices found", EMsgType.PASS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Handle NS device
 | 
					        // Handle NS device
 | 
				
			||||||
        handlerNS = new DeviceHandle();
 | 
					        handlerNS = new DeviceHandle();
 | 
				
			||||||
        result = LibUsb.open(deviceNS, handlerNS);
 | 
					        result = LibUsb.open(deviceNS, handlerNS);
 | 
				
			||||||
| 
						 | 
					@ -75,10 +90,11 @@ class UsbConnect {
 | 
				
			||||||
            logPrinter.print("Open NS USB device\n  Returned: "+UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
 | 
					            logPrinter.print("Open NS USB device\n  Returned: "+UsbErrorCodes.getErrCode(result), EMsgType.FAIL);
 | 
				
			||||||
            if (result == LibUsb.ERROR_ACCESS)
 | 
					            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" +
 | 
					                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" +
 | 
					                        String.format("Steps to set 'udev' rules:\n" +
 | 
				
			||||||
                        "root # vim /etc/udev/rules.d/99-NS.rules\n" +
 | 
					                                "root # vim /etc/udev/rules.d/99-NS"+(initForRCM?"RCM":"")+".rules\n" +
 | 
				
			||||||
                        "SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"057e\", ATTRS{idProduct}==\"3000\", GROUP=\"plugdev\"\n" +
 | 
					                                "SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", GROUP=\"plugdev\"\n" +
 | 
				
			||||||
                        "root # udevadm control --reload-rules && udevadm trigger\n", EMsgType.INFO);
 | 
					                                "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
 | 
					            // Let's make a bit dirty workaround since such shit happened
 | 
				
			||||||
            logPrinter.print("Requested context close", EMsgType.INFO);
 | 
					            logPrinter.print("Requested context close", EMsgType.INFO);
 | 
				
			||||||
            LibUsb.exit(contextNS);
 | 
					            LibUsb.exit(contextNS);
 | 
				
			||||||
| 
						 | 
					@ -107,6 +123,7 @@ class UsbConnect {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
 | 
					        if ( ! initForRCM){
 | 
				
			||||||
            // Set configuration (soft reset if needed)
 | 
					            // Set configuration (soft reset if needed)
 | 
				
			||||||
            result = LibUsb.setConfiguration(handlerNS, 1);     // 1 - configuration all we need
 | 
					            result = LibUsb.setConfiguration(handlerNS, 1);     // 1 - configuration all we need
 | 
				
			||||||
            if (result != LibUsb.SUCCESS){
 | 
					            if (result != LibUsb.SUCCESS){
 | 
				
			||||||
| 
						 | 
					@ -114,9 +131,8 @@ class UsbConnect {
 | 
				
			||||||
                close();
 | 
					                close();
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            logPrinter.print("Set active configuration to device.", EMsgType.PASS);
 | 
					            logPrinter.print("Set active configuration to device.", EMsgType.PASS);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        // Claim interface
 | 
					        // Claim interface
 | 
				
			||||||
        result = LibUsb.claimInterface(handlerNS, DEFAULT_INTERFACE);
 | 
					        result = LibUsb.claimInterface(handlerNS, DEFAULT_INTERFACE);
 | 
				
			||||||
        if (result != LibUsb.SUCCESS) {
 | 
					        if (result != LibUsb.SUCCESS) {
 | 
				
			||||||
| 
						 | 
					@ -124,7 +140,6 @@ class UsbConnect {
 | 
				
			||||||
            close();
 | 
					            close();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        logPrinter.print("Claim interface", EMsgType.PASS);
 | 
					        logPrinter.print("Claim interface", EMsgType.PASS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.connected = true;
 | 
					        this.connected = true;
 | 
				
			||||||
| 
						 | 
					@ -134,23 +149,36 @@ class UsbConnect {
 | 
				
			||||||
     * Get USB status
 | 
					     * Get USB status
 | 
				
			||||||
     * @return status of connection
 | 
					     * @return status of connection
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    boolean isConnected() { return connected; }
 | 
					    public boolean isConnected() { return connected; }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Getter for handler
 | 
					     * Getter for handler
 | 
				
			||||||
     * @return DeviceHandle of NS
 | 
					     * @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
 | 
					     * Correct exit
 | 
				
			||||||
     * */
 | 
					     * */
 | 
				
			||||||
    void close(){
 | 
					    public void close(){
 | 
				
			||||||
        // Close handler in the end
 | 
					        // Close handler in the end
 | 
				
			||||||
        if (handlerNS != null) {
 | 
					        if (handlerNS != null) {
 | 
				
			||||||
            // Try to release interface
 | 
					            // Try to release interface
 | 
				
			||||||
            int result = LibUsb.releaseInterface(handlerNS, DEFAULT_INTERFACE);
 | 
					            int result = LibUsb.releaseInterface(handlerNS, DEFAULT_INTERFACE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (result != LibUsb.SUCCESS)
 | 
					            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
 | 
					            else
 | 
				
			||||||
                logPrinter.print("Release interface", EMsgType.PASS);
 | 
					                logPrinter.print("Release interface", EMsgType.PASS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,8 +2,8 @@ package nsusbloader.COM.USB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.usb4java.LibUsb;
 | 
					import org.usb4java.LibUsb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UsbErrorCodes {
 | 
					public class UsbErrorCodes {
 | 
				
			||||||
    static String getErrCode(int value){
 | 
					    public static String getErrCode(int value){
 | 
				
			||||||
        switch (value){
 | 
					        switch (value){
 | 
				
			||||||
            case LibUsb.ERROR_ACCESS:
 | 
					            case LibUsb.ERROR_ACCESS:
 | 
				
			||||||
                return "ERROR_ACCESS";
 | 
					                return "ERROR_ACCESS";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,20 +2,32 @@ package nsusbloader.Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javafx.collections.FXCollections;
 | 
					import javafx.collections.FXCollections;
 | 
				
			||||||
import javafx.collections.ObservableList;
 | 
					import javafx.collections.ObservableList;
 | 
				
			||||||
 | 
					import javafx.concurrent.Task;
 | 
				
			||||||
import javafx.fxml.FXML;
 | 
					import javafx.fxml.FXML;
 | 
				
			||||||
import javafx.fxml.Initializable;
 | 
					import javafx.fxml.Initializable;
 | 
				
			||||||
import javafx.scene.control.*;
 | 
					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.scene.layout.Region;
 | 
				
			||||||
 | 
					import javafx.stage.DirectoryChooser;
 | 
				
			||||||
 | 
					import javafx.stage.FileChooser;
 | 
				
			||||||
import nsusbloader.AppPreferences;
 | 
					import nsusbloader.AppPreferences;
 | 
				
			||||||
 | 
					import nsusbloader.COM.NET.NETCommunications;
 | 
				
			||||||
 | 
					import nsusbloader.COM.USB.UsbCommunications;
 | 
				
			||||||
import nsusbloader.MediatorControl;
 | 
					import nsusbloader.MediatorControl;
 | 
				
			||||||
 | 
					import nsusbloader.NSLDataTypes.EModule;
 | 
				
			||||||
 | 
					import nsusbloader.ServiceWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.File;
 | 
				
			||||||
import java.net.URL;
 | 
					import java.net.URL;
 | 
				
			||||||
 | 
					import java.util.LinkedList;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.ResourceBundle;
 | 
					import java.util.ResourceBundle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class FrontController implements Initializable {
 | 
					public class FrontController implements Initializable {
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private Pane specialPane;
 | 
					    private AnchorPane usbNetPane;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private ChoiceBox<String> choiceProtocol, choiceNetUsb;
 | 
					    private ChoiceBox<String> choiceProtocol, choiceNetUsb;
 | 
				
			||||||
| 
						 | 
					@ -26,11 +38,19 @@ public class FrontController implements Initializable {
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private Button switchThemeBtn;
 | 
					    private Button switchThemeBtn;
 | 
				
			||||||
    @FXML
 | 
					    @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
 | 
					    @Override
 | 
				
			||||||
    public void initialize(URL url, ResourceBundle resourceBundle) {
 | 
					    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");
 | 
					        ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf");
 | 
				
			||||||
        choiceProtocol.setItems(choiceProtocolList);
 | 
					        choiceProtocol.setItems(choiceProtocolList);
 | 
				
			||||||
| 
						 | 
					@ -52,9 +72,9 @@ public class FrontController implements Initializable {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // Really bad disable-enable upload button function
 | 
					            // Really bad disable-enable upload button function
 | 
				
			||||||
            if (tableFilesListController.isFilesForUploadListEmpty())
 | 
					            if (tableFilesListController.isFilesForUploadListEmpty())
 | 
				
			||||||
                MediatorControl.getInstance().getContoller().disableUploadStopBtn(true);
 | 
					                disableUploadStopBtn(true);
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                MediatorControl.getInstance().getContoller().disableUploadStopBtn(false);
 | 
					                disableUploadStopBtn(false);
 | 
				
			||||||
        });  // Add listener to notify tableView controller
 | 
					        });  // Add listener to notify tableView controller
 | 
				
			||||||
        tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem());   // Notify tableView controller
 | 
					        tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem());   // Notify tableView controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,6 +112,28 @@ public class FrontController implements Initializable {
 | 
				
			||||||
        btnSwitchImage.getStyleClass().add("regionLamp");
 | 
					        btnSwitchImage.getStyleClass().add("regionLamp");
 | 
				
			||||||
        switchThemeBtn.setGraphic(btnSwitchImage);
 | 
					        switchThemeBtn.setGraphic(btnSwitchImage);
 | 
				
			||||||
        this.switchThemeBtn.setOnAction(e->switchTheme());
 | 
					        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
 | 
					     * Changes UI theme on the go
 | 
				
			||||||
| 
						 | 
					@ -125,4 +167,200 @@ public class FrontController implements Initializable {
 | 
				
			||||||
    String getNsIp(){
 | 
					    String getNsIp(){
 | 
				
			||||||
        return nsIpTextField.getText();
 | 
					        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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,19 +5,10 @@ import javafx.concurrent.Task;
 | 
				
			||||||
import javafx.fxml.FXML;
 | 
					import javafx.fxml.FXML;
 | 
				
			||||||
import javafx.fxml.Initializable;
 | 
					import javafx.fxml.Initializable;
 | 
				
			||||||
import javafx.scene.control.*;
 | 
					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.*;
 | 
				
			||||||
import nsusbloader.ModelControllers.UpdatesChecker;
 | 
					import nsusbloader.ModelControllers.UpdatesChecker;
 | 
				
			||||||
import nsusbloader.COM.NET.NETCommunications;
 | 
					 | 
				
			||||||
import nsusbloader.COM.USB.UsbCommunications;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.File;
 | 
					 | 
				
			||||||
import java.net.*;
 | 
					import java.net.*;
 | 
				
			||||||
import java.util.LinkedList;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.ResourceBundle;
 | 
					import java.util.ResourceBundle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,22 +18,18 @@ public class NSLMainController implements Initializable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    public TextArea logArea;            // Accessible from Mediator
 | 
					    public TextArea logArea;            // Accessible from Mediator
 | 
				
			||||||
    @FXML
 | 
					 | 
				
			||||||
    private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Region btnUpStopImage;
 | 
					 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    public ProgressBar progressBar;            // Accessible from Mediator
 | 
					    public ProgressBar progressBar;            // Accessible from Mediator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @FXML
 | 
				
			||||||
 | 
					    public FrontController FrontTabController;             // Accessible from Mediator | todo: incapsulate
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private SettingsController SettingsTabController;
 | 
					    private SettingsController SettingsTabController;
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    public FrontController FrontTabController;             // Accessible from Mediator | todo: incapsulate
 | 
					    private SplitMergeController SplitMergeTabController;
 | 
				
			||||||
 | 
					    @FXML
 | 
				
			||||||
    private Task<Void> usbNetCommunications;
 | 
					    private RcmController RcmTabController;
 | 
				
			||||||
    private Thread workThread;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private String previouslyOpenedPath;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void initialize(URL url, ResourceBundle rb) {
 | 
					    public void initialize(URL url, ResourceBundle rb) {
 | 
				
			||||||
| 
						 | 
					@ -56,27 +43,6 @@ public class NSLMainController implements Initializable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MediatorControl.getInstance().setController(this);
 | 
					        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()){
 | 
					        if (AppPreferences.getInstance().getAutoCheckUpdates()){
 | 
				
			||||||
            Task<List<String>> updTask = new UpdatesChecker();
 | 
					            Task<List<String>> updTask = new UpdatesChecker();
 | 
				
			||||||
            updTask.setOnSucceeded(event->{
 | 
					            updTask.setOnSucceeded(event->{
 | 
				
			||||||
| 
						 | 
					@ -110,201 +76,29 @@ public class NSLMainController implements Initializable {
 | 
				
			||||||
    public void setHostServices(HostServices hs ){ SettingsTabController.registerHostServices(hs);}
 | 
					    public void setHostServices(HostServices hs ){ SettingsTabController.registerHostServices(hs);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Functionality for selecting NSP button.
 | 
					     * Get 'Settings' controller
 | 
				
			||||||
 | 
					     * Used by FrontController
 | 
				
			||||||
     * */
 | 
					     * */
 | 
				
			||||||
    private void selectFilesBtnAction(){
 | 
					    public SettingsController getSettingsCtrlr(){
 | 
				
			||||||
        List<File> filesList;
 | 
					        return SettingsTabController;
 | 
				
			||||||
        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();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 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();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 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);
 | 
					    public FrontController getFrontCtrlr(){
 | 
				
			||||||
                workThread.setDaemon(true);
 | 
					        return FrontTabController;
 | 
				
			||||||
                workThread.start();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 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"));
 | 
					    public SplitMergeController getSmCtrlr(){
 | 
				
			||||||
 | 
					        return SplitMergeTabController;
 | 
				
			||||||
            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"));
 | 
					    public RcmController getRcmCtrlr(){ return RcmTabController; }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Save preferences before exit
 | 
					     * Save preferences before exit
 | 
				
			||||||
     * */
 | 
					     * */
 | 
				
			||||||
    public void exit(){
 | 
					    public void exit(){
 | 
				
			||||||
        AppPreferences.getInstance().setAll(
 | 
					        AppPreferences.getInstance().setAll(
 | 
				
			||||||
                FrontTabController.getSelectedProtocol(),
 | 
					                FrontTabController.getSelectedProtocol(),
 | 
				
			||||||
                previouslyOpenedPath,
 | 
					                FrontTabController.getRecentPath(),
 | 
				
			||||||
                FrontTabController.getSelectedNetUsb(),
 | 
					                FrontTabController.getSelectedNetUsb(),
 | 
				
			||||||
                FrontTabController.getNsIp(),
 | 
					                FrontTabController.getNsIp(),
 | 
				
			||||||
                SettingsTabController.isNsIpValidate(),
 | 
					                SettingsTabController.isNsIpValidate(),
 | 
				
			||||||
| 
						 | 
					@ -320,5 +114,8 @@ public class NSLMainController implements Initializable {
 | 
				
			||||||
                SettingsTabController.getNSPFileFilterForGL(),
 | 
					                SettingsTabController.getNSPFileFilterForGL(),
 | 
				
			||||||
                SettingsTabController.getGlOldVer()
 | 
					                SettingsTabController.getGlOldVer()
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SplitMergeTabController.updatePreferencesOnExit(); // NOTE: This shit above should be re-written to similar pattern
 | 
				
			||||||
 | 
					        RcmTabController.updatePreferencesOnExit();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,6 @@ import nsusbloader.NSLDataTypes.EFileStatus;
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.net.URL;
 | 
					import java.net.URL;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.ResourceBundle;
 | 
					import java.util.ResourceBundle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +38,7 @@ public class NSTableViewController implements Initializable {
 | 
				
			||||||
                    if (keyEvent.getCode() == KeyCode.DELETE && !MediatorControl.getInstance().getTransferActive()) {
 | 
					                    if (keyEvent.getCode() == KeyCode.DELETE && !MediatorControl.getInstance().getTransferActive()) {
 | 
				
			||||||
                        rowsObsLst.removeAll(table.getSelectionModel().getSelectedItems());
 | 
					                        rowsObsLst.removeAll(table.getSelectionModel().getSelectedItems());
 | 
				
			||||||
                        if (rowsObsLst.isEmpty())
 | 
					                        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();
 | 
					                        table.refresh();
 | 
				
			||||||
                    } else if (keyEvent.getCode() == KeyCode.SPACE) {
 | 
					                    } else if (keyEvent.getCode() == KeyCode.SPACE) {
 | 
				
			||||||
                        for (NSLRowModel item : table.getSelectionModel().getSelectedItems()) {
 | 
					                        for (NSLRowModel item : table.getSelectionModel().getSelectedItems()) {
 | 
				
			||||||
| 
						 | 
					@ -112,13 +111,13 @@ public class NSTableViewController implements Initializable {
 | 
				
			||||||
                    deleteMenuItem.setOnAction(actionEvent -> {
 | 
					                    deleteMenuItem.setOnAction(actionEvent -> {
 | 
				
			||||||
                        rowsObsLst.remove(row.getItem());
 | 
					                        rowsObsLst.remove(row.getItem());
 | 
				
			||||||
                        if (rowsObsLst.isEmpty())
 | 
					                        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();
 | 
					                        table.refresh();
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    MenuItem deleteAllMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_DeleteAll"));
 | 
					                    MenuItem deleteAllMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_DeleteAll"));
 | 
				
			||||||
                    deleteAllMenuItem.setOnAction(actionEvent -> {
 | 
					                    deleteAllMenuItem.setOnAction(actionEvent -> {
 | 
				
			||||||
                        rowsObsLst.clear();
 | 
					                        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();
 | 
					                        table.refresh();
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    contextMenu.getItems().addAll(deleteMenuItem, deleteAllMenuItem);
 | 
					                    contextMenu.getItems().addAll(deleteMenuItem, deleteAllMenuItem);
 | 
				
			||||||
| 
						 | 
					@ -163,7 +162,7 @@ public class NSTableViewController implements Initializable {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            rowsObsLst.add(new NSLRowModel(file, true));
 | 
					            rowsObsLst.add(new NSLRowModel(file, true));
 | 
				
			||||||
            MediatorControl.getInstance().getContoller().disableUploadStopBtn(false);
 | 
					            MediatorControl.getInstance().getContoller().getFrontCtrlr().disableUploadStopBtn(false);    // TODO: change to something better
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        table.refresh();
 | 
					        table.refresh();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -183,7 +182,7 @@ public class NSTableViewController implements Initializable {
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            for (File file: newFiles)
 | 
					            for (File file: newFiles)
 | 
				
			||||||
                rowsObsLst.add(new NSLRowModel(file, true));
 | 
					                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);
 | 
					        //rowsObsLst.get(0).setMarkForUpload(true);
 | 
				
			||||||
        table.refresh();
 | 
					        table.refresh();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										329
									
								
								src/main/java/nsusbloader/Controllers/RcmController.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								src/main/java/nsusbloader/Controllers/RcmController.java
									
									
									
									
									
										Normal 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());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										240
									
								
								src/main/java/nsusbloader/Controllers/SplitMergeController.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								src/main/java/nsusbloader/Controllers/SplitMergeController.java
									
									
									
									
									
										Normal 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());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,13 @@
 | 
				
			||||||
package nsusbloader;
 | 
					package nsusbloader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import nsusbloader.Controllers.NSLMainController;
 | 
					import nsusbloader.Controllers.NSLMainController;
 | 
				
			||||||
 | 
					import nsusbloader.NSLDataTypes.EModule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.concurrent.atomic.AtomicBoolean;
 | 
					import java.util.concurrent.atomic.AtomicBoolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class MediatorControl {
 | 
					public class MediatorControl {
 | 
				
			||||||
    private AtomicBoolean isTransferActive = new AtomicBoolean(false);  // Overcoded just for sure
 | 
					    private AtomicBoolean isTransferActive = new AtomicBoolean(false);  // Overcoded just for sure
 | 
				
			||||||
    private NSLMainController applicationController;
 | 
					    private NSLMainController mainCtrler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static MediatorControl getInstance(){
 | 
					    public static MediatorControl getInstance(){
 | 
				
			||||||
        return MediatorControlHold.INSTANCE;
 | 
					        return MediatorControlHold.INSTANCE;
 | 
				
			||||||
| 
						 | 
					@ -16,13 +17,15 @@ public class MediatorControl {
 | 
				
			||||||
        private static final MediatorControl INSTANCE = new MediatorControl();
 | 
					        private static final MediatorControl INSTANCE = new MediatorControl();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public void setController(NSLMainController controller){
 | 
					    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) {
 | 
					    public synchronized void setBgThreadActive(boolean isActive, EModule appModuleType) {
 | 
				
			||||||
        isTransferActive.set(state);
 | 
					        isTransferActive.set(isActive);
 | 
				
			||||||
        applicationController.notifyTransmissionStarted(state);
 | 
					        mainCtrler.getFrontCtrlr().notifyTransmThreadStarted(isActive, appModuleType);
 | 
				
			||||||
 | 
					        mainCtrler.getSmCtrlr().notifySmThreadStarted(isActive, appModuleType);
 | 
				
			||||||
 | 
					        mainCtrler.getRcmCtrlr().notifySmThreadStarted(isActive, appModuleType);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
 | 
					    public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
package nsusbloader.ModelControllers;
 | 
					package nsusbloader.ModelControllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EFileStatus;
 | 
					import nsusbloader.NSLDataTypes.EFileStatus;
 | 
				
			||||||
 | 
					import nsusbloader.NSLDataTypes.EModule;
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EMsgType;
 | 
					import nsusbloader.NSLDataTypes.EMsgType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
| 
						 | 
					@ -14,11 +15,11 @@ public class LogPrinter {
 | 
				
			||||||
    private BlockingQueue<Double> progressQueue;
 | 
					    private BlockingQueue<Double> progressQueue;
 | 
				
			||||||
    private HashMap<String, EFileStatus> statusMap;      // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
 | 
					    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.msgQueue = new LinkedBlockingQueue<>();
 | 
				
			||||||
        this.progressQueue = new LinkedBlockingQueue<>();
 | 
					        this.progressQueue = new LinkedBlockingQueue<>();
 | 
				
			||||||
        this.statusMap =  new HashMap<>();
 | 
					        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();
 | 
					        this.msgConsumer.start();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -42,7 +43,8 @@ public class LogPrinter {
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    msgQueue.put(message);
 | 
					                    msgQueue.put(message);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }catch (InterruptedException ie){
 | 
					        }
 | 
				
			||||||
 | 
					        catch (InterruptedException ie){
 | 
				
			||||||
            ie.printStackTrace();
 | 
					            ie.printStackTrace();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ import javafx.scene.control.TextArea;
 | 
				
			||||||
import nsusbloader.Controllers.NSTableViewController;
 | 
					import nsusbloader.Controllers.NSTableViewController;
 | 
				
			||||||
import nsusbloader.MediatorControl;
 | 
					import nsusbloader.MediatorControl;
 | 
				
			||||||
import nsusbloader.NSLDataTypes.EFileStatus;
 | 
					import nsusbloader.NSLDataTypes.EFileStatus;
 | 
				
			||||||
 | 
					import nsusbloader.NSLDataTypes.EModule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
| 
						 | 
					@ -20,10 +21,12 @@ public class MessagesConsumer extends AnimationTimer {
 | 
				
			||||||
    private final ProgressBar progressBar;
 | 
					    private final ProgressBar progressBar;
 | 
				
			||||||
    private final HashMap<String, EFileStatus> statusMap;
 | 
					    private final HashMap<String, EFileStatus> statusMap;
 | 
				
			||||||
    private final NSTableViewController tableViewController;
 | 
					    private final NSTableViewController tableViewController;
 | 
				
			||||||
 | 
					    private final EModule appModuleType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private boolean isInterrupted;
 | 
					    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.isInterrupted = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.msgQueue = msgQueue;
 | 
					        this.msgQueue = msgQueue;
 | 
				
			||||||
| 
						 | 
					@ -38,7 +41,7 @@ public class MessagesConsumer extends AnimationTimer {
 | 
				
			||||||
        progressBar.setProgress(0.0);
 | 
					        progressBar.setProgress(0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
 | 
					        progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
 | 
				
			||||||
        MediatorControl.getInstance().setTransferActive(true);
 | 
					        MediatorControl.getInstance().setBgThreadActive(true, appModuleType);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @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
 | 
					        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);
 | 
					            progressBar.setProgress(0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (statusMap.size() > 0)
 | 
					            if (statusMap.size() > 0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								src/main/java/nsusbloader/NSLDataTypes/EModule.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/main/java/nsusbloader/NSLDataTypes/EModule.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					package nsusbloader.NSLDataTypes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum EModule {
 | 
				
			||||||
 | 
					    USB_NET_TRANSFERS,
 | 
				
			||||||
 | 
					    SPLIT_MERGE_TOOL,
 | 
				
			||||||
 | 
					    RCM
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,9 @@ import java.util.Locale;
 | 
				
			||||||
import java.util.ResourceBundle;
 | 
					import java.util.ResourceBundle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class NSLMain extends Application {
 | 
					public class NSLMain extends Application {
 | 
				
			||||||
    public static final String appVersion = "v1.0";
 | 
					
 | 
				
			||||||
 | 
					    public static final String appVersion = "v2.0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void start(Stage primaryStage) throws Exception{
 | 
					    public void start(Stage primaryStage) throws Exception{
 | 
				
			||||||
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/NSLMain.fxml"));
 | 
					        FXMLLoader loader = new FXMLLoader(getClass().getResource("/NSLMain.fxml"));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										105
									
								
								src/main/java/nsusbloader/Utilities/JNIRcmLoader.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/main/java/nsusbloader/Utilities/JNIRcmLoader.java
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								src/main/java/nsusbloader/Utilities/RcmSmash.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/main/java/nsusbloader/Utilities/RcmSmash.java
									
									
									
									
									
										Normal 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; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										316
									
								
								src/main/java/nsusbloader/Utilities/RcmTask.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								src/main/java/nsusbloader/Utilities/RcmTask.java
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										285
									
								
								src/main/java/nsusbloader/Utilities/SplitMergeTool.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								src/main/java/nsusbloader/Utilities/SplitMergeTool.java
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
<?import javafx.scene.control.Button?>
 | 
					<?import javafx.scene.control.Button?>
 | 
				
			||||||
<?import javafx.scene.control.ChoiceBox?>
 | 
					<?import javafx.scene.control.ChoiceBox?>
 | 
				
			||||||
<?import javafx.scene.control.Label?>
 | 
					<?import javafx.scene.control.Label?>
 | 
				
			||||||
 | 
					<?import javafx.scene.control.Separator?>
 | 
				
			||||||
<?import javafx.scene.control.TextField?>
 | 
					<?import javafx.scene.control.TextField?>
 | 
				
			||||||
<?import javafx.scene.control.ToolBar?>
 | 
					<?import javafx.scene.control.ToolBar?>
 | 
				
			||||||
<?import javafx.scene.layout.AnchorPane?>
 | 
					<?import javafx.scene.layout.AnchorPane?>
 | 
				
			||||||
| 
						 | 
					@ -13,8 +14,9 @@
 | 
				
			||||||
<?import javafx.scene.layout.Pane?>
 | 
					<?import javafx.scene.layout.Pane?>
 | 
				
			||||||
<?import javafx.scene.layout.RowConstraints?>
 | 
					<?import javafx.scene.layout.RowConstraints?>
 | 
				
			||||||
<?import javafx.scene.layout.VBox?>
 | 
					<?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>
 | 
					   <children>
 | 
				
			||||||
      <VBox layoutX="10.0" layoutY="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
 | 
					      <VBox layoutX="10.0" layoutY="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
 | 
				
			||||||
         <children>
 | 
					         <children>
 | 
				
			||||||
| 
						 | 
					@ -38,13 +40,40 @@
 | 
				
			||||||
                  <RowConstraints vgrow="SOMETIMES" />
 | 
					                  <RowConstraints vgrow="SOMETIMES" />
 | 
				
			||||||
               </rowConstraints>
 | 
					               </rowConstraints>
 | 
				
			||||||
               <children>
 | 
					               <children>
 | 
				
			||||||
                  <Pane fx:id="specialPane" GridPane.columnIndex="1" />
 | 
					                  <Separator prefWidth="200.0" styleClass="strangeSeparator" GridPane.columnIndex="1" />
 | 
				
			||||||
               </children>
 | 
					               </children>
 | 
				
			||||||
               <VBox.margin>
 | 
					               <VBox.margin>
 | 
				
			||||||
                  <Insets bottom="2.0" />
 | 
					                  <Insets bottom="2.0" />
 | 
				
			||||||
               </VBox.margin>
 | 
					               </VBox.margin>
 | 
				
			||||||
            </GridPane>
 | 
					            </GridPane>
 | 
				
			||||||
            <fx:include fx:id="tableFilesList" source="TableView.fxml" VBox.vgrow="ALWAYS" />
 | 
					            <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>
 | 
					         </children>
 | 
				
			||||||
      </VBox>
 | 
					      </VBox>
 | 
				
			||||||
   </children>
 | 
					   </children>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,18 +1,15 @@
 | 
				
			||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<?import javafx.geometry.Insets?>
 | 
					<?import javafx.geometry.Insets?>
 | 
				
			||||||
<?import javafx.scene.control.Button?>
 | 
					 | 
				
			||||||
<?import javafx.scene.control.ProgressBar?>
 | 
					<?import javafx.scene.control.ProgressBar?>
 | 
				
			||||||
<?import javafx.scene.control.Tab?>
 | 
					<?import javafx.scene.control.Tab?>
 | 
				
			||||||
<?import javafx.scene.control.TabPane?>
 | 
					<?import javafx.scene.control.TabPane?>
 | 
				
			||||||
<?import javafx.scene.control.TextArea?>
 | 
					<?import javafx.scene.control.TextArea?>
 | 
				
			||||||
<?import javafx.scene.layout.AnchorPane?>
 | 
					<?import javafx.scene.layout.AnchorPane?>
 | 
				
			||||||
<?import javafx.scene.layout.HBox?>
 | 
					 | 
				
			||||||
<?import javafx.scene.layout.Pane?>
 | 
					 | 
				
			||||||
<?import javafx.scene.layout.VBox?>
 | 
					<?import javafx.scene.layout.VBox?>
 | 
				
			||||||
<?import javafx.scene.shape.SVGPath?>
 | 
					<?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>
 | 
					   <children>
 | 
				
			||||||
      <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
 | 
					      <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
 | 
				
			||||||
         <children>
 | 
					         <children>
 | 
				
			||||||
| 
						 | 
					@ -25,6 +22,24 @@
 | 
				
			||||||
                     <graphic>
 | 
					                     <graphic>
 | 
				
			||||||
                        <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" />
 | 
					                        <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>
 | 
					                     </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>
 | 
				
			||||||
                  <Tab closable="false">
 | 
					                  <Tab closable="false">
 | 
				
			||||||
                      <content>
 | 
					                      <content>
 | 
				
			||||||
| 
						 | 
					@ -54,34 +69,9 @@
 | 
				
			||||||
            </TabPane>
 | 
					            </TabPane>
 | 
				
			||||||
            <ProgressBar fx:id="progressBar" prefWidth="Infinity" progress="0.0">
 | 
					            <ProgressBar fx:id="progressBar" prefWidth="Infinity" progress="0.0">
 | 
				
			||||||
               <VBox.margin>
 | 
					               <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>
 | 
					               </VBox.margin>
 | 
				
			||||||
            </ProgressBar>
 | 
					            </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>
 | 
					         </children>
 | 
				
			||||||
      </VBox>
 | 
					      </VBox>
 | 
				
			||||||
   </children>
 | 
					   </children>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										218
									
								
								src/main/resources/RcmTab.fxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								src/main/resources/RcmTab.fxml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
| 
						 | 
					@ -127,7 +127,7 @@
 | 
				
			||||||
                  </VBox>
 | 
					                  </VBox>
 | 
				
			||||||
               </children>
 | 
					               </children>
 | 
				
			||||||
               <padding>
 | 
					               <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>
 | 
					               </padding>
 | 
				
			||||||
            </VBox>
 | 
					            </VBox>
 | 
				
			||||||
</ScrollPane>
 | 
					</ScrollPane>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										107
									
								
								src/main/resources/SplitMergeTab.fxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/main/resources/SplitMergeTab.fxml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
| 
						 | 
					@ -39,10 +39,26 @@ windowTitleNewVersionUnknown=Unable to check for new versions
 | 
				
			||||||
windowBodyNewVersionUnknown=Something went wrong\nMaybe internet unavailable, or GitHub is down
 | 
					windowBodyNewVersionUnknown=Something went wrong\nMaybe internet unavailable, or GitHub is down
 | 
				
			||||||
windowBodyNewVersionNOTAval=You're using the latest version
 | 
					windowBodyNewVersionNOTAval=You're using the latest version
 | 
				
			||||||
tab2_Cb_AllowXciNszXcz=Allow XCI / NSZ / XCZ files selection for Tinfoil
 | 
					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
 | 
					tab2_Lbl_Language=Language
 | 
				
			||||||
windowBodyRestartToApplyLang=Please restart application to apply changes.
 | 
					windowBodyRestartToApplyLang=Please restart application to apply changes.
 | 
				
			||||||
tab2_Cb_GLshowNspOnly=Show only *.nsp in GoldLeaf.
 | 
					tab2_Cb_GLshowNspOnly=Show only *.nsp in GoldLeaf.
 | 
				
			||||||
tab2_Cb_UseOldGlVersion=Use old GoldLeaf version
 | 
					tab2_Cb_UseOldGlVersion=Use old GoldLeaf version
 | 
				
			||||||
btn_OpenSplitFile=Select split NSP
 | 
					btn_OpenSplitFile=Select split NSP
 | 
				
			||||||
tab2_Lbl_ApplicationSettings=Main settings
 | 
					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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					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.
 | 
					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_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
 | 
					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.
 | 
					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_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
 | 
					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
 | 
					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
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					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.
 | 
					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_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
 | 
					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.
 | 
					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_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
 | 
					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
 | 
					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
 | 
					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
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/native/linux/amd64/smashlib.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/native/linux/amd64/smashlib.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/native/linux/x86/smashlib.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/native/linux/x86/smashlib.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/native/windows/amd64/smashlib.dll
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/native/windows/amd64/smashlib.dll
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/native/windows/x86/smashlib.dll
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/native/windows/x86/smashlib.dll
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -92,11 +92,6 @@
 | 
				
			||||||
.tool-bar{
 | 
					.tool-bar{
 | 
				
			||||||
    -fx-background-color: transparent;
 | 
					    -fx-background-color: transparent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.special-pane-as-border{
 | 
					 | 
				
			||||||
    -fx-background-color: #f7fafa;
 | 
					 | 
				
			||||||
    -fx-min-height: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
// -======================== Choice box =========================-
 | 
					// -======================== Choice box =========================-
 | 
				
			||||||
.choice-box {
 | 
					.choice-box {
 | 
				
			||||||
    -fx-background-color: #4f4f4f;
 | 
					    -fx-background-color: #4f4f4f;
 | 
				
			||||||
| 
						 | 
					@ -144,16 +139,16 @@
 | 
				
			||||||
    -fx-fill: #7effff;
 | 
					    -fx-fill: #7effff;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.tab-pane .tab{
 | 
					.tab-pane .tab{
 | 
				
			||||||
    -fx-background-color: #424242;
 | 
					    -fx-background-color: transparent;
 | 
				
			||||||
    -fx-focus-color: transparent;
 | 
					    -fx-focus-color: transparent;
 | 
				
			||||||
    -fx-faint-focus-color: transparent;
 | 
					    -fx-faint-focus-color: transparent;
 | 
				
			||||||
    -fx-border-radius: 0 0 0 0;
 | 
					    -fx-border-radius: 0 0 0 0;
 | 
				
			||||||
    -fx-border-width: 3 0 0 0;
 | 
					    -fx-border-width: 3 0 0 0;
 | 
				
			||||||
    -fx-border-color: #424242;
 | 
					    -fx-border-color: transparent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tab-pane .tab:selected{
 | 
					.tab-pane .tab:selected{
 | 
				
			||||||
    -fx-background-color: #2d2d2d;
 | 
					    -fx-background-color: transparent;
 | 
				
			||||||
    -fx-focus-color: transparent;
 | 
					    -fx-focus-color: transparent;
 | 
				
			||||||
    -fx-faint-focus-color: transparent;
 | 
					    -fx-faint-focus-color: transparent;
 | 
				
			||||||
    -fx-border-radius: 0 0 0 0;
 | 
					    -fx-border-radius: 0 0 0 0;
 | 
				
			||||||
| 
						 | 
					@ -168,8 +163,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tab-pane > .tab-header-area > .tab-header-background
 | 
					.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 {
 | 
					.tab-pane > .tab-header-area > .headers-region > .tab {
 | 
				
			||||||
    -fx-padding: 10;
 | 
					    -fx-padding: 10;
 | 
				
			||||||
| 
						 | 
					@ -255,8 +249,18 @@
 | 
				
			||||||
    -fx-background-radius : 0.0em;
 | 
					    -fx-background-radius : 0.0em;
 | 
				
			||||||
    -fx-border-radius :2.0em;
 | 
					    -fx-border-radius :2.0em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/* -========================= Separator ===================- */
 | 
				
			||||||
// -========================== Scroll =====================-
 | 
					.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 .increment-arrow,
 | 
				
			||||||
.scroll-bar .decrement-arrow {
 | 
					.scroll-bar .decrement-arrow {
 | 
				
			||||||
    -fx-background-color: #71e016;
 | 
					    -fx-background-color: #71e016;
 | 
				
			||||||
| 
						 | 
					@ -307,7 +311,6 @@
 | 
				
			||||||
    -fx-background-radius: 5;
 | 
					    -fx-background-radius: 5;
 | 
				
			||||||
    -fx-border-color: #2d2d2d;
 | 
					    -fx-border-color: #2d2d2d;
 | 
				
			||||||
    -fx-border-radius: 3;
 | 
					    -fx-border-radius: 3;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.check-box:hover .box {
 | 
					.check-box:hover .box {
 | 
				
			||||||
| 
						 | 
					@ -324,7 +327,46 @@
 | 
				
			||||||
.check-box:selected .mark, .check-box:selected:hover .mark{
 | 
					.check-box:selected .mark, .check-box:selected:hover .mark{
 | 
				
			||||||
    -fx-background-color: #4f4f4f;
 | 
					    -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{
 | 
					.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-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;
 | 
					    -fx-background-color: #71e016;
 | 
				
			||||||
| 
						 | 
					@ -352,3 +394,7 @@
 | 
				
			||||||
    -size: 17.5;
 | 
					    -size: 17.5;
 | 
				
			||||||
    -fx-min-width: 20;
 | 
					    -fx-min-width: 20;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//.lineGradient {
 | 
				
			||||||
 | 
					//    -fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect,  #00c8fc 30%, transparent  45%);
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
| 
						 | 
					@ -109,12 +109,7 @@
 | 
				
			||||||
.tool-bar{
 | 
					.tool-bar{
 | 
				
			||||||
    -fx-background-color: transparent;
 | 
					    -fx-background-color: transparent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/* -======================== Choice box =========================- */
 | 
				
			||||||
.special-pane-as-border{
 | 
					 | 
				
			||||||
    -fx-background-color: #2c2c2c;
 | 
					 | 
				
			||||||
    -fx-min-height: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
// -======================== Choice box =========================-
 | 
					 | 
				
			||||||
.choice-box {
 | 
					.choice-box {
 | 
				
			||||||
    -fx-background-color: #fefefe;
 | 
					    -fx-background-color: #fefefe;
 | 
				
			||||||
    -fx-border-color: #fefefe;
 | 
					    -fx-border-color: #fefefe;
 | 
				
			||||||
| 
						 | 
					@ -150,7 +145,7 @@
 | 
				
			||||||
    -fx-text-fill: #2c2c2c;
 | 
					    -fx-text-fill: #2c2c2c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// -======================== TAB PANE =========================-
 | 
					/* -======================== TAB PANE =========================- */
 | 
				
			||||||
.tab-pane .tab SVGPath{
 | 
					.tab-pane .tab SVGPath{
 | 
				
			||||||
    -fx-fill: #2c2c2c;
 | 
					    -fx-fill: #2c2c2c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -161,16 +156,16 @@
 | 
				
			||||||
    -fx-fill: #1c6fa2;
 | 
					    -fx-fill: #1c6fa2;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.tab-pane .tab{
 | 
					.tab-pane .tab{
 | 
				
			||||||
    -fx-background-color: #fefefe;
 | 
					    -fx-background-color: transparent;
 | 
				
			||||||
    -fx-focus-color: transparent;
 | 
					    -fx-focus-color: transparent;
 | 
				
			||||||
    -fx-faint-focus-color: transparent;
 | 
					    -fx-faint-focus-color: transparent;
 | 
				
			||||||
    -fx-border-radius: 0 0 0 0;
 | 
					    -fx-border-radius: 0 0 0 0;
 | 
				
			||||||
    -fx-border-width: 3 0 0 0;
 | 
					    -fx-border-width: 3 0 0 0;
 | 
				
			||||||
    -fx-border-color: #fefefe;
 | 
					    -fx-border-color: transparent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tab-pane .tab:selected{
 | 
					.tab-pane .tab:selected{
 | 
				
			||||||
    -fx-background-color: #ebebeb;
 | 
					    -fx-background-color: #fefefe;
 | 
				
			||||||
    -fx-focus-color: transparent;
 | 
					    -fx-focus-color: transparent;
 | 
				
			||||||
    -fx-faint-focus-color: transparent;
 | 
					    -fx-faint-focus-color: transparent;
 | 
				
			||||||
    -fx-border-radius: 0 0 0 0;
 | 
					    -fx-border-radius: 0 0 0 0;
 | 
				
			||||||
| 
						 | 
					@ -185,13 +180,13 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tab-pane > .tab-header-area > .tab-header-background
 | 
					.tab-pane > .tab-header-area > .tab-header-background
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
   -fx-background-color: #fefefe;
 | 
					   -fx-background-color: #ebebeb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.tab-pane > .tab-header-area > .headers-region > .tab {
 | 
					.tab-pane > .tab-header-area > .headers-region > .tab {
 | 
				
			||||||
    -fx-padding: 10;
 | 
					    -fx-padding: 10;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
// -=========================== TABLE ======================-
 | 
					/* -=========================== TABLE ======================- */
 | 
				
			||||||
.table-view {
 | 
					.table-view {
 | 
				
			||||||
    -fx-background-color: #fefefe;
 | 
					    -fx-background-color: #fefefe;
 | 
				
			||||||
    -fx-background-image: url(app_logo.png);
 | 
					    -fx-background-image: url(app_logo.png);
 | 
				
			||||||
| 
						 | 
					@ -240,7 +235,18 @@
 | 
				
			||||||
    -fx-padding: 0.0em; /* 0 */
 | 
					    -fx-padding: 0.0em; /* 0 */
 | 
				
			||||||
    -fx-table-cell-border-color: #b0b0b0;
 | 
					    -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 {
 | 
					.context-menu {
 | 
				
			||||||
  -fx-background-color: #fefefe;
 | 
					  -fx-background-color: #fefefe;
 | 
				
			||||||
  -fx-cursor: hand;
 | 
					  -fx-cursor: hand;
 | 
				
			||||||
| 
						 | 
					@ -251,7 +257,7 @@
 | 
				
			||||||
.context-menu .menu-item:focused .label {
 | 
					.context-menu .menu-item:focused .label {
 | 
				
			||||||
  -fx-text-fill: white;
 | 
					  -fx-text-fill: white;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
// -========================== Text Field =====================-
 | 
					/* -========================== Text Field =====================- */
 | 
				
			||||||
.text-field {
 | 
					.text-field {
 | 
				
			||||||
    -fx-border-color: #289de8;
 | 
					    -fx-border-color: #289de8;
 | 
				
			||||||
    -fx-border-width: 0 0 1 0;
 | 
					    -fx-border-width: 0 0 1 0;
 | 
				
			||||||
| 
						 | 
					@ -265,8 +271,19 @@
 | 
				
			||||||
    -fx-text-fill: #e82382;
 | 
					    -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{
 | 
					.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-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";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue