diff --git a/ohneschwanzenegger/mainwindow.cpp b/ohneschwanzenegger/mainwindow.cpp index cb8848b..ed5fe9b 100644 --- a/ohneschwanzenegger/mainwindow.cpp +++ b/ohneschwanzenegger/mainwindow.cpp @@ -25,20 +25,20 @@ MainWindow::MainWindow( QWidget *parent ) : QMainWindow( parent ), ui( new Ui::M sharedDirty = false; nandDirty = false; - ui->mainToolBar->setVisible( false );//hide toolbar for now + ui->mainToolBar->setVisible( false );//hide toolbar for now - //resize buttons to be same size - QFontMetrics fm( fontMetrics() ); - int max = fm.width( ui->pushButton_CachePathBrowse->text() ); - max = MAX( max, fm.width( ui->pushButton_GetTitle->text() ) ); - max = MAX( max, fm.width( ui->pushButton_initNand->text() ) ); - max = MAX( max, fm.width( ui->pushButton_nandPath->text() ) ); + //resize buttons to be same size + QFontMetrics fm( fontMetrics() ); + int max = fm.width( ui->pushButton_CachePathBrowse->text() ); + max = MAX( max, fm.width( ui->pushButton_GetTitle->text() ) ); + max = MAX( max, fm.width( ui->pushButton_initNand->text() ) ); + max = MAX( max, fm.width( ui->pushButton_nandPath->text() ) ); - max += 15; - ui->pushButton_CachePathBrowse->setMinimumWidth( max ); - ui->pushButton_GetTitle->setMinimumWidth( max ); - ui->pushButton_initNand->setMinimumWidth( max ); - ui->pushButton_nandPath->setMinimumWidth( max ); + max += 15; + ui->pushButton_CachePathBrowse->setMinimumWidth( max ); + ui->pushButton_GetTitle->setMinimumWidth( max ); + ui->pushButton_initNand->setMinimumWidth( max ); + ui->pushButton_nandPath->setMinimumWidth( max ); Wad::SetGlobalCert( QByteArray( (const char*)&certs_dat, CERTS_DAT_SIZE ) ); @@ -49,39 +49,39 @@ MainWindow::MainWindow( QWidget *parent ) : QMainWindow( parent ), ui( new Ui::M connect( &nus, SIGNAL( SendText( QString ) ), ui->statusBar, SLOT( showMessage( QString ) ) ); connect( &nus, SIGNAL( SendError( const QString &, NusJob ) ), this, SLOT( GetError( const QString &, NusJob ) ) ); connect( &nus, SIGNAL( SendDone() ), this, SLOT( NusIsDone() ) ); - connect( &nus, SIGNAL( SendData( NusJob ) ), this, SLOT( ReceiveTitleFromNus( NusJob) ) ); + connect( &nus, SIGNAL( SendData( NusJob ) ), this, SLOT( ReceiveTitleFromNus( NusJob ) ) ); //connect to the nand.bin to get text and crap from it connect( &nand, SIGNAL( SendError( const QString & ) ), this, SLOT( GetError( const QString & ) ) ); connect( &nand, SIGNAL( SendText( QString ) ), ui->statusBar, SLOT( showMessage( QString ) ) ); - LoadSettings(); - ui->lineEdit_nandPath->setText( "./testNand.bin" ); + LoadSettings(); + ui->lineEdit_nandPath->setText( "./testNand.bin" ); } MainWindow::~MainWindow() { - SaveSettings(); + SaveSettings(); delete ui; } void MainWindow::SaveSettings() { - QSettings s( QSettings::IniFormat, QSettings::UserScope, "WiiQt", "examples", this ); + QSettings s( QSettings::IniFormat, QSettings::UserScope, "WiiQt", "examples", this ); - //settings specific to this program - s.beginGroup( "ohneschwanzenegger" ); - s.setValue( "size", size() ); - s.setValue( "pos", pos() ); + //settings specific to this program + s.beginGroup( "ohneschwanzenegger" ); + s.setValue( "size", size() ); + s.setValue( "pos", pos() ); - s.endGroup(); + s.endGroup(); - //settings shared in multiple programs - //paths - s.beginGroup( "paths" ); - s.setValue( "nusCache", ui->lineEdit_cachePath->text() ); - s.endGroup(); + //settings shared in multiple programs + //paths + s.beginGroup( "paths" ); + s.setValue( "nusCache", ui->lineEdit_cachePath->text() ); + s.endGroup(); } #ifdef Q_WS_WIN @@ -91,21 +91,21 @@ void MainWindow::SaveSettings() #endif void MainWindow::LoadSettings() { - QSettings s( QSettings::IniFormat, QSettings::UserScope, "WiiQt", "examples", this ); + QSettings s( QSettings::IniFormat, QSettings::UserScope, "WiiQt", "examples", this ); - //settings specific to this program - s.beginGroup( "ohneschwanzenegger" ); - resize( s.value("size", QSize( 654, 507 ) ).toSize() ); - move( s.value("pos", QPoint( 2, 72 ) ).toPoint() ); - s.endGroup(); + //settings specific to this program + s.beginGroup( "ohneschwanzenegger" ); + resize( s.value("size", QSize( 654, 507 ) ).toSize() ); + move( s.value("pos", QPoint( 2, 72 ) ).toPoint() ); + s.endGroup(); - s.beginGroup( "paths" ); + s.beginGroup( "paths" ); - QString cachePath = s.value( "nusCache", PATH_PREFIX + "/NUS_cache" ).toString(); - ui->lineEdit_cachePath->setText( cachePath ); - if( !cachePath.isEmpty() ) - nus.SetCachePath( QFileInfo( cachePath ).absoluteFilePath() ); - s.endGroup(); + QString cachePath = s.value( "nusCache", PATH_PREFIX + "/NUS_cache" ).toString(); + ui->lineEdit_cachePath->setText( cachePath ); + if( !cachePath.isEmpty() ) + nus.SetCachePath( QFileInfo( cachePath ).absoluteFilePath() ); + s.endGroup(); } //some slots to respond to the NUS downloader @@ -113,13 +113,13 @@ void MainWindow::GetError( const QString &message, NusJob job ) { QString dataStuff = QString( "%1 items:" ).arg( job.data.size() ); for( int i = 0; i < job.data.size(); i++ ) - dataStuff += QString( " %1" ).arg( job.data.at( i ).size(), 0, 16, QChar( ' ' ) ); + dataStuff += QString( " %1" ).arg( job.data.at( i ).size(), 0, 16, QChar( ' ' ) ); QString str = tr( "Error getting title from NUS: %1" ).arg( message ); QString j = QString( "NusJob( %1, %2, %3, %4 )
" ) - .arg( job.tid, 16, 16, QChar( '0' ) ) - .arg( job.version ).arg( job.decrypt ? "decrypted" : "encrypted" ) - .arg( dataStuff ); + .arg( job.tid, 16, 16, QChar( '0' ) ) + .arg( job.version ).arg( job.decrypt ? "decrypted" : "encrypted" ) + .arg( dataStuff ); ui->plainTextEdit_log->appendHtml( str ); @@ -147,46 +147,46 @@ void MainWindow::NusIsDone() //make sure there is a setting.txt QTreeWidgetItem *item = ItemFromPath( "/title/00000001/00000002/data/setting.txt" ); - 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 + 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; - if( ui->lineEdit_tid->text().endsWith( "e", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 ) - reg = SETTING_TXT_PAL; - if( ui->lineEdit_tid->text().endsWith( "j", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 ) - reg = SETTING_TXT_JAP; - if( ui->lineEdit_tid->text().endsWith( "k", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 ) - reg = SETTING_TXT_KOR; - QByteArray ba = SettingTxtDialog::Edit( this, QByteArray(), reg ); //call a dialog to create a new setting.txt - if( !ba.isEmpty() ) //if the dialog returned anything ( cancel wasnt pressed ) write that new setting.txt to the nand - { - quint16 r = nand.CreateEntry( "/title/00000001/00000002/data/setting.txt", 0x1000, 1, NAND_FILE, NAND_READ, NAND_READ, NAND_READ ); - if( !r ) - { - ShowMessage( "Error creating setting.txt. maybe some folders are missing?" ); - } - else - { - if( !nand.SetData( r, ba ) ) - { - ShowMessage( "Error writing data for setting.txt." ); - } - else - { - nandDirty = true; - UpdateTree(); - } - } - } - } + quint8 reg = SETTING_TXT_UNK; + if( ui->lineEdit_tid->text().endsWith( "e", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 ) + reg = SETTING_TXT_PAL; + if( ui->lineEdit_tid->text().endsWith( "j", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 ) + reg = SETTING_TXT_JAP; + if( ui->lineEdit_tid->text().endsWith( "k", Qt::CaseInsensitive ) && ui->lineEdit_tid->text().size() == 4 ) + reg = SETTING_TXT_KOR; + QByteArray ba = SettingTxtDialog::Edit( this, QByteArray(), reg ); //call a dialog to create a new setting.txt + if( !ba.isEmpty() ) //if the dialog returned anything ( cancel wasnt pressed ) write that new setting.txt to the nand + { + quint16 r = nand.CreateEntry( "/title/00000001/00000002/data/setting.txt", 0x1000, 1, NAND_FILE, NAND_READ, NAND_READ, NAND_READ ); + if( !r ) + { + ShowMessage( "Error creating setting.txt. maybe some folders are missing?" ); + } + else + { + if( !nand.SetData( r, ba ) ) + { + ShowMessage( "Error writing data for setting.txt." ); + } + else + { + nandDirty = true; + UpdateTree(); + ShowMessage( tr( "Saved setting.txt" ) ); + } + } + } + } - //nand.Delete( "/title/00000001/00000002/content/title.tmd" ); if( nandDirty ) { - if( !FlushNand() ) - { - ShowMessage( "Error flushing nand. Maybe you used too much TP?" ); - } - nandDirty = false; + if( !FlushNand() ) + { + ShowMessage( "Error flushing nand. Maybe you used too much TP?" ); + } + nandDirty = false; } } @@ -199,7 +199,7 @@ void MainWindow::ReceiveTitleFromNus( NusJob job ) //do something with the data we got if( InstallNUSItem( job ) ) - nandDirty = true; + nandDirty = true; } @@ -207,7 +207,7 @@ void MainWindow::ReceiveTitleFromNus( NusJob job ) void MainWindow::on_pushButton_GetTitle_clicked() { if( !nandInited && !InitNand( ui->lineEdit_nandPath->text() ) ) - return; + return; bool ok = false; bool wholeUpdate = false; @@ -215,46 +215,46 @@ void MainWindow::on_pushButton_GetTitle_clicked() quint32 ver = 0; if( ui->lineEdit_tid->text().size() == 4 ) { - wholeUpdate = true; + wholeUpdate = true; } else { - tid = ui->lineEdit_tid->text().toLongLong( &ok, 16 ); - if( !ok ) - { - ShowMessage( "Error converting \"" + ui->lineEdit_tid->text() + "\" to a hex number." ); - return; - } - ver = TITLE_LATEST_VERSION; - if( !ui->lineEdit_version->text().isEmpty() ) - { - ver = ui->lineEdit_version->text().toInt( &ok, 10 ); - if( !ok ) - { - ShowMessage( "Error converting \"" + ui->lineEdit_version->text() + "\" to a decimal number." ); - return; - } - if( ver > 0xffff ) - { - ShowMessage( tr( "Version %1 is too high. Max is 65535" ).arg( ver ) ); - return; - } - } + tid = ui->lineEdit_tid->text().toLongLong( &ok, 16 ); + if( !ok ) + { + ShowMessage( "Error converting \"" + ui->lineEdit_tid->text() + "\" to a hex number." ); + return; + } + ver = TITLE_LATEST_VERSION; + if( !ui->lineEdit_version->text().isEmpty() ) + { + ver = ui->lineEdit_version->text().toInt( &ok, 10 ); + if( !ok ) + { + ShowMessage( "Error converting \"" + ui->lineEdit_version->text() + "\" to a decimal number." ); + return; + } + if( ver > 0xffff ) + { + ShowMessage( tr( "Version %1 is too high. Max is 65535" ).arg( ver ) ); + return; + } + } } //decide how we want nus to give us the title bool decrypt = true; nus.SetCachePath( ui->lineEdit_cachePath->text() ); if( wholeUpdate ) { - if( !nus.GetUpdate( ui->lineEdit_tid->text(), decrypt ) ) - { - ShowMessage( tr( "I dont know the titles that were in the %1 update" ).arg( ui->lineEdit_tid->text() ) ); - return; - } + if( !nus.GetUpdate( ui->lineEdit_tid->text(), decrypt ) ) + { + ShowMessage( tr( "I dont know the titles that were in the %1 update" ).arg( ui->lineEdit_tid->text() ) ); + return; + } } else { - nus.Get( tid, decrypt, ver ); + nus.Get( tid, decrypt, ver ); } } @@ -263,17 +263,17 @@ void MainWindow::on_pushButton_nandPath_clicked() { QString f = QFileDialog::getOpenFileName( this, tr( "Select nand.bin" ) ); if( f.isEmpty() ) - return; + return; ui->lineEdit_nandPath->setText( f ); - InitNand( ui->lineEdit_nandPath->text() ); + InitNand( ui->lineEdit_nandPath->text() ); } void MainWindow::on_pushButton_CachePathBrowse_clicked() { QString f = QFileDialog::getExistingDirectory( this, tr( "Select NUS Cache base folder" ) ); if( f.isEmpty() ) - return; + return; ui->lineEdit_cachePath->setText( f ); nus.SetCachePath( ui->lineEdit_cachePath->text() ); @@ -283,37 +283,37 @@ void MainWindow::on_pushButton_CachePathBrowse_clicked() void MainWindow::on_actionSetting_txt_triggered() { if( !nandInited ) - return; + return; - if( !ItemFromPath( "/title/00000001/00000002/data" ) ) - { - ShowMessage( tr( "You need to have a system menu before you can create a setting.txt" ) ); - return; - } + if( !ItemFromPath( "/title/00000001/00000002/data" ) ) + { + ShowMessage( tr( "You need to have a system menu before you can create a setting.txt" ) ); + return; + } - QByteArray ba; - if( ItemFromPath( "/title/00000001/00000002/data/setting.txt" ) ) - ba = nand.GetData( "/title/00000001/00000002/data/setting.txt" ); //read the current setting.txt + QByteArray ba; + if( ItemFromPath( "/title/00000001/00000002/data/setting.txt" ) ) + ba = nand.GetData( "/title/00000001/00000002/data/setting.txt" ); //read the current setting.txt ba = SettingTxtDialog::Edit( this, ba ); //call a dialog to edit that existing file and store the result in the same bytearray if( !ba.isEmpty() ) //if the dialog returned anything ( cancel wasnt pressed ) write that new setting.txt to the nand dump - { - quint16 r = CreateIfNeeded( "/title/00000001/00000002/data/setting.txt", 0x1000, 1, NAND_FILE, NAND_READ, NAND_READ, NAND_READ ); - if( !r || !nand.SetData( r, ba ) - || !nand.WriteMetaData() ) - { - ShowMessage( tr( "Error writing setting.txt" ) ); - } - else - ShowMessage( tr( "Saved setting.txt" ) ); - } + { + quint16 r = CreateIfNeeded( "/title/00000001/00000002/data/setting.txt", 0x1000, 1, NAND_FILE, NAND_READ, NAND_READ, NAND_READ ); + if( !r || !nand.SetData( r, ba ) + || !nand.WriteMetaData() ) + { + ShowMessage( tr( "Error writing setting.txt" ) ); + } + else + ShowMessage( tr( "Saved setting.txt" ) ); + } } //nand-dump -> flush void MainWindow::on_actionFlush_triggered() { - if( nandInited ) - FlushNand(); + if( nandInited ) + FlushNand(); } //nand-dump -> ImportWad @@ -321,45 +321,45 @@ void MainWindow::on_actionImportWad_triggered() { if( !nandInited && !InitNand( 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::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)") ); + ShowMessage( tr( "Error setting the basepath of the nand to %1" ).arg( QFileInfo( ui->lineEdit_nandPath->text() ).absoluteFilePath() ) ); + return; + } + //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( fns.isEmpty() ) - return; - foreach( QString fn, fns ) - { - QByteArray data = ReadFile( fn ); - if( data.isEmpty() ) - return; + if( fns.isEmpty() ) + return; + foreach( QString fn, fns ) + { + QByteArray data = ReadFile( fn ); + if( data.isEmpty() ) + return; - Wad wad( data ); - if( !wad.IsOk() ) - { - ShowMessage( tr( "Wad data not ok for \"%1\"" ).arg( fn ) ); - return; - } + Wad wad( data ); + if( !wad.IsOk() ) + { + ShowMessage( tr( "Wad data not ok for \"%1\"" ).arg( fn ) ); + return; + } - //work smart, not hard... just turn the wad into a NUSJob and reused the same code to install it - NusJob job; - job.tid = wad.Tid(); - job.data << wad.getTmd(); - job.data << wad.getTik(); + //work smart, not hard... just turn the wad into a NUSJob and reused the same code to install it + NusJob job; + job.tid = wad.Tid(); + job.data << wad.getTmd(); + job.data << wad.getTik(); - Tmd t( wad.getTmd() ); - job.version = t.Version(); - quint16 cnt = t.Count(); - for( quint16 i = 0; i < cnt; i++ ) - { - job.data << wad.Content( i ); - } + Tmd t( wad.getTmd() ); + job.version = t.Version(); + quint16 cnt = t.Count(); + 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 ); - } + job.decrypt = true; + ShowMessage( tr( "Installing %1 to nand" ).arg( fn ) ); + InstallNUSItem( job ); + } } @@ -367,54 +367,54 @@ void MainWindow::on_actionNew_nand_from_keys_triggered() { QString path = NewNandBin::GetNewNandPath( this ); if( path.isEmpty() ) - return; + return; InitNand( path ); ui->lineEdit_nandPath->setText( path ); - //these titles should be in order ( not really functional, but to emulate better how the wii comes from the factory ) - if( !nand.CreateEntry( "/title/00000001", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) - || !nand.CreateEntry( "/title/00000001/00000004", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) - || !nand.CreateEntry( "/title/00000001/00000009", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) - || !nand.CreateEntry( "/title/00000001/00000002", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) - || !nand.CreateEntry( "/title/00000001/00000100", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) - || !nand.CreateEntry( "/title/00000001/00000101", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) ) - { - ShowMessage( "Error creating title subdirs<\b>" ); - return; - } + //these titles should be in order ( not really functional, but to emulate better how the wii comes from the factory ) + if( !nand.CreateEntry( "/title/00000001", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) + || !nand.CreateEntry( "/title/00000001/00000004", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) + || !nand.CreateEntry( "/title/00000001/00000009", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) + || !nand.CreateEntry( "/title/00000001/00000002", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) + || !nand.CreateEntry( "/title/00000001/00000100", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) + || !nand.CreateEntry( "/title/00000001/00000101", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) ) + { + ShowMessage( "Error creating title subdirs<\b>" ); + return; + } - //add some factory test logs and whatnot - quint32 _uid = uid.GetUid( NAND_TEST_OWNER, true ); - if( !nand.CreateEntry( "/shared2/test", _uid, NAND_TEST_GROUP, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) - || !nand.CreateEntry( "/shared2/sys", _uid, NAND_TEST_GROUP, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) - { - ShowMessage( "Error creating folder for testlog<\b>" ); - return; - } - quint16 handle = nand.CreateEntry( "/shared2/test/testlog.txt", _uid, NAND_TEST_GROUP, NAND_FILE, NAND_RW, NAND_RW, NAND_RW ); - if( !handle ) - { - ShowMessage( "Error creating testlog<\b>" ); - return; - } - QByteArray tLog = ReadFile( ":/testlog.txt" ); - if( !nand.SetData( handle, tLog ) ) - { - ShowMessage( "Error writing to testlog.txt<\b>" ); - return; - } - UpdateTree(); - ShowMessage( "Created /shared2/test/testlog.txt" ); + //add some factory test logs and whatnot + quint32 _uid = uid.GetUid( NAND_TEST_OWNER, true ); + if( !nand.CreateEntry( "/shared2/test", _uid, NAND_TEST_GROUP, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) + || !nand.CreateEntry( "/shared2/sys", _uid, NAND_TEST_GROUP, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) + { + ShowMessage( "Error creating folder for testlog<\b>" ); + return; + } + quint16 handle = nand.CreateEntry( "/shared2/test/testlog.txt", _uid, NAND_TEST_GROUP, NAND_FILE, NAND_RW, NAND_RW, NAND_RW ); + if( !handle ) + { + ShowMessage( "Error creating testlog<\b>" ); + return; + } + QByteArray tLog = ReadFile( ":/testlog.txt" ); + if( !nand.SetData( handle, tLog ) ) + { + ShowMessage( "Error writing to testlog.txt<\b>" ); + return; + } + UpdateTree(); + ShowMessage( "Created /shared2/test/testlog.txt" ); } void MainWindow::on_pushButton_initNand_clicked() { if( ui->lineEdit_nandPath->text().isEmpty() ) { - ShowMessage( "Please enter a path for nand.bin<\b>" ); - return; + ShowMessage( "Please enter a path for nand.bin<\b>" ); + return; } - InitNand( ui->lineEdit_nandPath->text() ); + InitNand( ui->lineEdit_nandPath->text() ); } bool MainWindow::InitNand( const QString &path ) @@ -422,52 +422,52 @@ bool MainWindow::InitNand( const QString &path ) nandInited = false; sharedDirty = false; nandDirty = false; - ui->menuContent->setEnabled( false ); + ui->menuContent->setEnabled( false ); if( !nand.SetPath( path ) || !nand.InitNand() ) - return false; + return false; if( !UpdateTree() ) - return false; + return false; //setup the uid QTreeWidgetItem *it = ItemFromPath( "/sys/uid.sys" ); if( !it ) { - uid.CreateNew();//dont add any UID besides the system menu since we dont know what region it will be - if( !nand.CreateEntry( "/sys/uid.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) - { - ShowMessage( "Error creating new uid.sys" ); - return false; - } - uidDirty = true; + uid.CreateNew();//dont add any UID besides the system menu since we dont know what region it will be + if( !nand.CreateEntry( "/sys/uid.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) + { + ShowMessage( "Error creating new uid.sys" ); + return false; + } + uidDirty = true; } else { - QByteArray ba = nand.GetData( "/sys/uid.sys" ); - uid = UIDmap( ba ); + QByteArray ba = nand.GetData( "/sys/uid.sys" ); + uid = UIDmap( ba ); } //set up the shared map it = ItemFromPath( "/shared1/content.map" ); if( !it ) { - if( !nand.CreateEntry( "/shared1/content.map", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) - { - sharedDirty = true; - ShowMessage( "Error creating new content.map" ); - return false; - } + if( !nand.CreateEntry( "/shared1/content.map", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) + { + sharedDirty = true; + ShowMessage( "Error creating new content.map" ); + return false; + } } else { - QByteArray ba = nand.GetData( "/shared1/content.map" ); - shared = SharedContentMap( ba ); - if( !shared.Check() )//i really dont want to create a new one and rewrite all the contents to match it - ShowMessage( "Something about the shared map isnt right, but im using it anyways" ); - } + QByteArray ba = nand.GetData( "/shared1/content.map" ); + shared = SharedContentMap( ba ); + if( !shared.Check() )//i really dont want to create a new one and rewrite all the contents to match it + ShowMessage( "Something about the shared map isnt right, but im using it anyways" ); + } nandInited = true; - ui->menuContent->setEnabled( true ); - ShowMessage( "Set path to nand as " + path ); + ui->menuContent->setEnabled( true ); + ShowMessage( "Set path to nand as " + path ); return true; } @@ -480,15 +480,15 @@ bool MainWindow::FlushNand() bool r1 = true; bool r2 = true; if( uidDirty && !nand.SetData( "/sys/uid.sys", uid.Data() ) ) - r1 = false; + r1 = false; else - uidDirty = false; + uidDirty = false; if( sharedDirty && !nand.SetData( "/shared1/content.map", shared.Data() ) ) - r2 = false; + r2 = false; else - sharedDirty = false; + sharedDirty = false; return ( nand.WriteMetaData() && r1 && r2 ); } @@ -498,11 +498,11 @@ QTreeWidgetItem *MainWindow::FindItem( const QString &s, QTreeWidgetItem *parent int cnt = parent->childCount(); for( int i = 0; i child( i ); - if( r->text( 0 ) == s ) - { - return r; - } + QTreeWidgetItem *r = parent->child( i ); + if( r->text( 0 ) == s ) + { + return r; + } } return NULL; } @@ -512,20 +512,20 @@ QTreeWidgetItem *MainWindow::ItemFromPath( const QString &path ) QTreeWidgetItem *item = root; if( !path.startsWith( "/" ) || path.contains( "//" )) { - return NULL; + return NULL; } int slash = 1; while( slash ) { - int nextSlash = path.indexOf( "/", slash + 1 ); - QString lookingFor = path.mid( slash, nextSlash - slash ); - item = FindItem( lookingFor, item ); - if( !item ) - { - //qWarning() << "ItemFromPath ->item not found" << path; - return NULL; - } - slash = nextSlash + 1; + int nextSlash = path.indexOf( "/", slash + 1 ); + QString lookingFor = path.mid( slash, nextSlash - slash ); + item = FindItem( lookingFor, item ); + if( !item ) + { + //qWarning() << "ItemFromPath ->item not found" << path; + return NULL; + } + slash = nextSlash + 1; } return item; } @@ -535,10 +535,10 @@ QString MainWindow::PathFromItem( QTreeWidgetItem *item ) QString ret; while( item ) { - ret.prepend( "/" + item->text( 0 ) ); - item = item->parent(); - if( item->text( 0 ) == "/" )// dont add the root - break; + ret.prepend( "/" + item->text( 0 ) ); + item = item->parent(); + if( item->text( 0 ) == "/" )// dont add the root + break; } return ret; } @@ -547,12 +547,15 @@ bool MainWindow::UpdateTree() { //set up the tree so we know what all is in the nand without asking for it every time if( root ) - delete root; + { + delete root; + root = NULL; + } QTreeWidgetItem *r = nand.GetTree(); if( r->childCount() != 1 || r->child( 0 )->text( 0 ) != "/" ) { - ShowMessage( "The nand FS is seriously broken. I Couldn't even find a correct root" ); - return false; + ShowMessage( "The nand FS is seriously broken. I Couldn't even find a correct root" ); + return false; } root = r->takeChild( 0 ); delete r; @@ -562,31 +565,31 @@ bool MainWindow::UpdateTree() quint16 MainWindow::CreateIfNeeded( const QString &path, quint32 uid, quint16 gid, quint8 attr, quint8 user_perm, quint8 group_perm, quint8 other_perm ) { - // qDebug() << "MainWindow::CreateIfNeeded" << path; + // qDebug() << "MainWindow::CreateIfNeeded" << path; QTreeWidgetItem *item = ItemFromPath( path ); if( !item ) { - quint16 ret = nand.CreateEntry( path, uid, gid, attr, user_perm, group_perm, other_perm ); - if( ret && UpdateTree() ) - return ret; - return 0; + quint16 ret = nand.CreateEntry( path, uid, gid, attr, user_perm, group_perm, other_perm ); + if( ret && UpdateTree() ) + return ret; + return 0; } //TODO - if the item already exists, check that its attributes match the expected ones return item->text( 1 ).toInt(); } -bool MainWindow::InstallSharedContent( const QByteArray stuff, const QByteArray hash ) +bool MainWindow::InstallSharedContent( const QByteArray &stuff, const QByteArray &hash ) { //qDebug() << "MainWindow::InstallSharedContent"; QByteArray h; if( hash.isEmpty() ) - h = GetSha1( stuff ); + h = GetSha1( stuff ); else - h = hash; + h = hash; QString cid = shared.GetAppFromHash( hash ); if( !cid.isEmpty() ) //this one is already installed - return true; + return true; //qDebug() << "will create new"; //get next available cid in the shared map @@ -598,7 +601,7 @@ bool MainWindow::InstallSharedContent( const QByteArray stuff, const QByteArray //create the file quint16 r = CreateIfNeeded( "/shared1/" + cid + ".app", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ); if( !r ) - return false; + return false; //write the data to the file return nand.SetData( r, stuff ); @@ -617,31 +620,31 @@ bool MainWindow::InstallNUSItem( NusJob job ) QTreeWidgetItem *content; if( !job.tid || !job.data.size() > 2 ) { - qWarning() << "bad sizes"; - ShowMessage( "Error installing title " + title + " to nand" ); - return false; + qWarning() << "bad sizes"; + ShowMessage( "Error installing title " + title + " to nand" ); + return false; } QString tid = QString( "%1" ).arg( job.tid, 16, 16, QChar( '0' ) ); QString upper = tid.left( 8 ); QString lower = tid.right( 8 ); - Tmd t( job.data.takeFirst() ); - Ticket ticket( job.data.takeFirst() ); + Tmd t( job.data.takeFirst() ); + Ticket ticket( job.data.takeFirst() ); if( t.Tid() != job.tid || ticket.Tid() != job.tid ) { - qWarning() << "bad tid"; - goto error; + qWarning() << "bad tid"; + goto error; } cnt = t.Count(); if( job.data.size() != cnt ) { - qWarning() << "content count"; - goto error; + qWarning() << "content count"; + goto error; } //qDebug() << "uidDirty" << uidDirty; if( !uidDirty ) { - uidDirty = !uid.GetUid( job.tid, false ); + uidDirty = !uid.GetUid( job.tid, false ); } //qDebug() << "uidDirty" << uidDirty; _uid = uid.GetUid( job.tid ); @@ -649,8 +652,8 @@ bool MainWindow::InstallNUSItem( NusJob job ) _gid = t.Gid(); if( !_uid ) { - qWarning() << "no uid"; - goto error; + qWarning() << "no uid"; + goto error; } //create all the folders @@ -663,26 +666,26 @@ bool MainWindow::InstallNUSItem( NusJob job ) if( !CreateIfNeeded( "/title/" + upper + "/" + lower, 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) ) { qWarning() << "can't create title+upper+lower folder";goto error;} - if( !CreateIfNeeded( "/title/" + upper + "/" + lower + "/data", _uid, _gid, NAND_DIR, NAND_RW, 0, 0 ) ) - { qWarning() << "can't create data folder";goto error;} + if( !CreateIfNeeded( "/title/" + upper + "/" + lower + "/data", _uid, _gid, NAND_DIR, NAND_RW, 0, 0 ) ) + { qWarning() << "can't create data folder";goto error;} if( !CreateIfNeeded( "/title/" + upper + "/" + lower + "/content", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) ) - { qWarning() << "can't create content folder";goto error;} + { qWarning() << "can't create content folder";goto error;} //delete old tmd/.apps and whatever else in the content folder content = ItemFromPath( "/title/" + upper + "/" + lower + "/content" ); cnt = content->childCount(); for ( quint16 i = 0; i < cnt; i++ ) { - if( !nand.Delete( "/title/" + upper + "/" + lower + "/content/" + content->child( i )->text( 0 ) ) ) - { qWarning() << "error deleting old title"; goto error; } - deleted = true; + if( !nand.Delete( "/title/" + upper + "/" + lower + "/content/" + content->child( i )->text( 0 ) ) ) + { qWarning() << "error deleting old title"; goto error; } + deleted = true; } if( deleted ) { - //nand.WriteMetaData(); - UpdateTree(); - ShowMessage( tr( "Deleted old TMD and private contents for
%1" ).arg( title ) ); + //nand.WriteMetaData(); + UpdateTree(); + ShowMessage( tr( "Deleted old TMD and private contents for
%1" ).arg( title ) ); } cnt = t.Count(); @@ -690,79 +693,79 @@ bool MainWindow::InstallNUSItem( NusJob job ) //install ticket r = CreateIfNeeded( "/ticket/" + upper + "/" + lower + ".tik", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ); if( !r ) - { qWarning() << "can't create ticket";goto error;} + { qWarning() << "can't create ticket";goto error;} if( !nand.SetData( r, ticket.Data() ) ) - { qWarning() << "can't write to ticket";goto error;} + { qWarning() << "can't write to ticket";goto error;} //install tmd r = CreateIfNeeded( "/title/" + upper + "/" + lower + "/content/title.tmd", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ); if( !r ) - { qWarning() << "can't create tmd";goto error;} + { qWarning() << "can't create tmd";goto error;} if( !nand.SetData( r, t.Data() ) ) - { qWarning() << "can't write to tmd";goto error;} + { qWarning() << "can't write to tmd";goto error;} //install contents //qDebug() << "will install" << cnt << "contents"; for( quint16 i = 0; i < cnt; i++ ) { - //qDebug() << "installing" << i; - //make sure the data is decrypted - QByteArray decData; - QByteArray hash; - if( job.decrypt ) - { - decData = job.data.takeFirst(); - if( (quint32)decData.size() != t.Size( i ) ) - { - qDebug() << "wtf - size"; - decData.resize( t.Size( i ) ); - } - } - else - { - //decrypt the data - QByteArray encData = job.data.takeFirst(); - AesSetKey( ticket.DecryptedKey() ); - decData = AesDecrypt( i, encData ); - decData.resize( t.Size( i ) ); - } + //qDebug() << "installing" << i; + //make sure the data is decrypted + QByteArray decData; + QByteArray hash; + if( job.decrypt ) + { + decData = job.data.takeFirst(); + if( (quint32)decData.size() != t.Size( i ) ) + { + qDebug() << "wtf - size"; + decData.resize( t.Size( i ) ); + } + } + else + { + //decrypt the data + QByteArray encData = job.data.takeFirst(); + AesSetKey( ticket.DecryptedKey() ); + decData = AesDecrypt( i, encData ); + decData.resize( t.Size( i ) ); + } - //check the hash - hash = GetSha1( decData ); - if( hash != t.Hash( i ) ) - { - qWarning() << "hash" << i << "\n" << hash.toHex() << "\n" << t.Hash( i ).toHex(); - goto error; - } + //check the hash + hash = GetSha1( decData ); + if( hash != t.Hash( i ) ) + { + qWarning() << "hash" << i << "\n" << hash.toHex() << "\n" << t.Hash( i ).toHex(); + goto error; + } - //install the content - if( t.Type( i ) == 1 )//private - { - r = CreateIfNeeded( "/title/" + upper + "/" + lower + "/content/" + t.Cid( i ) + ".app" , 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ); - if( !r ) - { - qWarning() << "cant create content" << i; - goto error; - } - if ( !nand.SetData( r, decData ) ) - { - qWarning() << "cant write content" << i; - goto error; - } - } - else if( t.Type( i ) == 0x8001 )//shared - { - if ( !InstallSharedContent( decData, hash ) ) - { - qWarning() << "error installing shared" << i << hash.toHex(); - goto error; - } - } - else - { - qWarning() << "type" << hex << t.Type( i ); - goto error; - } + //install the content + if( t.Type( i ) == 1 )//private + { + r = CreateIfNeeded( "/title/" + upper + "/" + lower + "/content/" + t.Cid( i ) + ".app" , 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ); + if( !r ) + { + qWarning() << "cant create content" << i; + goto error; + } + if ( !nand.SetData( r, decData ) ) + { + qWarning() << "cant write content" << i; + goto error; + } + } + else if( t.Type( i ) == 0x8001 )//shared + { + if ( !InstallSharedContent( decData, hash ) ) + { + qWarning() << "error installing shared" << i << hash.toHex(); + goto error; + } + } + else + { + qWarning() << "type" << hex << t.Type( i ); + goto error; + } } qDebug() << "done installing"; ShowMessage( "Installed title " + title + " to nand" ); @@ -770,7 +773,7 @@ bool MainWindow::InstallNUSItem( NusJob job ) //nand.Delete( "/title/" + upper ); //UpdateTree(); return true; - error: + error: ShowMessage( "Error installing title " + title + " to nand" ); return false; } @@ -779,9 +782,9 @@ bool MainWindow::InstallNUSItem( NusJob job ) void MainWindow::on_actionAbout_triggered() { QString txt = tr( "This is an example program from WiiQt. It is designed to write titles to a nand.bin and even create one from scratch." - "

