Polish up archive support (#930)

* Fix directory path when extracting from archive

* Don't create new dir in execution dir of melonds
* Create it beside the archive instead

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* ArchiveUtil : Use QT functions for I/O

* Make it more platform independent, cleaner

* Fixes permission related crash on linux

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* NDSCart : Abstract out common code in LoadROM()

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Extract nds roms to memory

* Some stuff is still broken in the frontend

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* GBACart : Abstract out common code in LoadROM()

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Extract gba roms to memory

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Integrate archive support with recent files

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* onClickRecentFile : Pause emu thread conditionally

* Don't pause at start of the function
* If user opens an archive and hits cancel, it won't pause

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Handle Resets when loading from archives

* Ask user to pick the rom(s) again (i.e. GBA & NDS)
when there are multiple files in the archive(s)

* Directly load if only 1 file

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Archive support for drag-n-drop

* Also recent files support for drag-n-drop

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* main : Allocate rombuffer objects on stack

* Less messy, decreases chances of memory leaks

* Underlying implementation of qbytearray uses heap (hopefully?)

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* GetSavestateName : Archive support

* Construct ssname from srampath (since rompath has archive name)

NOTE: In general, archive name != rom file name !!!!!!!!!!

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Add srl and dsi as "direct-load" formats

* Direct-load = anything not in an archive

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Don't use static functions

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Remove QT stuff from Util_ROM

* Also, during reset, directly load file from archive (no rom picker)

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Remove QT includes from FrontendUtil.h

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Util_ROM/LoadROM() : Use SetupDSiNAND()

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Util_ROM/Reset() : Use strrchr()

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Util_ROM : Put Archive stuff behind ifdefs

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* main: Set parent widget for archive dialog boxes

Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>

* Revert "Util_ROM/Reset() : Use strrchr()"

This reverts commit c8af6f066f.
This commit is contained in:
Madhav Kanbur
2021-01-22 15:52:32 +05:30
committed by GitHub
parent d42ca1ec4b
commit 1e4c0c9d72
13 changed files with 449 additions and 108 deletions

View File

@ -1453,10 +1453,15 @@ void MainWindow::dragEnterEvent(QDragEnterEvent* event)
if (urls.count() > 1) return; // not handling more than one file at once
QString filename = urls.at(0).toLocalFile();
QString ext = filename.right(3);
if (ext == "nds" || ext == "srl" || ext == "dsi" || ext == "gba")
event->acceptProposedAction();
QStringList acceptedExts{".nds", ".srl", ".dsi", ".gba", ".rar",
".zip", ".7z", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2"};
for(const QString &ext : acceptedExts)
{
if(filename.endsWith(ext))
event->acceptProposedAction();
}
}
void MainWindow::dropEvent(QDropEvent* event)
@ -1471,6 +1476,10 @@ void MainWindow::dropEvent(QDropEvent* event)
QString filename = urls.at(0).toLocalFile();
QString ext = filename.right(3);
recentFileList.removeAll(filename);
recentFileList.prepend(filename);
updateRecentFilesMenu();
char _filename[1024];
strncpy(_filename, filename.toStdString().c_str(), 1023); _filename[1023] = '\0';
@ -1480,11 +1489,32 @@ void MainWindow::dropEvent(QDropEvent* event)
slot = 1;
res = Frontend::LoadROM(_filename, Frontend::ROMSlot_GBA);
}
else
else if(ext == "nds" || ext == "srl" || ext == "dsi")
{
slot = 0;
res = Frontend::LoadROM(_filename, Frontend::ROMSlot_NDS);
}
else
{
QByteArray romBuffer;
QString romFileName = pickAndExtractFileFromArchive(_filename, &romBuffer);
if(romFileName.isEmpty())
{
res = Frontend::Load_ROMLoadError;
}
else
{
slot = (romFileName.endsWith(".gba") ? 1 : 0);
QString sramFileName = QFileInfo(_filename).absolutePath() + QDir::separator() + QFileInfo(romFileName).completeBaseName() + ".sav";
if(slot == 0)
strncpy(Frontend::NDSROMExtension, QFileInfo(romFileName).suffix().toStdString().c_str(), 4);
res = Frontend::LoadROM((const u8*)romBuffer.constData(), romBuffer.size(),
_filename, romFileName.toStdString().c_str(), sramFileName.toStdString().c_str(),
slot);
}
}
if (res != Frontend::Load_OK)
{
@ -1548,6 +1578,54 @@ QString MainWindow::loadErrorStr(int error)
}
}
void MainWindow::loadROM(QByteArray *romData, QString archiveFileName, QString romFileName)
{
recentFileList.removeAll(archiveFileName);
recentFileList.prepend(archiveFileName);
updateRecentFilesMenu();
// Strip entire archive name and get folder path
strncpy(Config::LastROMFolder, QFileInfo(archiveFileName).absolutePath().toStdString().c_str(), 1024);
QString sramFileName = QFileInfo(archiveFileName).absolutePath() + QDir::separator() + QFileInfo(romFileName).completeBaseName() + ".sav";
int slot; int res;
if (romFileName.endsWith("gba"))
{
slot = 1;
res = Frontend::LoadROM((const u8*)romData->constData(), romData->size(),
archiveFileName.toStdString().c_str(),
romFileName.toStdString().c_str(), sramFileName.toStdString().c_str(),
Frontend::ROMSlot_GBA);
}
else
{
strncpy(Frontend::NDSROMExtension, QFileInfo(romFileName).suffix().toStdString().c_str(), 4);
slot = 0;
res = Frontend::LoadROM((const u8*)romData->constData(), romData->size(),
archiveFileName.toStdString().c_str(),
romFileName.toStdString().c_str(), sramFileName.toStdString().c_str(),
Frontend::ROMSlot_NDS);
}
if (res != Frontend::Load_OK)
{
QMessageBox::critical(this,
"melonDS",
loadErrorStr(res));
emuThread->emuUnpause();
}
else if (slot == 1)
{
// checkme
emuThread->emuUnpause();
}
else
{
emuThread->emuRun();
}
}
void MainWindow::loadROM(QString filename)
{
recentFileList.removeAll(filename);
@ -1620,43 +1698,62 @@ void MainWindow::onOpenFileArchive()
{
emuThread->emuPause();
QString filename = QFileDialog::getOpenFileName(this,
QString archiveFileName = QFileDialog::getOpenFileName(this,
"Open ROM Archive",
Config::LastROMFolder,
"Archived ROMs (*.zip *.7z *.rar *.tar *.tar.gz *.tar.xz *.tar.bz2);;Any file (*.*)");
if (filename.isEmpty())
if (archiveFileName.isEmpty())
{
emuThread->emuUnpause();
return;
}
QByteArray romBuffer;
QString romFileName = pickAndExtractFileFromArchive(archiveFileName, &romBuffer);
if(!romFileName.isEmpty())
{
loadROM(&romBuffer, archiveFileName, romFileName);
}
}
QString MainWindow::pickAndExtractFileFromArchive(QString archiveFileName, QByteArray *romBuffer)
{
printf("Finding list of ROMs...\n");
QVector<QString> archiveROMList = Archive::ListArchive(filename.toUtf8().constData());
QVector<QString> archiveROMList = Archive::ListArchive(archiveFileName.toUtf8().constData());
QString romFileName; // file name inside archive
if (archiveROMList.size() > 2)
{
archiveROMList.removeFirst();
bool ok;
QString toLoad = QInputDialog::getItem(this, "melonDS",
"The archive was found to have multiple files. Select which ROM you want to load.", archiveROMList.toList(), 0, false);
"The archive was found to have multiple files. Select which ROM you want to load.", archiveROMList.toList(), 0, false, &ok);
if(!ok) // User clicked on cancel
return QString();
printf("Extracting '%s'\n", toLoad.toUtf8().constData());
QVector<QString> extractResult = Archive::ExtractFileFromArchive(filename.toUtf8().constData(), toLoad.toUtf8().constData());
QVector<QString> extractResult = Archive::ExtractFileFromArchive(archiveFileName.toUtf8().constData(), toLoad.toUtf8().constData(), romBuffer);
if (extractResult[0] != QString("Err"))
{
filename = extractResult[0];
romFileName = extractResult[0];
}
else
else
{
QMessageBox::critical(this, "melonDS", QString("There was an error while trying to extract the ROM from the archive: ") + extractResult[1]);
}
}
}
else if (archiveROMList.size() == 2)
{
{
printf("Extracting the only ROM in archive\n");
QVector<QString> extractResult = Archive::ExtractFileFromArchive(filename.toUtf8().constData(), nullptr);
QVector<QString> extractResult = Archive::ExtractFileFromArchive(archiveFileName.toUtf8().constData(), archiveROMList.at(1).toUtf8().constData(), romBuffer);
if (extractResult[0] != QString("Err"))
{
filename = extractResult[0];
romFileName = extractResult[0];
}
else
else
{
QMessageBox::critical(this, "melonDS", QString("There was an error while trying to extract the ROM from the archive: ") + extractResult[1]);
}
@ -1670,7 +1767,7 @@ void MainWindow::onOpenFileArchive()
QMessageBox::critical(this, "melonDS", "The archive could not be read. It may be corrupt or you don't have the permissions.");
}
loadROM(filename);
return romFileName;
}
void MainWindow::onClearRecentFiles()
@ -1705,9 +1802,26 @@ void MainWindow::updateRecentFilesMenu()
void MainWindow::onClickRecentFile()
{
emuThread->emuPause();
QAction *act = (QAction *)sender();
loadROM(act->data().toString());
QString fileName = act->data().toString();
if(fileName.endsWith(".gba") || fileName.endsWith(".nds") || fileName.endsWith(".srl") || fileName.endsWith(".dsi"))
{
emuThread->emuPause();
loadROM(fileName);
}
else
{
// Archives
QString archiveFileName = fileName;
QByteArray romBuffer;
QString romFileName = MainWindow::pickAndExtractFileFromArchive(archiveFileName, &romBuffer);
if(!romFileName.isEmpty())
{
emuThread->emuPause();
loadROM(&romBuffer, archiveFileName, romFileName);
}
}
}
void MainWindow::onBootFirmware()