gsdx: Use the same ini code on both Windows and Linux

Partially replace the Linux ini code so that it:
 - works on both Windows and Linux
 - is backwards compatible with older GSdx inis
 - properly handles UTF-8 ini pathnames

Fix an issue with GSdx on Windows not being able to handle non-ASCII
ini pathnames.
This commit is contained in:
Jonathan Li 2019-08-18 09:35:21 +01:00
parent 476ccf8ac9
commit aef0f94dcf
2 changed files with 51 additions and 34 deletions

View File

@ -23,6 +23,7 @@
#include "GSdx.h"
#include "GS.h"
#include "PSX/GPU.h"
#include <fstream>
static void* s_hModule;
@ -117,8 +118,9 @@ bool GSdxApp::LoadResource(int id, std::vector<char>& buff, const char* type)
return true;
}
#endif
size_t GSdxApp::GetPrivateProfileString(const char* lpAppName, const char* lpKeyName, const char* lpDefault, char* lpReturnedString, size_t nSize, const char* lpFileName)
size_t GSdxApp::GetIniString(const char* lpAppName, const char* lpKeyName, const char* lpDefault, char* lpReturnedString, size_t nSize, const char* lpFileName)
{
BuildConfigurationMap(lpFileName);
@ -134,7 +136,7 @@ size_t GSdxApp::GetPrivateProfileString(const char* lpAppName, const char* lpKey
return 0;
}
bool GSdxApp::WritePrivateProfileString(const char* lpAppName, const char* lpKeyName, const char* pString, const char* lpFileName)
bool GSdxApp::WriteIniString(const char* lpAppName, const char* lpKeyName, const char* pString, const char* lpFileName)
{
BuildConfigurationMap(lpFileName);
@ -143,10 +145,15 @@ bool GSdxApp::WritePrivateProfileString(const char* lpAppName, const char* lpKey
m_configuration_map[key] = value;
// Save config to a file
FILE* f = fopen(lpFileName, "w");
FILE* f = px_fopen(lpFileName, "w");
if (f == NULL) return false; // FIXME print a nice message
// Maintain compatibility with GSDumpGUI/old Windows ini.
#ifdef _WIN32
fprintf(f, "[Settings]\n");
#endif
for (const auto& entry : m_configuration_map) {
// Do not save the inifile key which is not an option
if (entry.first.compare("inifile") == 0) continue;
@ -160,7 +167,7 @@ bool GSdxApp::WritePrivateProfileString(const char* lpAppName, const char* lpKey
return false;
}
int GSdxApp::GetPrivateProfileInt(const char* lpAppName, const char* lpKeyName, int nDefault, const char* lpFileName)
int GSdxApp::GetIniInt(const char* lpAppName, const char* lpKeyName, int nDefault, const char* lpFileName)
{
BuildConfigurationMap(lpFileName);
@ -172,7 +179,6 @@ int GSdxApp::GetPrivateProfileInt(const char* lpAppName, const char* lpKeyName,
} else
return atoi(value.c_str());
}
#endif
GSdxApp theApp;
@ -469,7 +475,6 @@ void GSdxApp::Init()
m_default_configuration["disable_ts_half_bottom"] = "0";
}
#if defined(__unix__)
void GSdxApp::ReloadConfig()
{
if (m_configuration_map.empty()) return;
@ -491,23 +496,39 @@ void GSdxApp::BuildConfigurationMap(const char* lpFileName)
m_configuration_map["inifile"] = inifile_value;
// Load config from file
char value[256];
char key[256];
FILE* f = fopen(lpFileName, "r");
if (f == NULL) return; // FIXME print a nice message
while( fscanf(f, "%255s = %255s\n", key, value) != EOF ) {
std::string key_s(key);
std::string value_s(value);
// Only keep option that have a default value (allow to purge old option of the GSdx.ini)
if (m_default_configuration.find(key_s) != m_default_configuration.end())
m_configuration_map[key_s] = value_s;
}
fclose(f);
}
#ifdef _WIN32
std::ifstream file(convert_utf8_to_utf16(lpFileName));
#else
std::ifstream file(lpFileName);
#endif
if (!file.is_open())
return;
std::string line;
while (std::getline(file, line)) {
const auto separator = line.find('=');
if (separator == std::string::npos)
continue;
std::string key = line.substr(0, separator);
// Trim trailing whitespace
key.erase(key.find_last_not_of(" \r\t") + 1);
if (key.empty())
continue;
// Only keep options that have a default value so older, no longer used
// ini options can be purged.
if (m_default_configuration.find(key) == m_default_configuration.end())
continue;
std::string value = line.substr(separator + 1);
// Trim leading whitespace
value.erase(0, value.find_first_not_of(" \r\t"));
m_configuration_map[key] = value;
}
}
void* GSdxApp::GetModuleHandlePtr()
{
@ -539,10 +560,10 @@ std::string GSdxApp::GetConfigS(const char* entry)
auto def = m_default_configuration.find(entry);
if (def != m_default_configuration.end()) {
GetPrivateProfileString(m_section.c_str(), entry, def->second.c_str(), buff, countof(buff), m_ini.c_str());
GetIniString(m_section.c_str(), entry, def->second.c_str(), buff, countof(buff), m_ini.c_str());
} else {
fprintf(stderr, "Option %s doesn't have a default value\n", entry);
GetPrivateProfileString(m_section.c_str(), entry, "", buff, countof(buff), m_ini.c_str());
GetIniString(m_section.c_str(), entry, "", buff, countof(buff), m_ini.c_str());
}
return {buff};
@ -550,7 +571,7 @@ std::string GSdxApp::GetConfigS(const char* entry)
void GSdxApp::SetConfig(const char* entry, const char* value)
{
WritePrivateProfileString(m_section.c_str(), entry, value, m_ini.c_str());
WriteIniString(m_section.c_str(), entry, value, m_ini.c_str());
}
int GSdxApp::GetConfigI(const char* entry)
@ -558,10 +579,10 @@ int GSdxApp::GetConfigI(const char* entry)
auto def = m_default_configuration.find(entry);
if (def != m_default_configuration.end()) {
return GetPrivateProfileInt(m_section.c_str(), entry, std::stoi(def->second), m_ini.c_str());
return GetIniInt(m_section.c_str(), entry, std::stoi(def->second), m_ini.c_str());
} else {
fprintf(stderr, "Option %s doesn't have a default value\n", entry);
return GetPrivateProfileInt(m_section.c_str(), entry, 0, m_ini.c_str());
return GetIniInt(m_section.c_str(), entry, 0, m_ini.c_str());
}
}

View File

@ -29,9 +29,7 @@ class GSdxApp
std::string m_ini;
std::string m_section;
std::map< std::string, std::string > m_default_configuration;
#if defined(__unix__)
std::map< std::string, std::string > m_configuration_map;
#endif
GSRendererType m_current_renderer_type;
public:
@ -44,14 +42,12 @@ public:
HMODULE GetModuleHandle() {return (HMODULE)GetModuleHandlePtr();}
#endif
#if defined(__unix__)
void BuildConfigurationMap(const char* lpFileName);
void ReloadConfig();
size_t GetPrivateProfileString(const char* lpAppName, const char* lpKeyName, const char* lpDefault, char* lpReturnedString, size_t nSize, const char* lpFileName);
bool WritePrivateProfileString(const char* lpAppName, const char* lpKeyName, const char* pString, const char* lpFileName);
int GetPrivateProfileInt(const char* lpAppName, const char* lpKeyName, int nDefault, const char* lpFileName);
#endif
size_t GetIniString(const char* lpAppName, const char* lpKeyName, const char* lpDefault, char* lpReturnedString, size_t nSize, const char* lpFileName);
bool WriteIniString(const char* lpAppName, const char* lpKeyName, const char* pString, const char* lpFileName);
int GetIniInt(const char* lpAppName, const char* lpKeyName, int nDefault, const char* lpFileName);
bool LoadResource(int id, std::vector<char>& buff, const char* type = nullptr);