wxGui branch: Did some heavy work on the configuration/ini stuff.

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@905 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-04-04 08:26:52 +00:00
parent 9c3bf215bf
commit cffa379f9c
6 changed files with 421 additions and 100 deletions

View File

@ -131,8 +131,6 @@ public:
bool closeGSonEsc; // closes the GS (and saves its state) on escape automatically.
int PsxType;
int Cdda;
int Mdec;
int Patch;
int CustomFps;
int Hacks;

View File

@ -25,30 +25,188 @@
class MainEmuFrame;
//////////////////////////////////////////////////////////////////////////////////////////
//
struct ConsoleLogOptions
class IniInterface // abstract base class!
{
bool Show;
// if true, DisplayPos is ignored and the console is automatically docked to the main window.
bool AutoDock;
// Display position used if AutoDock is false (ignored otherwise)
wxPoint DisplayPos;
wxSize DisplaySize;
protected:
wxConfigBase& m_Config;
public:
virtual ~IniInterface();
explicit IniInterface();
explicit IniInterface( wxConfigBase& config );
void SetPath( const wxString& path );
void Flush();
virtual void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() )=0;
virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=0;
virtual void Entry( const wxString& var, uint& value, const uint defvalue=0 )=0;
virtual void Entry( const wxString& var, bool& value, const bool defvalue=0 )=0;
virtual void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition )=0;
virtual void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize )=0;
virtual void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect )=0;
virtual void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 )=0;
};
class IniLoader : public IniInterface
{
public:
virtual ~IniLoader();
explicit IniLoader();
explicit IniLoader( wxConfigBase& config );
void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
void Entry( const wxString& var, bool& value, const bool defvalue=false );
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 );
};
class IniSaver : public IniInterface
{
public:
virtual ~IniSaver();
explicit IniSaver();
explicit IniSaver( wxConfigBase& config );
void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
void Entry( const wxString& var, bool& value, const bool defvalue=false );
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 );
};
//////////////////////////////////////////////////////////////////////////////////////////
//
class AppConfig : public wxFileConfig
class AppConfig
{
public:
ConsoleLogOptions ConLogBox;
struct ConsoleLogOptions
{
bool Visible;
// if true, DisplayPos is ignored and the console is automatically docked to the main window.
bool AutoDock;
// Display position used if AutoDock is false (ignored otherwise)
wxPoint DisplayPosition;
wxSize DisplaySize;
void LoadSave( IniInterface& conf );
};
struct FolderOptions
{
wxString Plugins;
wxString Bios;
wxString Snapshots;
wxString Savestates;
wxString MemoryCards;
};
// Options struct for each memory card.
struct McdOptions
{
wxString Filename; // user-configured location of this memory card
bool Enabled; // memory card enabled (if false, memcard will not show up in-game)
};
struct McdSysOptions
{
McdOptions Mcd[2];
bool EnableNTFS; // enables automatic ntfs compression of memory cards (Win32 only)
bool EnableEjection; // enables simulated ejection of memory cards when loading savestates
void LoadSave( IniInterface& conf );
};
struct CpuRecompilerOptions
{
struct
{
bool
Enabled:1, // universal toggle for the profiler.
RecBlocks_EE:1, // Enables per-block profiling for the EE recompiler [unimplemented]
RecBlocks_IOP:1, // Enables per-block profiling for the IOP recompiler [unimplemented]
RecBlocks_VU1:1; // Enables per-block profiling for the VU1 recompiler [unimplemented]
} Profiler;
struct
{
bool
EnableEE:1,
EnableIOP:1,
EnableVU0:1,
EnableVU1:1;
} Recompiler;
void LoadSave( IniInterface& conf );
};
struct VideoOptions
{
bool MultithreadGS; // Uses the multithreaded GS interface.
bool closeOnEsc; // Closes the GS/Video port on escape (good for fullscreen activity)
bool UseFramelimiter;
int RegionMode; // 0=NTSC and 1=PAL
int CustomFps;
int CustomFrameSkip;
int CustomConsecutiveFrames;
int CustomConsecutiveSkip;
void LoadSave( IniInterface& conf );
};
struct GamefixOptions
{
bool
VuAddSubHack:1, // Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
VuClipFlagHack:1, // Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
FpuCompareHack:1, // Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
FpuMulHack:1; // Fix for Tales of Destiny hangs.
void LoadSave();
};
struct SpeedhackOptions
{
int
EECycleRate:3, // EE cyclerate selector (1.0, 1.5, 2.0, 3.0)
IopCycleRate_X2:1, // enables the x2 multiplier of the IOP cyclerate
ExtWaitcycles:1, // enables extended waitcycles duration
IntcStat:1; // tells Pcsx2 to fast-forward through intc_stat waits.
void LoadSave( IniInterface& conf );
};
public:
wxPoint MainGuiPosition;
bool CdvdVerboseReads; // enables cdvd read activity verbosely dumped to the console
CpuRecompilerOptions Cpu;
SpeedhackOptions Speedhacks;
GamefixOptions Gamefixes;
VideoOptions Video;
ConsoleLogOptions ConLogBox;
FolderOptions Folders;
public:
AppConfig( const wxString& filename );
void LoadSettings();
void SaveSettings();
void LoadSave( IniInterface& ini );
};
//////////////////////////////////////////////////////////////////////////////////////////
@ -101,7 +259,6 @@ class Pcsx2App : public wxApp
protected:
MainEmuFrame* m_MainFrame;
ConsoleLogFrame* m_ConsoleFrame;
AppConfig* m_GlobalConfig;
wxBitmap* m_Bitmap_Logo;
public:
@ -120,10 +277,9 @@ public:
ConsoleLogFrame* GetConsoleFrame() const { return m_ConsoleFrame; }
void SetConsoleFrame( ConsoleLogFrame& frame ) { m_ConsoleFrame = &frame; }
AppConfig& GetActiveConfig() const;
bool TryOpenConfigCwd();
};
DECLARE_APP(Pcsx2App)
static AppConfig& Conf() { return wxGetApp().GetActiveConfig(); }
extern AppConfig g_Conf;

