mirror of https://github.com/PCSX2/pcsx2.git
GameDatabase / Patches:
* Made all database key comparisons case-insensitive, so that "patches" and "Patches" both work as expected, etc. * Applied patches should be remembered properly now when using suspend/resume and savestates (hopefully -- didn't test savestates yet). DevNotes: * Reorganized all game database code into a generic interface used by the emulation core (IGameDatabase), and app-side implementation (AppGameDatabase) that loads the files and provides info in a thread-safe manner. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3223 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
b5a0a7186e
commit
914474ebc9
|
@ -27,7 +27,7 @@
|
|||
#include "GS.h" // for gsRegionMode
|
||||
#include "Elfheader.h"
|
||||
#include "ps2/BiosTools.h"
|
||||
#include "DataBase_Loader.h"
|
||||
#include "GameDatabase.h"
|
||||
|
||||
wxString DiscID;
|
||||
|
||||
|
@ -354,7 +354,7 @@ static __forceinline void _reloadElfInfo(wxString elfpath)
|
|||
elfptr.Delete();
|
||||
|
||||
// Set the Game DataBase to the correct game based on Game Serial Code...
|
||||
if (DataBase_Loader* GameDB = AppHost_GetGameDatabase()) {
|
||||
if (IGameDatabase* GameDB = AppHost_GetGameDatabase()) {
|
||||
wxString gameSerial = DiscID;
|
||||
if (DiscID.IsEmpty()) { // Search for crc if no Serial Code
|
||||
gameSerial = wxString(wxsFormat( L"%8.8x", ElfCRC ));
|
||||
|
|
|
@ -121,7 +121,7 @@ set(pcsx2Sources
|
|||
COP0.cpp
|
||||
COP2.cpp
|
||||
Counters.cpp
|
||||
DataBase_Loader.cpp
|
||||
GameDatabase.cpp
|
||||
Dump.cpp
|
||||
Elfheader.cpp
|
||||
FiFo.cpp
|
||||
|
@ -194,7 +194,7 @@ set(pcsx2Headers
|
|||
Counters.h
|
||||
Dmac.h
|
||||
Dump.h
|
||||
DataBase_Loader.h
|
||||
GameDatabase.h
|
||||
Elfheader.h
|
||||
Gif.h
|
||||
GS.h
|
||||
|
@ -290,6 +290,7 @@ set(pcsx2GuiSources
|
|||
gui/AppCorePlugins.cpp
|
||||
gui/AppCoreThread.cpp
|
||||
gui/AppEventSources.cpp
|
||||
gui/AppGameDatabase.cpp
|
||||
gui/AppInit.cpp
|
||||
gui/AppMain.cpp
|
||||
gui/AppRes.cpp
|
||||
|
@ -355,6 +356,7 @@ set(pcsx2GuiHeaders
|
|||
gui/AppCorePlugins.h
|
||||
gui/AppEventListeners.h
|
||||
gui/AppForwardDefs.h
|
||||
gui/AppGameDatabase.h
|
||||
gui/ConsoleLogger.h
|
||||
gui/CpuUsageProvider.h
|
||||
gui/Dialogs/ConfigurationDialog.h
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "DataBase_Loader.h"
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// DataBase_Loader - Private Methods
|
||||
//------------------------------------------------------------------
|
||||
|
||||
void DataBase_Loader::doError(const wxString& line, key_pair& keyPair, bool doMsg) {
|
||||
if (doMsg) Console.Error("DataBase_Loader: Bad file data [%s]", line.c_str());
|
||||
keyPair.Clear();
|
||||
}
|
||||
|
||||
// Multiline Sections are in the form of:
|
||||
//
|
||||
// [section=value]
|
||||
// content
|
||||
// content
|
||||
// [/section]
|
||||
//
|
||||
// ... where the =value part is OPTIONAL.
|
||||
bool DataBase_Loader::extractMultiLine(const wxString& line, key_pair& keyPair, wxInputStream& ffile) {
|
||||
|
||||
if (line[0] != L'[') return false; // All multiline sections begin with a '['!
|
||||
|
||||
if (!line.EndsWith(L"]")) {
|
||||
doError(line, keyPair, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
keyPair.key = line;
|
||||
|
||||
// Use Mid() to strip off the left and right side brackets.
|
||||
wxString midLine(line.Mid(1, line.Length()-2));
|
||||
wxString lvalue(midLine.BeforeFirst(L'=').Trim(true).Trim(false));
|
||||
//wxString rvalue(midLine.AfterFirst(L'=').Trim(true).Trim(false));
|
||||
|
||||
wxString endString;
|
||||
endString.Printf( L"[/%s]", lvalue.c_str() );
|
||||
|
||||
while(!ffile.Eof()) {
|
||||
pxReadLine( ffile, m_dest, m_intermediate );
|
||||
if (m_dest == endString) break;
|
||||
keyPair.value += m_dest + L"\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataBase_Loader::extract(const wxString& line, key_pair& keyPair, wxInputStream& reader) {
|
||||
keyPair.Clear();
|
||||
|
||||
if( line.IsEmpty() ) return;
|
||||
|
||||
if( extractMultiLine(line, keyPair, reader) ) return;
|
||||
if( !pxParseAssignmentString( line, keyPair.key, keyPair.value ) ) return;
|
||||
if( keyPair.value.IsEmpty() )
|
||||
doError(line, keyPair, true);
|
||||
}
|
|
@ -1,395 +0,0 @@
|
|||
/* 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 <wx/wfstream.h>
|
||||
|
||||
struct key_pair;
|
||||
class Game_Data;
|
||||
|
||||
// This was originally configured to use deque, but there appear to be no uses of deque's sole
|
||||
// advantage: adding and removing items from the head of the list. So I changed it to vector
|
||||
// since it is a slightly lighter weight class. --air
|
||||
typedef std::vector<Game_Data> GameDataArray;
|
||||
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] == '[') {
|
||||
pxAssumeDev( 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() );
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class Game_Data {
|
||||
public:
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// DataBase_Loader:
|
||||
// Give the starting Key and Value you're looking for,
|
||||
// and it will extract the necessary data from the database.
|
||||
// Example:
|
||||
// ---------------------------------------------
|
||||
// Serial = SLUS-20486
|
||||
// Name = Marvel vs. Capcom 2
|
||||
// Region = NTSC-U
|
||||
// ---------------------------------------------
|
||||
// To Load this game data, use "Serial" as the initial Key
|
||||
// then specify "SLUS-20486" as the value in the constructor.
|
||||
// After the constructor loads the game data, you can use the
|
||||
// DataBase_Loader class's methods to get the other key's values.
|
||||
// Such as dbLoader.getString("Region") returns "NTSC-U"
|
||||
|
||||
class DataBase_Loader {
|
||||
protected:
|
||||
bool isComment(const wxString& s);
|
||||
void doError(const wxString& line, key_pair& keyPair, bool doMsg = false);
|
||||
bool extractMultiLine(const wxString& line, key_pair& keyPair, wxInputStream& reader);
|
||||
void extract(const wxString& line, key_pair& keyPair, wxInputStream& reader);
|
||||
|
||||
// temp areas used as buffers for accelerated loading of database content. These strings are
|
||||
// allocated and grown only once, and then reused for the duration of the database loading
|
||||
// process; saving thousands of heapp allocation operations.
|
||||
wxString m_dest;
|
||||
std::string m_intermediate;
|
||||
|
||||
public:
|
||||
GameDataArray gList; // List of all game data
|
||||
Game_Data* curGame; // Current game data (index into gList)
|
||||
wxString header; // Header of the database
|
||||
wxString baseKey; // Key to separate games by ("Serial")
|
||||
|
||||
DataBase_Loader(const wxString& file = L"GameIndex.dbf", const wxString& key = L"Serial", const wxString& value = wxEmptyString )
|
||||
: baseKey( key )
|
||||
{
|
||||
curGame = NULL;
|
||||
if (!wxFileExists(file)) {
|
||||
Console.Error(L"DataBase_Loader: DataBase Not Found! [%s]", file.c_str());
|
||||
}
|
||||
wxFFileInputStream reader( file );
|
||||
key_pair keyPair;
|
||||
wxString s0;
|
||||
Game_Data game;
|
||||
|
||||
while(!reader.Eof()) {
|
||||
while(!reader.Eof()) { // Find first game
|
||||
pxReadLine(reader, s0, m_intermediate);
|
||||
extract(s0.Trim(true).Trim(false), keyPair, reader);
|
||||
if (keyPair.CompareKey(key)) break;
|
||||
header += s0 + L'\n';
|
||||
}
|
||||
game.NewSerial( keyPair.value );
|
||||
game.kList.push_back(keyPair);
|
||||
|
||||
while(!reader.Eof()) { // Fill game data, find new game, repeat...
|
||||
pxReadLine(reader, s0, m_intermediate);
|
||||
extract(s0.Trim(true).Trim(false), keyPair, reader);
|
||||
if (!keyPair.IsOk()) continue;
|
||||
if (keyPair.CompareKey(key)) {
|
||||
gList.push_back(game);
|
||||
game.NewSerial(keyPair.value);
|
||||
}
|
||||
game.kList.push_back(keyPair);
|
||||
}
|
||||
}
|
||||
|
||||
if (game.IsOk()) gList.push_back(game);
|
||||
|
||||
if (value.IsEmpty()) return;
|
||||
if (setGame(value)) Console.WriteLn(L"DataBase_Loader: Found Game! [%s]", value.c_str());
|
||||
else Console.Warning(L"DataBase_Loader: Game Not Found! [%s]", value.c_str());
|
||||
}
|
||||
|
||||
virtual ~DataBase_Loader() throw() {
|
||||
// deque deletes its contents automatically.
|
||||
Console.WriteLn( "(GameDB) Destroying..." );
|
||||
}
|
||||
|
||||
// Sets the current game to the one matching the serial id given
|
||||
// Returns true if game found, false if not found...
|
||||
bool setGame(const wxString& id) {
|
||||
GameDataArray::iterator it( gList.begin() );
|
||||
for ( ; it != gList.end(); ++it) {
|
||||
if (it[0].id == id) {
|
||||
curGame = &it[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
curGame = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Saves changes to the database
|
||||
void saveToFile(const wxString& file = L"GameIndex.dbf") {
|
||||
wxFFileOutputStream writer( file );
|
||||
pxWriteMultiline(writer, header);
|
||||
GameDataArray::iterator it( gList.begin() );
|
||||
for ( ; it != gList.end(); ++it) {
|
||||
KeyPairArray::iterator i = it[0].kList.begin();
|
||||
for ( ; i != it[0].kList.end(); ++i) {
|
||||
pxWriteMultiline(writer, i[0].toString() );
|
||||
}
|
||||
pxWriteLine(writer, L"---------------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
// Adds new game data to the database, and sets curGame to the new game...
|
||||
// If searchDB is true, it searches the database to see if game already exists.
|
||||
void addGame(const wxString& id, bool searchDB = true) {
|
||||
if (searchDB && setGame(id)) return;
|
||||
Game_Data game(id);
|
||||
key_pair kp(baseKey, id);
|
||||
game.kList.push_back(kp);
|
||||
gList.push_back(game);
|
||||
curGame = &(gList.end()-1)[0];
|
||||
}
|
||||
|
||||
// Searches the current game's data to see if the given key exists
|
||||
bool 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else Console.Error("DataBase_Loader: Game not set!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Totally Deletes the specified key/pair value from the current game's data
|
||||
void 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else Console.Error("DataBase_Loader: Game not set!");
|
||||
}
|
||||
|
||||
// Gets a string representation of the 'value' for the given key
|
||||
wxString 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else Console.Error("DataBase_Loader: Game not set!");
|
||||
return wxString();
|
||||
}
|
||||
|
||||
bool sectionExists(const wxChar* key, const wxString& value) {
|
||||
return keyExists( wxsFormat(L"[%s = %s]", key, value.c_str()) );
|
||||
}
|
||||
|
||||
wxString getSection(const wxChar* key, const wxString& value) {
|
||||
return getString( wxsFormat(L"[%s = %s]", key, value.c_str()) );
|
||||
}
|
||||
|
||||
// Gets an integer representation of the 'value' for the given key
|
||||
int getInt(const wxChar* key) {
|
||||
return wxStrtoul(getString(key), NULL, 0);
|
||||
}
|
||||
|
||||
// Gets a u8 representation of the 'value' for the given key
|
||||
u8 getU8(const wxChar* key) {
|
||||
return (u8)wxAtoi(getString(key));
|
||||
}
|
||||
|
||||
// Gets a bool representation of the 'value' for the given key
|
||||
bool getBool(const wxChar* key) {
|
||||
return !!wxAtoi(getString(key));
|
||||
}
|
||||
|
||||
wxString getString(const char* key) {
|
||||
return getString(fromUTF8(key));
|
||||
}
|
||||
|
||||
bool keyExists(const char* key) {
|
||||
return keyExists(fromUTF8(key));
|
||||
}
|
||||
|
||||
int getInt(const char* key) {
|
||||
return getInt(fromUTF8(key));
|
||||
}
|
||||
|
||||
u8 getU8(const char* key) {
|
||||
return getU8(fromUTF8(key));
|
||||
}
|
||||
|
||||
bool getBool(const char* key) {
|
||||
return getBool(fromUTF8(key));
|
||||
}
|
||||
|
||||
// Write a string value to the specified key
|
||||
void writeString(const wxString& key, const wxString& value) {
|
||||
if (curGame) {
|
||||
KeyPairArray::iterator it( curGame->kList.begin() );
|
||||
for ( ; it != curGame->kList.end(); ++it) {
|
||||
if (it[0].CompareKey(key)) {
|
||||
it[0].value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
key_pair tKey(key, value);
|
||||
curGame->kList.push_back(tKey);
|
||||
}
|
||||
else Console.Error("DataBase_Loader: Game not set!");
|
||||
}
|
||||
|
||||
// Write a bool value to the specified key
|
||||
void writeBool(const wxString& key, bool value) {
|
||||
writeString(key, value ? L"1" : L"0");
|
||||
}
|
||||
};
|
||||
|
||||
static wxString compatToStringWX(int compat) {
|
||||
switch (compat) {
|
||||
case 6: return L"Perfect";
|
||||
case 5: return L"Playable";
|
||||
case 4: return L"In-Game";
|
||||
case 3: return L"Menu";
|
||||
case 2: return L"Intro";
|
||||
case 1: return L"Nothing";
|
||||
default: return L"Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
#define checkGamefix(gFix) { \
|
||||
if (gameDB->keyExists(#gFix)) { \
|
||||
SetGameFixConfig().gFix = gameDB->getBool(#gFix); \
|
||||
Console.WriteLn("Loading Gamefix: " #gFix); \
|
||||
gf++; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Load Game Settings found in database
|
||||
// (game fixes, round modes, clamp modes, etc...)
|
||||
// Returns number of gamefixes set
|
||||
static int loadGameSettings(DataBase_Loader* gameDB) {
|
||||
if (gameDB && gameDB->gameLoaded()) {
|
||||
SSE_MXCSR eeMX = EmuConfig.Cpu.sseMXCSR;
|
||||
SSE_MXCSR vuMX = EmuConfig.Cpu.sseVUMXCSR;
|
||||
int eeRM = eeMX.GetRoundMode();
|
||||
int vuRM = vuMX.GetRoundMode();
|
||||
bool rm = 0;
|
||||
int gf = 0;
|
||||
if (gameDB->keyExists("eeRoundMode")) { eeRM = gameDB->getInt("eeRoundMode"); rm=1; gf++; }
|
||||
if (gameDB->keyExists("vuRoundMode")) { vuRM = gameDB->getInt("vuRoundMode"); rm=1; gf++; }
|
||||
if (rm && eeRM<4 && vuRM<4) {
|
||||
Console.WriteLn("Game DataBase: Changing roundmodes! [ee=%d] [vu=%d]", eeRM, vuRM);
|
||||
SetCPUState(eeMX.SetRoundMode((SSE_RoundMode)eeRM), vuMX.SetRoundMode((SSE_RoundMode)vuRM));
|
||||
}
|
||||
if (gameDB->keyExists("eeClampMode")) {
|
||||
int clampMode = gameDB->getInt("eeClampMode");
|
||||
Console.WriteLn("Game DataBase: Changing EE/FPU clamp mode [mode=%d]", clampMode);
|
||||
SetRecompilerConfig().fpuOverflow = clampMode >= 1;
|
||||
SetRecompilerConfig().fpuExtraOverflow = clampMode >= 2;
|
||||
SetRecompilerConfig().fpuFullMode = clampMode >= 3;
|
||||
gf++;
|
||||
}
|
||||
if (gameDB->keyExists("vuClampMode")) {
|
||||
int clampMode = gameDB->getInt("vuClampMode");
|
||||
Console.WriteLn("Game DataBase: Changing VU0/VU1 clamp mode [mode=%d]", clampMode);
|
||||
SetRecompilerConfig().vuOverflow = clampMode >= 1;
|
||||
SetRecompilerConfig().vuExtraOverflow = clampMode >= 2;
|
||||
SetRecompilerConfig().vuSignOverflow = clampMode >= 3;
|
||||
gf++;
|
||||
}
|
||||
checkGamefix(VuAddSubHack);
|
||||
checkGamefix(VuClipFlagHack);
|
||||
checkGamefix(FpuCompareHack);
|
||||
checkGamefix(FpuMulHack);
|
||||
checkGamefix(FpuNegDivHack);
|
||||
checkGamefix(XgKickHack);
|
||||
checkGamefix(IPUWaitHack);
|
||||
checkGamefix(EETimingHack);
|
||||
checkGamefix(SkipMPEGHack);
|
||||
return gf;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern DataBase_Loader* AppHost_GetGameDatabase();
|
|
@ -0,0 +1,107 @@
|
|||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GameDatabase.h"
|
||||
|
||||
// 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) {
|
||||
GameDataArray::iterator it( gList.begin() );
|
||||
for ( ; it != gList.end(); ++it) {
|
||||
if (it[0].CompareId(id)) {
|
||||
curGame = &it[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
curGame = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
Game_Data* BaseGameDatabaseVector::createNewGame(const wxString& id) {
|
||||
gList.push_back(Game_Data(id));
|
||||
curGame = &(gList.end()-1)[0];
|
||||
return curGame;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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() ) {
|
||||
key_pair tKey(key, value);
|
||||
curGame->kList.push_back(tKey);
|
||||
}
|
||||
}
|
||||
else Console.Error("(GameDB) Game not set!");
|
||||
}
|
||||
|
||||
// Write a bool value to the specified key
|
||||
void BaseGameDatabaseVector::writeBool(const wxString& key, bool value) {
|
||||
writeString(key, value ? L"1" : L"0");
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
/* 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 <wx/wfstream.h>
|
||||
|
||||
struct key_pair;
|
||||
class Game_Data;
|
||||
|
||||
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] == '[') {
|
||||
pxAssumeDev( 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() );
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class Game_Data {
|
||||
public:
|
||||
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
|
||||
{
|
||||
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;
|
||||
|
||||
bool sectionExists(const wxChar* key, const wxString& value) {
|
||||
return keyExists(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", value.c_str()));
|
||||
}
|
||||
|
||||
wxString getSection(const wxChar* key, const wxString& value) {
|
||||
return getString(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", value.c_str()));
|
||||
}
|
||||
|
||||
// Gets an integer representation of the 'value' for the given key
|
||||
int getInt(const wxChar* key) {
|
||||
return wxStrtoul(getString(key), NULL, 0);
|
||||
}
|
||||
|
||||
// Gets a u8 representation of the 'value' for the given key
|
||||
u8 getU8(const wxChar* key) {
|
||||
return (u8)wxAtoi(getString(key));
|
||||
}
|
||||
|
||||
// Gets a bool representation of the 'value' for the given key
|
||||
bool getBool(const wxChar* key) {
|
||||
return !!wxAtoi(getString(key));
|
||||
}
|
||||
|
||||
bool keyExists(const char* key) {
|
||||
return keyExists(fromUTF8(key));
|
||||
}
|
||||
|
||||
wxString getString(const char* key) {
|
||||
return getString(fromUTF8(key));
|
||||
}
|
||||
|
||||
int getInt(const char* key) {
|
||||
return getInt(fromUTF8(key));
|
||||
}
|
||||
|
||||
u8 getU8(const char* key) {
|
||||
return getU8(fromUTF8(key));
|
||||
}
|
||||
|
||||
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<Game_Data> GameDataArray;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseGameDatabaseVector
|
||||
// --------------------------------------------------------------------------------------
|
||||
// [TODO] Create a version of this that uses google hashsets; should be several magnitudes
|
||||
// faster that way.
|
||||
class BaseGameDatabaseVector : public IGameDatabase
|
||||
{
|
||||
public:
|
||||
GameDataArray gList; // List of all game data
|
||||
Game_Data* curGame; // Current game data (index into gList)
|
||||
wxString m_baseKey;
|
||||
|
||||
public:
|
||||
BaseGameDatabaseVector()
|
||||
{
|
||||
curGame = NULL;
|
||||
m_baseKey = L"Serial";
|
||||
}
|
||||
|
||||
virtual ~BaseGameDatabaseVector() 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);
|
||||
};
|
||||
|
||||
extern IGameDatabase* AppHost_GetGameDatabase();
|
|
@ -204,8 +204,8 @@
|
|||
<Unit filename="../Config.h" />
|
||||
<Unit filename="../Counters.cpp" />
|
||||
<Unit filename="../Counters.h" />
|
||||
<Unit filename="../DataBase_Loader.cpp" />
|
||||
<Unit filename="../DataBase_Loader.h" />
|
||||
<Unit filename="../GameDatabase.cpp" />
|
||||
<Unit filename="../GameDatabase.h" />
|
||||
<Unit filename="../DebugTools/Debug.h" />
|
||||
<Unit filename="../DebugTools/DisASM.h" />
|
||||
<Unit filename="../DebugTools/DisR3000A.cpp" />
|
||||
|
@ -359,6 +359,8 @@
|
|||
<Unit filename="../gui/AppEventListeners.h" />
|
||||
<Unit filename="../gui/AppEventSources.cpp" />
|
||||
<Unit filename="../gui/AppForwardDefs.h" />
|
||||
<Unit filename="../gui/AppGameDatabase.cpp" />
|
||||
<Unit filename="../gui/AppGameDatabase.h" />
|
||||
<Unit filename="../gui/AppInit.cpp" />
|
||||
<Unit filename="../gui/AppMain.cpp" />
|
||||
<Unit filename="../gui/AppRes.cpp" />
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "IopCommon.h"
|
||||
#include "Patch.h"
|
||||
#include "DataBase_Loader.h"
|
||||
#include "GameDatabase.h"
|
||||
#include <wx/textfile.h>
|
||||
|
||||
IniPatch Patch[ MAX_PATCH ];
|
||||
|
@ -133,12 +133,11 @@ void TrimPatches(wxString& s)
|
|||
// Returns number of patches loaded
|
||||
int InitPatches(const wxString& name)
|
||||
{
|
||||
bool patchFound = false;
|
||||
bool patchFound = false;
|
||||
wxString patch;
|
||||
const wxString crc( L"[patches = " + name + L"]" );
|
||||
patchnumber = 0;
|
||||
|
||||
if (DataBase_Loader* GameDB = AppHost_GetGameDatabase() )
|
||||
|
||||
if (IGameDatabase* GameDB = AppHost_GetGameDatabase() )
|
||||
{
|
||||
if(GameDB->gameLoaded()) {
|
||||
if (GameDB->sectionExists(L"patches", name)) {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "Elfheader.h"
|
||||
#include "CDVD/CDVD.h"
|
||||
#include "Patch.h"
|
||||
#include "DataBase_Loader.h"
|
||||
#include "GameDatabase.h"
|
||||
#include "SamplProf.h"
|
||||
|
||||
using namespace R5900; // for R5900 disasm tools
|
||||
|
@ -574,60 +574,22 @@ __forceinline void CPU_INT( u32 n, s32 ecycle)
|
|||
cpuSetNextBranchDelta( cpuRegs.eCycle[n] );
|
||||
}
|
||||
|
||||
// Called from recompilers; __fastcall define is mandatory.
|
||||
void __fastcall eeGameStarting()
|
||||
{
|
||||
if (!g_GameStarted && ElfCRC) {
|
||||
wxString gameCRC( wxsFormat( L"%8.8x", ElfCRC ) );
|
||||
wxString gameName = L"Unknown Game (\?\?\?)";
|
||||
wxString gameSerial = L" [" + DiscID + L"]";
|
||||
wxString gameCompat = L" [Status = Unknown]";
|
||||
wxString gamePatch = L"";
|
||||
wxString gameFixes = L"";
|
||||
wxString gameCheats = L"";
|
||||
|
||||
if (DataBase_Loader* GameDB = AppHost_GetGameDatabase() )
|
||||
{
|
||||
if (GameDB->gameLoaded()) {
|
||||
int compat = GameDB->getInt("Compat");
|
||||
gameName = GameDB->getString("Name");
|
||||
gameName += L" (" + GameDB->getString("Region") + L")";
|
||||
gameCompat = L" [Status = "+compatToStringWX(compat)+L"]";
|
||||
}
|
||||
|
||||
if (EmuConfig.EnablePatches) {
|
||||
int patches = InitPatches(gameCRC);
|
||||
if (patches) {
|
||||
wxString pString( wxsFormat( L"%d", patches ) );
|
||||
gamePatch = L" [Patches = " + pString + L"]";
|
||||
}
|
||||
int fixes = loadGameSettings(GameDB);
|
||||
if (fixes) {
|
||||
wxString pString( wxsFormat( L"%d", fixes ) );
|
||||
gameFixes = L" [Fixes = " + pString + L"]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EmuConfig.EnableCheats) {
|
||||
int cheats = InitCheats(gameCRC);
|
||||
if (cheats) {
|
||||
wxString cString( wxsFormat( L"%d", cheats ) );
|
||||
gameCheats = L" [Cheats = " + cString + L"]";
|
||||
}
|
||||
}
|
||||
|
||||
Console.SetTitle(gameName+gameSerial+gameCompat+gameFixes+gamePatch+gameCheats);
|
||||
|
||||
GetMTGS().SendGameCRC(ElfCRC);
|
||||
if (!g_GameStarted)
|
||||
{
|
||||
Console.WriteLn( Color_Green, "(R5900) ELF Entry point! [addr=0x%08X]", ElfEntry );
|
||||
g_GameStarted = true;
|
||||
|
||||
if (0) ProfilerSetEnabled(true);
|
||||
GetCoreThread().GameStartingInThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn( Color_Green, "(R5900) Re-executed ELF Entry point (ignored) [addr=0x%08X]", ElfEntry );
|
||||
}
|
||||
|
||||
if (EmuConfig.EnablePatches) ApplyPatch(0);
|
||||
if (EmuConfig.EnableCheats) ApplyCheat(0);
|
||||
}
|
||||
|
||||
// Called from recompilers; __fastcall define is mandatory.
|
||||
void __fastcall eeloadReplaceOSDSYS()
|
||||
{
|
||||
g_SkipBiosHack = false;
|
||||
|
|
|
@ -257,17 +257,17 @@ void intSetBranch();
|
|||
void __fastcall intDoBranch(u32 target);
|
||||
|
||||
// modules loaded at hardcoded addresses by the kernel
|
||||
const u32 EEKERNEL_START = 0;
|
||||
const u32 EENULL_START = 0x81FC0;
|
||||
const u32 EELOAD_START = 0x82000;
|
||||
const u32 EELOAD_SIZE = 0x20000; // overestimate for searching
|
||||
const u32 EEKERNEL_START = 0;
|
||||
const u32 EENULL_START = 0x81FC0;
|
||||
const u32 EELOAD_START = 0x82000;
|
||||
const u32 EELOAD_SIZE = 0x20000; // overestimate for searching
|
||||
|
||||
void __fastcall eeGameStarting();
|
||||
void __fastcall eeloadReplaceOSDSYS();
|
||||
extern void __fastcall eeGameStarting();
|
||||
extern void __fastcall eeloadReplaceOSDSYS();
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// R5900 Public Interface / API
|
||||
//
|
||||
// --------------------------------------------------------------------------------------
|
||||
// R5900cpu
|
||||
// --------------------------------------------------------------------------------------
|
||||
// [TODO] : This is on the list to get converted to a proper C++ class. I'm putting it
|
||||
// off until I get my new IOPint and IOPrec re-merged. --air
|
||||
//
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
// Includes needed for cleanup, since we don't have a good system (yet) for
|
||||
// cleaning up these things.
|
||||
#include "sVU_zerorec.h"
|
||||
#include "DataBase_Loader.h"
|
||||
#include "GameDatabase.h"
|
||||
|
||||
extern void closeNewVif(int idx);
|
||||
extern void resetNewVif(int idx);
|
||||
|
|
|
@ -182,10 +182,6 @@ void SysCoreThread::DoCpuReset()
|
|||
cpuReset();
|
||||
}
|
||||
|
||||
void SysCoreThread::PostVsyncToUI()
|
||||
{
|
||||
}
|
||||
|
||||
// This is called from the PS2 VM at the start of every vsync (either 59.94 or 50 hz by PS2
|
||||
// clock scale, which does not correlate to the actual host machine vsync).
|
||||
//
|
||||
|
@ -197,11 +193,18 @@ void SysCoreThread::PostVsyncToUI()
|
|||
//
|
||||
void SysCoreThread::VsyncInThread()
|
||||
{
|
||||
PostVsyncToUI();
|
||||
if (EmuConfig.EnablePatches) ApplyPatch();
|
||||
if (EmuConfig.EnableCheats) ApplyCheat();
|
||||
}
|
||||
|
||||
void SysCoreThread::GameStartingInThread()
|
||||
{
|
||||
GetMTGS().SendGameCRC(ElfCRC);
|
||||
|
||||
if (EmuConfig.EnablePatches) ApplyPatch(0);
|
||||
if (EmuConfig.EnableCheats) ApplyCheat(0);
|
||||
}
|
||||
|
||||
void SysCoreThread::StateCheckInThread()
|
||||
{
|
||||
GetMTGS().RethrowException();
|
||||
|
|
|
@ -186,7 +186,7 @@ public:
|
|||
|
||||
virtual void StateCheckInThread();
|
||||
virtual void VsyncInThread();
|
||||
virtual void PostVsyncToUI()=0;
|
||||
virtual void GameStartingInThread();
|
||||
|
||||
virtual void ApplySettings( const Pcsx2Config& src );
|
||||
virtual void UploadStateCopy( const VmStateBuffer& copy );
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "AppCommon.h"
|
||||
#include "AppCoreThread.h"
|
||||
#include "RecentIsoList.h"
|
||||
#include "DataBase_Loader.h"
|
||||
#include "AppGameDatabase.h"
|
||||
|
||||
#include "System.h"
|
||||
#include "System/SysThreads.h"
|
||||
|
@ -318,7 +318,7 @@ struct pxAppResources
|
|||
ScopedPtr<wxImageList> ToolbarImages;
|
||||
ScopedPtr<wxIconBundle> IconBundle;
|
||||
ScopedPtr<wxBitmap> Bitmap_Logo;
|
||||
ScopedPtr<DataBase_Loader> GameDB;
|
||||
ScopedPtr<AppGameDatabase> GameDB;
|
||||
|
||||
pxAppResources();
|
||||
virtual ~pxAppResources() throw() { }
|
||||
|
@ -568,6 +568,7 @@ public:
|
|||
void SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override=wxEmptyString );
|
||||
void SysShutdown();
|
||||
void LogicalVsync();
|
||||
void GameStarting();
|
||||
|
||||
GSFrame& GetGsFrame() const;
|
||||
MainEmuFrame& GetMainFrame() const;
|
||||
|
@ -618,7 +619,7 @@ public:
|
|||
return m_Resources->ImageId;
|
||||
}
|
||||
|
||||
DataBase_Loader* GetGameDatabase();
|
||||
AppGameDatabase* GetGameDatabase();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Overrides of wxApp virtuals:
|
||||
|
|
|
@ -144,9 +144,12 @@ void AppCoreThread::ChangeCdvdSource()
|
|||
// TODO: Add a listener for CDVDsource changes? Or should we bother?
|
||||
}
|
||||
|
||||
extern int loadGameSettings(IGameDatabase* gameDB=NULL);
|
||||
|
||||
void AppCoreThread::OnResumeReady()
|
||||
{
|
||||
ApplySettings( g_Conf->EmuOptions );
|
||||
loadGameSettings();
|
||||
|
||||
CDVD_SourceType cdvdsrc( g_Conf->CdvdSource );
|
||||
if( cdvdsrc != CDVDsys_GetSourceType() || (cdvdsrc==CDVDsrc_Iso && (CDVDsys_GetFile(cdvdsrc) != g_Conf->CurrentIso)) )
|
||||
|
@ -230,9 +233,16 @@ void AppCoreThread::OnCleanupInThread()
|
|||
_parent::OnCleanupInThread();
|
||||
}
|
||||
|
||||
void AppCoreThread::PostVsyncToUI()
|
||||
void AppCoreThread::VsyncInThread()
|
||||
{
|
||||
wxGetApp().LogicalVsync();
|
||||
_parent::VsyncInThread();
|
||||
}
|
||||
|
||||
void AppCoreThread::GameStartingInThread()
|
||||
{
|
||||
wxGetApp().GameStarting();
|
||||
_parent::GameStartingInThread();
|
||||
}
|
||||
|
||||
void AppCoreThread::StateCheckInThread()
|
||||
|
|
|
@ -144,7 +144,8 @@ protected:
|
|||
virtual void OnResumeInThread( bool IsSuspended );
|
||||
virtual void OnSuspendInThread();
|
||||
virtual void OnCleanupInThread();
|
||||
virtual void PostVsyncToUI();
|
||||
virtual void VsyncInThread();
|
||||
virtual void GameStartingInThread();
|
||||
virtual void ExecuteTaskInThread();
|
||||
virtual void DoCpuReset();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "App.h"
|
||||
#include "AppGameDatabase.h"
|
||||
|
||||
class DBLoaderHelper
|
||||
{
|
||||
DeclareNoncopyableObject( DBLoaderHelper );
|
||||
|
||||
protected:
|
||||
IGameDatabase& m_gamedb;
|
||||
wxInputStream& m_reader;
|
||||
|
||||
// temp areas used as buffers for accelerated loading of database content. These strings are
|
||||
// allocated and grown only once, and then reused for the duration of the database loading
|
||||
// process; saving thousands of heapp allocation operations.
|
||||
|
||||
wxString m_dest;
|
||||
std::string m_intermediate;
|
||||
|
||||
key_pair m_keyPair;
|
||||
|
||||
public:
|
||||
DBLoaderHelper( wxInputStream& reader, IGameDatabase& db )
|
||||
: m_gamedb(db)
|
||||
, m_reader(reader)
|
||||
{
|
||||
}
|
||||
|
||||
wxString ReadHeader();
|
||||
void ReadGames();
|
||||
|
||||
protected:
|
||||
void doError(bool doMsg = false);
|
||||
bool extractMultiLine();
|
||||
void extract();
|
||||
};
|
||||
|
||||
void DBLoaderHelper::doError(bool doMsg) {
|
||||
if (doMsg) Console.Error("GameDatabase: Bad file data [%s]", m_dest.c_str());
|
||||
m_keyPair.Clear();
|
||||
}
|
||||
|
||||
// Multiline Sections are in the form of:
|
||||
//
|
||||
// [section=value]
|
||||
// content
|
||||
// content
|
||||
// [/section]
|
||||
//
|
||||
// ... where the =value part is OPTIONAL.
|
||||
bool DBLoaderHelper::extractMultiLine() {
|
||||
|
||||
if (m_dest[0] != L'[') return false; // All multiline sections begin with a '['!
|
||||
|
||||
if (!m_dest.EndsWith(L"]")) {
|
||||
doError(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_keyPair.key = m_dest;
|
||||
|
||||
// Use Mid() to strip off the left and right side brackets.
|
||||
wxString midLine(m_dest.Mid(1, m_dest.Length()-2));
|
||||
wxString lvalue(midLine.BeforeFirst(L'=').Trim(true).Trim(false));
|
||||
//wxString rvalue(midLine.AfterFirst(L'=').Trim(true).Trim(false));
|
||||
|
||||
wxString endString;
|
||||
endString.Printf( L"[/%s]", lvalue.c_str() );
|
||||
|
||||
while(!m_reader.Eof()) {
|
||||
pxReadLine( m_reader, m_dest, m_intermediate );
|
||||
if (m_dest.CmpNoCase(endString) == 0) break;
|
||||
m_keyPair.value += m_dest + L"\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DBLoaderHelper::extract() {
|
||||
|
||||
if( !pxParseAssignmentString( m_dest, m_keyPair.key, m_keyPair.value ) ) return;
|
||||
if( m_keyPair.value.IsEmpty() ) doError(true);
|
||||
}
|
||||
|
||||
wxString DBLoaderHelper::ReadHeader()
|
||||
{
|
||||
wxString header;
|
||||
header.reserve(2048);
|
||||
|
||||
while(!m_reader.Eof()) {
|
||||
pxReadLine(m_reader, m_dest, m_intermediate);
|
||||
m_dest.Trim(false).Trim(true);
|
||||
if( !(m_dest.IsEmpty() || m_dest.StartsWith(L"--") || m_dest.StartsWith( L"//" ) || m_dest.StartsWith( L";" )) ) break;
|
||||
header += m_dest + L'\n';
|
||||
}
|
||||
|
||||
if( !m_dest.IsEmpty() )
|
||||
{
|
||||
m_keyPair.Clear();
|
||||
if( !extractMultiLine() ) extract();
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
void DBLoaderHelper::ReadGames()
|
||||
{
|
||||
Game_Data* game = m_gamedb.createNewGame();
|
||||
|
||||
if (m_keyPair.IsOk())
|
||||
m_gamedb.writeString( m_keyPair.key, m_keyPair.value );
|
||||
|
||||
while(!m_reader.Eof()) { // Fill game data, find new game, repeat...
|
||||
pxReadLine(m_reader, m_dest, m_intermediate);
|
||||
m_dest.Trim(true).Trim(false);
|
||||
if( m_dest.IsEmpty() ) continue;
|
||||
|
||||
m_keyPair.Clear();
|
||||
if (!extractMultiLine()) extract();
|
||||
|
||||
if (!m_keyPair.IsOk()) continue;
|
||||
m_gamedb.writeString( m_keyPair.key, m_keyPair.value );
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// AppGameDatabase (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
AppGameDatabase& AppGameDatabase::LoadFromFile(const wxString& file, const wxString& key )
|
||||
{
|
||||
if (!wxFileExists(file))
|
||||
{
|
||||
Console.Error(L"GameDatabase: DataBase Not Found! [%s]", file.c_str());
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxFFileInputStream reader( file );
|
||||
|
||||
if (!reader.IsOk())
|
||||
{
|
||||
//throw Exception::FileNotFound( file );
|
||||
Console.Error(L"GameDatabase: Could not access file (permission denied?) [%s]", file.c_str());
|
||||
}
|
||||
|
||||
DBLoaderHelper loader( reader, *this );
|
||||
|
||||
header = loader.ReadHeader();
|
||||
loader.ReadGames();
|
||||
|
||||
//if (setGame(value)) Console.WriteLn(L"GameDatabase: Found Game! [%s]", value.c_str());
|
||||
//else Console.Warning(L"GameDatabase: Game Not Found! [%s]", value.c_str());
|
||||
|
||||
// Clear the current key after loading.
|
||||
curGame = NULL;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Saves changes to the database
|
||||
void AppGameDatabase::SaveToFile(const wxString& file) {
|
||||
wxFFileOutputStream writer( file );
|
||||
pxWriteMultiline(writer, header);
|
||||
GameDataArray::iterator it( gList.begin() );
|
||||
for ( ; it != gList.end(); ++it) {
|
||||
KeyPairArray::iterator i = it[0].kList.begin();
|
||||
for ( ; i != it[0].kList.end(); ++i) {
|
||||
pxWriteMultiline(writer, i[0].toString() );
|
||||
}
|
||||
pxWriteLine(writer, L"---------------------------------------------");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* 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 "GameDatabase.h"
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// AppGameDatabase
|
||||
// --------------------------------------------------------------------------------------
|
||||
// This class extends BaseGameDatabase_Impl and provides interfaces for loading and saving
|
||||
// the text-formatted game database.
|
||||
//
|
||||
// Example:
|
||||
// ---------------------------------------------
|
||||
// Serial = SLUS-20486
|
||||
// Name = Marvel vs. Capcom 2
|
||||
// Region = NTSC-U
|
||||
// ---------------------------------------------
|
||||
//
|
||||
// [-- separators are a standard part of the formatting]
|
||||
//
|
||||
|
||||
// To Load this game data, use "Serial" as the initial Key
|
||||
// then specify "SLUS-20486" as the value in the constructor.
|
||||
// After the constructor loads the game data, you can use the
|
||||
// GameDatabase class's methods to get the other key's values.
|
||||
// Such as dbLoader.getString("Region") returns "NTSC-U"
|
||||
|
||||
class AppGameDatabase : public BaseGameDatabaseVector
|
||||
{
|
||||
protected:
|
||||
wxString header; // Header of the database
|
||||
wxString baseKey; // Key to separate games by ("Serial")
|
||||
|
||||
public:
|
||||
AppGameDatabase() {}
|
||||
virtual ~AppGameDatabase() throw() {
|
||||
// deque deletes its contents automatically.
|
||||
Console.WriteLn( "(GameDB) Destroying..." );
|
||||
}
|
||||
|
||||
AppGameDatabase& LoadFromFile(const wxString& file = L"GameIndex.dbf", const wxString& key = L"Serial" );
|
||||
void SaveToFile(const wxString& file = L"GameIndex.dbf");
|
||||
};
|
||||
|
||||
static wxString compatToStringWX(int compat) {
|
||||
switch (compat) {
|
||||
case 6: return L"Perfect";
|
||||
case 5: return L"Playable";
|
||||
case 4: return L"In-Game";
|
||||
case 3: return L"Menu";
|
||||
case 2: return L"Intro";
|
||||
case 1: return L"Nothing";
|
||||
default: return L"Unknown";
|
||||
}
|
||||
}
|
|
@ -332,6 +332,127 @@ void Pcsx2App::LogicalVsync()
|
|||
}
|
||||
}
|
||||
|
||||
// Load Game Settings found in database
|
||||
// (game fixes, round modes, clamp modes, etc...)
|
||||
// Returns number of gamefixes set
|
||||
int loadGameSettings(IGameDatabase* gameDB) {
|
||||
if (!gameDB)
|
||||
gameDB = wxGetApp().GetGameDatabase();
|
||||
|
||||
if(!gameDB->gameLoaded()) return 0;
|
||||
|
||||
Pcsx2Config sysLocal( EmuConfig );
|
||||
|
||||
int gf = 0;
|
||||
|
||||
bool rm = false;
|
||||
if (gameDB->keyExists("eeRoundMode"))
|
||||
{
|
||||
SSE_RoundMode eeRM = (SSE_RoundMode)gameDB->getInt("eeRoundMode");
|
||||
if (EnumIsValid(eeRM))
|
||||
{
|
||||
Console.WriteLn("(GameDB) Changing EE/FPU roundmode to %d [%s]", eeRM, EnumToString(eeRM));
|
||||
sysLocal.Cpu.sseMXCSR.SetRoundMode(eeRM);
|
||||
rm = true;
|
||||
++gf;
|
||||
}
|
||||
}
|
||||
|
||||
if (gameDB->keyExists("vuRoundMode"))
|
||||
{
|
||||
SSE_RoundMode vuRM = (SSE_RoundMode)gameDB->getInt("vuRoundMode");
|
||||
if (EnumIsValid(vuRM))
|
||||
{
|
||||
Console.WriteLn("(GameDB) Changing VU0/VU1 roundmode to %d [%s]", vuRM, EnumToString(vuRM));
|
||||
sysLocal.Cpu.sseVUMXCSR.SetRoundMode(vuRM);
|
||||
rm = true;
|
||||
++gf;
|
||||
}
|
||||
}
|
||||
|
||||
if (gameDB->keyExists("eeClampMode")) {
|
||||
int clampMode = gameDB->getInt("eeClampMode");
|
||||
Console.WriteLn("(GameDB) Changing EE/FPU clamp mode [mode=%d]", clampMode);
|
||||
sysLocal.Recompiler.fpuOverflow = (clampMode >= 1);
|
||||
sysLocal.Recompiler.fpuExtraOverflow = (clampMode >= 2);
|
||||
sysLocal.Recompiler.fpuFullMode = (clampMode >= 3);
|
||||
gf++;
|
||||
}
|
||||
|
||||
if (gameDB->keyExists("vuClampMode")) {
|
||||
int clampMode = gameDB->getInt("vuClampMode");
|
||||
Console.WriteLn("(GameDB) Changing VU0/VU1 clamp mode [mode=%d]", clampMode);
|
||||
sysLocal.Recompiler.vuOverflow = (clampMode >= 1);
|
||||
sysLocal.Recompiler.vuExtraOverflow = (clampMode >= 2);
|
||||
sysLocal.Recompiler.vuSignOverflow = (clampMode >= 3);
|
||||
gf++;
|
||||
}
|
||||
|
||||
for( GamefixId id=GamefixId_FIRST; id<pxEnumEnd; ++id )
|
||||
{
|
||||
wxString key( EnumToString(id) );
|
||||
key += L"Hack";
|
||||
|
||||
if (gameDB->keyExists(key))
|
||||
{
|
||||
bool enableIt = gameDB->getBool(key);
|
||||
sysLocal.Gamefixes.Set(id, enableIt );
|
||||
Console.WriteLn(L"(GameDB) %s Gamefix: " + key, enableIt ? L"Enabled" : L"Disabled" );
|
||||
gf++;
|
||||
}
|
||||
}
|
||||
|
||||
GetCoreThread().ApplySettings( sysLocal );
|
||||
|
||||
return gf;
|
||||
}
|
||||
|
||||
#include "cdvd/CDVD.h"
|
||||
#include "Elfheader.h"
|
||||
#include "Patch.h"
|
||||
|
||||
|
||||
void Pcsx2App::GameStarting()
|
||||
{
|
||||
if( PostAppMethodMyself( &Pcsx2App::GameStarting ) ) return;
|
||||
|
||||
wxString gameCRC;
|
||||
wxString gameName (L"Unknown Game (\?\?\?)");
|
||||
wxString gameSerial (L" [" + DiscID + L"]");
|
||||
wxString gameCompat (L" [Status = Unknown]");
|
||||
wxString gamePatch;
|
||||
wxString gameFixes;
|
||||
wxString gameCheats;
|
||||
|
||||
if( ElfCRC ) gameCRC.Printf( L"%8.8x", ElfCRC );
|
||||
|
||||
if (IGameDatabase* GameDB = AppHost_GetGameDatabase() )
|
||||
{
|
||||
if (GameDB->gameLoaded()) {
|
||||
int compat = GameDB->getInt("Compat");
|
||||
gameName = GameDB->getString("Name");
|
||||
gameName += L" (" + GameDB->getString("Region") + L")";
|
||||
gameCompat = L" [Status = "+compatToStringWX(compat)+L"]";
|
||||
}
|
||||
|
||||
if (EmuConfig.EnablePatches) {
|
||||
if (int patches = InitPatches(gameCRC)) {
|
||||
gamePatch.Printf(L" [%d Patches]", patches);
|
||||
}
|
||||
if (int fixes = loadGameSettings(GameDB)) {
|
||||
gameFixes.Printf(L" [%d Fixes]", fixes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EmuConfig.EnableCheats) {
|
||||
if (int cheats = InitCheats(gameCRC)) {
|
||||
gameCheats.Printf(L" [Cheats = %d]", cheats);
|
||||
}
|
||||
}
|
||||
|
||||
Console.SetTitle(gameName+gameSerial+gameCompat+gameFixes+gamePatch+gameCheats);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Pcsx2App Event Handlers
|
||||
|
@ -987,16 +1108,20 @@ SysCoreAllocations& GetSysCoreAlloc()
|
|||
return *wxGetApp().m_CoreAllocs;
|
||||
}
|
||||
|
||||
DataBase_Loader* Pcsx2App::GetGameDatabase()
|
||||
AppGameDatabase* Pcsx2App::GetGameDatabase()
|
||||
{
|
||||
pxAppResources& res( GetResourceCache() );
|
||||
|
||||
|
||||
ScopedLock lock( m_mtx_LoadingGameDB );
|
||||
if( !res.GameDB ) res.GameDB = new DataBase_Loader();
|
||||
if( !res.GameDB )
|
||||
{
|
||||
res.GameDB = new AppGameDatabase();
|
||||
res.GameDB->LoadFromFile();
|
||||
}
|
||||
return res.GameDB;
|
||||
}
|
||||
|
||||
DataBase_Loader* AppHost_GetGameDatabase()
|
||||
IGameDatabase* AppHost_GetGameDatabase()
|
||||
{
|
||||
return wxGetApp().GetGameDatabase();
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "DataBase_Loader.h"
|
||||
#include "App.h"
|
||||
#include "ConfigurationPanels.h"
|
||||
|
||||
extern wxString DiscID;
|
||||
|
@ -42,11 +42,11 @@ wxTextCtrl* CreateMultiLineTextCtrl( wxWindow* parent, int digits, long flags =
|
|||
Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
||||
: BaseApplicableConfigPanel( parent )
|
||||
{
|
||||
//if (!GameDB) GameDB = new DataBase_Loader();
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
//if (!GameDB) GameDB = new GameDatabase();
|
||||
IGameDatabase* GameDB = AppHost_GetGameDatabase();
|
||||
pxAssume( GameDB != NULL );
|
||||
|
||||
searchBtn = new wxButton (this, wxID_DEFAULT, L"Search");
|
||||
searchBtn = new wxButton (this, wxID_ANY, _("Search"));
|
||||
|
||||
serialBox = CreateNumericalTextCtrl(this, 40, wxTE_LEFT);
|
||||
nameBox = CreateNumericalTextCtrl(this, 40, wxTE_LEFT);
|
||||
|
@ -56,11 +56,11 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
|||
patchesBox = CreateMultiLineTextCtrl(this, 40, wxTE_LEFT);
|
||||
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
gameFixes[i] = new pxCheckBox(this, EnumToString(i));
|
||||
gameFixes[i] = new pxCheckBox(this, EnumToString(i), wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER );
|
||||
|
||||
*this += Heading(_("Game Database Editor")).Bold() | StdExpand();
|
||||
*this += Heading(_("This panel lets you add and edit game titles, game fixes, and game patches.")) | StdExpand();
|
||||
|
||||
|
||||
wxFlexGridSizer& sizer1(*new wxFlexGridSizer(5, StdPadding));
|
||||
sizer1.AddGrowableCol(0);
|
||||
|
||||
|
@ -70,7 +70,7 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
|||
sizer1 += serialBox | pxCenter;
|
||||
sizer1 += 5;
|
||||
sizer1 += searchBtn;
|
||||
|
||||
|
||||
placeTextBox(nameBox, "Name: ");
|
||||
placeTextBox(regionBox, "Region: ");
|
||||
placeTextBox(compatBox, "Compatibility: ");
|
||||
|
@ -96,7 +96,7 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
|||
}
|
||||
|
||||
void Panels::GameDatabasePanel::PopulateFields() {
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
IGameDatabase* GameDB = AppHost_GetGameDatabase();
|
||||
|
||||
if (GameDB->gameLoaded()) {
|
||||
serialBox ->SetLabel(GameDB->getString("Serial"));
|
||||
|
@ -107,7 +107,13 @@ void Panels::GameDatabasePanel::PopulateFields() {
|
|||
patchesBox->SetLabel(GameDB->getString("[patches]"));
|
||||
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
gameFixes[i]->SetValue(GameDB->getBool(EnumToString(i)+wxString(L"Hack")));
|
||||
{
|
||||
wxString keyName (EnumToString(i)); keyName += L"Hack";
|
||||
if( GameDB->keyExists(keyName) )
|
||||
gameFixes[i]->SetValue(GameDB->getBool(keyName));
|
||||
else
|
||||
gameFixes[i]->SetIndeterminate();
|
||||
}
|
||||
}
|
||||
else {
|
||||
serialBox ->SetLabel(L"");
|
||||
|
@ -129,35 +135,37 @@ void Panels::GameDatabasePanel::PopulateFields() {
|
|||
|
||||
// returns True if the database is modified, or FALSE if no changes to save.
|
||||
bool Panels::GameDatabasePanel::WriteFieldsToDB() {
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
wxString wxStr( serialBox->GetValue() );
|
||||
IGameDatabase* GameDB = AppHost_GetGameDatabase();
|
||||
|
||||
if (wxStr.IsEmpty()) return false;
|
||||
if (wxStr != GameDB->getString("Serial")) {
|
||||
GameDB->addGame(wxStr);
|
||||
}
|
||||
if (serialBox->GetValue().IsEmpty()) return false;
|
||||
|
||||
writeTextBoxToDB("Name", nameBox->GetValue());
|
||||
writeTextBoxToDB("Region", regionBox->GetValue());
|
||||
writeTextBoxToDB("Compat", compatBox->GetValue());
|
||||
writeTextBoxToDB("[comments]", commentBox->GetValue());
|
||||
writeTextBoxToDB("[patches]", patchesBox->GetValue());
|
||||
// Only write the serial if its been changed
|
||||
if( !GameDB->setGame(serialBox->GetValue()) )
|
||||
GameDB->writeString(L"Serial", 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());
|
||||
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i) {
|
||||
const bool val = gameFixes[i]->GetValue();
|
||||
wxString keyName( EnumToString(i) ); keyName += L"Hack";
|
||||
if (!val) GameDB->deleteKey(keyName);
|
||||
else GameDB->writeBool(keyName, val);
|
||||
wxString keyName (EnumToString(i)); keyName += L"Hack";
|
||||
|
||||
if (gameFixes[i]->IsIndeterminate())
|
||||
GameDB->deleteKey(keyName);
|
||||
else
|
||||
GameDB->writeBool(keyName, gameFixes[i]->GetValue());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) {
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
IGameDatabase* GameDB = AppHost_GetGameDatabase();
|
||||
wxString wxStr = serialBox->GetValue();
|
||||
|
||||
|
||||
if( wxStr.IsEmpty() ) wxStr = DiscID;
|
||||
|
||||
|
||||
bool bySerial = 1;//searchType->GetSelection()==0;
|
||||
if (bySerial) GameDB->setGame(wxStr);
|
||||
|
||||
|
@ -166,49 +174,14 @@ void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) {
|
|||
}
|
||||
|
||||
void Panels::GameDatabasePanel::Apply() {
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
AppGameDatabase* GameDB = wxGetApp().GetGameDatabase();
|
||||
if( WriteFieldsToDB() )
|
||||
{
|
||||
Console.WriteLn("Saving changes to Game Database...");
|
||||
GameDB->saveToFile();
|
||||
GameDB->SaveToFile();
|
||||
}
|
||||
}
|
||||
|
||||
void Panels::GameDatabasePanel::AppStatusEvent_OnSettingsApplied()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
//#define lineIndent(_wxSizer, txt) {_wxSizer+=5;_wxSizer+=5;_wxSizer+=Heading(txt);_wxSizer+=5;_wxSizer+=5;}
|
||||
|
||||
//searchBox = CreateNumericalTextCtrl(this, 40, wxTE_LEFT);
|
||||
//searchType = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
|
||||
//searchList = new wxListBox (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE | wxLB_SORT | wxLB_NEEDED_SB);
|
||||
//searchList->SetFont (wxFont(searchList->GetFont().GetPointSize()+1, wxFONTFAMILY_MODERN, wxNORMAL, wxNORMAL, false, L"Lucida Console"));
|
||||
//searchList->SetMinSize(wxSize(wxDefaultCoord, std::max(searchList->GetMinSize().GetHeight(), 96)));
|
||||
|
||||
searchType->Append(L"Game Serial", (void*)0);
|
||||
searchType->Append(L"Game Name" , (void*)0);
|
||||
searchType->SetSelection(0);
|
||||
|
||||
sizer1 += searchType;
|
||||
sizer1 += 5;
|
||||
sizer1 += searchBox | pxCenter;
|
||||
sizer1 += 5;
|
||||
sizer1 += searchBtn;
|
||||
|
||||
sizer1 += 5;
|
||||
sizer1 += 5;
|
||||
sizer1 += searchList | StdExpand();// pxCenter;
|
||||
sizer1 += 5;
|
||||
sizer1 += 5;
|
||||
|
||||
lineIndent(sizer1, L"");
|
||||
sizer1 += 5;
|
||||
sizer1 += 5;
|
||||
sizer1 += new wxStaticLine(this) | StdExpand();
|
||||
sizer1 += 5;
|
||||
sizer1 += 5;
|
||||
lineIndent(sizer1, L"");
|
||||
lineIndent(sizer1, L"Game Info");
|
||||
*/
|
||||
|
|
|
@ -260,6 +260,14 @@
|
|||
RelativePath="..\..\Utilities\folderdesc.txt"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\GameDatabase.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\GameDatabase.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\PrecompiledHeader.cpp"
|
||||
>
|
||||
|
@ -312,22 +320,6 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Game DataBase"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\DataBase_Loader.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\DataBase_Loader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\File_Reader.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Patch"
|
||||
>
|
||||
|
@ -467,10 +459,6 @@
|
|||
RelativePath="..\..\System\PageFaultSource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Paths.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Plugins.h"
|
||||
>
|
||||
|
@ -1896,6 +1884,10 @@
|
|||
RelativePath="..\..\gui\AppEventSources.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\AppGameDatabase.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\AppInit.cpp"
|
||||
>
|
||||
|
@ -2657,6 +2649,10 @@
|
|||
RelativePath="..\..\gui\AppForwardDefs.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\AppGameDatabase.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\ApplyState.h"
|
||||
>
|
||||
|
|
|
@ -17,18 +17,17 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include <xmmintrin.h>
|
||||
|
||||
SSE_MXCSR g_sseMXCSR = { DEFAULT_sseMXCSR };
|
||||
SSE_MXCSR g_sseVUMXCSR = { DEFAULT_sseVUMXCSR };
|
||||
SSE_MXCSR g_sseMXCSR = { DEFAULT_sseMXCSR };
|
||||
SSE_MXCSR g_sseVUMXCSR = { DEFAULT_sseVUMXCSR };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetCPUState -- for assignment of SSE roundmodes and clampmodes.
|
||||
//
|
||||
void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVUMXCSR)
|
||||
{
|
||||
//Msgbox::Alert("SetCPUState: Config.sseMXCSR = %x; Config.sseVUMXCSR = %x \n", Config.sseMXCSR, Config.sseVUMXCSR);
|
||||
|
||||
g_sseMXCSR = sseMXCSR.ApplyReserveMask();
|
||||
g_sseVUMXCSR = sseVUMXCSR.ApplyReserveMask();
|
||||
g_sseMXCSR = sseMXCSR.ApplyReserveMask();
|
||||
g_sseVUMXCSR = sseVUMXCSR.ApplyReserveMask();
|
||||
|
||||
_mm_setcsr( g_sseMXCSR.bitmask );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue