diff --git a/WiiQt/nanddump.cpp b/WiiQt/nanddump.cpp index a119e1f..e919911 100644 --- a/WiiQt/nanddump.cpp +++ b/WiiQt/nanddump.cpp @@ -883,7 +883,7 @@ bool NandDump::InstallSave( const SaveGame &save ) QString path = basePath + p + "/data"; //make sure the path exists - if( !QFileInfo( path ).exists() || !QDir().mkpath( path ) ) + if( !QFileInfo( path ).exists() && !QDir().mkpath( path ) ) { qWarning() << "NandDump::InstallSave -> error creating" << path; return false; @@ -892,11 +892,13 @@ bool NandDump::InstallSave( const SaveGame &save ) if( !QFileInfo( basePath + p + "/content" ).exists() ) QDir().mkpath( basePath + p + "/content" ); + path = p + "/data"; + quint16 dataIdx = 0; quint16 entryIdx = 0; foreach( QString entry, save.entries ) - { - QString cp = ToNandPath( entry ); + { + QString cp = ToNandPath( entry ); quint8 attr = save.attr.at( entryIdx ); if( NAND_ATTR_TYPE( attr ) == NAND_FILE )//this is a file { diff --git a/WiiQt/tools.cpp b/WiiQt/tools.cpp index f539e74..0242a73 100644 --- a/WiiQt/tools.cpp +++ b/WiiQt/tools.cpp @@ -122,28 +122,10 @@ void AesSetKey( const QByteArray &key ) QByteArray GetSha1( const QByteArray &stuff ) { return QCryptographicHash::hash( stuff, QCryptographicHash::Sha1 ); - /*SHA1Context sha; - SHA1Reset( &sha ); - SHA1Input( &sha, (const unsigned char*)stuff.data(), stuff.size() ); - if( !SHA1Result( &sha ) ) - { - qWarning() << "GetSha1 -> sha error"; - return QByteArray(); - } - QByteArray ret( 20, '\0' ); - quint8 *p = (quint8 *)ret.data(); - for( int i = 0; i < 5 ; i++ ) - { - quint32 part = qFromBigEndian( sha.Message_Digest[ i ] ); - memcpy( p + ( i * 4 ), &part, 4 ); - } - return ret;*/ } - QByteArray GetMd5( const QByteArray &stuff ) { - //qDebug() << "GetMd5" << hex << stuff.size(); return QCryptographicHash::hash( stuff, QCryptographicHash::Md5 ); } @@ -245,6 +227,14 @@ const QByteArray DataFromSave( const SaveGame &save, const QString &name ) return QByteArray(); } +quint32 SaveItemSize( const SaveGame &save ) +{ + quint32 ret = 0; + foreach( QByteArray ba, save.data ) + ret += ba.size(); + return ret; +} + quint8 AttrFromSave( const SaveGame &save, const QString &name ) { if( !save.tid || save.entries.size() != save.attr.size() ) diff --git a/WiiQt/tools.h b/WiiQt/tools.h index 86eb818..1fa2896 100644 --- a/WiiQt/tools.h +++ b/WiiQt/tools.h @@ -64,6 +64,7 @@ QByteArray GetMd5( const QByteArray &stuff ); bool IsValidSave( const SaveGame &save ); const QByteArray DataFromSave( const SaveGame &save, const QString &name ); +quint32 SaveItemSize( const SaveGame &save ); quint8 AttrFromSave( const SaveGame &save, const QString &name ); //get a padded version of the given buffer diff --git a/saveToy/mainwindow.cpp b/saveToy/mainwindow.cpp index 849c9f8..42a38d7 100644 --- a/saveToy/mainwindow.cpp +++ b/saveToy/mainwindow.cpp @@ -15,7 +15,8 @@ #ifdef Q_WS_MAC static QString sneekPath = "/Volumes/VMware Shared Folders/host-c/QtWii/test"; #else -static QString sneekPath = "/media/SDHC_4GB"; +//static QString sneekPath = "/media/SDHC_4GB"; +static QString sneekPath = "../../test"; #endif MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), bannerthread( this ) @@ -43,7 +44,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi connect( &pcIconTimer, SIGNAL( timeout() ), this, SLOT( ShowNextPcIcon() ) ); //GetSavesFromSneek( "/media/WiiFat500" ); - GetSavesFromSneek( sneekPath ); + //GetSavesFromSneek( sneekPath ); //GetSavesFromPC( "./saveBackups" ); } @@ -754,3 +755,138 @@ void MainWindow::ClearPcGuiInfo() ui->plainTextEdit_pcDesc->clear(); ui->comboBox_pcSelect->clear(); } + +//button to install PC save clicked +void MainWindow::on_pushButton_pcInstall_clicked() +{ + QString nPath = bannerthread.NandBasePath(); + if( nPath.isEmpty() ) + { + return; + } + QListselected = ui->listWidget_pcSaves->selectedItems(); + quint32 cnt = selected.size(); + if( cnt != 1 ) + return; + + SaveListItem *si = static_cast< SaveListItem * >( selected.at( 0 ) ); + + int i = ui->comboBox_pcSelect->currentIndex(); + + //find the item in the list of infos that matches this item + currentPcSave = 0xffffffff; + cnt = pcInfos.size(); + for( quint32 i = 0; i < cnt; i++ ) + { + if( si->Tid() == pcInfos.at( i ).tid ) + { + currentPcSave = i; + break; + } + } + if( currentPcSave == 0xffffffff ) + { + qWarning() << "MainWindow::on_pushButton_pcInstall_clicked() -> tid not found"; + return; + } + if( i < 0 || i >= pcInfos.at( currentPcSave ).sizes.size() ) + { + qWarning() << "MainWindow::on_pushButton_pcInstall_clicked() -> index is out of range"; + return; + } + + //read datad.bin from the zip file + QString zipPath = pcInfos.at( currentPcSave ).paths.at( i ); + QByteArray dataBin; + QuaZip zip( zipPath ); + if( !zip.open( QuaZip::mdUnzip ) ) + { + qWarning("on_pushButton_pcInstall_clicked(): zip.open(): %d", zip.getZipError() ); + return; + } + zip.setFileNameCodec("IBM866"); + QuaZipFile file(&zip); + QString name; + for( bool more = zip.goToFirstFile(); more; more = zip.goToNextFile() ) + { + if( !file.open( QIODevice::ReadOnly ) ) + { + qWarning("on_pushButton_pcInstall_clicked(): file.open(): %d", file.getZipError() ); + zip.close(); + return; + } + name = file.getActualFileName(); + if( file.getZipError() != UNZ_OK ) + { + qWarning("on_pushButton_pcInstall_clicked(): file.getFileName(): %d", file.getZipError()); + file.close(); + zip.close(); + return; + } + if( name != "data.bin" ) + { + file.close(); + continue; + } + dataBin = file.readAll(); + if( file.getZipError() != UNZ_OK ) + { + qWarning("on_pushButton_pcInstall_clicked(): file.getFileName(): %d", file.getZipError()); + file.close(); + zip.close(); + return; + } + file.close(); + break; + } + zip.close(); + if( dataBin.isEmpty() ) + { + qWarning() << "no data.bin found in the archive" << zipPath; + return; + } + SaveGame save = SaveDataBin::StructFromDataBin( dataBin ); + if( !IsValidSave( save ) ) + { + qWarning() << "got an invalid save from the data.bin in" << zipPath; + return; + } + + //see if the sneek nand and already has a save for this game + cnt = ui->listWidget_sneekSaves->count(); + for( quint32 i = 0; i < cnt; i++ ) + { + QListWidgetItem* item = ui->listWidget_sneekSaves->item( i ); + si = static_cast< SaveListItem * >( item ); + bool ok = false; + quint64 t = si->Tid().toLongLong( &ok, 16 ); + if( !ok || t != save.tid ) + continue; + + //delete old save from sneek nand + if( !bannerthread.DeleteSaveFromSneekNand( save.tid ) ) + { + qWarning() << "error deleting the old save"; + return; + } + + //delete old save from sneek browser + si = static_cast< SaveListItem * >( ui->listWidget_sneekSaves->takeItem( i ) ); + delete si; + si = NULL; + + break; + } + bool success = bannerthread.InstallSaveToSneekNand( save ); + if( !success ) + { + qWarning() << "error installing the save"; + return; + } + //add this new item to the sneek list view + quint32 size = SaveItemSize( save ); + QByteArray bnr = DataFromSave( save, "/banner.bin" ); + SaveBanner sb( bnr ); + new SaveListItem( sb, QString( "%1" ).arg( save.tid, 16, 16, QChar( '0' ) ) , size, ui->listWidget_sneekSaves ); + ui->statusBar->showMessage( tr( "Installed save to extracted nand" ), 5000 ); +} diff --git a/saveToy/mainwindow.h b/saveToy/mainwindow.h index 2ee5727..e383a94 100644 --- a/saveToy/mainwindow.h +++ b/saveToy/mainwindow.h @@ -62,7 +62,8 @@ private: private slots: - void on_actionSet_Local_Path_triggered(); + void on_pushButton_pcInstall_clicked(); + void on_actionSet_Local_Path_triggered(); void on_pushButton_pcDelete_clicked(); void on_comboBox_pcSelect_currentIndexChanged(int index); void on_listWidget_pcSaves_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous); diff --git a/saveToy/mainwindow.ui b/saveToy/mainwindow.ui index 9fea557..6f6a411 100644 --- a/saveToy/mainwindow.ui +++ b/saveToy/mainwindow.ui @@ -21,7 +21,7 @@ - 0 + 1 diff --git a/saveToy/saveloadthread.cpp b/saveToy/saveloadthread.cpp index b52b305..3975a1d 100644 --- a/saveToy/saveloadthread.cpp +++ b/saveToy/saveloadthread.cpp @@ -63,7 +63,6 @@ SaveGame SaveLoadThread::GetSave( quint64 tid ) return nand.GetSaveData( tid ); } - void SaveLoadThread::run() { if ( abort ) @@ -262,6 +261,20 @@ void SaveLoadThread::GetPCSaves() emit SendProgress( 100 ); } +const QString SaveLoadThread::NandBasePath() +{ + if( isRunning() ) + return QString(); + return nand.BasePath(); +} + +bool SaveLoadThread::InstallSaveToSneekNand( SaveGame save ) +{ + if( isRunning() ) + return false; + return nand.InstallSave( save ); +} + void SaveLoadThread::GetSavesFromNandDump() { emit SendProgress( 0 ); diff --git a/saveToy/saveloadthread.h b/saveToy/saveloadthread.h index 21a9836..397c948 100644 --- a/saveToy/saveloadthread.h +++ b/saveToy/saveloadthread.h @@ -38,7 +38,9 @@ public: //TODO: these arent done on the work thread, but instead in the calling thread bool DeleteSaveFromSneekNand( quint64 tid ); + bool InstallSaveToSneekNand( SaveGame save ); SaveGame GetSave( quint64 tid ); + const QString NandBasePath(); void ForceQuit();