Game DB: Added a game database (mix of Nestopia's DB and NesCartDB) - used to correct invalid ROM headers and automatically detect NES 2.0 submappers

This commit is contained in:
Souryo 2016-06-15 21:59:34 -04:00
parent 756c3df5ce
commit 941d3884ef
22 changed files with 3324 additions and 135 deletions

View file

@ -354,8 +354,7 @@ void BaseMapper::Initialize(RomData &romData)
}
_hasBattery = romData.HasBattery || ForceBattery();
_isPalRom = romData.IsPalRom;
_isVsSystem = romData.IsVsSystem;
_gameSystem = romData.System;
_crc32 = romData.Crc32;
_hasBusConflicts = HasBusConflicts();
@ -453,7 +452,7 @@ void BaseMapper::ApplyCheats()
void BaseMapper::GetMemoryRanges(MemoryRanges &ranges)
{
if(IsVsSystem()) {
if(_gameSystem == GameSystem::VsUniSystem) {
ranges.AddHandler(MemoryOperation::Read, 0x6000, 0xFFFF);
ranges.AddHandler(MemoryOperation::Write, 0x6000, 0xFFFF);
} else {
@ -518,14 +517,9 @@ void BaseMapper::SetMirroringType(MirroringType type)
}
}
bool BaseMapper::IsPalRom()
GameSystem BaseMapper::GetGameSystem()
{
return _isPalRom;
}
bool BaseMapper::IsVsSystem()
{
return _isVsSystem;
return _gameSystem;
}
uint32_t BaseMapper::GetCrc32()

View file

@ -52,8 +52,7 @@ private:
uint8_t _nametableIndexes[4];
bool _onlyChrRam = false;
bool _isPalRom = false;
bool _isVsSystem = false;
GameSystem _gameSystem;
bool _hasBusConflicts = false;
string _romFilename;
@ -169,8 +168,7 @@ public:
void SetDefaultNametables(uint8_t* nametableA, uint8_t* nametableB);
bool IsPalRom();
bool IsVsSystem();
GameSystem GetGameSystem();
uint32_t GetCrc32();
uint8_t ReadRAM(uint16_t addr);

View file

@ -56,7 +56,7 @@ void Console::Initialize(string romFilename, stringstream *filestream, string ip
}
_apu.reset(new APU(_memoryManager.get()));
_controlManager.reset(_mapper->IsVsSystem() ? new VsControlManager() : new ControlManager());
_controlManager.reset(_mapper->GetGameSystem() == GameSystem::VsUniSystem ? new VsControlManager() : new ControlManager());
_memoryManager->RegisterIODevice(_mapper.get());
_memoryManager->RegisterIODevice(_ppu.get());
@ -311,7 +311,11 @@ double Console::UpdateNesModel(bool sendNotification)
NesModel model = EmulationSettings::GetNesModel();
uint32_t emulationSpeed = EmulationSettings::GetEmulationSpeed();
if(model == NesModel::Auto) {
model = _mapper->IsPalRom() ? NesModel::PAL : NesModel::NTSC;
switch(_mapper->GetGameSystem()) {
case GameSystem::NesPal: model = NesModel::PAL; break;
case GameSystem::Dendy: model = NesModel::Dendy; break;
default: model = NesModel::NTSC; break;
}
}
if(_model != model) {
_model = model;

View file

@ -402,6 +402,7 @@
<ClInclude Include="FdsLoader.h" />
<ClInclude Include="ForceDisconnectMessage.h" />
<ClInclude Include="FrontFareast.h" />
<ClInclude Include="GameDatabase.h" />
<ClInclude Include="HdVideoFilter.h" />
<ClInclude Include="iNesLoader.h" />
<ClInclude Include="IremH3001.h" />
@ -591,6 +592,7 @@
<ClCompile Include="GameClient.cpp" />
<ClCompile Include="GameClientConnection.cpp" />
<ClCompile Include="GameConnection.cpp" />
<ClCompile Include="GameDatabase.cpp" />
<ClCompile Include="GameServer.cpp" />
<ClCompile Include="GameServerConnection.cpp" />
<ClCompile Include="HdVideoFilter.cpp" />

View file

@ -628,6 +628,9 @@
<ClInclude Include="FrontFareast.h">
<Filter>Nes\Mappers</Filter>
</ClInclude>
<ClInclude Include="GameDatabase.h">
<Filter>Nes\RomLoader</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -783,5 +786,8 @@
<ClCompile Include="iNesLoader.cpp">
<Filter>Nes\RomLoader</Filter>
</ClCompile>
<ClCompile Include="GameDatabase.cpp">
<Filter>Nes\RomLoader</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -26,6 +26,8 @@ enum EmulationFlags
SwapDutyCycles = 0x10000,
DisableGameDatabase = 0x20000,
InBackground = 0x40000000,
};

View file

@ -156,6 +156,7 @@ public:
romData.MapperID = MapperFactory::FdsMapperID;
romData.MirroringType = MirroringType::Vertical;
romData.PrgRom = LoadBios();
romData.System = GameSystem::FDS;
if(romData.PrgRom.size() != 0x2000) {
romData.Error = true;

167
Core/GameDatabase.cpp Normal file
View file

@ -0,0 +1,167 @@
#pragma once
#include "stdafx.h"
#include "RomData.h"
#include "MessageManager.h"
#include "../Utilities/CRC32.h"
#include "GameDatabase.h"
std::unordered_map<uint32_t, GameInfo> GameDatabase::_gameDatabase;
template<typename T>
T GameDatabase::ToInt(string value)
{
if(value.empty()) {
return 0;
}
return std::stoi(value);
}
vector<string> GameDatabase::split(const string &s, char delim)
{
vector<string> tokens;
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
tokens.push_back(item);
}
return tokens;
}
void GameDatabase::InitDatabase()
{
if(_gameDatabase.size() == 0) {
ifstream db("MesenDB.txt", ios::in | ios::binary);
while(db.good()) {
string lineContent;
std::getline(db, lineContent);
if(lineContent.empty() || lineContent[0] == '#') {
continue;
}
vector<string> values = split(lineContent, ',');
if(values.size() >= 11) {
GameInfo gameInfo{
(uint32_t)std::stoll(values[0], nullptr, 16),
values[1],
values[2],
values[3],
values[4],
ToInt<uint8_t>(values[5]),
ToInt<uint32_t>(values[6]),
ToInt<uint32_t>(values[7]),
ToInt<uint32_t>(values[8]),
ToInt<uint32_t>(values[9]),
ToInt<uint32_t>(values[10]) == 0 ? false : true,
values.size() > 11 ? values[11] : ""
};
_gameDatabase[gameInfo.Crc] = gameInfo;
}
}
}
}
GameSystem GameDatabase::GetGameSystem(string system)
{
if(system.compare("NesNtsc") == 0) {
return GameSystem::NesNtsc;
} else if(system.compare("NesPal") == 0) {
return GameSystem::NesPal;
} else if(system.compare("Famicom") == 0) {
return GameSystem::Famicom;
} else if(system.compare("VsUni") == 0) {
return GameSystem::VsUniSystem;
} else if(system.compare("Dendy") == 0) {
return GameSystem::Dendy;
} else if(system.compare("Playchoice") == 0) {
return GameSystem::Playchoice;
}
return GameSystem::NesNtsc;
}
uint8_t GameDatabase::GetSubMapper(GameInfo &info)
{
switch(info.MapperID) {
case 4:
if(info.Board.compare("ACCLAIM-MC-ACC") == 0) {
return 3; //Acclaim MC-ACC (MMC3 clone)
}
break;
case 21:
if(info.Pcb.compare("352398") == 0) {
return 1; //VRC4a
} else if(info.Pcb.compare("352889") == 0) {
return 2; //VRC4c
}
break;
case 23:
if(info.Pcb.compare("352396") == 0) {
return 2; //VRC4e
} else if(info.Pcb.compare("350603") == 0 || info.Pcb.compare("350636") == 0 || info.Pcb.compare("350926") == 0 || info.Pcb.compare("351179") == 0 || info.Pcb.compare("LROG009-00") == 0) {
return 3; //VRC2b
}
break;
case 25:
if(info.Pcb.compare("351406") == 0) {
return 1; //VRC4b
} else if(info.Pcb.compare("352400") == 0) {
return 2; //VRC4d
} else if(info.Pcb.compare("351948") == 0) {
return 3; //VRC2c
}
break;
case 32:
if(info.Board.compare("IREM-G101-B") == 0) {
return 1; //Major League
}
break;
case 71:
if(info.Board.compare("CAMERICA-BF9097") == 0) {
return 1; //Fire Hawk
}
break;
case 78:
if(info.Board.compare("IREM-HOLYDIVER") == 0) {
return 3; //Holy Diver
}
break;
case 210:
if(info.Board.compare("NAMCOT-175") == 0) {
return 1; //Namco 175
} else if(info.Board.compare("NAMCOT-340") == 0) {
return 2; //Namco 340
}
break;
}
return 0;
}
void GameDatabase::UpdateRomData(uint32_t romCrc, RomData &romData)
{
InitDatabase();
auto result = _gameDatabase.find(romCrc);
if(result != _gameDatabase.end()) {
GameInfo info = result->second;
romData.MapperID = info.MapperID;
romData.System = GetGameSystem(info.System);
romData.SubMapperID = GetSubMapper(info);
if(info.ChrRamSize > 0) {
romData.ChrRamSize = info.ChrRamSize * 1024;
}
romData.HasBattery |= info.HasBattery;
if(!info.Mirroring.empty()) {
romData.MirroringType = info.Mirroring.compare("h") == 0 ? MirroringType::Horizontal : MirroringType::Vertical;
}
#ifdef _DEBUG
MessageManager::DisplayMessage("DB", "Mapper: " + std::to_string(romData.MapperID) + " Sub: " + std::to_string(romData.SubMapperID) + " System: " + info.System);
#endif
}
}

36
Core/GameDatabase.h Normal file
View file

@ -0,0 +1,36 @@
#pragma once
#include "stdafx.h"
#include <unordered_map>
struct GameInfo
{
uint32_t Crc;
string System;
string Board;
string Pcb;
string Chip;
uint8_t MapperID;
uint32_t PrgRomSize;
uint32_t ChrRomSize;
uint32_t ChrRamSize;
uint32_t WorkRamSize;
bool HasBattery;
string Mirroring;
};
class GameDatabase
{
private:
static std::unordered_map<uint32_t, GameInfo> _gameDatabase;
template<typename T> static T ToInt(string value);
static vector<string> split(const string &s, char delim);
static GameSystem GetGameSystem(string system);
static uint8_t GetSubMapper(GameInfo &info);
static void InitDatabase();
public:
static void UpdateRomData(uint32_t romCrc, RomData &romData);
};

View file

@ -17,20 +17,32 @@ enum class RomHeaderVersion
OldiNes = 2
};
enum class GameSystem
{
NesNtsc,
NesPal,
Famicom,
Dendy,
VsUniSystem,
Playchoice,
FDS,
Unknown,
};
struct RomData
{
string Filename;
uint16_t MapperID;
uint8_t SubMapperID = 0;
GameSystem System = GameSystem::Unknown;
bool HasBattery = false;
bool IsPalRom = false;
bool IsVsSystem = false;
bool IsPlayChoice = false;
bool HasTrainer = false;
MirroringType MirroringType;
int32_t ChrRamSize = -1;
bool IsNes20Header = false;
vector<uint8_t> PrgRom;
vector<uint8_t> ChrRom;
vector<uint8_t> TrainerData;

View file

@ -123,9 +123,15 @@ RomData RomLoader::GetRomData()
{
_romData.Filename = _filename;
//Use filename to detect PAL/VS system games
_romData.IsPalRom |= _filename.find("(e)") != string::npos || _filename.find("(E)") != string::npos;
_romData.IsVsSystem |= _filename.find("(VS)") != string::npos || _filename.find("(vs)") != string::npos || _filename.find("(Vs)") != string::npos || _filename.find("(vS)") != string::npos;
if(_romData.System == GameSystem::Unknown) {
//Use filename to detect PAL/VS system games
if(_filename.find("(e)") != string::npos || _filename.find("(E)") != string::npos) {
_romData.System = GameSystem::NesPal;
} else if(_filename.find("(VS)") != string::npos || _filename.find("(vs)") != string::npos || _filename.find("(Vs)") != string::npos || _filename.find("(vS)") != string::npos) {
_romData.System = GameSystem::VsUniSystem;
}
}
return _romData;
}

View file

@ -1,67 +1,8 @@
#include "stdafx.h"
#include "iNesLoader.h"
#include "../Utilities/CRC32.h"
#include "MessageManager.h"
std::unordered_map<uint32_t, uint8_t> iNesLoader::_mapperByCrc = {
//Namco 175 games that are marked as mapper 19 but should be 210, submapper 1
{ 0x0C47946D, 210 }, //Chibi Maruko-chan: Uki Uki Shopping
{ 0x808606F0, 210 }, //Famista 91'
{ 0x81B7F1A8, 210 }, //Heisei Tensai Bakabon
{ 0x46FD7843, 210 }, //Splatterhouse: Wanpaku Graffiti
{ 0x1DC0F740, 210 }, //Wagyan Land 2
//Namco 340 games that are marked as mapper 19 but should be 210, submapper 2
{ 0xBD523011, 210 }, //Dream Master
{ 0xC247CC80, 210 }, //Family Circuit '91
{ 0x6EC51DE5, 210 }, //Famista '92
{ 0xADFFD64F, 210 }, //Famista '93
{ 0x429103C9, 210 }, //Famista '94
{ 0x2447E03B, 210 }, //Top Striker
{ 0xD323B806, 210 }, //Wagnyan Land 3
};
std::unordered_map<uint32_t, uint8_t> iNesLoader::_submapperByCrc = {
//MC-ACC Games (MMC3 variant) - Mapper 4, SubMapper 3
{ 0xC527C297, 3 }, //Alien 3
{ 0xAF05F37E, 3 }, //George Foreman's KO Boxing
{ 0xA80A0F01, 3 }, //Incredible Crash Dummies
{ 0x982DFB38, 3 }, //Mickey's Safari in Letterland
{ 0x018A8699, 3 }, //Roger Clemens' MVP Baseball
{ 0x2370C0A9, 3 }, //Rollerblade Racer
{ 0x7416903F, 3 }, //Simpsons, The: Bart vs. The World
{ 0x5991B9D0, 3 }, //Simpsons, The: Bartman Meets Radioactive Man
{ 0xD679627A, 3 }, //Spider-Man: Return of the Sinister Six
{ 0x7E57FBEC, 3 }, //T&C Surf Designs 2: Thrilla's Surfari
{ 0xEA27B477, 3 }, //T2: Terminator 2: Judgment Day
{ 0x7B4ED0BB, 3 }, //WWF King of the Ring
{ 0xD4611B79, 3 }, //WWF WrestleMania: Steel Cage Challenge
//IREM-G101 - Mapper 32, SubMapper 1
{ 0x243A8735, 1 }, //Major League
//IREM Holy Diver - Mapper 78, SubMapper 1
{ 0xBA51AC6F, 3 }, //Holy Diver
//CAMERICA-BF9097 - Mapper 71, SubMapper 1
{ 0x1BC686A8, 1 }, //Fire Hawk
//Namco 175 games that are marked as mapper 19 but should be 210, submapper 1
{ 0x0C47946D, 1 }, //Chibi Maruko-chan: Uki Uki Shopping
{ 0x808606F0, 1 }, //Famista 91'
{ 0x81B7F1A8, 1 }, //Heisei Tensai Bakabon
{ 0x46FD7843, 1 }, //Splatterhouse: Wanpaku Graffiti
{ 0x1DC0F740, 1 }, //Wagyan Land 2
//Namco 340 games that are marked as mapper 19 but should be 210, submapper 2
{ 0xBD523011, 2 }, //Dream Master
{ 0xC247CC80, 2 }, //Family Circuit '91
{ 0x6EC51DE5, 2 }, //Famista '92
{ 0xADFFD64F, 2 }, //Famista '93
{ 0x429103C9, 2 }, //Famista '94
{ 0x2447E03B, 2 }, //Top Striker
{ 0xD323B806, 2 }, //Wagnyan Land 3
};
#include "GameDatabase.h"
#include "EmulationSettings.h"
RomData iNesLoader::LoadRom(vector<uint8_t>& romFile)
{
@ -74,13 +15,18 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile)
header.SanitizeHeader(romFile.size());
romData.IsNes20Header = (header.GetRomHeaderVersion() == RomHeaderVersion::Nes2_0);
romData.MapperID = header.GetMapperID();
romData.SubMapperID = header.GetSubMapper();
romData.MirroringType = header.GetMirroringType();
romData.HasBattery = header.HasBattery();
romData.IsPalRom = header.IsPalRom();
romData.IsVsSystem = header.IsVsSystem();
romData.IsPlayChoice = header.IsPlaychoice();
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();
@ -90,29 +36,14 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile)
buffer += 512;
}
if(header.GetRomHeaderVersion() != RomHeaderVersion::Nes2_0) {
//Check rom CRC to set submapper as needed
uint32_t romCrc = CRC32::GetCRC(buffer, header.GetPrgSize() + header.GetChrSize());
auto crcCheckResult = _mapperByCrc.find(romCrc);
if(crcCheckResult != _mapperByCrc.end()) {
romData.MapperID = crcCheckResult->second;
#ifdef _DEBUG
MessageManager::DisplayMessage("GameInfo", "Mapper number corrected.");
#endif
}
crcCheckResult = _submapperByCrc.find(romCrc);
if(crcCheckResult != _submapperByCrc.end()) {
romData.SubMapperID = crcCheckResult->second;
#ifdef _DEBUG
MessageManager::DisplayMessage("GameInfo", "Submapper number corrected.");
#endif
}
}
uint32_t romCrc = CRC32::GetCRC(buffer, header.GetPrgSize() + header.GetChrSize());
romData.PrgRom.insert(romData.PrgRom.end(), buffer, buffer + header.GetPrgSize());
buffer += header.GetPrgSize();
romData.ChrRom.insert(romData.ChrRom.end(), buffer, buffer + header.GetChrSize());
if(!EmulationSettings::CheckFlag(EmulationFlags::DisableGameDatabase) && header.GetRomHeaderVersion() != RomHeaderVersion::Nes2_0) {
GameDatabase::UpdateRomData(romCrc, romData);
}
return romData;
}

