added code for importing a wad into a nand

This commit is contained in:
megazig 2010-12-16 20:07:38 +00:00
parent 0ddcbca710
commit 6ce5ffc566
8 changed files with 191 additions and 27 deletions

View File

@ -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;

View File

@ -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 );

View File

@ -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

View File

@ -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( &copy );
b.open( QIODevice::ReadOnly );
QByteArray copy = stuff;
QBuffer b( &copy );
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;

View File

@ -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; }

View File

@ -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( "<b>Error setting the basepath of the nand to %1</b>" ).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( "<b>Error %1 title to nand</b>" ).arg( wad.WadName() ) );
}
//save a NUS job to a folder
void MainWindow::SaveJobToFolder( NusJob job )
{

View File

@ -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();

View File

@ -218,6 +218,7 @@
</property>
<addaction name="actionSetting_txt"/>
<addaction name="actionFlush"/>
<addaction name="actionImportWad"/>
</widget>
<addaction name="menuNand_Dump"/>
</widget>
@ -240,6 +241,11 @@
<string>Flush</string>
</property>
</action>
<action name="actionImportWad">
<property name="text">
<string>Import Wad</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>