mirror of
https://github.com/martravi/wiiqt6.git
synced 2024-11-25 14:17:00 +01:00
added code for importing a wad into a nand
git-svn-id: http://wiiqt.googlecode.com/svn/trunk@21 389f4c8b-5dfe-645f-db0e-df882bc27289
This commit is contained in:
parent
86c9d73b1e
commit
ba948e0e26
@ -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;
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -51,9 +51,18 @@ 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; }
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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/>
|
||||
|
Loading…
Reference in New Issue
Block a user