mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-28 00:30:24 -06:00
more WIP. ROM loading working, sorta. not loading saves or anything yet.
This commit is contained in:
@ -648,6 +648,9 @@ void Reset()
|
|||||||
|
|
||||||
void Eject()
|
void Eject()
|
||||||
{
|
{
|
||||||
|
if (Cart) delete Cart;
|
||||||
|
Cart = nullptr;
|
||||||
|
|
||||||
if (CartROM) delete[] CartROM;
|
if (CartROM) delete[] CartROM;
|
||||||
|
|
||||||
CartInserted = false;
|
CartInserted = false;
|
||||||
@ -656,9 +659,6 @@ void Eject()
|
|||||||
CartCRC = 0;
|
CartCRC = 0;
|
||||||
CartID = 0;
|
CartID = 0;
|
||||||
|
|
||||||
if (Cart) delete Cart;
|
|
||||||
Cart = nullptr;
|
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,12 +903,12 @@ bool LoadCart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen)
|
|||||||
if (savedata && savelen)
|
if (savedata && savelen)
|
||||||
NDSCart::LoadSave(savedata, savelen);
|
NDSCart::LoadSave(savedata, savelen);
|
||||||
|
|
||||||
//Running = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EjectCart()
|
void EjectCart()
|
||||||
{
|
{
|
||||||
printf("TODO!!!!\n");
|
NDSCart::EjectCart();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen)
|
bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen)
|
||||||
|
@ -55,8 +55,6 @@ bool CartInserted;
|
|||||||
u8* CartROM;
|
u8* CartROM;
|
||||||
u32 CartROMSize;
|
u32 CartROMSize;
|
||||||
u32 CartID;
|
u32 CartID;
|
||||||
bool CartIsHomebrew;
|
|
||||||
bool CartIsDSi;
|
|
||||||
|
|
||||||
NDSHeader Header;
|
NDSHeader Header;
|
||||||
NDSBanner Banner;
|
NDSBanner Banner;
|
||||||
@ -1505,16 +1503,14 @@ void DeInit()
|
|||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
|
if (Cart) delete Cart;
|
||||||
|
Cart = nullptr;
|
||||||
|
|
||||||
CartInserted = false;
|
CartInserted = false;
|
||||||
if (CartROM) delete[] CartROM;
|
if (CartROM) delete[] CartROM;
|
||||||
CartROM = nullptr;
|
CartROM = nullptr;
|
||||||
CartROMSize = 0;
|
CartROMSize = 0;
|
||||||
CartID = 0;
|
CartID = 0;
|
||||||
CartIsHomebrew = false;
|
|
||||||
CartIsDSi = false;
|
|
||||||
|
|
||||||
if (Cart) delete Cart;
|
|
||||||
Cart = nullptr;
|
|
||||||
|
|
||||||
ResetCart();
|
ResetCart();
|
||||||
}
|
}
|
||||||
@ -1624,7 +1620,8 @@ void DecryptSecureArea(u8* out)
|
|||||||
//bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
|
//bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
|
||||||
bool LoadROM(const u8* romdata, u32 romlen)
|
bool LoadROM(const u8* romdata, u32 romlen)
|
||||||
{
|
{
|
||||||
//NDS::Reset();
|
if (CartInserted)
|
||||||
|
EjectCart();
|
||||||
|
|
||||||
CartROMSize = 0x200;
|
CartROMSize = 0x200;
|
||||||
while (CartROMSize < romlen)
|
while (CartROMSize < romlen)
|
||||||
@ -1654,10 +1651,10 @@ bool LoadROM(const u8* romdata, u32 romlen)
|
|||||||
(u32)Header.GameCode[0];
|
(u32)Header.GameCode[0];
|
||||||
|
|
||||||
u8 unitcode = Header.UnitCode;
|
u8 unitcode = Header.UnitCode;
|
||||||
CartIsDSi = (unitcode & 0x02) != 0;
|
bool dsi = (unitcode & 0x02) != 0;
|
||||||
|
|
||||||
u32 arm9base = Header.ARM9ROMOffset;
|
u32 arm9base = Header.ARM9ROMOffset;
|
||||||
CartIsHomebrew = (arm9base < 0x4000) || (gamecode == 0x23232323);
|
bool homebrew = (arm9base < 0x4000) || (gamecode == 0x23232323);
|
||||||
|
|
||||||
ROMListEntry romparams;
|
ROMListEntry romparams;
|
||||||
if (!ReadROMParams(gamecode, &romparams))
|
if (!ReadROMParams(gamecode, &romparams))
|
||||||
@ -1667,7 +1664,7 @@ bool LoadROM(const u8* romdata, u32 romlen)
|
|||||||
|
|
||||||
romparams.GameCode = gamecode;
|
romparams.GameCode = gamecode;
|
||||||
romparams.ROMSize = CartROMSize;
|
romparams.ROMSize = CartROMSize;
|
||||||
if (CartIsHomebrew)
|
if (homebrew)
|
||||||
romparams.SaveMemType = 0; // no saveRAM for homebrew
|
romparams.SaveMemType = 0; // no saveRAM for homebrew
|
||||||
else
|
else
|
||||||
romparams.SaveMemType = 2; // assume EEPROM 64k (TODO FIXME)
|
romparams.SaveMemType = 2; // assume EEPROM 64k (TODO FIXME)
|
||||||
@ -1691,7 +1688,7 @@ bool LoadROM(const u8* romdata, u32 romlen)
|
|||||||
if (romparams.SaveMemType >= 8 && romparams.SaveMemType <= 10)
|
if (romparams.SaveMemType >= 8 && romparams.SaveMemType <= 10)
|
||||||
CartID |= 0x08000000; // NAND flag
|
CartID |= 0x08000000; // NAND flag
|
||||||
|
|
||||||
if (CartIsDSi)
|
if (dsi)
|
||||||
CartID |= 0x40000000;
|
CartID |= 0x40000000;
|
||||||
|
|
||||||
// cart ID for Jam with the Band
|
// cart ID for Jam with the Band
|
||||||
@ -1719,7 +1716,7 @@ bool LoadROM(const u8* romdata, u32 romlen)
|
|||||||
Key1_Encrypt((u32*)&CartROM[arm9base]);
|
Key1_Encrypt((u32*)&CartROM[arm9base]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("FAZIL");
|
||||||
CartInserted = true;
|
CartInserted = true;
|
||||||
|
|
||||||
u32 irversion = 0;
|
u32 irversion = 0;
|
||||||
@ -1731,7 +1728,7 @@ bool LoadROM(const u8* romdata, u32 romlen)
|
|||||||
irversion = 2; // Pokémon HG/SS, B/W, B2/W2
|
irversion = 2; // Pokémon HG/SS, B/W, B2/W2
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CartIsHomebrew)
|
if (homebrew)
|
||||||
Cart = new CartHomebrew(CartROM, CartROMSize, CartID);
|
Cart = new CartHomebrew(CartROM, CartROMSize, CartID);
|
||||||
else if (CartID & 0x08000000)
|
else if (CartID & 0x08000000)
|
||||||
Cart = new CartRetailNAND(CartROM, CartROMSize, CartID);
|
Cart = new CartRetailNAND(CartROM, CartROMSize, CartID);
|
||||||
@ -1741,7 +1738,7 @@ bool LoadROM(const u8* romdata, u32 romlen)
|
|||||||
Cart = new CartRetailBT(CartROM, CartROMSize, CartID);
|
Cart = new CartRetailBT(CartROM, CartROMSize, CartID);
|
||||||
else
|
else
|
||||||
Cart = new CartRetail(CartROM, CartROMSize, CartID);
|
Cart = new CartRetail(CartROM, CartROMSize, CartID);
|
||||||
|
printf("PFART\n");
|
||||||
if (Cart)
|
if (Cart)
|
||||||
Cart->Reset();
|
Cart->Reset();
|
||||||
/*{
|
/*{
|
||||||
@ -1762,14 +1759,14 @@ bool LoadROM(const u8* romdata, u32 romlen)
|
|||||||
//if (Cart) Cart->LoadSave(sram, romparams.SaveMemType);
|
//if (Cart) Cart->LoadSave(sram, romparams.SaveMemType);
|
||||||
if (Cart && romparams.SaveMemType > 0)
|
if (Cart && romparams.SaveMemType > 0)
|
||||||
Cart->SetupSave(romparams.SaveMemType);
|
Cart->SetupSave(romparams.SaveMemType);
|
||||||
|
printf("PROEUPRAOUTTE\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadSave(const u8* savedata, u32 savelen)
|
void LoadSave(const u8* savedata, u32 savelen)
|
||||||
{
|
{printf("CARTSAVE\n");
|
||||||
if (Cart)
|
if (Cart)
|
||||||
Cart->LoadSave(savedata, savelen);
|
Cart->LoadSave(savedata, savelen);printf("SAVE FARTED\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bool LoadROM(const char* path, const char* sram, bool direct)
|
/*bool LoadROM(const char* path, const char* sram, bool direct)
|
||||||
@ -1854,6 +1851,26 @@ int ImportSRAM(const u8* data, u32 length)
|
|||||||
return 0;
|
return 0;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
void EjectCart()
|
||||||
|
{
|
||||||
|
if (!CartInserted) return;
|
||||||
|
|
||||||
|
// ejecting the cart triggers the gamecard IRQ
|
||||||
|
NDS::SetIRQ(0, NDS::IRQ_CartIREQMC);
|
||||||
|
NDS::SetIRQ(1, NDS::IRQ_CartIREQMC);
|
||||||
|
|
||||||
|
if (Cart) delete Cart;
|
||||||
|
Cart = nullptr;
|
||||||
|
|
||||||
|
CartInserted = false;
|
||||||
|
if (CartROM) delete[] CartROM;
|
||||||
|
CartROM = nullptr;
|
||||||
|
CartROMSize = 0;
|
||||||
|
CartID = 0;
|
||||||
|
|
||||||
|
// CHECKME: does an eject imply anything for the ROM/SPI transfer registers?
|
||||||
|
}
|
||||||
|
|
||||||
void ResetCart()
|
void ResetCart()
|
||||||
{
|
{
|
||||||
// CHECKME: what if there is a transfer in progress?
|
// CHECKME: what if there is a transfer in progress?
|
||||||
|
@ -218,6 +218,8 @@ bool LoadROM(const u8* romdata, u32 romlen);
|
|||||||
void LoadSave(const u8* savedata, u32 savelen);
|
void LoadSave(const u8* savedata, u32 savelen);
|
||||||
void SetupDirectBoot(std::string romname);
|
void SetupDirectBoot(std::string romname);
|
||||||
|
|
||||||
|
void EjectCart();
|
||||||
|
|
||||||
//void FlushSRAMFile();
|
//void FlushSRAMFile();
|
||||||
|
|
||||||
//void RelocateSave(const char* path, bool write);
|
//void RelocateSave(const char* path, bool write);
|
||||||
|
@ -116,7 +116,45 @@ QVector<QString> ExtractFileFromArchive(QString path, QString wantedFile, QByteA
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ExtractFileFromArchive(const char* path, const char* wantedFile, u8 **romdata)
|
u32 ExtractFileFromArchive(QString path, QString wantedFile, u8** filedata, u32* filesize)
|
||||||
|
{
|
||||||
|
struct archive *a = archive_read_new();
|
||||||
|
struct archive_entry *entry;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!filedata) return -1;
|
||||||
|
|
||||||
|
archive_read_support_format_all(a);
|
||||||
|
archive_read_support_filter_all(a);
|
||||||
|
|
||||||
|
//r = archive_read_open_filename(a, path, 10240);
|
||||||
|
r = melon_archive_open(a, path, 10240);
|
||||||
|
if (r != ARCHIVE_OK)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (archive_read_next_header(a, &entry) == ARCHIVE_OK)
|
||||||
|
{
|
||||||
|
if (strcmp(wantedFile.toUtf8().constData(), archive_entry_pathname_utf8(entry)) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytesToRead = archive_entry_size(entry);
|
||||||
|
if (filesize) *filesize = bytesToRead;
|
||||||
|
*filedata = new u8[bytesToRead];
|
||||||
|
ssize_t bytesRead = archive_read_data(a, *filedata, bytesToRead);
|
||||||
|
|
||||||
|
archive_read_close(a);
|
||||||
|
archive_read_free(a);
|
||||||
|
|
||||||
|
return (u32)bytesRead;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*u32 ExtractFileFromArchive(const char* path, const char* wantedFile, u8 **romdata)
|
||||||
{
|
{
|
||||||
QByteArray romBuffer;
|
QByteArray romBuffer;
|
||||||
QVector<QString> extractResult = ExtractFileFromArchive(path, wantedFile, &romBuffer);
|
QVector<QString> extractResult = ExtractFileFromArchive(path, wantedFile, &romBuffer);
|
||||||
@ -131,6 +169,6 @@ u32 ExtractFileFromArchive(const char* path, const char* wantedFile, u8 **romdat
|
|||||||
memcpy(*romdata, romBuffer.data(), len);
|
memcpy(*romdata, romBuffer.data(), len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@ namespace Archive
|
|||||||
{
|
{
|
||||||
|
|
||||||
QVector<QString> ListArchive(QString path);
|
QVector<QString> ListArchive(QString path);
|
||||||
QVector<QString> ExtractFileFromArchive(QString path, QString wantedFile, QByteArray *romBuffer);
|
u32 ExtractFileFromArchive(QString path, QString wantedFile, u8** filedata, u32* filesize);
|
||||||
|
//QVector<QString> ExtractFileFromArchive(QString path, QString wantedFile, QByteArray *romBuffer);
|
||||||
//u32 ExtractFileFromArchive(const char* path, const char* wantedFile, u8 **romdata);
|
//u32 ExtractFileFromArchive(const char* path, const char* wantedFile, u8 **romdata);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ ARCodeFile* CheatFile;
|
|||||||
bool CheatsOn;
|
bool CheatsOn;
|
||||||
|
|
||||||
|
|
||||||
void Init_ROM()
|
/*void Init_ROM()
|
||||||
{
|
{
|
||||||
SavestateLoaded = false;
|
SavestateLoaded = false;
|
||||||
|
|
||||||
@ -73,55 +73,53 @@ void DeInit_ROM()
|
|||||||
delete CheatFile;
|
delete CheatFile;
|
||||||
CheatFile = nullptr;
|
CheatFile = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// TODO: currently, when failing to load a ROM for whatever reason, we attempt
|
// TODO: currently, when failing to load a ROM for whatever reason, we attempt
|
||||||
// to revert to the previous state and resume execution; this may not be a very
|
// to revert to the previous state and resume execution; this may not be a very
|
||||||
// good thing, depending on what state the core was left in.
|
// good thing, depending on what state the core was left in.
|
||||||
// should we do a better state revert (via the savestate system)? completely stop?
|
// should we do a better state revert (via the savestate system)? completely stop?
|
||||||
|
|
||||||
void SetupSRAMPath(int slot)
|
/*void SetupSRAMPath(int slot)
|
||||||
{
|
{
|
||||||
SRAMPath[slot] = ROMPath[slot].substr(0, ROMPath[slot].length() - 3) + "sav";
|
SRAMPath[slot] = ROMPath[slot].substr(0, ROMPath[slot].length() - 3) + "sav";
|
||||||
}
|
}*/
|
||||||
|
|
||||||
int VerifyDSBIOS()
|
QString VerifyDSBIOS()
|
||||||
{
|
{
|
||||||
FILE* f;
|
FILE* f;
|
||||||
long len;
|
long len;
|
||||||
|
|
||||||
if (!Config::ExternalBIOSEnable) return Load_OK;
|
|
||||||
|
|
||||||
f = Platform::OpenLocalFile(Config::BIOS9Path, "rb");
|
f = Platform::OpenLocalFile(Config::BIOS9Path, "rb");
|
||||||
if (!f) return Load_BIOS9Missing;
|
if (!f) return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
len = ftell(f);
|
len = ftell(f);
|
||||||
if (len != 0x1000)
|
if (len != 0x1000)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return Load_BIOS9Bad;
|
return "DS ARM9 BIOS is not a valid BIOS dump.";
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
f = Platform::OpenLocalFile(Config::BIOS7Path, "rb");
|
f = Platform::OpenLocalFile(Config::BIOS7Path, "rb");
|
||||||
if (!f) return Load_BIOS7Missing;
|
if (!f) return "DS ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
len = ftell(f);
|
len = ftell(f);
|
||||||
if (len != 0x4000)
|
if (len != 0x4000)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return Load_BIOS7Bad;
|
return "DS ARM7 BIOS is not a valid BIOS dump.";
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return Load_OK;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int VerifyDSiBIOS()
|
QString VerifyDSiBIOS()
|
||||||
{
|
{
|
||||||
FILE* f;
|
FILE* f;
|
||||||
long len;
|
long len;
|
||||||
@ -129,43 +127,41 @@ int VerifyDSiBIOS()
|
|||||||
// TODO: check the first 32 bytes
|
// TODO: check the first 32 bytes
|
||||||
|
|
||||||
f = Platform::OpenLocalFile(Config::DSiBIOS9Path, "rb");
|
f = Platform::OpenLocalFile(Config::DSiBIOS9Path, "rb");
|
||||||
if (!f) return Load_DSiBIOS9Missing;
|
if (!f) return "DSi ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
len = ftell(f);
|
len = ftell(f);
|
||||||
if (len != 0x10000)
|
if (len != 0x10000)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return Load_DSiBIOS9Bad;
|
return "DSi ARM9 BIOS is not a valid BIOS dump.";
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
f = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb");
|
f = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb");
|
||||||
if (!f) return Load_DSiBIOS7Missing;
|
if (!f) return "DSi ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
len = ftell(f);
|
len = ftell(f);
|
||||||
if (len != 0x10000)
|
if (len != 0x10000)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return Load_DSiBIOS7Bad;
|
return "DSi ARM7 BIOS is not a valid BIOS dump.";
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return Load_OK;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int VerifyDSFirmware()
|
QString VerifyDSFirmware()
|
||||||
{
|
{
|
||||||
FILE* f;
|
FILE* f;
|
||||||
long len;
|
long len;
|
||||||
|
|
||||||
if (!Config::ExternalBIOSEnable) return Load_FirmwareNotBootable;
|
|
||||||
|
|
||||||
f = Platform::OpenLocalFile(Config::FirmwarePath, "rb");
|
f = Platform::OpenLocalFile(Config::FirmwarePath, "rb");
|
||||||
if (!f) return Load_FirmwareNotBootable;
|
if (!f) return "DS firmware was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
len = ftell(f);
|
len = ftell(f);
|
||||||
@ -173,26 +169,27 @@ int VerifyDSFirmware()
|
|||||||
{
|
{
|
||||||
// 128KB firmware, not bootable
|
// 128KB firmware, not bootable
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return Load_FirmwareNotBootable;
|
// TODO report it somehow? detect in core?
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
else if (len != 0x40000 && len != 0x80000)
|
else if (len != 0x40000 && len != 0x80000)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return Load_FirmwareBad;
|
return "DS firmware is not a valid firmware dump.";
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return Load_OK;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int VerifyDSiFirmware()
|
QString VerifyDSiFirmware()
|
||||||
{
|
{
|
||||||
FILE* f;
|
FILE* f;
|
||||||
long len;
|
long len;
|
||||||
|
|
||||||
f = Platform::OpenLocalFile(Config::DSiFirmwarePath, "rb");
|
f = Platform::OpenLocalFile(Config::DSiFirmwarePath, "rb");
|
||||||
if (!f) return Load_FirmwareMissing;
|
if (!f) return "DSi firmware was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
len = ftell(f);
|
len = ftell(f);
|
||||||
@ -201,30 +198,132 @@ int VerifyDSiFirmware()
|
|||||||
// not 128KB
|
// not 128KB
|
||||||
// TODO: check whether those work
|
// TODO: check whether those work
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return Load_FirmwareBad;
|
return "DSi firmware is not a valid firmware dump.";
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return Load_OK;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int SetupDSiNAND()
|
QString VerifyDSiNAND()
|
||||||
{
|
{
|
||||||
FILE* f;
|
FILE* f;
|
||||||
long len;
|
long len;
|
||||||
|
|
||||||
f = Platform::OpenLocalFile(Config::DSiNANDPath, "r+b");
|
f = Platform::OpenLocalFile(Config::DSiNANDPath, "r+b");
|
||||||
if (!f) return Load_DSiNANDMissing;
|
if (!f) return "DSi NAND was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
// TODO: some basic checks
|
// TODO: some basic checks
|
||||||
// check that it has the nocash footer, and all
|
// check that it has the nocash footer, and all
|
||||||
|
|
||||||
DSi::SDMMCFile = f;
|
fclose(f);
|
||||||
|
|
||||||
return Load_OK;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString VerifySetup()
|
||||||
|
{
|
||||||
|
QString res;
|
||||||
|
|
||||||
|
if (Config::ExternalBIOSEnable)
|
||||||
|
{
|
||||||
|
res = VerifyDSBIOS();
|
||||||
|
if (!res.isEmpty()) return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config::ConsoleType == 1)
|
||||||
|
{
|
||||||
|
res = VerifyDSiBIOS();
|
||||||
|
if (!res.isEmpty()) return res;
|
||||||
|
|
||||||
|
if (Config::ExternalBIOSEnable)
|
||||||
|
{
|
||||||
|
res = VerifyDSiFirmware();
|
||||||
|
if (!res.isEmpty()) return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = VerifyDSiNAND();
|
||||||
|
if (!res.isEmpty()) return res;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Config::ExternalBIOSEnable)
|
||||||
|
{
|
||||||
|
res = VerifyDSFirmware();
|
||||||
|
if (!res.isEmpty()) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LoadROM(QStringList filepath, bool reset)
|
||||||
|
{
|
||||||
|
if (filepath.empty()) return false;
|
||||||
|
|
||||||
|
u8* filedata;
|
||||||
|
u32 filelen;
|
||||||
|
|
||||||
|
int num = filepath.count();
|
||||||
|
if (num == 1)
|
||||||
|
{
|
||||||
|
// regular file
|
||||||
|
|
||||||
|
FILE* f = Platform::OpenFile(filepath.at(0).toStdString(), "rb", true);
|
||||||
|
if (!f) return false;
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long len = ftell(f);
|
||||||
|
if (len > 0x40000000)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
filedata = new u8[len];
|
||||||
|
size_t nread = fread(filedata, (size_t)len, 1, f);
|
||||||
|
if (nread != 1)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
delete[] filedata;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
filelen = (u32)len;
|
||||||
|
}
|
||||||
|
#ifdef ARCHIVE_SUPPORT_ENABLED
|
||||||
|
else if (num == 2)
|
||||||
|
{
|
||||||
|
// file inside archive
|
||||||
|
|
||||||
|
u32 lenread = Archive::ExtractFileFromArchive(filepath.at(0), filepath.at(1), &filedata, &filelen);
|
||||||
|
if (lenread < 0) return false;
|
||||||
|
if (!filedata) return false;
|
||||||
|
if (lenread != filelen)
|
||||||
|
{
|
||||||
|
delete[] filedata;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (reset)
|
||||||
|
{
|
||||||
|
NDS::Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: SAVE
|
||||||
|
return NDS::LoadCart(filedata, filelen, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LoadCheats()
|
void LoadCheats()
|
||||||
{
|
{
|
||||||
if (CheatFile)
|
if (CheatFile)
|
||||||
@ -251,7 +350,7 @@ void LoadCheats()
|
|||||||
AREngine::SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
AREngine::SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int LoadBIOS()
|
/*int LoadBIOS()
|
||||||
{
|
{
|
||||||
DSi::CloseDSiNAND();
|
DSi::CloseDSiNAND();
|
||||||
|
|
||||||
@ -363,7 +462,7 @@ int LoadROM(const u8 *romdata, u32 romlength, const char *archivefilename, const
|
|||||||
PrevSRAMPath[slot] = SRAMPath[slot]; // safety
|
PrevSRAMPath[slot] = SRAMPath[slot]; // safety
|
||||||
return Load_OK;
|
return Load_OK;
|
||||||
}
|
}
|
||||||
else*/
|
else*-/
|
||||||
{
|
{
|
||||||
ROMPath[slot] = oldpath;
|
ROMPath[slot] = oldpath;
|
||||||
SRAMPath[slot] = oldsram;
|
SRAMPath[slot] = oldsram;
|
||||||
@ -443,13 +542,13 @@ int LoadROM(const char* file, int slot)
|
|||||||
PrevSRAMPath[slot] = SRAMPath[slot]; // safety
|
PrevSRAMPath[slot] = SRAMPath[slot]; // safety
|
||||||
return Load_OK;
|
return Load_OK;
|
||||||
}
|
}
|
||||||
else*/
|
else*-/
|
||||||
{
|
{
|
||||||
ROMPath[slot] = oldpath;
|
ROMPath[slot] = oldpath;
|
||||||
SRAMPath[slot] = oldsram;
|
SRAMPath[slot] = oldsram;
|
||||||
return Load_ROMLoadError;
|
return Load_ROMLoadError;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void ROMIcon(u8 (&data)[512], u16 (&palette)[16], u32* iconRef)
|
void ROMIcon(u8 (&data)[512], u16 (&palette)[16], u32* iconRef)
|
||||||
{
|
{
|
||||||
@ -535,7 +634,7 @@ void UnloadROM(int slot)
|
|||||||
|
|
||||||
int Reset()
|
int Reset()
|
||||||
{
|
{
|
||||||
DSi::CloseDSiNAND();
|
/*DSi::CloseDSiNAND();
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
bool directboot = Config::DirectBoot != 0;
|
bool directboot = Config::DirectBoot != 0;
|
||||||
@ -611,7 +710,7 @@ int Reset()
|
|||||||
|
|
||||||
bool ok = NDS::LoadROM(romdata, romlen, sramfilename, directboot);
|
bool ok = NDS::LoadROM(romdata, romlen, sramfilename, directboot);
|
||||||
delete romdata;
|
delete romdata;
|
||||||
if (!ok)*/
|
if (!ok)*-/
|
||||||
return Load_ROMLoadError;
|
return Load_ROMLoadError;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -650,13 +749,13 @@ int Reset()
|
|||||||
|
|
||||||
bool ok = NDS::LoadGBAROM(romdata, romlen, romfilename, SRAMPath[ROMSlot_GBA]);
|
bool ok = NDS::LoadGBAROM(romdata, romlen, romfilename, SRAMPath[ROMSlot_GBA]);
|
||||||
delete romdata;
|
delete romdata;
|
||||||
if (!ok)*/
|
if (!ok)*-/
|
||||||
return Load_ROMLoadError;
|
return Load_ROMLoadError;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadCheats();
|
LoadCheats();*/
|
||||||
|
|
||||||
return Load_OK;
|
return Load_OK;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
namespace ROMLoader
|
namespace ROMLoader
|
||||||
{
|
{
|
||||||
|
|
||||||
|
QString VerifySetup();
|
||||||
|
bool LoadROM(QStringList filepath, bool reset);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ROMSlot_NDS = 0,
|
ROMSlot_NDS = 0,
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
|
|
||||||
#include "main_shaders.h"
|
#include "main_shaders.h"
|
||||||
|
|
||||||
|
#include "ROMLoader.h"
|
||||||
#include "ArchiveUtil.h"
|
#include "ArchiveUtil.h"
|
||||||
|
|
||||||
// TODO: uniform variable spelling
|
// TODO: uniform variable spelling
|
||||||
@ -1792,7 +1793,7 @@ void MainWindow::dropEvent(QDropEvent* event)
|
|||||||
QList<QUrl> urls = event->mimeData()->urls();
|
QList<QUrl> urls = event->mimeData()->urls();
|
||||||
if (urls.count() > 1) return; // not handling more than one file at once
|
if (urls.count() > 1) return; // not handling more than one file at once
|
||||||
|
|
||||||
emuThread->emuPause();
|
/*emuThread->emuPause();
|
||||||
|
|
||||||
QString filename = urls.at(0).toLocalFile();
|
QString filename = urls.at(0).toLocalFile();
|
||||||
QString ext = filename.right(3).toLower();
|
QString ext = filename.right(3).toLower();
|
||||||
@ -1852,7 +1853,7 @@ void MainWindow::dropEvent(QDropEvent* event)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
emuThread->emuRun();
|
emuThread->emuRun();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onAppStateChanged(Qt::ApplicationState state)
|
void MainWindow::onAppStateChanged(Qt::ApplicationState state)
|
||||||
@ -1912,7 +1913,7 @@ QString MainWindow::loadErrorStr(int error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::loadROM(QByteArray *romData, QString archiveFileName, QString romFileName)
|
/*void MainWindow::loadROM(QByteArray *romData, QString archiveFileName, QString romFileName)
|
||||||
{
|
{
|
||||||
recentFileList.removeAll(archiveFileName);
|
recentFileList.removeAll(archiveFileName);
|
||||||
recentFileList.prepend(archiveFileName);
|
recentFileList.prepend(archiveFileName);
|
||||||
@ -2006,13 +2007,60 @@ void MainWindow::loadROM(QString filename)
|
|||||||
{
|
{
|
||||||
emuThread->emuRun();
|
emuThread->emuRun();
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
bool MainWindow::verifySetup()
|
||||||
|
{
|
||||||
|
QString res = ROMLoader::VerifySetup();
|
||||||
|
if (!res.isEmpty())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::pickAndLoadROM(bool gba)
|
QString MainWindow::pickFileFromArchive(QString archiveFileName)
|
||||||
|
{
|
||||||
|
QVector<QString> archiveROMList = Archive::ListArchive(archiveFileName);
|
||||||
|
|
||||||
|
QString romFileName = ""; // file name inside archive
|
||||||
|
|
||||||
|
if (archiveROMList.size() > 2)
|
||||||
|
{
|
||||||
|
archiveROMList.removeFirst();
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
QString toLoad = QInputDialog::getItem(this, "melonDS",
|
||||||
|
"This archive contains multiple files. Select which ROM you want to load.", archiveROMList.toList(), 0, false, &ok);
|
||||||
|
if (!ok) // User clicked on cancel
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
romFileName = toLoad;
|
||||||
|
}
|
||||||
|
else if (archiveROMList.size() == 2)
|
||||||
|
{
|
||||||
|
romFileName = archiveROMList.at(1);
|
||||||
|
}
|
||||||
|
else if ((archiveROMList.size() == 1) && (archiveROMList[0] == QString("OK")))
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, "melonDS", "This archive is empty.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", "This archive could not be read. It may be corrupt or you don't have the permissions.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return romFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList MainWindow::pickROM(bool gba)
|
||||||
{
|
{
|
||||||
QString console;
|
QString console;
|
||||||
QStringList romexts;
|
QStringList romexts;
|
||||||
QStringList arcexts{"*.zip", "*.7z", "*.rar", "*.tar", "*.gz", "*.xz", "*.bz2"};
|
QStringList arcexts{"*.zip", "*.7z", "*.rar", "*.tar", "*.tar.gz", "*.tar.xz", "*.tar.bz2"};
|
||||||
|
QStringList ret;
|
||||||
|
|
||||||
if (gba)
|
if (gba)
|
||||||
{
|
{
|
||||||
@ -2025,8 +2073,6 @@ void MainWindow::pickAndLoadROM(bool gba)
|
|||||||
romexts.append({"*.nds", "*.dsi", "*.srl"});
|
romexts.append({"*.nds", "*.dsi", "*.srl"});
|
||||||
}
|
}
|
||||||
|
|
||||||
emuThread->emuPause();
|
|
||||||
|
|
||||||
QString filter = romexts.join(' ') + " " + arcexts.join(' ');
|
QString filter = romexts.join(' ') + " " + arcexts.join(' ');
|
||||||
filter = console + " ROMs (" + filter + ");;Any file (*.*)";
|
filter = console + " ROMs (" + filter + ");;Any file (*.*)";
|
||||||
|
|
||||||
@ -2035,37 +2081,81 @@ void MainWindow::pickAndLoadROM(bool gba)
|
|||||||
QString::fromStdString(Config::LastROMFolder),
|
QString::fromStdString(Config::LastROMFolder),
|
||||||
filter);
|
filter);
|
||||||
if (filename.isEmpty())
|
if (filename.isEmpty())
|
||||||
{
|
return ret;
|
||||||
emuThread->emuUnpause();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos = filename.length() - 1;
|
int pos = filename.length() - 1;
|
||||||
while (filename[pos] != '/' && filename[pos] != '\\' && pos > 0) pos--;
|
while (filename[pos] != '/' && filename[pos] != '\\' && pos > 0) pos--;
|
||||||
QString path_dir = filename.left(pos);
|
QString path_dir = filename.left(pos);
|
||||||
QString path_file = filename.mid(pos+1);
|
QString path_file = filename.mid(pos+1);
|
||||||
QString path_ext = path_file.mid(path_file.lastIndexOf('.')).toLower();
|
|
||||||
|
|
||||||
Config::LastROMFolder = path_dir.toStdString();
|
Config::LastROMFolder = path_dir.toStdString();
|
||||||
|
|
||||||
printf("LOADING ROM: %s\n", filename.toStdString().c_str());
|
bool isarc = false;
|
||||||
printf("- %s\n", path_dir.toStdString().c_str());
|
for (const auto& ext : arcexts)
|
||||||
printf("- %s\n", path_file.toStdString().c_str());
|
|
||||||
printf("- %s\n", path_ext.toStdString().c_str());
|
|
||||||
|
|
||||||
if (arcexts.contains("*"+path_ext))
|
|
||||||
{
|
{
|
||||||
QByteArray romBuffer;
|
int l = ext.length() - 1;
|
||||||
QString arcfile = pickAndExtractFileFromArchive(filename, &romBuffer);
|
if (path_file.right(l).toLower() == ext.right(l))
|
||||||
|
{
|
||||||
printf("ARCHIVE: %s\n", arcfile.toStdString().c_str());
|
isarc = true;
|
||||||
printf("SIZE=%d\n", romBuffer.size());
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isarc)
|
||||||
|
{
|
||||||
|
path_file = pickFileFromArchive(filename);
|
||||||
|
if (path_file.isEmpty())
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret.append(filename);
|
||||||
|
ret.append(path_file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret.append(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onOpenFile()
|
void MainWindow::onOpenFile()
|
||||||
{
|
{
|
||||||
pickAndLoadROM(false);
|
emuThread->emuPause();
|
||||||
|
|
||||||
|
// stock path/archivepath in this module, alongside recent ROM list
|
||||||
|
// update them at the same time?
|
||||||
|
//
|
||||||
|
// 1. verify BIOS/firm/etc
|
||||||
|
// 2. pick ROM
|
||||||
|
// 3. set recent ROM, last folder, etc
|
||||||
|
// 4. reset system (if need be)
|
||||||
|
// 5. load ROM/SRAM into core
|
||||||
|
// 6. boot
|
||||||
|
if (!verifySetup())
|
||||||
|
{
|
||||||
|
emuThread->emuUnpause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList file = pickROM(false);
|
||||||
|
if (file.isEmpty())
|
||||||
|
{
|
||||||
|
emuThread->emuUnpause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add to recent ROM list
|
||||||
|
|
||||||
|
if (!ROMLoader::LoadROM(file, true))
|
||||||
|
{
|
||||||
|
// TODO: better error reporting?
|
||||||
|
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
||||||
|
emuThread->emuUnpause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("PROEUPRAON\n");
|
||||||
|
NDS::Start();printf("PROOT\n");
|
||||||
|
emuThread->emuRun();printf("ASSFAZIL\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onOpenFileArchive()
|
void MainWindow::onOpenFileArchive()
|
||||||
@ -2090,7 +2180,7 @@ void MainWindow::onOpenFileArchive()
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindow::pickAndExtractFileFromArchive(QString archiveFileName, QByteArray *romBuffer)
|
/*QString MainWindow::pickAndExtractFileFromArchive(QString archiveFileName, QByteArray *romBuffer)
|
||||||
{
|
{
|
||||||
printf("Finding list of ROMs...\n");
|
printf("Finding list of ROMs...\n");
|
||||||
QVector<QString> archiveROMList = Archive::ListArchive(archiveFileName.toUtf8().constData());
|
QVector<QString> archiveROMList = Archive::ListArchive(archiveFileName.toUtf8().constData());
|
||||||
@ -2142,7 +2232,7 @@ QString MainWindow::pickAndExtractFileFromArchive(QString archiveFileName, QByte
|
|||||||
}
|
}
|
||||||
|
|
||||||
return romFileName;
|
return romFileName;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void MainWindow::onClearRecentFiles()
|
void MainWindow::onClearRecentFiles()
|
||||||
{
|
{
|
||||||
@ -2201,7 +2291,7 @@ void MainWindow::updateRecentFilesMenu()
|
|||||||
|
|
||||||
void MainWindow::onClickRecentFile()
|
void MainWindow::onClickRecentFile()
|
||||||
{
|
{
|
||||||
QAction *act = (QAction *)sender();
|
/*QAction *act = (QAction *)sender();
|
||||||
QString fileName = act->data().toString();
|
QString fileName = act->data().toString();
|
||||||
|
|
||||||
if (fileName.endsWith(".gba", Qt::CaseInsensitive) ||
|
if (fileName.endsWith(".gba", Qt::CaseInsensitive) ||
|
||||||
@ -2223,7 +2313,7 @@ void MainWindow::onClickRecentFile()
|
|||||||
emuThread->emuPause();
|
emuThread->emuPause();
|
||||||
loadROM(&romBuffer, archiveFileName, romFileName);
|
loadROM(&romBuffer, archiveFileName, romFileName);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onBootFirmware()
|
void MainWindow::onBootFirmware()
|
||||||
@ -2868,7 +2958,8 @@ bool MelonApplication::event(QEvent *event)
|
|||||||
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent*>(event);
|
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent*>(event);
|
||||||
|
|
||||||
emuThread->emuPause();
|
emuThread->emuPause();
|
||||||
mainWindow->loadROM(openEvent->file());
|
//mainWindow->loadROM(openEvent->file());
|
||||||
|
printf("ASS EVENT???\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return QApplication::event(event);
|
return QApplication::event(event);
|
||||||
|
@ -292,13 +292,17 @@ private slots:
|
|||||||
void onFullscreenToggled();
|
void onFullscreenToggled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QStringList currentROM;
|
||||||
|
QStringList currentGBAROM;
|
||||||
QList<QString> recentFileList;
|
QList<QString> recentFileList;
|
||||||
QMenu *recentMenu;
|
QMenu *recentMenu;
|
||||||
void updateRecentFilesMenu();
|
void updateRecentFilesMenu();
|
||||||
|
|
||||||
QString pickAndExtractFileFromArchive(QString archiveFileName, QByteArray *romBuffer);
|
//QString pickAndExtractFileFromArchive(QString archiveFileName, QByteArray *romBuffer);
|
||||||
|
|
||||||
void pickAndLoadROM(bool gba);
|
bool verifySetup();
|
||||||
|
QString pickFileFromArchive(QString archiveFileName);
|
||||||
|
QStringList pickROM(bool gba);
|
||||||
|
|
||||||
void createScreenPanel();
|
void createScreenPanel();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user