mirror of
https://github.com/Maschell/JNUSTool.git
synced 2025-01-07 05:48:18 +01:00
Added multi selection and meta downloader
-added a progress function -added a meta download button -added mutli selection of titles -fixed byte[] to String function
This commit is contained in:
parent
8a597aa147
commit
626104209d
3
.gitignore
vendored
3
.gitignore
vendored
@ -50,4 +50,5 @@ bin
|
|||||||
/config
|
/config
|
||||||
/tmp*
|
/tmp*
|
||||||
UpdateGrabber.java
|
UpdateGrabber.java
|
||||||
updatetitles.csv
|
updatetitles.csv
|
||||||
|
src/de/mas/jnustool/StarterPRIATE.java
|
BIN
jar/JNUSTool.jar
BIN
jar/JNUSTool.jar
Binary file not shown.
@ -155,13 +155,16 @@ public class FEntry {
|
|||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadAndDecrypt() {
|
public void downloadAndDecrypt(Progress progress) {
|
||||||
createFolder();
|
createFolder();
|
||||||
long titleID = getTitleID();
|
long titleID = getTitleID();
|
||||||
File f = new File(String.format("%016X", titleID) +"/" +getFullPath().substring(1, getFullPath().length()));
|
File f = new File(String.format("%016X", titleID) +"/" +getFullPath().substring(1, getFullPath().length()));
|
||||||
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());
|
||||||
|
if(progress != null){
|
||||||
|
progress.finish();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,6 +175,7 @@ public class FEntry {
|
|||||||
if(f.length() == fst.getTmd().contents[this.getContentID()].size){
|
if(f.length() == fst.getTmd().contents[this.getContentID()].size){
|
||||||
Logger.log("Decrypting: " + String.format("%8.2f MB ", getFileLength()/1024.0/1024.0) + getFullPath());
|
Logger.log("Decrypting: " + String.format("%8.2f MB ", getFileLength()/1024.0/1024.0) + getFullPath());
|
||||||
Decryption decrypt = new Decryption(fst.getTmd().getNUSTitle().getTicket());
|
Decryption decrypt = new Decryption(fst.getTmd().getNUSTitle().getTicket());
|
||||||
|
decrypt.setProgressListener(progress);
|
||||||
decrypt.decrypt(this,getDownloadPath());
|
decrypt.decrypt(this,getDownloadPath());
|
||||||
return;
|
return;
|
||||||
}else{
|
}else{
|
||||||
@ -203,7 +207,7 @@ public class FEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
Downloader.getInstance().downloadAndDecrypt(this,progress);
|
||||||
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -5,17 +5,26 @@ import java.util.concurrent.Callable;
|
|||||||
public class FEntryDownloader implements Callable<Integer>
|
public class FEntryDownloader implements Callable<Integer>
|
||||||
{
|
{
|
||||||
FEntry f;
|
FEntry f;
|
||||||
|
Progress progress = null;
|
||||||
public void setTitle(FEntry f){
|
public void setTitle(FEntry f){
|
||||||
this.f = f;
|
this.f = f;
|
||||||
}
|
}
|
||||||
public FEntryDownloader(FEntry f){
|
public FEntryDownloader(FEntry f,Progress fatherProgress){
|
||||||
setTitle(f);
|
setTitle(f);
|
||||||
|
createProgressListener(fatherProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createProgressListener(Progress fatherProgress) {
|
||||||
|
if(fatherProgress != null){
|
||||||
|
progress = new Progress();
|
||||||
|
progress.setTotal(f.getFileLength());
|
||||||
|
fatherProgress.add(progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public Integer call() throws Exception {
|
public Integer call() throws Exception {
|
||||||
f.downloadAndDecrypt();
|
f.downloadAndDecrypt(progress);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ public class FST {
|
|||||||
int totalEntries = 0;
|
int totalEntries = 0;
|
||||||
int dirEntries = 0;
|
int dirEntries = 0;
|
||||||
public FEntry metaFENtry;
|
public FEntry metaFENtry;
|
||||||
|
public List<FEntry> metaFolder = new ArrayList<>();
|
||||||
private Directory FSTDirectory = new Directory("root");
|
private Directory FSTDirectory = new Directory("root");
|
||||||
|
|
||||||
private Directory contentDirectory = new Directory("root");
|
private Directory contentDirectory = new Directory("root");
|
||||||
@ -165,6 +166,8 @@ public class FST {
|
|||||||
this.totalContentSize += fileLength;
|
this.totalContentSize += fileLength;
|
||||||
if(in_nus_title)this.totalContentSizeInNUS += fileLength;
|
if(in_nus_title)this.totalContentSizeInNUS += fileLength;
|
||||||
|
|
||||||
|
boolean metafolder = false;
|
||||||
|
|
||||||
List<String> pathList = new ArrayList<>();
|
List<String> pathList = new ArrayList<>();
|
||||||
//getting the full path of entry
|
//getting the full path of entry
|
||||||
if(dir)
|
if(dir)
|
||||||
@ -180,7 +183,7 @@ public class FST {
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
int k = 0;
|
int k = 0;
|
||||||
int nameoffoff,nameoff_entrypath;
|
int nameoffoff,nameoff_entrypath;
|
||||||
|
|
||||||
for( j=0; j<level; ++j )
|
for( j=0; j<level; ++j )
|
||||||
{
|
{
|
||||||
nameoffoff = Util.getIntFromBytes(decrypteddata,base_offset+Entry[j]*0x10);
|
nameoffoff = Util.getIntFromBytes(decrypteddata,base_offset+Entry[j]*0x10);
|
||||||
@ -188,9 +191,11 @@ public class FST {
|
|||||||
nameoff_entrypath = nameOff + nameoffoff;
|
nameoff_entrypath = nameOff + nameoffoff;
|
||||||
while(decrypteddata[nameoff_entrypath + k] != 0){k++;}
|
while(decrypteddata[nameoff_entrypath + k] != 0){k++;}
|
||||||
String tmpname = new String(Arrays.copyOfRange(decrypteddata,nameoff_entrypath, nameoff_entrypath + k));
|
String tmpname = new String(Arrays.copyOfRange(decrypteddata,nameoff_entrypath, nameoff_entrypath + k));
|
||||||
|
if(j==1 && tmpname.equals("meta")){
|
||||||
|
metafolder = true;
|
||||||
|
}
|
||||||
if(!tmpname.equals("")){
|
if(!tmpname.equals("")){
|
||||||
pathList.add(tmpname);
|
pathList.add(tmpname);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(tmpname);
|
sb.append(tmpname);
|
||||||
@ -205,6 +210,9 @@ public class FST {
|
|||||||
if(filename.equals("meta.xml")){
|
if(filename.equals("meta.xml")){
|
||||||
metaFENtry = tmp;
|
metaFENtry = tmp;
|
||||||
}
|
}
|
||||||
|
if(metafolder){
|
||||||
|
metaFolder.add(tmp);
|
||||||
|
}
|
||||||
//Logger.log(fileEntries.get(i));
|
//Logger.log(fileEntries.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,6 +239,10 @@ public class FST {
|
|||||||
this.totalContentSizeInNUS = totalContentSizeInNUS;
|
this.totalContentSizeInNUS = totalContentSizeInNUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<FEntry> getMetaFolder() {
|
||||||
|
return metaFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<FEntry> getFileEntries() {
|
public List<FEntry> getFileEntries() {
|
||||||
return fileEntries;
|
return fileEntries;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package de.mas.jnustool;
|
package de.mas.jnustool;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
import de.mas.jnustool.gui.NUSGUI;
|
import de.mas.jnustool.gui.NUSGUI;
|
||||||
|
|
||||||
public class Logger {
|
public class Logger {
|
||||||
@ -7,7 +10,12 @@ 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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void messageBox(String string) {
|
||||||
|
JOptionPane.showMessageDialog(new JFrame(), string);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -214,15 +214,14 @@ public class NUSTitle {
|
|||||||
this.titleID = titleId;
|
this.titleID = titleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decryptFEntries(List<FEntry> list) {
|
public void decryptFEntries(List<FEntry> list,Progress progress) {
|
||||||
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){
|
||||||
if(!f.isDir() && f.isInNUSTitle()){
|
if(!f.isDir() && f.isInNUSTitle()){
|
||||||
dlList.add(new FEntryDownloader(f));
|
dlList.add(new FEntryDownloader(f,progress));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.invokeAll(dlList);
|
pool.invokeAll(dlList);
|
||||||
Logger.log("Done!");
|
Logger.log("Done!");
|
||||||
}
|
}
|
||||||
|
92
src/de/mas/jnustool/Progress.java
Normal file
92
src/de/mas/jnustool/Progress.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package de.mas.jnustool;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Progress {
|
||||||
|
private long total;
|
||||||
|
private long current;
|
||||||
|
private ProgressUpdateListener progressUpdateListener = null;
|
||||||
|
List<Progress> children = new ArrayList<>();
|
||||||
|
Progress father = null;
|
||||||
|
|
||||||
|
|
||||||
|
public long getTotalOfSingle() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(long total) {
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCurrentOfSingle() {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrent(long current) {
|
||||||
|
this.current = current;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCurrent(int i) {
|
||||||
|
if(this.current + i > getTotalOfSingle()){
|
||||||
|
setCurrent(getTotalOfSingle());
|
||||||
|
}else{
|
||||||
|
setCurrent(getCurrent() + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
if(father != null) father.update();
|
||||||
|
|
||||||
|
if(progressUpdateListener != null){
|
||||||
|
progressUpdateListener.updatePerformed(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Progress progress) {
|
||||||
|
progress.setFather(this);
|
||||||
|
children.add(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFather(Progress progressListener) {
|
||||||
|
this.father = progressListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCurrent() {
|
||||||
|
long tmp = getCurrentOfSingle();
|
||||||
|
for(Progress p : children){
|
||||||
|
tmp +=p.getCurrent();
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotal() {
|
||||||
|
long tmp = getTotalOfSingle();
|
||||||
|
for(Progress p : children){
|
||||||
|
tmp +=p.getTotal();
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgressUpdateListener(ProgressUpdateListener progressUpdateListener) {
|
||||||
|
this.progressUpdateListener = progressUpdateListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
setCurrent(0);
|
||||||
|
setTotal(0);
|
||||||
|
children = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int statusInPercent() {
|
||||||
|
return (int) ((getCurrent()*1.0)/(getTotal()*1.0)*100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
setCurrent(getTotalOfSingle());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
src/de/mas/jnustool/ProgressUpdateListener.java
Normal file
9
src/de/mas/jnustool/ProgressUpdateListener.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package de.mas.jnustool;
|
||||||
|
|
||||||
|
public interface ProgressUpdateListener {
|
||||||
|
/**
|
||||||
|
* Invoked when an action occurs.
|
||||||
|
*/
|
||||||
|
public void updatePerformed(Progress p);
|
||||||
|
|
||||||
|
}
|
@ -6,6 +6,10 @@ import java.io.FileReader;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
import java.util.concurrent.ForkJoinTask;
|
||||||
|
|
||||||
import de.mas.jnustool.gui.NUSGUI;
|
import de.mas.jnustool.gui.NUSGUI;
|
||||||
import de.mas.jnustool.gui.UpdateChooser;
|
import de.mas.jnustool.gui.UpdateChooser;
|
||||||
@ -37,23 +41,37 @@ public class Starter {
|
|||||||
if( args.length > 1 && args[1].length() == 32){
|
if( args.length > 1 && args[1].length() == 32){
|
||||||
key = args[1].substring(0, 32);
|
key = args[1].substring(0, 32);
|
||||||
}
|
}
|
||||||
|
if(titleID != 0){
|
||||||
|
NUSGUI m = new NUSGUI(new NUSTitle(titleID, key));
|
||||||
|
m.setVisible(true);
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
titleID = getTitleID().getTitleID();
|
for(NUSTitleInformation nus : getTitleID()){
|
||||||
}
|
|
||||||
if(titleID != 0){
|
final long tID = nus.getTitleID();
|
||||||
NUSGUI m = new NUSGUI(new NUSTitle(titleID, key), null);
|
new Thread(new Runnable() {
|
||||||
m.setVisible(true);
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
NUSGUI m = new NUSGUI(new NUSTitle(tID, null));
|
||||||
|
m.setVisible(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
}).start();;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static NUSTitleInformation getTitleID() {
|
private static List<NUSTitleInformation> getTitleID() {
|
||||||
List<NUSTitleInformation> updatelist = readUpdateCSV();
|
List<NUSTitleInformation> updatelist = readUpdateCSV();
|
||||||
NUSTitleInformation result = null;
|
List<NUSTitleInformation> result = null;
|
||||||
if(updatelist != null){
|
if(updatelist != null){
|
||||||
result = new NUSTitleInformation();
|
result = new ArrayList<>();
|
||||||
UpdateChooser.createAndShowGUI(updatelist,result);
|
UpdateChooser.createAndShowGUI(updatelist,result);
|
||||||
synchronized (result) {
|
synchronized (result) {
|
||||||
try {
|
try {
|
||||||
@ -63,6 +81,9 @@ public class Starter {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
Logger.messageBox("Updatefile is missing or not in config?");
|
||||||
|
System.exit(2);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -80,6 +101,7 @@ public class Starter {
|
|||||||
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 != 7) {
|
||||||
|
Logger.messageBox("Updatelist is broken!");
|
||||||
System.out.println("Updatelist is broken!");
|
System.out.println("Updatelist is broken!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -96,9 +118,10 @@ public class Starter {
|
|||||||
in.close();
|
in.close();
|
||||||
} catch (IOException | NumberFormatException e) {
|
} catch (IOException | NumberFormatException e) {
|
||||||
try {
|
try {
|
||||||
in.close();
|
if(in != null)in.close();
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
}
|
}
|
||||||
|
Logger.messageBox("Updatelist is broken or missing");
|
||||||
System.out.println("Updatelist is broken!");
|
System.out.println("Updatelist is broken!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -112,6 +135,7 @@ public class Starter {
|
|||||||
Downloader.URL_BASE = in.readLine();
|
Downloader.URL_BASE = in.readLine();
|
||||||
String commonkey = in.readLine();
|
String commonkey = in.readLine();
|
||||||
if(commonkey.length() != 32){
|
if(commonkey.length() != 32){
|
||||||
|
Logger.messageBox("CommonKey length is wrong");
|
||||||
System.out.println("Commonkey length is wrong");
|
System.out.println("Commonkey length is wrong");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
@ -121,4 +145,35 @@ public class Starter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void downloadMeta(List<NUSTitleInformation> output_, Progress totalProgress) {
|
||||||
|
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 nus = new NUSTitle(tID, null);
|
||||||
|
Progress childProgress = new Progress();
|
||||||
|
totalProgress.add(childProgress);
|
||||||
|
nus.decryptFEntries(nus.getFst().getMetaFolder(),childProgress);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,12 @@ import javax.swing.tree.TreePath;
|
|||||||
|
|
||||||
import de.mas.jnustool.FEntry;
|
import de.mas.jnustool.FEntry;
|
||||||
import de.mas.jnustool.NUSTitle;
|
import de.mas.jnustool.NUSTitle;
|
||||||
import de.mas.jnustool.util.Settings;
|
|
||||||
|
|
||||||
public class NUSGUI extends JFrame {
|
public class NUSGUI extends JFrame {
|
||||||
|
|
||||||
private static final long serialVersionUID = 4648172894076113183L;
|
private static final long serialVersionUID = 4648172894076113183L;
|
||||||
public static JTextArea output = new JTextArea(1,10);
|
public static JTextArea output = new JTextArea(1,10);
|
||||||
public NUSGUI(NUSTitle nus,Settings mode) {
|
public NUSGUI(NUSTitle nus) {
|
||||||
super();
|
super();
|
||||||
this.setResizable(false);
|
this.setResizable(false);
|
||||||
setSize(600, 768);
|
setSize(600, 768);
|
||||||
@ -64,7 +63,7 @@ public class NUSGUI extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nus.decryptFEntries(list);
|
nus.decryptFEntries(list, null);
|
||||||
}}).start();
|
}}).start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,9 @@ import javax.swing.BoxLayout;
|
|||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
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.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
@ -25,6 +27,9 @@ import javax.swing.ScrollPaneConstants;
|
|||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
|
||||||
|
import de.mas.jnustool.Progress;
|
||||||
|
import de.mas.jnustool.ProgressUpdateListener;
|
||||||
|
import de.mas.jnustool.Starter;
|
||||||
import de.mas.jnustool.util.NUSTitleInformation;
|
import de.mas.jnustool.util.NUSTitleInformation;
|
||||||
|
|
||||||
public class UpdateChooser extends JPanel {
|
public class UpdateChooser extends JPanel {
|
||||||
@ -42,7 +47,8 @@ public class UpdateChooser extends JPanel {
|
|||||||
setSize(800, 600);
|
setSize(800, 600);
|
||||||
|
|
||||||
Collections.sort(list_);
|
Collections.sort(list_);
|
||||||
output_.init(list_.get(0));
|
|
||||||
|
output_.add(list_.get(0));
|
||||||
String[] columnNames = { "TitleID", "Region", "Name" };
|
String[] columnNames = { "TitleID", "Region", "Name" };
|
||||||
String[][] tableData = new String[list_.size()][];
|
String[][] tableData = new String[list_.size()][];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -95,7 +101,7 @@ public class UpdateChooser extends JPanel {
|
|||||||
|
|
||||||
|
|
||||||
listSelectionModel.setSelectionMode(
|
listSelectionModel.setSelectionMode(
|
||||||
ListSelectionModel.SINGLE_SELECTION);
|
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
|
|
||||||
//Build output area.
|
//Build output area.
|
||||||
output = new JTextArea(1, 10);
|
output = new JTextArea(1, 10);
|
||||||
@ -123,38 +129,75 @@ public class UpdateChooser extends JPanel {
|
|||||||
splitPane.add(topHalf);
|
splitPane.add(topHalf);
|
||||||
JPanel listContainer = new JPanel(new GridLayout(1,1));
|
JPanel listContainer = new JPanel(new GridLayout(1,1));
|
||||||
add(listContainer, BorderLayout.NORTH);
|
add(listContainer, BorderLayout.NORTH);
|
||||||
JButton btnNewButton = new JButton("Okay");
|
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
add(panel, BorderLayout.SOUTH);
|
||||||
|
JButton btnNewButton = new JButton("Open FST");
|
||||||
|
panel.add(btnNewButton);
|
||||||
|
JProgressBar progressBar;
|
||||||
|
progressBar = new JProgressBar(0, 100);
|
||||||
|
progressBar.setValue(0);
|
||||||
|
progressBar.setStringPainted(true);
|
||||||
|
|
||||||
|
JButton btnDownloadMeta = new JButton("Download META");
|
||||||
|
JProgressBar progressBar_1 = new JProgressBar();
|
||||||
|
panel.add(progressBar_1);
|
||||||
|
progressBar_1.setValue(0);
|
||||||
|
Progress progress = new Progress();
|
||||||
|
progress.setProgressUpdateListener(new ProgressUpdateListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePerformed(Progress p) {
|
||||||
|
progressBar_1.setValue((int)p.statusInPercent());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btnDownloadMeta.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if(progressBar_1.getValue() == 0 || progressBar_1.getValue() == 100){
|
||||||
|
progressBar_1.setValue(1);
|
||||||
|
progress.clear();
|
||||||
|
new Thread(new Runnable(){
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Starter.downloadMeta(output_,progress);
|
||||||
|
JOptionPane.showMessageDialog(window, "Finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
}else{
|
||||||
|
JOptionPane.showMessageDialog(window, "Operation still in progress, please wait");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
panel.add(btnDownloadMeta);
|
||||||
|
|
||||||
|
|
||||||
btnNewButton.addActionListener(new ActionListener() {
|
btnNewButton.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
System.out.println("lol");
|
|
||||||
synchronized (output_) {
|
synchronized (output_) {
|
||||||
window.setVisible(false);
|
window.setVisible(false);
|
||||||
output_.notifyAll();
|
output_.notifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
add(btnNewButton, BorderLayout.SOUTH);
|
|
||||||
|
|
||||||
JPanel bottomHalf = new JPanel(new BorderLayout());
|
JPanel bottomHalf = new JPanel(new BorderLayout());
|
||||||
bottomHalf.add(controlPane, BorderLayout.PAGE_START);
|
bottomHalf.add(controlPane, BorderLayout.PAGE_START);
|
||||||
bottomHalf.add(outputPane, BorderLayout.CENTER);
|
bottomHalf.add(outputPane, BorderLayout.CENTER);
|
||||||
//XXX: next line needed if bottomHalf is a scroll pane:
|
|
||||||
//bottomHalf.setMinimumSize(new Dimension(400, 50));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NUSTitleInformation output_;
|
private static List<NUSTitleInformation> output_;
|
||||||
static List<NUSTitleInformation> list_;
|
static List<NUSTitleInformation> list_;
|
||||||
public static void createAndShowGUI(List<NUSTitleInformation> list,NUSTitleInformation output) {
|
public static void createAndShowGUI(List<NUSTitleInformation> list,List<NUSTitleInformation> result) {
|
||||||
//Create and set up the window.
|
//Create and set up the window.
|
||||||
JFrame frame = new JFrame("Select the title");
|
JFrame frame = new JFrame("Select the title");
|
||||||
|
|
||||||
//Create and set up the content pane.
|
//Create and set up the content pane.
|
||||||
list_ = list;
|
list_ = list;
|
||||||
output_ =output;
|
output_ =result;
|
||||||
UpdateChooser demo = new UpdateChooser(frame);
|
UpdateChooser demo = new UpdateChooser(frame);
|
||||||
demo.setOpaque(true);
|
demo.setOpaque(true);
|
||||||
frame.setContentPane(demo);
|
frame.setContentPane(demo);
|
||||||
@ -178,9 +221,12 @@ public class UpdateChooser extends JPanel {
|
|||||||
// Find out which indexes are selected.
|
// Find out which indexes are selected.
|
||||||
int minIndex = lsm.getMinSelectionIndex();
|
int minIndex = lsm.getMinSelectionIndex();
|
||||||
int maxIndex = lsm.getMaxSelectionIndex();
|
int maxIndex = lsm.getMaxSelectionIndex();
|
||||||
|
output_.clear();
|
||||||
for (int i = minIndex; i <= maxIndex; i++) {
|
for (int i = minIndex; i <= maxIndex; i++) {
|
||||||
if (lsm.isSelectedIndex(i)) {
|
if (lsm.isSelectedIndex(i)) {
|
||||||
output_.init(list_.get(i));
|
if(!output_.contains(list_.get(i))){
|
||||||
|
output_.add(list_.get(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import javax.crypto.spec.IvParameterSpec;
|
|||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import de.mas.jnustool.FEntry;
|
import de.mas.jnustool.FEntry;
|
||||||
|
import de.mas.jnustool.Progress;
|
||||||
import de.mas.jnustool.TIK;
|
import de.mas.jnustool.TIK;
|
||||||
|
|
||||||
public class Decryption {
|
public class Decryption {
|
||||||
@ -171,6 +172,10 @@ public class Decryption {
|
|||||||
|
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
ByteArrayBuffer overflow = new ByteArrayBuffer(BLOCKSIZE);
|
ByteArrayBuffer overflow = new ByteArrayBuffer(BLOCKSIZE);
|
||||||
|
if(progressListener != null){
|
||||||
|
progressListener.setTotal(toDownload.getFileLength());
|
||||||
|
progressListener.setCurrent(0);
|
||||||
|
}
|
||||||
do{
|
do{
|
||||||
inBlockBuffer = getChunkFromStream(inputStream,blockBuffer,overflow,BLOCKSIZE);
|
inBlockBuffer = getChunkFromStream(inputStream,blockBuffer,overflow,BLOCKSIZE);
|
||||||
if(first){
|
if(first){
|
||||||
@ -184,7 +189,9 @@ public class Decryption {
|
|||||||
if((wrote + inBlockBuffer) > toDownload.getFileLength()){
|
if((wrote + inBlockBuffer) > toDownload.getFileLength()){
|
||||||
inBlockBuffer = (int) (toDownload.getFileLength()- wrote);
|
inBlockBuffer = (int) (toDownload.getFileLength()- wrote);
|
||||||
}
|
}
|
||||||
|
if(progressListener != null){
|
||||||
|
progressListener.addCurrent(inBlockBuffer);
|
||||||
|
}
|
||||||
wrote += inBlockBuffer;
|
wrote += inBlockBuffer;
|
||||||
outputStream.write(output, 0, inBlockBuffer);
|
outputStream.write(output, 0, inBlockBuffer);
|
||||||
}while(inBlockBuffer == BLOCKSIZE);
|
}while(inBlockBuffer == BLOCKSIZE);
|
||||||
@ -209,9 +216,16 @@ public class Decryption {
|
|||||||
|
|
||||||
long wrote = 0;
|
long wrote = 0;
|
||||||
int inBlockBuffer;
|
int inBlockBuffer;
|
||||||
|
|
||||||
|
if(progressListener != null){
|
||||||
|
progressListener.setTotal(toDownload.getFileLength()/HASHBLOCKSIZE*BLOCKSIZE);
|
||||||
|
progressListener.setCurrent(0);
|
||||||
|
}
|
||||||
do{
|
do{
|
||||||
inBlockBuffer = getChunkFromStream(inputStream,encryptedBlockBuffer,overflow,BLOCKSIZE);
|
inBlockBuffer = getChunkFromStream(inputStream,encryptedBlockBuffer,overflow,BLOCKSIZE);
|
||||||
|
if(progressListener != null){
|
||||||
|
progressListener.addCurrent(inBlockBuffer);
|
||||||
|
}
|
||||||
if( writeSize > size )
|
if( writeSize > size )
|
||||||
writeSize = size;
|
writeSize = size;
|
||||||
|
|
||||||
@ -295,5 +309,12 @@ public class Decryption {
|
|||||||
return inBlockBuffer;
|
return inBlockBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Progress progressListener = null;
|
||||||
|
|
||||||
|
public void setProgressListener(Progress progressOfFile) {
|
||||||
|
this.progressListener = progressOfFile;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import java.net.HttpURLConnection;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import de.mas.jnustool.FEntry;
|
import de.mas.jnustool.FEntry;
|
||||||
|
import de.mas.jnustool.Progress;
|
||||||
|
|
||||||
public class Downloader {
|
public class Downloader {
|
||||||
private static Downloader instance;
|
private static Downloader instance;
|
||||||
@ -22,7 +23,7 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void downloadAndDecrypt(FEntry toDownload) throws IOException{
|
public void downloadAndDecrypt(FEntry toDownload, Progress progressOfFile) 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("/");
|
||||||
@ -45,7 +46,7 @@ public class Downloader {
|
|||||||
connection.connect();
|
connection.connect();
|
||||||
|
|
||||||
Decryption decryption = new Decryption(toDownload.getTicket());
|
Decryption decryption = new Decryption(toDownload.getTicket());
|
||||||
|
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()));
|
FileOutputStream outputStream = new FileOutputStream(String.format("%016X", toDownload.getTitleID()) +"/" + toDownload.getFullPath().substring(1, toDownload.getFullPath().length()));
|
||||||
if(!decryptWithHash){
|
if(!decryptWithHash){
|
||||||
|
@ -12,6 +12,7 @@ public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Ser
|
|||||||
private String content_platform;
|
private String content_platform;
|
||||||
private String company_code;
|
private String company_code;
|
||||||
private int region;
|
private int region;
|
||||||
|
private byte[] key;
|
||||||
|
|
||||||
|
|
||||||
public enum Region{
|
public enum Region{
|
||||||
@ -123,6 +124,21 @@ public class NUSTitleInformation implements Comparable<NUSTitleInformation>, Ser
|
|||||||
setID6(n.ID6);
|
setID6(n.ID6);
|
||||||
setLongnameEN(n.longnameEN);
|
setLongnameEN(n.longnameEN);
|
||||||
setProduct_code(n.product_code);
|
setProduct_code(n.product_code);
|
||||||
|
setKey(n.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(byte[] key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o){
|
||||||
|
return titleID == ((NUSTitleInformation)o).titleID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public class Util {
|
|||||||
{
|
{
|
||||||
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("%X", b));
|
hex.append(String.format("%02X", b));
|
||||||
}
|
}
|
||||||
return hex.toString();
|
return hex.toString();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user