View file

@ -1,14 +1,9 @@
#pragma once
#include "stdafx.h"
#include <unordered_map>
#include "RomData.h"
class iNesLoader
{
private:
static std::unordered_map<uint32_t, uint8_t> _mapperByCrc;
static std::unordered_map<uint32_t, uint8_t> _submapperByCrc;
public:
RomData LoadRom(vector<uint8_t>& romFile);
};

View file

@ -42,6 +42,8 @@ namespace Mesen.GUI.Config
public UInt32 OverclockRate = 100;
public bool OverclockAdjustApu = true;
public bool DisableGameDatabase = false;
public PreferenceInfo()
{
}
@ -78,6 +80,7 @@ namespace Mesen.GUI.Config
InteropEmu.SetFlag(EmulationFlags.PauseOnMovieEnd, preferenceInfo.PauseOnMovieEnd);
InteropEmu.SetFlag(EmulationFlags.AllowBackgroundInput, preferenceInfo.AllowBackgroundInput);
InteropEmu.SetFlag(EmulationFlags.PauseWhenInBackground, preferenceInfo.PauseWhenInBackground);
InteropEmu.SetFlag(EmulationFlags.DisableGameDatabase, preferenceInfo.DisableGameDatabase);
InteropEmu.SetOverclockRate(preferenceInfo.OverclockRate, preferenceInfo.OverclockAdjustApu);
}

