Headerless rom support (when found in built-in game database)

This commit is contained in:
Souryo 2017-03-18 19:11:26 -04:00
parent 5fc0df4155
commit 4d96c13334
7 changed files with 107 additions and 29 deletions

View file

@ -226,6 +226,76 @@ uint8_t GameDatabase::GetSubMapper(GameInfo &info)
return 0;
}
bool GameDatabase::GetiNesHeader(uint32_t romCrc, NESHeader &nesHeader)
{
GameInfo info = {};
InitDatabase();
auto result = _gameDatabase.find(romCrc);
if(result != _gameDatabase.end()) {
MessageManager::Log("[DB] Headerless ROM file found - using game database data.");
info = result->second;
nesHeader.Byte9 = 0;
if(info.PrgRomSize > 4096) {
uint16_t prgSize = info.PrgRomSize / 16;
nesHeader.PrgCount = prgSize & 0xFF;
nesHeader.Byte9 |= (prgSize & 0xF00) >> 8;
} else {
nesHeader.PrgCount = info.PrgRomSize / 16;
}
if(info.ChrRomSize > 2048) {
uint16_t chrSize = info.ChrRomSize / 8;
nesHeader.ChrCount = chrSize & 0xFF;
nesHeader.Byte9 |= (chrSize & 0xF00) >> 4;
} else {
nesHeader.ChrCount = info.ChrRomSize / 8;
}
nesHeader.Byte6 = (info.MapperID & 0x0F) << 4;
if(info.HasBattery) {
nesHeader.Byte6 |= 0x02;
}
if(info.Mirroring.compare("v") == 0) {
nesHeader.Byte6 |= 0x01;
}
nesHeader.Byte7 = (info.MapperID & 0xF0);
GameSystem system = GetGameSystem(info.System);
if(system == GameSystem::Playchoice) {
nesHeader.Byte7 |= 0x02;
} else if(system == GameSystem::VsUniSystem) {
nesHeader.Byte7 |= 0x01;
}
//Don't set this, otherwise the header will be used over the game DB data
//nesHeader.Byte7 |= 0x08; //NES 2.0 marker
nesHeader.Byte8 = ((GetSubMapper(info) & 0x0F) << 4) | ((info.MapperID & 0xF00) >> 8);
nesHeader.Byte10 = 0;
if(info.SaveRamSize > 0) {
nesHeader.Byte10 |= ((int)log2(info.SaveRamSize * 1024) - 6) << 4;
}
if(info.WorkRamSize > 0) {
nesHeader.Byte10 |= ((int)log2(info.WorkRamSize * 1024) - 6);
}
nesHeader.Byte11 = 0;
if(info.ChrRamSize > 0) {
nesHeader.Byte11 |= ((int)log2(info.ChrRamSize * 1024) - 6);
}
nesHeader.Byte12 = system == GameSystem::NesPal ? 0x01 : 0;
nesHeader.Byte13 = 0; //VS PPU variant
return true;
}
return false;
}
void GameDatabase::SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRomData)
{
GameInfo info = {};

View file

@ -20,4 +20,5 @@ private:
public:
static void InitializeInputDevices(string inputType, GameSystem system);
static void SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRomData);
static bool GetiNesHeader(uint32_t romCrc, NESHeader &nesHeader);
};

View file

@ -69,16 +69,6 @@ struct NESHeader
}
}
uint32_t GetPrgCount()
{
if(PrgCount == 0) {
//0 prg banks is a special value meaning 256 banks
return 256;
} else {
return PrgCount;
}
}
bool HasBattery()
{
return (Byte6 & 0x02) == 0x02;
@ -130,9 +120,13 @@ struct NESHeader
uint32_t GetPrgSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
return (((Byte9 & 0x0F) << 4) | GetPrgCount()) * 0x4000;
return (((Byte9 & 0x0F) << 4) | PrgCount) * 0x4000;
} else {
return GetPrgCount() * 0x4000;
if(PrgCount == 0) {
return 256 * 0x4000; //0 is a special value and means 256
} else {
return PrgCount * 0x4000;
}
}
}
@ -205,16 +199,18 @@ struct NESHeader
void SanitizeHeader(size_t romLength)
{
size_t calculatedLength = sizeof(NESHeader) + 0x4000 * GetPrgCount();
size_t calculatedLength = sizeof(NESHeader) + GetPrgSize();
while(calculatedLength > romLength) {
Byte9 = 0;
PrgCount--;
calculatedLength = sizeof(NESHeader) + 0x4000 * GetPrgCount();
calculatedLength = sizeof(NESHeader) + GetPrgSize();
}
calculatedLength = sizeof(NESHeader) + 0x4000 * GetPrgCount() + 0x2000 * ChrCount;
calculatedLength = sizeof(NESHeader) + GetPrgSize() + GetChrSize();
while(calculatedLength > romLength) {
Byte9 = 0;
ChrCount--;
calculatedLength = sizeof(NESHeader) + 0x4000 * GetPrgCount() + 0x2000 * ChrCount;
calculatedLength = sizeof(NESHeader) + GetPrgSize() + GetChrSize();
}
}
};
@ -252,7 +248,7 @@ struct GameInfo
string Board;
string Pcb;
string Chip;
uint8_t MapperID;
uint16_t MapperID;
uint32_t PrgRomSize;
uint32_t ChrRomSize;
uint32_t ChrRamSize;

View file

@ -113,7 +113,7 @@ bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName)
if(memcmp(buffer, "NES\x1a", 4) == 0) {
iNesLoader loader;
_romData = loader.LoadRom(fileData);
_romData = loader.LoadRom(fileData, nullptr);
} else if(memcmp(buffer, "FDS\x1a", 4) == 0 || memcmp(buffer, "\x1*NINTENDO-HVC*", 15) == 0) {
FdsLoader loader;
_romData = loader.LoadRom(fileData, _filename);
@ -127,8 +127,14 @@ bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName)
UnifLoader loader;
_romData = loader.LoadRom(fileData);
} else {
MessageManager::Log("Invalid rom file.");
_romData.Error = true;
NESHeader header = { };
if(GameDatabase::GetiNesHeader(crc, header)) {
iNesLoader loader;
_romData = loader.LoadRom(fileData, &header);
} else {
MessageManager::Log("Invalid rom file.");
_romData.Error = true;
}
}
_romData.Crc32 = crc;
@ -175,7 +181,7 @@ bool RomLoader::LoadFile(string filename, istream *filestream, string ipsFilenam
} else if(memcmp(header, "7z", 2) == 0) {
SZReader reader;
return LoadFromArchive(*input, reader, archiveFileIndex);
} else if(memcmp(header, "NES\x1a", 4) == 0 || memcmp(header, "NESM\x1a", 5) == 0 || memcmp(header, "NSFE", 4) == 0 || memcmp(header, "FDS\x1a", 4) == 0 || memcmp(header, "\x1*NINTENDO-HVC*", 15) == 0 || memcmp(header, "UNIF", 4) == 0) {
} else {
if(archiveFileIndex > 0) {
return false;
}

View file

@ -4,16 +4,20 @@
#include "GameDatabase.h"
#include "EmulationSettings.h"
RomData iNesLoader::LoadRom(vector<uint8_t>& romFile)
RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader)
{
RomData romData;
uint8_t* buffer = romFile.data();
NESHeader header;
memcpy((char*)&header, buffer, sizeof(NESHeader));
buffer += sizeof(NESHeader);
header.SanitizeHeader(romFile.size());
uint8_t* buffer = romFile.data();
if(preloadedHeader) {
header = *preloadedHeader;
header.SanitizeHeader(romFile.size() + sizeof(NESHeader));
} else {
memcpy((char*)&header, buffer, sizeof(NESHeader));
buffer += sizeof(NESHeader);
header.SanitizeHeader(romFile.size());
}
romData.Format = RomFormat::iNes;

View file

@ -5,5 +5,5 @@
class iNesLoader
{
public:
RomData LoadRom(vector<uint8_t>& romFile);
RomData LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader);
};

View file

@ -4,7 +4,7 @@
#
# Automatically generated database based on Nestopia's DB and NesCartDB
#
# Generated on 22/02/2017 using:
# Generated on 18/03/2017 using:
# -NesCartDB (dated 2016-08-20)
# -Nestopia UE's latest DB (dated 2015-10-22)
#
@ -177,6 +177,7 @@
0DC53188,Famicom,HVC-SGROM,HVC-SGROM-03,MMC1A,1,256,,8,0,0,0,,
0E1683C5,Famicom,TAITO-X1-005,P3-034A,X1-005,80,128,128,,0,0,1,,
0E197A5E,Famicom,,,,0,32,8,,0,0,0,h,
0E76E4C1,Famicom,,,,190,256,128,,0,0,0,,
0E997CF6,Famicom,HVC-SNROM,HVC-SNROM-08,MMC1B2,1,256,,8,0,8,1,,
0EAA7515,Famicom,,,,2,128,,8,0,0,0,v,
0EC6C023,NesNtsc,NES-EKROM,NES-EKROM-01,MMC5,5,256,256,,0,8,1,,