Add ability to load a ROM from a byte array instead of a file.

This commit is contained in:
SuuperW 2019-09-30 11:15:42 -05:00
parent d0b31758fc
commit e34c8fd52c
3 changed files with 157 additions and 117 deletions

View File

@ -401,21 +401,8 @@ void GameInfo::populate()
}*/
}
bool GameInfo::loadROM(std::string fname, u32 type)
bool GameInfo::loadROM(u32 type)
{
//printf("ROM %s\n", CommonSettings.loadToMemory?"loaded to RAM":"stream from disk");
closeROM();
char *noext = strdup(fname.c_str());
reader = ROMReaderInit(&noext); free(noext);
fROM = reader->Init(fname.c_str());
if (!fROM) return false;
headerOffset = (type == ROM_DSGBA)?DSGBA_LOADER_SIZE:0;
romsize = reader->Size(fROM) - headerOffset;
reader->Seek(fROM, headerOffset, SEEK_SET);
bool res = (reader->Read(fROM, &header, sizeof(header)) == sizeof(header));
if (res)
@ -511,31 +498,6 @@ bool GameInfo::loadROM(std::string fname, u32 type)
reader->Read(fROM, &secureArea[0], 0x4000);
}
//for now, we have to do this, because the DLDI patching requires it
bool loadToMemory = CommonSettings.loadToMemory;
if(isHomebrew())
loadToMemory = true;
//convert to an in-memory reader around a pre-read buffer if that's what's requested
if (loadToMemory)
{
reader->Seek(fROM, headerOffset, SEEK_SET);
romdataForReader = new u8[romsize];
if (reader->Read(fROM, romdataForReader, romsize) != romsize)
{
delete [] romdataForReader; romdataForReader = NULL;
romsize = 0;
return false;
}
reader->DeInit(fROM);
fROM = NULL;
reader = MemROMReaderRead_TrueInit(romdataForReader, romsize);
fROM = reader->Init(NULL);
}
if (hasRomBanner())
{
reader->Seek(fROM, header.IconOff, SEEK_SET);
@ -571,6 +533,63 @@ bool GameInfo::loadROM(std::string fname, u32 type)
romsize = 0;
reader->DeInit(fROM); fROM = NULL;
return false;
}
bool GameInfo::loadROM(std::string fname, u32 type)
{
//printf("ROM %s\n", CommonSettings.loadToMemory?"loaded to RAM":"stream from disk");
closeROM();
char *noext = strdup(fname.c_str());
reader = ROMReaderInit(&noext); free(noext);
fROM = reader->Init(fname.c_str());
if (!fROM) return false;
headerOffset = (type == ROM_DSGBA) ? DSGBA_LOADER_SIZE : 0;
romsize = reader->Size(fROM) - headerOffset;
reader->Seek(fROM, headerOffset, SEEK_SET);
//for now, we have to do this, because the DLDI patching requires it
bool loadToMemory = CommonSettings.loadToMemory;
if (isHomebrew())
loadToMemory = true;
//convert to an in-memory reader around a pre-read buffer if that's what's requested
if (loadToMemory)
{
reader->Seek(fROM, headerOffset, SEEK_SET);
romdataForReader = new u8[romsize];
if (reader->Read(fROM, romdataForReader, romsize) != romsize)
{
delete[] romdataForReader; romdataForReader = NULL;
romsize = 0;
return false;
}
reader->DeInit(fROM);
fROM = NULL;
reader = MemROMReaderRead_TrueInit(romdataForReader, romsize);
fROM = reader->Init(NULL);
}
return loadROM(type);
}
bool GameInfo::loadROM(u8* file, s32 fileSize)
{
closeROM();
// create memory stream
reader = MemROMReaderRead_TrueInit(file, fileSize);
fROM = reader->Init(NULL);
headerOffset = 0;
romsize = reader->Size(fROM) - headerOffset;
reader->Seek(fROM, headerOffset, SEEK_SET);
return loadROM(ROM_NDS);
}
void GameInfo::closeROM()
@ -667,45 +686,17 @@ struct LastRom {
std::string filename, physicalName, logicalFilename;
} lastRom;
int NDS_LoadROM(const char *filename, const char *physicalName, const char *logicalFilename)
void LoadGameInfo()
{
lastRom.filename = filename;
lastRom.physicalName = physicalName ? physicalName : "";
lastRom.logicalFilename = logicalFilename ? logicalFilename : "";
int ret;
char buf[MAX_PATH];
if (filename == NULL)
return -1;
ret = rom_init_path(filename, physicalName, logicalFilename);
if (ret < 1)
return ret;
if (cheatSearch)
cheatSearch->close();
FCEUI_StopMovie();
if (!gameInfo.ValidateHeader())
{
ret = -1;
return ret;
}
gameInfo.populate();
//run crc over the whole buffer (chunk at a time, to avoid coding a streaming crc
gameInfo.reader->Seek(gameInfo.fROM, 0, SEEK_SET);
gameInfo.crc = 0;
bool first = true;
for (;;) {
u8 buf[4096];
int read = gameInfo.reader->Read(gameInfo.fROM, buf, 4096);
if (read == 0) break;
if(first && read >= 512)
gameInfo.crcForCheatsDb = ~crc32(0, buf, 512);
first = false;
gameInfo.crc = crc32(gameInfo.crc, buf, read);
}
@ -743,6 +734,43 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
const char *makerName = Database::MakerNameForMakerCode(gameInfo.header.makerCode, true);
INFO("ROM developer: %s\n", ((gameInfo.header.makerCode == 0) && gameInfo.isHomebrew()) ? "Homebrew" : makerName);
//for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails
if (gameInfo.isHomebrew())
{
//note: gameInfo.romdataForReader is safe here because we made sure to load the rom into memory for isHomebrew
if (slot1_GetCurrentType() == NDS_SLOT1_R4)
DLDI::tryPatch((void*)gameInfo.romdataForReader, gameInfo.romsize, 1);
else if (slot2_GetCurrentType() == NDS_SLOT2_CFLASH)
DLDI::tryPatch((void*)gameInfo.romdataForReader, gameInfo.romsize, 0);
}
}
int NDS_LoadROM(const char *filename, const char *physicalName, const char *logicalFilename)
{
lastRom.filename = filename;
lastRom.physicalName = physicalName ? physicalName : "";
lastRom.logicalFilename = logicalFilename ? logicalFilename : "";
int ret;
char buf[MAX_PATH];
if (filename == NULL)
return -1;
ret = rom_init_path(filename, physicalName, logicalFilename);
if (ret < 1)
return ret;
if (cheatSearch)
cheatSearch->close();
FCEUI_StopMovie();
if (!gameInfo.ValidateHeader())
{
ret = -1;
return ret;
}
LoadGameInfo();
buf[0] = gameInfo.header.gameCode[0];
buf[1] = gameInfo.header.gameCode[1];
buf[2] = gameInfo.header.gameCode[2];
@ -769,16 +797,6 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
}
printf("\n");
//for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails
if(gameInfo.isHomebrew())
{
//note: gameInfo.romdataForReader is safe here because we made sure to load the rom into memory for isHomebrew
if (slot1_GetCurrentType() == NDS_SLOT1_R4)
DLDI::tryPatch((void*)gameInfo.romdataForReader, gameInfo.romsize, 1);
else if (slot2_GetCurrentType() == NDS_SLOT2_CFLASH)
DLDI::tryPatch((void*)gameInfo.romdataForReader, gameInfo.romsize, 0);
}
if (cheats != NULL)
{
memset(buf, 0, MAX_PATH);
@ -792,6 +810,20 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
return ret;
}
int NDS_LoadROM(u8* file, int fileSize)
{
gameInfo.loadROM(file, fileSize);
gameInfo.romType = ROM_NDS;
if (!gameInfo.ValidateHeader())
return -1;
// I'm not sure all this is necessary/wanted here.
LoadGameInfo();
NDS_Reset();
return 1;
}
void NDS_FreeROM(void)
{

View File

@ -373,6 +373,8 @@ struct GameInfo
bool IsCode(const char* code) const;
bool loadROM(std::string fname, u32 type = ROM_NDS);
bool loadROM(u8* file, s32 fileSize);
bool loadROM(u32 type);
void closeROM();
u32 readROM(u32 pos);
bool ValidateHeader();
@ -465,6 +467,7 @@ void NDS_suspendProcessingInput(bool suspend);
int NDS_LoadROM(const char *filename, const char* physicalFilename=0, const char* logicalFilename=0);
int NDS_LoadROM(u8* file, int fileSize);
void NDS_FreeROM(void);
void NDS_Reset();

View File

@ -65,3 +65,8 @@ DLL int GetFrameCount()
{
return currFrameCounter;
}
DLL bool LoadROM(u8* file, int fileSize)
{
return (NDS_LoadROM(file, fileSize) > 0);
}