Added more VS System info to DB, support for new NES 2.0 proposals (WIP) + some refactoring

This commit is contained in:
Sour 2018-07-07 14:52:51 -04:00
parent 7c8a54a4f6
commit d72d1f3c6d
59 changed files with 31781 additions and 31779 deletions

View file

@ -14,7 +14,7 @@ class AXROM : public BaseMapper
SelectCHRPage(0, 0);
}
bool HasBusConflicts() override { return _subMapperID == 2; }
bool HasBusConflicts() override { return _romInfo.SubMapperID == 2; }
void WriteRegister(uint16_t addr, uint8_t value) override
{

View file

@ -28,7 +28,7 @@ protected:
if(addr >= 0xC000) {
_prgPage = value & 0x03;
} else if(addr < 0xC000) {
if(_subMapperID == 1) {
if(_romInfo.SubMapperID == 1) {
//"232: 1 Aladdin Deck Enhancer"
//"Aladdin Deck Enhancer variation.Swap the bits of the outer bank number."
//But this seems to match the Pegasus 4-in-1 behavior? Wiki wrong?

View file

@ -13,7 +13,7 @@ protected:
void InitMapper() override
{
if(_subMapperID == 1) {
if(_romInfo.SubMapperID == 1) {
_bf9097Mode = true;
}

View file

@ -22,7 +22,7 @@ protected:
uint16_t RegisterStartAddress() override { return 0x6000; }
uint16_t RegisterEndAddress() override { return 0xFFFF; }
bool AllowRegisterRead() override { return true; }
ConsoleFeatures GetAvailableFeatures() override { return _mapperID == 157 ? (ConsoleFeatures)((int)ConsoleFeatures::BarcodeReader | (int)ConsoleFeatures::DatachBarcodeReader) : ConsoleFeatures::None; }
ConsoleFeatures GetAvailableFeatures() override { return _romInfo.MapperID == 157 ? (ConsoleFeatures)((int)ConsoleFeatures::BarcodeReader | (int)ConsoleFeatures::DatachBarcodeReader) : ConsoleFeatures::None; }
void InitMapper() override
{
@ -33,7 +33,7 @@ protected:
_prgPage = 0;
_prgBankSelect = 0;
if(_mapperID == 157) {
if(_romInfo.MapperID == 157) {
//"Mapper 157 is used for Datach Joint ROM System boards"
_barcodeReader.reset(new DatachBarcodeReader(_console));
_mapperControlDevice = _barcodeReader;
@ -42,7 +42,7 @@ protected:
//Only allow reads from 0x6000 to 0x7FFF
RemoveRegisterRange(0x8000, 0xFFFF, MemoryOperation::Read);
if(_mapperID != 16 || GetPRGPageCount() >= 0x20) {
if(_romInfo.MapperID != 16 || GetPRGPageCount() >= 0x20) {
//"For iNES Mapper 153 (with SRAM), the writeable ports must only be mirrored across $8000-$FFFF."
//"Mappers 157 and 159 do not need to support the FCG-1 and -2 and so should only mirror the ports across $8000-$FFFF."
@ -86,14 +86,14 @@ protected:
switch(addr & 0x000F) {
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
_chrRegs[addr & 0x07] = value;
if(_mapperID == 153 || GetPRGPageCount() >= 0x20) {
if(_romInfo.MapperID == 153 || GetPRGPageCount() >= 0x20) {
_prgBankSelect = 0;
for(int i = 0; i < 8; i++) {
_prgBankSelect |= (_chrRegs[i] & 0x01) << 4;
}
SelectPRGPage(0, _prgPage | _prgBankSelect);
SelectPRGPage(1, 0x0F | _prgBankSelect);
} else if(!HasChrRam() && _mapperID != 157) {
} else if(!HasChrRam() && _romInfo.MapperID != 157) {
SelectCHRPage(addr & 0x07, value);
}
break;

View file

@ -347,7 +347,7 @@ uint8_t BaseMapper::GetPowerOnByte(uint8_t defaultValue)
bool BaseMapper::HasBattery()
{
return _hasBattery;
return _romInfo.HasBattery;
}
void BaseMapper::LoadBattery()
@ -384,7 +384,7 @@ uint32_t BaseMapper::GetCHRPageCount()
string BaseMapper::GetBatteryFilename()
{
return FolderUtilities::CombinePath(FolderUtilities::GetSaveFolder(), FolderUtilities::GetFilename(_romName, false) + ".sav");
return FolderUtilities::CombinePath(FolderUtilities::GetSaveFolder(), FolderUtilities::GetFilename(_romInfo.RomName, false) + ".sav");
}
void BaseMapper::RestoreOriginalPrgRam()
@ -493,17 +493,10 @@ void BaseMapper::StreamState(bool saving)
void BaseMapper::Initialize(RomData &romData)
{
_mapperID = romData.MapperID;
_subMapperID = romData.SubMapperID;
_romInfo = romData.Info;
_databaseInfo = romData.DatabaseInfo;
_romName = romData.RomName;
_romFilename = romData.Filename;
_batteryFilename = GetBatteryFilename();
_hasBattery = romData.HasBattery;
if(romData.SaveRamSize == -1 || ForceSaveRamSize()) {
_saveRamSize = GetSaveRamSize();
} else {
@ -522,10 +515,7 @@ void BaseMapper::Initialize(RomData &romData)
memset(_isWriteRegisterAddr, 0, sizeof(_isWriteRegisterAddr));
AddRegisterRange(RegisterStartAddress(), RegisterEndAddress(), MemoryOperation::Any);
_nesHeader = romData.NesHeader;
_romFormat = romData.Format;
_mirroringType = romData.Mirroring;
_mirroringType = romData.Info.Mirroring;
_prgSize = (uint32_t)romData.PrgRom.size();
_chrRomSize = (uint32_t)romData.ChrRom.size();
@ -541,13 +531,7 @@ void BaseMapper::Initialize(RomData &romData)
_hasChrBattery = romData.SaveChrRamSize > 0 || ForceChrBattery();
_gameSystem = romData.System;
_hashInfo.Crc32Hash = romData.Crc32;
_hashInfo.PrgCrc32Hash = romData.PrgCrc32;
_hashInfo.PrgChrCrc32Hash = romData.PrgChrCrc32;
_hashInfo.Sha1Hash = romData.Sha1;
_hashInfo.PrgChrMd5Hash = romData.PrgChrMd5;
switch(romData.BusConflicts) {
switch(romData.Info.BusConflicts) {
case BusConflictType::Default: _hasBusConflicts = HasBusConflicts(); break;
case BusConflictType::Yes: _hasBusConflicts = true; break;
case BusConflictType::No: _hasBusConflicts = false; break;
@ -590,7 +574,7 @@ void BaseMapper::Initialize(RomData &romData)
//Load battery data if present
LoadBattery();
if(romData.HasTrainer) {
if(romData.Info.HasTrainer) {
if(_workRamSize >= 0x2000) {
memcpy(_workRam + 0x1000, romData.TrainerData.data(), 512);
} else if(_saveRamSize >= 0x2000) {
@ -604,6 +588,8 @@ void BaseMapper::Initialize(RomData &romData)
InitMapper(romData);
ApplyCheats();
_romInfo.HasChrRam = HasChrRam();
}
BaseMapper::~BaseMapper()
@ -643,7 +629,7 @@ void BaseMapper::ApplyCheats()
void BaseMapper::GetMemoryRanges(MemoryRanges &ranges)
{
if(_gameSystem == GameSystem::VsUniSystem || _gameSystem == GameSystem::VsDualSystem) {
if(_romInfo.System == GameSystem::VsSystem) {
ranges.AddHandler(MemoryOperation::Read, 0x6000, 0xFFFF);
ranges.AddHandler(MemoryOperation::Write, 0x6000, 0xFFFF);
} else {
@ -730,17 +716,9 @@ shared_ptr<BaseControlDevice> BaseMapper::GetMapperControlDevice()
return _mapperControlDevice;
}
MapperInfo BaseMapper::GetMapperInfo()
RomInfo BaseMapper::GetRomInfo()
{
return {
_romName,
_romFormat,
_gameSystem,
_mapperID,
_subMapperID,
_hashInfo,
HasChrRam()
};
return _romInfo;
}
MirroringType BaseMapper::GetMirroringType()
@ -859,7 +837,7 @@ void BaseMapper::WriteVRAM(uint16_t addr, uint8_t value)
bool BaseMapper::IsNes20()
{
return _nesHeader.GetRomHeaderVersion() == RomHeaderVersion::Nes2_0;
return _romInfo.NesHeader.GetRomHeaderVersion() == RomHeaderVersion::Nes2_0;
}
//Debugger Helper Functions
@ -1131,11 +1109,6 @@ CartridgeState BaseMapper::GetState()
return state;
}
NESHeader BaseMapper::GetNesHeader()
{
return _nesHeader;
}
void BaseMapper::GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* header)
{
if(header) {
@ -1147,7 +1120,7 @@ void BaseMapper::GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* h
out.insert(out.end(), originalFile.begin()+sizeof(NESHeader), originalFile.end());
} else {
vector<uint8_t> newFile;
newFile.insert(newFile.end(), (uint8_t*)&_nesHeader, ((uint8_t*)&_nesHeader) + sizeof(NESHeader));
newFile.insert(newFile.end(), (uint8_t*)&_romInfo.NesHeader, ((uint8_t*)&_romInfo.NesHeader) + sizeof(NESHeader));
newFile.insert(newFile.end(), _prgRom, _prgRom + _prgSize);
if(HasChrRom()) {
newFile.insert(newFile.end(), _chrRom, _chrRom + _chrRomSize);

View file

@ -31,10 +31,6 @@ private:
bool _onlyChrRam = false;
bool _hasBusConflicts = false;
string _romFilename;
string _romName;
RomFormat _romFormat;
bool _allowRegisterRead = false;
bool _isReadRegisterAddr[0x10000];
bool _isWriteRegisterAddr[0x10000];
@ -47,22 +43,15 @@ private:
uint32_t _prgPageNumbers[64];
uint32_t _chrPageNumbers[64];
HashInfo _hashInfo;
vector<uint8_t> _originalPrgRom;
vector<uint8_t> _originalChrRom;
protected:
RomInfo _romInfo;
shared_ptr<BaseControlDevice> _mapperControlDevice;
shared_ptr<Console> _console;
NESHeader _nesHeader;
GameInfo _databaseInfo;
uint16_t _mapperID;
uint8_t _subMapperID;
GameSystem _gameSystem;
uint8_t* _prgRom = nullptr;
uint8_t* _chrRom = nullptr;
uint8_t* _chrRam = nullptr;
@ -74,7 +63,6 @@ protected:
uint32_t _saveRamSize = 0;
uint32_t _workRamSize = 0;
uint8_t* _workRam = nullptr;
bool _hasBattery = false;
bool _hasChrBattery = false;
int16_t _vramOpenBusValue = -1;
@ -175,7 +163,7 @@ public:
virtual void SetDefaultNametables(uint8_t* nametableA, uint8_t* nametableB);
shared_ptr<BaseControlDevice> GetMapperControlDevice();
MapperInfo GetMapperInfo();
RomInfo GetRomInfo();
__forceinline uint8_t ReadRAM(uint16_t addr) override;
uint8_t DebugReadRAM(uint16_t addr);
@ -229,7 +217,6 @@ public:
bool IsWriteRegister(uint16_t addr);
bool IsReadRegister(uint16_t addr);
NESHeader GetNesHeader();
void GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* header);
vector<uint8_t> GetPrgChrCopy();

View file

@ -106,7 +106,7 @@ bool BizhawkMovie::InitializeGameData(ZipReader &reader)
if(line.compare(0, 4, "SHA1", 4) == 0) {
if(line.size() >= 45) {
HashInfo hashInfo;
hashInfo.Sha1Hash = line.substr(5, 40);
hashInfo.Sha1 = line.substr(5, 40);
if(_console->LoadMatchingRom("", hashInfo)) {
return true;
}
@ -114,8 +114,8 @@ bool BizhawkMovie::InitializeGameData(ZipReader &reader)
} else if(line.compare(0, 3, "MD5", 3) == 0) {
if(line.size() >= 36) {
HashInfo hashInfo;
hashInfo.PrgChrMd5Hash = line.substr(4, 32);
std::transform(hashInfo.PrgChrMd5Hash.begin(), hashInfo.PrgChrMd5Hash.end(), hashInfo.PrgChrMd5Hash.begin(), ::toupper);
hashInfo.PrgChrMd5 = line.substr(4, 32);
std::transform(hashInfo.PrgChrMd5.begin(), hashInfo.PrgChrMd5.end(), hashInfo.PrgChrMd5.begin(), ::toupper);
if(_console->LoadMatchingRom("", hashInfo)) {
return true;
}

View file

@ -20,14 +20,14 @@ protected:
_vramOpenBusValue = 0xFF;
}
bool HasBusConflicts() override { return (_mapperID == 3 && _subMapperID == 2) || _mapperID == 185; }
bool HasBusConflicts() override { return (_romInfo.MapperID == 3 && _romInfo.SubMapperID == 2) || _romInfo.MapperID == 185; }
void WriteRegister(uint16_t addr, uint8_t value) override
{
if(_enableCopyProtection) {
//"if C AND $0F is nonzero, and if C does not equal $13: CHR is enabled"
//Seicross (mapper 185 version) is assigned to submapper 16 (not a real submapper) to make it work properly
if((_subMapperID == 16 && !(value & 0x01)) || (_subMapperID == 0 && (value & 0x0F) != 0 && value != 0x13)) {
if((_romInfo.SubMapperID == 16 && !(value & 0x01)) || (_romInfo.SubMapperID == 0 && (value & 0x0F) != 0 && value != 0x13)) {
SelectCHRPage(0, 0);
} else {
RemovePpuMemoryMapping(0x0000, 0x1FFF);

View file

@ -17,7 +17,7 @@ class ColorDreams : public BaseMapper
void WriteRegister(uint16_t addr, uint8_t value) override
{
if(_mapperID == 144) {
if(_romInfo.MapperID == 144) {
//"This addition means that only the ROM's least significant bit always wins bus conflicts."
value |= (ReadRAM(addr) & 0x01);
}

View file

@ -162,8 +162,8 @@ bool Console::LoadMatchingRom(string romName, HashInfo hashInfo)
if(_initialized) {
string currentRomFilepath = GetRomPath().GetFilePath();
if(!currentRomFilepath.empty()) {
HashInfo gameHashInfo = GetMapperInfo().Hash;
if(gameHashInfo.Crc32Hash == hashInfo.Crc32Hash || gameHashInfo.Sha1Hash.compare(hashInfo.Sha1Hash) == 0 || gameHashInfo.PrgChrMd5Hash.compare(hashInfo.PrgChrMd5Hash) == 0) {
HashInfo gameHashInfo = GetRomInfo().Hash;
if(gameHashInfo.Crc32 == hashInfo.Crc32 || gameHashInfo.Sha1.compare(hashInfo.Sha1) == 0 || gameHashInfo.PrgChrMd5.compare(hashInfo.PrgChrMd5) == 0) {
//Current game matches, power cycle game and return
PowerCycle();
return true;
@ -183,8 +183,8 @@ string Console::FindMatchingRom(string romName, HashInfo hashInfo)
if(_initialized) {
VirtualFile currentRom = GetRomPath();
if(currentRom.IsValid() && !GetPatchFile().IsValid()) {
HashInfo gameHashInfo = GetMapperInfo().Hash;
if(gameHashInfo.Crc32Hash == hashInfo.Crc32Hash || gameHashInfo.Sha1Hash.compare(hashInfo.Sha1Hash) == 0 || gameHashInfo.PrgChrMd5Hash.compare(hashInfo.PrgChrMd5Hash) == 0) {
HashInfo gameHashInfo = GetRomInfo().Hash;
if(gameHashInfo.Crc32 == hashInfo.Crc32 || gameHashInfo.Sha1.compare(hashInfo.Sha1) == 0 || gameHashInfo.PrgChrMd5.compare(hashInfo.PrgChrMd5) == 0) {
//Current game matches
return currentRom;
}
@ -258,7 +258,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
if(_mapper) {
if(isDifferentGame) {
//Save current game state before loading another one
_saveStateManager->SaveRecentGame(GetMapperInfo().RomName, _romFilepath, _patchFilename);
_saveStateManager->SaveRecentGame(GetRomInfo().RomName, _romFilepath, _patchFilename);
}
//Send notification only if a game was already running and we successfully loaded the new one
@ -285,22 +285,20 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
_slave.reset();
}
if(!_master && _mapper->GetMapperInfo().System == GameSystem::VsDualSystem) {
RomInfo romInfo = _mapper->GetRomInfo();
if(!_master && romInfo.VsSystemType == VsSystemType::VsDualSystem) {
_slave.reset(new Console(shared_from_this()));
_slave->Init();
_slave->Initialize(romFile, patchFile);
}
GameSystem system = _mapper->GetMapperInfo().System;
switch(system) {
switch(romInfo.System) {
case GameSystem::FDS:
EmulationSettings::SetPpuModel(PpuModel::Ppu2C02);
_systemActionManager.reset(new FdsSystemActionManager(shared_from_this(), _mapper));
break;
case GameSystem::VsUniSystem:
case GameSystem::VsDualSystem:
case GameSystem::VsSystem:
_systemActionManager.reset(new VsSystemActionManager(shared_from_this()));
break;
@ -318,7 +316,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
pollCounter = _controlManager->GetPollCounter();
}
if(system == GameSystem::VsUniSystem || system == GameSystem::VsDualSystem) {
if(romInfo.System == GameSystem::VsSystem) {
_controlManager.reset(new VsControlManager(shared_from_this(), _systemActionManager, _mapper->GetMapperControlDevice()));
} else {
_controlManager.reset(new ControlManager(shared_from_this(), _systemActionManager, _mapper->GetMapperControlDevice()));
@ -380,7 +378,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
if(IsMaster()) {
string modelName = _model == NesModel::PAL ? "PAL" : (_model == NesModel::Dendy ? "Dendy" : "NTSC");
string messageTitle = MessageManager::Localize("GameLoaded") + " (" + modelName + ")";
MessageManager::DisplayMessage(messageTitle, FolderUtilities::GetFilename(GetMapperInfo().RomName, false));
MessageManager::DisplayMessage(messageTitle, FolderUtilities::GetFilename(GetRomInfo().RomName, false));
if(EmulationSettings::GetOverclockRate() != 100) {
MessageManager::DisplayMessage("ClockRate", std::to_string(EmulationSettings::GetOverclockRate()) + "%");
}
@ -396,7 +394,7 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile)
}
//Reset battery source to current game if new game failed to load
BatteryManager::Initialize(FolderUtilities::GetFilename(GetMapperInfo().RomName, false));
BatteryManager::Initialize(FolderUtilities::GetFilename(GetRomInfo().RomName, false));
if(_mapper) {
_videoDecoder->StartThread();
}
@ -491,9 +489,9 @@ VirtualFile Console::GetPatchFile()
return (VirtualFile)_patchFilename;
}
MapperInfo Console::GetMapperInfo()
RomInfo Console::GetRomInfo()
{
return _mapper ? _mapper->GetMapperInfo() : (MapperInfo {});
return _mapper ? _mapper->GetRomInfo() : (RomInfo {});
}
uint32_t Console::GetFrameCount()
@ -799,7 +797,7 @@ void Console::Run()
_notificationManager->SendNotification(ConsoleNotificationType::BeforeEmulationStop);
if(!crashed) {
_saveStateManager->SaveRecentGame(GetMapperInfo().RomName, _romFilepath, _patchFilename);
_saveStateManager->SaveRecentGame(GetRomInfo().RomName, _romFilepath, _patchFilename);
}
_videoDecoder->StopThread();
@ -865,7 +863,7 @@ void Console::UpdateNesModel(bool sendNotification)
NesModel model = EmulationSettings::GetNesModel();
if(model == NesModel::Auto) {
switch(_mapper->GetMapperInfo().System) {
switch(_mapper->GetRomInfo().System) {
case GameSystem::NesPal: model = NesModel::PAL; break;
case GameSystem::Dendy: model = NesModel::Dendy; break;
default: model = NesModel::NTSC; break;

View file

@ -28,7 +28,7 @@ class Debugger;
struct HdPackData;
struct HashInfo;
struct MapperInfo;
struct RomInfo;
enum class MemoryOperationType;
enum class NesModel;
@ -178,7 +178,7 @@ public:
VirtualFile GetRomPath();
VirtualFile GetPatchFile();
MapperInfo GetMapperInfo();
RomInfo GetRomInfo();
uint32_t GetFrameCount();
NesModel GetModel();

View file

@ -546,6 +546,7 @@
<ClInclude Include="MMC3_224.h" />
<ClInclude Include="MovieRecorder.h" />
<ClInclude Include="AsciiTurboFile.h" />
<ClInclude Include="NESHeader.h" />
<ClInclude Include="NotificationManager.h" />
<ClInclude Include="OpenBusHandler.h" />
<ClInclude Include="RawVideoFilter.h" />
@ -971,6 +972,7 @@
<ClCompile Include="LuaCallHelper.cpp" />
<ClCompile Include="LuaScriptingContext.cpp" />
<ClCompile Include="MovieRecorder.cpp" />
<ClCompile Include="NESHeader.cpp" />
<ClCompile Include="NotificationManager.cpp" />
<ClCompile Include="NsfLoader.cpp" />
<ClCompile Include="NsfPpu.cpp" />

View file

@ -1456,6 +1456,9 @@
<ClInclude Include="NotificationManager.h">
<Filter>Misc</Filter>
</ClInclude>
<ClInclude Include="NESHeader.h">
<Filter>Nes\RomLoader</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -1740,5 +1743,8 @@
<ClCompile Include="FdsLoader.cpp">
<Filter>Nes\RomLoader</Filter>
</ClCompile>
<ClCompile Include="NESHeader.cpp">
<Filter>Nes\RomLoader</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -38,7 +38,7 @@ string Debugger::_disassemblerOutput = "";
Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<PPU> ppu, shared_ptr<APU> apu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper)
{
_romName = console->GetMapperInfo().RomName;
_romName = console->GetRomInfo().RomName;
_console = console;
_cpu = cpu;
_ppu = ppu;
@ -1159,7 +1159,7 @@ void Debugger::StopCodeRunner()
void Debugger::GetNesHeader(uint8_t* header)
{
NESHeader nesHeader = _mapper->GetNesHeader();
NESHeader nesHeader = _mapper->GetRomInfo().NesHeader;
memcpy(header, &nesHeader, sizeof(NESHeader));
}

View file

@ -288,22 +288,6 @@ enum class ExpansionPortDevice
BattleBox = 17,
};
extern const vector<string> PpuModelNames;
enum class PpuModel
{
Ppu2C02 = 0,
Ppu2C03 = 1,
Ppu2C04A = 2,
Ppu2C04B = 3,
Ppu2C04C = 4,
Ppu2C04D = 5,
Ppu2C05A = 6,
Ppu2C05B = 7,
Ppu2C05C = 8,
Ppu2C05D = 9,
Ppu2C05E = 10
};
enum class VsInputType
{
Default = 0,

View file

@ -23,7 +23,7 @@ void FDS::InitMapper()
void FDS::InitMapper(RomData &romData)
{
_audio.reset(new FdsAudio(_console));
_romFilepath = romData.Filename;
_romFilepath = romData.Info.Filename;
_fdsDiskSides = romData.FdsDiskData;
_fdsDiskHeaders = romData.FdsDiskHeaders;
_fdsRawData = romData.RawData;

View file

@ -25,7 +25,7 @@ bool FceuxMovie::InitializeData(stringstream &filestream)
if(line.compare(0, 19, "romChecksum base64:", 19) == 0) {
vector<uint8_t> md5array = Base64::Decode(line.substr(19, line.size() - 20));
HashInfo hashInfo;
hashInfo.PrgChrMd5Hash = HexUtilities::ToHex(md5array);
hashInfo.PrgChrMd5 = HexUtilities::ToHex(md5array);
EmulationSettings::SetRamPowerOnState(RamPowerOnState::AllZeros);
if(_console->LoadMatchingRom("", hashInfo)) {
result = true;

View file

@ -136,15 +136,15 @@ RomData FdsLoader::LoadRom(vector<uint8_t>& romFile, string filename)
{
RomData romData;
romData.Sha1 = SHA1::GetHash(romFile);
romData.Crc32 = CRC32::GetCRC(romFile.data(), romFile.size());
romData.PrgCrc32 = CRC32::GetCRC(romFile.data(), romFile.size());
romData.Info.Hash.Sha1 = SHA1::GetHash(romFile);
romData.Info.Hash.Crc32 = CRC32::GetCRC(romFile.data(), romFile.size());
romData.Info.Hash.PrgCrc32 = CRC32::GetCRC(romFile.data(), romFile.size());
romData.Format = RomFormat::Fds;
romData.MapperID = MapperFactory::FdsMapperID;
romData.Mirroring = MirroringType::Vertical;
romData.Info.Format = RomFormat::Fds;
romData.Info.MapperID = MapperFactory::FdsMapperID;
romData.Info.Mirroring = MirroringType::Vertical;
romData.PrgRom = LoadBios();
romData.System = GameSystem::FDS;
romData.Info.System = GameSystem::FDS;
if(romData.PrgRom.size() != 0x2000) {
romData.Error = true;

View file

@ -22,7 +22,7 @@ protected:
_irqEnabled = false;
_ffeAltMode = true;
switch(_mapperID) {
switch(_romInfo.MapperID) {
case 6:
AddRegisterRange(0x8000, 0xFFFF, MemoryOperation::Write);
SelectPrgPage2x(0, 0);
@ -92,7 +92,7 @@ protected:
break;
default:
if(_mapperID == 6) {
if(_romInfo.MapperID == 6) {
if(addr >= 0x8000) {
if(HasChrRam() || _ffeAltMode) {
SelectPrgPage2x(0, (value & 0xFC) >> 1);
@ -100,7 +100,7 @@ protected:
}
SelectChrPage8x(0, value << 3);
}
} else if(_mapperID == 8) {
} else if(_romInfo.MapperID == 8) {
if(addr >= 0x8000) {
SelectPrgPage2x(0, (value & 0xF8) >> 2);
SelectChrPage8x(0, (value & 0x07) << 3);

View file

@ -137,7 +137,7 @@ bool GameClientConnection::AttemptLoadGame(string filename, uint32_t crc32Hash)
{
if(filename.size() > 0) {
HashInfo hashInfo;
hashInfo.Crc32Hash = crc32Hash;
hashInfo.Crc32 = crc32Hash;
if(_console->LoadMatchingRom(filename, hashInfo)) {
return true;
} else {

View file

@ -25,24 +25,25 @@ void GameDatabase::LoadGameDb(vector<string> data)
for(string &row : data) {
vector<string> values = StringUtilities::Split(row, ',');
if(values.size() >= 16) {
GameInfo gameInfo {
(uint32_t)std::stoll(values[0], nullptr, 16),
values[1],
values[2],
values[3],
values[4],
(uint16_t)ToInt<uint32_t>(values[5]),
ToInt<uint32_t>(values[6]),
ToInt<uint32_t>(values[7]),
ToInt<uint32_t>(values[8]),
ToInt<uint32_t>(values[9]),
ToInt<uint32_t>(values[10]),
ToInt<uint32_t>(values[11]) == 0 ? false : true,
values[12],
values[13],
values[14],
values[15]
};
GameInfo gameInfo;
gameInfo.Crc = (uint32_t)std::stoll(values[0], nullptr, 16);
gameInfo.System = values[1];
gameInfo.Board = values[2];
gameInfo.Pcb = values[3];
gameInfo.Chip = values[4];
gameInfo.MapperID = (uint16_t)ToInt<uint32_t>(values[5]);
gameInfo.PrgRomSize = ToInt<uint32_t>(values[6]);
gameInfo.ChrRomSize = ToInt<uint32_t>(values[7]);
gameInfo.ChrRamSize = ToInt<uint32_t>(values[8]);
gameInfo.WorkRamSize = ToInt<uint32_t>(values[9]);
gameInfo.SaveRamSize = ToInt<uint32_t>(values[10]);
gameInfo.HasBattery = ToInt<uint32_t>(values[11]) == 0 ? false : true;
gameInfo.Mirroring = values[12];
gameInfo.InputType = values[13];
gameInfo.BusConflicts = values[14];
gameInfo.SubmapperID = values[15];
gameInfo.VsSystemType = values[16];
gameInfo.PpuModel = values[17];
if(gameInfo.MapperID == 65000) {
gameInfo.MapperID = UnifLoader::GetMapperID(gameInfo.Board);
@ -99,10 +100,8 @@ GameSystem GameDatabase::GetGameSystem(string system)
return GameSystem::NesPal;
} else if(system.compare("Famicom") == 0) {
return GameSystem::Famicom;
} else if(system.compare("VsUni") == 0) {
return GameSystem::VsUniSystem;
} else if(system.compare("VsDual") == 0) {
return GameSystem::VsDualSystem;
} else if(system.compare("VsSystem") == 0) {
return GameSystem::VsSystem;
} else if(system.compare("Dendy") == 0) {
return GameSystem::Dendy;
} else if(system.compare("Playchoice") == 0) {
@ -112,6 +111,52 @@ GameSystem GameDatabase::GetGameSystem(string system)
return GameSystem::NesNtsc;
}
VsSystemType GameDatabase::GetVsSystemType(string system)
{
if(system.compare("IceClimber") == 0) {
return VsSystemType::IceClimberProtection;
} else if(system.compare("RaidOnBungelingBay") == 0) {
return VsSystemType::RaidOnBungelingBayProtection;
} else if(system.compare("RbiBaseball") == 0) {
return VsSystemType::RbiBaseballProtection;
} else if(system.compare("SuperXevious") == 0) {
return VsSystemType::SuperXeviousProtection;
} else if(system.compare("TkoBoxing") == 0) {
return VsSystemType::TkoBoxingProtection;
} else if(system.compare("VsDualSystem") == 0) {
return VsSystemType::VsDualSystem;
}
return VsSystemType::Default;
}
PpuModel GameDatabase::GetPpuModel(string model)
{
if(model.compare("RP2C04-0001") == 0) {
return PpuModel::Ppu2C04A;
} else if(model.compare("RP2C04-0002") == 0) {
return PpuModel::Ppu2C04B;
} else if(model.compare("RP2C04-0003") == 0) {
return PpuModel::Ppu2C04C;
} else if(model.compare("RP2C04-0004") == 0) {
return PpuModel::Ppu2C04D;
} else if(model.compare("RC2C05-01") == 0) {
return PpuModel::Ppu2C05A;
} else if(model.compare("RC2C05-02") == 0) {
return PpuModel::Ppu2C05B;
} else if(model.compare("RC2C05-03") == 0) {
return PpuModel::Ppu2C05C;
} else if(model.compare("RC2C05-04") == 0) {
return PpuModel::Ppu2C05D;
} else if(model.compare("RC2C05-05") == 0) {
return PpuModel::Ppu2C05E;
} else if(model.compare("RP2C03B") == 0 || model.compare("RP2C03G") == 0) {
return PpuModel::Ppu2C03;
}
return PpuModel::Ppu2C02;
}
void GameDatabase::InitializeInputDevices(uint32_t romCrc)
{
InitDatabase();
@ -136,7 +181,7 @@ void GameDatabase::InitializeInputDevices(string inputType, GameSystem system, b
}
};
bool isVsSystem = system == GameSystem::VsUniSystem;
bool isVsSystem = system == GameSystem::VsSystem;
bool isFamicom = (system == GameSystem::Famicom || system == GameSystem::FDS || system == GameSystem::Dendy);
if(inputType.compare("Zapper") == 0) {
@ -377,7 +422,7 @@ bool GameDatabase::GetiNesHeader(uint32_t romCrc, NESHeader &nesHeader)
GameSystem system = GetGameSystem(info.System);
if(system == GameSystem::Playchoice) {
nesHeader.Byte7 |= 0x02;
} else if(system == GameSystem::VsUniSystem) {
} else if(system == GameSystem::VsSystem) {
nesHeader.Byte7 |= 0x01;
}
@ -420,7 +465,7 @@ void GameDatabase::SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRom
info = result->second;
if(!forHeaderlessRom && info.Board == "UNK") {
//Boards marked as UNK should only be used for headerless roms (since their data is unverified)
romData.DatabaseInfo = {};
romData.Info.DatabaseInfo = {};
return;
}
@ -433,6 +478,19 @@ void GameDatabase::SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRom
}
MessageManager::Log("[DB] System : " + info.System);
if(GetGameSystem(info.System) == GameSystem::VsSystem) {
string type = "VS-UniSystem";
switch(GetVsSystemType(info.VsSystemType)) {
case VsSystemType::IceClimberProtection: type = "VS-UniSystem (Ice Climbers)"; break;
case VsSystemType::RaidOnBungelingBayProtection: type = "VS-DualSystem (Raid on Bungeling Bay)"; break;
case VsSystemType::RbiBaseballProtection: type = "VS-UniSystem (RBI Baseball)"; break;
case VsSystemType::SuperXeviousProtection: type = "VS-UniSystem (Super Xevious)"; break;
case VsSystemType::TkoBoxingProtection: type = "VS-UniSystem (TKO Boxing)"; break;
case VsSystemType::VsDualSystem: type = "VS-DualSystem"; break;
}
MessageManager::Log("[DB] VS System Type: " + type);
}
if(!info.Board.empty()) {
MessageManager::Log("[DB] Board: " + info.Board);
}
@ -475,28 +533,32 @@ void GameDatabase::SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRom
}
if(EmulationSettings::CheckFlag(EmulationFlags::AutoConfigureInput)) {
InitializeInputDevices(info.InputType, romData.System);
InitializeInputDevices(info.InputType, romData.Info.System);
}
#ifdef _DEBUG
MessageManager::DisplayMessage("DB", "Mapper: " + std::to_string(romData.MapperID) + " Sub: " + std::to_string(romData.SubMapperID) + " System: " + info.System);
MessageManager::DisplayMessage("DB", "Mapper: " + std::to_string(romData.Info.MapperID) + " Sub: " + std::to_string(romData.Info.SubMapperID) + " System: " + info.System);
#endif
} else {
MessageManager::Log("[DB] Game not found in database");
}
#ifdef LIBRETRO
SetVsSystemDefaults(romData.PrgCrc32);
SetVsSystemDefaults(romData.Info.Hash.PrgCrc32);
#endif
romData.DatabaseInfo = info;
romData.Info.DatabaseInfo = info;
}
void GameDatabase::UpdateRomData(GameInfo &info, RomData &romData)
{
romData.MapperID = info.MapperID;
romData.System = GetGameSystem(info.System);
romData.SubMapperID = GetSubMapper(info);
romData.BusConflicts = GetBusConflictType(info.BusConflicts);
romData.Info.MapperID = info.MapperID;
romData.Info.System = GetGameSystem(info.System);
if(romData.Info.System == GameSystem::VsSystem) {
romData.Info.VsSystemType = GetVsSystemType(info.VsSystemType);
romData.Info.PpuModel = GetPpuModel(info.PpuModel);
}
romData.Info.SubMapperID = GetSubMapper(info);
romData.Info.BusConflicts = GetBusConflictType(info.BusConflicts);
if(info.ChrRamSize > 0) {
romData.ChrRamSize = info.ChrRamSize * 1024;
}
@ -506,14 +568,14 @@ void GameDatabase::UpdateRomData(GameInfo &info, RomData &romData)
if(info.SaveRamSize > 0) {
romData.SaveRamSize = info.SaveRamSize * 1024;
}
romData.HasBattery |= info.HasBattery;
romData.Info.HasBattery |= info.HasBattery;
if(!info.Mirroring.empty()) {
switch(info.Mirroring[0]) {
case 'h': romData.Mirroring = MirroringType::Horizontal; break;
case 'v': romData.Mirroring = MirroringType::Vertical; break;
case '4': romData.Mirroring = MirroringType::FourScreens; break;
case 'a': romData.Mirroring = MirroringType::ScreenAOnly; break;
case 'h': romData.Info.Mirroring = MirroringType::Horizontal; break;
case 'v': romData.Info.Mirroring = MirroringType::Vertical; break;
case '4': romData.Info.Mirroring = MirroringType::FourScreens; break;
case 'a': romData.Info.Mirroring = MirroringType::ScreenAOnly; break;
}
}
}
@ -526,44 +588,11 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
uint8_t defaultDip = 0;
switch(prgCrc32) {
case 0xEB2DBA63: case 0x98CFE016:
//TKOBoxing
model = PpuModel::Ppu2C04C;
break;
case 0x135ADF7C:
//RBIBaseball
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C04A;
break;
case 0xED588F00:
//"DuckHunt", use defaults
model = PpuModel::Ppu2C03;
break;
case 0x16D3F469:
//NinjaJajamaruKun
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C05A;
break;
case 0x8850924B:
//Tetris
model = PpuModel::Ppu2C03;
inputType = VsInputType::SwapControllers;
defaultDip = 32;
defaultDip = 32; //????
break;
case 0x8C0C2DF5:
//TopGun
model = PpuModel::Ppu2C05D;
break;
case 0x70901B25:
//Slalom
model = PpuModel::Ppu2C04B;
break;
case 0xCF36261E:
//SuperSkyKid
@ -573,40 +602,7 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
case 0xE1AA8214:
//StarLuster
model = PpuModel::Ppu2C04A;
defaultDip = 32;
break;
case 0xD5D7EAC4:
//DrMario
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C04C;
break;
case 0xFFBEF374:
//Castlevania
model = PpuModel::Ppu2C04B;
break;
case 0xE2C0A2BE:
//Platoon
model = PpuModel::Ppu2C04A;
break;
case 0x29155E0C:
//ExciteBike
model = PpuModel::Ppu2C04D;
break;
case 0xCBE85490:
//ExciteBikeB
model = PpuModel::Ppu2C04C;
break;
case 0x07138C06:
//Clu Clu Land
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C04D;
defaultDip = 32; //????
break;
case 0x43A357EF:
@ -621,65 +617,21 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
model = PpuModel::Ppu2C04D;
break;
case 0x737DD1BF: case 0x4BF3972D: case 0x8B60CC58: case 0x8192C804:
case 0x737DD1BF: case 0x4BF3972D:
//SuperMarioBros
model = PpuModel::Ppu2C04D;
break;
case 0xE528F651:
//Pinball
inputType = VsInputType::SwapAB;
model = PpuModel::Ppu2C03;
break;
case 0xEC461DB9:
//PinballB
model = PpuModel::Ppu2C04A;
break;
case 0xAE8063EF:
//MachRiderFightingCourse, defaults
model = PpuModel::Ppu2C03;
break;
case 0x0B65A917: case 0x8A6A9848:
case 0x8A6A9848: //1 crc left
//MachRider
model = PpuModel::Ppu2C04B;
break;
case 0x46914E3E:
//Soccer
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C04C;
break;
case 0x70433F2C:
//Battle City
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C04A;
break;
case 0xD99A2087:
//Gradius
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C04A;
break;
case 0x1E438D52:
//Goonies
model = PpuModel::Ppu2C04C;
break;
case 0xFF5135A3:
//HoganAlley
model = PpuModel::Ppu2C04A;
break;
case 0x17AE56BE:
//FreedomForce
model = PpuModel::Ppu2C04A;
break;
case 0xC99EC059:
//RaidBungelingBay
inputType = VsInputType::SwapControllers;
@ -690,28 +642,6 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
//SuperXevious
model = PpuModel::Ppu2C04A;
break;
case 0xA93A5AEE:
//Golf
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C03;
break;
case 0xCC2C4B5D: case 0x86167220:
//GolfB
inputType = VsInputType::SwapControllers;
model = PpuModel::Ppu2C04B;
break;
case 0xCA85E56D:
//MightyBombJack
model = PpuModel::Ppu2C05B;
break;
case 0xFE446787:
//Gumshoe
model = PpuModel::Ppu2C05C;
break;
}
EmulationSettings::SetPpuModel(model);

View file

@ -12,6 +12,8 @@ private:
static BusConflictType GetBusConflictType(string busConflictSetting);
static GameSystem GetGameSystem(string system);
static VsSystemType GetVsSystemType(string system);
static PpuModel GetPpuModel(string model);
static uint8_t GetSubMapper(GameInfo &info);
static void InitDatabase();

View file

@ -58,8 +58,8 @@ void GameServerConnection::SendServerInformation()
void GameServerConnection::SendGameInformation()
{
_console->Pause();
MapperInfo mapperInfo = _console->GetMapperInfo();
GameInformationMessage gameInfo(mapperInfo.RomName, mapperInfo.Hash.Crc32Hash, _controllerPort, EmulationSettings::CheckFlag(EmulationFlags::Paused));
RomInfo romInfo = _console->GetRomInfo();
GameInformationMessage gameInfo(romInfo.RomName, romInfo.Hash.Crc32, _controllerPort, EmulationSettings::CheckFlag(EmulationFlags::Paused));
SendNetMessage(gameInfo);
SaveStateMessage saveState(_console);
SendNetMessage(saveState);
@ -117,7 +117,7 @@ void GameServerConnection::ProcessHandshakeResponse(HandShakeMessage* message)
MessageManager::DisplayMessage("NetPlay", _playerName + " (" + playerPortMessage + ") connected.");
if(_console->GetMapperInfo().RomName.size() > 0) {
if(_console->GetRomInfo().RomName.size() > 0) {
SendGameInformation();
}

View file

@ -40,7 +40,7 @@ HdPackBuilder::HdPackBuilder(shared_ptr<Console> console, string saveFolder, Sca
_hdData.Scale = scale;
}
_romName = FolderUtilities::GetFilename(_console->GetMapperInfo().RomName, false);
_romName = FolderUtilities::GetFilename(_console->GetRomInfo().RomName, false);
_instance = this;
}
@ -222,7 +222,7 @@ void HdPackBuilder::SaveHdPack()
int pngIndex = 0;
ss << "<ver>" << std::to_string(HdNesPack::CurrentVersion) << std::endl;
ss << "<scale>" << _hdData.Scale << std::endl;
ss << "<supportedRom>" << _console->GetMapperInfo().Hash.Sha1Hash << std::endl;
ss << "<supportedRom>" << _console->GetRomInfo().Hash.Sha1 << std::endl;
if(_flags & HdPackRecordFlags::IgnoreOverscan) {
OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
ss << "<overscan>" << overscan.Top << "," << overscan.Right << "," << overscan.Bottom << "," << overscan.Left << std::endl;

View file

@ -19,7 +19,7 @@ class IremG101 : public BaseMapper
SelectPRGPage(2, -2);
SelectPRGPage(3, -1);
if(_subMapperID == 1) {
if(_romInfo.SubMapperID == 1) {
//032: 1 Major League
//CIRAM A10 is tied high (fixed one-screen mirroring) and PRG banking style is fixed as 8+8+16F
SetMirroringType(MirroringType::ScreenAOnly);
@ -57,7 +57,7 @@ class IremG101 : public BaseMapper
break;
case 0x9000:
_prgMode = (value & 0x02) >> 1;
if(_subMapperID == 1) {
if(_romInfo.SubMapperID == 1) {
_prgMode = 0;
}
UpdatePrgMode();

View file

@ -21,7 +21,7 @@ protected:
{
SelectPRGPage(0, value & 0x07);
SelectCHRPage(0, (value >> 4) & 0x0F);
if(_subMapperID == 3) {
if(_romInfo.SubMapperID == 3) {
//078: 3 Holy Diver
SetMirroringType(value & 0x08 ? MirroringType::Vertical : MirroringType::Horizontal);
} else {

View file

@ -231,7 +231,7 @@ protected:
void UpdateMirroringState()
{
//"Mapper 211 behaves as though N were always set (1), and mapper 090 behaves as though N were always clear(0)."
if((_advancedNtControl || _mapperID == 211) && _mapperID != 90) {
if((_advancedNtControl || _romInfo.MapperID == 211) && _romInfo.MapperID != 90) {
for(int i = 0; i < 4; i++) {
SetNametable(i, _ntLowRegs[i] & 0x01);
}
@ -356,7 +356,7 @@ protected:
if(addr >= 0x2000) {
//This behavior only affects reads, not writes.
//Additional info: https://forums.nesdev.com/viewtopic.php?f=3&t=17198
if((_advancedNtControl || _mapperID == 211) && _mapperID != 90) {
if((_advancedNtControl || _romInfo.MapperID == 211) && _romInfo.MapperID != 90) {
uint8_t ntIndex = ((addr & 0x2FFF) - 0x2000) / 0x400;
if(_disableNtRam || (_ntLowRegs[ntIndex] & 0x80) != (_ntRamSelectBit & 0x80)) {
uint16_t chrPage = _ntLowRegs[ntIndex] | (_ntHighRegs[ntIndex] << 8);
@ -380,7 +380,7 @@ protected:
}
_lastPpuAddr = addr;
if(_mapperID == 209) {
if(_romInfo.MapperID == 209) {
switch(addr & 0x2FF8) {
case 0x0FD8:
case 0x0FE8:

View file

@ -20,6 +20,7 @@
#include "CheatManager.h"
#include "KeyManager.h"
#include "MemoryAccessCounter.h"
#include "RomData.h"
#define lua_pushintvalue(name, value) lua_pushliteral(lua, #name); lua_pushinteger(lua, (int)value); lua_settable(lua, -3);
#define lua_pushdoublevalue(name, value) lua_pushliteral(lua, #name); lua_pushnumber(lua, (double)value); lua_settable(lua, -3);
@ -759,20 +760,19 @@ int LuaApi::GetRomInfo(lua_State *lua)
LuaCallHelper l(lua);
checkparams();
MapperInfo mapperInfo = _console->GetMapperInfo();
RomInfo romInfo = _console->GetRomInfo();
string romPath = _console->GetRomPath();
lua_newtable(lua);
lua_pushstringvalue(name, mapperInfo.RomName);
lua_pushstringvalue(name, romInfo.RomName);
lua_pushstringvalue(path, romPath);
HashInfo hashInfo = mapperInfo.Hash;
lua_pushintvalue(fileCrc32Hash, hashInfo.Crc32Hash);
lua_pushstringvalue(fileSha1Hash, hashInfo.Sha1Hash);
lua_pushintvalue(prgChrCrc32Hash, hashInfo.PrgCrc32Hash);
lua_pushstringvalue(prgChrMd5Hash, hashInfo.PrgChrMd5Hash);
lua_pushintvalue(format, mapperInfo.Format);
lua_pushboolvalue(isChrRam, mapperInfo.UsesChrRam);
lua_pushintvalue(fileCrc32Hash, romInfo.Hash.Crc32);
lua_pushstringvalue(fileSha1Hash, romInfo.Hash.Sha1);
lua_pushintvalue(prgChrCrc32Hash, romInfo.Hash.PrgCrc32);
lua_pushstringvalue(prgChrMd5Hash, romInfo.Hash.PrgChrMd5);
lua_pushintvalue(format, romInfo.Format);
lua_pushboolvalue(isChrRam, romInfo.HasChrRam);
return 1;
}

View file

@ -138,7 +138,7 @@ class MMC1 : public BaseMapper
}
}
if(_subMapperID == 5) {
if(_romInfo.SubMapperID == 5) {
//SubMapper 5
//"001: 5 Fixed PRG SEROM, SHROM, SH1ROM use a fixed 32k PRG ROM with no banking support.
SelectPrgPage2x(0, 0);
@ -182,10 +182,10 @@ class MMC1 : public BaseMapper
_state.Reg8000 = GetPowerOnByte() | 0x0C; //On powerup: bits 2,3 of $8000 are set (this ensures the $8000 is bank 0, and $C000 is the last bank - needed for SEROM/SHROM/SH1ROM which do no support banking)
_state.RegA000 = GetPowerOnByte();
_state.RegC000 = GetPowerOnByte();
_state.RegE000 = (_databaseInfo.Board.find("MMC1B") != string::npos ? 0x10 : 0x00); //WRAM Disable: enabled by default for MMC1B
_state.RegE000 = (_romInfo.DatabaseInfo.Board.find("MMC1B") != string::npos ? 0x10 : 0x00); //WRAM Disable: enabled by default for MMC1B
//"MMC1A: PRG RAM is always enabled" - Normally these roms should be classified as mapper 155
_forceWramOn = (_databaseInfo.Board.compare("MMC1A") == 0);
_forceWramOn = (_romInfo.DatabaseInfo.Board.compare("MMC1A") == 0);
_lastChrReg = MMC1Registers::RegA000;

View file

@ -39,7 +39,7 @@ class MMC3 : public BaseMapper
bool IsMcAcc()
{
return _mapperID == 4 && _subMapperID == 3;
return _romInfo.MapperID == 4 && _romInfo.SubMapperID == 3;
}
protected:
@ -157,7 +157,7 @@ class MMC3 : public BaseMapper
_chrMode = (_state.Reg8000 & 0x80) >> 7;
_prgMode = (_state.Reg8000 & 0x40) >> 6;
if(_subMapperID == 1) {
if(_romInfo.SubMapperID == 1) {
//bool wramEnabled = (_state.Reg8000 & 0x20) == 0x20;
RemoveCpuMemoryMapping(0x6000, 0x7000);
@ -172,7 +172,7 @@ class MMC3 : public BaseMapper
_wramEnabled = (_state.RegA001 & 0x80) == 0x80;
_wramWriteProtected = (_state.RegA001 & 0x40) == 0x40;
if(IsNes20() && _subMapperID == 0) {
if(IsNes20() && _romInfo.SubMapperID == 0) {
if(_wramEnabled) {
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam, CanWriteToWorkRam() ? MemoryAccessType::ReadWrite : MemoryAccessType::Read);
} else {
@ -202,14 +202,14 @@ class MMC3 : public BaseMapper
virtual uint16_t GetPRGPageSize() override { return 0x2000; }
virtual uint16_t GetCHRPageSize() override { return 0x0400; }
virtual uint32_t GetSaveRamPageSize() override { return _subMapperID == 1 ? 0x200 : 0x2000; }
virtual uint32_t GetSaveRamSize() override { return _subMapperID == 1 ? 0x400 : 0x2000; }
virtual uint32_t GetSaveRamPageSize() override { return _romInfo.SubMapperID == 1 ? 0x200 : 0x2000; }
virtual uint32_t GetSaveRamSize() override { return _romInfo.SubMapperID == 1 ? 0x400 : 0x2000; }
virtual void InitMapper() override
{
//Force MMC3A irqs for boards that are known to use the A revision.
//Some MMC3B boards also have the A behavior, but currently no way to tell them apart.
_forceMmc3RevAIrqs = _databaseInfo.Chip.substr(0, 5).compare("MMC3A") == 0;
_forceMmc3RevAIrqs = _romInfo.DatabaseInfo.Chip.substr(0, 5).compare("MMC3A") == 0;
ResetMmc3();
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam);

View file

@ -284,7 +284,7 @@ protected:
{
_audio.reset(new MMC5Audio(_console));
_hasBattery = true;
_romInfo.HasBattery = true;
_chrMode = 0;
_prgRamProtect1 = 0;

View file

@ -12,7 +12,7 @@ protected:
SelectPRGPage(0, 0);
if(GetMirroringType() == MirroringType::FourScreens) {
SetMirroringType(_nesHeader.Byte6 & 0x01 ? MirroringType::ScreenBOnly : MirroringType::ScreenAOnly);
SetMirroringType(_romInfo.NesHeader.Byte6 & 0x01 ? MirroringType::ScreenBOnly : MirroringType::ScreenAOnly);
}
}

View file

@ -298,10 +298,10 @@ Supported mappers:
BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
{
#ifdef _DEBUG
MessageManager::DisplayMessage("GameInfo", "Mapper", std::to_string(romData.MapperID), std::to_string(romData.SubMapperID));
MessageManager::DisplayMessage("GameInfo", "Mapper", std::to_string(romData.Info.MapperID), std::to_string(romData.Info.SubMapperID));
#endif
switch(romData.MapperID) {
switch(romData.Info.MapperID) {
case 0: return new NROM();
case 1: return new MMC1();
case 2: return new UNROM();
@ -336,7 +336,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
case 32: return new IremG101();
case 33: return new TaitoTc0190();
case 34:
switch(romData.SubMapperID) {
switch(romData.Info.SubMapperID) {
case 0: return (romData.ChrRom.size() > 0) ? (BaseMapper*)new Nina01() : (BaseMapper*)new BnRom(); //BnROM uses CHR RAM (so no CHR rom in the .NES file)
case 1: return new Nina01();
case 2: return new BnRom();
@ -609,8 +609,8 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
case MapperFactory::FdsMapperID: return new FDS();
}
if(romData.MapperID != UnifBoards::UnknownBoard) {
MessageManager::DisplayMessage("Error", "UnsupportedMapper", "iNES #" + std::to_string(romData.MapperID));
if(romData.Info.MapperID != UnifBoards::UnknownBoard) {
MessageManager::DisplayMessage("Error", "UnsupportedMapper", "iNES #" + std::to_string(romData.Info.MapperID));
}
return nullptr;
}

View file

@ -187,7 +187,7 @@ bool MesenMovie::LoadGame()
}
HashInfo hashInfo;
hashInfo.Sha1Hash = sha1Hash;
hashInfo.Sha1 = sha1Hash;
VirtualFile romFile = _console->FindMatchingRom(gameFile, hashInfo);
bool gameLoaded = false;

View file

@ -10,6 +10,7 @@
#include "VirtualFile.h"
#include "SaveStateManager.h"
#include "NotificationManager.h"
#include "RomData.h"
MovieRecorder::MovieRecorder(shared_ptr<Console> console)
{
@ -77,7 +78,7 @@ void MovieRecorder::GetGameSettings(stringstream &out)
if(patchFile.IsValid()) {
WriteString(out, MovieKeys::PatchFile, patchFile.GetFileName());
WriteString(out, MovieKeys::PatchFileSha1, patchFile.GetSha1Hash());
WriteString(out, MovieKeys::PatchedRomSha1, _console->GetMapperInfo().Hash.Sha1Hash);
WriteString(out, MovieKeys::PatchedRomSha1, _console->GetRomInfo().Hash.Sha1);
}
switch(model) {

228
Core/NESHeader.cpp Normal file
View file

@ -0,0 +1,228 @@
#include "stdafx.h"
#include "NESHeader.h"
#include "RomData.h"
#include "MessageManager.h"
uint16_t NESHeader::GetMapperID()
{
switch(GetRomHeaderVersion()) {
case RomHeaderVersion::Nes2_0:
return ((Byte8 & 0x0F) << 4) | (Byte7 & 0xF0) | (Byte6 >> 4);
default:
case RomHeaderVersion::iNes:
return (Byte7 & 0xF0) | (Byte6 >> 4);
case RomHeaderVersion::OldiNes:
return (Byte6 >> 4);
}
}
bool NESHeader::HasBattery()
{
return (Byte6 & 0x02) == 0x02;
}
bool NESHeader::HasTrainer()
{
return (Byte6 & 0x04) == 0x04;
}
GameSystem NESHeader::GetNesGameSystem()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
switch(Byte12 & 0x03) {
case 0: return GameSystem::NesNtsc;
case 1: return GameSystem::NesPal;
case 2: return GameSystem::NesNtsc; //Game works with both NTSC/PAL, pick NTSC by default
case 3: return GameSystem::Dendy;
}
} else if(GetRomHeaderVersion() == RomHeaderVersion::iNes) {
return (Byte9 & 0x01) ? GameSystem::NesPal : GameSystem::NesNtsc;
}
return GameSystem::NesNtsc;
}
GameSystem NESHeader::GetGameSystem()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
switch(Byte7 & 0x03) {
case 0: return GetNesGameSystem();
case 1: return GameSystem::VsSystem;
case 2: return GameSystem::Playchoice;
case 3:
switch(Byte13) {
case 0: return GetNesGameSystem();
case 1: return GameSystem::VsSystem;
case 2: return GameSystem::Playchoice;
default:
MessageManager::Log("[iNES] Unsupported console type detected (using NES NTSC instead)");
return GameSystem::NesNtsc;
}
break;
}
} else if(GetRomHeaderVersion() == RomHeaderVersion::iNes) {
if(Byte7 & 0x01) {
return GameSystem::VsSystem;
} else if(Byte7 & 0x02) {
return GameSystem::Playchoice;
}
}
return GetNesGameSystem();
}
RomHeaderVersion NESHeader::GetRomHeaderVersion()
{
if((Byte7 & 0x0C) == 0x08) {
return RomHeaderVersion::Nes2_0;
} else if((Byte7 & 0x0C) == 0x00) {
return RomHeaderVersion::iNes;
} else {
return RomHeaderVersion::OldiNes;
}
}
uint32_t NESHeader::GetPrgSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
return (((Byte9 & 0x0F) << 8) | PrgCount) * 0x4000;
} else {
if(PrgCount == 0) {
return 256 * 0x4000; //0 is a special value and means 256
} else {
return PrgCount * 0x4000;
}
}
}
uint32_t NESHeader::GetChrSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
return (((Byte9 & 0xF0) << 4) | ChrCount) * 0x2000;
} else {
return ChrCount * 0x2000;
}
}
uint32_t NESHeader::GetWorkRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = Byte10 & 0x0F;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
uint32_t NESHeader::GetSaveRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = (Byte10 & 0xF0) >> 4;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
int32_t NESHeader::GetChrRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = Byte11 & 0x0F;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
uint32_t NESHeader::GetSaveChrRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = (Byte11 & 0xF0) >> 4;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
uint8_t NESHeader::GetSubMapper()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
return (Byte8 & 0xF0) >> 4;
} else {
return 0;
}
}
MirroringType NESHeader::GetMirroringType()
{
if(Byte6 & 0x08) {
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
if(Byte6 & 0x01) {
//Based on proposal by rainwarrior/Myask: http://wiki.nesdev.com/w/index.php/Talk:NES_2.0
return MirroringType::ScreenAOnly;
} else {
return MirroringType::FourScreens;
}
} else {
return MirroringType::FourScreens;
}
} else {
return Byte6 & 0x01 ? MirroringType::Vertical : MirroringType::Horizontal;
}
}
VsSystemType NESHeader::GetVsSystemType()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
if((Byte13 >> 4) <= 0x06) {
return (VsSystemType)(Byte13 >> 4);
}
MessageManager::Log("[iNES] Unknown VS System Type specified.");
}
return VsSystemType::Default;
}
PpuModel NESHeader::GetVsSystemPpuModel()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
switch(Byte13 & 0x0F) {
case 0: return PpuModel::Ppu2C03;
case 1:
MessageManager::Log("[iNES] Unsupport VS System Palette specified (2C03G).");
return PpuModel::Ppu2C03;
case 2: return PpuModel::Ppu2C04A;
case 3: return PpuModel::Ppu2C04B;
case 4: return PpuModel::Ppu2C04C;
case 5: return PpuModel::Ppu2C04D;
case 6: return PpuModel::Ppu2C03;
case 7: return PpuModel::Ppu2C03;
case 8: return PpuModel::Ppu2C05A;
case 9: return PpuModel::Ppu2C05B;
case 10: return PpuModel::Ppu2C05C;
case 11: return PpuModel::Ppu2C05D;
case 12: return PpuModel::Ppu2C05E;
default:
MessageManager::Log("[iNES] Unknown VS System Palette specified.");
break;
}
}
return PpuModel::Ppu2C03;
}
void NESHeader::SanitizeHeader(size_t romLength)
{
size_t calculatedLength = sizeof(NESHeader) + GetPrgSize();
while(calculatedLength > romLength) {
Byte9 = 0;
PrgCount--;
calculatedLength = sizeof(NESHeader) + GetPrgSize();
}
calculatedLength = sizeof(NESHeader) + GetPrgSize() + GetChrSize();
while(calculatedLength > romLength) {
Byte9 = 0;
ChrCount--;
calculatedLength = sizeof(NESHeader) + GetPrgSize() + GetChrSize();
}
}

49
Core/NESHeader.h Normal file
View file

@ -0,0 +1,49 @@
#pragma once
#include "Types.h"
enum class RomHeaderVersion;
struct NESHeader
{
/*
Thing Archaic iNES NES 2.0
Byte 6 Mapper low nibble, Mirroring, Battery/Trainer flags
Byte 7 Unused Mapper high nibble, Vs. Mapper high nibble, NES 2.0 signature, PlayChoice, Vs.
Byte 8 Unused Total PRG RAM size (linear) Mapper highest nibble, mapper variant
Byte 9 Unused TV system Upper bits of ROM size
Byte 10 Unused Unused PRG RAM size (logarithmic; battery and non-battery)
Byte 11 Unused Unused VRAM size (logarithmic; battery and non-battery)
Byte 12 Unused Unused TV system
Byte 13 Unused Unused Vs. PPU variant
*/
char NES[4];
uint8_t PrgCount;
uint8_t ChrCount;
uint8_t Byte6;
uint8_t Byte7;
uint8_t Byte8;
uint8_t Byte9;
uint8_t Byte10;
uint8_t Byte11;
uint8_t Byte12;
uint8_t Byte13;
uint8_t Reserved[2];
uint16_t GetMapperID();
bool HasBattery();
bool HasTrainer();
GameSystem GetNesGameSystem();
GameSystem GetGameSystem();
RomHeaderVersion GetRomHeaderVersion();
uint32_t GetPrgSize();
uint32_t GetChrSize();
uint32_t GetWorkRamSize();
uint32_t GetSaveRamSize();
int32_t GetChrRamSize();
uint32_t GetSaveChrRamSize();
uint8_t GetSubMapper();
MirroringType GetMirroringType();
VsSystemType GetVsSystemType();
PpuModel GetVsSystemPpuModel();
void SanitizeHeader(size_t romLength);
};

View file

@ -59,16 +59,16 @@ protected:
{
_audio.reset(new Namco163Audio(_console));
switch(_mapperID) {
switch(_romInfo.MapperID) {
case 19:
_variant = NamcoVariant::Namco163;
if(_databaseInfo.Board == "NAMCOT-163") {
if(_romInfo.DatabaseInfo.Board == "NAMCOT-163") {
_variant = NamcoVariant::Namco163;
_autoDetectVariant = false;
} else if(_databaseInfo.Board == "NAMCOT-175") {
} else if(_romInfo.DatabaseInfo.Board == "NAMCOT-175") {
_variant = NamcoVariant::Namco175;
_autoDetectVariant = false;
} else if(_databaseInfo.Board == "NAMCOT-340") {
} else if(_romInfo.DatabaseInfo.Board == "NAMCOT-340") {
_variant = NamcoVariant::Namco340;
_autoDetectVariant = false;
} else {
@ -76,7 +76,7 @@ protected:
}
break;
case 210:
switch(_subMapperID) {
switch(_romInfo.SubMapperID) {
case 0: _variant = NamcoVariant::Unknown; _autoDetectVariant = true; break;
case 1: _variant = NamcoVariant::Namco175; _autoDetectVariant = false; break;
case 2: _variant = NamcoVariant::Namco340; _autoDetectVariant = false; break;

View file

@ -21,19 +21,19 @@ void NsfLoader::Read(uint8_t *& data, char * dest, size_t len)
data += len;
}
void NsfLoader::InitializeFromHeader(RomData & romData)
void NsfLoader::InitializeFromHeader(RomData &romData)
{
NsfHeader &header = romData.NsfInfo;
NsfHeader &header = romData.Info.NsfInfo;
romData.Format = RomFormat::Nsf;
romData.MapperID = MapperFactory::NsfMapperID;
romData.Info.Format = RomFormat::Nsf;
romData.Info.MapperID = MapperFactory::NsfMapperID;
if(header.LoadAddress < 0x6000 || header.TotalSongs == 0) {
romData.Error = true;
}
if(header.Flags == 0x01) {
romData.System = GameSystem::NesPal;
romData.Info.System = GameSystem::NesPal;
}
if(header.PlaySpeedNtsc == 0) {
@ -119,7 +119,7 @@ void NsfLoader::InitHeader(NsfHeader & header)
RomData NsfLoader::LoadRom(vector<uint8_t>& romFile)
{
RomData romData;
NsfHeader &header = romData.NsfInfo;
NsfHeader &header = romData.Info.NsfInfo;
InitHeader(header);

View file

@ -67,7 +67,7 @@ void NsfMapper::SetNesModel(NesModel model)
void NsfMapper::InitMapper(RomData& romData)
{
_nsfHeader = romData.NsfInfo;
_nsfHeader = romData.Info.NsfInfo;
_hasBankSwitching = HasBankSwitching();
if(!_hasBankSwitching) {

View file

@ -83,7 +83,7 @@ private:
return false;
}
NsfHeader& header = romData.NsfInfo;
NsfHeader& header = romData.Info.NsfInfo;
uint32_t length;
Read(data, length);
@ -183,11 +183,11 @@ public:
RomData LoadRom(vector<uint8_t>& romFile)
{
RomData romData;
NsfHeader &header = romData.NsfInfo;
NsfHeader &header = romData.Info.NsfInfo;
InitHeader(header);
romData.Format = RomFormat::Nsf;
romData.Info.Format = RomFormat::Nsf;
uint8_t* data = romFile.data() + 4;
uint8_t* endOfData = romFile.data() + romFile.size();

View file

@ -2,6 +2,7 @@
#include "stdafx.h"
#include <cmath>
#include "Types.h"
#include "NESHeader.h"
enum class RomHeaderVersion
{
@ -10,200 +11,6 @@ enum class RomHeaderVersion
OldiNes = 2
};
struct NESHeader
{
/*
Thing Archaic iNES NES 2.0
Byte 6 Mapper low nibble, Mirroring, Battery/Trainer flags
Byte 7 Unused Mapper high nibble, Vs. Mapper high nibble, NES 2.0 signature, PlayChoice, Vs.
Byte 8 Unused Total PRG RAM size (linear) Mapper highest nibble, mapper variant
Byte 9 Unused TV system Upper bits of ROM size
Byte 10 Unused Unused PRG RAM size (logarithmic; battery and non-battery)
Byte 11 Unused Unused VRAM size (logarithmic; battery and non-battery)
Byte 12 Unused Unused TV system
Byte 13 Unused Unused Vs. PPU variant
*/
char NES[4];
uint8_t PrgCount;
uint8_t ChrCount;
uint8_t Byte6;
uint8_t Byte7;
uint8_t Byte8;
uint8_t Byte9;
uint8_t Byte10;
uint8_t Byte11;
uint8_t Byte12;
uint8_t Byte13;
uint8_t Reserved[2];
uint16_t GetMapperID()
{
switch(GetRomHeaderVersion()) {
case RomHeaderVersion::Nes2_0:
return ((Byte8 & 0x0F) << 4) | (Byte7 & 0xF0) | (Byte6 >> 4);
default:
case RomHeaderVersion::iNes:
return (Byte7 & 0xF0) | (Byte6 >> 4);
case RomHeaderVersion::OldiNes:
return (Byte6 >> 4);
}
}
bool HasBattery()
{
return (Byte6 & 0x02) == 0x02;
}
bool HasTrainer()
{
return (Byte6 & 0x04) == 0x04;
}
bool IsPalRom()
{
switch(GetRomHeaderVersion()) {
case RomHeaderVersion::Nes2_0: return (Byte12 & 0x01) == 0x01;
case RomHeaderVersion::iNes: return (Byte9 & 0x01) == 0x01;
default: return false;
}
}
bool IsPlaychoice()
{
switch(GetRomHeaderVersion()) {
case RomHeaderVersion::Nes2_0:
case RomHeaderVersion::iNes: return (Byte7 & 0x02) == 0x02;
default: return false;
}
}
bool IsVsSystem()
{
switch(GetRomHeaderVersion()) {
case RomHeaderVersion::Nes2_0:
case RomHeaderVersion::iNes: return (Byte7 & 0x01) == 0x01;
default: return false;
}
}
RomHeaderVersion GetRomHeaderVersion()
{
if((Byte7 & 0x0C) == 0x08) {
return RomHeaderVersion::Nes2_0;
} else if((Byte7 & 0x0C) == 0x00) {
return RomHeaderVersion::iNes;
} else {
return RomHeaderVersion::OldiNes;
}
}
uint32_t GetPrgSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
return (((Byte9 & 0x0F) << 8) | PrgCount) * 0x4000;
} else {
if(PrgCount == 0) {
return 256 * 0x4000; //0 is a special value and means 256
} else {
return PrgCount * 0x4000;
}
}
}
uint32_t GetChrSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
return (((Byte9 & 0xF0) << 4) | ChrCount) * 0x2000;
} else {
return ChrCount * 0x2000;
}
}
uint32_t GetWorkRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = Byte10 & 0x0F;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
uint32_t GetSaveRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = (Byte10 & 0xF0) >> 4;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
int32_t GetChrRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = Byte11 & 0x0F;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
uint32_t GetSaveChrRamSize()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
uint8_t value = (Byte11 & 0xF0) >> 4;
return value == 0 ? 0 : 128 * (uint32_t)std::pow(2, value - 1);
} else {
return -1;
}
}
uint8_t GetSubMapper()
{
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
return (Byte8 & 0xF0) >> 4;
} else {
return 0;
}
}
MirroringType GetMirroringType()
{
if(Byte6 & 0x08) {
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
if(Byte6 & 0x01) {
//Based on proposal by rainwarrior/Myask: http://wiki.nesdev.com/w/index.php/Talk:NES_2.0
return MirroringType::ScreenAOnly;
} else {
return MirroringType::FourScreens;
}
} else {
return MirroringType::FourScreens;
}
} else {
return Byte6 & 0x01 ? MirroringType::Vertical : MirroringType::Horizontal;
}
}
void SanitizeHeader(size_t romLength)
{
size_t calculatedLength = sizeof(NESHeader) + GetPrgSize();
while(calculatedLength > romLength) {
Byte9 = 0;
PrgCount--;
calculatedLength = sizeof(NESHeader) + GetPrgSize();
}
calculatedLength = sizeof(NESHeader) + GetPrgSize() + GetChrSize();
while(calculatedLength > romLength) {
Byte9 = 0;
ChrCount--;
calculatedLength = sizeof(NESHeader) + GetPrgSize() + GetChrSize();
}
}
};
struct NsfHeader
{
char Header[5];
@ -248,29 +55,47 @@ struct GameInfo
string InputType;
string BusConflicts;
string SubmapperID;
string VsSystemType;
string PpuModel;
};
struct RomData
struct RomInfo
{
string RomName;
string Filename;
RomFormat Format;
bool IsNes20Header = false;
uint16_t MapperID = 0;
uint8_t SubMapperID = 0;
GameSystem System = GameSystem::Unknown;
VsSystemType VsSystemType = VsSystemType::Default;
PpuModel PpuModel = PpuModel::Ppu2C02;
bool HasChrRam = false;
bool HasBattery = false;
bool HasTrainer = false;
MirroringType Mirroring = MirroringType::Horizontal;
BusConflictType BusConflicts = BusConflictType::Default;
HashInfo Hash;
NESHeader NesHeader;
NsfHeader NsfInfo;
GameInfo DatabaseInfo;
};
struct RomData
{
RomInfo Info;
int32_t ChrRamSize = -1;
int32_t SaveChrRamSize = -1;
int32_t SaveRamSize = -1;
int32_t WorkRamSize = -1;
bool IsNes20Header = false;
vector<uint8_t> PrgRom;
vector<uint8_t> ChrRom;
vector<uint8_t> TrainerData;
@ -278,16 +103,8 @@ struct RomData
vector<vector<uint8_t>> FdsDiskHeaders;
vector<uint8_t> RawData;
string Sha1;
string PrgChrMd5;
uint32_t Crc32 = 0;
uint32_t PrgCrc32 = 0;
uint32_t PrgChrCrc32 = 0;
bool Error = false;
bool BiosMissing = false;
NESHeader NesHeader;
NsfHeader NsfInfo;
GameInfo DatabaseInfo;
};
};

View file

@ -68,22 +68,22 @@ bool RomLoader::LoadFile(string filename, vector<uint8_t> &fileData)
}
}
_romData.Crc32 = crc;
_romData.Sha1 = SHA1::GetHash(fileData);
_romData.Info.Hash.Crc32 = crc;
_romData.Info.Hash.Sha1 = SHA1::GetHash(fileData);
_romData.RawData = fileData;
_romData.RomName = romName;
_romData.Filename = _filename;
_romData.Info.RomName = romName;
_romData.Info.Filename = _filename;
if(_romData.System == GameSystem::Unknown) {
if(_romData.Info.System == GameSystem::Unknown) {
//Use filename to detect PAL/VS system games
string name = _romData.Filename;
string name = _romData.Info.Filename;
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
if(name.find("(e)") != string::npos || name.find("(australia)") != string::npos || name.find("(europe)") != string::npos ||
name.find("(germany)") != string::npos || name.find("(spain)") != string::npos) {
_romData.System = GameSystem::NesPal;
_romData.Info.System = GameSystem::NesPal;
} else if(name.find("(vs)") != string::npos) {
_romData.System = GameSystem::VsUniSystem;
_romData.Info.System = GameSystem::VsSystem;
}
}
@ -103,7 +103,7 @@ string RomLoader::FindMatchingRomInFile(string filePath, HashInfo hashInfo)
RomLoader loader(true);
vector<uint8_t> fileData;
if(loader.LoadFile(filePath)) {
if(hashInfo.Crc32Hash == loader._romData.Crc32 || hashInfo.Sha1Hash.compare(loader._romData.Sha1) == 0) {
if(hashInfo.Crc32 == loader._romData.Info.Hash.Crc32 || hashInfo.Sha1.compare(loader._romData.Info.Hash.Sha1) == 0) {
return VirtualFile(filePath, file);
}
}
@ -112,7 +112,7 @@ string RomLoader::FindMatchingRomInFile(string filePath, HashInfo hashInfo)
RomLoader loader(true);
vector<uint8_t> fileData;
if(loader.LoadFile(filePath)) {
if(hashInfo.Crc32Hash == loader._romData.Crc32 || hashInfo.Sha1Hash.compare(loader._romData.Sha1) == 0) {
if(hashInfo.Crc32 == loader._romData.Info.Hash.Crc32 || hashInfo.Sha1.compare(loader._romData.Info.Hash.Sha1) == 0) {
return filePath;
}
}

View file

@ -9,6 +9,7 @@
#include "VideoDecoder.h"
#include "Debugger.h"
#include "MovieManager.h"
#include "RomData.h"
SaveStateManager::SaveStateManager(shared_ptr<Console> console)
{
@ -19,7 +20,7 @@ SaveStateManager::SaveStateManager(shared_ptr<Console> console)
string SaveStateManager::GetStateFilepath(int stateIndex)
{
string folder = FolderUtilities::GetSaveStateFolder();
string filename = FolderUtilities::GetFilename(_console->GetMapperInfo().RomName, false) + "_" + std::to_string(stateIndex) + ".mst";
string filename = FolderUtilities::GetFilename(_console->GetRomInfo().RomName, false) + "_" + std::to_string(stateIndex) + ".mst";
return FolderUtilities::CombinePath(folder, filename);
}
@ -65,14 +66,14 @@ void SaveStateManager::SaveState(ostream &stream)
stream.write((char*)&emuVersion, sizeof(emuVersion));
stream.write((char*)&formatVersion, sizeof(uint32_t));
MapperInfo mapperInfo = _console->GetMapperInfo();
stream.write((char*)&mapperInfo.MapperId, sizeof(uint16_t));
stream.write((char*)&mapperInfo.SubMapperId, sizeof(uint8_t));
RomInfo romInfo = _console->GetRomInfo();
stream.write((char*)&romInfo.MapperID, sizeof(uint16_t));
stream.write((char*)&romInfo.SubMapperID, sizeof(uint8_t));
string sha1Hash = mapperInfo.Hash.Sha1Hash;
string sha1Hash = romInfo.Hash.Sha1;
stream.write(sha1Hash.c_str(), sha1Hash.size());
string romName = mapperInfo.RomName;
string romName = romInfo.RomName;
uint32_t nameLength = (uint32_t)romName.size();
stream.write((char*)&nameLength, sizeof(uint32_t));
stream.write(romName.c_str(), romName.size());
@ -156,16 +157,16 @@ bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
stream.read(nameBuffer.data(), nameBuffer.size());
string romName(nameBuffer.data(), nameLength);
MapperInfo mapperInfo = _console->GetMapperInfo();
bool gameLoaded = !mapperInfo.Hash.Sha1Hash.empty();
if(mapperInfo.Hash.Sha1Hash != string(hash)) {
RomInfo romInfo = _console->GetRomInfo();
bool gameLoaded = !romInfo.Hash.Sha1.empty();
if(romInfo.Hash.Sha1 != string(hash)) {
//CRC doesn't match
if(!EmulationSettings::CheckFlag(EmulationFlags::AllowMismatchingSaveState) || !gameLoaded ||
mapperInfo.MapperId != mapperId || mapperInfo.SubMapperId != subMapperId)
romInfo.MapperID != mapperId || romInfo.SubMapperID != subMapperId)
{
//If mismatching states aren't allowed, or a game isn't loaded, or the mapper types don't match, try to find and load the matching ROM
HashInfo info;
info.Sha1Hash = hash;
info.Sha1 = hash;
if(!_console->LoadMatchingRom(romName, info)) {
MessageManager::DisplayMessage("SaveStates", "SaveStateMissingRom", romName);
return false;
@ -221,8 +222,8 @@ bool SaveStateManager::LoadState(int stateIndex)
void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath)
{
if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && !EmulationSettings::CheckFlag(EmulationFlags::DisableGameSelectionScreen) && _console->GetMapperInfo().Format != RomFormat::Nsf) {
string filename = FolderUtilities::GetFilename(_console->GetMapperInfo().RomName, false) + ".rgd";
if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && !EmulationSettings::CheckFlag(EmulationFlags::DisableGameSelectionScreen) && _console->GetRomInfo().Format != RomFormat::Nsf) {
string filename = FolderUtilities::GetFilename(_console->GetRomInfo().RomName, false) + ".rgd";
ZipWriter writer;
writer.Initialize(FolderUtilities::CombinePath(FolderUtilities::GetRecentGamesFolder(), filename));

View file

@ -35,7 +35,7 @@ protected:
uint8_t outerBank = ((_regs[0] ^ _regs[1]) & 0x10) << 1;
uint8_t innerBank = _regs[2] ^ _regs[3];
bool altMode = _mapperID == 167;
bool altMode = _romInfo.MapperID == 167;
if(_regs[1] & 0x08) {
//32 KiB NROM

View file

@ -18,7 +18,7 @@ protected:
//This cart appears to behave differently (maybe not an identical mapper?)
//IRQ seems to be triggered at a different timing (approx 100 cpu cycles before regular mapper 48 timings)
_isFlintstones = _subMapperID == 255;
_isFlintstones = _romInfo.SubMapperID == 255;
}
virtual void StreamState(bool saving) override

View file

@ -315,8 +315,7 @@ enum class GameSystem
NesPal,
Famicom,
Dendy,
VsUniSystem,
VsDualSystem,
VsSystem,
Playchoice,
FDS,
Unknown,
@ -331,11 +330,11 @@ enum class BusConflictType
struct HashInfo
{
uint32_t Crc32Hash = 0;
uint32_t PrgCrc32Hash = 0;
uint32_t PrgChrCrc32Hash = 0;
string Sha1Hash;
string PrgChrMd5Hash;
uint32_t Crc32 = 0;
uint32_t PrgCrc32 = 0;
uint32_t PrgChrCrc32 = 0;
string Sha1;
string PrgChrMd5;
};
enum class RomFormat
@ -347,14 +346,29 @@ enum class RomFormat
Nsf = 4,
};
struct MapperInfo
enum class VsSystemType
{
string RomName;
RomFormat Format;
GameSystem System;
uint16_t MapperId;
uint8_t SubMapperId;
HashInfo Hash;
bool UsesChrRam;
Default = 0,
RbiBaseballProtection = 1,
TkoBoxingProtection = 2,
SuperXeviousProtection = 3,
IceClimberProtection = 4,
VsDualSystem = 5,
RaidOnBungelingBayProtection = 6,
};
extern const vector<string> PpuModelNames;
enum class PpuModel
{
Ppu2C02 = 0,
Ppu2C03 = 1,
Ppu2C04A = 2,
Ppu2C04B = 3,
Ppu2C04C = 4,
Ppu2C04D = 5,
Ppu2C05A = 6,
Ppu2C05B = 7,
Ppu2C05C = 8,
Ppu2C05D = 9,
Ppu2C05E = 10
};

View file

@ -17,7 +17,7 @@ class UNROM : public BaseMapper
SelectCHRPage(0, 0);
}
bool HasBusConflicts() override { return _subMapperID == 2; }
bool HasBusConflicts() override { return _romInfo.SubMapperID == 2; }
void WriteRegister(uint16_t addr, uint8_t value) override
{

View file

@ -84,8 +84,8 @@ private:
if(fourCC.compare("MAPR") == 0) {
_mapperName = ReadString(data, chunkEnd);
if(_mapperName.size() > 0) {
romData.MapperID = GetMapperID(_mapperName);
if(romData.MapperID == UnifBoards::UnknownBoard) {
romData.Info.MapperID = GetMapperID(_mapperName);
if(romData.Info.MapperID == UnifBoards::UnknownBoard) {
Log("[UNIF] Error: Unknown board");
}
} else {
@ -111,24 +111,24 @@ private:
} else if(fourCC.compare("TVCI") == 0) {
uint8_t value;
Read(data, value);
romData.System = value == 1 ? GameSystem::NesPal : GameSystem::NesNtsc;
romData.Info.System = value == 1 ? GameSystem::NesPal : GameSystem::NesNtsc;
} else if(fourCC.compare("CTRL") == 0) {
//not supported
} else if(fourCC.compare("BATR") == 0) {
uint8_t value;
Read(data, value);
romData.HasBattery = value > 0;
romData.Info.HasBattery = value > 0;
} else if(fourCC.compare("MIRR") == 0) {
uint8_t value;
Read(data, value);
switch(value) {
default:
case 0: romData.Mirroring = MirroringType::Horizontal; break;
case 1: romData.Mirroring = MirroringType::Vertical; break;
case 2: romData.Mirroring = MirroringType::ScreenAOnly; break;
case 3: romData.Mirroring = MirroringType::ScreenBOnly; break;
case 4: romData.Mirroring = MirroringType::FourScreens; break;
case 0: romData.Info.Mirroring = MirroringType::Horizontal; break;
case 1: romData.Info.Mirroring = MirroringType::Vertical; break;
case 2: romData.Info.Mirroring = MirroringType::ScreenAOnly; break;
case 3: romData.Info.Mirroring = MirroringType::ScreenBOnly; break;
case 4: romData.Info.Mirroring = MirroringType::FourScreens; break;
}
} else {
//Unsupported/unused FourCCs: PCKn, CCKn, NAME, WRTR, READ, DINF, VROR
@ -181,12 +181,12 @@ public:
fullRom.insert(fullRom.end(), romData.PrgRom.begin(), romData.PrgRom.end());
fullRom.insert(fullRom.end(), romData.ChrRom.begin(), romData.ChrRom.end());
romData.Format = RomFormat::Unif;
romData.PrgCrc32 = CRC32::GetCRC(romData.PrgRom.data(), romData.PrgRom.size());
romData.PrgChrCrc32 = CRC32::GetCRC(fullRom.data(), fullRom.size());
romData.PrgChrMd5 = GetMd5Sum(fullRom.data(), fullRom.size());
romData.Info.Format = RomFormat::Unif;
romData.Info.Hash.PrgCrc32 = CRC32::GetCRC(romData.PrgRom.data(), romData.PrgRom.size());
romData.Info.Hash.PrgChrCrc32 = CRC32::GetCRC(fullRom.data(), fullRom.size());
romData.Info.Hash.PrgChrMd5 = GetMd5Sum(fullRom.data(), fullRom.size());
Log("PRG+CHR CRC32: 0x" + HexUtilities::ToHex(romData.PrgChrCrc32));
Log("PRG+CHR CRC32: 0x" + HexUtilities::ToHex(romData.Info.Hash.PrgChrCrc32));
Log("[UNIF] Board Name: " + _mapperName);
Log("[UNIF] PRG ROM: " + std::to_string(romData.PrgRom.size() / 1024) + " KB");
Log("[UNIF] CHR ROM: " + std::to_string(romData.ChrRom.size() / 1024) + " KB");
@ -195,7 +195,7 @@ public:
}
string mirroringType;
switch(romData.Mirroring) {
switch(romData.Info.Mirroring) {
case MirroringType::Horizontal: mirroringType = "Horizontal"; break;
case MirroringType::Vertical: mirroringType = "Vertical"; break;
case MirroringType::ScreenAOnly: mirroringType = "1-Screen (A)"; break;
@ -204,13 +204,13 @@ public:
}
Log("[UNIF] Mirroring: " + mirroringType);
Log("[UNIF] Battery: " + string(romData.HasBattery ? "Yes" : "No"));
Log("[UNIF] Battery: " + string(romData.Info.HasBattery ? "Yes" : "No"));
if(!_checkOnly) {
GameDatabase::SetGameInfo(romData.PrgChrCrc32, romData, !EmulationSettings::CheckFlag(EmulationFlags::DisableGameDatabase), false);
GameDatabase::SetGameInfo(romData.Info.Hash.PrgChrCrc32, romData, !EmulationSettings::CheckFlag(EmulationFlags::DisableGameDatabase), false);
}
if(romData.MapperID == UnifBoards::UnknownBoard) {
if(romData.Info.MapperID == UnifBoards::UnknownBoard) {
if(!_checkOnly) {
MessageManager::DisplayMessage("Error", "UnsupportedMapper", "UNIF: " + _mapperName);
}

View file

@ -36,11 +36,11 @@ class VRC2_4 : public BaseMapper
void DetectVariant()
{
switch(_mapperID) {
switch(_romInfo.MapperID) {
default:
case 21:
//Conflicts: VRC4c
switch(_subMapperID) {
switch(_romInfo.SubMapperID) {
default:
case 0: _variant = VRCVariant::VRC4a; break;
case 1: _variant = VRCVariant::VRC4a; break;
@ -52,7 +52,7 @@ class VRC2_4 : public BaseMapper
case 23:
//Conflicts: VRC4e
switch(_subMapperID) {
switch(_romInfo.SubMapperID) {
default:
case 0: _variant = VRCVariant::VRC2b; break;
case 2: _variant = VRCVariant::VRC4e; break;
@ -62,7 +62,7 @@ class VRC2_4 : public BaseMapper
case 25:
//Conflicts: VRC2c, VRC4d
switch(_subMapperID) {
switch(_romInfo.SubMapperID) {
default:
case 0: _variant = VRCVariant::VRC4b; break;
case 1: _variant = VRCVariant::VRC4b; break;
@ -74,7 +74,7 @@ class VRC2_4 : public BaseMapper
case 27: _variant = VRCVariant::VRC4_27; break; //Untested
}
_useHeuristics = (_subMapperID == 0) && _mapperID != 22 && _mapperID != 27;
_useHeuristics = (_romInfo.SubMapperID == 0) && _romInfo.MapperID != 22 && _romInfo.MapperID != 27;
}
protected:
@ -101,7 +101,7 @@ class VRC2_4 : public BaseMapper
void ProcessCpuClock() override
{
if((_useHeuristics && _mapperID != 22) || _variant >= VRCVariant::VRC4a) {
if((_useHeuristics && _romInfo.MapperID != 22) || _variant >= VRCVariant::VRC4a) {
//Only VRC4 supports IRQs
_irq->ProcessCpuClock();
}

View file

@ -16,6 +16,8 @@ void VsControlManager::Reset(bool softReset)
ControlManager::Reset(softReset);
_protectionCounter = 0;
UpdateSlaveMasterBit(_console->IsMaster() ? 0x00 : 0x02);
_vsSystemType = _console->GetRomInfo().VsSystemType;
if(!softReset && !_console->IsMaster() && _console->GetDualConsole()) {
RegisterInputProvider(this);
@ -72,11 +74,10 @@ void VsControlManager::RemapControllerButtons()
BaseControlDevice::SwapButtons(controllers[0], StandardController::Buttons::Start, controllers[0], StandardController::Buttons::Select);
BaseControlDevice::SwapButtons(controllers[1], StandardController::Buttons::Start, controllers[1], StandardController::Buttons::Select);
uint32_t crc = _console->GetMapperInfo().Hash.PrgCrc32Hash;
if(crc == 0x99FB3B3B) {
//Bit 3 of the input status must always be on (Raid on Bungeling Bay protection)
controllers[0]->InvertBit(StandardController::Buttons::Start);
controllers[1]->InvertBit(StandardController::Buttons::Start);
if(_vsSystemType == VsSystemType::RaidOnBungelingBayProtection || _vsSystemType == VsSystemType::IceClimberProtection) {
//Bit 3 of the input status must always be on
controllers[0]->SetBit(StandardController::Buttons::Start);
controllers[1]->SetBit(StandardController::Buttons::Start);
}
}
@ -89,8 +90,6 @@ uint8_t VsControlManager::ReadRAM(uint16_t addr)
{
uint8_t value = 0;
uint32_t crc = _console->GetMapperInfo().Hash.PrgCrc32Hash;
switch(addr) {
case 0x4016: {
uint32_t dipSwitches = EmulationSettings::GetDipSwitches();
@ -119,18 +118,15 @@ uint8_t VsControlManager::ReadRAM(uint16_t addr)
break;
case 0x5E01:
if(crc == 0xEB2DBA63 || crc == 0x98CFE016) {
//TKO Boxing
if(_vsSystemType == VsSystemType::TkoBoxingProtection) {
value = _protectionData[0][_protectionCounter++ & 0x1F];
} else if(crc == 0x135ADF7C) {
//RBI Baseball
} else if(_vsSystemType == VsSystemType::RbiBaseballProtection) {
value = _protectionData[1][_protectionCounter++ & 0x1F];
}
break;
default:
if((crc == 0xF9D3B0A3 || crc == 0x66BB838F || crc == 0x9924980A) && addr >= 0x5400 && addr <= 0x57FF) {
//Super devious
if(_vsSystemType == VsSystemType::SuperXeviousProtection) {
return _protectionData[2][_protectionCounter++ & 0x1F];
}
break;

View file

@ -19,6 +19,8 @@ private:
bool _refreshState = false;
VsSystemType _vsSystemType;
uint32_t _protectionCounter = 0;
const uint32_t _protectionData[3][32] = {
{

View file

@ -15,12 +15,10 @@ protected:
virtual void InitMapper() override
{
//Force VS system if mapper 99 (since we assume VsControlManager exists below)
if(_prgSize >= 0x10000) {
//Assume DualSystem if PRG ROM is 64kb or larger
_gameSystem = GameSystem::VsDualSystem;
} else {
_gameSystem = GameSystem::VsUniSystem;
if(!IsNes20()) {
//Force VS system if mapper 99
_romInfo.System = GameSystem::VsSystem;
_romInfo.VsSystemType = VsSystemType::Default;
}
//"Note: unlike all other mappers, an undersize mapper 99 image implies open bus instead of mirroring."
@ -50,7 +48,7 @@ protected:
void ProcessCpuClock() override
{
VsControlManager* controlManager = dynamic_cast<VsControlManager*>(_console->GetControlManager());
if(_prgChrSelectBit != controlManager->GetPrgChrSelectBit()) {
if(controlManager && _prgChrSelectBit != controlManager->GetPrgChrSelectBit()) {
_prgChrSelectBit = controlManager->GetPrgChrSelectBit();
if(_prgSize > 0x8000 && _prgSize < 0x10000) {

View file

@ -23,28 +23,25 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader
dataSize -= sizeof(NESHeader);
}
romData.Format = RomFormat::iNes;
romData.Info.Format = RomFormat::iNes;
romData.Info.IsNes20Header = (header.GetRomHeaderVersion() == RomHeaderVersion::Nes2_0);
romData.Info.MapperID = header.GetMapperID();
romData.Info.SubMapperID = header.GetSubMapper();
romData.Info.Mirroring = header.GetMirroringType();
romData.Info.HasBattery = header.HasBattery();
romData.Info.System = header.GetGameSystem();
romData.Info.VsSystemType = header.GetVsSystemType();
romData.Info.PpuModel = header.GetVsSystemPpuModel();
romData.Info.HasTrainer = header.HasTrainer();
romData.Info.NesHeader = header;
romData.IsNes20Header = (header.GetRomHeaderVersion() == RomHeaderVersion::Nes2_0);
romData.MapperID = header.GetMapperID();
romData.SubMapperID = header.GetSubMapper();
romData.Mirroring = header.GetMirroringType();
romData.HasBattery = header.HasBattery();
if(header.IsPalRom()) {
romData.System = GameSystem::NesPal;
} else if(header.IsVsSystem()) {
romData.System = GameSystem::VsUniSystem;
} else if(header.IsPlaychoice()) {
romData.System = GameSystem::Playchoice;
}
romData.HasTrainer = header.HasTrainer();
romData.ChrRamSize = header.GetChrRamSize();
romData.SaveChrRamSize = header.GetSaveChrRamSize();
romData.WorkRamSize = header.GetWorkRamSize();
romData.SaveRamSize = header.GetSaveRamSize();
romData.NesHeader = header;
if(romData.HasTrainer) {
if(romData.Info.HasTrainer) {
//512-byte trainer at $7000-$71FF (stored before PRG data)
romData.TrainerData.insert(romData.TrainerData.end(), buffer, buffer + 512);
buffer += 512;
@ -53,13 +50,13 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader
size_t bytesRead = buffer - romFile.data();
uint32_t romCrc = CRC32::GetCRC(buffer, romFile.size() - bytesRead);
romData.PrgChrCrc32 = romCrc;
romData.PrgChrMd5 = GetMd5Sum(buffer, romFile.size() - bytesRead);
romData.Info.Hash.PrgChrCrc32 = romCrc;
romData.Info.Hash.PrgChrMd5 = GetMd5Sum(buffer, romFile.size() - bytesRead);
uint32_t prgSize = 0;
uint32_t chrSize = 0;
if(EmulationSettings::CheckFlag(EmulationFlags::DisableGameDatabase) || !GameDatabase::GetDbRomSize(romData.PrgChrCrc32, prgSize, chrSize)) {
if(EmulationSettings::CheckFlag(EmulationFlags::DisableGameDatabase) || !GameDatabase::GetDbRomSize(romData.Info.Hash.PrgChrCrc32, prgSize, chrSize)) {
//Fallback on header sizes when game is not in DB (or DB is disabled)
prgSize = header.GetPrgSize();
chrSize = header.GetChrSize();
@ -75,37 +72,51 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader
buffer += prgSize;
romData.ChrRom.insert(romData.ChrRom.end(), buffer, buffer + chrSize);
romData.PrgCrc32 = CRC32::GetCRC(romData.PrgRom.data(), romData.PrgRom.size());
romData.Info.Hash.PrgCrc32 = CRC32::GetCRC(romData.PrgRom.data(), romData.PrgRom.size());
Log("PRG CRC32: 0x" + HexUtilities::ToHex(romData.PrgCrc32, true));
Log("PRG+CHR CRC32: 0x" + HexUtilities::ToHex(romData.PrgChrCrc32, true));
Log("PRG CRC32: 0x" + HexUtilities::ToHex(romData.Info.Hash.PrgCrc32, true));
Log("PRG+CHR CRC32: 0x" + HexUtilities::ToHex(romData.Info.Hash.PrgChrCrc32, true));
if(romData.IsNes20Header) {
if(romData.Info.IsNes20Header) {
Log("[iNes] NES 2.0 file: Yes");
}
Log("[iNes] Mapper: " + std::to_string(romData.MapperID) + " Sub:" + std::to_string(romData.SubMapperID));
Log("[iNes] Mapper: " + std::to_string(romData.Info.MapperID) + " Sub:" + std::to_string(romData.Info.SubMapperID));
if(romData.Info.System == GameSystem::VsSystem) {
string type = "Vs-UniSystem";
switch(romData.Info.VsSystemType) {
case VsSystemType::IceClimberProtection: type = "VS-UniSystem (Ice Climbers)"; break;
case VsSystemType::RaidOnBungelingBayProtection: type = "VS-DualSystem (Raid on Bungeling Bay)"; break;
case VsSystemType::RbiBaseballProtection: type = "VS-UniSystem (RBI Baseball)"; break;
case VsSystemType::SuperXeviousProtection: type = "VS-UniSystem (Super Xevious)"; break;
case VsSystemType::TkoBoxingProtection: type = "VS-UniSystem (TKO Boxing)"; break;
case VsSystemType::VsDualSystem: type = "VS-DualSystem"; break;
}
Log("[iNes] System: " + type);
}
Log("[iNes] PRG ROM: " + std::to_string(romData.PrgRom.size()/1024) + " KB");
Log("[iNes] CHR ROM: " + std::to_string(romData.ChrRom.size()/1024) + " KB");
if(romData.ChrRamSize > 0 || romData.IsNes20Header) {
if(romData.ChrRamSize > 0 || romData.Info.IsNes20Header) {
Log("[iNes] CHR RAM: " + std::to_string(romData.ChrRamSize / 1024) + " KB");
} else if(romData.ChrRom.size() == 0) {
Log("[iNes] CHR RAM: 8 KB");
}
if(romData.WorkRamSize > 0 || romData.IsNes20Header) {
if(romData.WorkRamSize > 0 || romData.Info.IsNes20Header) {
Log("[iNes] Work RAM: " + std::to_string(romData.WorkRamSize / 1024) + " KB");
}
if(romData.SaveRamSize > 0 || romData.IsNes20Header) {
if(romData.SaveRamSize > 0 || romData.Info.IsNes20Header) {
Log("[iNes] Save RAM: " + std::to_string(romData.SaveRamSize / 1024) + " KB");
}
Log("[iNes] Mirroring: " + string(romData.Mirroring == MirroringType::Horizontal ? "Horizontal" : romData.Mirroring == MirroringType::Vertical ? "Vertical" : "Four Screens"));
Log("[iNes] Battery: " + string(romData.HasBattery ? "Yes" : "No"));
if(romData.HasTrainer) {
Log("[iNes] Mirroring: " + string(romData.Info.Mirroring == MirroringType::Horizontal ? "Horizontal" : romData.Info.Mirroring == MirroringType::Vertical ? "Vertical" : "Four Screens"));
Log("[iNes] Battery: " + string(romData.Info.HasBattery ? "Yes" : "No"));
if(romData.Info.HasTrainer) {
Log("[iNes] Trainer: Yes");
}
if(!_checkOnly) {
GameDatabase::SetGameInfo(romData.PrgChrCrc32, romData, !EmulationSettings::CheckFlag(EmulationFlags::DisableGameDatabase) && header.GetRomHeaderVersion() != RomHeaderVersion::Nes2_0, preloadedHeader != nullptr);
GameDatabase::SetGameInfo(romData.Info.Hash.PrgChrCrc32, romData, !EmulationSettings::CheckFlag(EmulationFlags::DisableGameDatabase) && header.GetRomHeaderVersion() != RomHeaderVersion::Nes2_0, preloadedHeader != nullptr);
}
return romData;

File diff suppressed because it is too large Load diff

View file

@ -95,7 +95,7 @@ namespace InteropEmu {
}
};
struct RomInfo
struct InteropRomInfo
{
const char* RomName;
uint32_t Crc32;
@ -276,20 +276,20 @@ namespace InteropEmu {
}
}
DllExport void __stdcall GetRomInfo(RomInfo &romInfo, char* filename)
DllExport void __stdcall GetRomInfo(InteropRomInfo &interopRomInfo, char* filename)
{
string romPath = filename;
if(romPath.empty()) {
_returnString = _console->GetRomPath();
romInfo.RomName = _returnString.c_str();
MapperInfo mapperInfo = _console->GetMapperInfo();
romInfo.Crc32 = mapperInfo.Hash.Crc32Hash;
romInfo.PrgCrc32 = mapperInfo.Hash.PrgCrc32Hash;
romInfo.Format = mapperInfo.Format;
romInfo.IsChrRam = mapperInfo.UsesChrRam;
romInfo.MapperId = mapperInfo.MapperId;
if(mapperInfo.Hash.Sha1Hash.size() == 40) {
memcpy(romInfo.Sha1, mapperInfo.Hash.Sha1Hash.c_str(), 40);
interopRomInfo.RomName = _returnString.c_str();
RomInfo romInfo = _console->GetRomInfo();
interopRomInfo.Crc32 = romInfo.Hash.Crc32;
interopRomInfo.PrgCrc32 = romInfo.Hash.PrgCrc32;
interopRomInfo.Format = romInfo.Format;
interopRomInfo.IsChrRam = romInfo.HasChrRam;
interopRomInfo.MapperId = romInfo.MapperID;
if(romInfo.Hash.Sha1.size() == 40) {
memcpy(interopRomInfo.Sha1, romInfo.Hash.Sha1.c_str(), 40);
}
} else {
RomLoader romLoader(true);
@ -297,23 +297,23 @@ namespace InteropEmu {
RomData romData = romLoader.GetRomData();
_returnString = romPath;
romInfo.RomName = _returnString.c_str();
romInfo.Crc32 = romData.Crc32;
romInfo.PrgCrc32 = romData.PrgCrc32;
romInfo.Format = RomFormat::Unknown;
romInfo.IsChrRam = romData.ChrRom.size() == 0;
romInfo.MapperId = 0;
if(romData.Sha1.size() == 40) {
memcpy(romInfo.Sha1, romData.Sha1.c_str(), 40);
interopRomInfo.RomName = _returnString.c_str();
interopRomInfo.Crc32 = romData.Info.Hash.Crc32;
interopRomInfo.PrgCrc32 = romData.Info.Hash.PrgCrc32;
interopRomInfo.Format = RomFormat::Unknown;
interopRomInfo.IsChrRam = romData.ChrRom.size() == 0;
interopRomInfo.MapperId = 0;
if(romData.Info.Hash.Sha1.size() == 40) {
memcpy(interopRomInfo.Sha1, romData.Info.Hash.Sha1.c_str(), 40);
}
} else {
_returnString = "";
romInfo.RomName = _returnString.c_str();
romInfo.Crc32 = 0;
romInfo.PrgCrc32 = 0;
romInfo.Format = RomFormat::Unknown;
romInfo.IsChrRam = false;
romInfo.MapperId = 0;
interopRomInfo.RomName = _returnString.c_str();
interopRomInfo.Crc32 = 0;
interopRomInfo.PrgCrc32 = 0;
interopRomInfo.Format = RomFormat::Unknown;
interopRomInfo.IsChrRam = false;
interopRomInfo.MapperId = 0;
}
}
}

View file

@ -76,6 +76,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
$(CORE_DIR)/MessageManager.cpp \
$(CORE_DIR)/MovieManager.cpp \
$(CORE_DIR)/MovieRecorder.cpp \
$(CORE_DIR)/NESHeader.cpp \
$(CORE_DIR)/NotificationManager.cpp \
$(CORE_DIR)/NsfLoader.cpp \
$(CORE_DIR)/NsfMapper.cpp \

File diff suppressed because it is too large Load diff

View file

@ -835,7 +835,7 @@ extern "C" {
void update_core_controllers()
{
//Setup all "auto" ports
GameDatabase::InitializeInputDevices(_console->GetMapperInfo().Hash.PrgChrCrc32Hash);
GameDatabase::InitializeInputDevices(_console->GetRomInfo().Hash.PrgChrCrc32);
//TODO: Four Score