* fix installing saves to nand dump

* add installing saves to nand in savetoy
This commit is contained in:
giantpune@gmail.com 2011-01-04 05:37:50 +00:00
parent d5d094862d
commit 14b4cb1f3d
8 changed files with 171 additions and 26 deletions

View File

@ -883,7 +883,7 @@ bool NandDump::InstallSave( const SaveGame &save )
QString path = basePath + p + "/data"; QString path = basePath + p + "/data";
//make sure the path exists //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; qWarning() << "NandDump::InstallSave -> error creating" << path;
return false; return false;
@ -892,6 +892,8 @@ bool NandDump::InstallSave( const SaveGame &save )
if( !QFileInfo( basePath + p + "/content" ).exists() ) if( !QFileInfo( basePath + p + "/content" ).exists() )
QDir().mkpath( basePath + p + "/content" ); QDir().mkpath( basePath + p + "/content" );
path = p + "/data";
quint16 dataIdx = 0; quint16 dataIdx = 0;
quint16 entryIdx = 0; quint16 entryIdx = 0;
foreach( QString entry, save.entries ) foreach( QString entry, save.entries )

View File

@ -122,28 +122,10 @@ void AesSetKey( const QByteArray &key )
QByteArray GetSha1( const QByteArray &stuff ) QByteArray GetSha1( const QByteArray &stuff )
{ {
return QCryptographicHash::hash( stuff, QCryptographicHash::Sha1 ); 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 ) QByteArray GetMd5( const QByteArray &stuff )
{ {
//qDebug() << "GetMd5" << hex << stuff.size();
return QCryptographicHash::hash( stuff, QCryptographicHash::Md5 ); return QCryptographicHash::hash( stuff, QCryptographicHash::Md5 );
} }
@ -245,6 +227,14 @@ const QByteArray DataFromSave( const SaveGame &save, const QString &name )
return QByteArray(); 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 ) quint8 AttrFromSave( const SaveGame &save, const QString &name )
{ {
if( !save.tid || save.entries.size() != save.attr.size() ) if( !save.tid || save.entries.size() != save.attr.size() )

View File

@ -64,6 +64,7 @@ QByteArray GetMd5( const QByteArray &stuff );
bool IsValidSave( const SaveGame &save ); bool IsValidSave( const SaveGame &save );
const QByteArray DataFromSave( const SaveGame &save, const QString &name ); const QByteArray DataFromSave( const SaveGame &save, const QString &name );
quint32 SaveItemSize( const SaveGame &save );
quint8 AttrFromSave( const SaveGame &save, const QString &name ); quint8 AttrFromSave( const SaveGame &save, const QString &name );
//get a padded version of the given buffer //get a padded version of the given buffer

View File

@ -15,7 +15,8 @@
#ifdef Q_WS_MAC #ifdef Q_WS_MAC
static QString sneekPath = "/Volumes/VMware Shared Folders/host-c/QtWii/test"; static QString sneekPath = "/Volumes/VMware Shared Folders/host-c/QtWii/test";
#else #else
static QString sneekPath = "/media/SDHC_4GB"; //static QString sneekPath = "/media/SDHC_4GB";
static QString sneekPath = "../../test";
#endif #endif
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), bannerthread( this ) 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() ) ); connect( &pcIconTimer, SIGNAL( timeout() ), this, SLOT( ShowNextPcIcon() ) );
//GetSavesFromSneek( "/media/WiiFat500" ); //GetSavesFromSneek( "/media/WiiFat500" );
GetSavesFromSneek( sneekPath ); //GetSavesFromSneek( sneekPath );
//GetSavesFromPC( "./saveBackups" ); //GetSavesFromPC( "./saveBackups" );
} }
@ -754,3 +755,138 @@ void MainWindow::ClearPcGuiInfo()
ui->plainTextEdit_pcDesc->clear(); ui->plainTextEdit_pcDesc->clear();
ui->comboBox_pcSelect->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;
}
QList<QListWidgetItem*>selected = 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 );
}

View File

@ -62,6 +62,7 @@ private:
private slots: private slots:
void on_pushButton_pcInstall_clicked();
void on_actionSet_Local_Path_triggered(); void on_actionSet_Local_Path_triggered();
void on_pushButton_pcDelete_clicked(); void on_pushButton_pcDelete_clicked();
void on_comboBox_pcSelect_currentIndexChanged(int index); void on_comboBox_pcSelect_currentIndexChanged(int index);

View File

@ -21,7 +21,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="sneekTab"> <widget class="QWidget" name="sneekTab">
<attribute name="title"> <attribute name="title">

View File

@ -63,7 +63,6 @@ SaveGame SaveLoadThread::GetSave( quint64 tid )
return nand.GetSaveData( tid ); return nand.GetSaveData( tid );
} }
void SaveLoadThread::run() void SaveLoadThread::run()
{ {
if ( abort ) if ( abort )
@ -262,6 +261,20 @@ void SaveLoadThread::GetPCSaves()
emit SendProgress( 100 ); 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() void SaveLoadThread::GetSavesFromNandDump()
{ {
emit SendProgress( 0 ); emit SendProgress( 0 );

View File

@ -38,7 +38,9 @@ public:
//TODO: these arent done on the work thread, but instead in the calling thread //TODO: these arent done on the work thread, but instead in the calling thread
bool DeleteSaveFromSneekNand( quint64 tid ); bool DeleteSaveFromSneekNand( quint64 tid );
bool InstallSaveToSneekNand( SaveGame save );
SaveGame GetSave( quint64 tid ); SaveGame GetSave( quint64 tid );
const QString NandBasePath();
void ForceQuit(); void ForceQuit();