mirror of https://github.com/PCSX2/pcsx2.git
Commandline, UI, and Game Database Work:
* Improved console window behavior during startup and shutdown (also fixes minor threading issues) * Added better failsafes for avoiding "rouge" pcsx2 processes left behind when wxWidgets would fail to "notice" window closures properly. * Database loader is now thread-safe and cleans itself up properly on exit. * Added some handy enumeration tools for the gamefixes (prep work for making them commandline controllable). * ... and more prelim commandline work! (actual functional implementations coming very soon) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3212 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
dce5ca9aca
commit
2300f972e4
common/include/Utilities
pcsx2
|
@ -561,7 +561,9 @@ protected:
|
|||
void OnDialogCreated( wxCommandEvent& evt );
|
||||
void OnOkCancel(wxCommandEvent& evt);
|
||||
void OnCloseWindow(wxCloseEvent& event);
|
||||
|
||||
|
||||
bool ShouldPreventAppExit() const { return false; }
|
||||
|
||||
void DoAutoCenter();
|
||||
};
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
#include "ps2/BiosTools.h"
|
||||
#include "DataBase_Loader.h"
|
||||
|
||||
ScopedPtr<DataBase_Loader> GameDB;
|
||||
|
||||
wxString DiscID;
|
||||
|
||||
static cdvdStruct cdvd;
|
||||
|
@ -356,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 (GameDB) {
|
||||
if (DataBase_Loader* GameDB = AppHost_GetGameDatabase()) {
|
||||
wxString gameSerial = DiscID;
|
||||
if (DiscID.IsEmpty()) { // Search for crc if no Serial Code
|
||||
gameSerial = wxString(wxsFormat( L"%8.8x", ElfCRC ));
|
||||
|
@ -555,8 +553,6 @@ void cdvdReset()
|
|||
cdvd.RTC.day = (u8)curtime.GetDay(wxDateTime::GMT9);
|
||||
cdvd.RTC.month = (u8)curtime.GetMonth(wxDateTime::GMT9) + 1; // WX returns Jan as "0"
|
||||
cdvd.RTC.year = (u8)(curtime.GetYear(wxDateTime::GMT9) - 2000);
|
||||
|
||||
if( !GameDB ) GameDB = new DataBase_Loader();
|
||||
}
|
||||
|
||||
struct Freeze_v10Compat
|
||||
|
|
|
@ -19,6 +19,25 @@
|
|||
|
||||
class IniInterface;
|
||||
|
||||
class pxEnumEnd_t { };
|
||||
const pxEnumEnd_t pxEnumEnd = {};
|
||||
|
||||
// [TODO] Add assertion checks to ++/-- operators!
|
||||
#define ImplementEnumOperators( enumName ) \
|
||||
static __forceinline GamefixId& operator++( enumName& src ) { src = (enumName)((int)src+1); return src; } \
|
||||
static __forceinline GamefixId& operator--( enumName& src ) { src = (enumName)((int)src-1); return src; } \
|
||||
static __forceinline GamefixId operator++( enumName& src, int ) { enumName orig = src; src = (enumName)((int)src+1); return orig; } \
|
||||
static __forceinline GamefixId operator--( enumName& src, int ) { enumName orig = src; src = (enumName)((int)src-1); return src; } \
|
||||
\
|
||||
static __forceinline bool operator<( const enumName& left, const pxEnumEnd_t& ) { return (int)left < enumName##_COUNT; } \
|
||||
static __forceinline bool operator!=( const enumName& left, const pxEnumEnd_t& ) { return (int)left != enumName##_COUNT; } \
|
||||
static __forceinline bool operator==( const enumName& left, const pxEnumEnd_t& ) { return (int)left == enumName##_COUNT; } \
|
||||
\
|
||||
static __forceinline void EnumAssertOnBounds( enumName id ) { \
|
||||
pxAssume( ((int)id >= enumName##_FIRST) && ((int)id < enumName##_COUNT ) ); } \
|
||||
\
|
||||
extern const wxChar* EnumToString( enumName id )
|
||||
|
||||
enum PluginsEnum_t
|
||||
{
|
||||
PluginId_GS = 0,
|
||||
|
@ -37,6 +56,25 @@ enum PluginsEnum_t
|
|||
PluginId_Mcd
|
||||
};
|
||||
|
||||
enum GamefixId
|
||||
{
|
||||
GamefixId_FIRST = 0,
|
||||
|
||||
Fix_VuAddSub = GamefixId_FIRST,
|
||||
Fix_VuClipFlag,
|
||||
Fix_FpuCompare,
|
||||
Fix_FpuMultiply,
|
||||
Fix_FpuNegDiv,
|
||||
Fix_XGKick,
|
||||
Fix_IpuWait,
|
||||
Fix_EETiming,
|
||||
Fix_SkipMpeg,
|
||||
|
||||
GamefixId_COUNT
|
||||
};
|
||||
|
||||
ImplementEnumOperators( GamefixId );
|
||||
|
||||
//------------ DEFAULT sseMXCSR VALUES ---------------
|
||||
#define DEFAULT_sseMXCSR 0xffc0 //FPU rounding > DaZ, FtZ, "chop"
|
||||
#define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop"
|
||||
|
@ -440,6 +478,13 @@ struct Pcsx2Config
|
|||
GamefixOptions() : bitset( 0 ) {}
|
||||
void LoadSave( IniInterface& conf );
|
||||
|
||||
void Set( const wxString& list, bool enabled=true );
|
||||
bool Clear( const wxString& list ) { Set( list, false ); }
|
||||
|
||||
bool Get( GamefixId id ) const;
|
||||
void Set( GamefixId id, bool enabled=true );
|
||||
bool Clear( GamefixId id ) { Set( id, false ); }
|
||||
|
||||
bool operator ==( const GamefixOptions& right ) const
|
||||
{
|
||||
return OpEqu( bitset );
|
||||
|
@ -562,8 +607,6 @@ TraceLogFilters& SetTraceConfig();
|
|||
#define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP && GetSysCoreAlloc().IsRecAvailable_IOP())
|
||||
|
||||
//------------ SPECIAL GAME FIXES!!! ---------------
|
||||
#define NUM_OF_GAME_FIXES 9
|
||||
|
||||
#define CHECK_VUADDSUBHACK (EmuConfig.Gamefixes.VuAddSubHack) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
|
||||
#define CHECK_FPUCOMPAREHACK (EmuConfig.Gamefixes.FpuCompareHack) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
|
||||
#define CHECK_VUCLIPFLAGHACK (EmuConfig.Gamefixes.VuClipFlagHack) // Special Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
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.key.clear();
|
||||
keyPair.Clear();
|
||||
}
|
||||
|
||||
// Multiline Sections are in the form of:
|
||||
|
@ -47,8 +47,7 @@ bool DataBase_Loader::extractMultiLine(const wxString& line, key_pair& keyPair,
|
|||
}
|
||||
|
||||
void DataBase_Loader::extract(const wxString& line, key_pair& keyPair, wxInputStream& reader) {
|
||||
keyPair.key.clear();
|
||||
keyPair.value.clear();
|
||||
keyPair.Clear();
|
||||
|
||||
if( line.IsEmpty() ) return;
|
||||
|
||||
|
|
|
@ -28,6 +28,20 @@ struct 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!" );
|
||||
|
@ -54,8 +68,17 @@ class Game_Data {
|
|||
public:
|
||||
wxString id; // Serial Identification Code
|
||||
deque<key_pair> kList; // List of all (key, value) pairs for game data
|
||||
Game_Data(const wxString& _id)
|
||||
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:
|
||||
|
@ -83,8 +106,9 @@ protected:
|
|||
const wxString m_emptyString; // empty string for returning stuff .. never modify!
|
||||
wxString m_dest;
|
||||
std::string m_intermediate;
|
||||
|
||||
public:
|
||||
deque<Game_Data*> gList; // List of all game data
|
||||
deque<Game_Data> gList; // List of all game data
|
||||
Game_Data* curGame; // Current game data
|
||||
wxString header; // Header of the database
|
||||
wxString baseKey; // Key to separate games by ("Serial")
|
||||
|
@ -99,34 +123,34 @@ public:
|
|||
wxFFileInputStream reader( file );
|
||||
key_pair keyPair;
|
||||
wxString s0;
|
||||
Game_Data* game = NULL;
|
||||
Game_Data game;
|
||||
|
||||
try {
|
||||
while(!reader.Eof()) {
|
||||
while(!reader.Eof()) { // Find first game
|
||||
pxReadLine(reader, s0, m_intermediate);
|
||||
extract(s0.Trim(true).Trim(false), keyPair, reader);
|
||||
if (keyPair.key == key) break;
|
||||
if (keyPair.CompareKey(key)) break;
|
||||
header += s0 + L'\n';
|
||||
}
|
||||
game = new Game_Data(keyPair.value);
|
||||
game->kList.push_back(keyPair);
|
||||
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.key.IsEmpty()) continue;
|
||||
if (keyPair.key == key) {
|
||||
if (!keyPair.IsOk()) continue;
|
||||
if (keyPair.CompareKey(key)) {
|
||||
gList.push_back(game);
|
||||
game = new Game_Data(keyPair.value);
|
||||
game.NewSerial(keyPair.value);
|
||||
}
|
||||
game->kList.push_back(keyPair);
|
||||
game.kList.push_back(keyPair);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception::EndOfStream& ) {}
|
||||
|
||||
if (game) gList.push_back(game);
|
||||
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());
|
||||
|
@ -135,15 +159,16 @@ public:
|
|||
|
||||
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) {
|
||||
deque<Game_Data*>::iterator it = gList.begin();
|
||||
deque<Game_Data>::iterator it = gList.begin();
|
||||
for ( ; it != gList.end(); ++it) {
|
||||
if (it[0]->id == id) {
|
||||
curGame = it[0];
|
||||
if (it[0].id == id) {
|
||||
curGame = &it[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -162,10 +187,10 @@ public:
|
|||
void saveToFile(const wxString& file = L"GameIndex.dbf") {
|
||||
wxFFileOutputStream writer( file );
|
||||
pxWriteMultiline(writer, header);
|
||||
deque<Game_Data*>::iterator it = gList.begin();
|
||||
deque<Game_Data>::iterator it = gList.begin();
|
||||
for ( ; it != gList.end(); ++it) {
|
||||
deque<key_pair>::iterator i = it[0]->kList.begin();
|
||||
for ( ; i != it[0]->kList.end(); ++i) {
|
||||
deque<key_pair>::iterator i = it[0].kList.begin();
|
||||
for ( ; i != it[0].kList.end(); ++i) {
|
||||
pxWriteMultiline(writer, i[0].toString() );
|
||||
}
|
||||
pxWriteLine(writer, L"---------------------------------------------");
|
||||
|
@ -176,11 +201,11 @@ public:
|
|||
// 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 = new Game_Data(id);
|
||||
key_pair kp(baseKey, id);
|
||||
game->kList.push_back(kp);
|
||||
Game_Data game(id);
|
||||
key_pair kp(baseKey, id);
|
||||
game.kList.push_back(kp);
|
||||
gList.push_back(game);
|
||||
curGame = game;
|
||||
curGame = &(gList.end()-1)[0];
|
||||
}
|
||||
|
||||
// Searches the current game's data to see if the given key exists
|
||||
|
@ -188,7 +213,7 @@ public:
|
|||
if (curGame) {
|
||||
deque<key_pair>::iterator it = curGame->kList.begin();
|
||||
for ( ; it != curGame->kList.end(); ++it) {
|
||||
if (it[0].key == key) {
|
||||
if (it[0].CompareKey(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +227,7 @@ public:
|
|||
if (curGame) {
|
||||
deque<key_pair>::iterator it = curGame->kList.begin();
|
||||
for ( ; it != curGame->kList.end(); ++it) {
|
||||
if (it[0].key == key) {
|
||||
if (it[0].CompareKey(key)) {
|
||||
curGame->kList.erase(it);
|
||||
return;
|
||||
}
|
||||
|
@ -216,7 +241,7 @@ public:
|
|||
if (curGame) {
|
||||
deque<key_pair>::iterator it = curGame->kList.begin();
|
||||
for ( ; it != curGame->kList.end(); ++it) {
|
||||
if (it[0].key == key) {
|
||||
if (it[0].CompareKey(key)) {
|
||||
return it[0].value;
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +298,7 @@ public:
|
|||
if (curGame) {
|
||||
deque<key_pair>::iterator it = curGame->kList.begin();
|
||||
for ( ; it != curGame->kList.end(); ++it) {
|
||||
if (it[0].key == key) {
|
||||
if (it[0].CompareKey(key)) {
|
||||
it[0].value = value;
|
||||
return;
|
||||
}
|
||||
|
@ -357,4 +382,4 @@ static int loadGameSettings(DataBase_Loader* gameDB) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern ScopedPtr<DataBase_Loader> GameDB;
|
||||
extern DataBase_Loader* AppHost_GetGameDatabase();
|
|
@ -138,14 +138,17 @@ int InitPatches(const wxString& name)
|
|||
const wxString crc( L"[patches = " + name + L"]" );
|
||||
patchnumber = 0;
|
||||
|
||||
if (GameDB && GameDB->gameLoaded()) {
|
||||
if (GameDB->sectionExists(L"patches", name)) {
|
||||
patch = GameDB->getSection(L"patches", name);
|
||||
patchFound = true;
|
||||
}
|
||||
else if (GameDB->keyExists(L"[patches]")) {
|
||||
patch = GameDB->getString(L"[patches]");
|
||||
patchFound = true;
|
||||
if (DataBase_Loader* GameDB = AppHost_GetGameDatabase() )
|
||||
{
|
||||
if(GameDB->gameLoaded()) {
|
||||
if (GameDB->sectionExists(L"patches", name)) {
|
||||
patch = GameDB->getSection(L"patches", name);
|
||||
patchFound = true;
|
||||
}
|
||||
else if (GameDB->keyExists(L"[patches]")) {
|
||||
patch = GameDB->getString(L"[patches]");
|
||||
patchFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -246,6 +246,85 @@ void Pcsx2Config::GSOptions::LoadSave( IniInterface& ini )
|
|||
IniEntry( FramesToSkip );
|
||||
}
|
||||
|
||||
const wxChar *const tbl_GamefixNames[] =
|
||||
{
|
||||
L"VuAddSub",
|
||||
L"VuClipFlag",
|
||||
L"FpuCompare",
|
||||
L"FpuMul",
|
||||
L"FpuNegDiv",
|
||||
L"XGKick",
|
||||
L"IpuWait",
|
||||
L"EETiming",
|
||||
L"SkipMpeg"
|
||||
};
|
||||
|
||||
const __forceinline wxChar* EnumToString( GamefixId id )
|
||||
{
|
||||
return tbl_GamefixNames[id];
|
||||
}
|
||||
|
||||
// Enables a full list of gamefixes. The list can be either comma or pipe-delimited.
|
||||
// Example: "XGKick,IpuWait" or "EEtiming,FpuCompare"
|
||||
// If an unrecognized tag is encountered, a warning is printed to the console, but no error
|
||||
// is generated. This allows the system to function in the event that future versions of
|
||||
// PCSX2 remove old hacks once they become obsolete.
|
||||
void Pcsx2Config::GamefixOptions::Set( const wxString& list, bool enabled )
|
||||
{
|
||||
wxStringTokenizer izer( list, L",|", wxTOKEN_STRTOK );
|
||||
|
||||
while( izer.HasMoreTokens() )
|
||||
{
|
||||
wxString token( izer.GetNextToken() );
|
||||
|
||||
GamefixId i;
|
||||
for (i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
{
|
||||
if( token.CmpNoCase( EnumToString(i) ) == 0 ) break;
|
||||
}
|
||||
if( i < pxEnumEnd ) Set( i );
|
||||
}
|
||||
}
|
||||
|
||||
void Pcsx2Config::GamefixOptions::Set( GamefixId id, bool enabled )
|
||||
{
|
||||
EnumAssertOnBounds( id );
|
||||
switch(id)
|
||||
{
|
||||
case Fix_VuAddSub: VuAddSubHack = enabled; break;
|
||||
case Fix_VuClipFlag: VuClipFlagHack = enabled; break;
|
||||
case Fix_FpuCompare: FpuCompareHack = enabled; break;
|
||||
case Fix_FpuMultiply: FpuMulHack = enabled; break;
|
||||
case Fix_FpuNegDiv: FpuNegDivHack = enabled; break;
|
||||
case Fix_XGKick: XgKickHack = enabled; break;
|
||||
case Fix_IpuWait: IPUWaitHack = enabled; break;
|
||||
case Fix_EETiming: EETimingHack = enabled; break;
|
||||
case Fix_SkipMpeg: SkipMPEGHack = enabled; break;
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
bool Pcsx2Config::GamefixOptions::Get( GamefixId id ) const
|
||||
{
|
||||
EnumAssertOnBounds( id );
|
||||
switch(id)
|
||||
{
|
||||
case Fix_VuAddSub: return VuAddSubHack;
|
||||
case Fix_VuClipFlag: return VuClipFlagHack;
|
||||
case Fix_FpuCompare: return FpuCompareHack;
|
||||
case Fix_FpuMultiply: return FpuMulHack;
|
||||
case Fix_FpuNegDiv: return FpuNegDivHack;
|
||||
case Fix_XGKick: return XgKickHack;
|
||||
case Fix_IpuWait: return IPUWaitHack;
|
||||
case Fix_EETiming: return EETimingHack;
|
||||
case Fix_SkipMpeg: return SkipMPEGHack;
|
||||
|
||||
jNO_DEFAULT
|
||||
}
|
||||
return false; // unreachable, but we still need to suppress warnings >_<
|
||||
}
|
||||
|
||||
void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini )
|
||||
{
|
||||
GamefixOptions defaults;
|
||||
|
|
|
@ -585,23 +585,26 @@ void __fastcall eeGameStarting()
|
|||
wxString gameFixes = L"";
|
||||
wxString gameCheats = L"";
|
||||
|
||||
if (GameDB && 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"]";
|
||||
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"]";
|
||||
}
|
||||
int fixes = loadGameSettings(GameDB);
|
||||
if (fixes) {
|
||||
wxString pString( wxsFormat( L"%d", fixes ) );
|
||||
gameFixes = L" [Fixes = " + pString + 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"]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -328,7 +328,6 @@ void SysCoreAllocations::CleanupMess() throw()
|
|||
{
|
||||
try
|
||||
{
|
||||
GameDB.Delete();
|
||||
closeNewVif(0);
|
||||
closeNewVif(1);
|
||||
|
||||
|
|
|
@ -22,7 +22,11 @@
|
|||
|
||||
BaseCompressThread::~BaseCompressThread() throw()
|
||||
{
|
||||
if( m_PendingSaveFlag ) wxGetApp().ClearPendingSave();
|
||||
if( m_PendingSaveFlag )
|
||||
{
|
||||
wxGetApp().ClearPendingSave();
|
||||
m_PendingSaveFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseCompressThread::SetPendingSave()
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "AppCommon.h"
|
||||
#include "AppCoreThread.h"
|
||||
#include "RecentIsoList.h"
|
||||
#include "DataBase_Loader.h"
|
||||
|
||||
#include "System.h"
|
||||
#include "System/SysThreads.h"
|
||||
|
@ -317,6 +318,7 @@ struct pxAppResources
|
|||
ScopedPtr<wxImageList> ToolbarImages;
|
||||
ScopedPtr<wxIconBundle> IconBundle;
|
||||
ScopedPtr<wxBitmap> Bitmap_Logo;
|
||||
ScopedPtr<DataBase_Loader> GameDB;
|
||||
|
||||
pxAppResources();
|
||||
virtual ~pxAppResources() throw() { }
|
||||
|
@ -359,6 +361,78 @@ public:
|
|||
double GetFramerate() const;
|
||||
};
|
||||
|
||||
class StartupOptions
|
||||
{
|
||||
public:
|
||||
bool ForceWizard;
|
||||
bool ForceConsole;
|
||||
|
||||
// Disables the fast boot option when auto-running games. This option only applies
|
||||
// if SysAutoRun is also true.
|
||||
bool NoFastBoot;
|
||||
|
||||
// Specifies the Iso file to boot; used only if SysAutoRun is enabled and CdvdSource
|
||||
// is set to ISO.
|
||||
wxString IsoFile;
|
||||
|
||||
// Specifies the CDVD source type to use when AutoRunning
|
||||
CDVD_SourceType CdvdSource;
|
||||
|
||||
// Indicates if PCSX2 should autorun the configured CDVD source and/or ISO file.
|
||||
bool SysAutoRun;
|
||||
|
||||
StartupOptions()
|
||||
{
|
||||
ForceWizard = false;
|
||||
NoFastBoot = false;
|
||||
ForceConsole = false;
|
||||
SysAutoRun = false;
|
||||
CdvdSource = CDVDsrc_NoDisc;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CommandlineOverrides
|
||||
{
|
||||
public:
|
||||
AppConfig::FilenameOptions Filenames;
|
||||
wxDirName SettingsFolder;
|
||||
wxFileName SettingsFile;
|
||||
|
||||
bool DisableSpeedhacks;
|
||||
|
||||
// Note that gamefixes in this array should only be honored if the
|
||||
// "HasCustomGamefixes" boolean is also enabled.
|
||||
bool UseGamefix[GamefixId_COUNT];
|
||||
bool ApplyCustomGamefixes;
|
||||
|
||||
public:
|
||||
CommandlineOverrides()
|
||||
{
|
||||
DisableSpeedhacks = false;
|
||||
ApplyCustomGamefixes = false;
|
||||
}
|
||||
|
||||
// Returns TRUE if either speedhacks or gamefixes are being overridden.
|
||||
bool HasCustomHacks() const
|
||||
{
|
||||
return DisableSpeedhacks || ApplyCustomGamefixes;
|
||||
}
|
||||
|
||||
bool HasSettingsOverride() const
|
||||
{
|
||||
return SettingsFolder.IsOk() || SettingsFile.IsOk();
|
||||
}
|
||||
|
||||
bool HasPluginsOverride() const
|
||||
{
|
||||
for( int i=0; i<PluginId_Count; ++i )
|
||||
if( Filenames.Plugins[i].IsOk() ) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// =====================================================================================================
|
||||
// Pcsx2App - main wxApp class
|
||||
// =====================================================================================================
|
||||
|
@ -446,12 +520,18 @@ public:
|
|||
protected:
|
||||
int m_PendingSaves;
|
||||
bool m_ScheduledTermination;
|
||||
bool m_UseGUI;
|
||||
|
||||
public:
|
||||
FramerateManager FpsManager;
|
||||
CommandDictionary GlobalCommands;
|
||||
AcceleratorDictionary GlobalAccels;
|
||||
|
||||
StartupOptions Startup;
|
||||
CommandlineOverrides Overrides;
|
||||
|
||||
wxTimer* m_timer_Termination;
|
||||
|
||||
protected:
|
||||
ScopedPtr<PipeRedirectionBase> m_StdoutRedirHandle;
|
||||
ScopedPtr<PipeRedirectionBase> m_StderrRedirHandle;
|
||||
|
@ -459,11 +539,13 @@ protected:
|
|||
ScopedPtr<RecentIsoList> m_RecentIsoList;
|
||||
ScopedPtr<pxAppResources> m_Resources;
|
||||
|
||||
Threading::Mutex m_mtx_Resources;
|
||||
Threading::Mutex m_mtx_LoadingGameDB;
|
||||
|
||||
public:
|
||||
// Executor Thread for complex VM/System tasks. This thread is used to execute such tasks
|
||||
// in parallel to the main message pump, to allow the main pump to run without fear of
|
||||
// blocked threads stalling the GUI.
|
||||
|
||||
public:
|
||||
ExecutorThread SysExecutorThread;
|
||||
ScopedPtr<SysCoreAllocations> m_CoreAllocs;
|
||||
|
||||
|
@ -535,6 +617,8 @@ public:
|
|||
{
|
||||
return m_Resources->ImageId;
|
||||
}
|
||||
|
||||
DataBase_Loader* GetGameDatabase();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Overrides of wxApp virtuals:
|
||||
|
@ -546,17 +630,23 @@ public:
|
|||
void OnInitCmdLine( wxCmdLineParser& parser );
|
||||
bool OnCmdLineParsed( wxCmdLineParser& parser );
|
||||
bool OnCmdLineError( wxCmdLineParser& parser );
|
||||
bool ParseOverrides( wxCmdLineParser& parser );
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
void OnAssertFailure( const wxChar *file, int line, const wxChar *func, const wxChar *cond, const wxChar *msg );
|
||||
#endif
|
||||
|
||||
Threading::MutexRecursive m_mtx_ProgramLog;
|
||||
ConsoleLogFrame* m_ptr_ProgramLog;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Console / Program Logging Helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
ConsoleLogFrame* GetProgramLog();
|
||||
const ConsoleLogFrame* GetProgramLog() const;
|
||||
void ProgramLog_PostEvent( wxEvent& evt );
|
||||
Threading::Mutex& GetProgramLogLock();
|
||||
|
||||
void EnableAllLogging();
|
||||
void DisableWindowLogging() const;
|
||||
void DisableDiskLogging() const;
|
||||
|
@ -577,6 +667,7 @@ protected:
|
|||
void HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& event) const;
|
||||
void HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& event);
|
||||
|
||||
void OnScheduledTermination( wxTimerEvent& evt );
|
||||
void OnEmuKeyDown( wxKeyEvent& evt );
|
||||
void OnSysExecutorTaskTimeout( wxTimerEvent& evt );
|
||||
void OnDestroyWindow( wxWindowDestroyEvent& evt );
|
||||
|
|
|
@ -331,12 +331,16 @@ wxDirName GetLogFolder()
|
|||
|
||||
wxDirName GetSettingsFolder()
|
||||
{
|
||||
if( wxGetApp().Overrides.SettingsFolder.IsOk() )
|
||||
return wxGetApp().Overrides.SettingsFolder;
|
||||
|
||||
return UseDefaultSettingsFolder ? PathDefs::GetSettings() : SettingsFolder;
|
||||
}
|
||||
|
||||
wxString GetSettingsFilename()
|
||||
{
|
||||
return GetSettingsFolder().Combine( FilenameDefs::GetConfig() ).GetFullPath();
|
||||
wxFileName fname( wxGetApp().Overrides.SettingsFile.IsOk() ? wxGetApp().Overrides.SettingsFile : FilenameDefs::GetConfig() );
|
||||
return GetSettingsFolder().Combine( fname ).GetFullPath();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -254,14 +254,6 @@ public:
|
|||
void LoadSaveMemcards( IniInterface& ini );
|
||||
};
|
||||
|
||||
struct ConfigOverrides
|
||||
{
|
||||
AppConfig::FilenameOptions Filenames;
|
||||
wxString SettingsFolder;
|
||||
};
|
||||
|
||||
extern ConfigOverrides OverrideOptions;
|
||||
|
||||
extern wxFileConfig* OpenFileConfig( const wxString& filename );
|
||||
extern void RelocateLogfile();
|
||||
extern void AppConfig_OnChangedSettingsFolder( bool overwrite = false );
|
||||
|
|
|
@ -91,7 +91,7 @@ static void ConvertPluginFilenames( wxString (&passins)[PluginId_Count] )
|
|||
{
|
||||
const PluginInfo* pi = tbl_PluginInfo; do
|
||||
{
|
||||
passins[pi->id] = OverrideOptions.Filenames[pi->id].GetFullPath();
|
||||
passins[pi->id] = wxGetApp().Overrides.Filenames[pi->id].GetFullPath();
|
||||
|
||||
if( passins[pi->id].IsEmpty() || !wxFileExists( passins[pi->id] ) )
|
||||
passins[pi->id] = g_Conf->FullpathTo( pi->id );
|
||||
|
@ -101,6 +101,9 @@ static void ConvertPluginFilenames( wxString (&passins)[PluginId_Count] )
|
|||
typedef void (AppPluginManager::*FnPtr_AppPluginManager)();
|
||||
typedef void (AppPluginManager::*FnPtr_AppPluginPid)( PluginsEnum_t pid );
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// SysExecEvent_AppPluginManager
|
||||
// --------------------------------------------------------------------------------------
|
||||
class SysExecEvent_AppPluginManager : public SysExecEvent
|
||||
{
|
||||
protected:
|
||||
|
@ -122,6 +125,9 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// LoadSinglePluginEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
class LoadSinglePluginEvent : public pxInvokeActionEvent
|
||||
{
|
||||
typedef pxInvokeActionEvent _parent;
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
|
||||
using namespace pxSizerFlags;
|
||||
|
||||
static bool m_ForceWizard = false;
|
||||
static bool m_UseGUI = false;
|
||||
static bool m_NoFastBoot = false;
|
||||
static bool m_DisableSpeedhacks = false;
|
||||
|
||||
static void CpuCheckSSE2()
|
||||
{
|
||||
if( x86caps.hasStreamingSIMD2Extensions ) return;
|
||||
|
@ -110,7 +105,7 @@ void Pcsx2App::ReadUserModeSettings()
|
|||
wxString groupname( wxsFormat( L"CWD.%08x", hashres ) );
|
||||
|
||||
bool hasGroup = conf_usermode->HasGroup( groupname );
|
||||
bool forceWiz = m_ForceWizard || !hasGroup;
|
||||
bool forceWiz = Startup.ForceWizard || !hasGroup;
|
||||
|
||||
if( !forceWiz )
|
||||
{
|
||||
|
@ -208,26 +203,28 @@ void Pcsx2App::OpenMainFrame()
|
|||
MainEmuFrame* mainFrame = new MainEmuFrame( NULL, L"PCSX2" );
|
||||
m_id_MainFrame = mainFrame->GetId();
|
||||
|
||||
if( wxWindow* deleteme = GetProgramLog() )
|
||||
{
|
||||
deleteme->Destroy();
|
||||
g_Conf->ProgLogBox.Visible = true;
|
||||
m_id_ProgramLogBox = wxID_ANY;
|
||||
PostIdleAppMethod( &Pcsx2App::OpenProgramLog );
|
||||
}
|
||||
PostAppMethod( &Pcsx2App::OpenProgramLog );
|
||||
|
||||
SetTopWindow( mainFrame ); // not really needed...
|
||||
SetExitOnFrameDelete( true ); // but being explicit doesn't hurt...
|
||||
SetExitOnFrameDelete( false ); // but being explicit doesn't hurt...
|
||||
mainFrame->Show();
|
||||
}
|
||||
|
||||
void Pcsx2App::OpenProgramLog()
|
||||
{
|
||||
if( GetProgramLog() != NULL ) return;
|
||||
if( ConsoleLogFrame* frame = GetProgramLog() )
|
||||
{
|
||||
//pxAssume( );
|
||||
return;
|
||||
}
|
||||
|
||||
wxWindow* m_current_focus = wxGetActiveWindow();
|
||||
m_id_ProgramLogBox = (new ConsoleLogFrame( GetMainFramePtr(), L"PCSX2 Program Log", g_Conf->ProgLogBox ))->GetId();
|
||||
|
||||
ScopedLock lock( m_mtx_ProgramLog );
|
||||
m_ptr_ProgramLog = new ConsoleLogFrame( GetMainFramePtr(), L"PCSX2 Program Log", g_Conf->ProgLogBox );
|
||||
m_id_ProgramLogBox = m_ptr_ProgramLog->GetId();
|
||||
EnableAllLogging();
|
||||
|
||||
|
||||
if( m_current_focus ) m_current_focus->SetFocus();
|
||||
}
|
||||
|
||||
|
@ -330,21 +327,29 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
|
|||
_("All options are for the current session only and will not be saved.\n")
|
||||
);
|
||||
|
||||
wxString fixlist( L" " );
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
{
|
||||
if( i != GamefixId_FIRST ) fixlist += L",";
|
||||
fixlist += EnumToString(i);
|
||||
}
|
||||
|
||||
parser.AddParam( _("IsoFile"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL );
|
||||
parser.AddSwitch( L"h", L"help", _("displays this list of command line options"), wxCMD_LINE_OPTION_HELP );
|
||||
parser.AddSwitch( wxEmptyString,L"console", _("forces the program log/console to be visible") );
|
||||
|
||||
parser.AddSwitch( L"h", L"help", _("displays this list of command line options"), wxCMD_LINE_OPTION_HELP );
|
||||
parser.AddSwitch( wxEmptyString,L"nogui", _("disables display of the gui while running games") );
|
||||
parser.AddOption( wxEmptyString,L"elf", _("executes an ELF image"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddSwitch( wxEmptyString,L"nodisc", _("boots an empty dvd tray; use to enter the PS2 system menu") );
|
||||
parser.AddSwitch( wxEmptyString,L"usecd", _("boots from the CDVD plugin (overrides IsoFile parameter)") );
|
||||
|
||||
parser.AddSwitch( wxEmptyString,L"nogui", _("disables display of the gui while running games") );
|
||||
parser.AddOption( wxEmptyString,L"elf", _("executes an ELF image"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddSwitch( wxEmptyString,L"nodisc", _("boots an empty dvd tray; use to enter the PS2 system menu") );
|
||||
parser.AddSwitch( wxEmptyString,L"usecd", _("boots from the CDVD plugin (overrides IsoFile parameter)") );
|
||||
parser.AddSwitch( wxEmptyString,L"fullboot", _("disables fast booting") );
|
||||
parser.AddSwitch( wxEmptyString,L"nohacks", _("disables all speedhacks") );
|
||||
parser.AddSwitch( wxEmptyString,L"gamefixes", _("use the specified comma or pipe-delimited list of gamefixes.") + fixlist );
|
||||
|
||||
parser.AddSwitch( wxEmptyString,L"fullboot",_("disables fast booting") );
|
||||
parser.AddSwitch( wxEmptyString,L"nohacks", _("disables all speedhacks") );
|
||||
|
||||
parser.AddOption( wxEmptyString,L"cfgpath", _("changes the configuration file path"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddOption( wxEmptyString,L"cfg", _("specifies the PCSX2 configuration file to use"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddSwitch( wxEmptyString,L"forcewiz",_("forces PCSX2 to start the First-time Wizard") );
|
||||
parser.AddOption( wxEmptyString,L"cfgpath", _("changes the configuration file path"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddOption( wxEmptyString,L"cfg", _("specifies the PCSX2 configuration file to use"), wxCMD_LINE_VAL_STRING );
|
||||
parser.AddSwitch( wxEmptyString,L"forcewiz", _("forces PCSX2 to start the First-time Wizard") );
|
||||
|
||||
const PluginInfo* pi = tbl_PluginInfo; do {
|
||||
parser.AddOption( wxEmptyString, pi->GetShortname().Lower(),
|
||||
|
@ -361,50 +366,85 @@ bool Pcsx2App::OnCmdLineError( wxCmdLineParser& parser )
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
|
||||
bool Pcsx2App::ParseOverrides( wxCmdLineParser& parser )
|
||||
{
|
||||
if( parser.GetParamCount() >= 1 )
|
||||
wxString dest;
|
||||
|
||||
if( parser.Found( L"cfgpath", &dest ) && !dest.IsEmpty() )
|
||||
{
|
||||
// [TODO] : Unnamed parameter is taken as an "autorun" option for a cdvd/iso.
|
||||
parser.GetParam( 0 );
|
||||
Console.Warning( L"Config path override: " + dest );
|
||||
Overrides.SettingsFolder = dest;
|
||||
}
|
||||
|
||||
// Suppress wxWidgets automatic options parsing since none of them pertain to PCSX2 needs.
|
||||
//wxApp::OnCmdLineParsed( parser );
|
||||
|
||||
m_UseGUI = !parser.Found(L"nogui");
|
||||
m_DisableSpeedhacks = parser.Found(L"nohacks");
|
||||
m_NoFastBoot = parser.Found(L"fullboot");
|
||||
m_ForceWizard = parser.Found( L"forcewiz" );
|
||||
|
||||
wxString cfgPathOverride;
|
||||
//if( parser.Found(L"cfgpath", cfgPathOverride ) )
|
||||
if( parser.Found( L"cfg", &dest ) && !dest.IsEmpty() )
|
||||
{
|
||||
Console.Warning( L"Config file override: " + dest );
|
||||
Overrides.SettingsFile = dest;
|
||||
}
|
||||
|
||||
Overrides.DisableSpeedhacks = parser.Found(L"nohacks");
|
||||
|
||||
const PluginInfo* pi = tbl_PluginInfo; do
|
||||
{
|
||||
wxString dest;
|
||||
if( !parser.Found( pi->GetShortname().Lower(), &dest ) ) continue;
|
||||
|
||||
OverrideOptions.Filenames.Plugins[pi->id] = dest;
|
||||
|
||||
if( wxFileExists( dest ) )
|
||||
Console.Warning( pi->GetShortname() + L" override: " + dest );
|
||||
else
|
||||
{
|
||||
bool result = Msgbox::OkCancel(
|
||||
wxsFormat( _("Plugin Override Error! Specified %s plugin does not exist:\n\n"), pi->GetShortname().c_str() ) +
|
||||
dest +
|
||||
_("Press OK to use the default configured plugin, or Cancel to close."),
|
||||
_("Plugin Override Error - PCSX2"), wxICON_ERROR
|
||||
);
|
||||
wxDialogWithHelpers okcan( NULL, _("Plugin Override Error - PCSX2") );
|
||||
|
||||
if( !result ) return false;
|
||||
okcan += okcan.Heading( wxsFormat(
|
||||
_("%s Plugin Override Error! The following file does not exist or is not a valid %s plugin:\n\n"),
|
||||
pi->GetShortname().c_str(), pi->GetShortname().c_str()
|
||||
) );
|
||||
|
||||
okcan += okcan.GetCharHeight();
|
||||
okcan += okcan.Text(dest);
|
||||
okcan += okcan.GetCharHeight();
|
||||
okcan += okcan.Heading(_("Press OK to use the default configured plugin, or Cancel to close PCSX2."));
|
||||
|
||||
if( wxID_CANCEL == pxIssueConfirmation( okcan, MsgButtons().OKCancel() ) ) return false;
|
||||
}
|
||||
} while( ++pi, pi->shortname != NULL );
|
||||
|
||||
Overrides.Filenames.Plugins[pi->id] = dest;
|
||||
|
||||
parser.Found( L"cfgpath", &OverrideOptions.SettingsFolder );
|
||||
} while( ++pi, pi->shortname != NULL );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
|
||||
{
|
||||
if( parser.Found(L"console") )
|
||||
{
|
||||
Startup.ForceConsole = true;
|
||||
OpenProgramLog();
|
||||
}
|
||||
|
||||
// Suppress wxWidgets automatic options parsing since none of them pertain to PCSX2 needs.
|
||||
//wxApp::OnCmdLineParsed( parser );
|
||||
|
||||
m_UseGUI = !parser.Found(L"nogui");
|
||||
|
||||
if( !ParseOverrides(parser) ) return false;
|
||||
|
||||
// --- Parse Startup/Autoboot options ---
|
||||
|
||||
Startup.NoFastBoot = parser.Found(L"fullboot");
|
||||
Startup.ForceWizard = parser.Found(L"forcewiz");
|
||||
|
||||
if( parser.GetParamCount() >= 1 )
|
||||
{
|
||||
Startup.IsoFile = parser.GetParam( 0 );
|
||||
Startup.SysAutoRun = true;
|
||||
}
|
||||
|
||||
if( parser.Found(L"usecd") )
|
||||
{
|
||||
Startup.CdvdSource = CDVDsrc_Plugin;
|
||||
Startup.SysAutoRun = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -458,8 +498,23 @@ bool Pcsx2App::OnInit()
|
|||
SysExecutorThread.Start();
|
||||
DetectCpuAndUserMode();
|
||||
|
||||
PostAppMethod( &Pcsx2App::OpenMainFrame );
|
||||
PostAppMethod( &Pcsx2App::OpenProgramLog );
|
||||
if( Startup.ForceConsole ) g_Conf->ProgLogBox.Visible = true;
|
||||
|
||||
// Set Manual Exit Handling
|
||||
// ----------------------------
|
||||
// PCSX2 has a lot of event handling logistics, so we *cannot* depend on wxWidgets automatic event
|
||||
// loop termination code. We have a much safer system in place that continues to process messages
|
||||
// until all "important" threads are closed out -- not just until the main frame is closed(-ish).
|
||||
m_timer_Termination = new wxTimer( this, wxID_ANY );
|
||||
Connect( m_timer_Termination->GetId(), wxEVT_TIMER, wxTimerEventHandler(Pcsx2App::OnScheduledTermination) );
|
||||
SetExitOnFrameDelete( false );
|
||||
|
||||
|
||||
// Start GUI and/or Direct Emulation
|
||||
// -------------------------------------
|
||||
if( m_UseGUI )
|
||||
PostAppMethod( &Pcsx2App::OpenMainFrame );
|
||||
|
||||
PostAppMethod( &Pcsx2App::AllocateCoreStuffs );
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -491,6 +546,54 @@ bool Pcsx2App::OnInit()
|
|||
return true;
|
||||
}
|
||||
|
||||
static int m_term_threshold = 20;
|
||||
|
||||
void Pcsx2App::OnScheduledTermination( wxTimerEvent& evt )
|
||||
{
|
||||
if( !pxAssertDev( m_ScheduledTermination, "Scheduled Termination check is inconsistent with ScheduledTermination status." ) )
|
||||
{
|
||||
m_timer_Termination->Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_PendingSaves != 0 )
|
||||
{
|
||||
if( --m_term_threshold > 0 )
|
||||
{
|
||||
Console.WriteLn( "(App) %d saves are still pending; exit postponed...", m_PendingSaves );
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Error( "(App) %s pending saves have exceeded OnExit threshold and are being prematurely terminated!", m_PendingSaves );
|
||||
}
|
||||
|
||||
m_timer_Termination->Stop();
|
||||
Exit();
|
||||
}
|
||||
|
||||
|
||||
// Common exit handler which can be called from any event (though really it should
|
||||
// be called only from CloseWindow handlers since that's the more appropriate way
|
||||
// to handle cancelable window closures)
|
||||
//
|
||||
// returns true if the app can close, or false if the close event was canceled by
|
||||
// the glorious user, whomever (s)he-it might be.
|
||||
void Pcsx2App::PrepForExit()
|
||||
{
|
||||
if( m_ScheduledTermination ) return;
|
||||
m_ScheduledTermination = true;
|
||||
|
||||
SysExecutorThread.ShutdownQueue();
|
||||
DispatchEvent( AppStatus_Exiting );
|
||||
|
||||
m_timer_Termination->Start( 500 );
|
||||
|
||||
// This should be called by OnExit(), but sometimes wxWidgets fails to call OnExit(), so
|
||||
// do it here just in case (no harm anyway -- OnExit is the next logical step after
|
||||
// CloseWindow returns true from the TopLevel window).
|
||||
//CleanupRestartable();
|
||||
}
|
||||
|
||||
// This cleanup procedure can only be called when the App message pump is still active.
|
||||
// OnExit() must use CleanupOnExit instead.
|
||||
void Pcsx2App::CleanupRestartable()
|
||||
|
@ -499,13 +602,9 @@ void Pcsx2App::CleanupRestartable()
|
|||
|
||||
ShutdownPlugins();
|
||||
SysExecutorThread.ShutdownQueue();
|
||||
|
||||
//PingDispatcher( "Cleanup" );
|
||||
//DeletionDispatcher();
|
||||
IdleEventDispatcher( L"Cleanup" );
|
||||
|
||||
if( g_Conf )
|
||||
AppSaveSettings();
|
||||
if( g_Conf ) AppSaveSettings();
|
||||
}
|
||||
|
||||
// This cleanup handler can be called from OnExit (it doesn't need a running message pump),
|
||||
|
@ -561,7 +660,6 @@ void Pcsx2App::CleanupResources()
|
|||
int Pcsx2App::OnExit()
|
||||
{
|
||||
CleanupOnExit();
|
||||
|
||||
return wxApp::OnExit();
|
||||
}
|
||||
|
||||
|
@ -610,6 +708,7 @@ Pcsx2App::Pcsx2App()
|
|||
m_id_MainFrame = wxID_ANY;
|
||||
m_id_GsFrame = wxID_ANY;
|
||||
m_id_ProgramLogBox = wxID_ANY;
|
||||
m_ptr_ProgramLog = NULL;
|
||||
|
||||
SetAppName( L"pcsx2" );
|
||||
BuildCommandHash();
|
||||
|
|
|
@ -47,7 +47,6 @@ wxDirName Logs;
|
|||
bool UseDefaultLogs = true;
|
||||
|
||||
ScopedPtr<AppConfig> g_Conf;
|
||||
ConfigOverrides OverrideOptions;
|
||||
|
||||
template<typename DialogType>
|
||||
int AppOpenModalDialog( wxWindow* parent=NULL )
|
||||
|
@ -488,12 +487,18 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
|||
}
|
||||
}
|
||||
|
||||
// A call to this method informs the app that there is a pending save operation that must be
|
||||
// finished prior to exiting the app, or else data loss will occur. Any call to this method
|
||||
// should be matched by a call to ClearPendingSave().
|
||||
void Pcsx2App::StartPendingSave()
|
||||
{
|
||||
if( PostAppMethodMyself(&Pcsx2App::StartPendingSave) ) return;
|
||||
++m_PendingSaves;
|
||||
}
|
||||
|
||||
// If this method is called inappropriately then the entire pending save system will become
|
||||
// unreliable and data loss can occur on app exit. Devel and debug builds will assert if
|
||||
// such calls are detected (though the detection is far from fool-proof).
|
||||
void Pcsx2App::ClearPendingSave()
|
||||
{
|
||||
if( PostAppMethodMyself(&Pcsx2App::ClearPendingSave) ) return;
|
||||
|
@ -508,38 +513,6 @@ void Pcsx2App::ClearPendingSave()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Common exit handler which can be called from any event (though really it should
|
||||
// be called only from CloseWindow handlers since that's the more appropriate way
|
||||
// to handle cancelable window closures)
|
||||
//
|
||||
// returns true if the app can close, or false if the close event was canceled by
|
||||
// the glorious user, whomever (s)he-it might be.
|
||||
void Pcsx2App::PrepForExit()
|
||||
{
|
||||
SysExecutorThread.ShutdownQueue();
|
||||
|
||||
//SysExecutorThread.Cancel();
|
||||
DispatchEvent( AppStatus_Exiting );
|
||||
|
||||
if( m_PendingSaves != 0 )
|
||||
{
|
||||
// When the thread finishes, it will call ClearPendingSave, which in turn will
|
||||
// exit the app once all pending saves have "logged out." (if one does not track
|
||||
// itself using our PendingSaves feature, it would be lost -- too bad!)
|
||||
|
||||
Console.WriteLn( "App: Saves are pending; exit postponed..." );
|
||||
SetExitOnFrameDelete( false );
|
||||
m_ScheduledTermination = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// This should be called by OnExit(), but sometimes wxWidgets fails to call OnExit(), so
|
||||
// do it here just in case (no harm anyway -- OnExit is the next logical step after
|
||||
// CloseWindow returns true from the TopLevel window).
|
||||
CleanupRestartable();
|
||||
}
|
||||
|
||||
// This method generates debug assertions if the MainFrame handle is NULL (typically
|
||||
// indicating that PCSX2 is running in NoGUI mode, or that the main frame has been
|
||||
// closed). In most cases you'll want to use HasMainFrame() to test for thread
|
||||
|
@ -1013,3 +986,17 @@ SysCoreAllocations& GetSysCoreAlloc()
|
|||
{
|
||||
return *wxGetApp().m_CoreAllocs;
|
||||
}
|
||||
|
||||
DataBase_Loader* Pcsx2App::GetGameDatabase()
|
||||
{
|
||||
pxAppResources& res( GetResourceCache() );
|
||||
|
||||
ScopedLock lock( m_mtx_LoadingGameDB );
|
||||
if( !res.GameDB ) res.GameDB = new DataBase_Loader();
|
||||
return res.GameDB;
|
||||
}
|
||||
|
||||
DataBase_Loader* AppHost_GetGameDatabase()
|
||||
{
|
||||
return wxGetApp().GetGameDatabase();
|
||||
}
|
|
@ -89,6 +89,7 @@ RecentIsoManager& Pcsx2App::GetRecentIsoManager()
|
|||
|
||||
pxAppResources& Pcsx2App::GetResourceCache()
|
||||
{
|
||||
ScopedLock lock( m_mtx_Resources );
|
||||
if( !m_Resources )
|
||||
m_Resources = new pxAppResources();
|
||||
|
||||
|
|
|
@ -141,12 +141,15 @@ static bool OpenLogFile(wxFile& file, wxString& filename, wxWindow *parent)
|
|||
return file.Create(filename);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleLogFrame::ColorArray (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// fontsize - size of the font specified in points.
|
||||
// (actual font used is the system-selected fixed-width font)
|
||||
//
|
||||
ConsoleLogFrame::ColorArray::ColorArray( int fontsize ) :
|
||||
m_table( ConsoleColors_Count )
|
||||
ConsoleLogFrame::ColorArray::ColorArray( int fontsize )
|
||||
: m_table( ConsoleColors_Count )
|
||||
{
|
||||
Create( fontsize );
|
||||
}
|
||||
|
@ -225,7 +228,37 @@ enum MenuIDs_t
|
|||
MenuID_FontSize_Huge,
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedLogLock (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
class ScopedLogLock : ScopedLock
|
||||
{
|
||||
public:
|
||||
ConsoleLogFrame* WindowPtr;
|
||||
|
||||
public:
|
||||
ScopedLogLock()
|
||||
: ScopedLock( ((Pcsx2App&)*wxTheApp).GetProgramLogLock() )
|
||||
{
|
||||
WindowPtr = ((Pcsx2App&)*wxTheApp).m_ptr_ProgramLog;
|
||||
}
|
||||
|
||||
virtual ~ScopedLogLock() throw() {}
|
||||
|
||||
bool HasWindow() const
|
||||
{
|
||||
return WindowPtr != NULL;
|
||||
}
|
||||
|
||||
ConsoleLogFrame& GetWindow() const
|
||||
{
|
||||
return *WindowPtr;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleLogFrame (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, AppConfig::ConsoleLogOptions& options )
|
||||
: wxFrame(parent, wxID_ANY, title)
|
||||
, m_conf( options )
|
||||
|
@ -333,6 +366,7 @@ ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, A
|
|||
|
||||
ConsoleLogFrame::~ConsoleLogFrame()
|
||||
{
|
||||
ScopedLogLock locker;
|
||||
wxGetApp().OnProgramLogClosed( GetId() );
|
||||
}
|
||||
|
||||
|
@ -776,6 +810,11 @@ const IConsoleWriter ConsoleWriter_File =
|
|||
ConsoleToFile_SetTitle,
|
||||
};
|
||||
|
||||
Mutex& Pcsx2App::GetProgramLogLock()
|
||||
{
|
||||
return m_mtx_ProgramLog;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleToWindow Implementations
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -798,7 +837,8 @@ template< const IConsoleWriter& secondary >
|
|||
static void __concall ConsoleToWindow_Newline()
|
||||
{
|
||||
secondary.Newline();
|
||||
((Pcsx2App&)*wxTheApp).GetProgramLog()->Newline();
|
||||
ScopedLogLock locker;
|
||||
if( locker.WindowPtr ) locker.WindowPtr->Newline();
|
||||
}
|
||||
|
||||
template< const IConsoleWriter& secondary >
|
||||
|
@ -806,7 +846,9 @@ static void __concall ConsoleToWindow_DoWrite( const wxString& fmt )
|
|||
{
|
||||
if( secondary.DoWrite != NULL )
|
||||
secondary.DoWrite( fmt );
|
||||
((Pcsx2App&)*wxTheApp).GetProgramLog()->Write( Console.GetColor(), fmt );
|
||||
|
||||
ScopedLogLock locker;
|
||||
if( locker.WindowPtr ) locker.WindowPtr->Write( Console.GetColor(), fmt );
|
||||
}
|
||||
|
||||
template< const IConsoleWriter& secondary >
|
||||
|
@ -814,7 +856,9 @@ static void __concall ConsoleToWindow_DoWriteLn( const wxString& fmt )
|
|||
{
|
||||
if( secondary.DoWriteLn != NULL )
|
||||
secondary.DoWriteLn( fmt );
|
||||
((Pcsx2App&)*wxTheApp).GetProgramLog()->Write( Console.GetColor(), fmt + L"\n" );
|
||||
|
||||
ScopedLogLock locker;
|
||||
if( locker.WindowPtr ) locker.WindowPtr->Write( Console.GetColor(), fmt + L'\n' );
|
||||
}
|
||||
|
||||
typedef void __concall DoWriteFn(const wxString&);
|
||||
|
@ -843,7 +887,9 @@ static const IConsoleWriter ConsoleWriter_WindowAndFile =
|
|||
|
||||
void Pcsx2App::EnableAllLogging()
|
||||
{
|
||||
const bool logBoxOpen = (GetProgramLog() != NULL);
|
||||
ScopedLock lock( m_mtx_ProgramLog );
|
||||
|
||||
const bool logBoxOpen = (m_ptr_ProgramLog != NULL);
|
||||
const IConsoleWriter* newHandler = NULL;
|
||||
|
||||
if( emuLog )
|
||||
|
@ -888,6 +934,7 @@ void Pcsx2App::DisableDiskLogging() const
|
|||
|
||||
void Pcsx2App::DisableWindowLogging() const
|
||||
{
|
||||
ScopedLock lock( m_mtx_ProgramLog );
|
||||
Console_SetActiveHandler( (emuLog!=NULL) ? (IConsoleWriter&)ConsoleWriter_File : (IConsoleWriter&)ConsoleWriter_Stdout );
|
||||
Threading::Sleep( 5 );
|
||||
//Threading::Sleep( 5 );
|
||||
}
|
||||
|
|
|
@ -94,13 +94,13 @@ void MainEmuFrame::OnCloseWindow(wxCloseEvent& evt)
|
|||
|
||||
}
|
||||
|
||||
wxGetApp().PrepForExit();
|
||||
sApp.OnMainFrameClosed( GetId() );
|
||||
|
||||
if( m_menubar.FindItem(MenuId_IsoSelector) )
|
||||
m_menuCDVD.Remove(MenuId_IsoSelector);
|
||||
|
||||
RemoveEventHandler( &wxGetApp().GetRecentIsoManager() );
|
||||
wxGetApp().PostIdleAppMethod( &Pcsx2App::PrepForExit );
|
||||
|
||||
evt.Skip();
|
||||
}
|
||||
|
|
|
@ -330,7 +330,7 @@ namespace Panels
|
|||
class GameFixesPanel : public BaseApplicableConfigPanel
|
||||
{
|
||||
protected:
|
||||
pxCheckBox* m_checkbox[NUM_OF_GAME_FIXES];
|
||||
pxCheckBox* m_checkbox[GamefixId_COUNT];
|
||||
pxCheckBox* m_check_Enable;
|
||||
|
||||
public:
|
||||
|
@ -358,7 +358,7 @@ namespace Panels
|
|||
wxTextCtrl* compatBox;
|
||||
wxTextCtrl* commentBox;
|
||||
wxTextCtrl* patchesBox;
|
||||
pxCheckBox* gameFixes[NUM_OF_GAME_FIXES];
|
||||
pxCheckBox* gameFixes[GamefixId_COUNT];
|
||||
|
||||
public:
|
||||
GameDatabasePanel( wxWindow* parent );
|
||||
|
|
|
@ -42,7 +42,10 @@ wxTextCtrl* CreateMultiLineTextCtrl( wxWindow* parent, int digits, long flags =
|
|||
Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
||||
: BaseApplicableConfigPanel( parent )
|
||||
{
|
||||
if (!GameDB) GameDB = new DataBase_Loader();
|
||||
//if (!GameDB) GameDB = new DataBase_Loader();
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
pxAssume( GameDB != NULL );
|
||||
|
||||
searchBtn = new wxButton (this, wxID_DEFAULT, L"Search");
|
||||
|
||||
serialBox = CreateNumericalTextCtrl(this, 40, wxTE_LEFT);
|
||||
|
@ -52,15 +55,8 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
|||
commentBox = CreateMultiLineTextCtrl(this, 40, wxTE_LEFT);
|
||||
patchesBox = CreateMultiLineTextCtrl(this, 40, wxTE_LEFT);
|
||||
|
||||
gameFixes[0] = new pxCheckBox(this, L"VuAddSubHack");
|
||||
gameFixes[1] = new pxCheckBox(this, L"VuClipFlagHack");
|
||||
gameFixes[2] = new pxCheckBox(this, L"FpuCompareHack");
|
||||
gameFixes[3] = new pxCheckBox(this, L"FpuMulHack");
|
||||
gameFixes[4] = new pxCheckBox(this, L"FpuNegDivHack");
|
||||
gameFixes[5] = new pxCheckBox(this, L"XgKickHack");
|
||||
gameFixes[6] = new pxCheckBox(this, L"IPUWaitHack");
|
||||
gameFixes[7] = new pxCheckBox(this, L"EETimingHack");
|
||||
gameFixes[8] = new pxCheckBox(this, L"SkipMPEGHack");
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
gameFixes[i] = new pxCheckBox(this, EnumToString(i));
|
||||
|
||||
*this += Heading(_("Game Database Editor")).Bold() | StdExpand();
|
||||
*this += Heading(_("This panel lets you add and edit game titles, game fixes, and game patches.")) | StdExpand();
|
||||
|
@ -84,14 +80,13 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
|||
blankLine();
|
||||
|
||||
wxStaticBoxSizer& sizer2 = *new wxStaticBoxSizer(wxVERTICAL, this, _("PCSX2 Gamefixes"));
|
||||
wxFlexGridSizer& sizer3(*new wxFlexGridSizer(3));
|
||||
wxFlexGridSizer& sizer3(*new wxFlexGridSizer(3, 0, StdPadding*4));
|
||||
sizer3.AddGrowableCol(0);
|
||||
|
||||
for (int i = 0; i < NUM_OF_GAME_FIXES; i++) {
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
sizer3 += gameFixes[i];
|
||||
}
|
||||
|
||||
sizer2 += sizer3 | pxCenter;
|
||||
sizer2 += sizer3 | StdCenter();
|
||||
|
||||
*this += sizer1 | pxCenter;
|
||||
*this += sizer2 | pxCenter;
|
||||
|
@ -101,6 +96,8 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
|
|||
}
|
||||
|
||||
void Panels::GameDatabasePanel::PopulateFields() {
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
|
||||
if (GameDB->gameLoaded()) {
|
||||
serialBox ->SetLabel(GameDB->getString("Serial"));
|
||||
nameBox ->SetLabel(GameDB->getString("Name"));
|
||||
|
@ -108,15 +105,9 @@ void Panels::GameDatabasePanel::PopulateFields() {
|
|||
compatBox ->SetLabel(GameDB->getString("Compat"));
|
||||
commentBox->SetLabel(GameDB->getString("[comments]"));
|
||||
patchesBox->SetLabel(GameDB->getString("[patches]"));
|
||||
gameFixes[0]->SetValue(GameDB->getBool("VuAddSubHack"));
|
||||
gameFixes[1]->SetValue(GameDB->getBool("VuClipFlagHack"));
|
||||
gameFixes[2]->SetValue(GameDB->getBool("FpuCompareHack"));
|
||||
gameFixes[3]->SetValue(GameDB->getBool("FpuMulHack"));
|
||||
gameFixes[4]->SetValue(GameDB->getBool("FpuNegDivHack"));
|
||||
gameFixes[5]->SetValue(GameDB->getBool("XgKickHack"));
|
||||
gameFixes[6]->SetValue(GameDB->getBool("IPUWaitHack"));
|
||||
gameFixes[7]->SetValue(GameDB->getBool("EETimingHack"));
|
||||
gameFixes[8]->SetValue(GameDB->getBool("SkipMPEGHack"));
|
||||
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
gameFixes[i]->SetValue(GameDB->getBool(EnumToString(i)+wxString(L"Hack")));
|
||||
}
|
||||
else {
|
||||
serialBox ->SetLabel(L"");
|
||||
|
@ -125,7 +116,7 @@ void Panels::GameDatabasePanel::PopulateFields() {
|
|||
compatBox ->SetLabel(L"");
|
||||
commentBox->SetLabel(L"");
|
||||
patchesBox->SetLabel(L"");
|
||||
for (int i = 0; i < NUM_OF_GAME_FIXES; i++) {
|
||||
for (int i = 0; i < GamefixId_COUNT; i++) {
|
||||
gameFixes[i]->SetValue(0);
|
||||
}
|
||||
}
|
||||
|
@ -136,15 +127,11 @@ void Panels::GameDatabasePanel::PopulateFields() {
|
|||
else GameDB->writeString(wxT(_key), _value); \
|
||||
}
|
||||
|
||||
#define writeGameFixToDB(_key, _value) { \
|
||||
if (!_value) GameDB->deleteKey(wxT(_key)); \
|
||||
else GameDB->writeBool(wxT(_key), _value); \
|
||||
}
|
||||
|
||||
// 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() );
|
||||
|
||||
|
||||
if (wxStr.IsEmpty()) return false;
|
||||
if (wxStr != GameDB->getString("Serial")) {
|
||||
GameDB->addGame(wxStr);
|
||||
|
@ -155,19 +142,18 @@ bool Panels::GameDatabasePanel::WriteFieldsToDB() {
|
|||
writeTextBoxToDB("Compat", compatBox->GetValue());
|
||||
writeTextBoxToDB("[comments]", commentBox->GetValue());
|
||||
writeTextBoxToDB("[patches]", patchesBox->GetValue());
|
||||
writeGameFixToDB("VuAddSubHack", gameFixes[0]->GetValue());
|
||||
writeGameFixToDB("VuClipFlagHack", gameFixes[1]->GetValue());
|
||||
writeGameFixToDB("FpuCompareHack", gameFixes[2]->GetValue());
|
||||
writeGameFixToDB("FpuMulHack", gameFixes[3]->GetValue());
|
||||
writeGameFixToDB("FpuNegDivHack", gameFixes[4]->GetValue());
|
||||
writeGameFixToDB("XgKickHack", gameFixes[5]->GetValue());
|
||||
writeGameFixToDB("IPUWaitHack", gameFixes[6]->GetValue());
|
||||
writeGameFixToDB("EETimingHack", gameFixes[7]->GetValue());
|
||||
writeGameFixToDB("SkipMPEGHack", gameFixes[8]->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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) {
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
wxString wxStr = serialBox->GetValue();
|
||||
|
||||
if( wxStr.IsEmpty() ) wxStr = DiscID;
|
||||
|
@ -180,6 +166,7 @@ void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) {
|
|||
}
|
||||
|
||||
void Panels::GameDatabasePanel::Apply() {
|
||||
DataBase_Loader* GameDB = AppHost_GetGameDatabase();
|
||||
if( WriteFieldsToDB() )
|
||||
{
|
||||
Console.WriteLn("Saving changes to Game Database...");
|
||||
|
|
|
@ -31,7 +31,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
|
|||
wxString label, tooltip;
|
||||
};
|
||||
|
||||
const CheckTextMess check_text[NUM_OF_GAME_FIXES] =
|
||||
const CheckTextMess check_text[GamefixId_COUNT] =
|
||||
{
|
||||
{
|
||||
_("VU Add Hack - Fixes Tri-Ace games boot crash."),
|
||||
|
@ -71,12 +71,12 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
|
|||
)
|
||||
},
|
||||
{
|
||||
_("Skip MPEG hack - Skips videos/FMV's in games to avoid game hanging/freezes."),
|
||||
_("Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes."),
|
||||
wxEmptyString
|
||||
}
|
||||
};
|
||||
|
||||
for( int i=0; i<NUM_OF_GAME_FIXES; ++i )
|
||||
for( int i=0; i<GamefixId_COUNT; ++i )
|
||||
{
|
||||
groupSizer += (m_checkbox[i] = new pxCheckBox( this, check_text[i].label ));
|
||||
m_checkbox[i]->SetToolTip( check_text[i].tooltip );
|
||||
|
@ -102,31 +102,19 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
|
|||
EnableStuff();
|
||||
}
|
||||
|
||||
// I could still probably get rid of the for loop, but I think this is clearer.
|
||||
void Panels::GameFixesPanel::Apply()
|
||||
{
|
||||
g_Conf->EnableGameFixes = m_check_Enable->GetValue();
|
||||
|
||||
Pcsx2Config::GamefixOptions& opts( g_Conf->EmuOptions.Gamefixes );
|
||||
for (int i = 0; i < NUM_OF_GAME_FIXES; i++)
|
||||
{
|
||||
if (m_checkbox[i]->GetValue())
|
||||
{
|
||||
opts.bitset |= (1 << i);
|
||||
}
|
||||
else
|
||||
{
|
||||
opts.bitset &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
opts.Set((GamefixId)i, m_checkbox[i]->GetValue());
|
||||
}
|
||||
|
||||
void Panels::GameFixesPanel::EnableStuff()
|
||||
{
|
||||
for (int i = 0; i < NUM_OF_GAME_FIXES; i++)
|
||||
{
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
m_checkbox[i]->Enable(m_check_Enable->GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
void Panels::GameFixesPanel::OnEnable_Toggled( wxCommandEvent& evt )
|
||||
|
@ -138,8 +126,6 @@ void Panels::GameFixesPanel::OnEnable_Toggled( wxCommandEvent& evt )
|
|||
void Panels::GameFixesPanel::AppStatusEvent_OnSettingsApplied()
|
||||
{
|
||||
const Pcsx2Config::GamefixOptions& opts( g_Conf->EmuOptions.Gamefixes );
|
||||
for( int i=0; i<NUM_OF_GAME_FIXES; ++i )
|
||||
{
|
||||
m_checkbox[i]->SetValue( !!(opts.bitset & (1 << i)) );
|
||||
}
|
||||
for (GamefixId i=GamefixId_FIRST; i < pxEnumEnd; ++i)
|
||||
m_checkbox[i]->SetValue( opts.Get((GamefixId)i) );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue