diff --git a/jar/JNUSTool.jar b/jar/JNUSTool.jar index a085bf6..75fee95 100644 Binary files a/jar/JNUSTool.jar and b/jar/JNUSTool.jar differ diff --git a/release.zip b/release.zip index 327f354..719b0ad 100644 Binary files a/release.zip and b/release.zip differ diff --git a/src/de/mas/jnustool/Content.java b/src/de/mas/jnustool/Content.java index 5823868..f07f20b 100644 --- a/src/de/mas/jnustool/Content.java +++ b/src/de/mas/jnustool/Content.java @@ -47,12 +47,16 @@ public class Content { if(f.exists()){ if(f.length() == size){ Logger.log("Skipping Content: " + String.format("%08X", ID)); - progress.addCurrent((int) size); - return; + if(progress != null){ + 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); + Logger.log("Content " +String.format("%08X", ID) + " has a different filesize and may be broken. Downloading it again."); + new File(tmpPath).delete(); + Logger.log("Downloading Content: " + String.format("%08X", ID)); + Downloader.getInstance().downloadContent(tmd.titleID,ID,tmpPath,progress); + }else{ if(Settings.skipBrokenFiles){ Logger.log("Content " +String.format("%08X", ID) + " is broken. Ignoring it."); @@ -63,11 +67,17 @@ public class Content { } } }else{ - Logger.log("Download Content: " + String.format("%08X", ID)); - Downloader.getInstance().downloadContent(tmd.titleID,ID,tmpPath,progress); + Logger.log("Downloading Content: " + String.format("%08X", ID)); + Downloader.getInstance().downloadContent(tmd.titleID,ID,tmpPath,progress); } if ((type & 0x02) == 0x02){ - Downloader.getInstance().downloadContentH3(tmd.titleID,ID,tmpPath,null); + f = new File(tmpPath + "/" + String.format("%08X", ID ) + ".h3"); + if(!f.exists()){ + Logger.log("Downloading H3: " + String.format("%08X.h3", ID)); + Downloader.getInstance().downloadContentH3(tmd.titleID,ID,tmpPath,null); + }else{ + Logger.log("Skipping H3: " + String.format("%08X.h3", ID)); + } } } diff --git a/src/de/mas/jnustool/ContentDownloader.java b/src/de/mas/jnustool/ContentDownloader.java index 93127f8..b9c02d5 100644 --- a/src/de/mas/jnustool/ContentDownloader.java +++ b/src/de/mas/jnustool/ContentDownloader.java @@ -45,7 +45,12 @@ public class ContentDownloader implements Callable @Override public Integer call() throws Exception { - this.content.download(progress); + try{ + this.content.download(progress); + }catch(Exception e){ + e.printStackTrace(); + throw e; + } return null; } diff --git a/src/de/mas/jnustool/FEntryDownloader.java b/src/de/mas/jnustool/FEntryDownloader.java index d561e17..956957f 100644 --- a/src/de/mas/jnustool/FEntryDownloader.java +++ b/src/de/mas/jnustool/FEntryDownloader.java @@ -2,30 +2,35 @@ package de.mas.jnustool; import java.util.concurrent.Callable; -public class FEntryDownloader implements Callable -{ - FEntry f; +public class FEntryDownloader implements Callable{ + FEntry f; Progress progress = null; + public void setTitle(FEntry f){ this.f = f; } + public FEntryDownloader(FEntry f,Progress fatherProgress){ setTitle(f); createProgressListener(fatherProgress); - } - + } private void createProgressListener(Progress fatherProgress) { if(fatherProgress != null){ progress = new Progress(); fatherProgress.add(progress); - progress.addTotal(f.getFileLength()); - + progress.addTotal(f.getFileLength()); } } + @Override public Integer call() throws Exception { - f.downloadAndDecrypt(progress); + try{ + f.downloadAndDecrypt(progress); + }catch(Exception e){ + e.printStackTrace(); + throw e; + } return null; } diff --git a/src/de/mas/jnustool/FST.java b/src/de/mas/jnustool/FST.java index 42f073c..c49f607 100644 --- a/src/de/mas/jnustool/FST.java +++ b/src/de/mas/jnustool/FST.java @@ -83,11 +83,7 @@ public class FST { private void parse(byte[] decrypteddata, TitleMetaData tmd) throws IOException { if(!Arrays.equals(Arrays.copyOfRange(decrypteddata, 0, 3), new byte[]{0x46,0x53,0x54})){ - Logger.log(Util.ByteArrayToString(Arrays.copyOfRange(decrypteddata, 0, 3))); - - System.err.println("Not a FST. Maybe a wrong key?"); - throw new IllegalArgumentException("File not a FST"); - + throw new IllegalArgumentException("Not a FST. Maybe a wrong key? Don't worry if you only want to download encrypted files!"); } this.totalContentCount = Util.getIntFromBytes(decrypteddata, 8); int base_offset = 0x20+totalContentCount*0x20; diff --git a/src/de/mas/jnustool/NUSTitle.java b/src/de/mas/jnustool/NUSTitle.java index 9a64d3e..083386b 100644 --- a/src/de/mas/jnustool/NUSTitle.java +++ b/src/de/mas/jnustool/NUSTitle.java @@ -220,34 +220,63 @@ public class NUSTitle { } } - public void downloadEncryptedFiles(Progress progress) throws IOException { - + public void downloadEncryptedFiles(Progress progress) throws IOException { Util.createSubfolder(getContentPath()); - Downloader.getInstance().downloadTMD(titleID,version,getContentPath()); + Logger.log("---Downloading encrypted files---"); + Downloader.getInstance().downloadTMD(titleID,version,getContentPath()); + Logger.log("Downloaded title.tmd"); tmd.downloadContents(progress); - try{ - File f = new File(getContentPath() + "/" + "title.tik"); - if(!f.exists()){ + Logger.log("Downloaded content files"); + + File f = new File(getContentPath() + "/" + "title.tik"); + if(!f.exists()){ + try{ Downloader.getInstance().downloadTicket(titleID,getContentPath()); + Logger.log("Downloaded title.tik"); + }catch(Exception e){ + Logger.log("!!!Missing file: title.tik. You need to add it manually before you can install this title.!!!"); } - - FileOutputStream fos = new FileOutputStream(getContentPath() + "/title.cert"); - fos.write(ticket.cert0); - fos.write(tmd.cert); - fos.write(ticket.cert1); - fos.close(); - if(version > 0 && Settings.DL_ALL_VERSIONS){ - fos = new FileOutputStream(getContentPath() + "/title.cert." + version); - fos.write(ticket.cert0); - fos.write(tmd.cert); - fos.write(ticket.cert1); - fos.close(); - } + }else{ + Logger.log("Skipped title.tik"); + } + + f = new File(getContentPath() + "/" + "title.tik"); + byte[] defaultcert = null; + + Logger.log("Trying to create title.cert"); + if(!f.exists()){ + try{ + defaultcert = Util.getDefaultCert(); + }catch(Exception e){ + Logger.log("Failed to get missing cert from OSv10 cetk =(. Couldn't create title.cert"); + e.printStackTrace(); + return; + } + Logger.log("Got missing cert from OSv10 title"); + }else{ + defaultcert = ticket.cert1; + } + + try{ + FileOutputStream fos = new FileOutputStream(getContentPath() + "/title.cert"); + fos.write(tmd.cert1); + fos.write(tmd.cert2); + fos.write(defaultcert); + fos.close(); + if(version > 0 && Settings.DL_ALL_VERSIONS){ + fos = new FileOutputStream(getContentPath() + "/title.cert." + version); + fos.write(tmd.cert1); + fos.write(tmd.cert2); + fos.write(defaultcert); + fos.close(); + } }catch(Exception e){ e.printStackTrace(); Logger.log("Error while creating ticket files."); } + Logger.log("Created title.cert"); + Logger.log("---Successfully downloaded encrypted files---"); } public NUSTitleInformation readMeta(InputStream bis) { diff --git a/src/de/mas/jnustool/Starter.java b/src/de/mas/jnustool/Starter.java index 3b5040f..1200b31 100644 --- a/src/de/mas/jnustool/Starter.java +++ b/src/de/mas/jnustool/Starter.java @@ -25,7 +25,7 @@ public class Starter { private static String updateCSVPath; public static void main(String[] args) { - Logger.log("JNUSTool 0.0.8 - alpha - by Maschell"); + Logger.log("JNUSTool 0.0.8b - alpha - by Maschell"); Logger.log(""); try { readConfig(); diff --git a/src/de/mas/jnustool/TitleMetaData.java b/src/de/mas/jnustool/TitleMetaData.java index 62cfece..847252a 100644 --- a/src/de/mas/jnustool/TitleMetaData.java +++ b/src/de/mas/jnustool/TitleMetaData.java @@ -37,7 +37,8 @@ public class TitleMetaData { byte[] SHA2 = new byte[32]; // 0x1E4 ContentInfo[] contentInfos = new ContentInfo[64]; // 0x1E4 Content[] contents; // 0x1E4 - byte[] cert = new byte[0x300]; + byte[] cert1 = new byte[0x400]; + byte[] cert2 = new byte[0x300]; private NUSTitle nus; @@ -130,8 +131,11 @@ public class TitleMetaData { this.contents[i] = new Content(ID,index,type,size,buffer,this); } - if(f.read(cert,0, 0x300) != 0x300){ - Logger.log("Error reading TMD cert"); + if(f.read(cert2,0, 0x300) != 0x300){ + Logger.log("Error reading TMD cert2"); + } + if(f.read(cert1,0, 0x400) != 0x400){ + Logger.log("Error reading TMD cert1"); } f.close(); } @@ -155,7 +159,8 @@ public class TitleMetaData { sb.append("contentCount: " + contentCount +"\n"); sb.append("bootIndex: " + bootIndex +"\n"); sb.append("SHA2: " + Util.ByteArrayToString(SHA2) +"\n"); - sb.append("cert: " + Util.ByteArrayToString(cert) +"\n"); + sb.append("cert1: " + Util.ByteArrayToString(cert1) +"\n"); + sb.append("cert2: " + Util.ByteArrayToString(cert2) +"\n"); sb.append("contentInfos: \n"); for(int i = 0; i