mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-26 15:50:00 -06:00
Extract nds roms to memory
* Some stuff is still broken in the frontend Signed-off-by: Madhav Kanbur <abcdjdj@gmail.com>
This commit is contained in:
14
src/NDS.cpp
14
src/NDS.cpp
@ -823,6 +823,20 @@ void SetConsoleType(int type)
|
|||||||
ConsoleType = type;
|
ConsoleType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct)
|
||||||
|
{
|
||||||
|
if (NDSCart::LoadROM(romdata, filelength, sram, direct))
|
||||||
|
{
|
||||||
|
Running = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Failed to load ROM from archive\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LoadROM(const char* path, const char* sram, bool direct)
|
bool LoadROM(const char* path, const char* sram, bool direct)
|
||||||
{
|
{
|
||||||
if (NDSCart::LoadROM(path, sram, direct))
|
if (NDSCart::LoadROM(path, sram, direct))
|
||||||
|
@ -193,6 +193,7 @@ void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq,
|
|||||||
void SetConsoleType(int type);
|
void SetConsoleType(int type);
|
||||||
|
|
||||||
bool LoadROM(const char* path, const char* sram, bool direct);
|
bool LoadROM(const char* path, const char* sram, bool direct);
|
||||||
|
bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct);
|
||||||
bool LoadGBAROM(const char* path, const char* sram);
|
bool LoadGBAROM(const char* path, const char* sram);
|
||||||
void LoadBIOS();
|
void LoadBIOS();
|
||||||
void SetupDirectBoot();
|
void SetupDirectBoot();
|
||||||
|
@ -1026,6 +1026,22 @@ bool LoadROM(const char* path, const char* sram, bool direct)
|
|||||||
return LoadROMCommon(len, sram, direct);
|
return LoadROMCommon(len, sram, direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct)
|
||||||
|
{
|
||||||
|
NDS::Reset();
|
||||||
|
|
||||||
|
u32 len = filelength;
|
||||||
|
CartROMSize = 0x200;
|
||||||
|
while (CartROMSize < len)
|
||||||
|
CartROMSize <<= 1;
|
||||||
|
|
||||||
|
CartROM = new u8[CartROMSize];
|
||||||
|
memset(CartROM, 0, CartROMSize);
|
||||||
|
memcpy(CartROM, romdata, filelength);
|
||||||
|
|
||||||
|
return LoadROMCommon(filelength, sram, direct);
|
||||||
|
}
|
||||||
|
|
||||||
void RelocateSave(const char* path, bool write)
|
void RelocateSave(const char* path, bool write)
|
||||||
{
|
{
|
||||||
// herp derp
|
// herp derp
|
||||||
|
@ -46,6 +46,7 @@ void DoSavestate(Savestate* file);
|
|||||||
|
|
||||||
void DecryptSecureArea(u8* out);
|
void DecryptSecureArea(u8* out);
|
||||||
bool LoadROM(const char* path, const char* sram, bool direct);
|
bool LoadROM(const char* path, const char* sram, bool direct);
|
||||||
|
bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct);
|
||||||
|
|
||||||
void FlushSRAMFile();
|
void FlushSRAMFile();
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#ifndef FRONTENDUTIL_H
|
#ifndef FRONTENDUTIL_H
|
||||||
#define FRONTENDUTIL_H
|
#define FRONTENDUTIL_H
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
namespace Frontend
|
namespace Frontend
|
||||||
@ -76,6 +79,7 @@ int LoadBIOS();
|
|||||||
// load a ROM file to the specified cart slot
|
// load a ROM file to the specified cart slot
|
||||||
// note: loading a ROM to the NDS slot resets emulation
|
// note: loading a ROM to the NDS slot resets emulation
|
||||||
int LoadROM(const char* file, int slot);
|
int LoadROM(const char* file, int slot);
|
||||||
|
int LoadROM(const QByteArray *romdata, QString archivefilename, QString romfilename, int slot);
|
||||||
|
|
||||||
// unload the ROM loaded in the specified cart slot
|
// unload the ROM loaded in the specified cart slot
|
||||||
// simulating ejection of the cartridge
|
// simulating ejection of the cartridge
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
#include "FrontendUtil.h"
|
#include "FrontendUtil.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "SharedConfig.h"
|
#include "SharedConfig.h"
|
||||||
@ -283,6 +286,85 @@ int LoadBIOS()
|
|||||||
return Load_OK;
|
return Load_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LoadROM(const QByteArray *romdata, QString archivefilename, QString romfilename, 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 = VerifyDSiNAND();
|
||||||
|
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);
|
||||||
|
|
||||||
|
QString sramFile = QFileInfo(archivefilename).absolutePath() + QDir::separator() + QFileInfo(romfilename).completeBaseName() + ".sav";
|
||||||
|
strncpy(SRAMPath[slot], QDir::cleanPath(sramFile).toStdString().c_str(), 1024);
|
||||||
|
strncpy(ROMPath[slot], archivefilename.toStdString().c_str(), 1024);
|
||||||
|
|
||||||
|
NDS::SetConsoleType(Config::ConsoleType);
|
||||||
|
|
||||||
|
if (slot == ROMSlot_NDS && NDS::LoadROM((const u8*)romdata->constData(), romdata->size(), 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(ROMPath[slot], 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)
|
int LoadROM(const char* file, int slot)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
@ -53,7 +53,7 @@ QVector<QString> ListArchive(const char* path)
|
|||||||
return fileList;
|
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 *a = archive_read_new();
|
||||||
struct archive_entry *entry;
|
struct archive_entry *entry;
|
||||||
@ -67,11 +67,9 @@ QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile
|
|||||||
{
|
{
|
||||||
return QVector<QString> {"Err"};
|
return QVector<QString> {"Err"};
|
||||||
}
|
}
|
||||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
|
||||||
if (wantedFile == nullptr)
|
while (archive_read_next_header(a, &entry) == ARCHIVE_OK)
|
||||||
{
|
{
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (strcmp(wantedFile, archive_entry_pathname(entry)) == 0)
|
if (strcmp(wantedFile, archive_entry_pathname(entry)) == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -79,8 +77,8 @@ QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t bytesToWrite = archive_entry_size(entry);
|
size_t bytesToWrite = archive_entry_size(entry);
|
||||||
QByteArray archiveBuffer(bytesToWrite, '\0');
|
romBuffer->fill(0, bytesToWrite);
|
||||||
ssize_t bytesRead = archive_read_data(a, archiveBuffer.data(), bytesToWrite);
|
ssize_t bytesRead = archive_read_data(a, romBuffer->data(), bytesToWrite);
|
||||||
|
|
||||||
if (bytesRead < 0)
|
if (bytesRead < 0)
|
||||||
{
|
{
|
||||||
@ -88,18 +86,9 @@ QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile
|
|||||||
return QVector<QString> {"Err", archive_error_string(a)};
|
return QVector<QString> {"Err", archive_error_string(a)};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString extractToFolder = QFileInfo(path).absolutePath() + "/" + QFileInfo(path).baseName();
|
|
||||||
QDir().mkdir(extractToFolder);
|
|
||||||
|
|
||||||
QString nameToWrite = extractToFolder + "/" + archive_entry_pathname(entry);
|
|
||||||
QFile fileToWrite(nameToWrite);
|
|
||||||
if(fileToWrite.open(QIODevice::WriteOnly))
|
|
||||||
fileToWrite.write(archiveBuffer);
|
|
||||||
|
|
||||||
fileToWrite.close();
|
|
||||||
archive_read_close(a);
|
archive_read_close(a);
|
||||||
archive_read_free(a);
|
archive_read_free(a);
|
||||||
return QVector<QString> {nameToWrite};
|
return QVector<QString> {wantedFile};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace Archive
|
|||||||
{
|
{
|
||||||
|
|
||||||
QVector<QString> ListArchive(const char* path);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1501,6 +1501,44 @@ QString MainWindow::loadErrorStr(int error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::loadROM(QByteArray *romData, QString archiveFileName, QString romFileName)
|
||||||
|
{
|
||||||
|
// Strip entire archive name and get folder path
|
||||||
|
strncpy(Config::LastROMFolder, QFileInfo(archiveFileName).absolutePath().toStdString().c_str(), 1024);
|
||||||
|
|
||||||
|
int slot; int res;
|
||||||
|
/*if (!strcasecmp(ext, "gba"))
|
||||||
|
{
|
||||||
|
slot = 1;
|
||||||
|
res = Frontend::LoadROM(file, Frontend::ROMSlot_GBA);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slot = 0;
|
||||||
|
res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// TODO: GBA support here!
|
||||||
|
slot = 0;
|
||||||
|
res = Frontend::LoadROM(romData, archiveFileName, romFileName, 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)
|
void MainWindow::loadROM(QString filename)
|
||||||
{
|
{
|
||||||
recentFileList.removeAll(filename);
|
recentFileList.removeAll(filename);
|
||||||
@ -1573,28 +1611,31 @@ void MainWindow::onOpenFileArchive()
|
|||||||
{
|
{
|
||||||
emuThread->emuPause();
|
emuThread->emuPause();
|
||||||
|
|
||||||
QString filename = QFileDialog::getOpenFileName(this,
|
QString archiveFileName = QFileDialog::getOpenFileName(this,
|
||||||
"Open ROM Archive",
|
"Open ROM Archive",
|
||||||
Config::LastROMFolder,
|
Config::LastROMFolder,
|
||||||
"Archived ROMs (*.zip *.7z *.rar *.tar *.tar.gz *.tar.xz *.tar.bz2);;Any file (*.*)");
|
"Archived ROMs (*.zip *.7z *.rar *.tar *.tar.gz *.tar.xz *.tar.bz2);;Any file (*.*)");
|
||||||
if (filename.isEmpty())
|
if (archiveFileName.isEmpty())
|
||||||
{
|
{
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Finding list of ROMs...\n");
|
printf("Finding list of ROMs...\n");
|
||||||
QVector<QString> archiveROMList = Archive::ListArchive(filename.toUtf8().constData());
|
QVector<QString> archiveROMList = Archive::ListArchive(archiveFileName.toUtf8().constData());
|
||||||
|
QByteArray *romBuffer = new QByteArray();
|
||||||
|
QString romFileName; // file name inside archive
|
||||||
|
|
||||||
if (archiveROMList.size() > 2)
|
if (archiveROMList.size() > 2)
|
||||||
{
|
{
|
||||||
archiveROMList.removeFirst();
|
archiveROMList.removeFirst();
|
||||||
QString toLoad = QInputDialog::getItem(this, "melonDS",
|
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);
|
||||||
printf("Extracting '%s'\n", toLoad.toUtf8().constData());
|
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"))
|
if (extractResult[0] != QString("Err"))
|
||||||
{
|
{
|
||||||
filename = extractResult[0];
|
romFileName = extractResult[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1604,10 +1645,10 @@ void MainWindow::onOpenFileArchive()
|
|||||||
else if (archiveROMList.size() == 2)
|
else if (archiveROMList.size() == 2)
|
||||||
{
|
{
|
||||||
printf("Extracting the only ROM in archive\n");
|
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"))
|
if (extractResult[0] != QString("Err"))
|
||||||
{
|
{
|
||||||
filename = extractResult[0];
|
romFileName = extractResult[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1623,7 +1664,8 @@ void MainWindow::onOpenFileArchive()
|
|||||||
QMessageBox::critical(this, "melonDS", "The archive could not be read. It may be corrupt or you don't have the permissions.");
|
QMessageBox::critical(this, "melonDS", "The archive could not be read. It may be corrupt or you don't have the permissions.");
|
||||||
}
|
}
|
||||||
|
|
||||||
loadROM(filename);
|
loadROM(romBuffer, archiveFileName, romFileName);
|
||||||
|
delete romBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onClearRecentFiles()
|
void MainWindow::onClearRecentFiles()
|
||||||
|
@ -243,6 +243,7 @@ private:
|
|||||||
QMenu *recentMenu;
|
QMenu *recentMenu;
|
||||||
void updateRecentFilesMenu();
|
void updateRecentFilesMenu();
|
||||||
void loadROM(QString filename);
|
void loadROM(QString filename);
|
||||||
|
void loadROM(QByteArray *romData, QString archiveFileName, QString romFileName);
|
||||||
|
|
||||||
void createScreenPanel();
|
void createScreenPanel();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user