diff --git a/WiiQt/nanddump.cpp b/WiiQt/nanddump.cpp
index f52e85d..c0d27df 100644
--- a/WiiQt/nanddump.cpp
+++ b/WiiQt/nanddump.cpp
@@ -418,6 +418,80 @@ bool NandDump::InstallNusItem( NusJob job )
return true;
}
+bool NandDump::InstallWad( Wad wad )
+{
+ if( !wad.Tid() || wad.content_count() < 3 )
+ {
+ qWarning() << "NandDump::InstallNusItem -> invalid item";
+ return false;
+ }
+ if( !uidDirty )
+ {
+ uidDirty = uidMap.GetUid( wad.Tid(), false ) == 0;//only flag the uid as dirty if it has to be, this way it is only flushed if needed
+ }
+ uidMap.GetUid( wad.Tid() );
+ QString p = QString( "%1" ).arg( wad.Tid(), 16, 16, QChar( '0' ) );
+ p.insert( 8 ,"/" );
+ p.prepend( "/title/" );
+ QString path = basePath + p + "/content";
+ if( !QFileInfo( path ).exists() && !QDir().mkpath( path ) )
+ return false;
+
+ path = basePath + p + "/data";
+ if( !QFileInfo( path ).exists() && !QDir().mkpath( path ) )
+ return false;
+
+ QByteArray ba = wad.getTmd();
+ if( !InstallTmd( ba, wad.Tid() ) )
+ return false;
+
+ Tmd t( ba );
+
+ ba = wad.getTik();
+ Ticket ti( ba );
+ if( !InstallTicket( ba, wad.Tid() ) )
+ {
+ AbortInstalling( wad.Tid() );
+ return false;
+ }
+
+ quint32 cnt = qFromBigEndian( t.payload()->num_contents );
+ if( cnt != wad.content_count() )
+ {
+ AbortInstalling( wad.Tid() );
+ return false;
+ }
+
+ for( quint32 i = 0; i < cnt; i++ )
+ {
+ QByteArray decData = wad.Content(i);
+
+ if( t.Type( i ) == 0x8001 )
+ {
+ if( !InstallSharedContent( decData, t.Hash( i ) ) )
+ {
+ AbortInstalling( wad.Tid() );
+ return false;
+ }
+ }
+ else if( t.Type( i ) == 1 )
+ {
+ if( !InstallPrivateContent( decData, wad.Tid(), t.Cid( i ) ) )
+ {
+ AbortInstalling( wad.Tid() );
+ return false;
+ }
+ }
+ else//unknown content type
+ {
+ qWarning() << "NandDump::InstallWad -> unknown content type";
+ AbortInstalling( wad.Tid() );
+ return false;
+ }
+ }
+ return true;
+}
+
QMap< quint64, quint16 > NandDump::GetInstalledTitles()
{
QMap< quint64, quint16 >ret;
diff --git a/WiiQt/nanddump.h b/WiiQt/nanddump.h
index b8de5c7..efe5fd3 100644
--- a/WiiQt/nanddump.h
+++ b/WiiQt/nanddump.h
@@ -5,6 +5,7 @@
#include "includes.h"
#include "sharedcontentmap.h"
#include "uidmap.h"
+#include "wad.h"
struct SaveGame//struct to hold save data
{
@@ -54,6 +55,10 @@ public:
//returns false if something went wrong
bool InstallNusItem( NusJob job );
+ //installs a title to the nand dump from a wad
+ //returns false if something went wrong
+ bool InstallWad( Wad wad );
+
//tries to delete a title from the nand dump
//deleteData gives the option to just delete the title and leave behind its data
bool DeleteTitle( quint64 tid, bool deleteData = false );
diff --git a/WiiQt/nusdownloader.cpp b/WiiQt/nusdownloader.cpp
index 5e08010..6a406e2 100644
--- a/WiiQt/nusdownloader.cpp
+++ b/WiiQt/nusdownloader.cpp
@@ -618,7 +618,7 @@ QMap< quint64, quint16 > NusDownloader::List31j()
//titles.insert( 0x100000025ull, 2070 );//37v2070//3.1u has this one but not 3.1j??
titles.insert( 0x1000248415941ull, 0x1 );//photo2v1
titles.insert( 0x1000848414B4aull, 0 );//EULA - HAKJ
- titles.insert( 0x100024841464a, 0x7 ); // forcast v7 HAFJ
+ titles.insert( 0x100024841464aull, 0x7 );// forcast v7 HAFJ
titles.insert( 0x100000101ull, 5 );//miosv5
titles.insert( 0x1000848414C4aull, 0x2 );//regsel //region select isnt in the paper mario update, but putting it here just to be safe
titles.insert( 0x1000248414341ull, 0x2 );//nigaoeNRv2 - MII
diff --git a/WiiQt/wad.cpp b/WiiQt/wad.cpp
index fa53750..ec1d01c 100644
--- a/WiiQt/wad.cpp
+++ b/WiiQt/wad.cpp
@@ -6,34 +6,42 @@ static QByteArray globalCert;
Wad::Wad( const QByteArray stuff )
{
- ok = false;
- if( stuff.size() < 0x80 )//less than this and there is definitely nothing there
- {
- Err( "Size is < 0x80" );
- return;
- }
+ ok = false;
+ if( stuff.size() < 0x80 )//less than this and there is definitely nothing there
+ {
+ Err( "Size is < 0x80" );
+ return;
+ }
- QByteArray copy = stuff;
- QBuffer b( © );
- b.open( QIODevice::ReadOnly );
+ QByteArray copy = stuff;
+ QBuffer b( © );
+ b.open( QIODevice::ReadOnly );
- quint32 tmp;
- b.read( (char*)&tmp, 4 );
- if( qFromBigEndian( tmp ) != 0x20 )
- {
- b.close();
- Err( "Bad header size" );
- return;
- }
- b.read( (char*)&tmp, 4 );
- tmp = qFromBigEndian( tmp );
- if( tmp != 0x49730000 && tmp != 0x69620000 && tmp != 0x426b0000 )
- {
- b.close();
- hexdump( stuff, 0, 0x40 );
- Err( "Bad file magic word" );
- return;
- }
+ quint32 tmp;
+ if(b.read( (char*)&tmp, 4 ) != 4)
+ {
+ b.close();
+ Err( "Can't read header size" );
+ return;
+ }
+ if( qFromBigEndian( tmp ) != 0x20 )
+ {
+ b.close();
+ hexdump(stuff, 0, 0x10);
+ Err( "Bad header size" );
+ return;
+ }
+ b.read( (char*)&tmp, 4 );
+ tmp = qFromBigEndian( tmp );
+ if( tmp != 0x49730000 &&
+ tmp != 0x69620000 &&
+ tmp != 0x426b0000 )
+ {
+ b.close();
+ hexdump( stuff, 0, 0x40 );
+ Err( "Bad file magic word" );
+ return;
+ }
quint32 certSize;
quint32 tikSize;
@@ -184,6 +192,16 @@ void Wad::SetGlobalCert( const QByteArray &stuff )
globalCert = stuff;
}
+const QByteArray Wad::getTmd()
+{
+ return tmdData;
+}
+
+const QByteArray Wad::getTik()
+{
+ return tikData;
+}
+
const QByteArray Wad::Content( quint16 i )
{
if( tmdData.isEmpty() || tikData.isEmpty() )
@@ -213,6 +231,11 @@ const QByteArray Wad::Content( quint16 i )
return decData;
}
+quint32 Wad::content_count()
+{
+ return partsEnc.size();
+}
+
void Wad::Err( QString str )
{
ok = false;
diff --git a/WiiQt/wad.h b/WiiQt/wad.h
index 908455a..119c4d4 100644
--- a/WiiQt/wad.h
+++ b/WiiQt/wad.h
@@ -50,10 +50,19 @@ public:
//get all the parts of this wad put together in a wad ready for writing to disc or whatever
const QByteArray Data( quint32 magicWord = 0x49730000, const QByteArray footer = QByteArray() );
+
+ //get the tmd for the wad
+ const QByteArray getTmd();
+
+ //get the tik for the wad
+ const QByteArray getTik();
//get the decrypted data from a content
const QByteArray Content( quint16 i );
+ //get the number of contents
+ quint32 content_count();
+
//get the last error encountered while trying to do something
const QString LastError(){ return errStr; }
diff --git a/nand_dump/mainwindow.cpp b/nand_dump/mainwindow.cpp
index 0730f1b..bbaed57 100644
--- a/nand_dump/mainwindow.cpp
+++ b/nand_dump/mainwindow.cpp
@@ -313,6 +313,52 @@ void MainWindow::on_actionFlush_triggered()
nand.Flush();
}
+//nand-dump -> ImportWad
+void MainWindow::on_actionImportWad_triggered()
+{
+ if( nand.GetPath() != ui->lineEdit_nandPath->text() &&
+ !nand.SetPath( ui->lineEdit_nandPath->text() ) )
+ {
+ ShowMessage( tr( "Error setting the basepath of the nand to %1" ).arg( QFileInfo( ui->lineEdit_nandPath->text() ).absoluteFilePath() ) );
+ return;
+ }
+ QString fn = QFileDialog::getSaveFileName(this,
+ tr("Wad files(*.wad)"),
+ QCoreApplication::applicationDirPath(),
+ tr("WadFiles (*.wad)"));
+ if(fn == "") return;
+
+ QFile f(fn);
+ if(!f.open( QIODevice::ReadOnly)) {
+ ShowMessage( tr( "Error opening %1" ).arg( fn ) );
+ return;
+ }
+
+ qint64 len = f.size();
+ char* buffer = new char[len];
+ qint64 read = f.read(buffer, len);
+ f.close();
+ hexdump(buffer, 0x40);
+ if(read != len) {
+ ShowMessage( tr( "Error reading %1" ).arg( fn ) );
+ free(buffer);
+ return;
+ }
+ QByteArray data(buffer, len);
+ free(buffer);
+ Wad wad(data);
+ if( !wad.IsOk() ) {
+ ShowMessage( tr( "Wad data not ok" ) );;
+ return;
+ }
+
+ bool ok = nand.InstallWad( wad );
+ if( ok )
+ ShowMessage( tr( "Installed %1 title to nand" ).arg( wad.WadName() ) );
+ else
+ ShowMessage( tr( "Error %1 title to nand" ).arg( wad.WadName() ) );
+}
+
//save a NUS job to a folder
void MainWindow::SaveJobToFolder( NusJob job )
{
diff --git a/nand_dump/mainwindow.h b/nand_dump/mainwindow.h
index 48e5b00..2208d7f 100644
--- a/nand_dump/mainwindow.h
+++ b/nand_dump/mainwindow.h
@@ -41,6 +41,7 @@ public slots:
private slots:
void on_actionFlush_triggered();
void on_actionSetting_txt_triggered();
+ void on_actionImportWad_triggered();
void on_pushButton_wad_clicked();
void on_pushButton_decFolder_clicked();
void on_pushButton_nandPath_clicked();
diff --git a/nand_dump/mainwindow.ui b/nand_dump/mainwindow.ui
index 8fbe134..edfb471 100644
--- a/nand_dump/mainwindow.ui
+++ b/nand_dump/mainwindow.ui
@@ -218,6 +218,7 @@
+
@@ -240,6 +241,11 @@
Flush
+
+
+ Import Wad
+
+