mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-26 07:39:56 -06:00
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:
@ -63,6 +63,8 @@ extern char ROMPath [ROMSlot_MAX][1024];
|
||||
extern char SRAMPath[ROMSlot_MAX][1024];
|
||||
extern bool SavestateLoaded;
|
||||
|
||||
// Stores type of nds rom i.e. nds/srl/dsi. Should be updated everytime an NDS rom is loaded from an archive
|
||||
extern char NDSROMExtension[4];
|
||||
|
||||
// initialize the ROM handling utility
|
||||
void Init_ROM();
|
||||
@ -76,6 +78,7 @@ int LoadBIOS();
|
||||
// load a ROM file to the specified cart slot
|
||||
// note: loading a ROM to the NDS slot resets emulation
|
||||
int LoadROM(const char* file, int slot);
|
||||
int LoadROM(const u8 *romdata, u32 romlength, const char *archivefilename, const char *romfilename, const char *sramfilename, int slot);
|
||||
|
||||
// unload the ROM loaded in the specified cart slot
|
||||
// simulating ejection of the cartridge
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ARCHIVE_SUPPORT_ENABLED
|
||||
#include "ArchiveUtil.h"
|
||||
#endif
|
||||
#include "FrontendUtil.h"
|
||||
#include "Config.h"
|
||||
#include "SharedConfig.h"
|
||||
@ -38,6 +41,8 @@ char ROMPath [ROMSlot_MAX][1024];
|
||||
char SRAMPath [ROMSlot_MAX][1024];
|
||||
char PrevSRAMPath[ROMSlot_MAX][1024]; // for savestate 'undo load'
|
||||
|
||||
char NDSROMExtension[4];
|
||||
|
||||
bool SavestateLoaded;
|
||||
|
||||
ARCodeFile* CheatFile;
|
||||
@ -295,6 +300,84 @@ int LoadBIOS()
|
||||
return Load_OK;
|
||||
}
|
||||
|
||||
int LoadROM(const u8 *romdata, u32 romlength, const char *archivefilename, const char *romfilename, const char *sramfilename, int slot)
|
||||
{
|
||||
int res;
|
||||
bool directboot = Config::DirectBoot != 0;
|
||||
|
||||
if (Config::ConsoleType == 1 && slot == 1)
|
||||
{
|
||||
// cannot load a GBA ROM into a DSi
|
||||
return Load_ROMLoadError;
|
||||
}
|
||||
|
||||
res = VerifyDSBIOS();
|
||||
if (res != Load_OK) return res;
|
||||
|
||||
if (Config::ConsoleType == 1)
|
||||
{
|
||||
res = VerifyDSiBIOS();
|
||||
if (res != Load_OK) return res;
|
||||
|
||||
res = VerifyDSiFirmware();
|
||||
if (res != Load_OK) return res;
|
||||
|
||||
res = SetupDSiNAND();
|
||||
if (res != Load_OK) return res;
|
||||
|
||||
GBACart::Eject();
|
||||
ROMPath[ROMSlot_GBA][0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
res = VerifyDSFirmware();
|
||||
if (res != Load_OK)
|
||||
{
|
||||
if (res == Load_FirmwareNotBootable)
|
||||
directboot = true;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
char oldpath[1024];
|
||||
char oldsram[1024];
|
||||
strncpy(oldpath, ROMPath[slot], 1024);
|
||||
strncpy(oldsram, SRAMPath[slot], 1024);
|
||||
|
||||
strncpy(SRAMPath[slot], sramfilename, 1024);
|
||||
strncpy(ROMPath[slot], archivefilename, 1024);
|
||||
|
||||
NDS::SetConsoleType(Config::ConsoleType);
|
||||
|
||||
if (slot == ROMSlot_NDS && NDS::LoadROM(romdata, romlength, SRAMPath[slot], directboot))
|
||||
{
|
||||
SavestateLoaded = false;
|
||||
|
||||
LoadCheats();
|
||||
|
||||
// Reload the inserted GBA cartridge (if any)
|
||||
// TODO: report failure there??
|
||||
//if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]);
|
||||
|
||||
strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety
|
||||
return Load_OK;
|
||||
}
|
||||
else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(romdata, romlength, romfilename, SRAMPath[slot]))
|
||||
{
|
||||
SavestateLoaded = false; // checkme??
|
||||
|
||||
strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety
|
||||
return Load_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(ROMPath[slot], oldpath, 1024);
|
||||
strncpy(SRAMPath[slot], oldsram, 1024);
|
||||
return Load_ROMLoadError;
|
||||
}
|
||||
}
|
||||
|
||||
int LoadROM(const char* file, int slot)
|
||||
{
|
||||
DSi::CloseDSiNAND();
|
||||
@ -440,16 +523,76 @@ int Reset()
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupSRAMPath(0);
|
||||
if (!NDS::LoadROM(ROMPath[ROMSlot_NDS], SRAMPath[ROMSlot_NDS], directboot))
|
||||
return Load_ROMLoadError;
|
||||
char ext[5] = {0}; int _len = strlen(ROMPath[ROMSlot_NDS]);
|
||||
strncpy(ext, ROMPath[ROMSlot_NDS] + _len - 4, 4);
|
||||
|
||||
if(!strncmp(ext, ".nds", 4) || !strncmp(ext, ".srl", 4) || !strncmp(ext, ".dsi", 4))
|
||||
{
|
||||
SetupSRAMPath(0);
|
||||
if (!NDS::LoadROM(ROMPath[ROMSlot_NDS], SRAMPath[ROMSlot_NDS], directboot))
|
||||
return Load_ROMLoadError;
|
||||
}
|
||||
#ifdef ARCHIVE_SUPPORT_ENABLED
|
||||
else
|
||||
{
|
||||
u8 *romdata = nullptr; u32 romlen;
|
||||
char romfilename[1024] = {0}, sramfilename[1024];
|
||||
strncpy(sramfilename, SRAMPath[ROMSlot_NDS], 1024); // Use existing SRAMPath
|
||||
|
||||
int pos = strlen(sramfilename) - 1;
|
||||
while(pos > 0 && sramfilename[pos] != '/' && sramfilename[pos] != '\\')
|
||||
--pos;
|
||||
|
||||
strncpy(romfilename, &sramfilename[pos + 1], 1024);
|
||||
strncpy(&romfilename[strlen(romfilename) - 3], NDSROMExtension, 3); // extension could be nds, srl or dsi
|
||||
printf("RESET loading from archive : %s\n", romfilename);
|
||||
romlen = Archive::ExtractFileFromArchive(ROMPath[ROMSlot_NDS], romfilename, &romdata);
|
||||
if(!romdata)
|
||||
return Load_ROMLoadError;
|
||||
|
||||
bool ok = NDS::LoadROM(romdata, romlen, sramfilename, directboot);
|
||||
delete romdata;
|
||||
if(!ok)
|
||||
return Load_ROMLoadError;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ROMPath[ROMSlot_GBA][0] != '\0')
|
||||
{
|
||||
SetupSRAMPath(1);
|
||||
if (!NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]))
|
||||
return Load_ROMLoadError;
|
||||
char ext[5] = {0}; int _len = strlen(ROMPath[ROMSlot_GBA]);
|
||||
strncpy(ext, ROMPath[ROMSlot_NDS] + _len - 4, 4);
|
||||
|
||||
if(!strncmp(ext, ".gba", 4))
|
||||
{
|
||||
SetupSRAMPath(1);
|
||||
if (!NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]))
|
||||
return Load_ROMLoadError;
|
||||
}
|
||||
#ifdef ARCHIVE_SUPPORT_ENABLED
|
||||
else
|
||||
{
|
||||
u8 *romdata = nullptr; u32 romlen;
|
||||
char romfilename[1024] = {0}, sramfilename[1024];
|
||||
strncpy(sramfilename, SRAMPath[ROMSlot_GBA], 1024); // Use existing SRAMPath
|
||||
|
||||
int pos = strlen(sramfilename) - 1;
|
||||
while(pos > 0 && sramfilename[pos] != '/' && sramfilename[pos] != '\\')
|
||||
--pos;
|
||||
|
||||
strncpy(romfilename, &sramfilename[pos + 1], 1024);
|
||||
strncpy(&romfilename[strlen(romfilename) - 3], "gba", 3);
|
||||
printf("RESET loading from archive : %s\n", romfilename);
|
||||
romlen = Archive::ExtractFileFromArchive(ROMPath[ROMSlot_GBA], romfilename, &romdata);
|
||||
if(!romdata)
|
||||
return Load_ROMLoadError;
|
||||
|
||||
bool ok = NDS::LoadGBAROM(romdata, romlen, romfilename, SRAMPath[ROMSlot_GBA]);
|
||||
delete romdata;
|
||||
if(!ok)
|
||||
return Load_ROMLoadError;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
LoadCheats();
|
||||
@ -472,15 +615,24 @@ void GetSavestateName(int slot, char* filename, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
int l = strlen(ROMPath[ROMSlot_NDS]);
|
||||
char *rompath;
|
||||
char ext[5] = {0}; int _len = strlen(ROMPath[ROMSlot_NDS]);
|
||||
strncpy(ext, ROMPath[ROMSlot_NDS] + _len - 4, 4);
|
||||
|
||||
if(!strncmp(ext, ".nds", 4) || !strncmp(ext, ".srl", 4) || !strncmp(ext, ".dsi", 4))
|
||||
rompath = ROMPath[ROMSlot_NDS];
|
||||
else
|
||||
rompath = SRAMPath[ROMSlot_NDS]; // If archive, construct ssname from sram file
|
||||
|
||||
int l = strlen(rompath);
|
||||
pos = l;
|
||||
while (ROMPath[ROMSlot_NDS][pos] != '.' && pos > 0) pos--;
|
||||
while (rompath[pos] != '.' && pos > 0) pos--;
|
||||
if (pos == 0) pos = l;
|
||||
|
||||
// avoid buffer overflow. shoddy
|
||||
if (pos > len-5) pos = len-5;
|
||||
|
||||
strncpy(&filename[0], ROMPath[ROMSlot_NDS], pos);
|
||||
strncpy(&filename[0], rompath, pos);
|
||||
}
|
||||
strcpy(&filename[pos], ".ml");
|
||||
filename[pos+3] = '0'+slot;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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})
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
||||
|
Reference in New Issue
Block a user