mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 07:10: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;
|
||||
}
|
||||
|
||||
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))
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -243,6 +243,7 @@ private:
|
||||
QMenu *recentMenu;
|
||||
void updateRecentFilesMenu();
|
||||
void loadROM(QString filename);
|
||||
void loadROM(QByteArray *romData, QString archiveFileName, QString romFileName);
|
||||
|
||||
void createScreenPanel();
|
||||
|
||||
|
Reference in New Issue
Block a user