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:
Madhav Kanbur
2021-01-11 14:31:04 +05:30
parent 509a8aac3d
commit 89ff8fefd3
10 changed files with 177 additions and 27 deletions

View File

@ -823,6 +823,20 @@ void SetConsoleType(int 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)
{
if (NDSCart::LoadROM(path, sram, direct))

View File

@ -193,6 +193,7 @@ void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq,
void SetConsoleType(int type);
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);
void LoadBIOS();
void SetupDirectBoot();

View File

@ -1026,6 +1026,22 @@ bool LoadROM(const char* path, const char* sram, bool 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)
{
// herp derp

View File

@ -46,6 +46,7 @@ void DoSavestate(Savestate* file);
void DecryptSecureArea(u8* out);
bool LoadROM(const char* path, const char* sram, bool direct);
bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct);
void FlushSRAMFile();

View File

@ -19,6 +19,9 @@
#ifndef FRONTENDUTIL_H
#define FRONTENDUTIL_H
#include <QByteArray>
#include <QString>
#include "types.h"
namespace Frontend
@ -76,6 +79,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 QByteArray *romdata, QString archivefilename, QString romfilename, int slot);
// unload the ROM loaded in the specified cart slot
// simulating ejection of the cartridge

View File

@ -19,6 +19,9 @@
#include <stdio.h>
#include <string.h>
#include <QFileInfo>
#include <QDir>
#include "FrontendUtil.h"
#include "Config.h"
#include "SharedConfig.h"
@ -283,6 +286,85 @@ int LoadBIOS()
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 res;

View File

@ -53,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;
@ -67,11 +67,9 @@ 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;
@ -79,8 +77,8 @@ QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile
}
size_t bytesToWrite = archive_entry_size(entry);
QByteArray archiveBuffer(bytesToWrite, '\0');
ssize_t bytesRead = archive_read_data(a, archiveBuffer.data(), bytesToWrite);
romBuffer->fill(0, bytesToWrite);
ssize_t bytesRead = archive_read_data(a, romBuffer->data(), bytesToWrite);
if (bytesRead < 0)
{
@ -88,18 +86,9 @@ QVector<QString> ExtractFileFromArchive(const char* path, const char* wantedFile
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_free(a);
return QVector<QString> {nameToWrite};
return QVector<QString> {wantedFile};
}

View File

@ -18,7 +18,7 @@ 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);
}

View File

@ -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)
{
recentFileList.removeAll(filename);
@ -1573,28 +1611,31 @@ 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;
}
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)
{
archiveROMList.removeFirst();
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);
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
{
@ -1604,10 +1645,10 @@ void MainWindow::onOpenFileArchive()
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
{
@ -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.");
}
loadROM(filename);
loadROM(romBuffer, archiveFileName, romFileName);
delete romBuffer;
}
void MainWindow::onClearRecentFiles()

View File

@ -243,6 +243,7 @@ private:
QMenu *recentMenu;
void updateRecentFilesMenu();
void loadROM(QString filename);
void loadROM(QByteArray *romData, QString archiveFileName, QString romFileName);
void createScreenPanel();