IT SHOULD ONLY BE USED BY PEOPLE THAT KNOW HOW TO VERIFY THE FILES IT PRODUCES. AND HAVE A WAY TO FIX A BRICKED WII SHOULD THIS PROGRAM HAVE BUGS" - "

YOU HAVE BEEN WARNED" - "
giantpune" ); + "

IT SHOULD ONLY BE USED BY PEOPLE THAT KNOW HOW TO VERIFY THE FILES IT PRODUCES. AND HAVE A WAY TO FIX A BRICKED WII SHOULD THIS PROGRAM HAVE BUGS" + "

YOU HAVE BEEN WARNED" + "
giantpune" ); QMessageBox::critical( this, tr( "About" ), txt ); } @@ -789,25 +792,25 @@ void MainWindow::on_actionAbout_triggered() //add a default settings file if there is one laying around void MainWindow::TryToAddDefaultSettings() { - if( ItemFromPath( "/shared2/sys/SYSCONF" ) ) - return; + if( ItemFromPath( "/shared2/sys/SYSCONF" ) ) + return; - QByteArray stuff = ReadFile( "./default_SYSCONF" ); - if( stuff.isEmpty() ) - 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; + 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( "Error adding the default settings" ); - return; - } - UpdateTree(); - ShowMessage( "Wrote /shared2/sys/SYSCONF" ); + 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( "Error adding the default settings" ); + return; + } + UpdateTree(); + ShowMessage( "Wrote /shared2/sys/SYSCONF" ); } #endif @@ -815,188 +818,188 @@ void MainWindow::TryToAddDefaultSettings() //i have not been able to get the wii to create this data on its own using any officially release system menu or other program void MainWindow::AddStuffToMetaFolder() { - if( !ItemFromPath( "/meta" ) ) - return; + if( !ItemFromPath( "/meta" ) ) + return; - if( !CreateIfNeeded( "/meta/00000001", 0x1000, 1, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) - { - ShowMessage( "Cannot create folder for metacrap" ); - return; - } - bool written = false; + if( !CreateIfNeeded( "/meta/00000001", 0x1000, 1, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) + { + ShowMessage( "Cannot create folder for metacrap" ); + return; + } + bool written = false; - //these are the bare minimum metadata files ive seen on a nand - //i have seen some where there are full banners for the 0x10002 titles, but this is not always the case - for( quint16 i = 0; i < 3; i++ ) - { - quint64 tid; - quint16 ver; - QString desc; - switch( i ) - { - case 0: - tid = 0x100000004ull; - ver = 3; - desc = "sd_os1_1.64"; - break; - case 1: - tid = 0x100000009ull; - ver = 1; - desc = "sd_os1_1.64"; - break; - case 2: - tid = 0x100000002ull; - ver = 0; - desc = "systemmenu.rvl.0.4"; - break; - } - QString tidStr = QString( "%1" ).arg( tid, 16, 16, QChar( '0' ) ); - tidStr.insert( 8, "/" ); - QString path = "/meta/" + tidStr + "/title.met"; - if( ItemFromPath( path ) )//already have this metadata - continue; + //these are the bare minimum metadata files ive seen on a nand + //i have seen some where there are full banners for the 0x10002 titles, but this is not always the case + for( quint16 i = 0; i < 3; i++ ) + { + quint64 tid; + quint16 ver; + QString desc; + switch( i ) + { + case 0: + tid = 0x100000004ull; + ver = 3; + desc = "sd_os1_1.64"; + break; + case 1: + tid = 0x100000009ull; + ver = 1; + desc = "sd_os1_1.64"; + break; + case 2: + tid = 0x100000002ull; + ver = 0; + desc = "systemmenu.rvl.0.4"; + break; + } + QString tidStr = QString( "%1" ).arg( tid, 16, 16, QChar( '0' ) ); + tidStr.insert( 8, "/" ); + QString path = "/meta/" + tidStr + "/title.met"; + if( ItemFromPath( path ) )//already have this metadata + continue; - //create subfolder - path = "/meta/" + tidStr; - if( !CreateIfNeeded( path, 0x1000, 1, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) - { - ShowMessage( "Cannot create " + path + " for metacrap" ); - return; - } - path = "/meta/" + tidStr + "/title.met"; + //create subfolder + path = "/meta/" + tidStr; + if( !CreateIfNeeded( path, 0x1000, 1, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) + { + ShowMessage( "Cannot create " + path + " for metacrap" ); + return; + } + path = "/meta/" + tidStr + "/title.met"; - //generate metacrap - QByteArray stuff = GenMeta( desc, tid, ver ); + //generate metacrap + QByteArray stuff = GenMeta( desc, tid, ver ); - quint16 handle = nand.CreateEntry( path, 0x1000, 1, NAND_FILE, NAND_RW, NAND_RW, NAND_RW ); - if( !handle || !nand.SetData( handle, stuff ) || !UpdateTree() ) - { - ShowMessage( "Error writing data for " + path + " " ); - return; - } - written = true; - } - if( !written ) - { - ShowMessage( "Nothing to write in \"/meta\"" ); - return; - } - if( !nand.WriteMetaData() ) - { - ShowMessage( "Error writing nand metadata for \"/meta\"" ); - return; - } - ShowMessage( "Wrote entries for \"/meta\"" ); + quint16 handle = nand.CreateEntry( path, 0x1000, 1, NAND_FILE, NAND_RW, NAND_RW, NAND_RW ); + if( !handle || !nand.SetData( handle, stuff ) || !UpdateTree() ) + { + ShowMessage( "Error writing data for " + path + " " ); + return; + } + written = true; + } + if( !written ) + { + ShowMessage( "Nothing to write in \"/meta\"" ); + return; + } + if( !nand.WriteMetaData() ) + { + ShowMessage( "Error writing nand metadata for \"/meta\"" ); + return; + } + ShowMessage( "Wrote entries for \"/meta\"" ); } QByteArray MainWindow::GenMeta( const QString &desc, quint64 tid, quint16 version ) { - QByteArray ret( 0x40, '\0' ); - QBuffer buf( &ret ); - buf.open( QIODevice::WriteOnly ); - buf.write( desc.toLatin1().data() ); - tid = qFromBigEndian( tid ); - buf.seek( 0x20 ); - buf.write( (const char*)&tid, 8 ); - version = qFromBigEndian( version ); - buf.write( (const char*)&version, 4 ); - buf.close(); - return ret; + QByteArray ret( 0x40, '\0' ); + QBuffer buf( &ret ); + buf.open( QIODevice::WriteOnly ); + buf.write( desc.toLatin1().data() ); + tid = qFromBigEndian( tid ); + buf.seek( 0x20 ); + buf.write( (const char*)&tid, 8 ); + version = qFromBigEndian( version ); + buf.write( (const char*)&version, 4 ); + buf.close(); + return ret; } void MainWindow::on_actionWrite_meta_entries_triggered() { - AddStuffToMetaFolder(); + AddStuffToMetaFolder(); } //content -> format void MainWindow::on_actionFormat_triggered() { - if( nand.FilePath().isEmpty() ) - return; - if( QMessageBox::warning( this, tr( "Format" ), \ - tr( "You are about to format
%1.

