aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/qt_sdl
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/qt_sdl')
-rw-r--r--src/frontend/qt_sdl/ArchiveUtil.cpp47
-rw-r--r--src/frontend/qt_sdl/ArchiveUtil.h3
-rw-r--r--src/frontend/qt_sdl/CMakeLists.txt1
-rw-r--r--src/frontend/qt_sdl/main.cpp152
-rw-r--r--src/frontend/qt_sdl/main.h3
5 files changed, 164 insertions, 42 deletions
diff --git a/src/frontend/qt_sdl/ArchiveUtil.cpp b/src/frontend/qt_sdl/ArchiveUtil.cpp
index ba6e4b6..c1f2fc1 100644
--- a/src/frontend/qt_sdl/ArchiveUtil.cpp
+++ b/src/frontend/qt_sdl/ArchiveUtil.cpp
@@ -18,11 +18,6 @@
#include "ArchiveUtil.h"
-#ifdef _WIN32
- #include <direct.h>
- #define mkdir(dir, mode) _mkdir(dir)
-#endif
-
namespace Archive
{
@@ -58,7 +53,7 @@ QVector<QString> ListArchive(const char* path)
return fileList;
}
-QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile)
+QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile, QByteArray *romBuffer)
{
struct archive *a = archive_read_new();
struct archive_entry *entry;
@@ -72,38 +67,46 @@ QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile
{
return QVector<QString> {"Err"};
}
- while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
- if (wantedFile == nullptr)
- {
- break;
- }
+
+ while (archive_read_next_header(a, &entry) == ARCHIVE_OK)
+ {
if (strcmp(wantedFile, archive_entry_pathname(entry)) == 0)
{
break;
}
}
+
size_t bytesToWrite = archive_entry_size(entry);
- auto archiveBuffer = std::make_unique<u8[]>(bytesToWrite);
- ssize_t bytesRead = archive_read_data(a, archiveBuffer.get(), bytesToWrite);
+ romBuffer->fill(0, bytesToWrite);
+ ssize_t bytesRead = archive_read_data(a, romBuffer->data(), bytesToWrite);
+
if (bytesRead < 0)
{
printf(archive_error_string(a));
- archiveBuffer.reset(nullptr);
return QVector<QString> {"Err", archive_error_string(a)};
}
- QString nameToWrite = QFileInfo(path).absolutePath() + "/" + QFileInfo(path).baseName() + "/" + archive_entry_pathname(entry);
- mkdir(QFileInfo(path).baseName().toUtf8().constData(), 600); // Create directory otherwise fopen will not open the file
- FILE* fileToWrite = fopen(nameToWrite.toUtf8().constData(), "wb");
- fwrite((char*)archiveBuffer.get(), bytesToWrite, 1, fileToWrite);
- fclose(fileToWrite);
-
- archiveBuffer.reset(nullptr);
archive_read_close(a);
archive_read_free(a);
- return QVector<QString> {nameToWrite};
+ return QVector<QString> {wantedFile};
}
+u32 ExtractFileFromArchive(const char* path, const char* wantedFile, u8 **romdata)
+{
+ QByteArray romBuffer;
+ QVector<QString> extractResult = ExtractFileFromArchive(path, wantedFile, &romBuffer);
+
+ if(extractResult[0] == "Err")
+ {
+ return 0;
+ }
+
+ u32 len = romBuffer.size();
+ *romdata = new u8[romBuffer.size()];
+ memcpy(*romdata, romBuffer.data(), len);
+
+ return len;
+}
}
diff --git a/src/frontend/qt_sdl/ArchiveUtil.h b/src/frontend/qt_sdl/ArchiveUtil.h
index a6f404a..3095f07 100644
--- a/src/frontend/qt_sdl/ArchiveUtil.h
+++ b/src/frontend/qt_sdl/ArchiveUtil.h
@@ -18,7 +18,8 @@ namespace Archive
{
QVector<QString> ListArchive(const char* path);
-QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile);
+QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile, QByteArray *romBuffer);
+u32 ExtractFileFromArchive(const char* path, const char* wantedFile, u8 **romdata);
}
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index 237ccca..612c3fd 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -63,6 +63,7 @@ if (APPLE)
list(APPEND CMAKE_PREFIX_PATH "${LIBARCHIVE_DIR}")
endif()
pkg_check_modules(LIBARCHIVE REQUIRED libarchive)
+add_compile_definitions(ARCHIVE_SUPPORT_ENABLED)
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release))
add_executable(melonDS WIN32 ${SOURCES_QT_SDL})
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index f64494d..c5ce692 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -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()
diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h
index ba67401..9ab4c2a 100644
--- a/src/frontend/qt_sdl/main.h
+++ b/src/frontend/qt_sdl/main.h
@@ -255,6 +255,9 @@ private:
QMenu *recentMenu;
void updateRecentFilesMenu();
void loadROM(QString filename);
+ void loadROM(QByteArray *romData, QString archiveFileName, QString romFileName);
+
+ QString pickAndExtractFileFromArchive(QString archiveFileName, QByteArray *romBuffer);
void createScreenPanel();