Compare commits

...

75 commits
v6.1 ... master

Author SHA1 Message Date
Dmitry Isaenko d382181700 Update architecture. Change mediator, add simple observer to track active 'transfers' 2024-05-27 19:15:04 +03:00
Dmitry Isaenko 5ee9f6aacd
Merge pull request #160 from secretjupiter/patch-1
All checks were successful
continuous-integration/drone Build is passing
Added mandatory info to README.md for Apple Silicon users
2024-02-07 13:07:53 +03:00
Dmitry Isaenko 7f9b3a7598
Merge pull request #161 from Erimsaholut/master
Turkish Lang file
2024-02-07 13:07:24 +03:00
01ut cd9e3ddf30
Turkish Lang file
I just upload the .properties file
2024-02-03 16:05:11 +03:00
Kevin | Secret Jupiter d1ac1f5403
Added mandatory info to README.md for Apple Silicon users
Added mandatory info for Apple Silicon users
2024-01-28 22:00:45 +01:00
Dmitry Isaenko e9b0fa309e Merge remote-tracking branch 'origin/master'
All checks were successful
continuous-integration/drone Build is passing
2023-12-26 14:39:31 +03:00
Dmitry Isaenko c0bf247666 Bundle drivers to windows installer #156 2023-12-26 14:39:05 +03:00
Dmitry Isaenko 66758ffdb9
Merge pull request #154 from justindhillon/broken-links
Fix Broken Links
2023-11-15 18:01:36 +03:00
Justin Dhillon b32986682e revert maven.apache.org link 2023-11-11 12:49:17 -08:00
Justin Dhillon 2935d4ef55 revert broken link 2023-11-11 12:48:21 -08:00
Justin Dhillon 353b058388 revert Swarsele 2023-11-08 09:13:44 -08:00
Justin Dhillon 5b3ea13b08 revert Stephane Meden (JackFromNice) 2023-11-08 09:12:22 -08:00
Justin Dhillon 1251d39a6b revert Adubbz/Tinfoil 2023-11-08 09:11:36 -08:00
Justin Dhillon 57e7f72531
Merge branch 'developersu:master' into broken-links 2023-11-08 09:08:38 -08:00
Dmitry Isaenko 88ca0815ed Properly disable integration tests
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-08 15:08:24 +03:00
Dmitry Isaenko 66e7338fa5 Save few integration tests
Some checks failed
continuous-integration/drone/push Build is failing
2023-11-08 14:35:15 +03:00
Dmitry Isaenko fa236cb1ad Correct Goldleaf supported versions list 2023-11-08 14:34:00 +03:00
Justin Dhillon 5b120204ef fixed broken link 2023-11-07 10:10:24 -08:00
Justin Dhillon 94ad332bf7 fixed broken link to maven.apache.org/POM/4.0.0 2023-11-07 10:05:17 -08:00
Justin Dhillon b89bfa806d fixed broken link to github user developersu 2023-11-07 09:59:17 -08:00
Justin Dhillon abf7621f28 github account does not exist anymore, so I replaced the link with instagram 2023-11-07 09:57:50 -08:00
Justin Dhillon c5688f79df replaced missing github repo link with link to creator 2023-11-07 09:56:31 -08:00
Justin Dhillon 25910ac94c fixed broken website link 2023-11-07 09:55:05 -08:00
Justin Dhillon 474f90a427 replaced 404 github link to twitter profile 2023-11-07 09:52:55 -08:00
Dmitry Isaenko 8348c9f2ab Correct 'Font settings' window size.
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-30 00:09:27 +03:00
Dmitry Isaenko 47045b2aeb correct version
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-29 06:29:33 +03:00
Dmitry Isaenko 67351642ae Merge remote-tracking branch 'origin/master'
Some checks failed
continuous-integration/drone Build is failing
2023-10-29 06:16:10 +03:00
Dmitry Isaenko 3909371774 Add fonts selector for #153 2023-10-29 06:15:43 +03:00
Dmitry Isaenko 1e4593afb6
Merge pull request #145 from DDinghoya/patch-7
All checks were successful
continuous-integration/drone/push Build is passing
Update locale_ko_KR.properties
2023-06-02 15:54:55 +03:00
DDinghoya d3faa384ae
Update locale_ko_KR.properties 2023-05-30 23:32:29 +09:00
Dmitry Isaenko 9d4cac26e5
Merge pull request #144 from requinDr/patch-1
All checks were successful
continuous-integration/drone/push Build is passing
Update locale_fr_FR.properties
2023-05-17 16:32:32 +03:00
requinDr ad211cd562
\N -> \n 2023-05-17 00:16:11 +02:00
requinDr 4bdc5ffb63
Update locale_fr_FR.properties
Add missings translations and missing accents to French (note that a few translations are still missing)
2023-05-17 00:14:00 +02:00
Dmitry Isaenko 7db7af0cf8
Merge pull request #140 from exiori/patch-1
All checks were successful
continuous-integration/drone/push Build is passing
Update locale_zh_CN.properties
2023-04-15 14:24:13 +03:00
exiori 6052d385d9
Update locale_zh_CN.properties 2023-04-15 17:00:46 +08:00
exiori f6b875af0b
Update locale_zh_CN.properties
Update Dialog Tips
2023-04-05 10:58:17 +08:00
Dmitry Isaenko 01a25f071a Make CI output a bit more verbose
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-17 04:27:09 +03:00
Dmitry Isaenko c1651e874b Correct AppPreferences class. Fix #139
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-17 04:00:48 +03:00
Dmitry Isaenko 94845c1411 readme update
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-09 04:12:28 +03:00
Dmitry Isaenko 7cf3970aa7 Fix CI
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2023-02-10 21:23:22 +03:00
Dmitry Isaenko 5b69435e89 Setup builds for M1
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-10 21:09:26 +03:00
Dmitry Isaenko b463a63180 Fix 'class file version' mismatch. Aligned to Java11
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-10 03:15:58 +03:00
Dmitry Isaenko cbb9fd60b9 Correct CSS
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-09 18:16:10 +03:00
Dmitry Isaenko 5f0278fc7b Fix pom.xml
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-09 17:22:22 +03:00
Dmitry Isaenko 3981d0d8ca Merge remote-tracking branch 'origin/master'
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-09 15:26:32 +03:00
Dmitry Isaenko 29f29b7d31 Minor fixes 2023-02-09 15:25:13 +03:00
Dmitry Isaenko 38f495ebc1 Correct pom.xml
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-08 17:43:38 +03:00
Dmitry Isaenko 4d7c6f6ef1 Merge remote-tracking branch 'origin/master'
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-08 02:31:05 +03:00
Dmitry Isaenko 7f01805cd5 Fix CI+3: Append timestamps to installer artifact
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-08 02:21:55 +03:00
Dmitry Isaenko f82275e82d Fix CI+2
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-08 01:58:27 +03:00
Dmitry Isaenko 2356bfe0e9 Fix CI+1
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-08 01:50:27 +03:00
Dmitry Isaenko fc02a8af6b Fix CI
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-08 01:32:45 +03:00
Dmitry Isaenko c408f70b79 Switch to Java 11. Add win installer
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-08 01:15:30 +03:00
Dmitry Isaenko c39a5f4c5b Correct Java 8 related things
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-07 00:05:13 +03:00
Dmitry Isaenko ffa9c6903f https for secure!
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-06 16:21:11 +03:00
Dmitry Isaenko c34531a92f Fix dependencies resolution
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-06 16:16:03 +03:00
Dmitry Isaenko 83695511d3 Hide 'extended network settings' instead of setting it disabled
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-06 02:00:05 +03:00
Dmitry Isaenko c84f70ec10 "Installs Split NSP/XCI/NSZ/XCZ over Lan or USB", not only NSP. Also breaking every locale
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-04 17:05:57 +03:00
Dmitry Isaenko 6c51b8e1b6 Corrections at front and back end
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-04 15:25:34 +03:00
Dmitry Isaenko f8b60af41b FS drafts
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-01 12:44:45 +03:00
Dmitry Isaenko 4ccf833aa5 Fix issue where version was not showing in CLI mode; clear locale_en_US since it's just placeholder
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-26 07:59:56 +03:00
Dmitry Isaenko a60d929dcd Update readme
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-23 21:53:34 +03:00
Dmitry Isaenko 338bb699d1 Another one build-system-related fix
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-23 07:47:10 +03:00
Dmitry Isaenko 115625e3a3 Correct drone config to archive Launch4j artifact
Some checks failed
continuous-integration/drone/push Build is failing
2022-12-23 07:22:24 +03:00
Dmitry Isaenko 55df39923f Correct readme, update few icons, add freedesktop entry and svg icon. Could be useful for packagers.
Some checks failed
continuous-integration/drone/push Build is failing
2022-12-23 07:08:22 +03:00
Dmitry Isaenko 8b23b8967b Correct locales logic to get some kind of ISO 639-3 support, update pom, make ja_ryu appear (unfortunately as 'Japanese' language and not as 'Central Okinawan')
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-11 17:04:55 +03:00
Dmitry Isaenko 9aa4551ef0
Merge pull request #130 from kuragehimekurara1/master
All checks were successful
continuous-integration/drone/push Build is passing
Added Japanese translation and Ryukyuan language translation
2022-10-11 15:17:12 +03:00
kuragehime 610d04c9bd
Update locale_ja_ryu.properties 2022-10-08 03:24:08 +09:00
kuragehime 9b02750dd3
Update locale_ja_ryu.properties 2022-10-08 03:10:04 +09:00
kuragehime 89dd6fdbe0
Update locale_ja_JP.properties 2022-10-08 02:53:51 +09:00
kuragehime b75421bc9e
Update locale_ja_ryu.properties 2022-10-08 01:35:32 +09:00
kuragehime cc09128373
Update locale_ja_JP.properties 2022-10-08 01:02:16 +09:00
kuragehime 6244fd974a
Update locale_ja_JP.properties 2022-10-07 01:35:21 +09:00
kuragehime 2edea43d63
Create locale_ja_ryu.properties 2022-10-06 17:13:01 +09:00
kuragehime c9dbb37c14
Create locale_ja_JP.properties 2022-10-06 17:06:49 +09:00
109 changed files with 6823 additions and 914 deletions

View file

@ -4,7 +4,7 @@ name: default
steps: steps:
- name: test - name: test
image: maven:3-jdk-11 image: maven:3-openjdk-17
commands: commands:
- mvn -B -DskipTests clean package - mvn -B -DskipTests clean package
- mvn test -B - mvn test -B
@ -16,16 +16,38 @@ steps:
image: alpine:latest image: alpine:latest
commands: commands:
- mkdir -p /builds/ns-usbloader - mkdir -p /builds/ns-usbloader
- echo target/ns-usbloader-*jar
- cp target/ns-usbloader-*jar /builds/ns-usbloader/ - cp target/ns-usbloader-*jar /builds/ns-usbloader/
volumes: volumes:
- name: builds - name: builds
path: /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 - name: emerge-legacy-artifact
image: maven:3-jdk-11 image: maven:3-openjdk-17
commands: commands:
- . ./.make_legacy - . ./.make_legacy
- mvn -B -DskipTests clean package - mvn -B -DskipTests clean package
- echo target/ns-usbloader-*jar
- cp target/ns-usbloader-*jar /builds/ns-usbloader/ - cp target/ns-usbloader-*jar /builds/ns-usbloader/
volumes: volumes:
- name: m2 - name: m2
@ -33,6 +55,37 @@ steps:
- name: builds - name: builds
path: /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: volumes:
- name: m2 - name: m2
host: host:
@ -40,3 +93,9 @@ volumes:
- name: builds - name: builds
host: host:
path: /home/www/builds 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

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
offsets.txt
environment.txt

View file

@ -1,2 +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/<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/<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

5
.make_m1 Normal file
View file

@ -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

View file

