mirror of
https://github.com/martravi/wiiqt6.git
synced 2024-11-22 13:29:14 +01:00
* fix bug in NUS downloader that added some titles to the list and then used another list, forgetting about the first 2 titles
* fix bug in nandBin class when the current superblock was the last one git-svn-id: http://wiiqt.googlecode.com/svn/trunk@52 389f4c8b-5dfe-645f-db0e-df882bc27289
This commit is contained in:
parent
da0f3cc79e
commit
dfd31fe4ed
@ -48,115 +48,241 @@ bool NandBin::SetPath( const QString &path )
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#if 0 // apparently you dont need any extra reserved blocks for the thing to boot?
|
||||||
bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks )
|
bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks )
|
||||||
{
|
{
|
||||||
#ifndef NAND_BIN_CAN_WRITE
|
#ifndef NAND_BIN_CAN_WRITE
|
||||||
qWarning() << __FILE__ << "was built without write support";
|
qWarning() << __FILE__ << "was built without write support";
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
if( keys.size() != 0x400 || first8.size() != 0x108000 )
|
if( keys.size() != 0x400 || first8.size() != 0x108000 )
|
||||||
{
|
{
|
||||||
qWarning() << "NandBin::CreateNew -> bad sizes" << hex << keys.size() << first8.size();
|
qWarning() << "NandBin::CreateNew -> bad sizes" << hex << keys.size() << first8.size();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( f.isOpen() )
|
if( f.isOpen() )
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
//create the new file, write the first 8 blocks, fill it with 0xff, and write the keys.bin at the end
|
//create the new file, write the first 8 blocks, fill it with 0xff, and write the keys.bin at the end
|
||||||
f.setFileName( path );
|
f.setFileName( path );
|
||||||
if( !f.open( QIODevice::ReadWrite | QIODevice::Truncate ) )
|
if( !f.open( QIODevice::ReadWrite | QIODevice::Truncate ) )
|
||||||
{
|
{
|
||||||
qWarning() << "NandBin::CreateNew -> can't create file" << path;
|
qWarning() << "NandBin::CreateNew -> can't create file" << path;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
f.write( first8 );
|
f.write( first8 );
|
||||||
QByteArray block( 0x4200, 0xff );//generic empty block
|
QByteArray block( 0x4200, 0xff );//generic empty block
|
||||||
for( quint16 i = 0; i < 0x7fc0; i++ )
|
for( quint16 i = 0; i < 0x7fc0; i++ )
|
||||||
f.write( block );
|
f.write( block );
|
||||||
|
|
||||||
f.write( keys );
|
f.write( keys );
|
||||||
if( f.pos() != 0x21000400 )//no room left on the drive?
|
if( f.pos() != 0x21000400 )//no room left on the drive?
|
||||||
{
|
{
|
||||||
qWarning() << "NandBin::CreateNew -> dump size is wrong" << (quint32)f.pos();
|
qWarning() << "NandBin::CreateNew -> dump size is wrong" << (quint32)f.pos();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup variables
|
//setup variables
|
||||||
nandPath = path;
|
nandPath = path;
|
||||||
currentSuperCluster = 0x7f00;
|
currentSuperCluster = 0x7f00;
|
||||||
superClusterVersion = 1;
|
superClusterVersion = 0xf0000000;
|
||||||
type = 2;
|
type = 2;
|
||||||
fats.clear();
|
fats.clear();
|
||||||
memset( &fsts, 0, sizeof( fst_t ) * 0x17ff );
|
memset( &fsts, 0, sizeof( fst_t ) * 0x17ff );
|
||||||
|
|
||||||
for( quint16 i = 0; i < 0x17ff; i++ )
|
for( quint16 i = 0; i < 0x17ff; i++ )
|
||||||
fsts[ i ].fst_pos = i;
|
fsts[ i ].fst_pos = i;
|
||||||
|
|
||||||
//reserve blocks 0 - 7
|
//reserve blocks 0 - 7
|
||||||
for( quint16 i = 0; i < 0x40; i++ )
|
for( quint16 i = 0; i < 0x40; i++ )
|
||||||
{
|
{
|
||||||
fats << 0xfffc;
|
fats << 0xfffc;
|
||||||
}
|
}
|
||||||
//find 90 blocks to reserve. they always appear to be close to the end of the nand
|
//find 90 blocks to reserve. they always appear to be close to the end of the nand
|
||||||
//TODO - this isnt always 90, all my nands have a different number, and 90 is right in the middle
|
//TODO - this isnt always 90, all my nands have a different number, and 90 is right in the middle
|
||||||
quint16 bCnt = badBlocks.size();
|
//quint16 bCnt = badBlocks.size();
|
||||||
quint16 offset = 0;
|
/*quint16 offset = 0;
|
||||||
for( quint16 i = 0; i < bCnt; i++ )
|
for( quint16 i = 0; i < bCnt; i++ )
|
||||||
{
|
{
|
||||||
if( i >= 3998 )
|
if( i >= 3998 )
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//mark all the "normal" blocks - free, or bad
|
//mark all the "normal" blocks - free, or bad
|
||||||
for( quint16 i = 0x40; i < 0x7cf0 - bCnt; i++ )
|
for( quint16 i = 0x40; i < 0x7f00; i++ )
|
||||||
{
|
{
|
||||||
if( badBlocks.contains( i / 8 ) )
|
if( badBlocks.contains( i / 8 ) )
|
||||||
fats << 0xfffd;
|
fats << 0xfffd;
|
||||||
else
|
else
|
||||||
fats << 0xfffe;
|
fats << 0xfffe;
|
||||||
|
|
||||||
}
|
}
|
||||||
//mark the 90 reserved ones from above and reserve the superclusters
|
//mark the 90 reserved ones from above and reserve the superclusters
|
||||||
for( quint16 i = 0x7cf0 - bCnt; i < 0x8000; i++ )
|
for( quint16 i = 0x7f00; i < 0x8000; i++ )
|
||||||
{
|
{
|
||||||
fats << 0xfffc;
|
fats << 0xfffc;
|
||||||
}
|
}
|
||||||
|
|
||||||
//make the root item
|
//make the root item
|
||||||
fsts[ 0 ].filename[ 0 ] = '/';
|
fsts[ 0 ].filename[ 0 ] = '/';
|
||||||
fsts[ 0 ].attr = 0x16;
|
fsts[ 0 ].attr = 0x16;
|
||||||
fsts[ 0 ].sib = 0xffff;
|
fsts[ 0 ].sib = 0xffff;
|
||||||
fsts[ 0 ].sub = 0xffff;
|
fsts[ 0 ].sub = 0xffff;
|
||||||
|
|
||||||
fstInited = true;
|
fstInited = true;
|
||||||
|
|
||||||
//set keys
|
//set keys
|
||||||
QByteArray hmacKey = keys.mid( 0x144, 0x14 );
|
QByteArray hmacKey = keys.mid( 0x144, 0x14 );
|
||||||
spare.SetHMacKey( hmacKey );//set the hmac key for calculating spare data
|
spare.SetHMacKey( hmacKey );//set the hmac key for calculating spare data
|
||||||
key = keys.mid( 0x158, 0x10 );
|
key = keys.mid( 0x158, 0x10 );
|
||||||
|
|
||||||
//write the metada to each of the superblocks
|
//write the metada to each of the superblocks
|
||||||
for( quint8 i = 0; i < 0x10; i++ )
|
for( quint8 i = 0; i < 0x10; i++ )
|
||||||
{
|
{
|
||||||
if( !WriteMetaData() )
|
if( !WriteMetaData() )
|
||||||
{
|
{
|
||||||
qWarning() << "NandBin::CreateNew -> error writing superblock" << i;
|
qWarning() << "NandBin::CreateNew -> error writing superblock" << i;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//build the tree
|
//build the tree
|
||||||
if( root )
|
if( root )
|
||||||
delete root;
|
delete root;
|
||||||
root = new QTreeWidgetItem( QStringList() << nandPath );
|
root = new QTreeWidgetItem( QStringList() << nandPath );
|
||||||
AddChildren( root, 0 );
|
AddChildren( root, 0 );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
//#if 0 // this boots ok on real HW
|
||||||
|
bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks )
|
||||||
|
{
|
||||||
|
#ifndef NAND_BIN_CAN_WRITE
|
||||||
|
qWarning() << __FILE__ << "was built without write support";
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
if( keys.size() != 0x400 || first8.size() != 0x108000 )
|
||||||
|
{
|
||||||
|
qWarning() << "NandBin::CreateNew -> bad sizes" << hex << keys.size() << first8.size();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for( quint16 i = 0; i < 0x40; i++ )
|
||||||
|
{
|
||||||
|
if( badBlocks.contains( i / 8 ) )
|
||||||
|
{
|
||||||
|
qWarning() << "NandBin::CreateNew -> creating a nand with bad blocks in the first 8 is not supported";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( quint16 i = 0x7f00; i < 0x8000; i++ )
|
||||||
|
{
|
||||||
|
if( badBlocks.contains( i / 8 ) )
|
||||||
|
{
|
||||||
|
qWarning() << "NandBin::CreateNew -> creating a nand with bad blocks in the superclusters not supported";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( f.isOpen() )
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
//create the new file, write the first 8 blocks, fill it with 0xff, and write the keys.bin at the end
|
||||||
|
f.setFileName( path );
|
||||||
|
if( !f.open( QIODevice::ReadWrite | QIODevice::Truncate ) )
|
||||||
|
{
|
||||||
|
qWarning() << "NandBin::CreateNew -> can't create file" << path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
f.write( first8 );
|
||||||
|
QByteArray block( 0x4200, 0xff );//generic empty block
|
||||||
|
for( quint16 i = 0; i < 0x7fc0; i++ )
|
||||||
|
f.write( block );
|
||||||
|
|
||||||
|
f.write( keys );
|
||||||
|
if( f.pos() != 0x21000400 )//no room left on the drive?
|
||||||
|
{
|
||||||
|
qWarning() << "NandBin::CreateNew -> dump size is wrong" << (quint32)f.pos();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//setup variables
|
||||||
|
nandPath = path;
|
||||||
|
currentSuperCluster = 0x7f00;
|
||||||
|
superClusterVersion = 1;
|
||||||
|
type = 2;
|
||||||
|
fats.clear();
|
||||||
|
memset( &fsts, 0, sizeof( fst_t ) * 0x17ff );
|
||||||
|
|
||||||
|
for( quint16 i = 0; i < 0x17ff; i++ )
|
||||||
|
fsts[ i ].fst_pos = i;
|
||||||
|
|
||||||
|
//reserve blocks 0 - 7
|
||||||
|
for( quint16 i = 0; i < 0x40; i++ )
|
||||||
|
{
|
||||||
|
fats << 0xfffc;
|
||||||
|
}
|
||||||
|
//find 90 blocks to reserve. they always appear to be close to the end of the nand
|
||||||
|
//TODO - this isnt always 90, all my nands have a different number, and 90 is right in the middle
|
||||||
|
quint16 bCnt = badBlocks.size();
|
||||||
|
quint16 offset = 0;
|
||||||
|
for( quint16 i = 0; i < bCnt; i++ )
|
||||||
|
{
|
||||||
|
if( i >= 3998 )
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//mark all the "normal" blocks - free, or bad
|
||||||
|
for( quint16 i = 0x40; i < 0x7cf0 - offset; i++ )
|
||||||
|
{
|
||||||
|
if( badBlocks.contains( i / 8 ) )
|
||||||
|
fats << 0xfffd;
|
||||||
|
else
|
||||||
|
fats << 0xfffe;
|
||||||
|
|
||||||
|
}
|
||||||
|
//mark the 90 reserved ones from above and reserve the superclusters
|
||||||
|
for( quint16 i = 0x7cf0 - offset; i < 0x8000; i++ )
|
||||||
|
{
|
||||||
|
fats << 0xfffc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//make the root item
|
||||||
|
fsts[ 0 ].filename[ 0 ] = '/';
|
||||||
|
fsts[ 0 ].attr = 0x16;
|
||||||
|
fsts[ 0 ].sib = 0xffff;
|
||||||
|
fsts[ 0 ].sub = 0xffff;
|
||||||
|
|
||||||
|
fstInited = true;
|
||||||
|
|
||||||
|
//set keys
|
||||||
|
QByteArray hmacKey = keys.mid( 0x144, 0x14 );
|
||||||
|
spare.SetHMacKey( hmacKey );//set the hmac key for calculating spare data
|
||||||
|
key = keys.mid( 0x158, 0x10 );
|
||||||
|
|
||||||
|
//write the metada to each of the superblocks
|
||||||
|
for( quint8 i = 0; i < 0x10; i++ )
|
||||||
|
{
|
||||||
|
if( !WriteMetaData() )
|
||||||
|
{
|
||||||
|
qWarning() << "NandBin::CreateNew -> error writing superblock" << i;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the tree
|
||||||
|
if( root )
|
||||||
|
delete root;
|
||||||
|
root = new QTreeWidgetItem( QStringList() << nandPath );
|
||||||
|
AddChildren( root, 0 );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
QTreeWidgetItem *NandBin::GetTree()
|
QTreeWidgetItem *NandBin::GetTree()
|
||||||
{
|
{
|
||||||
//qDebug() << "NandBin::GetTree()";
|
//qDebug() << "NandBin::GetTree()";
|
||||||
@ -334,8 +460,9 @@ bool NandBin::ExtractFile( fst_t fst, const QString &parent )
|
|||||||
emit SendText( tr( "Extracting \"%1\"" ).arg( fi.absoluteFilePath() ) );
|
emit SendText( tr( "Extracting \"%1\"" ).arg( fi.absoluteFilePath() ) );
|
||||||
|
|
||||||
QByteArray data = GetFile( fst );
|
QByteArray data = GetFile( fst );
|
||||||
if( fst.size && !data.size() )//dont worry if files dont have anything in them anyways
|
if( fst.size && !data.size() )//dont worry if files dont have anything in them anyways
|
||||||
return false;
|
//return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
if( !WriteFile( fi.absoluteFilePath(), data ) )
|
if( !WriteFile( fi.absoluteFilePath(), data ) )
|
||||||
{
|
{
|
||||||
@ -588,28 +715,36 @@ qint32 NandBin::FindSuperblock()
|
|||||||
f.read( (char*)¤t, 4 );
|
f.read( (char*)¤t, 4 );
|
||||||
current = qFromBigEndian( current );
|
current = qFromBigEndian( current );
|
||||||
|
|
||||||
//qDebug() << "superblock" << hex << current << currentSuperCluster << loc;
|
//qDebug() << "superblock" << hex << current << currentSuperCluster << loc;
|
||||||
|
|
||||||
if( current > superClusterVersion )
|
if( current > superClusterVersion )
|
||||||
superClusterVersion = current;
|
superClusterVersion = current;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//qDebug() << "using superblock" << hex << superClusterVersion << currentSuperCluster - 0x10 << f.pos() - n_len[ type ];
|
//qDebug() << "using superblock" << hex << superClusterVersion << currentSuperCluster - 0x10 << f.pos() - n_len[ type ];
|
||||||
currentSuperCluster -= ( 0x10 * rewind );
|
//currentSuperCluster -= ( 0x10 * rewind );
|
||||||
loc -= ( n_len[ type ] * rewind );
|
//loc -= ( n_len[ type ] * rewind );
|
||||||
|
rewind = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if( loc == n_end[ type ] )
|
||||||
|
{
|
||||||
|
rewind = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( !superClusterVersion )
|
if( !superClusterVersion )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
//qDebug() << "using superblock" << hex << superClusterVersion << currentSuperCluster << "page:" << ( loc / 0x840 );
|
currentSuperCluster -= ( 0x10 * rewind );
|
||||||
|
loc -= ( n_len[ type ] * rewind );
|
||||||
|
|
||||||
|
//qDebug() << "using superblock" << hex << superClusterVersion << currentSuperCluster << "page:" << ( loc / 0x840 );
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
fst_t NandBin::GetFST( quint16 entry )
|
fst_t NandBin::GetFST( quint16 entry )
|
||||||
{
|
{
|
||||||
//qDebug() << "NandBin::GetFST(" << hex << entry << ")";
|
//qDebug() << "NandBin::GetFST(" << hex << entry << ")";
|
||||||
fst_t fst;
|
fst_t fst;
|
||||||
if( entry >= 0x17FF )
|
if( entry >= 0x17FF )
|
||||||
{
|
{
|
||||||
@ -627,6 +762,7 @@ fst_t NandBin::GetFST( quint16 entry )
|
|||||||
int loc_entry = ( ( ( entry / 0x40 ) * n_fst[ type ] ) + entry ) * 0x20;
|
int loc_entry = ( ( ( entry / 0x40 ) * n_fst[ type ] ) + entry ) * 0x20;
|
||||||
if( (quint32)f.size() < loc_fst + loc_entry + sizeof( fst_t ) )
|
if( (quint32)f.size() < loc_fst + loc_entry + sizeof( fst_t ) )
|
||||||
{
|
{
|
||||||
|
qDebug() << hex << (quint32)f.size() << loc_fst << loc_entry << type << n_fst[ type ];
|
||||||
emit SendError( tr( "Tried to read fst_t beyond size of nand.bin" ) );
|
emit SendError( tr( "Tried to read fst_t beyond size of nand.bin" ) );
|
||||||
fst.filename[ 0 ] = '\0';
|
fst.filename[ 0 ] = '\0';
|
||||||
return fst;
|
return fst;
|
||||||
|
@ -531,11 +531,7 @@ bool NusDownloader::GetUpdate( const QString & upd, bool decrypt )
|
|||||||
QString s = upd.toLower();
|
QString s = upd.toLower();
|
||||||
QMap< quint64, quint16 > titles;
|
QMap< quint64, quint16 > titles;
|
||||||
|
|
||||||
//hell, give everybody these.
|
if( s == "2.1e" ) titles = List21e();
|
||||||
titles.insert( 0x1000248414741ull, 0x3 );//news channel HAGA
|
|
||||||
titles.insert( 0x1000248414641ull, 0x3 );//Weather Channel HAFA
|
|
||||||
|
|
||||||
if( s == "2.1e" ) titles = List21e();
|
|
||||||
else if( s == "3.0e" ) titles = List30e();
|
else if( s == "3.0e" ) titles = List30e();
|
||||||
else if( s == "3.1e" ) titles = List31e();
|
else if( s == "3.1e" ) titles = List31e();
|
||||||
else if( s == "3.3e" ) titles = List33e();
|
else if( s == "3.3e" ) titles = List33e();
|
||||||
@ -572,6 +568,10 @@ bool NusDownloader::GetUpdate( const QString & upd, bool decrypt )
|
|||||||
|
|
||||||
else return false;//unknown update
|
else return false;//unknown update
|
||||||
|
|
||||||
|
//hell, give everybody these.
|
||||||
|
titles.insert( 0x1000248414741ull, 0x3 );//news channel HAGA
|
||||||
|
titles.insert( 0x1000248414641ull, 0x3 );//Weather Channel HAFA
|
||||||
|
|
||||||
QMap< quint64, quint16 >::ConstIterator i = titles.begin();
|
QMap< quint64, quint16 >::ConstIterator i = titles.begin();
|
||||||
while( i != titles.end() )
|
while( i != titles.end() )
|
||||||
{
|
{
|
||||||
@ -855,8 +855,8 @@ QMap< quint64, quint16 > NusDownloader::List30e()
|
|||||||
titles.insert( 0x1000248414341ull, 4 );//nigaoeNRv4 - MII
|
titles.insert( 0x1000248414341ull, 4 );//nigaoeNRv4 - MII
|
||||||
titles.insert( 0x1000248414141ull, 0x1 );//photov1
|
titles.insert( 0x1000248414141ull, 0x1 );//photov1
|
||||||
titles.insert( 0x1000248414241ull, 7 );//shoppingv7
|
titles.insert( 0x1000248414241ull, 7 );//shoppingv7
|
||||||
titles.insert( 0x1000248414741ull, 0x3 );//news channel HAGA
|
// titles.insert( 0x1000248414741ull, 0x3 );//news channel HAGA
|
||||||
titles.insert( 0x1000248414641ull, 0x3 );//Weather Channel HAFA
|
// titles.insert( 0x1000248414641ull, 0x3 );//Weather Channel HAFA
|
||||||
return titles;
|
return titles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ QList< quint64 > tids;
|
|||||||
QList< quint64 > validIoses;//dont put stubs in this list.
|
QList< quint64 > validIoses;//dont put stubs in this list.
|
||||||
QTreeWidgetItem *root;
|
QTreeWidgetItem *root;
|
||||||
QList<quint16> fats;
|
QList<quint16> fats;
|
||||||
|
quint32 verbose = 0;
|
||||||
|
|
||||||
|
|
||||||
bool CheckTitleIntegrity( quint64 tid );
|
bool CheckTitleIntegrity( quint64 tid );
|
||||||
@ -29,8 +30,9 @@ void Usage()
|
|||||||
qDebug() << " check installed titles for required IOS, proper uid & gid";
|
qDebug() << " check installed titles for required IOS, proper uid & gid";
|
||||||
qDebug() << " -clInfo shows free, used, and lost ( marked used, but dont belong to any file ) clusters";
|
qDebug() << " -clInfo shows free, used, and lost ( marked used, but dont belong to any file ) clusters";
|
||||||
qDebug() << " -spare calculate & compare ecc for all pages in the nand";
|
qDebug() << " -spare calculate & compare ecc for all pages in the nand";
|
||||||
qDebug() << " calculate & compare hmac signatures for all files and superblocks";
|
qDebug() << " calculate & compare hmac signatures for all files and superblocks";
|
||||||
qDebug() << " -all does all of the above";
|
qDebug() << " -all does all of the above";
|
||||||
|
qDebug() << " -v increase verbosity";
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,18 +372,23 @@ bool CheckTitleIntegrity( quint64 tid )
|
|||||||
t = Tmd( ba );
|
t = Tmd( ba );
|
||||||
if( t.Tid() != tid )
|
if( t.Tid() != tid )
|
||||||
{
|
{
|
||||||
qDebug() << "the TMD contains the wrong TID";
|
qDebug() << "\tthe TMD contains the wrong TID";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if( verbose )
|
||||||
|
{
|
||||||
|
qDebug() << "\tversion:" << t.Version() << hex << t.Version();
|
||||||
|
qDebug() << "\taccess :" << hex << t.AccessFlags();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ticket ticket( ba, false );
|
Ticket ticket( ba, false );
|
||||||
if( ticket.Tid() != tid )
|
if( ticket.Tid() != tid )
|
||||||
{
|
{
|
||||||
qDebug() << "the ticket contains the wrong TID";
|
qDebug() << "\tthe ticket contains the wrong TID";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,6 +657,8 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
root = NULL;
|
root = NULL;
|
||||||
|
|
||||||
|
verbose = args.count( "-v" );
|
||||||
|
|
||||||
//these only serve to show info. no action is taken
|
//these only serve to show info. no action is taken
|
||||||
if( args.contains( "-boot", Qt::CaseInsensitive ) || args.contains( "-all", Qt::CaseInsensitive ) )
|
if( args.contains( "-boot", Qt::CaseInsensitive ) || args.contains( "-all", Qt::CaseInsensitive ) )
|
||||||
{
|
{
|
||||||
|
@ -146,7 +146,7 @@ void MainWindow::NusIsDone()
|
|||||||
|
|
||||||
//make sure there is a setting.txt
|
//make sure there is a setting.txt
|
||||||
QTreeWidgetItem *item = ItemFromPath( "/title/00000001/00000002/data/setting.txt" );
|
QTreeWidgetItem *item = ItemFromPath( "/title/00000001/00000002/data/setting.txt" );
|
||||||
if( !item )
|
if( !item && ItemFromPath( "/title/00000001/00000002/data" ) )//only try to make setting.txt if it is missing and there is a folder to hold it
|
||||||
{
|
{
|
||||||
quint8 reg = SETTING_TXT_UNK;
|
quint8 reg = SETTING_TXT_UNK;
|
||||||
if( ui->lineEdit_tid->text().endsWith( "e", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 )
|
if( ui->lineEdit_tid->text().endsWith( "e", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 )
|
||||||
@ -165,7 +165,7 @@ void MainWindow::NusIsDone()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( !nand.SetData( r, ba) )
|
if( !nand.SetData( r, ba ) )
|
||||||
{
|
{
|
||||||
ShowMessage( "<b>Error writing data for setting.txt.</b>" );
|
ShowMessage( "<b>Error writing data for setting.txt.</b>" );
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ void MainWindow::NusIsDone()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//nand.Delete( "/title/00000001/00000002/content/title.tmd" );
|
//nand.Delete( "/title/00000001/00000002/content/title.tmd" );
|
||||||
if( nandDirty )
|
if( nandDirty )
|
||||||
@ -310,40 +310,43 @@ void MainWindow::on_actionImportWad_triggered()
|
|||||||
{
|
{
|
||||||
ShowMessage( tr( "<b>Error setting the basepath of the nand to %1</b>" ).arg( QFileInfo( ui->lineEdit_nandPath->text() ).absoluteFilePath() ) );
|
ShowMessage( tr( "<b>Error setting the basepath of the nand to %1</b>" ).arg( QFileInfo( ui->lineEdit_nandPath->text() ).absoluteFilePath() ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString fn = QFileDialog::getOpenFileName( this, tr("Wad files(*.wad)"), QCoreApplication::applicationDirPath(), tr("WadFiles (*.wad)") );
|
//QString fn = QFileDialog::getOpenFileName( this, tr("Wad files(*.wad)"), QCoreApplication::applicationDirPath(), tr("WadFiles (*.wad)") );
|
||||||
|
QStringList fns = QFileDialog::getOpenFileNames( this, tr("Wad files(*.wad)"), QCoreApplication::applicationDirPath(), tr("WadFiles (*.wad)") );
|
||||||
|
|
||||||
if( fn.isEmpty() )
|
if( fns.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
foreach( QString fn, fns )
|
||||||
|
{
|
||||||
|
QByteArray data = ReadFile( fn );
|
||||||
|
if( data.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
QByteArray data = ReadFile( fn );
|
Wad wad( data );
|
||||||
if( data.isEmpty() )
|
if( !wad.IsOk() )
|
||||||
return;
|
{
|
||||||
|
ShowMessage( tr( "Wad data not ok for \"%1\"" ).arg( fn ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Wad wad( data );
|
//work smart, not hard... just turn the wad into a NUSJob and reused the same code to install it
|
||||||
if( !wad.IsOk() )
|
NusJob job;
|
||||||
{
|
job.tid = wad.Tid();
|
||||||
ShowMessage( tr( "Wad data not ok for \"%1\"" ).arg( fn ) );
|
job.data << wad.getTmd();
|
||||||
return;
|
job.data << wad.getTik();
|
||||||
}
|
|
||||||
|
|
||||||
//work smart, not hard... just turn the wad into a NUSJob and reused the same code to install it
|
Tmd t( wad.getTmd() );
|
||||||
NusJob job;
|
job.version = t.Version();
|
||||||
job.tid = wad.Tid();
|
quint16 cnt = t.Count();
|
||||||
job.data << wad.getTmd();
|
for( quint16 i = 0; i < cnt; i++ )
|
||||||
job.data << wad.getTik();
|
{
|
||||||
|
job.data << wad.Content( i );
|
||||||
|
}
|
||||||
|
|
||||||
Tmd t( wad.getTmd() );
|
job.decrypt = true;
|
||||||
job.version = t.Version();
|
ShowMessage( tr( "Installing %1 to nand" ).arg( fn ) );
|
||||||
quint16 cnt = t.Count();
|
InstallNUSItem( job );
|
||||||
for( quint16 i = 0; i < cnt; i++ )
|
}
|
||||||
{
|
|
||||||
job.data << wad.Content( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
job.decrypt = true;
|
|
||||||
ShowMessage( tr( "Installing %1 to nand" ).arg( fn ) );
|
|
||||||
InstallNUSItem( job );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +441,7 @@ bool MainWindow::InitNand( const QString &path )
|
|||||||
//nand.Delete( "/title/00000001/00000002/content/title.tmd" );
|
//nand.Delete( "/title/00000001/00000002/content/title.tmd" );
|
||||||
|
|
||||||
nandInited = true;
|
nandInited = true;
|
||||||
ShowMessage( "Set path to nand as " + path );
|
ShowMessage( "Set path to nand as " + path );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,3 +759,29 @@ void MainWindow::on_actionAbout_triggered()
|
|||||||
"<br>giantpune" );
|
"<br>giantpune" );
|
||||||
QMessageBox::critical( this, tr( "About" ), txt );
|
QMessageBox::critical( this, tr( "About" ), txt );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
//add a default settings file if there is one laying around
|
||||||
|
void MainWindow::TryToAddDefaultSettings()
|
||||||
|
{
|
||||||
|
if( ItemFromPath( "/shared2/sys/SYSCONF" ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QByteArray stuff = ReadFile( "./default_SYSCONF" );
|
||||||
|
if( stuff.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
quint32 uiD = uid.GetUid( NAND_TEST_OWNER );
|
||||||
|
if( !CreateIfNeeded( "/shared2/sys", uiD, NAND_TEST_GROUP, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
quint16 handle = nand.CreateEntry( "/shared2/sys/SYSCONF", uiD, NAND_TEST_GROUP, NAND_FILE, NAND_RW, NAND_RW, NAND_RW );
|
||||||
|
if( !handle || !nand.SetData( handle, stuff ) || !nand.WriteMetaData() )
|
||||||
|
{
|
||||||
|
ShowMessage( "<b>Error adding the default settings</b>" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UpdateTree();
|
||||||
|
ShowMessage( "Wrote /shared2/sys/SYSCONF" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -48,6 +48,9 @@ private:
|
|||||||
|
|
||||||
void SaveSettings();
|
void SaveSettings();
|
||||||
void LoadSettings();
|
void LoadSettings();
|
||||||
|
#if 0
|
||||||
|
void TryToAddDefaultSettings();
|
||||||
|
#endif
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
//slots for getting info from the NUS downloader
|
//slots for getting info from the NUS downloader
|
||||||
|
@ -145,8 +145,28 @@ void NgDialog::on_pushButton_keys_clicked()
|
|||||||
if( fn.isEmpty() )
|
if( fn.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QByteArray ba = ReadFile( fn );
|
QFile file( fn );
|
||||||
if( ba.size() != 0x400 )
|
QByteArray ba;
|
||||||
|
switch( file.size() )
|
||||||
|
{
|
||||||
|
case 0x400:
|
||||||
|
if( !file.open( QIODevice::ReadOnly ) )
|
||||||
|
break;
|
||||||
|
ba = file.readAll();
|
||||||
|
file.close();
|
||||||
|
break;
|
||||||
|
case 0x21000400:
|
||||||
|
if( !file.open( QIODevice::ReadOnly ) )
|
||||||
|
break;
|
||||||
|
file.seek( 0x21000000 );
|
||||||
|
ba = file.read( 0x400 );
|
||||||
|
file.close();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ba.size() != 0x400 )
|
||||||
{
|
{
|
||||||
ui->label_message->setText( tr( "keys.bin should be 0x400 bytes" ) );
|
ui->label_message->setText( tr( "keys.bin should be 0x400 bytes" ) );
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user