mirror of
https://github.com/developersu/ns-usbloader.git
synced 2025-05-14 15:15:05 -04:00
v0.6 GoldLeaf v0.6.1 support
This commit is contained in:
parent
d34d522f46
commit
cd73968306
20 changed files with 1076 additions and 597 deletions
|
@ -25,7 +25,8 @@ public class AppPreferences {
|
|||
String HostPort,
|
||||
String HostExtra,
|
||||
boolean autoCheck4Updates,
|
||||
boolean tinfoilXciSupport
|
||||
boolean tinfoilXciSupport,
|
||||
boolean nspFileFilterForGl
|
||||
){
|
||||
setProtocol(Protocol);
|
||||
setRecent(PreviouslyOpened);
|
||||
|
@ -41,6 +42,7 @@ public class AppPreferences {
|
|||
setHostExtra(HostExtra);
|
||||
setAutoCheckUpdates(autoCheck4Updates);
|
||||
setTfXCI(tinfoilXciSupport);
|
||||
setNspFileFilterGL(nspFileFilterForGl);
|
||||
}
|
||||
public String getTheme(){
|
||||
String theme = preferences.get("THEME", "/res/app_dark.css"); // Don't let user to change settings manually
|
||||
|
@ -109,4 +111,7 @@ public class AppPreferences {
|
|||
|
||||
public String getLanguage(){return preferences.get("USR_LANG", Locale.getDefault().getISO3Language());}
|
||||
public void setLanguage(String langStr){preferences.put("USR_LANG", langStr);}
|
||||
|
||||
public boolean getNspFileFilterGL(){return preferences.getBoolean("GL_NSP_FILTER", false); }
|
||||
public void setNspFileFilterGL(boolean prop){preferences.putBoolean("GL_NSP_FILTER", prop);}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import javafx.scene.control.*;
|
|||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Region;
|
||||
import nsusbloader.AppPreferences;
|
||||
import nsusbloader.MediatorControl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
@ -49,6 +50,11 @@ public class FrontController implements Initializable {
|
|||
nsIpTextField.setVisible(true);
|
||||
}
|
||||
}
|
||||
// Really bad disable-enable upload button function
|
||||
if (tableFilesListController.isFilesForUploadListEmpty())
|
||||
MediatorControl.getInstance().getContoller().disableUploadStopBtn(true);
|
||||
else
|
||||
MediatorControl.getInstance().getContoller().disableUploadStopBtn(false);
|
||||
}); // Add listener to notify tableView controller
|
||||
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import nsusbloader.USB.UsbCommunications;
|
|||
import java.io.File;
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
@ -56,7 +57,10 @@ public class NSLMainController implements Initializable {
|
|||
|
||||
MediatorControl.getInstance().setController(this);
|
||||
|
||||
uploadStopBtn.setDisable(true);
|
||||
if (FrontTabController.getSelectedProtocol().equals("TinFoil"))
|
||||
uploadStopBtn.setDisable(true);
|
||||
else
|
||||
uploadStopBtn.setDisable(false);
|
||||
selectNspBtn.setOnAction(e->{ selectFilesBtnAction(); });
|
||||
uploadStopBtn.setOnAction(e->{ uploadBtnAction(); });
|
||||
|
||||
|
@ -128,23 +132,26 @@ public class NSLMainController implements Initializable {
|
|||
if ((workThread == null || !workThread.isAlive())){
|
||||
// Collect files
|
||||
List<File> nspToUpload;
|
||||
if ((nspToUpload = FrontTabController.tableFilesListController.getFilesForUpload()) == null) {
|
||||
if ((nspToUpload = FrontTabController.tableFilesListController.getFilesForUpload()) == null && FrontTabController.getSelectedProtocol().equals("TinFoil")) {
|
||||
logArea.setText(resourceBundle.getString("logsNoFolderFileSelected"));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n");
|
||||
for (File item: nspToUpload)
|
||||
logArea.appendText(" "+item.getAbsolutePath()+"\n");
|
||||
if ((nspToUpload = FrontTabController.tableFilesListController.getFilesForUpload()) != null){
|
||||
logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n");
|
||||
for (File item: nspToUpload)
|
||||
logArea.appendText(" "+item.getAbsolutePath()+"\n");
|
||||
}
|
||||
else {
|
||||
logArea.clear();
|
||||
nspToUpload = new LinkedList<>();
|
||||
}
|
||||
}
|
||||
// If USB selected
|
||||
if (FrontTabController.getSelectedProtocol().equals("GoldLeaf") ||
|
||||
(
|
||||
FrontTabController.getSelectedProtocol().equals("TinFoil")
|
||||
&& FrontTabController.getSelectedNetUsb().equals("USB")
|
||||
)
|
||||
( FrontTabController.getSelectedProtocol().equals("TinFoil") && FrontTabController.getSelectedNetUsb().equals("USB") )
|
||||
){
|
||||
usbNetCommunications = new UsbCommunications(nspToUpload, FrontTabController.getSelectedProtocol());
|
||||
usbNetCommunications = new UsbCommunications(nspToUpload, FrontTabController.getSelectedProtocol(), SettingsTabController.getNSPFileFilterForGL());
|
||||
workThread = new Thread(usbNetCommunications);
|
||||
workThread.setDaemon(true);
|
||||
workThread.start();
|
||||
|
@ -217,7 +224,10 @@ public class NSLMainController implements Initializable {
|
|||
* Crunch. Now you see that I'm not a programmer.. This function called from NSTableViewController
|
||||
* */
|
||||
public void disableUploadStopBtn(boolean disable){
|
||||
uploadStopBtn.setDisable(disable);
|
||||
if (FrontTabController.getSelectedProtocol().equals("TinFoil"))
|
||||
uploadStopBtn.setDisable(disable);
|
||||
else
|
||||
uploadStopBtn.setDisable(false);
|
||||
}
|
||||
/**
|
||||
* Drag-n-drop support (dragOver consumer)
|
||||
|
@ -285,7 +295,8 @@ public class NSLMainController implements Initializable {
|
|||
SettingsTabController.getHostPort(),
|
||||
SettingsTabController.getHostExtra(),
|
||||
SettingsTabController.getAutoCheckForUpdates(),
|
||||
SettingsTabController.getTfXCISupport()
|
||||
SettingsTabController.getTfXCISupport(),
|
||||
SettingsTabController.getNSPFileFilterForGL()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.io.File;
|
|||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class NSTableViewController implements Initializable {
|
||||
|
@ -33,8 +32,6 @@ public class NSTableViewController implements Initializable {
|
|||
private TableView<NSLRowModel> table;
|
||||
private ObservableList<NSLRowModel> rowsObsLst;
|
||||
|
||||
private String protocol;
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||
rowsObsLst = FXCollections.observableArrayList();
|
||||
|
@ -55,7 +52,6 @@ public class NSTableViewController implements Initializable {
|
|||
} else if (keyEvent.getCode() == KeyCode.SPACE) {
|
||||
for (NSLRowModel item : table.getSelectionModel().getSelectedItems()) {
|
||||
item.setMarkForUpload(!item.isMarkForUpload());
|
||||
restrictSelection(item);
|
||||
}
|
||||
table.refresh();
|
||||
}
|
||||
|
@ -107,7 +103,6 @@ public class NSTableViewController implements Initializable {
|
|||
@Override
|
||||
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean oldValue, Boolean newValue) {
|
||||
model.setMarkForUpload(newValue);
|
||||
restrictSelection(model);
|
||||
}
|
||||
});
|
||||
return booleanProperty;
|
||||
|
@ -162,7 +157,7 @@ public class NSTableViewController implements Initializable {
|
|||
if (!row.isEmpty() && mouseEvent.getButton() == MouseButton.PRIMARY){
|
||||
NSLRowModel thisItem = row.getItem();
|
||||
thisItem.setMarkForUpload(!thisItem.isMarkForUpload());
|
||||
restrictSelection(thisItem);
|
||||
table.refresh();
|
||||
}
|
||||
mouseEvent.consume();
|
||||
}
|
||||
|
@ -174,18 +169,6 @@ public class NSTableViewController implements Initializable {
|
|||
table.setItems(rowsObsLst);
|
||||
table.getColumns().addAll(statusColumn, fileNameColumn, fileSizeColumn, uploadColumn);
|
||||
}
|
||||
/**
|
||||
* See uploadColumn callback. In case of GoldLeaf we have to restrict selection
|
||||
* */
|
||||
private void restrictSelection(NSLRowModel modelChecked){
|
||||
if (!protocol.equals("TinFoil") && rowsObsLst.size() > 1) { // Tinfoil doesn't need any restrictions. If only one file in list, also useless
|
||||
for (NSLRowModel model: rowsObsLst){
|
||||
if (model != modelChecked)
|
||||
model.setMarkForUpload(false);
|
||||
}
|
||||
}
|
||||
table.refresh();
|
||||
}
|
||||
/**
|
||||
* Add files when user selected them
|
||||
* */
|
||||
|
@ -196,21 +179,15 @@ public class NSTableViewController implements Initializable {
|
|||
filesAlreayInList.add(model.getNspFileName());
|
||||
for (File file: newFiles)
|
||||
if (!filesAlreayInList.contains(file.getName())) {
|
||||
if (protocol.equals("TinFoil"))
|
||||
rowsObsLst.add(new NSLRowModel(file, true));
|
||||
else
|
||||
rowsObsLst.add(new NSLRowModel(file, false));
|
||||
rowsObsLst.add(new NSLRowModel(file, true));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (File file: newFiles)
|
||||
if (protocol.equals("TinFoil"))
|
||||
rowsObsLst.add(new NSLRowModel(file, true));
|
||||
else
|
||||
rowsObsLst.add(new NSLRowModel(file, false));
|
||||
rowsObsLst.add(new NSLRowModel(file, true));
|
||||
MediatorControl.getInstance().getContoller().disableUploadStopBtn(false);
|
||||
}
|
||||
rowsObsLst.get(0).setMarkForUpload(true);
|
||||
//rowsObsLst.get(0).setMarkForUpload(true);
|
||||
table.refresh();
|
||||
}
|
||||
/**
|
||||
|
@ -237,14 +214,16 @@ public class NSTableViewController implements Initializable {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
public boolean isFilesForUploadListEmpty(){
|
||||
return rowsObsLst.isEmpty();
|
||||
}
|
||||
/**
|
||||
* Update files in case something is wrong. Requested from UsbCommunications
|
||||
* */
|
||||
public void setFileStatus(String fileName, EFileStatus status){
|
||||
for (NSLRowModel model: rowsObsLst){
|
||||
if (model.getNspFileName().equals(fileName)){
|
||||
if (model.getNspFileName().equals(fileName))
|
||||
model.setStatus(status);
|
||||
}
|
||||
}
|
||||
table.refresh();
|
||||
}
|
||||
|
@ -252,25 +231,10 @@ public class NSTableViewController implements Initializable {
|
|||
* Called if selected different USB protocol
|
||||
* */
|
||||
public void setNewProtocol(String newProtocol){
|
||||
protocol = newProtocol;
|
||||
if (rowsObsLst.isEmpty())
|
||||
return;
|
||||
if (newProtocol.equals("TinFoil")){
|
||||
for (NSLRowModel model: rowsObsLst)
|
||||
model.setMarkForUpload(true);
|
||||
}
|
||||
else {
|
||||
ListIterator<NSLRowModel> iterator = rowsObsLst.listIterator();
|
||||
while (iterator.hasNext()){
|
||||
NSLRowModel current = iterator.next();
|
||||
if (current.getNspFileName().toLowerCase().endsWith("xci"))
|
||||
iterator.remove();
|
||||
else
|
||||
current.setMarkForUpload(false);
|
||||
}
|
||||
if (!rowsObsLst.isEmpty())
|
||||
rowsObsLst.get(0).setMarkForUpload(true);
|
||||
}
|
||||
if (! newProtocol.equals("TinFoil"))
|
||||
rowsObsLst.removeIf(current -> current.getNspFileName().toLowerCase().endsWith("xci"));
|
||||
table.refresh();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ import java.util.jar.JarEntry;
|
|||
import java.util.jar.JarFile;
|
||||
|
||||
public class SettingsController implements Initializable {
|
||||
|
||||
@FXML
|
||||
private CheckBox nspFilesFilterForGLCB;
|
||||
@FXML
|
||||
private CheckBox validateNSHostNameCb;
|
||||
@FXML
|
||||
|
@ -64,6 +65,8 @@ public class SettingsController implements Initializable {
|
|||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||
nspFilesFilterForGLCB.setSelected(AppPreferences.getInstance().getNspFileFilterGL());
|
||||
|
||||
validateNSHostNameCb.setSelected(AppPreferences.getInstance().getNsIpValidationNeeded());
|
||||
|
||||
expertSettingsVBox.setDisable(!AppPreferences.getInstance().getExpertMode());
|
||||
|
@ -243,7 +246,7 @@ public class SettingsController implements Initializable {
|
|||
});
|
||||
|
||||
}
|
||||
|
||||
public boolean getNSPFileFilterForGL(){return nspFilesFilterForGLCB.isSelected(); }
|
||||
public boolean getExpertModeSelected(){ return expertModeCb.isSelected(); }
|
||||
public boolean getAutoIpSelected(){ return autoDetectIpCb.isSelected(); }
|
||||
public boolean getRandPortSelected(){ return randPortCb.isSelected(); }
|
||||
|
|
|
@ -49,7 +49,7 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
|
|||
}
|
||||
catch (UnsupportedEncodingException uee){
|
||||
isValid = false;
|
||||
logPrinter.print("NET: Unsupported encoding for 'URLEncoder'. Internal issue you can't fix. Please report. . Returned:\n\t"+uee.getMessage(), EMsgType.FAIL);
|
||||
logPrinter.print("NET: Unsupported encoding for 'URLEncoder'. Internal issue you can't fix. Please report. Returned:\n\t"+uee.getMessage(), EMsgType.FAIL);
|
||||
for (File nspFile : filesList)
|
||||
nspMap.put(nspFile.getName(), nspFile);
|
||||
close(EFileStatus.FAILED);
|
||||
|
|
|
@ -24,7 +24,7 @@ public class NETPacket {
|
|||
"Accept-Ranges: bytes\r\n"+
|
||||
"Content-Range: bytes %d-%d/%d\r\n"+
|
||||
"Content-Length: %d\r\n"+
|
||||
"Last-Modified: Mon, 18 Mar 2019 12:57:33 GMT\r\n\r\n";
|
||||
"Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT\r\n\r\n";
|
||||
private static final String CODE_400 =
|
||||
"HTTP/1.0 400 invalid range\r\n"+
|
||||
"Server: NS-USBloader-"+NSLMain.appVersion+"\r\n" +
|
||||
|
|
|
@ -12,10 +12,9 @@ import java.util.Locale;
|
|||
import java.util.ResourceBundle;
|
||||
|
||||
public class NSLMain extends Application {
|
||||
public static final String appVersion = "v0.5.3";
|
||||
public static final String appVersion = "v0.6";
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception{
|
||||
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/NSLMain.fxml"));
|
||||
|
||||
Locale userLocale = new Locale(AppPreferences.getInstance().getLanguage()); // NOTE: user locale based on ISO3 Language codes
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package nsusbloader.USB.PFS;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Data class to hold NCA, tik, xml etc. meta-information
|
||||
* */
|
||||
public class NCAFile {
|
||||
//private int ncaNumber;
|
||||
private byte[] ncaFileName;
|
||||
private long ncaOffset;
|
||||
private long ncaSize;
|
||||
|
||||
//public void setNcaNumber(int ncaNumber){ this.ncaNumber = ncaNumber; }
|
||||
public void setNcaFileName(byte[] ncaFileName) { this.ncaFileName = ncaFileName; }
|
||||
public void setNcaOffset(long ncaOffset) { this.ncaOffset = ncaOffset; }
|
||||
public void setNcaSize(long ncaSize) { this.ncaSize = ncaSize; }
|
||||
|
||||
//public int getNcaNumber() {return this.ncaNumber; }
|
||||
public byte[] getNcaFileName() { return ncaFileName; }
|
||||
public byte[] getNcaFileNameLength() { return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ncaFileName.length).array(); }
|
||||
public long getNcaOffset() { return ncaOffset; }
|
||||
public long getNcaSize() { return ncaSize; }
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
package nsusbloader.USB.PFS;
|
||||
|
||||
import nsusbloader.ModelControllers.LogPrinter;
|
||||
import nsusbloader.NSLDataTypes.EMsgType;
|
||||
import nsusbloader.ServiceWindow;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Used in GoldLeaf USB protocol
|
||||
* */
|
||||
public class PFSProvider {
|
||||
private static final byte[] PFS0 = new byte[]{(byte)0x50, (byte)0x46, (byte)0x53, (byte)0x30}; // PFS0, and what did you think?
|
||||
|
||||
private LogPrinter logPrinter;
|
||||
private ResourceBundle rb;
|
||||
|
||||
private RandomAccessFile randAccessFile;
|
||||
private String nspFileName;
|
||||
private NCAFile[] ncaFiles;
|
||||
private long bodySize;
|
||||
private int ticketID = -1;
|
||||
|
||||
public PFSProvider(File nspFile, LogPrinter logPrinter){
|
||||
this.logPrinter = logPrinter;
|
||||
try {
|
||||
this.randAccessFile = new RandomAccessFile(nspFile, "r");
|
||||
nspFileName = nspFile.getName();
|
||||
}
|
||||
catch (FileNotFoundException fnfe){
|
||||
logPrinter.print("PFS File not founnd: \n "+fnfe.getMessage(), EMsgType.FAIL);
|
||||
nspFileName = null;
|
||||
}
|
||||
Locale userLocale = new Locale(Locale.getDefault().getISO3Language());
|
||||
rb = ResourceBundle.getBundle("locale", userLocale);
|
||||
}
|
||||
|
||||
public boolean init() {
|
||||
if (nspFileName == null)
|
||||
return false;
|
||||
|
||||
int filesCount;
|
||||
int header;
|
||||
|
||||
logPrinter.print("PFS Start NSP file analyze for ["+nspFileName+"]", EMsgType.INFO);
|
||||
try {
|
||||
byte[] fileStartingBytes = new byte[12];
|
||||
// Read PFS0, files count, header, padding (4 zero bytes)
|
||||
if (randAccessFile.read(fileStartingBytes) == 12)
|
||||
logPrinter.print("PFS Read file starting bytes.", EMsgType.PASS);
|
||||
else {
|
||||
logPrinter.print("PFS Read file starting bytes.", EMsgType.FAIL);
|
||||
randAccessFile.close();
|
||||
return false;
|
||||
}
|
||||
// Check PFS0
|
||||
if (Arrays.equals(PFS0, Arrays.copyOfRange(fileStartingBytes, 0, 4)))
|
||||
logPrinter.print("PFS Read 'PFS0'.", EMsgType.PASS);
|
||||
else {
|
||||
logPrinter.print("PFS Read 'PFS0'.", EMsgType.WARNING);
|
||||
if (!ServiceWindow.getConfirmationWindow(nspFileName+"\n"+rb.getString("windowTitleConfirmWrongPFS0"), rb.getString("windowBodyConfirmWrongPFS0"))) {
|
||||
randAccessFile.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Get files count
|
||||
filesCount = ByteBuffer.wrap(Arrays.copyOfRange(fileStartingBytes, 4, 8)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
if (filesCount > 0 ) {
|
||||
logPrinter.print("PFS Read files count [" + filesCount + "]", EMsgType.PASS);
|
||||
}
|
||||
else {
|
||||
logPrinter.print("PFS Read files count", EMsgType.FAIL);
|
||||
randAccessFile.close();
|
||||
return false;
|
||||
}
|
||||
// Get header
|
||||
header = ByteBuffer.wrap(Arrays.copyOfRange(fileStartingBytes, 8, 12)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
if (header > 0 )
|
||||
logPrinter.print("PFS Read header ["+header+"]", EMsgType.PASS);
|
||||
else {
|
||||
logPrinter.print("PFS Read header ", EMsgType.FAIL);
|
||||
randAccessFile.close();
|
||||
return false;
|
||||
}
|
||||
//*********************************************************************************************
|
||||
// Create NCA set
|
||||
this.ncaFiles = new NCAFile[filesCount];
|
||||
// Collect files from NSP
|
||||
byte[] ncaInfoArr = new byte[24]; // should be unsigned long, but.. java.. u know my pain man
|
||||
|
||||
HashMap<Integer, Long> ncaNameOffsets = new LinkedHashMap<>();
|
||||
|
||||
int offset;
|
||||
long nca_offset;
|
||||
long nca_size;
|
||||
long nca_name_offset;
|
||||
|
||||
for (int i=0; i<filesCount; i++){
|
||||
if (randAccessFile.read(ncaInfoArr) == 24) {
|
||||
logPrinter.print("PFS Read NCA inside NSP: " + i, EMsgType.PASS);
|
||||
}
|
||||
else {
|
||||
logPrinter.print("PFS Read NCA inside NSP: "+i, EMsgType.FAIL);
|
||||
randAccessFile.close();
|
||||
return false;
|
||||
}
|
||||
offset = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 0, 4)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
nca_offset = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 4, 12)).order(ByteOrder.LITTLE_ENDIAN).getLong();
|
||||
nca_size = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 12, 20)).order(ByteOrder.LITTLE_ENDIAN).getLong();
|
||||
nca_name_offset = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 20, 24)).order(ByteOrder.LITTLE_ENDIAN).getInt(); // yes, cast from int to long.
|
||||
|
||||
logPrinter.print(" Padding check", offset == 0?EMsgType.PASS:EMsgType.WARNING);
|
||||
logPrinter.print(" NCA offset check: "+nca_offset, nca_offset >= 0?EMsgType.PASS:EMsgType.WARNING);
|
||||
logPrinter.print(" NCA size check: "+nca_size, nca_size >= 0?EMsgType.PASS: EMsgType.WARNING);
|
||||
logPrinter.print(" NCA name offset check: "+nca_name_offset, nca_name_offset >= 0?EMsgType.PASS:EMsgType.WARNING);
|
||||
|
||||
NCAFile ncaFile = new NCAFile();
|
||||
ncaFile.setNcaOffset(nca_offset);
|
||||
ncaFile.setNcaSize(nca_size);
|
||||
this.ncaFiles[i] = ncaFile;
|
||||
|
||||
ncaNameOffsets.put(i, nca_name_offset);
|
||||
}
|
||||
// Final offset
|
||||
byte[] bufForInt = new byte[4];
|
||||
if ((randAccessFile.read(bufForInt) == 4) && (Arrays.equals(bufForInt, new byte[4])))
|
||||
logPrinter.print("PFS Final padding check", EMsgType.PASS);
|
||||
else
|
||||
logPrinter.print("PFS Final padding check", EMsgType.WARNING);
|
||||
|
||||
// Calculate position including header for body size offset
|
||||
bodySize = randAccessFile.getFilePointer()+header;
|
||||
//*********************************************************************************************
|
||||
// Collect file names from NCAs
|
||||
logPrinter.print("PFS Collecting file names", EMsgType.INFO);
|
||||
List<Byte> ncaFN; // Temporary
|
||||
byte[] b = new byte[1]; // Temporary
|
||||
for (int i=0; i<filesCount; i++){
|
||||
ncaFN = new ArrayList<>();
|
||||
randAccessFile.seek(filesCount*24+16+ncaNameOffsets.get(i)); // Files cont * 24(bit for each meta-data) + 4 bytes goes after all of them + 12 bit what were in the beginning
|
||||
while ((randAccessFile.read(b)) != -1){
|
||||
if (b[0] == 0x00)
|
||||
break;
|
||||
else
|
||||
ncaFN.add(b[0]);
|
||||
}
|
||||
byte[] exchangeTempArray = new byte[ncaFN.size()];
|
||||
for (int j=0; j < ncaFN.size(); j++)
|
||||
exchangeTempArray[j] = ncaFN.get(j);
|
||||
// Find and store ticket (.tik)
|
||||
if (new String(exchangeTempArray, StandardCharsets.UTF_8).toLowerCase().endsWith(".tik"))
|
||||
this.ticketID = i;
|
||||
this.ncaFiles[i].setNcaFileName(Arrays.copyOf(exchangeTempArray, exchangeTempArray.length));
|
||||
}
|
||||
randAccessFile.close();
|
||||
}
|
||||
catch (IOException ioe){
|
||||
logPrinter.print("PFS Failed NSP file analyze for ["+nspFileName+"]\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
logPrinter.print("PFS Finish NSP file analyze for ["+nspFileName+"]", EMsgType.PASS);
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Return file name as byte array
|
||||
* */
|
||||
public byte[] getBytesNspFileName(){
|
||||
return nspFileName.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
/**
|
||||
* Return file name as String
|
||||
* */
|
||||
public String getStringNspFileName(){
|
||||
return nspFileName;
|
||||
}
|
||||
/**
|
||||
* Return file name length as byte array
|
||||
* */
|
||||
public byte[] getBytesNspFileNameLength(){
|
||||
return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(getBytesNspFileName().length).array();
|
||||
}
|
||||
/**
|
||||
* Return NCA count inside of file as byte array
|
||||
* */
|
||||
public byte[] getBytesCountOfNca(){
|
||||
return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ncaFiles.length).array();
|
||||
}
|
||||
/**
|
||||
* Return NCA count inside of file as int
|
||||
* */
|
||||
public int getIntCountOfNca(){
|
||||
return ncaFiles.length;
|
||||
}
|
||||
/**
|
||||
* Return requested-by-number NCA file inside of file
|
||||
* */
|
||||
public NCAFile getNca(int ncaNumber){
|
||||
return ncaFiles[ncaNumber];
|
||||
}
|
||||
/**
|
||||
* Return bodySize
|
||||
* */
|
||||
public long getBodySize(){
|
||||
return bodySize;
|
||||
}
|
||||
/**
|
||||
* Return special NCA file: ticket
|
||||
* (sugar)
|
||||
* */
|
||||
public int getNcaTicketID(){
|
||||
return ticketID;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue