diff --git a/common/src/Utilities/Exceptions.cpp b/common/src/Utilities/Exceptions.cpp index 6648fdd29c..4b51482203 100644 --- a/common/src/Utilities/Exceptions.cpp +++ b/common/src/Utilities/Exceptions.cpp @@ -40,14 +40,14 @@ namespace Exception m_message( msg_xlt ), m_stacktrace( wxEmptyString ) // unsupported yet { - // Major hack. After a couple of tries, I'm still not managing to get Linux to catch these exceptions, so that the user actually - // gets the messages. Since Console is unavailable at this level, I'm using a simple printf, which of course, means it doesn't get - // logged. But at least the user sees it. - // - // I'll rip this out once I get Linux to actually catch these exceptions. Say, in BeginExecution or StartGui, like I would expect. - // -- arcum42 + // Linux/GCC exception handling is still suspect (this is likely to do with GCC more + // than linux), and fails to propagate exceptions up the stack from EErec code. This + // could likely be because of the EErec using EBP. So to ensure the user at least + // gets a log of the error, we output to console here in the constructor. + #ifdef __LINUX__ - wxLogError( msg_eng.c_str() ); + //wxLogError( msg_eng.c_str() ); + Console::Error( msg_eng ); #endif } @@ -58,7 +58,10 @@ namespace Exception m_message( GetTranslation( msg_eng ) ), m_stacktrace( wxEmptyString ) // unsupported yet { - wxLogError( m_message_eng.c_str() ); +#ifdef __LINUX__ + //wxLogError( m_message_eng.c_str() ); + Console::Error( msg_eng ); +#endif } wxString BaseException::LogMessage() const diff --git a/pcsx2/Config.h b/pcsx2/Config.h index a6ff5f8326..57a7e1552b 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -58,17 +58,33 @@ public: // ------------------------------------------------------------------------ struct FolderOptions { - wxDirName Plugins; - wxDirName Settings; - wxDirName Bios; - wxDirName Snapshots; - wxDirName Savestates; - wxDirName MemoryCards; - wxDirName Logs; - + wxDirName + Plugins, + Settings, + Bios, + Snapshots, + Savestates, + MemoryCards, + Logs; + wxDirName RunIso; // last used location for Iso loading. + bool + UseDefaultPlugins:1, + UseDefaultSettings:1, + UseDefaultBios:1, + UseDefaultSnapshots:1, + UseDefaultSavestates:1, + UseDefaultMemoryCards:1, + UseDefaultLogs:1; + void LoadSave( IniInterface& conf ); + void ApplyDefaults(); + + void Set( FoldersEnum_t folderidx, const wxString& src, bool useDefault ); + + const wxDirName& operator[]( FoldersEnum_t folderidx ) const; + const bool IsDefault( FoldersEnum_t folderidx ) const; }; // ------------------------------------------------------------------------ @@ -167,19 +183,7 @@ public: void LoadSave( IniInterface& conf ); }; - public: - AppConfig() : - Listbook_ImageSize( 32 ) - , Toolbar_ImageSize( 24 ) - { - } - - wxString FullpathToBios() const; - wxString FullpathToMcd( uint mcdidx ) const; - wxString FullpathTo( PluginsEnum_t pluginId ) const; - - bool UseAdminMode; // dictates if the program uses /home/user or /cwd for the program data wxPoint MainGuiPosition; bool CdvdVerboseReads; // enables cdvd read activity verbosely dumped to the console @@ -213,7 +217,23 @@ public: FilenameOptions BaseFilenames; McdSysOptions MemoryCards; +protected: + // indicates if the main AppConfig settings are valid (excludes the status of UseAdminMode, + // which is a special value that's initialized independently of the rest of the config) + bool m_IsLoaded; + public: + AppConfig() : + Listbook_ImageSize( 32 ) + , Toolbar_ImageSize( 24 ) + , m_IsLoaded( false ) + { + } + + wxString FullpathToBios() const; + wxString FullpathToMcd( uint mcdidx ) const; + wxString FullpathTo( PluginsEnum_t pluginId ) const; + void Load(); void Save(); void Apply(); diff --git a/pcsx2/Paths.h b/pcsx2/Paths.h index d642927bfc..f1f0a7d388 100644 --- a/pcsx2/Paths.h +++ b/pcsx2/Paths.h @@ -134,6 +134,18 @@ namespace Path extern void RemoveDirectory( const wxString& src ); } +enum FoldersEnum_t +{ + FolderId_Plugins = 0, + FolderId_Settings, + FolderId_Bios, + FolderId_Snapshots, + FolderId_Savestates, + FolderId_MemoryCards, + FolderId_Logs, + FolderId_COUNT +}; + ////////////////////////////////////////////////////////////////////////////////////////// // PathDefs Namespace -- contains default values for various pcsx2 path names and locations. // @@ -157,6 +169,8 @@ namespace PathDefs extern wxDirName GetLogs(); extern wxDirName GetThemes(); + extern wxDirName Get( FoldersEnum_t folderidx ); + // Base folder names used to extend out the documents/approot folder base into a complete // path. These are typically for internal AppConfig use only, barring a few special cases. namespace Base diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 5c258dd70e..13f941d098 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -66,7 +66,7 @@ protected: public: // ctor & dtor - ConsoleLogFrame(MainEmuFrame *pParent, const wxString& szTitle); + ConsoleLogFrame( MainEmuFrame *pParent, const wxString& szTitle, const AppConfig::ConsoleLogOptions& options ); virtual ~ConsoleLogFrame(); virtual void Write( const wxString& text ); diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp index c24ab660c9..59c99e44d8 100644 --- a/pcsx2/gui/AppConfig.cpp +++ b/pcsx2/gui/AppConfig.cpp @@ -80,7 +80,6 @@ namespace PathDefs static const wxDirName retval( L"themes" ); return retval; } - }; // Specifies the root folder for the application install. @@ -141,8 +140,103 @@ namespace PathDefs { return GetDocuments() + Base::Logs(); } + + wxDirName Get( FoldersEnum_t folderidx ) + { + switch( folderidx ) + { + case FolderId_Plugins: return GetPlugins(); + case FolderId_Settings: return GetSettings(); + case FolderId_Bios: return GetBios(); + case FolderId_Snapshots: return GetSnapshots(); + case FolderId_Savestates: return GetSavestates(); + case FolderId_MemoryCards: return GetMemoryCards(); + case FolderId_Logs: return GetLogs(); + + jNO_DEFAULT + } + return wxDirName(); + } }; + +const wxDirName& AppConfig::FolderOptions::operator[]( FoldersEnum_t folderidx ) const +{ + switch( folderidx ) + { + case FolderId_Plugins: return Plugins; + case FolderId_Settings: return Settings; + case FolderId_Bios: return Bios; + case FolderId_Snapshots: return Snapshots; + case FolderId_Savestates: return Savestates; + case FolderId_MemoryCards: return MemoryCards; + case FolderId_Logs: return Logs; + + jNO_DEFAULT + } + return Plugins; // unreachable, but supresses warnings. +} + +const bool AppConfig::FolderOptions::IsDefault( FoldersEnum_t folderidx ) const +{ + switch( folderidx ) + { + case FolderId_Plugins: return UseDefaultPlugins; + case FolderId_Settings: return UseDefaultSettings; + case FolderId_Bios: return UseDefaultBios; + case FolderId_Snapshots: return UseDefaultSnapshots; + case FolderId_Savestates: return UseDefaultSavestates; + case FolderId_MemoryCards: return UseDefaultMemoryCards; + case FolderId_Logs: return UseDefaultLogs; + + jNO_DEFAULT + } + return false; +} + +void AppConfig::FolderOptions::Set( FoldersEnum_t folderidx, const wxString& src, bool useDefault ) +{ + switch( folderidx ) + { + case FolderId_Plugins: + Plugins = src; + UseDefaultPlugins = useDefault; + break; + + case FolderId_Settings: + Settings = src; + UseDefaultSettings = useDefault; + break; + + case FolderId_Bios: + Bios = src; + UseDefaultBios = useDefault; + break; + + case FolderId_Snapshots: + Snapshots = src; + UseDefaultSnapshots = useDefault; + break; + + case FolderId_Savestates: + Savestates = src; + UseDefaultSavestates = useDefault; + break; + + case FolderId_MemoryCards: + MemoryCards = src; + UseDefaultMemoryCards = useDefault; + break; + + case FolderId_Logs: + Logs = src; + UseDefaultLogs = useDefault; + break; + + jNO_DEFAULT + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // namespace FilenameDefs @@ -256,6 +350,7 @@ wxString AppConfig::FullpathToMcd( uint mcdidx ) const { return Path::Combine( F // syntax errors. >_< // #define IniEntry( varname, defval ) ini.Entry( wxT(#varname), varname, defval ) +#define IniEntryBitfield( varname, defval ) varname = ini.EntryBitfield( wxT(#varname), defval ) // ------------------------------------------------------------------------ void AppConfig::LoadSaveUserMode( IniInterface& ini ) @@ -297,6 +392,8 @@ void AppConfig::LoadSave( IniInterface& ini ) // void AppConfig::Apply() { + if( !m_IsLoaded ) return; + // Ensure existence of necessary documents folders. Plugins and other parts // of PCSX2 rely on them. @@ -336,6 +433,8 @@ void AppConfig::Apply() // ------------------------------------------------------------------------ void AppConfig::Load() { + m_IsLoaded = true; + // Note: Extra parenthesis resolves "I think this is a function" issues with C++. IniLoader loader( (IniLoader()) ); LoadSave( loader ); @@ -343,6 +442,8 @@ void AppConfig::Load() void AppConfig::Save() { + if( !m_IsLoaded ) return; + IniSaver saver( (IniSaver()) ); LoadSave( saver ); } @@ -368,11 +469,25 @@ void AppConfig::SpeedhackOptions::LoadSave( IniInterface& ini ) ini.SetPath( L".." ); } +void AppConfig::FolderOptions::ApplyDefaults() +{ + if( UseDefaultPlugins ) Plugins = PathDefs::GetPlugins(); + if( UseDefaultSettings ) Settings = PathDefs::GetSettings(); + if( UseDefaultBios ) Bios = PathDefs::GetBios(); + if( UseDefaultSnapshots ) Snapshots = PathDefs::GetSnapshots(); + if( UseDefaultSavestates ) Savestates = PathDefs::GetSavestates(); + if( UseDefaultMemoryCards ) MemoryCards = PathDefs::GetMemoryCards(); + if( UseDefaultLogs ) Logs = PathDefs::GetLogs(); +} + // ------------------------------------------------------------------------ void AppConfig::FolderOptions::LoadSave( IniInterface& ini ) { ini.SetPath( L"Folders" ); + if( ini.IsSaving() ) + ApplyDefaults(); + IniEntry( Plugins, PathDefs::GetPlugins() ); IniEntry( Settings, PathDefs::GetSettings() ); IniEntry( Bios, PathDefs::GetBios() ); @@ -380,9 +495,20 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini ) IniEntry( Savestates, PathDefs::GetSavestates() ); IniEntry( MemoryCards, PathDefs::GetMemoryCards() ); IniEntry( Logs, PathDefs::GetLogs() ); - + IniEntry( RunIso, PathDefs::GetDocuments() ); // raw default is always the Documents folder. + IniEntryBitfield( UseDefaultPlugins, true ); + IniEntryBitfield( UseDefaultSettings, true ); + IniEntryBitfield( UseDefaultBios, true ); + IniEntryBitfield( UseDefaultSnapshots, true ); + IniEntryBitfield( UseDefaultSavestates, true ); + IniEntryBitfield( UseDefaultMemoryCards, true ); + IniEntryBitfield( UseDefaultLogs, true ); + + if( ini.IsLoading() ) + ApplyDefaults(); + ini.SetPath( L".." ); } diff --git a/pcsx2/gui/ConsoleLogger.cpp b/pcsx2/gui/ConsoleLogger.cpp index 1f105e57bf..d9acfb9ce3 100644 --- a/pcsx2/gui/ConsoleLogger.cpp +++ b/pcsx2/gui/ConsoleLogger.cpp @@ -116,7 +116,7 @@ void ConsoleLogFrame::ColorArray::SetFont( const wxFont& font ) static const Console::Colors DefaultConsoleColor = Color_White; // ------------------------------------------------------------------------ -ConsoleLogFrame::ConsoleLogFrame(MainEmuFrame *parent, const wxString& title) : +ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, const AppConfig::ConsoleLogOptions& options ) : wxFrame(parent, wxID_ANY, title) , m_TextCtrl( *new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH2 ) ) @@ -141,14 +141,8 @@ ConsoleLogFrame::ConsoleLogFrame(MainEmuFrame *parent, const wxString& title) : CreateStatusBar(); ClearColor(); - // Sync with configuration settings: - - wxASSERT_MSG( g_Conf != NULL, L"Console Log Frames must be created AFTER the configuration has been loaded" ); - if( g_Conf != NULL ) - { - SetSize( wxRect( g_Conf->ConLogBox.DisplayPosition, g_Conf->ConLogBox.DisplaySize ) ); - Show( g_Conf->ConLogBox.Visible ); - } + SetSize( wxRect( options.DisplayPosition, options.DisplaySize ) ); + Show( options.Visible ); // Bind Events: diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.cpp b/pcsx2/gui/Dialogs/ConfigurationDialog.cpp index 8de1bdc3cf..5a1e61c96e 100644 --- a/pcsx2/gui/Dialogs/ConfigurationDialog.cpp +++ b/pcsx2/gui/Dialogs/ConfigurationDialog.cpp @@ -24,7 +24,6 @@ #include "ConfigurationDialog.h" #include "Panels/ConfigurationPanels.h" -#include #include using namespace wxHelpers; @@ -48,9 +47,18 @@ Dialogs::ConfigurationDialog::ConfigurationDialog( wxWindow* parent, int id ) : m_listbook.SetImageList( &wxGetApp().GetImgList_Config() ); const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config ); + g_ApplyState.StartBook( &m_listbook ); + + g_ApplyState.SetCurrentPage( m_listbook.GetPageCount() ); m_listbook.AddPage( new PathsPanel( m_listbook ), _("Folders"), false, cfgid.Paths ); + + g_ApplyState.SetCurrentPage( m_listbook.GetPageCount() ); m_listbook.AddPage( new PluginSelectorPanel( m_listbook ), _("Plugins"), false, cfgid.Plugins ); + + g_ApplyState.SetCurrentPage( m_listbook.GetPageCount() ); m_listbook.AddPage( new SpeedHacksPanel( m_listbook ), _("Speedhacks"), false, cfgid.Speedhacks ); + + g_ApplyState.SetCurrentPage( m_listbook.GetPageCount() ); m_listbook.AddPage( new GameFixesPanel( m_listbook ), _("Game Fixes"), false, cfgid.Gamefixes ); mainSizer.Add( &m_listbook ); @@ -66,43 +74,20 @@ Dialogs::ConfigurationDialog::ConfigurationDialog( wxWindow* parent, int id ) : Dialogs::ConfigurationDialog::~ConfigurationDialog() { -} - -bool Dialogs::ConfigurationDialog::ApplySettings() -{ - AppConfig confcopy( *g_Conf ); - - try - { - int pagecount = m_listbook.GetPageCount(); - for( int i=0; iApply( confcopy ); - } - - *g_Conf = confcopy; - g_Conf->Apply(); - g_Conf->Save(); - } - catch( Exception::CannotApplySettings& ex ) - { - wxMessageBox( ex.DisplayMessage(), _("Cannot apply settings...") ); - - // TODO : Automatically switch focus to the panel that failed. - return false; - } - return true; + g_ApplyState.DoCleanup(); } void Dialogs::ConfigurationDialog::OnOk_Click( wxCommandEvent& evt ) { - evt.Skip(); - if( ApplySettings() ) Close(); + if( g_ApplyState.ApplyAll() ) + { + Close(); + evt.Skip(); + } } void Dialogs::ConfigurationDialog::OnApply_Click( wxCommandEvent& evt ) { evt.Skip(); - ApplySettings(); + g_ApplyState.ApplyAll(); } diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.h b/pcsx2/gui/Dialogs/ConfigurationDialog.h index 1dc54734d4..734ab355fa 100644 --- a/pcsx2/gui/Dialogs/ConfigurationDialog.h +++ b/pcsx2/gui/Dialogs/ConfigurationDialog.h @@ -37,7 +37,6 @@ namespace Dialogs ConfigurationDialog(wxWindow* parent, int id=wxID_ANY); protected: - bool ApplySettings(); void OnOk_Click( wxCommandEvent& evt ); void OnApply_Click( wxCommandEvent& evt ); }; diff --git a/pcsx2/gui/Dialogs/PickUserModeDialog.cpp b/pcsx2/gui/Dialogs/PickUserModeDialog.cpp index 1d8464988c..9320cc275f 100644 --- a/pcsx2/gui/Dialogs/PickUserModeDialog.cpp +++ b/pcsx2/gui/Dialogs/PickUserModeDialog.cpp @@ -23,33 +23,6 @@ using namespace wxHelpers; -Panels::UsermodeSelectionPanel::UsermodeSelectionPanel( wxWindow* parent ) : - BaseApplicableConfigPanel( parent ) -, m_radio_user( NULL ) -, m_radio_cwd( NULL ) -{ - wxStaticBoxSizer& s_boxer = *new wxStaticBoxSizer( wxVERTICAL, this, _( "Usermode Selection" ) ); - AddStaticText( s_boxer, - L"Please select your preferred default location for PCSX2 user-level documents below " - L"(includes memory cards, screenshots, settings, and savestates). " - L"These folder locations can be overridden at any time using the Core Settings panel.", - 480, wxALIGN_CENTRE ); - - m_radio_user = &AddRadioButton( s_boxer, _("User Documents (recommended)"), _("Location: ") + wxStandardPaths::Get().GetDocumentsDir() ); - m_radio_cwd = &AddRadioButton( s_boxer, _("Current working folder (intended for developer use only)"), _("Location: ") + wxGetCwd() ); - - s_boxer.AddSpacer( 4 ); - SetSizerAndFit( &s_boxer ); -} - -void Panels::UsermodeSelectionPanel::Apply( AppConfig& conf ) -{ - if( !m_radio_cwd->GetValue() && !m_radio_user->GetValue() ) - throw Exception::CannotApplySettings( wxLt( "You must select one of the available user modes before proceeding." ) ); - conf.UseAdminMode = m_radio_cwd->GetValue(); -} - - Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent, int id ) : wxDialogWithHelpers( parent, id, _("PCSX2 First Time configuration"), false ) , m_panel_usersel( new Panels::UsermodeSelectionPanel( this ) ) @@ -58,10 +31,7 @@ Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent, int id ) : AddStaticText( s_main, _("PCSX2 is starting from a new or unknown folder and needs to be configured."), 0, wxALIGN_CENTRE ); - s_main.AddSpacer( 8 ); - s_main.Add( m_panel_usersel, SizerFlags::StdGroupie() ); - - //new wxListCt + s_main.Add( m_panel_usersel, wxSizerFlags().Expand().Border( wxALL, 8 ) ); AddOkCancel( s_main ); SetSizerAndFit( &s_main ); @@ -76,10 +46,8 @@ void Dialogs::PickUserModeDialog::OnOk_Click( wxCommandEvent& evt ) try { m_panel_usersel->Apply( confcopy ); - *g_Conf = confcopy; g_Conf->Apply(); - g_Conf->Save(); Close(); evt.Skip(); diff --git a/pcsx2/gui/IniInterface.cpp b/pcsx2/gui/IniInterface.cpp index 42ca88ba45..316e2652ad 100644 --- a/pcsx2/gui/IniInterface.cpp +++ b/pcsx2/gui/IniInterface.cpp @@ -66,7 +66,7 @@ void IniLoader::Entry( const wxString& var, wxString& value, const wxString& def void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName& defvalue ) { wxString dest; - m_Config.Read( var, &dest, wxString() ); + m_Config.Read( var, &dest, wxEmptyString ); if( dest.IsEmpty() ) value = defvalue; @@ -93,9 +93,18 @@ void IniLoader::Entry( const wxString& var, uint& value, const uint defvalue ) void IniLoader::Entry( const wxString& var, bool& value, const bool defvalue ) { + // TODO : Stricter value checking on enabled/disabled? wxString dest; m_Config.Read( var, &dest, defvalue ? L"enabled" : L"disabled" ); - value = (dest == L"enabled") || (dest == L"1"); + value = (dest == L"enabled") || (dest != L"0"); +} + +bool IniLoader::EntryBitfield( const wxString& var, bool value, const bool defvalue ) +{ + // Note: 'value' param is used by inisaver only. + bool result; + Entry( var, result, defvalue ); + return result; } void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue ) @@ -175,6 +184,12 @@ void IniSaver::Entry( const wxString& var, bool& value, const bool defvalue ) m_Config.Write( var, value ? L"enabled" : L"disabled" ); } +bool IniSaver::EntryBitfield( const wxString& var, bool value, const bool defvalue ) +{ + m_Config.Write( var, value ? L"enabled" : L"disabled" ); + return value; +} + void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue ) { m_Config.Write( var, ToString( value ) ); diff --git a/pcsx2/gui/IniInterface.h b/pcsx2/gui/IniInterface.h index 5f13e795c7..64e9254286 100644 --- a/pcsx2/gui/IniInterface.h +++ b/pcsx2/gui/IniInterface.h @@ -52,7 +52,10 @@ public: virtual void Entry( const wxString& var, wxFileName& value, const wxFileName& defvalue=wxFileName() )=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, bool& value, const bool defvalue=false )=0; + + // This special form of Entry is provided for bitfields, which cannot be passed by reference. + virtual bool EntryBitfield( const wxString& var, bool value, const bool defvalue=false )=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; @@ -78,13 +81,15 @@ public: bool IsLoading() const { return true; } - void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() ); + void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxEmptyString ); void Entry( const wxString& var, wxDirName& value, const wxDirName& defvalue=wxDirName() ); void Entry( const wxString& var, wxFileName& value, const wxFileName& defvalue=wxFileName() ); 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 ); + bool EntryBitfield( 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 ); @@ -116,6 +121,8 @@ public: void Entry( const wxString& var, uint& value, const uint defvalue=0 ); void Entry( const wxString& var, bool& value, const bool defvalue=false ); + bool EntryBitfield( 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 ); diff --git a/pcsx2/gui/MainFrame.cpp b/pcsx2/gui/MainFrame.cpp index 601dbd4b52..0a57611969 100644 --- a/pcsx2/gui/MainFrame.cpp +++ b/pcsx2/gui/MainFrame.cpp @@ -269,14 +269,15 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title): // ------------------------------------------------------------------------ - m_menuRun.Append(Menu_BootIso, _("Run ISO"), MakeIsoMenu(), _("Performs a complete bootup sequence (recommended for best compat)")); - m_menuRun.Append(Menu_BootIsoFast, _("Run ISO (skip Bios)"), MakeIsoMenu(), _("Skips PS2 startup screens when booting; may cause compat issues")); - m_menuRun.Append(Menu_BootQuickCDVD,_("Run CDVD"), MakeCdvdMenu(), _("Skips PS2 init screens when running cdvd images")); - m_menuRun.Append(Menu_BootFullCDVD, _("Run CDVD (skip Bios)"), MakeCdvdMenu(), _("Skips PS2 startup screens when booting; may cause compat issues")); - m_menuRun.Append(Menu_RunWithoutDisc,_("Run without Disc"), _("Use this to access the PS2 system configuration menu")); - m_menuRun.Append(Menu_RunELF, _("Run ELF File..."), wxEmptyString); - m_menuRun.AppendSeparator(); + m_menuRun.Append(Menu_RunIso, _("Run ISO"), MakeIsoMenu() ); + m_menuRun.Append(Menu_BootCDVD, _("Run CDVD"), MakeCdvdMenu() ); + m_menuRun.Append(Menu_RunWithoutDisc,_("Run without Disc"), _("Use this to access the PS2 system configuration menu")); + m_menuRun.Append(Menu_RunELF, _("Run ELF File..."), _("For running raw PS2 binaries.")); + m_menuRun.AppendSeparator(); + m_menuRun.Append(Menu_SkipBiosToggle,_("Skip Bios on Boot"), _("Enable this to skip PS2 bootup screens (may hurt compat)")); + + m_menuRun.AppendSeparator(); m_menuRun.Append(Menu_SuspendExec, _("Suspend"), _T("Stops emulation dead in its tracks")); m_menuRun.Append(Menu_ResumeExec, _("Resume"), _T("Resumes suspended emulation")); m_menuRun.Append(Menu_States, _("States"), MakeStatesMenu(), wxEmptyString); diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h index 18a47a3fdf..2c5ff5a331 100644 --- a/pcsx2/gui/MainFrame.h +++ b/pcsx2/gui/MainFrame.h @@ -45,13 +45,13 @@ protected: Menu_Misc, // Misc options and help! // Run SubSection - Menu_BootIsoFast = 20, // Opens Recent Files sub-menu, and boots selected iso using QuickBoot - Menu_BootIso, // Opens Recent Files sub-menu, and boots selected iso using FullBoot - Menu_IsoBrowse, // sub-menu opened up by BootIso - Menu_BootQuickCDVD, // opens a submenu filled by CDVD plugin (usually list of drives) - Menu_BootFullCDVD, // opens a submenu filled by CDVD plugin (usually list of drives) + Menu_RunIso = 20, // Opens submenu with Iso browser, and recent isos. + Menu_IsoBrowse, // Open dialog, runs selected iso. + Menu_BootCDVD, // opens a submenu filled by CDVD plugin (usually list of drives) Menu_RunWithoutDisc, // used to enter the bios (subs in cdvdnull) Menu_RunELF, + Menu_SkipBiosToggle, // enables the Bios Skip speedhack + Menu_EnableSkipBios, // check marked menu that toggles Skip Bios boot feature. Menu_SuspendExec, // suspends active emulation Menu_ResumeExec, // restores active emulation Menu_Reset, // Issues a complete reset. diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index bbb03cf4a9..b2492b6145 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -26,11 +26,20 @@ #include #include +#include +#include #include "wxHelpers.h" #include "Utilities/SafeArray.h" #include "Utilities/Threading.h" +// Annoyances of C++ forward declarations. Having to type in this red tape mess +// is keeping me form eating a good sandwich right now... >_< +namespace Panels +{ + class BaseApplicableConfigPanel; +} + namespace Exception { // -------------------------------------------------------------------------- @@ -41,31 +50,111 @@ namespace Exception // class CannotApplySettings : public BaseException { + protected: + Panels::BaseApplicableConfigPanel* m_Panel; + public: virtual ~CannotApplySettings() throw() {} - CannotApplySettings( const CannotApplySettings& src ) : BaseException( src ) {} + CannotApplySettings( const CannotApplySettings& src ) : + BaseException( src ) + , m_Panel( src.m_Panel ) {} - explicit CannotApplySettings( const char* msg=wxLt("Cannot apply new settings, one of the settings is invalid.") ) : - BaseException( msg ) {} + explicit CannotApplySettings( Panels::BaseApplicableConfigPanel* thispanel, const char* msg=wxLt("Cannot apply new settings, one of the settings is invalid.") ) : + BaseException( msg ) + , m_Panel( thispanel ) + {} - explicit CannotApplySettings( const wxString& msg_eng, const wxString& msg_xlt ) : - BaseException( msg_eng, msg_xlt ) { } + explicit CannotApplySettings( Panels::BaseApplicableConfigPanel* thispanel, const wxString& msg_eng, const wxString& msg_xlt ) : + BaseException( msg_eng, msg_xlt ) + , m_Panel( thispanel ) + {} + + Panels::BaseApplicableConfigPanel* GetPanel() + { + return m_Panel; + } }; } namespace Panels { + + typedef std::list PanelApplyList_t; + + struct StaticApplyState + { + // Static collection of ApplicableConfigPanels currently available to the user. + PanelApplyList_t PanelList; + + // Current book page being initialized. Any apply objects created will use + // this page as their "go here on error" page. (used to take the user to the + // page with the option that failed apply validation). + int CurOwnerPage; + + // TODO : Rename me to CurOwnerBook, or rename the one above to ParentPage. + wxBookCtrlBase* ParentBook; + + StaticApplyState() : + PanelList() + , CurOwnerPage( wxID_NONE ) + , ParentBook( NULL ) + { + } + + void SetCurrentPage( int page ) + { + CurOwnerPage = page; + } + + void ClearCurrentPage() + { + CurOwnerPage = wxID_NONE; + } + + void StartBook( wxBookCtrlBase* book ); + bool ApplyAll(); + void DoCleanup(); + }; + + extern StaticApplyState g_ApplyState; + ////////////////////////////////////////////////////////////////////////////////////////// // Extends the Panel class to add an Apply() method, which is invoked from the parent // window (usually the ConfigurationDialog) when either Ok or Apply is clicked. // + // Thread Safety: None. This class is only safe when used from the GUI thread, as it uses + // static vars and assumes that only one Applicableconfig system is available to the + // use rate any time (ie, a singular modal dialog). + // class BaseApplicableConfigPanel : public wxPanelWithHelpers { + protected: + int m_OwnerPage; + wxBookCtrlBase* m_OwnerBook; + public: - virtual ~BaseApplicableConfigPanel() { } + virtual ~BaseApplicableConfigPanel() + { + g_ApplyState.PanelList.remove( this ); + } + BaseApplicableConfigPanel( wxWindow* parent ) : - wxPanelWithHelpers( parent, wxID_ANY ) { } - + wxPanelWithHelpers( parent, wxID_ANY ) + , m_OwnerPage( g_ApplyState.CurOwnerPage ) + , m_OwnerBook( g_ApplyState.ParentBook ) + { + g_ApplyState.PanelList.push_back( this ); + } + + int GetOwnerPage() const { return m_OwnerPage; } + wxBookCtrlBase* GetOwnerBook() { return m_OwnerBook; } + + void SetFocusToMe() + { + if( (m_OwnerBook == NULL) || (m_OwnerPage == wxID_NONE) ) return; + m_OwnerBook->SetSelection( m_OwnerPage ); + } + // This method attempts to assign the settings for the panel into the given // configuration structure (which is typically a copy of g_Conf). If validation // of form contents fails, the function should throw Exception::CannotApplySettings. @@ -124,18 +213,20 @@ namespace Panels class PathsPanel : public BaseApplicableConfigPanel { protected: - class DirPickerPanel : public wxPanelWithHelpers + class DirPickerPanel : public BaseApplicableConfigPanel { protected: - wxDirName (*m_GetDefaultFunc)(); - wxDirPickerCtrl* m_pickerCtrl; - wxCheckBox* m_checkCtrl; + FoldersEnum_t m_FolderId; + wxDirPickerCtrl* m_pickerCtrl; + wxCheckBox* m_checkCtrl; public: - DirPickerPanel( wxWindow* parent, const wxDirName& initPath, wxDirName (*getDefault)(), const wxString& label, const wxString& dialogLabel ); + DirPickerPanel( wxWindow* parent, FoldersEnum_t folderid, const wxString& label, const wxString& dialogLabel ); + void Apply( AppConfig& conf ); protected: void UseDefaultPath_Click(wxCommandEvent &event); + void UpdateCheckStatus( bool someNoteworthyBoolean ); }; class MyBasePanel : public wxPanelWithHelpers @@ -147,8 +238,8 @@ namespace Panels MyBasePanel(wxWindow& parent, int id=wxID_ANY); protected: - void AddDirPicker( wxBoxSizer& sizer, const wxDirName& initPath, wxDirName (*getDefaultFunc)(), - const wxString& label, const wxString& popupLabel, enum ExpandedMsgEnum tooltip ); + void AddDirPicker( wxBoxSizer& sizer, FoldersEnum_t folderid, const wxString& label, + const wxString& popupLabel, enum ExpandedMsgEnum tooltip ); }; class StandardPanel : public MyBasePanel diff --git a/pcsx2/gui/Panels/MiscPanelStuff.cpp b/pcsx2/gui/Panels/MiscPanelStuff.cpp new file mode 100644 index 0000000000..d73d320f02 --- /dev/null +++ b/pcsx2/gui/Panels/MiscPanelStuff.cpp @@ -0,0 +1,110 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2009 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "PrecompiledHeader.h" +#include "ConfigurationPanels.h" + +#include + + +Panels::StaticApplyState Panels::g_ApplyState; + +// ----------------------------------------------------------------------- +// This method should be called by the parent dalog box of a configuration +// on dialog destruction. It asserts if the ApplyList hasn't been cleaned up +// and then cleans it up forcefully. +// +void Panels::StaticApplyState::DoCleanup() +{ + wxASSERT_MSG( PanelList.size() != 0, L"PanelList list hasn't been cleaned up." ); + PanelList.clear(); + ParentBook = NULL; +} + +void Panels::StaticApplyState::StartBook( wxBookCtrlBase* book ) +{ + DevAssert( ParentBook == NULL, "An ApplicableConfig session is already in progress." ); + ParentBook = book; +} + +// ----------------------------------------------------------------------- +// Returns false if one of the panels fails input validation (in which case dialogs +// should not be closed, etc). +// +bool Panels::StaticApplyState::ApplyAll() +{ + bool retval = true; + try + { + AppConfig confcopy( *g_Conf ); + + PanelApplyList_t::iterator yay = PanelList.begin(); + while( yay != PanelList.end() ) + { + //DbgCon::Status( L"Writing settings for: " + (*yay)->GetLabel() ); + (*yay)->Apply( confcopy ); + yay++; + } + + // If an exception is thrown above, this code below won't get run. + // (conveniently skipping any option application! :D) + + *g_Conf = confcopy; + g_Conf->Apply(); + g_Conf->Save(); + } + catch( Exception::CannotApplySettings& ex ) + { + wxMessageBox( ex.DisplayMessage(), _("Cannot apply settings...") ); + + if( ex.GetPanel() != NULL ) + ex.GetPanel()->SetFocusToMe(); + + retval = false; + + } + + return retval; +} + +// ----------------------------------------------------------------------- +Panels::UsermodeSelectionPanel::UsermodeSelectionPanel( wxWindow* parent ) : + BaseApplicableConfigPanel( parent ) +, m_radio_user( NULL ) +, m_radio_cwd( NULL ) +{ + wxStaticBoxSizer& s_boxer = *new wxStaticBoxSizer( wxVERTICAL, this, _( "Usermode Selection" ) ); + AddStaticText( s_boxer, + L"Please select your preferred default location for PCSX2 user-level documents below " + L"(includes memory cards, screenshots, settings, and savestates). " + L"These folder locations can be overridden at any time using the Core Settings panel.", + 480, wxALIGN_CENTRE ); + + m_radio_user = &AddRadioButton( s_boxer, _("User Documents (recommended)"), _("Location: ") + wxStandardPaths::Get().GetDocumentsDir() ); + m_radio_cwd = &AddRadioButton( s_boxer, _("Current working folder (intended for developer use only)"), _("Location: ") + wxGetCwd() ); + + s_boxer.AddSpacer( 4 ); + SetSizerAndFit( &s_boxer ); +} + +void Panels::UsermodeSelectionPanel::Apply( AppConfig& conf ) +{ + if( !m_radio_cwd->GetValue() && !m_radio_user->GetValue() ) + throw Exception::CannotApplySettings( this, wxLt( "You must select one of the available user modes before proceeding." ) ); + conf.UseAdminMode = m_radio_cwd->GetValue(); +} diff --git a/pcsx2/gui/Panels/PathsPanel.cpp b/pcsx2/gui/Panels/PathsPanel.cpp index 7a07a936fe..7ea3308feb 100644 --- a/pcsx2/gui/Panels/PathsPanel.cpp +++ b/pcsx2/gui/Panels/PathsPanel.cpp @@ -25,20 +25,31 @@ using namespace wxHelpers; static const int BetweenFolderSpace = 5; +// Pass me TRUE if the default path is to be used, and the DirPcikerCtrl disabled from use. +void Panels::PathsPanel::DirPickerPanel::UpdateCheckStatus( bool someNoteworthyBoolean ) +{ + m_pickerCtrl->Enable( !someNoteworthyBoolean ); + if( someNoteworthyBoolean ) + m_pickerCtrl->SetPath( PathDefs::Get( m_FolderId ).ToString() ); +} + void Panels::PathsPanel::DirPickerPanel::UseDefaultPath_Click(wxCommandEvent &event) { wxASSERT( m_pickerCtrl != NULL && m_checkCtrl != NULL ); - m_pickerCtrl->Enable( !m_checkCtrl->IsChecked() ); - m_pickerCtrl->SetPath( m_GetDefaultFunc().ToString() ); + UpdateCheckStatus( m_checkCtrl->IsChecked() ); } // ------------------------------------------------------------------------ -Panels::PathsPanel::DirPickerPanel::DirPickerPanel( wxWindow* parent, const wxDirName& initPath, wxDirName (*getDefault)(), +// If initPath is NULL, then it's assumed the default folder is to be used, which is +// obtained from invoking the specified getDefault() function. +// +Panels::PathsPanel::DirPickerPanel::DirPickerPanel( wxWindow* parent, FoldersEnum_t folderid, const wxString& label, const wxString& dialogLabel ) : - wxPanelWithHelpers( parent, wxID_ANY ) -, m_GetDefaultFunc( getDefault ) + BaseApplicableConfigPanel( parent ) +, m_FolderId( folderid ) { - wxDirName normalized( initPath ); + const bool isDefault = g_Conf->Folders.IsDefault( m_FolderId ); + wxDirName normalized( isDefault ? g_Conf->Folders[m_FolderId] : PathDefs::Get(m_FolderId) ); normalized.Normalize(); wxStaticBoxSizer& s_box = *new wxStaticBoxSizer( wxVERTICAL, this, label ); @@ -51,13 +62,21 @@ Panels::PathsPanel::DirPickerPanel::DirPickerPanel( wxWindow* parent, const wxDi ); s_box.Add( m_pickerCtrl, wxSizerFlags().Border(wxLEFT | wxRIGHT | wxTOP, 5).Expand() ); - m_checkCtrl = &AddCheckBox( s_box, _("Use operating system default settings") ); + m_checkCtrl = &AddCheckBox( s_box, _("Use installation default setting") ); + m_checkCtrl->SetValue( isDefault ); + UpdateCheckStatus( isDefault ); SetSizerAndFit( &s_box ); Connect( m_checkCtrl->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PathsPanel::DirPickerPanel::UseDefaultPath_Click ) ); } +void Panels::PathsPanel::DirPickerPanel::Apply( AppConfig& conf ) +{ + throw Exception::CannotApplySettings( this ); + conf.Folders.Set( m_FolderId, m_pickerCtrl->GetPath(), m_checkCtrl->GetValue() ); +} + // ------------------------------------------------------------------------ Panels::PathsPanel::MyBasePanel::MyBasePanel( wxWindow& parent, int id ) : wxPanelWithHelpers( &parent, id ) @@ -65,9 +84,9 @@ Panels::PathsPanel::MyBasePanel::MyBasePanel( wxWindow& parent, int id ) : { } -void Panels::PathsPanel::MyBasePanel::AddDirPicker( wxBoxSizer& sizer, const wxDirName& initPath, wxDirName (*getDefaultFunc)(), const wxString& label, const wxString& popupLabel, ExpandedMsgEnum tooltip ) +void Panels::PathsPanel::MyBasePanel::AddDirPicker( wxBoxSizer& sizer, FoldersEnum_t folderid, const wxString& label, const wxString& popupLabel, ExpandedMsgEnum tooltip ) { - DirPickerPanel* dpan = new DirPickerPanel( this, initPath, getDefaultFunc, label, popupLabel ); + DirPickerPanel* dpan = new DirPickerPanel( this, folderid, label, popupLabel ); dpan->SetToolTip( pxE(tooltip) ); sizer.Add( dpan, SizerFlags::StdGroupie() ); } @@ -76,24 +95,31 @@ void Panels::PathsPanel::MyBasePanel::AddDirPicker( wxBoxSizer& sizer, const wxD Panels::PathsPanel::StandardPanel::StandardPanel( wxWindow& parent, int id ) : MyBasePanel( parent, id ) { - AddDirPicker( s_main, g_Conf->Folders.Bios, PathDefs::GetBios, - _("Bios:"), _("Select folder with PS2 Bios"), Msg_Tooltips_Bios ); + // TODO : Replace the callback mess here with the new FolderId enumeration setup. :) + + AddDirPicker( s_main, FolderId_Bios, + _("Bios:"), + _("Select folder with PS2 Bios"), Msg_Tooltips_Bios ); s_main.AddSpacer( BetweenFolderSpace ); - AddDirPicker( s_main, g_Conf->Folders.Savestates, PathDefs::GetSavestates, - _("Savestates:"), _("Select folder for Savestates"), Msg_Tooltips_Savestates ); + AddDirPicker( s_main, FolderId_Savestates, + _("Savestates:"), + _("Select folder for Savestates"), Msg_Tooltips_Savestates ); s_main.AddSpacer( BetweenFolderSpace ); - AddDirPicker( s_main, g_Conf->Folders.Snapshots, PathDefs::GetSnapshots, - _("Snapshots:"), _("Select a folder for Snapshots"), Msg_Tooltips_Snapshots ); + AddDirPicker( s_main, FolderId_Snapshots, + _("Snapshots:"), + _("Select a folder for Snapshots"), Msg_Tooltips_Snapshots ); s_main.AddSpacer( BetweenFolderSpace ); - AddDirPicker( s_main, g_Conf->Folders.Logs, PathDefs::GetLogs, - _("Logs/Dumps:" ), _("Select a folder for logs/dumps"), Msg_Tooltips_Logs ); + AddDirPicker( s_main, FolderId_Logs, + _("Logs/Dumps:" ), + _("Select a folder for logs/dumps"), Msg_Tooltips_Logs ); s_main.AddSpacer( BetweenFolderSpace ); - AddDirPicker( s_main, g_Conf->Folders.MemoryCards, PathDefs::GetMemoryCards, - _("Memorycards:"), _("Select a default Memorycards folder"), Msg_Tooltips_Memorycards ); + AddDirPicker( s_main, FolderId_MemoryCards, + _("Memorycards:"), + _("Select a default Memorycards folder"), Msg_Tooltips_Memorycards ); s_main.AddSpacer( 5 ); SetSizerAndFit( &s_main ); @@ -107,12 +133,14 @@ Panels::PathsPanel::AdvancedPanel::AdvancedPanel( wxWindow& parent, int id ) : wxStaticBoxSizer& advanced = *new wxStaticBoxSizer( wxVERTICAL, this, _("Advanced") ); AddStaticText( advanced, pxE(Msg_Dialog_AdvancedPaths), 420, wxALIGN_CENTRE ); - AddDirPicker( advanced, g_Conf->Folders.Plugins, PathDefs::GetPlugins, - _("Plugins:"), _("Select folder for PCSX2 plugins"), Msg_Tooltips_PluginsPath ); + AddDirPicker( advanced, FolderId_Plugins, + _("Plugins:"), + _("Select folder for PCSX2 plugins"), Msg_Tooltips_PluginsPath ); advanced.AddSpacer( BetweenFolderSpace ); - AddDirPicker( advanced, g_Conf->Folders.Settings, PathDefs::GetSettings, - _("Settings:"), _("Select a folder for PCSX2 settings/inis"), Msg_Tooltips_SettingsPath ); + AddDirPicker( advanced, FolderId_Settings, + _("Settings:"), + _("Select a folder for PCSX2 settings/inis"), Msg_Tooltips_SettingsPath ); advanced.AddSpacer( 4 ); advanced.Add( new UsermodeSelectionPanel( this ), SizerFlags::StdGroupie() ); diff --git a/pcsx2/gui/main.cpp b/pcsx2/gui/main.cpp index f11a31c97e..83ba2f11cd 100644 --- a/pcsx2/gui/main.cpp +++ b/pcsx2/gui/main.cpp @@ -219,9 +219,8 @@ bool Pcsx2App::OnInit() g_Conf->Folders.Logs.Mkdir(); - m_ProgramLogBox = new ConsoleLogFrame( NULL, L"PCSX2 Program Log" ); + m_ProgramLogBox = new ConsoleLogFrame( NULL, L"PCSX2 Program Log", g_Conf->ConLogBox ); m_Ps2ConLogBox = m_ProgramLogBox; // just use a single logger for now. - m_ProgramLogBox->Hide(); //m_Ps2ConLogBox = new ConsoleLogFrame( NULL, L"PS2 Console Log" ); SysInit(); @@ -264,6 +263,9 @@ bool Pcsx2App::OnInit() int Pcsx2App::OnExit() { g_Conf->Save(); + safe_delete( g_RecentIsoList ); + safe_delete( m_Bitmap_Logo ); + safe_delete( g_Conf ); return wxApp::OnExit(); } diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 91bb8238db..a8886e4d6f 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -2089,6 +2089,10 @@ RelativePath="..\..\gui\Panels\GameFixesPanel.cpp" > + +