pcsx2/pcsx2/GameDatabase.h

220 lines
6.3 KiB
C++

/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
//#include "Common.h"
#include "AppConfig.h"
#include "Utilities/HashMap.h"
#include <unordered_map>
#include <wx/wfstream.h>
struct key_pair;
struct Game_Data;
class StringHashNoCase
{
public:
StringHashNoCase() {}
HashTools::hash_key_t operator()( const wxString& src ) const
{
return HashTools::Hash( (const char *)src.Lower().wc_str(), src.length() * sizeof( wxChar ) );
}
};
typedef std::vector<key_pair> KeyPairArray;
struct key_pair {
wxString key;
wxString value;
key_pair() {}
key_pair(const wxString& _key, const wxString& _value)
: key(_key) , value(_value) {}
void Clear() {
key.clear();
value.clear();
}
// Performs case-insensitive compare against the key value.
bool CompareKey( const wxString& cmpto ) const {
return key.CmpNoCase(cmpto) == 0;
}
bool IsOk() const {
return !key.IsEmpty();
}
wxString toString() const {
if (key[0] == '[') {
pxAssertDev( key.EndsWith(L"]"), "Malformed multiline key detected: missing end bracket!" );
// Terminating tag must be written without the "rvalue" -- in the form of:
// [/patches]
// Use Mid() to strip off the left and right side brackets.
wxString midLine(key.Mid(1, key.Length()-2));
wxString keyLvalue(midLine.BeforeFirst(L'=').Trim(true).Trim(false));
return wxsFormat( L"%s\n%s[/%s]\n",
key.c_str(), value.c_str(), keyLvalue.c_str()
);
}
else {
// Note: 6 char padding on the l-value makes things look nicer.
return wxsFormat(L"%-6s = %s\n", key.c_str(), value.c_str() );
}
}
};
// --------------------------------------------------------------------------------------
// 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
Game_Data(const wxString& _id = wxEmptyString)
: id(_id) {}
// 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 {
return id.CmpNoCase(_id) == 0;
}
void clear() {
id.clear();
kList.clear();
}
bool keyExists(const wxChar* key) const;
void deleteKey(const wxChar* key);
wxString getString(const wxChar* key) const;
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) const {
return keyExists(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", WX_STR(value)));
}
wxString getSection(const wxChar* key, const wxString& value) const {
return getString(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", WX_STR(value)).wx_str());
}
// Gets an integer representation of the 'value' for the given key
int getInt(const wxChar* key) const {
unsigned long val;
getString(key).ToULong(&val);
return val;
}
// Gets a u8 representation of the 'value' for the given key
u8 getU8(const wxChar* key) const {
return (u8)wxAtoi(getString(key));
}
// Gets a bool representation of the 'value' for the given key
bool getBool(const wxChar* key) const {
return !!wxAtoi(getString(key));
}
bool keyExists(const char* key) const {
return keyExists(fromUTF8(key).wx_str());
}
bool keyExists(const wxString& key) const {
return keyExists(key.wx_str());
}
wxString getString(const char* key) const {
return getString(fromUTF8(key).wx_str());
}
int getInt(const char* key) const {
return getInt(fromUTF8(key).wx_str());
}
u8 getU8(const char* key) const {
return getU8(fromUTF8(key).wx_str());
}
bool getBool(const char* key) const {
return getBool(fromUTF8(key).wx_str());
}
bool getBool(const wxString& key) const {
return getBool(key.wx_str());
}
};
// --------------------------------------------------------------------------------------
// IGameDatabase
// --------------------------------------------------------------------------------------
class IGameDatabase
{
public:
virtual ~IGameDatabase() throw() {}
virtual wxString getBaseKey() const=0;
virtual bool findGame(Game_Data& dest, const wxString& id)=0;
virtual Game_Data* createNewGame( const wxString& id )=0;
virtual void updateGame(const Game_Data& game)=0;
};
typedef std::unordered_map<wxString, Game_Data*, StringHashNoCase> GameDataHash;
// --------------------------------------------------------------------------------------
// BaseGameDatabaseImpl
// --------------------------------------------------------------------------------------
// [TODO] Create a version of this that uses google hashsets; should be several magnitudes
// faster that way.
class BaseGameDatabaseImpl : public IGameDatabase
{
protected:
GameDataHash gHash; // hash table of game serials matched to their gList indexes!
wxString m_baseKey;
std::vector<Game_Data*> m_BlockTable;
uint m_BlockTableWritePos;
int m_CurBlockWritePos;
int m_GamesPerBlock;
public:
BaseGameDatabaseImpl();
virtual ~BaseGameDatabaseImpl() throw();
wxString getBaseKey() const { return m_baseKey; }
void setBaseKey( const wxString& key ) { m_baseKey = key; }
bool findGame(Game_Data& dest, const wxString& id);
Game_Data* createNewGame( const wxString& id );
void updateGame(const Game_Data& game);
};
extern IGameDatabase* AppHost_GetGameDatabase();