From 24ae022a7495876fadb1e4ec1ebc9a667198f0d9 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Tue, 22 Jun 2010 18:57:48 +0000 Subject: [PATCH] Fully implement hash-based database lookup. Fix some bugs that caused startup crashes in previous revisions of mine. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3273 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/Utilities/HashMap.h | 16 ++-- pcsx2/CDVD/CDVD.cpp | 35 ++++--- pcsx2/CDVD/CDVD.h | 2 +- pcsx2/GameDatabase.cpp | 103 ++++++++++---------- pcsx2/GameDatabase.h | 124 ++++++++++++------------- pcsx2/Patch.cpp | 11 ++- pcsx2/R5900.cpp | 2 +- pcsx2/System.cpp | 22 ++++- pcsx2/System.h | 3 +- pcsx2/gui/AppCoreThread.cpp | 34 +++---- pcsx2/gui/AppGameDatabase.cpp | 18 +++- pcsx2/gui/AppGameDatabase.h | 2 +- pcsx2/gui/AppMain.cpp | 2 +- pcsx2/gui/FrameForGS.cpp | 2 + pcsx2/gui/Panels/ConfigurationPanels.h | 2 +- pcsx2/gui/Panels/GameDatabasePanel.cpp | 71 +++++++------- plugins/GSdx/stdafx.h | 1 - 17 files changed, 239 insertions(+), 211 deletions(-) diff --git a/common/include/Utilities/HashMap.h b/common/include/Utilities/HashMap.h index fe249ef72f..2002728233 100644 --- a/common/include/Utilities/HashMap.h +++ b/common/include/Utilities/HashMap.h @@ -208,7 +208,7 @@ public: hash_key_t operator()( const wxString& src ) const { - return Hash( (const char *)src.data(), src.length() * sizeof( wchar_t ) ); + return Hash( (const char *)src.data(), src.length() * sizeof( wxChar ) ); } // Returns a hashcode for a character. @@ -555,12 +555,12 @@ public: /// matter, don't use this class at all! Use the string-specialized classes and /// . /// -template< class Key, class T > -class HashMap : public google::dense_hash_map +template< class Key, class T, class HashFunctor=CommonHashClass > +class HashMap : public google::dense_hash_map { DeclareNoncopyableObject( HashMap ); - typedef typename google::dense_hash_map _parent; + typedef typename google::dense_hash_map _parent; public: using _parent::operator[]; @@ -577,7 +577,7 @@ public: /// are *not* used as actual values in the set. /// HashMap( const Key& emptyKey, const Key& deletedKey, int initialCapacity=33 ) : - google::dense_hash_map( initialCapacity ) + google::dense_hash_map( initialCapacity ) { set_empty_key( emptyKey ); set_deleted_key( deletedKey ); @@ -653,14 +653,14 @@ public: } -template< class T > -class pxDictionary : public HashTools::HashMap +template< class T, class HashFunctor=HashTools::CommonHashClass > +class pxDictionary : public HashTools::HashMap { public: virtual ~pxDictionary() {} pxDictionary( int initialCapacity=33, const wxString& emptyKey = L"@@-EMPTY-@@", const wxString& deletedKey = L"@@-DELETED-@@" ) - : HashTools::HashMap( emptyKey, deletedKey, initialCapacity) + : HashTools::HashMap( emptyKey, deletedKey, initialCapacity) { } }; diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 4e32e220b8..af47e7d231 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -29,7 +29,11 @@ #include "ps2/BiosTools.h" #include "GameDatabase.h" -wxString DiscID; +// This typically reflects the Sony-assigned serial code for the Disc, if one exists. +// (examples: SLUS-2113, etc). +// If the disc is homebrew then it probably won't have a valid serial; in which case +// this string will be empty. +wxString DiscSerial; static cdvdStruct cdvd; @@ -340,9 +344,9 @@ static __forceinline void _reloadElfInfo(wxString elfpath) if (!fname) fname = elfpath.AfterLast(':'); if (fname.Matches(L"????_???.??*")) - DiscID = fname(0,4) + L"-" + fname(5,3) + fname(9,2); + DiscSerial = fname(0,4) + L"-" + fname(5,3) + fname(9,2); - Console.WriteLn("Disc ID = %s", DiscID.ToUTF8().data()); + Console.WriteLn("Disc ID = %s", DiscSerial.ToUTF8().data()); elfptr = loadElf(elfpath); ElfCRC = elfptr->getCRC(); @@ -355,18 +359,13 @@ static __forceinline void _reloadElfInfo(wxString elfpath) // Set the Game DataBase to the correct game based on Game Serial Code... if (IGameDatabase* GameDB = AppHost_GetGameDatabase()) { - wxString gameSerial = DiscID; - if (gameSerial.IsEmpty()) { // Search for crc if no Serial Code - gameSerial = wxsFormat( L"%8.8x", ElfCRC ); - } - + wxString gameSerial( SysGetDiscID() ); wxString serialMsg; - if(!DiscID.IsEmpty()) - serialMsg = L"serial=" + DiscID + L" "; + if(!DiscSerial.IsEmpty()) + serialMsg = L"serial=" + DiscSerial + L" "; - //Game_Data CurrentGame; - //if (GameDB->getGame(CurrentGame, gameSerial)) - if (GameDB->setGame(gameSerial)) + Game_Data game; + if (GameDB->findGame(game, gameSerial)) { Console.WriteLn(L"(GameDB) Found Game! %s [CRC=%8.8x]", serialMsg.c_str(), ElfCRC ); // [TODO] Display lots of other info from the database here! @@ -416,14 +415,14 @@ void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) cdvdReloadElfInfo(); // convert the number characters to a real 32 bit number - numbers = StrToS32(DiscID(5,5)); + numbers = StrToS32(DiscSerial(5,5)); // combine the lower 7 bits of each char // to make the 4 letters fit into a single u32 - letters = (s32)((DiscID[3]&0x7F)<< 0) | - (s32)((DiscID[2]&0x7F)<< 7) | - (s32)((DiscID[1]&0x7F)<<14) | - (s32)((DiscID[0]&0x7F)<<21); + letters = (s32)((DiscSerial[3]&0x7F)<< 0) | + (s32)((DiscSerial[2]&0x7F)<< 7) | + (s32)((DiscSerial[1]&0x7F)<<14) | + (s32)((DiscSerial[0]&0x7F)<<21); // calculate magic numbers key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80 diff --git a/pcsx2/CDVD/CDVD.h b/pcsx2/CDVD/CDVD.h index d88f424f69..d42287462d 100644 --- a/pcsx2/CDVD/CDVD.h +++ b/pcsx2/CDVD/CDVD.h @@ -145,4 +145,4 @@ extern void cdvdWrite(u8 key, u8 rt); extern void cdvdReloadElfInfo(wxString elfoverride = wxEmptyString); -extern wxString DiscID; +extern wxString DiscSerial; diff --git a/pcsx2/GameDatabase.cpp b/pcsx2/GameDatabase.cpp index 16f6242be8..ba1832adbc 100644 --- a/pcsx2/GameDatabase.cpp +++ b/pcsx2/GameDatabase.cpp @@ -18,89 +18,88 @@ // Sets the current game to the one matching the serial id given // Returns true if game found, false if not found... -bool BaseGameDatabaseVector::setGame(const wxString& id) { +bool BaseGameDatabaseImpl::findGame(Game_Data& dest, const wxString& id) { GameDataHash::const_iterator iter( gHash.find(id) ); if( iter == gHash.end() ) { - curGame = NULL; + dest.clear(); return false; } - curGame = &gList[iter->second]; + dest = gList[iter->second]; return true; } -Game_Data* BaseGameDatabaseVector::createNewGame(const wxString& id) { - gList.push_back(Game_Data(id)); - gHash[id] = gList.size()-1; - curGame = &(gList.end()-1)[0]; - return curGame; +void BaseGameDatabaseImpl::addNewGame(const Game_Data& game) +{ + gList.push_back(game); + gHash[game.id] = gList.size()-1; +} + +void BaseGameDatabaseImpl::updateGame(const Game_Data& game) +{ + GameDataHash::const_iterator iter( gHash.find(game.id) ); + + if( iter == gHash.end() ) { + gList.push_back(game); + gHash[game.id] = gList.size()-1; + } + else + { + // Re-assign existing vector/array entry! + gList[gHash[game.id]] = game; + } } // Searches the current game's data to see if the given key exists -bool BaseGameDatabaseVector::keyExists(const wxChar* key) { - if (curGame) { - KeyPairArray::iterator it( curGame->kList.begin() ); - for ( ; it != curGame->kList.end(); ++it) { - if (it[0].CompareKey(key)) { - return true; - } +bool Game_Data::keyExists(const wxChar* key) { + KeyPairArray::iterator it( kList.begin() ); + for ( ; it != kList.end(); ++it) { + if (it[0].CompareKey(key)) { + return true; } } - else Console.Error("(GameDB) Game not set!"); return false; } // Totally Deletes the specified key/pair value from the current game's data -void BaseGameDatabaseVector::deleteKey(const wxChar* key) { - if (curGame) { - KeyPairArray::iterator it( curGame->kList.begin() ); - for ( ; it != curGame->kList.end(); ++it) { - if (it[0].CompareKey(key)) { - curGame->kList.erase(it); - return; - } +void Game_Data::deleteKey(const wxChar* key) { + KeyPairArray::iterator it( kList.begin() ); + for ( ; it != kList.end(); ++it) { + if (it[0].CompareKey(key)) { + kList.erase(it); + return; } } - else Console.Error("(GameDB) Game not set!"); } // Gets a string representation of the 'value' for the given key -wxString BaseGameDatabaseVector::getString(const wxChar* key) { - if (curGame) { - KeyPairArray::iterator it( curGame->kList.begin() ); - for ( ; it != curGame->kList.end(); ++it) { - if (it[0].CompareKey(key)) { - return it[0].value; - } +wxString Game_Data::getString(const wxChar* key) { + KeyPairArray::iterator it( kList.begin() ); + for ( ; it != kList.end(); ++it) { + if (it[0].CompareKey(key)) { + return it[0].value; } } - else Console.Error("(GameDB) Game not set!"); return wxString(); } -void BaseGameDatabaseVector::writeString(const wxString& key, const wxString& value) { - if (key.CmpNoCase(m_baseKey) == 0) - curGame = createNewGame(value); - - if (curGame) { - KeyPairArray::iterator it( curGame->kList.begin() ); - for ( ; it != curGame->kList.end(); ++it) { - if (it[0].CompareKey(key)) { - if( value.IsEmpty() ) - curGame->kList.erase(it); - else - it[0].value = value; - return; - } - } - if( !value.IsEmpty() ) { - curGame->kList.push_back(key_pair(key, value)); +void Game_Data::writeString(const wxString& key, const wxString& value) { + KeyPairArray::iterator it( kList.begin() ); + for ( ; it != kList.end(); ++it) { + if (it[0].CompareKey(key)) { + if( value.IsEmpty() ) + kList.erase(it); + else + it[0].value = value; + return; } } - else Console.Error("(GameDB) Game not set!"); + if( !value.IsEmpty() ) { + kList.push_back(key_pair(key, value)); + } } // Write a bool value to the specified key -void BaseGameDatabaseVector::writeBool(const wxString& key, bool value) { +void Game_Data::writeBool(const wxString& key, bool value) { writeString(key, value ? L"1" : L"0"); } \ No newline at end of file diff --git a/pcsx2/GameDatabase.h b/pcsx2/GameDatabase.h index 9168af07ca..375c9b6f2d 100644 --- a/pcsx2/GameDatabase.h +++ b/pcsx2/GameDatabase.h @@ -15,14 +15,14 @@ #pragma once -#include "Common.h" +//#include "Common.h" #include "AppConfig.h" #include "Utilities/HashMap.h" #include struct key_pair; -class Game_Data; +struct Game_Data; typedef std::vector KeyPairArray; @@ -70,47 +70,40 @@ struct key_pair { } }; -class Game_Data { -public: - wxString id; // Serial Identification Code +// -------------------------------------------------------------------------------------- +// Game_Data +// -------------------------------------------------------------------------------------- +// This container is more or less required to be a simple struct (POD classification) -- +// no virtuals and no inheritance. This is because it is used in a std::vector, so POD +// makes things... smoother. +struct Game_Data +{ + wxString id; // Serial Identification Code KeyPairArray kList; // List of all (key, value) pairs for game data -public: Game_Data(const wxString& _id = wxEmptyString) : id(_id) {} - - void NewSerial( const wxString& _id ) { - id = _id; - kList.clear(); - } - - bool IsOk() const { - return !id.IsEmpty(); - } // Performs a case-insensitive compare of two IDs, returns TRUE if the IDs match // or FALSE if the ids differ in a case-insensitive way. - bool CompareId( const wxString& _id ) const - { + bool CompareId( const wxString& _id ) const { return id.CmpNoCase(_id) == 0; } -}; - -// -------------------------------------------------------------------------------------- -// IGameDatabase -// -------------------------------------------------------------------------------------- -class IGameDatabase -{ -public: - virtual ~IGameDatabase() throw() {} - virtual wxString getBaseKey() const=0; - virtual bool gameLoaded()=0; - virtual bool setGame(const wxString& id)=0; - virtual Game_Data* createNewGame(const wxString& id=wxEmptyString)=0; - virtual bool keyExists(const wxChar* key)=0; - virtual void deleteKey(const wxChar* key)=0; - virtual wxString getString(const wxChar* key)=0; + void clear() { + id.clear(); + kList.clear(); + } + + bool keyExists(const wxChar* key); + void deleteKey(const wxChar* key); + wxString getString(const wxChar* key); + void writeString(const wxString& key, const wxString& value); + void writeBool(const wxString& key, bool value); + + bool IsOk() const { + return !id.IsEmpty(); + } bool sectionExists(const wxChar* key, const wxString& value) { return keyExists(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", value.c_str())); @@ -154,57 +147,62 @@ public: bool getBool(const char* key) { return getBool(fromUTF8(key)); } - - // Writes a string of data associated with the specified key to the current - // game database. If the key being written is the baseKey, then a new slot is - // created to account for it, or the existing slot is set as the current game. - // - virtual void writeString(const wxString& key, const wxString& value)=0; - virtual void writeBool(const wxString& key, bool value)=0; }; -typedef std::vector GameDataArray; -typedef pxDictionary GameDataHash; +// -------------------------------------------------------------------------------------- +// IGameDatabase +// -------------------------------------------------------------------------------------- +class IGameDatabase +{ +public: + virtual ~IGameDatabase() throw() {} + + virtual wxString getBaseKey() const=0; + virtual bool findGame(Game_Data& dest, const wxString& id)=0; + virtual void addNewGame(const Game_Data& game)=0; + virtual void updateGame(const Game_Data& game)=0; +}; + +class StringHashNoCase +{ +public: + StringHashNoCase() {} + + HashTools::hash_key_t operator()( const wxString& src ) const + { + return HashTools::Hash( (const char *)src.Lower().data(), src.length() * sizeof( wxChar ) ); + } +}; + +typedef std::vector GameDataArray; +typedef pxDictionary GameDataHash; // -------------------------------------------------------------------------------------- -// BaseGameDatabaseVector +// BaseGameDatabaseImpl // -------------------------------------------------------------------------------------- // [TODO] Create a version of this that uses google hashsets; should be several magnitudes // faster that way. -class BaseGameDatabaseVector : public IGameDatabase +class BaseGameDatabaseImpl : public IGameDatabase { public: GameDataArray gList; // List of all game data GameDataHash gHash; // hash table of game serials matched to their gList indexes! - Game_Data* curGame; // Current game data (index into gList) wxString m_baseKey; public: - BaseGameDatabaseVector() + BaseGameDatabaseImpl() { - curGame = NULL; m_baseKey = L"Serial"; } - virtual ~BaseGameDatabaseVector() throw() {} + virtual ~BaseGameDatabaseImpl() throw() {} wxString getBaseKey() const { return m_baseKey; } void setBaseKey( const wxString& key ) { m_baseKey = key; } - // Returns true if a game is currently loaded into the database - // Returns false if otherwise (this means you need to call setGame() - // or it could mean the game was not found in the database at all...) - bool gameLoaded() { - return curGame != NULL; - } - - bool setGame(const wxString& id); - Game_Data* createNewGame(const wxString& id=wxEmptyString); - bool keyExists(const wxChar* key); - void deleteKey(const wxChar* key); - wxString getString(const wxChar* key); - void writeString(const wxString& key, const wxString& value); - void writeBool(const wxString& key, bool value); + bool findGame(Game_Data& dest, const wxString& id); + void addNewGame(const Game_Data& game); + void updateGame(const Game_Data& game); }; -extern IGameDatabase* AppHost_GetGameDatabase(); \ No newline at end of file +extern IGameDatabase* AppHost_GetGameDatabase(); diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index e934955b10..397602b0b2 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -139,13 +139,14 @@ int InitPatches(const wxString& name) if (IGameDatabase* GameDB = AppHost_GetGameDatabase() ) { - if(GameDB->gameLoaded()) { - if (GameDB->sectionExists(L"patches", name)) { - patch = GameDB->getSection(L"patches", name); + Game_Data game; + if (GameDB->findGame(game,name)) { + if (game.sectionExists(L"patches", name)) { + patch = game.getSection(L"patches", name); patchFound = true; } - else if (GameDB->keyExists(L"[patches]")) { - patch = GameDB->getString(L"[patches]"); + else if (game.keyExists(L"[patches]")) { + patch = game.getString(L"[patches]"); patchFound = true; } } diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 908d3b6a77..35b2e689c4 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -88,7 +88,7 @@ void cpuReset() g_SkipBiosHack = EmuConfig.UseBOOT2Injection; ElfCRC = 0; - DiscID = L""; + DiscSerial = L""; ElfEntry = -1; LastELF = L""; } diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index b34651324a..4d1fd830f1 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -24,6 +24,7 @@ // cleaning up these things. #include "sVU_zerorec.h" #include "GameDatabase.h" +#include "Elfheader.h" extern void closeNewVif(int idx); extern void resetNewVif(int idx); @@ -406,9 +407,9 @@ void SysClearExecutionCache() // allocation is below a certain memory address (specified in "bounds" parameter). // The allocated block has code execution privileges. // Returns NULL on allocation failure. -u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller) +u8* SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller) { - u8 *Mem = (u8*)HostSys::Mmap( base, size ); + u8* Mem = (u8*)HostSys::Mmap( base, size ); if( (Mem == NULL) || (bounds != 0 && (((uptr)Mem + size) > bounds)) ) { @@ -434,3 +435,20 @@ u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller) } return Mem; } + +// This function always returns a valid DiscID -- using the Sony serial when possible, and +// falling back on the CRC checksum of the ELF binary if the PS2 software being run is +// homebrew or some other serial-less item. +wxString SysGetDiscID() +{ + if( !DiscSerial.IsEmpty() ) return DiscSerial; + + if( !ElfCRC ) + { + // FIXME: If the system is currently running the BIOS, it should return a serial based on + // the BIOS being run (either a checksum of the BIOS roms, and/or a string based on BIOS + // region and revision). + } + + return wxsFormat( L"%8.8x", ElfCRC ); +} diff --git a/pcsx2/System.h b/pcsx2/System.h index 37a3ed7a26..acfd943468 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -67,11 +67,12 @@ extern SysCoreAllocations& GetSysCoreAlloc(); extern void SysLogMachineCaps(); // Detects cpu type and fills cpuInfo structs. extern void SysClearExecutionCache(); // clears recompiled execution caches! - extern u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller="Unnamed"); extern void vSyncDebugStuff( uint frame ); extern void NTFS_CompressFile( const wxString& file, bool compressStatus=true ); +extern wxString SysGetDiscID(); + // -------------------------------------------------------------------------------------- // PCSX2_SEH - Defines existence of "built in" Structured Exception Handling support. // -------------------------------------------------------------------------------------- diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 0422ccf06f..ce3b23a2b6 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -176,13 +176,14 @@ void AppCoreThread::OnResumeReady() static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) { if (!gameDB) gameDB = wxGetApp().GetGameDatabase(); - if (!gameDB->gameLoaded()) return 0; + Game_Data game; + if (!gameDB->findGame(game, SysGetDiscID())) return 0; int gf = 0; - if (gameDB->keyExists("eeRoundMode")) + if (game.keyExists("eeRoundMode")) { - SSE_RoundMode eeRM = (SSE_RoundMode)gameDB->getInt("eeRoundMode"); + SSE_RoundMode eeRM = (SSE_RoundMode)game.getInt("eeRoundMode"); if (EnumIsValid(eeRM)) { Console.WriteLn("(GameDB) Changing EE/FPU roundmode to %d [%s]", eeRM, EnumToString(eeRM)); @@ -191,9 +192,9 @@ static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) { } } - if (gameDB->keyExists("vuRoundMode")) + if (game.keyExists("vuRoundMode")) { - SSE_RoundMode vuRM = (SSE_RoundMode)gameDB->getInt("vuRoundMode"); + SSE_RoundMode vuRM = (SSE_RoundMode)game.getInt("vuRoundMode"); if (EnumIsValid(vuRM)) { Console.WriteLn("(GameDB) Changing VU0/VU1 roundmode to %d [%s]", vuRM, EnumToString(vuRM)); @@ -202,8 +203,8 @@ static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) { } } - if (gameDB->keyExists("eeClampMode")) { - int clampMode = gameDB->getInt("eeClampMode"); + if (game.keyExists("eeClampMode")) { + int clampMode = game.getInt("eeClampMode"); Console.WriteLn("(GameDB) Changing EE/FPU clamp mode [mode=%d]", clampMode); dest.Recompiler.fpuOverflow = (clampMode >= 1); dest.Recompiler.fpuExtraOverflow = (clampMode >= 2); @@ -211,8 +212,8 @@ static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) { gf++; } - if (gameDB->keyExists("vuClampMode")) { - int clampMode = gameDB->getInt("vuClampMode"); + if (game.keyExists("vuClampMode")) { + int clampMode = game.getInt("vuClampMode"); Console.WriteLn("(GameDB) Changing VU0/VU1 clamp mode [mode=%d]", clampMode); dest.Recompiler.vuOverflow = (clampMode >= 1); dest.Recompiler.vuExtraOverflow = (clampMode >= 2); @@ -225,9 +226,9 @@ static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) { wxString key( EnumToString(id) ); key += L"Hack"; - if (gameDB->keyExists(key)) + if (game.keyExists(key)) { - bool enableIt = gameDB->getBool(key); + bool enableIt = game.getBool(key); dest.Gamefixes.Set(id, enableIt ); Console.WriteLn(L"(GameDB) %s Gamefix: " + key, enableIt ? L"Enabled" : L"Disabled" ); gf++; @@ -252,14 +253,15 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src ) wxString gameCompat; if (ElfCRC) gameCRC.Printf( L"%8.8x", ElfCRC ); - if (!DiscID.IsEmpty()) gameSerial = L" [" + DiscID + L"]"; + if (!DiscSerial.IsEmpty()) gameSerial = L" [" + DiscSerial + L"]"; if (IGameDatabase* GameDB = AppHost_GetGameDatabase() ) { - if (GameDB->gameLoaded()) { - int compat = GameDB->getInt("Compat"); - gameName = GameDB->getString("Name"); - gameName += L" (" + GameDB->getString("Region") + L")"; + Game_Data game; + if (GameDB->findGame(game, SysGetDiscID())) { + int compat = game.getInt("Compat"); + gameName = game.getString("Name"); + gameName += L" (" + game.getString("Region") + L")"; gameCompat = L" [Status = "+compatToStringWX(compat)+L"]"; } diff --git a/pcsx2/gui/AppGameDatabase.cpp b/pcsx2/gui/AppGameDatabase.cpp index 4f0fd44d6f..a59c2ee417 100644 --- a/pcsx2/gui/AppGameDatabase.cpp +++ b/pcsx2/gui/AppGameDatabase.cpp @@ -118,10 +118,14 @@ wxString DBLoaderHelper::ReadHeader() void DBLoaderHelper::ReadGames() { - Game_Data* game = m_gamedb.createNewGame(); + Game_Data game; if (m_keyPair.IsOk()) - m_gamedb.writeString( m_keyPair.key, m_keyPair.value ); + { + game.writeString(m_keyPair.key, m_keyPair.value); + if( m_keyPair.CompareKey(m_gamedb.getBaseKey()) ) + game.id = m_keyPair.value; + } while(!m_reader.Eof()) { // Fill game data, find new game, repeat... pxReadLine(m_reader, m_dest, m_intermediate); @@ -132,7 +136,13 @@ void DBLoaderHelper::ReadGames() if (!extractMultiLine()) extract(); if (!m_keyPair.IsOk()) continue; - m_gamedb.writeString( m_keyPair.key, m_keyPair.value ); + if( m_keyPair.CompareKey(m_gamedb.getBaseKey()) ) + { + m_gamedb.addNewGame(game); + game.clear(); + game.id = m_keyPair.value; + } + game.writeString( m_keyPair.key, m_keyPair.value ); } } @@ -161,8 +171,6 @@ AppGameDatabase& AppGameDatabase::LoadFromFile(const wxString& file, const wxStr header = loader.ReadHeader(); loader.ReadGames(); - curGame = NULL; - return *this; } diff --git a/pcsx2/gui/AppGameDatabase.h b/pcsx2/gui/AppGameDatabase.h index 8aabf4888b..eb2c0386f5 100644 --- a/pcsx2/gui/AppGameDatabase.h +++ b/pcsx2/gui/AppGameDatabase.h @@ -39,7 +39,7 @@ // GameDatabase class's methods to get the other key's values. // Such as dbLoader.getString("Region") returns "NTSC-U" -class AppGameDatabase : public BaseGameDatabaseVector +class AppGameDatabase : public BaseGameDatabaseImpl { protected: wxString header; // Header of the database diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index c7aad08527..8cadc010c6 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -1109,4 +1109,4 @@ AppGameDatabase* Pcsx2App::GetGameDatabase() IGameDatabase* AppHost_GetGameDatabase() { return wxGetApp().GetGameDatabase(); -} \ No newline at end of file +} diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp index 533575b838..4f6af117cf 100644 --- a/pcsx2/gui/FrameForGS.cpp +++ b/pcsx2/gui/FrameForGS.cpp @@ -30,6 +30,8 @@ void GSPanel::InitDefaultAccelerators() typedef KeyAcceleratorCode AAC; + if( !m_Accels ) m_Accels = new AcceleratorDictionary; + m_Accels->Map( AAC( WXK_F1 ), "States_FreezeCurrentSlot" ); m_Accels->Map( AAC( WXK_F3 ), "States_DefrostCurrentSlot"); m_Accels->Map( AAC( WXK_F2 ), "States_CycleSlotForward" ); diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index a5b50f9824..184cb92ee0 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -366,7 +366,7 @@ namespace Panels void AppStatusEvent_OnSettingsApplied(); protected: - void PopulateFields(); + void PopulateFields( const wxString& serial=wxEmptyString ); bool WriteFieldsToDB(); void Search_Click( wxCommandEvent& evt ); }; diff --git a/pcsx2/gui/Panels/GameDatabasePanel.cpp b/pcsx2/gui/Panels/GameDatabasePanel.cpp index a2f05c0dcf..56c72d2d1c 100644 --- a/pcsx2/gui/Panels/GameDatabasePanel.cpp +++ b/pcsx2/gui/Panels/GameDatabasePanel.cpp @@ -18,7 +18,7 @@ #include "AppGameDatabase.h" #include "ConfigurationPanels.h" -extern wxString DiscID; +extern wxString DiscSerial; using namespace pxSizerFlags; #define blankLine() { \ @@ -43,7 +43,6 @@ wxTextCtrl* CreateMultiLineTextCtrl( wxWindow* parent, int digits, long flags = Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent ) : BaseApplicableConfigPanel( parent ) { - //if (!GameDB) GameDB = new GameDatabase(); IGameDatabase* GameDB = AppHost_GetGameDatabase(); pxAssume( GameDB != NULL ); @@ -96,33 +95,36 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent ) PopulateFields(); } -void Panels::GameDatabasePanel::PopulateFields() { +void Panels::GameDatabasePanel::PopulateFields( const wxString& id ) { IGameDatabase* GameDB = AppHost_GetGameDatabase(); + if (!pxAssert(GameDB)) return; - if (GameDB->gameLoaded()) { - serialBox ->SetLabel(GameDB->getString("Serial")); - nameBox ->SetLabel(GameDB->getString("Name")); - regionBox ->SetLabel(GameDB->getString("Region")); - compatBox ->SetLabel(GameDB->getString("Compat")); - commentBox->SetLabel(GameDB->getString("[comments]")); - patchesBox->SetLabel(GameDB->getString("[patches]")); + Game_Data game; + if (GameDB->findGame(game, id.IsEmpty() ? SysGetDiscID() : id)) + { + serialBox ->SetLabel(game.getString("Serial")); + nameBox ->SetLabel(game.getString("Name")); + regionBox ->SetLabel(game.getString("Region")); + compatBox ->SetLabel(game.getString("Compat")); + commentBox->SetLabel(game.getString("[comments]")); + patchesBox->SetLabel(game.getString("[patches]")); for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i) { wxString keyName (EnumToString(i)); keyName += L"Hack"; - if( GameDB->keyExists(keyName) ) - gameFixes[i]->SetValue(GameDB->getBool(keyName)); + if( game.keyExists(keyName) ) + gameFixes[i]->SetValue(game.getBool(keyName)); else gameFixes[i]->SetIndeterminate(); } } else { - serialBox ->SetLabel(L""); - nameBox ->SetLabel(L""); - regionBox ->SetLabel(L""); - compatBox ->SetLabel(L""); - commentBox->SetLabel(L""); - patchesBox->SetLabel(L""); + serialBox ->SetLabel(wxEmptyString); + nameBox ->SetLabel(wxEmptyString); + regionBox ->SetLabel(wxEmptyString); + compatBox ->SetLabel(wxEmptyString); + commentBox->SetLabel(wxEmptyString); + patchesBox->SetLabel(wxEmptyString); for (int i = 0; i < GamefixId_COUNT; i++) { gameFixes[i]->SetValue(0); } @@ -137,40 +139,39 @@ void Panels::GameDatabasePanel::PopulateFields() { // returns True if the database is modified, or FALSE if no changes to save. bool Panels::GameDatabasePanel::WriteFieldsToDB() { IGameDatabase* GameDB = AppHost_GetGameDatabase(); + if (!GameDB) return false; if (serialBox->GetValue().IsEmpty()) return false; - // Only write the serial if its been changed - if( !GameDB->setGame(serialBox->GetValue()) ) - GameDB->writeString(L"Serial", serialBox->GetValue()); + Game_Data game; + GameDB->findGame(game, serialBox->GetValue()); - GameDB->writeString(L"Name", nameBox->GetValue()); - GameDB->writeString(L"Region", regionBox->GetValue()); - GameDB->writeString(L"Compat", compatBox->GetValue()); - GameDB->writeString(L"[comments]", commentBox->GetValue()); - GameDB->writeString(L"[patches]", patchesBox->GetValue()); + game.id = serialBox->GetValue(); + + game.writeString(L"Serial", serialBox->GetValue()); + game.writeString(L"Name", nameBox->GetValue()); + game.writeString(L"Region", regionBox->GetValue()); + game.writeString(L"Compat", compatBox->GetValue()); + game.writeString(L"[comments]", commentBox->GetValue()); + game.writeString(L"[patches]", patchesBox->GetValue()); for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i) { wxString keyName (EnumToString(i)); keyName += L"Hack"; if (gameFixes[i]->IsIndeterminate()) - GameDB->deleteKey(keyName); + game.deleteKey(keyName); else - GameDB->writeBool(keyName, gameFixes[i]->GetValue()); + game.writeBool(keyName, gameFixes[i]->GetValue()); } + GameDB->updateGame(game); return true; } void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) { IGameDatabase* GameDB = AppHost_GetGameDatabase(); - wxString wxStr = serialBox->GetValue(); + if( !GameDB ) return; - if( wxStr.IsEmpty() ) wxStr = DiscID; - - bool bySerial = 1;//searchType->GetSelection()==0; - if (bySerial) GameDB->setGame(wxStr); - - PopulateFields(); + PopulateFields( serialBox->GetValue() ); evt.Skip(); } diff --git a/plugins/GSdx/stdafx.h b/plugins/GSdx/stdafx.h index 6b63120705..73c95e6a5f 100644 --- a/plugins/GSdx/stdafx.h +++ b/plugins/GSdx/stdafx.h @@ -119,7 +119,6 @@ typedef signed long long int64; // directx -//#include #include #include #include