File diff suppressed because it is too large Load diff

View file

@ -241,6 +241,8 @@
<Control ID="lblClockRatePercent">% (Recommandé: 100%)</Control>
<Control ID="chkOverclockAdjustApu">Ne pas overclocker l'APU (Empêche le changement de tonalité causé par l'overclocking)</Control>
<Control ID="chkDisableGameDatabase">Désactiver la base de données des jeux</Control>
<Control ID="btnOK">OK</Control>
<Control ID="btnCancel">Annuler</Control>
</Form>

View file

@ -241,6 +241,8 @@
<Control ID="lblClockRatePercent">% (デフォルト: 100%)</Control>
<Control ID="chkOverclockAdjustApu">APUのオーバークロックを無効にする (オーバークロックによる音声のピッチ変化を中和)</Control>
<Control ID="chkDisableGameDatabase">ゲームデータベースを無効にする</Control>
<Control ID="btnOK">OK</Control>
<Control ID="btnCancel">キャンセル</Control>
</Form>

View file

@ -81,6 +81,7 @@
this.nudOverclockRate = new System.Windows.Forms.NumericUpDown();
this.lblClockRatePercent = new System.Windows.Forms.Label();
this.tmrSyncDateTime = new System.Windows.Forms.Timer(this.components);
this.chkDisableGameDatabase = new System.Windows.Forms.CheckBox();
this.tlpMain.SuspendLayout();
this.flowLayoutPanel2.SuspendLayout();
this.tabMain.SuspendLayout();
@ -105,7 +106,7 @@
//
// baseConfigPanel
//
this.baseConfigPanel.Location = new System.Drawing.Point(0, 255);
this.baseConfigPanel.Location = new System.Drawing.Point(0, 282);
this.baseConfigPanel.Size = new System.Drawing.Size(487, 29);
//
// tlpMain
@ -136,7 +137,7 @@
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.Size = new System.Drawing.Size(473, 223);
this.tlpMain.Size = new System.Drawing.Size(473, 250);
this.tlpMain.TabIndex = 1;
//
// chkSingleInstance
@ -220,11 +221,12 @@
this.chkDisableScreensaver.TabIndex = 11;
this.chkDisableScreensaver.Text = "Disable screensaver while emulation is running";
this.chkDisableScreensaver.UseVisualStyleBackColor = true;
this.chkDisableScreensaver.Visible = false;
//
// btnOpenMesenFolder
//
this.btnOpenMesenFolder.AutoSize = true;
this.btnOpenMesenFolder.Location = new System.Drawing.Point(3, 197);
this.btnOpenMesenFolder.Location = new System.Drawing.Point(3, 224);
this.btnOpenMesenFolder.Name = "btnOpenMesenFolder";
this.btnOpenMesenFolder.Size = new System.Drawing.Size(117, 23);
this.btnOpenMesenFolder.TabIndex = 16;
@ -271,7 +273,7 @@
this.tabMain.Location = new System.Drawing.Point(0, 0);
this.tabMain.Name = "tabMain";
this.tabMain.SelectedIndex = 0;
this.tabMain.Size = new System.Drawing.Size(487, 255);
this.tabMain.Size = new System.Drawing.Size(487, 282);
this.tabMain.TabIndex = 2;
//
// tpgGeneral
@ -280,7 +282,7 @@
this.tpgGeneral.Location = new System.Drawing.Point(4, 22);
this.tpgGeneral.Name = "tpgGeneral";
this.tpgGeneral.Padding = new System.Windows.Forms.Padding(3);
this.tpgGeneral.Size = new System.Drawing.Size(479, 229);
this.tpgGeneral.Size = new System.Drawing.Size(479, 256);
this.tpgGeneral.TabIndex = 0;
this.tpgGeneral.Text = "General";
this.tpgGeneral.UseVisualStyleBackColor = true;
@ -542,7 +544,7 @@
this.tpgAdvanced.Location = new System.Drawing.Point(4, 22);
this.tpgAdvanced.Name = "tpgAdvanced";
this.tpgAdvanced.Padding = new System.Windows.Forms.Padding(3);
this.tpgAdvanced.Size = new System.Drawing.Size(479, 229);
this.tpgAdvanced.Size = new System.Drawing.Size(479, 256);
this.tpgAdvanced.TabIndex = 1;
this.tpgAdvanced.Text = "Advanced";
this.tpgAdvanced.UseVisualStyleBackColor = true;
@ -551,29 +553,31 @@
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.chkUseAlternativeMmc3Irq, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.chkAllowInvalidInput, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.chkRemoveSpriteLimit, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.chkFdsAutoLoadDisk, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.chkFdsFastForwardOnLoad, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.grpOverclocking, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.chkDisableGameDatabase, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.chkUseAlternativeMmc3Irq, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.chkAllowInvalidInput, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.chkRemoveSpriteLimit, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.chkFdsAutoLoadDisk, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.chkFdsFastForwardOnLoad, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.grpOverclocking, 0, 6);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 6;
this.tableLayoutPanel1.RowCount = 7;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(473, 223);
this.tableLayoutPanel1.Size = new System.Drawing.Size(473, 250);
this.tableLayoutPanel1.TabIndex = 0;
//
// chkUseAlternativeMmc3Irq
//
this.chkUseAlternativeMmc3Irq.AutoSize = true;
this.chkUseAlternativeMmc3Irq.Location = new System.Drawing.Point(3, 3);
this.chkUseAlternativeMmc3Irq.Location = new System.Drawing.Point(3, 26);
this.chkUseAlternativeMmc3Irq.Name = "chkUseAlternativeMmc3Irq";
this.chkUseAlternativeMmc3Irq.Size = new System.Drawing.Size(197, 17);
this.chkUseAlternativeMmc3Irq.TabIndex = 0;
@ -583,7 +587,7 @@
// chkAllowInvalidInput
//
this.chkAllowInvalidInput.AutoSize = true;
this.chkAllowInvalidInput.Location = new System.Drawing.Point(3, 26);
this.chkAllowInvalidInput.Location = new System.Drawing.Point(3, 49);
this.chkAllowInvalidInput.Name = "chkAllowInvalidInput";
this.chkAllowInvalidInput.Size = new System.Drawing.Size(341, 17);
this.chkAllowInvalidInput.TabIndex = 1;
@ -593,7 +597,7 @@
// chkRemoveSpriteLimit
//
this.chkRemoveSpriteLimit.AutoSize = true;
this.chkRemoveSpriteLimit.Location = new System.Drawing.Point(3, 49);
this.chkRemoveSpriteLimit.Location = new System.Drawing.Point(3, 72);
this.chkRemoveSpriteLimit.Name = "chkRemoveSpriteLimit";
this.chkRemoveSpriteLimit.Size = new System.Drawing.Size(205, 17);
this.chkRemoveSpriteLimit.TabIndex = 2;
@ -603,7 +607,7 @@
// chkFdsAutoLoadDisk
//
this.chkFdsAutoLoadDisk.AutoSize = true;
this.chkFdsAutoLoadDisk.Location = new System.Drawing.Point(3, 72);
this.chkFdsAutoLoadDisk.Location = new System.Drawing.Point(3, 95);
this.chkFdsAutoLoadDisk.Name = "chkFdsAutoLoadDisk";
this.chkFdsAutoLoadDisk.Size = new System.Drawing.Size(303, 17);
this.chkFdsAutoLoadDisk.TabIndex = 3;
@ -613,7 +617,7 @@
// chkFdsFastForwardOnLoad
//
this.chkFdsFastForwardOnLoad.AutoSize = true;
this.chkFdsFastForwardOnLoad.Location = new System.Drawing.Point(3, 95);
this.chkFdsFastForwardOnLoad.Location = new System.Drawing.Point(3, 118);
this.chkFdsFastForwardOnLoad.Name = "chkFdsFastForwardOnLoad";
this.chkFdsFastForwardOnLoad.Size = new System.Drawing.Size(342, 17);
this.chkFdsFastForwardOnLoad.TabIndex = 4;
@ -624,9 +628,9 @@
//
this.grpOverclocking.Controls.Add(this.tableLayoutPanel2);
this.grpOverclocking.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpOverclocking.Location = new System.Drawing.Point(3, 118);
this.grpOverclocking.Location = new System.Drawing.Point(3, 141);
this.grpOverclocking.Name = "grpOverclocking";
this.grpOverclocking.Size = new System.Drawing.Size(467, 102);
this.grpOverclocking.Size = new System.Drawing.Size(467, 106);
this.grpOverclocking.TabIndex = 5;
this.grpOverclocking.TabStop = false;
this.grpOverclocking.Text = "Overclocking";
@ -647,7 +651,7 @@
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(461, 83);
this.tableLayoutPanel2.Size = new System.Drawing.Size(461, 87);
this.tableLayoutPanel2.TabIndex = 0;
//
// lblOverclockWarning
@ -734,11 +738,21 @@
this.tmrSyncDateTime.Enabled = true;
this.tmrSyncDateTime.Tick += new System.EventHandler(this.tmrSyncDateTime_Tick);
//
// chkDisableGameDatabase
//
this.chkDisableGameDatabase.AutoSize = true;
this.chkDisableGameDatabase.Location = new System.Drawing.Point(3, 3);
this.chkDisableGameDatabase.Name = "chkDisableGameDatabase";
this.chkDisableGameDatabase.Size = new System.Drawing.Size(170, 17);
this.chkDisableGameDatabase.TabIndex = 6;
this.chkDisableGameDatabase.Text = "Disable built-in game database";
this.chkDisableGameDatabase.UseVisualStyleBackColor = true;
//
// frmPreferences
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(487, 284);
this.ClientSize = new System.Drawing.Size(487, 311);
this.Controls.Add(this.tabMain);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
@ -836,5 +850,6 @@
private System.Windows.Forms.Label lblClockRate;
private System.Windows.Forms.NumericUpDown nudOverclockRate;
private System.Windows.Forms.Label lblClockRatePercent;
private System.Windows.Forms.CheckBox chkDisableGameDatabase;
}
}