This cannot be undone. Are you sure you want to do it?" ).arg( nand.FilePath() ),\ - QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes ) - return; + if( nand.FilePath().isEmpty() ) + return; + if( QMessageBox::warning( this, tr( "Format" ), \ + tr( "You are about to format
%1.

This cannot be undone. Are you sure you want to do it?" ).arg( nand.FilePath() ),\ + QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes ) + return; - ShowMessage( "Formatting nand..." ); - if( !nand.Format() ) - { - ShowMessage( "Error! This nand may be broken now :(" ); - return; - } + ShowMessage( "Formatting nand..." ); + if( !nand.Format() ) + { + ShowMessage( "Error! This nand may be broken now :(" ); + return; + } - //add folders to root - if( !nand.CreateEntry( "/sys", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) - || !nand.CreateEntry( "/ticket", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) - || !nand.CreateEntry( "/title", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) - || !nand.CreateEntry( "/shared1", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) - || !nand.CreateEntry( "/shared2", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) - || !nand.CreateEntry( "/import", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) - || !nand.CreateEntry( "/meta", 0x1000, 1, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) - || !nand.CreateEntry( "/tmp", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) - { - ShowMessage( "Error! Can't create base folders in the new nand." ); - return; - } - //add cert.sys - quint16 handle = nand.CreateEntry( "/sys/cert.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, NAND_READ ); - if( !handle || !nand.SetData( handle, QByteArray( (const char*)&certs_dat, CERTS_DAT_SIZE ) ) ) - { - ShowMessage( "Error! Can't cert.sys." ); - return; - } + //add folders to root + if( !nand.CreateEntry( "/sys", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) + || !nand.CreateEntry( "/ticket", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) + || !nand.CreateEntry( "/title", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ ) + || !nand.CreateEntry( "/shared1", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) + || !nand.CreateEntry( "/shared2", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) + || !nand.CreateEntry( "/import", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 ) + || !nand.CreateEntry( "/meta", 0x1000, 1, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) + || !nand.CreateEntry( "/tmp", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) ) + { + ShowMessage( "Error! Can't create base folders in the new nand." ); + return; + } + //add cert.sys + quint16 handle = nand.CreateEntry( "/sys/cert.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, NAND_READ ); + if( !handle || !nand.SetData( handle, QByteArray( (const char*)&certs_dat, CERTS_DAT_SIZE ) ) ) + { + ShowMessage( "Error! Can't cert.sys." ); + return; + } - //wipe all user-created entries from uid.sys - QByteArray uidData = uid.Data(); - QBuffer buf( &uidData ); - buf.open( QIODevice::ReadWrite ); + //wipe all user-created entries from uid.sys + QByteArray uidData = uid.Data(); + QBuffer buf( &uidData ); + buf.open( QIODevice::ReadWrite ); - quint64 tid; - quint16 titles = 0; - quint32 cnt = uidData.size() / 12; - for( quint32 i = 0; i < cnt; i++ ) - { - buf.seek( i * 12 ); - buf.read( (char*)&tid, 8 ); - tid = qFromBigEndian( tid ); - quint32 upper = ( ( tid >> 32 ) & 0xffffffff ); - quint32 lower = ( tid & 0xffffffff ); - //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' - lower == 0x48415858 || //original HBC - tid == 0x100000000ull || //bannerbomb -> ATD ( or any other program that uses the SU tid ) - ( upper == 0x10000 && ( ( lower & 0xffffff00 ) == 0x555000 ) ) ) //a disc update partition - break; - titles++; - } - buf.close(); + quint64 tid; + quint16 titles = 0; + quint32 cnt = uidData.size() / 12; + for( quint32 i = 0; i < cnt; i++ ) + { + buf.seek( i * 12 ); + buf.read( (char*)&tid, 8 ); + tid = qFromBigEndian( tid ); + quint32 upper = ( ( tid >> 32 ) & 0xffffffff ); + quint32 lower = ( tid & 0xffffffff ); + //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' + lower == 0x48415858 || //original HBC + tid == 0x100000000ull || //bannerbomb -> ATD ( or any other program that uses the SU tid ) + ( upper == 0x10000 && ( ( lower & 0xffffff00 ) == 0x555000 ) ) ) //a disc update partition + break; + titles++; + } + buf.close(); - uidData.resize( 12 * titles ); - //hexdump12( uidData ); - uid = UIDmap( uidData ); + uidData.resize( 12 * titles ); + //hexdump12( uidData ); + uid = UIDmap( uidData ); - uidDirty = true; - sharedDirty = true; - shared = SharedContentMap(); - if( !nand.CreateEntry( "/sys/uid.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) - { - ShowMessage( "Error! Can't create /sys/uid.sys" ); - return; - } - //clear content.map - if( !nand.CreateEntry( "/shared1/content.map", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) - { - ShowMessage( "Error! Can't create /shared1/content.map" ); - return; - } + uidDirty = true; + sharedDirty = true; + shared = SharedContentMap(); + if( !nand.CreateEntry( "/sys/uid.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) + { + ShowMessage( "Error! Can't create /sys/uid.sys" ); + return; + } + //clear content.map + if( !nand.CreateEntry( "/shared1/content.map", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) ) + { + ShowMessage( "Error! Can't create /shared1/content.map" ); + return; + } - //commit - if( !nand.WriteMetaData() || !UpdateTree() ) - { - ShowMessage( "Error finalizing formatting!" ); - return; - } - ShowMessage( "Done!" ); + //commit + if( !nand.WriteMetaData() || !UpdateTree() ) + { + ShowMessage( "Error finalizing formatting!" ); + return; + } + ShowMessage( "Done!" ); } diff --git a/ohneschwanzenegger/mainwindow.h b/ohneschwanzenegger/mainwindow.h index 30c231e..b144caa 100644 --- a/ohneschwanzenegger/mainwindow.h +++ b/ohneschwanzenegger/mainwindow.h @@ -44,15 +44,15 @@ private: bool InstallNUSItem( NusJob job ); quint16 CreateIfNeeded( const QString &path, quint32 uid, quint16 gid, quint8 attr, quint8 user_perm, quint8 group_perm, quint8 other_perm ); - bool InstallSharedContent( const QByteArray stuff, const QByteArray hash = QByteArray() ); + bool InstallSharedContent( const QByteArray &stuff, const QByteArray &hash = QByteArray() ); - void SaveSettings(); - void LoadSettings(); + void SaveSettings(); + void LoadSettings(); #if 0 - void TryToAddDefaultSettings(); + void TryToAddDefaultSettings(); #endif - void AddStuffToMetaFolder(); - QByteArray GenMeta( const QString &desc, quint64 tid, quint16 version ); + void AddStuffToMetaFolder(); + QByteArray GenMeta( const QString &desc, quint64 tid, quint16 version ); public slots: //slots for getting info from the NUS downloader @@ -62,9 +62,9 @@ public slots: void ReceiveTitleFromNus( NusJob job ); private slots: - void on_actionFormat_triggered(); - void on_actionWrite_meta_entries_triggered(); - void on_pushButton_CachePathBrowse_clicked(); + void on_actionFormat_triggered(); + void on_actionWrite_meta_entries_triggered(); + void on_pushButton_CachePathBrowse_clicked(); void on_actionAbout_triggered(); void on_pushButton_initNand_clicked(); void on_actionNew_nand_from_keys_triggered();