diff options
Diffstat (limited to 'src/frontend/qt_sdl')
-rw-r--r-- | src/frontend/qt_sdl/ArchiveUtil.cpp | 47 | ||||
-rw-r--r-- | src/frontend/qt_sdl/ArchiveUtil.h | 3 | ||||
-rw-r--r-- | src/frontend/qt_sdl/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/frontend/qt_sdl/main.cpp | 152 | ||||
-rw-r--r-- | src/frontend/qt_sdl/main.h | 3 |
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(); |