View File

@ -19,36 +19,176 @@
#include "PrecompiledHeader.h"
#include "App.h"
static const wxSize DefaultConsoleSize( 540, 540 );
AppConfig::AppConfig( const wxString& filename ) :
wxFileConfig( wxEmptyString, wxEmptyString, filename, wxEmptyString, wxCONFIG_USE_RELATIVE_PATH )
IniInterface::IniInterface( wxConfigBase& config ) :
m_Config( config )
{
SetRecordDefaults();
// Allow wx to use our config, and enforces auto-cleanup as well
wxConfigBase::Set( this );
}
void AppConfig::LoadSettings()
IniInterface::IniInterface() :
m_Config( *wxConfigBase::Get() )
{
wxString spos( Read( wxT("ConLogDisplayPosition"), "docked" ) );
if( spos == "docked" )
ConLogBox.AutoDock = true;
else
ConLogBox.AutoDock = !TryParse( ConLogBox.DisplayPos, spos );
TryParse( ConLogBox.DisplaySize, Read( wxT("ConLogDisplaySize"), ToString( DefaultConsoleSize ) ), DefaultConsoleSize );
Read( wxT( "ConLogVisible" ), &ConLogBox.Show, IsDevBuild );
TryParse( MainGuiPosition, Read( wxT("MainWindowPosition"), ToString( wxDefaultPosition ) ), wxDefaultPosition );
}
IniInterface::~IniInterface()
{
Flush();
}
void AppConfig::SaveSettings()
void IniInterface::SetPath( const wxString& path )
{
m_Config.SetPath( path );
}
void IniInterface::Flush()
{
m_Config.Flush();
}
//////////////////////////////////////////////////////////////////////////////////////////
//
IniLoader::IniLoader( wxConfigBase& config ) : IniInterface( config )
{
}
IniLoader::IniLoader() : IniInterface() {}
IniLoader::~IniLoader() {}
void IniLoader::Entry( const wxString& var, wxString& value, const wxString& defvalue )
{
m_Config.Read( var, &value, defvalue );
}
void IniLoader::Entry( const wxString& var, int& value, const int defvalue )
{
m_Config.Read( var, &value, defvalue );
}
void IniLoader::Entry( const wxString& var, uint& value, const uint defvalue )
{
m_Config.Read( var, (int*)&value, (int)defvalue );
}
void IniLoader::Entry( const wxString& var, bool& value, const bool defvalue )
{
wxString dest;
m_Config.Read( var, &dest, defvalue ? "enabled" : "disabled" );
value = (dest == "enabled") || (dest == "1");
}
void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::Entry( const wxString& var, wxSize& value, const wxSize& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::Entry( const wxString& var, wxRect& value, const wxRect& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue )
{
wxString retval;
m_Config.Read( var, &retval, enumArray[defvalue] );
int i=0;
while( enumArray[i] != NULL && ( retval != enumArray[i] ) ) i++;
if( enumArray[i] == NULL )
{
Console::Notice( "Loadini Warning > Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.",
params retval.c_str(), var.c_str(), enumArray[defvalue] );
value = defvalue;
}
else
value = i;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
IniSaver::IniSaver( wxConfigBase& config ) : IniInterface( config )
{
}
IniSaver::IniSaver() : IniInterface() {}
IniSaver::~IniSaver() {}
void IniSaver::Entry( const wxString& var, wxString& value, const wxString& defvalue )
{
m_Config.Write( var, value );
}
void IniSaver::Entry( const wxString& var, int& value, const int defvalue )
{
m_Config.Write( var, value );
}
void IniSaver::Entry( const wxString& var, uint& value, const uint defvalue )
{
m_Config.Write( var, (int)value );
}
void IniSaver::Entry( const wxString& var, bool& value, const bool defvalue )
{
m_Config.Write( var, value ? "enabled" : "disabled" );
}
void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::Entry( const wxString& var, wxSize& value, const wxSize& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::Entry( const wxString& var, wxRect& value, const wxRect& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue )
{
m_Config.Write( var, enumArray[value] );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
#define IniEntry( varname, defval ) ini.Entry( wxT( #varname ), varname, defval )
void AppConfig::LoadSave( IniInterface& ini )
{
IniEntry( MainGuiPosition, wxDefaultPosition );
IniEntry( CdvdVerboseReads, false );
// Process various sub-components:
ConLogBox.LoadSave( ini );
Speedhacks.LoadSave( ini );
ini.Flush();
}
void AppConfig::ConsoleLogOptions::LoadSave( IniInterface& ini )
{
ini.SetPath( wxT("ConsoleLog") );
IniEntry( Visible, false );
IniEntry( AutoDock, true );
IniEntry( DisplayPosition, wxDefaultPosition );
IniEntry( DisplaySize, wxSize( 540, 540 ) );
ini.SetPath( wxT("..") );
}
void AppConfig::SpeedhackOptions::LoadSave( IniInterface& ini )
{
Write( wxT("ConLogDisplayPosition"), ConLogBox.AutoDock ? "docked" : ToString( ConLogBox.DisplayPos ) );
Write( wxT("ConLogDisplaySize"), ToString( ConLogBox.DisplaySize ) );
}

View File

@ -125,7 +125,7 @@ void ConsoleLogFrame::OnMoveAround( wxMoveEvent& evt )
void ConsoleLogFrame::OnResize( wxSizeEvent& evt )
{
Conf().ConLogBox.DisplaySize = GetSize();
g_Conf.ConLogBox.DisplaySize = GetSize();
evt.Skip();
}

View File

@ -94,8 +94,8 @@ void MainEmuFrame::PopulatePadMenu()
void MainEmuFrame::OnMoveAround( wxMoveEvent& evt )
{
if( Conf().ConLogBox.AutoDock )
m_logbox.SetPosition( Conf().ConLogBox.DisplayPos = GetPosition() + wxSize( GetSize().x, 0 ) );
if( g_Conf.ConLogBox.AutoDock )
m_logbox.SetPosition( g_Conf.ConLogBox.DisplayPosition = GetPosition() + wxSize( GetSize().x, 0 ) );
//evt.Skip();
}
@ -133,7 +133,7 @@ void MainEmuFrame::ConnectMenus()
void MainEmuFrame::OnLogBoxHidden()
{
Conf().ConLogBox.Show = false;
g_Conf.ConLogBox.Visible = false;
m_MenuItem_Console.Check( false );
}
@ -205,32 +205,32 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, int id, const wxString& title, cons
wxRect screenzone( wxPoint(), wxGetDisplaySize() );
// Use default window position if the configured windowpos is invalid (partially offscreen)
if( Conf().MainGuiPosition == wxDefaultPosition || !screenzone.Contains( wxRect( Conf().MainGuiPosition, GetSize() ) ) )
Conf().MainGuiPosition = GetPosition();
if( g_Conf.MainGuiPosition == wxDefaultPosition || !screenzone.Contains( wxRect( g_Conf.MainGuiPosition, GetSize() ) ) )
g_Conf.MainGuiPosition = GetPosition();
else
SetPosition( Conf().MainGuiPosition );
SetPosition( g_Conf.MainGuiPosition );
// ------------------------------------------------------------------------
// Sort out the console log window position (must be done after fitting the window
// sizer, to ensure correct 'docked mode' positioning).
Conf().ConLogBox.DisplaySize.Set(
std::min( std::max( Conf().ConLogBox.DisplaySize.GetWidth(), 160 ), screenzone.GetWidth() ),
std::min( std::max( Conf().ConLogBox.DisplaySize.GetHeight(), 160 ), screenzone.GetHeight() )
g_Conf.ConLogBox.DisplaySize.Set(
std::min( std::max( g_Conf.ConLogBox.DisplaySize.GetWidth(), 160 ), screenzone.GetWidth() ),
std::min( std::max( g_Conf.ConLogBox.DisplaySize.GetHeight(), 160 ), screenzone.GetHeight() )
);
if( Conf().ConLogBox.AutoDock )
if( g_Conf.ConLogBox.AutoDock )
{
Conf().ConLogBox.DisplayPos = GetPosition() + wxSize( GetSize().x, 0 );
g_Conf.ConLogBox.DisplayPosition = GetPosition() + wxSize( GetSize().x, 0 );
}
else if( Conf().ConLogBox.DisplayPos != wxDefaultPosition )
else if( g_Conf.ConLogBox.DisplayPosition != wxDefaultPosition )
{
if( !screenzone.Contains( wxRect( Conf().ConLogBox.DisplayPos, wxSize( 75, 150 ) ) ) )
Conf().ConLogBox.DisplayPos = wxDefaultPosition;
if( !screenzone.Contains( wxRect( g_Conf.ConLogBox.DisplayPosition, wxSize( 75, 150 ) ) ) )
g_Conf.ConLogBox.DisplayPosition = wxDefaultPosition;
}
m_logbox.SetSize( wxRect( Conf().ConLogBox.DisplayPos, Conf().ConLogBox.DisplaySize ) );
m_logbox.Show( Conf().ConLogBox.Show );
m_logbox.SetSize( wxRect( g_Conf.ConLogBox.DisplayPosition, g_Conf.ConLogBox.DisplaySize ) );
m_logbox.Show( g_Conf.ConLogBox.Visible );
// ------------------------------------------------------------------------
@ -296,7 +296,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, int id, const wxString& title, cons
ConnectMenus();
m_MenuItem_Console.Check( Conf().ConLogBox.Show );
m_MenuItem_Console.Check( g_Conf.ConLogBox.Visible );
}
void MainEmuFrame::Menu_QuickBootCD_Click(wxCommandEvent &event)
@ -361,7 +361,7 @@ void MainEmuFrame::Menu_Debug_Logging_Click(wxCommandEvent &event)
void MainEmuFrame::Menu_ShowConsole(wxCommandEvent &event)
{
m_logbox.Show( event.IsChecked() );
m_logbox.Show( g_Conf.ConLogBox.Visible = event.IsChecked() );
}
void MainEmuFrame::Menu_ShowAboutBox(wxCommandEvent &event)

View File

@ -26,44 +26,35 @@
IMPLEMENT_APP(Pcsx2App)
AppConfig g_Conf;
const wxRect wxDefaultRect( wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord );
//////////////////////////////////////////////////////////////////////////////////////////
// PathDefs Namespace -- contains default values for various pcsx2 path names and locations.
//
// Note: The members of this namespace are intended for default value initialization only.
// Most of the time you should use the path folder assignments in Conf() instead, since those
// are user-configurable.
//
namespace PathDefs
{
const wxString Screenshots( "snaps" );
const wxString Snapshots( "snaps" );
const wxString Savestates( "sstates" );
const wxString MemoryCards( "memcards" );
const wxString Configs( "inis" );
const wxString Plugins( "plugins" );
wxString Working;
void Initialize()
{
char temp[g_MaxPath];
_getcwd( temp, g_MaxPath );
Working = temp;
}
// Fetches the path location for user-consumable documents -- stuff users are likely to want to
// share with other programs: screenshots, memory cards, and savestates.
// [TODO] : Ideally this should be optional, configurable, or conditional such that the Pcsx2
// executable working directory can be used. I'm not entirely sure yet the best way to go
// about implementating that toggle, though.
wxString GetDocuments()
{
#ifdef _WIN32
return Path::Combine( wxStandardPaths::Get().GetDocumentsDir(), wxGetApp().GetAppName() );
#else
return wxGetHomeDir();
#endif
return "";
return Path::Combine( wxStandardPaths::Get().GetDocumentsDir(), wxGetApp().GetAppName() );
}
wxString GetScreenshots()
wxString GetSnapshots()
{
return Path::Combine( GetDocuments(), Screenshots );
return Path::Combine( GetDocuments(), Snapshots );
}
wxString GetBios()
@ -90,28 +81,70 @@ namespace PathDefs
{
return Plugins;
}
wxString GetWorking()
{
return wxGetCwd();
}
};
namespace FilenameDefs
{
wxString GetConfig()
{
// TODO : ini extension on Win32 is normal. Linux ini filename default might differ
// from this? like pcsx2_conf or something ... ?
return wxGetApp().GetAppName() + ".ini";
}
};
Pcsx2App::Pcsx2App() :
m_ConsoleFrame( NULL ),
m_GlobalConfig( NULL )
m_ConsoleFrame( NULL )
{
SetAppName( "Pcsx2" );
}
wxFileConfig* OpenConfig( const wxString& filename )
{
return new wxFileConfig( wxEmptyString, wxEmptyString, filename, wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );
}
// returns true if a configuration file is present in the current working dir (cwd).
// returns false if not (in which case the calling code should fall back on using OpenConfigUserLocal())
bool Pcsx2App::TryOpenConfigCwd()
{
wxString inipath_cwd( Path::Combine( wxGetCwd(), PathDefs::Configs ) );
if( !Path::isDirectory( inipath_cwd ) ) return false;
wxString inifile_cwd( Path::Combine( inipath_cwd, FilenameDefs::GetConfig() ) );
if( !Path::isFile( inifile_cwd ) ) return false;
if( Path::getFileSize( inifile_cwd ) <= 1 ) return false;
wxConfigBase::Set( OpenConfig( inifile_cwd ) );
return true;
}
bool Pcsx2App::OnInit()
{
wxInitAllImageHandlers();
// wxWidgets fails badly on Windows, when it comes to picking "default" locations for ini files.
// So for now I have to specify the ini file location manually.
// Ini Startup: The ini file could be in one of two locations, depending on how Pcsx2 has
// been installed or configured. The first place we look is in our program's working
// directory. If the ini there exist, and is *not* empty, then we'll use it. Otherwise
// we fall back on the ini file in the user's Documents folder.
if( !TryOpenConfigCwd() )
{
Path::CreateDirectory( PathDefs::GetDocuments() );
Path::CreateDirectory( PathDefs::GetConfigs() );
Path::CreateDirectory( PathDefs::GetDocuments() );
Path::CreateDirectory( PathDefs::GetConfigs() );
// Allow wx to use our config, and enforces auto-cleanup as well
wxConfigBase::Set( OpenConfig( Path::Combine( PathDefs::GetConfigs(), FilenameDefs::GetConfig() ) ) );
wxConfigBase::Get()->SetRecordDefaults();
}
// FIXME: I think that linux might adhere to a different extension standard than .ini -- I forget which tho.
m_GlobalConfig = new AppConfig( Path::Combine( PathDefs::GetConfigs(), GetAppName() ) + ".ini" );
m_GlobalConfig->LoadSettings();
g_Conf.LoadSave( IniLoader() );
m_Bitmap_Logo = new wxBitmap( EmbeddedImage<png_BackgroundLogo>().GetImage() );
@ -124,7 +157,7 @@ bool Pcsx2App::OnInit()
int Pcsx2App::OnExit()
{
m_GlobalConfig->SaveSettings();
g_Conf.LoadSave( IniSaver() );
return wxApp::OnExit();
}
@ -133,9 +166,3 @@ const wxBitmap& Pcsx2App::GetLogoBitmap() const
wxASSERT( m_Bitmap_Logo != NULL );
return *m_Bitmap_Logo;
}
AppConfig& Pcsx2App::GetActiveConfig() const
{
wxASSERT( m_GlobalConfig != NULL );
return *m_GlobalConfig;
}