@ -1,9 +1,9 @@
# 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) [![Build Status](https://ci.redrise.ru/api/badges/desu/ns-usbloader/status.svg)](https://ci.redrise.ru/desu/ns-usbloader) ![License](https://img.shields.io/badge/License-GPLv3-blue.svg) ![Releases](https://img.shields.io/github/downloads/developersu/ns-usbloader/total.svg) ![LatestVer](https://img.shields.io/github/release/developersu/ns-usbloader.svg) [![Build Status](https://ci.redrise.ru/api/badges/desu/ns-usbloader/status.svg)](https://ci.redrise.ru/desu/ns-usbloader)
NS-USBloader is: 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**. Alternative to default **usb_install_pc.py**, **remote_install_pc.py**, **GoldTree**/**Quark**.
* RCM payload tool that works on Windows, macOS (Intel and Apple Silicon) and Linux (x86, amd64 and Raspberry Pi ARM). * 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! * It's a tool for creating split files!
@ -22,9 +22,9 @@ With GUI and cookies. Works on Windows, macOS and Linux.
Sometimes I add new posts about this project [on my blog page](https://developersu.blogspot.com/search/label/NS-USBloader). Sometimes I add new posts about this project [on my blog page](https://developersu.blogspot.com/search/label/NS-USBloader).
![Application screenshot](screenshots/1.png) <img src="screenshots/1.png" alt="screenshot" width="250"/> <img src="screenshots/2.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/3.png" alt="screenshot" width="250"/> <img src="screenshots/4.png" alt="screenshot" width="250"/>
<img src="screenshots/4.png" alt="screenshot" width="250"/> <img src="screenshots/5.png" alt="screenshot" width="250"/> <img src="screenshots/5.png" alt="screenshot" width="250"/>
#### License #### License
@ -42,36 +42,41 @@ Sometimes I add new posts about this project [on my blog page](https://developer
* [Pablo Curiel (DarkMatterCore)](https://github.com/DarkMatterCore) * [Pablo Curiel (DarkMatterCore)](https://github.com/DarkMatterCore)
* [wolfposd](https://github.com/wolfposd) * [wolfposd](https://github.com/wolfposd)
* [agungrbudiman](https://github.com/agungrbudiman) * [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) * French by [Stephane Meden (JackFromNice)](https://github.com/JackFromNice)
* Italian by [unbranched](https://github.com/unbranched) * Italian by [unbranched](https://github.com/unbranched)
* Korean by [DDinghoya](https://github.com/DDinghoya) * Korean by [DDinghoya](https://github.com/DDinghoya)
* Portuguese by [almircanella](https://github.com/almircanella) * Portuguese by [almircanella](https://github.com/almircanella)
* Spanish by [/u/cokimaya007](https://www.reddit.com/u/cokimaya007), [Kuziel Alejandro](https://github.com/Uzi-Oni) * 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)](https://www.xxgame.net) * 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)](https://www.xxgame.net) * Chinese (Traditional) by [qazrfv1234](https://github.com/qazrfv1234), [FFT9 (XXgame Group)](http://xxgame.net/)
* German by [Swarsele](https://github.com/Swarsele) * German by [Swarsele](https://github.com/Swarsele)
* Vietnamese by [Hai Phan Nguyen (pnghai)](https://github.com/pnghai) * Vietnamese by [Hai Phan Nguyen (pnghai)](https://github.com/pnghai)
* Czech by [Spenaat](https://github.com/spenaat) * Czech by [Spenaat](https://github.com/spenaat)
* Arabic by [eslamabdel](https://github.com/eslamabdel) * Arabic by [eslamabdel](https://github.com/eslamabdel)
* Romanian by [Călin Ilie](https://github.com/calini) * Romanian by [Călin Ilie](https://github.com/calini)
* Swedish by [Daniel Nylander](https://github.com/yeager) - (coming soon) * 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 ### 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.5 | v0.4 - v0.5.2, v0.8+ |
| v0.6 | none | | v0.6 | none |
| v0.6.1 | v0.6 | | v0.6.1 | v0.6 |
| v0.7 - 0.7.3 | v0.7+ | | v0.7 - 0.7.3 | v0.7+ |
| v0.8 - 0.9 | v1.0+ | | v0.8 - 0.9 | v1.0+ |
| v0.10 | v6.0 | | v0.10 | v6.0+ |
where '+' means 'any next NS-USBloader version'. where '+' means 'any next NS-USBloader version'.
@ -117,24 +122,23 @@ Double-click on downloaded .jar file. Follow instructions. Or see 'Linux' sectio
Set 'Security & Privacy' settings if needed. Set 'Security & Privacy' settings if needed.
*Please note: JDK 11 is recommended for using on MacOS (EXCEPT APPLE SILICON). 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) ##### 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! Download application with `-m1.jar` postfix.
* OpenJDK 17 also should be a working solution. [Tell us if it works for you!]((https://github.com/developersu/ns-usbloader/issues/91))
Manually install libusb with Homebrew by running `brew install libusb` in your Terminal.
##### Windows: ##### Windows:
* [Download and install Java JRE](http://java.com/download/) (8u60 or higher)
* Get this application (JAR file) and double-click 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. * Once application opens click on 'Gear' icon.
* Click 'Download and install drivers' * Click 'Download and install drivers'
* Install drivers * Install drivers
#### And how to use it? #### 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. 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.
@ -144,19 +148,19 @@ There are three tabs. First one is main.
##### 'Gamepad' tab. ##### '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. 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. 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 ##### 'RCM' tab
@ -172,7 +176,7 @@ Here you can configure settings for network file transmission. Usually you shoul
Also here you can: 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 '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. ##### 'Dialog with three dots' tab.
@ -185,7 +189,7 @@ To get help run ``$ java -jar ns-usbloader-4.0.jar --help``
``` ```
-c,--clean Remove/reset settings and exit -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 -h,--help Show this help
-m,--merge <...> Merge files. Check '-m help' for information. -m,--merge <...> Merge files. Check '-m help' for information.
-n,--tfn <...> Install via Awoo Network mode. Check '-n help' for information. -n,--tfn <...> Install via Awoo Network mode. Check '-n help' for information.
@ -216,7 +220,7 @@ Send RCM payload:
$ java -jar ns-usbloader-4.0.jar -r C:\Users\Superhero\hekate.bin $ java -jar ns-usbloader-4.0.jar -r C:\Users\Superhero\hekate.bin
Send files to Awoo Installer via Net-install: 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 $ 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 ./* $ java -jar ns-usbloader-4.0.jar -g ver=v0.8 ./*
Split files: Split files:
$ java -jar ns-usbloader-4.0.jar -s /tmp/ ~/*.nsp $ java -jar ns-usbloader-4.0.jar -s /tmp/ ~/*.nsp
@ -227,14 +231,14 @@ $ java -jar ns-usbloader-4.0.jar -m /tmp/ ~/*.nsp
### Other notes ### 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. 'Status' = 'Uploaded' that appears in the table does not mean that file has been installed. It means that it has been sent to NS without any issues! That's what this app about.
Handling successful/failed installation is a purpose of the other side application: Awoo/Awoo-like or GoldLeaf. And they don't provide any feedback interfaces so I can't detect success/failure. Handling successful/failed installation is a purpose of the other side application: Awoo/Awoo-like or Goldleaf. And they don't provide any feedback interfaces so I can't detect success/failure.
#### What is this '-legacy' jar?! #### 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 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. **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). (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 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
@ -254,17 +258,14 @@ This is non-commercial project.
Nevertheless, I'll be more than happy if you find a chance to make a donation for charity to people I trust: Nevertheless, I'll be more than happy if you find a chance to make a donation for charity to people I trust:
* BTC → bc1q67j4yjmt67mes0hv03fyydjejmw6ahw0v932su * BTC → 1BnErE3n6LEdEjvvFrt4FMdXd1UGa5L7Ge
* ETH → 0x82Ab0ddE183C12cAa6eD61DF3671675C4bdC42fc * ETH → 0x9c29418129553bE171181bb6245151aa0576A3b7
* DOGE → D8o42b952yjEWZ5Ajq4ZtjGvx1kR7DyDHm * DOT → 15BWSwmA4xEHZdq3gGftWg7dctMQk9vXwqA92Pg22gsxDweF
* DOT → 1511KQqm6Mme5Za4rtgsSdzCyuEzQ6CC1a6XLxQJXXW3GWpo * LTC → ltc1qfjvzxm04tax077ra9rvmxdnsum8alws2n20fag
* LTC → LRFXTN4rTEiQ3RxzssMFC5S1WMRd1raN2Q * ETC → 0xe9064De288C8454942533a005AB72515e689226E
* LUNA → terra1n0sfmljpuu87h7lrn9nzxadfa3qxthlmvtq5lf * USDT (TRC20) → TKgp5SvJGiqYNFtvJfEDGLFbezFEHq1tBy
* TRX → TU3AyFkF12Jg1yApcXGz91R8xKvXV1EzkW * USDT (ERC20) → 0x9c29418129553bE171181bb6245151aa0576A3b7
* ETC → 0x78A946fC9708c024298c9a4f8961A49B7a830d53 * XRP → rGmGaLsKmSUbxWfyi4mujtVamTzj3Nqxbw.
* USDT (TRC20) → TU3AyFkF12Jg1yApcXGz91R8xKvXV1EzkW
* USDT (ERC20) → 0x82Ab0ddE183C12cAa6eD61DF3671675C4bdC42fc
* XRP → r91kfRiRsvnDp7evHNmXkrL3yAL7eakWk1
Thanks! Thanks!

View file

@ -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;

View file

@ -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

View file

@ -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'

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

File diff suppressed because it is too large Load diff

BIN
misc/windows/NSIS/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

13
misc/windows/update_version.sh Executable file
View file

@ -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

138
pom.xml
View file

@ -8,12 +8,10 @@
<name>NS-USBloader</name> <name>NS-USBloader</name>
<artifactId>ns-usbloader</artifactId> <artifactId>ns-usbloader</artifactId>
<version>6.1</version> <version>7.1</version> <!-- linked via script to NSIS system. Should have format of 2 blocks of numbers -->
<url>https://redrise.ru</url> <url>https://redrise.ru</url>
<description> <description>NS multi-tool</description>
NS multi-tool
</description>
<inceptionYear>2019</inceptionYear> <inceptionYear>2019</inceptionYear>
<organization> <organization>
<name>Dmitry Isaenko</name> <name>Dmitry Isaenko</name>
@ -40,16 +38,25 @@
</developer> </developer>
</developers> </developers>
<repositories>
<repository>
<id>redrise</id>
<name>redrise.ru repository</name>
<url>https://repo.redrise.ru/releases</url>
</repository>
</repositories>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.build.timestamp.format>yyyyMMdd.HHmmss</maven.build.timestamp.format> <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> </properties>
<issueManagement> <issueManagement>
<system>GitHub</system> <system>GitHub</system>
<url>https://github.com/developer_su/${project.artifactId}/issues</url> <url>https://github.com/developersu/${project.artifactId}/issues</url>
</issueManagement> </issueManagement>
<!-- openJFX Linux -->
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli --> <!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency> <dependency>
@ -58,89 +65,69 @@
<version>1.5.0</version> <version>1.5.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- openJFX Linux -->
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-graphics</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>linux</classifier> <classifier>linux</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId> <artifactId>javafx-controls</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>linux</classifier> <classifier>linux</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId> <artifactId>javafx-fxml</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>linux</classifier>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>18.0.1</version>
<classifier>linux</classifier> <classifier>linux</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- openJFX Windows --> <!-- openJFX Windows -->
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-graphics</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>win</classifier> <classifier>win</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId> <artifactId>javafx-controls</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>win</classifier> <classifier>win</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId> <artifactId>javafx-fxml</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>win</classifier>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>18.0.1</version>
<classifier>win</classifier> <classifier>win</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- openJFX MAC --> <!-- openJFX MAC -->
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-graphics</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>mac</classifier> <classifier>mac</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId> <artifactId>javafx-controls</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>mac</classifier> <classifier>mac</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId> <artifactId>javafx-fxml</artifactId>
<version>18.0.1</version> <version>${javafx.version}</version>
<classifier>mac</classifier>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>18.0.1</version>
<classifier>mac</classifier> <classifier>mac</classifier>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
@ -170,6 +157,13 @@
<version>5.9.0</version> <version>5.9.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- redrise repository -->
<dependency>
<groupId>ru.redrise</groupId>
<artifactId>libKonogonka</artifactId>
<version>0.1</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}-${project.version}-${maven.build.timestamp}</finalName> <finalName>${project.artifactId}-${project.version}-${maven.build.timestamp}</finalName>
@ -185,6 +179,16 @@
</resources> </resources>
<plugins> <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 --> <!-- Junit5 -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -199,17 +203,23 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version> <version>3.10.1</version>
<configuration> <configuration>
<source>1.8</source> <release>11</release>
<target>1.8</target>
</configuration> </configuration>
</plugin> </plugin>
<!-- Don't generate default JAR without dependencies --> <!-- Don't generate default JAR without dependencies -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <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> <executions>
<execution> <execution>
<id>default-jar</id> <id>default-jar</id>
@ -243,14 +253,13 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Launch4j
<plugin> <plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId> <groupId>com.akathist.maven.plugins.launch4j</groupId>
<version>1.7.25</version> <version>2.2.0</version>
<artifactId>launch4j-maven-plugin</artifactId> <artifactId>launch4j-maven-plugin</artifactId>
<executions> <executions>
<execution> <execution>
<id>l4j-NS-USBloader</id> <id>l4j-ns-usbloader</id>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>launch4j</goal> <goal>launch4j</goal>
@ -258,34 +267,37 @@
<configuration> <configuration>
<headerType>gui</headerType> <headerType>gui</headerType>
<icon>appicon.ico</icon> <icon>appicon.ico</icon>
<outfile>target/NS-USBloader-${project.version}.exe</outfile> <outfile>target/${project.name}.exe</outfile>
<jar>target/ns-usbloader-${project.version}-jar-with-dependencies.jar</jar> <jar>target/${project.artifactId}-${project.version}-${maven.build.timestamp}.jar</jar>
<errTitle>NS-USBloader</errTitle> <!-- <downloadUrl>https://download.oracle.com/java/17/archive/jdk-17.0.1_windows-x64_bin.msi</downloadUrl> -->
<classPath> <errTitle>Launching error</errTitle>
<mainClass>nsusbloader.Main</mainClass> <!-- <dontWrapJar>true</dontWrapJar> -->
<addDependencies>false</addDependencies>
<preCp>anything</preCp>
</classPath>
<jre> <jre>
<minVersion>1.8</minVersion> <path>%PWD%/jdk</path>
<minVersion>11.0.0</minVersion>
</jre> </jre>
<versionInfo> <versionInfo>
<fileVersion>1.0.0.0</fileVersion> <fileVersion>${project.version}.0.0</fileVersion>
<txtFileVersion>${project.version}</txtFileVersion> <txtFileVersion>${project.version}</txtFileVersion>
<fileDescription>Awoo and GoldLeaf installer for your NS</fileDescription> <fileDescription>NS multi-tool</fileDescription>
<copyright>GNU General Public License v3, 2019 ${project.organization.name}. Russia/LPR.</copyright> <copyright>GNU General Public License v3, ${project.inceptionYear} ${project.organization.name}, Russia.</copyright>
<productVersion>1.0.0.0</productVersion> <productVersion>${project.version}.0.0</productVersion>
<txtProductVersion>${project.version}</txtProductVersion> <txtProductVersion>${project.version}</txtProductVersion>
<companyName>${project.organization.name}</companyName> <companyName>${project.organization.name}</companyName>
<productName>${project.name}</productName> <productName>${project.name}</productName>
<internalName>${project.name}</internalName> <internalName>${project.name}</internalName>
<originalFilename>${project.name}.exe</originalFilename> <originalFilename>${project.name}.exe</originalFilename>
</versionInfo> </versionInfo>
<messages>
<startupErr>Startup error</startupErr>
<jreNotFoundErr>JDK not found</jreNotFoundErr>
<jreVersionErr>JDK Version mismatch</jreVersionErr>
<launcherErr>Launcher Error</launcherErr>
</messages>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
-->
</plugins> </plugins>
</build> </build>
</project> </project>

View file

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg <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" width="132.50603mm"
height="58.000351mm" height="45.000351mm"
viewBox="0 0 132.50603 58.000351" viewBox="0 0 132.50603 45.000351"
version="1.1" version="1.1"
id="svg8" id="svg8"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)" inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="Application Logo.svg"> 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 <defs
id="defs2" /> id="defs2" />
<sodipodi:namedview <sodipodi:namedview
@ -23,28 +23,31 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1.4142136" inkscape:zoom="4.0000001"
inkscape:cx="383.67648" inkscape:cx="233.49999"
inkscape:cy="100.29922" inkscape:cy="127.875"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:current-layer="svg8" inkscape:current-layer="flowRoot1022"
showgrid="false" showgrid="false"
units="mm" units="mm"
inkscape:window-width="1860" inkscape:window-width="3754"
inkscape:window-height="1058" inkscape:window-height="2127"
inkscape:window-x="1980" inkscape:window-x="1166"
inkscape:window-y="0" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:window-maximized="1"
fit-margin-top="0" fit-margin-top="0"
fit-margin-left="0" fit-margin-left="0"
fit-margin-right="0" fit-margin-right="0"
fit-margin-bottom="0" fit-margin-bottom="0"
inkscape:document-rotation="0"> inkscape:document-rotation="0"
inkscape:showpageshadow="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid829" id="grid829"
originx="-40.993969" originx="-40.99399"
originy="-37.999746" /> originy="-37.999752" />
</sodipodi:namedview> </sodipodi:namedview>
<metadata <metadata
id="metadata5"> id="metadata5">
@ -54,7 +57,6 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@ -114,145 +116,65 @@
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff;stroke-width:0.0680452" style="fill:#ffffff;stroke-width:0.0680452"
inkscape:label="usb_logo" /> inkscape:label="usb_logo" />
<text <g
xml:space="preserve" aria-label="NS-USBloader"
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"
transform="scale(0.97866107,1.0218042)" transform="scale(0.97866107,1.0218042)"
inkscape:label="ns-usbloader"><tspan id="text982"
sodipodi:role="line" 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"
id="tspan980" inkscape:label="ns-usbloader">
x="47.959785" <path
y="17.188828" 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-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> 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 <path
style="fill:#000000;fill-opacity:1;stroke-width:0.264583" 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" 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" id="rect1136"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="csssssssc" /> 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> </svg>

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -18,6 +18,8 @@
*/ */
package nsusbloader; package nsusbloader;
import javafx.scene.text.Font;
import java.util.Locale; import java.util.Locale;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
@ -27,22 +29,26 @@ public class AppPreferences {
private final Preferences preferences; private final Preferences preferences;
private final Locale locale; private final Locale locale;
public static final String[] goldleafSupportedVersions = {"v0.5", "v0.7.x", "v0.8-0.9", "v0.10"}; 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(){ private AppPreferences(){
this.preferences = Preferences.userRoot().node("NS-USBloader"); this.preferences = Preferences.userRoot().node("NS-USBloader");
String localeCode = preferences.get("locale", Locale.getDefault().toString()); 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(){ 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$)")) if (!theme.matches("(^/res/app_dark.css$)|(^/res/app_light.css$)"))
theme = "/res/app_dark.css"; theme = "/res/app_dark.css";
return theme; return theme;
} }
public int getProtocol(){ 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) if (protocolIndex < 0 || protocolIndex > 1)
protocolIndex = 0; protocolIndex = 0;
return protocolIndex; return protocolIndex;
@ -50,7 +56,7 @@ public class AppPreferences {
public void setProtocol(int protocolIndex){ preferences.putInt("protocol_index", protocolIndex); } public void setProtocol(int protocolIndex){ preferences.putInt("protocol_index", protocolIndex); }
public String getNetUsb(){ 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$)")) if (!netUsb.matches("(^USB$)|(^NET$)"))
netUsb = "USB"; netUsb = "USB";
return netUsb; return netUsb;
@ -114,7 +120,7 @@ public class AppPreferences {
public void setNspFileFilterGL(boolean prop){preferences.putBoolean("GL_NSP_FILTER", prop);} public void setNspFileFilterGL(boolean prop){preferences.putBoolean("GL_NSP_FILTER", prop);}
public int getGlVersion(){ 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);} 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 String getLastOpenedTab(){ return preferences.get("recent_tab", ""); }
public void setLastOpenedTab(String tabId){ preferences.put("recent_tab", tabId); } 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);
}
} }

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -39,10 +39,13 @@ import java.util.ResourceBundle;
public class FilesDropHandle { public class FilesDropHandle {
public FilesDropHandle(List<File> files, String filesRegex, String foldersRegex){ public FilesDropHandle(List<File> files,
String filesRegex,
String foldersRegex,
NSTableViewController tableController){
FilesDropHandleTask filesDropHandleTask = new FilesDropHandleTask(files, filesRegex, foldersRegex); FilesDropHandleTask filesDropHandleTask = new FilesDropHandleTask(files, filesRegex, foldersRegex);
ResourceBundle resourceBundle = MediatorControl.getInstance().getResourceBundle(); ResourceBundle resourceBundle = MediatorControl.INSTANCE.getResourceBundle();
Button cancelButton = new Button(resourceBundle.getString("btn_Cancel")); Button cancelButton = new Button(resourceBundle.getString("btn_Cancel"));
ProgressIndicator progressIndicator = new ProgressIndicator(); ProgressIndicator progressIndicator = new ProgressIndicator();
@ -87,6 +90,7 @@ public class FilesDropHandle {
Scene mainScene = new Scene(parentVBox, 310, 185); Scene mainScene = new Scene(parentVBox, 310, 185);
mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme()); mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
parentVBox.setStyle(AppPreferences.getInstance().getFontStyle());
stage.setOnHidden(windowEvent -> filesDropHandleTask.cancel(true ) ); stage.setOnHidden(windowEvent -> filesDropHandleTask.cancel(true ) );
@ -100,7 +104,7 @@ public class FilesDropHandle {
List<File> allFiles = filesDropHandleTask.getValue(); List<File> allFiles = filesDropHandleTask.getValue();
if (! allFiles.isEmpty()) { if (! allFiles.isEmpty()) {
MediatorControl.getInstance().getGamesController().tableFilesListController.setFiles(allFiles); tableController.setFiles(allFiles);
} }
stage.close(); stage.close();
}); });

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -32,7 +32,7 @@ public class FilesDropHandleTask extends Task<List<File>> {
private final List<File> filesDropped; private final List<File> filesDropped;
private final List<File> allFiles; private final List<File> allFiles;
private String messageTemplate; private final String messageTemplate;
private long filesScanned = 0; private long filesScanned = 0;
private long filesAdded = 0; private long filesAdded = 0;
@ -43,12 +43,12 @@ public class FilesDropHandleTask extends Task<List<File>> {
this.filesRegex = filesRegex; this.filesRegex = filesRegex;
this.foldersRegex = foldersRegex; this.foldersRegex = foldersRegex;
this.allFiles = new ArrayList<>(); this.allFiles = new ArrayList<>();
this.messageTemplate = MediatorControl.getInstance().getResourceBundle().getString("windowBodyFilesScanned"); this.messageTemplate = MediatorControl.INSTANCE.getResourceBundle().getString("windowBodyFilesScanned");
} }
@Override @Override
protected List<File> call() { protected List<File> call() {
if (filesDropped == null || filesDropped.size() == 0) if (filesDropped == null || filesDropped.isEmpty())
return allFiles; return allFiles;
for (File file : filesDropped){ for (File file : filesDropped){

View file

@ -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();
}
}

View file

@ -0,0 +1,155 @@
/*
Copyright 2019-2024 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.INSTANCE.getLogArea().getScene().getRoot().setStyle(
String.format("-fx-font-family: \"%s\"; -fx-font-size: %.0f;", fontFamily, fontSize));
closeWindow();
}
private void closeWindow(){
((Stage) cancelBtn.getScene().getWindow()).close();
}
}

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko, wolfposd Copyright 2019-2024 Dmitry Isaenko, wolfposd
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -31,6 +31,7 @@ import javafx.scene.layout.Region;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import nsusbloader.AppPreferences; import nsusbloader.AppPreferences;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.com.net.NETCommunications; import nsusbloader.com.net.NETCommunications;
import nsusbloader.com.usb.UsbCommunications; import nsusbloader.com.usb.UsbCommunications;
import nsusbloader.FilesHelper; import nsusbloader.FilesHelper;
@ -45,12 +46,14 @@ import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
public class GamesController implements Initializable { public class GamesController implements Initializable, ISubscriber {
private static final String REGEX_ONLY_NSP = ".*\\.nsp$"; private static final String REGEX_ONLY_NSP = ".*\\.nsp$";
private static final String REGEX_ALLFILES_TINFOIL = ".*\\.(nsp$|xci$|nsz$|xcz$)"; private static final String REGEX_ALLFILES_TINFOIL = ".*\\.(nsp$|xci$|nsz$|xcz$)";
private static final String REGEX_ALLFILES = ".*"; private static final String REGEX_ALLFILES = ".*";
private static final MediatorControl mediator = MediatorControl.INSTANCE;
@FXML @FXML
private AnchorPane usbNetPane; private AnchorPane usbNetPane;
@ -63,10 +66,10 @@ public class GamesController implements Initializable {
@FXML @FXML
private Button switchThemeBtn; private Button switchThemeBtn;
@FXML @FXML
public NSTableViewController tableFilesListController; // Accessible from Mediator (for drag-n-drop support) private NSTableViewController tableFilesListController;
@FXML @FXML
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn; private Button selectNspBtn, selectSplitBtn, uploadStopBtn;
private String previouslyOpenedPath; private String previouslyOpenedPath;
private Region btnUpStopImage, btnSelectImage; private Region btnUpStopImage, btnSelectImage;
private ResourceBundle resourceBundle; private ResourceBundle resourceBundle;
@ -101,6 +104,7 @@ public class GamesController implements Initializable {
disableUploadStopBtn(tableFilesListController.isFilesForUploadListEmpty()); disableUploadStopBtn(tableFilesListController.isFilesForUploadListEmpty());
}); // Add listener to notify tableView controller }); // Add listener to notify tableView controller
tableFilesListController.setNewProtocol(getSelectedProtocolByName()); // Notify tableView controller tableFilesListController.setNewProtocol(getSelectedProtocolByName()); // Notify tableView controller
tableFilesListController.setGamesController(this);
ObservableList<String> choiceNetUsbList = FXCollections.observableArrayList("USB", "NET"); ObservableList<String> choiceNetUsbList = FXCollections.observableArrayList("USB", "NET");
choiceNetUsb.setItems(choiceNetUsbList); choiceNetUsb.setItems(choiceNetUsbList);
@ -141,8 +145,8 @@ public class GamesController implements Initializable {
this.btnSelectImage = new Region(); this.btnSelectImage = new Region();
setFilesSelectorButtonBehaviour(preferences.getDirectoriesChooserForRoms()); setFilesSelectorButtonBehaviour(preferences.getDirectoriesChooserForRoms());
selectSplitNspBtn.setOnAction(e-> selectSplitBtnAction()); selectSplitBtn.setOnAction(e-> selectSplitBtnAction());
selectSplitNspBtn.getStyleClass().add("buttonSelect"); selectSplitBtn.getStyleClass().add("buttonSelect");
uploadStopBtn.setOnAction(e-> uploadBtnAction()); uploadStopBtn.setOnAction(e-> uploadBtnAction());
uploadStopBtn.setDisable(isTinfoil()); uploadStopBtn.setDisable(isTinfoil());
@ -204,11 +208,11 @@ public class GamesController implements Initializable {
} }
private boolean isAllFiletypesAllowedForGL() { private boolean isAllFiletypesAllowedForGL() {
return ! MediatorControl.getInstance().getSettingsController().getGoldleafSettings().getNSPFileFilterForGL(); return ! mediator.getSettingsController().getGoldleafSettings().getNSPFileFilterForGL();
} }
private boolean isXciNszXczSupport() { private boolean isXciNszXczSupport() {
return MediatorControl.getInstance().getSettingsController().getTinfoilSettings().isXciNszXczSupport(); return mediator.getSettingsController().getTinfoilSettings().isXciNszXczSupport();
} }
/** /**
@ -216,7 +220,7 @@ public class GamesController implements Initializable {
* tinfoil + xcinszxcz </br> * tinfoil + xcinszxcz </br>
* tinfoil + nsponly </br> * tinfoil + nsponly </br>
* goldleaf </br> * goldleaf </br>
* etc.. * etc...
*/ */
private String getRegexForFiles() { private String getRegexForFiles() {
if (isTinfoil() && isXciNszXczSupport()) if (isTinfoil() && isXciNszXczSupport())
@ -326,7 +330,7 @@ public class GamesController implements Initializable {
} }
/** /**
* Functionality for selecting Split NSP button. * Functionality for selecting Split-file button.
* */ * */
private void selectSplitBtnAction(){ private void selectSplitBtnAction(){
File splitFile; File splitFile;
@ -338,11 +342,28 @@ public class GamesController implements Initializable {
splitFile = dirChooser.showDialog(usbNetPane.getScene().getWindow()); 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); tableFilesListController.setFile(splitFile);
uploadStopBtn.setDisable(false); // Is it useful? uploadStopBtn.setDisable(false); // Is it useful?
previouslyOpenedPath = splitFile.getParent(); 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 * It's button listener when no transmission executes
@ -351,56 +372,58 @@ public class GamesController implements Initializable {
if (workThread != null && workThread.isAlive()) if (workThread != null && workThread.isAlive())
return; return;
// Collect files
List<File> nspToUpload;
TextArea logArea = MediatorControl.getInstance().getContoller().logArea;
if (isTinfoil() && tableFilesListController.getFilesForUpload() == null) { if (isTinfoil() && tableFilesListController.getFilesForUpload() == null) {
logArea.setText(resourceBundle.getString("tab3_Txt_NoFolderOrFileSelected")); ServiceWindow.getInfoNotification("(o_o\")", resourceBundle.getString("tab3_Txt_NoFolderOrFileSelected"));
return; return;
} }
if ((nspToUpload = tableFilesListController.getFilesForUpload()) != null){ // Collect files
List<File> nspToUpload = tableFilesListController.getFilesForUpload();
if (nspToUpload == null)
nspToUpload = new ArrayList<>();
//todo: add to make it visible
/*
else {
TextArea logArea = mediator.getLogArea();
logArea.setText(resourceBundle.getString("tab3_Txt_FilesToUploadTitle")+"\n"); logArea.setText(resourceBundle.getString("tab3_Txt_FilesToUploadTitle")+"\n");
nspToUpload.forEach(item -> logArea.appendText(" "+item.getAbsolutePath()+"\n")); nspToUpload.forEach(item -> logArea.appendText(" "+item.getAbsolutePath()+"\n"));
} }
else { */
logArea.clear();
nspToUpload = new LinkedList<>();
}
SettingsController settings = MediatorControl.getInstance().getSettingsController(); SettingsController settings = mediator.getSettingsController();
// If USB selected // If USB selected
if (isGoldLeaf()){ if (isGoldLeaf()){
final SettingsBlockGoldleafController goldleafSettings = settings.getGoldleafSettings(); final SettingsBlockGoldleafController goldleafSettings = settings.getGoldleafSettings();
usbNetCommunications = new UsbCommunications(nspToUpload, "GoldLeaf" + goldleafSettings.getGlVer(), goldleafSettings.getNSPFileFilterForGL()); usbNetCommunications = new UsbCommunications(nspToUpload, "GoldLeaf" + goldleafSettings.getGlVer(), goldleafSettings.getNSPFileFilterForGL());
} }
else if (( isTinfoil() && getSelectedNetUsb().equals("USB") )){ else {
usbNetCommunications = new UsbCommunications(nspToUpload, "TinFoil", false); if (getSelectedNetUsb().equals("USB")){
} usbNetCommunications = new UsbCommunications(nspToUpload, "TinFoil", false);
else { // NET INSTALL OVER TINFOIL
final String ipValidationPattern = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
final SettingsBlockTinfoilController tinfoilSettings = settings.getTinfoilSettings();
if (tinfoilSettings.isValidateNSHostName() && ! getNsIp().matches(ipValidationPattern)) {
if (!ServiceWindow.getConfirmationWindow(resourceBundle.getString("windowTitleBadIp"), resourceBundle.getString("windowBodyBadIp")))
return;
} }
else { // NET INSTALL OVER TINFOIL
final String ipValidationPattern = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
final SettingsBlockTinfoilController tinfoilSettings = settings.getTinfoilSettings();
String nsIP = getNsIp(); if (tinfoilSettings.isValidateNSHostName() && ! getNsIp().matches(ipValidationPattern)) {
if (!ServiceWindow.getConfirmationWindow(resourceBundle.getString("windowTitleBadIp"), resourceBundle.getString("windowBodyBadIp")))
return;
}
if (! tinfoilSettings.isExpertModeSelected()) String nsIP = getNsIp();
usbNetCommunications = new NETCommunications(nspToUpload, nsIP, false, "", "", "");
else { if (! tinfoilSettings.isExpertModeSelected())
usbNetCommunications = new NETCommunications( usbNetCommunications = new NETCommunications(nspToUpload, nsIP, false, "", "", "");
nspToUpload, else {
nsIP, usbNetCommunications = new NETCommunications(
tinfoilSettings.isNoRequestsServe(), nspToUpload,
tinfoilSettings.isAutoDetectIp()?"":tinfoilSettings.getHostIp(), nsIP,
tinfoilSettings.isRandomlySelectPort()?"":tinfoilSettings.getHostPort(), tinfoilSettings.isNoRequestsServe(),
tinfoilSettings.isNoRequestsServe()?tinfoilSettings.getHostExtra():"" tinfoilSettings.isAutoDetectIp()?"":tinfoilSettings.getHostIp(),
); tinfoilSettings.isRandomlySelectPort()?"":tinfoilSettings.getHostPort(),
tinfoilSettings.isNoRequestsServe()?tinfoilSettings.getHostExtra():""
);
}
} }
} }
workThread = new Thread(usbNetCommunications); workThread = new Thread(usbNetCommunications);
@ -429,7 +452,7 @@ public class GamesController implements Initializable {
* */ * */
@FXML @FXML
private void handleDragOver(DragEvent event){ private void handleDragOver(DragEvent event){
if (event.getDragboard().hasFiles() && ! MediatorControl.getInstance().getTransferActive()) if (event.getDragboard().hasFiles() && ! mediator.getTransferActive())
event.acceptTransferModes(TransferMode.ANY); event.acceptTransferModes(TransferMode.ANY);
event.consume(); event.consume();
} }
@ -439,47 +462,15 @@ public class GamesController implements Initializable {
@FXML @FXML
private void handleDrop(DragEvent event) { private void handleDrop(DragEvent event) {
List<File> files = event.getDragboard().getFiles(); List<File> files = event.getDragboard().getFiles();
new FilesDropHandle(files, getRegexForFiles(), getRegexForFolders()); new FilesDropHandle(files, getRegexForFiles(), getRegexForFolders(), tableFilesListController);
event.setDropCompleted(true); event.setDropCompleted(true);
event.consume(); event.consume();
} }
/** /**
* This thing modify UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission" * This function called from NSTableViewController
* Called from mediator
* TODO: remove shitcoding practices
* */ * */
public void notifyThreadStarted(boolean isActive, EModule type){ void disableUploadStopBtn(boolean disable){
if (! type.equals(EModule.USB_NET_TRANSFERS)){
usbNetPane.setDisable(isActive);
return;
}
selectNspBtn.setDisable(isActive);
selectSplitNspBtn.setDisable(isActive);
btnUpStopImage.getStyleClass().clear();
if (isActive) {
btnUpStopImage.getStyleClass().add("regionStop");
uploadStopBtn.setOnAction(e-> stopBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
uploadStopBtn.getStyleClass().remove("buttonUp");
uploadStopBtn.getStyleClass().add("buttonStop");
}
else {
btnUpStopImage.getStyleClass().add("regionUpload");
uploadStopBtn.setOnAction(e-> uploadBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
uploadStopBtn.getStyleClass().remove("buttonStop");
uploadStopBtn.getStyleClass().add("buttonUp");
}
}
/**
* Crunch. This function called from NSTableViewController
* */
public void disableUploadStopBtn(boolean disable){
if (isTinfoil()) if (isTinfoil())
uploadStopBtn.setDisable(disable); uploadStopBtn.setDisable(disable);
else else
@ -498,27 +489,24 @@ public class GamesController implements Initializable {
}).start(); }).start();
} }
public void updateFilesSelectorButtonBehaviour(boolean isDirectoryChooser){ void setFilesSelectorButtonBehaviour(boolean isDirectoryChooser){
btnSelectImage.getStyleClass().clear(); btnSelectImage.getStyleClass().clear();
setFilesSelectorButtonBehaviour(isDirectoryChooser);
}
private void setFilesSelectorButtonBehaviour(boolean isDirectoryChooser){
if (isDirectoryChooser){ if (isDirectoryChooser){
selectNspBtn.setOnAction(e -> selectFoldersBtnAction()); selectNspBtn.setOnAction(e -> selectFoldersBtnAction());
btnSelectImage.getStyleClass().add("regionScanFolders"); btnSelectImage.getStyleClass().add("regionScanFolders");
selectSplitNspBtn.setVisible(false); selectSplitBtn.setVisible(false);
} }
else { else {
selectNspBtn.setOnAction(e -> selectFilesBtnAction()); selectNspBtn.setOnAction(e -> selectFilesBtnAction());
btnSelectImage.getStyleClass().add("regionSelectFiles"); btnSelectImage.getStyleClass().add("regionSelectFiles");
selectSplitNspBtn.setVisible(true); selectSplitBtn.setVisible(true);
} }
selectNspBtn.setGraphic(btnSelectImage); selectNspBtn.setGraphic(btnSelectImage);
} }
/** /**
* Get 'Recent' path * Get 'Recent' path
*/ */
public String getRecentPath(){ private String getRecentPath(){
return previouslyOpenedPath; return previouslyOpenedPath;
} }
@ -530,4 +518,42 @@ public class GamesController implements Initializable {
preferences.setNetUsb(getSelectedNetUsb()); preferences.setNetUsb(getSelectedNetUsb());
preferences.setNsIp(getNsIp()); preferences.setNsIp(getNsIp());
} }
/**
* This thing modifies UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission"
* */
@Override
public void notify(EModule type, boolean isActive, Payload payload) {
if (! type.equals(EModule.USB_NET_TRANSFERS)){
usbNetPane.setDisable(isActive);
return;
}
selectNspBtn.setDisable(isActive);
selectSplitBtn.setDisable(isActive);
btnUpStopImage.getStyleClass().clear();
if (isActive) {
btnUpStopImage.getStyleClass().add("regionStop");
uploadStopBtn.setOnAction(e-> stopBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
uploadStopBtn.getStyleClass().remove("buttonUp");
uploadStopBtn.getStyleClass().add("buttonStop");
return;
}
btnUpStopImage.getStyleClass().add("regionUpload");
uploadStopBtn.setOnAction(e-> uploadBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
uploadStopBtn.getStyleClass().remove("buttonStop");
uploadStopBtn.getStyleClass().add("buttonUp");
Map<String, EFileStatus> statusMap = payload.getStatusMap();
if (! statusMap.isEmpty()) {
for (String key : statusMap.keySet())
tableFilesListController.setFileStatus(key, statusMap.get(key));
}
}
} }

View file

@ -0,0 +1,25 @@
/*
Copyright 2019-2024 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 nsusbloader.NSLDataTypes.EModule;
public interface ISubscriber {
void notify(EModule type, boolean status, Payload payload);
}

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -18,7 +18,6 @@
*/ */
package nsusbloader.Controllers; package nsusbloader.Controllers;
import javafx.application.HostServices;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
@ -35,15 +34,15 @@ public class NSLMainController implements Initializable {
private ResourceBundle resourceBundle; private ResourceBundle resourceBundle;
@FXML @FXML
public TextArea logArea; // Accessible from Mediator private TextArea logArea;
@FXML @FXML
public ProgressBar progressBar; // Accessible from Mediator private ProgressBar progressBar;
@FXML @FXML
private TabPane mainTabPane; private TabPane mainTabPane;
@FXML @FXML
private Tab GamesTabHolder, RCMTabHolder, SMTabHolder; private Tab GamesTabHolder, RCMTabHolder, SMTabHolder, PatchesTabHolder;
@FXML @FXML
private GamesController GamesTabController; private GamesController GamesTabController;
@ -55,6 +54,8 @@ public class NSLMainController implements Initializable {
private RcmController RcmTabController; private RcmController RcmTabController;
@FXML @FXML
private NxdtController NXDTabController; private NxdtController NXDTabController;
@FXML
private PatchesController PatchesTabController;
@Override @Override
public void initialize(URL url, ResourceBundle rb) { public void initialize(URL url, ResourceBundle rb) {
@ -66,13 +67,31 @@ public class NSLMainController implements Initializable {
logArea.appendText(rb.getString("tab3_Txt_GreetingsMessage2")+"\n"); logArea.appendText(rb.getString("tab3_Txt_GreetingsMessage2")+"\n");
MediatorControl.getInstance().setController(this); AppPreferences preferences = AppPreferences.getInstance();
if (AppPreferences.getInstance().getAutoCheckUpdates()){ if (preferences.getAutoCheckUpdates())
checkForUpdates(); checkForUpdates();
}
if (preferences.getPatchesTabInvisible())
mainTabPane.getTabs().remove(3);
openLastOpenedTab(); openLastOpenedTab();
TransfersPublisher transfersPublisher = new TransfersPublisher(
GamesTabController,
SplitMergeTabController,
RcmTabController,
NXDTabController,
PatchesTabController);
MediatorControl.INSTANCE.configure(
resourceBundle,
SettingsTabController,
logArea,
progressBar,
GamesTabController,
transfersPublisher);
} }
private void checkForUpdates(){ private void checkForUpdates(){
Task<List<String>> updTask = new UpdatesChecker(); Task<List<String>> updTask = new UpdatesChecker();
@ -95,38 +114,7 @@ public class NSLMainController implements Initializable {
updates.setDaemon(true); updates.setDaemon(true);
updates.start(); updates.start();
} }
/**
* Get resources
* TODO: Find better solution; used in UsbCommunications() -> GL -> SelectFile command
* @return ResourceBundle
*/
public ResourceBundle getResourceBundle() {
return resourceBundle;
}
/**
* Provide hostServices to Settings tab
* */
public void setHostServices(HostServices hs ){ SettingsTabController.getGenericSettings().registerHostServices(hs);}
/**
* Get 'Settings' controller
* Used by FrontController
* */
public SettingsController getSettingsCtrlr(){
return SettingsTabController;
}
public GamesController getGamesCtrlr(){
return GamesTabController;
}
public SplitMergeController getSmCtrlr(){
return SplitMergeTabController;
}
public RcmController getRcmCtrlr(){ return RcmTabController; }
public NxdtController getNXDTabController(){ return NXDTabController; }
/** /**
* Save preferences before exit * Save preferences before exit
* */ * */
@ -136,7 +124,7 @@ public class NSLMainController implements Initializable {
SplitMergeTabController.updatePreferencesOnExit(); // NOTE: This shit above should be re-written to similar pattern SplitMergeTabController.updatePreferencesOnExit(); // NOTE: This shit above should be re-written to similar pattern
RcmTabController.updatePreferencesOnExit(); RcmTabController.updatePreferencesOnExit();
NXDTabController.updatePreferencesOnExit(); NXDTabController.updatePreferencesOnExit();
PatchesTabController.updatePreferencesOnExit();
saveLastOpenedTab(); saveLastOpenedTab();
} }
@ -152,6 +140,9 @@ public class NSLMainController implements Initializable {
case "SMTabHolder": case "SMTabHolder":
mainTabPane.getSelectionModel().select(SMTabHolder); mainTabPane.getSelectionModel().select(SMTabHolder);
break; break;
case "PatchesTabHolder":
mainTabPane.getSelectionModel().select(PatchesTabHolder);
break;
} }
} }
private void saveLastOpenedTab(){ private void saveLastOpenedTab(){

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko, wolfposd Copyright 2019-2024 Dmitry Isaenko, wolfposd
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -42,6 +42,8 @@ public class NSTableViewController implements Initializable {
private TableView<NSLRowModel> table; private TableView<NSLRowModel> table;
private ObservableList<NSLRowModel> rowsObsLst; private ObservableList<NSLRowModel> rowsObsLst;
private GamesController gamesController;
@Override @Override
public void initialize(URL url, ResourceBundle resourceBundle) { public void initialize(URL url, ResourceBundle resourceBundle) {
rowsObsLst = FXCollections.observableArrayList(); rowsObsLst = FXCollections.observableArrayList();
@ -52,10 +54,10 @@ public class NSTableViewController implements Initializable {
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setOnKeyPressed(keyEvent -> { table.setOnKeyPressed(keyEvent -> {
if (!rowsObsLst.isEmpty()) { if (!rowsObsLst.isEmpty()) {
if (keyEvent.getCode() == KeyCode.DELETE && !MediatorControl.getInstance().getTransferActive()) { if (keyEvent.getCode() == KeyCode.DELETE && !MediatorControl.INSTANCE.getTransferActive()) {
rowsObsLst.removeAll(table.getSelectionModel().getSelectedItems()); rowsObsLst.removeAll(table.getSelectionModel().getSelectedItems());
if (rowsObsLst.isEmpty()) if (rowsObsLst.isEmpty())
MediatorControl.getInstance().getGamesController().disableUploadStopBtn(true); // TODO: change to something better gamesController.disableUploadStopBtn(true);
table.refresh(); table.refresh();
} else if (keyEvent.getCode() == KeyCode.SPACE) { } else if (keyEvent.getCode() == KeyCode.SPACE) {
for (NSLRowModel item : table.getSelectionModel().getSelectedItems()) { for (NSLRowModel item : table.getSelectionModel().getSelectedItems()) {
@ -173,13 +175,13 @@ public class NSTableViewController implements Initializable {
deleteMenuItem.setOnAction(actionEvent -> { deleteMenuItem.setOnAction(actionEvent -> {
rowsObsLst.remove(row.getItem()); rowsObsLst.remove(row.getItem());
if (rowsObsLst.isEmpty()) if (rowsObsLst.isEmpty())
MediatorControl.getInstance().getGamesController().disableUploadStopBtn(true); // TODO: change to something better gamesController.disableUploadStopBtn(true);
table.refresh(); table.refresh();
}); });
MenuItem deleteAllMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_DeleteAll")); MenuItem deleteAllMenuItem = new MenuItem(resourceBundle.getString("tab1_table_contextMenu_Btn_DeleteAll"));
deleteAllMenuItem.setOnAction(actionEvent -> { deleteAllMenuItem.setOnAction(actionEvent -> {
rowsObsLst.clear(); rowsObsLst.clear();
MediatorControl.getInstance().getGamesController().disableUploadStopBtn(true); // TODO: change to something better gamesController.disableUploadStopBtn(true);
table.refresh(); table.refresh();
}); });
contextMenu.getItems().addAll(deleteMenuItem, deleteAllMenuItem); contextMenu.getItems().addAll(deleteMenuItem, deleteAllMenuItem);
@ -189,7 +191,7 @@ public class NSTableViewController implements Initializable {
Bindings.when( Bindings.when(
Bindings.isNotNull( Bindings.isNotNull(
row.itemProperty())) row.itemProperty()))
.then(MediatorControl.getInstance().getTransferActive()?null:contextMenu) .then(MediatorControl.INSTANCE.getTransferActive()?null:contextMenu)
.otherwise((ContextMenu) null) .otherwise((ContextMenu) null)
); );
// Just.. don't ask.. // Just.. don't ask..
@ -210,6 +212,11 @@ public class NSTableViewController implements Initializable {
table.getColumns().add(fileSizeColumn); table.getColumns().add(fileSizeColumn);
table.getColumns().add(uploadColumn); table.getColumns().add(uploadColumn);
} }
public void setGamesController(GamesController gamesController) {
this.gamesController = gamesController;
}
/** /**
* Add single file when user selected it (Split file usually) * Add single file when user selected it (Split file usually)
* */ * */
@ -224,7 +231,7 @@ public class NSTableViewController implements Initializable {
} }
else { else {
rowsObsLst.add(new NSLRowModel(file, true)); rowsObsLst.add(new NSLRowModel(file, true));
MediatorControl.getInstance().getGamesController().disableUploadStopBtn(false); // TODO: change to something better gamesController.disableUploadStopBtn(false);
} }
table.refresh(); table.refresh();
} }
@ -244,7 +251,7 @@ public class NSTableViewController implements Initializable {
else { else {
for (File file: newFiles) for (File file: newFiles)
rowsObsLst.add(new NSLRowModel(file, true)); rowsObsLst.add(new NSLRowModel(file, true));
MediatorControl.getInstance().getGamesController().disableUploadStopBtn(false); // TODO: change to something better gamesController.disableUploadStopBtn(false);
} }
//rowsObsLst.get(0).setMarkForUpload(true); //rowsObsLst.get(0).setMarkForUpload(true);
table.refresh(); table.refresh();

View file

@ -25,8 +25,6 @@ import javafx.scene.control.Label;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import nsusbloader.AppPreferences; import nsusbloader.AppPreferences;
import nsusbloader.FilesHelper;
import nsusbloader.MediatorControl;
import nsusbloader.ModelControllers.CancellableRunnable; import nsusbloader.ModelControllers.CancellableRunnable;
import nsusbloader.NSLDataTypes.EModule; import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.Utilities.nxdumptool.NxdtTask; import nsusbloader.Utilities.nxdumptool.NxdtTask;
@ -35,7 +33,7 @@ import java.io.File;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class NxdtController implements Initializable { public class NxdtController implements Initializable, ISubscriber {
@FXML @FXML
private Label saveToLocationLbl, statusLbl; private Label saveToLocationLbl, statusLbl;
@ -79,7 +77,6 @@ public class NxdtController implements Initializable {
* */ * */
private void startDumpProcess(){ private void startDumpProcess(){
if ((workThread == null || ! workThread.isAlive())){ if ((workThread == null || ! workThread.isAlive())){
MediatorControl.getInstance().getContoller().logArea.clear();
nxdtTask = new NxdtTask(saveToLocationLbl.getText()); nxdtTask = new NxdtTask(saveToLocationLbl.getText());
workThread = new Thread(nxdtTask); workThread = new Thread(nxdtTask);
@ -97,12 +94,22 @@ public class NxdtController implements Initializable {
} }
} }
public void notifyThreadStarted(boolean isActive, EModule type){ /**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
AppPreferences.getInstance().setNXDTSaveToLocation(saveToLocationLbl.getText());
}
@Override
public void notify(EModule type, boolean isActive, Payload payload) {
if (! type.equals(EModule.NXDT)){ if (! type.equals(EModule.NXDT)){
injectPldBtn.setDisable(isActive); injectPldBtn.setDisable(isActive);
return; return;
} }
statusLbl.setText(payload.getMessage());
if (isActive) { if (isActive) {
btnDumpStopImage.getStyleClass().clear(); btnDumpStopImage.getStyleClass().clear();
btnDumpStopImage.getStyleClass().add("regionStop"); btnDumpStopImage.getStyleClass().add("regionStop");
@ -121,16 +128,4 @@ public class NxdtController implements Initializable {
injectPldBtn.getStyleClass().remove("buttonStop"); injectPldBtn.getStyleClass().remove("buttonStop");
injectPldBtn.getStyleClass().add("buttonUp"); injectPldBtn.getStyleClass().add("buttonUp");
} }
public void setOneLineStatus(boolean status){
if (status)
statusLbl.setText(rb.getString("done_txt"));
else
statusLbl.setText(rb.getString("failure_txt"));
}
/**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
AppPreferences.getInstance().setNXDTSaveToLocation(saveToLocationLbl.getText());
}
} }

View file

@ -0,0 +1,343 @@
/*
Copyright 2018-2024 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, ISubscriber {
@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;
if (MediatorControl.INSTANCE.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;
if (MediatorControl.INSTANCE.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;
if (MediatorControl.INSTANCE.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();
}
@Override
public void notify(EModule type, boolean isActive, Payload payload) {
if (! type.equals(EModule.PATCHES)) {
patchesToolPane.setDisable(isActive);
return;
}
statusLbl.setText(payload.getMessage());
convertRegionEs.getStyleClass().clear();
makeFsBtn.setVisible(! isActive);
makeLoaderBtn.setVisible(! isActive);
if (isActive) {
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");
}
void updatePreferencesOnExit(){
AppPreferences.getInstance().setPatchesSaveToLocation(saveToLbl.getText());
if (locationKeysLbl.getText().isEmpty())
return;
AppPreferences.getInstance().setKeysLocation(locationKeysLbl.getText());
}
}

View file

@ -0,0 +1,48 @@
/*
Copyright 2019-2024 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 nsusbloader.NSLDataTypes.EFileStatus;
import java.util.Collections;
import java.util.Map;
public class Payload {
private final String message;
private final Map<String, EFileStatus> statusMap;
public Payload(){
this("");
}
public Payload(String message){
this(message, Collections.emptyMap());
}
public Payload(String message, Map<String, EFileStatus> statusMap){
this.message = message;
this.statusMap = statusMap;
}
public String getMessage() {
return message;
}
public Map<String, EFileStatus> getStatusMap() {
return statusMap;
}
}

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -41,7 +41,7 @@ import java.io.File;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class RcmController implements Initializable { public class RcmController implements Initializable, ISubscriber {
@FXML @FXML
private ToggleGroup rcmToggleGrp; private ToggleGroup rcmToggleGrp;
@ -68,12 +68,14 @@ public class RcmController implements Initializable {
@FXML @FXML
private Label statusLbl; private Label statusLbl;
private AppPreferences preferences;
private ResourceBundle rb; private ResourceBundle rb;
private String myRegexp; private String myRegexp;
@Override @Override
public void initialize(URL url, ResourceBundle resourceBundle) { public void initialize(URL url, ResourceBundle resourceBundle) {
this.rb = resourceBundle; this.rb = resourceBundle;
final AppPreferences preferences = AppPreferences.getInstance(); this.preferences = AppPreferences.getInstance();
rcmToggleGrp.selectToggle(pldrRadio1); rcmToggleGrp.selectToggle(pldrRadio1);
pldrRadio1.setOnAction(e -> statusLbl.setText("")); pldrRadio1.setOnAction(e -> statusLbl.setText(""));
@ -193,8 +195,7 @@ public class RcmController implements Initializable {
} }
private void smash(){ private void smash(){
statusLbl.setText(""); if (MediatorControl.INSTANCE.getTransferActive()) {
if (MediatorControl.getInstance().getTransferActive()) {
ServiceWindow.getErrorNotification(rb.getString("windowTitleError"), ServiceWindow.getErrorNotification(rb.getString("windowTitleError"),
rb.getString("windowBodyPleaseStopOtherProcessFirst")); rb.getString("windowBodyPleaseStopOtherProcessFirst"));
return; return;
@ -273,31 +274,28 @@ public class RcmController implements Initializable {
private void bntResetPayloader(ActionEvent event){ private void bntResetPayloader(ActionEvent event){
final Node btn = (Node)event.getSource(); final Node btn = (Node)event.getSource();
statusLbl.setText("");
switch (btn.getId()){ switch (btn.getId()){
case "resPldBtn1": case "resPldBtn1":
payloadFNameLbl1.setText(""); payloadFNameLbl1.setText("");
payloadFPathLbl1.setText(""); payloadFPathLbl1.setText("");
statusLbl.setText("");
break; break;
case "resPldBtn2": case "resPldBtn2":
payloadFNameLbl2.setText(""); payloadFNameLbl2.setText("");
payloadFPathLbl2.setText(""); payloadFPathLbl2.setText("");
statusLbl.setText("");
break; break;
case "resPldBtn3": case "resPldBtn3":
payloadFNameLbl3.setText(""); payloadFNameLbl3.setText("");
payloadFPathLbl3.setText(""); payloadFPathLbl3.setText("");
statusLbl.setText("");
break; break;
case "resPldBtn4": case "resPldBtn4":
payloadFNameLbl4.setText(""); payloadFNameLbl4.setText("");
payloadFPathLbl4.setText(""); payloadFPathLbl4.setText("");
statusLbl.setText("");
break; break;
case "resPldBtn5": case "resPldBtn5":
payloadFNameLbl5.setText(""); payloadFNameLbl5.setText("");
payloadFPathLbl5.setText(""); payloadFPathLbl5.setText("");
statusLbl.setText("");
} }
} }
@ -324,27 +322,20 @@ public class RcmController implements Initializable {
} }
} }
public void setOneLineStatus(boolean statusSuccess){ @Override
if (statusSuccess) public void notify(EModule type, boolean isActive, Payload payload) {
statusLbl.setText(rb.getString("done_txt")); rcmToolPane.setDisable(isActive);
else if (type.equals(EModule.RCM))
statusLbl.setText(rb.getString("failure_txt")); statusLbl.setText(payload.getMessage());
}
public void notifyThreadStarted(boolean isStart, EModule type){
rcmToolPane.setDisable(isStart);
if (type.equals(EModule.RCM) && isStart){
MediatorControl.getInstance().getContoller().logArea.clear();
}
} }
/** /**
* Save application settings on exit * Save application settings on exit
* */ * */
public void updatePreferencesOnExit(){ public void updatePreferencesOnExit(){
AppPreferences.getInstance().setRecentRcm(1, payloadFPathLbl1.getText()); preferences.setRecentRcm(1, payloadFPathLbl1.getText());
AppPreferences.getInstance().setRecentRcm(2, payloadFPathLbl2.getText()); preferences.setRecentRcm(2, payloadFPathLbl2.getText());
AppPreferences.getInstance().setRecentRcm(3, payloadFPathLbl3.getText()); preferences.setRecentRcm(3, payloadFPathLbl3.getText());
AppPreferences.getInstance().setRecentRcm(4, payloadFPathLbl4.getText()); preferences.setRecentRcm(4, payloadFPathLbl4.getText());
AppPreferences.getInstance().setRecentRcm(5, payloadFPathLbl5.getText()); preferences.setRecentRcm(5, payloadFPathLbl5.getText());
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -43,6 +43,9 @@ import java.util.ResourceBundle;
public class SettingsBlockGenericController implements Initializable { public class SettingsBlockGenericController implements Initializable {
@FXML @FXML
private ChoiceBox<LocaleHolder> languagesChB; private ChoiceBox<LocaleHolder> languagesChB;
@FXML
private Button fontSelectBtn;
@FXML @FXML
private Button submitLanguageBtn, private Button submitLanguageBtn,
driversInstallBtn, driversInstallBtn,
@ -52,9 +55,7 @@ public class SettingsBlockGenericController implements Initializable {
direcroriesChooserForRomsCB; direcroriesChooserForRomsCB;
@FXML @FXML
private Hyperlink newVersionHyperlink; private Hyperlink newVersionHyperlink;
private ResourceBundle resourceBundle; private ResourceBundle resourceBundle;
private HostServices hostServices; private HostServices hostServices;
@Override @Override
@ -65,8 +66,8 @@ public class SettingsBlockGenericController implements Initializable {
autoCheckForUpdatesCB.setSelected(preferences.getAutoCheckUpdates()); autoCheckForUpdatesCB.setSelected(preferences.getAutoCheckUpdates());
direcroriesChooserForRomsCB.setSelected(preferences.getDirectoriesChooserForRoms()); direcroriesChooserForRomsCB.setSelected(preferences.getDirectoriesChooserForRoms());
direcroriesChooserForRomsCB.setOnAction(actionEvent -> direcroriesChooserForRomsCB.setOnAction(actionEvent ->
MediatorControl.getInstance().getGamesController().updateFilesSelectorButtonBehaviour(direcroriesChooserForRomsCB.isSelected()) MediatorControl.INSTANCE.getGamesController().setFilesSelectorButtonBehaviour(direcroriesChooserForRomsCB.isSelected())
); );
Region btnSwitchImage = new Region(); Region btnSwitchImage = new Region();
btnSwitchImage.getStyleClass().add("regionUpdatesCheck"); btnSwitchImage.getStyleClass().add("regionUpdatesCheck");
@ -78,9 +79,18 @@ public class SettingsBlockGenericController implements Initializable {
languagesChB.setItems(settingsLanguagesSetup.getLanguages()); languagesChB.setItems(settingsLanguagesSetup.getLanguages());
languagesChB.getSelectionModel().select(settingsLanguagesSetup.getRecentLanguage()); languagesChB.getSelectionModel().select(settingsLanguagesSetup.getRecentLanguage());
hostServices = MediatorControl.INSTANCE.getHostServices();
newVersionHyperlink.setOnAction(e-> hostServices.showDocument(newVersionHyperlink.getText())); newVersionHyperlink.setOnAction(e-> hostServices.showDocument(newVersionHyperlink.getText()));
checkForUpdBtn.setOnAction(e->checkForUpdatesAction()); checkForUpdBtn.setOnAction(e->checkForUpdatesAction());
submitLanguageBtn.setOnAction(e->languageButtonAction()); 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(){ private void setDriversInstallFeature(){
@ -138,8 +148,6 @@ public class SettingsBlockGenericController implements Initializable {
return direcroriesChooserForRomsCB.isSelected(); return direcroriesChooserForRomsCB.isSelected();
} }
protected void registerHostServices(HostServices hostServices){ this.hostServices = hostServices;}
void setNewVersionLink(String newVer){ void setNewVersionLink(String newVer){
newVersionHyperlink.setVisible(true); newVersionHyperlink.setVisible(true);
newVersionHyperlink.setText("https://github.com/developersu/ns-usbloader/releases/tag/"+newVer); newVersionHyperlink.setText("https://github.com/developersu/ns-usbloader/releases/tag/"+newVer);

View file

@ -38,7 +38,7 @@ public class SettingsBlockGoldleafController implements Initializable {
final AppPreferences preferences = AppPreferences.getInstance(); final AppPreferences preferences = AppPreferences.getInstance();
nspFilesFilterForGLCB.setSelected(preferences.getNspFileFilterGL()); nspFilesFilterForGLCB.setSelected(preferences.getNspFileFilterGL());
glVersionChoiceBox.getItems().addAll(AppPreferences.goldleafSupportedVersions); glVersionChoiceBox.getItems().addAll(AppPreferences.GOLDLEAF_SUPPORTED_VERSIONS);
glVersionChoiceBox.getSelectionModel().select(preferences.getGlVersion()); glVersionChoiceBox.getSelectionModel().select(preferences.getGlVersion());
} }

View file

@ -55,7 +55,7 @@ public class SettingsBlockTinfoilController implements Initializable {
final AppPreferences preferences = AppPreferences.getInstance(); final AppPreferences preferences = AppPreferences.getInstance();
networkExpertSettingsVBox.disableProperty().bind(networkExpertModeCB.selectedProperty().not()); networkExpertSettingsVBox.visibleProperty().bind(networkExpertModeCB.selectedProperty());
pcIpTF.disableProperty().bind(autoDetectIpCB.selectedProperty()); pcIpTF.disableProperty().bind(autoDetectIpCB.selectedProperty());
pcPortTF.disableProperty().bind(randomlySelectPortCB.selectedProperty()); pcPortTF.disableProperty().bind(randomlySelectPortCB.selectedProperty());

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -31,7 +31,6 @@ import javafx.stage.FileChooser;
import nsusbloader.AppPreferences; import nsusbloader.AppPreferences;
import nsusbloader.FilesHelper; import nsusbloader.FilesHelper;
import nsusbloader.MediatorControl; import nsusbloader.MediatorControl;
import nsusbloader.ModelControllers.CancellableRunnable;
import nsusbloader.NSLDataTypes.EModule; import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.ServiceWindow; import nsusbloader.ServiceWindow;
import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor; import nsusbloader.Utilities.splitmerge.SplitMergeTaskExecutor;
@ -41,7 +40,7 @@ import java.net.URL;
import java.util.List; import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class SplitMergeController implements Initializable { public class SplitMergeController implements Initializable, ISubscriber {
@FXML @FXML
private ToggleGroup splitMergeTogGrp; private ToggleGroup splitMergeTogGrp;
@FXML @FXML
@ -147,13 +146,87 @@ public class SplitMergeController implements Initializable {
convertBtn.setOnAction(actionEvent -> setConvertBtnAction()); convertBtn.setOnAction(actionEvent -> setConvertBtnAction());
} }
public void notifyThreadStarted(boolean isStart, EModule type){ // todo: refactor: remove everything, place to separate container and just disable. /**
if (! type.equals(EModule.SPLIT_MERGE_TOOL)){ * It's button listener when convert-process in progress
smToolPane.setDisable(isStart); * */
private void stopBtnAction(){
if (smThread != null && smThread.isAlive()) {
smThread.interrupt();
}
}
/**
* It's button listener when convert-process NOT in progress
* */
private void setConvertBtnAction(){
if (MediatorControl.INSTANCE.getTransferActive()) {
ServiceWindow.getErrorNotification(
resourceBundle.getString("windowTitleError"),
resourceBundle.getString("windowBodyPleaseFinishTransfersFirst")
);
return; return;
} }
if (isStart){
MediatorControl.getInstance().getContoller().logArea.clear(); if (splitRad.isSelected())
smTask = new SplitMergeTaskExecutor(true, BlockListViewController.getItems(), saveToPathLbl.getText());
else
smTask = new SplitMergeTaskExecutor(false, BlockListViewController.getItems(), saveToPathLbl.getText());
smThread = new Thread(smTask);
smThread.setDaemon(true);
smThread.start();
}
/**
* Drag-n-drop support (dragOver consumer)
* */
@FXML
private void handleDragOver(DragEvent event){
if (event.getDragboard().hasFiles() && ! MediatorControl.INSTANCE.getTransferActive())
event.acceptTransferModes(TransferMode.ANY);
event.consume();
}
/**
* Drag-n-drop support (drop consumer)
* */
@FXML
private void handleDrop(DragEvent event) {
List<File> files = event.getDragboard().getFiles();
File firstFile = files.get(0);
if (firstFile.isDirectory())
mergeRad.fire();
else
splitRad.fire();
this.BlockListViewController.addAll(files);
event.setDropCompleted(true);
event.consume();
}
/**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
if (splitRad.isSelected())
AppPreferences.getInstance().setSplitMergeType(0);
else
AppPreferences.getInstance().setSplitMergeType(1);
AppPreferences.getInstance().setSplitMergeRecent(saveToPathLbl.getText());
}
@Override
public void notify(EModule type, boolean isActive, Payload payload) {
// todo: refactor: remove everything, place to separate container and just disable.
if (! type.equals(EModule.SPLIT_MERGE_TOOL)){
smToolPane.setDisable(isActive);
return;
}
statusLbl.setText(payload.getMessage());
if (isActive){
splitRad.setDisable(true); splitRad.setDisable(true);
mergeRad.setDisable(true); mergeRad.setDisable(true);
selectFileFolderBtn.setDisable(true); selectFileFolderBtn.setDisable(true);
@ -182,79 +255,4 @@ public class SplitMergeController implements Initializable {
else else
convertRegion.getStyleClass().add("regionOneToSplit"); convertRegion.getStyleClass().add("regionOneToSplit");
} }
/**
* It's button listener when convert-process in progress
* */
private void stopBtnAction(){
if (smThread != null && smThread.isAlive()) {
smThread.interrupt();
}
}
/**
* It's button listener when convert-process NOT in progress
* */
private void setConvertBtnAction(){
statusLbl.setText("");
if (MediatorControl.getInstance().getTransferActive()) {
ServiceWindow.getErrorNotification(
resourceBundle.getString("windowTitleError"),
resourceBundle.getString("windowBodyPleaseFinishTransfersFirst")
);
return;
}
if (splitRad.isSelected())
smTask = new SplitMergeTaskExecutor(true, BlockListViewController.getItems(), saveToPathLbl.getText());
else
smTask = new SplitMergeTaskExecutor(false, BlockListViewController.getItems(), saveToPathLbl.getText());
smThread = new Thread(smTask);
smThread.setDaemon(true);
smThread.start();
}
/**
* Drag-n-drop support (dragOver consumer)
* */
@FXML
private void handleDragOver(DragEvent event){
if (event.getDragboard().hasFiles() && ! MediatorControl.getInstance().getTransferActive())
event.acceptTransferModes(TransferMode.ANY);
event.consume();
}
/**
* Drag-n-drop support (drop consumer)
* */
@FXML
private void handleDrop(DragEvent event) {
List<File> files = event.getDragboard().getFiles();
File firstFile = files.get(0);
if (firstFile.isDirectory())
mergeRad.fire();
else
splitRad.fire();
this.BlockListViewController.addAll(files);
event.setDropCompleted(true);
event.consume();
}
public void setOneLineStatus(boolean status){
if (status)
statusLbl.setText(resourceBundle.getString("done_txt"));
else
statusLbl.setText(resourceBundle.getString("failure_txt"));
}
/**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
if (splitRad.isSelected())
AppPreferences.getInstance().setSplitMergeType(0);
else
AppPreferences.getInstance().setSplitMergeType(1);
AppPreferences.getInstance().setSplitMergeRecent(saveToPathLbl.getText());
}
} }

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -18,44 +18,57 @@
*/ */
package nsusbloader; package nsusbloader;
import javafx.application.HostServices;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import nsusbloader.Controllers.*; import nsusbloader.Controllers.*;
import nsusbloader.NSLDataTypes.EModule; import nsusbloader.NSLDataTypes.EModule;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicBoolean;
public class MediatorControl { public class MediatorControl {
private final AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure public static final MediatorControl INSTANCE = new MediatorControl();
private NSLMainController mainController;
public static MediatorControl getInstance(){ private ResourceBundle resourceBundle;
return MediatorControlHold.INSTANCE; private TransfersPublisher transfersPublisher;
private HostServices hostServices;
private GamesController gamesController;
private SettingsController settingsController;
private TextArea logArea;
private ProgressBar progressBar;
private MediatorControl(){}
public void configure(ResourceBundle resourceBundle,
SettingsController settingsController,
TextArea logArea,
ProgressBar progressBar,
GamesController gamesController,
TransfersPublisher transfersPublisher) {
this.resourceBundle = resourceBundle;
this.settingsController = settingsController;
this.gamesController = gamesController;
this.logArea = logArea;
this.progressBar = progressBar;
this.transfersPublisher = transfersPublisher;
}
public void setHostServices(HostServices hostServices) {
this.hostServices = hostServices;
} }
private static class MediatorControlHold { public HostServices getHostServices() { return hostServices; }
private static final MediatorControl INSTANCE = new MediatorControl(); public ResourceBundle getResourceBundle(){ return resourceBundle; }
} public SettingsController getSettingsController() { return settingsController; }
public void setController(NSLMainController controller){ public GamesController getGamesController() { return gamesController; }
this.mainController = controller; public TextArea getLogArea() { return logArea; }
public ProgressBar getProgressBar() { return progressBar; }
public synchronized void setTransferActive(EModule appModuleType, boolean isActive, Payload payload) {
transfersPublisher.setTransferActive(appModuleType, isActive, payload);
} }
public NSLMainController getContoller(){ return mainController; } public synchronized boolean getTransferActive() {
public GamesController getGamesController(){ return mainController.getGamesCtrlr(); }; return transfersPublisher.getTransferActive();
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 ResourceBundle getResourceBundle(){
return mainController.getResourceBundle();
} }
public synchronized void setBgThreadActive(boolean isActive, EModule appModuleType) {
isTransferActive.set(isActive);
getGamesController().notifyThreadStarted(isActive, appModuleType);
getSplitMergeController().notifyThreadStarted(isActive, appModuleType);
getRcmController().notifyThreadStarted(isActive, appModuleType);
getNxdtController().notifyThreadStarted(isActive, appModuleType);
}
public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
} }

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -40,9 +40,13 @@ public class LogPrinterGui implements ILogPrinter {
LogPrinterGui(EModule whoIsAsking){ LogPrinterGui(EModule whoIsAsking){
this.msgQueue = new LinkedBlockingQueue<>(); this.msgQueue = new LinkedBlockingQueue<>();
this.progressQueue = new LinkedBlockingQueue<>(); this.progressQueue = new LinkedBlockingQueue<>();
this.statusMap = new HashMap<>(); this.statusMap = new HashMap<>();
this.oneLinerStatus = new AtomicBoolean(); this.oneLinerStatus = new AtomicBoolean();
this.msgConsumer = new MessagesConsumer(whoIsAsking, this.msgQueue, this.progressQueue, this.statusMap, this.oneLinerStatus); this.msgConsumer = new MessagesConsumer(whoIsAsking,
this.msgQueue,
this.progressQueue,
this.statusMap,
this.oneLinerStatus);
this.msgConsumer.start(); this.msgConsumer.start();
} }
/** /**

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -22,24 +22,26 @@ import javafx.animation.AnimationTimer;
import javafx.scene.control.ProgressBar; import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextArea; import javafx.scene.control.TextArea;
import nsusbloader.Controllers.NSTableViewController; import nsusbloader.Controllers.Payload;
import nsusbloader.MediatorControl; import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EModule; import nsusbloader.NSLDataTypes.EModule;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class MessagesConsumer extends AnimationTimer { public class MessagesConsumer extends AnimationTimer {
private final BlockingQueue<String> msgQueue; private static final MediatorControl mediator = MediatorControl.INSTANCE;
private final TextArea logsArea; private static final TextArea logsArea = mediator.getLogArea();
private static final ProgressBar progressBar = mediator.getProgressBar();;
private static final ResourceBundle resourceBundle = mediator.getResourceBundle();
private final BlockingQueue<String> msgQueue;
private final BlockingQueue<Double> progressQueue; private final BlockingQueue<Double> progressQueue;
private final ProgressBar progressBar;
private final HashMap<String, EFileStatus> statusMap; private final HashMap<String, EFileStatus> statusMap;
private final NSTableViewController tableViewController;
private final EModule appModuleType; private final EModule appModuleType;
private final AtomicBoolean oneLinerStatus; private final AtomicBoolean oneLinerStatus;
@ -53,22 +55,16 @@ public class MessagesConsumer extends AnimationTimer {
AtomicBoolean oneLinerStatus){ AtomicBoolean oneLinerStatus){
this.appModuleType = appModuleType; this.appModuleType = appModuleType;
this.isInterrupted = false; this.isInterrupted = false;
this.msgQueue = msgQueue; this.msgQueue = msgQueue;
this.logsArea = MediatorControl.getInstance().getContoller().logArea;
this.progressQueue = progressQueue; this.progressQueue = progressQueue;
this.progressBar = MediatorControl.getInstance().getContoller().progressBar;
this.statusMap = statusMap; this.statusMap = statusMap;
this.tableViewController = MediatorControl.getInstance().getGamesController().tableFilesListController;
this.oneLinerStatus = oneLinerStatus; this.oneLinerStatus = oneLinerStatus;
progressBar.setProgress(0.0); progressBar.setProgress(0.0);
progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS); progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
MediatorControl.getInstance().setBgThreadActive(true, appModuleType);
logsArea.clear();
mediator.setTransferActive(appModuleType, true, new Payload());
} }
@Override @Override
@ -89,30 +85,18 @@ public class MessagesConsumer extends AnimationTimer {
}); });
} }
if (isInterrupted) // It's safe 'cuz it's could't be interrupted while HashMap populating if (isInterrupted) // safe, could not be interrupted while HashMap populating
updateElementsAndStop(); updateElementsAndStop();
} }
private void updateElementsAndStop(){ private void updateElementsAndStop(){
MediatorControl.getInstance().setBgThreadActive(false, appModuleType); Payload payload = new Payload(
resourceBundle.getString(oneLinerStatus.get() ? "done_txt" : "failure_txt"),
statusMap);
mediator.setTransferActive(appModuleType, false, payload);
progressBar.setProgress(0.0); progressBar.setProgress(0.0);
if (statusMap.size() > 0){
for (String key : statusMap.keySet())
tableViewController.setFileStatus(key, statusMap.get(key));
}
switch (appModuleType){
case RCM:
MediatorControl.getInstance().getRcmController().setOneLineStatus(oneLinerStatus.get());
break;
case NXDT:
MediatorControl.getInstance().getNxdtController().setOneLineStatus(oneLinerStatus.get());
break;
case SPLIT_MERGE_TOOL:
MediatorControl.getInstance().getSplitMergeController().setOneLineStatus(oneLinerStatus.get());
break;
}
this.stop(); this.stop();
} }

View file

@ -22,5 +22,6 @@ public enum EModule {
USB_NET_TRANSFERS, USB_NET_TRANSFERS,
SPLIT_MERGE_TOOL, SPLIT_MERGE_TOOL,
RCM, RCM,
NXDT NXDT,
PATCHES
} }

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -28,6 +28,7 @@ import nsusbloader.Controllers.NSLMainController;
import nsusbloader.cli.CommandLineInterface; import nsusbloader.cli.CommandLineInterface;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class NSLMain extends Application { public class NSLMain extends Application {
@ -41,16 +42,15 @@ public class NSLMain extends Application {
Locale userLocale = AppPreferences.getInstance().getLocale(); Locale userLocale = AppPreferences.getInstance().getLocale();
ResourceBundle rb = ResourceBundle.getBundle("locale", userLocale); ResourceBundle rb = ResourceBundle.getBundle("locale", userLocale);
NSLMain.appVersion = ResourceBundle.getBundle("app").getString("_version");
loader.setResources(rb); loader.setResources(rb);
Parent root = loader.load(); Parent root = loader.load();
primaryStage.getIcons().addAll( primaryStage.getIcons().addAll(
new Image(getClass().getResourceAsStream("/res/app_icon32x32.png")), new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon32x32.png"))),
new Image(getClass().getResourceAsStream("/res/app_icon48x48.png")), new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon48x48.png"))),
new Image(getClass().getResourceAsStream("/res/app_icon64x64.png")), new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon64x64.png"))),
new Image(getClass().getResourceAsStream("/res/app_icon128x128.png")) new Image(Objects.requireNonNull(getClass().getResourceAsStream("/res/app_icon128x128.png")))
); );
primaryStage.setTitle("NS-USBloader "+appVersion); primaryStage.setTitle("NS-USBloader "+appVersion);
@ -62,19 +62,21 @@ public class NSLMain extends Application {
); );
mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme()); mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
root.setStyle(AppPreferences.getInstance().getFontStyle());
primaryStage.setScene(mainScene); primaryStage.setScene(mainScene);
primaryStage.show(); primaryStage.show();
primaryStage.setOnCloseRequest(e->{ primaryStage.setOnCloseRequest(e->{
if (MediatorControl.getInstance().getTransferActive()) if (MediatorControl.INSTANCE.getTransferActive())
if(! ServiceWindow.getConfirmationWindow(rb.getString("windowTitleConfirmExit"), if(! ServiceWindow.getConfirmationWindow(rb.getString("windowTitleConfirmExit"),
rb.getString("windowBodyConfirmExit"))) rb.getString("windowBodyConfirmExit")))
e.consume(); e.consume();
}); });
NSLMainController controller = loader.getController(); NSLMainController controller = loader.getController();
controller.setHostServices(getHostServices()); MediatorControl.INSTANCE.setHostServices(getHostServices());
primaryStage.setOnHidden(e-> { primaryStage.setOnHidden(e-> {
AppPreferences.getInstance().setSceneHeight(mainScene.getHeight()); AppPreferences.getInstance().setSceneHeight(mainScene.getHeight());
AppPreferences.getInstance().setSceneWidth(mainScene.getWidth()); AppPreferences.getInstance().setSceneWidth(mainScene.getWidth());
@ -83,6 +85,7 @@ public class NSLMain extends Application {
} }
public static void main(String[] args) { public static void main(String[] args) {
NSLMain.appVersion = ResourceBundle.getBundle("app").getString("_version");
if (args.length == 0) { if (args.length == 0) {
launch(args); launch(args);
} }

View file

@ -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");
}
}

View file

@ -44,7 +44,6 @@ public class ServiceWindow {
alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE); alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE);
alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE); alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
alertBox.setResizable(true); // Java bug workaround for JDR11/OpenJFX. TODO: nothing. really. 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(); Stage dialogStage = (Stage) alertBox.getDialogPane().getScene().getWindow();
dialogStage.setAlwaysOnTop(true); dialogStage.setAlwaysOnTop(true);
@ -54,6 +53,9 @@ public class ServiceWindow {
new Image("/res/warn_ico64x64.png"), new Image("/res/warn_ico64x64.png"),
new Image("/res/warn_ico128x128.png") new Image("/res/warn_ico128x128.png")
); );
alertBox.getDialogPane().getStylesheets().add(AppPreferences.getInstance().getTheme());
dialogStage.getScene().getRoot().setStyle(AppPreferences.getInstance().getFontStyle());
alertBox.show(); alertBox.show();
dialogStage.toFront(); dialogStage.toFront();
} }
@ -68,7 +70,6 @@ public class ServiceWindow {
alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE); alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE);
alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE); alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
alertBox.setResizable(true); // Java bug workaround for JDR11/OpenJFX. TODO: nothing. really. 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(); Stage dialogStage = (Stage) alertBox.getDialogPane().getScene().getWindow();
dialogStage.setAlwaysOnTop(true); dialogStage.setAlwaysOnTop(true);
@ -78,6 +79,10 @@ public class ServiceWindow {
new Image("/res/ask_ico64x64.png"), new Image("/res/ask_ico64x64.png"),
new Image("/res/ask_ico128x128.png") new Image("/res/ask_ico128x128.png")
); );
alertBox.getDialogPane().getStylesheets().add(AppPreferences.getInstance().getTheme());
dialogStage.getScene().getRoot().setStyle(AppPreferences.getInstance().getFontStyle());
dialogStage.toFront(); dialogStage.toFront();
Optional<ButtonType> result = alertBox.showAndWait(); Optional<ButtonType> result = alertBox.showAndWait();

View file

@ -0,0 +1,47 @@
/*
Copyright 2019-2024 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 nsusbloader.Controllers.ISubscriber;
import nsusbloader.Controllers.Payload;
import nsusbloader.NSLDataTypes.EModule;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class TransfersPublisher {
private final AtomicBoolean isTransferActive = new AtomicBoolean(false);
private final List<ISubscriber> subscribers = new ArrayList<>();
public TransfersPublisher(ISubscriber... subscriber){
subscribers.addAll(Arrays.asList(subscriber));
}
public void setTransferActive(EModule appModuleType, boolean isActive, Payload payload) {
isTransferActive.set(isActive);
subscribers.forEach(s->s.notify(appModuleType, isActive, payload));
}
public boolean getTransferActive() {
return isTransferActive.get();
}
}

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2022 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -26,16 +26,14 @@ public class LocaleHolder {
private final String localeCode; private final String localeCode;
private final String languageName; 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) { public LocaleHolder(String localeFileName) {
String country = localeFileName.substring(7, 9); String language = localeFileName.substring(7, 9);
String language = localeFileName.substring(10, 12); String country;
this.locale = new Locale(country, language); 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.localeCode = locale.toString();
this.languageName = locale.getDisplayLanguage(locale) + " (" + locale + ")"; this.languageName = locale.getDisplayLanguage(locale) + " (" + locale + ")";
} }
@ -47,7 +45,7 @@ public class LocaleHolder {
public String getLocaleCode(){ public String getLocaleCode(){
return localeCode; return localeCode;
}; }
public Locale getLocale() { public Locale getLocale() {
return locale; return locale;

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2023 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -25,8 +25,8 @@ import java.net.URL;
public class DownloadDriversTask extends Task<String> { 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 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; private static File driversInstallerFile;
@ -38,7 +38,7 @@ public class DownloadDriversTask extends Task<String> {
} }
private boolean isDriversDownloaded(){ private boolean isDriversDownloaded(){
return driversInstallerFile != null && driversInstallerFile.length() == driversFileSize; return driversInstallerFile != null && driversInstallerFile.length() == DRIVERS_FILE_SIZE;
} }
private boolean downloadDrivers(){ private boolean downloadDrivers(){
@ -64,7 +64,7 @@ public class DownloadDriversTask extends Task<String> {
while ((bytesRead = bis.read(dataBuffer, 0, 1024)) != -1) { while ((bytesRead = bis.read(dataBuffer, 0, 1024)) != -1) {
fos.write(dataBuffer, 0, bytesRead); fos.write(dataBuffer, 0, bytesRead);
totalRead += bytesRead; totalRead += bytesRead;
updateProgress(totalRead, driversFileSize); updateProgress(totalRead, DRIVERS_FILE_SIZE);
if (this.isCancelled()) { if (this.isCancelled()) {
bis.close(); bis.close();
fos.close(); fos.close();

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2023 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -32,19 +32,32 @@ import javafx.scene.layout.VBox;
import javafx.stage.Stage; import javafx.stage.Stage;
import nsusbloader.AppPreferences; import nsusbloader.AppPreferences;
import java.io.BufferedReader; import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class DriversInstall { public class DriversInstall {
private static volatile boolean isRunning; private static volatile boolean isRunning;
private final ResourceBundle resourceBundle;
private Label runInstallerStatusLabel; private Label runInstallerStatusLabel;
public DriversInstall(ResourceBundle rb){ 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) if (DriversInstall.isRunning)
return; return;
@ -52,11 +65,11 @@ public class DriversInstall {
DownloadDriversTask downloadTask = new DownloadDriversTask(); DownloadDriversTask downloadTask = new DownloadDriversTask();
Button cancelButton = new Button(rb.getString("btn_Cancel")); Button cancelButton = new Button(resourceBundle.getString("btn_Cancel"));
HBox hBoxInformation = new HBox(); HBox hBoxInformation = new HBox();
hBoxInformation.setAlignment(Pos.TOP_LEFT); 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 progressBar = new ProgressBar();
progressBar.setPrefWidth(Double.MAX_VALUE); progressBar.setPrefWidth(Double.MAX_VALUE);
@ -93,7 +106,7 @@ public class DriversInstall {
Stage stage = new Stage(); Stage stage = new Stage();
stage.setTitle(rb.getString("windowTitleDownloadDrivers")); stage.setTitle(resourceBundle.getString("windowTitleDownloadDrivers"));
stage.getIcons().addAll( stage.getIcons().addAll(
new Image("/res/dwnload_ico32x32.png"), //TODO: REDRAW new Image("/res/dwnload_ico32x32.png"), //TODO: REDRAW
new Image("/res/dwnload_ico48x48.png"), new Image("/res/dwnload_ico48x48.png"),
@ -106,6 +119,7 @@ public class DriversInstall {
Scene mainScene = new Scene(parentVBox, 405, 155); Scene mainScene = new Scene(parentVBox, 405, 155);
mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme()); mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
parentVBox.setStyle(AppPreferences.getInstance().getFontStyle());
stage.setOnHidden(windowEvent -> { stage.setOnHidden(windowEvent -> {
downloadTask.cancel(true ); downloadTask.cancel(true );
@ -117,7 +131,7 @@ public class DriversInstall {
stage.toFront(); stage.toFront();
downloadTask.setOnSucceeded(event -> { downloadTask.setOnSucceeded(event -> {
cancelButton.setText(rb.getString("btn_Close")); cancelButton.setText(resourceBundle.getString("btn_Close"));
String returnedValue = downloadTask.getValue(); String returnedValue = downloadTask.getValue();
@ -143,7 +157,7 @@ public class DriversInstall {
return true; return true;
} }
catch (Exception e){ catch (Exception e){
runInstallerStatusLabel.setText("Error: "+e.toString()); runInstallerStatusLabel.setText("Error: "+e);
e.printStackTrace(); e.printStackTrace();
return false; return false;
} }

View file

@ -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);
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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; }
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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; }
}

View file

@ -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();
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -32,7 +32,6 @@ public class CommandLineInterface {
} }
final Options cliOptions = createCliOptions(); final Options cliOptions = createCliOptions();
CommandLineParser cliParser = new DefaultParser(); CommandLineParser cliParser = new DefaultParser();
try{ try{
CommandLine cli = cliParser.parse(cliOptions, args); CommandLine cli = cliParser.parse(cliOptions, args);
@ -68,6 +67,11 @@ public class CommandLineInterface {
new GoldLeafCli(arguments); new GoldLeafCli(arguments);
return; return;
} }
if (cli.hasOption("experimental")){
final String[] arguments = cli.getOptionValues("experimental");
new ExperimentalCli(arguments);
return;
}
/* /*
if (cli.hasOption("x") || cli.hasOption("nxdt")){ if (cli.hasOption("x") || cli.hasOption("nxdt")){
final String[] arguments = cli.getOptionValues("nxdt"); final String[] arguments = cli.getOptionValues("nxdt");
@ -154,6 +158,12 @@ public class CommandLineInterface {
.hasArgs() .hasArgs()
.argName("...") .argName("...")
.build(); .build();
final Option experimentalOption = Option.builder()
.longOpt("experimental")
.desc("Enable testing and experimental functions")
.hasArgs()
.argName("y|n")
.build();
/* nxdumptool */ /* nxdumptool */
/* /*
final Option nxdtOption = Option.builder("x") final Option nxdtOption = Option.builder("x")
@ -184,6 +194,7 @@ public class CommandLineInterface {
group.addOption(helpOption); group.addOption(helpOption);
group.addOption(tinfoilOption); group.addOption(tinfoilOption);
group.addOption(glOption); group.addOption(glOption);
group.addOption(experimentalOption);
//group.addOption(nxdtOption); //group.addOption(nxdtOption);
group.addOption(splitOption); group.addOption(splitOption);
group.addOption(mergeOption); group.addOption(mergeOption);

View file

@ -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");
}
}

View file

@ -34,7 +34,7 @@ public class GoldLeafCli {
private int parseFileSince = 1; private int parseFileSince = 1;
public GoldLeafCli(String[] arguments) throws InterruptedException, IncorrectSetupException{ GoldLeafCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
this.arguments = arguments; this.arguments = arguments;
checkArguments(); checkArguments();
@ -43,7 +43,7 @@ public class GoldLeafCli {
runGoldLeafBackend(); runGoldLeafBackend();
} }
public void checkArguments() throws IncorrectSetupException{ private void checkArguments() throws IncorrectSetupException{
if (arguments == null || arguments.length == 0) { if (arguments == null || arguments.length == 0) {
throw new IncorrectSetupException("No arguments.\n" + throw new IncorrectSetupException("No arguments.\n" +
"Try 'ns-usbloader -g help' for more information."); "Try 'ns-usbloader -g help' for more information.");
@ -75,7 +75,7 @@ public class GoldLeafCli {
private String getGlSupportedVersions(){ private String getGlSupportedVersions(){
StringBuilder builder = new StringBuilder("Supported versions: \n"); StringBuilder builder = new StringBuilder("Supported versions: \n");
for (String a : AppPreferences.goldleafSupportedVersions){ for (String a : AppPreferences.GOLDLEAF_SUPPORTED_VERSIONS){
builder.append("\t"); builder.append("\t");
builder.append(a); builder.append(a);
builder.append("\n"); builder.append("\n");
@ -83,7 +83,7 @@ public class GoldLeafCli {
return builder.toString(); return builder.toString();
} }
public void parseGoldLeafVersion() throws IncorrectSetupException{ private void parseGoldLeafVersion() throws IncorrectSetupException{
String argument1 = arguments[0]; String argument1 = arguments[0];
if (! argument1.startsWith("ver=")) { if (! argument1.startsWith("ver=")) {
@ -98,7 +98,7 @@ public class GoldLeafCli {
"Try 'ns-usbloader -g help' for more information."); "Try 'ns-usbloader -g help' for more information.");
} }
for (String version : AppPreferences.goldleafSupportedVersions){ for (String version : AppPreferences.GOLDLEAF_SUPPORTED_VERSIONS){
if (version.equals(goldLeafVersion)) if (version.equals(goldLeafVersion))
return; return;
} }
@ -107,7 +107,7 @@ public class GoldLeafCli {
getGlSupportedVersions()); getGlSupportedVersions());
} }
public void parseFilesArguments() throws IncorrectSetupException{ private void parseFilesArguments() throws IncorrectSetupException{
filesList = new ArrayList<>(); filesList = new ArrayList<>();
File file; File file;
@ -123,7 +123,7 @@ public class GoldLeafCli {
} }
} }
public void runGoldLeafBackend() throws InterruptedException { private void runGoldLeafBackend() throws InterruptedException {
Runnable task = new UsbCommunications(filesList, Runnable task = new UsbCommunications(filesList,
"GoldLeaf"+goldLeafVersion, "GoldLeaf"+goldLeafVersion,
filterForNsp); filterForNsp);

View file

@ -27,7 +27,7 @@ public class NxdtCli {
private final String[] arguments; private final String[] arguments;
private String saveTo; private String saveTo;
public NxdtCli(String[] arguments) throws InterruptedException, IncorrectSetupException{ NxdtCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
this.arguments = arguments; this.arguments = arguments;
parseArgument(); parseArgument();
runBackend(); runBackend();

View file

@ -29,7 +29,7 @@ public class TinfoilUsbCli {
private final String[] arguments; private final String[] arguments;
private List<File> filesList; private List<File> filesList;
public TinfoilUsbCli(String[] arguments) throws InterruptedException, IncorrectSetupException{ TinfoilUsbCli(String[] arguments) throws InterruptedException, IncorrectSetupException{
this.arguments = arguments; this.arguments = arguments;
checkArguments(); checkArguments();
parseFilesArguments(); parseFilesArguments();

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2022 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -933,7 +933,7 @@ class GoldLeaf_010 extends TransferModule {
private boolean selectFile(){ private boolean selectFile(){
File selectedFile = CompletableFuture.supplyAsync(() -> { File selectedFile = CompletableFuture.supplyAsync(() -> {
FileChooser fChooser = new FileChooser(); FileChooser fChooser = new FileChooser();
fChooser.setTitle(MediatorControl.getInstance().getResourceBundle().getString("btn_OpenFile")); // TODO: FIX BAD IMPLEMENTATION fChooser.setTitle(MediatorControl.INSTANCE.getResourceBundle().getString("btn_OpenFile")); // TODO: FIX BAD IMPLEMENTATION
fChooser.setInitialDirectory(new File(System.getProperty("user.home")));// TODO: Consider fixing; not a priority. fChooser.setInitialDirectory(new File(System.getProperty("user.home")));// TODO: Consider fixing; not a priority.
fChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("*", "*")); fChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("*", "*"));
return fChooser.showOpenDialog(null); // Leave as is for now. return fChooser.showOpenDialog(null); // Leave as is for now.

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -918,7 +918,7 @@ class GoldLeaf_07 extends TransferModule {
private boolean selectFile(){ private boolean selectFile(){
File selectedFile = CompletableFuture.supplyAsync(() -> { File selectedFile = CompletableFuture.supplyAsync(() -> {
FileChooser fChooser = new FileChooser(); FileChooser fChooser = new FileChooser();
fChooser.setTitle(MediatorControl.getInstance().getResourceBundle().getString("btn_OpenFile")); // TODO: FIX BAD IMPLEMENTATION fChooser.setTitle(MediatorControl.INSTANCE.getResourceBundle().getString("btn_OpenFile")); // TODO: FIX BAD IMPLEMENTATION
fChooser.setInitialDirectory(new File(System.getProperty("user.home"))); // TODO: Consider fixing; not a prio. fChooser.setInitialDirectory(new File(System.getProperty("user.home"))); // TODO: Consider fixing; not a prio.
fChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("*", "*")); fChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("*", "*"));
return fChooser.showOpenDialog(null); // Leave as is for now. return fChooser.showOpenDialog(null); // Leave as is for now.

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2020 Dmitry Isaenko Copyright 2019-2024 Dmitry Isaenko
This file is part of NS-USBloader. This file is part of NS-USBloader.
@ -941,7 +941,7 @@ class GoldLeaf_08 extends TransferModule {
private boolean selectFile(){ private boolean selectFile(){
File selectedFile = CompletableFuture.supplyAsync(() -> { File selectedFile = CompletableFuture.supplyAsync(() -> {
FileChooser fChooser = new FileChooser(); FileChooser fChooser = new FileChooser();
fChooser.setTitle(MediatorControl.getInstance().getResourceBundle().getString("btn_OpenFile")); // TODO: FIX BAD IMPLEMENTATION fChooser.setTitle(MediatorControl.INSTANCE.getResourceBundle().getString("btn_OpenFile")); // TODO: FIX BAD IMPLEMENTATION
fChooser.setInitialDirectory(new File(System.getProperty("user.home")));// TODO: Consider fixing; not a prio. fChooser.setInitialDirectory(new File(System.getProperty("user.home")));// TODO: Consider fixing; not a prio.
fChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("*", "*")); fChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("*", "*"));
return fChooser.showOpenDialog(null); // Leave as is for now. return fChooser.showOpenDialog(null); // Leave as is for now.

View file

@ -66,7 +66,7 @@ public class UsbCommunications extends CancellableRunnable {
case "TinFoil": case "TinFoil":
module = new TinFoil(handler, nspMap, this, logPrinter); module = new TinFoil(handler, nspMap, this, logPrinter);
break; break;
case "GoldLeafv0.10": case "GoldLeafv0.10+":
module = new GoldLeaf_010(handler, nspMap, this, logPrinter, nspFilterForGl); module = new GoldLeaf_010(handler, nspMap, this, logPrinter, nspFilterForGl);
break; break;
case "GoldLeafv0.8-0.9": case "GoldLeafv0.8-0.9":

View file

@ -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>

View file

@ -55,7 +55,7 @@
<Insets /> <Insets />
</HBox.margin> </HBox.margin>
</Button> </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> <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" /> <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> </graphic></Button>

View file

@ -15,7 +15,7 @@ Steps to roll NXDT functionality back:
* Set 'Visible' on NXDT Tab selector (SVGPath container) * 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> <children>
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children> <children>
@ -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" /> <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> </graphic>
</Tab> </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"> <Tab closable="false">
<content> <content>
<fx:include fx:id="SettingsTab" source="SettingsTab.fxml" VBox.vgrow="ALWAYS" /> <fx:include fx:id="SettingsTab" source="SettingsTab.fxml" VBox.vgrow="ALWAYS" />

View file

@ -12,21 +12,12 @@
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.SVGPath?> <?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"> <HBox alignment="CENTER">
<children> <children>
<Label styleClass="nxdt" text="nx"> <Label styleClass="nxdt" text="nx" />
<font> <Label styleClass="bold-text" text="dumptool" />
<Font name="System Bold" size="18.0" />
</font>
</Label>
<Label text="dumptool">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Label>
</children> </children>
</HBox> </HBox>
<GridPane> <GridPane>

View file

@ -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>

View file

@ -14,18 +14,13 @@
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.SVGPath?> <?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"> <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%);" /> <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"> <HBox alignment="CENTER">
<children> <children>
<Label text="%tabRcm_Lbl_FuseeGelee"> <Label styleClass="bold-text" text="%tabRcm_Lbl_FuseeGelee" />
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
</children> </children>
</HBox> </HBox>
<GridPane> <GridPane>
@ -57,11 +52,7 @@
<Label fx:id="payloadFNameLbl1" /> <Label fx:id="payloadFNameLbl1" />
</children> </children>
</HBox> </HBox>
<Label fx:id="payloadFPathLbl1" disable="true"> <Label fx:id="payloadFPathLbl1" disable="true" styleClass="italic-text" />
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children> </children>
</VBox> </VBox>
<Button fx:id="selPldBtn1" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect"> <Button fx:id="selPldBtn1" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
@ -86,11 +77,7 @@
<Label fx:id="payloadFNameLbl2" /> <Label fx:id="payloadFNameLbl2" />
</children> </children>
</HBox> </HBox>
<Label fx:id="payloadFPathLbl2" disable="true"> <Label fx:id="payloadFPathLbl2" disable="true" styleClass="italic-text" />
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children> </children>
</VBox> </VBox>
<Button fx:id="selPldBtn2" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect"> <Button fx:id="selPldBtn2" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
@ -115,11 +102,7 @@
<Label fx:id="payloadFNameLbl3" /> <Label fx:id="payloadFNameLbl3" />
</children> </children>
</HBox> </HBox>
<Label fx:id="payloadFPathLbl3" disable="true"> <Label fx:id="payloadFPathLbl3" disable="true" styleClass="italic-text" />
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children> </children>
</VBox> </VBox>
<Button fx:id="selPldBtn3" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect"> <Button fx:id="selPldBtn3" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
@ -144,11 +127,7 @@
<Label fx:id="payloadFNameLbl4" /> <Label fx:id="payloadFNameLbl4" />
</children> </children>
</HBox> </HBox>
<Label fx:id="payloadFPathLbl4" disable="true"> <Label fx:id="payloadFPathLbl4" disable="true" styleClass="italic-text" />
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children> </children>
</VBox> </VBox>
<Button fx:id="selPldBtn4" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect"> <Button fx:id="selPldBtn4" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">
@ -173,11 +152,7 @@
<Label fx:id="payloadFNameLbl5" /> <Label fx:id="payloadFNameLbl5" />
</children> </children>
</HBox> </HBox>
<Label fx:id="payloadFPathLbl5" disable="true"> <Label fx:id="payloadFPathLbl5" disable="true" styleClass="italic-text" />
<font>
<Font name="System Italic" size="13.0" />
</font>
</Label>
</children> </children>
</VBox> </VBox>
<Button fx:id="selPldBtn5" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect"> <Button fx:id="selPldBtn5" mnemonicParsing="false" onAction="#bntSelectPayloader" styleClass="buttonSelect">

View file

@ -10,7 +10,7 @@
<?import javafx.scene.layout.Pane?> <?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?> <?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> <children>
<Label text="%tab2_Lbl_ApplicationSettings" /> <Label text="%tab2_Lbl_ApplicationSettings" />
<HBox alignment="CENTER_LEFT" spacing="5.0"> <HBox alignment="CENTER_LEFT" spacing="5.0">
@ -28,6 +28,11 @@
<Insets left="5.0" /> <Insets left="5.0" />
</VBox.margin> </VBox.margin>
</HBox> </HBox>
<Button fx:id="fontSelectBtn" mnemonicParsing="false" text="%tab2_Btn_ApplicationFont">
<VBox.margin>
<Insets left="5.0" />
</VBox.margin>
</Button>
<HBox> <HBox>
<children> <children>
<VBox> <VBox>

View file

@ -12,19 +12,14 @@
<?import javafx.scene.layout.Pane?> <?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.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"> <VBox spacing="15.0">
<children> <children>
<Pane minHeight="-Infinity" prefHeight="10.0" style="-fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #00c8fc 40%, transparent 45%);" /> <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"> <HBox alignment="CENTER">
<children> <children>
<Label text="%tabSplMrg_Lbl_SplitNMergeTitle"> <Label styleClass="bold-text" text="%tabSplMrg_Lbl_SplitNMergeTitle" />
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
</children> </children>
</HBox> </HBox>
<GridPane> <GridPane>

View file

@ -45,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_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 tab2_Lbl_Language=Language
windowBodyRestartToApplyLang=Please restart application to apply changes. windowBodyRestartToApplyLang=Please restart application to apply changes.
btn_OpenSplitFile=Select split NSP btn_OpenSplitFile=Select split
tab2_Lbl_ApplicationSettings=Main settings tab2_Lbl_ApplicationSettings=Main settings
tabSplMrg_Lbl_SplitNMergeTitle=Split & merge files tool tabSplMrg_Lbl_SplitNMergeTitle=Split & merge files tool
tabSplMrg_RadioBtn_Split=Split tabSplMrg_RadioBtn_Split=Split
@ -79,3 +79,19 @@ windowBodyFilesScanned=Files scanned: %d\nWould be added: %d
tab2_Lbl_AwooBlockTitle=Awoo Installer and compatible tab2_Lbl_AwooBlockTitle=Awoo Installer and compatible
tabRcm_Lbl_Payload=Payload: 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:

View file

@ -43,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_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 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. 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 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_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 tabSplMrg_RadioBtn_Split=\u062A\u0642\u0633\u064A\u0645

View file

@ -43,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_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 tab2_Lbl_Language=Jazyk
windowBodyRestartToApplyLang=Pro aplikov\u00E1n\u00ED zm\u011Bn restartujte aplikaci. 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 tab2_Lbl_ApplicationSettings=Hlavn\u00ED nastaven\u00ED
tabSplMrg_Lbl_SplitNMergeTitle=Utilita k rozd\u011Blen\u00ED/slou\u010Den\u00ED soubor\u016F tabSplMrg_Lbl_SplitNMergeTitle=Utilita k rozd\u011Blen\u00ED/slou\u010Den\u00ED soubor\u016F
tabSplMrg_RadioBtn_Split=Rozd\u011Blit tabSplMrg_RadioBtn_Split=Rozd\u011Blit

View file

@ -45,7 +45,7 @@ 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_AllowXciNszXczDesc=Von einigen Drittanbietern verwendet, welche XCI/NSZ/XCZ unterst\u00FCtzen, nutzt z Transfer Protocol. Nicht \u00E4ndern, wenn unsicher.
tab2_Lbl_Language=Sprache tab2_Lbl_Language=Sprache
windowBodyRestartToApplyLang=Bitte die Applikation neustarten um die Einstellungen zu \u00FCbernehmen. 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. tab2_Cb_GLshowNspOnly=Nur *.nsp in GoldLeaf zeigen.
btn_Cancel=Abbrechen btn_Cancel=Abbrechen

View file

@ -1,80 +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://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
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:

View file

@ -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 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_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_FilesToUploadTitle=Fichiers a envoyer:
tab3_Txt_GreetingsMessage=Bienvenue sur NS-USBloader tab3_Txt_GreetingsMessage=Bienvenue sur NS-USBloader
@ -9,21 +11,21 @@ windowBodyConfirmExit=Le transfert de donn\u00E9es est en cours et la fermeture
windowTitleConfirmExit=Non, ne faites pas \u00E7a! windowTitleConfirmExit=Non, ne faites pas \u00E7a!
btn_Stop=Interrompre btn_Stop=Interrompre
tab3_Txt_GreetingsMessage2=--\n\ tab3_Txt_GreetingsMessage2=--\n\
Source: https://git.redrise.ru/desu/ns-usbloader\n\ Source : https://git.redrise.ru/desu/ns-usbloader\n\
Mirror: https://github.com/developersu/ns-usbloader/\n\ Mirror : https://github.com/developersu/ns-usbloader/\n\
Site: https://redrise.ru\n\ Site : https://redrise.ru\n\
Dmitry Isaenko [developer.su] 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_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_BtnDelete=Supprimer
tab1_table_contextMenu_Btn_DeleteAll=Supprimer tout tab1_table_contextMenu_Btn_DeleteAll=Supprimer tout
tab2_Lbl_HostIP=IP de l'ordinateur tab2_Lbl_HostIP=IP de l'ordinateur
tab1_Lbl_NSIP=IP de NS: tab1_Lbl_NSIP=IP de NS:
tab2_Cb_ValidateNSHostName=Toujours v\u00E9rifier que l'adresse IP de NS entr\u00E9e est correcte 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 ? 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_Cb_ExpertMode=Mode expert
tab2_Lbl_HostPort=port tab2_Lbl_HostPort=port
tab2_Cb_AutoDetectIp=D\u00E9tection automatique d'IP tab2_Cb_AutoDetectIp=D\u00E9tection automatique d'IP
@ -37,12 +39,24 @@ tab2_Cb_AutoCheckForUpdates=V\u00E9rifier automatiquement les mises \u00E0 jour
windowTitleNewVersionAval=Nouvelle version disponible windowTitleNewVersionAval=Nouvelle version disponible
windowTitleNewVersionNOTAval=Aucune nouvelle version disponible windowTitleNewVersionNOTAval=Aucune nouvelle version disponible
windowTitleNewVersionUnknown=Impossible de v\u00E9rifier les nouvelles versions 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 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_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_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_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.

View file

@ -45,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_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 tab2_Lbl_Language=Lingua
windowBodyRestartToApplyLang=Riavvia l'applicazione per applicare le modifiche. windowBodyRestartToApplyLang=Riavvia l'applicazione per applicare le modifiche.
btn_OpenSplitFile=Seleziona NSP troncato btn_OpenSplitFile=Seleziona il file truncato
tab2_Lbl_ApplicationSettings=Impostazioni principali tab2_Lbl_ApplicationSettings=Impostazioni principali
tabSplMrg_Lbl_SplitNMergeTitle=Strumento tronca e unisci file tabSplMrg_Lbl_SplitNMergeTitle=Strumento tronca e unisci file
tabSplMrg_RadioBtn_Split=Tronca tabSplMrg_RadioBtn_Split=Tronca

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
btn_OpenFile=\uD30C\uC77C \uC120\uD0DD 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_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. 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_EnteredAsMsg1=\uB2E4\uC74C\uACFC \uAC19\uC774 \uC785\uB825\uB418\uC5C8\uC2B5\uB2C8\uB2E4:
@ -45,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_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 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. 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 tab2_Lbl_ApplicationSettings=\uC8FC\uC694 \uC124\uC815
tabSplMrg_Lbl_SplitNMergeTitle=\uD30C\uC77C \uBD84\uD560 & \uBCD1\uD569 \uB3C4\uAD6C tabSplMrg_Lbl_SplitNMergeTitle=\uD30C\uC77C \uBD84\uD560 & \uBCD1\uD569 \uB3C4\uAD6C
tabSplMrg_RadioBtn_Split=\uBD84\uD560 tabSplMrg_RadioBtn_Split=\uBD84\uD560
@ -79,4 +79,15 @@ windowBodyFilesScanned=\uC2A4\uCE94 \uB41C \uD30C\uC77C: %d\n\uCD94\uAC00 \uB420
tab2_Lbl_AwooBlockTitle=Awoo \uC124\uCE58 \uD504\uB85C\uADF8\uB7A8\uACFC \uD638\uD658\uC131 tab2_Lbl_AwooBlockTitle=Awoo \uC124\uCE58 \uD504\uB85C\uADF8\uB7A8\uACFC \uD638\uD658\uC131
tabRcm_Lbl_Payload=\uD398\uC774\uB85C\uB4DC: tabRcm_Lbl_Payload=\uD398\uC774\uB85C\uB4DC:
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM 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.

View file

@ -43,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_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 tab2_Lbl_Language=Idioma
windowBodyRestartToApplyLang=Por favor, reinicie para aplicar as modifica\u00E7\u00F5es. 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 tab2_Lbl_ApplicationSettings=Configura\u00E7\u00F5es principais
tabSplMrg_Lbl_SplitNMergeTitle=Ferramenta de Fragmentar (Split) & Mesclar (Merge) arquivos tabSplMrg_Lbl_SplitNMergeTitle=Ferramenta de Fragmentar (Split) & Mesclar (Merge) arquivos
tabSplMrg_RadioBtn_Split=Fragmentar (Dividir) tabSplMrg_RadioBtn_Split=Fragmentar (Dividir)

View file

@ -45,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_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 tab2_Lbl_Language=Limb\u0103
windowBodyRestartToApplyLang=Te rog restarteaz\u0103 aplica\u021Bia pentru a aplica set\u0103rile noi. 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 tab2_Lbl_ApplicationSettings=Set\u0103ri principale
tabSplMrg_Lbl_SplitNMergeTitle=Unealt\u0103 pentru \u00EEmp\u0103r\u021Bire \u0219i lipire de fi\u0219iere tabSplMrg_Lbl_SplitNMergeTitle=Unealt\u0103 pentru \u00EEmp\u0103r\u021Bire \u0219i lipire de fi\u0219iere
tabSplMrg_RadioBtn_Split=\u00CEmparte tabSplMrg_RadioBtn_Split=\u00CEmparte

View file

@ -23,7 +23,7 @@ tab2_Lbl_HostIP=IP \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0430
tab1_Lbl_NSIP=NS IP: 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. 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 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_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_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 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
@ -44,7 +44,7 @@ tab2_Lbl_AllowXciNszXczDesc=\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u04
tab2_Lbl_Language=\u042F\u0437\u044B\u043A tab2_Lbl_Language=\u042F\u0437\u044B\u043A
windowBodyRestartToApplyLang=\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443. windowBodyRestartToApplyLang=\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u0447\u0442\u043E\u0431\u044B \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443.
tab2_Cb_GLshowNspOnly=\u041E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u044C \u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0444\u0430\u0439\u043B\u044B *.nsp \u0432 GoldLeaf. tab2_Cb_GLshowNspOnly=\u041E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u044C \u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0444\u0430\u0439\u043B\u044B *.nsp \u0432 GoldLeaf.
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 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_Lbl_SplitNMergeTitle=\u0423\u0442\u0438\u043B\u0438\u0442\u0430 \u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0438 \u0438 \u0441\u043B\u0438\u044F\u043D\u0438\u044F \u0444\u0430\u0439\u043B\u043E\u0432
tabSplMrg_Btn_Convert=\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C tabSplMrg_Btn_Convert=\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C
@ -77,5 +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 tab2_Lbl_AwooBlockTitle=Awoo Installer \u0438 \u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C\u044B\u0435
tabRcm_Lbl_Payload=Payload: tabRcm_Lbl_Payload=Payload:
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM 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:

View file

@ -45,7 +45,7 @@ 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_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 tab2_Lbl_Language=Spr\u00E5k
windowBodyRestartToApplyLang=Starta om programmet f\u00F6r att verkst\u00E4lla \u00E4ndringar. windowBodyRestartToApplyLang=Starta om programmet f\u00F6r att verkst\u00E4lla \u00E4ndringar.
btn_OpenSplitFile=V\u00E4lj delad NSP btn_OpenSplitFile=V\u00E4lj delad ROM
tab2_Lbl_ApplicationSettings=Huvudinst\u00E4llningar tab2_Lbl_ApplicationSettings=Huvudinst\u00E4llningar
tabSplMrg_Lbl_SplitNMergeTitle=Verktyg f\u00F6r att dela upp och sl\u00E5 ihop filer tabSplMrg_Lbl_SplitNMergeTitle=Verktyg f\u00F6r att dela upp och sl\u00E5 ihop filer
tabSplMrg_RadioBtn_Split=Dela upp tabSplMrg_RadioBtn_Split=Dela upp

View file

@ -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:

View file

@ -44,7 +44,7 @@ tab2_Lbl_AllowXciNszXczDesc=\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u04
tab2_Lbl_Language=\u041C\u043E\u0432\u0430 tab2_Lbl_Language=\u041C\u043E\u0432\u0430
windowBodyRestartToApplyLang=\u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0456\u0442\u044C \u0434\u043E\u0434\u0430\u0442\u043E\u043A \u0449\u043E\u0431 \u0437\u043C\u0456\u043D\u0438 \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443. windowBodyRestartToApplyLang=\u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0456\u0442\u044C \u0434\u043E\u0434\u0430\u0442\u043E\u043A \u0449\u043E\u0431 \u0437\u043C\u0456\u043D\u0438 \u0432\u0441\u0442\u0443\u043F\u0438\u043B\u0438 \u0432 \u0441\u0438\u043B\u0443.
tab2_Cb_GLshowNspOnly=\u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u0432\u0438\u043A\u043B\u044E\u0447\u043D\u043E *.nsp \u0444\u0430\u0439\u043B\u0438 \u0443 GoldLeaf. tab2_Cb_GLshowNspOnly=\u0412\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u0432\u0438\u043A\u043B\u044E\u0447\u043D\u043E *.nsp \u0444\u0430\u0439\u043B\u0438 \u0443 GoldLeaf.
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 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_Lbl_SplitNMergeTitle=\u041F\u043E\u043C\u0456\u0447\u043D\u0438\u043A \u0440\u043E\u0437\u0431\u0432\u043A\u0438 \u0442\u0430 \u043E\u0431'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0444\u0430\u0439\u043B\u0456\u0432
tabSplMrg_Btn_Convert=\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0443\u0432\u0430\u0442\u0438 tabSplMrg_Btn_Convert=\u041A\u043E\u043D\u0432\u0435\u0440\u0442\u0443\u0432\u0430\u0442\u0438
@ -77,4 +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 tab2_Lbl_AwooBlockTitle=Awoo Installer \u0442\u0430 \u0441\u0443\u043C\u0456\u0441\u043D\u0456
tabRcm_Lbl_Payload=Payload: tabRcm_Lbl_Payload=Payload:
tabRcm_Lbl_FuseeGelee=Fus\u00E9e Gel\u00E9e RCM 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:

Some files were not shown because too many files have changed in this diff Show more