mirror of https://github.com/PCSX2/pcsx2.git
Portable mode: now allows fully custom folders, but still allows relocation of pcsx2 folder without breaking (install mode unmodified).
Details: The major differences between install and portable modes should now be: 1. Portable mode doesn't use the registry at all. 2. Portable mode uses the folders inside pcsx2 folder as default (install mode has some default at "my documents"). 3. Portable mode tries to save relative paths at the ini file where possible*. Specifically, portable mode now allows to select custom folders for plugins, bios, etc via the standard UI, which allows using several portable pcsx2 folder sharing the same resources (bios, iso, memcards, etc). * Relative paths where possible = the following sequence (thanks to pseudonym for the brilliant idea): 1. If the file/folder is inside pcsx2 folder, it's saved as completely relative (to pcsx2.exe) 2. Else, if the file/folder is at the same drive as pcsx2.exe, it's saved as absolute path without the drive letter (e.g. /ISO/...) 3. Else, saved as absolute path, including the drive letter (for linux, without drive letter naturally). This allows to create a removable drive with (one or more) pcsx2 folder on it, configure all the files/folders to point to the same drive (ISOs, save states, etc), and then take this drive, plug it into another computer (where it will be assigned with a different drive letter), and everything will continue working. Please test it if you can. Bugs here can be inconvenient... git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4507 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
97ce1783eb
commit
9c234de3ec
|
@ -50,7 +50,7 @@ public:
|
||||||
bool IsSaving() const { return !IsLoading(); }
|
bool IsSaving() const { return !IsLoading(); }
|
||||||
|
|
||||||
virtual void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() )=0;
|
virtual void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() )=0;
|
||||||
virtual void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName() )=0;
|
virtual void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false )=0;
|
||||||
virtual void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false )=0;
|
virtual void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false )=0;
|
||||||
virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=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, uint& value, const uint defvalue=0 )=0;
|
||||||
|
@ -113,7 +113,7 @@ public:
|
||||||
bool IsLoading() const { return true; }
|
bool IsLoading() const { return true; }
|
||||||
|
|
||||||
void Entry( const wxString& var, wxString& value, const wxString defvalue=wxEmptyString );
|
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, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false );
|
||||||
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
|
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
|
||||||
void Entry( const wxString& var, int& value, const int defvalue=0 );
|
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, uint& value, const uint defvalue=0 );
|
||||||
|
@ -151,7 +151,7 @@ public:
|
||||||
bool IsLoading() const { return false; }
|
bool IsLoading() const { return false; }
|
||||||
|
|
||||||
void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() );
|
void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() );
|
||||||
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName() );
|
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false );
|
||||||
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
|
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
|
||||||
void Entry( const wxString& var, int& value, const int defvalue=0 );
|
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, uint& value, const uint defvalue=0 );
|
||||||
|
@ -175,6 +175,7 @@ protected:
|
||||||
// syntax errors. >_<
|
// syntax errors. >_<
|
||||||
//
|
//
|
||||||
#define IniEntry( varname ) ini.Entry( wxT(#varname), varname, varname )
|
#define IniEntry( varname ) ini.Entry( wxT(#varname), varname, varname )
|
||||||
|
#define IniEntryDirFile( varname, isAllowRelative ) ini.Entry( wxT(#varname), varname, varname, isAllowRelative )
|
||||||
#define IniBitfield( varname ) varname = ini.EntryBitfield( wxT(#varname), varname, varname )
|
#define IniBitfield( varname ) varname = ini.EntryBitfield( wxT(#varname), varname, varname )
|
||||||
#define IniBitBool( varname ) varname = ini.EntryBitBool( wxT(#varname), !!varname, varname )
|
#define IniBitBool( varname ) varname = ini.EntryBitBool( wxT(#varname), !!varname, varname )
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,50 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsContains( const wxDirName& dir ) const
|
||||||
|
{
|
||||||
|
return IsContains( (wxFileName)dir );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Auto relative works as follows:
|
||||||
|
// 1. if either base or subject are relative, return subject (should never be used with relative paths).
|
||||||
|
// 2. else if subject is somewhere inside base folder, then result is subject relative to base.
|
||||||
|
// 3. (windows only, implicitly) else if subject is on the same driveletter as base, result is absolute path of subject without the driveletter.
|
||||||
|
// 4. else, result is absolute path of subject.
|
||||||
|
//
|
||||||
|
// returns ok if both this and base are absolute paths.
|
||||||
|
static wxString MakeAutoRelativeTo(const wxFileName _subject, const wxString& pathbase)
|
||||||
|
{
|
||||||
|
wxFileName subject( _subject );
|
||||||
|
wxDirName base ( pathbase );
|
||||||
|
if( base.IsRelative() || subject.IsRelative() )
|
||||||
|
return subject.GetFullPath();
|
||||||
|
|
||||||
|
wxString bv( base.GetVolume() ); bv.MakeUpper();
|
||||||
|
wxString sv( subject.GetVolume() ); sv.MakeUpper();
|
||||||
|
|
||||||
|
if( base.IsContains( subject ) )
|
||||||
|
{
|
||||||
|
subject.MakeRelativeTo( base.GetFullPath() );
|
||||||
|
}
|
||||||
|
else if( base.HasVolume() && subject.HasVolume() && bv == sv )
|
||||||
|
{
|
||||||
|
wxString unusedVolume;
|
||||||
|
wxString pathSansVolume;
|
||||||
|
subject.SplitVolume(subject.GetFullPath(), &unusedVolume, &pathSansVolume);
|
||||||
|
subject = pathSansVolume;
|
||||||
|
}
|
||||||
|
//implicit else: this stays fully absolute
|
||||||
|
|
||||||
|
return subject.GetFullPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
static wxString MakeAutoRelativeTo(const wxDirName subject, const wxString& pathbase)
|
||||||
|
{
|
||||||
|
return MakeAutoRelativeTo( wxFileName( subject ), pathbase );
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the number of sub folders in this directory path
|
// Returns the number of sub folders in this directory path
|
||||||
size_t GetCount() const { return GetDirCount(); }
|
size_t GetCount() const { return GetDirCount(); }
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,8 @@ void IniLoader::Entry( const wxString& var, wxString& value, const wxString defv
|
||||||
value = defvalue;
|
value = defvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue )
|
|
||||||
|
void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue, bool isAllowRelative )
|
||||||
{
|
{
|
||||||
wxString dest;
|
wxString dest;
|
||||||
if( m_Config ) m_Config->Read( var, &dest, wxEmptyString );
|
if( m_Config ) m_Config->Read( var, &dest, wxEmptyString );
|
||||||
|
@ -116,7 +117,14 @@ void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName de
|
||||||
if( dest.IsEmpty() )
|
if( dest.IsEmpty() )
|
||||||
value = defvalue;
|
value = defvalue;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
value = dest;
|
value = dest;
|
||||||
|
if( isAllowRelative )
|
||||||
|
value = g_fullBaseDirName + value;
|
||||||
|
|
||||||
|
if( value.IsAbsolute() )
|
||||||
|
value.Normalize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
|
void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
|
||||||
|
@ -124,8 +132,8 @@ void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName
|
||||||
wxString dest( defvalue.GetFullPath() );
|
wxString dest( defvalue.GetFullPath() );
|
||||||
if( m_Config ) m_Config->Read( var, &dest, defvalue.GetFullPath() );
|
if( m_Config ) m_Config->Read( var, &dest, defvalue.GetFullPath() );
|
||||||
value = dest;
|
value = dest;
|
||||||
if( isAllowRelative && value.IsRelative() )
|
if( isAllowRelative )
|
||||||
value = g_fullBaseDirName+value;
|
value = g_fullBaseDirName + value;
|
||||||
|
|
||||||
if( value.IsAbsolute() )
|
if( value.IsAbsolute() )
|
||||||
value.Normalize();
|
value.Normalize();
|
||||||
|
@ -263,28 +271,24 @@ void IniSaver::Entry( const wxString& var, wxString& value, const wxString defva
|
||||||
m_Config->Write( var, value );
|
m_Config->Write( var, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue )
|
void IniSaver::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue, bool isAllowRelative )
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if( !m_Config ) return;
|
||||||
|
wxDirName res(value);
|
||||||
|
|
||||||
|
if ( res.IsAbsolute() )
|
||||||
|
res.Normalize();
|
||||||
|
|
||||||
|
if (isAllowRelative)
|
||||||
|
res = wxDirName::MakeAutoRelativeTo( res, g_fullBaseDirName.ToString() );
|
||||||
|
|
||||||
|
|
||||||
/*if( value == defvalue )
|
/*if( value == defvalue )
|
||||||
m_Config->Write( var, wxString() );
|
m_Config->Write( var, wxString() );
|
||||||
else*/
|
else*/
|
||||||
m_Config->Write( var, value.ToString() );
|
m_Config->Write( var, res.ToString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//If isAllowRelative is true, we're saving as relative if the file is somewhere inside the PARENT of pcsx2 folder.
|
|
||||||
//When a file is saved as relative, it's always relative to pcsx2 main folder (even if the file is outside of it).
|
|
||||||
//e.g. at the next folder structure, files at ISOs_2 and ISOs_3 will be saved relative, but files at ISOs_1 will be saved absolute.
|
|
||||||
// -root
|
|
||||||
// |-ISOs_1
|
|
||||||
// |-parent_of_pcsx2_folder
|
|
||||||
// |-ISOs_2
|
|
||||||
// |-pcsx2_folder
|
|
||||||
// |-pcsx2.exe
|
|
||||||
// |-plugins
|
|
||||||
// | |-...
|
|
||||||
// |-ISOs_3
|
|
||||||
void IniSaver::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
|
void IniSaver::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if( !m_Config ) return;
|
||||||
|
@ -293,10 +297,8 @@ void IniSaver::Entry( const wxString& var, wxFileName& value, const wxFileName d
|
||||||
if ( res.IsAbsolute() )
|
if ( res.IsAbsolute() )
|
||||||
res.Normalize();
|
res.Normalize();
|
||||||
|
|
||||||
wxDirName upper( g_fullBaseDirName );
|
if (isAllowRelative)
|
||||||
upper.RemoveLast();
|
res = wxDirName::MakeAutoRelativeTo( res, g_fullBaseDirName.ToString() );
|
||||||
if( isAllowRelative && upper.IsContains( value ) )
|
|
||||||
res.MakeRelativeTo(g_fullBaseDirName.ToString());
|
|
||||||
|
|
||||||
m_Config->Write( var, res.GetFullPath() );
|
m_Config->Write( var, res.GetFullPath() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -483,7 +483,7 @@ void App_LoadSaveInstallSettings( IniInterface& ini )
|
||||||
ini.Entry( L"Install_Dir", InstallFolder, (wxDirName)(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()) );
|
ini.Entry( L"Install_Dir", InstallFolder, (wxDirName)(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()) );
|
||||||
SetFullBaseDir( InstallFolder );
|
SetFullBaseDir( InstallFolder );
|
||||||
|
|
||||||
ini.Entry( L"PluginsFolder", PluginsFolder, InstallFolder + PathDefs::Base::Plugins() );
|
//ini.Entry( L"PluginsFolder", PluginsFolder, InstallFolder + PathDefs::Base::Plugins() );
|
||||||
ini.Entry( L"ThemesFolder", ThemesFolder, InstallFolder + PathDefs::Base::Themes() );
|
ini.Entry( L"ThemesFolder", ThemesFolder, InstallFolder + PathDefs::Base::Themes() );
|
||||||
|
|
||||||
ini.Flush();
|
ini.Flush();
|
||||||
|
@ -644,20 +644,20 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini )
|
||||||
IniBitBool( UseDefaultLangs );
|
IniBitBool( UseDefaultLangs );
|
||||||
IniBitBool( UseDefaultPluginsFolder );
|
IniBitBool( UseDefaultPluginsFolder );
|
||||||
|
|
||||||
//when saving in portable mode, we save empty strings
|
//when saving in portable mode, we save relative paths if possible
|
||||||
// --> on load they'll be initialized to default (relative) paths
|
// --> on load, these relative paths will be expanded relative to the exe folder.
|
||||||
bool rel = ( ini.IsSaving() && IsPortable() );
|
bool rel = ( ini.IsLoading() || IsPortable() );
|
||||||
wxDirName e(L"");
|
|
||||||
|
IniEntryDirFile( Bios, rel);
|
||||||
ini.Entry( L"Bios", rel?e:Bios, Bios );
|
IniEntryDirFile( Snapshots, rel );
|
||||||
ini.Entry( L"Snapshots", rel?e:Snapshots, Snapshots );
|
IniEntryDirFile( Savestates, rel );
|
||||||
ini.Entry( L"Savestates", rel?e:Savestates, Savestates );
|
IniEntryDirFile( MemoryCards, rel );
|
||||||
ini.Entry( L"MemoryCards", rel?e:MemoryCards, MemoryCards );
|
IniEntryDirFile( Logs, rel );
|
||||||
ini.Entry( L"Logs", rel?e:Logs, Logs );
|
IniEntryDirFile( Langs, rel );
|
||||||
ini.Entry( L"Langs", rel?e:Langs, Langs );
|
ini.Entry( L"PluginsFolder", PluginsFolder, InstallFolder + PathDefs::Base::Plugins(), rel );
|
||||||
|
|
||||||
IniEntry( RunIso );
|
IniEntryDirFile( RunIso, rel );
|
||||||
IniEntry( RunELF );
|
IniEntryDirFile( RunELF, rel );
|
||||||
|
|
||||||
if( ini.IsLoading() )
|
if( ini.IsLoading() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,7 +107,7 @@ Panels::BiosSelectorPanel::BiosSelectorPanel( wxWindow* parent )
|
||||||
m_ComboBox->SetFont( wxFont( m_ComboBox->GetFont().GetPointSize()+1, wxFONTFAMILY_MODERN, wxNORMAL, wxNORMAL, false, L"Lucida Console" ) );
|
m_ComboBox->SetFont( wxFont( m_ComboBox->GetFont().GetPointSize()+1, wxFONTFAMILY_MODERN, wxNORMAL, wxNORMAL, false, L"Lucida Console" ) );
|
||||||
m_ComboBox->SetMinSize( wxSize( wxDefaultCoord, std::max( m_ComboBox->GetMinSize().GetHeight(), 96 ) ) );
|
m_ComboBox->SetMinSize( wxSize( wxDefaultCoord, std::max( m_ComboBox->GetMinSize().GetHeight(), 96 ) ) );
|
||||||
|
|
||||||
if (InstallationMode != InstallMode_Portable)
|
//if (InstallationMode != InstallMode_Portable)
|
||||||
m_FolderPicker->SetStaticDesc( _("Click the Browse button to select a different folder where PCSX2 will look for PS2 BIOS roms.") );
|
m_FolderPicker->SetStaticDesc( _("Click the Browse button to select a different folder where PCSX2 will look for PS2 BIOS roms.") );
|
||||||
|
|
||||||
wxButton* refreshButton = new wxButton( this, wxID_ANY, _("Refresh list") );
|
wxButton* refreshButton = new wxButton( this, wxID_ANY, _("Refresh list") );
|
||||||
|
|
|
@ -117,9 +117,9 @@ void Panels::DirPickerPanel::Init( FoldersEnum_t folderid, const wxString& dialo
|
||||||
// The default path is invalid... What should we do here? hmm..
|
// The default path is invalid... What should we do here? hmm..
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InstallationMode == InstallMode_Portable)
|
// if (InstallationMode == InstallMode_Portable)
|
||||||
InitForPortableMode(normalized);
|
// InitForPortableMode(normalized);
|
||||||
else
|
// else
|
||||||
InitForRegisteredMode(normalized, dialogLabel, isCompact);
|
InitForRegisteredMode(normalized, dialogLabel, isCompact);
|
||||||
|
|
||||||
// wx warns when paths don't exist, but this is typically normal when the wizard
|
// wx warns when paths don't exist, but this is typically normal when the wizard
|
||||||
|
@ -128,9 +128,11 @@ void Panels::DirPickerPanel::Init( FoldersEnum_t folderid, const wxString& dialo
|
||||||
AppStatusEvent_OnSettingsApplied(); // forces default settings based on g_Conf
|
AppStatusEvent_OnSettingsApplied(); // forces default settings based on g_Conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// InitForPortableMode is currently unused because portable now allows fully custom folders.
|
||||||
void Panels::DirPickerPanel::InitForPortableMode( const wxString& normalized )
|
void Panels::DirPickerPanel::InitForPortableMode( const wxString& normalized )
|
||||||
{
|
{
|
||||||
// In portable mode the path is unchangeable, and only a browse button is provided (which
|
// In portable mode the path is unchangeable, and only a "open in explorer" button is provided (which
|
||||||
// itself is windows-only at this time).
|
// itself is windows-only at this time).
|
||||||
|
|
||||||
m_textCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
|
m_textCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
|
||||||
|
|
|
@ -375,7 +375,7 @@ Panels::PluginSelectorPanel::ComboBoxPanel::ComboBoxPanel( PluginSelectorPanel*
|
||||||
s_plugin += m_configbutton[pid];
|
s_plugin += m_configbutton[pid];
|
||||||
} while( ++pi, pi->shortname != NULL );
|
} while( ++pi, pi->shortname != NULL );
|
||||||
|
|
||||||
if (InstallationMode != InstallMode_Portable)
|
// if (InstallationMode != InstallMode_Portable)
|
||||||
m_FolderPicker.SetStaticDesc( _("Click the Browse button to select a different folder for PCSX2 plugins.") );
|
m_FolderPicker.SetStaticDesc( _("Click the Browse button to select a different folder for PCSX2 plugins.") );
|
||||||
|
|
||||||
*this += s_plugin | pxExpand;
|
*this += s_plugin | pxExpand;
|
||||||
|
|
Loading…
Reference in New Issue