mirror of
https://github.com/martravi/wiiqt.git
synced 2024-11-22 09:09:18 +01:00
* fix installing saves to nand dump
* add installing saves to nand in savetoy
This commit is contained in:
parent
d5d094862d
commit
14b4cb1f3d
@ -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,11 +892,13 @@ 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 )
|
||||||
{
|
{
|
||||||
QString cp = ToNandPath( entry );
|
QString cp = ToNandPath( entry );
|
||||||
quint8 attr = save.attr.at( entryIdx );
|
quint8 attr = save.attr.at( entryIdx );
|
||||||
if( NAND_ATTR_TYPE( attr ) == NAND_FILE )//this is a file
|
if( NAND_ATTR_TYPE( attr ) == NAND_FILE )//this is a 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() )
|
||||||
|
@ -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
|
||||||
|
@ -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 );
|
||||||
|
}
|
||||||
|
@ -62,7 +62,8 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
private slots:
|
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_pushButton_pcDelete_clicked();
|
||||||
void on_comboBox_pcSelect_currentIndexChanged(int index);
|
void on_comboBox_pcSelect_currentIndexChanged(int index);
|
||||||
void on_listWidget_pcSaves_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous);
|
void on_listWidget_pcSaves_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous);
|
||||||
|
@ -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">
|
||||||
|
@ -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 );
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user