mirror of
https://github.com/martravi/wiiqt6.git
synced 2024-11-22 21:29:15 +01:00
*NUSdownloader: get regsel v1 for 2.X updates. v2 requires ios31, which didnt come around till 3.0
*nandBin: #ifdef out code not used when not built with write ability *nandChecker: add stuff for checking system menu against setting.txt * add stuff for displaying title name and other information *ohneswansenegger: fix bug which caused formatted nand to use previous content.map and uid.sys git-svn-id: http://wiiqt.googlecode.com/svn/trunk@63 389f4c8b-5dfe-645f-db0e-df882bc27289
This commit is contained in:
parent
6b5441637b
commit
a283f45b7d
@ -59,9 +59,13 @@ const QString NandBin::FilePath()
|
|||||||
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
|
||||||
|
Q_UNUSED( path );
|
||||||
|
Q_UNUSED( keys );
|
||||||
|
Q_UNUSED( first8 );
|
||||||
|
Q_UNUSED( badBlocks );
|
||||||
qWarning() << __FILE__ << "was built without write support";
|
qWarning() << __FILE__ << "was built without write support";
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#else
|
||||||
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();
|
||||||
@ -152,15 +156,17 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
|||||||
AddChildren( root, 0 );
|
AddChildren( root, 0 );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
bool NandBin::Format( bool secure )
|
bool NandBin::Format( bool secure )
|
||||||
{
|
{
|
||||||
#ifndef NAND_BIN_CAN_WRITE
|
#ifndef NAND_BIN_CAN_WRITE
|
||||||
|
Q_UNUSED( secure );
|
||||||
qWarning() << __FILE__ << "was built without write support";
|
qWarning() << __FILE__ << "was built without write support";
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#else
|
||||||
if( !f.isOpen() || fats.size() != 0x8000 )
|
if( !f.isOpen() || fats.size() != 0x8000 )
|
||||||
{
|
{
|
||||||
qWarning() << "NandBin::Format -> error" << hex << fats.size() << f.isOpen();
|
qWarning() << "NandBin::Format -> error" << hex << fats.size() << f.isOpen();
|
||||||
@ -210,7 +216,7 @@ bool NandBin::Format( bool secure )
|
|||||||
AddChildren( root, 0 );
|
AddChildren( root, 0 );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // this boots ok on real HW. trap15 thinks these reserved blocks are IOS's way of marking ones it thinks are bad
|
#if 0 // this boots ok on real HW. trap15 thinks these reserved blocks are IOS's way of marking ones it thinks are bad
|
||||||
@ -519,7 +525,7 @@ bool NandBin::ExtractFile( fst_t fst, const QString &parent )
|
|||||||
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 true;
|
//return true;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( !WriteFile( fi.absoluteFilePath(), data ) )
|
if( !WriteFile( fi.absoluteFilePath(), data ) )
|
||||||
{
|
{
|
||||||
@ -1254,9 +1260,11 @@ bool NandBin::WriteDecryptedCluster( quint32 pageNo, const QByteArray &data, fst
|
|||||||
bool NandBin::WritePage( quint32 pageNo, const QByteArray &data )
|
bool NandBin::WritePage( quint32 pageNo, const QByteArray &data )
|
||||||
{
|
{
|
||||||
#ifndef NAND_BIN_CAN_WRITE
|
#ifndef NAND_BIN_CAN_WRITE
|
||||||
|
Q_UNUSED( pageNo );
|
||||||
|
Q_UNUSED( data );
|
||||||
qWarning() << __FILE__ << "was built without write support";
|
qWarning() << __FILE__ << "was built without write support";
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#else
|
||||||
//qDebug() << "NandBin::WritePage(" << hex << pageNo << ")";
|
//qDebug() << "NandBin::WritePage(" << hex << pageNo << ")";
|
||||||
quint32 n_pagelen[] = { 0x800, 0x840, 0x840 };
|
quint32 n_pagelen[] = { 0x800, 0x840, 0x840 };
|
||||||
if( (quint32)data.size() != n_pagelen[ type ] )
|
if( (quint32)data.size() != n_pagelen[ type ] )
|
||||||
@ -1274,6 +1282,7 @@ bool NandBin::WritePage( quint32 pageNo, const QByteArray &data )
|
|||||||
//qDebug() << "writing page at:" << f.pos() << hex << (quint32)f.pos();
|
//qDebug() << "writing page at:" << f.pos() << hex << (quint32)f.pos();
|
||||||
//hexdump( data, 0, 0x20 );
|
//hexdump( data, 0, 0x20 );
|
||||||
return ( f.write( data ) == data.size() );
|
return ( f.write( data ) == data.size() );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 NandBin::CreateNode( const QString &name, quint32 uid, quint16 gid, quint8 attr, quint8 user_perm, quint8 group_perm, quint8 other_perm )
|
quint16 NandBin::CreateNode( const QString &name, quint32 uid, quint16 gid, quint8 attr, quint8 user_perm, quint8 group_perm, quint8 other_perm )
|
||||||
|
@ -607,7 +607,7 @@ QMap< quint64, quint16 > NusDownloader::List20j()
|
|||||||
titles.insert( 0x100000100ull, 0x2 ); //bcv2
|
titles.insert( 0x100000100ull, 0x2 ); //bcv2
|
||||||
titles.insert( 0x100000101ull, 0x4 ); //miosv4
|
titles.insert( 0x100000101ull, 0x4 ); //miosv4
|
||||||
titles.insert( 0x1000848414B4aull, 0 ); //EULA - HAKJ
|
titles.insert( 0x1000848414B4aull, 0 ); //EULA - HAKJ
|
||||||
titles.insert( 0x1000848414C4aull, 0x2 ); //regsel //region select isnt in the paper mario update, but putting it here just to be safe
|
titles.insert( 0x1000848414C4aull, 1 ); //regsel //region select isnt in the paper mario update, but putting it here just to be safe
|
||||||
titles.insert( 0x1000248414341ull, 0x2 ); //nigaoeNRv2 - MII
|
titles.insert( 0x1000248414341ull, 0x2 ); //nigaoeNRv2 - MII
|
||||||
titles.insert( 0x1000248414141ull, 0x1 ); //photov1
|
titles.insert( 0x1000248414141ull, 0x1 ); //photov1
|
||||||
titles.insert( 0x1000248414241ull, 0x4 ); //shoppingv4
|
titles.insert( 0x1000248414241ull, 0x4 ); //shoppingv4
|
||||||
@ -859,7 +859,7 @@ QMap< quint64, quint16 > NusDownloader::List20e()
|
|||||||
titles.insert( 0x100000100ull, 0x2 ); //bcv2
|
titles.insert( 0x100000100ull, 0x2 ); //bcv2
|
||||||
titles.insert( 0x100000101ull, 0x4 ); //miosv4
|
titles.insert( 0x100000101ull, 0x4 ); //miosv4
|
||||||
titles.insert( 0x1000848414B50ull, 0 ); //EULA - HAKP
|
titles.insert( 0x1000848414B50ull, 0 ); //EULA - HAKP
|
||||||
titles.insert( 0x1000848414C50ull, 0x2 ); //regsel //region select isnt in the paper mario update, but putting it here just to be safe
|
titles.insert( 0x1000848414C50ull, 1 ); //regsel //region select isnt in the paper mario update, but putting it here just to be safe
|
||||||
titles.insert( 0x1000248414341ull, 0x2 ); //nigaoeNRv2 - MII
|
titles.insert( 0x1000248414341ull, 0x2 ); //nigaoeNRv2 - MII
|
||||||
titles.insert( 0x1000248414141ull, 0x1 ); //photov1
|
titles.insert( 0x1000248414141ull, 0x1 ); //photov1
|
||||||
titles.insert( 0x1000248414241ull, 0x4 ); //shoppingv4
|
titles.insert( 0x1000248414241ull, 0x4 ); //shoppingv4
|
||||||
|
@ -502,6 +502,8 @@ static int check_rsa( const QByteArray &h, const quint8 *sig, const quint8 *key,
|
|||||||
if( strncmp( (char*)h.constData(), (char*) x + n - 20, 20 ) == 0 )
|
if( strncmp( (char*)h.constData(), (char*) x + n - 20, 20 ) == 0 )
|
||||||
return ERROR_RSA_FAKESIGNED;
|
return ERROR_RSA_FAKESIGNED;
|
||||||
|
|
||||||
|
qDebug() << "Decrypted signature hash:" << QByteArray( (const char*)&x[ n-20 ], 20 ).toHex();
|
||||||
|
qDebug() << " SHA1 hash:" << h.toHex();
|
||||||
return ERROR_RSA_HASH;
|
return ERROR_RSA_HASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
#include "../WiiQt/uidmap.h"
|
#include "../WiiQt/uidmap.h"
|
||||||
#include "../WiiQt/tools.h"
|
#include "../WiiQt/tools.h"
|
||||||
#include "../WiiQt/tiktmd.h"
|
#include "../WiiQt/tiktmd.h"
|
||||||
|
#include "../WiiQt/settingtxtdialog.h"
|
||||||
|
#include "../WiiQt/u8.h"
|
||||||
|
|
||||||
|
|
||||||
//yippie for global variables
|
//yippie for global variables
|
||||||
|
QStringList args;
|
||||||
NandBin nand;
|
NandBin nand;
|
||||||
SharedContentMap sharedM;
|
SharedContentMap sharedM;
|
||||||
UIDmap uidM;
|
UIDmap uidM;
|
||||||
@ -15,6 +18,8 @@ QList< quint64 > validIoses;//dont put stubs in this list.
|
|||||||
QTreeWidgetItem *root;
|
QTreeWidgetItem *root;
|
||||||
QList<quint16> fats;
|
QList<quint16> fats;
|
||||||
quint32 verbose = 0;
|
quint32 verbose = 0;
|
||||||
|
bool tryToKeepGoing = false;
|
||||||
|
QByteArray sysMenuResource;
|
||||||
|
|
||||||
|
|
||||||
bool CheckTitleIntegrity( quint64 tid );
|
bool CheckTitleIntegrity( quint64 tid );
|
||||||
@ -24,22 +29,32 @@ void Usage()
|
|||||||
qDebug() << "usage" << QCoreApplication::arguments().at( 0 ) << "nand.bin" << "<other options>";
|
qDebug() << "usage" << QCoreApplication::arguments().at( 0 ) << "nand.bin" << "<other options>";
|
||||||
qDebug() << "\nOther options:";
|
qDebug() << "\nOther options:";
|
||||||
qDebug() << " -boot shows information about boot 1 and 2";
|
qDebug() << " -boot shows information about boot 1 and 2";
|
||||||
|
qDebug() << "\n";
|
||||||
qDebug() << " -fs verify the filesystem is in tact";
|
qDebug() << " -fs verify the filesystem is in tact";
|
||||||
qDebug() << " verifies presence of uid & content.map & checks the hashes in the content.map";
|
qDebug() << " verifies presence of uid & content.map & checks the hashes in the content.map";
|
||||||
qDebug() << " check installed titles for RSA & sha1 validity";
|
qDebug() << " check installed titles for RSA & sha1 validity";
|
||||||
qDebug() << " check installed titles for required IOS, proper uid & gid";
|
qDebug() << " check installed titles for required IOS, proper uid & gid";
|
||||||
|
qDebug() << "\n";
|
||||||
|
qDebug() << " -settingtxt show setting.txt. this must be combined with \"-fs\"";
|
||||||
|
qDebug() << "\n";
|
||||||
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() << "\n";
|
||||||
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() << "\n";
|
||||||
qDebug() << " -all does all of the above";
|
qDebug() << " -all does all of the above";
|
||||||
|
qDebug() << "\n";
|
||||||
qDebug() << " -v increase verbosity";
|
qDebug() << " -v increase verbosity";
|
||||||
|
qDebug() << "\n";
|
||||||
|
qDebug() << " -continue try to keep going as fas as possible on errors that should be fatal";
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fail( const QString& str )
|
void Fail( const QString& str )
|
||||||
{
|
{
|
||||||
qDebug() << str;
|
qDebug() << str;
|
||||||
exit( 1 );
|
if( !tryToKeepGoing )
|
||||||
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TidTxt( quint64 tid )
|
QString TidTxt( quint64 tid )
|
||||||
@ -168,7 +183,8 @@ QTreeWidgetItem *ItemFromPath( const QString &path )
|
|||||||
item = FindItem( lookingFor, item );
|
item = FindItem( lookingFor, item );
|
||||||
if( !item )
|
if( !item )
|
||||||
{
|
{
|
||||||
qWarning() << "ItemFromPath ->item not found" << path;
|
if( verbose )
|
||||||
|
qWarning() << "ItemFromPath ->item not found" << path;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
slash = nextSlash + 1;
|
slash = nextSlash + 1;
|
||||||
@ -322,11 +338,43 @@ bool RecurseCheckGidUid( QTreeWidgetItem *item, const QString &uidS, const QStri
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintName( const QByteArray &app )
|
||||||
|
{
|
||||||
|
QString desc;
|
||||||
|
if( app.size() == 0x40 )//tag for IOS, region select, ...
|
||||||
|
{
|
||||||
|
desc = QString( app ) + " " + QString( app.right( 0x10 ) );
|
||||||
|
}
|
||||||
|
else if( U8::GetU8Offset( app ) >= 0 ) //maybe this is an IMET header. try to get a name from it
|
||||||
|
{
|
||||||
|
U8 u8( app );
|
||||||
|
if( u8.IsOK() )
|
||||||
|
{
|
||||||
|
QStringList names = u8.IMETNames();
|
||||||
|
quint8 cnt = names.size();
|
||||||
|
if( cnt >= 2 ) //try to use english name first
|
||||||
|
desc = names.at( 1 );
|
||||||
|
for( quint8 i = 0; i < cnt && desc.isEmpty(); i++ )
|
||||||
|
{
|
||||||
|
desc = names.at( i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( desc.isEmpty() )
|
||||||
|
{
|
||||||
|
qDebug() << "\tUnable to get title";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qDebug() << "\tname: " << desc;
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckTitleIntegrity( quint64 tid )
|
bool CheckTitleIntegrity( quint64 tid )
|
||||||
{
|
{
|
||||||
if( validIoses.contains( tid ) )//this one has already been checked
|
if( validIoses.contains( tid ) )//this one has already been checked
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// if( verbose )
|
||||||
|
// qDebug() << "\n";
|
||||||
qDebug() << "Checking" << TidTxt( tid ).insert( 8, "-" ) << "...";
|
qDebug() << "Checking" << TidTxt( tid ).insert( 8, "-" ) << "...";
|
||||||
QString p = TidTxt( tid );
|
QString p = TidTxt( tid );
|
||||||
p.insert( 8 ,"/" );
|
p.insert( 8 ,"/" );
|
||||||
@ -350,7 +398,8 @@ bool CheckTitleIntegrity( quint64 tid )
|
|||||||
qDebug() << "error getting" << it << "data";
|
qDebug() << "error getting" << it << "data";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch( check_cert_chain( ba ) )
|
qint32 ch = check_cert_chain( ba );
|
||||||
|
switch( ch )
|
||||||
{
|
{
|
||||||
case ERROR_SIG_TYPE:
|
case ERROR_SIG_TYPE:
|
||||||
case ERROR_SUB_TYPE:
|
case ERROR_SUB_TYPE:
|
||||||
@ -358,7 +407,7 @@ bool CheckTitleIntegrity( quint64 tid )
|
|||||||
case ERROR_RSA_TYPE_UNKNOWN:
|
case ERROR_RSA_TYPE_UNKNOWN:
|
||||||
case ERROR_RSA_TYPE_MISMATCH:
|
case ERROR_RSA_TYPE_MISMATCH:
|
||||||
case ERROR_CERT_NOT_FOUND:
|
case ERROR_CERT_NOT_FOUND:
|
||||||
qDebug() << "\t" << it << "RSA signature isn't even close";
|
qDebug() << "\t" << it << "RSA signature isn't even close (" << ch << ")";
|
||||||
//return false; //maye in the future this will be true, but for now, this doesnt mean it wont boot
|
//return false; //maye in the future this will be true, but for now, this doesnt mean it wont boot
|
||||||
break;
|
break;
|
||||||
case ERROR_RSA_FAKESIGNED:
|
case ERROR_RSA_FAKESIGNED:
|
||||||
@ -374,12 +423,6 @@ bool CheckTitleIntegrity( quint64 tid )
|
|||||||
{
|
{
|
||||||
qDebug() << "\tthe 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();
|
|
||||||
if( t.AccessFlags() )
|
|
||||||
qDebug() << "\taccess :" << hex << t.AccessFlags();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -397,7 +440,6 @@ bool CheckTitleIntegrity( quint64 tid )
|
|||||||
if( upper == 0x10005 || upper == 0x10007 ) //dont try to verify all the contents of DLC, it will just find a bunch of missing contents and bitch about them
|
if( upper == 0x10005 || upper == 0x10007 ) //dont try to verify all the contents of DLC, it will just find a bunch of missing contents and bitch about them
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
||||||
quint16 cnt = t.Count();
|
quint16 cnt = t.Count();
|
||||||
for( quint16 i = 0; i < cnt; i++ )
|
for( quint16 i = 0; i < cnt; i++ )
|
||||||
{
|
{
|
||||||
@ -428,17 +470,44 @@ bool CheckTitleIntegrity( quint64 tid )
|
|||||||
"\n\texpected" << t.Hash( i ).toHex() <<
|
"\n\texpected" << t.Hash( i ).toHex() <<
|
||||||
"\n\tactual " << realH.toHex();
|
"\n\tactual " << realH.toHex();
|
||||||
//return false; //dont return false, as this this title may still boot
|
//return false; //dont return false, as this this title may still boot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if we are going to check the setting.txt stuff, we need to get the system menu resource file to compare ( check for opera bricks )
|
||||||
|
//so far, i think this file is always boot index 1, type 1
|
||||||
|
if( tid == 0x100000002ull && t.BootIndex( i ) == 1 &&
|
||||||
|
( args.contains( "-settingtxt", Qt::CaseInsensitive ) || args.contains( "-all", Qt::CaseInsensitive ) ) )
|
||||||
|
{
|
||||||
|
sysMenuResource = ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
//print a description of this title
|
||||||
|
if( verbose > 1 && t.BootIndex( i ) == 0 )
|
||||||
|
{
|
||||||
|
PrintName( ba );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//print version
|
||||||
|
if( verbose )
|
||||||
|
{
|
||||||
|
quint16 vers = t.Version();
|
||||||
|
qDebug() << "\tversion:" << QString( "%1.%2" ).arg( ( vers >> 8 ) & 0xff ).arg( vers & 0xff ) << vers << "hex:" << hex << t.Version();
|
||||||
|
if( t.AccessFlags() )
|
||||||
|
qDebug() << "\taccess :" << hex << t.AccessFlags();
|
||||||
|
}
|
||||||
|
|
||||||
quint64 ios = t.IOS();
|
quint64 ios = t.IOS();
|
||||||
if( ios && !validIoses.contains( ios ) )
|
if( ios && !validIoses.contains( ios ) )
|
||||||
{
|
{
|
||||||
qDebug() << "\tthe IOS for this title is not bootable\n\t" << TidTxt( ios ).insert( 8, "-" ) ;
|
qDebug() << "\tthe IOS for this title is not bootable\n\t" << TidTxt( ios ).insert( 8, "-" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( verbose > 1 && upper != 1 )
|
||||||
|
qDebug() << "\trequires IOS" << ((quint32)( ios & 0xffffffff )) << TidTxt( ios ).insert( 8, "-" );
|
||||||
quint32 uid = uidM.GetUid( tid, false );
|
quint32 uid = uidM.GetUid( tid, false );
|
||||||
if( !uid )
|
if( !uid )
|
||||||
{
|
{
|
||||||
@ -576,7 +645,10 @@ void SetUpTree()
|
|||||||
return;
|
return;
|
||||||
QTreeWidgetItem *r = nand.GetTree();
|
QTreeWidgetItem *r = nand.GetTree();
|
||||||
if( r->childCount() != 1 || r->child( 0 )->text( 0 ) != "/" )
|
if( r->childCount() != 1 || r->child( 0 )->text( 0 ) != "/" )
|
||||||
|
{
|
||||||
|
tryToKeepGoing = false;
|
||||||
Fail( "The nand FS is seriously broken. I Couldn't even find a correct root" );
|
Fail( "The nand FS is seriously broken. I Couldn't even find a correct root" );
|
||||||
|
}
|
||||||
|
|
||||||
root = r->takeChild( 0 );
|
root = r->takeChild( 0 );
|
||||||
delete r;
|
delete r;
|
||||||
@ -643,11 +715,147 @@ void CheckHmac()
|
|||||||
qDebug() << sclBad;
|
qDebug() << sclBad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckSettingTxt()
|
||||||
|
{
|
||||||
|
qDebug() << "Checking setting.txt stuff...";
|
||||||
|
QByteArray settingTxt = nand.GetData( "/title/00000001/00000002/data/setting.txt" );
|
||||||
|
if( settingTxt.isEmpty() )
|
||||||
|
{
|
||||||
|
Fail( "Error reading setting.txt" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settingTxt = SettingTxtDialog::LolCrypt( settingTxt );
|
||||||
|
QString area;
|
||||||
|
bool hArea = false;
|
||||||
|
bool hModel = false;
|
||||||
|
bool hDvd = false;
|
||||||
|
bool hMpch = false;
|
||||||
|
bool hCode = false;
|
||||||
|
bool hSer = false;
|
||||||
|
bool hVideo = false;
|
||||||
|
bool hGame = false;
|
||||||
|
bool shownSetting = false;
|
||||||
|
QString str( settingTxt );
|
||||||
|
str.replace( "\r\n", "\n" );//maybe not needed to do this in 2 steps, but there may be some reason the file only uses "\n", so do it this way to be safe
|
||||||
|
QStringList parts = str.split( "\n", QString::SkipEmptyParts );
|
||||||
|
foreach( QString part, parts )
|
||||||
|
{
|
||||||
|
if( part.startsWith( "AREA=" ) )
|
||||||
|
{
|
||||||
|
if( hArea ) goto error;
|
||||||
|
hArea = true;
|
||||||
|
area = part;
|
||||||
|
area.remove( 0, 5 );
|
||||||
|
}
|
||||||
|
else if( part.startsWith( "MODEL=" ) )
|
||||||
|
{
|
||||||
|
if( hModel ) goto error;
|
||||||
|
hModel = true;
|
||||||
|
}
|
||||||
|
else if( part.startsWith( "DVD=" ) )
|
||||||
|
{
|
||||||
|
if( hDvd ) goto error;
|
||||||
|
hDvd = true;
|
||||||
|
}
|
||||||
|
else if( part.startsWith( "MPCH=" ) )
|
||||||
|
{
|
||||||
|
if( hMpch ) goto error;
|
||||||
|
hMpch = true;
|
||||||
|
}
|
||||||
|
else if( part.startsWith( "CODE=" ) )
|
||||||
|
{
|
||||||
|
if( hCode ) goto error;
|
||||||
|
hCode = true;
|
||||||
|
}
|
||||||
|
else if( part.startsWith( "SERNO=" ) )
|
||||||
|
{
|
||||||
|
if( hSer ) goto error;
|
||||||
|
hSer = true;
|
||||||
|
}
|
||||||
|
else if( part.startsWith( "VIDEO=" ) )
|
||||||
|
{
|
||||||
|
if( hVideo ) goto error;
|
||||||
|
hVideo = true;
|
||||||
|
}
|
||||||
|
else if( part.startsWith( "GAME=" ) )
|
||||||
|
{
|
||||||
|
if( hGame ) goto error;
|
||||||
|
hGame = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "Extra stuff in the setting.txt.";
|
||||||
|
hexdump( settingTxt );
|
||||||
|
qDebug() << QString( settingTxt );
|
||||||
|
shownSetting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//something is missing
|
||||||
|
if( !hArea || !hModel || !hDvd || !hMpch || !hCode || !hSer || !hVideo || !hGame )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
//check for opera brick,
|
||||||
|
//or in certain cases ( such as KOR area setting on the wrong system menu, a full brick presenting as green & purple garbage instead of the "press A" screen )
|
||||||
|
if( sysMenuResource.isEmpty() )
|
||||||
|
{
|
||||||
|
qDebug() << "Error getting the resource file for the system menu.\nCan\'t check it against setting.txt";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
U8 u8( sysMenuResource );
|
||||||
|
QStringList entries = u8.Entries();
|
||||||
|
if( !u8.IsOK() || !entries.size() )
|
||||||
|
{
|
||||||
|
qDebug() << "Error parsing the resource file for the system menu.\nCan\'t check it against setting.txt";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QString sysMenuPath;
|
||||||
|
//these are all the possibilities i saw for AREA in libogc
|
||||||
|
if( area == "AUS" || area == "EUR" ) //supported by 4.3e
|
||||||
|
sysMenuPath = "html/EU2/iplsetting.ash/EU/EU/ENG/index01.html";
|
||||||
|
else if( area == "USA" || area == "BRA" || area == "HKG" || area == "ASI" || area == "LTN" || area == "SAF" ) //supported by 4.3u
|
||||||
|
sysMenuPath = "html/US2/iplsetting.ash/FIX/US/ENG/index01.html";
|
||||||
|
else if( area == "JPN" || area == "TWN" || area == "ROC" ) //supported by 4.3j
|
||||||
|
sysMenuPath = "html/JP2/iplsetting.ash/JP/JP/JPN/index01.html";
|
||||||
|
else if( area == "KOR" ) //supported by 4.3k
|
||||||
|
sysMenuPath = "html/KR2/iplsetting.ash/KR/KR/KOR/index01.html";
|
||||||
|
else
|
||||||
|
qDebug() << "unknown AREA setting";
|
||||||
|
if( !entries.contains( sysMenuPath ) )
|
||||||
|
{
|
||||||
|
qDebug() << sysMenuPath << "Was not found in the system menu resources, and is needed by the AREA setting" << area;
|
||||||
|
Fail( "This will likely result in a full/opera brick" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( verbose )
|
||||||
|
qDebug() << "system menu resource matches setting.txt AREA setting.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( verbose )
|
||||||
|
{
|
||||||
|
shownSetting = true;
|
||||||
|
hexdump( settingTxt );
|
||||||
|
qDebug() << str;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
error:
|
||||||
|
qDebug() << "Something is wrong with this setting.txt";
|
||||||
|
if( !shownSetting )
|
||||||
|
{
|
||||||
|
hexdump( settingTxt );
|
||||||
|
qDebug() << str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
QCoreApplication a( argc, argv );
|
QCoreApplication a( argc, argv );
|
||||||
QStringList args = QCoreApplication::arguments();
|
args = QCoreApplication::arguments();
|
||||||
if( args.size() < 2 )
|
if( args.size() < 3 )
|
||||||
Usage();
|
Usage();
|
||||||
|
|
||||||
if( !QFile( args.at( 1 ) ).exists() )
|
if( !QFile( args.at( 1 ) ).exists() )
|
||||||
@ -660,6 +868,9 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
verbose = args.count( "-v" );
|
verbose = args.count( "-v" );
|
||||||
|
|
||||||
|
if( args.contains( "-continue", Qt::CaseInsensitive ) )
|
||||||
|
tryToKeepGoing = true;
|
||||||
|
|
||||||
//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 ) )
|
||||||
{
|
{
|
||||||
@ -692,6 +903,10 @@ int main( int argc, char *argv[] )
|
|||||||
//if( !CheckTitleIntegrity( tid ) && tid == 0x100000002ull ) //well, this SHOULD be the case. but nintendo doesnt care so much about
|
//if( !CheckTitleIntegrity( tid ) && tid == 0x100000002ull ) //well, this SHOULD be the case. but nintendo doesnt care so much about
|
||||||
//Fail( "The System menu isnt valid" ); //checking signatures & hashes as the rest of us.
|
//Fail( "The System menu isnt valid" ); //checking signatures & hashes as the rest of us.
|
||||||
}
|
}
|
||||||
|
if( args.contains( "-settingtxt", Qt::CaseInsensitive ) || args.contains( "-all", Qt::CaseInsensitive ) )
|
||||||
|
{
|
||||||
|
CheckSettingTxt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( args.contains( "-clInfo", Qt::CaseInsensitive ) || args.contains( "-all", Qt::CaseInsensitive ) )
|
if( args.contains( "-clInfo", Qt::CaseInsensitive ) || args.contains( "-all", Qt::CaseInsensitive ) )
|
||||||
|
@ -24,7 +24,11 @@ SOURCES += main.cpp \
|
|||||||
../WiiQt/sha1.c \
|
../WiiQt/sha1.c \
|
||||||
../WiiQt/uidmap.cpp \
|
../WiiQt/uidmap.cpp \
|
||||||
../WiiQt/sharedcontentmap.cpp \
|
../WiiQt/sharedcontentmap.cpp \
|
||||||
../WiiQt/nandspare.cpp
|
../WiiQt/nandspare.cpp \
|
||||||
|
../WiiQt/settingtxtdialog.cpp \
|
||||||
|
../WiiQt/u8.cpp \
|
||||||
|
../WiiQt/lz77.cpp \
|
||||||
|
../WiiQt/ash.cpp
|
||||||
|
|
||||||
HEADERS += ../WiiQt/tiktmd.h \
|
HEADERS += ../WiiQt/tiktmd.h \
|
||||||
../WiiQt/nandbin.h \
|
../WiiQt/nandbin.h \
|
||||||
@ -32,4 +36,11 @@ HEADERS += ../WiiQt/tiktmd.h \
|
|||||||
../WiiQt/blocks0to7.h \
|
../WiiQt/blocks0to7.h \
|
||||||
../WiiQt/uidmap.h \
|
../WiiQt/uidmap.h \
|
||||||
../WiiQt/sharedcontentmap.h \
|
../WiiQt/sharedcontentmap.h \
|
||||||
../WiiQt/nandspare.h
|
../WiiQt/nandspare.h \
|
||||||
|
../WiiQt/settingtxtdialog.h \
|
||||||
|
../WiiQt/u8.h \
|
||||||
|
../WiiQt/lz77.h \
|
||||||
|
../WiiQt/ash.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
../WiiQt/settingtxtdialog.ui
|
||||||
|
@ -953,7 +953,7 @@ void MainWindow::on_actionFormat_triggered()
|
|||||||
tid = qFromBigEndian( tid );
|
tid = qFromBigEndian( tid );
|
||||||
quint32 upper = ( ( tid >> 32 ) & 0xffffffff );
|
quint32 upper = ( ( tid >> 32 ) & 0xffffffff );
|
||||||
quint32 lower = ( tid & 0xffffffff );
|
quint32 lower = ( tid & 0xffffffff );
|
||||||
qDebug() << hex << i << QString( "%1" ).arg( tid, 16, 16, QChar( '0' ) ) << upper << lower << QChar( ( lower >> 24 ) & 0xff ) << ( lower & 0xffffff00 );
|
//qDebug() << hex << i << QString( "%1" ).arg( tid, 16, 16, QChar( '0' ) ) << upper << lower << QChar( ( lower >> 24 ) & 0xff ) << ( lower & 0xffffff00 );
|
||||||
if( ( upper == 0x10001 && ( ( lower >> 24 ) & 0xff ) != 0x48 ) || //a channel, not starting with 'H'
|
if( ( upper == 0x10001 && ( ( lower >> 24 ) & 0xff ) != 0x48 ) || //a channel, not starting with 'H'
|
||||||
( upper == 0x10000 && ( ( lower & 0xffffff00 ) == 0x555000 ) ) ) //a disc update partition
|
( upper == 0x10000 && ( ( lower & 0xffffff00 ) == 0x555000 ) ) ) //a disc update partition
|
||||||
break;
|
break;
|
||||||
@ -962,16 +962,18 @@ void MainWindow::on_actionFormat_triggered()
|
|||||||
buf.close();
|
buf.close();
|
||||||
|
|
||||||
uidData.resize( 12 * titles );
|
uidData.resize( 12 * titles );
|
||||||
hexdump12( uidData );
|
//hexdump12( uidData );
|
||||||
uid = UIDmap( uidData );
|
uid = UIDmap( uidData );
|
||||||
|
|
||||||
//clear content.map
|
uidDirty = true;
|
||||||
|
sharedDirty = true;
|
||||||
shared = SharedContentMap();
|
shared = SharedContentMap();
|
||||||
if( !nand.CreateEntry( "/sys/uid.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) )
|
if( !nand.CreateEntry( "/sys/uid.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) )
|
||||||
{
|
{
|
||||||
ShowMessage( "<b>Error! Can't /sys/uid.sys</b>" );
|
ShowMessage( "<b>Error! Can't /sys/uid.sys</b>" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//clear content.map
|
||||||
if( !nand.CreateEntry( "/shared1/content.map", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) )
|
if( !nand.CreateEntry( "/shared1/content.map", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) )
|
||||||
{
|
{
|
||||||
ShowMessage( "<b>Error! Can't /shared1/content.map</b>" );
|
ShowMessage( "<b>Error! Can't /shared1/content.map</b>" );
|
||||||
|
Loading…
Reference in New Issue
Block a user