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; 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))

View File

@ -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();

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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};
} }

View File

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

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) 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()

View File

@ -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();