Compare commits
91 Commits
Author | SHA1 | Date |
---|---|---|
Dmitry Isaenko | 5ee9f6aacd | |
Dmitry Isaenko | 7f9b3a7598 | |
01ut | cd9e3ddf30 | |
Kevin | Secret Jupiter | d1ac1f5403 | |
Dmitry Isaenko | e9b0fa309e | |
Dmitry Isaenko | c0bf247666 | |
Dmitry Isaenko | 66758ffdb9 | |
Justin Dhillon | b32986682e | |
Justin Dhillon | 2935d4ef55 | |
Justin Dhillon | 353b058388 | |
Justin Dhillon | 5b3ea13b08 | |
Justin Dhillon | 1251d39a6b | |
Justin Dhillon | 57e7f72531 | |
Dmitry Isaenko | 88ca0815ed | |
Dmitry Isaenko | 66e7338fa5 | |
Dmitry Isaenko | fa236cb1ad | |
Justin Dhillon | 5b120204ef | |
Justin Dhillon | 94ad332bf7 | |
Justin Dhillon | b89bfa806d | |
Justin Dhillon | abf7621f28 | |
Justin Dhillon | c5688f79df | |
Justin Dhillon | 25910ac94c | |
Justin Dhillon | 474f90a427 | |
Dmitry Isaenko | 8348c9f2ab | |
Dmitry Isaenko | 47045b2aeb | |
Dmitry Isaenko | 67351642ae | |
Dmitry Isaenko | 3909371774 | |
Dmitry Isaenko | 1e4593afb6 | |
DDinghoya | d3faa384ae | |
Dmitry Isaenko | 9d4cac26e5 | |
requinDr | ad211cd562 | |
requinDr | 4bdc5ffb63 | |
Dmitry Isaenko | 7db7af0cf8 | |
exiori | 6052d385d9 | |
exiori | f6b875af0b | |
Dmitry Isaenko | 01a25f071a | |
Dmitry Isaenko | c1651e874b | |
Dmitry Isaenko | 94845c1411 | |
Dmitry Isaenko | 7cf3970aa7 | |
Dmitry Isaenko | 5b69435e89 | |
Dmitry Isaenko | b463a63180 | |
Dmitry Isaenko | cbb9fd60b9 | |
Dmitry Isaenko | 5f0278fc7b | |
Dmitry Isaenko | 3981d0d8ca | |
Dmitry Isaenko | 29f29b7d31 | |
Dmitry Isaenko | 38f495ebc1 | |
Dmitry Isaenko | 4d7c6f6ef1 | |
Dmitry Isaenko | 7f01805cd5 | |
Dmitry Isaenko | f82275e82d | |
Dmitry Isaenko | 2356bfe0e9 | |
Dmitry Isaenko | fc02a8af6b | |
Dmitry Isaenko | c408f70b79 | |
Dmitry Isaenko | c39a5f4c5b | |
Dmitry Isaenko | ffa9c6903f | |
Dmitry Isaenko | c34531a92f | |
Dmitry Isaenko | 83695511d3 | |
Dmitry Isaenko | c84f70ec10 | |
Dmitry Isaenko | 6c51b8e1b6 | |
Dmitry Isaenko | f8b60af41b | |
Dmitry Isaenko | 4ccf833aa5 | |
Dmitry Isaenko | a60d929dcd | |
Dmitry Isaenko | 338bb699d1 | |
Dmitry Isaenko | 115625e3a3 | |
Dmitry Isaenko | 55df39923f | |
Dmitry Isaenko | 8b23b8967b | |
Dmitry Isaenko | 9aa4551ef0 | |
kuragehime | 610d04c9bd | |
kuragehime | 9b02750dd3 | |
kuragehime | 89dd6fdbe0 | |
kuragehime | b75421bc9e | |
kuragehime | cc09128373 | |
kuragehime | 6244fd974a | |
kuragehime | 2edea43d63 | |
kuragehime | c9dbb37c14 | |
Dmitry Isaenko | 51a3b1e7a1 | |
Dmitry Isaenko | 182c5293b5 | |
Dmitry Isaenko | 38af160ae7 | |
Dmitry Isaenko | edc27d6db0 | |
DDinghoya | d08993be17 | |
Dmitry Isaenko | bc2cf44a97 | |
Dmitry Isaenko | eefaa70f95 | |
Dmitry Isaenko | 5ed2167e9d | |
Dmitry Isaenko | 0b8092077a | |
Dmitry Isaenko | 5f03939b91 | |
Dmitry Isaenko | 503edcd127 | |
DDinghoya | ac3c0a3698 | |
Dmitry Isaenko | 0fab994a45 | |
exiori | 5b67821d3b | |
Dmitry Isaenko | 8547eb0e4e | |
Dmitry Isaenko | a6f95f32bb | |
qazrfv1234 | eb72fd17b6 |
|
@ -0,0 +1,101 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: maven:3-openjdk-17
|
||||
commands:
|
||||
- mvn -B -DskipTests clean package
|
||||
- mvn test -B
|
||||
volumes:
|
||||
- name: m2
|
||||
path: /root/.m2
|
||||
|
||||
- name: archive-standard-artifact
|
||||
image: alpine:latest
|
||||
commands:
|
||||
- mkdir -p /builds/ns-usbloader
|
||||
- echo target/ns-usbloader-*jar
|
||||
- cp target/ns-usbloader-*jar /builds/ns-usbloader/
|
||||
volumes:
|
||||
- name: builds
|
||||
path: /builds
|
||||
|
||||
- name: make-win-installer
|
||||
image: wheatstalk/makensis:3
|
||||
commands:
|
||||
- cp target/NS-USBloader.exe misc/windows/NSIS/
|
||||
- misc/windows/update_version.sh
|
||||
- cd misc/windows/NSIS
|
||||
- makensis -V4 ./installer.nsi
|
||||
- echo Installer-*.exe
|
||||
- cp Installer-*.exe /builds/ns-usbloader/
|
||||
- rm ./NS-USBloader.exe
|
||||
- rm ./Installer-*.exe
|
||||
- cd ../../../
|
||||
volumes:
|
||||
- name: builds
|
||||
path: /builds
|
||||
- name: jdk
|
||||
path: /drone/src/misc/windows/NSIS/jdk
|
||||
- name: drivers
|
||||
path: /drone/src/misc/windows/NSIS/Drivers_set.exe
|
||||
|
||||
- name: emerge-legacy-artifact
|
||||
image: maven:3-openjdk-17
|
||||
commands:
|
||||
- . ./.make_legacy
|
||||
- mvn -B -DskipTests clean package
|
||||
- echo target/ns-usbloader-*jar
|
||||
- cp target/ns-usbloader-*jar /builds/ns-usbloader/
|
||||
volumes:
|
||||
- name: m2
|
||||
path: /root/.m2
|
||||
- name: builds
|
||||
path: /builds
|
||||
|
||||
- name: make-legacy-win-installer
|
||||
image: wheatstalk/makensis:3
|
||||
commands:
|
||||
- cp target/NS-USBloader.exe misc/windows/NSIS/
|
||||
- misc/windows/update_version.sh legacy
|
||||
- cd misc/windows/NSIS
|
||||
- makensis -V4 ./installer.nsi
|
||||
- echo Installer-*.exe
|
||||
- cp Installer-*.exe /builds/ns-usbloader/
|
||||
- cd ../../../
|
||||
volumes:
|
||||
- name: builds
|
||||
path: /builds
|
||||
- name: jdk
|
||||
path: /drone/src/misc/windows/NSIS/jdk
|
||||
- name: drivers
|
||||
path: /drone/src/misc/windows/NSIS/Drivers_set.exe
|
||||
|
||||
- name: emerge-mac-m1-artifact
|
||||
image: maven:3-openjdk-17
|
||||
commands:
|
||||
- . ./.make_m1
|
||||
- mvn -B -DskipTests clean package
|
||||
- echo target/ns-usbloader-*jar
|
||||
- cp target/ns-usbloader-*jar /builds/ns-usbloader/
|
||||
volumes:
|
||||
- name: m2
|
||||
path: /root/.m2
|
||||
- name: builds
|
||||
path: /builds
|
||||
|
||||
volumes:
|
||||
- name: m2
|
||||
host:
|
||||
path: /home/docker/drone/files/m2
|
||||
- name: builds
|
||||
host:
|
||||
path: /home/www/builds
|
||||
- name: jdk
|
||||
host:
|
||||
path: /home/docker/drone/files/assembly/openjdk-19.0.2
|
||||
- name: drivers
|
||||
host:
|
||||
path: /home/docker/drone/files/assembly/Drivers_set.exe
|
|
@ -0,0 +1,2 @@
|
|||
offsets.txt
|
||||
environment.txt
|
|
@ -0,0 +1,3 @@
|
|||
sed -z -i -e 's/<groupId>org.usb4java<\/groupId>\n\s*<artifactId>usb4java<\/artifactId>\s*<version>1.3.0<\/version>/<groupId>org.usb4java<\/groupId>\n<artifactId>usb4java<\/artifactId>\n<version>1.2.0<\/version>/g' pom.xml
|
||||
sed -z -i -e 's/<finalName>${project.artifactId}-${project.version}-${maven.build.timestamp}<\/finalName>/<finalName>${project.artifactId}-${project.version}-legacy-${maven.build.timestamp}<\/finalName>/g' pom.xml
|
||||
sed -z -i -e 's/<jar>target\/${project.artifactId}-${project.version}-${maven.build.timestamp}.jar<\/jar>/<jar>target\/${project.artifactId}-${project.version}-legacy-${maven.build.timestamp}.jar<\/jar>/g' pom.xml
|
|
@ -0,0 +1,5 @@
|
|||
sed -z -i -e 's/<groupId>org.usb4java<\/groupId>\n<artifactId>usb4java<\/artifactId>\n<version>1.2.0<\/version>/<groupId>org.usb4java<\/groupId>\n<artifactId>usb4java<\/artifactId>\n<version>1.3.0<\/version>/g' pom.xml
|
||||
sed -z -i -e 's/<classifier>mac<\/classifier>/<classifier>mac-aarch64<\/classifier>/g' pom.xml
|
||||
sed -z -i -e 's/<finalName>${project.artifactId}-${project.version}-legacy-${maven.build.timestamp}<\/finalName>/<finalName>${project.artifactId}-${project.version}-m1-${maven.build.timestamp}<\/finalName>/g' pom.xml
|
||||
sed -i -e '/<groupId>com.akathist.maven.plugins.launch4j/,/<\/executions>/d' pom.xml
|
||||
sed -z -i -e 's/<plugin>\n\s*<\/plugin>//g' pom.xml
|
|
@ -1,31 +0,0 @@
|
|||
pipeline {
|
||||
agent {
|
||||
docker {
|
||||
image 'maven:3-jdk-11'
|
||||
args '-v /home/docker/jenkins/files/m2:/root/.m2'
|
||||
}
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -B -DskipTests clean package'
|
||||
}
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: 'target/*.jar, target/*.exe'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn test'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'target/surefire-reports/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
109
README.md
|
@ -1,12 +1,11 @@
|
|||
# NS-USBloader
|
||||
<h1 align="center"><img src="screenshots/ApplicationLogo.svg" alt="NS-USBloader" width="450px"/></h1>
|
||||
|
||||
![License](https://img.shields.io/badge/License-GPLv3-blue.svg) ![Releases](https://img.shields.io/github/downloads/developersu/ns-usbloader/total.svg) ![LatestVer](https://img.shields.io/github/release/developersu/ns-usbloader.svg) ![CI](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fredrise.ru%2Fjen%2Fjob%2Fns-usbloader%2Fjob%2Fmaster%2F)
|
||||
[Support author](#support-this-app)
|
||||
![License](https://img.shields.io/badge/License-GPLv3-blue.svg) ![Releases](https://img.shields.io/github/downloads/developersu/ns-usbloader/total.svg) ![LatestVer](https://img.shields.io/github/release/developersu/ns-usbloader.svg) [![Build Status](https://ci.redrise.ru/api/badges/desu/ns-usbloader/status.svg)](https://ci.redrise.ru/desu/ns-usbloader)
|
||||
|
||||
NS-USBloader is:
|
||||
* A PC-side installer for **[Huntereb/Awoo-Installer](https://github.com/Huntereb/Awoo-Installer)** / other compatible installers (USB and Network supported) and **[XorTroll/GoldLeaf](https://github.com/XorTroll/Goldleaf)** (USB) NSP installer.
|
||||
* A PC-side installer for **[Huntereb/Awoo-Installer](https://github.com/Huntereb/Awoo-Installer)** / other compatible installers (USB and Network supported) and **[XorTroll/Goldleaf](https://github.com/XorTroll/Goldleaf)** (USB) NSP installer.
|
||||
Alternative to default **usb_install_pc.py**, **remote_install_pc.py**, **GoldTree**/**Quark**.
|
||||
* This application also could be used as RCM payload on Windows, MacOS and Linux (supported arch: x86, x86_64 and Raspberry Pi).
|
||||
* RCM payload tool that works on Windows, macOS (Intel and Apple Silicon) and Linux (x86, amd64 and Raspberry Pi ARM).
|
||||
* It's a tool for creating split files!
|
||||
* Also you can use it for merging split-files into one :)
|
||||
|
||||
|
@ -14,12 +13,18 @@ Alternative to default **usb_install_pc.py**, **remote_install_pc.py**, **GoldTr
|
|||
[Click here for Android version ;)](https://github.com/developersu/ns-usbloader-mobile)
|
||||
|
||||
With GUI and cookies. Works on Windows, macOS and Linux.
|
||||
### Let's stay in touch:
|
||||
#### [→ Independent source code storage](https://git.redrise.ru/desu/ns-usbloader)
|
||||
#### [→ Mirror, issues tracker, place to send PRs](https://github.com/developersu/ns-usbloader)
|
||||
#### [→ Nightly builds](https://redrise.ru/builds/ns-usbloader/)
|
||||
|
||||
Sometimes I add new posts about this project [on my home page](https://developersu.blogspot.com/search/label/NS-USBloader).
|
||||
[Support/Donate](#support-this-app)
|
||||
|
||||
![Application screenshot](screenshots/1.png)
|
||||
<img src="screenshots/2.png" alt="screenshot" width="250"/> <img src="screenshots/3.png" alt="screenshot" width="250"/>
|
||||
<img src="screenshots/4.png" alt="screenshot" width="250"/> <img src="screenshots/5.png" alt="screenshot" width="250"/>
|
||||
Sometimes I add new posts about this project [on my blog page](https://developersu.blogspot.com/search/label/NS-USBloader).
|
||||
|
||||
<img src="screenshots/1.png" alt="screenshot" width="250"/> <img src="screenshots/2.png" alt="screenshot" width="250"/>
|
||||
<img src="screenshots/3.png" alt="screenshot" width="250"/> <img src="screenshots/4.png" alt="screenshot" width="250"/>
|
||||
<img src="screenshots/5.png" alt="screenshot" width="250"/>
|
||||
|
||||
#### License
|
||||
|
||||
|
@ -37,34 +42,41 @@ Sometimes I add new posts about this project [on my home page](https://developer
|
|||
* [Pablo Curiel (DarkMatterCore)](https://github.com/DarkMatterCore)
|
||||
* [wolfposd](https://github.com/wolfposd)
|
||||
* [agungrbudiman](https://github.com/agungrbudiman)
|
||||
* Perfect algorithms and great examples taken from mrdude project [mrdude2478/IPS_Patch_Creator](https://github.com/mrdude2478/IPS_Patch_Creator/)
|
||||
|
||||
* French by [Stephane Meden (JackFromNice)](https://github.com/JackFromNice)
|
||||
* Italian by [unbranched](https://github.com/unbranched)
|
||||
* Korean by [DDinghoya](https://github.com/DDinghoya)
|
||||
* Portuguese by [almircanella](https://github.com/almircanella)
|
||||
* Spanish by [/u/cokimaya007](https://www.reddit.com/u/cokimaya007), Kuziel Alejandro
|
||||
* Chinese (Simplified) by [Huang YunKun (htynkn)](https://github.com/htynkn), [FFT9 (XXgame Group)](https://www.xxgame.net)
|
||||
* Chinese (Traditional) by [qazrfv1234](https://github.com/qazrfv1234), [FFT9 (XXgame Group)](https://www.xxgame.net)
|
||||
* Spanish by [/u/cokimaya007](https://www.reddit.com/u/cokimaya007), [Kuziel Alejandro](https://github.com/Uzi-Oni)
|
||||
* Chinese (Simplified) by [Huang YunKun (htynkn)](https://github.com/htynkn), [FFT9 (XXgame Group)](http://xxgame.net/)
|
||||
* Chinese (Traditional) by [qazrfv1234](https://github.com/qazrfv1234), [FFT9 (XXgame Group)](http://xxgame.net/)
|
||||
* German by [Swarsele](https://github.com/Swarsele)
|
||||
* Vietnamese by [Hai Phan Nguyen (pnghai)](https://github.com/pnghai)
|
||||
* Czech by [Spenaat](https://github.com/spenaat)
|
||||
* Arabic by [eslamabdel](https://github.com/eslamabdel)
|
||||
* Romanian by [Călin Ilie](https://github.com/calini)
|
||||
* Swedish by [Daniel Nylander](https://github.com/yeager)
|
||||
* Japanese by [kuragehime](https://github.com/kuragehimekurara1)
|
||||
* Ryukyuan languages by [kuragehime](https://github.com/kuragehimekurara1)
|
||||
|
||||
* Angelo Elias Dalzotto makes packages in AUR
|
||||
* Phoenix[Msc] provides his shiny Mac M1 for debug
|
||||
|
||||
### System requirements
|
||||
|
||||
JRE/JDK 8u60 or higher for Windows
|
||||
- JDK 11 for macOS and Linux
|
||||
- libusb, if you have a Mac with Apple Silicon (install via `brew install libusb`)
|
||||
|
||||
JDK 11 for MacOS and Linux
|
||||
|
||||
### Supported GoldLeaf versions
|
||||
| GoldLeaf version | NS-USBloader version |
|
||||
| ---------------- | -------------------- |
|
||||
### Supported Goldleaf versions
|
||||
| Goldleaf version | NS-USBloader version |
|
||||
|------------------|----------------------|
|
||||
| v0.5 | v0.4 - v0.5.2, v0.8+ |
|
||||
| v0.6 | none |
|
||||
| v0.6.1 | v0.6 |
|
||||
| v0.7 - 0.7.3 | v0.7+ |
|
||||
| v0.8 - 0.9 | v1.0+ |
|
||||
| v0.10 | v6.0+ |
|
||||
|
||||
where '+' means 'any next NS-USBloader version'.
|
||||
|
||||
|
@ -94,6 +106,8 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="0955", ATTRS{idProduct}=="7321", MODE="0666"
|
|||
root # udevadm control --reload-rules && udevadm trigger
|
||||
```
|
||||
|
||||
5. For HiDPI use scaling like `java -Dglass.gtk.uiScale=150% -jar application.jar`
|
||||
|
||||
##### Raspberry Pi
|
||||
|
||||
1. Install JDK: `sudo apt install default-jdk`
|
||||
|
@ -108,24 +122,23 @@ Double-click on downloaded .jar file. Follow instructions. Or see 'Linux' sectio
|
|||
|
||||
Set 'Security & Privacy' settings if needed.
|
||||
|
||||
*Please note: JDK 11 is recommended for using on MacOS (EXCEPT APPLE SILICONE). There are few really weird issues already reported from JDK 14 users on Mac.*
|
||||
*Please note: JDK 19 is recommended for using on macOS. There are issues already reported from users on Mac with JDK 14.*
|
||||
|
||||
##### macOS on Apple Silicon (ARM)
|
||||
|
||||
* Some users [tested](https://github.com/developersu/ns-usbloader/issues/91) this application with [Zulu-JDK with FX support](https://www.azul.com/downloads/zulu-community/?version=java-11-lts&os=macos&architecture=arm-64-bit&package=jdk-fx). Try it!
|
||||
* OpenJDK 17 also should be a working solution.
|
||||
Download application with `-m1.jar` postfix.
|
||||
|
||||
Manually install libusb with Homebrew by running `brew install libusb` in your Terminal.
|
||||
|
||||
##### Windows:
|
||||
|
||||
* [Download and install Java JRE](http://java.com/download/) (8u60 or higher)
|
||||
* Get this application (JAR file) and double-click on on it (alternatively open 'cmd', go to place where jar located and execute via `java -jar thisAppName.jar`)
|
||||
* Once application opens click on 'Gear' icon.
|
||||
* Click 'Download and install drivers'
|
||||
* Install drivers
|
||||
|
||||
#### And how to use it?
|
||||
|
||||
The first thing you should do it install Awoo ([Huntereb](https://github.com/Huntereb/Awoo-Installer)) or GoldLeaf ([XorTroll](https://github.com/XorTroll/Goldleaf)) on your NS.
|
||||
The first thing you should do it install Awoo ([Huntereb](https://github.com/Huntereb/Awoo-Installer)) or Goldleaf ([XorTroll](https://github.com/XorTroll/Goldleaf)) on your NS.
|
||||
|
||||
Take a look on app, find where is the option to install from USB and/or Network. Maybe (very old) [this article (about TinFoil)](https://developersu.blogspot.com/2019/02/ns-usbloader-en.html) will be helpful.
|
||||
|
||||
|
@ -135,19 +148,19 @@ There are three tabs. First one is main.
|
|||
|
||||
##### 'Gamepad' tab.
|
||||
|
||||
At the top of you selecting from drop-down application and protocol that you're going to use. For GoldLeaf only USB is available. Lamp icon stands for switching themes (light or dark).
|
||||
At the top of you selecting from drop-down application and protocol that you're going to use. For Goldleaf only USB is available. Lamp icon stands for switching themes (light or dark).
|
||||
|
||||
Then you may drag-n-drop files (split-files aka folders) to application or use 'Select NSP files' button. Multiple selection for files available. Click it again and select files from another folder it you want, it will be added into the table.
|
||||
|
||||
Table.
|
||||
|
||||
There you can select checkbox for files that will be sent to application (AW/GL). ~~Since GoldLeaf v0.5 allow you only one file transmission per time, only one file is available for selection.~~
|
||||
There you can select checkbox for files that will be sent to application (AW/GL). ~~Since Goldleaf v0.5 allow you only one file transmission per time, only one file is available for selection.~~
|
||||
|
||||
Also you can use space to select/un-select files and 'delete' button for deleting. By right-mouse-click you can see context menu where you can delete one OR all items from the table.
|
||||
Also, you can use space to select/un-select files and 'delete' button for deleting. By right-mouse-click you can see context menu where you can delete one OR all items from the table.
|
||||
|
||||
For GoldLeaf v0.6.1 and NS-USBloader v0.6 (and higher) you will have to use 'Explore content' -> 'Remote PC (via USB)' You will see two drives HOME:/ and VIRT:/. First drive is pointing to your home directory. Second one is reflection of what you've added to table (first application tab). Also VIRT:/ drive have limited functionality in comparison to HOME:/. E.g. you can't write files to this drive since it's not a drive. But don't worry, it won't make any impact on GoldLeaf or your NS if you try.
|
||||
For Goldleaf v0.6.1 and NS-USBloader v0.6 (and higher) you will have to use 'Explore content' -> 'Remote PC (via USB)' You will see two drives HOME:/ and VIRT:/. First drive is pointing to your home directory. Second one is reflection of what you've added to table (first application tab). Also VIRT:/ drive have limited functionality in comparison to HOME:/. E.g. you can't write files to this drive since it's not a drive. But don't worry, it won't make any impact on Goldleaf or your NS if you try.
|
||||
|
||||
Also, for GoldLeaf write files (from NS to PC): You have to 'Stop execution' properly before accessing files transferred from GL. Usually you have to wait 5sec or less. It will guarantee that your files properly written to PC.
|
||||
Also, for Goldleaf write files (from NS to PC): You have to 'Stop execution' properly before accessing files transferred from GL. Usually you have to wait 5sec or less. It will guarantee that your files properly written to PC.
|
||||
|
||||
##### 'RCM' tab
|
||||
|
||||
|
@ -163,7 +176,7 @@ Here you can configure settings for network file transmission. Usually you shoul
|
|||
|
||||
Also here you can:
|
||||
* Set 'Auto-check for updates' for checking for updates when application starts, or click button to verify if new version released immediately.
|
||||
* Set 'Show only *.nsp in GoldLeaf' to filter all files displayed at HOME:/ drive. So only NSP files will appear.
|
||||
* Set 'Show only *.nsp in Goldleaf' to filter all files displayed at HOME:/ drive. So only NSP files will appear.
|
||||
|
||||
##### 'Dialog with three dots' tab.
|
||||
|
||||
|
@ -176,7 +189,7 @@ To get help run ``$ java -jar ns-usbloader-4.0.jar --help``
|
|||
|
||||
```
|
||||
-c,--clean Remove/reset settings and exit
|
||||
-g,--goldleaf <...> Install via GoldLeaf mode. Check '-g help' for information.
|
||||
-g,--Goldleaf <...> Install via Goldleaf mode. Check '-g help' for information.
|
||||
-h,--help Show this help
|
||||
-m,--merge <...> Merge files. Check '-m help' for information.
|
||||
-n,--tfn <...> Install via Awoo Network mode. Check '-n help' for information.
|
||||
|
@ -207,7 +220,7 @@ Send RCM payload:
|
|||
$ java -jar ns-usbloader-4.0.jar -r C:\Users\Superhero\hekate.bin
|
||||
Send files to Awoo Installer via Net-install:
|
||||
$ java -jar ns-usbloader-4.0.jar -n nsip=192.168.0.1 ./file.nsz ./file.nsp ~/*.xci
|
||||
Send files to GoldLeaf v0.8:
|
||||
Send files to Goldleaf v0.8:
|
||||
$ java -jar ns-usbloader-4.0.jar -g ver=v0.8 ./*
|
||||
Split files:
|
||||
$ java -jar ns-usbloader-4.0.jar -s /tmp/ ~/*.nsp
|
||||
|
@ -218,9 +231,16 @@ $ java -jar ns-usbloader-4.0.jar -m /tmp/ ~/*.nsp
|
|||
### Other notes
|
||||
|
||||
'Status' = 'Uploaded' that appears in the table does not mean that file has been installed. It means that it has been sent to NS without any issues! That's what this app about.
|
||||
Handling successful/failed installation is a purpose of the other side application: Awoo/Awoo-like or GoldLeaf. And they don't provide any feedback interfaces so I can't detect success/failure.
|
||||
Handling successful/failed installation is a purpose of the other side application: Awoo/Awoo-like or Goldleaf. And they don't provide any feedback interfaces so I can't detect success/failure.
|
||||
|
||||
usb4java since NS-USBloader-v0.2.3 switched to 1.2.0 instead of 1.3.0. This should not impact anyone except users of macOS High Sierra (and Sierra, and El Capitan) where previous versions of NS-USBloader didn't work. Now builds with usb4java-1.2.0 marked as '-legacy' and builds with usb4java-1.3.0 doesn't have postfixes.
|
||||
#### What is this '-legacy' jar?!
|
||||
|
||||
**JAR with NO postfixes** recommended for Windows users, Linux users and macOS users who're using Mojave or later versions.
|
||||
|
||||
**JAR with '-legacy' postfix** is for macOS users who're still using OS X releases before (!) Mojave.
|
||||
(It also works for Linux and for Windows, but sometimes it doesn't work for Windows and I don't know why).
|
||||
|
||||
We have this situation because of weird behaviour inside usb4java library used in this application for USB interactions. In '-legacy' it's v1.2.0 and in 'normal' it's v1.3.0
|
||||
|
||||
### Translators!
|
||||
|
||||
|
@ -232,18 +252,21 @@ To convert files of any locale to readable format (and vise-versa) you can use t
|
|||
|
||||
## Support this app
|
||||
|
||||
If you like this app, just give a star.
|
||||
If you like this app, just give a star (@ GitHub).
|
||||
|
||||
If you want to make a donation*, please see below:
|
||||
This is non-commercial project.
|
||||
|
||||
<a href="https://liberapay.com/developersu/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
|
||||
Nevertheless, I'll be more than happy if you find a chance to make a donation for charity to people I trust:
|
||||
|
||||
<a href="https://paypal.me/developersu" title="PayPal"><img src="https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-100px.png" border="0" alt="PayPal Logo" /></a>
|
||||
* BTC → 1BnErE3n6LEdEjvvFrt4FMdXd1UGa5L7Ge
|
||||
* ETH → 0x9c29418129553bE171181bb6245151aa0576A3b7
|
||||
* DOT → 15BWSwmA4xEHZdq3gGftWg7dctMQk9vXwqA92Pg22gsxDweF
|
||||
* LTC → ltc1qfjvzxm04tax077ra9rvmxdnsum8alws2n20fag
|
||||
* ETC → 0xe9064De288C8454942533a005AB72515e689226E
|
||||
* USDT (TRC20) → TKgp5SvJGiqYNFtvJfEDGLFbezFEHq1tBy
|
||||
* USDT (ERC20) → 0x9c29418129553bE171181bb6245151aa0576A3b7
|
||||
* XRP → rGmGaLsKmSUbxWfyi4mujtVamTzj3Nqxbw.
|
||||
|
||||
[yoomoney](https://yoomoney.ru/to/410014301951665)
|
||||
|
||||
*Please note: this is non-commercial application.
|
||||
|
||||
Thanks
|
||||
Thanks!
|
||||
|
||||
Appreciate assistance and support of both [Vitaliy](https://github.com/SebastianUA) and [Konstantin](https://github.com/konstantin-kelemen). Without you all this magic would not have happened.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=NS-USBloader
|
||||
Exec=ns-usbloader
|
||||
Comment=NS multi tool
|
||||
Terminal=false
|
||||
Icon=ns-usbloader.svg
|
||||
Categories=Game;
|
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="45mm"
|
||||
height="45mm"
|
||||
viewBox="0 0 45.000001 45"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="ns-usbloader.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6568543"
|
||||
inkscape:cx="206.82873"
|
||||
inkscape:cy="90.421279"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="svg8"
|
||||
showgrid="false"
|
||||
units="mm"
|
||||
inkscape:window-width="3754"
|
||||
inkscape:window-height="2127"
|
||||
inkscape:window-x="1166"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid829"
|
||||
originx="-40.993993"
|
||||
originy="-37.999754" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="g851"
|
||||
inkscape:label="mainGRP"
|
||||
transform="translate(-40.993968,-26.999903)">
|
||||
<path
|
||||
id="path847"
|
||||
transform="scale(0.26458333)"
|
||||
d="m 188.97656,102.04688 c -18.97637,0 -34.01562,18.70089 -34.01562,30.23632 -0.0219,42.2441 -0.0386,69.16374 0,109.60742 0,11.85827 15.03925,30.23633 34.01562,30.23633 h 48.94141 V 102.04688 Z"
|
||||
style="fill:#00c8fc;fill-opacity:1;stroke-width:1"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="con" />
|
||||
<path
|
||||
id="rect823"
|
||||
d="m 64.973294,26.999903 v 45 h 21.02 v -45 z"
|
||||
style="fill:#ec0000;fill-opacity:1;stroke-width:0.116442"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="big" />
|
||||
</g>
|
||||
<path
|
||||
id="path862"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.392613"
|
||||
d="m 11.547015,28.4105 a 2.1593723,2.1593723 0 0 0 -2.2000565,2.117691 2.1593723,2.1593723 0 0 0 2.1176905,2.200059 2.1593723,2.1593723 0 0 0 2.200555,-2.1167 2.1593723,2.1593723 0 0 0 -2.1167,-2.20105 l -0.04267,2.158874 z m 3.840427,-3.937182 a 2.1593723,2.1593723 0 0 0 -2.199561,2.117693 2.1593723,2.1593723 0 0 0 2.117195,2.200057 2.1593723,2.1593723 0 0 0 2.200555,-2.117195 2.1593723,2.1593723 0 0 0 -2.1167,-2.200555 l -0.04217,2.158876 z m -7.6809635,0 a 2.1593722,2.1593722 0 0 0 -2.200057,2.117693 2.1593722,2.1593722 0 0 0 2.117691,2.200057 2.1593722,2.1593722 0 0 0 2.200554,-2.117195 2.1593722,2.1593722 0 0 0 -2.117195,-2.200555 l -0.04218,2.158876 z m 3.8405365,-3.938173 a 2.1593723,2.1593723 0 0 0 -2.2000565,2.117691 2.1593723,2.1593723 0 0 0 2.1176905,2.200059 2.1593723,2.1593723 0 0 0 2.200555,-2.1167 2.1593723,2.1593723 0 0 0 -2.1167,-2.20105 l -0.04267,2.158874 z"
|
||||
inkscape:label="small_c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
inkscape:label="slogan"
|
||||
id="layer1"
|
||||
transform="translate(-40.993968,-213.9999)"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
aria-label="everywhere"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,-24.077084,181.70833)"
|
||||
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:35.0667px;line-height:1.25;font-family:Raleway;-inkscape-font-specification:'Raleway, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="flowRoot1022"
|
||||
inkscape:label="flowRoot1022"
|
||||
inkscape:groupmode="layer" />
|
||||
</g>
|
||||
<path
|
||||
id="path853"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.272727"
|
||||
d="m 11.506852,6.300096 a 4.5000001,4.5000001 0 0 1 4.49918,4.500616 4.5000001,4.5000001 0 0 1 -4.500411,4.499384 4.5000001,4.5000001 0 0 1 -4.4995895,-4.500205 4.5000001,4.5000001 0 0 1 4.5000005,-4.499795"
|
||||
inkscape:label="big_c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path1334"
|
||||
d="m 35.091899,7.050931 -1.966235,3.404775 h 1.402615 v 17.402765 l -3.579993,-3.388515 c -0.231149,-0.288377 -0.393301,-0.665687 -0.402284,-1.053816 0,-1.570143 -3.97e-4,-2.502567 -9.76e-4,-2.845788 0.662828,-0.232646 1.141253,-0.857572 1.141253,-1.600489 0,-0.939842 -0.76265,-1.702559 -1.702831,-1.702559 -0.940589,0 -1.702967,0.76265 -1.702967,1.702559 0,0.742917 0.478154,1.367843 1.140438,1.600489 l -4.76e-4,2.812447 c 0,0.762241 0.418205,1.560957 0.90847,2.069322 -0.01456,-0.01388 -0.03007,-0.02831 2.83e-4,8.15e-4 0.01211,0.01075 3.797875,3.595101 3.797875,3.595101 0.230809,0.287762 0.39194,0.664868 0.401196,1.052727 v 1.968677 c -1.30057,0.260954 -2.28042,1.409421 -2.28042,2.787065 0,1.570687 1.273194,2.843881 2.843405,2.843881 1.570686,0 2.843946,-1.273194 2.843946,-2.843881 0,-1.377917 -0.980663,-2.526381 -2.282303,-2.787335 v -1.934186 c 0,-0.005 2.59e-4,-0.0099 0,-0.01498 v -4.278078 c 0.0098,-0.38711 0.171203,-0.763741 0.402285,-1.051231 0,0 3.785488,-3.583532 3.797733,-3.594625 0.03043,-0.02872 0.01454,-0.01444 2.59e-4,-2.58e-4 0.490197,-0.508364 0.908134,-1.307418 0.908134,-2.069798 l -3.97e-4,-2.710376 h 1.141588 v -3.405646 h -3.405338 v 3.405663 h 1.140097 c 0,0 -0.0012,0.713861 -0.0012,2.743583 -0.0089,0.388196 -0.170862,0.765917 -0.402012,1.054155 l -3.580815,3.389238 V 10.455706 h 1.404858 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff;stroke-width:0.0680452"
|
||||
inkscape:label="usb_logo" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
d="m 21.967046,0 c -0.0065,-1.9994448e-6 -0.01188,0.0054 -0.01188,0.01188 v 44.976581 c 0,0.0065 0.0054,0.01188 0.01188,0.01188 h 2.000395 c 0.0065,0 0.01188,-0.0054 0.01188,-0.01188 V 0.011885 c 0,-0.0065 -0.0054,-0.011879999445 -0.01188,-0.011879999445 z"
|
||||
id="rect1136"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csssssssc" />
|
||||
</svg>
|
After Width: | Height: | Size: 6.5 KiB |
|
@ -0,0 +1,8 @@
|
|||
#### How to prepare JRE from JDK to bundle it with application
|
||||
|
||||
1. Run `java --list-modules`
|
||||
2. Update resulting list s/@.*\n/\,/g
|
||||
3. Run `jlink --no-header-files --no-man-pages --compress=2 --add-modules !!!_PASTE_RESULT_HERE_!!! --output jre`
|
||||
4. JRE created at folder 'jre
|
||||
|
||||
jlink --no-header-files --no-man-pages --compress=2 --add-modules $($(java --list-modules) -join "," -replace "@[0-9].*") --output jre-11'
|
|
@ -0,0 +1,160 @@
|
|||
;Include Modern UI
|
||||
!include "MUI.nsh"
|
||||
Unicode true
|
||||
;Name and file
|
||||
|
||||
!define APPNAME "NS-USBloader"
|
||||
!define COMPANYNAME "Dmitry Isaenko"
|
||||
!define VERSIONMAJOR 0
|
||||
!define VERSIONMINOR 0
|
||||
!define VERSIONBUILD 0
|
||||
|
||||
Name "NS-USBloader"
|
||||
OutFile "Installer.exe"
|
||||
|
||||
;Default installation folder
|
||||
InstallDir "$PROGRAMFILES\${APPNAME}"
|
||||
|
||||
;Get installation folder from registry if available
|
||||
InstallDirRegKey HKCU "Software\${APPNAME}" ""
|
||||
|
||||
;Request application privileges for Windows Vista
|
||||
RequestExecutionLevel admin
|
||||
|
||||
!define MUI_ICON installer_logo.ico
|
||||
!define MUI_UNICON uninstaller_logo.ico
|
||||
; !define MUI_FINISHPAGE_NOAUTOCLOSE
|
||||
|
||||
!define MUI_WELCOMEFINISHPAGE_BITMAP "leftbar.bmp"
|
||||
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "leftbar_uninstall.bmp"
|
||||
|
||||
!define MUI_FINISHPAGE_LINK "NS-USBloader at GitHub"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION https://github.com/developersu/NS-USBloader/
|
||||
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\NS-USBloader.exe"
|
||||
!define MUI_FINISHPAGE_SHOWREADME
|
||||
!define MUI_FINISHPAGE_SHOWREADME_TEXT $(l10n_CreateShortcut)
|
||||
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortCut
|
||||
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
||||
;--------------------------------
|
||||
;Interface Settings
|
||||
|
||||
!define MUI_ABORTWARNING
|
||||
;--------------------------------
|
||||
;Language Selection Dialog Settings
|
||||
|
||||
;Remember the installer language
|
||||
!define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
|
||||
!define MUI_LANGDLL_REGISTRY_KEY "Software\${APPNAME}"
|
||||
!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
|
||||
|
||||
;--------------------------------
|
||||
;Pages
|
||||
;!define MUI_HEADERIMAGE
|
||||
;!define MUI_HEADERIMAGE_RIGHTi
|
||||
;!define MUI_HEADERIMAGE_BITMAP "install_header.bmp"
|
||||
;!define MUI_HEADERIMAGE_UNBITMAP "install_header.bmp"
|
||||
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
;--------------------------------
|
||||
;Languages
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "SpanishInternational"
|
||||
!insertmacro MUI_LANGUAGE "SimpChinese"
|
||||
!insertmacro MUI_LANGUAGE "TradChinese"
|
||||
!insertmacro MUI_LANGUAGE "Japanese"
|
||||
!insertmacro MUI_LANGUAGE "Korean"
|
||||
!insertmacro MUI_LANGUAGE "Italian"
|
||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||
!insertmacro MUI_LANGUAGE "Vietnamese"
|
||||
!insertmacro MUI_LANGUAGE "Arabic"
|
||||
!insertmacro MUI_LANGUAGE "Czech"
|
||||
!insertmacro MUI_LANGUAGE "Romanian"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "Swedish"
|
||||
|
||||
;Language strings
|
||||
LangString l10n_CreateShortcut ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||
LangString l10n_CreateShortcut ${LANG_RUSSIAN} "Создать ярлык на Рабочем столе"
|
||||
|
||||
;--------------------------------
|
||||
Section "NS-USBloader" Install
|
||||
|
||||
SetOutPath "$INSTDIR"
|
||||
file /r jdk
|
||||
file Drivers_set.exe
|
||||
file NS-USBloader.exe
|
||||
file logo.ico
|
||||
|
||||
; Registry information for add/remove programs
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "Publisher" "$\"${COMPANYNAME}$\""
|
||||
|
||||
; Start Menu
|
||||
CreateDirectory "$SMPROGRAMS\${APPNAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\NS-USBloader.exe" "" "$INSTDIR\logo.ico"
|
||||
CreateShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
;Store installation folder
|
||||
WriteRegStr HKCU "Software\${APPNAME}" "" $INSTDIR
|
||||
|
||||
;Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
SectionEnd
|
||||
;--------------------------------
|
||||
;Installer Functions
|
||||
|
||||
Function .onInit
|
||||
; set mandatory installation rule to section
|
||||
SectionSetFlags ${Install} 17
|
||||
FunctionEnd
|
||||
|
||||
Function un.onInit
|
||||
!insertmacro MUI_UNGETLANGUAGE
|
||||
FunctionEnd
|
||||
|
||||
|
||||
Function CreateDesktopShortCut
|
||||
CreateShortcut "$DESKTOP\NS-USBloader.lnk" "$INSTDIR\NS-USBloader.exe"
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Uninstaller Section
|
||||
|
||||
Section "Uninstall"
|
||||
|
||||
; Start Menu
|
||||
Delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk"
|
||||
Delete "$SMPROGRAMS\${APPNAME}\Uninstall.lnk"
|
||||
Delete "$DESKTOP\NS-USBloader.lnk"
|
||||
rmDir "$SMPROGRAMS\${APPNAME}"
|
||||
|
||||
;Delete installed files
|
||||
RMDir /r "$INSTDIR\jdk\*"
|
||||
Delete "$INSTDIR\Drivers_set.exe"
|
||||
Delete "$INSTDIR\NS-USBloader.exe"
|
||||
Delete "$INSTDIR\logo.ico"
|
||||
Delete "$SMPROGRAMS\Uninstall.exe"
|
||||
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
DeleteRegKey /ifempty HKCU "Software\${APPNAME}"
|
||||
; Cleanup records stored for uninstaller from the registry
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
|
||||
|
||||
SectionEnd
|
||||
;--------------------------------
|
||||
;Uninstaller Functions
|
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 151 KiB |
After Width: | Height: | Size: 151 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 114 KiB |
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
TIMESTAMP=`date +%Y%m%d.%H%M%S`
|
||||
VERSIONMAJOR=`grep '<version>' pom.xml | head -1 | sed -e 's/^.*<version>//g' -e 's/\..*$//g'`
|
||||
VERSIONMINOR=`grep '<version>' pom.xml | head -1 | sed -E 's/^.*<version>[0-9]+?\.//g' | sed -E -e 's/(\..*|-SNAPSHOT|)<\/version>.*$//g'`
|
||||
sed -z -i -e "s/!define\ VERSIONMAJOR\ [0-9]/!define\ VERSIONMAJOR $VERSIONMAJOR\ /" misc/windows/NSIS/installer.nsi
|
||||
sed -z -i -e "s/!define\ VERSIONMINOR\ [0-9]/!define\ VERSIONMINOR $VERSIONMINOR\ /" misc/windows/NSIS/installer.nsi
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
sed -z -i -e "s/OutFile\ \"Installer.exe\"/OutFile\ \"Installer-$VERSIONMAJOR.$VERSIONMINOR-$TIMESTAMP.exe\"\ /" misc/windows/NSIS/installer.nsi
|
||||
else
|
||||
sed -z -i -e "s/OutFile\ \"Installer-$VERSIONMAJOR.$VERSIONMINOR-[0-9]*\.[0-9]*.exe\"/OutFile\ \"Installer-legacy-$VERSIONMAJOR.$VERSIONMINOR-$TIMESTAMP.exe\"\ /" misc/windows/NSIS/installer.nsi
|
||||
fi
|
163
pom.xml
|
@ -8,12 +8,10 @@
|
|||
<name>NS-USBloader</name>
|
||||
|
||||
<artifactId>ns-usbloader</artifactId>
|
||||
<version>5.2-SNAPSHOT</version>
|
||||
<version>7.1</version> <!-- linked via script to NSIS system. Should have format of 2 blocks of numbers -->
|
||||
|
||||
<url>https://github.com/developersu/ns-usbloader/</url>
|
||||
<description>
|
||||
NSP USB loader for Awoo Installer and compatible (USB and Network) and GoldLeaf
|
||||
</description>
|
||||
<url>https://redrise.ru</url>
|
||||
<description>NS multi-tool</description>
|
||||
<inceptionYear>2019</inceptionYear>
|
||||
<organization>
|
||||
<name>Dmitry Isaenko</name>
|
||||
|
@ -40,106 +38,96 @@
|
|||
</developer>
|
||||
</developers>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>redrise</id>
|
||||
<name>redrise.ru repository</name>
|
||||
<url>https://repo.redrise.ru/releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.build.timestamp.format>yyyyMMdd.HHmmss</maven.build.timestamp.format>
|
||||
<javafx.version>19.0.2.1</javafx.version>
|
||||
<maven.compiler.release>11</maven.compiler.release>
|
||||
</properties>
|
||||
|
||||
<issueManagement>
|
||||
<system>GitHub</system>
|
||||
<url>https://github.com/developer_su/${project.artifactId}/issues</url>
|
||||
<url>https://github.com/developersu/${project.artifactId}/issues</url>
|
||||
</issueManagement>
|
||||
<!-- openJFX Linux -->
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.4</version>
|
||||
<version>1.5.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- openJFX Linux -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>17</version>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>17</version>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>17</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>17</version>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>linux</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- openJFX Windows -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>17</version>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>17</version>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>17</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>17</version>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>win</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- openJFX MAC -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>17</version>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>17</version>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>17</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>17</version>
|
||||
<version>${javafx.version}</version>
|
||||
<classifier>mac</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
@ -154,24 +142,53 @@
|
|||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.5.2</version>
|
||||
<version>5.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.5.2</version>
|
||||
<version>5.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.5.2</version>
|
||||
<version>5.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- redrise repository -->
|
||||
<dependency>
|
||||
<groupId>ru.redrise</groupId>
|
||||
<artifactId>libKonogonka</artifactId>
|
||||
<version>0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${project.artifactId}-${project.version}-${maven.build.timestamp}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources-filtered</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<!--OpenJFX for Java9+
|
||||
<plugin>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-maven-plugin</artifactId>
|
||||
<version>0.0.8</version>
|
||||
<configuration>
|
||||
<mainClass>nsusbloader.NSLMain</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
-->
|
||||
<!-- Junit5 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -186,16 +203,23 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<release>11</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Don't generate default JAR without dependencies -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>3.1.2</version>
|
||||
<!--
|
||||
<configuration>
|
||||
<manifestEntries>
|
||||
<Automatic-Module-Name>nsusbloader</Automatic-Module-Name>
|
||||
</manifestEntries>
|
||||
</configuration>
|
||||
-->
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-jar</id>
|
||||
|
@ -217,6 +241,7 @@
|
|||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
@ -228,14 +253,13 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Launch4j
|
||||
<plugin>
|
||||
<groupId>com.akathist.maven.plugins.launch4j</groupId>
|
||||
<version>1.7.25</version>
|
||||
<version>2.2.0</version>
|
||||
<artifactId>launch4j-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>l4j-NS-USBloader</id>
|
||||
<id>l4j-ns-usbloader</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>launch4j</goal>
|
||||
|
@ -243,34 +267,37 @@
|
|||
<configuration>
|
||||
<headerType>gui</headerType>
|
||||
<icon>appicon.ico</icon>
|
||||
<outfile>target/NS-USBloader-${project.version}.exe</outfile>
|
||||
<jar>target/ns-usbloader-${project.version}-jar-with-dependencies.jar</jar>
|
||||
<errTitle>NS-USBloader</errTitle>
|
||||
<classPath>
|
||||
<mainClass>nsusbloader.Main</mainClass>
|
||||
<addDependencies>false</addDependencies>
|
||||
<preCp>anything</preCp>
|
||||
</classPath>
|
||||
<outfile>target/${project.name}.exe</outfile>
|
||||
<jar>target/${project.artifactId}-${project.version}-${maven.build.timestamp}.jar</jar>
|
||||
<!-- <downloadUrl>https://download.oracle.com/java/17/archive/jdk-17.0.1_windows-x64_bin.msi</downloadUrl> -->
|
||||
<errTitle>Launching error</errTitle>
|
||||
<!-- <dontWrapJar>true</dontWrapJar> -->
|
||||
<jre>
|
||||
<minVersion>1.8</minVersion>
|
||||
<path>%PWD%/jdk</path>
|
||||
<minVersion>11.0.0</minVersion>
|
||||
</jre>
|
||||
<versionInfo>
|
||||
<fileVersion>1.0.0.0</fileVersion>
|
||||
<fileVersion>${project.version}.0.0</fileVersion>
|
||||
<txtFileVersion>${project.version}</txtFileVersion>
|
||||
<fileDescription>Awoo and GoldLeaf installer for your NS</fileDescription>
|
||||
<copyright>GNU General Public License v3, 2019 ${project.organization.name}. Russia/LPR.</copyright>
|
||||
<productVersion>1.0.0.0</productVersion>
|
||||
<fileDescription>NS multi-tool</fileDescription>
|
||||
<copyright>GNU General Public License v3, ${project.inceptionYear} ${project.organization.name}, Russia.</copyright>
|
||||
<productVersion>${project.version}.0.0</productVersion>
|
||||
<txtProductVersion>${project.version}</txtProductVersion>
|
||||
<companyName>${project.organization.name}</companyName>
|
||||
<productName>${project.name}</productName>
|
||||
<internalName>${project.name}</internalName>
|
||||
<originalFilename>${project.name}.exe</originalFilename>
|
||||
</versionInfo>
|
||||
<messages>
|
||||
<startupErr>Startup error</startupErr>
|
||||
<jreNotFoundErr>JDK not found</jreNotFoundErr>
|
||||
<jreVersionErr>JDK Version mismatch</jreVersionErr>
|
||||
<launcherErr>Launcher Error</launcherErr>
|
||||
</messages>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,19 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="132.50603mm"
|
||||
height="58.000351mm"
|
||||
viewBox="0 0 132.50603 58.000351"
|
||||
height="45.000351mm"
|
||||
viewBox="0 0 132.50603 45.000351"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
sodipodi:docname="Application Logo.svg">
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="Application Logo.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
|
@ -23,28 +23,31 @@
|
|||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="383.67648"
|
||||
inkscape:cy="100.29922"
|
||||
inkscape:zoom="4.0000001"
|
||||
inkscape:cx="233.49999"
|
||||
inkscape:cy="127.875"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="svg8"
|
||||
inkscape:current-layer="flowRoot1022"
|
||||
showgrid="false"
|
||||
units="mm"
|
||||
inkscape:window-width="1860"
|
||||
inkscape:window-height="1058"
|
||||
inkscape:window-x="1980"
|
||||
inkscape:window-width="3754"
|
||||
inkscape:window-height="2127"
|
||||
inkscape:window-x="1166"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:document-rotation="0">
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid829"
|
||||
originx="-40.993969"
|
||||
originy="-37.999746" />
|
||||
originx="-40.99399"
|
||||
originy="-37.999752" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
|
@ -54,7 +57,6 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
@ -114,145 +116,65 @@
|
|||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff;stroke-width:0.0680452"
|
||||
inkscape:label="usb_logo" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.43163px;line-height:1.25;font-family:Play;-inkscape-font-specification:'Play, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.357908"
|
||||
x="47.959785"
|
||||
y="17.188828"
|
||||
id="text982"
|
||||
<g
|
||||
aria-label="NS-USBloader"
|
||||
transform="scale(0.97866107,1.0218042)"
|
||||
inkscape:label="ns-usbloader"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan980"
|
||||
x="47.959785"
|
||||
y="17.188828"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3619px;font-family:Play;-inkscape-font-specification:'Play, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.357908">NS-USBloader</tspan></text>
|
||||
id="text982"
|
||||
style="font-size:1.43163px;line-height:1.25;font-family:Play;-inkscape-font-specification:'Play, Normal';letter-spacing:0px;word-spacing:0px;fill:#ffffff;stroke-width:0.357908"
|
||||
inkscape:label="ns-usbloader">
|
||||
<path
|
||||
d="M 56.49804,17.188828 H 54.934697 L 50.217947,9.9065918 V 17.188828 H 49.082185 V 8.5169542 h 1.563342 l 4.716751,7.1619788 V 8.5169542 h 1.135762 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path880" />
|
||||
<path
|
||||
d="m 64.488451,14.249209 v 0.62801 q 0,1.389637 -0.788353,1.924113 -0.788352,0.521115 -2.458589,0.521115 -1.068952,0 -2.645656,-0.213791 v -1.082314 q 1.576704,0.334048 2.725827,0.334048 0.921971,0 1.403,-0.200429 0.49439,-0.21379 0.49439,-0.8418 v -1.122399 q 0,-0.547838 -0.320686,-0.77499 -0.307323,-0.240515 -1.122399,-0.240515 H 60.76048 q -1.309466,0 -1.83058,-0.521114 -0.507752,-0.534476 -0.507752,-1.563342 v -0.694819 q 0,-1.0288662 0.721542,-1.5232565 0.734905,-0.4943903 2.685742,-0.4943903 0.935333,0 2.231438,0.1469809 v 0.9754187 q -1.483171,-0.2271523 -2.324971,-0.2271523 -1.242657,0 -1.656876,0.2538761 -0.400857,0.2405142 -0.400857,0.8284374 v 0.988781 q 0,0.454305 0.320686,0.668095 0.320686,0.200429 1.135762,0.200429 h 1.042228 q 1.349552,0 1.83058,0.49439 0.481029,0.481028 0.481029,1.536618 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path882" />
|
||||
<path
|
||||
d="m 69.472442,13.848352 h -3.714608 v -0.962056 h 3.714608 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path884" />
|
||||
<path
|
||||
d="m 77.903799,8.5169542 v 6.4537978 q 0,2.351695 -3.393923,2.351695 -0.681456,0 -1.215932,-0.09353 -0.534476,-0.08017 -1.055591,-0.307323 -0.521114,-0.240515 -0.815076,-0.734905 -0.293961,-0.49439 -0.293961,-1.215933 V 8.5169542 h 1.242656 V 14.95739 q 0,0.855162 0.574562,1.175847 0.574562,0.320686 1.590066,0.320686 1.015505,0 1.563343,-0.320686 0.561199,-0.320685 0.561199,-1.175847 V 8.5169542 Z"
|
||||
style="font-size:13.3619px"
|
||||
id="path886" />
|
||||
<path
|
||||
d="m 85.907587,14.249209 v 0.62801 q 0,1.389637 -0.788352,1.924113 -0.788353,0.521115 -2.45859,0.521115 -1.068952,0 -2.645656,-0.213791 v -1.082314 q 1.576704,0.334048 2.725827,0.334048 0.921971,0 1.403,-0.200429 0.49439,-0.21379 0.49439,-0.8418 v -1.122399 q 0,-0.547838 -0.320686,-0.77499 -0.307323,-0.240515 -1.122399,-0.240515 h -1.015505 q -1.309466,0 -1.83058,-0.521114 -0.507752,-0.534476 -0.507752,-1.563342 v -0.694819 q 0,-1.0288662 0.721542,-1.5232565 0.734905,-0.4943903 2.685742,-0.4943903 0.935333,0 2.231438,0.1469809 v 0.9754187 q -1.483171,-0.2271523 -2.324971,-0.2271523 -1.242657,0 -1.656875,0.2538761 -0.400857,0.2405142 -0.400857,0.8284374 v 0.988781 q 0,0.454305 0.320685,0.668095 0.320686,0.200429 1.135762,0.200429 h 1.042228 q 1.349552,0 1.83058,0.49439 0.481029,0.481028 0.481029,1.536618 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path888" />
|
||||
<path
|
||||
d="m 94.031625,14.008695 v 1.456447 q 0,0.948695 -0.721543,1.33619 -0.721542,0.387496 -2.351694,0.387496 H 87.764894 V 8.5169542 h 3.099961 q 1.122399,0 1.750409,0.2271523 0.641371,0.2271523 0.828437,0.5611998 0.200429,0.3340475 0.200429,0.8551617 v 1.162485 q 0,0.534476 -0.307324,0.815076 -0.293962,0.2806 -0.881885,0.414219 v 0.05345 q 0.694819,0.120257 1.135761,0.481028 0.440943,0.360771 0.440943,0.921971 z m -1.603428,-2.725827 v -1.015505 q 0,-0.4943902 -0.360771,-0.6948187 -0.360772,-0.2004285 -1.202571,-0.2004285 h -1.803857 v 2.9396182 h 1.843942 q 0.828438,0 1.175848,-0.240514 0.347409,-0.253876 0.347409,-0.788352 z m 0.307324,4.128827 v -1.309466 q 0,-0.34741 -0.146981,-0.547838 -0.133619,-0.213791 -0.440943,-0.293962 -0.293962,-0.09353 -0.534476,-0.106895 -0.227152,-0.02672 -0.654733,-0.02672 h -1.89739 v 3.16677 h 1.89739 q 0.975419,0 1.376276,-0.200428 0.400857,-0.200429 0.400857,-0.681457 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path890" />
|
||||
<path
|
||||
d="M 97.07815,17.188828 H 95.875579 V 7.8354973 h 1.202571 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path892" />
|
||||
<path
|
||||
d="m 104.8815,12.899658 v 2.244799 q 0,0.601285 -0.14698,1.015504 -0.14698,0.414219 -0.37413,0.641371 -0.22715,0.227153 -0.65474,0.34741 -0.41421,0.120257 -0.80171,0.146981 -0.37413,0.02672 -1.00214,0.02672 -0.80172,0 -1.25602,-0.05345 -0.44094,-0.05345 -0.895248,-0.253876 -0.440942,-0.213791 -0.641371,-0.668095 -0.187067,-0.454305 -0.187067,-1.202571 v -2.244799 q 0,-0.641372 0.146981,-1.082314 0.160343,-0.440943 0.374134,-0.681457 0.227152,-0.240515 0.654731,-0.360772 0.42758,-0.133619 0.78835,-0.160342 0.37414,-0.02672 1.01551,-0.02672 0.64137,0 1.00214,0.02672 0.37413,0.02672 0.80171,0.160342 0.42759,0.120257 0.64138,0.360772 0.22715,0.240514 0.37413,0.681457 0.16034,0.440942 0.16034,1.082314 z m -1.22929,2.418503 v -2.618932 q 0,-0.895247 -0.36077,-1.109038 -0.36078,-0.21379 -1.38964,-0.21379 -1.02887,0 -1.38964,0.21379 -0.36077,0.213791 -0.36077,1.109038 v 2.618932 q 0,0.427581 0.0935,0.681457 0.0935,0.253876 0.34741,0.374134 0.25388,0.106895 0.52112,0.133619 0.26723,0.02672 0.78835,0.02672 0.52111,0 0.78835,-0.02672 0.26724,-0.02672 0.52111,-0.133619 0.25388,-0.120258 0.34741,-0.374134 0.0935,-0.253876 0.0935,-0.681457 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path894" />
|
||||
<path
|
||||
d="m 111.85643,17.188828 h -1.16249 V 16.57418 q -0.14698,0.748267 -1.95084,0.748267 -1.33619,0 -1.8573,-0.400857 -0.50775,-0.414219 -0.50775,-1.656876 0,-1.082314 0.48103,-1.483171 0.48103,-0.414219 1.8573,-0.414219 h 1.93748 v -1.028866 q 0,-0.534476 -0.33405,-0.721543 -0.32069,-0.187067 -1.2293,-0.187067 -0.98878,0 -2.21807,0.160343 v -0.881885 q 1.32283,-0.120257 2.39178,-0.120257 1.63015,0 2.11118,0.400857 0.48103,0.387495 0.48103,1.630152 z m -1.20257,-1.309467 V 14.11559 h -1.85731 q -0.82844,0 -1.04223,0.213791 -0.20042,0.21379 -0.20042,0.975419 0,0.681456 0.21379,0.962056 0.22715,0.267238 0.93533,0.267238 h 0.24051 q 0.34741,0 0.57456,-0.01336 0.24052,-0.01336 0.53448,-0.06681 0.29396,-0.06681 0.44094,-0.200429 0.16035,-0.14698 0.16035,-0.374134 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path896" />
|
||||
<path
|
||||
d="m 119.59297,17.188828 h -1.17585 v -0.761629 q 0,0.34741 -0.58792,0.62801 -0.57456,0.267238 -1.5767,0.267238 -1.403,0 -1.97757,-0.440943 -0.57456,-0.440943 -0.57456,-1.61679 v -2.846085 q 0,-0.975419 0.60129,-1.402999 0.60128,-0.427581 2.01765,-0.427581 0.76162,0 1.40299,0.200428 0.65474,0.200429 0.6681,0.62801 h 0.0267 q -0.0267,-1.095676 -0.0267,-1.6435142 V 7.8354973 h 1.20257 z m -1.20257,-1.696962 v -3.193494 q 0,-0.868524 -1.77713,-0.868524 -1.06895,0 -1.403,0.160343 -0.32069,0.160343 -0.32069,0.708181 v 3.193494 q 0,0.547838 0.36077,0.77499 0.37414,0.227153 1.25602,0.227153 0.98878,0 1.42973,-0.227153 0.4543,-0.227152 0.4543,-0.77499 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path898" />
|
||||
<path
|
||||
d="m 126.88855,14.222486 h -4.34261 v 0.975418 q 0,0.681457 0.48103,0.975419 0.48102,0.2806 1.42972,0.2806 0.92197,0 2.17799,-0.320686 v 0.921972 q -1.20257,0.267238 -2.33833,0.267238 -2.96635,0 -2.96635,-1.977562 v -2.552123 q 0,-1.189209 0.68146,-1.696961 0.68146,-0.507752 2.17799,-0.507752 1.403,0 2.04437,0.49439 0.65473,0.481028 0.65473,1.710323 z m -1.20257,-0.788352 v -1.015505 q 0,-0.587924 -0.36077,-0.801714 -0.36077,-0.227152 -1.20257,-0.227152 -0.80171,0 -1.18921,0.21379 -0.38749,0.213791 -0.38749,0.815076 v 1.015505 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path900" />
|
||||
<path
|
||||
d="m 132.20659,11.616915 h -0.6681 q -0.82844,0 -1.22929,0.21379 -0.3875,0.213791 -0.3875,0.801715 v 4.556408 h -1.20257 v -6.46716 h 1.13576 v 1.05559 q 0,-0.467667 0.57456,-0.828438 0.58793,-0.360771 1.18921,-0.360771 h 0.58793 z"
|
||||
style="font-size:13.3619px"
|
||||
id="path902" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
d="m 21.967046,0 c -0.0065,-1.9994448e-6 -0.01188,0.0054 -0.01188,0.01188 v 44.976581 c 0,0.0065 0.0054,0.01188 0.01188,0.01188 h 2.000395 c 0.0065,0 0.01188,-0.0054 0.01188,-0.01188 V 0.011885 c 0,-0.0065 -0.0054,-0.011879999445 -0.01188,-0.011879999445 z"
|
||||
id="rect1136"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csssssssc" />
|
||||
<g
|
||||
inkscape:label="CREATIVE_COMMONS_SHIELD"
|
||||
transform="matrix(0.1713381,0,0,0.17131892,77.526533,36.479842)"
|
||||
id="g287"
|
||||
inkscape:export-filename="/mnt/hgfs/Bov/Documents/Work/2007/cc/identity/srr buttons/big/by-sa.png"
|
||||
inkscape:export-xdpi="300.23013"
|
||||
inkscape:export-ydpi="300.23013">
|
||||
<path
|
||||
id="path3817_2_"
|
||||
nodetypes="ccccccc"
|
||||
d="m 182.23532,75.39014 114.06396,0.20312 c 1.59375,0 3.01758,-0.23682 3.01758,3.18018 l -0.13965,37.56689 H 179.3569 V 78.63379 c 0,-1.68457 0.16309,-3.24365 2.87842,-3.24365 z"
|
||||
style="fill:#aab2ab" />
|
||||
<g
|
||||
id="g5908_2_"
|
||||
transform="matrix(0.872921,0,0,0.872921,50.12536,143.2144)">
|
||||
<path
|
||||
id="path5906_2_"
|
||||
cx="296.35416"
|
||||
ry="22.939548"
|
||||
cy="264.3577"
|
||||
type="arc"
|
||||
rx="22.939548"
|
||||
d="m 187.20944,-55.6792 c 0.006,8.68024 -7.02786,15.72095 -15.7081,15.72708 -8.68021,0.005 -15.72205,-7.02786 -15.72708,-15.70804 0,-0.0067 0,-0.01233 0,-0.01904 -0.005,-8.68134 7.02783,-15.72205 15.70807,-15.72711 8.68134,-0.0056 15.72208,7.02789 15.72711,15.70807 0,0.0056 0,0.01233 0,0.01904 z"
|
||||
style="fill:#ffffff" />
|
||||
<g
|
||||
id="g5706_2_"
|
||||
transform="translate(-289.6157,99.0653)">
|
||||
<path
|
||||
id="path5708_2_"
|
||||
d="m 473.88455,-167.54724 c 3.48541,3.48596 5.22839,7.75391 5.22839,12.80273 0,5.04938 -1.7128,9.27148 -5.13834,12.66736 -3.63531,3.5766 -7.93179,5.36432 -12.88947,5.36432 -4.89777,0 -9.11987,-1.77261 -12.6651,-5.31955 -3.54584,-3.54581 -5.31845,-7.78299 -5.31845,-12.71213 0,-4.92859 1.77261,-9.19598 5.31845,-12.80273 3.4552,-3.48651 7.67725,-5.22894 12.6651,-5.22894 5.04829,0 9.31401,1.74243 12.79942,5.22894 z m -23.11798,2.34485 c -2.94675,2.97638 -4.41956,6.46289 -4.41956,10.46234 0,3.99835 1.45828,7.4552 4.37424,10.37067 2.91653,2.9165 6.38849,4.37476 10.41705,4.37476 4.02853,0 7.53018,-1.47281 10.50656,-4.41901 2.8259,-2.73584 4.23941,-6.17706 4.23941,-10.32642 0,-4.11804 -1.43646,-7.61292 -4.30768,-10.48474 -2.87064,-2.87067 -6.34988,-4.30652 -10.43829,-4.30652 -4.08837,0 -7.54638,1.44318 -10.37173,4.32892 z m 7.75449,8.70312 c -0.45032,-0.98163 -1.12433,-1.47223 -2.02325,-1.47223 -1.58914,0 -2.38342,1.06952 -2.38342,3.2085 0,2.13959 0.79428,3.20911 2.38342,3.20911 1.04938,0 1.79895,-0.5213 2.24866,-1.56512 l 2.20276,1.17303 c -1.04993,1.86548 -2.62506,2.79901 -4.72549,2.79901 -1.6199,0 -2.91763,-0.4967 -3.89206,-1.48956 -0.97607,-0.99341 -1.46274,-2.36273 -1.46274,-4.10797 0,-1.71558 0.50229,-3.07709 1.50748,-4.08563 1.00519,-1.00793 2.25705,-1.51251 3.75781,-1.51251 2.22012,0 3.80984,0.87488 4.77081,2.62286 z m 10.36334,0 c -0.45087,-0.98163 -1.11148,-1.47223 -1.98239,-1.47223 -1.62106,0 -2.43213,1.06952 -2.43213,3.2085 0,2.13959 0.81107,3.20911 2.43213,3.20911 1.05103,0 1.78717,-0.5213 2.20724,-1.56512 l 2.25201,1.17303 c -1.04825,1.86548 -2.62119,2.79901 -4.71768,2.79901 -1.61771,0 -2.91263,-0.4967 -3.88647,-1.48956 -0.97217,-0.99341 -1.45938,-2.36273 -1.45938,-4.10797 0,-1.71558 0.49448,-3.07709 1.48288,-4.08563 0.98782,-1.00793 2.24527,-1.51251 3.77347,-1.51251 2.21619,0 3.80368,0.87488 4.76132,2.62286 z" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
d="M 297.29639,74.91064 H 181.06688 c -1.24658,0 -2.26074,1.01465 -2.26074,2.26123 v 39.49561 c 0,0.28174 0.22852,0.51074 0.51025,0.51074 h 119.73 c 0.28174,0 0.51074,-0.229 0.51074,-0.51074 v -39.4956 c 0,-1.24659 -1.01416,-2.26124 -2.26074,-2.26124 z m -116.22951,1.02149 h 116.22951 c 0.68359,0 1.23926,0.55615 1.23926,1.23975 0,0 0,15.91943 0,27.41846 H 215.4619 c -3.04492,5.50537 -8.91113,9.24365 -15.64355,9.24365 -6.73535,0 -12.6001,-3.73486 -15.64355,-9.24365 h -4.34814 c 0,-11.49902 0,-27.41846 0,-27.41846 -2e-5,-0.6836 0.55663,-1.23975 1.24022,-1.23975 z"
|
||||
id="path294" />
|
||||
<g
|
||||
enable-background="new "
|
||||
id="g296">
|
||||
<path
|
||||
d="m 265.60986,112.8833 c 0.0801,0.15576 0.1875,0.28174 0.32129,0.37842 0.13379,0.0962 0.29004,0.16797 0.46973,0.21436 0.18066,0.0469 0.36719,0.0703 0.55957,0.0703 0.12988,0 0.26953,-0.0107 0.41895,-0.0327 0.14844,-0.0215 0.28809,-0.064 0.41895,-0.12598 0.12988,-0.062 0.23926,-0.14795 0.3252,-0.25684 0.0879,-0.10889 0.13086,-0.24707 0.13086,-0.41553 0,-0.18018 -0.0576,-0.32617 -0.17285,-0.43848 -0.11426,-0.1123 -0.26562,-0.20508 -0.45215,-0.28027 -0.18555,-0.0742 -0.39746,-0.13965 -0.63281,-0.1958 -0.23633,-0.0562 -0.47559,-0.11816 -0.71777,-0.18701 -0.24902,-0.062 -0.49121,-0.13818 -0.72754,-0.22852 -0.23535,-0.0898 -0.44727,-0.20703 -0.63379,-0.3501 -0.18652,-0.14307 -0.33691,-0.32178 -0.45215,-0.53662 -0.11426,-0.21484 -0.17188,-0.47461 -0.17188,-0.7793 0,-0.34277 0.0732,-0.63965 0.21875,-0.8916 0.14648,-0.25195 0.33789,-0.46191 0.57422,-0.63037 0.23535,-0.16797 0.50293,-0.29248 0.80176,-0.37354 0.29785,-0.0806 0.59668,-0.12109 0.89453,-0.12109 0.34863,0 0.68262,0.0391 1.00293,0.11719 0.31934,0.0776 0.60449,0.2041 0.85254,0.37842 0.24902,0.17432 0.44629,0.39697 0.59277,0.66797 0.14551,0.271 0.21875,0.59961 0.21875,0.98535 h -1.42188 c -0.0127,-0.19922 -0.0547,-0.36426 -0.125,-0.49463 -0.0713,-0.13086 -0.16602,-0.2334 -0.2832,-0.30859 -0.11816,-0.0742 -0.25293,-0.12744 -0.4043,-0.1582 -0.15234,-0.0312 -0.31738,-0.0469 -0.49707,-0.0469 -0.11719,0 -0.23535,0.0127 -0.35254,0.0371 -0.11816,0.0254 -0.22461,0.0688 -0.32031,0.13086 -0.0967,0.0625 -0.17578,0.14014 -0.2373,0.2334 -0.0615,0.0937 -0.0928,0.21191 -0.0928,0.35498 0,0.13086 0.0244,0.23682 0.0742,0.31738 0.0498,0.0811 0.14844,0.15576 0.29395,0.22412 0.14551,0.0684 0.34766,0.13721 0.60547,0.20557 0.25781,0.0684 0.59473,0.15576 1.01172,0.26123 0.12402,0.0249 0.2959,0.0703 0.5166,0.13574 0.2207,0.0654 0.43945,0.16943 0.65723,0.3125 0.21777,0.14355 0.40527,0.33496 0.56445,0.57422 0.1582,0.23975 0.2373,0.54639 0.2373,0.91992 0,0.30518 -0.0596,0.58838 -0.17773,0.84961 -0.11816,0.26172 -0.29395,0.4873 -0.52734,0.67676 -0.2334,0.19043 -0.52246,0.33789 -0.86719,0.44385 -0.3457,0.10596 -0.74609,0.15869 -1.19922,0.15869 -0.36719,0 -0.72363,-0.0454 -1.06934,-0.13574 -0.34473,-0.0903 -0.65039,-0.23242 -0.91504,-0.42578 -0.26367,-0.19336 -0.47363,-0.43994 -0.62988,-0.73877 -0.15527,-0.29932 -0.22949,-0.65381 -0.22363,-1.06494 h 1.42188 c -3e-5,0.22412 0.04,0.41406 0.12106,0.56933 z"
|
||||
id="path298"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
d="m 273.8667,107.8667 2.49316,6.66406 h -1.52246 l -0.50391,-1.48438 h -2.49316 l -0.52246,1.48438 h -1.47461 l 2.52051,-6.66406 z m 0.084,4.08594 -0.83984,-2.44336 h -0.0186 l -0.86914,2.44336 z"
|
||||
id="path300"
|
||||
style="fill:#ffffff" />
|
||||
</g>
|
||||
<g
|
||||
enable-background="new "
|
||||
id="g302">
|
||||
<path
|
||||
d="m 239.17821,107.8667 c 0.31738,0 0.60742,0.0283 0.86914,0.084 0.26172,0.0561 0.48633,0.14795 0.67383,0.27539 0.18652,0.12744 0.33203,0.29688 0.43457,0.5083 0.10254,0.21142 0.1543,0.47266 0.1543,0.78369 0,0.33594 -0.0762,0.61523 -0.22949,0.83936 -0.15234,0.22412 -0.37891,0.40723 -0.67773,0.55029 0.41211,0.11816 0.71973,0.3252 0.92285,0.62109 0.20312,0.29589 0.30469,0.65234 0.30469,1.06934 0,0.33594 -0.0654,0.62695 -0.19629,0.87305 -0.13086,0.24561 -0.30762,0.44629 -0.52832,0.60205 -0.22168,0.15576 -0.47461,0.271 -0.75781,0.34521 -0.28418,0.0752 -0.5752,0.1123 -0.875,0.1123 h -3.23633 v -6.66406 h 3.14159 z m -0.1875,2.69531 c 0.26172,0 0.47656,-0.062 0.64551,-0.18604 0.16797,-0.12451 0.25195,-0.32568 0.25195,-0.60498 0,-0.15527 -0.0283,-0.28271 -0.084,-0.38184 -0.0566,-0.0996 -0.13086,-0.17676 -0.22461,-0.23291 -0.0937,-0.0557 -0.20117,-0.0947 -0.32227,-0.11621 -0.12207,-0.022 -0.24805,-0.0327 -0.37891,-0.0327 h -1.37305 v 1.55469 z m 0.0859,2.82813 c 0.14355,0 0.28027,-0.0137 0.41113,-0.042 0.13086,-0.0278 0.24707,-0.0747 0.34668,-0.13965 0.0996,-0.0654 0.17871,-0.1543 0.23828,-0.26611 0.0596,-0.11181 0.0889,-0.25488 0.0889,-0.4292 0,-0.3418 -0.0967,-0.58594 -0.29004,-0.73193 -0.19336,-0.14599 -0.44922,-0.21924 -0.7666,-0.21924 h -1.59961 v 1.82812 z"
|
||||
id="path304"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
d="m 241.88914,107.8667 h 1.64355 l 1.56055,2.63184 1.55078,-2.63184 h 1.63379 l -2.47363,4.10645 v 2.55762 h -1.46875 v -2.59473 z"
|
||||
id="path306"
|
||||
style="fill:#ffffff" />
|
||||
</g>
|
||||
<g
|
||||
id="g6316_1_"
|
||||
transform="matrix(0.624995,0,0,0.624995,391.2294,176.9332)">
|
||||
<path
|
||||
id="path6318_1_"
|
||||
cx="475.97119"
|
||||
ry="29.209877"
|
||||
cy="252.08646"
|
||||
type="arc"
|
||||
rx="29.209877"
|
||||
d="m -175.0083,-139.1153 c 0.006,9.4118 -7.61725,17.04779 -17.02982,17.05481 -9.41101,0.007 -17.047,-7.61725 -17.05481,-17.02979 0,-0.008 0,-0.0172 0,-0.025 -0.006,-9.41254 7.6188,-17.047 17.02982,-17.05481 9.41257,-0.007 17.04855,7.61804 17.05481,17.02985 0,0.009 0,0.0164 0,0.025 z"
|
||||
style="fill:#ffffff" />
|
||||
<g
|
||||
id="g6320_1_"
|
||||
transform="translate(-23.9521,-89.72962)">
|
||||
<path
|
||||
id="path6322_1_"
|
||||
d="m -168.2204,-68.05536 c -5.17194,0 -9.54852,1.80469 -13.13135,5.41333 -3.67661,3.73444 -5.51413,8.1532 -5.51413,13.25635 0,5.10315 1.83752,9.49152 5.51413,13.1626 3.67502,3.67194 8.05316,5.50787 13.13135,5.50787 5.14066,0 9.59537,-1.85156 13.36728,-5.55475 3.55005,-3.51562 5.3266,-7.88831 5.3266,-13.11572 0,-5.22662 -1.8078,-9.64697 -5.42191,-13.25635 -3.61407,-3.60864 -8.03756,-5.41333 -13.27197,-5.41333 z m 0.0469,3.36017 c 4.23752,0 7.836,1.49298 10.79697,4.48053 2.98907,2.9563 4.48441,6.56567 4.48441,10.82898 0,4.29382 -1.46252,7.85712 -4.39224,10.68915 -3.08438,3.04926 -6.71411,4.57349 -10.88913,4.57349 -4.17505,0 -7.7735,-1.5094 -10.79541,-4.52661 -3.02188,-3.01953 -4.53284,-6.59692 -4.53284,-10.73602 0,-4.13831 1.52658,-7.74847 4.57971,-10.82898 2.92815,-2.98756 6.51098,-4.48054 10.74853,-4.48054 z" />
|
||||
<path
|
||||
id="path6324_1_"
|
||||
d="m -176.49548,-52.02087 c 0.74377,-4.69769 4.05161,-7.20862 8.1954,-7.20862 5.96097,0 9.59225,4.32501 9.59225,10.09229 0,5.62738 -3.86411,9.99927 -9.686,9.99927 -4.00473,0 -7.58914,-2.46484 -8.24228,-7.30084 h 4.70319 c 0.14062,2.51099 1.77032,3.39459 4.09845,3.39459 2.65317,0 4.37817,-2.4649 4.37817,-6.23291 0,-3.95233 -1.49063,-6.04535 -4.28598,-6.04535 -2.04846,0 -3.8172,0.74457 -4.19064,3.30157 l 1.36874,-0.007 -3.70316,3.7016 -3.7016,-3.7016 z" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g313">
|
||||
<circle
|
||||
cx="242.56226"
|
||||
cy="90.224609"
|
||||
r="10.8064"
|
||||
id="circle315"
|
||||
style="fill:#ffffff" />
|
||||
<g
|
||||
id="g317">
|
||||
<path
|
||||
d="m 245.68994,87.09766 c 0,-0.4165 -0.33789,-0.75342 -0.75391,-0.75342 h -4.77246 c -0.41602,0 -0.75391,0.33691 -0.75391,0.75342 v 4.77295 h 1.33105 v 5.65234 h 3.61719 v -5.65234 h 1.33203 v -4.77295 z"
|
||||
id="path319" />
|
||||
<circle
|
||||
cx="242.5498"
|
||||
cy="84.083008"
|
||||
r="1.63232"
|
||||
id="circle321" />
|
||||
</g>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="m 242.53467,78.31836 c -3.23145,0 -5.96826,1.12744 -8.20752,3.38379 -2.29785,2.33301 -3.44629,5.09521 -3.44629,8.28418 0,3.18897 1.14844,5.93213 3.44629,8.22705 2.29785,2.29443 5.03418,3.44189 8.20752,3.44189 3.21289,0 5.99805,-1.15674 8.35352,-3.47168 2.2207,-2.19678 3.33008,-4.92969 3.33008,-8.19727 0,-3.26758 -1.12891,-6.02881 -3.3877,-8.28418 -2.25879,-2.25634 -5.02442,-3.38378 -8.2959,-3.38378 z m 0.0293,2.09961 c 2.64844,0 4.89746,0.93359 6.74707,2.80078 1.87012,1.84717 2.80469,4.10352 2.80469,6.76758 0,2.68359 -0.91504,4.91113 -2.74609,6.68066 -1.92773,1.90576 -4.19629,2.8584 -6.80566,2.8584 -2.60937,0 -4.8584,-0.94287 -6.74658,-2.82959 -1.88965,-1.88623 -2.8335,-4.12256 -2.8335,-6.70947 0,-2.58643 0.9541,-4.84229 2.8623,-6.76758 1.83057,-1.86719 4.07031,-2.80078 6.71777,-2.80078 z"
|
||||
id="path323"
|
||||
style="fill-rule:evenodd" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
inkscape:label="HeyMomLookAtMe"
|
||||
inkscape:transform-center-y="-0.1984375"
|
||||
inkscape:transform-center-x="-0.33072917"
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.82222px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="108.57767"
|
||||
y="48.318489"
|
||||
id="text921"><tspan
|
||||
sodipodi:role="line"
|
||||
x="108.57767"
|
||||
y="48.318489"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.82222px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans Bold';stroke-width:0.264583"
|
||||
id="tspan923">Dmitry Isaenko</tspan></text>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 33 KiB |
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package nsusbloader;
|
||||
|
||||
import javafx.scene.text.Font;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
|
@ -27,22 +29,26 @@ public class AppPreferences {
|
|||
|
||||
private final Preferences preferences;
|
||||
private final Locale locale;
|
||||
public static final String[] goldleafSupportedVersions = {"v0.5", "v0.7.x", "v0.8-0.9"};
|
||||
public static final String[] GOLDLEAF_SUPPORTED_VERSIONS = {"v0.5", "v0.7.x", "v0.8-0.9", "v0.10+"};
|
||||
private static final Font DEFAULT_FONT = Font.getDefault();
|
||||
|
||||
private AppPreferences(){
|
||||
this.preferences = Preferences.userRoot().node("NS-USBloader");
|
||||
String localeCode = preferences.get("locale", Locale.getDefault().toString());
|
||||
this.locale = new Locale(localeCode.substring(0, 2), localeCode.substring(3, 5));
|
||||
if (localeCode.length() < 5)
|
||||
this.locale = new Locale("en", "EN");
|
||||
else
|
||||
this.locale = new Locale(localeCode.substring(0, 2), localeCode.substring(3));
|
||||
}
|
||||
|
||||
public String getTheme(){
|
||||
String theme = preferences.get("THEME", "/res/app_dark.css"); // Don't let user to change settings manually
|
||||
String theme = preferences.get("THEME", "/res/app_dark.css"); // Don't let user change settings manually
|
||||
if (!theme.matches("(^/res/app_dark.css$)|(^/res/app_light.css$)"))
|
||||
theme = "/res/app_dark.css";
|
||||
return theme;
|
||||
}
|
||||
public int getProtocol(){
|
||||
int protocolIndex = preferences.getInt("protocol_index", 0); // Don't let user to change settings manually
|
||||
int protocolIndex = preferences.getInt("protocol_index", 0); // Don't let user change settings manually
|
||||
if (protocolIndex < 0 || protocolIndex > 1)
|
||||
protocolIndex = 0;
|
||||
return protocolIndex;
|
||||
|
@ -50,7 +56,7 @@ public class AppPreferences {
|
|||
public void setProtocol(int protocolIndex){ preferences.putInt("protocol_index", protocolIndex); }
|
||||
|
||||
public String getNetUsb(){
|
||||
String netUsb = preferences.get("NETUSB", "USB"); // Don't let user to change settings manually
|
||||
String netUsb = preferences.get("NETUSB", "USB"); // Don't let user change settings manually
|
||||
if (!netUsb.matches("(^USB$)|(^NET$)"))
|
||||
netUsb = "USB";
|
||||
return netUsb;
|
||||
|
@ -114,7 +120,7 @@ public class AppPreferences {
|
|||
public void setNspFileFilterGL(boolean prop){preferences.putBoolean("GL_NSP_FILTER", prop);}
|
||||
|
||||
public int getGlVersion(){
|
||||
return preferences.getInt("gl_ver", goldleafSupportedVersions.length - 1);
|
||||
return preferences.getInt("gl_ver", GOLDLEAF_SUPPORTED_VERSIONS.length - 1);
|
||||
}
|
||||
public void setGlVersion(int version){ preferences.putInt("gl_ver", version);}
|
||||
|
||||
|
@ -138,4 +144,28 @@ public class AppPreferences {
|
|||
|
||||
public String getLastOpenedTab(){ return preferences.get("recent_tab", ""); }
|
||||
public void setLastOpenedTab(String tabId){ preferences.put("recent_tab", tabId); }
|
||||
// Patches
|
||||
public String getKeysLocation(){ return preferences.get("keys", ""); }
|
||||
public void setKeysLocation(String path){ preferences.put("keys", path); }
|
||||
|
||||
public String getPatchesSaveToLocation(){ return FilesHelper.getRealFolder(preferences.get("patches_saveto", System.getProperty("user.home"))); }
|
||||
public void setPatchesSaveToLocation(String value){ preferences.put("patches_saveto", value); }
|
||||
|
||||
public boolean getPatchesTabInvisible(){return preferences.getBoolean("patches_tab_visible", true); }
|
||||
public void setPatchesTabInvisible(boolean value){preferences.putBoolean("patches_tab_visible", value);}
|
||||
public String getPatchPattern(String type, int moduleNumber, int offsetId){ return preferences.get(String.format("%s_%02x_%02x", type, moduleNumber, offsetId), ""); }
|
||||
public void setPatchPattern(String fullTypeSpecifier, String offset){ preferences.put(fullTypeSpecifier, offset); }
|
||||
|
||||
public String getFontFamily(){ return preferences.get("font_family", DEFAULT_FONT.getFamily()); }
|
||||
public double getFontSize(){ return preferences.getDouble("font_size", DEFAULT_FONT.getSize()); }
|
||||
public String getFontStyle(){
|
||||
final String fontFamily = preferences.get("font_family", DEFAULT_FONT.getFamily());
|
||||
final double fontSize = preferences.getDouble("font_size", DEFAULT_FONT.getSize());
|
||||
|
||||
return String.format("-fx-font-family: \"%s\"; -fx-font-size: %.0f;", fontFamily, fontSize);
|
||||
}
|
||||
public void setFontStyle(String fontFamily, double size){
|
||||
preferences.put("font_family", fontFamily);
|
||||
preferences.putDouble("font_size", size);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ public class FilesDropHandle {
|
|||
Scene mainScene = new Scene(parentVBox, 310, 185);
|
||||
|
||||
mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
parentVBox.setStyle(AppPreferences.getInstance().getFontStyle());
|
||||
|
||||
stage.setOnHidden(windowEvent -> filesDropHandleTask.cancel(true ) );
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Controllers;
|
||||
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Stage;
|
||||
import nsusbloader.AppPreferences;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class FontSettings {
|
||||
public FontSettings(ResourceBundle resourceBundle) throws Exception{
|
||||
Stage stage = new Stage();
|
||||
stage.setMinWidth(650);
|
||||
stage.setMinHeight(450);
|
||||
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/FontSettings.fxml"));
|
||||
fxmlLoader.setResources(resourceBundle);
|
||||
|
||||
stage.setTitle(resourceBundle.getString("tab2_Btn_ApplicationFont"));
|
||||
stage.getIcons().addAll(
|
||||
new Image("/res/app_icon32x32.png"),
|
||||
new Image("/res/app_icon48x48.png"),
|
||||
new Image("/res/app_icon64x64.png"),
|
||||
new Image("/res/app_icon128x128.png"));
|
||||
|
||||
Parent parent = fxmlLoader.load();
|
||||
Scene fontScene = new Scene(parent, 660, 525);
|
||||
|
||||
fontScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
parent.setStyle(AppPreferences.getInstance().getFontStyle());
|
||||
|
||||
stage.setAlwaysOnTop(true);
|
||||
stage.setScene(fontScene);
|
||||
stage.show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Controllers;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.stage.Stage;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.MediatorControl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class FontSettingsController implements Initializable {
|
||||
private final AppPreferences preferences = AppPreferences.getInstance();
|
||||
|
||||
@FXML
|
||||
private Button applyBtn, cancelBtn, resetBtn;
|
||||
|
||||
@FXML
|
||||
private ListView<String> fontsLv;
|
||||
|
||||
@FXML
|
||||
private Spinner<Double> fontSizeSpinner;
|
||||
|
||||
@FXML
|
||||
private Text exampleText;
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||
applyBtn.setDefaultButton(true);
|
||||
applyBtn.getStyleClass().add("buttonUp");
|
||||
applyBtn.setOnAction(e -> applyChanges());
|
||||
|
||||
cancelBtn.setCancelButton(true);
|
||||
cancelBtn.setOnAction(e -> closeWindow());
|
||||
|
||||
resetBtn.setOnAction(e -> reset());
|
||||
|
||||
fontsLv.setCellFactory(item -> getCellFactory());
|
||||
fontsLv.setItems(getFonts());
|
||||
fontsLv.getSelectionModel().select(preferences.getFontFamily());
|
||||
fontsLv.getSelectionModel().selectedIndexProperty().addListener(
|
||||
(observableValue, oldValueNumber, newValueNumber) -> setExampleTextFont());
|
||||
fontsLv.setFixedCellSize(40.0);
|
||||
|
||||
fontSizeSpinner.setEditable(false);
|
||||
fontSizeSpinner.setValueFactory(getValueFactory());
|
||||
|
||||
exampleText.setText(resourceBundle.getString("fontPreviewText"));
|
||||
|
||||
fontSizeSpinner.getValueFactory().setValue(preferences.getFontSize());
|
||||
}
|
||||
|
||||
private ListCell<String> getCellFactory(){
|
||||
return new ListCell<>(){
|
||||
@Override
|
||||
protected void updateItem(String item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty || item == null)
|
||||
return;
|
||||
Font font = Font.font(item);
|
||||
Text itemText = new Text(item);
|
||||
itemText.setFont(font);
|
||||
setGraphic(itemText);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ObservableList<String> getFonts(){
|
||||
ObservableList<String> fonts = FXCollections.observableArrayList();
|
||||
fonts.addAll(Font.getFamilies());
|
||||
|
||||
return fonts;
|
||||
}
|
||||
|
||||
private SpinnerValueFactory<Double> getValueFactory(){
|
||||
return new SpinnerValueFactory<>() {
|
||||
@Override
|
||||
public void decrement(int i) {
|
||||
double value = getValue() - i;
|
||||
if (value < 4)
|
||||
return;
|
||||
|
||||
setValue(value);
|
||||
setExampleTextFont(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(int i) {
|
||||
double value = getValue() + i;
|
||||
if (value > 100)
|
||||
return;
|
||||
|
||||
setValue(value);
|
||||
setExampleTextFont(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setExampleTextFont(){
|
||||
setExampleTextFont(fontsLv.getSelectionModel().getSelectedItem(), fontSizeSpinner.getValue());
|
||||
}
|
||||
private void setExampleTextFont(double size){
|
||||
setExampleTextFont(fontsLv.getSelectionModel().getSelectedItem(), size);
|
||||
}
|
||||
private void setExampleTextFont(String font, double size){
|
||||
exampleText.setFont(Font.font(font, size));
|
||||
}
|
||||
|
||||
private void reset(){
|
||||
final Font defaultFont = Font.getDefault();
|
||||
exampleText.setFont(defaultFont);
|
||||
|
||||
fontsLv.getSelectionModel().select(defaultFont.getFamily());
|
||||
fontSizeSpinner.getValueFactory().setValue(defaultFont.getSize());
|
||||
}
|
||||
|
||||
private void applyChanges(){
|
||||
final String fontFamily = fontsLv.getSelectionModel().getSelectedItem();
|
||||
final double fontSize = fontSizeSpinner.getValue().intValue();
|
||||
|
||||
preferences.setFontStyle(fontFamily, fontSize);
|
||||
MediatorControl.getInstance().updateApplicationFont(fontFamily, fontSize);
|
||||
|
||||
closeWindow();
|
||||
}
|
||||
|
||||
private void closeWindow(){
|
||||
((Stage) cancelBtn.getScene().getWindow()).close();
|
||||
}
|
||||
}
|
|
@ -66,7 +66,7 @@ public class GamesController implements Initializable {
|
|||
public NSTableViewController tableFilesListController; // Accessible from Mediator (for drag-n-drop support)
|
||||
|
||||
@FXML
|
||||
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
|
||||
private Button selectNspBtn, selectSplitBtn, uploadStopBtn;
|
||||
private String previouslyOpenedPath;
|
||||
private Region btnUpStopImage, btnSelectImage;
|
||||
private ResourceBundle resourceBundle;
|
||||
|
@ -141,8 +141,8 @@ public class GamesController implements Initializable {
|
|||
this.btnSelectImage = new Region();
|
||||
setFilesSelectorButtonBehaviour(preferences.getDirectoriesChooserForRoms());
|
||||
|
||||
selectSplitNspBtn.setOnAction(e-> selectSplitBtnAction());
|
||||
selectSplitNspBtn.getStyleClass().add("buttonSelect");
|
||||
selectSplitBtn.setOnAction(e-> selectSplitBtnAction());
|
||||
selectSplitBtn.getStyleClass().add("buttonSelect");
|
||||
|
||||
uploadStopBtn.setOnAction(e-> uploadBtnAction());
|
||||
uploadStopBtn.setDisable(isTinfoil());
|
||||
|
@ -326,7 +326,7 @@ public class GamesController implements Initializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Functionality for selecting Split NSP button.
|
||||
* Functionality for selecting Split-file button.
|
||||
* */
|
||||
private void selectSplitBtnAction(){
|
||||
File splitFile;
|
||||
|
@ -338,11 +338,28 @@ public class GamesController implements Initializable {
|
|||
|
||||
splitFile = dirChooser.showDialog(usbNetPane.getScene().getWindow());
|
||||
|
||||
if (splitFile != null && splitFile.getName().toLowerCase().endsWith(".nsp")) {
|
||||
if (splitFile == null)
|
||||
return;
|
||||
|
||||
int fileNameLen = splitFile.getName().length();
|
||||
String fileExtension = splitFile.getName().toLowerCase().substring(fileNameLen-4, fileNameLen);
|
||||
|
||||
if (fileExtension.equals(".nsp")){
|
||||
tableFilesListController.setFile(splitFile);
|
||||
uploadStopBtn.setDisable(false); // Is it useful?
|
||||
previouslyOpenedPath = splitFile.getParent();
|
||||
}
|
||||
|
||||
if (isTinfoil() && isXciNszXczSupport()){
|
||||
switch(fileExtension){
|
||||
case ".xci":
|
||||
case ".nsz":
|
||||
case ".xcz":
|
||||
tableFilesListController.setFile(splitFile);
|
||||
uploadStopBtn.setDisable(false); // Is it useful?
|
||||
previouslyOpenedPath = splitFile.getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* It's button listener when no transmission executes
|
||||
|
@ -456,7 +473,7 @@ public class GamesController implements Initializable {
|
|||
}
|
||||
|
||||
selectNspBtn.setDisable(isActive);
|
||||
selectSplitNspBtn.setDisable(isActive);
|
||||
selectSplitBtn.setDisable(isActive);
|
||||
btnUpStopImage.getStyleClass().clear();
|
||||
|
||||
if (isActive) {
|
||||
|
@ -506,12 +523,12 @@ public class GamesController implements Initializable {
|
|||
if (isDirectoryChooser){
|
||||
selectNspBtn.setOnAction(e -> selectFoldersBtnAction());
|
||||
btnSelectImage.getStyleClass().add("regionScanFolders");
|
||||
selectSplitNspBtn.setVisible(false);
|
||||
selectSplitBtn.setVisible(false);
|
||||
}
|
||||
else {
|
||||
selectNspBtn.setOnAction(e -> selectFilesBtnAction());
|
||||
btnSelectImage.getStyleClass().add("regionSelectFiles");
|
||||
selectSplitNspBtn.setVisible(true);
|
||||
selectSplitBtn.setVisible(true);
|
||||
}
|
||||
selectNspBtn.setGraphic(btnSelectImage);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public class NSLMainController implements Initializable {
|
|||
@FXML
|
||||
private TabPane mainTabPane;
|
||||
@FXML
|
||||
private Tab GamesTabHolder, RCMTabHolder, SMTabHolder;
|
||||
private Tab GamesTabHolder, RCMTabHolder, SMTabHolder, PatchesTabHolder;
|
||||
|
||||
@FXML
|
||||
private GamesController GamesTabController;
|
||||
|
@ -55,6 +55,8 @@ public class NSLMainController implements Initializable {
|
|||
private RcmController RcmTabController;
|
||||
@FXML
|
||||
private NxdtController NXDTabController;
|
||||
@FXML
|
||||
private PatchesController PatchesTabController;
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
|
@ -68,9 +70,13 @@ public class NSLMainController implements Initializable {
|
|||
|
||||
MediatorControl.getInstance().setController(this);
|
||||
|
||||
if (AppPreferences.getInstance().getAutoCheckUpdates()){
|
||||
AppPreferences preferences = AppPreferences.getInstance();
|
||||
|
||||
if (preferences.getAutoCheckUpdates())
|
||||
checkForUpdates();
|
||||
}
|
||||
|
||||
if (preferences.getPatchesTabInvisible())
|
||||
mainTabPane.getTabs().remove(3);
|
||||
|
||||
openLastOpenedTab();
|
||||
}
|
||||
|
@ -127,6 +133,8 @@ public class NSLMainController implements Initializable {
|
|||
public RcmController getRcmCtrlr(){ return RcmTabController; }
|
||||
|
||||
public NxdtController getNXDTabController(){ return NXDTabController; }
|
||||
|
||||
public PatchesController getPatchesTabController(){ return PatchesTabController; }
|
||||
/**
|
||||
* Save preferences before exit
|
||||
* */
|
||||
|
@ -136,7 +144,7 @@ public class NSLMainController implements Initializable {
|
|||
SplitMergeTabController.updatePreferencesOnExit(); // NOTE: This shit above should be re-written to similar pattern
|
||||
RcmTabController.updatePreferencesOnExit();
|
||||
NXDTabController.updatePreferencesOnExit();
|
||||
|
||||
PatchesTabController.updatePreferencesOnExit();
|
||||
saveLastOpenedTab();
|
||||
}
|
||||
|
||||
|
@ -152,6 +160,9 @@ public class NSLMainController implements Initializable {
|
|||
case "SMTabHolder":
|
||||
mainTabPane.getSelectionModel().select(SMTabHolder);
|
||||
break;
|
||||
case "PatchesTabHolder":
|
||||
mainTabPane.getSelectionModel().select(PatchesTabHolder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void saveLastOpenedTab(){
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Controllers;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.input.DragEvent;
|
||||
import javafx.scene.input.TransferMode;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.DirectoryChooser;
|
||||
import javafx.stage.FileChooser;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.FilesHelper;
|
||||
import nsusbloader.MediatorControl;
|
||||
import nsusbloader.NSLDataTypes.EModule;
|
||||
import nsusbloader.ServiceWindow;
|
||||
import nsusbloader.Utilities.patches.es.EsPatchMaker;
|
||||
import nsusbloader.Utilities.patches.fs.FsPatchMaker;
|
||||
import nsusbloader.Utilities.patches.loader.LoaderPatchMaker;
|
||||
|
||||
// TODO: CLI SUPPORT
|
||||
public class PatchesController implements Initializable {
|
||||
@FXML
|
||||
private VBox patchesToolPane;
|
||||
@FXML
|
||||
private Button makeEsBtn, makeFsBtn, makeLoaderBtn;
|
||||
@FXML
|
||||
private Label shortNameFirmwareLbl, locationFirmwareLbl, saveToLbl, shortNameKeysLbl, locationKeysLbl, statusLbl,
|
||||
locationAtmosphereLbl, shortNameAtmoLbl;
|
||||
private Thread workThread;
|
||||
|
||||
private String previouslyOpenedPath;
|
||||
private ResourceBundle resourceBundle;
|
||||
private Region convertRegionEs;
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.previouslyOpenedPath = System.getProperty("user.home");
|
||||
|
||||
String myRegexp;
|
||||
if (File.separator.equals("/"))
|
||||
myRegexp = "^.+/";
|
||||
else
|
||||
myRegexp = "^.+\\\\";
|
||||
locationFirmwareLbl.textProperty().addListener((observableValue, currentText, updatedText) ->
|
||||
shortNameFirmwareLbl.setText(updatedText.replaceAll(myRegexp, "")));
|
||||
|
||||
locationKeysLbl.textProperty().addListener((observableValue, currentText, updatedText) ->
|
||||
shortNameKeysLbl.setText(updatedText.replaceAll(myRegexp, "")));
|
||||
|
||||
locationAtmosphereLbl.textProperty().addListener((observableValue, currentText, updatedText) ->
|
||||
shortNameAtmoLbl.setText(updatedText.replaceAll(myRegexp, "")));
|
||||
|
||||
convertRegionEs = createCakeRegion();
|
||||
makeEsBtn.setGraphic(convertRegionEs);
|
||||
|
||||
makeFsBtn.setGraphic(createCakeRegion());
|
||||
makeLoaderBtn.setGraphic(createCakeRegion());
|
||||
|
||||
AppPreferences preferences = AppPreferences.getInstance();
|
||||
String keysLocation = preferences.getKeysLocation();
|
||||
File keysFile = new File(keysLocation);
|
||||
|
||||
if (keysFile.exists() && keysFile.isFile()) {
|
||||
locationKeysLbl.setText(keysLocation);
|
||||
}
|
||||
|
||||
saveToLbl.setText(preferences.getPatchesSaveToLocation());
|
||||
makeEsBtn.disableProperty().bind(Bindings.or(
|
||||
Bindings.isEmpty(locationFirmwareLbl.textProperty()),
|
||||
Bindings.isEmpty(locationKeysLbl.textProperty())));
|
||||
makeEsBtn.setOnAction(actionEvent -> makeEs());
|
||||
|
||||
makeFsBtn.disableProperty().bind(Bindings.or(
|
||||
Bindings.isEmpty(locationFirmwareLbl.textProperty()),
|
||||
Bindings.isEmpty(locationKeysLbl.textProperty())));
|
||||
makeFsBtn.setOnAction(actionEvent -> makeFs());
|
||||
|
||||
makeLoaderBtn.disableProperty().bind(Bindings.isEmpty(locationAtmosphereLbl.textProperty()));
|
||||
makeLoaderBtn.setOnAction(actionEvent -> makeLoader());
|
||||
}
|
||||
private Region createCakeRegion(){
|
||||
Region cakeRegion = new Region();
|
||||
cakeRegion.getStyleClass().add("regionCake");
|
||||
return cakeRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag-n-drop support (dragOver consumer)
|
||||
* */
|
||||
@FXML
|
||||
private void handleDragOver(DragEvent event){
|
||||
if (event.getDragboard().hasFiles())
|
||||
event.acceptTransferModes(TransferMode.ANY);
|
||||
event.consume();
|
||||
}
|
||||
/**
|
||||
* Drag-n-drop support (drop consumer)
|
||||
* */
|
||||
@FXML
|
||||
private void handleDrop(DragEvent event){
|
||||
List<File> filesDropped = event.getDragboard().getFiles();
|
||||
for (File file : filesDropped){
|
||||
if (file.isDirectory()) {
|
||||
if (file.getName().toLowerCase().contains("atmosphe"))
|
||||
locationAtmosphereLbl.setText(file.getAbsolutePath());
|
||||
else
|
||||
locationFirmwareLbl.setText(file.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
String fileName = file.getName().toLowerCase();
|
||||
if ((fileName.endsWith(".dat")) ||
|
||||
(fileName.endsWith(".keys") &&
|
||||
! fileName.equals("dev.keys") &&
|
||||
! fileName.equals("title.keys")))
|
||||
locationKeysLbl.setText(file.getAbsolutePath());
|
||||
else if (fileName.equals("offsets.txt"))
|
||||
setOffsets(file);
|
||||
}
|
||||
event.setDropCompleted(true);
|
||||
event.consume();
|
||||
}
|
||||
|
||||
private void setOffsets(File fileWithOffsets){
|
||||
AppPreferences preferences = AppPreferences.getInstance();
|
||||
int count = 0;
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(fileWithOffsets))) {
|
||||
String fileLine;
|
||||
String[] lineValues;
|
||||
while ((fileLine = reader.readLine()) != null) {
|
||||
if (fileLine.startsWith("#"))
|
||||
continue;
|
||||
lineValues = fileLine.trim().split("\\s+?=\\s+?", 2);
|
||||
if (lineValues.length == 2) {
|
||||
String[] pointer = lineValues[0].split("_", 3);
|
||||
if (! pointer[0].equals("ES") && ! pointer[0].equals("FS"))
|
||||
continue;
|
||||
if (! pointer[1].matches("^([0-9A-Fa-f]{2})$"))
|
||||
continue;
|
||||
if (! pointer[2].matches("^([0-9A-Fa-f]{2})$"))
|
||||
continue;
|
||||
if (! lineValues[1].matches("^(([0-9A-Fa-f]{2})|\\.)+?$"))
|
||||
continue;
|
||||
preferences.setPatchPattern(lineValues[0], lineValues[1]);
|
||||
|
||||
System.out.println(pointer[0]+"_"+pointer[1]+"_"+pointer[2]+" = "+lineValues[1]);
|
||||
count++;
|
||||
statusLbl.setText("OK "+count);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void selectFirmware(){
|
||||
DirectoryChooser directoryChooser = new DirectoryChooser();
|
||||
directoryChooser.setTitle(resourceBundle.getString("tabPatches_Lbl_Firmware"));
|
||||
directoryChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath)));
|
||||
File firmware = directoryChooser.showDialog(patchesToolPane.getScene().getWindow());
|
||||
if (firmware == null)
|
||||
return;
|
||||
locationFirmwareLbl.setText(firmware.getAbsolutePath());
|
||||
previouslyOpenedPath = firmware.getParent();
|
||||
}
|
||||
@FXML
|
||||
private void selectAtmosphereFolder(){
|
||||
DirectoryChooser directoryChooser = new DirectoryChooser();
|
||||
directoryChooser.setTitle(resourceBundle.getString("tabPatches_Lbl_Atmo"));
|
||||
directoryChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath)));
|
||||
File firmware = directoryChooser.showDialog(patchesToolPane.getScene().getWindow());
|
||||
if (firmware == null)
|
||||
return;
|
||||
locationAtmosphereLbl.setText(firmware.getAbsolutePath());
|
||||
previouslyOpenedPath = firmware.getParent();
|
||||
}
|
||||
@FXML
|
||||
private void selectSaveTo(){
|
||||
DirectoryChooser directoryChooser = new DirectoryChooser();
|
||||
directoryChooser.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFolder"));
|
||||
directoryChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath)));
|
||||
File saveToDir = directoryChooser.showDialog(patchesToolPane.getScene().getWindow());
|
||||
if (saveToDir == null)
|
||||
return;
|
||||
saveToLbl.setText(saveToDir.getAbsolutePath());
|
||||
}
|
||||
@FXML
|
||||
private void selectProdKeys(){
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle(resourceBundle.getString("tabPatches_Lbl_Keys"));
|
||||
fileChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath)));
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("keys", "*.dat", "*.keys"));
|
||||
File keys = fileChooser.showOpenDialog(patchesToolPane.getScene().getWindow());
|
||||
if (keys == null || ! keys.exists())
|
||||
return;
|
||||
|
||||
locationKeysLbl.setText(keys.getAbsolutePath());
|
||||
previouslyOpenedPath = keys.getParent();
|
||||
}
|
||||
|
||||
private void makeEs(){
|
||||
if (locationFirmwareLbl.getText().isEmpty() || locationKeysLbl.getText().isEmpty()){
|
||||
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"),
|
||||
resourceBundle.getString("tabPatches_ServiceWindowMessageEsFs"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (workThread != null && workThread.isAlive())
|
||||
return;
|
||||
statusLbl.setText("");
|
||||
|
||||
if (MediatorControl.getInstance().getTransferActive()) {
|
||||
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"),
|
||||
resourceBundle.getString("windowBodyPleaseStopOtherProcessFirst"));
|
||||
return;
|
||||
}
|
||||
|
||||
EsPatchMaker esPatchMaker = new EsPatchMaker(locationFirmwareLbl.getText(), locationKeysLbl.getText(),
|
||||
saveToLbl.getText());
|
||||
workThread = new Thread(esPatchMaker);
|
||||
|
||||
workThread.setDaemon(true);
|
||||
workThread.start();
|
||||
}
|
||||
private void makeFs(){
|
||||
if (locationFirmwareLbl.getText().isEmpty() || locationKeysLbl.getText().isEmpty()){
|
||||
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"),
|
||||
resourceBundle.getString("tabPatches_ServiceWindowMessageEsFs"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (workThread != null && workThread.isAlive())
|
||||
return;
|
||||
statusLbl.setText("");
|
||||
|
||||
if (MediatorControl.getInstance().getTransferActive()) {
|
||||
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"),
|
||||
resourceBundle.getString("windowBodyPleaseStopOtherProcessFirst"));
|
||||
return;
|
||||
}
|
||||
|
||||
FsPatchMaker fsPatchMaker = new FsPatchMaker(locationFirmwareLbl.getText(), locationKeysLbl.getText(),
|
||||
saveToLbl.getText());
|
||||
workThread = new Thread(fsPatchMaker);
|
||||
|
||||
workThread.setDaemon(true);
|
||||
workThread.start();
|
||||
}
|
||||
private void makeLoader(){
|
||||
if (locationAtmosphereLbl.getText().isEmpty()){
|
||||
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"),
|
||||
resourceBundle.getString("tabPatches_ServiceWindowMessageLoader"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (workThread != null && workThread.isAlive())
|
||||
return;
|
||||
statusLbl.setText("");
|
||||
|
||||
if (MediatorControl.getInstance().getTransferActive()) {
|
||||
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"),
|
||||
resourceBundle.getString("windowBodyPleaseStopOtherProcessFirst"));
|
||||
return;
|
||||
}
|
||||
|
||||
LoaderPatchMaker loaderPatchMaker = new LoaderPatchMaker(locationAtmosphereLbl.getText(), saveToLbl.getText());
|
||||
workThread = new Thread(loaderPatchMaker);
|
||||
|
||||
workThread.setDaemon(true);
|
||||
workThread.start();
|
||||
}
|
||||
private void interruptProcessOfPatchMaking(){
|
||||
if (workThread == null || ! workThread.isAlive())
|
||||
return;
|
||||
|
||||
workThread.interrupt();
|
||||
}
|
||||
|
||||
public void notifyThreadStarted(boolean isActive, EModule type) {
|
||||
if (! type.equals(EModule.PATCHES)) {
|
||||
patchesToolPane.setDisable(isActive);
|
||||
return;
|
||||
}
|
||||
|
||||
convertRegionEs.getStyleClass().clear();
|
||||
makeFsBtn.setVisible(! isActive);
|
||||
makeLoaderBtn.setVisible(! isActive);
|
||||
|
||||
if (isActive) {
|
||||
MediatorControl.getInstance().getContoller().logArea.clear();
|
||||
convertRegionEs.getStyleClass().add("regionStop");
|
||||
|
||||
makeEsBtn.setOnAction(e-> interruptProcessOfPatchMaking());
|
||||
makeEsBtn.setText(resourceBundle.getString("btn_Stop"));
|
||||
makeEsBtn.getStyleClass().remove("buttonUp");
|
||||
makeEsBtn.getStyleClass().add("buttonStop");
|
||||
return;
|
||||
}
|
||||
convertRegionEs.getStyleClass().add("regionCake");
|
||||
|
||||
makeEsBtn.setOnAction(actionEvent -> makeEs());
|
||||
makeEsBtn.setText(resourceBundle.getString("tabPatches_Btn_MakeEs"));
|
||||
makeEsBtn.getStyleClass().remove("buttonStop");
|
||||
makeEsBtn.getStyleClass().add("buttonUp");
|
||||
}
|
||||
|
||||
public void setOneLineStatus(boolean statusSuccess){
|
||||
if (statusSuccess)
|
||||
statusLbl.setText(resourceBundle.getString("done_txt"));
|
||||
else
|
||||
statusLbl.setText(resourceBundle.getString("failure_txt"));
|
||||
}
|
||||
|
||||
void updatePreferencesOnExit(){
|
||||
AppPreferences.getInstance().setPatchesSaveToLocation(saveToLbl.getText());
|
||||
if (locationKeysLbl.getText().isEmpty())
|
||||
return;
|
||||
AppPreferences.getInstance().setKeysLocation(locationKeysLbl.getText());
|
||||
}
|
||||
|
||||
}
|
|
@ -43,6 +43,9 @@ import java.util.ResourceBundle;
|
|||
public class SettingsBlockGenericController implements Initializable {
|
||||
@FXML
|
||||
private ChoiceBox<LocaleHolder> languagesChB;
|
||||
@FXML
|
||||
private Button fontSelectBtn;
|
||||
|
||||
@FXML
|
||||
private Button submitLanguageBtn,
|
||||
driversInstallBtn,
|
||||
|
@ -81,6 +84,14 @@ public class SettingsBlockGenericController implements Initializable {
|
|||
newVersionHyperlink.setOnAction(e-> hostServices.showDocument(newVersionHyperlink.getText()));
|
||||
checkForUpdBtn.setOnAction(e->checkForUpdatesAction());
|
||||
submitLanguageBtn.setOnAction(e->languageButtonAction());
|
||||
fontSelectBtn.setOnAction(e -> openFontSettings());
|
||||
}
|
||||
private void openFontSettings() {
|
||||
try {
|
||||
new FontSettings(resourceBundle);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void setDriversInstallFeature(){
|
||||
|
|
|
@ -38,7 +38,7 @@ public class SettingsBlockGoldleafController implements Initializable {
|
|||
final AppPreferences preferences = AppPreferences.getInstance();
|
||||
|
||||
nspFilesFilterForGLCB.setSelected(preferences.getNspFileFilterGL());
|
||||
glVersionChoiceBox.getItems().addAll(AppPreferences.goldleafSupportedVersions);
|
||||
glVersionChoiceBox.getItems().addAll(AppPreferences.GOLDLEAF_SUPPORTED_VERSIONS);
|
||||
|
||||
glVersionChoiceBox.getSelectionModel().select(preferences.getGlVersion());
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SettingsBlockTinfoilController implements Initializable {
|
|||
|
||||
final AppPreferences preferences = AppPreferences.getInstance();
|
||||
|
||||
networkExpertSettingsVBox.disableProperty().bind(networkExpertModeCB.selectedProperty().not());
|
||||
networkExpertSettingsVBox.visibleProperty().bind(networkExpertModeCB.selectedProperty());
|
||||
|
||||
pcIpTF.disableProperty().bind(autoDetectIpCB.selectedProperty());
|
||||
pcPortTF.disableProperty().bind(randomlySelectPortCB.selectedProperty());
|
||||
|
|
|
@ -40,11 +40,12 @@ public class MediatorControl {
|
|||
}
|
||||
|
||||
public NSLMainController getContoller(){ return mainController; }
|
||||
public GamesController getGamesController(){ return mainController.getGamesCtrlr(); };
|
||||
public SettingsController getSettingsController(){ return mainController.getSettingsCtrlr(); };
|
||||
public SplitMergeController getSplitMergeController(){ return mainController.getSmCtrlr(); };
|
||||
public RcmController getRcmController(){ return mainController.getRcmCtrlr(); };
|
||||
public NxdtController getNxdtController(){ return mainController.getNXDTabController(); };
|
||||
public GamesController getGamesController(){ return mainController.getGamesCtrlr(); }
|
||||
public SettingsController getSettingsController(){ return mainController.getSettingsCtrlr(); }
|
||||
public SplitMergeController getSplitMergeController(){ return mainController.getSmCtrlr(); }
|
||||
public RcmController getRcmController(){ return mainController.getRcmCtrlr(); }
|
||||
public NxdtController getNxdtController(){ return mainController.getNXDTabController(); }
|
||||
public PatchesController getPatchesController(){ return mainController.getPatchesTabController(); }
|
||||
|
||||
public ResourceBundle getResourceBundle(){
|
||||
return mainController.getResourceBundle();
|
||||
|
@ -56,6 +57,11 @@ public class MediatorControl {
|
|||
getSplitMergeController().notifyThreadStarted(isActive, appModuleType);
|
||||
getRcmController().notifyThreadStarted(isActive, appModuleType);
|
||||
getNxdtController().notifyThreadStarted(isActive, appModuleType);
|
||||
getPatchesController().notifyThreadStarted(isActive, appModuleType);
|
||||
}
|
||||
public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
|
||||
public void updateApplicationFont(String fontFamily, double fontSize){
|
||||
mainController.logArea.getScene().getRoot().setStyle(
|
||||
String.format("-fx-font-family: \"%s\"; -fx-font-size: %.0f;", fontFamily, fontSize));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,8 @@ public class MessagesConsumer extends AnimationTimer {
|
|||
case SPLIT_MERGE_TOOL:
|
||||
MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get());
|
||||
break;
|
||||
case PATCHES:
|
||||
MediatorControl.getInstance().getPatchesController().setOneLineStatus(oneLinerStatus.get());
|
||||
}
|
||||
this.stop();
|
||||
}
|
||||
|
|
|
@ -22,5 +22,6 @@ public enum EModule {
|
|||
USB_NET_TRANSFERS,
|
||||
SPLIT_MERGE_TOOL,
|
||||
RCM,
|
||||
NXDT
|
||||
NXDT,
|
||||
PATCHES
|
||||
}
|
||||
|
|
|
@ -28,11 +28,12 @@ import nsusbloader.Controllers.NSLMainController;
|
|||
import nsusbloader.cli.CommandLineInterface;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class NSLMain extends Application {
|
||||
|
||||
public static final String appVersion = "v5.2";
|
||||
public static String appVersion;
|
||||
public static boolean isCli;
|
||||
|
||||
@Override
|
||||
|
@ -46,10 +47,10 @@ public class NSLMain extends Application {
|
|||
Parent root = loader.load();
|
||||
|
||||
primaryStage.getIcons().addAll(
|
||||
new Image(getClass().getResourceAsStream("/res/app_icon32x32.png")),
|
||||
new Image(getClass().getResourceAsStream("/res/app_icon48x48.png")),
|
||||
new Image(getClass().getResourceAsStream("/res/app_icon64x64.png")),
|
||||
new Image(getClass().getResourceAsStream("/res/app_icon128x128.png"))
|
||||
new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon32x32.png"))),
|
||||
new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon48x48.png"))),
|
||||
new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon64x64.png"))),
|
||||
new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon128x128.png")))
|
||||
);
|
||||
|
||||
primaryStage.setTitle("NS-USBloader "+appVersion);
|
||||
|
@ -61,6 +62,7 @@ public class NSLMain extends Application {
|
|||
);
|
||||
|
||||
mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
root.setStyle(AppPreferences.getInstance().getFontStyle());
|
||||
|
||||
primaryStage.setScene(mainScene);
|
||||
primaryStage.show();
|
||||
|
@ -82,6 +84,7 @@ public class NSLMain extends Application {
|
|||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
NSLMain.appVersion = ResourceBundle.getBundle("app").getString("_version");
|
||||
if (args.length == 0) {
|
||||
launch(args);
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
Copyright 2019-2020 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Debug tool like hexdump <3
|
||||
*/
|
||||
public class RainbowHexDump {
|
||||
private static final String ANSI_RESET = "\u001B[0m";
|
||||
private static final String ANSI_BLACK = "\u001B[30m";
|
||||
private static final String ANSI_RED = "\u001B[31m";
|
||||
private static final String ANSI_GREEN = "\u001B[32m";
|
||||
private static final String ANSI_YELLOW = "\u001B[33m";
|
||||
private static final String ANSI_BLUE = "\u001B[34m";
|
||||
private static final String ANSI_PURPLE = "\u001B[35m";
|
||||
private static final String ANSI_CYAN = "\u001B[36m";
|
||||
private static final String ANSI_WHITE = "\u001B[37m";
|
||||
|
||||
public static void hexDumpUTF8(byte[] byteArray){
|
||||
System.out.print(ANSI_BLUE);
|
||||
for (int i=0; i < byteArray.length; i++)
|
||||
System.out.printf("%02d-", i%100);
|
||||
System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET);
|
||||
for (byte b: byteArray)
|
||||
System.out.printf("%02x ", b);
|
||||
System.out.println();
|
||||
System.out.print("\t\t\t"
|
||||
+ new String(byteArray, StandardCharsets.UTF_8)
|
||||
+ "\n");
|
||||
}
|
||||
|
||||
public static void hexDumpUTF8ForWin(byte[] byteArray){
|
||||
for (int i=0; i < byteArray.length; i++)
|
||||
System.out.printf("%02d-", i%100);
|
||||
System.out.println(">"+byteArray.length);
|
||||
for (byte b: byteArray)
|
||||
System.out.printf("%02x ", b);
|
||||
System.out.println();
|
||||
System.out.print(new String(byteArray, StandardCharsets.UTF_8)
|
||||
+ "\n");
|
||||
}
|
||||
|
||||
public static void hexDumpUTF16LE(byte[] byteArray){
|
||||
System.out.print(ANSI_BLUE);
|
||||
for (int i=0; i < byteArray.length; i++)
|
||||
System.out.printf("%02d-", i%100);
|
||||
System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET);
|
||||
for (byte b: byteArray)
|
||||
System.out.printf("%02x ", b);
|
||||
System.out.print(new String(byteArray, StandardCharsets.UTF_16LE)
|
||||
+ "\n");
|
||||
}
|
||||
}
|
|
@ -44,7 +44,6 @@ public class ServiceWindow {
|
|||
alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE);
|
||||
alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||
alertBox.setResizable(true); // Java bug workaround for JDR11/OpenJFX. TODO: nothing. really.
|
||||
alertBox.getDialogPane().getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
|
||||
Stage dialogStage = (Stage) alertBox.getDialogPane().getScene().getWindow();
|
||||
dialogStage.setAlwaysOnTop(true);
|
||||
|
@ -54,6 +53,9 @@ public class ServiceWindow {
|
|||
new Image("/res/warn_ico64x64.png"),
|
||||
new Image("/res/warn_ico128x128.png")
|
||||
);
|
||||
alertBox.getDialogPane().getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
dialogStage.getScene().getRoot().setStyle(AppPreferences.getInstance().getFontStyle());
|
||||
|
||||
alertBox.show();
|
||||
dialogStage.toFront();
|
||||
}
|
||||
|
@ -68,7 +70,6 @@ public class ServiceWindow {
|
|||
alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE);
|
||||
alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||
alertBox.setResizable(true); // Java bug workaround for JDR11/OpenJFX. TODO: nothing. really.
|
||||
alertBox.getDialogPane().getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
|
||||
Stage dialogStage = (Stage) alertBox.getDialogPane().getScene().getWindow();
|
||||
dialogStage.setAlwaysOnTop(true);
|
||||
|
@ -78,6 +79,10 @@ public class ServiceWindow {
|
|||
new Image("/res/ask_ico64x64.png"),
|
||||
new Image("/res/ask_ico128x128.png")
|
||||
);
|
||||
|
||||
alertBox.getDialogPane().getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
dialogStage.getScene().getRoot().setStyle(AppPreferences.getInstance().getFontStyle());
|
||||
|
||||
dialogStage.toFront();
|
||||
|
||||
Optional<ButtonType> result = alertBox.showAndWait();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019-2020 Dmitry Isaenko
|
||||
Copyright 2019-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
|
@ -26,16 +26,14 @@ public class LocaleHolder {
|
|||
private final String localeCode;
|
||||
private final String languageName;
|
||||
|
||||
public LocaleHolder(Locale locale){
|
||||
this.locale = locale;
|
||||
this.localeCode = locale.toString();
|
||||
this.languageName = locale.getDisplayLanguage(locale) + " (" + locale + ")";
|
||||
}
|
||||
|
||||
public LocaleHolder(String localeFileName) {
|
||||
String country = localeFileName.substring(7, 9);
|
||||
String language = localeFileName.substring(10, 12);
|
||||
this.locale = new Locale(country, language);
|
||||
String language = localeFileName.substring(7, 9);
|
||||
String country;
|
||||
if (localeFileName.length() > 23) // ISO 639-3 not supported by Java
|
||||
country = localeFileName.substring(10, localeFileName.indexOf('.'));
|
||||
else // ISO 639-1
|
||||
country = localeFileName.substring(10, 12);
|
||||
this.locale = new Locale(language, country);
|
||||
this.localeCode = locale.toString();
|
||||
this.languageName = locale.getDisplayLanguage(locale) + " (" + locale + ")";
|
||||
}
|
||||
|
@ -47,7 +45,7 @@ public class LocaleHolder {
|
|||
|
||||
public String getLocaleCode(){
|
||||
return localeCode;
|
||||
};
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019-2020 Dmitry Isaenko
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
|
@ -25,8 +25,8 @@ import java.net.URL;
|
|||
|
||||
public class DownloadDriversTask extends Task<String> {
|
||||
|
||||
public static final long DRIVERS_FILE_SIZE = 3857375;
|
||||
private static final String driverFileLocationURL = "https://github.com/developersu/NS-Drivers/releases/download/v1.0/Drivers_set.exe";
|
||||
private static final long driversFileSize = 3857375;
|
||||
|
||||
private static File driversInstallerFile;
|
||||
|
||||
|
@ -38,7 +38,7 @@ public class DownloadDriversTask extends Task<String> {
|
|||
}
|
||||
|
||||
private boolean isDriversDownloaded(){
|
||||
return driversInstallerFile != null && driversInstallerFile.length() == driversFileSize;
|
||||
return driversInstallerFile != null && driversInstallerFile.length() == DRIVERS_FILE_SIZE;
|
||||
}
|
||||
|
||||
private boolean downloadDrivers(){
|
||||
|
@ -64,7 +64,7 @@ public class DownloadDriversTask extends Task<String> {
|
|||
while ((bytesRead = bis.read(dataBuffer, 0, 1024)) != -1) {
|
||||
fos.write(dataBuffer, 0, bytesRead);
|
||||
totalRead += bytesRead;
|
||||
updateProgress(totalRead, driversFileSize);
|
||||
updateProgress(totalRead, DRIVERS_FILE_SIZE);
|
||||
if (this.isCancelled()) {
|
||||
bis.close();
|
||||
fos.close();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019-2020 Dmitry Isaenko
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
|
@ -32,19 +32,32 @@ import javafx.scene.layout.VBox;
|
|||
import javafx.stage.Stage;
|
||||
import nsusbloader.AppPreferences;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.File;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class DriversInstall {
|
||||
|
||||
private static volatile boolean isRunning;
|
||||
|
||||
private final ResourceBundle resourceBundle;
|
||||
private Label runInstallerStatusLabel;
|
||||
|
||||
public DriversInstall(ResourceBundle rb){
|
||||
this.resourceBundle = rb;
|
||||
|
||||
if (isDriversDistributesWithExecutable())
|
||||
runInstaller("Drivers_set.exe");
|
||||
else
|
||||
runDownloadProcess();
|
||||
}
|
||||
|
||||
private boolean isDriversDistributesWithExecutable(){
|
||||
final File drivers = new File("Drivers_set.exe");
|
||||
|
||||
return drivers.length() == DownloadDriversTask.DRIVERS_FILE_SIZE;
|
||||
}
|
||||
|
||||
private void runDownloadProcess(){
|
||||
if (DriversInstall.isRunning)
|
||||
return;
|
||||
|
||||
|
@ -52,11 +65,11 @@ public class DriversInstall {
|
|||
|
||||
DownloadDriversTask downloadTask = new DownloadDriversTask();
|
||||
|
||||
Button cancelButton = new Button(rb.getString("btn_Cancel"));
|
||||
Button cancelButton = new Button(resourceBundle.getString("btn_Cancel"));
|
||||
|
||||
HBox hBoxInformation = new HBox();
|
||||
hBoxInformation.setAlignment(Pos.TOP_LEFT);
|
||||
hBoxInformation.getChildren().add(new Label(rb.getString("windowBodyDownloadDrivers")));
|
||||
hBoxInformation.getChildren().add(new Label(resourceBundle.getString("windowBodyDownloadDrivers")));
|
||||
|
||||
ProgressBar progressBar = new ProgressBar();
|
||||
progressBar.setPrefWidth(Double.MAX_VALUE);
|
||||
|
@ -93,7 +106,7 @@ public class DriversInstall {
|
|||
|
||||
Stage stage = new Stage();
|
||||
|
||||
stage.setTitle(rb.getString("windowTitleDownloadDrivers"));
|
||||
stage.setTitle(resourceBundle.getString("windowTitleDownloadDrivers"));
|
||||
stage.getIcons().addAll(
|
||||
new Image("/res/dwnload_ico32x32.png"), //TODO: REDRAW
|
||||
new Image("/res/dwnload_ico48x48.png"),
|
||||
|
@ -106,6 +119,7 @@ public class DriversInstall {
|
|||
Scene mainScene = new Scene(parentVBox, 405, 155);
|
||||
|
||||
mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
|
||||
parentVBox.setStyle(AppPreferences.getInstance().getFontStyle());
|
||||
|
||||
stage.setOnHidden(windowEvent -> {
|
||||
downloadTask.cancel(true );
|
||||
|
@ -117,7 +131,7 @@ public class DriversInstall {
|
|||
stage.toFront();
|
||||
|
||||
downloadTask.setOnSucceeded(event -> {
|
||||
cancelButton.setText(rb.getString("btn_Close"));
|
||||
cancelButton.setText(resourceBundle.getString("btn_Close"));
|
||||
|
||||
String returnedValue = downloadTask.getValue();
|
||||
|
||||
|
@ -143,7 +157,7 @@ public class DriversInstall {
|
|||
return true;
|
||||
}
|
||||
catch (Exception e){
|
||||
runInstallerStatusLabel.setText("Error: "+e.toString());
|
||||
runInstallerStatusLabel.setText("Error: "+e);
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches;
|
||||
/**
|
||||
* Searches instructions (via known patterns) that follows 'specific instruction' we want to patch.
|
||||
* Returns offset of the pattern. Not offset of the 'specific instruction'.
|
||||
* */
|
||||
public abstract class AHeuristic {
|
||||
protected boolean isLDR(int expression){ return (expression >> 22 & 0x2FF) == 0x2e5; }// LDR ! Sounds like LDP, don't mess up
|
||||
protected boolean isLDP(int expression){ return (expression >> 22 & 0x1F9) == 0xA1; }// LDP !
|
||||
protected boolean isCBNZ(int expression){ return (expression >> 24 & 0x7f) == 0x35; }
|
||||
protected boolean isMOV(int expression){ return (expression >> 23 & 0xff) == 0xA5; }
|
||||
protected boolean isTBZ(int expression){ return (expression >> 24 & 0x7f) == 0x36; }
|
||||
protected boolean isLDRB_LDURB(int expression){ return (expression >> 21 & 0x7f7) == 0x1c2; }
|
||||
protected boolean isMOV_REG(int expression){ return (expression & 0x7FE0FFE0) == 0x2A0003E0; }
|
||||
protected boolean isB(int expression) { return (expression >> 26 & 0x3f) == 0x5; }
|
||||
protected boolean isBL(int expression){ return (expression >> 26 & 0x3f) == 0x25; }
|
||||
protected boolean isADD(int expression){ return (expression >> 23 & 0xff) == 0x22; }
|
||||
public abstract boolean isFound();
|
||||
public abstract boolean wantLessEntropy();
|
||||
public abstract int getOffset() throws Exception;
|
||||
public abstract String getDetails();
|
||||
|
||||
/**
|
||||
* Should be used if wantLessEntropy() == true
|
||||
* @return isFound();
|
||||
* */
|
||||
public abstract boolean setOffsetsNearby(int offsetNearby);
|
||||
}
|
|
@ -0,0 +1,591 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import nsusbloader.NSLMain;
|
||||
|
||||
public class BinToAsmPrinter {
|
||||
static {
|
||||
boolean notWindows = ! System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
|
||||
if(notWindows && NSLMain.isCli){
|
||||
ANSI_RESET = "\u001B[0m";
|
||||
ANSI_GREEN = "\u001B[32m";
|
||||
ANSI_BLUE = "\u001B[34m";
|
||||
ANSI_YELLOW = "\u001B[33m";
|
||||
ANSI_PURPLE = "\u001B[35m";
|
||||
ANSI_CYAN = "\u001B[36m";
|
||||
ANSI_RED = "\u001B[31m";
|
||||
}
|
||||
else {
|
||||
ANSI_RESET = ANSI_RED = ANSI_GREEN = ANSI_BLUE = ANSI_YELLOW = ANSI_PURPLE = ANSI_CYAN = "";
|
||||
}
|
||||
}
|
||||
private static final String ANSI_RESET;
|
||||
private static final String ANSI_RED;
|
||||
private static final String ANSI_GREEN;
|
||||
private static final String ANSI_BLUE;
|
||||
private static final String ANSI_YELLOW;
|
||||
private static final String ANSI_PURPLE;
|
||||
private static final String ANSI_CYAN;
|
||||
|
||||
public static String print(int instructionExpression, int offset){
|
||||
if (instructionExpression == 0xd503201f)
|
||||
return printNOP(instructionExpression);
|
||||
|
||||
if ((instructionExpression & 0x7FE0FFE0) == 0x2A0003E0) {
|
||||
return printMOVRegister(instructionExpression);
|
||||
}
|
||||
|
||||
switch ((instructionExpression >> 23 & 0b011111111)){
|
||||
case 0xA5:
|
||||
return printMOV(instructionExpression);
|
||||
case 0x62:
|
||||
if (((instructionExpression & 0x1f) == 0x1f)){
|
||||
return printCMN(instructionExpression);
|
||||
}
|
||||
}
|
||||
|
||||
switch (instructionExpression >> 24 & 0xff) {
|
||||
case 0x34:
|
||||
case 0xb4:
|
||||
return printCBZ(instructionExpression, offset);
|
||||
case 0xb5:
|
||||
case 0x35:
|
||||
return printCBNZ(instructionExpression, offset);
|
||||
case 0x36:
|
||||
case 0xb6:
|
||||
return printTBZ(instructionExpression, offset);
|
||||
case 0x54:
|
||||
return printBConditional(instructionExpression, offset);
|
||||
}
|
||||
switch ((instructionExpression >> 26 & 0b111111)) {
|
||||
case 0x5:
|
||||
return printB(instructionExpression, offset);
|
||||
case 0x25:
|
||||
return printBL(instructionExpression, offset);
|
||||
}
|
||||
|
||||
return printUnknown(instructionExpression);
|
||||
}
|
||||
public static String printSimplified(int instructionExpression, int offset){
|
||||
if (instructionExpression == 0xd503201f)
|
||||
return printNOPSimplified(instructionExpression, offset);
|
||||
|
||||
if ((instructionExpression & 0x7FE0FFE0) == 0x2A0003E0) {
|
||||
return printMOVRegisterSimplified(instructionExpression, offset);
|
||||
}
|
||||
|
||||
switch (instructionExpression >> 22 & 0b1011111111) {
|
||||
case 0x2e5:
|
||||
return printLRDImmUnsignSimplified(instructionExpression, offset);
|
||||
case 0xe5:
|
||||
return printLRDBImmUnsignSimplified(instructionExpression, offset);
|
||||
}
|
||||
|
||||
if ((instructionExpression >> 21 & 0x7FF) == 0x1C2)
|
||||
return printImTooLazy("LDURB", instructionExpression, offset);
|
||||
|
||||
// same to (afterJumpExpression >> 23 & 0x1F9) != 0xA1
|
||||
switch (instructionExpression >> 22 & 0x1FF){
|
||||
case 0xA3: // 0b10100011
|
||||
case 0xA7: // 0b10100111
|
||||
case 0xA5: // 0b10100101
|
||||
return printImTooLazy("LDP", instructionExpression, offset);
|
||||
}
|
||||
|
||||
switch ((instructionExpression >> 23 & 0x1ff)){
|
||||
case 0xA5:
|
||||
return printMOVSimplified(instructionExpression, offset);
|
||||
case 0x22:
|
||||
return printImTooLazy("ADD", instructionExpression, offset);
|
||||
case 0x62:
|
||||
if (((instructionExpression & 0x1f) == 0x1f)){
|
||||
return printCMNSimplified(instructionExpression, offset);
|
||||
}
|
||||
case 0xA2:
|
||||
return printSUBSimplified(instructionExpression, offset);
|
||||
case 0xE2:
|
||||
case 0x1e2:
|
||||
return printCMPSimplified(instructionExpression, offset);
|
||||
case 0x24:
|
||||
case 0x124:
|
||||
return printANDSimplified(instructionExpression, offset);
|
||||
}
|
||||
|
||||
switch (instructionExpression >> 24 & 0xff) {
|
||||
case 0x34:
|
||||
case 0xb4:
|
||||
return printCBZSimplified(instructionExpression, offset);
|
||||
case 0xb5:
|
||||
case 0x35:
|
||||
return printCBNZSimplified(instructionExpression, offset);
|
||||
case 0x36:
|
||||
case 0xb6:
|
||||
return printTBZSimplified(instructionExpression, offset);
|
||||
case 0x54:
|
||||
return printBConditionalSimplified(instructionExpression, offset);
|
||||
case 0xeb:
|
||||
case 0x6b:
|
||||
if ((instructionExpression & 0x1f) == 0b11111)
|
||||
return printCMPShiftedRegisterSimplified(instructionExpression, offset);
|
||||
}
|
||||
|
||||
switch (instructionExpression >> 26 & 0b111111) {
|
||||
case 0x5:
|
||||
return printBSimplified(instructionExpression, offset);
|
||||
case 0x25:
|
||||
return printBLSimplified(instructionExpression, offset);
|
||||
}
|
||||
|
||||
if ((instructionExpression >> 10 & 0x3FFFFF) == 0x3597c0 && ((instructionExpression & 0x1F) == 0))
|
||||
return printRetSimplified(instructionExpression, offset);
|
||||
return printUnknownSimplified(instructionExpression, offset);
|
||||
}
|
||||
|
||||
private static String printCBZ(int instructionExpression, int offset){
|
||||
int conditionalJumpLocation = ((instructionExpression >> 5 & 0x7FFFF) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(ANSI_YELLOW + "sf == 0 ? <Wt> else <Xt>\n" +
|
||||
"CBZ <?t>, <label> |.....CBZ signature......|\n" +
|
||||
ANSI_CYAN + " sf 0 1 1 0 1 0 0 |imm19..........................................................||Rd.............|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n\n"+
|
||||
ANSI_YELLOW + "CBZ " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
(instructionExpression >> 31 == 0) ? "w" : "x", (instructionExpression & 0b11111),
|
||||
conditionalJumpLocation, (conditionalJumpLocation + 0x100));
|
||||
}
|
||||
|
||||
|
||||
private static String printCBNZ(int instructionExpression, int offset){
|
||||
int conditionalJumpLocation = ((instructionExpression >> 5 & 0x7FFFF) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(ANSI_YELLOW + "sf == 0 ? <Wt> else <Xt>\n" +
|
||||
"CBNZ <?t>, <label> |.....CBZ signature......|\n" +
|
||||
ANSI_CYAN + " sf 0 1 1 0 1 0 |imm19..........................................................||Rd.............|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n\n"+
|
||||
ANSI_YELLOW + "CBNZ " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
(instructionExpression >> 31 == 0) ? "w" : "x", (instructionExpression & 0b11111),
|
||||
conditionalJumpLocation, (conditionalJumpLocation + 0x100));
|
||||
}
|
||||
|
||||
private static String printCMN(int instructionExpression){
|
||||
int Rn = instructionExpression >> 5 & 0x1F;
|
||||
int imm = instructionExpression >> 10 & 0xFFF;
|
||||
|
||||
return String.format(ANSI_YELLOW + "sf == 0 ? <Wt> else <Xt>\n" +
|
||||
"CMN <?n>, <label> |.....CMN signature...........| |..CMN signature.|\n" +
|
||||
ANSI_CYAN+" sf 0 1 1 0 0 0 1 0 |imm12......................................||Rn.............| 1 1 1 1 1" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n\n" +
|
||||
ANSI_YELLOW + "CMN " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + "\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
(instructionExpression >> 31 == 0) ? "w" : "x", Rn, imm);
|
||||
}
|
||||
|
||||
private static String printB(int instructionExpression, int offset){
|
||||
int conditionalJumpLocationPatch = ((instructionExpression & 0x3ffffff) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(ANSI_YELLOW+"B <label> |....B signature...|\n" +
|
||||
" "+ANSI_CYAN+" 0 0 0 1 0 1 |imm26...................................................................................|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n" +
|
||||
ANSI_YELLOW + "%s " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
((instructionExpression >> 26 & 0b111111) == 5)?"B":"Some weird stuff",
|
||||
conditionalJumpLocationPatch, (conditionalJumpLocationPatch + 0x100));
|
||||
}
|
||||
|
||||
|
||||
private static String printBL(int instructionExpression, int offset){
|
||||
int conditionalJumpLocationPatch = ((instructionExpression & 0x3ffffff) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(ANSI_YELLOW+"BL <label> |...BL signature...|\n" +
|
||||
" "+ANSI_CYAN+" 1 0 0 1 0 1 |imm26...................................................................................|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n" +
|
||||
ANSI_YELLOW + "%s " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
((instructionExpression >> 26 & 0b111111) == 25)?"BL":"Some weird stuff",
|
||||
conditionalJumpLocationPatch, (conditionalJumpLocationPatch + 0x100));
|
||||
}
|
||||
|
||||
|
||||
private static String printMOV(int instructionExpression){
|
||||
int imm16 = instructionExpression >> 5 & 0xFFFF;
|
||||
int sfHw = (instructionExpression >> 22 & 1);
|
||||
|
||||
return String.format(ANSI_YELLOW + "sf == 0 && hw == 0x ? <Wt> else <Xt>\n" +
|
||||
"MOV <?t>, <label> |.....MOV signature...........|\n" +
|
||||
ANSI_CYAN +" sf 1 0 1 0 0 1 0 1 |hw...|imm16.................................................||Rd.............|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n" +
|
||||
ANSI_YELLOW + "MOV " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + "\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
(sfHw == 0) ? "w" : "x", (instructionExpression & 0b11111), imm16);
|
||||
}
|
||||
|
||||
private static String printMOVRegister(int instructionExpression){
|
||||
String sfHw = (instructionExpression >> 31 & 1) == 0 ? "W" : "X";
|
||||
int Rm = instructionExpression >> 16 & 0xF;
|
||||
int Rd = instructionExpression & 0xF;
|
||||
|
||||
return String.format(ANSI_YELLOW + "sf == 0 && hw == 0x ? <Wt> else <Xt>\n" +
|
||||
"MOV (register) <?d>, <?m> |.....MOV (register) signature.......|\n" +
|
||||
ANSI_CYAN +" sf 0 1 0 1 0 1 0 0 0 0 |Rm..............| 0 0 0 0 0 0 1 1 1 1 1 |Rd.............|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n" +
|
||||
ANSI_YELLOW + "MOV(reg) " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "%s%d" + ANSI_RESET + "\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
sfHw, Rm, sfHw, Rd);
|
||||
}
|
||||
|
||||
private static String printNOP(int instructionExpression){
|
||||
return String.format(
|
||||
ANSI_YELLOW+"NOP |.....NOP signature..........................................................................................|\n" +
|
||||
ANSI_CYAN +" 1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 " + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n"+
|
||||
"Instruction (BE) : %s | %s\n" +
|
||||
ANSI_YELLOW + "%s" + ANSI_RESET + "\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
(instructionExpression == 0xd503201f)?"NOP":"Some weird stuff");
|
||||
}
|
||||
|
||||
private static String printTBZ(int instructionExpression, int offset){
|
||||
int xwSelector = (instructionExpression >> 31 & 1);
|
||||
int imm = instructionExpression >> 18 & 0b11111;
|
||||
int Rt = instructionExpression & 0b11111;
|
||||
int label = (offset + (instructionExpression >> 5 & 0x3fff) * 4) & 0xfffff;
|
||||
|
||||
return String.format(ANSI_YELLOW + "sf == 0 && hw == 0x ? <Wt> else <Xt>\n" +
|
||||
"TBZ <?t>,#<imm>, <label> |.....TBZ signature.......|\n" +
|
||||
ANSI_CYAN+" b5 0 1 1 0 1 1 0 |b40.............|imm14.........................................||Rt.............|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n" +
|
||||
ANSI_YELLOW + "TBZ " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ", " + ANSI_PURPLE + "%x" + ANSI_RESET + "\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
(xwSelector == 0) ? "w" : "x", Rt, imm, label);
|
||||
}
|
||||
|
||||
private static String printBConditional(int instructionExpression, int offset){
|
||||
int conditionalJumpLocation = ((instructionExpression >> 4 & 0b1111111111111111111) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(
|
||||
ANSI_YELLOW+"B.%s <label> |...B.cond signature.......|\n" +
|
||||
ANSI_CYAN+" 0 1 0 1 0 1 0 0 |imm19..........................................................| 0 |.condit...|" + ANSI_RESET + "\n" +
|
||||
ANSI_GREEN +" 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n" +
|
||||
ANSI_YELLOW + "B.%s " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
getBConditionalMarker(instructionExpression & 0xf),
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression),
|
||||
getBConditionalMarker(instructionExpression & 0xf),
|
||||
conditionalJumpLocation, (conditionalJumpLocation + 0x100));
|
||||
}
|
||||
|
||||
private static String printUnknown(int instructionExpression){
|
||||
return String.format(ANSI_RED + " 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 " + ANSI_RESET + "\n" +
|
||||
"Instruction (BE) : %s | %s\n",
|
||||
intAsBinString(instructionExpression), intAsHexString(instructionExpression));
|
||||
}
|
||||
|
||||
private static String getBConditionalMarker(int cond){
|
||||
switch (cond){
|
||||
case 0b0000: return "EQ";
|
||||
case 0b0001: return "NE";
|
||||
case 0b0010: return "CS";
|
||||
case 0b0011: return "CC";
|
||||
case 0b0100: return "MI";
|
||||
case 0b0101: return "PL";
|
||||
case 0b0110: return "VS";
|
||||
case 0b0111: return "VC";
|
||||
case 0b1000: return "HI";
|
||||
case 0b1001: return "LS";
|
||||
case 0b1010: return "GE";
|
||||
case 0b1011: return "LT";
|
||||
case 0b1100: return "GT";
|
||||
case 0b1101: return "LE";
|
||||
case 0b1110: return "AL";
|
||||
default: return "??";
|
||||
}
|
||||
/*
|
||||
"__________________CheatSheet_____________________________________\n"+
|
||||
"0000 | EQ | Z set | equal\n"+
|
||||
"0001 | NE | Z clear | not equal\n"+
|
||||
"0010 | CS | C set | unsigned higher or same\n"+
|
||||
"0011 | CC | C clear | unsigned lower\n"+
|
||||
"0100 | MI | N set | negative\n"+
|
||||
"0101 | PL | N clear | positive or zero\n"+
|
||||
"0110 | VS | V set | overflow\n"+
|
||||
"0111 | VC | V clear | no overflow\n"+
|
||||
"1000 | HI | C set & V clear | unsigned higher\n"+
|
||||
"1001 | LS | C clear or Z set | unsigned lower or same\n"+
|
||||
"1010 | GE | N equals V | greater or equal\n"+
|
||||
"1011 | LT | N not equals V | less than\n"+
|
||||
"1100 | GT | Z clear AND (N equals V) | greater that\n"+
|
||||
"1101 | LE | Z set OR (N not equals V) | less than or equal\n"+
|
||||
"1110 | AL | (ignored) | always\n";
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
private static String printCBZSimplified(int instructionExpression, int offset){
|
||||
int conditionalJumpLocation = ((instructionExpression >> 5 & 0x7FFFF) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " CBZ " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (" + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
(instructionExpression >> 31 == 0) ? "w" : "x", (instructionExpression & 0b11111),
|
||||
conditionalJumpLocation, (conditionalJumpLocation + 0x100));
|
||||
}
|
||||
|
||||
private static String printCBNZSimplified(int instructionExpression, int offset){
|
||||
int conditionalJumpLocation = ((instructionExpression >> 5 & 0x7FFFF) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " CBNZ " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (" + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
(instructionExpression >> 31 == 0) ? "w" : "x", (instructionExpression & 0b11111),
|
||||
conditionalJumpLocation, (conditionalJumpLocation + 0x100));
|
||||
}
|
||||
|
||||
private static String printBSimplified(int instructionExpression, int offset){
|
||||
int conditionalJumpLocationPatch = ((instructionExpression & 0x3ffffff) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " B " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
conditionalJumpLocationPatch, (conditionalJumpLocationPatch + 0x100));
|
||||
}
|
||||
|
||||
|
||||
private static String printBLSimplified(int instructionExpression, int offset){
|
||||
int conditionalJumpLocationPatch = ((instructionExpression & 0x3ffffff) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " BL " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
conditionalJumpLocationPatch, (conditionalJumpLocationPatch + 0x100));
|
||||
}
|
||||
|
||||
private static String printMOVSimplified(int instructionExpression, int offset){
|
||||
int imm16 = instructionExpression >> 5 & 0xFFFF;
|
||||
int sfHw = (instructionExpression >> 22 & 1);
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " MOV " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
(sfHw == 0) ? "w" : "x", (instructionExpression & 0b11111), imm16);
|
||||
}
|
||||
|
||||
private static String printNOPSimplified(int instructionExpression, int offset){
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " NOP " + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression);
|
||||
}
|
||||
|
||||
private static String printTBZSimplified(int instructionExpression, int offset){
|
||||
int xwSelector = (instructionExpression >> 31 & 1);
|
||||
int imm = instructionExpression >> 18 & 0b11111;
|
||||
int Rt = instructionExpression & 0b11111;
|
||||
int label = offset + (instructionExpression >> 5 & 0x3fff) * 4;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " TBZ " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ", " + ANSI_PURPLE + "%x" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
(xwSelector == 0) ? "w" : "x", Rt, imm, label);
|
||||
}
|
||||
|
||||
private static String printBConditionalSimplified(int instructionExpression, int offset){
|
||||
int conditionalJumpLocation = ((instructionExpression >> 4 & 0b1111111111111111111) * 4 + offset) & 0xfffff;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " B.%s " + ANSI_BLUE + "#0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ")\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
getBConditionalMarker(instructionExpression & 0xf),
|
||||
conditionalJumpLocation, (conditionalJumpLocation + 0x100));
|
||||
}
|
||||
private static String printImTooLazy(String name, int instructionExpression, int offset){
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " "+name+" . . . \n"+ ANSI_RESET,
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression);
|
||||
}
|
||||
|
||||
private static String printSUBSimplified(int instructionExpression, int offset){
|
||||
String wx = (instructionExpression >> 31 == 0) ? "W" : "X";
|
||||
int Rt = instructionExpression & 0x1f;
|
||||
int Rn = instructionExpression >> 5 & 0x1F;
|
||||
int imm12 = instructionExpression >> 10 & 0xFFF; // unsigned only
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " SUB (imm) " + ANSI_GREEN + "%s%d, " + ANSI_BLUE + "%s%d, #0x%x" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
wx, Rt, wx, Rn, imm12);
|
||||
}
|
||||
|
||||
private static String printMOVRegisterSimplified(int instructionExpression, int offset){ //ADD (immediate)
|
||||
String sfHw = (instructionExpression >> 31 & 1) == 0 ? "W" : "X";
|
||||
int Rm = instructionExpression >> 16 & 0x1F;
|
||||
int Rd = instructionExpression & 0x1F;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " MOV (reg) " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "%s%d" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
sfHw, Rm, sfHw, Rd);
|
||||
}
|
||||
|
||||
private static String printCMNSimplified(int instructionExpression, int offset){
|
||||
int Rn = instructionExpression >> 5 & 0x1F;
|
||||
int imm = instructionExpression >> 10 & 0xFFF;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " CMN " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "#0x%x" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
(instructionExpression >> 31 == 0) ? "w" : "x", Rn, imm);
|
||||
}
|
||||
|
||||
private static String printLRDImmUnsignSimplified(int instructionExpression, int offset){
|
||||
String wx = (instructionExpression >> 31 == 0) ? "W" : "X";
|
||||
int Rt = instructionExpression & 0x1f;
|
||||
int Rn = instructionExpression >> 5 & 0xF;
|
||||
int imm12 = (instructionExpression >> 10 & 0xFFF) * 8; // unsigned only
|
||||
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " LDR(imm) " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "[%s%d, #0x%x]" + ANSI_RESET + " (note: unsigned offset)\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
wx, Rt, wx, Rn, imm12);
|
||||
}
|
||||
private static String printLRDBImmUnsignSimplified(int instructionExpression, int offset){
|
||||
String wx = (instructionExpression >> 31 == 0) ? "W" : "X";
|
||||
int Rt = instructionExpression & 0x1f;
|
||||
int Rn = instructionExpression >> 5 & 0xF;
|
||||
int imm12 = (instructionExpression >> 10 & 0xFFF) * 8; // unsigned only
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " LDRB(imm) " + ANSI_GREEN + "%s%d " + ANSI_BLUE + "[%s%d, #0x%x]" + ANSI_RESET + " (note: unsigned offset)\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
wx, Rt, wx, Rn, imm12);
|
||||
}
|
||||
|
||||
private static String printCMPSimplified(int instructionExpression, int offset){
|
||||
String sf = (instructionExpression >> 31 == 0) ? "W" : "X";
|
||||
int Rn = instructionExpression >> 5 & 0x1F;
|
||||
int conditionalJumpLocation = (instructionExpression >> 10) & 0xfff;
|
||||
int LSL = (instructionExpression >> 22 & 0b1) == 1 ? 12 : 0;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " CMP " + ANSI_GREEN + sf + "%d," +
|
||||
ANSI_BLUE + "0x%x" + ANSI_RESET + " (Real: " + ANSI_BLUE + "#0x%x" + ANSI_RESET + ") " + ANSI_PURPLE + "LSL #%d" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
Rn,
|
||||
conditionalJumpLocation, (conditionalJumpLocation + 0x100),
|
||||
LSL);
|
||||
}
|
||||
|
||||
private static String printCMPShiftedRegisterSimplified(int instructionExpression, int offset){
|
||||
String sf = (instructionExpression >> 31 == 0) ? "W" : "X";
|
||||
int Rn = instructionExpression >> 5 & 0x1F;
|
||||
int Rm = instructionExpression >> 16 & 0x1F;
|
||||
int imm6 = instructionExpression >> 10 & 0x3f;
|
||||
int LSL = (instructionExpression >> 22 & 0b11);
|
||||
String LSLStr;
|
||||
switch (LSL){
|
||||
case 0b00:
|
||||
LSLStr = "LSL";
|
||||
break;
|
||||
case 0b01:
|
||||
LSLStr = "LSR";
|
||||
break;
|
||||
case 0b10:
|
||||
LSLStr = "ASR";
|
||||
break;
|
||||
case 0b11:
|
||||
LSLStr = "RESERVED";
|
||||
break;
|
||||
default:
|
||||
LSLStr = "?";
|
||||
}
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " CMP (sr) " + ANSI_GREEN + sf + "%d," +
|
||||
ANSI_BLUE + sf + "%d " + ANSI_BLUE + LSLStr + ANSI_PURPLE + " %d" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression,
|
||||
Rn, Rm, imm6);
|
||||
}
|
||||
|
||||
private static String printANDSimplified(int instructionExpression, int offset){
|
||||
String sf = (instructionExpression >> 31 == 0) ? "W" : "X";
|
||||
int Rn = instructionExpression & 0x1F;
|
||||
int Rd = instructionExpression >> 5 & 0x1F;
|
||||
int imm;
|
||||
if (sf.equals("W"))
|
||||
imm = instructionExpression >> 10 & 0xfff;
|
||||
else
|
||||
imm = instructionExpression >> 10 & 0x1fff;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " AND " + ANSI_GREEN + sf + "%d, " + ANSI_BLUE +
|
||||
sf + "%d" + ANSI_PURPLE + " # ??? 0b%s " + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression, Rn, Rd, Converter.intToBinaryString(imm));
|
||||
}
|
||||
|
||||
private static String printRetSimplified(int instructionExpression, int offset){
|
||||
int Xn = (instructionExpression >> 5) & 0x1F;
|
||||
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " RET " + ANSI_GREEN + " X%d" + ANSI_RESET + "\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression, Xn == 0 ? 30 : Xn);
|
||||
}
|
||||
|
||||
private static String printUnknownSimplified(int instructionExpression, int offset){
|
||||
return String.format(
|
||||
"%05x "+ANSI_CYAN+"%08x (%08x)"+ANSI_YELLOW + " ??? 0b"+ANSI_RESET+ Converter.intToBinaryString(instructionExpression) +"\n",
|
||||
offset, Integer.reverseBytes(instructionExpression), instructionExpression);
|
||||
}
|
||||
|
||||
private static String intAsBinString(int number) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for(int i = 31; i >= 0 ; i--) {
|
||||
int mask = 1 << i;
|
||||
result.append((number & mask) != 0 ? "1" : "0");
|
||||
result.append(" ");
|
||||
if (i % 4 == 0)
|
||||
result.append(" ");
|
||||
}
|
||||
result.replace(result.length() - 1, result.length(), "");
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
private static String intAsHexString(int number) {
|
||||
number = Integer.reverseBytes(number);
|
||||
StringBuilder result = new StringBuilder();
|
||||
for(int i = 0; i <= 3 ; i++) {
|
||||
int mask = 0xff << i*8;
|
||||
result.append(String.format("%02x", (byte)((number & mask) >> i*8)));
|
||||
result.append(" ");
|
||||
}
|
||||
result.replace(result.length() - 1, result.length(), "");
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches;
|
||||
|
||||
public class MalformedIniFileException extends Exception{
|
||||
public MalformedIniFileException(){}
|
||||
public MalformedIniFileException(String message){
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SimplyFind {
|
||||
private String what;
|
||||
private final byte[] where;
|
||||
|
||||
private Matcher matcherHex;
|
||||
private Matcher matcherDot;
|
||||
|
||||
private final List<Integer> findings = new ArrayList<>();
|
||||
private final int statementLength;
|
||||
private final List<SearchBlock> searchBlocks = new ArrayList<>();
|
||||
/**
|
||||
* Abstraction layer for searching patterns like "..CAFE..BE" in bytes array.
|
||||
* It's 'String' combination of hex values and '.' which stands for unknown value.
|
||||
* Returns offset of the first symbol.
|
||||
* */
|
||||
public SimplyFind(String what, byte[] where){
|
||||
this.where = where;
|
||||
if (! what.contains(".")){
|
||||
doKMPSearch(Converter.hexStringToByteArray(what), 0);
|
||||
this.statementLength = what.length()/2;
|
||||
return;
|
||||
}
|
||||
this.what = what.replaceAll("\\.", "\\.\\.");
|
||||
this.statementLength = this.what.length()/2;
|
||||
|
||||
buildSearchingSequence();
|
||||
complexSearch();
|
||||
}
|
||||
private void buildSearchingSequence(){
|
||||
Pattern patternHex = Pattern.compile("[0-9]|[A-F]|[a-f]");
|
||||
Pattern patternDot = Pattern.compile("\\.");
|
||||
this.matcherHex = patternHex.matcher(what);
|
||||
this.matcherDot = patternDot.matcher(what);
|
||||
|
||||
int nextDotPos = 0;
|
||||
int nextHexPos;
|
||||
|
||||
while(true){
|
||||
nextHexPos = getNextNumberPosition(nextDotPos);
|
||||
if (nextHexPos == -1)
|
||||
break;
|
||||
|
||||
nextDotPos = getNextDotPosition(nextHexPos);
|
||||
if (nextDotPos == -1) {
|
||||
searchBlocks.add(new SearchBlock(what.substring(nextHexPos), nextHexPos));
|
||||
break;
|
||||
}
|
||||
String searchStatement = what.substring(nextHexPos, nextDotPos);
|
||||
searchBlocks.add(new SearchBlock(searchStatement, nextHexPos));
|
||||
}
|
||||
}
|
||||
private int getNextNumberPosition(int since){
|
||||
if (matcherHex.find(since))
|
||||
return matcherHex.start();
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int getNextDotPosition(int since){
|
||||
if (matcherDot.find(since))
|
||||
return matcherDot.start();
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void complexSearch(){
|
||||
SearchBlock block = searchBlocks.get(0);
|
||||
doKMPSearch(block.statement, block.offsetInStatement);
|
||||
findings.removeIf(this::searchForward);
|
||||
}
|
||||
private boolean searchForward(int offset){
|
||||
for (int i = 1; i < searchBlocks.size(); i++) {
|
||||
SearchBlock block = searchBlocks.get(i);
|
||||
if (! doDumbSearch(block.statement, offset+block.offsetInStatement)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void doKMPSearch(byte[] subject, int skip){
|
||||
int whereSize = where.length;
|
||||
int subjectSize = subject.length;
|
||||
|
||||
int[] pf = new int[subjectSize];
|
||||
|
||||
int j = 0;
|
||||
for (int i = 1; i < subjectSize; i++ ) {
|
||||
while ((j > 0) && (subject[j] != subject[i]))
|
||||
j = pf[j-1];
|
||||
if (subject[j] == subject[i])
|
||||
j++;
|
||||
pf[i] = j;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (int i = 0; i < whereSize; i++){
|
||||
while ((j > 0) && (subject[j] != where[i]))
|
||||
j = pf[j - 1];
|
||||
if (subject[j] == where[i])
|
||||
j++;
|
||||
if (j == subjectSize) {
|
||||
findings.add(i-j+1-skip);
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doDumbSearch(byte[] subject, int since){
|
||||
for (int i = 0; i < subject.length; i++) {
|
||||
if (where[since + i] != subject[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getStatementLength() {
|
||||
return statementLength;
|
||||
}
|
||||
|
||||
public List<Integer> getResults(){
|
||||
return findings;
|
||||
}
|
||||
|
||||
private static class SearchBlock{
|
||||
byte[] statement;
|
||||
int offsetInStatement;
|
||||
|
||||
SearchBlock(String statement, int offset){
|
||||
if (statement != null) {
|
||||
this.statement = Converter.hexStringToByteArray(statement);
|
||||
}
|
||||
this.offsetInStatement = offset/2;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.es;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import libKonogonka.fs.NCA.NCAProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
class EsNcaSearchTask implements Callable<NCAProvider> {
|
||||
private final List<NCAProvider> ncaProviders;
|
||||
|
||||
EsNcaSearchTask(List<NCAProvider> ncaProviders){
|
||||
this.ncaProviders = ncaProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NCAProvider call() {
|
||||
try {
|
||||
for (NCAProvider ncaProvider : ncaProviders) {
|
||||
String titleId = Converter.byteArrToHexStringAsLE(ncaProvider.getTitleId());
|
||||
if (titleId.startsWith("0100000000000033") && ncaProvider.getContentType() == 0) {
|
||||
return ncaProvider;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
---
|
||||
Based on ES-AutoIPS.py patch script made by GBATemp member MrDude.
|
||||
Taken from: https://gbatemp.net/threads/info-on-sha-256-hashes-on-fs-patches.581550/
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.es;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import libKonogonka.fs.NCA.NCAProvider;
|
||||
import libKonogonka.fs.NSO.NSO0Header;
|
||||
import libKonogonka.fs.NSO.NSO0Provider;
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.es.finders.HeuristicEsWizard;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class EsPatch {
|
||||
private static final byte[] HEADER = "PATCH".getBytes(StandardCharsets.US_ASCII);
|
||||
private static final byte[] FOOTER = "EOF".getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
private final NCAProvider ncaProvider;
|
||||
private final String saveToLocation;
|
||||
private final ILogPrinter logPrinter;
|
||||
|
||||
private Long fwVersion;
|
||||
private String buildId;
|
||||
private byte[] _textSection;
|
||||
|
||||
private HeuristicEsWizard wizard;
|
||||
|
||||
EsPatch(NCAProvider ncaProvider, String saveToLocation, ILogPrinter logPrinter) throws Exception{
|
||||
this.ncaProvider = ncaProvider;
|
||||
this.saveToLocation = saveToLocation + File.separator +
|
||||
"atmosphere" + File.separator + "exefs_patches" + File.separator + "es_patches";
|
||||
this.logPrinter = logPrinter;
|
||||
|
||||
getPlainFirmwareVersion();
|
||||
NSO0Provider nso0Provider = new NSO0Provider(ncaProvider.getNCAContentProvider(0).getPfs0().getStreamProducer(0));
|
||||
getBuildId(nso0Provider);
|
||||
getTextSection(nso0Provider);
|
||||
findAllOffsets();
|
||||
mkDirs();
|
||||
writeFile();
|
||||
logPrinter.print(" == Debug information ==\n"+wizard.getDebug(), EMsgType.NULL);
|
||||
}
|
||||
private void getPlainFirmwareVersion() throws Exception{
|
||||
final byte[] byteSdkVersion = ncaProvider.getSdkVersion();
|
||||
fwVersion = Long.parseLong(""+byteSdkVersion[3]+byteSdkVersion[2]+byteSdkVersion[1]+byteSdkVersion[0]);
|
||||
logPrinter.print("Internal firmware version: "+byteSdkVersion[3] +"."+byteSdkVersion[2] +"."+byteSdkVersion[1] +"."+byteSdkVersion[0], EMsgType.INFO);
|
||||
if (byteSdkVersion[3] < 9 || fwVersion < 9300)
|
||||
logPrinter.print("WARNING! FIRMWARES VERSIONS BEFORE 9.0.0 ARE NOT SUPPORTED! USING PRODUCED ES PATCHES (IF ANY) COULD BREAK SOMETHING! IT'S NEVER BEEN TESTED!", EMsgType.WARNING);
|
||||
}
|
||||
private void getBuildId(NSO0Provider nso0Provider) throws Exception{
|
||||
NSO0Header nso0DecompressedHeader = nso0Provider.getAsDecompressedNSO0().getHeader();
|
||||
byte[] buildIdBytes = nso0DecompressedHeader.getModuleId();
|
||||
buildId = Converter.byteArrToHexStringAsLE(buildIdBytes).substring(0, 40).toUpperCase();
|
||||
logPrinter.print("Build ID: "+buildId, EMsgType.INFO);
|
||||
}
|
||||
private void getTextSection(NSO0Provider nso0Provider) throws Exception{
|
||||
_textSection = nso0Provider.getAsDecompressedNSO0().getTextRaw();
|
||||
}
|
||||
private void findAllOffsets() throws Exception{
|
||||
this.wizard = new HeuristicEsWizard(fwVersion, _textSection);
|
||||
String errorsAndNotes = wizard.getErrorsAndNotes();
|
||||
if (errorsAndNotes.length() > 0)
|
||||
logPrinter.print(errorsAndNotes, EMsgType.WARNING);
|
||||
}
|
||||
private void mkDirs(){
|
||||
File parentFolder = new File(saveToLocation);
|
||||
parentFolder.mkdirs();
|
||||
}
|
||||
|
||||
private void writeFile() throws Exception{
|
||||
String patchFileLocation = saveToLocation + File.separator + buildId + ".ips";
|
||||
int offset1 = wizard.getOffset1();
|
||||
int offset2 = wizard.getOffset2();
|
||||
int offset3 = wizard.getOffset3();
|
||||
|
||||
ByteBuffer handyEsPatch = ByteBuffer.allocate(0x23).order(ByteOrder.LITTLE_ENDIAN);
|
||||
handyEsPatch.put(HEADER);
|
||||
if (offset1 > 0) {
|
||||
logPrinter.print("Patch component 1 will be used", EMsgType.PASS);
|
||||
handyEsPatch.put(getPatch1(offset1));
|
||||
}
|
||||
if (offset2 > 0) {
|
||||
logPrinter.print("Patch component 2 will be used", EMsgType.PASS);
|
||||
handyEsPatch.put(getPatch2(offset2));
|
||||
}
|
||||
if (offset3 > 0) {
|
||||
logPrinter.print("Patch component 3 will be used", EMsgType.PASS);
|
||||
handyEsPatch.put(getPatch3(offset3));
|
||||
}
|
||||
handyEsPatch.put(FOOTER);
|
||||
|
||||
byte[] esPatch = new byte[handyEsPatch.position()];
|
||||
((Buffer) handyEsPatch).rewind();
|
||||
handyEsPatch.get(esPatch);
|
||||
|
||||
try (BufferedOutputStream stream = new BufferedOutputStream(
|
||||
Files.newOutputStream(Paths.get(patchFileLocation)))){
|
||||
stream.write(esPatch);
|
||||
}
|
||||
|
||||
logPrinter.print("Patch created at "+patchFileLocation, EMsgType.PASS);
|
||||
}
|
||||
|
||||
// WE EXPECT TO SEE CBZ (for patch 1) INSTRUCTION RIGHT BEFORE FOUND SEQUENCE (requiredInstructionOffsetInternal)
|
||||
// IN RESULTING FILE InstructionOffset SHOULD BE INCREMENTED by 0x100 to get real offset
|
||||
// (because header for decompressed NSO0 size = 0x100; it's fixed alignment produced by libKonogonka)
|
||||
private byte[] getPatch1(int offset) throws Exception{
|
||||
int requiredInstructionOffsetInternal = offset - 4;
|
||||
int requiredInstructionOffsetReal = requiredInstructionOffsetInternal + 0x100;
|
||||
int instructionExpression = Converter.getLEint(_textSection, requiredInstructionOffsetInternal);
|
||||
int patch = ((0x14 << 24) | (instructionExpression >> 5) & 0x7FFFF);
|
||||
|
||||
logPrinter.print(BinToAsmPrinter.printSimplified(patch, requiredInstructionOffsetInternal), EMsgType.NULL);
|
||||
|
||||
// Somehow IPS patches uses offsets written as big_endian (0.o) and bytes dat should be patched as LE.
|
||||
ByteBuffer prePatch = ByteBuffer.allocate(10).order(ByteOrder.BIG_ENDIAN)
|
||||
.putInt(requiredInstructionOffsetReal)
|
||||
.putShort((short) 4)
|
||||
.putInt(Integer.reverseBytes(patch));
|
||||
|
||||
return Arrays.copyOfRange(prePatch.array(), 1, 10);
|
||||
}
|
||||
private byte[] getPatch2(int offset) throws Exception{
|
||||
final int NopInstruction = 0x1F2003D5; // reversed
|
||||
int offsetReal = offset - 4 + 0x100;
|
||||
|
||||
logPrinter.print(BinToAsmPrinter.printSimplified(Integer.reverseBytes(NopInstruction), offset - 4), EMsgType.NULL);
|
||||
|
||||
ByteBuffer prePatch = ByteBuffer.allocate(10).order(ByteOrder.BIG_ENDIAN)
|
||||
.putInt(offsetReal)
|
||||
.putShort((short) 4)
|
||||
.putInt(NopInstruction);
|
||||
|
||||
return Arrays.copyOfRange(prePatch.array(), 1, 10);
|
||||
}
|
||||
private byte[] getPatch3(int offset) throws Exception{
|
||||
int requiredInstructionOffsetInternal = offset - 4;
|
||||
int requiredInstructionOffsetReal = requiredInstructionOffsetInternal + 0x100;
|
||||
|
||||
int instructionExpression = Converter.getLEint(_textSection, requiredInstructionOffsetInternal);
|
||||
int patch = ((0x14 << 24) | (instructionExpression >> 5) & 0x7FFFF);
|
||||
|
||||
logPrinter.print(BinToAsmPrinter.printSimplified(patch, requiredInstructionOffsetInternal), EMsgType.NULL);
|
||||
|
||||
ByteBuffer prePatch = ByteBuffer.allocate(10).order(ByteOrder.BIG_ENDIAN)
|
||||
.putInt(requiredInstructionOffsetReal)
|
||||
.putShort((short) 4)
|
||||
.putInt(Integer.reverseBytes(patch));
|
||||
|
||||
return Arrays.copyOfRange(prePatch.array(), 1, 10);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.es;
|
||||
|
||||
import libKonogonka.KeyChainHolder;
|
||||
import libKonogonka.fs.NCA.NCAProvider;
|
||||
import nsusbloader.ModelControllers.CancellableRunnable;
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.ModelControllers.Log;
|
||||
import nsusbloader.NSLDataTypes.EModule;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class EsPatchMaker extends CancellableRunnable {
|
||||
private int THREADS_POOL_SIZE;
|
||||
private final ILogPrinter logPrinter;
|
||||
private final String pathToFirmware;
|
||||
private final String pathToKeysFile;
|
||||
private final String saveTo;
|
||||
|
||||
private File firmware;
|
||||
private KeyChainHolder keyChainHolder;
|
||||
private ExecutorService executorService;
|
||||
private List<String> ncaFilesList; // inside the folder
|
||||
|
||||
private boolean oneLinerStatus = false;
|
||||
|
||||
public EsPatchMaker(String pathToFirmware, String pathToKeysFile, String saveTo){
|
||||
this.logPrinter = Log.getPrinter(EModule.PATCHES);
|
||||
/*
|
||||
this.logPrinter = new ILogPrinter() {
|
||||
public void print(String message, EMsgType type) throws InterruptedException {}
|
||||
public void updateProgress(Double value) throws InterruptedException {}
|
||||
public void update(HashMap<String, File> nspMap, EFileStatus status) {}
|
||||
public void update(File file, EFileStatus status) {}
|
||||
public void updateOneLinerStatus(boolean status) {}
|
||||
public void close() {}
|
||||
};
|
||||
*/
|
||||
this.pathToFirmware = pathToFirmware;
|
||||
this.pathToKeysFile = pathToKeysFile;
|
||||
this.saveTo = saveTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logPrinter.print("..:: Make ES Patches ::..", EMsgType.INFO);
|
||||
receiveFirmware();
|
||||
buildKeyChainHolder();
|
||||
receiveNcaFileNamesList();
|
||||
specifyThreadsPoolSize();
|
||||
createPool();
|
||||
executePool();
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
try{
|
||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||
} catch (Exception ignore){}
|
||||
}
|
||||
finally {
|
||||
logPrinter.updateOneLinerStatus(oneLinerStatus);
|
||||
logPrinter.close();
|
||||
}
|
||||
}
|
||||
private void receiveFirmware() throws Exception{
|
||||
logPrinter.print("Looking at firmware", EMsgType.INFO);
|
||||
this.firmware = new File(pathToFirmware);
|
||||
if (! firmware.exists())
|
||||
throw new Exception("Firmware directory does not exist " + pathToFirmware);
|
||||
}
|
||||
private void buildKeyChainHolder() throws Exception{
|
||||
logPrinter.print("Reading keys", EMsgType.INFO);
|
||||
this.keyChainHolder = new KeyChainHolder(pathToKeysFile, null);
|
||||
}
|
||||
private void receiveNcaFileNamesList() throws Exception{
|
||||
logPrinter.print("Collecting NCA files", EMsgType.INFO);
|
||||
String[] fileNamesArray = firmware.list((File directory, String file) -> ( ! file.endsWith(".cnmt.nca") && file.endsWith(".nca")));
|
||||
ncaFilesList = Arrays.asList(Objects.requireNonNull(fileNamesArray));
|
||||
if (ncaFilesList.size() == 0)
|
||||
throw new Exception("No NCA files found in firmware folder");
|
||||
}
|
||||
private void specifyThreadsPoolSize(){
|
||||
THREADS_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors()+1, 4);
|
||||
THREADS_POOL_SIZE = Math.min(THREADS_POOL_SIZE, ncaFilesList.size());
|
||||
}
|
||||
|
||||
private void createPool() throws Exception{
|
||||
logPrinter.print("Creating sub-tasks pool", EMsgType.INFO);
|
||||
this.executorService = Executors.newFixedThreadPool(
|
||||
THREADS_POOL_SIZE,
|
||||
runnable -> {
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
}
|
||||
|
||||
private void executePool() throws Exception{ //TODO: FIX. Exceptions thrown only by logPrinter
|
||||
try {
|
||||
logPrinter.print("Executing sub-tasks pool", EMsgType.INFO);
|
||||
List<Future<NCAProvider>> futuresResults = executorService.invokeAll(getSubTasksCollection());
|
||||
for (Future<NCAProvider> future : futuresResults){
|
||||
NCAProvider ncaProvider = future.get();
|
||||
if (ncaProvider != null) {
|
||||
makePatches(ncaProvider);
|
||||
break;
|
||||
}
|
||||
}
|
||||
executorService.shutdown();
|
||||
}
|
||||
catch (InterruptedException ie){
|
||||
executorService.shutdownNow();
|
||||
boolean interruptedSuccessfully = false;
|
||||
try {
|
||||
interruptedSuccessfully = executorService.awaitTermination(20, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (InterruptedException awaitInterrupt){
|
||||
logPrinter.print("Force interrupting task...", EMsgType.WARNING);
|
||||
}
|
||||
logPrinter.print("Task interrupted "+(interruptedSuccessfully?"successfully":"with some issues"), EMsgType.WARNING);
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
logPrinter.print("Task failed: "+e.getMessage(), EMsgType.FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
private void makePatches(NCAProvider ncaProvider) throws Exception{
|
||||
logPrinter.print(String.format("File found: .."+File.separator+"%s"+File.separator+"%s",
|
||||
ncaProvider.getFile().getParentFile().getName(), ncaProvider.getFile().getName())
|
||||
, EMsgType.INFO);
|
||||
new EsPatch(ncaProvider, saveTo, logPrinter);
|
||||
oneLinerStatus = true;
|
||||
}
|
||||
private List<Callable<NCAProvider>> getSubTasksCollection() throws Exception{
|
||||
logPrinter.print("Forming sub-tasks collection", EMsgType.INFO);
|
||||
List<Callable<NCAProvider>> subTasks = new ArrayList<>();
|
||||
|
||||
int ncaPerThreadAmount = ncaFilesList.size() / THREADS_POOL_SIZE;
|
||||
Iterator<String> iterator = ncaFilesList.listIterator();
|
||||
|
||||
for (int i = 1; i < THREADS_POOL_SIZE; i++){
|
||||
Callable<NCAProvider> task = new EsNcaSearchTask(getNextSet(iterator, ncaPerThreadAmount));
|
||||
subTasks.add(task);
|
||||
}
|
||||
int leftovers = ncaFilesList.size() % THREADS_POOL_SIZE;
|
||||
Callable<NCAProvider> task = new EsNcaSearchTask(getNextSet(iterator, ncaPerThreadAmount+leftovers));
|
||||
subTasks.add(task);
|
||||
return subTasks;
|
||||
}
|
||||
private List<NCAProvider> getNextSet(Iterator<String> iterator, int amount) throws Exception{
|
||||
List<NCAProvider> ncas = new ArrayList<>();
|
||||
for (int j = 0; j < amount; j++){
|
||||
String ncaFileName = iterator.next();
|
||||
File nca = new File(firmware.getAbsolutePath()+File.separator+ncaFileName);
|
||||
NCAProvider provider = new NCAProvider(nca, keyChainHolder.getRawKeySet());
|
||||
ncas.add(provider);
|
||||
}
|
||||
return ncas;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.es.finders;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.Utilities.patches.AHeuristic;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.SimplyFind;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class HeuristicEs1 extends AHeuristic {
|
||||
private static final String PATTERN = AppPreferences.getInstance().getPatchPattern("ES", 1, 0);
|
||||
|
||||
private final List<Integer> findings;
|
||||
private final byte[] where;
|
||||
|
||||
HeuristicEs1(byte[] where){
|
||||
this.where = where;
|
||||
SimplyFind simplyfind = new SimplyFind(PATTERN, where);
|
||||
this.findings = simplyfind.getResults();
|
||||
|
||||
this.findings.removeIf(this::dropStep1);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep2);
|
||||
}
|
||||
|
||||
// Check ranges
|
||||
private boolean dropStep1(int offsetOfPatternFound){
|
||||
return ((offsetOfPatternFound < 0x10000 || offsetOfPatternFound > 0xffffc));
|
||||
}
|
||||
// Remove non-CBZ
|
||||
private boolean dropStep2(int offsetOfPatternFound){
|
||||
return ((where[offsetOfPatternFound - 1] & (byte) 0b01111111) != 0x34);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(){
|
||||
return findings.size() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wantLessEntropy(){
|
||||
return findings.size() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() throws Exception{
|
||||
if(findings.isEmpty())
|
||||
throw new Exception("Nothing found");
|
||||
if (findings.size() > 1)
|
||||
throw new Exception("Too many offsets");
|
||||
return findings.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOffsetsNearby(int offsetNearby) {
|
||||
findings.removeIf(offset -> {
|
||||
if (offset > offsetNearby)
|
||||
return ! (offset < offsetNearby - 0xffff);
|
||||
return ! (offset > offsetNearby - 0xffff);
|
||||
});
|
||||
return isFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetails(){
|
||||
int cbzOffsetInternal = findings.get(0) - 4;
|
||||
int instructionExpression = Converter.getLEint(where, cbzOffsetInternal);
|
||||
int conditionalJumpLocation = ((instructionExpression >> 5 & 0x7FFFF) * 4 + cbzOffsetInternal) & 0xfffff;
|
||||
|
||||
int secondExpressionsPairElement1 = Converter.getLEint(where, conditionalJumpLocation);
|
||||
int secondExpressionsPairElement2 = Converter.getLEint(where, conditionalJumpLocation+4);
|
||||
|
||||
return BinToAsmPrinter.printSimplified(instructionExpression, cbzOffsetInternal) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, cbzOffsetInternal + 4),
|
||||
cbzOffsetInternal + 4) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, cbzOffsetInternal + 8),
|
||||
cbzOffsetInternal + 8) +
|
||||
"...\n" +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement1, conditionalJumpLocation) +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement2, conditionalJumpLocation + 4);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.es.finders;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.Utilities.patches.AHeuristic;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.SimplyFind;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class HeuristicEs2 extends AHeuristic {
|
||||
private static final String PATTERN = AppPreferences.getInstance().getPatchPattern("ES", 2, 0);
|
||||
|
||||
private List<Integer> findings;
|
||||
private final byte[] where;
|
||||
|
||||
HeuristicEs2(byte[] where){
|
||||
this.where = where;
|
||||
find();
|
||||
|
||||
this.findings.removeIf(this::dropStep1);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep2);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep3);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep4);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep5);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep6);
|
||||
}
|
||||
private void find(){
|
||||
SimplyFind simplyfind = new SimplyFind(PATTERN, where);
|
||||
findings = new ArrayList<>();
|
||||
// This approach a bit different. We're looking for pattern we want to patch, not the next one.
|
||||
// So easier way is just to shift every value and pretend that nothing happened.
|
||||
for (int offset : simplyfind.getResults())
|
||||
findings.add(offset+4);
|
||||
}
|
||||
|
||||
// Limit range
|
||||
private boolean dropStep1(int offsetOfPatternFound){
|
||||
return ((offsetOfPatternFound < 0x10000 || offsetOfPatternFound > 0xffffc));
|
||||
}
|
||||
// Is CBNZ next?
|
||||
private boolean dropStep2(int offsetOfPatternFound){
|
||||
return ! isCBNZ(Converter.getLEint(where, offsetOfPatternFound));
|
||||
}
|
||||
// Check what's above
|
||||
private boolean dropStep3(int offsetOfPatternFound){
|
||||
return ! isMOV(Converter.getLEint(where, offsetOfPatternFound-4));
|
||||
}
|
||||
// Check what's beyond or after jump
|
||||
private boolean dropStep4(int offsetOfPatternFound) {
|
||||
int nextExpression = Converter.getLEint(where, offsetOfPatternFound + 4);
|
||||
return ! isLDRB_LDURB(nextExpression); // Drop if not LDRB OR LDURB
|
||||
}
|
||||
|
||||
// Check second after jump if LDR-TBZ
|
||||
private boolean dropStep5(int offsetOfPatternFound) {
|
||||
int expression = Converter.getLEint(where, offsetOfPatternFound);
|
||||
int afterJumpPosition = ((expression >> 5 & 0x7FFFF) * 4 + offsetOfPatternFound) & 0xfffff;
|
||||
int secondAfterJumpExpression = Converter.getLEint(where, afterJumpPosition+4);
|
||||
return ! isBL(secondAfterJumpExpression); //Second after jump = BL? No -> Drop
|
||||
}
|
||||
|
||||
// Check second after jump if LDR-TBZ
|
||||
private boolean dropStep6(int offsetOfPatternFound) {
|
||||
int expression = Converter.getLEint(where, offsetOfPatternFound);
|
||||
int afterJumpPosition = ((expression >> 5 & 0x7FFFF) * 4 + offsetOfPatternFound) & 0xfffff;
|
||||
int forthAfterJumpExpression = Converter.getLEint(where, afterJumpPosition+12);
|
||||
return ! isBL(forthAfterJumpExpression); //Forth after jump = BL? No -> Drop
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(){
|
||||
return findings.size() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wantLessEntropy(){
|
||||
return findings.size() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() throws Exception{
|
||||
if(findings.isEmpty())
|
||||
throw new Exception("Nothing found");
|
||||
if (findings.size() > 1)
|
||||
throw new Exception("Too many offsets");
|
||||
return findings.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOffsetsNearby(int offsetNearby) {
|
||||
findings.removeIf(offset -> {
|
||||
if (offset > offsetNearby)
|
||||
return ! (offset < offsetNearby - 0xffff);
|
||||
return ! (offset > offsetNearby - 0xffff);
|
||||
});
|
||||
return isFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetails(){
|
||||
int secondExpressionOffset = findings.get(0);
|
||||
|
||||
int firstExpression = Converter.getLEint(where, secondExpressionOffset-4);
|
||||
int secondExpression = Converter.getLEint(where, secondExpressionOffset);
|
||||
int conditionalJumpLocation = 0;
|
||||
if ((secondExpression >> 24 & 0x7f) == 0x35) {
|
||||
conditionalJumpLocation = ((secondExpression >> 5 & 0x7FFFF) * 4 + secondExpressionOffset) & 0xfffff;
|
||||
}
|
||||
else if ((firstExpression >> 24 & 0x7f) == 0x36) {
|
||||
conditionalJumpLocation = (secondExpressionOffset-4 + (firstExpression >> 5 & 0x3fff) * 4) & 0xfffff;
|
||||
}
|
||||
int secondExpressionsPairElement1 = Converter.getLEint(where, conditionalJumpLocation);
|
||||
int secondExpressionsPairElement2 = Converter.getLEint(where, conditionalJumpLocation + 4);
|
||||
int secondExpressionsPairElement3 = Converter.getLEint(where, conditionalJumpLocation + 8);
|
||||
int secondExpressionsPairElement4 = Converter.getLEint(where, conditionalJumpLocation + 12);
|
||||
|
||||
return BinToAsmPrinter.printSimplified(Converter.getLEint(where, secondExpressionOffset - 4), secondExpressionOffset - 4) +
|
||||
BinToAsmPrinter.printSimplified(secondExpression, secondExpressionOffset) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, secondExpressionOffset + 4), secondExpressionOffset + 4) +
|
||||
"...\n" +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement1, conditionalJumpLocation) +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement2, conditionalJumpLocation + 4) +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement3, conditionalJumpLocation + 8) +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement4, conditionalJumpLocation + 12);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.es.finders;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.Utilities.patches.AHeuristic;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.SimplyFind;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class HeuristicEs3 extends AHeuristic {
|
||||
private static final String PATTERN0 = AppPreferences.getInstance().getPatchPattern("ES", 3, 0);
|
||||
private static final String PATTERN1 = AppPreferences.getInstance().getPatchPattern("ES", 3, 1);
|
||||
|
||||
private final List<Integer> findings;
|
||||
private final byte[] where;
|
||||
|
||||
HeuristicEs3(long fwVersion, byte[] where){
|
||||
this.where = where;
|
||||
String pattern = getPattern(fwVersion);
|
||||
SimplyFind simplyfind = new SimplyFind(pattern, where);
|
||||
this.findings = simplyfind.getResults();
|
||||
|
||||
this.findings.removeIf(this::dropStep1);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep2);
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep3);
|
||||
}
|
||||
private String getPattern(long fwVersion){
|
||||
if (fwVersion < 10400)
|
||||
return PATTERN0;
|
||||
return PATTERN1;
|
||||
}
|
||||
// Let's focus on CBZ-ONLY statements
|
||||
private boolean dropStep1(int offsetOfPatternFound){
|
||||
return ((where[offsetOfPatternFound - 1] & (byte) 0b01111111) != 0x34);
|
||||
}
|
||||
|
||||
private boolean dropStep2(int offsetOfPatternFound){
|
||||
int conditionalJumpLocation = getCBZConditionalJumpLocation(offsetOfPatternFound - 4);
|
||||
|
||||
int afterJumpSecondExpressions = Converter.getLEint(where, conditionalJumpLocation);
|
||||
int afterJumpThirdExpressions = Converter.getLEint(where, conditionalJumpLocation+4);
|
||||
// Check first is 'MOV'; second is 'B'
|
||||
return (! isMOV_REG(afterJumpSecondExpressions)) || ! isB(afterJumpThirdExpressions);
|
||||
}
|
||||
|
||||
private boolean dropStep3(int offsetOfPatternFound){
|
||||
int conditionalJumpLocation = getCBZConditionalJumpLocation(offsetOfPatternFound-4);
|
||||
int afterJumpSecondExpressions = Converter.getLEint(where, conditionalJumpLocation+4);
|
||||
int secondPairConditionalJumpLocation = ((afterJumpSecondExpressions & 0x3ffffff) * 4 + (conditionalJumpLocation+4)) & 0xfffff;
|
||||
|
||||
int thirdExpressionsPairElement1 = Converter.getLEint(where, secondPairConditionalJumpLocation);
|
||||
int thirdExpressionsPairElement2 = Converter.getLEint(where, secondPairConditionalJumpLocation+4);
|
||||
// Check first is 'ADD'; second is 'BL'
|
||||
return (! isADD(thirdExpressionsPairElement1)) || (! isBL(thirdExpressionsPairElement2));
|
||||
}
|
||||
|
||||
private int getCBZConditionalJumpLocation(int cbzOffsetInternal){
|
||||
int cbzExpression = Converter.getLEint(where, cbzOffsetInternal);
|
||||
return ((cbzExpression >> 5 & 0x7FFFF) * 4 + cbzOffsetInternal) & 0xfffff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(){
|
||||
return findings.size() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wantLessEntropy(){
|
||||
return findings.size() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() throws Exception{
|
||||
if(findings.isEmpty())
|
||||
throw new Exception("Nothing found");
|
||||
if (findings.size() > 1)
|
||||
throw new Exception("Too many offsets");
|
||||
return findings.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOffsetsNearby(int offsetNearby) {
|
||||
findings.removeIf(offset -> {
|
||||
if (offset > offsetNearby)
|
||||
return ! (offset < offsetNearby - 0xffff);
|
||||
return ! (offset > offsetNearby - 0xffff);
|
||||
});
|
||||
return isFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetails(){
|
||||
int cbzOffsetInternal = findings.get(0) - 4;
|
||||
int cbzExpression = Converter.getLEint(where, cbzOffsetInternal);
|
||||
int conditionalJumpLocation = ((cbzExpression >> 5 & 0x7FFFF) * 4 + cbzOffsetInternal) & 0xfffff;
|
||||
|
||||
int secondExpressionsPairElement1 = Converter.getLEint(where, conditionalJumpLocation);
|
||||
int secondExpressionsPairElement2 = Converter.getLEint(where, conditionalJumpLocation+4);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(BinToAsmPrinter.printSimplified(cbzExpression, cbzOffsetInternal));
|
||||
builder.append(BinToAsmPrinter.printSimplified(Converter.getLEint(where, cbzOffsetInternal+4), cbzOffsetInternal+4));
|
||||
builder.append(BinToAsmPrinter.printSimplified(Converter.getLEint(where, cbzOffsetInternal+8), cbzOffsetInternal+8));
|
||||
builder.append("...\n");
|
||||
|
||||
builder.append(BinToAsmPrinter.printSimplified(secondExpressionsPairElement1, conditionalJumpLocation));
|
||||
builder.append(BinToAsmPrinter.printSimplified(secondExpressionsPairElement2, conditionalJumpLocation+4));
|
||||
|
||||
if (((secondExpressionsPairElement2 >> 26 & 0b111111) == 0x5)){
|
||||
builder.append("...\n");
|
||||
int conditionalJumpLocation2 = ((secondExpressionsPairElement2 & 0x3ffffff) * 4 + (conditionalJumpLocation+4)) & 0xfffff;
|
||||
|
||||
builder.append(BinToAsmPrinter.printSimplified(Converter.getLEint(where, conditionalJumpLocation2), conditionalJumpLocation2));
|
||||
builder.append(BinToAsmPrinter.printSimplified(Converter.getLEint(where, conditionalJumpLocation2+4), conditionalJumpLocation2+4));
|
||||
}
|
||||
else {
|
||||
builder.append("NO CONDITIONAL JUMP ON 2nd iteration (HeuristicEs3)");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.es.finders;
|
||||
|
||||
import nsusbloader.Utilities.patches.AHeuristic;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HeuristicEsWizard {
|
||||
private final List<AHeuristic> all;
|
||||
private final List<AHeuristic> found;
|
||||
private final List<AHeuristic> wantLessEntropy;
|
||||
|
||||
private final StringBuilder errorsAndNotes;
|
||||
|
||||
private int offset1 = -1;
|
||||
private int offset2 = -1;
|
||||
private int offset3 = -1;
|
||||
|
||||
public HeuristicEsWizard(long fwVersion, byte[] where) throws Exception{
|
||||
this.errorsAndNotes = new StringBuilder();
|
||||
|
||||
this.all = Arrays.asList(
|
||||
new HeuristicEs1(where),
|
||||
new HeuristicEs2(where),
|
||||
new HeuristicEs3(fwVersion, where)
|
||||
);
|
||||
|
||||
this.found = all.stream()
|
||||
.filter(AHeuristic::isFound)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (found.isEmpty())
|
||||
throw new Exception("Nothing found!");
|
||||
|
||||
this.wantLessEntropy = all.stream()
|
||||
.filter(AHeuristic::wantLessEntropy)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
shareOffsetsWithEachOther();
|
||||
|
||||
assignOffset1();
|
||||
assignOffset2();
|
||||
assignOffset3();
|
||||
}
|
||||
|
||||
private void shareOffsetsWithEachOther(){
|
||||
for (AHeuristic es : wantLessEntropy) {
|
||||
if (shareWithNext(es))
|
||||
return;
|
||||
}
|
||||
}
|
||||
private boolean shareWithNext(AHeuristic es){
|
||||
try {
|
||||
for (AHeuristic foundEs : found) {
|
||||
if (es.setOffsetsNearby(foundEs.getOffset())) {
|
||||
found.add(es);
|
||||
wantLessEntropy.remove(es);
|
||||
shareOffsetsWithEachOther();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e){ e.printStackTrace(); }
|
||||
return false;
|
||||
}
|
||||
|
||||
private void assignOffset1(){
|
||||
try {
|
||||
offset1 = all.get(0).getOffset();
|
||||
}
|
||||
catch (Exception e){ errorsAndNotes.append(e.getLocalizedMessage()).append("\n"); }
|
||||
}
|
||||
private void assignOffset2(){
|
||||
try {
|
||||
offset2 = all.get(1).getOffset();
|
||||
}
|
||||
catch (Exception e){ errorsAndNotes.append(e.getLocalizedMessage()).append("\n"); }
|
||||
}
|
||||
private void assignOffset3(){
|
||||
try {
|
||||
offset3 = all.get(2).getOffset();
|
||||
}
|
||||
catch (Exception e){ errorsAndNotes.append(e.getLocalizedMessage()).append("\n"); }
|
||||
}
|
||||
|
||||
public String getErrorsAndNotes(){
|
||||
return errorsAndNotes.toString();
|
||||
}
|
||||
|
||||
public String getDebug(){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (all.get(0).isFound()){
|
||||
builder.append("\t\t-=== 1 ===-\n");
|
||||
builder.append(all.get(0).getDetails());
|
||||
}
|
||||
if (all.get(1).isFound()){
|
||||
builder.append("\t\t-=== 2 ===-\n");
|
||||
builder.append(all.get(1).getDetails());
|
||||
}
|
||||
if (all.get(2).isFound()){
|
||||
builder.append("\t\t-=== 3 ===-\n");
|
||||
builder.append(all.get(2).getDetails());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public int getOffset1() { return offset1; }
|
||||
public int getOffset2() { return offset2; }
|
||||
public int getOffset3() { return offset3; }
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.fs;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
import nsusbloader.Utilities.patches.MalformedIniFileException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class FsIniMaker {
|
||||
private static final String FILE_HEADER_TEXT = "# UTF-8\n" +
|
||||
"# A KIP section is [kip1_name:sha256_hex_8bytes]\n" +
|
||||
"# A patchset is .patch_name=kip_section_dec:offset_hex_0x:length_hex_0x:src_data_hex,dst_data_hex\n" +
|
||||
"# _dec: 1 char decimal | _hex_0x: max u32 prefixed with 0x | _hex: hex array.\n" +
|
||||
"# Kip1 section decimals: TEXT: 0, RODATA: 1, DATA: 2.\n"; // Sending good vibes to Mr. ITotalJustice
|
||||
|
||||
private final ILogPrinter logPrinter;
|
||||
private final String saveToLocation;
|
||||
private final int offset1;
|
||||
private final int offset2;
|
||||
|
||||
private String firmwareVersionInformationNotice;
|
||||
private String sectionDeclaration;
|
||||
private String patchSet1;
|
||||
private String patchSet2;
|
||||
|
||||
public FsIniMaker(ILogPrinter logPrinter,
|
||||
String saveToLocation,
|
||||
byte[] _textSection,
|
||||
int wizardOffset1,
|
||||
int wizardOffset2,
|
||||
byte[] sdkVersion,
|
||||
String patchName,
|
||||
boolean filesystemTypeFat32) throws Exception{
|
||||
this.logPrinter = logPrinter;
|
||||
this.saveToLocation = saveToLocation;
|
||||
this.offset1 = wizardOffset1 - 4;
|
||||
this.offset2 = wizardOffset2 - 4;
|
||||
|
||||
mkDirs();
|
||||
makeFwVersionInformationNotice(filesystemTypeFat32, sdkVersion);
|
||||
makeSectionDeclaration(patchName);
|
||||
makePatchSet1(_textSection);
|
||||
makePatchSet2(_textSection);
|
||||
writeFile();
|
||||
}
|
||||
|
||||
private void mkDirs(){
|
||||
File parentFolder = new File(saveToLocation + File.separator + "bootloader");
|
||||
parentFolder.mkdirs();
|
||||
}
|
||||
|
||||
private void makeFwVersionInformationNotice(boolean isFat32, byte[] fwVersion){
|
||||
String fwVersionFormatted = fwVersion[3]+"."+fwVersion[2]+"."+fwVersion[1]+"."+fwVersion[0];
|
||||
if (isFat32)
|
||||
firmwareVersionInformationNotice = "\n#FS (FAT)"+fwVersionFormatted+"\n";
|
||||
else
|
||||
firmwareVersionInformationNotice = "\n#FS (ExFAT) "+fwVersionFormatted+"\n";
|
||||
}
|
||||
|
||||
private void makeSectionDeclaration(String patchName){
|
||||
sectionDeclaration = "[FS:"+patchName.substring(0, 16)+"]";
|
||||
}
|
||||
|
||||
private void makePatchSet1(byte[] _textSection){
|
||||
if (offset1 > 0) {
|
||||
byte[] originalInstruction = Arrays.copyOfRange(_textSection, offset1, offset1 + 4);
|
||||
patchSet1 = String.format(".nosigchk=0:0x%02X:0x4:%s,1F2003D5",
|
||||
offset1, Converter.byteArrToHexStringAsLE(originalInstruction, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void makePatchSet2(byte[] _textSection){
|
||||
if (offset2 > 0) {
|
||||
byte[] originalInstruction = Arrays.copyOfRange(_textSection, offset2, offset2 + 4);
|
||||
patchSet2 = String.format(".nosigchk=0:0x%02X:0x4:%s,E0031F2A",
|
||||
offset2, Converter.byteArrToHexStringAsLE(originalInstruction, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeFile() throws Exception{
|
||||
final String iniLocation = saveToLocation + File.separator + "bootloader" + File.separator + "patches.ini";
|
||||
final Path iniLocationPath = Paths.get(iniLocation);
|
||||
|
||||
boolean iniNotExists = Files.notExists(iniLocationPath);
|
||||
|
||||
try (RandomAccessFile ini = new RandomAccessFile(iniLocation, "rw")){
|
||||
if (iniNotExists)
|
||||
ini.writeBytes(FILE_HEADER_TEXT);
|
||||
else {
|
||||
String line;
|
||||
while ((line = ini.readLine()) != null){
|
||||
if (! line.startsWith(sectionDeclaration))
|
||||
continue;
|
||||
|
||||
if (offset1 > 0) {
|
||||
String expression1 = ini.readLine();
|
||||
if (expression1 == null || ! expression1.startsWith(patchSet1))
|
||||
throw new MalformedIniFileException("Somewhere near "+ini.getFilePointer());
|
||||
}
|
||||
String expression2 = ini.readLine();
|
||||
if (offset2 > 0) {
|
||||
if (expression2 == null || ! expression2.startsWith(patchSet2))
|
||||
throw new MalformedIniFileException("Somewhere near "+ini.getFilePointer());
|
||||
}
|
||||
else {
|
||||
if (expression2 == null || ! expression2.startsWith(".nosigchk"))
|
||||
return;
|
||||
throw new MalformedIniFileException("Somewhere near "+ini.getFilePointer());
|
||||
}
|
||||
return; // Ini file already contains correct information regarding patch file we made.
|
||||
}
|
||||
}
|
||||
|
||||
ini.writeBytes(firmwareVersionInformationNotice);
|
||||
ini.writeBytes(sectionDeclaration);
|
||||
ini.writeBytes("\n");
|
||||
|
||||
if (offset1 > 0) {
|
||||
ini.writeBytes(patchSet1);
|
||||
ini.writeBytes("\n");
|
||||
}
|
||||
if (offset2 > 0) {
|
||||
ini.writeBytes(patchSet2);
|
||||
ini.writeBytes("\n");
|
||||
}
|
||||
}
|
||||
catch (MalformedIniFileException e){
|
||||
e.printStackTrace();
|
||||
logPrinter.print(
|
||||
"Existing patches.ini file is malformed or contains incorrect (outdated) information regarding current patch.\n" +
|
||||
"It's now saved at "+iniLocation+".OLD\n" +
|
||||
"New patches.ini file created instead.", EMsgType.WARNING);
|
||||
Files.move(iniLocationPath, Paths.get(iniLocation+".OLD"),
|
||||
StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||
writeFile();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright 2018-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.fs;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import libKonogonka.fs.NCA.NCAProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
class FsNcaSearchTask implements Callable<List<NCAProvider>> {
|
||||
private final List<NCAProvider> ncaProviders;
|
||||
|
||||
FsNcaSearchTask(List<NCAProvider> ncaProviders){
|
||||
this.ncaProviders = ncaProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NCAProvider> call() {
|
||||
List<NCAProvider> result = new ArrayList<>();
|
||||
try {
|
||||
for (NCAProvider ncaProvider : ncaProviders) {
|
||||
String titleId = Converter.byteArrToHexStringAsLE(ncaProvider.getTitleId());
|
||||
if (titleId.equals("0100000000000819") || titleId.equals("010000000000081b")) // eq. FAT32 || exFAT
|
||||
result.add(ncaProvider);
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
Copyright 2018-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
---
|
||||
Based on https://github.com/mrdude2478/IPS_Patch_Creator patch script made by GBATemp member MrDude.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.fs;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import libKonogonka.KeyChainHolder;
|
||||
import libKonogonka.fs.NCA.NCAProvider;
|
||||
import libKonogonka.fs.RomFs.FileSystemEntry;
|
||||
import libKonogonka.fs.RomFs.RomFsProvider;
|
||||
import libKonogonka.fs.other.System2.System2Provider;
|
||||
import libKonogonka.fs.other.System2.ini1.Ini1Provider;
|
||||
import libKonogonka.fs.other.System2.ini1.KIP1Provider;
|
||||
import libKonogonka.aesctr.InFileStreamProducer;
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.fs.finders.HeuristicFsWizard;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FsPatch {
|
||||
private static final byte[] HEADER = "PATCH".getBytes(StandardCharsets.US_ASCII);
|
||||
private static final byte[] FOOTER = "EOF".getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
private final NCAProvider ncaProvider;
|
||||
private final String saveToLocation;
|
||||
private final KeyChainHolder keyChainHolder;
|
||||
private final ILogPrinter logPrinter;
|
||||
|
||||
private String patchName;
|
||||
private byte[] _textSection;
|
||||
private boolean filesystemTypeFat32;
|
||||
|
||||
private HeuristicFsWizard wizard;
|
||||
// Called twice: once for FAT32, once for ExFAT
|
||||
FsPatch(NCAProvider ncaProvider,
|
||||
String saveToLocation,
|
||||
KeyChainHolder keyChainHolder,
|
||||
ILogPrinter logPrinter) throws Exception{
|
||||
this.ncaProvider = ncaProvider;
|
||||
this.saveToLocation = saveToLocation;
|
||||
this.keyChainHolder = keyChainHolder;
|
||||
this.logPrinter = logPrinter;
|
||||
|
||||
KIP1Provider kip1Provider = getKIP1Provider();
|
||||
getPatchName(kip1Provider);
|
||||
getTextSection(kip1Provider);
|
||||
checkFirmwareVersion();
|
||||
getFilesystemType();
|
||||
findAllOffsets();
|
||||
mkDirs();
|
||||
writeFile();
|
||||
new FsIniMaker(logPrinter,
|
||||
saveToLocation,
|
||||
_textSection,
|
||||
wizard.getOffset1(),
|
||||
wizard.getOffset2(),
|
||||
ncaProvider.getSdkVersion(),
|
||||
patchName,
|
||||
filesystemTypeFat32);
|
||||
logPrinter.print(" == Debug information ==\n"+wizard.getDebug(), EMsgType.NULL);
|
||||
}
|
||||
private KIP1Provider getKIP1Provider() throws Exception{
|
||||
RomFsProvider romFsProvider = ncaProvider.getNCAContentProvider(0).getRomfs();
|
||||
|
||||
FileSystemEntry package2FsEntry = romFsProvider.getRootEntry().getContent()
|
||||
.stream()
|
||||
.filter(e -> e.getName().equals("nx"))
|
||||
.collect(Collectors.toList())
|
||||
.get(0)
|
||||
.getContent()
|
||||
.stream()
|
||||
.filter(e -> e.getName().equals("package2"))
|
||||
.collect(Collectors.toList())
|
||||
.get(0);
|
||||
InFileStreamProducer producer = romFsProvider.getStreamProducer(package2FsEntry);
|
||||
System2Provider system2Provider = new System2Provider(producer, keyChainHolder);
|
||||
Ini1Provider ini1Provider = system2Provider.getIni1Provider();
|
||||
|
||||
KIP1Provider kip1Provider = ini1Provider.getKip1List().stream()
|
||||
.filter(provider -> provider.getHeader().getName().startsWith("FS"))
|
||||
.collect(Collectors.toList())
|
||||
.get(0);
|
||||
|
||||
if (kip1Provider == null)
|
||||
throw new Exception("No FS KIP1");
|
||||
|
||||
return kip1Provider;
|
||||
}
|
||||
private void getPatchName(KIP1Provider kip1Provider) throws Exception{
|
||||
int kip1EncryptedSize = (int) kip1Provider.getSize();
|
||||
byte[] kip1EncryptedRaw = new byte[kip1EncryptedSize];
|
||||
|
||||
try (BufferedInputStream kip1ProviderStream = kip1Provider.getStreamProducer().produce()) {
|
||||
if (kip1EncryptedSize != kip1ProviderStream.read(kip1EncryptedRaw))
|
||||
throw new Exception("Unencrypted FS KIP1 read failure");
|
||||
}
|
||||
|
||||
byte[] sha256ofKip1 = MessageDigest.getInstance("SHA-256").digest(kip1EncryptedRaw);
|
||||
patchName = Converter.byteArrToHexStringAsLE(sha256ofKip1, true) + ".ips";
|
||||
}
|
||||
private void getTextSection(KIP1Provider kip1Provider) throws Exception{
|
||||
_textSection = kip1Provider.getAsDecompressed().getTextRaw();
|
||||
}
|
||||
private void checkFirmwareVersion() throws Exception{
|
||||
final byte[] byteSdkVersion = ncaProvider.getSdkVersion();
|
||||
long fwVersion = Long.parseLong(""+byteSdkVersion[3]+byteSdkVersion[2]+byteSdkVersion[1]+byteSdkVersion[0]);
|
||||
logPrinter.print("Internal firmware version: " + byteSdkVersion[3] +"."+ byteSdkVersion[2] +"."+ byteSdkVersion[1] +"."+ byteSdkVersion[0], EMsgType.INFO);
|
||||
if (byteSdkVersion[3] < 9 || fwVersion < 9300)
|
||||
logPrinter.print("WARNING! FIRMWARES VERSIONS BEFORE 9.0.0 ARE NOT SUPPORTED! " +
|
||||
"USING PRODUCED ES PATCHES (IF ANY) COULD BREAK SOMETHING! IT'S NEVER BEEN TESTED!", EMsgType.WARNING);
|
||||
}
|
||||
private void getFilesystemType() throws Exception{
|
||||
String titleId = Converter.byteArrToHexStringAsLE(ncaProvider.getTitleId());
|
||||
filesystemTypeFat32 = titleId.equals("0100000000000819");
|
||||
if (filesystemTypeFat32)
|
||||
logPrinter.print("\n\t\t-- [ FAT32 ] --\n", EMsgType.INFO);
|
||||
else
|
||||
logPrinter.print("\n\t\t-- [ ExFAT ] --\n", EMsgType.INFO);
|
||||
}
|
||||
private void findAllOffsets() throws Exception{
|
||||
this.wizard = new HeuristicFsWizard(_textSection);
|
||||
String errorsAndNotes = wizard.getErrorsAndNotes();
|
||||
if (errorsAndNotes.length() > 0)
|
||||
logPrinter.print(errorsAndNotes, EMsgType.WARNING);
|
||||
}
|
||||
private void mkDirs(){
|
||||
File parentFolder = new File(saveToLocation + File.separator +
|
||||
"atmosphere" + File.separator + "kip_patches" + File.separator + "fs_patches");
|
||||
parentFolder.mkdirs();
|
||||
}
|
||||
|
||||
private void writeFile() throws Exception{
|
||||
String patchFileLocation = saveToLocation + File.separator +
|
||||
"atmosphere" + File.separator + "kip_patches" + File.separator + "fs_patches" + File.separator + patchName;
|
||||
int offset1 = wizard.getOffset1();
|
||||
int offset2 = wizard.getOffset2();
|
||||
|
||||
ByteBuffer handyFsPatch = ByteBuffer.allocate(0x100).order(ByteOrder.LITTLE_ENDIAN);
|
||||
handyFsPatch.put(HEADER);
|
||||
if (offset1 > 0) {
|
||||
logPrinter.print("Patch component 1 will be used", EMsgType.PASS);
|
||||
handyFsPatch.put(getPatch1(offset1));
|
||||
}
|
||||
if (offset2 > 0) {
|
||||
logPrinter.print("Patch component 2 will be used", EMsgType.PASS);
|
||||
handyFsPatch.put(getPatch2(offset2));
|
||||
}
|
||||
handyFsPatch.put(FOOTER);
|
||||
|
||||
byte[] fsPatch = new byte[handyFsPatch.position()];
|
||||
((Buffer) handyFsPatch).rewind();
|
||||
handyFsPatch.get(fsPatch);
|
||||
|
||||
try (BufferedOutputStream stream = new BufferedOutputStream(
|
||||
Files.newOutputStream(Paths.get(patchFileLocation)))){
|
||||
stream.write(fsPatch);
|
||||
}
|
||||
logPrinter.print("Patch created at "+patchFileLocation, EMsgType.PASS);
|
||||
}
|
||||
|
||||
private byte[] getPatch1(int offset) throws Exception{
|
||||
int requiredInstructionOffsetInternal = offset - 4;
|
||||
int requiredInstructionOffsetReal = requiredInstructionOffsetInternal + 0x100;
|
||||
final int patch = 0x1F2003D5; // NOP
|
||||
|
||||
logPrinter.print(BinToAsmPrinter.printSimplified(Integer.reverseBytes(patch), requiredInstructionOffsetInternal), EMsgType.NULL);
|
||||
|
||||
// Somehow IPS patches uses offsets written as big_endian (0.o) and bytes dat should be patched as LE.
|
||||
ByteBuffer prePatch = ByteBuffer.allocate(10).order(ByteOrder.BIG_ENDIAN)
|
||||
.putInt(requiredInstructionOffsetReal)
|
||||
.putShort((short) 4)
|
||||
.putInt(patch);
|
||||
|
||||
return Arrays.copyOfRange(prePatch.array(), 1, 10);
|
||||
}
|
||||
private byte[] getPatch2(int offset) throws Exception{
|
||||
int requiredInstructionOffsetInternal = offset - 4;
|
||||
int requiredInstructionOffsetReal = requiredInstructionOffsetInternal + 0x100;
|
||||
final int patch = 0xE0031F2A; // mov w0, wzr
|
||||
logPrinter.print(BinToAsmPrinter.printSimplified(Integer.reverseBytes(patch), requiredInstructionOffsetInternal), EMsgType.NULL);
|
||||
|
||||
// Somehow IPS patches uses offsets written as big_endian (0.o) and bytes dat should be patched as LE.
|
||||
ByteBuffer prePatch = ByteBuffer.allocate(10).order(ByteOrder.BIG_ENDIAN)
|
||||
.putInt(requiredInstructionOffsetReal)
|
||||
.putShort((short) 4)
|
||||
.putInt(patch);
|
||||
|
||||
return Arrays.copyOfRange(prePatch.array(), 1, 10);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.fs;
|
||||
|
||||
import libKonogonka.KeyChainHolder;
|
||||
import libKonogonka.fs.NCA.NCAProvider;
|
||||
import nsusbloader.ModelControllers.CancellableRunnable;
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.ModelControllers.Log;
|
||||
import nsusbloader.NSLDataTypes.EModule;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class FsPatchMaker extends CancellableRunnable {
|
||||
private int THREADS_POOL_SIZE;
|
||||
private final ILogPrinter logPrinter;
|
||||
private final String pathToFirmware;
|
||||
private final String pathToKeysFile;
|
||||
private final String saveTo;
|
||||
|
||||
private File firmware;
|
||||
private KeyChainHolder keyChainHolder;
|
||||
private ExecutorService executorService;
|
||||
private List<String> ncaFilesList; // inside the folder
|
||||
|
||||
private boolean oneLinerStatus = false;
|
||||
|
||||
public FsPatchMaker(String pathToFirmware, String pathToKeysFile, String saveTo){
|
||||
this.logPrinter = Log.getPrinter(EModule.PATCHES);
|
||||
/*
|
||||
this.logPrinter = new ILogPrinter() {
|
||||
public void print(String message, EMsgType type) throws InterruptedException {}
|
||||
public void updateProgress(Double value) throws InterruptedException {}
|
||||
public void update(HashMap<String, File> nspMap, EFileStatus status) {}
|
||||
public void update(File file, EFileStatus status) {}
|
||||
public void updateOneLinerStatus(boolean status) {}
|
||||
public void close() {}
|
||||
};
|
||||
*/
|
||||
this.pathToFirmware = pathToFirmware;
|
||||
this.pathToKeysFile = pathToKeysFile;
|
||||
this.saveTo = saveTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logPrinter.print("..:: Make FS Patches ::..", EMsgType.INFO);
|
||||
receiveFirmware();
|
||||
buildKeyChainHolder();
|
||||
receiveNcaFileNamesList();
|
||||
specifyThreadsPoolSize();
|
||||
createPool();
|
||||
executePool();
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
try{
|
||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||
} catch (Exception ignore){}
|
||||
}
|
||||
finally {
|
||||
logPrinter.updateOneLinerStatus(oneLinerStatus);
|
||||
logPrinter.close();
|
||||
}
|
||||
}
|
||||
private void receiveFirmware() throws Exception{
|
||||
logPrinter.print("Looking at firmware", EMsgType.INFO);
|
||||
this.firmware = new File(pathToFirmware);
|
||||
if (! firmware.exists())
|
||||
throw new Exception("Firmware directory does not exist " + pathToFirmware);
|
||||
}
|
||||
private void buildKeyChainHolder() throws Exception{
|
||||
logPrinter.print("Reading keys", EMsgType.INFO);
|
||||
this.keyChainHolder = new KeyChainHolder(pathToKeysFile, null);
|
||||
}
|
||||
private void receiveNcaFileNamesList() throws Exception{
|
||||
logPrinter.print("Collecting NCA files", EMsgType.INFO);
|
||||
String[] fileNamesArray = firmware.list(
|
||||
(File directory, String file) -> ( ! file.endsWith(".cnmt.nca") && file.endsWith(".nca")));
|
||||
ncaFilesList = Arrays.asList(Objects.requireNonNull(fileNamesArray));
|
||||
if (ncaFilesList.size() == 0)
|
||||
throw new Exception("No NCA files found in firmware folder");
|
||||
}
|
||||
private void specifyThreadsPoolSize(){
|
||||
THREADS_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors()+1, 4);
|
||||
THREADS_POOL_SIZE = Math.min(THREADS_POOL_SIZE, ncaFilesList.size());
|
||||
}
|
||||
|
||||
private void createPool() throws Exception{
|
||||
logPrinter.print("Creating sub-tasks pool", EMsgType.INFO);
|
||||
this.executorService = Executors.newFixedThreadPool(
|
||||
THREADS_POOL_SIZE,
|
||||
runnable -> {
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
}
|
||||
|
||||
private void executePool() throws Exception{ //TODO: FIX. Exceptions thrown only by logPrinter
|
||||
try {
|
||||
logPrinter.print("Executing sub-tasks pool", EMsgType.INFO);
|
||||
List<Future<List<NCAProvider>>> futuresResults = executorService.invokeAll(getSubTasksCollection());
|
||||
int counter = 0;
|
||||
for (Future<List<NCAProvider>> future : futuresResults){
|
||||
List<NCAProvider> ncaProviders = future.get();
|
||||
for (NCAProvider ncaProvider : ncaProviders) {
|
||||
makePatches(ncaProvider);
|
||||
if (++counter > 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
executorService.shutdown();
|
||||
}
|
||||
catch (InterruptedException ie){
|
||||
executorService.shutdownNow();
|
||||
boolean interruptedSuccessfully = false;
|
||||
try {
|
||||
interruptedSuccessfully = executorService.awaitTermination(20, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (InterruptedException awaitInterrupt){
|
||||
logPrinter.print("Force interrupting task...", EMsgType.WARNING);
|
||||
}
|
||||
logPrinter.print("Task interrupted "+(interruptedSuccessfully?"successfully":"with some issues"), EMsgType.WARNING);
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
logPrinter.print("Task failed: "+e.getMessage(), EMsgType.FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
private void makePatches(NCAProvider ncaProvider) throws Exception{
|
||||
final File foundFile = ncaProvider.getFile();
|
||||
logPrinter.print(String.format("File found: .."+File.separator+"%s"+File.separator+"%s",
|
||||
foundFile.getParentFile().getName(), foundFile.getName()), EMsgType.INFO);
|
||||
new FsPatch(ncaProvider, saveTo, keyChainHolder, logPrinter);
|
||||
oneLinerStatus = true;
|
||||
}
|
||||
private List<Callable<List<NCAProvider>>> getSubTasksCollection() throws Exception{
|
||||
logPrinter.print("Forming sub-tasks collection", EMsgType.INFO);
|
||||
List<Callable<List<NCAProvider>>> subTasks = new ArrayList<>();
|
||||
|
||||
int ncaPerThreadAmount = ncaFilesList.size() / THREADS_POOL_SIZE;
|
||||
Iterator<String> iterator = ncaFilesList.listIterator();
|
||||
|
||||
for (int i = 1; i < THREADS_POOL_SIZE; i++){
|
||||
Callable<List<NCAProvider>> task = new FsNcaSearchTask(getNextSet(iterator, ncaPerThreadAmount));
|
||||
subTasks.add(task);
|
||||
}
|
||||
int leftovers = ncaFilesList.size() % THREADS_POOL_SIZE;
|
||||
Callable<List<NCAProvider>> task = new FsNcaSearchTask(getNextSet(iterator, ncaPerThreadAmount+leftovers));
|
||||
subTasks.add(task);
|
||||
return subTasks;
|
||||
}
|
||||
private List<NCAProvider> getNextSet(Iterator<String> iterator, int amount) throws Exception{
|
||||
List<NCAProvider> ncas = new ArrayList<>();
|
||||
for (int j = 0; j < amount; j++){
|
||||
String ncaFileName = iterator.next();
|
||||
File nca = new File(firmware.getAbsolutePath()+File.separator+ncaFileName);
|
||||
NCAProvider provider = new NCAProvider(nca, keyChainHolder.getRawKeySet());
|
||||
ncas.add(provider);
|
||||
}
|
||||
return ncas;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright 2018-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.fs.finders;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.Utilities.patches.AHeuristic;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.SimplyFind;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class HeuristicFs1 extends AHeuristic {
|
||||
private static final String PATTERN = AppPreferences.getInstance().getPatchPattern("FS", 1, 0); // TBZ
|
||||
|
||||
private final byte[] where;
|
||||
private final List<Integer> findings;
|
||||
|
||||
HeuristicFs1(byte[] where) {
|
||||
this.where = where;
|
||||
this.findings = new ArrayList<>();
|
||||
SimplyFind simplyfind = new SimplyFind(PATTERN, where);
|
||||
simplyfind.getResults().forEach(var -> findings.add(var + 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound() {
|
||||
return findings.size() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wantLessEntropy() {
|
||||
return findings.size() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() throws Exception {
|
||||
if (findings.isEmpty())
|
||||
throw new Exception("Nothing found");
|
||||
if (findings.size() > 1)
|
||||
throw new Exception("Too many offsets");
|
||||
return findings.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOffsetsNearby(int offsetNearby) {
|
||||
findings.removeIf(offset -> {
|
||||
if (offset > offsetNearby)
|
||||
return !(offset < offsetNearby - 0xffff);
|
||||
return !(offset > offsetNearby - 0xffff);
|
||||
});
|
||||
return isFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetails() {
|
||||
int offsetInternal = findings.get(0) - 4;
|
||||
int firstExpression = Converter.getLEint(where, offsetInternal);
|
||||
int conditionalJumpLocation = offsetInternal + (firstExpression >> 5 & 0x3fff) * 4;
|
||||
|
||||
int secondExpressionsPairElement1 = Converter.getLEint(where, conditionalJumpLocation);
|
||||
int secondExpressionsPairElement2 = Converter.getLEint(where, conditionalJumpLocation + 4);
|
||||
|
||||
return BinToAsmPrinter.printSimplified(firstExpression, offsetInternal) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, offsetInternal + 4), offsetInternal + 4) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, offsetInternal + 8), offsetInternal + 8) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, offsetInternal + 12), offsetInternal + 12) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, offsetInternal + 16), offsetInternal + 16) +
|
||||
"...\n" +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement1, conditionalJumpLocation) +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement2, conditionalJumpLocation + 4);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Copyright 2018-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.fs.finders;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.Utilities.patches.AHeuristic;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.SimplyFind;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class HeuristicFs2 extends AHeuristic {
|
||||
private static final String PATTERN = AppPreferences.getInstance().getPatchPattern("FS", 2, 0);
|
||||
|
||||
private final byte[] where;
|
||||
private final List<Integer> findings;
|
||||
|
||||
HeuristicFs2(byte[] where){
|
||||
this.where = where;
|
||||
this.findings = new ArrayList<>();
|
||||
SimplyFind simplyfind = new SimplyFind(PATTERN, where);
|
||||
simplyfind.getResults().forEach(var -> findings.add(var + 4));
|
||||
|
||||
if(findings.size() < 2)
|
||||
return;
|
||||
|
||||
this.findings.removeIf(this::dropStep1);
|
||||
}
|
||||
// All matches are somewhere in 0x6xxxx-0x7xxxx, then let's just limit search field by 0x80000
|
||||
private boolean dropStep1(int offsetOfPatternFound){
|
||||
return (offsetOfPatternFound > 0x80000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(){
|
||||
return findings.size() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wantLessEntropy(){
|
||||
return findings.size() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() throws Exception{
|
||||
if(findings.isEmpty())
|
||||
throw new Exception("Nothing found");
|
||||
if (findings.size() > 1)
|
||||
throw new Exception("Too many offsets");
|
||||
return findings.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOffsetsNearby(int offsetNearby) {
|
||||
findings.removeIf(offset -> {
|
||||
if (offset > offsetNearby)
|
||||
return ! (offset < offsetNearby - 0xffff);
|
||||
return ! (offset > offsetNearby - 0xffff);
|
||||
});
|
||||
return isFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetails(){
|
||||
int offsetInternal = findings.get(0) - 4;
|
||||
int firstExpression = Converter.getLEint(where, offsetInternal);
|
||||
int conditionalJumpLocation = ((firstExpression & 0x3ffffff) * 4 + offsetInternal) & 0xfffff;
|
||||
int secondExpressionsPairElement1 = Converter.getLEint(where, conditionalJumpLocation);
|
||||
int secondExpressionsPairElement2 = Converter.getLEint(where, conditionalJumpLocation+4);
|
||||
|
||||
return BinToAsmPrinter.printSimplified(firstExpression, offsetInternal) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, offsetInternal + 4), offsetInternal + 4) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, offsetInternal + 8), offsetInternal + 8) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(where, offsetInternal + 12), offsetInternal + 12) +
|
||||
"...\n" +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement1, conditionalJumpLocation) +
|
||||
BinToAsmPrinter.printSimplified(secondExpressionsPairElement2, conditionalJumpLocation + 4);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright 2018-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.fs.finders;
|
||||
|
||||
import nsusbloader.Utilities.patches.AHeuristic;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HeuristicFsWizard {
|
||||
private final List<AHeuristic> all;
|
||||
private final List<AHeuristic> found;
|
||||
private final List<AHeuristic> wantLessEntropy;
|
||||
|
||||
private final StringBuilder errorsAndNotes;
|
||||
|
||||
private int offset1 = -1;
|
||||
private int offset2 = -1;
|
||||
|
||||
public HeuristicFsWizard(byte[] where) throws Exception{
|
||||
this.errorsAndNotes = new StringBuilder();
|
||||
|
||||
this.all = Arrays.asList(
|
||||
new HeuristicFs1(where),
|
||||
new HeuristicFs2(where)
|
||||
);
|
||||
|
||||
this.found = all.stream()
|
||||
.filter(AHeuristic::isFound)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (found.isEmpty())
|
||||
throw new Exception("Nothing found!");
|
||||
|
||||
this.wantLessEntropy = all.stream()
|
||||
.filter(AHeuristic::wantLessEntropy)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
shareOffsetsWithEachOther();
|
||||
|
||||
assignOffset1();
|
||||
assignOffset2();
|
||||
}
|
||||
|
||||
private void shareOffsetsWithEachOther(){
|
||||
for (AHeuristic es : wantLessEntropy) {
|
||||
if (shareWithNext(es))
|
||||
return;
|
||||
}
|
||||
}
|
||||
private boolean shareWithNext(AHeuristic es){
|
||||
try {
|
||||
for (AHeuristic foundEs : found) {
|
||||
if (es.setOffsetsNearby(foundEs.getOffset())) {
|
||||
found.add(es);
|
||||
wantLessEntropy.remove(es);
|
||||
shareOffsetsWithEachOther();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e){ e.printStackTrace(); }
|
||||
return false;
|
||||
}
|
||||
|
||||
private void assignOffset1(){
|
||||
try {
|
||||
offset1 = all.get(0).getOffset();
|
||||
}
|
||||
catch (Exception e){ errorsAndNotes.append(e.getLocalizedMessage()).append("\n"); }
|
||||
}
|
||||
private void assignOffset2(){
|
||||
try {
|
||||
offset2 = all.get(1).getOffset();
|
||||
}
|
||||
catch (Exception e){ errorsAndNotes.append(e.getLocalizedMessage()).append("\n"); }
|
||||
}
|
||||
|
||||
public String getErrorsAndNotes(){
|
||||
return errorsAndNotes.toString();
|
||||
}
|
||||
|
||||
public String getDebug(){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (all.get(0).isFound()){
|
||||
builder.append("\t\t-=== 1 ===-\n");
|
||||
builder.append(all.get(0).getDetails());
|
||||
}
|
||||
if (all.get(1).isFound()){
|
||||
builder.append("\t\t-=== 2 ===-\n");
|
||||
builder.append(all.get(1).getDetails());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public int getOffset1() { return offset1; }
|
||||
public int getOffset2() { return offset2; }
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.loader;
|
||||
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
import nsusbloader.Utilities.patches.MalformedIniFileException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
public class LoaderIniMaker {
|
||||
private static final String FILE_HEADER_TEXT = "# UTF-8\n" +
|
||||
"# A KIP section is [kip1_name:sha256_hex_8bytes]\n" +
|
||||
"# A patchset is .patch_name=kip_section_dec:offset_hex_0x:length_hex_0x:src_data_hex,dst_data_hex\n" +
|
||||
"# _dec: 1 char decimal | _hex_0x: max u32 prefixed with 0x | _hex: hex array.\n" +
|
||||
"# Kip1 section decimals: TEXT: 0, RODATA: 1, DATA: 2.\n"; // Sending good vibes to Mr. ITotalJustice
|
||||
|
||||
private final ILogPrinter logPrinter;
|
||||
private final String saveToLocation;
|
||||
private final int offset;
|
||||
|
||||
private String sectionDeclaration;
|
||||
private String patchSet;
|
||||
|
||||
LoaderIniMaker(ILogPrinter logPrinter,
|
||||
String saveToLocation,
|
||||
int foundOffset,
|
||||
String patchName) throws Exception{
|
||||
this.logPrinter = logPrinter;
|
||||
this.saveToLocation = saveToLocation;
|
||||
this.offset = foundOffset + 6;
|
||||
|
||||
mkDirs();
|
||||
makeSectionDeclaration(patchName);
|
||||
makePatchSet1();
|
||||
writeFile();
|
||||
}
|
||||
|
||||
private void mkDirs(){
|
||||
File parentFolder = new File(saveToLocation + File.separator + "bootloader");
|
||||
parentFolder.mkdirs();
|
||||
}
|
||||
|
||||
private void makeSectionDeclaration(String patchName){
|
||||
sectionDeclaration = "[Loader:"+patchName.substring(0, 16)+"]";
|
||||
}
|
||||
|
||||
private void makePatchSet1(){
|
||||
patchSet = String.format(".nosigchk=0:0x%02X:0x1:01,00", offset);
|
||||
}
|
||||
|
||||
private void writeFile() throws Exception{
|
||||
final String iniLocation = saveToLocation + File.separator + "bootloader" + File.separator + "patches.ini";
|
||||
final Path iniLocationPath = Paths.get(iniLocation);
|
||||
|
||||
boolean iniNotExists = Files.notExists(iniLocationPath);
|
||||
|
||||
try (RandomAccessFile ini = new RandomAccessFile(iniLocation, "rw")){
|
||||
if (iniNotExists)
|
||||
ini.writeBytes(FILE_HEADER_TEXT);
|
||||
else {
|
||||
String line;
|
||||
while ((line = ini.readLine()) != null){
|
||||
if (! line.startsWith(sectionDeclaration))
|
||||
continue;
|
||||
|
||||
String expression = ini.readLine();
|
||||
|
||||
if (expression == null || ! expression.startsWith(patchSet))
|
||||
throw new MalformedIniFileException("Somewhere near "+ini.getFilePointer());
|
||||
|
||||
return; // Ini file already contains correct information regarding patch file we made.
|
||||
}
|
||||
}
|
||||
|
||||
ini.writeBytes("\n#Loader (Atmosphere)\n");
|
||||
ini.writeBytes(sectionDeclaration);
|
||||
ini.writeBytes("\n");
|
||||
|
||||
ini.writeBytes(patchSet);
|
||||
ini.writeBytes("\n");
|
||||
}
|
||||
catch (MalformedIniFileException e){
|
||||
e.printStackTrace();
|
||||
logPrinter.print(
|
||||
"Existing patches.ini file is malformed or contains incorrect (outdated) information regarding current patch.\n" +
|
||||
"It's now saved at "+iniLocation+".OLD\n" +
|
||||
"New patches.ini file created instead.", EMsgType.WARNING);
|
||||
Files.move(iniLocationPath, Paths.get(iniLocation+".OLD"),
|
||||
StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||
writeFile();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
Copyright 2018-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
---
|
||||
Based on https://github.com/mrdude2478/IPS_Patch_Creator patch script made by GBATemp member MrDude.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.loader;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import libKonogonka.fs.other.System2.ini1.KIP1Provider;
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
import nsusbloader.Utilities.patches.BinToAsmPrinter;
|
||||
import nsusbloader.Utilities.patches.SimplyFind;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LoaderPatch {
|
||||
private static final byte[] HEADER = "PATCH".getBytes(StandardCharsets.US_ASCII);
|
||||
private static final byte[] FOOTER = "EOF".getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
private static final String ATMOSPHERE_NEW_PATTERN = "01C0BE121F00016B";
|
||||
//private static final String ATMOSPHERE_OLD_PATTERN = "003C00121F280071"; Must be patched using different (to current implementation) code
|
||||
|
||||
private final String saveToLocation;
|
||||
private final ILogPrinter logPrinter;
|
||||
|
||||
private String patchName;
|
||||
private byte[] _textSection;
|
||||
|
||||
private int offset;
|
||||
|
||||
LoaderPatch(KIP1Provider loaderProvider,
|
||||
String saveToLocation,
|
||||
ILogPrinter logPrinter) throws Exception{
|
||||
this.saveToLocation = saveToLocation;
|
||||
this.logPrinter = logPrinter;
|
||||
|
||||
getPatchName(loaderProvider);
|
||||
getTextSection(loaderProvider);
|
||||
findOffset();
|
||||
mkDirs();
|
||||
writeFile();
|
||||
new LoaderIniMaker(logPrinter, saveToLocation, offset, patchName);
|
||||
}
|
||||
private void getPatchName(KIP1Provider kip1Provider) throws Exception{
|
||||
int kip1EncryptedSize = (int) kip1Provider.getSize();
|
||||
byte[] kip1EncryptedRaw = new byte[kip1EncryptedSize];
|
||||
|
||||
try (BufferedInputStream kip1ProviderStream = kip1Provider.getStreamProducer().produce()) {
|
||||
if (kip1EncryptedSize != kip1ProviderStream.read(kip1EncryptedRaw))
|
||||
throw new Exception("Unencrypted FS KIP1 read failure");
|
||||
}
|
||||
|
||||
byte[] sha256ofKip1 = MessageDigest.getInstance("SHA-256").digest(kip1EncryptedRaw);
|
||||
patchName = Converter.byteArrToHexStringAsLE(sha256ofKip1, true) + ".ips";
|
||||
}
|
||||
private void getTextSection(KIP1Provider kip1Provider) throws Exception{
|
||||
_textSection = kip1Provider.getAsDecompressed().getTextRaw();
|
||||
}
|
||||
private void findOffset() throws Exception{
|
||||
SimplyFind simplyFind = new SimplyFind(ATMOSPHERE_NEW_PATTERN, _textSection); // Atm 13+
|
||||
if (simplyFind.getResults().size() == 0)
|
||||
throw new Exception("Offset not found");
|
||||
|
||||
offset = simplyFind.getResults().get(0);
|
||||
|
||||
if (offset <= 0)
|
||||
throw new Exception("Found offset is incorrect");
|
||||
|
||||
for (int i = 0; i < simplyFind.getResults().size(); i++) {
|
||||
int offsetInternal = simplyFind.getResults().get(i) + 4;
|
||||
logPrinter.print("Only first (#1) found record will be patched!", EMsgType.INFO);
|
||||
logPrinter.print("Found #" + (i+1) +"\n"+
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(_textSection, offsetInternal), offsetInternal) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(_textSection, offsetInternal + 4), offsetInternal + 4) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(_textSection, offsetInternal + 8), offsetInternal + 8) +
|
||||
BinToAsmPrinter.printSimplified(Converter.getLEint(_textSection, offsetInternal + 12), offsetInternal + 12),
|
||||
EMsgType.NULL);
|
||||
}
|
||||
}
|
||||
private void mkDirs(){
|
||||
File parentFolder = new File(saveToLocation + File.separator +
|
||||
"atmosphere" + File.separator + "kip_patches" + File.separator + "loader_patches");
|
||||
parentFolder.mkdirs();
|
||||
}
|
||||
|
||||
private void writeFile() throws Exception{
|
||||
String patchFileLocation = saveToLocation + File.separator +
|
||||
"atmosphere" + File.separator + "kip_patches" + File.separator + "loader_patches" + File.separator + patchName;
|
||||
|
||||
ByteBuffer handyFsPatch = ByteBuffer.allocate(0x100).order(ByteOrder.LITTLE_ENDIAN);
|
||||
handyFsPatch.put(HEADER);
|
||||
handyFsPatch.put(getPatch1(offset));
|
||||
handyFsPatch.put(FOOTER);
|
||||
|
||||
byte[] fsPatch = new byte[handyFsPatch.position()];
|
||||
((Buffer) handyFsPatch).rewind();
|
||||
handyFsPatch.get(fsPatch);
|
||||
|
||||
try (BufferedOutputStream stream = new BufferedOutputStream(
|
||||
Files.newOutputStream(Paths.get(patchFileLocation)))){
|
||||
stream.write(fsPatch);
|
||||
}
|
||||
logPrinter.print("Patch created at "+patchFileLocation, EMsgType.PASS);
|
||||
}
|
||||
|
||||
private byte[] getPatch1(int offset) throws Exception{
|
||||
int requiredInstructionOffsetInternal = offset + 6;
|
||||
int requiredInstructionOffsetReal = requiredInstructionOffsetInternal + 0x100;
|
||||
final byte[] patch = new byte[]{0x00, 0x01, 0x00};
|
||||
|
||||
int instructionPatched = Converter.getLEint(_textSection, offset + 4) & 0xff00ffff;
|
||||
|
||||
logPrinter.print("Patch will be applied", EMsgType.PASS);
|
||||
logPrinter.print(BinToAsmPrinter.printSimplified(instructionPatched, offset+4), EMsgType.NULL);
|
||||
|
||||
ByteBuffer prePatch = ByteBuffer.allocate(7).order(ByteOrder.BIG_ENDIAN)
|
||||
.putInt(requiredInstructionOffsetReal)
|
||||
.put(patch);
|
||||
|
||||
return Arrays.copyOfRange(prePatch.array(), 1, 7);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
Copyright 2018-2022 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.Utilities.patches.loader;
|
||||
|
||||
import libKonogonka.Converter;
|
||||
import libKonogonka.fs.other.System2.ini1.KIP1Provider;
|
||||
import nsusbloader.ModelControllers.CancellableRunnable;
|
||||
import nsusbloader.ModelControllers.ILogPrinter;
|
||||
import nsusbloader.ModelControllers.Log;
|
||||
import nsusbloader.NSLDataTypes.EModule;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
import nsusbloader.Utilities.patches.SimplyFind;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
public class LoaderPatchMaker extends CancellableRunnable {
|
||||
|
||||
private final ILogPrinter logPrinter;
|
||||
private final String atmosphereLocation;
|
||||
private final String saveTo;
|
||||
|
||||
private String package3Location;
|
||||
private KIP1Provider loaderProvider;
|
||||
|
||||
private boolean oneLinerStatus = false;
|
||||
|
||||
public LoaderPatchMaker(String atmosphereLocation, String saveTo){
|
||||
this.logPrinter = Log.getPrinter(EModule.PATCHES);
|
||||
/*
|
||||
this.logPrinter = new ILogPrinter() {
|
||||
public void print(String message, EMsgType type) throws InterruptedException {}
|
||||
public void updateProgress(Double value) throws InterruptedException {}
|
||||
public void update(HashMap<String, File> nspMap, EFileStatus status) {}
|
||||
public void update(File file, EFileStatus status) {}
|
||||
public void updateOneLinerStatus(boolean status) {}
|
||||
public void close() {}
|
||||
};
|
||||
//*/
|
||||
this.atmosphereLocation = atmosphereLocation;
|
||||
this.saveTo = saveTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logPrinter.print("..:: Make Loader Patches ::..", EMsgType.INFO);
|
||||
checkPackage3();
|
||||
createLoaderKip1Provider();
|
||||
makePatches();
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
try{
|
||||
logPrinter.print(e.getMessage(), EMsgType.FAIL);
|
||||
} catch (Exception ignore){}
|
||||
}
|
||||
finally {
|
||||
logPrinter.updateOneLinerStatus(oneLinerStatus);
|
||||
logPrinter.close();
|
||||
}
|
||||
}
|
||||
private void checkPackage3() throws Exception{
|
||||
logPrinter.print("Looking at Atmosphere", EMsgType.INFO);
|
||||
if (Files.notExists(Paths.get(atmosphereLocation)))
|
||||
throw new Exception("Atmosphere directory does not exist at " + atmosphereLocation);
|
||||
|
||||
package3Location = atmosphereLocation +File.separator+"package3";
|
||||
if (Files.exists(Paths.get(package3Location)))
|
||||
return;
|
||||
|
||||
package3Location = atmosphereLocation +File.separator+"fusee-secondary.bin";
|
||||
if (Files.notExists(Paths.get(package3Location)))
|
||||
throw new Exception("package3 / fusee-secondary.bin file not found at " + atmosphereLocation);
|
||||
}
|
||||
|
||||
private void createLoaderKip1Provider() throws Exception{
|
||||
Path package3Path = Paths.get(package3Location);
|
||||
|
||||
try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(package3Path))) {
|
||||
byte[] data = new byte[0x400];
|
||||
if (0x400 != stream.read(data))
|
||||
throw new Exception("Failed to read first 0x400 bytes of package3 / fusee-secondary file.");
|
||||
|
||||
SimplyFind simplyFind = new SimplyFind(".6f61646572", data); // eq. '.oader'
|
||||
List<Integer> results = simplyFind.getResults();
|
||||
if (results.size() == 0)
|
||||
throw new Exception("Failed to find 'Loader' offset at package3 / fusee-secondary file.");
|
||||
|
||||
int offset = results.get(0);
|
||||
int kip1Offset = Converter.getLEint(data, offset - 0x10);
|
||||
int kip1Size = Converter.getLEint(data, offset - 0xC);
|
||||
|
||||
loaderProvider = new KIP1Provider(package3Location, kip1Offset);
|
||||
|
||||
if (kip1Size != loaderProvider.getSize())
|
||||
throw new Exception("Incorrect calculations for KIP1. PK31 value: "+kip1Size+"KIP1Provider value: "+loaderProvider.getSize());
|
||||
logPrinter.print("Loader KIP1 found", EMsgType.PASS);
|
||||
}
|
||||
}
|
||||
private void makePatches() throws Exception{
|
||||
new LoaderPatch(loaderProvider, saveTo, logPrinter);
|
||||
oneLinerStatus = true;
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ public class CommandLineInterface {
|
|||
}
|
||||
|
||||
final Options cliOptions = createCliOptions();
|
||||
|
||||
CommandLineParser cliParser = new DefaultParser();
|
||||
try{
|
||||
CommandLine cli = cliParser.parse(cliOptions, args);
|
||||
|
@ -68,6 +67,11 @@ public class CommandLineInterface {
|
|||
new GoldLeafCli(arguments);
|
||||
return;
|
||||
}
|
||||
if (cli.hasOption("experimental")){
|
||||
final String[] arguments = cli.getOptionValues("experimental");
|
||||
new ExperimentalCli(arguments);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
if (cli.hasOption("x") || cli.hasOption("nxdt")){
|
||||
final String[] arguments = cli.getOptionValues("nxdt");
|
||||
|
@ -154,6 +158,12 @@ public class CommandLineInterface {
|
|||
.hasArgs()
|
||||
.argName("...")
|
||||
.build();
|
||||
final Option experimentalOption = Option.builder()
|
||||
.longOpt("experimental")
|
||||
.desc("Enable testing and experimental functions")
|
||||
.hasArgs()
|
||||
.argName("y|n")
|
||||
.build();
|
||||
/* nxdumptool */
|
||||
/*
|
||||
final Option nxdtOption = Option.builder("x")
|
||||
|
@ -184,6 +194,7 @@ public class CommandLineInterface {
|
|||
group.addOption(helpOption);
|
||||
group.addOption(tinfoilOption);
|
||||
group.addOption(glOption);
|
||||
group.addOption(experimentalOption);
|
||||
//group.addOption(nxdtOption);
|
||||
group.addOption(splitOption);
|
||||
group.addOption(mergeOption);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright 2019-2023 Dmitry Isaenko
|
||||
|
||||
This file is part of NS-USBloader.
|
||||
|
||||
NS-USBloader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
NS-USBloader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package nsusbloader.cli;
|
||||
|
||||
import nsusbloader.AppPreferences;
|
||||
|
||||
public class ExperimentalCli {
|
||||
ExperimentalCli(String[] arguments) throws IncorrectSetupException{
|
||||
if (arguments == null || arguments.length == 0)
|
||||
throw new IncorrectSetupException("No arguments.\nShould be 'y' or 'n'");
|
||||
|
||||
if (arguments.length > 1)
|
||||
throw new IncorrectSetupException("Too many arguments.\nShould be 'y' or 'n' only");
|
||||
|
||||
String arg = arguments[0].toLowerCase().substring(0, 1);
|
||||
|
||||
if (arg.equals("y")) {
|
||||
AppPreferences.getInstance().setPatchesTabInvisible(false);
|
||||
System.out.println("Experimental functions enabled");
|
||||
return;
|
||||
}
|
||||
if (arg.equals("n")) {
|
||||
AppPreferences.getInstance().setPatchesTabInvisible(true);
|
||||
System.out.println("Experimental functions disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IncorrectSetupException("Incorrect arguments.\nCould be 'y' or 'n' only");
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ public class GoldLeafCli {
|
|||
|
||||
private int parseFileSince = 1;
|
||||
|
||||
public GoldLeafCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
|
||||
GoldLeafCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
|
||||
this.arguments = arguments;
|
||||
|
||||
checkArguments();
|
||||
|
@ -43,7 +43,7 @@ public class GoldLeafCli {
|
|||
runGoldLeafBackend();
|
||||
}
|
||||
|
||||
public void checkArguments() throws IncorrectSetupException{
|
||||
private void checkArguments() throws IncorrectSetupException{
|
||||
if (arguments == null || arguments.length == 0) {
|
||||
throw new IncorrectSetupException("No arguments.\n" +
|
||||
"Try 'ns-usbloader -g help' for more information.");
|
||||
|
@ -75,7 +75,7 @@ public class GoldLeafCli {
|
|||
private String getGlSupportedVersions(){
|
||||
StringBuilder builder = new StringBuilder("Supported versions: \n");
|
||||
|
||||
for (String a : AppPreferences.goldleafSupportedVersions){
|
||||
for (String a : AppPreferences.GOLDLEAF_SUPPORTED_VERSIONS){
|
||||
builder.append("\t");
|
||||
builder.append(a);
|
||||
builder.append("\n");
|
||||
|
@ -83,7 +83,7 @@ public class GoldLeafCli {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public void parseGoldLeafVersion() throws IncorrectSetupException{
|
||||
private void parseGoldLeafVersion() throws IncorrectSetupException{
|
||||
String argument1 = arguments[0];
|
||||
|
||||
if (! argument1.startsWith("ver=")) {
|
||||
|
@ -98,7 +98,7 @@ public class GoldLeafCli {
|
|||
"Try 'ns-usbloader -g help' for more information.");
|
||||
}
|
||||
|
||||
for (String version : AppPreferences.goldleafSupportedVersions){
|
||||
for (String version : AppPreferences.GOLDLEAF_SUPPORTED_VERSIONS){
|
||||
if (version.equals(goldLeafVersion))
|
||||
return;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class GoldLeafCli {
|
|||
getGlSupportedVersions());
|
||||
}
|
||||
|
||||
public void parseFilesArguments() throws IncorrectSetupException{
|
||||
private void parseFilesArguments() throws IncorrectSetupException{
|
||||
filesList = new ArrayList<>();
|
||||
File file;
|
||||
|
||||
|
@ -123,7 +123,7 @@ public class GoldLeafCli {
|
|||
}
|
||||
}
|
||||
|
||||
public void runGoldLeafBackend() throws InterruptedException {
|
||||
private void runGoldLeafBackend() throws InterruptedException {
|
||||
Runnable task = new UsbCommunications(filesList,
|
||||
"GoldLeaf"+goldLeafVersion,
|
||||
filterForNsp);
|
||||
|
|
|
@ -27,7 +27,7 @@ public class NxdtCli {
|
|||
private final String[] arguments;
|
||||
private String saveTo;
|
||||
|
||||
public NxdtCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
|
||||
NxdtCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
|
||||
this.arguments = arguments;
|
||||
parseArgument();
|
||||
runBackend();
|
||||
|
|
|
@ -29,7 +29,7 @@ public class TinfoilUsbCli {
|
|||
private final String[] arguments;
|
||||
private List<File> filesList;
|
||||
|
||||
public TinfoilUsbCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
|
||||
TinfoilUsbCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
|
||||
this.arguments = arguments;
|
||||
checkArguments();
|
||||
parseFilesArguments();
|
||||
|
|
|
@ -197,7 +197,7 @@ class TinFoil extends TransferModule {
|
|||
ae.printStackTrace();
|
||||
return true;
|
||||
} catch (NullPointerException npe){
|
||||
print("NullPointerException (in some moment application didn't find something. Something important.):" +
|
||||
print("Application didn't find something important. Make sure you have enough space on medium!" +
|
||||
"\n "+npe.getMessage(), EMsgType.FAIL);
|
||||
npe.printStackTrace();
|
||||
return true;
|
||||
|
|
|
@ -49,7 +49,7 @@ public class UsbCommunications extends CancellableRunnable {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
print("\tStart", EMsgType.INFO);
|
||||
print("\tStart");
|
||||
|
||||
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
|
||||
|
||||
|
@ -66,6 +66,9 @@ public class UsbCommunications extends CancellableRunnable {
|
|||
case "TinFoil":
|
||||
module = new TinFoil(handler, nspMap, this, logPrinter);
|
||||
break;
|
||||
case "GoldLeafv0.10+":
|
||||
module = new GoldLeaf_010(handler, nspMap, this, logPrinter, nspFilterForGl);
|
||||
break;
|
||||
case "GoldLeafv0.8-0.9":
|
||||
module = new GoldLeaf_08(handler, nspMap, this, logPrinter, nspFilterForGl);
|
||||
break;
|
||||
|
@ -87,12 +90,12 @@ public class UsbCommunications extends CancellableRunnable {
|
|||
*/
|
||||
private void close(EFileStatus status){
|
||||
logPrinter.update(nspMap, status);
|
||||
print("\tEnd", EMsgType.INFO);
|
||||
print("\tEnd");
|
||||
logPrinter.close();
|
||||
}
|
||||
private void print(String message, EMsgType type){
|
||||
private void print(String message){
|
||||
try {
|
||||
logPrinter.print(message, type);
|
||||
logPrinter.print(message, EMsgType.INFO);
|
||||
}
|
||||
catch (InterruptedException ie){
|
||||
ie.printStackTrace();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
_version=v${project.version}
|
|
@ -0,0 +1,40 @@
|
|||
<?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.ListView?>
|
||||
<?import javafx.scene.control.Spinner?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
|
||||
<AnchorPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.FontSettingsController">
|
||||
<children>
|
||||
<VBox layoutX="344.0" layoutY="132.0" prefHeight="200.0" prefWidth="100.0" spacing="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<children>
|
||||
<ListView fx:id="fontsLv" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
|
||||
<Text fx:id="exampleText" strokeType="OUTSIDE" strokeWidth="0.0" />
|
||||
<HBox alignment="CENTER_RIGHT" spacing="5.0">
|
||||
<children>
|
||||
<Label text="%fontSize" wrapText="true" />
|
||||
<Spinner fx:id="fontSizeSpinner" minWidth="100.0" />
|
||||
<Pane HBox.hgrow="ALWAYS" />
|
||||
<Button fx:id="resetBtn" mnemonicParsing="false" text="%btn_ResetToDefaults">
|
||||
<HBox.margin>
|
||||
<Insets right="5.0" />
|
||||
</HBox.margin>
|
||||
</Button>
|
||||
<Button fx:id="cancelBtn" mnemonicParsing="false" text="%btn_Cancel" wrapText="true" />
|
||||
<Button fx:id="applyBtn" mnemonicParsing="false" styleClass="buttonUp" text="%btn_Select" wrapText="true" />
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
</children>
|
||||
</AnchorPane>
|
|
@ -55,7 +55,7 @@
|
|||
<Insets />
|
||||
</HBox.margin>
|
||||
</Button>
|
||||
<Button fx:id="selectSplitNspBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_OpenSplitFile">
|
||||
<Button fx:id="selectSplitBtn" 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>
|
||||
|
|
|
@ -15,7 +15,7 @@ Steps to roll NXDT functionality back:
|
|||
* Set 'Visible' on NXDT Tab selector (SVGPath container)
|
||||
-->
|
||||
|
||||
<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">
|
||||
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NSLMainController">
|
||||
<children>
|
||||
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<children>
|
||||
|
@ -47,6 +47,14 @@ Steps to roll NXDT functionality back:
|
|||
<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 fx:id="PatchesTabHolder" closable="false">
|
||||
<content>
|
||||
<fx:include fx:id="PatchesTab" source="PatchesTab.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" VBox.vgrow="ALWAYS" />
|
||||
</content>
|
||||
<graphic>
|
||||
<SVGPath content="M 5.7207031,0.20898438 C 4.9048038,0.22904941 4.0506554,0.62991967 3.421875,1.3671875 L 0.88671875,4.3398438 C -0.18640114,5.5981134 -0.18550676,7.3497999 0.890625,8.2675781 L 4.0273438,10.941406 C 6.6544469,8.8548374 9.2821295,6.7689991 11.910156,4.6835938 L 7.3007812,0.75195312 C 6.8972341,0.40778687 6.4010191,0.23063674 5.8828125,0.2109375 5.8288326,0.20888551 5.7750964,0.20764671 5.7207031,0.20898438 Z M 19.292969,0.44921875 C 18.77426,0.4506047 18.272727,0.60956864 17.857422,0.93945312 13.098348,4.719624 9.1497641,7.8546793 4.625,11.451172 H 4.62305 c -1.286759,1.021757 -2.5730291,2.044129 -3.85937502,3.066406 -1.107479,0.879692 -1.16921304,2.628898 -0.140625,3.923828 l 2.42968752,3.060547 c 1.0285869,1.29493 2.7479899,1.629691 3.8554687,0.75 L 24.001876,8.6737831 C 25.109431,7.7941362 25.171165,6.0449297 24.142578,4.75 L 21.712891,1.6914062 C 21.070024,0.8820747 20.157482,0.44690884 19.292969,0.44921875 Z M 14.550781,5.7402344 c 0.139019,-0.00739 0.26467,0.035715 0.341797,0.1328125 l 3.601563,4.5351561 c 0.154252,0.194198 0.05862,0.524614 -0.212891,0.740235 l -7.669922,6.089843 C 10.339882,17.453897 9.9980034,17.47154 9.84375,17.277344 L 6.2421875,12.744141 C 6.0879341,12.549944 6.1836303,12.221473 6.4550781,12.005859 L 14.123047,5.9140625 c 0.135725,-0.1078073 0.288715,-0.166439 0.427734,-0.1738281 z m -1.044922,1.4140625 c -0.161808,0.0078 -0.316999,0.066599 -0.443359,0.1679687 -0.331549,0.2651389 -0.384928,0.7490485 -0.119141,1.0800782 0.265722,0.3309315 0.749564,0.3834278 1.080079,0.1171874 0.329672,-0.2655771 0.3821,-0.7479194 0.117187,-1.078125 C 13.98715,7.2496671 13.751194,7.1429424 13.505859,7.1542969 Z m 2.695313,3.3554691 c -0.161811,0.0078 -0.317006,0.06659 -0.44336,0.167968 -0.331029,0.265668 -0.383535,0.749595 -0.117187,1.080078 0.265523,0.32977 0.74795,0.382208 1.078125,0.117188 0.330388,-0.264941 0.383708,-0.747437 0.119141,-1.078125 -0.153867,-0.192337 -0.390703,-0.299131 -0.636719,-0.287109 z m -3.878906,0.345703 c -0.161811,0.0078 -0.317006,0.06659 -0.44336,0.167969 -0.330387,0.264941 -0.383706,0.747436 -0.11914,1.078124 0.265085,0.331648 0.74908,0.385036 1.080078,0.119141 0.331029,-0.265668 0.383535,-0.749595 0.117187,-1.080078 -0.153858,-0.191033 -0.389764,-0.297009 -0.634765,-0.285156 z m -3.8632816,0.34375 c -0.1624871,0.0074 -0.3184262,0.0662 -0.4453125,0.167969 -0.3310296,0.265668 -0.3835352,0.749595 -0.1171875,1.080078 0.2649414,0.330388 0.747437,0.383707 1.078125,0.11914 C 9.3062569,12.301321 9.3596452,11.817326 9.09375,11.486328 8.9402947,11.294564 8.7043254,11.187834 8.4589844,11.199219 Z M 20.761719,12.232422 12.880859,18.492188 17.5,22.431641 c 1.076128,0.917777 2.805784,0.643037 3.878906,-0.615235 l 2.535156,-2.972656 c 1.073119,-1.258273 1.072172,-3.009959 -0.0039,-3.927734 z m -9.605469,2.33789 c -0.161811,0.0078 -0.317006,0.06659 -0.443359,0.167969 -0.32977,0.265523 -0.382208,0.74795 -0.117188,1.078125 0.264795,0.329134 0.745796,0.382385 1.076172,0.119141 0.331648,-0.265085 0.385036,-0.74908 0.119141,-1.080078 -0.153858,-0.191034 -0.389765,-0.29701 -0.634766,-0.285157 z" />
|
||||
</graphic>
|
||||
</Tab>
|
||||
<Tab closable="false">
|
||||
<content>
|
||||
<fx:include fx:id="SettingsTab" source="SettingsTab.fxml" VBox.vgrow="ALWAYS" />
|
||||
|
|
|
@ -12,21 +12,12 @@
|
|||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.SVGPath?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
<VBox spacing="15.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NxdtController">
|
||||
<VBox spacing="15.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NxdtController">
|
||||
<HBox alignment="CENTER">
|
||||
<children>
|
||||
<Label styleClass="nxdt" text="nx">
|
||||
<font>
|
||||
<Font name="System Bold" size="18.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label text="dumptool">
|
||||
<font>
|
||||
<Font name="System Bold" size="18.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label styleClass="nxdt" text="nx" />
|
||||
<Label styleClass="bold-text" text="dumptool" />
|
||||
</children>
|
||||
</HBox>
|
||||
<GridPane>
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
<?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.ScrollPane?>
|
||||
<?import javafx.scene.control.Separator?>
|
||||
<?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?>
|
||||
|
||||
<ScrollPane fitToWidth="true" onDragDropped="#handleDrop" onDragOver="#handleDragOver" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.PatchesController">
|
||||
<VBox fx:id="patchesToolPane" spacing="15.0">
|
||||
<Pane minHeight="-Infinity" prefHeight="10.0" style="-fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #2cd882 40%, transparent 45%);" />
|
||||
<HBox alignment="CENTER">
|
||||
<children>
|
||||
<Label styleClass="bold-text" text="%tabPatches_Lbl_Title" />
|
||||
</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>
|
||||
<VBox spacing="5.0">
|
||||
<children>
|
||||
<HBox alignment="CENTER_LEFT" spacing="5.0">
|
||||
<children>
|
||||
<Label minHeight="-Infinity" minWidth="-Infinity" text="%tabPatches_Lbl_Firmware" wrapText="true" />
|
||||
<Label fx:id="shortNameFirmwareLbl" textOverrun="LEADING_WORD_ELLIPSIS" />
|
||||
<Pane HBox.hgrow="ALWAYS" />
|
||||
<Button minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#selectFirmware" styleClass="buttonSelect" text="%tabSplMrg_Btn_SelectFolder" wrapText="true">
|
||||
<graphic>
|
||||
<SVGPath content="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" fill="#289de8" />
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="locationFirmwareLbl" disable="true" styleClass="italic-text" textOverrun="LEADING_WORD_ELLIPSIS" />
|
||||
<HBox alignment="CENTER_LEFT" spacing="5.0">
|
||||
<children>
|
||||
<Label minHeight="-Infinity" minWidth="-Infinity" text="%tabPatches_Lbl_Atmo" wrapText="true" />
|
||||
<Label fx:id="shortNameAtmoLbl" textOverrun="LEADING_WORD_ELLIPSIS" />
|
||||
<Pane HBox.hgrow="ALWAYS" />
|
||||
<Button minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#selectAtmosphereFolder" styleClass="buttonSelect" text="%tabSplMrg_Btn_SelectFolder" wrapText="true">
|
||||
<graphic>
|
||||
<SVGPath content="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" fill="#289de8" />
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="locationAtmosphereLbl" disable="true" styleClass="italic-text" textOverrun="LEADING_WORD_ELLIPSIS" />
|
||||
</children>
|
||||
</VBox>
|
||||
<Separator prefWidth="200.0" />
|
||||
<VBox spacing="5.0">
|
||||
<children>
|
||||
<HBox alignment="CENTER_LEFT" spacing="5.0">
|
||||
<children>
|
||||
<Label minHeight="-Infinity" minWidth="-Infinity" text="%tabPatches_Lbl_Keys" wrapText="true" />
|
||||
<Label fx:id="shortNameKeysLbl" />
|
||||
<Pane HBox.hgrow="ALWAYS" />
|
||||
<Button minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#selectProdKeys" styleClass="buttonSelect" text="%btn_Select">
|
||||
<graphic>
|
||||
<SVGPath content="M22,18V22H18V19H15V16H12L9.74,13.74C9.19,13.91 8.61,14 8,14A6,6 0 0,1 2,8A6,6 0 0,1 8,2A6,6 0 0,1 14,8C14,8.61 13.91,9.19 13.74,9.74L22,18M7,5A2,2 0 0,0 5,7A2,2 0 0,0 7,9A2,2 0 0,0 9,7A2,2 0 0,0 7,5Z" fill="#289de8" />
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="locationKeysLbl" disable="true" styleClass="italic-text" textOverrun="LEADING_WORD_ELLIPSIS" />
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox spacing="5.0">
|
||||
<children>
|
||||
<HBox alignment="CENTER_LEFT" spacing="5.0">
|
||||
<children>
|
||||
<Label minHeight="-Infinity" minWidth="-Infinity" text="%tabSplMrg_Lbl_SaveToLocation" wrapText="true" />
|
||||
<Label fx:id="saveToLbl" />
|
||||
<Pane HBox.hgrow="ALWAYS" />
|
||||
<Button minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#selectSaveTo" styleClass="buttonSelect" text="%btn_Select">
|
||||
<graphic>
|
||||
<SVGPath content="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" fill="#289de8" />
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
</VBox>
|
||||
</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" spacing="5.0">
|
||||
<children>
|
||||
<Button fx:id="makeFsBtn" contentDisplay="TOP" mnemonicParsing="false" styleClass="buttonUp" text="%tabPatches_Btn_MakeFs" />
|
||||
<Button fx:id="makeEsBtn" contentDisplay="TOP" mnemonicParsing="false" styleClass="buttonUp" text="%tabPatches_Btn_MakeEs" />
|
||||
<Button fx:id="makeLoaderBtn" contentDisplay="TOP" mnemonicParsing="false" styleClass="buttonUp" text="%tabPatches_Btn_MakeAtmo" />
|
||||
</children>
|
||||
</HBox>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
</ScrollPane>
|
|
@ -14,18 +14,13 @@
|
|||
<?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">
|
||||
<ScrollPane fitToWidth="true" xmlns="http://javafx.com/javafx/18" 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="%tabRcm_Lbl_FuseeGelee">
|
||||
<font>
|
||||
<Font name="System Bold" size="15.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label styleClass="bold-text" text="%tabRcm_Lbl_FuseeGelee" />
|
||||
</children>
|
||||
</HBox>
|
||||
<GridPane>
|
||||
|
@ -57,11 +52,7 @@
|
|||
<Label fx:id="payloadFNameLbl1" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="payloadFPathLbl1" disable="true">
|
||||
<font>
|
||||
<Font name="System Italic" size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="payloadFPathLbl1" disable="true" styleClass="italic-text" />
|
||||
</children>
|
||||
</VBox>
|
||||
<Button fx:id="selPldBtn1" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
|
||||
|
@ -86,11 +77,7 @@
|
|||
<Label fx:id="payloadFNameLbl2" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="payloadFPathLbl2" disable="true">
|
||||
<font>
|
||||
<Font name="System Italic" size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="payloadFPathLbl2" disable="true" styleClass="italic-text" />
|
||||
</children>
|
||||
</VBox>
|
||||
<Button fx:id="selPldBtn2" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
|
||||
|
@ -115,11 +102,7 @@
|
|||
<Label fx:id="payloadFNameLbl3" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="payloadFPathLbl3" disable="true">
|
||||
<font>
|
||||
<Font name="System Italic" size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="payloadFPathLbl3" disable="true" styleClass="italic-text" />
|
||||
</children>
|
||||
</VBox>
|
||||
<Button fx:id="selPldBtn3" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
|
||||
|
@ -144,11 +127,7 @@
|
|||
<Label fx:id="payloadFNameLbl4" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="payloadFPathLbl4" disable="true">
|
||||
<font>
|
||||
<Font name="System Italic" size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="payloadFPathLbl4" disable="true" styleClass="italic-text" />
|
||||
</children>
|
||||
</VBox>
|
||||
<Button fx:id="selPldBtn4" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
|
||||
|
@ -173,11 +152,7 @@
|
|||
<Label fx:id="payloadFNameLbl5" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="payloadFPathLbl5" disable="true">
|
||||
<font>
|
||||
<Font name="System Italic" size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="payloadFPathLbl5" disable="true" styleClass="italic-text" />
|
||||
</children>
|
||||
</VBox>
|
||||
<Button fx:id="selPldBtn5" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox spacing="5.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.SettingsBlockGenericController">
|
||||
<VBox spacing="5.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.SettingsBlockGenericController">
|
||||
<children>
|
||||
<Label text="%tab2_Lbl_ApplicationSettings" />
|
||||
<HBox alignment="CENTER_LEFT" spacing="5.0">
|
||||
|
@ -28,6 +28,11 @@
|
|||
<Insets left="5.0" />
|
||||
</VBox.margin>
|
||||
</HBox>
|
||||
<Button fx:id="fontSelectBtn" mnemonicParsing="false" text="%tab2_Btn_ApplicationFont">
|
||||
<VBox.margin>
|
||||
<Insets left="5.0" />
|
||||
</VBox.margin>
|
||||
</Button>
|
||||
<HBox>
|
||||
<children>
|
||||
<VBox>
|
||||
|
|
|
@ -12,19 +12,14 @@
|
|||
<?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 fx:id="smToolPane" onDragDropped="#handleDrop" onDragOver="#handleDragOver" spacing="20.0" xmlns="http://javafx.com/javafx/18" 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>
|
||||
<Label styleClass="bold-text" text="%tabSplMrg_Lbl_SplitNMergeTitle" />
|
||||
</children>
|
||||
</HBox>
|
||||
<GridPane>
|
||||
|
|
|
@ -11,8 +11,9 @@ windowBodyConfirmExit=Data transfer is in progress and closing this application
|
|||
windowTitleConfirmExit=No, don't do this!
|
||||
btn_Stop=Interrupt
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Status
|
||||
tab1_table_Lbl_FileName=File name
|
||||
|
@ -44,7 +45,7 @@ tab2_Cb_AllowXciNszXcz=Allow XCI / NSZ / XCZ files selection for Awoo
|
|||
tab2_Lbl_AllowXciNszXczDesc=Used by applications that support XCI/NSZ/XCZ and utilizes Awoo (aka Adubbz/TinFoil) transfer protocol. Don't change if not sure. Enable for Awoo Installer.
|
||||
tab2_Lbl_Language=Language
|
||||
windowBodyRestartToApplyLang=Please restart application to apply changes.
|
||||
btn_OpenSplitFile=Select split NSP
|
||||
btn_OpenSplitFile=Select split
|
||||
tab2_Lbl_ApplicationSettings=Main settings
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Split & merge files tool
|
||||
tabSplMrg_RadioBtn_Split=Split
|
||||
|
@ -77,4 +78,20 @@ windowTitleAddingFiles=Searching for files...
|
|||
windowBodyFilesScanned=Files scanned: %d\nWould be added: %d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo Installer and compatible
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
tabPatches_Lbl_Firmware=Firmware:
|
||||
tabPatches_Lbl_Atmo=Atmosphere:
|
||||
tabPatches_Btn_fromFolder=From folder
|
||||
tabPatches_Btn_asZipFile=as ZIP file
|
||||
tabPatches_Lbl_Title=Patches
|
||||
tabPatches_Lbl_Keys=Keys:
|
||||
tabPatches_Btn_MakeEs=Make ES
|
||||
tabPatches_Btn_MakeFs=Make FS
|
||||
tabPatches_Btn_MakeAtmo=Make Loader (Atmosphere)
|
||||
tabPatches_Btn_MakeAll=Make all
|
||||
tabPatches_ServiceWindowMessageEsFs=Both firmware and keys should be set to generate patches. Otherwise, it's not clear what to patch.
|
||||
tabPatches_ServiceWindowMessageLoader=Atmosphere folder should be defined to generate 'Loader' patch.
|
||||
tab2_Btn_ApplicationFont=Change application font
|
||||
btn_ResetToDefaults=Reset
|
||||
fontPreviewText=Text preview
|
||||
fontSize=Font size:
|
||||
|
|
|
@ -9,8 +9,9 @@ windowBodyConfirmExit=\u062C\u0627\u0631\u064A \u0646\u0642\u0644 \u0627\u0644\u
|
|||
windowTitleConfirmExit=\u0644\u0627 , \u0644\u0627 \u062A\u0641\u0639\u0644 \u0630\u0644\u0643!
|
||||
btn_Stop=\u0625\u064A\u0642\u0627\u0641
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
\u0627\u0644\u0645\u0635\u062F\u0631: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u0627\u0644\u0645\u0648\u0642\u0639: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
\u0627\u0644\u0645\u0635\u062F\u0631: https://git.redrise.ru/desu/ns-usbloader/\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u0627\u0644\u0645\u0648\u0642\u0639: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=\u0627\u0644\u062D\u0627\u0644\u0629
|
||||
tab1_table_Lbl_FileName=\u0627\u0633\u0645 \u0627\u0644\u0645\u0644\u0641
|
||||
|
@ -42,7 +43,7 @@ tab2_Cb_AllowXciNszXcz=\u0627\u0644\u0633\u0645\u0627\u062D \u0644\u0628\u0631\u
|
|||
tab2_Lbl_AllowXciNszXczDesc=\u0645\u0633\u062A\u062E\u062F\u0645 \u0628\u0627\u0644\u0628\u0631\u0627\u0645\u062C \u0627\u0644\u062A\u064A \u062A\u062F\u0639\u0645 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0645\u0646 \u0627\u0644\u0646\u0648\u0639 "\u0625\u0643\u0633 \u0633\u064A \u0622\u064A" \u0623\u0648 "\u0625\u0646 \u0625\u0633 \u0632\u062F" \u0623\u0648 "\u0625\u0643\u0633 \u0633\u064A \u0632\u062F" \u0648\u062A\u0633\u062A\u062E\u062F\u0645 \u0628\u0631\u0648\u062A\u0648\u0643\u0648\u0644 \u0627\u0644\u0646\u0642\u0644 \u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644 "\u062A\u064A\u0646\u0641\u0648\u064A\u0644". \u0644\u0627 \u062A\u0639\u062F\u0644 \u0625\u0630\u0627 \u0644\u0645 \u062A\u0643\u0646 \u0645\u062A\u0623\u0643\u062F . \u0648\u0641\u0639\u0644\u0647 \u0625\u0630\u0627 \u0643\u0646\u062A \u062A\u0633\u062A\u062E\u062F\u0645 \u0628\u0631\u0646\u0627\u0645\u062C \u062A\u0646\u0635\u064A\u0628 "\u0623\u0648\u0648\u0648".
|
||||
tab2_Lbl_Language=\u0627\u0644\u0644\u063A\u0629
|
||||
windowBodyRestartToApplyLang=\u0645\u0646 \u0641\u0636\u0644\u0643 \u0623\u0639\u062F \u062A\u0634\u0641\u064A\u0644 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0644\u062A\u0637\u0628\u064A\u0642 \u0627\u0644\u062A\u0639\u062F\u064A\u0644\u0627\u062A.
|
||||
btn_OpenSplitFile=\u0627\u062E\u062A\u0631 \u062A\u0642\u0633\u064A\u0645 \u0645\u0644\u0641 \u0627\u0644 "\u0625\u0646 \u0625\u0633 \u0628\u064A"
|
||||
btn_OpenSplitFile=\u0627\u062E\u062A\u0631 \u062A\u0642\u0633\u064A\u0645 \u0645\u0644\u0641 \u0627\u0644
|
||||
tab2_Lbl_ApplicationSettings=\u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=\u0623\u062F\u0627\u0629 \u062A\u0642\u0633\u064A\u0645 \u0648\u062F\u0645\u062C \u0627\u0644\u0645\u0644\u0641\u0627\u062A
|
||||
tabSplMrg_RadioBtn_Split=\u062A\u0642\u0633\u064A\u0645
|
||||
|
@ -70,3 +71,4 @@ tab2_Cb_GlVersion=\u0625\u0635\u062F\u0627\u0631 \u0628\u0631\u0646\u0627\u0645\
|
|||
tab2_Cb_GLshowNspOnly=\u0627\u0639\u0631\u0636 \u0641\u0642\u0637 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0630\u0627\u062A \u0627\u0644\u0625\u0645\u062A\u062F\u0627\u062F "\u0625\u0646 \u0625\u0633 \u0628\u064A" \u0641\u064A \u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644\u0640 "\u062C\u0648\u0644\u062F \u0644\u064A\u0641".
|
||||
windowBodyPleaseStopOtherProcessFirst=\u0645\u0646 \u0641\u0636\u0644\u0643 \u0642\u0645 \u0628\u0625\u064A\u0642\u0627\u0641 \u0627\u0644\u0639\u0645\u0644\u064A\u0627\u062A \u0627\u0644\u0623\u062E\u0631\u0649 \u0642\u0628\u0644 \u0627\u0644\u0625\u0633\u062A\u0645\u0631\u0627\u0631.
|
||||
|
||||
|
||||
|
|
|
@ -9,8 +9,9 @@ windowBodyConfirmExit=Pr\u00E1v\u011B prob\u00EDh\u00E1 p\u0159enos dat a zav\u0
|
|||
windowTitleConfirmExit=Ne, te\u010F nechci odej\u00EDt!
|
||||
btn_Stop=P\u0159eru\u0161it
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Stav
|
||||
tab1_table_Lbl_FileName=N\u00E1zev souboru
|
||||
|
@ -42,7 +43,7 @@ tab2_Cb_AllowXciNszXcz=Umo\u017Enit volbu XCI / NSZ / XCZ soubor\u016F pro Awoo
|
|||
tab2_Lbl_AllowXciNszXczDesc=Lze vyu\u017E\u00EDt v aplikac\u00EDch, kter\u00E9 podporuj\u00ED soubory typu XCI/NSZ/XCZ a pro p\u0159enos vyu\u017E\u00EDvaj\u00ED protokol Tinfoil. Nem\u011B\u0148te, jestli tomu nerozum\u00EDte. Aktivujte pro Awoo Installer.
|
||||
tab2_Lbl_Language=Jazyk
|
||||
windowBodyRestartToApplyLang=Pro aplikov\u00E1n\u00ED zm\u011Bn restartujte aplikaci.
|
||||
btn_OpenSplitFile=Zvolit rozd\u011Blen\u00E9 NSP
|
||||
btn_OpenSplitFile=Zvolit rozd\u011Blen\u00E9 soubor
|
||||
tab2_Lbl_ApplicationSettings=Hlavn\u00ED nastaven\u00ED
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Utilita k rozd\u011Blen\u00ED/slou\u010Den\u00ED soubor\u016F
|
||||
tabSplMrg_RadioBtn_Split=Rozd\u011Blit
|
||||
|
@ -70,3 +71,4 @@ tab2_Cb_GlVersion=GoldLeaf verze
|
|||
tab2_Cb_GLshowNspOnly=Uk\u00E1zat v GoldLeafu pouze *.nsp.
|
||||
windowBodyPleaseStopOtherProcessFirst=Pros\u00EDm, p\u0159ed pokra\u010Dov\u00E1n\u00EDm nejprve zru\u0161te aktivn\u00ED p\u0159enos.
|
||||
|
||||
|
||||
|
|
|
@ -11,8 +11,9 @@ windowBodyConfirmExit=Der Datentransfer ist noch nicht abgeschlossen; das Schlie
|
|||
windowTitleConfirmExit=Nein, mach das nicht!
|
||||
btn_Stop=Unterbrechen
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Status
|
||||
tab1_table_Lbl_FileName=Dateiname
|
||||
|
@ -44,8 +45,9 @@ tab2_Cb_AllowXciNszXcz=Erlaube XCI- NSZ- XCZ-Dateien-Verwendung f\u00FCr Awoo
|
|||
tab2_Lbl_AllowXciNszXczDesc=Von einigen Drittanbietern verwendet, welche XCI/NSZ/XCZ unterst\u00FCtzen, nutzt z Transfer Protocol. Nicht \u00E4ndern, wenn unsicher.
|
||||
tab2_Lbl_Language=Sprache
|
||||
windowBodyRestartToApplyLang=Bitte die Applikation neustarten um die Einstellungen zu \u00FCbernehmen.
|
||||
btn_OpenSplitFile=Split-NSP ausw\uFFFDhlen
|
||||
btn_OpenSplitFile=Split-file ausw\uFFFDhlen
|
||||
tab2_Cb_GLshowNspOnly=Nur *.nsp in GoldLeaf zeigen.
|
||||
btn_Cancel=Abbrechen
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
btn_OpenFile=Select files
|
||||
btn_OpenFolders=Select folder
|
||||
btn_Upload=Upload to NS
|
||||
btn_OpenFolders_tooltip=Select a folder to be scanned.\nThis folder and all of its subfolders will be scanned.\nAll matching files will be added to the list.
|
||||
tab3_Txt_EnteredAsMsg1=You have been entered as:
|
||||
tab3_Txt_EnteredAsMsg2=You should be root or have configured 'udev' rules for this user to avoid any issues.
|
||||
tab3_Txt_FilesToUploadTitle=Files to upload:
|
||||
tab3_Txt_GreetingsMessage=Welcome to NS-USBloader
|
||||
tab3_Txt_NoFolderOrFileSelected=No files selected: nothing to upload.
|
||||
windowBodyConfirmExit=Data transfer is in progress and closing this application will interrupt it.\nIt's the worse thing you can do now.\nInterrupt proccess and exit?
|
||||
windowTitleConfirmExit=No, don't do this!
|
||||
btn_Stop=Interrupt
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Status
|
||||
tab1_table_Lbl_FileName=File name
|
||||
tab1_table_Lbl_Size=Size
|
||||
tab1_table_Lbl_Upload=Upload?
|
||||
tab1_table_contextMenu_Btn_BtnDelete=Remove
|
||||
tab1_table_contextMenu_Btn_DeleteAll=Remove all
|
||||
tab2_Lbl_HostIP=Host IP
|
||||
tab1_Lbl_NSIP=NS IP:
|
||||
tab2_Cb_ValidateNSHostName=Always validate NS IP input.
|
||||
windowBodyBadIp=Are you sure that you entered NS IP address correctly?
|
||||
windowTitleBadIp=IP address of NS most likely incorrect
|
||||
tab2_Cb_ExpertMode=Expert mode (NET setup)
|
||||
tab2_Lbl_HostPort=port
|
||||
tab2_Cb_AutoDetectIp=Auto-detect IP
|
||||
tab2_Cb_RandSelectPort=Randomly get port
|
||||
tab2_Cb_DontServeRequests=Don't serve requests
|
||||
tab2_Lbl_DontServeRequestsDesc=If selected, this computer won't reply to NSP files requests coming from NS (over the net) and use defined host settings to tell Awoo where should it look for files.
|
||||
tab2_Lbl_HostExtra=extra
|
||||
windowTitleErrorPort=Port set incorrectly!
|
||||
windowBodyErrorPort=Port can't be 0 or greater than 65535.
|
||||
tab2_Cb_AutoCheckForUpdates=Auto check for updates
|
||||
windowTitleNewVersionAval=New version available
|
||||
windowTitleNewVersionNOTAval=No new versions available
|
||||
windowTitleNewVersionUnknown=Unable to check for new versions
|
||||
windowBodyNewVersionUnknown=Something went wrong\nMaybe internet unavailable, or GitHub is down
|
||||
windowBodyNewVersionNOTAval=You're using the latest version
|
||||
tab2_Cb_AllowXciNszXcz=Allow XCI / NSZ / XCZ files selection for Awoo
|
||||
tab2_Lbl_AllowXciNszXczDesc=Used by applications that support XCI/NSZ/XCZ and utilizes Awoo (aka Adubbz/TinFoil) transfer protocol. Don't change if not sure. Enable for Awoo Installer.
|
||||
tab2_Lbl_Language=Language
|
||||
windowBodyRestartToApplyLang=Please restart application to apply changes.
|
||||
btn_OpenSplitFile=Select split NSP
|
||||
tab2_Lbl_ApplicationSettings=Main settings
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Split & merge files tool
|
||||
tabSplMrg_RadioBtn_Split=Split
|
||||
tabSplMrg_RadioBtn_Merge=Merge
|
||||
tabSplMrg_Txt_File=File:
|
||||
tabSplMrg_Txt_Folder=Split file (folder):
|
||||
tabSplMrg_Btn_SelectFile=Select File
|
||||
tabSplMrg_Btn_SelectFolder=Select Folder
|
||||
tabSplMrg_Lbl_SaveToLocation=Save to:
|
||||
tabSplMrg_Btn_ChangeSaveToLocation=Change
|
||||
tabSplMrg_Btn_Convert=Convert
|
||||
windowTitleError=Error
|
||||
windowBodyPleaseFinishTransfersFirst=Unable to split/merge files when application USB/Network process active. Please interrupt active transfers first.
|
||||
done_txt=Done!
|
||||
failure_txt=Failed
|
||||
btn_Select=Select
|
||||
btn_InjectPayloader=Inject payload
|
||||
tabNXDT_Btn_Start=Start!
|
||||
tab2_Btn_InstallDrivers=Download and install drivers
|
||||
windowTitleDownloadDrivers=Download and install drivers
|
||||
windowBodyDownloadDrivers=Downloading drivers (libusbK v3.0.7.0)...
|
||||
btn_Cancel=Cancel
|
||||
btn_Close=Close
|
||||
tab2_Cb_GlVersion=GoldLeaf version
|
||||
tab2_Cb_GLshowNspOnly=Show only *.nsp in GoldLeaf.
|
||||
windowBodyPleaseStopOtherProcessFirst=Please stop other active process before continuing.
|
||||
tab2_Cb_foldersSelectorForRoms=Select folder with ROM files instead of selecting ROMs individually.
|
||||
tab2_Cb_foldersSelectorForRomsDesc=Changes 'Select files' button behaviour on 'Games' tab: instead of selecting ROM files one-by-one you can choose folder to add every supported file at once.
|
||||
windowTitleAddingFiles=Searching for files...
|
||||
windowBodyFilesScanned=Files scanned: %d\nWould be added: %d
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
tabRcm_Lbl_Payload=Payload:
|
|
@ -1,47 +1,81 @@
|
|||
btn_OpenFile=Seleccionar los archivos
|
||||
btn_OpenFile=Seleccionar archivos
|
||||
btn_OpenFolders=Seleccionar carpeta
|
||||
btn_Upload=Enviar a NS
|
||||
tab3_Txt_EnteredAsMsg1=Est\u00E1 conectado como:
|
||||
tab3_Txt_EnteredAsMsg2=Deber\u00EDa ser root o haber configurado las reglas 'udev' de este usuario para evitar problemas.
|
||||
tab3_Txt_FilesToUploadTitle=Archivos a subir:
|
||||
btn_OpenFolders_tooltip=Select a folder to be scanned.\nThis folder and all of its subfolders will be scanned.\nAll matching files will be added to the list.
|
||||
tab3_Txt_EnteredAsMsg1=Est\u00E1s conectado como:
|
||||
tab3_Txt_EnteredAsMsg2=Debes tener permisos root o haber configurado las reglas 'udev' de este usuario para evitar problemas.
|
||||
tab3_Txt_FilesToUploadTitle=Archivos a enviar:
|
||||
tab3_Txt_GreetingsMessage=Bienvenido a NS-USBloader
|
||||
tab3_Txt_NoFolderOrFileSelected=No ha seleccionado ning\u00FAn archivo: Nada se subir\u00E1.
|
||||
windowBodyConfirmExit=Transferencia de datos en progreso, cerrar la aplicaci\u00F3n lo interrumpir\u00E1.\nNo se recomienda.\nInterrumpir proceso y salir?
|
||||
windowTitleConfirmExit=No, no haga esto!
|
||||
tab3_Txt_NoFolderOrFileSelected=Ning\u00FAn archivo seleccionado: No se enviar\u00E1 nada.
|
||||
windowBodyConfirmExit=Se est\u00E1n transfiriendo archivos y cerrar la aplicaci\u00F3n lo interrumpir\u00E1.\nNo debes hacer esto.\n\u00BFInterrumpir el proceso y salir?
|
||||
windowTitleConfirmExit=\u00A1No hagas esto!
|
||||
btn_Stop=Interrumpir
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Estado
|
||||
tab1_table_Lbl_Status=Estatus
|
||||
tab1_table_Lbl_FileName=Nombre del archivo
|
||||
tab1_table_Lbl_Size=Tama\u00F1o
|
||||
tab1_table_Lbl_Upload=Enviar?
|
||||
tab1_table_contextMenu_Btn_BtnDelete=Eliminar
|
||||
tab1_table_contextMenu_Btn_DeleteAll=Eliminar todo
|
||||
tab1_table_Lbl_Upload=\u00BFEnviar?
|
||||
tab1_table_contextMenu_Btn_BtnDelete=Quitar
|
||||
tab1_table_contextMenu_Btn_DeleteAll=Quitar todos
|
||||
tab2_Lbl_HostIP=IP del host
|
||||
tab1_Lbl_NSIP=NS IP:
|
||||
tab2_Cb_ValidateNSHostName=Validar siempre la entrada de IP de la NS.
|
||||
windowBodyBadIp=Est\u00E1 seguro de que ha introducido la IP de la NS correctamente?
|
||||
windowTitleBadIp=Es posible que la direcci\u00F3n IP de la NS sea incorrecta
|
||||
tab2_Cb_ExpertMode=Modo Experto
|
||||
tab2_Lbl_HostPort=Puerto
|
||||
tab2_Cb_AutoDetectIp=Detectar IP autom\u00E1ticamente
|
||||
tab2_Cb_RandSelectPort=Obtener el puerto autom\u00E1ticamente
|
||||
tab2_Cb_DontServeRequests=No contestar solicitudes
|
||||
tab2_Lbl_DontServeRequestsDesc=Si habilita esta opci\u00F3n, el ordenador no responder\u00E1 solicitudes de archivos NSP de la NS (en la red), y usar\u00E1 las configuraciones definidas por el host para indicar a Awoo donde se encuentran los archivos
|
||||
tab2_Lbl_HostExtra=Extra
|
||||
windowTitleErrorPort=Puerto asignado incorrectamente!
|
||||
windowBodyErrorPort=El puerto no puede ser 0 o mayor que 65535
|
||||
tab2_Cb_AutoCheckForUpdates=Comprobar actualizaciones autom\u00E1ticamente
|
||||
windowTitleNewVersionAval=Actualizaci\u00F3n disponible
|
||||
windowTitleNewVersionNOTAval=No hay actualizaciones disponibles
|
||||
windowTitleNewVersionUnknown=No fue posible encontrar actualizaciones
|
||||
windowBodyNewVersionUnknown=Algo fall\u00F3\nLa conexi\u00F3n a internet no funciona correctamente, o GitHub est\u00E1 ca\u00EDdo
|
||||
tab1_Lbl_NSIP=IP del NS:
|
||||
tab2_Cb_ValidateNSHostName=Siempre verifica el IP del NS.
|
||||
windowBodyBadIp=\u00BFEst\u00E1s seguro que la direcci\u00F3n IP ingresada es la del NS?
|
||||
windowTitleBadIp=La IP del NS parece ser incorrecta.
|
||||
tab2_Cb_ExpertMode=Modo experto (NET setup)
|
||||
tab2_Lbl_HostPort=puerto
|
||||
tab2_Cb_AutoDetectIp=Detectar autom\u00E1ticamente la IP
|
||||
tab2_Cb_RandSelectPort=Obtener puerto aleatoriamente
|
||||
tab2_Cb_DontServeRequests=No responder solicitudes
|
||||
tab2_Lbl_DontServeRequestsDesc=Si se activa, esta computadora no responder\u00E1 a las solicitudes de archivos NSP provenientes del NS (en la red) y se usar\u00E1n las configuraciones definidas por el host para decirle a Awoo Installer (o aplicaciones compatibles) donde buscar por los archivos.
|
||||
tab2_Lbl_HostExtra=extra
|
||||
windowTitleErrorPort=\u00A1Puerto incorrecto!
|
||||
windowBodyErrorPort=\u00A1Puerto incorrecto!
|
||||
tab2_Cb_AutoCheckForUpdates=Buscar actualizaciones autom\u00E1ticamente
|
||||
windowTitleNewVersionAval=Nueva versi\u00F3n disponible
|
||||
windowTitleNewVersionNOTAval=No hay ninguna nueva versi\u00F3n disponible
|
||||
windowTitleNewVersionUnknown=No se pueden buscar actualizaciones
|
||||
windowBodyNewVersionUnknown=Algo sali\u00F3 mal\nQuiz\u00E1s no tienes conexi\u00F3n a internet, o GitHub est\u00E1 caido
|
||||
windowBodyNewVersionNOTAval=Est\u00E1s usando la \u00FAltima versi\u00F3n
|
||||
tab2_Cb_AllowXciNszXcz=Permite la selecci\u00F3n de archivos XCI / NSZ / XCZ para Awoo
|
||||
tab2_Lbl_AllowXciNszXczDesc=Usado por algunas aplicaciones de terceros que soportan XCI/NSZ/XCZ y que utilizan el protocolo de transferencia de Tinfoil. Si no est\u00E1 seguro no cambie la opci\u00F3n.
|
||||
tab2_Cb_AllowXciNszXcz=Permitir seleccionar archivos XCI / NSZ / XCZ en Awoo
|
||||
tab2_Lbl_AllowXciNszXczDesc=Usado por aplicaciones que soportan XCI/NSZ/XCZ y utilizan el protocolo de transferencia Awoo (Adubbz/TinFoil). No modificar si no est\u00E1s seguro. Habilitar para Awoo Installer.
|
||||
tab2_Lbl_Language=Idioma
|
||||
windowBodyRestartToApplyLang=Por favor, reinicie el programa para aplicar los cambios.
|
||||
tab2_Cb_GLshowNspOnly=Mostrar solo *.nsp en GoldLeaf.
|
||||
windowBodyRestartToApplyLang=Reinicia la aplicaci\u00F3n para aplicar los cambios.
|
||||
btn_OpenSplitFile=Seleccionar NSP en partes
|
||||
tab2_Lbl_ApplicationSettings=Ajustes principales
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Herramienta para dividir y fusionar archivos
|
||||
tabSplMrg_RadioBtn_Split=Dividir
|
||||
tabSplMrg_RadioBtn_Merge=Fusionar
|
||||
tabSplMrg_Txt_File=Archivo:
|
||||
tabSplMrg_Txt_Folder=Archivo dividido (carpeta):
|
||||
tabSplMrg_Btn_SelectFile=Seleccionar archivo
|
||||
tabSplMrg_Btn_SelectFolder=Seleccionar carpeta
|
||||
tabSplMrg_Lbl_SaveToLocation=Guardar en:
|
||||
tabSplMrg_Btn_ChangeSaveToLocation=Cambiar
|
||||
tabSplMrg_Btn_Convert=Convertir
|
||||
windowTitleError=Error
|
||||
windowBodyPleaseFinishTransfersFirst=No se pueden dividir/fusionar archivos mientras se est\u00E1 realizando otro proceso. Por favor, cancela las operaciones de transferencia activas primero.
|
||||
done_txt=\u00A1Listo!
|
||||
failure_txt=Error
|
||||
btn_Select=Seleccionar
|
||||
btn_InjectPayloader=Injectar payload
|
||||
tabNXDT_Btn_Start=\u00A1Iniciar!
|
||||
tab2_Btn_InstallDrivers=Descargar e instalar controladores
|
||||
windowTitleDownloadDrivers=Descargar e instalar controladores
|
||||
windowBodyDownloadDrivers=Descargando controladores (libusbK v3.0.7.0)...
|
||||
btn_Cancel=Cancelar
|
||||
|
||||
btn_Close=Cerrar
|
||||
tab2_Cb_GlVersion=Versi\u00F3n de GoldLeaf
|
||||
tab2_Cb_GLshowNspOnly=Mostrar solo *.nsp en GoldLeaf.
|
||||
windowBodyPleaseStopOtherProcessFirst=Det\u00E9n los dem\u00E1s procesos activos antes de continuar.
|
||||
tab2_Cb_foldersSelectorForRoms=Seleccionar una carpeta con archivos ROM en lugar de seleccionarlos individualmente.
|
||||
tab2_Cb_foldersSelectorForRomsDesc=Cambia el comportamiento del bot\u00F3n de 'Seleccionar archivos' en la pesta\u00F1a 'Juegos': en lugar de seleccionar archivos ROM uno por uno puedes seleccionar una carpeta para instalarlos todos a la vez.
|
||||
windowTitleAddingFiles=Buscando archivos...
|
||||
windowBodyFilesScanned=Archivos encontrados: %d\nSe a\u00F1adir\u00E1n: %d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo Installer y compatibles
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
btn_OpenFile=Selectionner les fichiers
|
||||
btn_OpenFile=S\u00E9l\u00E9ctionner les fichiers
|
||||
btn_OpenFolders=S\u00E9l\u00E9ctionner un dossier
|
||||
btn_Upload=Envoyer vers NS
|
||||
tab3_Txt_EnteredAsMsg1=Vous etes connect\u00E9 en tant que:
|
||||
btn_OpenFolders_tooltip=S\u00E9lectionnez un dossier \u00E0 analyser.\nCe dossier et tous ses sous-dossiers seront analys\u00E9s.\nTous les fichiers pertinents seront ajout\u00E9s à la liste.
|
||||
tab3_Txt_EnteredAsMsg1=Vous \u00EAtes connect\u00E9 en tant que :
|
||||
tab3_Txt_EnteredAsMsg2=Vous devez \u00EAtre root ou avoir configur\u00E9 les r\u00E8gles 'udev' pour cet utilisateur afin d'\u00E9viter tout probl\u00E8me.
|
||||
tab3_Txt_FilesToUploadTitle=Fichiers a envoyer:
|
||||
tab3_Txt_GreetingsMessage=Bienvenue sur NS-USBloader
|
||||
|
@ -9,20 +11,21 @@ windowBodyConfirmExit=Le transfert de donn\u00E9es est en cours et la fermeture
|
|||
windowTitleConfirmExit=Non, ne faites pas \u00E7a!
|
||||
btn_Stop=Interrompre
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source : https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror : https://github.com/developersu/ns-usbloader/\n\
|
||||
Site : https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Upload=Envoyer ?
|
||||
tab1_table_Lbl_Size=Taille
|
||||
tab1_table_Lbl_FileName=Nom de fichier
|
||||
tab1_table_Lbl_Status=Statut
|
||||
tab1_table_Lbl_FileName=Nom de fichier
|
||||
tab1_table_Lbl_Size=Taille
|
||||
tab1_table_Lbl_Upload=Envoyer ?
|
||||
tab1_table_contextMenu_Btn_BtnDelete=Supprimer
|
||||
tab1_table_contextMenu_Btn_DeleteAll=Supprimer tout
|
||||
tab2_Lbl_HostIP=IP de l'ordinateur
|
||||
tab1_Lbl_NSIP=IP de NS:
|
||||
tab2_Cb_ValidateNSHostName=Toujours v\u00E9rifier que l'adresse IP de NS entr\u00E9e est correcte
|
||||
windowTitleBadIp=L'adresse IP de NS est probablement incorrecte
|
||||
windowBodyBadIp=\u00CAtes-vous s\u00FBr que l'adresse IP de NS entr\u00E9e est correcte ?
|
||||
windowTitleBadIp=L'adresse IP de NS est probablement incorrecte
|
||||
tab2_Cb_ExpertMode=Mode expert
|
||||
tab2_Lbl_HostPort=port
|
||||
tab2_Cb_AutoDetectIp=D\u00E9tection automatique d'IP
|
||||
|
@ -36,11 +39,24 @@ tab2_Cb_AutoCheckForUpdates=V\u00E9rifier automatiquement les mises \u00E0 jour
|
|||
windowTitleNewVersionAval=Nouvelle version disponible
|
||||
windowTitleNewVersionNOTAval=Aucune nouvelle version disponible
|
||||
windowTitleNewVersionUnknown=Impossible de v\u00E9rifier les nouvelles versions
|
||||
windowBodyNewVersionNOTAval=Vous utilisez la derni\u00E8re version
|
||||
windowBodyNewVersionUnknown=Une erreur s'est produite\nPeut-\u00EAtre des probl\u00E8mes de connexion Internet ou GitHub est en panne
|
||||
windowBodyNewVersionNOTAval=Vous utilisez la derni\u00E8re version
|
||||
tab2_Cb_AllowXciNszXcz=Autoriser la s\u00E9lection de fichiers XCI / NSZ / XCZ pour Awoo
|
||||
tab2_Lbl_AllowXciNszXczDesc=Utilis\u00E9 par certaines applications tierces prenant en charge XCI/NSZ/XCZ et utilisant le protocole de transfert TinFoil. Ne changez pas en cas de doute.
|
||||
tab2_Lbl_Language=La langue
|
||||
tab2_Lbl_Language=Langue
|
||||
windowBodyRestartToApplyLang=Red\u00E9marrez l'application pour appliquer les modifications.
|
||||
btn_OpenSplitFile=S\u00E9lectionner un NSP divis\u00E9
|
||||
tab2_Lbl_ApplicationSettings=Param\u00E8tres principaux
|
||||
tabSplMrg_RadioBtn_Split=Diviser
|
||||
tabSplMrg_RadioBtn_Merge=Fusionner
|
||||
failure_txt=Erreur
|
||||
btn_Select=S\u00E9lectionner
|
||||
btn_InjectPayloader=Injecter le payload
|
||||
tab2_Btn_InstallDrivers=T\u00E9l\u00E9charger et installer les pilotes
|
||||
windowTitleDownloadDrivers=T\u00E9l\u00E9charger et installer les pilotes
|
||||
btn_Cancel=Annuler
|
||||
|
||||
btn_Close=Fermer
|
||||
tab2_Cb_GlVersion=Version de GoldLeaf
|
||||
tab2_Cb_GLshowNspOnly=N'afficher que les *.nsp dans GoldLeaf.
|
||||
tab2_Cb_foldersSelectorForRoms=S\u00E9lectionnez un dossier contenant des fichiers ROM plutôt que de les s\u00E9lectionner individuellement.
|
||||
|
||||
|
|
|
@ -11,8 +11,9 @@ windowBodyConfirmExit=Il trasferimento dei dati \u00E8 in corso e la chiusura de
|
|||
windowTitleConfirmExit=No, non farlo!
|
||||
btn_Stop=Interrompi
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Sorgenti: https://github.com/developersu/ns-usbloader/\n\
|
||||
Sito: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Sorgenti: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Sito: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Stato
|
||||
tab1_table_Lbl_FileName=Nome file
|
||||
|
@ -44,7 +45,7 @@ tab2_Cb_AllowXciNszXcz=Consenti la selezione di file XCI / NSZ / XCZ per Awoo
|
|||
tab2_Lbl_AllowXciNszXczDesc=Usato dalle applicazioni che supportano XCI/NSZ/XCZ ed utilizza il protocollo di trasferimento di Awoo (o Adubbz/TinFoil). Non cambiarlo se non sei sicuro. Attivalo per Awoo Installer.
|
||||
tab2_Lbl_Language=Lingua
|
||||
windowBodyRestartToApplyLang=Riavvia l'applicazione per applicare le modifiche.
|
||||
btn_OpenSplitFile=Seleziona NSP troncato
|
||||
btn_OpenSplitFile=Seleziona il file truncato
|
||||
tab2_Lbl_ApplicationSettings=Impostazioni principali
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Strumento tronca e unisci file
|
||||
tabSplMrg_RadioBtn_Split=Tronca
|
||||
|
@ -78,3 +79,4 @@ windowBodyFilesScanned=File scansionati: %d\nVerranno aggiunti: %d
|
|||
tab2_Lbl_AwooBlockTitle=Awoo Installer e compatibili
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
btn_OpenFile=\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E
|
||||
btn_OpenFolders=\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u9078\u629E
|
||||
btn_Upload=NS\u306B\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9
|
||||
btn_OpenFolders_tooltip=\u30B9\u30AD\u30E3\u30F3\u3059\u308B\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n\u3053\u306E\u30D5\u30A9\u30EB\u30C0\u3068\u305D\u306E\u3059\u3079\u3066\u306E\u30B5\u30D6\u30D5\u30A9\u30EB\u30C0\u304C\u30B9\u30AD\u30E3\u30F3\u3055\u308C\u307E\u3059\u3002\n\u4E00\u81F4\u3059\u308B\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u30EA\u30B9\u30C8\u306B\u8FFD\u52A0\u3055\u308C\u307E\u3059\u3002
|
||||
tab3_Txt_EnteredAsMsg1=\u3042\u306A\u305F\u306F\u6B21\u306E\u3088\u3046\u306B\u5165\u529B\u3055\u308C\u307E\u3057\u305F:
|
||||
tab3_Txt_EnteredAsMsg2=\u554F\u984C\u3092\u56DE\u907F\u3059\u308B\u306B\u306F\u3001root \u306B\u306A\u308B\u304B\u3001\u3053\u306E\u30E6\u30FC\u30B6\u30FC\u306B\u300Cudev\u300D\u30EB\u30FC\u30EB\u3092\u8A2D\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
|
||||
tab3_Txt_FilesToUploadTitle=\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3059\u308B\u30D5\u30A1\u30A4\u30EB:
|
||||
tab3_Txt_GreetingsMessage=NS-USBloader\u3078\u3088\u3046\u3053\u305D
|
||||
tab3_Txt_NoFolderOrFileSelected=\u30D5\u30A1\u30A4\u30EB\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093: \u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3059\u308B\u3082\u306E\u304C\u3042\u308A\u307E\u305B\u3093\u3002
|
||||
windowBodyConfirmExit=\u30C7\u30FC\u30BF\u8EE2\u9001\u304C\u9032\u884C\u4E2D\u3067\u3059\u3002\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u9589\u3058\u308B\u3068\u4E2D\u65AD\u3055\u308C\u307E\u3059\u3002\n\u6700\u60AA\u306E\u4E8B\u614B\u3067\u3059\u3002\n\u51E6\u7406\u3092\u4E2D\u65AD\u3057\u3066\u7D42\u4E86\u3057\u307E\u3059\u304B?
|
||||
windowTitleConfirmExit=\u3044\u3044\u3048\u3001\u3053\u308C\u3092\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\uFF01
|
||||
btn_Stop=\u5272\u308A\u8FBC\u307F
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=\u30B9\u30C6\u30FC\u30BF\u30B9
|
||||
tab1_table_Lbl_FileName=\u30D5\u30A1\u30A4\u30EB\u540D
|
||||
tab1_table_Lbl_Size=\u30B5\u30A4\u30BA
|
||||
tab1_table_Lbl_Upload=\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\uFF1F
|
||||
tab1_table_contextMenu_Btn_BtnDelete=\u524A\u9664\u3059\u308B
|
||||
tab1_table_contextMenu_Btn_DeleteAll=\u3059\u3079\u3066\u524A\u9664\u3059\u308B
|
||||
tab2_Lbl_HostIP=\u30DB\u30B9\u30C8 IP
|
||||
tab1_Lbl_NSIP=NS IP:
|
||||
tab2_Cb_ValidateNSHostName=NS IP \u5165\u529B\u3092\u5E38\u306B\u691C\u8A3C\u3057\u307E\u3059\u3002
|
||||
windowBodyBadIp=NS IP \u30A2\u30C9\u30EC\u30B9\u3092\u6B63\u3057\u304F\u5165\u529B\u3057\u307E\u3057\u305F\u304B?
|
||||
windowTitleBadIp=NS\u306EIP\u30A2\u30C9\u30EC\u30B9\u304C\u9593\u9055\u3063\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059
|
||||
tab2_Cb_ExpertMode=\u30A8\u30AD\u30B9\u30D1\u30FC\u30C8\u30E2\u30FC\u30C9 (NET \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7)
|
||||
tab2_Lbl_HostPort=\u30DD\u30FC\u30C8
|
||||
tab2_Cb_AutoDetectIp=IP\u306E\u81EA\u52D5\u691C\u51FA
|
||||
tab2_Cb_RandSelectPort=\u30E9\u30F3\u30C0\u30E0\u306B\u30DD\u30FC\u30C8\u3092\u53D6\u5F97
|
||||
tab2_Cb_DontServeRequests=\u30EA\u30AF\u30A8\u30B9\u30C8\u3092\u51E6\u7406\u3057\u306A\u3044
|
||||
tab2_Lbl_DontServeRequestsDesc=\u9078\u629E\u3059\u308B\u3068\u3001\u3053\u306E\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF\u306F NS (\u30CD\u30C3\u30C8\u7D4C\u7531) \u304B\u3089\u306E NSP \u30D5\u30A1\u30A4\u30EB\u8981\u6C42\u306B\u5FDC\u7B54\u305B\u305A\u3001\u5B9A\u7FA9\u3055\u308C\u305F\u30DB\u30B9\u30C8\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066 Awoo \u30A4\u30F3\u30B9\u30C8\u30FC\u30E9 (\u307E\u305F\u306F\u4E92\u63DB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3) \u306B\u30D5\u30A1\u30A4\u30EB\u3092\u63A2\u3059\u5834\u6240\u3092\u4F1D\u3048\u307E\u3059\u3002
|
||||
tab2_Lbl_HostExtra=\u30A8\u30AD\u30B9\u30C8\u30E9
|
||||
windowTitleErrorPort=\u30DD\u30FC\u30C8\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093!
|
||||
windowBodyErrorPort=\u30DD\u30FC\u30C8\u3092 0 \u307E\u305F\u306F 65535 \u3088\u308A\u5927\u304D\u304F\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002
|
||||
tab2_Cb_AutoCheckForUpdates=\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u306E\u81EA\u52D5\u30C1\u30A7\u30C3\u30AF
|
||||
windowTitleNewVersionAval=\u65B0\u3057\u3044\u30D0\u30FC\u30B8\u30E7\u30F3\u304C\u5229\u7528\u53EF\u80FD\u3067\u3059
|
||||
windowTitleNewVersionNOTAval=\u65B0\u3057\u3044\u30D0\u30FC\u30B8\u30E7\u30F3\u306F\u3042\u308A\u307E\u305B\u3093
|
||||
windowTitleNewVersionUnknown=\u65B0\u3057\u3044\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093
|
||||
windowBodyNewVersionUnknown=\u554F\u984C\u304C\u767A\u751F\u3057\u307E\u3057\u305F\n\u30A4\u30F3\u30BF\u30FC\u30CD\u30C3\u30C8\u304C\u5229\u7528\u3067\u304D\u306A\u3044\u304B\u3001GitHub\u304C\u30C0\u30A6\u30F3\u3057\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059
|
||||
windowBodyNewVersionNOTAval=\u6700\u65B0\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059
|
||||
tab2_Cb_AllowXciNszXcz=Awoo \u306E XCI / NSZ / XCZ \u30D5\u30A1\u30A4\u30EB\u306E\u9078\u629E\u3092\u8A31\u53EF
|
||||
tab2_Lbl_AllowXciNszXczDesc=XCI/NSZ/XCZ \u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3001Awoo (\u5225\u540D Adubbz/TinFoil) \u8EE2\u9001\u30D7\u30ED\u30C8\u30B3\u30EB\u3092\u5229\u7528\u3059\u308B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3067\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002 \u3088\u304F\u308F\u304B\u3089\u306A\u3044\u5834\u5408\u306F\u5909\u66F4\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002 Awoo \u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FC\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002
|
||||
tab2_Lbl_Language=\u8A00\u8A9E
|
||||
windowBodyRestartToApplyLang=\u5909\u66F4\u3092\u9069\u7528\u3059\u308B\u306B\u306F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u518D\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
||||
btn_OpenSplitFile=\u30B9\u30D7\u30EA\u30C3\u30C8ROM\u3092\u9078\u629E
|
||||
tab2_Lbl_ApplicationSettings=\u4E3B\u306A\u8A2D\u5B9A
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=\u30D5\u30A1\u30A4\u30EB\u306E\u5206\u5272\u3068\u7D50\u5408\u30C4\u30FC\u30EB
|
||||
tabSplMrg_RadioBtn_Split=\u30D5\u30A1\u30A4\u30EB\u306E\u5206\u5272\u3068\u7D50\u5408\u30C4\u30FC\u30EB
|
||||
tabSplMrg_RadioBtn_Merge=\u30DE\u30FC\u30B8
|
||||
tabSplMrg_Txt_File=\u30D5\u30A1\u30A4\u30EB\uFF1A
|
||||
tabSplMrg_Txt_Folder=\u5206\u5272\u30D5\u30A1\u30A4\u30EB (\u30D5\u30A9\u30EB\u30C0\u30FC):
|
||||
tabSplMrg_Btn_SelectFile=\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u3076
|
||||
tabSplMrg_Btn_SelectFolder=\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u9078\u629E
|
||||
tabSplMrg_Lbl_SaveToLocation=\u306B\u4FDD\u5B58\uFF1A
|
||||
tabSplMrg_Btn_ChangeSaveToLocation=\u5909\u5316\u3059\u308B
|
||||
tabSplMrg_Btn_Convert=\u5909\u63DB
|
||||
windowTitleError=\u30A8\u30E9\u30FC
|
||||
windowBodyPleaseFinishTransfersFirst=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3 USB/\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF \u30D7\u30ED\u30BB\u30B9\u304C\u30A2\u30AF\u30C6\u30A3\u30D6\u306A\u5834\u5408\u3001\u30D5\u30A1\u30A4\u30EB\u3092\u5206\u5272/\u30DE\u30FC\u30B8\u3067\u304D\u307E\u305B\u3093\u3002 \u6700\u521D\u306B\u30A2\u30AF\u30C6\u30A3\u30D6\u306A\u8EE2\u9001\u3092\u4E2D\u65AD\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
||||
done_txt=\u7D42\u308F\u308A\uFF01
|
||||
failure_txt=\u5931\u6557
|
||||
btn_Select=\u9078\u629E\u3059\u308B
|
||||
btn_InjectPayloader=\u30DA\u30A4\u30ED\u30FC\u30C9\u3092\u633F\u5165\u3059\u308B
|
||||
tabNXDT_Btn_Start=\u59CB\u3081\u308B\uFF01
|
||||
tab2_Btn_InstallDrivers=\u30C9\u30E9\u30A4\u30D0\u30FC\u306E\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3068\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB
|
||||
windowTitleDownloadDrivers=\u30C9\u30E9\u30A4\u30D0\u30FC\u306E\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3068\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB
|
||||
windowBodyDownloadDrivers=\u30C9\u30E9\u30A4\u30D0\u30FC\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u3066\u3044\u307E\u3059 (libusbK v3.0.7.0)...
|
||||
btn_Cancel=\u30AD\u30E3\u30F3\u30BB\u30EB
|
||||
btn_Close=\u9589\u3058\u308B
|
||||
tab2_Cb_GlVersion=GoldLeaf\u30D0\u30FC\u30B8\u30E7\u30F3
|
||||
tab2_Cb_GLshowNspOnly=GoldLeaf\u3067 *.nsp \u306E\u307F\u3092\u8868\u793A\u3057\u307E\u3059\u3002
|
||||
windowBodyPleaseStopOtherProcessFirst=\u7D9A\u884C\u3059\u308B\u524D\u306B\u3001\u4ED6\u306E\u30A2\u30AF\u30C6\u30A3\u30D6\u306A\u30D7\u30ED\u30BB\u30B9\u3092\u505C\u6B62\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
||||
tab2_Cb_foldersSelectorForRoms=ROM \u3092\u500B\u5225\u306B\u9078\u629E\u3059\u308B\u306E\u3067\u306F\u306A\u304F\u3001ROM \u30D5\u30A1\u30A4\u30EB\u306E\u3042\u308B\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u629E\u3057\u307E\u3059\u3002
|
||||
tab2_Cb_foldersSelectorForRomsDesc=[\u30B2\u30FC\u30E0] \u30BF\u30D6\u306E [\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E] \u30DC\u30BF\u30F3\u306E\u52D5\u4F5C\u3092\u5909\u66F4: ROM \u30D5\u30A1\u30A4\u30EB\u3092 1 \u3064\u305A\u3064\u9078\u629E\u3059\u308B\u4EE3\u308F\u308A\u306B\u3001\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u9078\u629E\u3057\u3066\u3001\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u308B\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u4E00\u5EA6\u306B\u8FFD\u52A0\u3067\u304D\u307E\u3059\u3002
|
||||
windowTitleAddingFiles=\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3057\u3066\u3044\u307E\u3059...
|
||||
windowBodyFilesScanned=\u30B9\u30AD\u30E3\u30F3\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB: %d\n\u8FFD\u52A0\u4E88\u5B9A: %d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FC\u3068\u4E92\u63DB\u6027
|
||||
tabRcm_Lbl_Payload=\u30DA\u30A4\u30ED\u30FC\u30C9\uFF1A
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
btn_OpenFile=\u30D5\u30A1\u30A4\u30EB\u9078\u629E
|
||||
btn_OpenFolders=\u30D5\u30A9\u30EB\u30C0\u30FC\u9078\u629E
|
||||
btn_Upload=NS\u3093\u304B\u3044\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9
|
||||
btn_OpenFolders_tooltip=\u30B9\u30AD\u30E3\u30F3\u3059\u308B\u30D5\u30A9\u30EB\u30C0\u9078\u629E\u3057\u304F\u3043\u307F\u305D\u30FC\u308C\u30FC\u3002\n\u304F\u306C\u30D5\u30A9\u30EB\u30C0\u3068\u3045\u3046\u306C\u307E\u3058\u308A\u306C\u30B5\u30D6\u30D5\u30A9\u30EB\u30C0\u306C\u30B9\u30AD\u30E3\u30F3\u3055\u308A\u3084\u3073\u30FC\u3093\u3002\n\u4E00\u81F4\u3059\u308B\u307E\u3058\u308A\u306C\u30D5\u30A1\u30A4\u30EB\u306C\u30EA\u30B9\u30C8\u3093\u304B\u3044\u3044\u308A\u3057\u30FC\u3089\u308A\u3084\u3073\u30FC\u3093\u3002
|
||||
tab3_Txt_EnteredAsMsg1=\u3046\u3093\u3058\u3087\u30FC\u6B21\u306C\u3050\u3068\u3045\u5165\u529B\u3055\u308A\u3084\u3073\u305F\u3093:
|
||||
tab3_Txt_EnteredAsMsg2=\u554F\u984C\u56DE\u907F\u3059\u3093\u304C\u30FC\u3001root \u306A\u3044\u304C\u3001\u304F\u306C\u30E6\u30FC\u30B6\u30FC\u3093\u304B\u3044\u300Cudev\u300D\u30EB\u30FC\u30EB\u8A2D\u5B9A\u3059\u308B\u3044\u308A\u3086\u30FC\u306C\u3042\u3044\u3073\u30FC\u3093\u3002
|
||||
tab3_Txt_FilesToUploadTitle=\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3059\u308B\u30D5\u30A1\u30A4\u30EB:
|
||||
tab3_Txt_GreetingsMessage=NS-USBloader\u3093\u304B\u3044\u3081\u3093\u305D\u30FC\u308C\u30FC
|
||||
tab3_Txt_NoFolderOrFileSelected=\u30D5\u30A1\u30A4\u30EB\u306C\u9078\u629E\u3055\u308A\u3084\u3073\u3089\u3093: \u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3059\u3057\u304C\u3042\u3044\u3073\u3089\u3093\u3002
|
||||
windowBodyConfirmExit=\u30C7\u30FC\u30BF\u8EE2\u9001\u306C\u9032\u884C\u4E2D\u3084\u3044\u3073\u30FC\u3093\u3002\u304F\u306C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u304F\u30FC\u3044\u3093\u3067\u3043\u4E2D\u65AD\u3055\u308A\u3084\u3073\u30FC\u3093\u3002\n\u6700\u60AA\u306C\u4E8B\u614B\u3084\u3044\u3073\u30FC\u3093\u3002\n\u51E6\u7406\u4E2D\u65AD\u3057\u7D42\u4E86\u3055\u3073\u30FC\u304C?
|
||||
windowTitleConfirmExit=\u3046\u3045\u30FC\u3046\u3045\u30FC\u3001\u304F\u308A\u3055\u3093\u3050\u30FC\u3068\u3045\u30FC\u304F\u3043\u307F\u305D\u30FC\u308C\u30FC\uFF01
|
||||
btn_Stop=\u5272\u308A\u8FBC\u307F
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=\u30B9\u30C6\u30FC\u30BF\u30B9
|
||||
tab1_table_Lbl_FileName=\u30D5\u30A1\u30A4\u30EB\u540D
|
||||
tab1_table_Lbl_Size=\u30B5\u30A4\u30BA
|
||||
tab1_table_Lbl_Upload=\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\uFF1F
|
||||
tab1_table_contextMenu_Btn_BtnDelete=\u524A\u9664\u3059\u3093
|
||||
tab1_table_contextMenu_Btn_DeleteAll=\u307E\u3058\u308A\u524A\u9664\u3059\u3093
|
||||
tab2_Lbl_HostIP=\u30DB\u30B9\u30C8 IP
|
||||
tab1_Lbl_NSIP=NS IP:
|
||||
tab2_Cb_ValidateNSHostName=NS IP \u5165\u529B\u5E38\u306B\u691C\u8A3C\u3055\u3073\u30FC\u3093\u3002
|
||||
windowBodyBadIp=NS IP \u30A2\u30C9\u30EC\u30B9\u6B63\u3057\u304F\u5165\u529B\u3055\u3073\u305F\u304C?
|
||||
windowTitleBadIp=NS\u306CIP\u30A2\u30C9\u30EC\u30B9\u306C\u3070\u3063\u307A\u30FC\u3068\u30FC\u308B\u53EF\u80FD\u6027\u304C\u3042\u3044\u3073\u30FC\u3093
|
||||
tab2_Cb_ExpertMode=\u30A8\u30AD\u30B9\u30D1\u30FC\u30C8\u30E2\u30FC\u30C9 (NET \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7)
|
||||
tab2_Lbl_HostPort=\u30DD\u30FC\u30C8
|
||||
tab2_Cb_AutoDetectIp=IP\u306C\u81EA\u52D5\u691C\u51FA
|
||||
tab2_Cb_RandSelectPort=\u30E9\u30F3\u30C0\u30E0\u3093\u304B\u3044\u30DD\u30FC\u30C8\u53D6\u5F97
|
||||
tab2_Cb_DontServeRequests=\u30EA\u30AF\u30A8\u30B9\u30C8\u51E6\u7406\u3055\u3093
|
||||
tab2_Lbl_DontServeRequestsDesc=\u9078\u629E\u3057\u30FC\u306D\u30FC\u3001\u304F\u306C\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF\u30FC NS (\u30CD\u30C3\u30C8\u7D4C\u7531) \u304B\u3089\u306C NSP \u30D5\u30A1\u30A4\u30EB\u8981\u6C42\u3093\u304B\u3044\u5FDC\u7B54\u3055\u3058\u3001\u5B9A\u7FA9\u3055\u3063\u305F\u308B\u30DB\u30B9\u30C8\u8A2D\u5B9A\u4F7F\u7528\u3057 Awoo \u30A4\u30F3\u30B9\u30C8\u30FC\u30E9 (\u3042\u3089\u3093\u3067\u3043\u4E92\u63DB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3) \u3093\u304B\u3044\u30D5\u30A1\u30A4\u30EB\u304B\u3081\u30FC\u3044\u308B\u3070\u3059\u3061\u3066\u30FC\u3084\u3073\u30FC\u3093\u3002
|
||||
tab2_Lbl_HostExtra=\u30A8\u30AD\u30B9\u30C8\u30E9
|
||||
windowTitleErrorPort=\u30DD\u30FC\u30C8\u306C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308A\u3084\u3073\u3089\u3093!
|
||||
windowBodyErrorPort=\u30DD\u30FC\u30C8 0 \u3042\u3089\u3093\u3067\u3043 65535 \u3086\u308A\u307E\u304E\u304F\u3059\u3057\u3047\u30FC\u306A\u3084\u3073\u3089\u3093\u3002
|
||||
tab2_Cb_AutoCheckForUpdates=\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u306C\u81EA\u52D5\u30C1\u30A7\u30C3\u30AF
|
||||
windowTitleNewVersionAval=\u307F\u30FC\u3055\u308B\u30D0\u30FC\u30B8\u30E7\u30F3\u306C\u5229\u7528\u53EF\u80FD\u3084\u3044\u3073\u30FC\u3093
|
||||
windowTitleNewVersionNOTAval=\u307F\u30FC\u3055\u308B\u30D0\u30FC\u30B8\u30E7\u30F3\u30FC\u3042\u3044\u3073\u3089\u3093
|
||||
windowTitleNewVersionUnknown=\u307F\u30FC\u3055\u308B\u30D0\u30FC\u30B8\u30E7\u30F3\u78BA\u8A8D\u306A\u3084\u3073\u3089\u3093
|
||||
windowBodyNewVersionUnknown=\u554F\u984C\u304C\u767A\u751F\u3055\u3073\u305F\u3093\n\u30A4\u30F3\u30BF\u30FC\u30CD\u30C3\u30C8\u306C\u5229\u7528\u306A\u3089\u3093\u304C\u3001GitHub\u304C\u30C0\u30A6\u30F3\u305D\u30FC\u308B\u53EF\u80FD\u6027\u304C\u3042\u3044\u3073\u30FC\u3093
|
||||
windowBodyNewVersionNOTAval=\u6700\u65B0\u30D0\u30FC\u30B8\u30E7\u30F3\u4F7F\u7528\u305D\u30FC\u3044\u3073\u30FC\u3093
|
||||
tab2_Cb_AllowXciNszXcz=Awoo \u306C XCI / NSZ / XCZ \u30D5\u30A1\u30A4\u30EB\u306C\u9078\u629E\u8A31\u53EF
|
||||
tab2_Lbl_AllowXciNszXczDesc=XCI/NSZ/XCZ \u30B5\u30DD\u30FC\u30C8\u3057\u30FC\u3001Awoo (\u5225\u540D Adubbz/TinFoil) \u8EE2\u9001\u30D7\u30ED\u30C8\u30B3\u30EB\u5229\u7528\u3059\u308B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3063\u3057\u4F7F\u7528\u3055\u308A\u3084\u3073\u30FC\u3093\u3002 \u3086\u30FC\u308F\u304B\u3089\u3093\u3070\u30FC\u3084\u5909\u66F4\u3055\u3093\u3050\u30FC\u3068\u3045\u30FC\u304F\u3043\u307F\u305D\u30FC\u308C\u30FC\u3002 Awoo \u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FC\u6709\u52B9\u306A\u3055\u3073\u30FC\u3093\u3002
|
||||
tab2_Lbl_Language=\u8A00\u8A9E
|
||||
windowBodyRestartToApplyLang=\u5909\u66F4\u9069\u7528\u3059\u3093\u304C\u30FC\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u518D\u8D77\u52D5\u3057\u304F\u3043\u307F\u305D\u30FC\u308C\u30FC\u3002
|
||||
btn_OpenSplitFile=\u30B9\u30D7\u30EA\u30C3\u30C8ROM\u9078\u629E
|
||||
tab2_Lbl_ApplicationSettings=\u4E3B\u306A\u8A2D\u5B9A
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=\u30D5\u30A1\u30A4\u30EB\u306C\u5206\u5272\u3068\u3045\u7D50\u5408\u30C4\u30FC\u30EB
|
||||
tabSplMrg_RadioBtn_Split=\u30D5\u30A1\u30A4\u30EB\u306C\u5206\u5272\u3068\u3045\u7D50\u5408\u30C4\u30FC\u30EB
|
||||
tabSplMrg_RadioBtn_Merge=\u30DE\u30FC\u30B8
|
||||
tabSplMrg_Txt_File=\u30D5\u30A1\u30A4\u30EB\uFF1A
|
||||
tabSplMrg_Txt_Folder=\u5206\u5272\u30D5\u30A1\u30A4\u30EB (\u30D5\u30A9\u30EB\u30C0\u30FC):
|
||||
tabSplMrg_Btn_SelectFile=\u30D5\u30A1\u30A4\u30EB\u3044\u3089\u3076\u3093
|
||||
tabSplMrg_Btn_SelectFolder=\u30D5\u30A9\u30EB\u30C0\u30FC\u9078\u629E
|
||||
tabSplMrg_Lbl_SaveToLocation=\u3093\u304B\u3044\u4FDD\u5B58\uFF1A
|
||||
tabSplMrg_Btn_ChangeSaveToLocation=\u5909\u308F\u3044\u3093
|
||||
tabSplMrg_Btn_Convert=\u5909\u63DB
|
||||
windowTitleError=\u30A8\u30E9\u30FC
|
||||
windowBodyPleaseFinishTransfersFirst=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3 USB/\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF \u30D7\u30ED\u30BB\u30B9\u306C\u30A2\u30AF\u30C6\u30A3\u30D6\u306A\u3070\u30FC\u3001\u30D5\u30A1\u30A4\u30EB\u5206\u5272/\u30DE\u30FC\u30B8\u306A\u3084\u3073\u3089\u3093\u3002 \u6700\u521D\u3093\u304B\u3044\u30A2\u30AF\u30C6\u30A3\u30D6\u306A\u8EE2\u9001\u4E2D\u65AD\u3057\u304F\u3043\u307F\u305D\u30FC\u308C\u30FC\u3002
|
||||
done_txt=\u3046\u308F\u3044\uFF01
|
||||
failure_txt=\u5931\u6557
|
||||
btn_Select=\u9078\u629E\u3059\u3093
|
||||
btn_InjectPayloader=\u30DA\u30A4\u30ED\u30FC\u30C9\u633F\u5165\u3059\u3093
|
||||
tabNXDT_Btn_Start=\u59CB\u307F\u30FC\u3093\uFF01
|
||||
tab2_Btn_InstallDrivers=\u30C9\u30E9\u30A4\u30D0\u30FC\u306C\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3068\u3045\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB
|
||||
windowTitleDownloadDrivers=\u30C9\u30E9\u30A4\u30D0\u30FC\u306C\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3068\u3045\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB
|
||||
windowBodyDownloadDrivers=\u30C9\u30E9\u30A4\u30D0\u30FC\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u305D\u30FC\u3044\u3073\u30FC\u3093 (libusbK v3.0.7.0)...
|
||||
btn_Cancel=\u30AD\u30E3\u30F3\u30BB\u30EB
|
||||
btn_Close=\u304F\u30FC\u3044\u3093
|
||||
tab2_Cb_GlVersion=Gold Leaf\u30D0\u30FC\u30B8\u30E7\u30F3
|
||||
tab2_Cb_GLshowNspOnly=GoldLeaf\u3067\u3043 *.nsp \u306C\u307F\u8868\u793A\u3055\u3073\u30FC\u3093\u3002
|
||||
windowBodyPleaseStopOtherProcessFirst=\u884C\u3059\u308B\u524D\u306B\u3001\u4ED6\u306C\u30A2\u30AF\u30C6\u30A3\u30D6\u306A\u30D7\u30ED\u30BB\u30B9\u505C\u6B62\u3057\u304F\u3043\u307F\u305D\u30FC\u308C\u30FC\u3002
|
||||
tab2_Cb_foldersSelectorForRoms=ROM \u500B\u5225\u306B\u9078\u629E\u3059\u308B\u306C\u3067\u30FC\u306A\u304F\u3001ROM \u30D5\u30A1\u30A4\u30EB\u306C\u3042\u308B\u30D5\u30A9\u30EB\u30C0\u9078\u629E\u3055\u3073\u30FC\u3093\u3002
|
||||
tab2_Cb_foldersSelectorForRomsDesc=[\u30B2\u30FC\u30E0] \u30BF\u30D6\u306C [\u30D5\u30A1\u30A4\u30EB\u9078\u629E] \u30DC\u30BF\u30F3\u306C\u52D5\u4F5C\u5909\u66F4: ROM \u30D5\u30A1\u30A4\u30EB 1 \u3061\u306A\u30FC\u9078\u629E\u3059\u308B\u4EE3\u308F\u308A\u3093\u304B\u3044\u3001\u30D5\u30A9\u30EB\u30C0\u30FC\u9078\u629E\u3057\u3001\u30B5\u30DD\u30FC\u30C8\u3055\u308A\u3068\u30FC\u308B\u307E\u3058\u308A\u306C\u30D5\u30A1\u30A4\u30EB\u4E00\u5EA6\u3093\u304B\u3044\u8FFD\u52A0\u306A\u3084\u3073\u30FC\u3093\u3002
|
||||
windowTitleAddingFiles=\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u305D\u30FC\u3044\u3073\u30FC\u3093...
|
||||
windowBodyFilesScanned=\u30B9\u30AD\u30E3\u30F3\u3055\u3063\u305F\u308B\u30D5\u30A1\u30A4\u30EB: %d\n\u8FFD\u52A0\u4E88\u5B9A: %d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FC\u3068\u3045\u4E92\u63DB\u6027
|
||||
tabRcm_Lbl_Payload=\u30DA\u30A4\u30ED\u30FC\u30C9\uFF1A
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
|
@ -1,22 +1,24 @@
|
|||
btn_OpenFile=\uD30C\uC77C \uC120\uD0DD
|
||||
btn_OpenFolders=\uD30C\uC77C \uC120\uD0DD
|
||||
btn_OpenFolders=\uD30C\uC77C \uC120\uD0DD
|
||||
btn_Upload=NS\uC5D0 \uC5C5\uB85C\uB4DC
|
||||
btn_OpenFolders_tooltip=\uC2A4\uCE94\uD560 \uD3F4\uB354\uB97C \uC120\uD0DD\uD569\uB2C8\uB2E4.\n\uC774 \uD3F4\uB354\uC640 \uBAA8\uB4E0 \uD558\uC704 \uD3F4\uB354\uAC00 \uAC80\uC0C9\uB429\uB2C8\uB2E4.\n\uC77C\uCE58\uD558\uB294 \uBAA8\uB4E0 \uD30C\uC77C\uC774 \uBAA9\uB85D\uC5D0 \uCD94\uAC00\uB429\uB2C8\uB2E4.
|
||||
tab3_Txt_EnteredAsMsg1=\uB2E4\uC74C\uACFC \uAC19\uC774 \uC785\uB825\uB418\uC5C8\uC2B5\uB2C8\uB2E4:
|
||||
tab3_Txt_EnteredAsMsg2=\uBB38\uC81C\uB97C \uBC29\uC9C0\uD558\uB824\uBA74 \uC774 \uC0AC\uC6A9\uC790\uC5D0 \uB300\uD574 \uB8E8\uD2B8\uC774\uAC70\uB098 'udev'\uADDC\uCE59\uC744 \uAD6C\uC131\uD574\uC57C \uD569\uB2C8\uB2E4.
|
||||
tab3_Txt_FilesToUploadTitle=\uC5C5\uB85C\uB4DC \uD560 \uD30C\uC77C:
|
||||
tab3_Txt_GreetingsMessage=NS-USBloader\uC5D0 \uC624\uC2E0 \uAC83\uC744 \uD658\uC601\uD569\uB2C8\uB2E4
|
||||
tab3_Txt_GreetingsMessage=NS-USB\uB85C\uB354\uC5D0 \uC624\uC2E0 \uAC83\uC744 \uD658\uC601\uD569\uB2C8\uB2E4.
|
||||
tab3_Txt_NoFolderOrFileSelected=\uC120\uD0DD\uD55C \uD30C\uC77C \uC5C6\uC74C: \uC5C5\uB85C\uB4DC \uD560 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
windowBodyConfirmExit=\uB370\uC774\uD130 \uC804\uC1A1\uC774 \uC9C4\uD589 \uC911\uC774\uBA70 \uC774 \uC751\uC6A9 \uD504\uB85C\uADF8\uB7A8\uC744 \uB2EB\uC73C\uBA74 \uC911\uB2E8\uB429\uB2C8\uB2E4.\n\uC9C0\uAE08 \uD560 \uC218 \uC788\uB294 \uAC83\uC740 \uB354 \uB098\uC05C \uC77C\uC785\uB2C8\uB2E4.\n\uD504\uB85C\uC138\uC2A4\uB97C \uC911\uB2E8\uD558\uACE0 \uC885\uB8CC\uD558\uACA0\uC2B5\uB2C8\uAE4C?
|
||||
windowTitleConfirmExit=\uC544\uB2C8\uC624, \uC774\uAC83\uC740 \uD558\uC9C0\uB9C8\uC138\uC694!
|
||||
btn_Stop=\uC911\uB2E8
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=\uC0C1\uD0DC
|
||||
tab1_table_Lbl_FileName=\uD30C\uC77C \uC774\uB984
|
||||
tab1_table_Lbl_Size=\uD06C\uAE30
|
||||
tab1_table_Lbl_Upload=\uC5C5\uB85C\uB4DC\uD569\uB2C8\uAE4C?
|
||||
tab1_table_Lbl_Upload=\uC5C5\uB85C\uB4DC?
|
||||
tab1_table_contextMenu_Btn_BtnDelete=\uC0AD\uC81C
|
||||
tab1_table_contextMenu_Btn_DeleteAll=\uBAA8\uB450 \uC0AD\uC81C
|
||||
tab2_Lbl_HostIP=\uD638\uC2A4\uD2B8 IP
|
||||
|
@ -43,7 +45,7 @@ tab2_Cb_AllowXciNszXcz=Awoo \uC6A9 XCI / NSZ / XCZ \uD30C\uC77C \uC120\uD0DD \uD
|
|||
tab2_Lbl_AllowXciNszXczDesc=XCI / NSZ / XCZ\uB97C \uC9C0\uC6D0\uD558\uACE0 Tinfoil \uC804\uC1A1 \uD504\uB85C\uD1A0\uCF5C\uC744 \uD65C\uC6A9\uD558\uB294 \uC560\uD50C\uB9AC\uCF00\uC774\uC158\uC5D0\uC11C \uC0AC\uC6A9\uB429\uB2C8\uB2E4. \uD655\uC2E4\uD558\uC9C0 \uC54A\uC740 \uACBD\uC6B0 \uBCC0\uACBD\uD558\uC9C0 \uB9C8\uC2ED\uC2DC\uC624. Awoo \uC124\uCE58 \uD504\uB85C\uADF8\uB7A8\uC5D0 \uB300\uD574 \uD65C\uC131\uD654\uD569\uB2C8\uB2E4.
|
||||
tab2_Lbl_Language=\uC5B8\uC5B4
|
||||
windowBodyRestartToApplyLang=\uBCC0\uACBD \uC0AC\uD56D\uC744 \uC801\uC6A9\uD558\uB824\uBA74 \uC751\uC6A9 \uD504\uB85C\uADF8\uB7A8\uC744 \uB2E4\uC2DC \uC2DC\uC791\uD558\uC2ED\uC2DC\uC624.
|
||||
btn_OpenSplitFile=\uBD84\uD560 NSP \uC120\uD0DD
|
||||
btn_OpenSplitFile=\uBD84\uD560 ROM \uC120\uD0DD
|
||||
tab2_Lbl_ApplicationSettings=\uC8FC\uC694 \uC124\uC815
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=\uD30C\uC77C \uBD84\uD560 & \uBCD1\uD569 \uB3C4\uAD6C
|
||||
tabSplMrg_RadioBtn_Split=\uBD84\uD560
|
||||
|
@ -74,3 +76,18 @@ tab2_Cb_foldersSelectorForRoms=ROM\uC744 \uAC1C\uBCC4\uC801\uC73C\uB85C \uC120\u
|
|||
tab2_Cb_foldersSelectorForRomsDesc='\uAC8C\uC784' \uD0ED\uC5D0\uC11C '\uD30C\uC77C \uC120\uD0DD' \uBC84\uD2BC \uB3D9\uC791 \uBCC0\uACBD: ROM \uD30C\uC77C\uC744 \uD558\uB098\uC529 \uC120\uD0DD\uD558\uB294 \uB300\uC2E0 \uD3F4\uB354\uB97C \uC120\uD0DD\uD558\uC5EC \uC9C0\uC6D0\uB418\uB294 \uBAA8\uB4E0 \uD30C\uC77C\uC744 \uD55C \uBC88\uC5D0 \uCD94\uAC00 \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.
|
||||
windowTitleAddingFiles=\uD30C\uC77C \uAC80\uC0C9 \uC911...
|
||||
windowBodyFilesScanned=\uC2A4\uCE94 \uB41C \uD30C\uC77C: %d\n\uCD94\uAC00 \uB420 \uAC83: %d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo \uC124\uCE58 \uD504\uB85C\uADF8\uB7A8\uACFC \uD638\uD658\uC131
|
||||
tabRcm_Lbl_Payload=\uD398\uC774\uB85C\uB4DC:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
tabPatches_Lbl_Firmware=\uD38C\uC6E8\uC5B4:
|
||||
tabPatches_Lbl_Atmo=Atmosphere:
|
||||
tabPatches_Btn_fromFolder=\uD3F4\uB354\uC5D0\uC11C
|
||||
tabPatches_Btn_asZipFile=ZIP \uD30C\uC77C\uB85C
|
||||
tabPatches_Lbl_Title=\uD328\uCE58
|
||||
tabPatches_Lbl_Keys=\uD0A4:
|
||||
tabPatches_Btn_MakeEs=ES \uB9CC\uB4E4\uAE30
|
||||
tabPatches_Btn_MakeFs=FS \uB9CC\uB4E4\uAE30
|
||||
tabPatches_Btn_MakeAtmo=\uB85C\uB354 \uB9CC\uB4E4\uAE30 (Atmosphere)
|
||||
tabPatches_Btn_MakeAll=\uBAA8\uB450 \uB9CC\uB4E4\uAE30
|
||||
tabPatches_ServiceWindowMessageEsFs=\uD38C\uC6E8\uC5B4\uC640 \uD0A4 \uBAA8\uB450 \uD328\uCE58\uB97C \uC0DD\uC131\uD558\uB3C4\uB85D \uC124\uC815\uD574\uC57C \uD569\uB2C8\uB2E4. \uADF8\uB807\uC9C0 \uC54A\uC73C\uBA74 \uBB34\uC5C7\uC744 \uD328\uCE58\uD560\uC9C0 \uBA85\uD655\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
tabPatches_ServiceWindowMessageLoader='\uB85C\uB354' \uD328\uCE58\uB97C \uC0DD\uC131\uD558\uB824\uBA74 Atmosphere \uD3F4\uB354\uB97C \uC815\uC758\uD574\uC57C \uD569\uB2C8\uB2E4.
|
||||
|
|
|
@ -9,8 +9,9 @@ windowBodyConfirmExit=Transfer\u00EAncia de dados em progresso: Fechar ir\u00E1
|
|||
windowTitleConfirmExit=N\u00E3o, n\u00E3o fa\u00E7a isso!
|
||||
btn_Stop=Interromper!
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Fonte: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Fonte: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Status
|
||||
tab1_table_Lbl_FileName=Nome do Arquivo
|
||||
|
@ -42,7 +43,7 @@ tab2_Cb_AllowXciNszXcz=permitir arquivos XCI / NSZ / XCZ para o awoo
|
|||
tab2_Lbl_AllowXciNszXczDesc=Usado por aplica\u00E7\u00F5es que suportam XCI/NSZ/XCZ e utiliza protocolos de transfer\u00EAncia do Tinfoil. N\u00E3o mude o que n\u00E3o tem certeza. Ative para uso com o Awoo-Installer.
|
||||
tab2_Lbl_Language=Idioma
|
||||
windowBodyRestartToApplyLang=Por favor, reinicie para aplicar as modifica\u00E7\u00F5es.
|
||||
btn_OpenSplitFile=Select split NSP
|
||||
btn_OpenSplitFile=Select split file
|
||||
tab2_Lbl_ApplicationSettings=Configura\u00E7\u00F5es principais
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Ferramenta de Fragmentar (Split) & Mesclar (Merge) arquivos
|
||||
tabSplMrg_RadioBtn_Split=Fragmentar (Dividir)
|
||||
|
@ -69,3 +70,4 @@ btn_Close=Fechar
|
|||
tab2_Cb_GlVersion=Vers\u00E3o do GoldLeaf
|
||||
tab2_Cb_GLshowNspOnly=Mostrar apenas *.nsp no GoldLeaf.
|
||||
windowBodyPleaseStopOtherProcessFirst=Por favor, pare outros processos ativos antes de prosseguir
|
||||
|
||||
|
|
|
@ -11,8 +11,9 @@ windowBodyConfirmExit=Transferul de date este \u00EEn desf\u0103\u0219urare \u02
|
|||
windowTitleConfirmExit=Nu, nu face asta!
|
||||
btn_Stop=\u00CEntrerupere
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Status
|
||||
tab1_table_Lbl_FileName=Numele fi\u0219ierului
|
||||
|
@ -44,7 +45,7 @@ tab2_Cb_AllowXciNszXcz=Adaug\u0103 fi\u0219iere XCI / NSZ / XCZ pentru selec\u02
|
|||
tab2_Lbl_AllowXciNszXczDesc=Folosit de aplica\u021Bii care suport\u0103 XCI/NSZ/XCZ \u0219i folosesc protocolul de transfer al lui Tinfoil. Nu schimba dac\u0103\u00A0nu e\u0219ti sigur. Bifeaz\u0103 pentru Awoo Installer.
|
||||
tab2_Lbl_Language=Limb\u0103
|
||||
windowBodyRestartToApplyLang=Te rog restarteaz\u0103 aplica\u021Bia pentru a aplica set\u0103rile noi.
|
||||
btn_OpenSplitFile=Selecteaz\u0103 pentru NSP frac\u021Bionat
|
||||
btn_OpenSplitFile=Selecteaz\u0103 pentru ROM frac\u021Bionat
|
||||
tab2_Lbl_ApplicationSettings=Set\u0103ri principale
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Unealt\u0103 pentru \u00EEmp\u0103r\u021Bire \u0219i lipire de fi\u0219iere
|
||||
tabSplMrg_RadioBtn_Split=\u00CEmparte
|
||||
|
@ -74,4 +75,4 @@ windowBodyPleaseStopOtherProcessFirst=Te rog opre\u0219te toate cel\u0103lalte p
|
|||
tab2_Cb_foldersSelectorForRoms=Selecteaz\u0103 directorul cu fi\u0219iere ROM \u00EEn loc s\u0103 selectezi fi\u0219iere ROM individual.
|
||||
tab2_Cb_foldersSelectorForRomsDesc=Face ca 'Selecteaz\u0103 fi\u0219ierele' \u00EEn tab-ul 'Games' s\u0103 selecteze toate fi\u0219ierele de-o dat\u0103\u00A0\u00EEn loc de a selecta fi\u0219iere ROM unul c\u00E2te unul.
|
||||
windowTitleAddingFiles=Caut fi\u0219iere...
|
||||
windowBodyFilesScanned=Fi\u0219iere scanate: %d\nVor fi ad\u0103ugate: %d
|
||||
windowBodyFilesScanned=Fi\u0219iere scanate: %d\nVor fi ad\u0103ugate: %d
|
||||
|
|
|
@ -9,8 +9,9 @@ windowBodyConfirmExit=\u0421\u0435\u0439\u0447\u0430\u0441 \u043F\u0440\u043E\u0
|
|||
windowTitleConfirmExit=\u041D\u0435\u0442, \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0441\u044C!
|
||||
btn_Stop=\u041F\u0440\u0435\u0440\u0432\u0430\u0442\u044C
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u0421\u0430\u0439\u0442: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
\u0417\u0435\u0440\u043A\u0430\u043B\u043E: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u0421\u0430\u0439\u0442: https://redrise.ru\n\
|
||||
\u0418\u0441\u0430\u0435\u043D\u043A\u043E \u0414\u043C\u0438\u0442\u0440\u0438\u0439 [developer.su]
|
||||
tab1_table_Lbl_Upload=\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044C?
|
||||
tab1_table_Lbl_Size=\u0420\u0430\u0437\u043C\u0435\u0440
|
||||
|
@ -22,7 +23,7 @@ tab2_Lbl_HostIP=IP \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0430
|
|||
tab1_Lbl_NSIP=NS IP:
|
||||
tab2_Cb_ValidateNSHostName=\u0412\u0441\u0435\u0433\u0434\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C NS IP.
|
||||
windowTitleBadIp=IP \u0430\u0434\u0440\u0435\u0441 NS \u043F\u043E\u0445\u043E\u0436\u0435 \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439
|
||||
windowBodyBadIp=\u0412\u044B \u0443\u0432\u0435\u0440\u0435\u043D\u044B \u0447\u0442\u043E IP \u0430\u0434\u0440\u0435\u0441 NS \u0432\u0432\u0435\u0434\u0451\u043D \u0431\u0435\u0437 \u043E\u0448\u0438\u0431\u043E\u043A?
|
||||
windowBodyBadIp=\u0412\u044B \u0443\u0432\u0435\u0440\u0435\u043D\u044B, \u0447\u0442\u043E IP \u0430\u0434\u0440\u0435\u0441 NS \u0432\u0432\u0435\u0434\u0451\u043D \u0431\u0435\u0437 \u043E\u0448\u0438\u0431\u043E\u043A?
|
||||
tab2_Cb_ExpertMode=\u0420\u0435\u0436\u0438\u043C \u044D\u043A\u0441\u043F\u0435\u0440\u0442\u0430 (\u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0441\u0435\u0442\u0438)
|
||||
tab2_Lbl_HostPort=\u043F\u043E\u0440\u0442
|
||||
tab2_Cb_AutoDetectIp=\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u044F\u0442\u044C IP
|
||||
|
@ -43,7 +44,7 @@ tab2_Lbl_AllowXciNszXczDesc=\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u04
|
|||
tab2_Lbl_Language=\u042F\u0437\u044B\u043A
|
||||
windowBodyRestartToApplyLang=\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443.
|
||||
tab2_Cb_GLshowNspOnly=\u041E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u044C \u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0444\u0430\u0439\u043B\u044B *.nsp \u0432 GoldLeaf.
|
||||
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 \u0444\u0430\u0439\u043B
|
||||
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
|
||||
|
@ -76,4 +77,21 @@ windowBodyFilesScanned=\u0424\u0430\u0439\u043B\u043E\u0432 \u043F\u0440\u043E\u
|
|||
tab2_Lbl_AwooBlockTitle=Awoo Installer \u0438 \u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C\u044B\u0435
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
tabPatches_Btn_asZipFile=\u0432 \u0432\u0438\u0434\u0435 ZIP
|
||||
tabPatches_Btn_fromFolder=\u0418\u0437 \u043F\u0430\u043F\u043A\u0438
|
||||
tabPatches_Btn_MakeAll=\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0432\u0441\u0451
|
||||
tabPatches_Btn_MakeAtmo=\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0434\u043B\u044F Loader (Atmosphere)
|
||||
tabPatches_Btn_MakeEs=\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0434\u043B\u044F ES
|
||||
tabPatches_Btn_MakeFs=\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0434\u043B\u044F FS
|
||||
tabPatches_Lbl_Atmo=Atmosphere:
|
||||
tabPatches_Lbl_Firmware=\u041F\u0440\u043E\u0448\u0438\u0432\u043A\u0430:
|
||||
tabPatches_Lbl_Keys=\u041A\u043B\u044E\u0447\u0438:
|
||||
tabPatches_Lbl_Title=\u041F\u0430\u0442\u0447\u0438
|
||||
tabPatches_ServiceWindowMessageEsFs=\u0414\u043B\u044F \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u043F\u0430\u0442\u0447\u0435\u0439 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u0443\u043A\u0430\u0437\u0430\u0442\u044C \u043A\u0430\u043A \u043F\u0443\u0442\u044C \u043A \u043F\u0440\u043E\u0448\u0438\u0432\u043A\u0435, \u0442\u0430\u043A \u0438 \u043F\u0443\u0442\u044C \u043A \u0444\u0430\u0439\u043B\u0443 \u043A\u043B\u044E\u0447\u0435\u0439. \u0418\u043D\u0430\u0447\u0435 \u043D\u0435 \u043F\u043E\u043D\u044F\u0442\u043D\u043E \u0447\u0442\u043E \u0436\u0435 \u043F\u0430\u0442\u0447\u0438\u0442\u044C.
|
||||
tabPatches_ServiceWindowMessageLoader=\u0414\u043B\u044F \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u043F\u0430\u0442\u0447\u0430 \u00ABLoader\u00BB \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u0443\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u0443\u0442\u044C \u043A Atmosphere.
|
||||
tab2_Btn_ApplicationFont=\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0448\u0440\u0438\u0444\u0442 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F
|
||||
btn_ResetToDefaults=\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C
|
||||
fontPreviewText=\u041F\u0440\u0438\u043C\u0435\u0440 \u0442\u0435\u043A\u0441\u0442\u0430
|
||||
fontSize=\u0420\u0430\u0437\u043C\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u043E\u0432:
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
btn_OpenFile=V\u00E4lj filer
|
||||
btn_OpenFolders=V\u00E4lj mapp
|
||||
btn_Upload=Skicka upp till NS
|
||||
btn_OpenFolders_tooltip=V\u00E4lj en mapp att skanna.\nDenna mapp och alla dess undermappar kommer att skannas.\nAlla matchande filer kommer att l\u00E4ggas till i listan.
|
||||
tab3_Txt_EnteredAsMsg1=Du har startat som:
|
||||
tab3_Txt_EnteredAsMsg2=Du b\u00F6r vara root eller ha konfigurerat 'udev'-regler f\u00F6r denna anv\u00E4ndare f\u00F6r att undvika problem.
|
||||
tab3_Txt_FilesToUploadTitle=Filer att skicka upp:
|
||||
tab3_Txt_GreetingsMessage=V\u00E4lkommen till NS-USBloader
|
||||
tab3_Txt_NoFolderOrFileSelected=Inga filer markerade: ingenting att skicka upp.
|
||||
windowBodyConfirmExit=Data\u00F6verf\u00F6ring p\u00E5g\u00E5r och st\u00E4nger du detta program kommer den avbrytas.\nDet \u00E4r det v\u00E4rsta du kan g\u00F6ra nu.\nAvbryta processen och avsluta?
|
||||
windowTitleConfirmExit=Nej, g\u00F6r inte detta!
|
||||
btn_Stop=Avbryt
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Status
|
||||
tab1_table_Lbl_FileName=Filnamn
|
||||
tab1_table_Lbl_Size=Storlek
|
||||
tab1_table_Lbl_Upload=Skicka upp?
|
||||
tab1_table_contextMenu_Btn_BtnDelete=Ta bort
|
||||
tab1_table_contextMenu_Btn_DeleteAll=Ta bort alla
|
||||
tab2_Lbl_HostIP=V\u00E4rdens IP
|
||||
tab1_Lbl_NSIP=NS IP:
|
||||
tab2_Cb_ValidateNSHostName=Validera alltid NS IP-inmatning.
|
||||
windowBodyBadIp=\u00C4r du s\u00E4ker p\u00E5 att du har angivet NS IP-adress korrekt?
|
||||
windowTitleBadIp=IP-adress f\u00F6r NS \u00E4r antagligen felaktig
|
||||
tab2_Cb_ExpertMode=Expertl\u00E4ge (NET setup)
|
||||
tab2_Lbl_HostPort=port
|
||||
tab2_Cb_AutoDetectIp=Autodetektera IP
|
||||
tab2_Cb_RandSelectPort=Slumpm\u00E4ssig port
|
||||
tab2_Cb_DontServeRequests=Hantera inte beg\u00E4ran
|
||||
tab2_Lbl_DontServeRequestsDesc=Om vald, kommer denna dator inte att svara p\u00E5 beg\u00E4ran av NSP-filer som kommer fr\u00E5n NS (\u00F6ver n\u00E4tet) och anv\u00E4nder definierade v\u00E4rdinst\u00E4llningar f\u00F6r att instruera Awoo Installer (eller kompatibla program) var den ska leta efter filer.
|
||||
tab2_Lbl_HostExtra=extra
|
||||
windowTitleErrorPort=Port inst\u00E4lld felaktigt!
|
||||
windowBodyErrorPort=Port kan inte vara 0 eller h\u00F6gre \u00E4n 65535.
|
||||
tab2_Cb_AutoCheckForUpdates=Automatisk uppdateringskontroll
|
||||
windowTitleNewVersionAval=Ny version tillg\u00E4nglig
|
||||
windowTitleNewVersionNOTAval=Inga nya versioner tillg\u00E4ngliga
|
||||
windowTitleNewVersionUnknown=Kunde inte leta efter nya versioner
|
||||
windowBodyNewVersionUnknown=N\u00E5gonting gick fel\nKanske inte kan n\u00E5 internet, eller GitHub \u00E4r nere
|
||||
windowBodyNewVersionNOTAval=Du anv\u00E4nder den senaste versionen
|
||||
tab2_Cb_AllowXciNszXcz=Till\u00E5t val av XCI / NSZ / XCZ-filer f\u00F6r Awoo
|
||||
tab2_Lbl_AllowXciNszXczDesc=Anv\u00E4nds av program som har st\u00F6d f\u00F6r XCI/NSZ/XCZ och anv\u00E4nder Awoo (aka Adubbz/TinFoil) \u00F6verf\u00F6ringsprotokoll. \u00C4ndra inte om du \u00E4r os\u00E4ker. Aktivera f\u00F6r Awoo Installer.
|
||||
tab2_Lbl_Language=Spr\u00E5k
|
||||
windowBodyRestartToApplyLang=Starta om programmet f\u00F6r att verkst\u00E4lla \u00E4ndringar.
|
||||
btn_OpenSplitFile=V\u00E4lj delad ROM
|
||||
tab2_Lbl_ApplicationSettings=Huvudinst\u00E4llningar
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Verktyg f\u00F6r att dela upp och sl\u00E5 ihop filer
|
||||
tabSplMrg_RadioBtn_Split=Dela upp
|
||||
tabSplMrg_RadioBtn_Merge=Sl\u00E5 ihop
|
||||
tabSplMrg_Txt_File=Fil:
|
||||
tabSplMrg_Txt_Folder=Dela upp fil (mapp):
|
||||
tabSplMrg_Btn_SelectFile=V\u00E4lj fil
|
||||
tabSplMrg_Btn_SelectFolder=V\u00E4lj mapp
|
||||
tabSplMrg_Lbl_SaveToLocation=Spara till:
|
||||
tabSplMrg_Btn_ChangeSaveToLocation=\u00C4ndra
|
||||
tabSplMrg_Btn_Convert=Konvertera
|
||||
windowTitleError=Fel
|
||||
windowBodyPleaseFinishTransfersFirst=Kunde inte dela upp/sl\u00E5 ihop filer n\u00E4r programmets USB/n\u00E4tverksprocess \u00E4r aktiv. Avbryt f\u00F6rst aktiva \u00F6verf\u00F6ringar.
|
||||
done_txt=F\u00E4rdig!
|
||||
failure_txt=Misslyckades
|
||||
btn_Select=V\u00E4lj
|
||||
btn_InjectPayloader=Injicera payload
|
||||
tabNXDT_Btn_Start=Starta!
|
||||
tab2_Btn_InstallDrivers=H\u00E4mta och installera drivrutiner
|
||||
windowTitleDownloadDrivers=H\u00E4mta och installera drivrutiner
|
||||
windowBodyDownloadDrivers=H\u00E4mtar drivrutiner (libusbK v3.0.7.0)...
|
||||
btn_Cancel=Avbryt
|
||||
btn_Close=St\u00E4ng
|
||||
tab2_Cb_GlVersion=GoldLeaf version
|
||||
tab2_Cb_GLshowNspOnly=Visa endast *.nsp i GoldLeaf.
|
||||
windowBodyPleaseStopOtherProcessFirst=Stoppa andra aktiva processer innan du forts\u00E4tter.
|
||||
tab2_Cb_foldersSelectorForRoms=V\u00E4lj mapp med ROM-filer ist\u00E4llet f\u00F6r att v\u00E4lja enstaka ROM-filer.
|
||||
tab2_Cb_foldersSelectorForRomsDesc=\u00C4ndrar 'V\u00E4lj filer'-knappens beteende p\u00E5 'Spel'-fliken: ist\u00E4llet f\u00F6r att v\u00E4lja enstaka ROM-filer s\u00E5 kan du v\u00E4lja mapp f\u00F6r att l\u00E4gga till alla filer som st\u00F6ds p\u00E5 en g\u00E5ng.
|
||||
windowTitleAddingFiles=Letar efter filer...
|
||||
windowBodyFilesScanned=Filer genoms\u00F6kta: %d\nKommer att l\u00E4ggas till: %d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo Installer och kompatibla
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
|
@ -0,0 +1,97 @@
|
|||
btn_OpenFile=Dosya secimi
|
||||
btn_OpenFolders=Klasor secimi
|
||||
btn_Upload=NS'e yukle
|
||||
btn_OpenFolders_tooltip=Taranmasi icin bir klasor secin.\nBu klasor ve butun alt klasorleri taranacaktir.\nButun uyusan dosyalar listeye eklenecektir.
|
||||
tab3_Txt_EnteredAsMsg1=Olarak giris yaptiniz:
|
||||
tab3_Txt_EnteredAsMsg2=Bir cok hatadan kacinmak icin root olmaniz ya da bu kullanici icin 'udev' kurallarini ayarlamaniz gerekmektedir.
|
||||
tab3_Txt_FilesToUploadTitle=Yuklenecek dosyalar:
|
||||
tab3_Txt_GreetingsMessage= NS-USBloader'a Hos Geldiniz
|
||||
tab3_Txt_NoFolderOrFileSelected=Hicbir dosya secilmedi: hicbir sey yuklenmedi.
|
||||
windowBodyConfirmExit=Data transferi devam ediyor ve uygulamayi kapatmak bunu yarida kesecek.\nBu su an yapabileceginiz en kotu sey.\nIslemi yardida kes ve cik ?
|
||||
windowTitleConfirmExit=Hayir,Bunu yapma!
|
||||
btn_Stop=Hata
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=Durum
|
||||
tab1_table_Lbl_FileName=Dosya Ismi
|
||||
tab1_table_Lbl_Size=Boyut
|
||||
tab1_table_Lbl_Upload=Yukle?
|
||||
tab1_table_contextMenu_Btn_BtnDelete=Kaldir
|
||||
tab1_table_contextMenu_Btn_DeleteAll=Hepsini kaldir
|
||||
tab2_Lbl_HostIP=Host IP
|
||||
tab1_Lbl_NSIP=NS IP:
|
||||
tab2_Cb_ValidateNSHostName= NS IP girislerinizi her zaman dogrulayin.
|
||||
windowBodyBadIp=Girilen NS IP adresinin dogru olduguna emin misiniz?
|
||||
windowTitleBadIp=NS'in IP adressi buyuk ihtimalle yanlis
|
||||
tab2_Cb_ExpertMode=Uzman modu (NET setup)
|
||||
tab2_Lbl_HostPort=Port
|
||||
tab2_Cb_AutoDetectIp=Oto-Tespit IP
|
||||
tab2_Cb_RandSelectPort=Portu rastgele al
|
||||
tab2_Cb_DontServeRequests=Istekleri yerine getirme
|
||||
tab2_Lbl_DontServeRequestsDesc=Eger secili ise, bu bilgisayar NS'den (ag uzerinden) gelen NSP dosyalarinin isteklerine yanit vermez ve Awoo Installer'a (veya uyumlu uygulamalara) dosyalari nerede aramasi gerektigini soylemek icin tanimlanmis ana bilgisayar ayarlarini kullanir.
|
||||
tab2_Lbl_HostExtra=Ekstra
|
||||
windowTitleErrorPort=Port seti hatali!
|
||||
windowBodyErrorPort=Port 0 olamaz ve 65535'den buyuk olamaz.
|
||||
tab2_Cb_AutoCheckForUpdates=Guncellemeleri otomatik kontrol et
|
||||
windowTitleNewVersionAval=Yeni versiyon mevcut
|
||||
windowTitleNewVersionNOTAval=Yeni versiyon mevcut degil
|
||||
windowTitleNewVersionUnknown=Yeni versiyon kontrolu yapilamiyor
|
||||
windowBodyNewVersionUnknown=Bir sey ters gitti\nBelki internet yoktur ya da GitHub cokmustur
|
||||
windowBodyNewVersionNOTAval=En son versiyonu kullaniyorsunuz
|
||||
tab2_Cb_AllowXciNszXcz=XCI / NSZ / XCZ dosyalaninin Awoo icin seciminine izin ver.
|
||||
tab2_Lbl_AllowXciNszXczDesc=XCI/NSZ/XCZ'yi destekleyen uygulamalar tarafindan kullanilir ve Awoo (Adubbz/TinFoil olarak da bilinir) transfer protokolunu uygular. Emin degilseniz degistirmeyin. Installer icin AWOO'yu etkinlestirin.
|
||||
tab2_Lbl_Language=Dil
|
||||
windowBodyRestartToApplyLang=Lutfen degisikliklerin uygulanabilmesi icin uygulamayi yendiden baslatin.
|
||||
btn_OpenSplitFile=Bolme sec
|
||||
tab2_Lbl_ApplicationSettings=Ana ayarlar
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=Dosyalari bolme & birlestirme araci
|
||||
tabSplMrg_RadioBtn_Split=Ayir
|
||||
tabSplMrg_RadioBtn_Merge=Birlestir
|
||||
tabSplMrg_Txt_File=Dosya:
|
||||
tabSplMrg_Txt_Folder=Dosyayi ayir (klasor):
|
||||
tabSplMrg_Btn_SelectFile=Dosya sec
|
||||
tabSplMrg_Btn_SelectFolder=Klasor Sec
|
||||
tabSplMrg_Lbl_SaveToLocation=Buraya kaydet:
|
||||
tabSplMrg_Btn_ChangeSaveToLocation=Degistir
|
||||
tabSplMrg_Btn_Convert=Cevir
|
||||
windowTitleError=Hata
|
||||
windowBodyPleaseFinishTransfersFirst=Bolme/Birlestirme islemleri USB/Network transfer sureci aktifken yapilamaz. Lutfen once aktif transfer isleminizi bitiriniz.
|
||||
done_txt=Hazir!
|
||||
failure_txt=Basarisiz
|
||||
btn_Select=Secim yap
|
||||
btn_InjectPayloader=payload yukle (enject)
|
||||
tabNXDT_Btn_Start=Basla!
|
||||
tab2_Btn_InstallDrivers=Suruculeri indir ve yukle
|
||||
windowTitleDownloadDrivers=Suruculeri indir ve yukle
|
||||
windowBodyDownloadDrivers=Suruculer indiriliyor (libusbK v3.0.7.0)...
|
||||
btn_Cancel=Iptal
|
||||
btn_Close=Kapat
|
||||
tab2_Cb_GlVersion=GoldLeaf versiyonu
|
||||
tab2_Cb_GLshowNspOnly=Goldleaf'ta sadece *.nsp goster.
|
||||
windowBodyPleaseStopOtherProcessFirst=Lutfen devam etmeden once butun diger aktif islemleri durdurun.
|
||||
tab2_Cb_foldersSelectorForRoms=Direkt ROM dosyalini secmek yerine ROM klasorunu sec
|
||||
tab2_Cb_foldersSelectorForRomsDesc=Oyunlar' sekmesinde 'Dosyalari Sec' dugmesi davranisini degistirir: Tek tek ROM dosyalarini secmek yerine, desteklenen her dosyayi bir klasor secerek ekleyebilirsiniz.
|
||||
windowTitleAddingFiles=Dosyalar araniyor...
|
||||
windowBodyFilesScanned=Dosyalar tarandi: %d\nEklenecek: %d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo Yukleyicisi ve Uyumu
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
tabPatches_Lbl_Firmware=Firmware:
|
||||
tabPatches_Lbl_Atmo=Atmosphere:
|
||||
tabPatches_Btn_fromFolder=Klasorden
|
||||
tabPatches_Btn_asZipFile=ZIP dosyasi olarak
|
||||
tabPatches_Lbl_Title=Yamalar
|
||||
tabPatches_Lbl_Keys=Anahtarlar:
|
||||
tabPatches_Btn_MakeEs=ES yap
|
||||
tabPatches_Btn_MakeFs=FS yap
|
||||
tabPatches_Btn_MakeAtmo=Loader yap (Atmosphere)
|
||||
tabPatches_Btn_MakeAll=Hepsini yap
|
||||
tabPatches_ServiceWindowMessageEsFs=Firmware ve anahtarlar, yamalari olusturmak icin ayarlanmalidir. Aksi takdirde, neyi duzeltecegi belirsiz olacaktir.
|
||||
tabPatches_ServiceWindowMessageLoader='Loader' yamasi olusturmak icin Atmosphere klasoru tanimlanmalidir.
|
||||
tab2_Btn_ApplicationFont=Uygulama yazi tipini degistir
|
||||
btn_ResetToDefaults=Reset
|
||||
fontPreviewText=Yazi Onizlemesi
|
||||
fontSize=Yazi boyutu:
|
|
@ -9,8 +9,9 @@ windowBodyConfirmExit=\u0417\u0430\u0440\u0430\u0437 \u0432\u0456\u0434\u0431\u0
|
|||
windowTitleConfirmExit=\u041D\u0456, \u0437\u0443\u043F\u0438\u043D\u0438\u0441\u044C!
|
||||
btn_Stop=\u041F\u0435\u0440\u0435\u0440\u0432\u0430\u0442\u0438
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
\u0421\u0438\u0440\u0446\u0435\u0432\u0438\u0439 \u043A\u043E\u0434: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u0421\u0430\u0439\u0442: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
\u0421\u0438\u0440\u0446\u0435\u0432\u0438\u0439 \u043A\u043E\u0434: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
\u0414\u0437\u0435\u0440\u043A\u0430\u043B\u043E: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u0421\u0430\u0439\u0442: https://redrise.ru\n\
|
||||
\u0418\u0441\u0430\u0454\u043D\u043A\u043E \u0414\u043C\u0438\u0442\u0440\u043E [developer.su]
|
||||
tab1_table_Lbl_Status=\u0421\u0442\u0430\u043D
|
||||
tab1_table_Lbl_FileName=\u0406\u043C'\u044F \u0444\u0430\u0439\u043B\u0443
|
||||
|
@ -43,7 +44,7 @@ tab2_Lbl_AllowXciNszXczDesc=\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u04
|
|||
tab2_Lbl_Language=\u041C\u043E\u0432\u0430
|
||||
windowBodyRestartToApplyLang=\u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0456\u0442\u044C \u0434\u043E\u0434\u0430\u0442\u043E\u043A \u0449\u043E\u0431 \u0437\u043C\u0456\u043D\u0438 \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443.
|
||||
tab2_Cb_GLshowNspOnly=\u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u0432\u0438\u043A\u043B\u044E\u0447\u043D\u043E *.nsp \u0444\u0430\u0439\u043B\u0438 \u0443 GoldLeaf.
|
||||
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 \u0444\u0430\u0439\u043B
|
||||
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
|
||||
|
@ -76,3 +77,20 @@ windowBodyFilesScanned=\u0424\u0430\u0439\u043B\u0456\u0432 \u043F\u0440\u043E\u
|
|||
tab2_Lbl_AwooBlockTitle=Awoo Installer \u0442\u0430 \u0441\u0443\u043C\u0456\u0441\u043D\u0456
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
tabPatches_Btn_asZipFile=\u044F\u043A ZIP
|
||||
tabPatches_Btn_fromFolder=\u0417 \u0434\u0438\u0440\u0435\u043A\u0442\u043E\u0440\u0456\u0457
|
||||
tabPatches_Btn_MakeAll=\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0432\u0441\u0456
|
||||
tabPatches_Btn_MakeAtmo=\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0434\u043B\u044F Loader (Atmosphere)
|
||||
tabPatches_Btn_MakeEs=\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0434\u043B\u044F ES
|
||||
tabPatches_Btn_MakeFs=\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0434\u043B\u044F FS
|
||||
tabPatches_Lbl_Atmo=Atmosphere:
|
||||
tabPatches_Lbl_Firmware=\u041F\u0440\u043E\u0448\u0438\u0432\u043A\u0430:
|
||||
tabPatches_Lbl_Keys=\u041A\u043B\u044E\u0447\u0456:
|
||||
tabPatches_Lbl_Title=\u041F\u0430\u0442\u0447\u0438
|
||||
tabPatches_ServiceWindowMessageEsFs=\u0414\u043B\u044F \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043D\u044F \u043F\u0430\u0442\u0447\u0456\u0432 \u043D\u0435\u043E\u0431\u0445\u0456\u0434\u043D\u043E \u0432\u043A\u0430\u0437\u0430\u0442\u0438 \u044F\u043A \u0448\u043B\u044F\u0445 \u0434\u043E \u043F\u0440\u043E\u0448\u0438\u0432\u043A\u0438, \u0442\u0430\u043A \u0456 \u0434\u043E \u0444\u0430\u0439\u043B\u0443 \u043A\u043B\u044E\u0447\u0456\u0432. \u0411\u043E \u0456\u043D\u0430\u043A\u0448\u0435 \u043D\u0435 \u0437\u0440\u043E\u0437\u0443\u043C\u0456\u043B\u043E \u0449\u043E \u0436 \u0442\u0440\u0435\u0431\u0430 \u043F\u0430\u0442\u0447\u0438\u0442\u0438.
|
||||
tabPatches_ServiceWindowMessageLoader=\u0414\u043B\u044F \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0456\u0457 "Loader"-\u043F\u0430\u0442\u0447\u0443 \u043D\u0435\u043E\u0431\u0445\u0456\u0434\u043D\u043E \u0432\u043A\u0430\u0437\u0430\u0442\u0438 \u0448\u043B\u044F\u0445 \u0434\u043E Atmosphere.
|
||||
tab2_Btn_ApplicationFont=\u0417\u043C\u0456\u043D\u0438\u0442\u0438 \u0448\u0440\u0438\u0444\u0442 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u0438
|
||||
btn_ResetToDefaults=C\u043A\u0438\u043D\u0443\u0442\u0438
|
||||
fontPreviewText=\u041F\u0440\u0438\u043A\u043B\u0430\u0434 \u0442\u0435\u043A\u0441\u0442\u0443
|
||||
fontSize=\u0420\u043E\u0437\u043C\u0456\u0440 \u0448\u0440\u0438\u0444\u0442\u0456\u0432:
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
btn_InjectPayloader=N\u1EA1p payload
|
||||
btn_OpenFile=Ch\u1ECDn t\u1EADp tin .NSP
|
||||
btn_OpenSplitFile=Ch\u1ECDn NSP t\u00E1ch
|
||||
btn_OpenSplitFile=Ch\u1ECDn ROM t\u00E1ch
|
||||
btn_Select=Ch\u1ECDn
|
||||
btn_Stop=Ng\u1EAFt
|
||||
btn_Upload=T\u1EA3i l\u00EAn NS
|
||||
|
@ -34,7 +34,11 @@ tab3_Txt_EnteredAsMsg1=B\u1EA1n \u0111\u00E3 truy nh\u1EADp d\u01B0\u1EDBi d\u1E
|
|||
tab3_Txt_EnteredAsMsg2=B\u1EA1n n\u00EAn c\u00F3 quy\u1EC1n root ho\u1EB7c c\u1EA5u h\u00ECnh quy\u1EC1n 'udev' cho ng\u01B0\u1EDDi d\u00F9ng n\u00E0y \u0111\u1EC3 tr\u00E1nh c\u00E1c v\u1EA5n \u0111\u1EC1 ph\u00E1t sinh.
|
||||
tab3_Txt_FilesToUploadTitle=T\u1EADp tin s\u1EBD t\u1EA3i l\u00EAn\:
|
||||
tab3_Txt_GreetingsMessage=Ch\u00E0o m\u1EEBng \u0111\u1EBFn NS-USBloader
|
||||
tab3_Txt_GreetingsMessage2=--\nNgu\u1ED3n\: https\://github.com/developersu/ns-usbloader/\nTrang\: https\://developersu.blogspot.com/search/label/NS-USBloader\nDmitry Isaenko [developer.su]
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Ngu\u1ED3n: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Trang: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab3_Txt_NoFolderOrFileSelected=Kh\u00F4ng c\u00F3 t\u1EADp tin n\u00E0o \u0111\u01B0\u1EE3c ch\u1ECDn\: kh\u00F4ng c\u00F3 g\u00EC \u0111\u1EC3 t\u1EA3i l\u00EAn.
|
||||
tabSplMrg_Btn_ChangeSaveToLocation=Thay \u0111\u1ED5i
|
||||
tabSplMrg_Btn_Convert=Chuy\u1EC3n \u0111\u1ED5i
|
||||
|
@ -62,3 +66,4 @@ windowTitleNewVersionNOTAval=Ch\u01B0a c\u00F3 phi\u00EAn b\u1EA3n m\u1EDBi
|
|||
windowTitleNewVersionUnknown=Kh\u00F4ng th\u1EC3 ki\u1EC3m tra phi\u00EAn b\u1EA3n m\u1EDBi
|
||||
btn_Cancel=H\u1EE7y B\u1ECF
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
btn_OpenFile=\u9009\u62E9.NSP\u6587\u4EF6
|
||||
btn_OpenFolders=\u9009\u62e9\u76ee\u5f55
|
||||
btn_OpenFolders=\u9009\u62E9\u76EE\u5F55
|
||||
btn_Upload=\u4E0A\u4F20\u5230NS
|
||||
btn_OpenFolders_tooltip=\u6b63\u5728\u626b\u63cf\u9009\u4e2d\u7684\u76ee\u5f55.\n\u6240\u6709\u7684\u76ee\u5f55\u626b\u63cf\u5b8c\u6210.\n\u7b26\u5408\u7684\u6587\u4ef6\u5df2\u7ecf\u6dfb\u52a0\u5230\u5217\u8868\u4e2d.
|
||||
btn_OpenFolders_tooltip=\u6B63\u5728\u626B\u63CF\u9009\u4E2D\u7684\u76EE\u5F55.\n\u6240\u6709\u7684\u76EE\u5F55\u626B\u63CF\u5B8C\u6210.\n\u7B26\u5408\u7684\u6587\u4EF6\u5DF2\u7ECF\u6DFB\u52A0\u5230\u5217\u8868\u4E2D.
|
||||
tab3_Txt_EnteredAsMsg1=\u4F60\u6B63\u5728\u4F7F\u7528:
|
||||
tab3_Txt_EnteredAsMsg2=\u4F60\u5E94\u8BE5\u4F7F\u7528root\u8D26\u53F7\u6216\u8005\u4E3A\u5F53\u524D\u7528\u6237\u914D\u7F6E'udev'\u89C4\u5219\u6765\u907F\u514D\u53EF\u80FD\u7684\u95EE\u9898\u3002
|
||||
tab3_Txt_FilesToUploadTitle=\u8981\u4E0A\u4F20\u7684\u6587\u4EF6:
|
||||
|
@ -11,8 +11,9 @@ windowBodyConfirmExit=\u6570\u636E\u6B63\u5728\u4F20\u8F93\u4E2D\uFF0C\u5173\u95
|
|||
windowTitleConfirmExit=\u4E0D, \u4E0D\u8FDB\u884C\u8FD9\u9879\u64CD\u4F5C\uFF01
|
||||
btn_Stop=\u4E2D\u65AD
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
\u6E90\u4EE3\u7801: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u7F51\u7AD9: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
\u6E90\u4EE3\u7801: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
\u7F51\u7AD9: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=\u72B6\u6001
|
||||
tab1_table_Lbl_FileName=\u6587\u4EF6\u540D
|
||||
|
@ -43,8 +44,8 @@ windowBodyNewVersionNOTAval=\u4F60\u6B63\u5728\u4F7F\u7528\u6700\u65B0\u7248
|
|||
tab2_Cb_AllowXciNszXcz=Awoo\u6A21\u5F0F\u5141\u8BB8\u9009\u62E9XCI\u6587\u4EF6
|
||||
tab2_Lbl_AllowXciNszXczDesc=\u7528\u4E8E\u4E00\u4E9B\u652F\u6301XCI/NSZ/XCZ\u548CTinfoil\u4F20\u8F93\u534F\u8BAE\u7684\u7B2C\u4E09\u65B9\u5E94\u7528\u3002\u5982\u679C\u4E0D\u6E05\u695A\u4E0D\u8981\u4FEE\u6539\u3002
|
||||
tab2_Lbl_Language=\u8BED\u8A00
|
||||
windowBodyRestartToApplyLang=\u8BF7\u91CD\u542F\u5E94\u7528\u4EE5\u5E94\u7528\u66F4\u6539\u3002
|
||||
btn_OpenSplitFile=\u9009\u62E9\u5206\u5272\u7684NSP
|
||||
windowBodyRestartToApplyLang=\u8bf7\u91cd\u542f\u7a0b\u5e8f\u005c\u006e\u914d\u7f6e\u624d\u4f1a\u751f\u6548\uff01
|
||||
btn_OpenSplitFile=\u9009\u62E9\u5206\u5272\u7684ROM
|
||||
tab2_Lbl_ApplicationSettings=\u4E3B\u8981\u8BBE\u5B9A
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=\u5206\u5272&\u5408\u5E76\u6587\u4EF6\u5DE5\u5177
|
||||
tabSplMrg_RadioBtn_Split=\u5206\u5272&\u5408\u5E76\u6587\u4EF6\u5DE5\u5177
|
||||
|
@ -71,10 +72,11 @@ btn_Close=\u5173\u95ED
|
|||
tab2_Cb_GlVersion=GoldLeaf\u7248\u672C
|
||||
tab2_Cb_GLshowNspOnly=\u5728GoldLeaf\u5185\u4EC5\u663E\u793A*.nsp\u6587\u4EF6
|
||||
windowBodyPleaseStopOtherProcessFirst=\u5982\u8981\u6267\u884C\u76EE\u524D\u7684\u64CD\u4F5C\u7A0B\u5E8F,\u8BF7\u5148\u505C\u6B62\u5176\u4ED6\u6B63\u5728\u5904\u7406\u7684\u7A0B\u5E8F.
|
||||
tab2_Cb_foldersSelectorForRoms=\u9009\u4e2d\u540e\u5207\u6362\u6210\u9009\u62e9\u76ee\u5f55\u6a21\u5f0f.
|
||||
tab2_Cb_foldersSelectorForRomsDesc=Changes 'Select files' button behaviour on 'Games' tab: instead of selecting ROM files one-by-one you can choose folder to add every supported file at once.
|
||||
windowTitleAddingFiles=\u641c\u7d22\u6587\u4ef6\u4e2d...
|
||||
windowBodyFilesScanned=\u626b\u63cf\u6587\u4ef6: %25d\n\u88ab\u6dfb\u52a0: %25d
|
||||
tab2_Lbl_AwooBlockTitle=awoo installer \u5b8c\u6210
|
||||
tab2_Cb_foldersSelectorForRoms=\u9009\u4E2D\u540E\u5207\u6362\u6210\u9009\u62E9\u76EE\u5F55\u6A21\u5F0F
|
||||
tab2_Cb_foldersSelectorForRomsDesc=\u542F\u7528\u6B64\u529F\u80FD\u540E\uFF0C\u5C06\u6539\u53D8\u201C\u6E38\u620F\u6807\u7B7E\u201D\u4E2D\u7684\u201C\u9009\u62E9\u6587\u4EF6\u201D\u6309\u952E\u529F\u80FD\uFF1A\u4ECE\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6\u66FF\u6362\u4E3A\u9009\u62E9\u4E00\u4E2A\u76EE\u5F55\u3002
|
||||
windowTitleAddingFiles=\u641C\u7D22\u6587\u4EF6\u4E2D...
|
||||
windowBodyFilesScanned=\u626B\u63CF\u6587\u4EF6: %25d\n\u88AB\u6DFB\u52A0: %25d
|
||||
tab2_Lbl_AwooBlockTitle=awoo installer \u5B8C\u6210
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
btn_OpenFile=\u9078\u64C7\u6A94\u6848
|
||||
btn_OpenFolders=\u9009\u62e9\u8def\u5f84
|
||||
btn_OpenFolders=\u9078\u64C7\u8CC7\u6599\u593E
|
||||
btn_Upload=\u4E0A\u50B3\u81F3NS
|
||||
btn_OpenFolders_tooltip=\u6383\u63cf\u9078\u4e2d\u7684\u8def\u5f91.\n\u6240\u6709\u7684\u8def\u5f91\u6383\u63cf\u5b8c\u6210.\n\u5339\u914d\u7684\u6a94\u6848\u5df2\u6dfb\u52a0\u5230\u5217\u8868.
|
||||
btn_OpenFolders_tooltip=\u9078\u64C7\u8981\u6AA2\u67E5\u7684\u8CC7\u6599\u593E.\n\u6703\u6AA2\u67E5\u8CC7\u6599\u593E\u8207\u6240\u6709\u5B50\u76EE\u9304.\n\u6240\u6709\u7B26\u5408\u7684\u6A94\u6848\u90FD\u6703\u52A0\u5165\u4F47\u5217.
|
||||
tab3_Txt_EnteredAsMsg1=\u76EE\u524D\u767B\u5165\u7684\u4F7F\u7528\u8005:
|
||||
tab3_Txt_EnteredAsMsg2=\u57F7\u884C\u6B64\u64CD\u4F5C\u6642\u4F60\u5FC5\u9808\u64C1\u6709\u6700\u9AD8\u5B58\u53D6\u6B0A\u9650,\u6216\u8005\u5DF2\u914D\u7F6E\u4E86'udev'\u898F\u5247,\u4EE5\u78BA\u4FDD\u4E0D\u6703\u51FA\u73FE\u4EFB\u4F55\u554F\u984C.
|
||||
tab3_Txt_EnteredAsMsg2=\u57F7\u884C\u6B64\u64CD\u4F5C\u6642\u4F60\u5FC5\u9808\u64C1\u6709\u7BA1\u7406\u54E1\u6B0A\u9650,\u6216\u6B64\u767B\u5165\u7684\u4F7F\u7528\u8005\u5E33\u6236\u5DF2\u914D\u7F6E'udev'\u898F\u5247,\u4EE5\u907F\u514D\u767C\u751F\u554F\u984C.
|
||||
tab3_Txt_FilesToUploadTitle=\u4E0A\u50B3\u7684\u6A94\u6848:
|
||||
tab3_Txt_GreetingsMessage=\u6B61\u8FCE\u4F7F\u7528NS-USBloader
|
||||
tab3_Txt_NoFolderOrFileSelected=\u5C1A\u672A\u9078\u53D6\u6A94\u6848: \u4E0A\u50B3\u4F47\u5217\u6C92\u6709\u9805\u76EE
|
||||
windowBodyConfirmExit=\u6B64\u6642\u9000\u51FA\u7A0B\u5F0F\u5C07\u6703\u4E2D\u65B7\u6B63\u5728\u50B3\u8F38\u7684\u8CC7\u6599.\n\u9019\u9805\u64CD\u4F5C\u53EF\u80FD\u6703\u9020\u6210\u4EE4\u4EBA\u5F8C\u6094\u7684\u640D\u5BB3.\n\u662F\u5426\u78BA\u8A8D\u8981\u4E2D\u65B7\u50B3\u8F38\u4E26\u4E14\u7D50\u675F\u7A0B\u5F0F?
|
||||
windowBodyConfirmExit=\u6B64\u6642\u9000\u51FA\u7A0B\u5F0F\u5C07\u6703\u4E2D\u65B7\u6B63\u5728\u50B3\u8F38\u7684\u8CC7\u6599.\n\u518D\u6B21\u50B3\u8F38\u8CC7\u6599\u5C07\u91CD\u8907\u4F54\u7528\u6642\u9593.\n\u662F\u5426\u78BA\u8A8D\u8981\u4E2D\u65B7\u50B3\u8F38\u4E26\u4E14\u7D50\u675F\u7A0B\u5F0F?
|
||||
windowTitleConfirmExit=\u4E0D,\u8ACB\u52FF\u9000\u51FA!
|
||||
btn_Stop=\u4E2D\u65B7\u64CD\u4F5C
|
||||
tab3_Txt_GreetingsMessage2=--\n\
|
||||
Source: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\
|
||||
Source: https://git.redrise.ru/desu/ns-usbloader\n\
|
||||
Mirror: https://github.com/developersu/ns-usbloader/\n\
|
||||
Site: https://redrise.ru\n\
|
||||
Dmitry Isaenko [developer.su]
|
||||
tab1_table_Lbl_Status=\u72C0\u614B
|
||||
tab1_table_Lbl_FileName=\u6A94\u6848\u540D\u7A31
|
||||
|
@ -30,7 +31,7 @@ tab2_Lbl_HostPort=\u9023\u63A5\u57E0
|
|||
tab2_Cb_AutoDetectIp=\u81EA\u52D5\u5075\u6E2CIP
|
||||
tab2_Cb_RandSelectPort=\u96A8\u6A5F\u9078\u53D6\u9023\u63A5\u57E0
|
||||
tab2_Cb_DontServeRequests=\u4E0D\u56DE\u61C9NS\u8ACB\u6C42
|
||||
tab2_Lbl_DontServeRequestsDesc=\u555F\u7528\u6B64\u8A2D\u5B9A\u5F8C,\u6B64\u96FB\u8166\u5C07\u4E0D\u6703\u56DE\u61C9\u4F86\u81EANS(\u900F\u904E\u7DB2\u8DEF)\u7684NSP\u6A94\u6848\u8ACB\u6C42,\u4E26\u8B93Awoo\u5C0B\u627E\u6A94\u6848\u4F86\u6E90\u6642\u4F7F\u7528\u9810\u8A2D\u7684\u4E3B\u6A5F\u8A2D\u5B9A.
|
||||
tab2_Lbl_DontServeRequestsDesc=\u555F\u7528\u6B64\u8A2D\u5B9A\u5F8C,\u6B64\u96FB\u8166\u5C07\u4E0D\u6703\u56DE\u61C9\u4F86\u81EANS(\u900F\u904E\u7DB2\u8DEF)\u7684NSP\u6A94\u6848\u8ACB\u6C42,\u4E26\u8B93Awoo(\u6216\u5176\u4ED6\u540C\u985E\u578B\u7A0B\u5F0F)\u5C0B\u627E\u6A94\u6848\u4F86\u6E90\u6642\u4F7F\u7528\u9810\u8A2D\u7684\u4E3B\u6A5F\u8A2D\u5B9A.
|
||||
tab2_Lbl_HostExtra=\u5176\u4ED6
|
||||
windowTitleErrorPort=\u9023\u63A5\u57E0\u8A2D\u5B9A\u4E0D\u6B63\u78BA!
|
||||
windowBodyErrorPort=\u9023\u63A5\u57E0\u8A2D\u5B9A\u503C\u5FC5\u9808\u4ECB\u65BC0\u523065535\u4E4B\u9593.
|
||||
|
@ -44,7 +45,7 @@ tab2_Cb_AllowXciNszXcz=\u5141\u8A31Awoo\u6A21\u5F0F\u6642\u9078\u53D6XCI / NSZ /
|
|||
tab2_Lbl_AllowXciNszXczDesc=\u6B64\u8A2D\u5B9A\u5C08\u70BA\u652F\u63F4XCI/NSZ/XCZ\u6A94\u6848\u683C\u5F0F\u8207Tinfoil\u50B3\u8F38\u5354\u8B70\u7684\u7B2C\u4E09\u65B9\u7A0B\u5F0F\u4F7F\u7528. \u5982\u4E0D\u78BA\u5B9A,\u8ACB\u52FF\u8B8A\u66F4\u6B64\u9805\u8A2D\u5B9A. \u4F7F\u7528Awoo Installer\u8ACB\u555F\u7528\u6B64\u8A2D\u5B9A.
|
||||
tab2_Lbl_Language=\u4ECB\u9762\u8A9E\u7CFB
|
||||
windowBodyRestartToApplyLang=\u8ACB\u91CD\u65B0\u555F\u52D5\u7A0B\u5F0F\u4EE5\u5957\u7528\u8B8A\u66F4\u7684\u8A2D\u5B9A.
|
||||
btn_OpenSplitFile=\u9078\u64C7\u5206\u5272\u7684NSP
|
||||
btn_OpenSplitFile=\u9078\u64C7\u5206\u5272\u7684ROM
|
||||
tab2_Lbl_ApplicationSettings=\u4E3B\u8981\u8A2D\u5B9A
|
||||
tabSplMrg_Lbl_SplitNMergeTitle=\u5206\u5272&\u5408\u4F75\u6A94\u6848\u5DE5\u5177
|
||||
tabSplMrg_RadioBtn_Split=\u5206\u5272&\u5408\u4F75\u6A94\u6848\u5DE5\u5177
|
||||
|
@ -57,7 +58,7 @@ tabSplMrg_Lbl_SaveToLocation=\u5132\u5B58\u8DEF\u5F91:
|
|||
tabSplMrg_Btn_ChangeSaveToLocation=\u8B8A\u66F4
|
||||
tabSplMrg_Btn_Convert=\u8F49\u6A94
|
||||
windowTitleError=\u932F\u8AA4
|
||||
windowBodyPleaseFinishTransfersFirst=\u7576\u7A0B\u5F0F\u6B63\u5728\u8655\u7406USB/Network\u5B89\u88DD\u6642\u7121\u6CD5\u540C\u6642\u57F7\u884C\u5206\u5272/\u5408\u4F75\u6A94\u6848. \u5982\u9700\u7E7C\u7E8C,\u5FC5\u9808\u4E2D\u65B7\u76EE\u524D\u7684\u50B3\u8F38.
|
||||
windowBodyPleaseFinishTransfersFirst=\u7576\u7A0B\u5F0F\u6B63\u5728\u8655\u7406USB/\u7DB2\u8DEF\u5B89\u88DD\u6642\u7121\u6CD5\u540C\u6642\u57F7\u884C\u5206\u5272/\u5408\u4F75\u6A94\u6848. \u5982\u9700\u7E7C\u7E8C,\u5FC5\u9808\u4E2D\u65B7\u76EE\u524D\u7684\u50B3\u8F38.
|
||||
done_txt=\u5B8C\u6210!
|
||||
failure_txt=\u5931\u6557
|
||||
btn_Select=\u9078\u64C7
|
||||
|
@ -71,10 +72,11 @@ btn_Close=\u95DC\u9589
|
|||
tab2_Cb_GlVersion=GoldLeaf\u7248\u672C
|
||||
tab2_Cb_GLshowNspOnly=\u5728GoldLeaf\u5167\u50C5\u986F\u793A*.nsp\u6A94\u6848
|
||||
windowBodyPleaseStopOtherProcessFirst=\u5982\u8981\u57F7\u884C\u76EE\u524D\u7684\u64CD\u4F5C\u7A0B\u5E8F,\u8ACB\u5148\u505C\u6B62\u5176\u4ED6\u6B63\u5728\u8655\u7406\u7684\u7A0B\u5E8F.
|
||||
tab2_Cb_foldersSelectorForRoms=\u9078\u4e2d\u5f8c\u5207\u63db\u70ba\u9078\u64c7\u8def\u5f91\u529f\u80fd
|
||||
tab2_Cb_foldersSelectorForRomsDesc=Changes 'Select files' button behaviour on 'Games' tab: instead of selecting ROM files one-by-one you can choose folder to add every supported file at once.
|
||||
windowTitleAddingFiles=\u6aa2\u7d22\u6a94\u6848\u4e2d...
|
||||
windowBodyFilesScanned=\u6a94\u6848\u6383\u63cf\u5230: %25d\n\u88ab\u6dfb\u52a0: %25d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo Installer and compatible
|
||||
tab2_Cb_foldersSelectorForRoms=\u9078\u64C7\u6A94\u6848\u6642\u7531\u539F\u5148\u500B\u5225\u9078\u53D6\u8B8A\u66F4\u70BA\u6307\u5B9A\u8CC7\u6599\u593E\u5167\u7684\u6240\u6709\u7B26\u5408\u6A94\u6848.
|
||||
tab2_Cb_foldersSelectorForRomsDesc=\u555F\u7528\u6B64\u8A2D\u5B9A\u5F8C,\u5C07\u8B8A\u66F4'\u904A\u6232\u63A7\u5236\u5668'\u5206\u9801\u4E0B\u65B9\u7684'\u9078\u64C7\u6A94\u6848'\u6309\u9215\u529F\u80FD: \u7531\u539F\u5148\u7684\u500B\u5225\u6A94\u6848\u9032\u884C\u9010\u4E00\u9078\u53D6\uFF0C\u53D6\u4EE3\u70BA\u4E00\u6B21\u52A0\u5165\u6307\u5B9A\u8CC7\u6599\u593E\u5167\u7B26\u5408\u7684\u6240\u6709\u6A94\u6848.
|
||||
windowTitleAddingFiles=\u6B63\u5728\u52A0\u5165\u4F47\u5217...
|
||||
windowBodyFilesScanned=\u6A94\u6848\u5DF2\u6383\u63CF:%25d\n \u5DF2\u52A0\u5165: %25d
|
||||
tab2_Lbl_AwooBlockTitle=Awoo Installer \u8207\u540C\u985E\u578B\u7A0B\u5F0F
|
||||
tabRcm_Lbl_Payload=Payload:
|
||||
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM
|
||||
|
||||
|
|
|
@ -5,6 +5,18 @@
|
|||
-fx-background: #2d2d2d;
|
||||
}
|
||||
|
||||
Text {
|
||||
-fx-fill: white;
|
||||
}
|
||||
|
||||
.bold-text{
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.italic-text{
|
||||
-fx-font-style: italic;
|
||||
}
|
||||
|
||||
.button, .buttonUp, .buttonStop, .buttonSelect{
|
||||
-fx-background-color: #4f4f4f;
|
||||
-fx-border-color: #4f4f4f;
|
||||
|
@ -235,21 +247,31 @@
|
|||
-fx-border-width: 2;
|
||||
}
|
||||
|
||||
.list-cell, .list-cell:selected, .list-cell:filled:selected{
|
||||
.list-cell:even,
|
||||
.list-cell:even:selected,
|
||||
.list-cell:even:filled:selected{
|
||||
-fx-background-color: -fx-table-cell-border-color, #424242;
|
||||
-fx-background-insets: 0, 0 0 1 0;
|
||||
-fx-table-cell-border-color: #6d8484;
|
||||
}
|
||||
.list-cell:odd, .list-cell:odd:selected, .list-cell:odd:filled:selected{
|
||||
.list-cell:odd,
|
||||
.list-cell:odd:selected,
|
||||
.list-cell:odd:filled:selected{
|
||||
-fx-background-color: -fx-table-cell-border-color, #4f4f4f;
|
||||
-fx-background-insets: 0, 0 0 1 0;
|
||||
-fx-table-cell-border-color: #6d8484;
|
||||
}
|
||||
|
||||
.list-cell .text, .list-cell:odd .text{
|
||||
.list-cell .text,
|
||||
.list-cell:odd .text,
|
||||
.list-cell Text,
|
||||
.list-cell:odd Text{
|
||||
-fx-fill: #f7fafa;
|
||||
}
|
||||
.list-cell:filled:selected .text, .list-cell:odd:filled:selected .text{
|
||||
.list-cell:filled:selected .text,
|
||||
.list-cell:odd:filled:selected .text,
|
||||
.list-cell:filled:selected Text,
|
||||
.list-cell:odd:filled:selected Text{
|
||||
-fx-fill: #08f3ff;
|
||||
}
|
||||
/* -========================== Context menu =====================- */
|
||||
|
@ -409,6 +431,13 @@
|
|||
-fx-min-height: 24;
|
||||
-fx-min-width: 36;
|
||||
}
|
||||
.regionCake{
|
||||
-fx-shape: "M4,8H8V4A2,2 0 0,1 10,2H14A2,2 0 0,1 16,4V8H20A2,2 0 0,1 22,10V14A2,2 0 0,1 20,16H16V20A2,2 0 0,1 14,22H10A2,2 0 0,1 8,20V16H4A2,2 0 0,1 2,14V10A2,2 0 0,1 4,8Z";
|
||||
-fx-background-color: #71e016;
|
||||
-size: 24;
|
||||
-fx-min-height: -size;
|
||||
-fx-min-width: -size;
|
||||
}
|
||||
.regionDump{
|
||||
-fx-shape: "M 4.0078125 0 C 1.5078125 0 0 1.4882812 0 3.984375 L 0 15.988281 C 0 18.417969 1.4927148 20 4.0078125 20 L 6.5 20 L 6.5 0 L 4.0078125 0 z M 23.5 0 L 23.5 20 C 24.504057 19.999294 25.159942 20 25.992188 20 C 28.414062 20 30 18.496094 30 15.996094 L 30 3.9765625 C 30 1.5195311 28.508726 0 26.003906 0 L 23.5 0 z M 11.990234 2.8886719 L 11.990234 9.9003906 L 6.9902344 9.9003906 L 14.990234 20 L 22.990234 9.9003906 L 17.990234 9.9003906 C 17.990234 8.2387016 17.9999 3.6538029 18 2.8886719 L 11.990234 2.8886719 z M 3.1015625 2.9570312 C 4.1485235 2.9562481 4.9977514 3.8046013 4.9980469 4.8515625 C 4.998831 5.8992865 4.1492865 6.7488309 3.1015625 6.7480469 C 2.0546013 6.7477509 1.2062483 5.8985235 1.2070312 4.8515625 C 1.2073268 3.8053642 2.0553642 2.9573267 3.1015625 2.9570312 z M 26.865234 11.148438 C 27.912958 11.147652 28.762503 11.997198 28.761719 13.044922 C 28.761423 14.091883 27.912195 14.940236 26.865234 14.939453 C 25.819036 14.939158 24.970999 14.09112 24.970703 13.044922 C 24.96992 11.997961 25.818273 11.148733 26.865234 11.148438 z ";
|
||||
-fx-background-color: #71e016;
|
||||
|
@ -438,6 +467,7 @@
|
|||
}
|
||||
.nxdt.label .text {
|
||||
-fx-fill: #cb0010;
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.regionWindows {
|
||||
|
@ -461,7 +491,39 @@
|
|||
-fx-min-height: -size;
|
||||
-fx-min-width: 24;
|
||||
}
|
||||
//
|
||||
/********************* Spinner **************************/
|
||||
.spinner{
|
||||
-fx-background-color: #4f4f4f;
|
||||
-fx-border-radius: 3;
|
||||
-fx-border-width: 1;
|
||||
-fx-border-color: #4f4f4f;
|
||||
-fx-mark-color: #eea11e;
|
||||
-fx-effect: none;
|
||||
}
|
||||
|
||||
.spinner .increment-arrow-button,
|
||||
.spinner .decrement-arrow-button {
|
||||
-fx-background-radius: 0;
|
||||
-fx-background-color: #4f4f4f;
|
||||
}
|
||||
|
||||
.spinner .increment-arrow-button:hover .increment-arrow,
|
||||
.spinner .decrement-arrow-button:hover .decrement-arrow {
|
||||
-fx-background-color: #ff8000;
|
||||
}
|
||||
|
||||
.spinner .increment-arrow-button:hover:pressed .increment-arrow,
|
||||
.spinner .decrement-arrow-button:hover:pressed .decrement-arrow,
|
||||
.spinner .increment-arrow-button:pressed .increment-arrow,
|
||||
.spinner .decrement-arrow-button:pressed .decrement-arrow {
|
||||
-fx-background-color: #71e016;
|
||||
}
|
||||
|
||||
.spinner .increment-arrow-button .increment-arrow,
|
||||
.spinner .decrement-arrow-button .decrement-arrow {
|
||||
-fx-background-color: #eea11e;
|
||||
}
|
||||
|
||||
//.lineGradient {
|
||||
// -fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #00c8fc 30%, transparent 45%);
|
||||
//}
|
|
@ -5,6 +5,18 @@
|
|||
-fx-background: #ebebeb;
|
||||
}
|
||||
|
||||
Text {
|
||||
-fx-fill: black;
|
||||
}
|
||||
|
||||
.bold-text{
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.italic-text{
|
||||
-fx-font-style: italic;
|
||||
}
|
||||
|
||||
.button, .buttonUp, .buttonStop, .buttonSelect{
|
||||
-fx-background-color: #fefefe;
|
||||
-fx-background-insets: 0 0 0 0, 0, 1, 2;
|
||||
|
@ -253,23 +265,35 @@
|
|||
-fx-border-width: 2;
|
||||
}
|
||||
|
||||
.list-cell, .list-cell:selected, .list-cell:filled:selected{
|
||||
.list-cell:even{
|
||||
-fx-background-color: -fx-table-cell-border-color, #ebfffe;
|
||||
-fx-background-insets: 0, 0 0 1 0;
|
||||
-fx-table-cell-border-color: #b0b0b0;
|
||||
}
|
||||
.list-cell:odd, .list-cell:odd:selected, .list-cell:odd:filled:selected{
|
||||
.list-cell:odd{
|
||||
-fx-background-color: -fx-table-cell-border-color, #fefefe;
|
||||
-fx-background-insets: 0, 0 0 1 0;
|
||||
-fx-table-cell-border-color: #b0b0b0;
|
||||
}
|
||||
|
||||
.list-cell .text, .list-cell:odd .text{
|
||||
.list-cell:even:selected,
|
||||
.list-cell:even:filled:selected,
|
||||
.list-cell:odd:selected,
|
||||
.list-cell:odd:filled:selected{
|
||||
-fx-background-color: -fx-table-cell-border-color, #e4ffde;
|
||||
}
|
||||
|
||||
.list-cell .text,
|
||||
.list-cell:odd .text,
|
||||
.list-cell Text,
|
||||
.list-cell:odd Text{
|
||||
-fx-fill: #2c2c2c;
|
||||
}
|
||||
.list-cell:filled:selected .text, .list-cell:odd:filled:selected .text{
|
||||
.list-cell:filled:selected .text,
|
||||
.list-cell:odd:filled:selected .text,
|
||||
.list-cell:filled:selected Text,
|
||||
.list-cell:odd:filled:selected Text{
|
||||
-fx-fill: #2c2c2c;
|
||||
-fx-font-weight: bold
|
||||
}
|
||||
/* -========================= Separator ===================- */
|
||||
.separator *.line {
|
||||
|
@ -327,6 +351,13 @@
|
|||
-fx-min-height: 24;
|
||||
-fx-min-width: 36;
|
||||
}
|
||||
.regionCake{
|
||||
-fx-shape: "M4,8H8V4A2,2 0 0,1 10,2H14A2,2 0 0,1 16,4V8H20A2,2 0 0,1 22,10V14A2,2 0 0,1 20,16H16V20A2,2 0 0,1 14,22H10A2,2 0 0,1 8,20V16H4A2,2 0 0,1 2,14V10A2,2 0 0,1 4,8Z";
|
||||
-fx-background-color: #71e016;
|
||||
-size: 24;
|
||||
-fx-min-height: -size;
|
||||
-fx-min-width: -size;
|
||||
}
|
||||
.regionDump{
|
||||
-fx-shape: "M 4.0078125 0 C 1.5078125 0 0 1.4882812 0 3.984375 L 0 15.988281 C 0 18.417969 1.4927148 20 4.0078125 20 L 6.5 20 L 6.5 0 L 4.0078125 0 z M 23.5 0 L 23.5 20 C 24.504057 19.999294 25.159942 20 25.992188 20 C 28.414062 20 30 18.496094 30 15.996094 L 30 3.9765625 C 30 1.5195311 28.508726 0 26.003906 0 L 23.5 0 z M 11.990234 2.8886719 L 11.990234 9.9003906 L 6.9902344 9.9003906 L 14.990234 20 L 22.990234 9.9003906 L 17.990234 9.9003906 C 17.990234 8.2387016 17.9999 3.6538029 18 2.8886719 L 11.990234 2.8886719 z M 3.1015625 2.9570312 C 4.1485235 2.9562481 4.9977514 3.8046013 4.9980469 4.8515625 C 4.998831 5.8992865 4.1492865 6.7488309 3.1015625 6.7480469 C 2.0546013 6.7477509 1.2062483 5.8985235 1.2070312 4.8515625 C 1.2073268 3.8053642 2.0553642 2.9573267 3.1015625 2.9570312 z M 26.865234 11.148438 C 27.912958 11.147652 28.762503 11.997198 28.761719 13.044922 C 28.761423 14.091883 27.912195 14.940236 26.865234 14.939453 C 25.819036 14.939158 24.970999 14.09112 24.970703 13.044922 C 24.96992 11.997961 25.818273 11.148733 26.865234 11.148438 z ";
|
||||
-fx-background-color: #71e016;
|
||||
|
@ -356,6 +387,7 @@
|
|||
}
|
||||
.nxdt.label .text {
|
||||
-fx-fill: #9d010e;
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
.regionWindows {
|
||||
-fx-shape: "M3,12V6.75L9,5.43V11.91L3,12M20,3V11.75L10,11.9V5.21L20,3M3,13L9,13.09V19.9L3,18.75V13M20,13.25V22L10,20.09V13.1L20,13.25Z";
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* Copyright WTFPL */
|
||||
package integration;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Environment {
|
||||
public final String CONTAINER = "environment.txt";
|
||||
|
||||
private String atmosphere;
|
||||
private String prodkeys;
|
||||
private String firmwares;
|
||||
private String saveTo;
|
||||
|
||||
public Environment() throws Exception{
|
||||
if (Files.notExists(Path.of(CONTAINER))) {
|
||||
boolean createdTemplate = createTemplate();
|
||||
throw new Exception("'environment.txt' not found\n" +
|
||||
"Please "+(createdTemplate?"":"create and ") +
|
||||
"set values in file");
|
||||
}
|
||||
|
||||
read();
|
||||
|
||||
if (isNotValid())
|
||||
throw new Exception("'environment.txt' doesn't contain valid data\n");
|
||||
}
|
||||
private void read() throws Exception{
|
||||
HashMap<String, String> rawKeySet = new HashMap<>();
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(CONTAINER))) {
|
||||
String fileLine;
|
||||
String[] keyValue;
|
||||
while ((fileLine = br.readLine()) != null) {
|
||||
keyValue = fileLine.trim().split("\\s+?=\\s+?", 2);
|
||||
if (keyValue.length == 2)
|
||||
rawKeySet.put(keyValue[0], keyValue[1]);
|
||||
}
|
||||
}
|
||||
|
||||
atmosphere = rawKeySet.get("ATMOSPHERE");
|
||||
prodkeys = rawKeySet.get("PRODKEYS");
|
||||
firmwares = rawKeySet.get("NS_GLOBAL_FIRMWARES");
|
||||
saveTo = rawKeySet.get("SAVE_TO");
|
||||
}
|
||||
private boolean isNotValid(){
|
||||
return atmosphere == null || atmosphere.isBlank() ||
|
||||
prodkeys == null || prodkeys.isBlank() ||
|
||||
firmwares == null || firmwares.isBlank();
|
||||
}
|
||||
private boolean createTemplate(){
|
||||
try(FileWriter writer = new FileWriter(CONTAINER)){
|
||||
writer.write(
|
||||
"ATMOSPHERE = \n" +
|
||||
"PRODKEYS = \n" +
|
||||
"NS_GLOBAL_FIRMWARES = \n" +
|
||||
"SAVE_TO = /tmp");
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getAtmosphereLocation() {
|
||||
return atmosphere;
|
||||
}
|
||||
|
||||
public String getProdkeysLocation() {
|
||||
return prodkeys;
|
||||
}
|
||||
|
||||
public String getFirmwaresLocation() {
|
||||
return firmwares;
|
||||
}
|
||||
|
||||
public String getSaveToLocation() {
|
||||
return saveTo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* Copyright WTFPL */
|
||||
package integration;
|
||||
|
||||
import nsusbloader.NSLMain;
|
||||
import nsusbloader.Utilities.patches.es.EsPatchMaker;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Disabled
|
||||
public class EsIntegrationTest {
|
||||
static String pathToFirmware;
|
||||
static String pathToFirmwares;
|
||||
static String pathToKeysFile;
|
||||
static String saveTo;
|
||||
|
||||
@BeforeAll
|
||||
static void init() throws Exception{
|
||||
NSLMain.isCli = true;
|
||||
Environment environment = new Environment();
|
||||
pathToKeysFile = environment.getProdkeysLocation();
|
||||
saveTo = environment.getSaveToLocation() + File.separator + "ES_LPR";
|
||||
pathToFirmwares = environment.getFirmwaresLocation();
|
||||
pathToFirmware = pathToFirmware + File.separator + "Firmware 14.1.0";
|
||||
}
|
||||
|
||||
@DisplayName("ES Integration validation - everything")
|
||||
@Test
|
||||
void makeEss() throws Exception{
|
||||
File[] fwDirs = new File(pathToFirmwares).listFiles((file, s) -> {
|
||||
return s.matches("^Firmware (9\\.|[0-9][0-9]\\.).*");
|
||||
//return s.matches("^Firmware 10.0.1.*");
|
||||
});
|
||||
assert fwDirs != null;
|
||||
Arrays.sort(fwDirs);
|
||||
for (File dir : fwDirs){
|
||||
EsPatchMaker esPatchMaker = new EsPatchMaker(dir.getAbsolutePath(), pathToKeysFile, saveTo);
|
||||
Thread workThread = new Thread(esPatchMaker);
|
||||
workThread.start();
|
||||
workThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("ES Integration validation - one particular firmware")
|
||||
@Test
|
||||
void makeEs() throws Exception{
|
||||
EsPatchMaker esPatchMaker = new EsPatchMaker(pathToFirmware, pathToKeysFile, saveTo);
|
||||
Thread workThread = new Thread(esPatchMaker);
|
||||
workThread.start();
|
||||
workThread.join();
|
||||
}
|
||||
}
|