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); 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 void WriteRegister(uint16_t addr, uint8_t value) override
{ {

View file

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

View file

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

View file

@ -22,7 +22,7 @@ protected:
uint16_t RegisterStartAddress() override { return 0x6000; } uint16_t RegisterStartAddress() override { return 0x6000; }
uint16_t RegisterEndAddress() override { return 0xFFFF; } uint16_t RegisterEndAddress() override { return 0xFFFF; }
bool AllowRegisterRead() override { return true; } 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 void InitMapper() override
{ {
@ -33,7 +33,7 @@ protected:
_prgPage = 0; _prgPage = 0;
_prgBankSelect = 0; _prgBankSelect = 0;
if(_mapperID == 157) { if(_romInfo.MapperID == 157) {
//"Mapper 157 is used for Datach Joint ROM System boards" //"Mapper 157 is used for Datach Joint ROM System boards"
_barcodeReader.reset(new DatachBarcodeReader(_console)); _barcodeReader.reset(new DatachBarcodeReader(_console));
_mapperControlDevice = _barcodeReader; _mapperControlDevice = _barcodeReader;
@ -42,7 +42,7 @@ protected:
//Only allow reads from 0x6000 to 0x7FFF //Only allow reads from 0x6000 to 0x7FFF
RemoveRegisterRange(0x8000, 0xFFFF, MemoryOperation::Read); 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." //"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." //"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) { switch(addr & 0x000F) {
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
_chrRegs[addr & 0x07] = value; _chrRegs[addr & 0x07] = value;
if(_mapperID == 153 || GetPRGPageCount() >= 0x20) { if(_romInfo.MapperID == 153 || GetPRGPageCount() >= 0x20) {
_prgBankSelect = 0; _prgBankSelect = 0;
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
_prgBankSelect |= (_chrRegs[i] & 0x01) << 4; _prgBankSelect |= (_chrRegs[i] & 0x01) << 4;
} }
SelectPRGPage(0, _prgPage | _prgBankSelect); SelectPRGPage(0, _prgPage | _prgBankSelect);
SelectPRGPage(1, 0x0F | _prgBankSelect); SelectPRGPage(1, 0x0F | _prgBankSelect);
} else if(!HasChrRam() && _mapperID != 157) { } else if(!HasChrRam() && _romInfo.MapperID != 157) {
SelectCHRPage(addr & 0x07, value); SelectCHRPage(addr & 0x07, value);
} }
break; break;

View file

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

View file

@ -31,10 +31,6 @@ private:
bool _onlyChrRam = false; bool _onlyChrRam = false;
bool _hasBusConflicts = false; bool _hasBusConflicts = false;
string _romFilename;
string _romName;
RomFormat _romFormat;
bool _allowRegisterRead = false; bool _allowRegisterRead = false;
bool _isReadRegisterAddr[0x10000]; bool _isReadRegisterAddr[0x10000];
bool _isWriteRegisterAddr[0x10000]; bool _isWriteRegisterAddr[0x10000];
@ -47,22 +43,15 @@ private:
uint32_t _prgPageNumbers[64]; uint32_t _prgPageNumbers[64];
uint32_t _chrPageNumbers[64]; uint32_t _chrPageNumbers[64];
HashInfo _hashInfo;
vector<uint8_t> _originalPrgRom; vector<uint8_t> _originalPrgRom;
vector<uint8_t> _originalChrRom; vector<uint8_t> _originalChrRom;
protected: protected:
RomInfo _romInfo;
shared_ptr<BaseControlDevice> _mapperControlDevice; shared_ptr<BaseControlDevice> _mapperControlDevice;
shared_ptr<Console> _console; shared_ptr<Console> _console;
NESHeader _nesHeader;
GameInfo _databaseInfo;
uint16_t _mapperID;
uint8_t _subMapperID;
GameSystem _gameSystem;
uint8_t* _prgRom = nullptr; uint8_t* _prgRom = nullptr;
uint8_t* _chrRom = nullptr; uint8_t* _chrRom = nullptr;
uint8_t* _chrRam = nullptr; uint8_t* _chrRam = nullptr;
@ -74,7 +63,6 @@ protected:
uint32_t _saveRamSize = 0; uint32_t _saveRamSize = 0;
uint32_t _workRamSize = 0; uint32_t _workRamSize = 0;
uint8_t* _workRam = nullptr; uint8_t* _workRam = nullptr;
bool _hasBattery = false;
bool _hasChrBattery = false; bool _hasChrBattery = false;
int16_t _vramOpenBusValue = -1; int16_t _vramOpenBusValue = -1;
@ -175,7 +163,7 @@ public:
virtual void SetDefaultNametables(uint8_t* nametableA, uint8_t* nametableB); virtual void SetDefaultNametables(uint8_t* nametableA, uint8_t* nametableB);
shared_ptr<BaseControlDevice> GetMapperControlDevice(); shared_ptr<BaseControlDevice> GetMapperControlDevice();
MapperInfo GetMapperInfo(); RomInfo GetRomInfo();
__forceinline uint8_t ReadRAM(uint16_t addr) override; __forceinline uint8_t ReadRAM(uint16_t addr) override;
uint8_t DebugReadRAM(uint16_t addr); uint8_t DebugReadRAM(uint16_t addr);
@ -229,7 +217,6 @@ public:
bool IsWriteRegister(uint16_t addr); bool IsWriteRegister(uint16_t addr);
bool IsReadRegister(uint16_t addr); bool IsReadRegister(uint16_t addr);
NESHeader GetNesHeader();
void GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* header); void GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* header);
vector<uint8_t> GetPrgChrCopy(); 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.compare(0, 4, "SHA1", 4) == 0) {
if(line.size() >= 45) { if(line.size() >= 45) {
HashInfo hashInfo; HashInfo hashInfo;
hashInfo.Sha1Hash = line.substr(5, 40); hashInfo.Sha1 = line.substr(5, 40);
if(_console->LoadMatchingRom("", hashInfo)) { if(_console->LoadMatchingRom("", hashInfo)) {
return true; return true;
} }
@ -114,8 +114,8 @@ bool BizhawkMovie::InitializeGameData(ZipReader &reader)
} else if(line.compare(0, 3, "MD5", 3) == 0) { } else if(line.compare(0, 3, "MD5", 3) == 0) {
if(line.size() >= 36) { if(line.size() >= 36) {
HashInfo hashInfo; HashInfo hashInfo;
hashInfo.PrgChrMd5Hash = line.substr(4, 32); hashInfo.PrgChrMd5 = line.substr(4, 32);
std::transform(hashInfo.PrgChrMd5Hash.begin(), hashInfo.PrgChrMd5Hash.end(), hashInfo.PrgChrMd5Hash.begin(), ::toupper); std::transform(hashInfo.PrgChrMd5.begin(), hashInfo.PrgChrMd5.end(), hashInfo.PrgChrMd5.begin(), ::toupper);
if(_console->LoadMatchingRom("", hashInfo)) { if(_console->LoadMatchingRom("", hashInfo)) {
return true; return true;
} }

View file

@ -20,14 +20,14 @@ protected:
_vramOpenBusValue = 0xFF; _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 void WriteRegister(uint16_t addr, uint8_t value) override
{ {
if(_enableCopyProtection) { if(_enableCopyProtection) {
//"if C AND $0F is nonzero, and if C does not equal $13: CHR is enabled" //"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 //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); SelectCHRPage(0, 0);
} else { } else {
RemovePpuMemoryMapping(0x0000, 0x1FFF); RemovePpuMemoryMapping(0x0000, 0x1FFF);

View file

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

View file

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

View file

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

View file

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

View file

@ -1456,6 +1456,9 @@
<ClInclude Include="NotificationManager.h"> <ClInclude Include="NotificationManager.h">
<Filter>Misc</Filter> <Filter>Misc</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="NESHeader.h">
<Filter>Nes\RomLoader</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">
@ -1740,5 +1743,8 @@
<ClCompile Include="FdsLoader.cpp"> <ClCompile Include="FdsLoader.cpp">
<Filter>Nes\RomLoader</Filter> <Filter>Nes\RomLoader</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="NESHeader.cpp">
<Filter>Nes\RomLoader</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </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) 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; _console = console;
_cpu = cpu; _cpu = cpu;
_ppu = ppu; _ppu = ppu;
@ -1159,7 +1159,7 @@ void Debugger::StopCodeRunner()
void Debugger::GetNesHeader(uint8_t* header) void Debugger::GetNesHeader(uint8_t* header)
{ {
NESHeader nesHeader = _mapper->GetNesHeader(); NESHeader nesHeader = _mapper->GetRomInfo().NesHeader;
memcpy(header, &nesHeader, sizeof(NESHeader)); memcpy(header, &nesHeader, sizeof(NESHeader));
} }

View file

@ -288,22 +288,6 @@ enum class ExpansionPortDevice
BattleBox = 17, 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 enum class VsInputType
{ {
Default = 0, Default = 0,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,24 +25,25 @@ void GameDatabase::LoadGameDb(vector<string> data)
for(string &row : data) { for(string &row : data) {
vector<string> values = StringUtilities::Split(row, ','); vector<string> values = StringUtilities::Split(row, ',');
if(values.size() >= 16) { if(values.size() >= 16) {
GameInfo gameInfo { GameInfo gameInfo;
(uint32_t)std::stoll(values[0], nullptr, 16), gameInfo.Crc = (uint32_t)std::stoll(values[0], nullptr, 16);
values[1], gameInfo.System = values[1];
values[2], gameInfo.Board = values[2];
values[3], gameInfo.Pcb = values[3];
values[4], gameInfo.Chip = values[4];
(uint16_t)ToInt<uint32_t>(values[5]), gameInfo.MapperID = (uint16_t)ToInt<uint32_t>(values[5]);
ToInt<uint32_t>(values[6]), gameInfo.PrgRomSize = ToInt<uint32_t>(values[6]);
ToInt<uint32_t>(values[7]), gameInfo.ChrRomSize = ToInt<uint32_t>(values[7]);
ToInt<uint32_t>(values[8]), gameInfo.ChrRamSize = ToInt<uint32_t>(values[8]);
ToInt<uint32_t>(values[9]), gameInfo.WorkRamSize = ToInt<uint32_t>(values[9]);
ToInt<uint32_t>(values[10]), gameInfo.SaveRamSize = ToInt<uint32_t>(values[10]);
ToInt<uint32_t>(values[11]) == 0 ? false : true, gameInfo.HasBattery = ToInt<uint32_t>(values[11]) == 0 ? false : true;
values[12], gameInfo.Mirroring = values[12];
values[13], gameInfo.InputType = values[13];
values[14], gameInfo.BusConflicts = values[14];
values[15] gameInfo.SubmapperID = values[15];
}; gameInfo.VsSystemType = values[16];
gameInfo.PpuModel = values[17];
if(gameInfo.MapperID == 65000) { if(gameInfo.MapperID == 65000) {
gameInfo.MapperID = UnifLoader::GetMapperID(gameInfo.Board); gameInfo.MapperID = UnifLoader::GetMapperID(gameInfo.Board);
@ -99,10 +100,8 @@ GameSystem GameDatabase::GetGameSystem(string system)
return GameSystem::NesPal; return GameSystem::NesPal;
} else if(system.compare("Famicom") == 0) { } else if(system.compare("Famicom") == 0) {
return GameSystem::Famicom; return GameSystem::Famicom;
} else if(system.compare("VsUni") == 0) { } else if(system.compare("VsSystem") == 0) {
return GameSystem::VsUniSystem; return GameSystem::VsSystem;
} else if(system.compare("VsDual") == 0) {
return GameSystem::VsDualSystem;
} else if(system.compare("Dendy") == 0) { } else if(system.compare("Dendy") == 0) {
return GameSystem::Dendy; return GameSystem::Dendy;
} else if(system.compare("Playchoice") == 0) { } else if(system.compare("Playchoice") == 0) {
@ -112,6 +111,52 @@ GameSystem GameDatabase::GetGameSystem(string system)
return GameSystem::NesNtsc; 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) void GameDatabase::InitializeInputDevices(uint32_t romCrc)
{ {
InitDatabase(); 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); bool isFamicom = (system == GameSystem::Famicom || system == GameSystem::FDS || system == GameSystem::Dendy);
if(inputType.compare("Zapper") == 0) { if(inputType.compare("Zapper") == 0) {
@ -377,7 +422,7 @@ bool GameDatabase::GetiNesHeader(uint32_t romCrc, NESHeader &nesHeader)
GameSystem system = GetGameSystem(info.System); GameSystem system = GetGameSystem(info.System);
if(system == GameSystem::Playchoice) { if(system == GameSystem::Playchoice) {
nesHeader.Byte7 |= 0x02; nesHeader.Byte7 |= 0x02;
} else if(system == GameSystem::VsUniSystem) { } else if(system == GameSystem::VsSystem) {
nesHeader.Byte7 |= 0x01; nesHeader.Byte7 |= 0x01;
} }
@ -420,7 +465,7 @@ void GameDatabase::SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRom
info = result->second; info = result->second;
if(!forHeaderlessRom && info.Board == "UNK") { if(!forHeaderlessRom && info.Board == "UNK") {
//Boards marked as UNK should only be used for headerless roms (since their data is unverified) //Boards marked as UNK should only be used for headerless roms (since their data is unverified)
romData.DatabaseInfo = {}; romData.Info.DatabaseInfo = {};
return; return;
} }
@ -433,6 +478,19 @@ void GameDatabase::SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRom
} }
MessageManager::Log("[DB] System : " + info.System); 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()) { if(!info.Board.empty()) {
MessageManager::Log("[DB] Board: " + info.Board); 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)) { if(EmulationSettings::CheckFlag(EmulationFlags::AutoConfigureInput)) {
InitializeInputDevices(info.InputType, romData.System); InitializeInputDevices(info.InputType, romData.Info.System);
} }
#ifdef _DEBUG #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 #endif
} else { } else {
MessageManager::Log("[DB] Game not found in database"); MessageManager::Log("[DB] Game not found in database");
} }
#ifdef LIBRETRO #ifdef LIBRETRO
SetVsSystemDefaults(romData.PrgCrc32); SetVsSystemDefaults(romData.Info.Hash.PrgCrc32);
#endif #endif
romData.DatabaseInfo = info; romData.Info.DatabaseInfo = info;
} }
void GameDatabase::UpdateRomData(GameInfo &info, RomData &romData) void GameDatabase::UpdateRomData(GameInfo &info, RomData &romData)
{ {
romData.MapperID = info.MapperID; romData.Info.MapperID = info.MapperID;
romData.System = GetGameSystem(info.System); romData.Info.System = GetGameSystem(info.System);
romData.SubMapperID = GetSubMapper(info); if(romData.Info.System == GameSystem::VsSystem) {
romData.BusConflicts = GetBusConflictType(info.BusConflicts); 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) { if(info.ChrRamSize > 0) {
romData.ChrRamSize = info.ChrRamSize * 1024; romData.ChrRamSize = info.ChrRamSize * 1024;
} }
@ -506,14 +568,14 @@ void GameDatabase::UpdateRomData(GameInfo &info, RomData &romData)
if(info.SaveRamSize > 0) { if(info.SaveRamSize > 0) {
romData.SaveRamSize = info.SaveRamSize * 1024; romData.SaveRamSize = info.SaveRamSize * 1024;
} }
romData.HasBattery |= info.HasBattery; romData.Info.HasBattery |= info.HasBattery;
if(!info.Mirroring.empty()) { if(!info.Mirroring.empty()) {
switch(info.Mirroring[0]) { switch(info.Mirroring[0]) {
case 'h': romData.Mirroring = MirroringType::Horizontal; break; case 'h': romData.Info.Mirroring = MirroringType::Horizontal; break;
case 'v': romData.Mirroring = MirroringType::Vertical; break; case 'v': romData.Info.Mirroring = MirroringType::Vertical; break;
case '4': romData.Mirroring = MirroringType::FourScreens; break; case '4': romData.Info.Mirroring = MirroringType::FourScreens; break;
case 'a': romData.Mirroring = MirroringType::ScreenAOnly; break; case 'a': romData.Info.Mirroring = MirroringType::ScreenAOnly; break;
} }
} }
} }
@ -526,44 +588,11 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
uint8_t defaultDip = 0; uint8_t defaultDip = 0;
switch(prgCrc32) { 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: case 0x8850924B:
//Tetris //Tetris
model = PpuModel::Ppu2C03; defaultDip = 32; //????
inputType = VsInputType::SwapControllers;
defaultDip = 32;
break; break;
case 0x8C0C2DF5:
//TopGun
model = PpuModel::Ppu2C05D;
break;
case 0x70901B25:
//Slalom
model = PpuModel::Ppu2C04B;
break;
case 0xCF36261E: case 0xCF36261E:
//SuperSkyKid //SuperSkyKid
@ -573,40 +602,7 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
case 0xE1AA8214: case 0xE1AA8214:
//StarLuster //StarLuster
model = PpuModel::Ppu2C04A; defaultDip = 32; //????
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;
break; break;
case 0x43A357EF: case 0x43A357EF:
@ -621,65 +617,21 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
model = PpuModel::Ppu2C04D; model = PpuModel::Ppu2C04D;
break; break;
case 0x737DD1BF: case 0x4BF3972D: case 0x8B60CC58: case 0x8192C804: case 0x737DD1BF: case 0x4BF3972D:
//SuperMarioBros //SuperMarioBros
model = PpuModel::Ppu2C04D; model = PpuModel::Ppu2C04D;
break; break;
case 0xE528F651:
//Pinball
inputType = VsInputType::SwapAB;
model = PpuModel::Ppu2C03;
break;
case 0xEC461DB9:
//PinballB
model = PpuModel::Ppu2C04A;
break;
case 0xAE8063EF: case 0xAE8063EF:
//MachRiderFightingCourse, defaults //MachRiderFightingCourse, defaults
model = PpuModel::Ppu2C03; model = PpuModel::Ppu2C03;
break; break;
case 0x0B65A917: case 0x8A6A9848: case 0x8A6A9848: //1 crc left
//MachRider //MachRider
model = PpuModel::Ppu2C04B; model = PpuModel::Ppu2C04B;
break; 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: case 0xC99EC059:
//RaidBungelingBay //RaidBungelingBay
inputType = VsInputType::SwapControllers; inputType = VsInputType::SwapControllers;
@ -690,28 +642,6 @@ void GameDatabase::SetVsSystemDefaults(uint32_t prgCrc32)
//SuperXevious //SuperXevious
model = PpuModel::Ppu2C04A; model = PpuModel::Ppu2C04A;
break; 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); EmulationSettings::SetPpuModel(model);

View file

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

View file

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

View file

@ -40,7 +40,7 @@ HdPackBuilder::HdPackBuilder(shared_ptr<Console> console, string saveFolder, Sca
_hdData.Scale = scale; _hdData.Scale = scale;
} }
_romName = FolderUtilities::GetFilename(_console->GetMapperInfo().RomName, false); _romName = FolderUtilities::GetFilename(_console->GetRomInfo().RomName, false);
_instance = this; _instance = this;
} }
@ -222,7 +222,7 @@ void HdPackBuilder::SaveHdPack()
int pngIndex = 0; int pngIndex = 0;
ss << "<ver>" << std::to_string(HdNesPack::CurrentVersion) << std::endl; ss << "<ver>" << std::to_string(HdNesPack::CurrentVersion) << std::endl;
ss << "<scale>" << _hdData.Scale << 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) { if(_flags & HdPackRecordFlags::IgnoreOverscan) {
OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions(); OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
ss << "<overscan>" << overscan.Top << "," << overscan.Right << "," << overscan.Bottom << "," << overscan.Left << std::endl; 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(2, -2);
SelectPRGPage(3, -1); SelectPRGPage(3, -1);
if(_subMapperID == 1) { if(_romInfo.SubMapperID == 1) {
//032: 1 Major League //032: 1 Major League
//CIRAM A10 is tied high (fixed one-screen mirroring) and PRG banking style is fixed as 8+8+16F //CIRAM A10 is tied high (fixed one-screen mirroring) and PRG banking style is fixed as 8+8+16F
SetMirroringType(MirroringType::ScreenAOnly); SetMirroringType(MirroringType::ScreenAOnly);
@ -57,7 +57,7 @@ class IremG101 : public BaseMapper
break; break;
case 0x9000: case 0x9000:
_prgMode = (value & 0x02) >> 1; _prgMode = (value & 0x02) >> 1;
if(_subMapperID == 1) { if(_romInfo.SubMapperID == 1) {
_prgMode = 0; _prgMode = 0;
} }
UpdatePrgMode(); UpdatePrgMode();

View file

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

View file

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

View file

@ -20,6 +20,7 @@
#include "CheatManager.h" #include "CheatManager.h"
#include "KeyManager.h" #include "KeyManager.h"
#include "MemoryAccessCounter.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_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); #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); LuaCallHelper l(lua);
checkparams(); checkparams();
MapperInfo mapperInfo = _console->GetMapperInfo(); RomInfo romInfo = _console->GetRomInfo();
string romPath = _console->GetRomPath(); string romPath = _console->GetRomPath();
lua_newtable(lua); lua_newtable(lua);
lua_pushstringvalue(name, mapperInfo.RomName); lua_pushstringvalue(name, romInfo.RomName);
lua_pushstringvalue(path, romPath); lua_pushstringvalue(path, romPath);
HashInfo hashInfo = mapperInfo.Hash; lua_pushintvalue(fileCrc32Hash, romInfo.Hash.Crc32);
lua_pushintvalue(fileCrc32Hash, hashInfo.Crc32Hash); lua_pushstringvalue(fileSha1Hash, romInfo.Hash.Sha1);
lua_pushstringvalue(fileSha1Hash, hashInfo.Sha1Hash); lua_pushintvalue(prgChrCrc32Hash, romInfo.Hash.PrgCrc32);
lua_pushintvalue(prgChrCrc32Hash, hashInfo.PrgCrc32Hash); lua_pushstringvalue(prgChrMd5Hash, romInfo.Hash.PrgChrMd5);
lua_pushstringvalue(prgChrMd5Hash, hashInfo.PrgChrMd5Hash); lua_pushintvalue(format, romInfo.Format);
lua_pushintvalue(format, mapperInfo.Format); lua_pushboolvalue(isChrRam, romInfo.HasChrRam);
lua_pushboolvalue(isChrRam, mapperInfo.UsesChrRam);
return 1; return 1;
} }

View file

@ -138,7 +138,7 @@ class MMC1 : public BaseMapper
} }
} }
if(_subMapperID == 5) { if(_romInfo.SubMapperID == 5) {
//SubMapper 5 //SubMapper 5
//"001: 5 Fixed PRG SEROM, SHROM, SH1ROM use a fixed 32k PRG ROM with no banking support. //"001: 5 Fixed PRG SEROM, SHROM, SH1ROM use a fixed 32k PRG ROM with no banking support.
SelectPrgPage2x(0, 0); 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.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.RegA000 = GetPowerOnByte();
_state.RegC000 = 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 //"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; _lastChrReg = MMC1Registers::RegA000;

View file

@ -39,7 +39,7 @@ class MMC3 : public BaseMapper
bool IsMcAcc() bool IsMcAcc()
{ {
return _mapperID == 4 && _subMapperID == 3; return _romInfo.MapperID == 4 && _romInfo.SubMapperID == 3;
} }
protected: protected:
@ -157,7 +157,7 @@ class MMC3 : public BaseMapper
_chrMode = (_state.Reg8000 & 0x80) >> 7; _chrMode = (_state.Reg8000 & 0x80) >> 7;
_prgMode = (_state.Reg8000 & 0x40) >> 6; _prgMode = (_state.Reg8000 & 0x40) >> 6;
if(_subMapperID == 1) { if(_romInfo.SubMapperID == 1) {
//bool wramEnabled = (_state.Reg8000 & 0x20) == 0x20; //bool wramEnabled = (_state.Reg8000 & 0x20) == 0x20;
RemoveCpuMemoryMapping(0x6000, 0x7000); RemoveCpuMemoryMapping(0x6000, 0x7000);
@ -172,7 +172,7 @@ class MMC3 : public BaseMapper
_wramEnabled = (_state.RegA001 & 0x80) == 0x80; _wramEnabled = (_state.RegA001 & 0x80) == 0x80;
_wramWriteProtected = (_state.RegA001 & 0x40) == 0x40; _wramWriteProtected = (_state.RegA001 & 0x40) == 0x40;
if(IsNes20() && _subMapperID == 0) { if(IsNes20() && _romInfo.SubMapperID == 0) {
if(_wramEnabled) { if(_wramEnabled) {
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam, CanWriteToWorkRam() ? MemoryAccessType::ReadWrite : MemoryAccessType::Read); SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam, CanWriteToWorkRam() ? MemoryAccessType::ReadWrite : MemoryAccessType::Read);
} else { } else {
@ -202,14 +202,14 @@ class MMC3 : public BaseMapper
virtual uint16_t GetPRGPageSize() override { return 0x2000; } virtual uint16_t GetPRGPageSize() override { return 0x2000; }
virtual uint16_t GetCHRPageSize() override { return 0x0400; } virtual uint16_t GetCHRPageSize() override { return 0x0400; }
virtual uint32_t GetSaveRamPageSize() override { return _subMapperID == 1 ? 0x200 : 0x2000; } virtual uint32_t GetSaveRamPageSize() override { return _romInfo.SubMapperID == 1 ? 0x200 : 0x2000; }
virtual uint32_t GetSaveRamSize() override { return _subMapperID == 1 ? 0x400 : 0x2000; } virtual uint32_t GetSaveRamSize() override { return _romInfo.SubMapperID == 1 ? 0x400 : 0x2000; }
virtual void InitMapper() override virtual void InitMapper() override
{ {
//Force MMC3A irqs for boards that are known to use the A revision. //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. //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(); ResetMmc3();
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam); SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam);

View file

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

View file

@ -12,7 +12,7 @@ protected:
SelectPRGPage(0, 0); SelectPRGPage(0, 0);
if(GetMirroringType() == MirroringType::FourScreens) { 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) BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
{ {
#ifdef _DEBUG #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 #endif
switch(romData.MapperID) { switch(romData.Info.MapperID) {
case 0: return new NROM(); case 0: return new NROM();
case 1: return new MMC1(); case 1: return new MMC1();
case 2: return new UNROM(); case 2: return new UNROM();
@ -336,7 +336,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
case 32: return new IremG101(); case 32: return new IremG101();
case 33: return new TaitoTc0190(); case 33: return new TaitoTc0190();
case 34: 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 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 1: return new Nina01();
case 2: return new BnRom(); case 2: return new BnRom();
@ -609,8 +609,8 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
case MapperFactory::FdsMapperID: return new FDS(); case MapperFactory::FdsMapperID: return new FDS();
} }
if(romData.MapperID != UnifBoards::UnknownBoard) { if(romData.Info.MapperID != UnifBoards::UnknownBoard) {
MessageManager::DisplayMessage("Error", "UnsupportedMapper", "iNES #" + std::to_string(romData.MapperID)); MessageManager::DisplayMessage("Error", "UnsupportedMapper", "iNES #" + std::to_string(romData.Info.MapperID));
} }
return nullptr; return nullptr;
} }

View file

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

View file

@ -10,6 +10,7 @@
#include "VirtualFile.h" #include "VirtualFile.h"
#include "SaveStateManager.h" #include "SaveStateManager.h"
#include "NotificationManager.h" #include "NotificationManager.h"
#include "RomData.h"
MovieRecorder::MovieRecorder(shared_ptr<Console> console) MovieRecorder::MovieRecorder(shared_ptr<Console> console)
{ {
@ -77,7 +78,7 @@ void MovieRecorder::GetGameSettings(stringstream &out)
if(patchFile.IsValid()) { if(patchFile.IsValid()) {
WriteString(out, MovieKeys::PatchFile, patchFile.GetFileName()); WriteString(out, MovieKeys::PatchFile, patchFile.GetFileName());
WriteString(out, MovieKeys::PatchFileSha1, patchFile.GetSha1Hash()); WriteString(out, MovieKeys::PatchFileSha1, patchFile.GetSha1Hash());
WriteString(out, MovieKeys::PatchedRomSha1, _console->GetMapperInfo().Hash.Sha1Hash); WriteString(out, MovieKeys::PatchedRomSha1, _console->GetRomInfo().Hash.Sha1);
} }
switch(model) { 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)); _audio.reset(new Namco163Audio(_console));
switch(_mapperID) { switch(_romInfo.MapperID) {
case 19: case 19:
_variant = NamcoVariant::Namco163; _variant = NamcoVariant::Namco163;
if(_databaseInfo.Board == "NAMCOT-163") { if(_romInfo.DatabaseInfo.Board == "NAMCOT-163") {
_variant = NamcoVariant::Namco163; _variant = NamcoVariant::Namco163;
_autoDetectVariant = false; _autoDetectVariant = false;
} else if(_databaseInfo.Board == "NAMCOT-175") { } else if(_romInfo.DatabaseInfo.Board == "NAMCOT-175") {
_variant = NamcoVariant::Namco175; _variant = NamcoVariant::Namco175;
_autoDetectVariant = false; _autoDetectVariant = false;
} else if(_databaseInfo.Board == "NAMCOT-340") { } else if(_romInfo.DatabaseInfo.Board == "NAMCOT-340") {
_variant = NamcoVariant::Namco340; _variant = NamcoVariant::Namco340;
_autoDetectVariant = false; _autoDetectVariant = false;
} else { } else {
@ -76,7 +76,7 @@ protected:
} }
break; break;
case 210: case 210:
switch(_subMapperID) { switch(_romInfo.SubMapperID) {
case 0: _variant = NamcoVariant::Unknown; _autoDetectVariant = true; break; case 0: _variant = NamcoVariant::Unknown; _autoDetectVariant = true; break;
case 1: _variant = NamcoVariant::Namco175; _autoDetectVariant = false; break; case 1: _variant = NamcoVariant::Namco175; _autoDetectVariant = false; break;
case 2: _variant = NamcoVariant::Namco340; _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; 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.Info.Format = RomFormat::Nsf;
romData.MapperID = MapperFactory::NsfMapperID; romData.Info.MapperID = MapperFactory::NsfMapperID;
if(header.LoadAddress < 0x6000 || header.TotalSongs == 0) { if(header.LoadAddress < 0x6000 || header.TotalSongs == 0) {
romData.Error = true; romData.Error = true;
} }
if(header.Flags == 0x01) { if(header.Flags == 0x01) {
romData.System = GameSystem::NesPal; romData.Info.System = GameSystem::NesPal;
} }
if(header.PlaySpeedNtsc == 0) { if(header.PlaySpeedNtsc == 0) {
@ -119,7 +119,7 @@ void NsfLoader::InitHeader(NsfHeader & header)
RomData NsfLoader::LoadRom(vector<uint8_t>& romFile) RomData NsfLoader::LoadRom(vector<uint8_t>& romFile)
{ {
RomData romData; RomData romData;
NsfHeader &header = romData.NsfInfo; NsfHeader &header = romData.Info.NsfInfo;
InitHeader(header); InitHeader(header);

View file

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

View file

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

View file

@ -2,6 +2,7 @@
#include "stdafx.h" #include "stdafx.h"
#include <cmath> #include <cmath>
#include "Types.h" #include "Types.h"
#include "NESHeader.h"
enum class RomHeaderVersion enum class RomHeaderVersion
{ {
@ -10,200 +11,6 @@ enum class RomHeaderVersion
OldiNes = 2 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 struct NsfHeader
{ {
char Header[5]; char Header[5];
@ -248,29 +55,47 @@ struct GameInfo
string InputType; string InputType;
string BusConflicts; string BusConflicts;
string SubmapperID; string SubmapperID;
string VsSystemType;
string PpuModel;
}; };
struct RomData struct RomInfo
{ {
string RomName; string RomName;
string Filename; string Filename;
RomFormat Format; RomFormat Format;
bool IsNes20Header = false;
uint16_t MapperID = 0; uint16_t MapperID = 0;
uint8_t SubMapperID = 0; uint8_t SubMapperID = 0;
GameSystem System = GameSystem::Unknown; GameSystem System = GameSystem::Unknown;
VsSystemType VsSystemType = VsSystemType::Default;
PpuModel PpuModel = PpuModel::Ppu2C02;
bool HasChrRam = false;
bool HasBattery = false; bool HasBattery = false;
bool HasTrainer = false; bool HasTrainer = false;
MirroringType Mirroring = MirroringType::Horizontal; MirroringType Mirroring = MirroringType::Horizontal;
BusConflictType BusConflicts = BusConflictType::Default; BusConflictType BusConflicts = BusConflictType::Default;
HashInfo Hash;
NESHeader NesHeader;
NsfHeader NsfInfo;
GameInfo DatabaseInfo;
};
struct RomData
{
RomInfo Info;
int32_t ChrRamSize = -1; int32_t ChrRamSize = -1;
int32_t SaveChrRamSize = -1; int32_t SaveChrRamSize = -1;
int32_t SaveRamSize = -1; int32_t SaveRamSize = -1;
int32_t WorkRamSize = -1; int32_t WorkRamSize = -1;
bool IsNes20Header = false;
vector<uint8_t> PrgRom; vector<uint8_t> PrgRom;
vector<uint8_t> ChrRom; vector<uint8_t> ChrRom;
vector<uint8_t> TrainerData; vector<uint8_t> TrainerData;
@ -278,16 +103,8 @@ struct RomData
vector<vector<uint8_t>> FdsDiskHeaders; vector<vector<uint8_t>> FdsDiskHeaders;
vector<uint8_t> RawData; vector<uint8_t> RawData;
string Sha1;
string PrgChrMd5;
uint32_t Crc32 = 0;
uint32_t PrgCrc32 = 0;
uint32_t PrgChrCrc32 = 0;
bool Error = false; bool Error = false;
bool BiosMissing = 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.Info.Hash.Crc32 = crc;
_romData.Sha1 = SHA1::GetHash(fileData); _romData.Info.Hash.Sha1 = SHA1::GetHash(fileData);
_romData.RawData = fileData; _romData.RawData = fileData;
_romData.RomName = romName; _romData.Info.RomName = romName;
_romData.Filename = _filename; _romData.Info.Filename = _filename;
if(_romData.System == GameSystem::Unknown) { if(_romData.Info.System == GameSystem::Unknown) {
//Use filename to detect PAL/VS system games //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); 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 || 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) { 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) { } 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); RomLoader loader(true);
vector<uint8_t> fileData; vector<uint8_t> fileData;
if(loader.LoadFile(filePath)) { 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); return VirtualFile(filePath, file);
} }
} }
@ -112,7 +112,7 @@ string RomLoader::FindMatchingRomInFile(string filePath, HashInfo hashInfo)
RomLoader loader(true); RomLoader loader(true);
vector<uint8_t> fileData; vector<uint8_t> fileData;
if(loader.LoadFile(filePath)) { 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; return filePath;
} }
} }

View file

@ -9,6 +9,7 @@
#include "VideoDecoder.h" #include "VideoDecoder.h"
#include "Debugger.h" #include "Debugger.h"
#include "MovieManager.h" #include "MovieManager.h"
#include "RomData.h"
SaveStateManager::SaveStateManager(shared_ptr<Console> console) SaveStateManager::SaveStateManager(shared_ptr<Console> console)
{ {
@ -19,7 +20,7 @@ SaveStateManager::SaveStateManager(shared_ptr<Console> console)
string SaveStateManager::GetStateFilepath(int stateIndex) string SaveStateManager::GetStateFilepath(int stateIndex)
{ {
string folder = FolderUtilities::GetSaveStateFolder(); 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); return FolderUtilities::CombinePath(folder, filename);
} }
@ -65,14 +66,14 @@ void SaveStateManager::SaveState(ostream &stream)
stream.write((char*)&emuVersion, sizeof(emuVersion)); stream.write((char*)&emuVersion, sizeof(emuVersion));
stream.write((char*)&formatVersion, sizeof(uint32_t)); stream.write((char*)&formatVersion, sizeof(uint32_t));
MapperInfo mapperInfo = _console->GetMapperInfo(); RomInfo romInfo = _console->GetRomInfo();
stream.write((char*)&mapperInfo.MapperId, sizeof(uint16_t)); stream.write((char*)&romInfo.MapperID, sizeof(uint16_t));
stream.write((char*)&mapperInfo.SubMapperId, sizeof(uint8_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()); stream.write(sha1Hash.c_str(), sha1Hash.size());
string romName = mapperInfo.RomName; string romName = romInfo.RomName;
uint32_t nameLength = (uint32_t)romName.size(); uint32_t nameLength = (uint32_t)romName.size();
stream.write((char*)&nameLength, sizeof(uint32_t)); stream.write((char*)&nameLength, sizeof(uint32_t));
stream.write(romName.c_str(), romName.size()); stream.write(romName.c_str(), romName.size());
@ -156,16 +157,16 @@ bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
stream.read(nameBuffer.data(), nameBuffer.size()); stream.read(nameBuffer.data(), nameBuffer.size());
string romName(nameBuffer.data(), nameLength); string romName(nameBuffer.data(), nameLength);
MapperInfo mapperInfo = _console->GetMapperInfo(); RomInfo romInfo = _console->GetRomInfo();
bool gameLoaded = !mapperInfo.Hash.Sha1Hash.empty(); bool gameLoaded = !romInfo.Hash.Sha1.empty();
if(mapperInfo.Hash.Sha1Hash != string(hash)) { if(romInfo.Hash.Sha1 != string(hash)) {
//CRC doesn't match //CRC doesn't match
if(!EmulationSettings::CheckFlag(EmulationFlags::AllowMismatchingSaveState) || !gameLoaded || 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 //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; HashInfo info;
info.Sha1Hash = hash; info.Sha1 = hash;
if(!_console->LoadMatchingRom(romName, info)) { if(!_console->LoadMatchingRom(romName, info)) {
MessageManager::DisplayMessage("SaveStates", "SaveStateMissingRom", romName); MessageManager::DisplayMessage("SaveStates", "SaveStateMissingRom", romName);
return false; return false;
@ -221,8 +222,8 @@ bool SaveStateManager::LoadState(int stateIndex)
void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath) void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath)
{ {
if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && !EmulationSettings::CheckFlag(EmulationFlags::DisableGameSelectionScreen) && _console->GetMapperInfo().Format != RomFormat::Nsf) { if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && !EmulationSettings::CheckFlag(EmulationFlags::DisableGameSelectionScreen) && _console->GetRomInfo().Format != RomFormat::Nsf) {
string filename = FolderUtilities::GetFilename(_console->GetMapperInfo().RomName, false) + ".rgd"; string filename = FolderUtilities::GetFilename(_console->GetRomInfo().RomName, false) + ".rgd";
ZipWriter writer; ZipWriter writer;
writer.Initialize(FolderUtilities::CombinePath(FolderUtilities::GetRecentGamesFolder(), filename)); 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 outerBank = ((_regs[0] ^ _regs[1]) & 0x10) << 1;
uint8_t innerBank = _regs[2] ^ _regs[3]; uint8_t innerBank = _regs[2] ^ _regs[3];
bool altMode = _mapperID == 167; bool altMode = _romInfo.MapperID == 167;
if(_regs[1] & 0x08) { if(_regs[1] & 0x08) {
//32 KiB NROM //32 KiB NROM

View file

@ -18,7 +18,7 @@ protected:
//This cart appears to behave differently (maybe not an identical mapper?) //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) //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 virtual void StreamState(bool saving) override

View file

@ -315,8 +315,7 @@ enum class GameSystem
NesPal, NesPal,
Famicom, Famicom,
Dendy, Dendy,
VsUniSystem, VsSystem,
VsDualSystem,
Playchoice, Playchoice,
FDS, FDS,
Unknown, Unknown,
@ -331,11 +330,11 @@ enum class BusConflictType
struct HashInfo struct HashInfo
{ {
uint32_t Crc32Hash = 0; uint32_t Crc32 = 0;
uint32_t PrgCrc32Hash = 0; uint32_t PrgCrc32 = 0;
uint32_t PrgChrCrc32Hash = 0; uint32_t PrgChrCrc32 = 0;
string Sha1Hash; string Sha1;
string PrgChrMd5Hash; string PrgChrMd5;
}; };
enum class RomFormat enum class RomFormat
@ -347,14 +346,29 @@ enum class RomFormat
Nsf = 4, Nsf = 4,
}; };
struct MapperInfo enum class VsSystemType
{ {
string RomName; Default = 0,
RomFormat Format; RbiBaseballProtection = 1,
GameSystem System; TkoBoxingProtection = 2,
uint16_t MapperId; SuperXeviousProtection = 3,
uint8_t SubMapperId; IceClimberProtection = 4,
VsDualSystem = 5,
HashInfo Hash; RaidOnBungelingBayProtection = 6,
bool UsesChrRam;
}; };
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); 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 void WriteRegister(uint16_t addr, uint8_t value) override
{ {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -23,28 +23,25 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader
dataSize -= sizeof(NESHeader); 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.ChrRamSize = header.GetChrRamSize();
romData.SaveChrRamSize = header.GetSaveChrRamSize(); romData.SaveChrRamSize = header.GetSaveChrRamSize();
romData.WorkRamSize = header.GetWorkRamSize(); romData.WorkRamSize = header.GetWorkRamSize();
romData.SaveRamSize = header.GetSaveRamSize(); romData.SaveRamSize = header.GetSaveRamSize();
romData.NesHeader = header;
if(romData.HasTrainer) { if(romData.Info.HasTrainer) {
//512-byte trainer at $7000-$71FF (stored before PRG data) //512-byte trainer at $7000-$71FF (stored before PRG data)
romData.TrainerData.insert(romData.TrainerData.end(), buffer, buffer + 512); romData.TrainerData.insert(romData.TrainerData.end(), buffer, buffer + 512);
buffer += 512; buffer += 512;
@ -53,13 +50,13 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader
size_t bytesRead = buffer - romFile.data(); size_t bytesRead = buffer - romFile.data();
uint32_t romCrc = CRC32::GetCRC(buffer, romFile.size() - bytesRead); uint32_t romCrc = CRC32::GetCRC(buffer, romFile.size() - bytesRead);
romData.PrgChrCrc32 = romCrc; romData.Info.Hash.PrgChrCrc32 = romCrc;
romData.PrgChrMd5 = GetMd5Sum(buffer, romFile.size() - bytesRead); romData.Info.Hash.PrgChrMd5 = GetMd5Sum(buffer, romFile.size() - bytesRead);
uint32_t prgSize = 0; uint32_t prgSize = 0;
uint32_t chrSize = 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) //Fallback on header sizes when game is not in DB (or DB is disabled)
prgSize = header.GetPrgSize(); prgSize = header.GetPrgSize();
chrSize = header.GetChrSize(); chrSize = header.GetChrSize();
@ -75,37 +72,51 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader
buffer += prgSize; buffer += prgSize;
romData.ChrRom.insert(romData.ChrRom.end(), buffer, buffer + chrSize); 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 CRC32: 0x" + HexUtilities::ToHex(romData.Info.Hash.PrgCrc32, true));
Log("PRG+CHR CRC32: 0x" + HexUtilities::ToHex(romData.PrgChrCrc32, 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] 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] PRG ROM: " + std::to_string(romData.PrgRom.size()/1024) + " KB");
Log("[iNes] CHR ROM: " + std::to_string(romData.ChrRom.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"); Log("[iNes] CHR RAM: " + std::to_string(romData.ChrRamSize / 1024) + " KB");
} else if(romData.ChrRom.size() == 0) { } else if(romData.ChrRom.size() == 0) {
Log("[iNes] CHR RAM: 8 KB"); 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"); 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] 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] Mirroring: " + string(romData.Info.Mirroring == MirroringType::Horizontal ? "Horizontal" : romData.Info.Mirroring == MirroringType::Vertical ? "Vertical" : "Four Screens"));
Log("[iNes] Battery: " + string(romData.HasBattery ? "Yes" : "No")); Log("[iNes] Battery: " + string(romData.Info.HasBattery ? "Yes" : "No"));
if(romData.HasTrainer) { if(romData.Info.HasTrainer) {
Log("[iNes] Trainer: Yes"); Log("[iNes] Trainer: Yes");
} }
if(!_checkOnly) { 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; 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; const char* RomName;
uint32_t Crc32; 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; string romPath = filename;
if(romPath.empty()) { if(romPath.empty()) {
_returnString = _console->GetRomPath(); _returnString = _console->GetRomPath();
romInfo.RomName = _returnString.c_str(); interopRomInfo.RomName = _returnString.c_str();
MapperInfo mapperInfo = _console->GetMapperInfo(); RomInfo romInfo = _console->GetRomInfo();
romInfo.Crc32 = mapperInfo.Hash.Crc32Hash; interopRomInfo.Crc32 = romInfo.Hash.Crc32;
romInfo.PrgCrc32 = mapperInfo.Hash.PrgCrc32Hash; interopRomInfo.PrgCrc32 = romInfo.Hash.PrgCrc32;
romInfo.Format = mapperInfo.Format; interopRomInfo.Format = romInfo.Format;
romInfo.IsChrRam = mapperInfo.UsesChrRam; interopRomInfo.IsChrRam = romInfo.HasChrRam;
romInfo.MapperId = mapperInfo.MapperId; interopRomInfo.MapperId = romInfo.MapperID;
if(mapperInfo.Hash.Sha1Hash.size() == 40) { if(romInfo.Hash.Sha1.size() == 40) {
memcpy(romInfo.Sha1, mapperInfo.Hash.Sha1Hash.c_str(), 40); memcpy(interopRomInfo.Sha1, romInfo.Hash.Sha1.c_str(), 40);
} }
} else { } else {
RomLoader romLoader(true); RomLoader romLoader(true);
@ -297,23 +297,23 @@ namespace InteropEmu {
RomData romData = romLoader.GetRomData(); RomData romData = romLoader.GetRomData();
_returnString = romPath; _returnString = romPath;
romInfo.RomName = _returnString.c_str(); interopRomInfo.RomName = _returnString.c_str();
romInfo.Crc32 = romData.Crc32; interopRomInfo.Crc32 = romData.Info.Hash.Crc32;
romInfo.PrgCrc32 = romData.PrgCrc32; interopRomInfo.PrgCrc32 = romData.Info.Hash.PrgCrc32;
romInfo.Format = RomFormat::Unknown; interopRomInfo.Format = RomFormat::Unknown;
romInfo.IsChrRam = romData.ChrRom.size() == 0; interopRomInfo.IsChrRam = romData.ChrRom.size() == 0;
romInfo.MapperId = 0; interopRomInfo.MapperId = 0;
if(romData.Sha1.size() == 40) { if(romData.Info.Hash.Sha1.size() == 40) {
memcpy(romInfo.Sha1, romData.Sha1.c_str(), 40); memcpy(interopRomInfo.Sha1, romData.Info.Hash.Sha1.c_str(), 40);
} }
} else { } else {
_returnString = ""; _returnString = "";
romInfo.RomName = _returnString.c_str(); interopRomInfo.RomName = _returnString.c_str();
romInfo.Crc32 = 0; interopRomInfo.Crc32 = 0;
romInfo.PrgCrc32 = 0; interopRomInfo.PrgCrc32 = 0;
romInfo.Format = RomFormat::Unknown; interopRomInfo.Format = RomFormat::Unknown;
romInfo.IsChrRam = false; interopRomInfo.IsChrRam = false;
romInfo.MapperId = 0; interopRomInfo.MapperId = 0;
} }
} }
} }

View file

@ -76,6 +76,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
$(CORE_DIR)/MessageManager.cpp \ $(CORE_DIR)/MessageManager.cpp \
$(CORE_DIR)/MovieManager.cpp \ $(CORE_DIR)/MovieManager.cpp \
$(CORE_DIR)/MovieRecorder.cpp \ $(CORE_DIR)/MovieRecorder.cpp \
$(CORE_DIR)/NESHeader.cpp \
$(CORE_DIR)/NotificationManager.cpp \ $(CORE_DIR)/NotificationManager.cpp \
$(CORE_DIR)/NsfLoader.cpp \ $(CORE_DIR)/NsfLoader.cpp \
$(CORE_DIR)/NsfMapper.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() void update_core_controllers()
{ {
//Setup all "auto" ports //Setup all "auto" ports
GameDatabase::InitializeInputDevices(_console->GetMapperInfo().Hash.PrgChrCrc32Hash); GameDatabase::InitializeInputDevices(_console->GetRomInfo().Hash.PrgChrCrc32);
//TODO: Four Score //TODO: Four Score