mirror of
https://github.com/Maschell/JNUSTool.git
synced 2024-11-28 02:44:19 +01:00
Added download of encrypted content
- Decryption from files - Decryption to new folder structures - updates csv with version numbers - download and decrypt different versions (gui only)
This commit is contained in:
parent
9bbb016d97
commit
85f87c57bb
2
.gitignore
vendored
2
.gitignore
vendored
@ -52,3 +52,5 @@ bin
|
|||||||
UpdateGrabber.java
|
UpdateGrabber.java
|
||||||
updatetitles.csv
|
updatetitles.csv
|
||||||
src/de/mas/jnustool/StarterPRIATE.java
|
src/de/mas/jnustool/StarterPRIATE.java
|
||||||
|
jar/tmp*
|
||||||
|
src/de/mas/jnustool/XMLGEN.java
|
BIN
jar/JNUSTool.jar
BIN
jar/JNUSTool.jar
Binary file not shown.
@ -1,322 +1,327 @@
|
|||||||
0005000E-10100600;1;WUP;00AF;WUP-U-AKNJ;AKNJAF;TEKKEN TAG TOURNAMENT 2 Wii U EDITION
|
0005000E-10100600;1;WUP;00AF;WUP-U-AKNJ;AKNJAF;TEKKEN TAG TOURNAMENT 2 Wii U EDITION;16
|
||||||
0005000E-10101B00;4;WUP;0001;WUP-U-APLP;APLP01;LEGO® CITY UNDERCOVER
|
0005000E-10101B00;4;WUP;0001;WUP-U-APLP;APLP01;LEGO® CITY UNDERCOVER;16
|
||||||
0005000E-10101C00;1;WUP;0001;WUP-U-ARPJ;ARPJ01;New SUPER MARIO BROS. U
|
0005000E-10101C00;1;WUP;0001;WUP-U-ARPJ;ARPJ01;New SUPER MARIO BROS. U;32,48,65
|
||||||
0005000E-10101D00;2;WUP;0001;WUP-U-ARPE;ARPE01;New SUPER MARIO BROS. U
|
0005000E-10101D00;2;WUP;0001;WUP-U-ARPE;ARPE01;New SUPER MARIO BROS. U;32,48,64
|
||||||
0005000E-10101E00;4;WUP;0001;WUP-U-ARPP;ARPP01;New SUPER MARIO BROS. U
|
0005000E-10101E00;4;WUP;0001;WUP-U-ARPP;ARPP01;New SUPER MARIO BROS. U;32,48,64,80
|
||||||
0005000E-10101F00;1;WUP;0001;WUP-U-ALCJ;ALCJ01;Nintendo Land
|
0005000E-10101F00;1;WUP;0001;WUP-U-ALCJ;ALCJ01;Nintendo Land;32
|
||||||
0005000E-10102000;2;WUP;0001;WUP-U-ALCE;ALCE01;Nintendo Land
|
0005000E-10102000;2;WUP;0001;WUP-U-ALCE;ALCE01;Nintendo Land;32
|
||||||
0005000E-10102100;4;WUP;0001;WUP-U-ALCP;ALCP01;Nintendo Land
|
0005000E-10102100;4;WUP;0001;WUP-U-ALCP;ALCP01;Nintendo Land;32
|
||||||
0005000E-10102200;1;WUP;0001;WUP-U-ASTJ;ASTJ01;Wii Fit U
|
0005000E-10102200;1;WUP;0001;WUP-U-ASTJ;ASTJ01;Wii Fit U;32,48,64,81
|
||||||
0005000E-10102300;2;WUP;0001;WUP-U-ASTE;ASTE01;Wii Fit U
|
0005000E-10102300;2;WUP;0001;WUP-U-ASTE;ASTE01;Wii Fit U;16,48,64,81
|
||||||
0005000E-10102400;4;WUP;0001;WUP-U-ASTP;ASTP01;Wii Fit U
|
0005000E-10102400;4;WUP;0001;WUP-U-ASTP;ASTP01;Wii Fit U;16,48,64,81
|
||||||
0005000E-10104D00;1;WUP;0008;WUP-U-AHDJ;AHDJ08;MONSTER HUNTER 3(tri-)G HD Ver.
|
0005000E-10104D00;1;WUP;0008;WUP-U-AHDJ;AHDJ08;MONSTER HUNTER 3(tri-)G HD Ver.;16,32,48,65,80,96
|
||||||
0005000E-10106900;1;WUP;0001;WUP-U-AURJ;AURJ01;Mario & Sonic at the Sochi 2014 Olympic Winter Games
|
0005000E-10106900;1;WUP;0001;WUP-U-AURJ;AURJ01;Mario & Sonic at the Sochi 2014 Olympic Winter Games;16,32
|
||||||
0005000E-10106B00;2;WUP;0041;WUP-U-ASSE;ASSE41;Assassin's Creed® III
|
0005000E-10106B00;2;WUP;0041;WUP-U-ASSE;ASSE41;Assassin's Creed® III;16,32,48,64,80
|
||||||
0005000E-1010AE00;2;WUP;0041;WUP-U-AJDE;AJDE41;JUST DANCE 4
|
0005000E-1010AE00;2;WUP;0041;WUP-U-AJDE;AJDE41;JUST DANCE 4;16,32
|
||||||
0005000E-1010AF00;2;WUP;0041;WUP-U-AMVE;AMVE41;Marvel Avengers™: Battle for Earth
|
0005000E-1010AF00;2;WUP;0041;WUP-U-AMVE;AMVE41;Marvel Avengers™: Battle for Earth;16
|
||||||
0005000E-1010B000;2;WUP;0041;WUP-U-ARBE;ARBE41;Rabbids Land
|
0005000E-1010B000;2;WUP;0041;WUP-U-ARBE;ARBE41;Rabbids Land;16
|
||||||
0005000E-1010B300;2;WUP;008P;WUP-U-AS2E;AS2E8P;Sonic & All-Stars Racing Transformed
|
0005000E-1010B300;2;WUP;008P;WUP-U-AS2E;AS2E8P;Sonic & All-Stars Racing Transformed;16,32,48
|
||||||
0005000E-1010B400;2;WUP;0041;WUP-U-ASPE;ASPE41;ESPN Sports Connection
|
0005000E-1010B400;2;WUP;0041;WUP-U-ASPE;ASPE41;ESPN Sports Connection;16,33
|
||||||
0005000E-1010B600;2;WUP;0041;WUP-U-AYSE;AYSE41;Your Shape® Fitness Evolved 2013
|
0005000E-1010B600;2;WUP;0041;WUP-U-AYSE;AYSE41;Your Shape® Fitness Evolved 2013;16,32
|
||||||
0005000E-1010C700;2;WUP;0001;WUP-U-AURE;AURE01;Mario & Sonic at the Sochi 2014 Olympic Winter Games
|
0005000E-1010C700;2;WUP;0001;WUP-U-AURE;AURE01;Mario & Sonic at the Sochi 2014 Olympic Winter Games;16,32
|
||||||
0005000E-1010C800;4;WUP;0001;WUP-U-AURP;AURP01;Mario & Sonic at the Sochi 2014 Olympic Winter Games
|
0005000E-1010C800;4;WUP;0001;WUP-U-AURP;AURP01;Mario & Sonic at the Sochi 2014 Olympic Winter Games;16,32
|
||||||
0005000E-1010CF00;2;WUP;0052;WUP-U-AECE;AECE52;Call of Duty: Black Ops II
|
0005000E-1010CF00;2;WUP;0052;WUP-U-AECE;AECE52;Call of Duty: Black Ops II;16,32,48,64,80,96,112,128
|
||||||
0005000E-1010DA00;2;WUP;0054;WUP-U-ANBE;ANBE54;NBA 2K13
|
0005000E-1010DA00;2;WUP;0054;WUP-U-ANBE;ANBE54;NBA 2K13;16,32
|
||||||
0005000E-1010DC00;2;WUP;0069;WUP-U-AMEE;AMEE69;Mass Effect™ 3 Special Edition
|
0005000E-1010DC00;2;WUP;0069;WUP-U-AMEE;AMEE69;Mass Effect™ 3 Special Edition;16
|
||||||
0005000E-1010DD00;2;WUP;0041;WUP-U-AZUE;AZUE41;ZombiU
|
0005000E-1010DD00;2;WUP;0041;WUP-U-AZUE;AZUE41;ZombiU;16,32
|
||||||
0005000E-1010E300;2;WUP;0041;WUP-U-AS9E;AS9E41;Splinter Cell Blacklist
|
0005000E-1010E300;2;WUP;0041;WUP-U-AS9E;AS9E41;Splinter Cell Blacklist;16,32,48
|
||||||
0005000E-1010EA00;1;WUP;00C8;WUP-U-AHBJ;AHBJC8;WARRIORS OROCHI 3 Hyper
|
0005000E-1010EA00;1;WUP;00C8;WUP-U-AHBJ;AHBJC8;WARRIORS OROCHI 3 Hyper;16,32,48,64
|
||||||
0005000E-1010EB00;1;WUP;0001;WUP-P-AMKJ;AMKJ01;MARIO KART 8
|
0005000E-1010EB00;1;WUP;0001;WUP-P-AMKJ;AMKJ01;MARIO KART 8;17,33,48,64
|
||||||
0005000E-1010EC00;2;WUP;0001;WUP-P-AMKE;AMKE01;MARIO KART 8
|
0005000E-1010EC00;2;WUP;0001;WUP-P-AMKE;AMKE01;MARIO KART 8;16,32,48,64
|
||||||
0005000E-1010ED00;4;WUP;0001;WUP-P-AMKP;AMKP01;MARIO KART 8
|
0005000E-1010ED00;4;WUP;0001;WUP-P-AMKP;AMKP01;MARIO KART 8;16,32,48,64
|
||||||
0005000E-1010EE00;4;WUP;0069;WUP-U-AF3P;AF3P69;FIFA 13
|
0005000E-1010EE00;4;WUP;0069;WUP-U-AF3P;AF3P69;FIFA 13 ;16
|
||||||
0005000E-1010EF00;4;WUP;0041;WUP-U-AZUP;AZUP41;ZombiU
|
0005000E-1010EF00;4;WUP;0041;WUP-U-AZUP;AZUP41;ZombiU;16,32
|
||||||
0005000E-1010F000;4;WUP;0041;WUP-U-AJDP;AJDP41;JUST DANCE 4
|
0005000E-1010F000;4;WUP;0041;WUP-U-AJDP;AJDP41;JUST DANCE 4;16,32
|
||||||
0005000E-1010F500;4;WUP;0069;WUP-U-AMEP;AMEP69;Mass Effect™ 3 Special Edition
|
0005000E-1010F500;4;WUP;0069;WUP-U-AMEP;AMEP69;Mass Effect™ 3 Special Edition;16
|
||||||
0005000E-1010F600;4;WUP;0041;WUP-U-ASSP;ASSP41;Assassin's Creed® III
|
0005000E-1010F600;4;WUP;0041;WUP-U-ASSP;ASSP41;Assassin's Creed® III;16,48,64,80
|
||||||
0005000E-1010F700;4;WUP;0041;WUP-U-AYSP;AYSP41;Your Shape® Fitness Evolved 2013
|
0005000E-1010F700;4;WUP;0041;WUP-U-AYSP;AYSP41;Your Shape® Fitness Evolved 2013;16,33
|
||||||
0005000E-1010F800;4;WUP;00AF;WUP-U-AKNP;AKNPAF;TEKKEN TAG TOURNAMENT 2 Wii U EDITION
|
0005000E-1010F800;4;WUP;00AF;WUP-U-AKNP;AKNPAF;TEKKEN TAG TOURNAMENT 2 Wii U EDITION;32
|
||||||
0005000E-1010FB00;4;WUP;00NK;WUP-U-WDLP;WDLPNK;Puddle
|
0005000E-1010FB00;4;WUP;00NK;WUP-U-WDLP;WDLPNK;Puddle;16
|
||||||
0005000E-1010FC00;4;WUP;0041;WUP-U-ARBP;ARBP41;Rabbids Land
|
0005000E-1010FC00;4;WUP;0041;WUP-U-ARBP;ARBP41;Rabbids Land;16
|
||||||
0005000E-1010FF00;4;WUP;00WR;WUP-U-AGPP;AGPPWR;Game Party Champions
|
0005000E-1010FF00;4;WUP;00WR;WUP-U-AGPP;AGPPWR;Game Party Champions;16
|
||||||
0005000E-10110000;2;WUP;00AF;WUP-U-AKNE;AKNEAF;TEKKEN TAG TOURNAMENT 2 Wii U EDITION
|
0005000E-10110000;2;WUP;00AF;WUP-U-AKNE;AKNEAF;TEKKEN TAG TOURNAMENT 2 Wii U EDITION;32
|
||||||
0005000E-10110100;2;WUP;00JX;WUP-U-WASE;WASEJX;Nano Assault Neo
|
0005000E-10110100;2;WUP;00JX;WUP-U-WASE;WASEJX;Nano Assault Neo;17
|
||||||
0005000E-10110200;2;WUP;00C8;WUP-U-AHBE;AHBEC8;WARRIORS OROCHI 3 Hyper(NA)
|
0005000E-10110200;2;WUP;00C8;WUP-U-AHBE;AHBEC8;WARRIORS OROCHI 3 Hyper(NA);16,32
|
||||||
0005000E-10110600;4;WUP;00JX;WUP-U-WASP;WASPJX;Nano Assault Neo
|
0005000E-10110600;4;WUP;00JX;WUP-U-WASP;WASPJX;Nano Assault Neo;17
|
||||||
0005000E-10110800;4;WUP;0041;WUP-U-AMVP;AMVP41;Marvel Avengers™: Battle for Earth
|
0005000E-10110800;4;WUP;0041;WUP-U-AMVP;AMVP41;Marvel Avengers™: Battle for Earth;16
|
||||||
0005000E-10110900;1;WUP;00C8;WUP-U-ANGJ;ANGJC8;NINJA GAIDEN 3: Razor's Edge
|
0005000E-10110900;1;WUP;00C8;WUP-U-ANGJ;ANGJC8;NINJA GAIDEN 3: Razor's Edge;16,32,48,64
|
||||||
0005000E-10110A00;2;WUP;0001;WUP-U-ANGE;ANGE01;NINJA GAIDEN 3: Razor's Edge
|
0005000E-10110A00;2;WUP;0001;WUP-U-ANGE;ANGE01;NINJA GAIDEN 3: Razor's Edge;16,32,48,64,80
|
||||||
0005000E-10110B00;4;WUP;0001;WUP-U-ANGP;ANGP01;NINJA GAIDEN 3: Razor's Edge
|
0005000E-10110B00;4;WUP;0001;WUP-U-ANGP;ANGP01;NINJA GAIDEN 3: Razor's Edge;17,32,48
|
||||||
0005000E-10110E00;1;WUP;0001;WUP-P-AXFJ;AXFJ01;Super Smash Bros. for Wii U
|
0005000E-10110E00;1;WUP;0001;WUP-P-AXFJ;AXFJ01;Super Smash Bros. for Wii U;16,49,64,80,96,112,128,144,160,176,192,208
|
||||||
0005000E-10111700;2;WUP;00WR;WUP-U-AJSE;AJSEWR;Injustice: Gods Among Us
|
0005000E-10111700;2;WUP;00WR;WUP-U-AJSE;AJSEWR;Injustice: Gods Among Us;16
|
||||||
0005000E-10111A00;4;WUP;00WR;WUP-U-AJSP;AJSPWR;Injustice: Gods Among Us
|
0005000E-10111A00;4;WUP;00WR;WUP-U-AJSP;AJSPWR;Injustice: Gods Among Us;16
|
||||||
0005000E-10111C00;1;WUP;00C8;WUP-U-AG9J;AG9JC8;Romance of the Three Kingdoms 12
|
0005000E-10111C00;1;WUP;00C8;WUP-U-AG9J;AG9JC8;Romance of the Three Kingdoms 12;16,33
|
||||||
0005000E-10111D00;4;WUP;0041;WUP-U-ASPP;ASPP41;Sports Connection
|
0005000E-10111D00;4;WUP;0041;WUP-U-ASPP;ASPP41;Sports Connection;16
|
||||||
0005000E-10111F00;4;WUP;008P;WUP-U-AS2P;AS2P8P;Sonic & All-Stars Racing Transformed
|
0005000E-10111F00;4;WUP;008P;WUP-U-AS2P;AS2P8P;Sonic & All-Stars Racing Transformed;32,48
|
||||||
0005000E-10112000;2;WUP;00G9;WUP-U-ACRE;ACREG9;THE CROODS
|
0005000E-10112000;2;WUP;00G9;WUP-U-ACRE;ACREG9;THE CROODS;16
|
||||||
0005000E-10112100;4;WUP;0041;WUP-U-AKFP;AKFP41;Know Your Friends
|
0005000E-10112100;4;WUP;0041;WUP-U-AKFP;AKFP41;Know Your Friends;16
|
||||||
0005000E-10112200;4;WUP;00FZ;WUP-U-WBDP;WBDPFZ;Trine 2 Director's Cut
|
0005000E-10112200;4;WUP;00FZ;WUP-U-WBDP;WBDPFZ;Trine 2 Director's Cut;16
|
||||||
0005000E-10112300;1;WUP;0041;WUP-U-AZUJ;AZUJ41;ZombiU
|
0005000E-10112300;1;WUP;0041;WUP-U-AZUJ;AZUJ41;ZombiU;16,32
|
||||||
0005000E-10112400;1;WUP;0041;WUP-U-ASSJ;ASSJ41;Assassin's Creed® III
|
0005000E-10112400;1;WUP;0041;WUP-U-ASSJ;ASSJ41;Assassin's Creed® III;16,32,48,64,80
|
||||||
0005000E-10112500;1;WUP;0041;WUP-U-ASPJ;ASPJ41;Sports Connection
|
0005000E-10112500;1;WUP;0041;WUP-U-ASPJ;ASPJ41;Sports Connection;17
|
||||||
0005000E-10112800;1;WUP;0041;WUP-U-AS9J;AS9J41;Splinter Cell Blacklist
|
0005000E-10112800;1;WUP;0041;WUP-U-AS9J;AS9J41;Splinter Cell Blacklist;17,32,48
|
||||||
0005000E-10112B00;4;WUP;00C8;WUP-U-AHBP;AHBPC8;WARRIORS OROCHI 3 Hyper(EU)
|
0005000E-10112B00;4;WUP;00C8;WUP-U-AHBP;AHBPC8;WARRIORS OROCHI 3 Hyper(EU);16,32
|
||||||
0005000E-10112F00;4;WUP;0054;WUP-U-ANBP;ANBP54;NBA 2K13
|
0005000E-10112F00;4;WUP;0054;WUP-U-ANBP;ANBP54;NBA 2K13;32
|
||||||
0005000E-10113000;1;WUP;0013;WUP-U-AMEJ;AMEJ13;Mass Effect™ 3 Special Edition
|
0005000E-10113000;1;WUP;0013;WUP-U-AMEJ;AMEJ13;Mass Effect™ 3 Special Edition;16
|
||||||
0005000E-10113100;1;WUP;0008;WUP-U-ABHJ;ABHJ08;BIOHAZARD REVELATIONS Unveiled Edition
|
0005000E-10113100;1;WUP;0008;WUP-U-ABHJ;ABHJ08;BIOHAZARD REVELATIONS Unveiled Edition;16
|
||||||
0005000E-10113400;4;WUP;0052;WUP-U-AECP;AECP52;Call of Duty: Black Ops II
|
0005000E-10113400;4;WUP;0052;WUP-U-AECP;AECP52;Call of Duty: Black Ops II;16,32,48,64,80,96,112,128
|
||||||
0005000E-10113500;4;WUP;0052;WUP-U-AECI;AECI52;Call of Duty: Black Ops II
|
0005000E-10113500;4;WUP;0052;WUP-U-AECI;AECI52;Call of Duty: Black Ops II;16,32,48,64,80,96,112,144
|
||||||
0005000E-10113700;4;WUP;0052;WUP-U-AECD;AECD52;Call of Duty: Black Ops II
|
0005000E-10113700;4;WUP;0052;WUP-U-AECD;AECD52;Call of Duty: Black Ops II;16,32,48,64,80,96,112,144
|
||||||
0005000E-10113800;4;WUP;00Y4;WUP-U-WBAP;WBAPY4;Zen Pinball 2
|
0005000E-10113800;4;WUP;00Y4;WUP-U-WBAP;WBAPY4;Zen Pinball 2;17,32,48,65,80,96
|
||||||
0005000E-10113C00;2;WUP;00GT;WUP-U-AFBE;AFBEGT;Funky Barn
|
0005000E-10113C00;2;WUP;00GT;WUP-U-AFBE;AFBEGT;Funky Barn;16
|
||||||
0005000E-10115E00;1;WUP;00GD;WUP-U-ADQJ;ADQJGD;Dragon Quest X
|
0005000E-10115E00;1;WUP;00GD;WUP-U-ADQJ;ADQJGD;Dragon Quest X;16,80,128,144,160,192,208,224,240,256,272,288,304,336,368,384,400,416,432,448,464,480,496,512,528,544,560,624,640,656,672,688,704,736,752,784,800,816,832,848,960,976,992,1008,1024,1040,1056,1072,1088,1104,1120,1136,1152,1168,1184,1200,1216,1232,1248,1264,1280,1296,1312,1328,1344,1360,1376,1392,1408,1424,1440,1456,1472,1488,1504,1520,1536,1552,1568,1584,1600,1616,1632,1648,1664,1680,1696,1712,1728,1744,1760,1776,1792,1808,1824,1840,1856,1872,1888,1904,1920,1936,1952,1968,1984,2000,2016,2032,2048,2064,2080,2096,2112,2128,2144,2160,2176,2192,2208,2224,2240,2256,2272,2288,2304,2320
|
||||||
0005000E-10115F00;2;WUP;00Y4;WUP-U-WBAE;WBAEY4;Zen Pinball 2
|
0005000E-10115F00;2;WUP;00Y4;WUP-U-WBAE;WBAEY4;Zen Pinball 2;16,32,48,65,80,96
|
||||||
0005000E-10116100;1;WUP;0001;WUP-P-AX5J;AX5J01;XenobladeX
|
0005000E-10116100;1;WUP;0001;WUP-P-AX5J;AX5J01;XenobladeX;16,32,48
|
||||||
0005000E-10116300;1;WUP;0001;WUP-U-ACMJ;ACMJ01;The Wonderful 101
|
0005000E-10116300;1;WUP;0001;WUP-U-ACMJ;ACMJ01;The Wonderful 101;16
|
||||||
0005000E-10116500;4;WUP;00TW;WUP-U-WAAP;WAAPTW;Toki Tori 2+
|
0005000E-10116500;4;WUP;00TW;WUP-U-WAAP;WAAPTW;Toki Tori 2+;16,32
|
||||||
0005000E-10116600;1;WUP;00C8;WUP-U-AH9J;AH9JC8;Fist of the North Star: Ken's Rage 2
|
0005000E-10116600;1;WUP;00C8;WUP-U-AH9J;AH9JC8;Fist of the North Star: Ken's Rage 2;17
|
||||||
0005000E-10117200;4;WUP;0008;WUP-U-AHDP;AHDP08;MONSTER HUNTER 3 ULTIMATE
|
0005000E-10117200;4;WUP;0008;WUP-U-AHDP;AHDP08;MONSTER HUNTER 3 ULTIMATE;16,32
|
||||||
0005000E-10117700;4;WUP;00TJ;WUP-U-WCAP;WCAPTJ;Chasing Aurora
|
0005000E-10117700;4;WUP;00TJ;WUP-U-WCAP;WCAPTJ;Chasing Aurora;17
|
||||||
0005000E-10118300;2;WUP;0008;WUP-U-AHDE;AHDE08;MONSTER HUNTER 3 ULTIMATE
|
0005000E-10118300;2;WUP;0008;WUP-U-AHDE;AHDE08;MONSTER HUNTER 3 ULTIMATE;16,32
|
||||||
0005000E-10118400;4;WUP;00GT;WUP-U-AFBP;AFBPGT;Funky Barn
|
0005000E-10118400;4;WUP;00GT;WUP-U-AFBP;AFBPGT;Funky Barn;16
|
||||||
0005000E-1011A700;4;WUP;0041;WUP-U-AZUD;AZUD41;ZombiU
|
0005000E-1011A700;4;WUP;0041;WUP-U-AZUD;AZUD41;ZombiU;16,32
|
||||||
0005000E-1011AF00;2;WUP;00XY;WUP-U-WBTE;WBTEXY;BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien
|
0005000E-1011AF00;2;WUP;00XY;WUP-U-WBTE;WBTEXY;BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien;16,33
|
||||||
0005000E-1011B300;4;WUP;00TZ;WUP-U-AFBZ;AFBZTZ;Funky Barn (Download Version)
|
0005000E-1011B300;4;WUP;00TZ;WUP-U-AFBZ;AFBZTZ;Funky Barn (Download Version);16
|
||||||
0005000E-1011B400;1;WUP;00GD;WUP-U-AECJ;AECJGD;Call of Duty: Black Ops II
|
0005000E-1011B400;1;WUP;00GD;WUP-U-AECJ;AECJGD;Call of Duty: Black Ops II;16,32,48,64,80,96
|
||||||
0005000E-1011B600;1;WUP;00GD;WUP-U-AQDJ;AQDJGD;Dragon Quest X Beta test
|
0005000E-1011B600;1;WUP;00GD;WUP-U-AQDJ;AQDJGD;Dragon Quest X Beta test;16,32,48,64,96
|
||||||
0005000E-1011B700;4;WUP;0041;WUP-U-WLAP;WLAP41;Uplay
|
0005000E-1011B700;4;WUP;0041;WUP-U-WLAP;WLAP41;Uplay;16,32,33,48,64
|
||||||
0005000E-1011BA00;2;WUP;0041;WUP-U-WLAE;WLAE41;Uplay
|
0005000E-1011BA00;2;WUP;0041;WUP-U-WLAE;WLAE41;Uplay;16,33,48,64
|
||||||
0005000E-1011C000;2;WUP;00TJ;WUP-U-WCAE;WCAETJ;Chasing Aurora
|
0005000E-1011C000;2;WUP;00TJ;WUP-U-WCAE;WCAETJ;Chasing Aurora;16
|
||||||
0005000E-10128400;4;WUP;0069;WUP-U-ANSP;ANSP69;Need for Speed™ Most Wanted U
|
0005000E-10128400;4;WUP;0069;WUP-U-ANSP;ANSP69;Need for Speed™ Most Wanted U;16,32
|
||||||
0005000E-10128700;2;WUP;00TW;WUP-U-WAAE;WAAETW;Toki Tori 2+
|
0005000E-10128700;2;WUP;00TW;WUP-U-WAAE;WAAETW;Toki Tori 2+;16,32
|
||||||
0005000E-10128800;2;WUP;0069;WUP-U-ANSE;ANSE69;Need for Speed™ Most Wanted U
|
0005000E-10128800;2;WUP;0069;WUP-U-ANSE;ANSE69;Need for Speed™ Most Wanted U;16,32
|
||||||
0005000E-10128A00;2;WUP;00FZ;WUP-U-WBDE;WBDEFZ;Trine 2 Director's Cut
|
0005000E-10128A00;2;WUP;00FZ;WUP-U-WBDE;WBDEFZ;Trine 2 Director's Cut;16
|
||||||
0005000E-10128F00;2;WUP;008P;WUP-U-ASNE;ASNE8P;SONIC LOST WORLD
|
0005000E-10128F00;2;WUP;008P;WUP-U-ASNE;ASNE8P;SONIC LOST WORLD;16,32,48
|
||||||
0005000E-10129000;2;WUP;0008;WUP-U-WDKE;WDKE08;DuckTales: Remastered
|
0005000E-10129000;2;WUP;0008;WUP-U-WDKE;WDKE08;DuckTales: Remastered;16,32
|
||||||
0005000E-10129200;4;WUP;0008;WUP-U-WDKP;WDKP08;DuckTales: Remastered
|
0005000E-10129200;4;WUP;0008;WUP-U-WDKP;WDKP08;DuckTales: Remastered;16,32
|
||||||
0005000E-1012AC00;4;WUP;0041;WUP-U-AS9P;AS9P41;Splinter Cell Blacklist
|
0005000E-1012AC00;4;WUP;0041;WUP-U-AS9P;AS9P41;Splinter Cell Blacklist;16,32,48
|
||||||
0005000E-1012B100;4;WUP;008P;WUP-U-ASNP;ASNP8P;SONIC LOST WORLD
|
0005000E-1012B100;4;WUP;008P;WUP-U-ASNP;ASNP8P;SONIC LOST WORLD;16,32,48
|
||||||
0005000E-1012B400;4;WUP;0008;WUP-U-ABHP;ABHP08;RESIDENT EVIL REVELATIONS
|
0005000E-1012B400;4;WUP;0008;WUP-U-ABHP;ABHP08;RESIDENT EVIL REVELATIONS;16
|
||||||
0005000E-1012B700;1;WUP;0013;WUP-U-ANSJ;ANSJ13;Need for Speed™ Most Wanted U
|
0005000E-1012B700;1;WUP;0013;WUP-U-ANSJ;ANSJ13;Need for Speed™ Most Wanted U;16,32
|
||||||
0005000E-1012BC00;1;WUP;0001;WUP-U-AC3J;AC3J01;PIKMIN 3
|
0005000E-1012BC00;1;WUP;0001;WUP-U-AC3J;AC3J01;PIKMIN 3;17,48,64,80,96
|
||||||
0005000E-1012BD00;2;WUP;0001;WUP-U-AC3E;AC3E01;PIKMIN 3
|
0005000E-1012BD00;2;WUP;0001;WUP-U-AC3E;AC3E01;PIKMIN 3;33,48,64,80,96
|
||||||
0005000E-1012BE00;4;WUP;0001;WUP-U-AC3P;AC3P01;PIKMIN 3
|
0005000E-1012BE00;4;WUP;0001;WUP-U-AC3P;AC3P01;PIKMIN 3;17,48,64,80,96
|
||||||
0005000E-1012C500;4;WUP;00AF;WUP-U-ACRP;ACRPAF;THE CROODS
|
0005000E-1012C500;4;WUP;00AF;WUP-U-ACRP;ACRPAF;THE CROODS;16
|
||||||
0005000E-1012CF00;2;WUP;0008;WUP-U-ABHE;ABHE08;RESIDENT EVIL REVELATIONS
|
0005000E-1012CF00;2;WUP;0008;WUP-U-ABHE;ABHE08;RESIDENT EVIL REVELATIONS;16
|
||||||
0005000E-1012DC00;2;WUP;0001;WUP-U-ACME;ACME01;The Wonderful 101
|
0005000E-1012DC00;2;WUP;0001;WUP-U-ACME;ACME01;The Wonderful 101;16
|
||||||
0005000E-1012F100;1;WUP;0001;WUP-U-AWSJ;AWSJ01;Wii Sports Club
|
0005000E-1012F100;1;WUP;0001;WUP-U-AWSJ;AWSJ01;Wii Sports Club;16,32,48,64,80,96,112
|
||||||
0005000E-10131D00;1;WUP;0001;WUP-U-ASEJ;ASEJ01;????????
|
0005000E-10131D00;1;WUP;0001;WUP-P-ASEJ;ASEJ01;????????;17,32
|
||||||
0005000E-10131F00;1;WUP;0001;WUP-U-AYCJ;AYCJ01;yoshi's woolly world
|
0005000E-10131F00;1;WUP;0001;WUP-U-AYCJ;AYCJ01;yoshi's woolly world;32
|
||||||
0005000E-10132400;4;WUP;00WR;WUP-U-ALMP;ALMPWR;LEGO® MARVEL Super Heroes
|
0005000E-10132400;4;WUP;00WR;WUP-U-ALMP;ALMPWR;LEGO® MARVEL Super Heroes;16,32,48
|
||||||
0005000E-10132500;1;WUP;0001;WUP-U-WB9J;WB9J01;Wii Fit U Quick Check
|
0005000E-10132500;1;WUP;0001;WUP-U-WB9J;WB9J01;Wii Fit U Quick Check;16,64,81
|
||||||
0005000E-10132600;2;WUP;0001;WUP-U-WB9E;WB9E01;Wii Fit U Quick Check
|
0005000E-10132600;2;WUP;0001;WUP-U-WB9E;WB9E01;Wii Fit U Quick Check;16,64,81
|
||||||
0005000E-10132700;4;WUP;0001;WUP-U-WB9P;WB9P01;Wii Fit U Quick Check
|
0005000E-10132700;4;WUP;0001;WUP-U-WB9P;WB9P01;Wii Fit U Quick Check;16,64,81
|
||||||
0005000E-10132800;2;WUP;00UP;WUP-U-WEPE;WEPEUP;Unepic EnjoyUp Games
|
0005000E-10132800;2;WUP;00UP;WUP-U-WEPE;WEPEUP;Unepic EnjoyUp Games;16,32
|
||||||
0005000E-10132900;2;WUP;004Q;WUP-U-ADSE;ADSE4Q;Disney INFINITY
|
0005000E-10132900;2;WUP;004Q;WUP-U-ADSE;ADSE4Q;Disney INFINITY;16,32,49
|
||||||
0005000E-10132A00;4;WUP;00Y4;WUP-U-WA2P;WA2PY4;Star Wars Pinball
|
0005000E-10132A00;4;WUP;00Y4;WUP-U-WA2P;WA2PY4;Star Wars Pinball;17,32,48
|
||||||
0005000E-10132B00;2;WUP;00WR;WUP-P-ALME;ALMEWR;LEGO® MARVEL Super Heroes
|
0005000E-10132B00;2;WUP;00WR;WUP-P-ALME;ALMEWR;LEGO® MARVEL Super Heroes;16,32
|
||||||
0005000E-10135200;2;WUP;00Y4;WUP-U-WA2E;WA2EY4;Star Wars Pinball
|
0005000E-10135200;2;WUP;00Y4;WUP-U-WA2E;WA2EY4;Star Wars Pinball;16,33,48
|
||||||
0005000E-10135300;4;WUP;0001;WUP-U-ACMP;ACMP01;The Wonderful 101
|
0005000E-10135300;4;WUP;0001;WUP-U-ACMP;ACMP01;The Wonderful 101;16
|
||||||
0005000E-10135700;1;WUP;008P;WUP-U-ASNJ;ASNJ8P;SONIC LOST WORLD
|
0005000E-10135700;1;WUP;008P;WUP-U-ASNJ;ASNJ8P;SONIC LOST WORLD;16,32,48
|
||||||
0005000E-10136300;4;WUP;00XY;WUP-U-WBTP;WBTPXY;BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien
|
0005000E-10136300;4;WUP;00XY;WUP-U-WBTP;WBTPXY;BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien;17
|
||||||
0005000E-10136C00;4;WUP;00WR;WUP-U-AZEP;AZEPWR;Batman™: Arkham Origins
|
0005000E-10136C00;4;WUP;00WR;WUP-U-AZEP;AZEPWR;Batman™: Arkham Origins;16
|
||||||
0005000E-10136F00;4;WUP;004Q;WUP-U-ADSP;ADSP4Q;Disney Infinity
|
0005000E-10136F00;4;WUP;004Q;WUP-U-ADSP;ADSP4Q;Disney Infinity;16,32,49
|
||||||
0005000E-10137000;4;WUP;004Q;WUP-U-ADSZ;ADSZ4Q;Disney Infinity
|
0005000E-10137000;4;WUP;004Q;WUP-U-ADSZ;ADSZ4Q;Disney Infinity;16,32,49
|
||||||
0005000E-10137C00;2;WUP;00WR;WUP-U-AZEE;AZEEWR;Batman™: Arkham Origins
|
0005000E-10137C00;2;WUP;00WR;WUP-U-AZEE;AZEEWR;Batman™: Arkham Origins;16
|
||||||
0005000E-10137F00;2;WUP;0001;WUP-P-ARKE;ARKE01;Donkey Kong Country Tropical Freeze
|
0005000E-10137F00;2;WUP;0001;WUP-P-ARKE;ARKE01;Donkey Kong Country Tropical Freeze;16
|
||||||
0005000E-10138300;4;WUP;0001;WUP-P-ARKP;ARKP01;Donkey Kong Country Tropical Freeze
|
0005000E-10138300;4;WUP;0001;WUP-P-ARKP;ARKP01;Donkey Kong Country Tropical Freeze;17
|
||||||
0005000E-10138700;4;WUP;00YV;WUP-P-WB6P;WB6PYV;Spin the Bottle: Bumpie's Party
|
0005000E-10138700;4;WUP;00YV;WUP-P-WB6P;WB6PYV;Spin the Bottle: Bumpie's Party;16,33
|
||||||
0005000E-10138800;4;WUP;0041;WUP-U-ASBP;ASBP41;Assassin's Creed® IV Black Flag
|
0005000E-10138800;4;WUP;0041;WUP-U-ASBP;ASBP41;Assassin's Creed® IV Black Flag;16,32
|
||||||
0005000E-10138B00;2;WUP;0041;WUP-U-ASBE;ASBE41;Assassin's Creed® IV Black Flag
|
0005000E-10138B00;2;WUP;0041;WUP-U-ASBE;ASBE41;Assassin's Creed® IV Black Flag;16,32
|
||||||
0005000E-10138E00;4;WUP;0041;WUP-U-WB7P;WB7P41;Rayman Legends Challenges App
|
0005000E-10138E00;4;WUP;0041;WUP-U-WB7P;WB7P41;Rayman Legends Challenges App;16
|
||||||
0005000E-10138F00;1;WUP;0001;WUP-U-ADNJ;ADNJ01;Devil's Third
|
0005000E-10138F00;1;WUP;0001;WUP-U-ADNJ;ADNJ01;Devil's Third;16
|
||||||
0005000E-10139200;2;WUP;0052;WUP-U-ASFE;ASFE52;Skylanders SWAP Force
|
0005000E-10139200;2;WUP;0052;WUP-U-ASFE;ASFE52;Skylanders SWAP Force;16
|
||||||
0005000E-10139500;2;WUP;0041;WUP-U-WB7E;WB7E41;Rayman Legends Challenges App
|
0005000E-10139500;2;WUP;0041;WUP-U-WB7E;WB7E41;Rayman Legends Challenges App;16
|
||||||
0005000E-10139900;2;WUP;0041;WUP-P-AJ5E;AJ5E41;JUST DANCE® 2014
|
0005000E-10139900;2;WUP;0041;WUP-P-AJ5E;AJ5E41;JUST DANCE® 2014;16
|
||||||
0005000E-10140400;4;WUP;0052;WUP-U-ASFP;ASFP52;Skylanders SWAP Force
|
0005000E-10140400;4;WUP;0052;WUP-U-ASFP;ASFP52;Skylanders SWAP Force;16
|
||||||
0005000E-10140700;1;WUP;00WR;WUP-U-AJSJ;AJSJWR;Injustice: Gods Among Us
|
0005000E-10140700;1;WUP;00WR;WUP-U-AJSJ;AJSJWR;Injustice: Gods Among Us;16
|
||||||
0005000E-10142700;4;WUP;0001;WUP-P-AA9P;AA9P01;Art Academy: SketchPad
|
0005000E-10142700;4;WUP;0001;WUP-P-AA9P;AA9P01;Art Academy: SketchPad;16
|
||||||
0005000E-10142A00;2;WUP;005G;WUP-U-AZBE;AZBE5G;Zumba Fitness World Party
|
0005000E-10142A00;2;WUP;005G;WUP-U-AZBE;AZBE5G;Zumba Fitness World Party;16
|
||||||
0005000E-10142B00;1;WUP;0001;WUP-P-AA9J;AA9J01;Art Academy: SketchPad
|
0005000E-10142B00;1;WUP;0001;WUP-P-AA9J;AA9J01;Art Academy: SketchPad;16
|
||||||
0005000E-10142C00;2;WUP;0001;WUP-P-AA9E;AA9E01;Art Academy: SketchPad
|
0005000E-10142C00;2;WUP;0001;WUP-P-AA9E;AA9E01;Art Academy: SketchPad;16
|
||||||
0005000E-10143F00;4;WUP;0041;WUP-P-AJ5P;AJ5P41;JUST DANCE® 2014
|
0005000E-10143F00;4;WUP;0041;WUP-P-AJ5P;AJ5P41;JUST DANCE® 2014;16
|
||||||
0005000E-10144000;2;WUP;00G9;WUP-U-ADVE;ADVEG9;Adventure Time: Explore the Dungeon Because I Don't Know!
|
0005000E-10144000;2;WUP;00G9;WUP-U-ADVE;ADVEG9;Adventure Time: Explore the Dungeon Because I Don't Know!;16
|
||||||
0005000E-10144800;1;WUP;0001;WUP-P-ARKJ;ARKJ01;Donkey Kong Country Tropical Freeze
|
0005000E-10144800;1;WUP;0001;WUP-P-ARKJ;ARKJ01;Donkey Kong Country Tropical Freeze;17
|
||||||
0005000E-10144D00;2;WUP;0001;WUP-U-AWSE;AWSE01;Wii Sports Club
|
0005000E-10144D00;2;WUP;0001;WUP-U-AWSE;AWSE01;Wii Sports Club;16,33,48,64,80,96,112
|
||||||
0005000E-10144E00;4;WUP;0001;WUP-U-AWSP;AWSP01;Wii Sports Club
|
0005000E-10144E00;4;WUP;0001;WUP-U-AWSP;AWSP01;Wii Sports Club;16,33,48,64,80,96,112
|
||||||
0005000E-10144F00;2;WUP;0001;WUP-P-AXFE;AXFE01;Super Smash Bros. for Wii U
|
0005000E-10144F00;2;WUP;0001;WUP-P-AXFE;AXFE01;Super Smash Bros. for Wii U;32,48,64,80,96,112,128,144,160,176,192,208
|
||||||
0005000E-10145000;4;WUP;0001;WUP-P-AXFP;AXFP01;Super Smash Bros. for Wii U
|
0005000E-10145000;4;WUP;0001;WUP-P-AXFP;AXFP01;Super Smash Bros. for Wii U;32,48,64,80,96,112,128,144,160,176,192,208
|
||||||
0005000E-10145600;7;WUP;0001;WUP-U-ADBA;ADBA01;Animal Crossing Plaza
|
0005000E-10145600;7;WUP;0001;WUP-U-ADBA;ADBA01;Animal Crossing Plaza;16
|
||||||
0005000E-10145800;4;WUP;00UP;WUP-U-WEPP;WEPPUP;Unepic EnjoyUp Games
|
0005000E-10145800;4;WUP;00UP;WUP-U-WEPP;WEPPUP;Unepic EnjoyUp Games;16,32
|
||||||
0005000E-10145900;4;WUP;00HL;WUP-U-WCDP;WCDPHL;Coaster Crazy Deluxe
|
0005000E-10145900;4;WUP;00HL;WUP-U-WCDP;WCDPHL;Coaster Crazy Deluxe;16
|
||||||
0005000E-10145F00;1;WUP;0001;WUP-P-WMGJ;WMGJ01;NES REMIX
|
0005000E-10145F00;1;WUP;0001;WUP-P-WMGJ;WMGJ01;NES REMIX;16
|
||||||
0005000E-10146000;2;WUP;0001;WUP-P-WMGE;WMGE01;NES REMIX
|
0005000E-10146000;2;WUP;0001;WUP-P-WMGE;WMGE01;NES REMIX;16
|
||||||
0005000E-10146100;4;WUP;0001;WUP-P-WMGP;WMGP01;NES REMIX
|
0005000E-10146100;4;WUP;0001;WUP-P-WMGP;WMGP01;NES REMIX;16
|
||||||
0005000E-10146800;2;WUP;0052;WUP-P-ACPE;ACPE52;Call of Duty: Ghosts
|
0005000E-10146800;2;WUP;0052;WUP-P-ACPE;ACPE52;Call of Duty: Ghosts;16,32,48,64,80,96,112
|
||||||
0005000E-10147600;4;WUP;00DZ;WUP-P-WEVP;WEVPDZ;EvoFish
|
0005000E-10147600;4;WUP;00DZ;WUP-P-WEVP;WEVPDZ;EvoFish;17
|
||||||
0005000E-10147F00;2;WUP;00YV;WUP-P-WB6E;WB6EYV;Spin the Bottle: Bumpie's Party
|
0005000E-10147F00;2;WUP;00YV;WUP-P-WB6E;WB6EYV;Spin the Bottle: Bumpie's Party;16,32
|
||||||
0005000E-10148000;1;WUP;00AF;WUP-P-AUNJ;AUNJAF;ONE PIECE UNLIMITED WORLD R
|
0005000E-10148000;1;WUP;00AF;WUP-P-AUNJ;AUNJAF;ONE PIECE UNLIMITED WORLD R;16
|
||||||
0005000E-10148200;2;WUP;00UP;WUP-U-WAEE;WAEEUP;Rock 'N Racing Off Road
|
0005000E-10148200;2;WUP;00UP;WUP-U-WAEE;WAEEUP;Rock 'N Racing Off Road;16
|
||||||
0005000E-10148F00;1;WUP;0041;WUP-U-WLAJ;WLAJ41;Uplay
|
0005000E-10148F00;1;WUP;0041;WUP-U-WLAJ;WLAJ41;Uplay;16
|
||||||
0005000E-10149200;4;WUP;00SS;WUP-U-WDFP;WDFPSS;Spot The Differences: Party!
|
0005000E-10149200;4;WUP;00SS;WUP-U-WDFP;WDFPSS;Spot The Differences: Party!;16,32
|
||||||
0005000E-10149500;2;WUP;00CS;WUP-P-WKTE;WKTECS;Scram Kitty and his Buddy on Rails
|
0005000E-10149500;2;WUP;00CS;WUP-P-WKTE;WKTECS;Scram Kitty and his Buddy on Rails;16,32
|
||||||
0005000E-10149700;1;WUP;0001;WUP-P-WAUJ;WAUJ01;?? ??
|
0005000E-10149700;1;WUP;0001;WUP-P-WAUJ;WAUJ01;?? ??;34,48
|
||||||
0005000E-1014C600;4;WUP;00CX;WUP-U-WGSP;WGSPCX;Giana Sisters Twisted Dreams
|
0005000E-1014C600;4;WUP;00CX;WUP-U-WGSP;WGSPCX;Giana Sisters Twisted Dreams;16
|
||||||
0005000E-1014C800;1;WUP;0041;WUP-U-ASBJ;ASBJ41;Assassin's Creed® IV Black Flag
|
0005000E-1014C800;1;WUP;0041;WUP-U-ASBJ;ASBJ41;Assassin's Creed® IV Black Flag;16
|
||||||
0005000E-1014CB00;2;WUP;00CX;WUP-P-WGSE;WGSECX;Giana Sisters Twisted Dreams
|
0005000E-1014CB00;2;WUP;00CX;WUP-P-WGSE;WGSECX;Giana Sisters Twisted Dreams;16
|
||||||
0005000E-1014CF00;2;WUP;00HL;WUP-U-WCDE;WCDEHL;Coaster Crazy Deluxe
|
0005000E-1014CF00;2;WUP;00HL;WUP-U-WCDE;WCDEHL;Coaster Crazy Deluxe;16,32
|
||||||
0005000E-1014D100;4;WUP;00CS;WUP-U-WKTP;WKTPCS;Scram Kitty and his Buddy on Rails
|
0005000E-1014D100;4;WUP;00CS;WUP-U-WKTP;WKTPCS;Scram Kitty and his Buddy on Rails;17,32
|
||||||
0005000E-1014D900;1;WUP;008P;WUP-P-APTJ;APTJ8P;PUYOPUYOTETRIS
|
0005000E-1014D900;1;WUP;008P;WUP-P-APTJ;APTJ8P;PUYOPUYOTETRIS;16,32
|
||||||
0005000E-1014DA00;1;WUP;0008;WUP-U-AMFJ;AMFJ08;Monster Hunter Frontier G
|
0005000E-1014DA00;1;WUP;0008;WUP-U-AMFJ;AMFJ08;Monster Hunter Frontier G;80,96,112,128,144,160,176,192,208,224,240,256,288,304,320,336,352,368,400,432,448,464,480,496,512,528,544,560,576,592,608,624,640,656,672,688,704,720,736,752,768,784,800,816,832,848,864,880,896,912,928,944,960,976,992,1008,1024,1040,1056,1072,1088,1104,1120,1136,1152,1168,1184,1200,1216,1232,1248,1264,1280,1296,1312,1328,1344,1360,1376
|
||||||
0005000E-1014DE00;2;WUP;00WR;WUP-U-ALAE;ALAEWR;The LEGO® Movie Videogame
|
0005000E-1014DE00;2;WUP;00WR;WUP-U-ALAE;ALAEWR;The LEGO® Movie Videogame;16
|
||||||
0005000E-1014E000;4;WUP;00WR;WUP-U-ALAP;ALAPWR;The LEGO® Movie Videogame
|
0005000E-1014E000;4;WUP;00WR;WUP-U-ALAP;ALAPWR;The LEGO® Movie Videogame;18
|
||||||
0005000E-1014E100;4;WUP;00AF;WUP-U-ADVP;ADVPAF;Adventure Time: Explore the Dungeon Because I Don't Know!
|
0005000E-1014E100;4;WUP;00AF;WUP-U-ADVP;ADVPAF;Adventure Time: Explore the Dungeon Because I Don't Know!;16
|
||||||
0005000E-1014E300;4;WUP;00GT;WUP-U-AZBP;AZBPGT;Zumba Fitness World Party
|
0005000E-1014E300;4;WUP;00GT;WUP-U-AZBP;AZBPGT;Zumba Fitness World Party;16
|
||||||
0005000E-10154600;1;WUP;00WR;WUP-U-AZEJ;AZEJWR;Batman™: Arkham Origins
|
0005000E-10154600;1;WUP;00WR;WUP-U-AZEJ;AZEJWR;Batman™: Arkham Origins;16
|
||||||
0005000E-10154D00;4;WUP;00BU;WUP-U-WC3P;WC3PBU;The Mysterious Cities of Gold: Secret Paths
|
0005000E-10154D00;4;WUP;00BU;WUP-U-WC3P;WC3PBU;The Mysterious Cities of Gold: Secret Paths;16
|
||||||
0005000E-10156100;4;WUP;0052;WUP-P-ACPP;ACPP52;Call of Duty: Ghosts
|
0005000E-10156100;4;WUP;0052;WUP-P-ACPP;ACPP52;Call of Duty: Ghosts;16,32,48,64,80,96,112
|
||||||
0005000E-10156500;2;WUP;00BU;WUP-U-WC3E;WC3EBU;The Mysterious Cities of Gold: Secret Paths
|
0005000E-10156500;2;WUP;00BU;WUP-U-WC3E;WC3EBU;The Mysterious Cities of Gold: Secret Paths;16
|
||||||
0005000E-10157600;4;WUP;0052;WUP-P-ACPI;ACPI52;Call of Duty: Ghosts
|
0005000E-10157600;4;WUP;0052;WUP-P-ACPI;ACPI52;Call of Duty: Ghosts;16,32,48,64,80,96,112
|
||||||
0005000E-10157900;1;WUP;00GD;WUP-P-ACPJ;ACPJGD;Call of Duty: Ghosts
|
0005000E-10157900;1;WUP;00GD;WUP-P-ACPJ;ACPJGD;Call of Duty: Ghosts;16,32,48,64,80,97,112
|
||||||
0005000E-10159800;1;WUP;0001;WUP-U-AFCJ;AFCJ01;Wii Fit U (Free)
|
0005000E-10159800;1;WUP;0001;WUP-U-AFCJ;AFCJ01;Wii Fit U (Free);48,64,81
|
||||||
0005000E-10159900;2;WUP;0001;WUP-U-AFCE;AFCE01;Wii Fit U (Free)
|
0005000E-10159900;2;WUP;0001;WUP-U-AFCE;AFCE01;Wii Fit U (Free);48,64,81
|
||||||
0005000E-10159A00;4;WUP;0001;WUP-U-AFCP;AFCP01;Wii Fit U (promo)
|
0005000E-10159A00;4;WUP;0001;WUP-U-AFCP;AFCP01;Wii Fit U (promo);48,64,81
|
||||||
0005000E-1015A300;1;WUP;00AF;WUP-U-ADSJ;ADSJAF;Disney INFINITY
|
0005000E-1015A300;1;WUP;00AF;WUP-U-ADSJ;ADSJAF;Disney INFINITY;17
|
||||||
0005000E-1015B200;2;WUP;0041;WUP-P-ACLE;ACLE41;CHILD of LIGHT
|
0005000E-1015B200;2;WUP;0041;WUP-P-ACLE;ACLE41;CHILD of LIGHT;16
|
||||||
0005000E-1015D300;2;WUP;00AS;WUP-P-WLCE;WLCEAS;Lucadian Chronicles
|
0005000E-1015D300;2;WUP;00AS;WUP-P-WLCE;WLCEAS;Lucadian Chronicles;32
|
||||||
0005000E-1015EB00;1;WUP;00R7;WUP-U-WHYJ;WHYJR7;Mighty Switch Force!™ Hyper Drive Edition
|
0005000E-1015EB00;1;WUP;00R7;WUP-U-WHYJ;WHYJR7;Mighty Switch Force!™ Hyper Drive Edition;18
|
||||||
0005000E-10161F00;1;WUP;0001;WUP-U-ABAJ;ABAJ01;Mario Party 10
|
0005000E-10161F00;1;WUP;0001;WUP-U-ABAJ;ABAJ01;Mario Party 10;16
|
||||||
0005000E-10162300;4;WUP;00YR;WUP-U-WCZP;WCZPYR;Color Zen
|
0005000E-10162300;4;WUP;00YR;WUP-U-WCZP;WCZPYR;Color Zen;17
|
||||||
0005000E-10162B00;1;WUP;0001;WUP-P-AGMJ;AGMJ01;Splatoon
|
0005000E-10162B00;1;WUP;0001;WUP-P-AGMJ;AGMJ01;Splatoon;16,32,48,64,80,96,112,128,144,160
|
||||||
0005000E-10162D00;2;WUP;0001;WUP-U-ABAE;ABAE01;Mario Party 10
|
0005000E-10162D00;2;WUP;0001;WUP-U-ABAE;ABAE01;Mario Party 10;16
|
||||||
0005000E-10169600;4;WUP;00UP;WUP-U-WEPS;WEPSUP;Unepic EnjoyUp Games
|
0005000E-10169600;4;WUP;00UP;WUP-U-WEPS;WEPSUP;Unepic EnjoyUp Games;16,32
|
||||||
0005000E-1016A200;4;WUP;00SS;WUP-U-WBXP;WBXPSS;Bombing Bastards
|
0005000E-1016A200;4;WUP;00SS;WUP-U-WBXP;WBXPSS;Bombing Bastards;16
|
||||||
0005000E-1016A400;4;WUP;00WR;WUP-P-BTMP;BTMPWR;LEGO® Batman™ 3 Beyond Gotham
|
0005000E-1016A400;4;WUP;00WR;WUP-P-BTMP;BTMPWR;LEGO® Batman™ 3 Beyond Gotham;16,32,48
|
||||||
0005000E-1016A600;1;WUP;00TF;WUP-P-WB6J;WB6JTF;??????????????
|
0005000E-1016A600;1;WUP;00TF;WUP-P-WB6J;WB6JTF;??????????????;17
|
||||||
0005000E-1016AB00;2;WUP;00SS;WUP-U-WBXE;WBXESS;Bombing Bastards
|
0005000E-1016AB00;2;WUP;00SS;WUP-U-WBXE;WBXESS;Bombing Bastards;16
|
||||||
0005000E-1016AC00;2;WUP;009T;WUP-U-WMLE;WMLE9T;Armillo
|
0005000E-1016AC00;2;WUP;009T;WUP-U-WMLE;WMLE9T;Armillo;16
|
||||||
0005000E-1016AD00;2;WUP;00WR;WUP-P-BTME;BTMEWR;LEGO® Batman™ 3 Beyond Gotham
|
0005000E-1016AD00;2;WUP;00WR;WUP-P-BTME;BTMEWR;LEGO® Batman™ 3 Beyond Gotham;16,32,48
|
||||||
0005000E-1016B200;2;WUP;009V;WUP-U-WMRE;WMRE9V;Master Reboot
|
0005000E-1016B200;2;WUP;009V;WUP-U-WMRE;WMRE9V;Master Reboot;16
|
||||||
0005000E-1016C700;4;WUP;009T;WUP-U-WMLP;WMLP9T;Armillo
|
0005000E-1016C700;4;WUP;009T;WUP-U-WMLP;WMLP9T;Armillo;16
|
||||||
0005000E-1016CE00;2;WUP;00YR;WUP-U-WCZE;WCZEYR;Color Zen
|
0005000E-1016CE00;2;WUP;00YR;WUP-U-WCZE;WCZEYR;Color Zen;16
|
||||||
0005000E-1016D500;4;WUP;009Y;WUP-P-WCTP;WCTP9Y;Super Toy Cars
|
0005000E-1016D500;4;WUP;009Y;WUP-P-WCTP;WCTP9Y;Super Toy Cars;22
|
||||||
0005000E-1016D800;1;WUP;0041;WUP-P-ACLJ;ACLJ41;CHILD of LIGHT
|
0005000E-1016D800;1;WUP;0041;WUP-P-ACLJ;ACLJ41;CHILD of LIGHT;16
|
||||||
0005000E-1016DC00;2;WUP;004Q;WUP-P-ADRE;ADRE4Q;Disney Infinity [2.0]
|
0005000E-1016DC00;2;WUP;004Q;WUP-P-ADRE;ADRE4Q;Disney Infinity [2.0];16,32,64,80
|
||||||
0005000E-1016DE00;2;WUP;009Y;WUP-P-WCTE;WCTE9Y;Super Toy Cars
|
0005000E-1016DE00;2;WUP;009Y;WUP-P-WCTE;WCTE9Y;Super Toy Cars;16
|
||||||
0005000E-1016E100;2;WUP;00AY;WUP-P-WKNE;WKNEAY;Shovel Knight
|
0005000E-1016E100;2;WUP;00AY;WUP-P-WKNE;WKNEAY;Shovel Knight;16,32,48,64,80
|
||||||
0005000E-1016E300;2;WUP;008S;WUP-P-WGRE;WGRE8S;GravBlocks+ From Nothing Game Studios
|
0005000E-1016E300;2;WUP;008S;WUP-P-WGRE;WGRE8S;GravBlocks+ From Nothing Game Studios;16
|
||||||
0005000E-1016E800;4;WUP;009V;WUP-U-WMRP;WMRP9V;Master Reboot
|
0005000E-1016E800;4;WUP;009V;WUP-U-WMRP;WMRP9V;Master Reboot;16
|
||||||
0005000E-1016EA00;4;WUP;0041;WUP-P-ACLP;ACLP41;CHILD of LIGHT
|
0005000E-1016EA00;4;WUP;0041;WUP-P-ACLP;ACLP41;CHILD of LIGHT;16
|
||||||
0005000E-1016FF00;2;WUP;00NT;WUP-P-WFWE;WFWENT;Flowerworks HD Follie's Adventure
|
0005000E-1016FF00;2;WUP;00NT;WUP-P-WFWE;WFWENT;Flowerworks HD Follie's Adventure;16
|
||||||
0005000E-10170200;2;WUP;007Z;WUP-U-WGAE;WGAE7Z;Pier Solar and the Great Architects
|
0005000E-10170200;2;WUP;007Z;WUP-U-WGAE;WGAE7Z;Pier Solar and the Great Architects;16,33
|
||||||
0005000E-10170600;1;WUP;00AF;WUP-U-APWJ;APWJAF;KAMEN RIDER BATTRIDE WAR ? PREMIUM TV&MOVIE SOUND ED.
|
0005000E-10170600;1;WUP;00AF;WUP-U-APWJ;APWJAF;KAMEN RIDER BATTRIDE WAR ? PREMIUM TV&MOVIE SOUND ED.;16
|
||||||
0005000E-10170700;1;WUP;00AF;WUP-U-ABWJ;ABWJAF;KAMEN RIDER BATTRIDE WAR ?
|
0005000E-10170700;1;WUP;00AF;WUP-U-ABWJ;ABWJAF;KAMEN RIDER BATTRIDE WAR ?;17
|
||||||
0005000E-10172A00;2;WUP;009Z;WUP-N-HRLE;HRLE9Z;Crunchyroll
|
0005000E-10172A00;2;WUP;009Z;WUP-N-HRLE;HRLE9Z;Crunchyroll;16
|
||||||
0005000E-10172B00;4;WUP;009Z;WUP-N-HRLP;HRLP9Z;Crunchyroll
|
0005000E-10172B00;4;WUP;009Z;WUP-N-HRLP;HRLP9Z;Crunchyroll;17
|
||||||
0005000E-10173300;4;WUP;00UB;WUP-U-WCGP;WCGPUB;Stealth Inc 2 A Game of Clones
|
0005000E-10173300;4;WUP;00UB;WUP-U-WCGP;WCGPUB;Stealth Inc 2 A Game of Clones;16,32
|
||||||
0005000E-10175B00;2;WUP;008P;WUP-P-BSSE;BSSE8P;Sonic Boom: Rise of Lyric
|
0005000E-10175B00;2;WUP;008P;WUP-P-BSSE;BSSE8P;Sonic Boom: Rise of Lyric;16
|
||||||
0005000E-10175D00;4;WUP;00AF;WUP-P-AUNP;AUNPAF;ONE PIECE Unlimited World Red
|
0005000E-10175D00;4;WUP;00AF;WUP-P-AUNP;AUNPAF;ONE PIECE Unlimited World Red;16
|
||||||
0005000E-10176500;2;WUP;00UB;WUP-U-WCGE;WCGEUB;Stealth Inc 2 A Game of Clones
|
0005000E-10176500;2;WUP;00UB;WUP-U-WCGE;WCGEUB;Stealth Inc 2 A Game of Clones;16
|
||||||
0005000E-10176900;2;WUP;0001;WUP-P-AGME;AGME01;Splatoon
|
0005000E-10176900;2;WUP;0001;WUP-P-AGME;AGME01;Splatoon;16,32,48,64,80,96,128,144,160
|
||||||
0005000E-10176A00;4;WUP;0001;WUP-P-AGMP;AGMP01;Splatoon
|
0005000E-10176A00;4;WUP;0001;WUP-P-AGMP;AGMP01;Splatoon;32,48,64,80,96,112,128,144,160
|
||||||
0005000E-10176F00;4;WUP;0041;WUP-P-BJDP;BJDP41;JUST DANCE® 2015
|
0005000E-10176F00;4;WUP;0041;WUP-P-BJDP;BJDP41;JUST DANCE® 2015;16
|
||||||
0005000E-10177600;2;WUP;0001;WUP-U-ADNE;ADNE01;Devil's Third
|
0005000E-10177600;2;WUP;0001;WUP-U-ADNE;ADNE01;Devil's Third;16
|
||||||
0005000E-10177800;4;WUP;008P;WUP-P-BSSP;BSSP8P;Sonic Boom: Rise of Lyric
|
0005000E-10177800;4;WUP;008P;WUP-P-BSSP;BSSP8P;Sonic Boom: Rise of Lyric;16
|
||||||
0005000E-10178F00;4;WUP;00AY;WUP-P-WKNP;WKNPAY;Shovel Knight
|
0005000E-10178F00;4;WUP;00AY;WUP-P-WKNP;WKNPAY;Shovel Knight;16,32,48
|
||||||
0005000E-10179100;2;WUP;0041;WUP-P-BJDE;BJDE41;JUST DANCE® 2015
|
0005000E-10179100;2;WUP;0041;WUP-P-BJDE;BJDE41;JUST DANCE® 2015;16
|
||||||
0005000E-1017BE00;1;WUP;0001;WUP-U-BXAJ;BXAJ01;Art Academy: Home Studio
|
0005000E-1017BE00;1;WUP;0001;WUP-U-BXAJ;BXAJ01;Art Academy: Home Studio;48
|
||||||
0005000E-1017BF00;2;WUP;0001;WUP-U-BXAE;BXAE01;Art Academy: Home Studio
|
0005000E-1017BF00;2;WUP;0001;WUP-U-BXAE;BXAE01;Art Academy: Home Studio;17
|
||||||
0005000E-1017C600;2;WUP;0052;WUP-P-BK7E;BK7E52;Skylanders Trap Team
|
0005000E-1017C600;2;WUP;0052;WUP-P-BK7E;BK7E52;Skylanders Trap Team;16
|
||||||
0005000E-1017CD00;1;WUP;00C8;WUP-U-BWPJ;BWPJC8;Hyrule Warriors
|
0005000E-1017CD00;1;WUP;00C8;WUP-U-BWPJ;BWPJC8;Hyrule Warriors;32,49,64,80,98,112,113,128,144,160,176,192,208
|
||||||
0005000E-1017D800;2;WUP;0001;WUP-U-BWPE;BWPE01;Hyrule Warriors
|
0005000E-1017D800;2;WUP;0001;WUP-U-BWPE;BWPE01;Hyrule Warriors;16,32,48,64,80,96,112,128
|
||||||
0005000E-1017D900;4;WUP;0001;WUP-U-BWPP;BWPP01;Hyrule Warriors
|
0005000E-1017D900;4;WUP;0001;WUP-U-BWPP;BWPP01;Hyrule Warriors;16,33,48,64,80,96,112,128
|
||||||
0005000E-1017DA00;2;WUP;011S;WUP-P-ACQE;ACQE1S;Costume Quest 2
|
0005000E-1017DA00;2;WUP;011S;WUP-P-ACQE;ACQE1S;Costume Quest 2;16
|
||||||
0005000E-1017E000;4;WUP;00XQ;WUP-P-WK8P;WK8PXQ;Turtle Tale
|
0005000E-1017E000;4;WUP;00XQ;WUP-P-WK8P;WK8PXQ;Turtle Tale;16
|
||||||
0005000E-10180500;1;WUP;0001;WUP-P-AKBJ;AKBJ01;Captain Toad: Treasure Tracker
|
0005000E-10180500;1;WUP;0001;WUP-P-AKBJ;AKBJ01;Captain Toad: Treasure Tracker;16
|
||||||
0005000E-10180600;2;WUP;0001;WUP-P-AKBE;AKBE01;Captain Toad: Treasure Tracker
|
0005000E-10180600;2;WUP;0001;WUP-P-AKBE;AKBE01;Captain Toad: Treasure Tracker;16
|
||||||
0005000E-10180700;4;WUP;0001;WUP-P-AKBP;AKBP01;Captain Toad: Treasure Tracker
|
0005000E-10180700;4;WUP;0001;WUP-P-AKBP;AKBP01;Captain Toad: Treasure Tracker;16
|
||||||
0005000E-10181F00;4;WUP;0052;WUP-P-BK7P;BK7P52;Skylanders Trap Team
|
0005000E-10181F00;4;WUP;0052;WUP-P-BK7P;BK7P52;Skylanders Trap Team;16
|
||||||
0005000E-10182C00;4;WUP;00XT;WUP-U-AJTP;AJTPXT;Jett Tailfin
|
0005000E-10182C00;4;WUP;00XT;WUP-U-AJTP;AJTPXT;Jett Tailfin;16
|
||||||
0005000E-10183000;2;WUP;010P;WUP-P-ARNE;ARNE0P;Runbow
|
0005000E-10183000;2;WUP;010P;WUP-P-ARNE;ARNE0P;Runbow;16,33,49
|
||||||
0005000E-10183900;2;WUP;00UP;WUP-U-BMVE;BMVEUP;99Moves
|
0005000E-10183900;2;WUP;00UP;WUP-U-BMVE;BMVEUP;99Moves;16,32
|
||||||
0005000E-10184D00;2;WUP;0001;WUP-U-AYCE;AYCE01;Yoshi's Woolly World
|
0005000E-10184D00;2;WUP;0001;WUP-U-AYCE;AYCE01;Yoshi's Woolly World;17
|
||||||
0005000E-10187100;4;WUP;00LW;WUP-U-BUGP;BUGPLW;Underground
|
0005000E-10187100;4;WUP;00LW;WUP-U-BUGP;BUGPLW;Underground;16,32
|
||||||
0005000E-10188B00;1;WUP;0001;WUP-U-AXYJ;AXYJ01;Kirby and the Rainbow Curse
|
0005000E-10188B00;1;WUP;0001;WUP-U-AXYJ;AXYJ01;Kirby and the Rainbow Curse;16
|
||||||
0005000E-10188C00;4;WUP;004Q;WUP-P-ADRP;ADRP4Q;Disney Infinity [2.0]
|
0005000E-10188C00;4;WUP;004Q;WUP-P-ADRP;ADRP4Q;Disney Infinity [2.0];16,32,64,80
|
||||||
0005000E-10188D00;4;WUP;004Q;WUP-P-ADRZ;ADRZ4Q;Disney Infinity [2.0]
|
0005000E-10188D00;4;WUP;004Q;WUP-P-ADRZ;ADRZ4Q;Disney Infinity [2.0];16,32,64,80
|
||||||
0005000E-10189200;2;WUP;011C;WUP-P-BSPE;BSPE1C;Sportsball
|
0005000E-10189200;2;WUP;011C;WUP-P-BSPE;BSPE1C;Sportsball;16
|
||||||
0005000E-1018C400;1;WUP;00AF;WUP-P-BSFJ;BSFJAF;???F??????????? ????SF???????????
|
0005000E-1018C400;1;WUP;00AF;WUP-P-BSFJ;BSFJAF;???F??????????? ????SF???????????;16
|
||||||
0005000E-1018DB00;1;WUP;0001;WUP-U-AMAJ;AMAJ01;Super Mario Maker
|
0005000E-1018D900;1;WUP;00AF;WUP-P-APHJ;APHJAF;LOST REAVERS;17
|
||||||
0005000E-1018DC00;2;WUP;0001;WUP-U-AMAE;AMAE01;Super Mario Maker
|
0005000E-1018DB00;1;WUP;0001;WUP-U-AMAJ;AMAJ01;Super Mario Maker;16,32,48,64,80,96,113,128
|
||||||
0005000E-1018DD00;4;WUP;0001;WUP-U-AMAP;AMAP01;Super Mario Maker
|
0005000E-1018DC00;2;WUP;0001;WUP-U-AMAE;AMAE01;Super Mario Maker;16,32,48,64,80,96,113,128
|
||||||
0005000E-1018DE00;4;WUP;00NK;WUP-U-ATCP;ATCPNK;Tetrobot and Co.
|
0005000E-1018DD00;4;WUP;0001;WUP-U-AMAP;AMAP01;Super Mario Maker;32,48,64,80,96,113,128
|
||||||
0005000E-1018ED00;2;WUP;00NK;WUP-U-ATCE;ATCENK;Tetrobot and Co.
|
0005000E-1018DE00;4;WUP;00NK;WUP-U-ATCP;ATCPNK;Tetrobot and Co.;16
|
||||||
0005000E-10191700;4;WUP;00UP;WUP-U-BMVP;BMVPUP;99Moves
|
0005000E-1018ED00;2;WUP;00NK;WUP-U-ATCE;ATCENK;Tetrobot and Co.;16
|
||||||
0005000E-10191800;4;WUP;00UP;WUP-U-WAEP;WAEPUP;Rock 'N Racing Off Road
|
0005000E-10191700;4;WUP;00UP;WUP-U-BMVP;BMVPUP;99Moves;16,32
|
||||||
0005000E-10192200;1;WUP;00AF;WUP-P-BRSJ;BRSJAF;KAMEN RIDER SUMMON RIDE!
|
0005000E-10191800;4;WUP;00UP;WUP-U-WAEP;WAEPUP;Rock 'N Racing Off Road;16
|
||||||
0005000E-10194200;2;WUP;00WR;WUP-U-APZE;APZEWR;LEGO® DIMENSIONS™
|
0005000E-10192200;1;WUP;00AF;WUP-P-BRSJ;BRSJAF;KAMEN RIDER SUMMON RIDE!;16,33,48,64,80
|
||||||
0005000E-10195D00;4;WUP;00WR;WUP-U-APZP;APZPWR;LEGO® DIMENSIONS™
|
0005000E-10194200;2;WUP;00WR;WUP-U-APZE;APZEWR;LEGO® DIMENSIONS™;16,32,48,64,80
|
||||||
0005000E-10197800;4;WUP;011S;WUP-P-ACQP;ACQP1S;Costume Quest 2
|
0005000E-10195D00;4;WUP;00WR;WUP-U-APZP;APZPWR;LEGO® DIMENSIONS™;32,48,64,80,96
|
||||||
0005000E-10199000;1;WUP;0001;WUP-P-AVXJ;AVXJ01;Mario Tennis: Ultra Smash
|
0005000E-10197800;4;WUP;011S;WUP-P-ACQP;ACQP1S;Costume Quest 2;16
|
||||||
0005000E-1019AD00;2;WUP;011A;WUP-P-BEQE;BEQE1A;Elliot Quest
|
0005000E-10199000;1;WUP;0001;WUP-P-AVXJ;AVXJ01;Mario Tennis: Ultra Smash;16,32
|
||||||
0005000E-101A1B00;2;WUP;00RG;WUP-U-BS2E;BS2ERG;Swords & Soldiers II
|
0005000E-1019AD00;2;WUP;011A;WUP-P-BEQE;BEQE1A;Elliot Quest;16,32,48,64,80,96
|
||||||
0005000E-101A2600;1;WUP;00W4;WUP-U-WKFJ;WKFJW4;Kung Fu Rabbit
|
0005000E-101A1B00;2;WUP;00RG;WUP-U-BS2E;BS2ERG;Swords & Soldiers II;16
|
||||||
0005000E-101A2E00;1;WUP;00TF;WUP-P-WEXJ;WEXJTF;XType+
|
0005000E-101A2600;1;WUP;00W4;WUP-U-WKFJ;WKFJW4;Kung Fu Rabbit;16
|
||||||
0005000E-101A3500;2;WUP;0001;WUP-P-AVXE;AVXE01;Mario Tennis: Ultra Smash
|
0005000E-101A2E00;1;WUP;00TF;WUP-P-WEXJ;WEXJTF;XType+;16
|
||||||
0005000E-101A3600;4;WUP;0001;WUP-P-AVXP;AVXP01;Mario Tennis: Ultra Smash
|
0005000E-101A3500;2;WUP;0001;WUP-P-AVXE;AVXE01;Mario Tennis: Ultra Smash;16,32
|
||||||
0005000E-101A3B00;2;WUP;00LY;WUP-P-BLPE;BLPELY;Life of Pixel
|
0005000E-101A3600;4;WUP;0001;WUP-P-AVXP;AVXP01;Mario Tennis: Ultra Smash;32
|
||||||
0005000E-101A4900;4;WUP;00LY;WUP-U-BLPP;BLPPLY;Life of Pixel
|
0005000E-101A3B00;2;WUP;00LY;WUP-P-BLPE;BLPELY;Life of Pixel;16
|
||||||
0005000E-101A5C00;4;WUP;00WR;WUP-U-ALJP;ALJPWR;LEGO® Jurassic World™
|
0005000E-101A4900;4;WUP;00LY;WUP-U-BLPP;BLPPLY;Life of Pixel;16
|
||||||
0005000E-101A5E00;4;WUP;00UB;WUP-U-ALLP;ALLPUB;OlliOlli
|
0005000E-101A5C00;4;WUP;00WR;WUP-U-ALJP;ALJPWR;LEGO® Jurassic World™;16
|
||||||
0005000E-101A5F00;2;WUP;00WY;WUP-U-BSXE;BSXEWY;Shantae and the Pirate's Curse
|
0005000E-101A5E00;4;WUP;00UB;WUP-U-ALLP;ALLPUB;OlliOlli;16
|
||||||
0005000E-101A6200;2;WUP;00WR;WUP-U-ALJE;ALJEWR;LEGO® Jurassic World™
|
0005000E-101A5F00;2;WUP;00WY;WUP-U-BSXE;BSXEWY;Shantae and the Pirate's Curse;16
|
||||||
0005000E-101A6300;4;WUP;00YR;WUP-U-ACUP;ACUPYR;Cube Life: Island Survival
|
0005000E-101A6200;2;WUP;00WR;WUP-U-ALJE;ALJEWR;LEGO® Jurassic World™;16
|
||||||
0005000E-101A6400;2;WUP;00YR;WUP-U-ACUE;ACUEYR;Cube Life: Island Survival
|
0005000E-101A6300;4;WUP;00YR;WUP-U-ACUP;ACUPYR;Cube Life: Island Survival;16
|
||||||
0005000E-101A6500;2;WUP;00VZ;WUP-P-BKFE;BKFEVZ;Kung Fu Panda Showdown of Legendary Legends
|
0005000E-101A6400;2;WUP;00YR;WUP-U-ACUE;ACUEYR;Cube Life: Island Survival;16
|
||||||
0005000E-101A6900;2;WUP;00UB;WUP-P-ALLE;ALLEUB;OlliOlli
|
0005000E-101A6500;2;WUP;00VZ;WUP-P-BKFE;BKFEVZ;Kung Fu Panda Showdown of Legendary Legends;16
|
||||||
0005000E-101A9500;4;WUP;00WY;WUP-U-BSXP;BSXPWY;Shantae and the Pirate's Curse
|
0005000E-101A6900;2;WUP;00UB;WUP-P-ALLE;ALLEUB;OlliOlli;17
|
||||||
0005000E-101A9F00;2;WUP;0147;WUP-P-BDAE;BDAE47;Dot Arcade
|
0005000E-101A9500;4;WUP;00WY;WUP-U-BSXP;BSXPWY;Shantae and the Pirate's Curse;16
|
||||||
0005000E-101AA500;4;WUP;00VZ;WUP-P-BKFP;BKFPVZ;Kung Fu Panda Showdown of Legendary Legends
|
0005000E-101A9F00;2;WUP;0147;WUP-P-BDAE;BDAE47;Dot Arcade;16
|
||||||
0005000E-101ABC00;2;WUP;0001;WUP-U-AXYE;AXYE01;Kirby and the Rainbow Curse
|
0005000E-101AA200;2;WUP;014K;WUP-U-APJE;APJE4K;Vector Assault;18
|
||||||
0005000E-101AC700;2;WUP;00VZ;WUP-P-BFNE;BFNEVZ;Adventure Time Finn and Jake Investigations
|
0005000E-101AA500;4;WUP;00VZ;WUP-P-BKFP;BKFPVZ;Kung Fu Panda Showdown of Legendary Legends;16,32
|
||||||
0005000E-101AC900;2;WUP;004Q;WUP-P-BD3E;BD3E4Q;DISNEY INFINITY 3.0 EDITION
|
0005000E-101ABC00;2;WUP;0001;WUP-U-AXYE;AXYE01;Kirby and the Rainbow Curse;16
|
||||||
0005000E-101AFE00;4;WUP;00VZ;WUP-P-BFNP;BFNPVZ;Adventure Time Finn and Jake Investigations
|
0005000E-101AC700;2;WUP;00VZ;WUP-P-BFNE;BFNEVZ;Adventure Time Finn and Jake Investigations;16
|
||||||
0005000E-101B3D00;4;WUP;004Q;WUP-P-BD3P;BD3P4Q;DISNEY INFINITY 3.0: PLAY WITHOUT LIMITS
|
0005000E-101AC900;2;WUP;004Q;WUP-P-BD3E;BD3E4Q;DISNEY INFINITY 3.0 EDITION;16,32,49
|
||||||
0005000E-101B3E00;4;WUP;004Q;WUP-P-BD3Z;BD3Z4Q;DISNEY INFINITY 3.0: PLAY WITHOUT LIMITS
|
0005000E-101AFE00;4;WUP;00VZ;WUP-P-BFNP;BFNPVZ;Adventure Time Finn and Jake Investigations;16
|
||||||
0005000E-101B8500;2;WUP;0052;WUP-P-BS5E;BS5E52;Skylanders SuperChargers
|
0005000E-101B3D00;4;WUP;004Q;WUP-P-BD3P;BD3P4Q;DISNEY INFINITY 3.0: PLAY WITHOUT LIMITS;16,32,49
|
||||||
0005000E-101B9000;2;WUP;0041;WUP-P-AJ6E;AJ6E41;JUST DANCE® 2016
|
0005000E-101B3E00;4;WUP;004Q;WUP-P-BD3Z;BD3Z4Q;DISNEY INFINITY 3.0: PLAY WITHOUT LIMITS;16,32,49
|
||||||
0005000E-101B9800;4;WUP;0041;WUP-P-AJ6P;AJ6P41;JUST DANCE® 2016
|
0005000E-101B8500;2;WUP;0052;WUP-P-BS5E;BS5E52;Skylanders SuperChargers;16,32,64,80,96
|
||||||
0005000E-101BA400;2;WUP;0052;WUP-P-AGNE;AGNE52;Guitar Hero Live
|
0005000E-101B9000;2;WUP;0041;WUP-P-AJ6E;AJ6E41;JUST DANCE® 2016;16,32
|
||||||
0005000E-101BAA00;2;WUP;010C;WUP-U-ATTE;ATTE0C;Totem Topple
|
0005000E-101B9800;4;WUP;0041;WUP-P-AJ6P;AJ6P41;JUST DANCE® 2016;16,32
|
||||||
0005000E-101BB300;4;WUP;008V;WUP-P-WLSP;WLSP8V;ZaciSa: Defense of the Crayon Dimension!
|
0005000E-101BA400;2;WUP;0052;WUP-P-AGNE;AGNE52;Guitar Hero Live;16,32,48,64
|
||||||
0005000E-101BB800;4;WUP;011A;WUP-P-BEQP;BEQP1A;Elliot Quest
|
0005000E-101BAA00;2;WUP;010C;WUP-U-ATTE;ATTE0C;Totem Topple;16
|
||||||
0005000E-101BC600;4;WUP;0052;WUP-P-AGNP;AGNP52;Guitar Hero Live
|
0005000E-101BB300;4;WUP;008V;WUP-P-WLSP;WLSP8V;ZaciSa: Defense of the Crayon Dimension!;16
|
||||||
0005000E-101BE900;4;WUP;00WR;WUP-P-ALRP;ALRPWR;LEGO® MARVEL's Avengers
|
0005000E-101BB800;4;WUP;011A;WUP-P-BEQP;BEQP1A;Elliot Quest;16,32,48,64,80
|
||||||
0005000E-101BEF00;2;WUP;00WR;WUP-P-ALRE;ALREWR;LEGO® MARVEL's Avengers
|
0005000E-101BC600;4;WUP;0052;WUP-P-AGNP;AGNP52;Guitar Hero Live;18,32,48,64
|
||||||
0005000E-101BFC00;4;WUP;0052;WUP-P-BS5P;BS5P52;Skylanders SuperChargers
|
0005000E-101BE900;4;WUP;00WR;WUP-P-ALRP;ALRPWR;LEGO® MARVEL's Avengers;16
|
||||||
0005000E-101C0700;4;WUP;00UB;WUP-U-AN3P;AN3PUB;Nova-111
|
0005000E-101BEF00;2;WUP;00WR;WUP-P-ALRE;ALREWR;LEGO® MARVEL's Avengers;16
|
||||||
0005000E-101C0A00;2;WUP;00UB;WUP-U-AN3E;AN3EUB;Nova-111
|
0005000E-101BFC00;4;WUP;0052;WUP-P-BS5P;BS5P52;Skylanders SuperChargers;32,48,64,80,97
|
||||||
0005000E-101C0B00;2;WUP;00UB;WUP-P-BS7E;BS7EUB;The Swindle
|
0005000E-101C0700;4;WUP;00UB;WUP-U-AN3P;AN3PUB;Nova-111;16
|
||||||
0005000E-101C0C00;4;WUP;00UB;WUP-P-BS7P;BS7PUB;The Swindle
|
0005000E-101C0A00;2;WUP;00UB;WUP-U-AN3E;AN3EUB;Nova-111;16
|
||||||
0005000E-101C3100;2;WUP;0167;WUP-U-AFEE;AFEE67;Freedom Planet
|
0005000E-101C0B00;2;WUP;00UB;WUP-P-BS7E;BS7EUB;The Swindle;16
|
||||||
0005000E-101C3900;4;WUP;015G;WUP-P-AWBP;AWBP5G;Word Search by POWGI
|
0005000E-101C0C00;4;WUP;00UB;WUP-P-BS7P;BS7PUB;The Swindle;16
|
||||||
0005000E-101C4C00;4;WUP;0001;WUP-P-AX5D;AX5D01;Xenoblade Chronicles X
|
0005000E-101C3100;2;WUP;0167;WUP-U-AFEE;AFEE67;Freedom Planet;17
|
||||||
0005000E-101C4D00;2;WUP;0001;WUP-P-AX5E;AX5E01;Xenoblade Chronicles X
|
0005000E-101C3900;4;WUP;015G;WUP-P-AWBP;AWBP5G;Word Search by POWGI;16
|
||||||
0005000E-101C6A00;2;WUP;016E;WUP-P-AD5E;AD5E6E;Octodad: Dadliest Catch
|
0005000E-101C4C00;4;WUP;0001;WUP-P-AX5D;AX5D01;Xenoblade Chronicles X;16
|
||||||
0005000E-101C6E00;4;WUP;00RG;WUP-U-BS2P;BS2PRG;Swords & Soldiers II
|
0005000E-101C4D00;2;WUP;0001;WUP-P-AX5E;AX5E01;Xenoblade Chronicles X;16,32,48
|
||||||
0005000E-101C8B00;4;WUP;00YT;WUP-P-AWMP;AWMPYT;WICKED MONSTERS BLAST! HD PLUS
|
0005000E-101C6A00;2;WUP;016E;WUP-P-AD5E;AD5E6E;Octodad: Dadliest Catch;16
|
||||||
0005000E-101CC900;4;WUP;0167;WUP-U-AFEP;AFEP67;Freedom Planet
|
0005000E-101C6E00;4;WUP;00RG;WUP-U-BS2P;BS2PRG;Swords & Soldiers II;16
|
||||||
0005000E-101CE100;2;WUP;0175;WUP-U-ACHE;ACHE75;Canvaleon
|
0005000E-101C8B00;4;WUP;00YT;WUP-P-AWMP;AWMPYT;WICKED MONSTERS BLAST! HD PLUS;16
|
||||||
0005000E-101D0700;4;WUP;0175;WUP-U-ACHP;ACHP75;Canvaleon
|
0005000E-101CC900;4;WUP;0167;WUP-U-AFEP;AFEP67;Freedom Planet;16
|
||||||
0005000E-101D0900;2;WUP;00FV;WUP-U-AGWE;AGWEFV;Gunman Clive HD Collection
|
0005000E-101CE100;2;WUP;0175;WUP-U-ACHE;ACHE75;Canvaleon;16,32
|
||||||
0005000E-101D2C00;1;WUP;00SA;WUP-P-ATXJ;ATXJSA;Bike Rider UltraDX WORLD TOUR
|
0005000E-101D0700;4;WUP;0175;WUP-U-ACHP;ACHP75;Canvaleon;16,32
|
||||||
0005000E-101D3900;4;WUP;017D;WUP-P-AQCP;AQCP7D;The Quiet Collection
|
0005000E-101D0900;2;WUP;00FV;WUP-U-AGWE;AGWEFV;Gunman Clive HD Collection;16
|
||||||
0005000E-101D4200;2;WUP;00DV;WUP-P-ABPE;ABPEDV;Brunswick Pro Bowling
|
0005000E-101D2C00;1;WUP;00SA;WUP-P-ATXJ;ATXJSA;Bike Rider UltraDX WORLD TOUR;16,32
|
||||||
0005000E-101D6100;4;WUP;00FV;WUP-U-AGWP;AGWPFV;Gunman Clive HD Collection
|
0005000E-101D3000;1;WUP;00AF;WUP-P-BT3J;BT3JAF;Taiko no Tatsujin Atsumete? TomodachiDaisakusen!;16
|
||||||
0005000E-101D6D00;4;WUP;010P;WUP-P-ARNP;ARNP0P;Runbow
|
0005000E-101D3900;4;WUP;017D;WUP-P-AQCP;AQCP7D;The Quiet Collection;16
|
||||||
0005000E-101D7400;4;WUP;010C;WUP-U-ATTP;ATTP0C;Totem Topple
|
0005000E-101D4200;2;WUP;00DV;WUP-P-ABPE;ABPEDV;Brunswick Pro Bowling;16
|
||||||
0005000E-101D7500;4;WUP;00DU;WUP-P-AUMP;AUMPDU;Minecraft: Wii U Edition
|
0005000E-101D6100;4;WUP;00FV;WUP-U-AGWP;AGWPFV;Gunman Clive HD Collection;16
|
||||||
0005000E-101D9D00;2;WUP;00DU;WUP-P-AUME;AUMEDU;Minecraft: Wii U Edition
|
0005000E-101D6D00;4;WUP;010P;WUP-P-ARNP;ARNP0P;Runbow;17,33
|
||||||
0005000E-101DBE00;1;WUP;0188;WUP-P-AUMJ;AUMJ88;Minecraft: Wii U Edition
|
0005000E-101D7400;4;WUP;010C;WUP-U-ATTP;ATTP0C;Totem Topple;16
|
||||||
0005000E-101DC100;4;WUP;016E;WUP-P-AD5P;AD5P6E;Octodad: Dadliest Catch
|
0005000E-101D7500;4;WUP;00DU;WUP-P-AUMP;AUMPDU;Minecraft: Wii U Edition;16,32,48
|
||||||
0005000E-101DDC00;1;WUP;00AF;WUP-P-BD3J;BD3JAF;????????????3.0
|
0005000E-101D8300;4;WUP;00TJ;WUP-U-AEJP;AEJPTJ;Electronic Super Joy;16
|
||||||
|
0005000E-101D9D00;2;WUP;00DU;WUP-P-AUME;AUMEDU;Minecraft: Wii U Edition;16,32,48
|
||||||
|
0005000E-101DBE00;1;WUP;0188;WUP-P-AUMJ;AUMJ88;Minecraft: Wii U Edition;16,32,48
|
||||||
|
0005000E-101DC100;4;WUP;016E;WUP-P-AD5P;AD5P6E;Octodad: Dadliest Catch;16
|
||||||
|
0005000E-101DD700;1;WUP;013P;WUP-P-ARNJ;ARNJ3P;Runbow;16,17
|
||||||
|
0005000E-101DDC00;1;WUP;00AF;WUP-P-BD3J;BD3JAF;????????????3.0;17,33
|
||||||
|
|
@ -1,5 +1,11 @@
|
|||||||
package de.mas.jnustool;
|
package de.mas.jnustool;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import de.mas.jnustool.util.Downloader;
|
||||||
|
import de.mas.jnustool.util.Settings;
|
||||||
import de.mas.jnustool.util.Util;
|
import de.mas.jnustool.util.Util;
|
||||||
|
|
||||||
public class Content {
|
public class Content {
|
||||||
@ -9,17 +15,50 @@ public class Content {
|
|||||||
short type; // 6 0xB0A
|
short type; // 6 0xB0A
|
||||||
long size; // 8 0xB0C
|
long size; // 8 0xB0C
|
||||||
byte[] SHA2 = new byte[32]; // 16 0xB14
|
byte[] SHA2 = new byte[32]; // 16 0xB14
|
||||||
|
TitleMetaData tmd;
|
||||||
|
AtomicInteger error_output_done = new AtomicInteger(0);// 16 0xB14
|
||||||
|
|
||||||
|
|
||||||
public Content(int ID, short index, short type, long size, byte[] SHA2) {
|
public Content(int ID, short index, short type, long size, byte[] SHA2,TitleMetaData tmd) {
|
||||||
this.ID = ID;
|
this.ID = ID;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.SHA2 = SHA2;
|
this.SHA2 = SHA2;
|
||||||
|
this.tmd = tmd;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "ID: " + ID +" index: " + index + " type: " + type + " size: " + size + " SHA2: " + Util.ByteArrayToString(SHA2);
|
return "ID: " + ID +" index: " + index + " type: " + type + " size: " + size + " SHA2: " + Util.ByteArrayToString(SHA2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void download(Progress progress) throws IOException{
|
||||||
|
String tmpPath = tmd.getContentPath();
|
||||||
|
if ((type & 0x02) == 0x02){
|
||||||
|
Downloader.getInstance().downloadContentH3(tmd.titleID,ID,tmpPath,null);
|
||||||
|
}
|
||||||
|
File f = new File(tmpPath + "/" + String.format("%08X", ID ) + ".app");
|
||||||
|
if(f.exists()){
|
||||||
|
if(f.length() == size){
|
||||||
|
Logger.log("Skipping Content: " + String.format("%08X", ID));
|
||||||
|
progress.addCurrent((int) size);
|
||||||
|
}else{
|
||||||
|
if(Settings.downloadWhenCachedFilesMissingOrBroken){
|
||||||
|
Logger.log("Content " +String.format("%08X", ID) + " is broken. Downloading it again.");
|
||||||
|
Downloader.getInstance().downloadContent(tmd.titleID,ID,tmpPath,progress);
|
||||||
|
}else{
|
||||||
|
if(Settings.skipBrokenFiles){
|
||||||
|
Logger.log("Content " +String.format("%08X", ID) + " is broken. Ignoring it.");
|
||||||
|
}else{
|
||||||
|
Logger.log("Content " +String.format("%08X", ID) + " is broken. Downloading not allowed.");
|
||||||
|
System.exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Logger.log("Download Content: " + String.format("%08X", ID));
|
||||||
|
Downloader.getInstance().downloadContent(tmd.titleID,ID,tmpPath,progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
32
src/de/mas/jnustool/ContentDownloader.java
Normal file
32
src/de/mas/jnustool/ContentDownloader.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package de.mas.jnustool;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class ContentDownloader implements Callable<Integer>
|
||||||
|
{
|
||||||
|
Content c;
|
||||||
|
Progress progress = null;
|
||||||
|
public void setContent(Content c){
|
||||||
|
this.c = c;
|
||||||
|
}
|
||||||
|
public ContentDownloader(Content f,Progress fatherProgress){
|
||||||
|
setContent(f);
|
||||||
|
createProgress(fatherProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProgress(Progress fatherProgress) {
|
||||||
|
if(fatherProgress != null){
|
||||||
|
progress = new Progress();
|
||||||
|
fatherProgress.add(progress);
|
||||||
|
progress.addTotal(c.size);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() throws Exception {
|
||||||
|
c.download(progress);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,6 +7,7 @@ import java.util.List;
|
|||||||
import de.mas.jnustool.util.Decryption;
|
import de.mas.jnustool.util.Decryption;
|
||||||
import de.mas.jnustool.util.Downloader;
|
import de.mas.jnustool.util.Downloader;
|
||||||
import de.mas.jnustool.util.Settings;
|
import de.mas.jnustool.util.Settings;
|
||||||
|
import de.mas.jnustool.util.Util;
|
||||||
|
|
||||||
public class FEntry {
|
public class FEntry {
|
||||||
private FST fst;
|
private FST fst;
|
||||||
@ -125,28 +126,11 @@ public class FEntry {
|
|||||||
NUScontentID = nUScontentID;
|
NUScontentID = nUScontentID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createFolder() {
|
|
||||||
long titleID = getTitleID();
|
|
||||||
String [] path = getFullPath().split("/");
|
|
||||||
File f = new File (String.format("%016X", titleID));
|
|
||||||
if(!f.exists())f.mkdir();
|
|
||||||
|
|
||||||
String folder = String.format("%016X", titleID) +"/";
|
|
||||||
File folder_ = null;
|
|
||||||
for(int i = 0;i<path.length-1;i++){
|
|
||||||
if(!path[i].equals("")){
|
|
||||||
folder += path[i] + "/";
|
|
||||||
folder_ = new File(folder);
|
|
||||||
if(!folder_.exists()){
|
|
||||||
folder_.mkdir();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
public String getDownloadPath(){
|
public String getDownloadPath(){
|
||||||
|
|
||||||
String [] path = getFullPath().split("/");
|
String [] path = getFullPath().split("/");
|
||||||
String folder = String.format("%016X", getTitleID()) +"/";
|
String folder = getTargetPath() +"/";
|
||||||
for(int i = 0;i<path.length-1;i++){
|
for(int i = 0;i<path.length-1;i++){
|
||||||
if(!path[i].equals("")){
|
if(!path[i].equals("")){
|
||||||
folder += path[i] + "/";
|
folder += path[i] + "/";
|
||||||
@ -156,9 +140,9 @@ public class FEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void downloadAndDecrypt(Progress progress) {
|
public void downloadAndDecrypt(Progress progress) {
|
||||||
createFolder();
|
Util.createSubfolder(fst.getTmd().getNUSTitle().getTargetPath() + getFullPath());
|
||||||
long titleID = getTitleID();
|
|
||||||
File f = new File(String.format("%016X", titleID) +"/" +getFullPath().substring(1, getFullPath().length()));
|
File f = new File(fst.getTmd().getNUSTitle().getTargetPath() + getFullPath());
|
||||||
if(f.exists()){
|
if(f.exists()){
|
||||||
if(f.length() == getFileLength()){
|
if(f.length() == getFileLength()){
|
||||||
Logger.log("Skipping: " + String.format("%8.2f MB ",getFileLength()/1024.0/1024.0) + getFullPath());
|
Logger.log("Skipping: " + String.format("%8.2f MB ",getFileLength()/1024.0/1024.0) + getFullPath());
|
||||||
@ -188,7 +172,9 @@ public class FEntry {
|
|||||||
Logger.log("Ignoring the missing file: " + this.getFileName());
|
Logger.log("Ignoring the missing file: " + this.getFileName());
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
Logger.log("Content missing. Downloading the file from the server: " + this.getFileName());
|
if(fst.getTmd().contents[this.getContentID()].error_output_done.addAndGet(1) == 1){
|
||||||
|
Logger.log("Content " + String.format("%08X",getContentID()) + " missing. Downloading the files from the server");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -202,12 +188,14 @@ public class FEntry {
|
|||||||
Logger.log("Ignoring the missing file: " + this.getFileName());
|
Logger.log("Ignoring the missing file: " + this.getFileName());
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
Logger.log("Content missing. Downloading the file from the server: " + this.getFileName());
|
if(fst.getTmd().contents[this.getContentID()].error_output_done.addAndGet(1) == 1){
|
||||||
|
Logger.log("Content " + String.format("%08X",getContentID()) + " missing. Downloading the files from the server");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Logger.log("Downloading: " + String.format("%8.2f MB ", getFileLength()/1024.0/1024.0) + getFullPath());
|
Logger.log("Downloading: " + String.format("%8.2f MB ", getFileLength()/1024.0/1024.0) + getFullPath());
|
||||||
Downloader.getInstance().downloadAndDecrypt(this,progress);
|
Downloader.getInstance().downloadAndDecrypt(this,progress,false);
|
||||||
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -237,6 +225,14 @@ public class FEntry {
|
|||||||
return fst.getTmd().getNUSTitle().getTicket();
|
return fst.getTmd().getNUSTitle().getTicket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTargetPath(){
|
||||||
|
return fst.getTmd().getNUSTitle().getTargetPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] downloadAsByteArray() throws IOException {
|
||||||
|
return Downloader.getInstance().downloadAndDecrypt(this,null,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,8 +18,9 @@ public class FEntryDownloader implements Callable<Integer>
|
|||||||
private void createProgressListener(Progress fatherProgress) {
|
private void createProgressListener(Progress fatherProgress) {
|
||||||
if(fatherProgress != null){
|
if(fatherProgress != null){
|
||||||
progress = new Progress();
|
progress = new Progress();
|
||||||
progress.setTotal(f.getFileLength());
|
|
||||||
fatherProgress.add(progress);
|
fatherProgress.add(progress);
|
||||||
|
progress.addTotal(f.getFileLength());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,7 +31,6 @@ public class FST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void buildDirectories() {
|
private void buildDirectories() {
|
||||||
|
|
||||||
String contentfolder = "";
|
String contentfolder = "";
|
||||||
Directory curContent = contentDirectory;
|
Directory curContent = contentDirectory;
|
||||||
for(FEntry f : getFileEntries()){
|
for(FEntry f : getFileEntries()){
|
||||||
@ -62,7 +61,6 @@ public class FST {
|
|||||||
curContent.addFile(f);
|
curContent.addFile(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//FST
|
//FST
|
||||||
if(current.containsFolder(s)){
|
if(current.containsFolder(s)){
|
||||||
current = current.get(s);
|
current = current.get(s);
|
||||||
@ -77,13 +75,8 @@ public class FST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void parse(byte[] decrypteddata, TitleMetaData tmd) throws IOException {
|
private void parse(byte[] decrypteddata, TitleMetaData tmd) throws IOException {
|
||||||
|
|
||||||
if(!Arrays.equals(Arrays.copyOfRange(decrypteddata, 0, 3), new byte[]{0x46,0x53,0x54})){
|
if(!Arrays.equals(Arrays.copyOfRange(decrypteddata, 0, 3), new byte[]{0x46,0x53,0x54})){
|
||||||
@ -122,7 +115,6 @@ public class FST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int offset = base_offset + i*0x10;
|
int offset = base_offset + i*0x10;
|
||||||
|
|
||||||
//getting the type
|
//getting the type
|
||||||
@ -218,23 +210,18 @@ public class FST {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public long getTotalContentSize() {
|
public long getTotalContentSize() {
|
||||||
return totalContentSize;
|
return totalContentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTotalContentSize(long totalContentSize) {
|
public void setTotalContentSize(long totalContentSize) {
|
||||||
this.totalContentSize = totalContentSize;
|
this.totalContentSize = totalContentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getTotalContentSizeInNUS() {
|
public long getTotalContentSizeInNUS() {
|
||||||
return totalContentSizeInNUS;
|
return totalContentSizeInNUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTotalContentSizeInNUS(long totalContentSizeInNUS) {
|
public void setTotalContentSizeInNUS(long totalContentSizeInNUS) {
|
||||||
this.totalContentSizeInNUS = totalContentSizeInNUS;
|
this.totalContentSizeInNUS = totalContentSizeInNUS;
|
||||||
}
|
}
|
||||||
@ -243,37 +230,30 @@ public class FST {
|
|||||||
return metaFolder;
|
return metaFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<FEntry> getFileEntries() {
|
public List<FEntry> getFileEntries() {
|
||||||
return fileEntries;
|
return fileEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setFileEntries(List<FEntry> fileEntries) {
|
public void setFileEntries(List<FEntry> fileEntries) {
|
||||||
this.fileEntries = fileEntries;
|
this.fileEntries = fileEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getTotalContentCount() {
|
public int getTotalContentCount() {
|
||||||
return totalContentCount;
|
return totalContentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTotalContentCount(int totalContentCount) {
|
public void setTotalContentCount(int totalContentCount) {
|
||||||
this.totalContentCount = totalContentCount;
|
this.totalContentCount = totalContentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getTotalEntries() {
|
public int getTotalEntries() {
|
||||||
return totalEntries;
|
return totalEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTotalEntries(int totalEntries) {
|
public void setTotalEntries(int totalEntries) {
|
||||||
this.totalEntries = totalEntries;
|
this.totalEntries = totalEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getDirEntries() {
|
public int getDirEntries() {
|
||||||
return dirEntries;
|
return dirEntries;
|
||||||
}
|
}
|
||||||
@ -283,13 +263,11 @@ public class FST {
|
|||||||
this.dirEntries = dirEntries;
|
this.dirEntries = dirEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "entryCount: " + totalContentCount+ " entries: " + totalEntries;
|
return "entryCount: " + totalContentCount+ " entries: " + totalEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getFileCount() {
|
public int getFileCount() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(FEntry f: getFileEntries()){
|
for(FEntry f: getFileEntries()){
|
||||||
@ -316,8 +294,6 @@ public class FST {
|
|||||||
return contentDirectory;
|
return contentDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public TitleMetaData getTmd() {
|
public TitleMetaData getTmd() {
|
||||||
return tmd;
|
return tmd;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ public class Logger {
|
|||||||
public static void log(String string) {
|
public static void log(String string) {
|
||||||
NUSGUI.output.append(string + "\n");
|
NUSGUI.output.append(string + "\n");
|
||||||
NUSGUI.output.setCaretPosition(NUSGUI.output.getDocument().getLength());
|
NUSGUI.output.setCaretPosition(NUSGUI.output.getDocument().getLength());
|
||||||
//System.out.println(string);
|
System.out.println(string);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package de.mas.jnustool;
|
package de.mas.jnustool;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@ -9,18 +12,39 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import de.mas.jnustool.util.Decryption;
|
import de.mas.jnustool.util.Decryption;
|
||||||
import de.mas.jnustool.util.Downloader;
|
import de.mas.jnustool.util.Downloader;
|
||||||
|
import de.mas.jnustool.util.NUSTitleInformation;
|
||||||
import de.mas.jnustool.util.Settings;
|
import de.mas.jnustool.util.Settings;
|
||||||
|
import de.mas.jnustool.util.Util;
|
||||||
|
|
||||||
public class NUSTitle {
|
public class NUSTitle {
|
||||||
private TitleMetaData tmd;
|
private TitleMetaData tmd;
|
||||||
private TIK ticket;
|
private TIK ticket;
|
||||||
private FST fst;
|
private FST fst;
|
||||||
private long titleID;
|
private long titleID;
|
||||||
public NUSTitle(long titleId,String key) {
|
private String targetPath = new String();
|
||||||
|
private String longNameFolder = new String();
|
||||||
|
private int version = -1;
|
||||||
|
|
||||||
|
private String getTMDName(){
|
||||||
|
String result = "title.tmd";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NUSTitle(long titleId,int version, String key) {
|
||||||
|
setVersion(version);
|
||||||
setTitleID(titleId);
|
setTitleID(titleId);
|
||||||
try {
|
try {
|
||||||
|
/*
|
||||||
if(Settings.downloadContent){
|
if(Settings.downloadContent){
|
||||||
File f = new File(getContentPath());
|
File f = new File(getContentPath());
|
||||||
if(!f.exists())f.mkdir();
|
if(!f.exists())f.mkdir();
|
||||||
@ -28,26 +52,27 @@ public class NUSTitle {
|
|||||||
|
|
||||||
if(Settings.downloadContent){
|
if(Settings.downloadContent){
|
||||||
|
|
||||||
File f = new File(getContentPath() + "/" + "tmd");
|
File f = new File(getContentPath() + "/" + getTMDName());
|
||||||
if(!(f.exists() && Settings.skipExistingTMDTICKET)){
|
if(!(f.exists() && Settings.skipExistingTMDTICKET)){
|
||||||
Logger.log("Downloading TMD");
|
Logger.log("Downloading TMD");
|
||||||
Downloader.getInstance().downloadTMD(titleId,getContentPath());
|
Downloader.getInstance().downloadTMD(titleId,getContentPath());
|
||||||
}else{
|
}else{
|
||||||
Logger.log("Skipped download of TMD. Already existing");
|
Logger.log("Skipped download of TMD. Already existing");
|
||||||
}
|
}
|
||||||
|
|
||||||
f = new File(getContentPath() + "/" + "cetk");
|
f = new File(getContentPath() + "/" + "cetk");
|
||||||
if(!(f.exists() && Settings.skipExistingTMDTICKET)){
|
if(!(f.exists() && Settings.skipExistingTMDTICKET)){
|
||||||
if(key == null){
|
if(key == null){
|
||||||
System.out.print("Downloading Ticket");
|
Logger.log("Downloading Ticket");
|
||||||
Downloader.getInstance().downloadTicket(titleId,getContentPath());
|
Downloader.getInstance().downloadTicket(titleId,getContentPath());
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
Logger.log("Skipped download of ticket. Already existing");
|
Logger.log("Skipped download of ticket. Already existing");
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if(Settings.useCachedFiles){
|
if(Settings.useCachedFiles){
|
||||||
File f = new File(getContentPath() + "/" + "tmd");
|
File f = new File(getContentPath() + "/" + getTMDName());
|
||||||
if(f.exists()){
|
if(f.exists()){
|
||||||
Logger.log("Using cached TMD.");
|
Logger.log("Using cached TMD.");
|
||||||
tmd = new TitleMetaData(f);
|
tmd = new TitleMetaData(f);
|
||||||
@ -58,7 +83,7 @@ public class NUSTitle {
|
|||||||
if(tmd == null){
|
if(tmd == null){
|
||||||
if(Settings.downloadWhenCachedFilesMissingOrBroken){
|
if(Settings.downloadWhenCachedFilesMissingOrBroken){
|
||||||
if(Settings.useCachedFiles) Logger.log("Getting missing tmd from Server!");
|
if(Settings.useCachedFiles) Logger.log("Getting missing tmd from Server!");
|
||||||
tmd = new TitleMetaData(Downloader.getInstance().downloadTMDToByteArray(titleId));
|
tmd = new TitleMetaData(Downloader.getInstance().downloadTMDToByteArray(titleId,this.version));
|
||||||
}else{
|
}else{
|
||||||
Logger.log("Downloading of missing files is not enabled. Exiting");
|
Logger.log("Downloading of missing files is not enabled. Exiting");
|
||||||
System.exit(2);
|
System.exit(2);
|
||||||
@ -69,7 +94,7 @@ public class NUSTitle {
|
|||||||
ticket = new TIK(key,titleId);
|
ticket = new TIK(key,titleId);
|
||||||
}else{
|
}else{
|
||||||
if(Settings.useCachedFiles){
|
if(Settings.useCachedFiles){
|
||||||
File f = new File(getContentPath() + "/" + "cetk");
|
File f = new File(getContentPath() + "/" + "title.tik");
|
||||||
if(f.exists()){
|
if(f.exists()){
|
||||||
Logger.log("Using cached cetk.");
|
Logger.log("Using cached cetk.");
|
||||||
ticket = new TIK(f,titleId);
|
ticket = new TIK(f,titleId);
|
||||||
@ -88,16 +113,16 @@ public class NUSTitle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Settings.downloadContent){
|
/*if(Settings.downloadContent){
|
||||||
File f = new File(getContentPath() + "/" + String.format("%08x", tmd.contents[0].ID) + ".app");
|
File f = new File(getContentPath() + "/" + String.format("%08x", tmd.contents[0].ID) + ".app");
|
||||||
if(!(f.exists() && Settings.skipExistingFiles)){
|
if(!(f.exists() && Settings.skipExistingFiles)){
|
||||||
Logger.log("Downloading FST (" + String.format("%08x", tmd.contents[0].ID) + ")");
|
Logger.log("Downloading FST (" + String.format("%08x", tmd.contents[0].ID) + ")");
|
||||||
Downloader.getInstance().downloadContent(titleId,tmd.contents[0].ID,getContentPath());
|
Downloader.getInstance().downloadContent(titleId,tmd.contents[0].ID,getContentPath(),null);
|
||||||
}else{
|
}else{
|
||||||
if(f.length() != tmd.contents[0].size){
|
if(f.length() != tmd.contents[0].size){
|
||||||
if(Settings.downloadWhenCachedFilesMissingOrBroken){
|
if(Settings.downloadWhenCachedFilesMissingOrBroken){
|
||||||
Logger.log("FST already existing, but broken. Downloading it again.");
|
Logger.log("FST already existing, but broken. Downloading it again.");
|
||||||
Downloader.getInstance().downloadContent(titleId,tmd.contents[0].ID,getContentPath());
|
Downloader.getInstance().downloadContent(titleId,tmd.contents[0].ID,getContentPath(),null);
|
||||||
}else{
|
}else{
|
||||||
Logger.log("FST already existing, but broken. No download allowed.");
|
Logger.log("FST already existing, but broken. No download allowed.");
|
||||||
System.exit(2);
|
System.exit(2);
|
||||||
@ -105,10 +130,8 @@ public class NUSTitle {
|
|||||||
}else{
|
}else{
|
||||||
Logger.log("Skipped download of FST. Already existing");
|
Logger.log("Skipped download of FST. Already existing");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
Decryption decryption = new Decryption(ticket.getDecryptedKey(),0);
|
Decryption decryption = new Decryption(ticket.getDecryptedKey(),0);
|
||||||
@ -140,16 +163,33 @@ public class NUSTitle {
|
|||||||
byte[] decryptedFST = decryption.decrypt(encryptedFST);
|
byte[] decryptedFST = decryption.decrypt(encryptedFST);
|
||||||
|
|
||||||
fst = new FST(decryptedFST,tmd);
|
fst = new FST(decryptedFST,tmd);
|
||||||
|
|
||||||
tmd.setNUSTitle(this);
|
tmd.setNUSTitle(this);
|
||||||
|
|
||||||
|
setTargetPath(String.format("%016X", getTitleID()));
|
||||||
|
|
||||||
|
setLongNameFolder(String.format("%016X", getTitleID()));
|
||||||
|
|
||||||
|
if(tmd.isUpdate()){
|
||||||
|
byte[] metaxml = fst.metaFENtry.downloadAsByteArray();
|
||||||
|
if(metaxml != null){
|
||||||
|
InputStream bis = new ByteArrayInputStream(metaxml);
|
||||||
|
NUSTitleInformation nusinfo = readMeta(bis);
|
||||||
|
String folder = nusinfo.getLongnameEN() + " [" + nusinfo.getID6() + "]";
|
||||||
|
String subfolder = "/" + "updates" + "/" + "v" + tmd.titleVersion;
|
||||||
|
setTargetPath(folder + subfolder);
|
||||||
|
setLongNameFolder(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(Settings.downloadContent){
|
if(Settings.downloadContent){
|
||||||
tmd.downloadContents();
|
downloadEncryptedFiles(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.log("Total Size of Content Files: " + ((int)((getTotalContentSize()/1024.0/1024.0)*100))/100.0 +" MB");
|
Logger.log("Total Size of Content Files: " + ((int)((getTotalContentSize()/1024.0/1024.0)*100))/100.0 +" MB");
|
||||||
Logger.log("Total Size of Decrypted Files: " + ((int)((fst.getTotalContentSizeInNUS()/1024.0/1024.0)*100))/100.0 +" MB");
|
Logger.log("Total Size of Decrypted Files: " + ((int)((fst.getTotalContentSizeInNUS()/1024.0/1024.0)*100))/100.0 +" MB");
|
||||||
Logger.log("Entries: " + fst.getTotalEntries());
|
Logger.log("Entries: " + fst.getTotalEntries());
|
||||||
Logger.log("Entries: " + fst.getFileCount());
|
Logger.log("Files: " + fst.getFileCount());
|
||||||
Logger.log("Files in NUSTitle: " + fst.getFileCountInNUS());
|
Logger.log("Files in NUSTitle: " + fst.getFileCountInNUS());
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -158,10 +198,51 @@ public class NUSTitle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void downloadEncryptedFiles(Progress progress) throws IOException {
|
||||||
|
Util.createSubfolder(getContentPath());
|
||||||
|
|
||||||
|
Downloader.getInstance().downloadTMD(titleID,version,getContentPath());
|
||||||
|
Downloader.getInstance().downloadTicket(titleID,getContentPath());
|
||||||
|
|
||||||
|
tmd.downloadContents(progress);
|
||||||
|
|
||||||
|
FileOutputStream fos = new FileOutputStream(getContentPath() +"/title.cert");
|
||||||
|
fos.write(ticket.cert0);
|
||||||
|
fos.write(tmd.cert);
|
||||||
|
fos.write(ticket.cert1);
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
NUSTitleInformation readMeta(InputStream bis) {
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder builder;
|
||||||
|
|
||||||
|
String ID6 = null;
|
||||||
|
try {
|
||||||
|
builder = factory.newDocumentBuilder();
|
||||||
|
Document document = builder.parse(bis);
|
||||||
|
String proc = document.getElementsByTagName("product_code").item(0).getTextContent().toString();
|
||||||
|
String comp = document.getElementsByTagName("company_code").item(0).getTextContent().toString();
|
||||||
|
String title_id = document.getElementsByTagName("title_id").item(0).getTextContent().toString();
|
||||||
|
|
||||||
|
String longname = document.getElementsByTagName("longname_en").item(0).getTextContent().toString();
|
||||||
|
longname = longname.replace("\n", " ");
|
||||||
|
String id = proc.substring(proc.length()-4, proc.length());
|
||||||
|
comp = comp.substring(comp.length()-2, comp.length());
|
||||||
|
ID6 = id+comp;
|
||||||
|
String company_code = document.getElementsByTagName("company_code").item(0).getTextContent().toString();
|
||||||
|
String content_platform = document.getElementsByTagName("content_platform").item(0).getTextContent().toString();
|
||||||
|
String region = document.getElementsByTagName("region").item(0).getTextContent().toString();
|
||||||
|
NUSTitleInformation nusinfo = new NUSTitleInformation(Util.StringToLong(title_id),longname,ID6,proc,content_platform,company_code,Integer.parseInt(region),new String[1]);
|
||||||
|
return nusinfo;
|
||||||
|
|
||||||
|
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public FST getFst() {
|
public FST getFst() {
|
||||||
return fst;
|
return fst;
|
||||||
@ -171,7 +252,6 @@ public class NUSTitle {
|
|||||||
this.fst = fst;
|
this.fst = fst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TitleMetaData getTmd() {
|
public TitleMetaData getTmd() {
|
||||||
return tmd;
|
return tmd;
|
||||||
}
|
}
|
||||||
@ -184,8 +264,6 @@ public class NUSTitle {
|
|||||||
return ticket;
|
return ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void setTicket(TIK ticket) {
|
public void setTicket(TIK ticket) {
|
||||||
this.ticket = ticket;
|
this.ticket = ticket;
|
||||||
}
|
}
|
||||||
@ -194,18 +272,18 @@ public class NUSTitle {
|
|||||||
return tmd.getTotalContentSize();
|
return tmd.getTotalContentSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getContentPath() {
|
public String getContentPath() {
|
||||||
return getContentPathPrefix() + String.format("%016X", getTitleID());
|
String result = getContentPathPrefix() + String.format("%016X", getTitleID());
|
||||||
|
if(version > 0){
|
||||||
|
result += "_v" + version;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContentPathPrefix() {
|
public String getContentPathPrefix() {
|
||||||
return "tmp_";
|
return "tmp_";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public long getTitleID() {
|
public long getTitleID() {
|
||||||
return titleID;
|
return titleID;
|
||||||
}
|
}
|
||||||
@ -215,6 +293,8 @@ public class NUSTitle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void decryptFEntries(List<FEntry> list,Progress progress) {
|
public void decryptFEntries(List<FEntry> list,Progress progress) {
|
||||||
|
Util.createSubfolder(getTargetPath());
|
||||||
|
//progress = null;
|
||||||
ForkJoinPool pool = ForkJoinPool.commonPool();
|
ForkJoinPool pool = ForkJoinPool.commonPool();
|
||||||
List<FEntryDownloader> dlList = new ArrayList<>();
|
List<FEntryDownloader> dlList = new ArrayList<>();
|
||||||
for(FEntry f : list){
|
for(FEntry f : list){
|
||||||
@ -226,6 +306,32 @@ public class NUSTitle {
|
|||||||
Logger.log("Done!");
|
Logger.log("Done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTargetPath(String path){
|
||||||
|
path = path.replaceAll("[:\\\\*?|<>]", "");
|
||||||
|
this.targetPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTargetPath() {
|
||||||
|
return this.targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLongNameFolder() {
|
||||||
|
return longNameFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongNameFolder(String path) {
|
||||||
|
path = path.replaceAll("[:\\\\*?|<>]", "");
|
||||||
|
longNameFolder = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(int version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,42 +2,63 @@ package de.mas.jnustool;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
public class Progress {
|
public class Progress {
|
||||||
private long total;
|
private AtomicLong total = new AtomicLong();
|
||||||
private long current;
|
private AtomicLong current = new AtomicLong();
|
||||||
private ProgressUpdateListener progressUpdateListener = null;
|
private ProgressUpdateListener progressUpdateListener = null;
|
||||||
List<Progress> children = new ArrayList<>();
|
List<Progress> children = new ArrayList<>();
|
||||||
Progress father = null;
|
Progress father = null;
|
||||||
|
private AtomicLong totalChildren = new AtomicLong();
|
||||||
|
private AtomicLong currentChildren = new AtomicLong();
|
||||||
|
|
||||||
|
|
||||||
public long getTotalOfSingle() {
|
public long getTotalOfSingle() {
|
||||||
return total;
|
return total.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTotal(long total) {
|
private void setTotalOfSingle(long total) {
|
||||||
this.total = total;
|
this.total.set(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getCurrentOfSingle() {
|
public long getCurrentOfSingle() {
|
||||||
return current;
|
return current.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrent(long current) {
|
private void setCurrent(long current) {
|
||||||
this.current = current;
|
this.current.set(current);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCurrent(int i) {
|
public void addTotal(long i) {
|
||||||
if(this.current + i > getTotalOfSingle()){
|
setTotalOfSingle(getTotalOfSingle() + i);
|
||||||
setCurrent(getTotalOfSingle());
|
if(father != null) father.addTotalChildren(i);
|
||||||
}else{
|
|
||||||
setCurrent(getCurrent() + i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addCurrentChildren(long i) {
|
||||||
|
if(father != null) father.addCurrentChildren(i);
|
||||||
|
this.currentChildren.addAndGet(i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addTotalChildren(long i) {
|
||||||
|
if(father != null){
|
||||||
|
father.addTotalChildren(i);
|
||||||
|
}
|
||||||
|
this.totalChildren.addAndGet(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCurrent(int i) {
|
||||||
|
if(this.current.get() + i > getTotalOfSingle()){
|
||||||
|
setCurrent(getTotalOfSingle());
|
||||||
|
}else{
|
||||||
|
setCurrent(getCurrentOfSingle() + i);
|
||||||
|
if(father != null) father.addCurrentChildren(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void update() {
|
private void update() {
|
||||||
if(father != null) father.update();
|
if(father != null) father.update();
|
||||||
|
|
||||||
@ -48,36 +69,43 @@ public class Progress {
|
|||||||
|
|
||||||
public void add(Progress progress) {
|
public void add(Progress progress) {
|
||||||
progress.setFather(this);
|
progress.setFather(this);
|
||||||
|
addChildrenTotal(progress.getTotalOfSingle());
|
||||||
children.add(progress);
|
children.add(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addChildrenTotal(long totalOfSingle) {
|
||||||
|
this.totalChildren.addAndGet(totalOfSingle);
|
||||||
|
}
|
||||||
|
|
||||||
private void setFather(Progress progressListener) {
|
private void setFather(Progress progressListener) {
|
||||||
this.father = progressListener;
|
this.father = progressListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getCurrent() {
|
public long getCurrent() {
|
||||||
long tmp = getCurrentOfSingle();
|
return this.currentChildren.get() + this.current.get();
|
||||||
for(Progress p : children){
|
|
||||||
tmp +=p.getCurrent();
|
|
||||||
}
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getTotal() {
|
public long getTotal() {
|
||||||
long tmp = getTotalOfSingle();
|
return this.totalChildren.get() + this.total.get();
|
||||||
for(Progress p : children){
|
|
||||||
tmp +=p.getTotal();
|
|
||||||
}
|
}
|
||||||
return tmp;
|
|
||||||
|
|
||||||
|
public void setTotal(long total) {
|
||||||
|
this.total.set(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setProgressUpdateListener(ProgressUpdateListener progressUpdateListener) {
|
public void setProgressUpdateListener(ProgressUpdateListener progressUpdateListener) {
|
||||||
this.progressUpdateListener = progressUpdateListener;
|
this.progressUpdateListener = progressUpdateListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
setCurrent(0);
|
current.set(0);
|
||||||
setTotal(0);
|
currentChildren.set(0);
|
||||||
|
total.set(0);
|
||||||
|
totalChildren.set(0);
|
||||||
|
father = null;
|
||||||
children = new ArrayList<>();
|
children = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,4 +130,10 @@ public class Progress {
|
|||||||
return inprogress;
|
return inprogress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resetCurrent() {
|
||||||
|
while(getCurrentOfSingle() > 0){
|
||||||
|
addCurrent((int)getCurrentOfSingle() * (-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,11 @@ public class Starter {
|
|||||||
private static String updateCSVPath;
|
private static String updateCSVPath;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Logger.log("JNUSTool 0.0.4 - pre alpha - by Maschell");
|
|
||||||
|
Logger.log("JNUSTool 0.0.5 - alpha - by Maschell");
|
||||||
Logger.log("");
|
Logger.log("");
|
||||||
try {
|
try {
|
||||||
readConfig();
|
readConfig();
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Error while reading config! Needs to be:");
|
System.err.println("Error while reading config! Needs to be:");
|
||||||
System.err.println("DOWNLOAD URL BASE");
|
System.err.println("DOWNLOAD URL BASE");
|
||||||
@ -42,7 +42,7 @@ public class Starter {
|
|||||||
key = args[1].substring(0, 32);
|
key = args[1].substring(0, 32);
|
||||||
}
|
}
|
||||||
if(titleID != 0){
|
if(titleID != 0){
|
||||||
NUSGUI m = new NUSGUI(new NUSTitle(titleID, key));
|
NUSGUI m = new NUSGUI(new NUSTitle(titleID,-1, key));
|
||||||
m.setVisible(true);
|
m.setVisible(true);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -53,16 +53,12 @@ public class Starter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
NUSGUI m = new NUSGUI(new NUSTitle(tID, null));
|
NUSGUI m = new NUSGUI(new NUSTitle(tID,nus.getSelectedVersion(), null));
|
||||||
m.setVisible(true);
|
m.setVisible(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}).start();;
|
}).start();;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -100,9 +96,9 @@ public class Starter {
|
|||||||
String line;
|
String line;
|
||||||
while((line = in.readLine()) != null){
|
while((line = in.readLine()) != null){
|
||||||
String[] infos = line.split(";");
|
String[] infos = line.split(";");
|
||||||
if(infos.length != 7) {
|
if(infos.length != 8) {
|
||||||
Logger.messageBox("Updatelist is broken!");
|
Logger.messageBox("Updatelist is broken!");
|
||||||
System.out.println("Updatelist is broken!");
|
Logger.log("Updatelist is broken!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
long titleID = Util.StringToLong(infos[0].replace("-", ""));
|
long titleID = Util.StringToLong(infos[0].replace("-", ""));
|
||||||
@ -112,7 +108,9 @@ public class Starter {
|
|||||||
String product_code = infos[4];
|
String product_code = infos[4];
|
||||||
String ID6 = infos[5];
|
String ID6 = infos[5];
|
||||||
String longnameEN = infos[6];
|
String longnameEN = infos[6];
|
||||||
NUSTitleInformation info = new NUSTitleInformation(titleID, longnameEN, ID6, product_code, content_platform, company_code, region);
|
String[] versions = infos[7].split(",");
|
||||||
|
NUSTitleInformation info = new NUSTitleInformation(titleID, longnameEN, ID6, product_code, content_platform, company_code, region,versions);
|
||||||
|
|
||||||
list.add(info);
|
list.add(info);
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
@ -122,7 +120,7 @@ public class Starter {
|
|||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
}
|
}
|
||||||
Logger.messageBox("Updatelist is broken or missing");
|
Logger.messageBox("Updatelist is broken or missing");
|
||||||
System.out.println("Updatelist is broken!");
|
Logger.log("Updatelist is broken!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
@ -136,7 +134,7 @@ public class Starter {
|
|||||||
String commonkey = in.readLine();
|
String commonkey = in.readLine();
|
||||||
if(commonkey.length() != 32){
|
if(commonkey.length() != 32){
|
||||||
Logger.messageBox("CommonKey length is wrong");
|
Logger.messageBox("CommonKey length is wrong");
|
||||||
System.out.println("Commonkey length is wrong");
|
Logger.log("Commonkey length is wrong");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
Util.commonKey = Util.hexStringToByteArray(commonkey);
|
Util.commonKey = Util.hexStringToByteArray(commonkey);
|
||||||
@ -145,20 +143,37 @@ public class Starter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean deleteFolder(File element) {
|
||||||
|
if (element.isDirectory()) {
|
||||||
|
for (File sub : element.listFiles()) {
|
||||||
|
if(sub.isFile()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (File sub : element.listFiles()) {
|
||||||
|
if(!deleteFolder(sub)) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
element.delete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static void downloadMeta(List<NUSTitleInformation> output_, Progress totalProgress) {
|
public static void downloadMeta(List<NUSTitleInformation> output_, Progress totalProgress) {
|
||||||
ForkJoinPool pool = ForkJoinPool.commonPool();
|
ForkJoinPool pool = ForkJoinPool.commonPool();
|
||||||
List<ForkJoinTask<Boolean>> list = new ArrayList<>();
|
List<ForkJoinTask<Boolean>> list = new ArrayList<>();
|
||||||
|
|
||||||
for(NUSTitleInformation nus : output_){
|
for(NUSTitleInformation nus : output_){
|
||||||
final long tID = nus.getTitleID();
|
final long tID = nus.getTitleID();
|
||||||
list.add(pool.submit(new Callable<Boolean>(){
|
list.add(pool.submit(new Callable<Boolean>(){
|
||||||
@Override
|
@Override
|
||||||
public Boolean call() throws Exception {
|
public Boolean call() throws Exception {
|
||||||
NUSTitle nus = new NUSTitle(tID, null);
|
NUSTitle nusa = new NUSTitle(tID,nus.getSelectedVersion(),Util.ByteArrayToString(nus.getKey()));
|
||||||
Progress childProgress = new Progress();
|
Progress childProgress = new Progress();
|
||||||
|
|
||||||
totalProgress.add(childProgress);
|
totalProgress.add(childProgress);
|
||||||
nus.decryptFEntries(nus.getFst().getMetaFolder(),childProgress);
|
deleteFolder(new File(nusa.getLongNameFolder() + "/updates"));
|
||||||
|
nusa.setTargetPath(nusa.getLongNameFolder());
|
||||||
|
nusa.decryptFEntries(nusa.getFst().getMetaFolder(),childProgress);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@ -176,4 +191,36 @@ public class Starter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void downloadEncrypted(List<NUSTitleInformation> output_, Progress progress) {
|
||||||
|
ForkJoinPool pool = ForkJoinPool.commonPool();
|
||||||
|
List<ForkJoinTask<Boolean>> list = new ArrayList<>();
|
||||||
|
|
||||||
|
for(NUSTitleInformation nus : output_){
|
||||||
|
final long tID = nus.getTitleID();
|
||||||
|
list.add(pool.submit(new Callable<Boolean>(){
|
||||||
|
@Override
|
||||||
|
public Boolean call() throws Exception {
|
||||||
|
NUSTitle nusa = new NUSTitle(tID,nus.getSelectedVersion(), Util.ByteArrayToString(nus.getKey()));
|
||||||
|
Progress childProgress = new Progress();
|
||||||
|
progress.add(childProgress);
|
||||||
|
nusa.downloadEncryptedFiles(progress);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
for(ForkJoinTask<Boolean> task : list){
|
||||||
|
try {
|
||||||
|
task.get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package de.mas.jnustool;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import de.mas.jnustool.util.Decryption;
|
import de.mas.jnustool.util.Decryption;
|
||||||
import de.mas.jnustool.util.Util;
|
import de.mas.jnustool.util.Util;
|
||||||
@ -12,6 +13,9 @@ public class TIK {
|
|||||||
private byte[] encryptedKey = new byte[16];
|
private byte[] encryptedKey = new byte[16];
|
||||||
private byte[] decryptedKey = new byte[16];
|
private byte[] decryptedKey = new byte[16];
|
||||||
|
|
||||||
|
public byte[] cert0 = new byte[0x400];
|
||||||
|
public byte[] cert1 = new byte[0x300];
|
||||||
|
|
||||||
public TIK(File cetk,long titleid) throws IOException{
|
public TIK(File cetk,long titleid) throws IOException{
|
||||||
parse(cetk);
|
parse(cetk);
|
||||||
calculateDecryptedKey(titleid);
|
calculateDecryptedKey(titleid);
|
||||||
@ -34,13 +38,28 @@ public class TIK {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void parse(byte[] cetk) throws IOException {
|
private void parse(byte[] cetk) throws IOException {
|
||||||
|
if(cetk != null){
|
||||||
System.arraycopy(cetk, 0x1bf, this.encryptedKey, 0,16);
|
System.arraycopy(cetk, 0x1bf, this.encryptedKey, 0,16);
|
||||||
|
if(cetk.length >= 0x650 + 0x400){
|
||||||
|
cert0 = Arrays.copyOfRange(cetk, 0x650, 0x650 + 0x400);
|
||||||
|
cert1 = Arrays.copyOfRange(cetk, 0x350, 0x350 + 0x300);
|
||||||
|
}else{
|
||||||
|
Logger.log("No certs for TIK found. File too short!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parse(File cetk) throws IOException {
|
private void parse(File cetk) throws IOException {
|
||||||
RandomAccessFile f = new RandomAccessFile(cetk, "r");
|
RandomAccessFile f = new RandomAccessFile(cetk, "r");
|
||||||
f.seek(0x1bf);
|
f.seek(0x1bf);
|
||||||
f.read(this.encryptedKey, 0, 16);
|
f.read(this.encryptedKey, 0, 16);
|
||||||
|
|
||||||
|
f.seek(0x650);
|
||||||
|
f.read(cert0, 0, 0x400);
|
||||||
|
f.seek(0x350);
|
||||||
|
f.read(cert1, 0, 0x300);
|
||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +85,9 @@ public class TIK {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "encrypted key: " + Util.ByteArrayToString(encryptedKey)+ " decrypted key: " + Util.ByteArrayToString(decryptedKey);
|
String result = "Encrypted key: " + Util.ByteArrayToString(encryptedKey)+ " Decrypted key: " + Util.ByteArrayToString(decryptedKey) + "\n";
|
||||||
|
result += "cert0:" + Util.ByteArrayToString(cert0) + "\n";
|
||||||
|
result += "cert1:" + Util.ByteArrayToString(cert1) + "\n";
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,10 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
|
||||||
import de.mas.jnustool.util.Downloader;
|
|
||||||
import de.mas.jnustool.util.Settings;
|
|
||||||
import de.mas.jnustool.util.Util;
|
import de.mas.jnustool.util.Util;
|
||||||
|
|
||||||
public class TitleMetaData {
|
public class TitleMetaData {
|
||||||
@ -28,7 +29,7 @@ public class TitleMetaData {
|
|||||||
byte[] SHA2 = new byte[32]; // 0x1E4
|
byte[] SHA2 = new byte[32]; // 0x1E4
|
||||||
ContentInfo[] contentInfos = new ContentInfo[64]; // 0x1E4
|
ContentInfo[] contentInfos = new ContentInfo[64]; // 0x1E4
|
||||||
Content[] contents; // 0x1E4
|
Content[] contents; // 0x1E4
|
||||||
|
byte[] cert = new byte[0x300];
|
||||||
|
|
||||||
private NUSTitle nus;
|
private NUSTitle nus;
|
||||||
|
|
||||||
@ -112,7 +113,11 @@ public class TitleMetaData {
|
|||||||
byte[] buffer = new byte[0x20]; // 16 0xB14
|
byte[] buffer = new byte[0x20]; // 16 0xB14
|
||||||
f.read(buffer,0, 0x20);
|
f.read(buffer,0, 0x20);
|
||||||
|
|
||||||
this.contents[i] = new Content(ID,index,type,size,buffer);
|
this.contents[i] = new Content(ID,index,type,size,buffer,this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(f.read(cert,0, 0x300) != 0x300){
|
||||||
|
Logger.log("Error reading TMD cert");
|
||||||
}
|
}
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
@ -136,6 +141,7 @@ public class TitleMetaData {
|
|||||||
sb.append("contentCount: " + contentCount +"\n");
|
sb.append("contentCount: " + contentCount +"\n");
|
||||||
sb.append("bootIndex: " + bootIndex +"\n");
|
sb.append("bootIndex: " + bootIndex +"\n");
|
||||||
sb.append("SHA2: " + Util.ByteArrayToString(SHA2) +"\n");
|
sb.append("SHA2: " + Util.ByteArrayToString(SHA2) +"\n");
|
||||||
|
sb.append("cert: " + Util.ByteArrayToString(cert) +"\n");
|
||||||
sb.append("contentInfos: \n");
|
sb.append("contentInfos: \n");
|
||||||
for(int i = 0; i<contents.length-1;i++){
|
for(int i = 0; i<contents.length-1;i++){
|
||||||
sb.append(" " + contentInfos[i] +"\n");
|
sb.append(" " + contentInfos[i] +"\n");
|
||||||
@ -157,36 +163,22 @@ public class TitleMetaData {
|
|||||||
return totalContentSize;
|
return totalContentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadContents() throws IOException{
|
public boolean isUpdate() {
|
||||||
|
return (titleID & 0x5000000000000L) == 0x5000000000000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadContents(Progress progress) throws IOException{
|
||||||
String tmpPath = getContentPath();
|
String tmpPath = getContentPath();
|
||||||
File f = new File(tmpPath);
|
File f = new File(tmpPath);
|
||||||
if(!f.exists())f.mkdir();
|
if(!f.exists())f.mkdir();
|
||||||
|
|
||||||
|
ForkJoinPool pool = ForkJoinPool.commonPool();
|
||||||
|
List<ContentDownloader> dlList = new ArrayList<>();
|
||||||
for(Content c : contents){
|
for(Content c : contents){
|
||||||
if(c != contents[0]){
|
dlList.add(new ContentDownloader(c,progress));
|
||||||
f = new File(tmpPath + "/" + String.format("%08X", c.ID ) + ".app");
|
|
||||||
if(f.exists()){
|
|
||||||
if(f.length() == c.size){
|
|
||||||
Logger.log("Skipping Content: " + String.format("%08X", c.ID));
|
|
||||||
}else{
|
|
||||||
if(Settings.downloadWhenCachedFilesMissingOrBroken){
|
|
||||||
Logger.log("Content " +String.format("%08X", c.ID) + " is broken. Downloading it again.");
|
|
||||||
Downloader.getInstance().downloadContent(titleID,c.ID,tmpPath);
|
|
||||||
}else{
|
|
||||||
if(Settings.skipBrokenFiles){
|
|
||||||
Logger.log("Content " +String.format("%08X", c.ID) + " is broken. Ignoring it.");
|
|
||||||
}else{
|
|
||||||
Logger.log("Content " +String.format("%08X", c.ID) + " is broken. Downloading not allowed.");
|
|
||||||
System.exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
Logger.log("Download Content: " + String.format("%08X", c.ID));
|
|
||||||
Downloader.getInstance().downloadContent(titleID,c.ID,tmpPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pool.invokeAll(dlList);
|
||||||
|
Logger.log("Done!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import java.util.List;
|
|||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JProgressBar;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
@ -22,8 +23,6 @@ import de.mas.jnustool.NUSTitle;
|
|||||||
import de.mas.jnustool.Progress;
|
import de.mas.jnustool.Progress;
|
||||||
import de.mas.jnustool.ProgressUpdateListener;
|
import de.mas.jnustool.ProgressUpdateListener;
|
||||||
|
|
||||||
import javax.swing.JProgressBar;
|
|
||||||
|
|
||||||
public class NUSGUI extends JFrame {
|
public class NUSGUI extends JFrame {
|
||||||
|
|
||||||
private static final long serialVersionUID = 4648172894076113183L;
|
private static final long serialVersionUID = 4648172894076113183L;
|
||||||
|
@ -1,31 +1,42 @@
|
|||||||
package de.mas.jnustool.gui;
|
package de.mas.jnustool.gui;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.ItemListener;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.EventObject;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.DefaultCellEditor;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JProgressBar;
|
import javax.swing.JProgressBar;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
|
import javax.swing.JTextField;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.ScrollPaneConstants;
|
import javax.swing.ScrollPaneConstants;
|
||||||
|
import javax.swing.event.CellEditorListener;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import javax.swing.table.TableCellEditor;
|
||||||
|
|
||||||
import de.mas.jnustool.Logger;
|
import de.mas.jnustool.Logger;
|
||||||
import de.mas.jnustool.Progress;
|
import de.mas.jnustool.Progress;
|
||||||
@ -45,19 +56,34 @@ public class UpdateChooser extends JPanel {
|
|||||||
ListSelectionModel listSelectionModel;
|
ListSelectionModel listSelectionModel;
|
||||||
public UpdateChooser(JFrame window) {
|
public UpdateChooser(JFrame window) {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
setSize(800, 600);
|
setSize(800, 650);
|
||||||
|
|
||||||
Collections.sort(list_);
|
Collections.sort(list_);
|
||||||
|
|
||||||
output_.add(list_.get(0));
|
output_.add(list_.get(0));
|
||||||
String[] columnNames = { "TitleID", "Region", "Name" };
|
String[] columnNames = { "TitleID", "Region", "Name","version"};
|
||||||
String[][] tableData = new String[list_.size()][];
|
String[][] tableData = new String[list_.size()][];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
HashMap<Integer,JComboBox<String>> comboboxes = new HashMap<>();
|
||||||
for(NUSTitleInformation n: list_){
|
for(NUSTitleInformation n: list_){
|
||||||
tableData[i] = new String[3];
|
tableData[i] = new String[4];
|
||||||
tableData[i][0] = n.getTitleIDAsString();
|
tableData[i][0] = n.getTitleIDAsString();
|
||||||
tableData[i][1] = n.getRegionAsRegion().toString();
|
tableData[i][1] = n.getRegionAsRegion().toString();
|
||||||
tableData[i][2] = n.getLongnameEN();
|
tableData[i][2] = n.getLongnameEN();
|
||||||
|
tableData[i][3] = n.getLatestVersion();
|
||||||
|
|
||||||
|
JComboBox<String> comboBox = new JComboBox<>();
|
||||||
|
for(String v : n.getAllVersions()){
|
||||||
|
comboBox.addItem(v);
|
||||||
|
}
|
||||||
|
final int position = i;
|
||||||
|
comboBox.addItemListener(new ItemListener() {
|
||||||
|
public void itemStateChanged(ItemEvent e) {
|
||||||
|
list_.get(position).setSelectedVersion((String) e.getItem());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
comboboxes.put(i,comboBox);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +91,16 @@ public class UpdateChooser extends JPanel {
|
|||||||
table = new JTable(tableData, columnNames);
|
table = new JTable(tableData, columnNames);
|
||||||
|
|
||||||
|
|
||||||
|
EachRowEditor rowEditor = new EachRowEditor(table);
|
||||||
|
|
||||||
|
for (Entry<Integer, JComboBox<String>> entry : comboboxes.entrySet())
|
||||||
|
{
|
||||||
|
rowEditor.setEditorAt(entry.getKey(), new DefaultCellEditor(entry.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.getColumn("version").setCellEditor(rowEditor);
|
||||||
|
|
||||||
|
|
||||||
//table.setModel(tableModel);
|
//table.setModel(tableModel);
|
||||||
for (int c = 0; c < table.getColumnCount(); c++)
|
for (int c = 0; c < table.getColumnCount(); c++)
|
||||||
@ -85,16 +121,7 @@ public class UpdateChooser extends JPanel {
|
|||||||
|
|
||||||
table.setSelectionModel(listSelectionModel);
|
table.setSelectionModel(listSelectionModel);
|
||||||
|
|
||||||
table.addMouseListener(new MouseAdapter() {
|
|
||||||
public void mousePressed(MouseEvent me) {
|
|
||||||
if (me.getClickCount() == 2) {
|
|
||||||
synchronized (output_) {
|
|
||||||
window.setVisible(false);
|
|
||||||
output_.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
JScrollPane tablePane = new JScrollPane(table);
|
JScrollPane tablePane = new JScrollPane(table);
|
||||||
//Build control area (use default FlowLayout).
|
//Build control area (use default FlowLayout).
|
||||||
@ -141,6 +168,7 @@ public class UpdateChooser extends JPanel {
|
|||||||
progressBar.setStringPainted(true);
|
progressBar.setStringPainted(true);
|
||||||
|
|
||||||
JButton btnDownloadMeta = new JButton("Download META");
|
JButton btnDownloadMeta = new JButton("Download META");
|
||||||
|
JButton btnDownloadEncrypted = new JButton("Download Enctrypted");
|
||||||
JProgressBar progressBar_1 = new JProgressBar();
|
JProgressBar progressBar_1 = new JProgressBar();
|
||||||
panel.add(progressBar_1);
|
panel.add(progressBar_1);
|
||||||
progressBar_1.setValue(0);
|
progressBar_1.setValue(0);
|
||||||
@ -153,6 +181,7 @@ public class UpdateChooser extends JPanel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
btnDownloadMeta.addActionListener(new ActionListener() {
|
btnDownloadMeta.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if(!progress.isInProgress()){
|
if(!progress.isInProgress()){
|
||||||
@ -161,6 +190,8 @@ public class UpdateChooser extends JPanel {
|
|||||||
new Thread(new Runnable(){
|
new Thread(new Runnable(){
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
progressBar_1.setValue(0);
|
||||||
|
progress.clear();
|
||||||
Starter.downloadMeta(output_,progress);
|
Starter.downloadMeta(output_,progress);
|
||||||
progress.operationFinish();
|
progress.operationFinish();
|
||||||
Logger.messageBox("Finished");
|
Logger.messageBox("Finished");
|
||||||
@ -175,14 +206,53 @@ public class UpdateChooser extends JPanel {
|
|||||||
});
|
});
|
||||||
panel.add(btnDownloadMeta);
|
panel.add(btnDownloadMeta);
|
||||||
|
|
||||||
|
btnDownloadEncrypted.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if(!progress.isInProgress()){
|
||||||
|
progress.clear();
|
||||||
|
progress.operationStart();
|
||||||
|
new Thread(new Runnable(){
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
progressBar_1.setValue(0);
|
||||||
|
progress.clear();
|
||||||
|
Starter.downloadEncrypted(output_,progress);
|
||||||
|
progress.operationFinish();
|
||||||
|
Logger.messageBox("Finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
}else{
|
||||||
|
Logger.messageBox("Operation still in progress, please wait");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
panel.add(btnDownloadEncrypted);
|
||||||
|
|
||||||
|
|
||||||
btnNewButton.addActionListener(new ActionListener() {
|
btnNewButton.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if(!progress.isInProgress()){
|
||||||
synchronized (output_) {
|
synchronized (output_) {
|
||||||
window.setVisible(false);
|
window.setVisible(false);
|
||||||
output_.notifyAll();
|
output_.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
table.addMouseListener(new MouseAdapter() {
|
||||||
|
public void mousePressed(MouseEvent me) {
|
||||||
|
if(!progress.isInProgress()){
|
||||||
|
if (me.getClickCount() == 2) {
|
||||||
|
synchronized (output_) {
|
||||||
|
window.setVisible(false);
|
||||||
|
output_.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
JPanel bottomHalf = new JPanel(new BorderLayout());
|
JPanel bottomHalf = new JPanel(new BorderLayout());
|
||||||
@ -206,7 +276,7 @@ public class UpdateChooser extends JPanel {
|
|||||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
|
||||||
//Display the window.
|
//Display the window.
|
||||||
frame.setSize(610, 600);
|
frame.setSize(672, 600);
|
||||||
|
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
@ -235,4 +305,93 @@ public class UpdateChooser extends JPanel {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* each row TableCellEditor
|
||||||
|
*
|
||||||
|
* @version 1.1 09/09/99
|
||||||
|
* @author Nobuo Tamemasa
|
||||||
|
*/
|
||||||
|
|
||||||
|
class EachRowEditor implements TableCellEditor {
|
||||||
|
protected Hashtable editors;
|
||||||
|
|
||||||
|
protected TableCellEditor editor, defaultEditor;
|
||||||
|
|
||||||
|
JTable table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a EachRowEditor. create default editor
|
||||||
|
*
|
||||||
|
* @see TableCellEditor
|
||||||
|
* @see DefaultCellEditor
|
||||||
|
*/
|
||||||
|
public EachRowEditor(JTable table) {
|
||||||
|
this.table = table;
|
||||||
|
editors = new Hashtable();
|
||||||
|
defaultEditor = new DefaultCellEditor(new JTextField());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param row
|
||||||
|
* table row
|
||||||
|
* @param editor
|
||||||
|
* table cell editor
|
||||||
|
*/
|
||||||
|
public void setEditorAt(int row, TableCellEditor editor) {
|
||||||
|
editors.put(new Integer(row), editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value,
|
||||||
|
boolean isSelected, int row, int column) {
|
||||||
|
//editor = (TableCellEditor)editors.get(new Integer(row));
|
||||||
|
//if (editor == null) {
|
||||||
|
// editor = defaultEditor;
|
||||||
|
//}
|
||||||
|
return editor.getTableCellEditorComponent(table, value, isSelected,
|
||||||
|
row, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getCellEditorValue() {
|
||||||
|
return editor.getCellEditorValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean stopCellEditing() {
|
||||||
|
return editor.stopCellEditing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelCellEditing() {
|
||||||
|
editor.cancelCellEditing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(EventObject anEvent) {
|
||||||
|
selectEditor((MouseEvent) anEvent);
|
||||||
|
return editor.isCellEditable(anEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCellEditorListener(CellEditorListener l) {
|
||||||
|
editor.addCellEditorListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCellEditorListener(CellEditorListener l) {
|
||||||
|
editor.removeCellEditorListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSelectCell(EventObject anEvent) {
|
||||||
|
selectEditor((MouseEvent) anEvent);
|
||||||
|
return editor.shouldSelectCell(anEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void selectEditor(MouseEvent e) {
|
||||||
|
int row;
|
||||||
|
if (e == null) {
|
||||||
|
row = table.getSelectionModel().getAnchorSelectionIndex();
|
||||||
|
} else {
|
||||||
|
row = table.rowAtPoint(e.getPoint());
|
||||||
|
}
|
||||||
|
editor = (TableCellEditor) editors.get(new Integer(row));
|
||||||
|
if (editor == null) {
|
||||||
|
editor = defaultEditor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ public class Decryption {
|
|||||||
ByteArrayBuffer overflow = new ByteArrayBuffer(BLOCKSIZE);
|
ByteArrayBuffer overflow = new ByteArrayBuffer(BLOCKSIZE);
|
||||||
if(progressListener != null){
|
if(progressListener != null){
|
||||||
progressListener.setTotal(toDownload.getFileLength());
|
progressListener.setTotal(toDownload.getFileLength());
|
||||||
progressListener.setCurrent(0);
|
progressListener.resetCurrent();
|
||||||
}
|
}
|
||||||
do{
|
do{
|
||||||
inBlockBuffer = getChunkFromStream(inputStream,blockBuffer,overflow,BLOCKSIZE);
|
inBlockBuffer = getChunkFromStream(inputStream,blockBuffer,overflow,BLOCKSIZE);
|
||||||
@ -219,7 +219,7 @@ public class Decryption {
|
|||||||
|
|
||||||
if(progressListener != null){
|
if(progressListener != null){
|
||||||
progressListener.setTotal(toDownload.getFileLength()/HASHBLOCKSIZE*BLOCKSIZE);
|
progressListener.setTotal(toDownload.getFileLength()/HASHBLOCKSIZE*BLOCKSIZE);
|
||||||
progressListener.setCurrent(0);
|
progressListener.resetCurrent();
|
||||||
}
|
}
|
||||||
do{
|
do{
|
||||||
inBlockBuffer = getChunkFromStream(inputStream,encryptedBlockBuffer,overflow,BLOCKSIZE);
|
inBlockBuffer = getChunkFromStream(inputStream,encryptedBlockBuffer,overflow,BLOCKSIZE);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package de.mas.jnustool.util;
|
package de.mas.jnustool.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
@ -23,7 +25,7 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void downloadAndDecrypt(FEntry toDownload, Progress progressOfFile) throws IOException{
|
public byte[] downloadAndDecrypt(FEntry toDownload, Progress progressOfFile, boolean asByteArray) throws IOException{
|
||||||
String URL = URL_BASE + "/" + String.format("%016X", toDownload.getTitleID()) + "/" + String.format("%08X", toDownload.getNUScontentID());
|
String URL = URL_BASE + "/" + String.format("%016X", toDownload.getTitleID()) + "/" + String.format("%08X", toDownload.getNUScontentID());
|
||||||
URL url = new URL(URL);
|
URL url = new URL(URL);
|
||||||
String [] path = toDownload.getFullPath().split("/");
|
String [] path = toDownload.getFullPath().split("/");
|
||||||
@ -38,36 +40,50 @@ public class Downloader {
|
|||||||
int BLOCKSIZE = 0x10000;
|
int BLOCKSIZE = 0x10000;
|
||||||
int HASHBLOCKSIZE = 0xFC00;
|
int HASHBLOCKSIZE = 0xFC00;
|
||||||
fileOffset = ((toDownload.getFileOffset() / HASHBLOCKSIZE) * BLOCKSIZE);
|
fileOffset = ((toDownload.getFileOffset() / HASHBLOCKSIZE) * BLOCKSIZE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.setRequestProperty("Range", "bytes=" + fileOffset +"-");
|
connection.setRequestProperty("Range", "bytes=" + fileOffset +"-");
|
||||||
|
try{
|
||||||
connection.connect();
|
connection.connect();
|
||||||
|
}catch(Exception e){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Decryption decryption = new Decryption(toDownload.getTicket());
|
Decryption decryption = new Decryption(toDownload.getTicket());
|
||||||
decryption.setProgressListener(progressOfFile);
|
decryption.setProgressListener(progressOfFile);
|
||||||
InputStream input = connection.getInputStream();
|
InputStream input = connection.getInputStream();
|
||||||
FileOutputStream outputStream = new FileOutputStream(String.format("%016X", toDownload.getTitleID()) +"/" + toDownload.getFullPath().substring(1, toDownload.getFullPath().length()));
|
OutputStream outputStream;
|
||||||
|
|
||||||
|
if(!asByteArray){
|
||||||
|
outputStream = new FileOutputStream(toDownload.getTargetPath() +"/" + toDownload.getFullPath().substring(1, toDownload.getFullPath().length()));
|
||||||
|
}else{
|
||||||
|
outputStream = new ByteArrayOutputStream((int) toDownload.getFileLength());
|
||||||
|
}
|
||||||
|
|
||||||
if(!decryptWithHash){
|
if(!decryptWithHash){
|
||||||
decryption.decryptFile(input, outputStream, toDownload);
|
decryption.decryptFile(input, outputStream, toDownload);
|
||||||
}else{
|
}else{
|
||||||
decryption.decryptFileHash(input, outputStream, toDownload);
|
decryption.decryptFileHash(input, outputStream, toDownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.disconnect();
|
connection.disconnect();
|
||||||
|
if(asByteArray){
|
||||||
|
return ((ByteArrayOutputStream)outputStream).toByteArray();
|
||||||
|
}else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String URL_BASE = "";
|
public static String URL_BASE = "";
|
||||||
|
|
||||||
public void downloadTMD(long titleID,int version,String path) throws IOException {
|
public void downloadTMD(long titleID,int version,String path) throws IOException {
|
||||||
downloadTMD(titleID,path);
|
String version_suf = "";
|
||||||
|
if(version > 0) version_suf = "." + version;
|
||||||
|
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/tmd" + version_suf;
|
||||||
|
System.out.println(URL);
|
||||||
|
downloadFile(URL, "title.tmd",path,null);
|
||||||
}
|
}
|
||||||
public void downloadTMD(long titleID,String path) throws IOException {
|
|
||||||
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/tmd";
|
public void downloadFile(String fileURL,String filename,String tmpPath, Progress progress) throws IOException{
|
||||||
downloadFile(URL, "tmd",path);
|
|
||||||
}
|
|
||||||
public void downloadFile(String fileURL,String filename,String tmpPath) throws IOException{
|
|
||||||
int BUFFER_SIZE = 0x800;
|
int BUFFER_SIZE = 0x800;
|
||||||
URL url = new URL(fileURL);
|
URL url = new URL(fileURL);
|
||||||
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
|
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
|
||||||
@ -78,11 +94,16 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileOutputStream outputStream = new FileOutputStream(filename);
|
FileOutputStream outputStream = new FileOutputStream(filename);
|
||||||
|
if(progress != null){
|
||||||
|
progress.resetCurrent();
|
||||||
|
}
|
||||||
int bytesRead = -1;
|
int bytesRead = -1;
|
||||||
byte[] buffer = new byte[BUFFER_SIZE];
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
outputStream.write(buffer, 0, bytesRead);
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
if(progress != null){
|
||||||
|
progress.addCurrent(bytesRead);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
@ -92,21 +113,24 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void downloadFile(String fileURL,String filename) throws IOException{
|
public void downloadFile(String fileURL,String filename) throws IOException{
|
||||||
downloadFile(fileURL, filename,null);
|
downloadFile(fileURL, filename,null,null);
|
||||||
}
|
}
|
||||||
public void downloadTicket(long titleID,String path) throws IOException {
|
public void downloadTicket(long titleID,String path) throws IOException {
|
||||||
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/cetk";
|
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/cetk";
|
||||||
downloadFile(URL, "cetk",path);
|
downloadFile(URL, "title.tik",path,null);
|
||||||
}
|
}
|
||||||
public void downloadContent(long titleID,int contentID) throws IOException {
|
public void downloadContent(long titleID,int contentID,Progress progress) throws IOException {
|
||||||
downloadContent(titleID,contentID, null);
|
downloadContent(titleID,contentID, null,progress);
|
||||||
}
|
}
|
||||||
public byte[] downloadContentToByteArray(long titleID,int contentID) throws IOException {
|
public byte[] downloadContentToByteArray(long titleID,int contentID) throws IOException {
|
||||||
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/" + String.format("%08X", contentID);
|
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/" + String.format("%08X", contentID);
|
||||||
return downloadFileToByteArray(URL);
|
return downloadFileToByteArray(URL);
|
||||||
}
|
}
|
||||||
public byte[] downloadTMDToByteArray(long titleID) throws IOException {
|
public byte[] downloadTMDToByteArray(long titleID, int version) throws IOException {
|
||||||
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/tmd";
|
String version_suf = "";
|
||||||
|
if(version > 0) version_suf = "." + version;
|
||||||
|
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/tmd" +version_suf;
|
||||||
|
System.out.println(URL);
|
||||||
return downloadFileToByteArray(URL);
|
return downloadFileToByteArray(URL);
|
||||||
}
|
}
|
||||||
private byte[] downloadFileToByteArray(String fileURL) throws IOException {
|
private byte[] downloadFileToByteArray(String fileURL) throws IOException {
|
||||||
@ -141,17 +165,23 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
httpConn.disconnect();
|
httpConn.disconnect();
|
||||||
return file;
|
return file;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] downloadTicketToByteArray(long titleID) throws IOException {
|
public byte[] downloadTicketToByteArray(long titleID) throws IOException {
|
||||||
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/cetk";
|
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/cetk";
|
||||||
return downloadFileToByteArray(URL);
|
return downloadFileToByteArray(URL);
|
||||||
}
|
}
|
||||||
public void downloadContent(long titleID,int contentID, String tmpPath) throws IOException {
|
public void downloadContent(long titleID,int contentID, String tmpPath, Progress progress) throws IOException {
|
||||||
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/" + String.format("%08X", contentID);
|
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/" + String.format("%08X", contentID);
|
||||||
downloadFile(URL, String.format("%08X", contentID) +".app",tmpPath);
|
downloadFile(URL, String.format("%08x", contentID) +".app",tmpPath,progress);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public void downloadContentH3(long titleID, int contentID, String tmpPath, Progress progress) throws IOException {
|
||||||
|
String URL = URL_BASE + "/" + String.format("%016X", titleID) + "/" + String.format("%08X", contentID) + ".h3";
|
||||||
|
downloadFile(URL, String.format("%08X", contentID) +".h3",tmpPath,progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package de.mas.jnustool.util;
|
package de.mas.jnustool.util;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Serializable{
|
public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Serializable{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -13,7 +15,9 @@ public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Ser
|
|||||||
private String company_code;
|
private String company_code;
|
||||||
private int region;
|
private int region;
|
||||||
private byte[] key;
|
private byte[] key;
|
||||||
|
private ArrayList<Integer> versions = new ArrayList<>();
|
||||||
|
|
||||||
|
private String selectedVersion = "latest";
|
||||||
|
|
||||||
public enum Region{
|
public enum Region{
|
||||||
EUR,
|
EUR,
|
||||||
@ -22,7 +26,7 @@ public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Ser
|
|||||||
UKWN
|
UKWN
|
||||||
}
|
}
|
||||||
|
|
||||||
public NUSTitleInformation(long titleID, String longnameEN, String ID6, String product_code,String content_platform,String company_code,int region) {
|
public NUSTitleInformation(long titleID, String longnameEN, String ID6, String product_code,String content_platform,String company_code,int region, String[] versions) {
|
||||||
setTitleID(titleID);
|
setTitleID(titleID);
|
||||||
setLongnameEN(longnameEN);
|
setLongnameEN(longnameEN);
|
||||||
setID6(ID6);
|
setID6(ID6);
|
||||||
@ -30,12 +34,21 @@ public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Ser
|
|||||||
setCompany_code(company_code);
|
setCompany_code(company_code);
|
||||||
setContent_platform(content_platform);
|
setContent_platform(content_platform);
|
||||||
setRegion(region);
|
setRegion(region);
|
||||||
|
for(String s : versions){
|
||||||
|
if(s != null){
|
||||||
|
this.versions.add(Integer.parseInt(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public NUSTitleInformation() {
|
public NUSTitleInformation() {
|
||||||
// TODO Auto-generated constructor stub
|
// TODO Auto-generated constructor stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NUSTitleInformation(long titleID, String longnameEN, String ID6, String product_code,String content_platform,String company_code,int region) {
|
||||||
|
this(titleID, longnameEN, ID6, product_code,content_platform,company_code,region,new String[1]);
|
||||||
|
}
|
||||||
|
|
||||||
public Region getRegionAsRegion() {
|
public Region getRegionAsRegion() {
|
||||||
switch (region) {
|
switch (region) {
|
||||||
case 1: return Region.JAP;
|
case 1: return Region.JAP;
|
||||||
@ -108,7 +121,12 @@ public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Ser
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return getTitleIDAsString() + ";" + region +";" + getContent_platform() + ";" + getCompany_code() + ";"+ getProduct_code()+ ";" + getID6() + ";" + getLongnameEN();
|
String result = getTitleIDAsString() + ";" + region +";" + getContent_platform() + ";" + getCompany_code() + ";"+ getProduct_code()+ ";" + getID6() + ";" + getLongnameEN();
|
||||||
|
for(Integer i :versions){
|
||||||
|
result += ";" + i;
|
||||||
|
}
|
||||||
|
result += ";" + getSelectedVersion();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -140,5 +158,40 @@ public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Ser
|
|||||||
return titleID == ((NUSTitleInformation)o).titleID;
|
return titleID == ((NUSTitleInformation)o).titleID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLatestVersion() {
|
||||||
|
String result = "latest";
|
||||||
|
if(versions != null && !versions.isEmpty()){
|
||||||
|
result = versions.get(versions.size()-1) + "";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAllVersions() {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
if(versions != null && !versions.isEmpty()){
|
||||||
|
for(Integer v: versions){
|
||||||
|
list.add(v + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.add("latest");
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedVersion(String string) {
|
||||||
|
this.selectedVersion = string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSelectedVersion() {
|
||||||
|
int version = -1;
|
||||||
|
if(this.selectedVersion == "latest"){
|
||||||
|
version = -1;
|
||||||
|
}else{
|
||||||
|
try{
|
||||||
|
version = Integer.parseInt(this.selectedVersion);
|
||||||
|
}catch(Exception e){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package de.mas.jnustool.util;
|
|||||||
|
|
||||||
public class Settings {
|
public class Settings {
|
||||||
public static boolean downloadContent = false;
|
public static boolean downloadContent = false;
|
||||||
public static boolean useCachedFiles = false;
|
public static boolean useCachedFiles = true;
|
||||||
public static boolean downloadWhenCachedFilesMissingOrBroken = true;
|
public static boolean downloadWhenCachedFilesMissingOrBroken = true;
|
||||||
public static boolean skipBrokenFiles = false;
|
public static boolean skipBrokenFiles = false;
|
||||||
public static boolean skipExistingFiles = true;
|
public static boolean skipExistingFiles = true;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package de.mas.jnustool.util;
|
package de.mas.jnustool.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -21,6 +22,7 @@ public class Util {
|
|||||||
|
|
||||||
public static String ByteArrayToString(byte[] ba)
|
public static String ByteArrayToString(byte[] ba)
|
||||||
{
|
{
|
||||||
|
if(ba == null) return null;
|
||||||
StringBuilder hex = new StringBuilder(ba.length * 2);
|
StringBuilder hex = new StringBuilder(ba.length * 2);
|
||||||
for(byte b : ba){
|
for(byte b : ba){
|
||||||
hex.append(String.format("%02X", b));
|
hex.append(String.format("%02X", b));
|
||||||
@ -59,4 +61,26 @@ public class Util {
|
|||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void createSubfolder(String folder){
|
||||||
|
|
||||||
|
String [] path = folder.split("/");
|
||||||
|
File folder_ = null;
|
||||||
|
String foldername = new String();
|
||||||
|
if(path.length == 1){
|
||||||
|
folder_ = new File(folder);
|
||||||
|
if(!folder_.exists()){
|
||||||
|
folder_.mkdir();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i = 0;i<path.length-1;i++){
|
||||||
|
if(!path[i].equals("")){
|
||||||
|
foldername += path[i] + "/";
|
||||||
|
folder_ = new File(foldername);
|
||||||
|
if(!folder_.exists()){
|
||||||
|
folder_.mkdir();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user