View file

@ -45,6 +45,8 @@ namespace Mesen.GUI.Forms.Config
AddBinding("OverclockRate", nudOverclockRate);
AddBinding("OverclockAdjustApu", chkOverclockAdjustApu);
AddBinding("DisableGameDatabase", chkDisableGameDatabase);
UpdateCloudDisplay();
}

View file

@ -661,6 +661,9 @@
<Content Include="Dependencies\LICENSE.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Dependencies\MesenDB.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Dependencies\Newtonsoft.Json.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

View file

@ -578,6 +578,8 @@ namespace Mesen.GUI
SwapDutyCycles = 0x10000,
DisableGameDatabase = 0x20000,
InBackground = 0x40000000,
}

View file

@ -86,7 +86,7 @@ namespace Mesen.GUI
if(entry.Name.Contains(suffix)) {
string outputFilename = Path.Combine(ConfigManager.HomeFolder, entry.Name.Replace(suffix, ""));
ExtractFile(entry, outputFilename);
} else if(entry.Name == "MesenUpdater.exe") {
} else if(entry.Name == "MesenUpdater.exe" || entry.Name == "MesenDB.txt") {
string outputFilename = Path.Combine(ConfigManager.HomeFolder, entry.Name.Replace(suffix, ""));
ExtractFile(entry, outputFilename);
} else if(entry.Name.StartsWith("Google.Apis") || entry.Name == "BouncyCastle.Crypto.dll" || entry.Name == "Zlib.Portable.dll" || entry.Name == "Newtonsoft.Json.dll") {