mirror of
https://github.com/martravi/wiiqt.git
synced 2024-11-22 17:19:18 +01:00
* add access functions to the nandBin class to get the cluster map for whole nand and for a given file
* change the nandExtract program a bit. move nand extraction to a thread to keep it from hanging the main thread * add pretty block map
This commit is contained in:
parent
09d82184d9
commit
167f73aa41
7
.gitattributes
vendored
7
.gitattributes
vendored
@ -33,12 +33,17 @@ WiiQt/uidmap.cpp -text
|
|||||||
WiiQt/uidmap.h -text
|
WiiQt/uidmap.h -text
|
||||||
WiiQt/wad.cpp -text
|
WiiQt/wad.cpp -text
|
||||||
WiiQt/wad.h -text
|
WiiQt/wad.h -text
|
||||||
nandExtract/includes.h -text
|
nandExtract/black.png -text
|
||||||
|
nandExtract/blue.png -text
|
||||||
|
nandExtract/green.png -text
|
||||||
|
nandExtract/grey.png -text
|
||||||
nandExtract/main.cpp -text
|
nandExtract/main.cpp -text
|
||||||
nandExtract/nandExtract.pro -text
|
nandExtract/nandExtract.pro -text
|
||||||
nandExtract/nandwindow.cpp -text
|
nandExtract/nandwindow.cpp -text
|
||||||
nandExtract/nandwindow.h -text
|
nandExtract/nandwindow.h -text
|
||||||
nandExtract/nandwindow.ui -text
|
nandExtract/nandwindow.ui -text
|
||||||
|
nandExtract/pink.png -text
|
||||||
|
nandExtract/rc.qrc -text
|
||||||
nandExtract/readmii.txt -text
|
nandExtract/readmii.txt -text
|
||||||
nand_dump/main.cpp -text
|
nand_dump/main.cpp -text
|
||||||
nand_dump/mainwindow.cpp -text
|
nand_dump/mainwindow.cpp -text
|
||||||
|
@ -5,6 +5,7 @@ NandBin::NandBin( QObject * parent, const QString &path ) : QObject( parent )
|
|||||||
{
|
{
|
||||||
type = -1;
|
type = -1;
|
||||||
fatNames = false;
|
fatNames = false;
|
||||||
|
fstInited = false;
|
||||||
root = NULL;
|
root = NULL;
|
||||||
|
|
||||||
if( !path.isEmpty() )
|
if( !path.isEmpty() )
|
||||||
@ -22,6 +23,7 @@ NandBin::~NandBin()
|
|||||||
|
|
||||||
bool NandBin::SetPath( const QString &path )
|
bool NandBin::SetPath( const QString &path )
|
||||||
{
|
{
|
||||||
|
fstInited = false;
|
||||||
//nandPath = path;
|
//nandPath = path;
|
||||||
if( f.isOpen() )
|
if( f.isOpen() )
|
||||||
f.close();
|
f.close();
|
||||||
@ -160,7 +162,10 @@ bool NandBin::ExtractDir( fst_t fst, QString parent )
|
|||||||
|
|
||||||
QFileInfo fi( parent + "/" + filename );
|
QFileInfo fi( parent + "/" + filename );
|
||||||
if( filename != "/" && !fi.exists() && !QDir().mkpath( fi.absoluteFilePath() ) )
|
if( filename != "/" && !fi.exists() && !QDir().mkpath( fi.absoluteFilePath() ) )
|
||||||
|
{
|
||||||
|
emit SendError( tr( "Can\'t create directory \"%1\"" ).arg( fi.absoluteFilePath() ) );
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if( fst.sub != 0xffff && !ExtractFST( fst.sub, fi.absoluteFilePath() ) )
|
if( fst.sub != 0xffff && !ExtractFST( fst.sub, fi.absoluteFilePath() ) )
|
||||||
return false;
|
return false;
|
||||||
@ -179,22 +184,18 @@ bool NandBin::ExtractFile( fst_t fst, QString parent )
|
|||||||
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 false;
|
return false;
|
||||||
|
|
||||||
QFile out( fi.absoluteFilePath() );
|
if( !WriteFile( fi.absoluteFilePath(), data ) )
|
||||||
if( out.exists() )// !! delete existing files
|
|
||||||
out.remove();
|
|
||||||
|
|
||||||
if( !out.open( QIODevice::WriteOnly ) )
|
|
||||||
{
|
{
|
||||||
emit SendError( tr( "Can't open \"%1\" for writing" ).arg( fi.absoluteFilePath() ) );
|
emit SendError( tr( "Error writing \"%1\"" ).arg( fi.absoluteFilePath() ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out.write( data );
|
|
||||||
out.close();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NandBin::InitNand( QIcon dirs, QIcon files )
|
bool NandBin::InitNand( QIcon dirs, QIcon files )
|
||||||
{
|
{
|
||||||
|
fstInited = false;
|
||||||
|
fats.clear();
|
||||||
type = GetDumpType( f.size() );
|
type = GetDumpType( f.size() );
|
||||||
if( type < 0 || type > 3 )
|
if( type < 0 || type > 3 )
|
||||||
return false;
|
return false;
|
||||||
@ -211,6 +212,16 @@ bool NandBin::InitNand( QIcon dirs, QIcon files )
|
|||||||
loc_fat = loc_super;
|
loc_fat = loc_super;
|
||||||
loc_fst = loc_fat + 0x0C + n_fatlen[ type ];
|
loc_fst = loc_fat + 0x0C + n_fatlen[ type ];
|
||||||
|
|
||||||
|
//cache all the entries
|
||||||
|
for( quint16 i = 0; i < 0x17ff; i++ )
|
||||||
|
fsts[ i ] = GetFST( i );
|
||||||
|
|
||||||
|
//cache all the fats
|
||||||
|
for( quint16 i = 0; i < 0x8000; i++ )
|
||||||
|
fats << GetFAT( i );
|
||||||
|
|
||||||
|
fstInited = true;
|
||||||
|
|
||||||
if( root )
|
if( root )
|
||||||
delete root;
|
delete root;
|
||||||
|
|
||||||
@ -220,7 +231,7 @@ bool NandBin::InitNand( QIcon dirs, QIcon files )
|
|||||||
root = new QTreeWidgetItem( QStringList() << nandPath );
|
root = new QTreeWidgetItem( QStringList() << nandPath );
|
||||||
AddChildren( root, 0 );
|
AddChildren( root, 0 );
|
||||||
|
|
||||||
ShowInfo();
|
//ShowInfo();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,6 +360,11 @@ fst_t NandBin::GetFST( quint16 entry )
|
|||||||
fst.filename[ 0 ] = '\0';
|
fst.filename[ 0 ] = '\0';
|
||||||
return fst;
|
return fst;
|
||||||
}
|
}
|
||||||
|
if( fstInited )//we've already read this once, just give back the one we already know
|
||||||
|
{
|
||||||
|
//qDebug() << "reading from cache" << hex << entry;
|
||||||
|
return fsts[ entry ];
|
||||||
|
}
|
||||||
// compensate for 64 bytes of ecc data every 64 fst entries
|
// compensate for 64 bytes of ecc data every 64 fst entries
|
||||||
quint32 n_fst[] = { 0, 2, 2 };
|
quint32 n_fst[] = { 0, 2, 2 };
|
||||||
int loc_entry = ( ( ( entry / 0x40 ) * n_fst[ type ] ) + entry ) * 0x20;
|
int loc_entry = ( ( ( entry / 0x40 ) * n_fst[ type ] ) + entry ) * 0x20;
|
||||||
@ -390,6 +406,8 @@ fst_t NandBin::GetFST( quint16 entry )
|
|||||||
|
|
||||||
quint16 NandBin::GetFAT( quint16 fat_entry )
|
quint16 NandBin::GetFAT( quint16 fat_entry )
|
||||||
{
|
{
|
||||||
|
if( fstInited )
|
||||||
|
return fats.at( fat_entry );
|
||||||
/*
|
/*
|
||||||
* compensate for "off-16" storage at beginning of superblock
|
* compensate for "off-16" storage at beginning of superblock
|
||||||
* 53 46 46 53 XX XX XX XX 00 00 00 00
|
* 53 46 46 53 XX XX XX XX 00 00 00 00
|
||||||
@ -508,6 +526,26 @@ QByteArray NandBin::GetFile( fst_t fst )
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QList<quint16> NandBin::GetFatsForFile( quint16 i )
|
||||||
|
{
|
||||||
|
//qDebug() << "NandBin::GetFatsForFile" << i;
|
||||||
|
QList<quint16> ret;
|
||||||
|
fst_t fst = GetFST( i );
|
||||||
|
|
||||||
|
if( fst.filename[ 0 ] == '\0' )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
quint16 fat = fst.sub;
|
||||||
|
quint16 j = 0;//just to make sure a broken nand doesnt lead to an endless loop
|
||||||
|
while ( fat < 0x8000 && fat > 0 && ++j )
|
||||||
|
{
|
||||||
|
ret << fat;
|
||||||
|
fat = GetFAT( fat );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void NandBin::SetFixNamesForFAT( bool fix )
|
void NandBin::SetFixNamesForFAT( bool fix )
|
||||||
{
|
{
|
||||||
fatNames = fix;
|
fatNames = fix;
|
||||||
|
@ -78,6 +78,12 @@ public:
|
|||||||
//ie... /title/00000001/00000002/data/setting.txt
|
//ie... /title/00000001/00000002/data/setting.txt
|
||||||
const QByteArray GetData( const QString &path );
|
const QByteArray GetData( const QString &path );
|
||||||
|
|
||||||
|
//returns the fats for this nand.
|
||||||
|
const QList<quint16> GetFats() { return fats; }
|
||||||
|
|
||||||
|
//get the fats for a given file
|
||||||
|
const QList<quint16> GetFatsForFile( quint16 i );
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray key;
|
QByteArray key;
|
||||||
@ -93,6 +99,15 @@ private:
|
|||||||
QIcon groupIcon;
|
QIcon groupIcon;
|
||||||
QIcon keyIcon;
|
QIcon keyIcon;
|
||||||
|
|
||||||
|
//read all the fst and remember them rather than seeking back and forth in the file all the time
|
||||||
|
// uses ~120KiB RAM
|
||||||
|
bool fstInited;
|
||||||
|
fst_t fsts[ 0x17ff ];
|
||||||
|
|
||||||
|
//cache the fat to keep from having to look them up repeatedly
|
||||||
|
// uses ~64KiB
|
||||||
|
QList<quint16>fats;
|
||||||
|
|
||||||
int GetDumpType( quint64 fileSize );
|
int GetDumpType( quint64 fileSize );
|
||||||
bool GetKey( int type );
|
bool GetKey( int type );
|
||||||
QByteArray ReadKeyfile( QString path );
|
QByteArray ReadKeyfile( QString path );
|
||||||
|
BIN
nandExtract/black.png
Executable file
BIN
nandExtract/black.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
nandExtract/blue.png
Executable file
BIN
nandExtract/blue.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
nandExtract/green.png
Executable file
BIN
nandExtract/green.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
nandExtract/grey.png
Executable file
BIN
nandExtract/grey.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
@ -1,35 +0,0 @@
|
|||||||
#ifndef INCLUDES_H
|
|
||||||
#define INCLUDES_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QGraphicsScene>
|
|
||||||
#include <QGraphicsPixmapItem>
|
|
||||||
#include <QLayout>
|
|
||||||
#include <QList>
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QMessageBox>
|
|
||||||
//#include <QNetworkAccessManager>
|
|
||||||
//#include <QNetworkReply>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QSettings>
|
|
||||||
#include <QtDebug>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QtGui>
|
|
||||||
#include <QtGui/QMainWindow>
|
|
||||||
#include <QTreeWidget>
|
|
||||||
#include <QTreeWidgetItem>
|
|
||||||
#include <qpushbutton.h>
|
|
||||||
#include <QWidget>
|
|
||||||
//#include <QDomDocument>
|
|
||||||
//#include <QDomElement>
|
|
||||||
|
|
||||||
|
|
||||||
#endif // INCLUDES_H
|
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
Q_INIT_RESOURCE( rc );
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
NandWindow w;
|
NandWindow w;
|
||||||
w.show();
|
w.show();
|
||||||
|
@ -9,10 +9,15 @@ SOURCES += main.cpp \
|
|||||||
../WiiQt/tools.cpp \
|
../WiiQt/tools.cpp \
|
||||||
../WiiQt/savebanner.cpp \
|
../WiiQt/savebanner.cpp \
|
||||||
../WiiQt/aes.c \
|
../WiiQt/aes.c \
|
||||||
../WiiQt/sha1.c
|
../WiiQt/sha1.c \
|
||||||
|
nandthread.cpp
|
||||||
|
|
||||||
HEADERS += nandwindow.h \
|
HEADERS += nandwindow.h \
|
||||||
../WiiQt/nandbin.h \
|
../WiiQt/nandbin.h \
|
||||||
../WiiQt/tools.h
|
../WiiQt/tools.h \
|
||||||
|
nandthread.h
|
||||||
|
|
||||||
FORMS += nandwindow.ui
|
FORMS += nandwindow.ui
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
rc.qrc
|
||||||
|
@ -1,12 +1,38 @@
|
|||||||
#include "nandwindow.h"
|
#include "nandwindow.h"
|
||||||
#include "ui_nandwindow.h"
|
#include "ui_nandwindow.h"
|
||||||
|
|
||||||
NandWindow::NandWindow(QWidget *parent) :
|
NandWindow::NandWindow( QWidget *parent ) : QMainWindow( parent ), ui( new Ui::NandWindow ), nThread( this )
|
||||||
QMainWindow(parent),
|
|
||||||
ui(new Ui::NandWindow),
|
|
||||||
nandBin( this )
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi( this );
|
||||||
|
freeSpace = 0;
|
||||||
|
|
||||||
|
//setup the block map
|
||||||
|
ui->graphicsView_blocks->setScene( &gv );
|
||||||
|
ui->graphicsView_blocks->setAlignment( Qt::AlignRight );
|
||||||
|
ui->graphicsView_blocks->setRenderHint( QPainter::Antialiasing );
|
||||||
|
|
||||||
|
QPixmap blue( ":/blue.png" );
|
||||||
|
QPixmap green( ":/green.png" );
|
||||||
|
QPixmap pink( ":/pink.png" );
|
||||||
|
QPixmap grey( ":/grey.png" );
|
||||||
|
|
||||||
|
quint16 i = 0;
|
||||||
|
for( quint16 y = 0; y < 352; y += 11 )
|
||||||
|
{
|
||||||
|
for( quint16 x = 0; x < 1408; x += 11 )
|
||||||
|
{
|
||||||
|
pmi[ i ] = new QGraphicsPixmapItem( grey );
|
||||||
|
pmi[ i ]->setPos( x, y );
|
||||||
|
gv.addItem( pmi[ i ] );//items belong to this now. no need to delete them
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//put the progressbar on the status bar
|
||||||
|
ui->progressBar->setVisible( false );
|
||||||
|
ui->statusBar->addPermanentWidget( ui->progressBar, 0 );
|
||||||
|
|
||||||
//ui->treeWidget->header()->resizeSection( 0, 300 );//name
|
//ui->treeWidget->header()->resizeSection( 0, 300 );//name
|
||||||
QFontMetrics fm( fontMetrics() );
|
QFontMetrics fm( fontMetrics() );
|
||||||
ui->treeWidget->header()->resizeSection( 0, fm.width( QString( 22, 'W' ) ) );//name
|
ui->treeWidget->header()->resizeSection( 0, fm.width( QString( 22, 'W' ) ) );//name
|
||||||
@ -19,8 +45,12 @@ NandWindow::NandWindow(QWidget *parent) :
|
|||||||
ui->treeWidget->header()->resizeSection( 7, fm.width( "WWWWW" ) );//attr
|
ui->treeWidget->header()->resizeSection( 7, fm.width( "WWWWW" ) );//attr
|
||||||
|
|
||||||
|
|
||||||
connect( &nandBin, SIGNAL( SendError( QString ) ), this, SLOT( GetError( QString ) ) );
|
//connect( &nandBin, SIGNAL( SendError( QString ) ), this, SLOT( GetError( QString ) ) );
|
||||||
connect( &nandBin, SIGNAL( SendText( QString ) ), this, SLOT( GetStatusUpdate( QString ) ) );
|
//connect( &nandBin, SIGNAL( SendText( QString ) ), this, SLOT( GetStatusUpdate( QString ) ) );
|
||||||
|
connect( &nThread, SIGNAL( SendError( QString ) ), this, SLOT( GetError( QString ) ) );
|
||||||
|
connect( &nThread, SIGNAL( SendText( QString ) ), this, SLOT( GetStatusUpdate( QString ) ) );
|
||||||
|
connect( &nThread, SIGNAL( SendExtractDone() ), this, SLOT( ThreadIsDone() ) );
|
||||||
|
connect( &nThread, SIGNAL( SendProgress( int ) ), ui->progressBar, SLOT( setValue( int ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
NandWindow::~NandWindow()
|
NandWindow::~NandWindow()
|
||||||
@ -28,6 +58,13 @@ NandWindow::~NandWindow()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NandWindow::ThreadIsDone()
|
||||||
|
{
|
||||||
|
qDebug() << "NandWindow::ThreadIsDone";
|
||||||
|
ui->progressBar->setVisible( false );
|
||||||
|
ui->statusBar->showMessage( "Done extracting", 5000 );
|
||||||
|
}
|
||||||
|
|
||||||
void NandWindow::changeEvent(QEvent *e)
|
void NandWindow::changeEvent(QEvent *e)
|
||||||
{
|
{
|
||||||
QMainWindow::changeEvent(e);
|
QMainWindow::changeEvent(e);
|
||||||
@ -47,17 +84,10 @@ void NandWindow::GetStatusUpdate( QString s )
|
|||||||
|
|
||||||
void NandWindow::GetError( QString str )
|
void NandWindow::GetError( QString str )
|
||||||
{
|
{
|
||||||
|
QMessageBox::warning( this, tr( "Error" ), str, QMessageBox::Ok );
|
||||||
qWarning() << str;
|
qWarning() << str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NandWindow::ExtractShit()
|
|
||||||
{
|
|
||||||
ui->statusBar->showMessage( "Trying to extract..." );
|
|
||||||
nandBin.ExtractToDir( exItem, exPath );//who cares if it returns false? not me. thats what the qDebug() info is for
|
|
||||||
ui->statusBar->showMessage( "Done", 5000 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//nand window right-clicked
|
//nand window right-clicked
|
||||||
void NandWindow::on_treeWidget_customContextMenuRequested( QPoint pos )
|
void NandWindow::on_treeWidget_customContextMenuRequested( QPoint pos )
|
||||||
{
|
{
|
||||||
@ -84,11 +114,8 @@ void NandWindow::on_treeWidget_customContextMenuRequested( QPoint pos )
|
|||||||
if( path.isEmpty() )
|
if( path.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
exPath = path;
|
ui->progressBar->setVisible( true );
|
||||||
exItem = item;
|
nThread.Extract( item, path );
|
||||||
|
|
||||||
//ghetto, but gives the dialog box time to dissappear before the gui freezes as it extracts the nand
|
|
||||||
QTimer::singleShot( 250, this, SLOT( ExtractShit() ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,7 +127,8 @@ void NandWindow::on_actionOpen_Nand_triggered()
|
|||||||
if( path.isEmpty() )
|
if( path.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !nandBin.SetPath( path ) )
|
blocks.clear();
|
||||||
|
if( !nThread.SetPath( path ) )
|
||||||
{
|
{
|
||||||
qDebug() << " error in nandBin.SetPath";
|
qDebug() << " error in nandBin.SetPath";
|
||||||
ui->statusBar->showMessage( "Error setting path to " + path );
|
ui->statusBar->showMessage( "Error setting path to " + path );
|
||||||
@ -112,7 +140,8 @@ void NandWindow::on_actionOpen_Nand_triggered()
|
|||||||
groupIcon.addPixmap( style()->standardPixmap( QStyle::SP_DirClosedIcon ), QIcon::Normal, QIcon::Off );
|
groupIcon.addPixmap( style()->standardPixmap( QStyle::SP_DirClosedIcon ), QIcon::Normal, QIcon::Off );
|
||||||
groupIcon.addPixmap( style()->standardPixmap( QStyle::SP_DirOpenIcon ), QIcon::Normal, QIcon::On );
|
groupIcon.addPixmap( style()->standardPixmap( QStyle::SP_DirOpenIcon ), QIcon::Normal, QIcon::On );
|
||||||
keyIcon.addPixmap( style()->standardPixmap( QStyle::SP_FileIcon ) );
|
keyIcon.addPixmap( style()->standardPixmap( QStyle::SP_FileIcon ) );
|
||||||
if( !nandBin.InitNand( groupIcon, keyIcon ) )
|
|
||||||
|
if( !nThread.InitNand( groupIcon, keyIcon ) )
|
||||||
{
|
{
|
||||||
qDebug() << " error in nandBin.InitNand()";
|
qDebug() << " error in nandBin.InitNand()";
|
||||||
ui->statusBar->showMessage( "Error reading " + path );
|
ui->statusBar->showMessage( "Error reading " + path );
|
||||||
@ -120,9 +149,12 @@ void NandWindow::on_actionOpen_Nand_triggered()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ui->treeWidget->clear();
|
ui->treeWidget->clear();
|
||||||
|
GetBlocksfromNand();
|
||||||
|
DrawBlockMap();
|
||||||
|
|
||||||
//get an item holding a tree with all the items of the nand
|
//get an item holding a tree with all the items of the nand
|
||||||
QTreeWidgetItem* tree = nandBin.GetTree();
|
//QTreeWidgetItem* tree = nandBin.GetTree();
|
||||||
|
QTreeWidgetItem* tree = nThread.GetTree();
|
||||||
|
|
||||||
//take the actual contents of the nand from the made up root and add them to the gui widget
|
//take the actual contents of the nand from the made up root and add them to the gui widget
|
||||||
ui->treeWidget->addTopLevelItems( tree->takeChildren() );
|
ui->treeWidget->addTopLevelItems( tree->takeChildren() );
|
||||||
@ -135,6 +167,160 @@ void NandWindow::on_actionOpen_Nand_triggered()
|
|||||||
ui->treeWidget->topLevelItem( 0 )->setExpanded( true );
|
ui->treeWidget->topLevelItem( 0 )->setExpanded( true );
|
||||||
|
|
||||||
ui->statusBar->showMessage( "Loaded " + path, 5000 );
|
ui->statusBar->showMessage( "Loaded " + path, 5000 );
|
||||||
|
}
|
||||||
//nandBin.GetData( "/title/00000001/00000002/data/setting.txt" );//testing 1,2,1,2
|
|
||||||
|
void NandWindow::GetBlocksfromNand()
|
||||||
|
{
|
||||||
|
blocks.clear();
|
||||||
|
freeSpace = 0;
|
||||||
|
|
||||||
|
QList<quint16> clusters = nThread.GetFats();
|
||||||
|
if( !clusters.size() == 0x8000 )
|
||||||
|
{
|
||||||
|
QMessageBox::warning( this, tr( "Error" ), tr( "Expected 0x8000 clusters from the nand, but got %1 instead!" ).arg( clusters.size(), 0, 16 ), QMessageBox::Ok );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//QString str;
|
||||||
|
for( quint16 i = 0; i < 0x8000; i += 8 )//first cluster of each block.
|
||||||
|
{
|
||||||
|
quint16 thisBlock = clusters.at( i );
|
||||||
|
|
||||||
|
//str += QString( "%1 " ).arg( thisBlock, 4, 16 );
|
||||||
|
if( thisBlock == 0xFFFC
|
||||||
|
|| thisBlock == 0xFFFD )
|
||||||
|
{
|
||||||
|
//qDebug() << "adding" << hex << thisBlock;
|
||||||
|
blocks << thisBlock;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool used = 0;
|
||||||
|
for( quint16 j = i; j < i + 8; j++ )//each individual cluster
|
||||||
|
{
|
||||||
|
thisBlock = clusters.at( i );
|
||||||
|
if( thisBlock == 0xFFFE )
|
||||||
|
freeSpace += 0x800;
|
||||||
|
|
||||||
|
else used = true;
|
||||||
|
}
|
||||||
|
blocks << ( used ? 1 : 0xfffe ); // just put 1 for used blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<quint16> NandWindow::ToBlocks( QList<quint16> clusters )
|
||||||
|
{
|
||||||
|
//qDebug() << "NandWindow::ToBlocks" << clusters;
|
||||||
|
QList<quint16> ret;
|
||||||
|
quint16 size = clusters.size();
|
||||||
|
for( quint16 i = 0; i < size; i++ )
|
||||||
|
{
|
||||||
|
quint16 block = ( clusters.at( i ) / 8 );
|
||||||
|
if( !ret.contains( block ) )
|
||||||
|
ret << block;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//expects blocks, not clusters!!
|
||||||
|
void NandWindow::DrawBlockMap( QList<quint16> newFile )
|
||||||
|
{
|
||||||
|
if( blocks.size() != 0x1000 )
|
||||||
|
{
|
||||||
|
qWarning() << "NandWindow::DrawBlockMap -> current blocks are fucked up, son" << hex << blocks.size();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QPixmap blue( ":/blue.png" );
|
||||||
|
QPixmap green( ":/green.png" );
|
||||||
|
QPixmap pink( ":/pink.png" );
|
||||||
|
QPixmap grey( ":/grey.png" );
|
||||||
|
QPixmap black( ":/black.png" );
|
||||||
|
|
||||||
|
for( quint16 i = 0; i < 0x1000; i++ )
|
||||||
|
{
|
||||||
|
quint16 thisBlock;
|
||||||
|
if( !newFile.contains( i ) )
|
||||||
|
{
|
||||||
|
thisBlock = blocks.at( i );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thisBlock = 2;
|
||||||
|
}
|
||||||
|
switch( thisBlock )
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 1://used, but not in this file
|
||||||
|
pmi[ i ]->setPixmap( green );
|
||||||
|
break;
|
||||||
|
case 2://used in this file
|
||||||
|
pmi[ i ]->setPixmap( pink );
|
||||||
|
break;
|
||||||
|
case 0xFFFE://free block
|
||||||
|
pmi[ i ]->setPixmap( grey );
|
||||||
|
break;
|
||||||
|
case 0xFFFC://reserved
|
||||||
|
pmi[ i ]->setPixmap( blue );
|
||||||
|
break;
|
||||||
|
case 0xFFFD: // bad block
|
||||||
|
pmi[ i ]->setPixmap( black );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//show nand usage
|
||||||
|
void NandWindow::on_actionShow_Usage_triggered()
|
||||||
|
{
|
||||||
|
//128x32
|
||||||
|
/*QList<quint16> clusters = nThread.GetFats();//each of these is 0x4000 bytes ( neglecting the ecc )
|
||||||
|
quint16 badBlocks = 0;
|
||||||
|
quint16 reserved = 0;
|
||||||
|
quint16 freeBlocks = 0;
|
||||||
|
QList<quint16>badOnes;
|
||||||
|
for( quint16 i = 0; i < 0x8000; i++ )
|
||||||
|
{
|
||||||
|
quint16 fat = GetFAT( i );
|
||||||
|
if( 0xfffc == fat )
|
||||||
|
reserved++;
|
||||||
|
else if( 0xfffd == fat )
|
||||||
|
{
|
||||||
|
badBlocks++;
|
||||||
|
if( i % 8 == 0 )
|
||||||
|
{
|
||||||
|
badOnes << ( i / 8 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( 0xfffe == fat )
|
||||||
|
freeBlocks++;
|
||||||
|
}
|
||||||
|
if( badBlocks )
|
||||||
|
badBlocks /= 8;
|
||||||
|
|
||||||
|
if( reserved )
|
||||||
|
reserved /= 8;
|
||||||
|
|
||||||
|
if( freeBlocks )
|
||||||
|
freeBlocks /= 8;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//some item in the nand tree was clicked
|
||||||
|
void NandWindow::on_treeWidget_currentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous )
|
||||||
|
{
|
||||||
|
Q_UNUSED( previous );
|
||||||
|
|
||||||
|
if( !current || current->text( 6 ) == "00" )
|
||||||
|
return;
|
||||||
|
bool ok = false;
|
||||||
|
quint16 entry = current->text( 1 ).toInt( &ok );
|
||||||
|
if( !ok )
|
||||||
|
{
|
||||||
|
qDebug() << "NandWindow::on_treeWidget_currentItemChanged ->" << current->text( 1 ) << "isnt a decimal number";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<quint16> blocks = ToBlocks( nThread.GetFatsForFile( entry ) );
|
||||||
|
//qDebug() << "blocks for" << current->text( 0 ) << blocks;
|
||||||
|
DrawBlockMap( blocks );
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#ifndef NANDWINDOW_H
|
#ifndef NANDWINDOW_H
|
||||||
#define NANDWINDOW_H
|
#define NANDWINDOW_H
|
||||||
|
|
||||||
#include "includes.h"
|
#include "../WiiQt/includes.h"
|
||||||
#include "../WiiQt/nandbin.h"
|
//#include "../WiiQt/nandbin.h"
|
||||||
|
|
||||||
|
#include "nandthread.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class NandWindow;
|
class NandWindow;
|
||||||
@ -20,21 +22,32 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Ui::NandWindow *ui;
|
Ui::NandWindow *ui;
|
||||||
|
|
||||||
NandBin nandBin;
|
NandThread nThread;
|
||||||
|
|
||||||
|
//changes the blocks in the blockmap with different colors
|
||||||
|
void DrawBlockMap( QList<quint16> newFile = QList<quint16>() );
|
||||||
|
QGraphicsScene gv;//scene to hold the blockmap images
|
||||||
|
QGraphicsPixmapItem *pmi[ 0x1000 ];//pointers to all the blocks in the display
|
||||||
|
//quint16 ClusterToBlock( quint16 cluster );
|
||||||
|
|
||||||
|
QList<quint16> blocks;
|
||||||
|
quint32 freeSpace;
|
||||||
|
void GetBlocksfromNand();
|
||||||
|
|
||||||
|
QList<quint16> ToBlocks( QList<quint16> clusters );
|
||||||
|
|
||||||
|
|
||||||
//just put these here and create a slot to make the GUI not
|
|
||||||
//look so ugly when it hangs while stuff is extracting
|
|
||||||
QString exPath;
|
|
||||||
QTreeWidgetItem* exItem;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void GetError( QString );
|
void GetError( QString );
|
||||||
void GetStatusUpdate( QString );
|
void GetStatusUpdate( QString );
|
||||||
|
void ThreadIsDone();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void on_treeWidget_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
|
||||||
|
void on_actionShow_Usage_triggered();
|
||||||
void on_actionOpen_Nand_triggered();
|
void on_actionOpen_Nand_triggered();
|
||||||
void on_treeWidget_customContextMenuRequested(QPoint pos);
|
void on_treeWidget_customContextMenuRequested(QPoint pos);
|
||||||
void ExtractShit();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NANDWINDOW_H
|
#endif // NANDWINDOW_H
|
||||||
|
@ -15,6 +15,12 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="margin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QTreeWidget" name="treeWidget">
|
<widget class="QTreeWidget" name="treeWidget">
|
||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
@ -62,6 +68,35 @@
|
|||||||
</column>
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QGraphicsView" name="graphicsView_blocks">
|
||||||
|
<property name="interactive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="renderHints">
|
||||||
|
<set>QPainter::Antialiasing|QPainter::HighQualityAntialiasing|QPainter::SmoothPixmapTransform|QPainter::TextAntialiasing</set>
|
||||||
|
</property>
|
||||||
|
<property name="cacheMode">
|
||||||
|
<set>QGraphicsView::CacheBackground</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenuBar" name="menuBar">
|
<widget class="QMenuBar" name="menuBar">
|
||||||
@ -79,7 +114,14 @@
|
|||||||
</property>
|
</property>
|
||||||
<addaction name="actionOpen_Nand"/>
|
<addaction name="actionOpen_Nand"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuInfo">
|
||||||
|
<property name="title">
|
||||||
|
<string>Info</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionShow_Usage"/>
|
||||||
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
|
<addaction name="menuInfo"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QToolBar" name="mainToolBar">
|
<widget class="QToolBar" name="mainToolBar">
|
||||||
<attribute name="toolBarArea">
|
<attribute name="toolBarArea">
|
||||||
@ -98,6 +140,14 @@
|
|||||||
<string>Ctrl+O</string>
|
<string>Ctrl+O</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionShow_Usage">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show Usage...</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+U</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
BIN
nandExtract/pink.png
Executable file
BIN
nandExtract/pink.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
9
nandExtract/rc.qrc
Normal file
9
nandExtract/rc.qrc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>blue.png</file>
|
||||||
|
<file>green.png</file>
|
||||||
|
<file>grey.png</file>
|
||||||
|
<file>pink.png</file>
|
||||||
|
<file>black.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
Loading…
Reference in New Issue
Block a user