From 36453885fc3d6d0ef32c0fb0803ffa46df25f6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Wed, 6 Mar 2019 20:38:57 -0300 Subject: [PATCH 01/42] XDG Base Dir Spec followup #383 * Add XDG Base Dir Spec for other Unix alike platform. * Add XDG Base Dir support for the fallback on SDL port. * Add migration for Unix configuration file. We migrate from 'vbam.conf' to 'vbam.ini' automatically. * Refactor code for portability of dir creation functions. * Fix for MacOS compilation directive. --- src/Util.cpp | 60 ++++++++++++++++++++++++++++++++++++ src/Util.h | 4 +++ src/common/ConfigManager.cpp | 25 ++++++++------- src/common/ConfigManager.h | 2 +- src/sdl/SDL.cpp | 29 ++++++++++++----- src/wx/wxvbam.cpp | 42 +++++++++---------------- 6 files changed, 115 insertions(+), 47 deletions(-) diff --git a/src/Util.cpp b/src/Util.cpp index dc2135b2..6daa7809 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -64,6 +64,66 @@ bool FileExists(const char *filename) #endif } +// Get user-specific config dir manually. +// apple: ~/Library/Application Support/ +// windows: %APPDATA% +// unix: ${XDG_CONFIG_HOME:-~/.config} +std::string get_xdg_user_config_home() +{ + std::string path; +#ifdef __APPLE__ + std::string home(getenv("HOME")); + path = home + "/Library/Application Support/"; +#elif _WIN32 + std::string app_data(getenv("LOCALAPPDATA")); + path = app_data + '\\'; +#else // Unix + char *xdg_var = getenv("XDG_CONFIG_HOME"); + if (!xdg_var || !*xdg_var) + { + std::string xdg_default(getenv("HOME")); + xdg_default += "/.config"; + path = xdg_default; + } + else + { + path = xdg_var; + } + path += '/'; +#endif + return path; +} + +// Get user-specific data dir manually. +// apple: ~/Library/Application Support/ +// windows: %APPDATA% +// unix: ${XDG_DATA_HOME:-~/.local/share} +std::string get_xdg_user_data_home() +{ + std::string path; +#ifdef __APPLE__ + std::string home(getenv("HOME")); + path = home + "/Library/Application Support/"; +#elif _WIN32 + std::string app_data(getenv("LOCALAPPDATA")); + path = app_data + '\\'; +#else // Unix + char *xdg_var = getenv("XDG_DATA_HOME"); + if (!xdg_var || !*xdg_var) + { + std::string xdg_default(getenv("HOME")); + xdg_default += "/.local/share"; + path = xdg_default; + } + else + { + path = xdg_var; + } + path += '/'; +#endif + return path; +} + void utilReadScreenPixels(uint8_t *dest, int w, int h) { uint8_t *b = dest; diff --git a/src/Util.h b/src/Util.h index 2cf0646a..69bcaab6 100644 --- a/src/Util.h +++ b/src/Util.h @@ -1,6 +1,7 @@ #ifndef UTIL_H #define UTIL_H +#include #include "System.h" enum IMAGE_TYPE { IMAGE_UNKNOWN = -1, IMAGE_GBA = 0, IMAGE_GB = 1 }; @@ -13,6 +14,9 @@ typedef struct { bool FileExists(const char *filename); +std::string get_xdg_user_config_home(); +std::string get_xdg_user_data_home(); + void utilReadScreenPixels(uint8_t *dest, int w, int h); bool utilWritePNGFile(const char *, int, int, uint8_t *); bool utilWriteBMPFile(const char *, int, int, uint8_t *); diff --git a/src/common/ConfigManager.cpp b/src/common/ConfigManager.cpp index a5e05014..b741338d 100644 --- a/src/common/ConfigManager.cpp +++ b/src/common/ConfigManager.cpp @@ -38,6 +38,9 @@ extern "C" { #include #define GETCWD _getcwd #define snprintf sprintf +#define stat _stat +#define mkdir(X,Y) (_mkdir(X)) +#define S_ISDIR _S_IFDIR #endif // _WIN32 #ifndef __GNUC__ @@ -647,7 +650,7 @@ const char* FindConfigFile(const char *name) } if (homeDir) { - sprintf(path, "%s%c%s%c%s", homeDir, FILE_SEP, DOT_DIR, FILE_SEP, name); + sprintf(path, "%s%c%s", homeDir, FILE_SEP, name); if (FileExists(path)) { return path; @@ -717,11 +720,11 @@ const char* FindConfigFile(const char *name) void LoadConfigFile() { -#if !defined(_WIN32) && !defined(__APPLE__) - homeDir = getenv("HOME"); -#else - homeDir = 0; -#endif + struct stat s; + std::string homeDirTmp = get_xdg_user_config_home() + FILE_SEP + DOT_DIR; + homeDir = (char *)homeDirTmp.c_str(); + if (stat(homeDir, &s) == -1 || !S_ISDIR(s.st_mode)) + mkdir(homeDir, 0755); if (preferences == NULL) { @@ -738,11 +741,11 @@ void LoadConfigFile() void SaveConfigFile() { -#if !defined(_WIN32) && !defined(__APPLE__) - homeDir = getenv("HOME"); -#else - homeDir = 0; -#endif + struct stat s; + std::string homeDirTmp = get_xdg_user_config_home() + FILE_SEP + DOT_DIR; + homeDir = (char *)homeDirTmp.c_str(); + if (stat(homeDir, &s) == -1 || !S_ISDIR(s.st_mode)) + mkdir(homeDir, 0755); const char* configFile = FindConfigFile("vbam.ini"); diff --git a/src/common/ConfigManager.h b/src/common/ConfigManager.h index 066d9a0d..77ac8c7b 100644 --- a/src/common/ConfigManager.h +++ b/src/common/ConfigManager.h @@ -164,7 +164,7 @@ extern const char *saveDir; extern const char *batteryDir; // Directory within homedir to use for default save location. -#define DOT_DIR ".vbam" +#define DOT_DIR "visualboyadvance-m" void SetHome(char *_arg0); void SaveConfigFile(); diff --git a/src/sdl/SDL.cpp b/src/sdl/SDL.cpp index 5add3508..8a2c6787 100644 --- a/src/sdl/SDL.cpp +++ b/src/sdl/SDL.cpp @@ -71,6 +71,9 @@ #include #define GETCWD _getcwd #define snprintf sprintf +#define stat _stat +#define mkdir(X,Y) (_mkdir(X)) +#define S_ISDIR _S_IFDIR #endif // _WIN32 #ifndef __GNUC__ @@ -202,6 +205,7 @@ int sdlMirroringEnable = 1; void systemConsoleMessage(const char*); char* home; +char homeDataDir[2048]; char screenMessageBuffer[21]; uint32_t screenMessageTime = 0; @@ -246,7 +250,7 @@ void StartLirc(void) fprintf(stdout, "Success\n"); //read the config file char LIRCConfigLoc[2048]; - sprintf(LIRCConfigLoc, "%s/%s/%s", homeDir, DOT_DIR, "lircrc"); + sprintf(LIRCConfigLoc, "%s/%s", homeDataDir, "lircrc"); fprintf(stdout, "LIRC Config file:"); if (lirc_readconfig(LIRCConfigLoc, &LIRCConfigInfo, NULL) == 0) { //check vbam dir for lircrc @@ -366,8 +370,8 @@ FILE* sdlFindFile(const char* name) } if (homeDir) { - fprintf(stdout, "Searching home directory: %s%c%s\n", homeDir, FILE_SEP, DOT_DIR); - sprintf(path, "%s%c%s%c%s", homeDir, FILE_SEP, DOT_DIR, FILE_SEP, name); + fprintf(stdout, "Searching home directory: %s\n", homeDataDir); + sprintf(path, "%s%c%s", homeDataDir, FILE_SEP, name); f = fopen(path, "r"); if (f != NULL) return f; @@ -659,7 +663,7 @@ static char* sdlStateName(int num) sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), num + 1); else if (homeDir) - sprintf(stateName, "%s/%s/%s%d.sgm", homeDir, DOT_DIR, sdlGetFilename(filename), num + 1); + sprintf(stateName, "%s/%s%d.sgm", homeDataDir, sdlGetFilename(filename), num + 1); else sprintf(stateName, "%s%d.sgm", filename, num + 1); @@ -758,7 +762,7 @@ void sdlWriteBattery() if (batteryDir) sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); else if (homeDir) - sprintf(buffer, "%s/%s/%s.sav", homeDir, DOT_DIR, sdlGetFilename(filename)); + sprintf(buffer, "%s/%s.sav", homeDataDir, sdlGetFilename(filename)); else sprintf(buffer, "%s.sav", filename); @@ -774,7 +778,7 @@ void sdlReadBattery() if (batteryDir) sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); else if (homeDir) - sprintf(buffer, "%s/%s/%s.sav", homeDir, DOT_DIR, sdlGetFilename(filename)); + sprintf(buffer, "%s/%s.sav", homeDataDir, sdlGetFilename(filename)); else sprintf(buffer, "%s.sav", filename); @@ -1637,12 +1641,21 @@ void handleRewinds() } } +void SetHomeDataDir() +{ + sprintf(homeDataDir, "%s%s", get_xdg_user_data_home().c_str(), DOT_DIR); + struct stat s; + if (stat(homeDataDir, &s) == -1 || !S_ISDIR(s.st_mode)) + mkdir(homeDataDir, 0755); +} + int main(int argc, char** argv) { fprintf(stdout, "%s\n", VBA_NAME_AND_SUBVERSION); home = argv[0]; SetHome(home); + SetHomeDataDir(); frameSkip = 2; gbBorderOn = 0; @@ -2213,7 +2226,7 @@ void systemScreenCapture(int a) if (screenShotDir) sprintf(buffer, "%s/%s%02d.bmp", screenShotDir, sdlGetFilename(filename), a); else if (homeDir) - sprintf(buffer, "%s/%s/%s%02d.bmp", homeDir, DOT_DIR, sdlGetFilename(filename), a); + sprintf(buffer, "%s/%s%02d.bmp", homeDataDir, sdlGetFilename(filename), a); else sprintf(buffer, "%s%02d.bmp", filename, a); @@ -2222,7 +2235,7 @@ void systemScreenCapture(int a) if (screenShotDir) sprintf(buffer, "%s/%s%02d.png", screenShotDir, sdlGetFilename(filename), a); else if (homeDir) - sprintf(buffer, "%s/%s/%s%02d.png", homeDir, DOT_DIR, sdlGetFilename(filename), a); + sprintf(buffer, "%s/%s%02d.png", homeDataDir, sdlGetFilename(filename), a); else sprintf(buffer, "%s%02d.png", filename, a); emulator.emuWritePNG(buffer); diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index e6db8bb1..3731f9c8 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -32,26 +32,6 @@ IMPLEMENT_APP(wxvbamApp) IMPLEMENT_DYNAMIC_CLASS(MainFrame, wxFrame) -// Get XDG_CONFIG_HOME dir manually -// only native support for XDG config when wxWidgets >= 3.1 -static wxString get_xdg_user_config_home() -{ - wxString path; - char *xdg_config_home = getenv("XDG_CONFIG_HOME"); - // Default for XDG_CONFIG_HOME is '$HOME/.config' - if (!xdg_config_home || !*xdg_config_home) - { - wxString xdg_default(getenv("HOME")); - xdg_default += "/.config"; - path = xdg_default; - } - else - { - path = xdg_config_home; - } - return path + "/"; -} - // generate config file path static void get_config_path(wxPathList& path, bool exists = true) { @@ -79,7 +59,7 @@ static void get_config_path(wxPathList& path, bool exists = true) wxLogDebug(wxT("GetDataDir(): %s"), stdp.GetDataDir().mb_str()); wxLogDebug(wxT("GetLocalDataDir(): %s"), stdp.GetLocalDataDir().mb_str()); wxLogDebug(wxT("GetPluginsDir(): %s"), stdp.GetPluginsDir().mb_str()); -#if defined(__LINUX__) +#if defined(__WXGTK__) wxLogDebug(wxT("XdgConfigDir: %s"), get_xdg_user_config_home() + current_app_name); #endif debug_dumped = true; @@ -87,11 +67,11 @@ static void get_config_path(wxPathList& path, bool exists = true) // When native support for XDG dirs is available (wxWidgets >= 3.1), // this will be no longer necessary -#if defined(__LINUX__) +#if defined(__WXGTK__) // XDG spec manual support // ${XDG_CONFIG_HOME:-$HOME/.config}/`appname` wxString old_config = wxString(getenv("HOME")) + "/.vbam"; - wxString new_config = get_xdg_user_config_home(); + wxString new_config(get_xdg_user_config_home()); if (!wxDirExists(old_config) && wxIsWritable(new_config)) { path.Add(new_config + current_app_name); @@ -253,12 +233,20 @@ bool wxvbamApp::OnInit() // this needs to be in a subdir to support other config as well // but subdir flag behaves differently 2.8 vs. 2.9. Oh well. // NOTE: this does not support XDG (freedesktop.org) paths -#if defined(__WXMSW__) || defined(__APPLE__) wxString confname("vbam.ini"); -#else - wxString confname("vbam.conf"); -#endif wxFileName vbamconf(GetConfigurationPath(), confname); +// /MIGRATION +// migrate from 'vbam.conf' to 'vbam.ini' to manage a single config +// file for all platforms. +#if !defined(__WXMSW__) && !defined(__APPLE__) + wxString oldConf(GetConfigurationPath() + "/vbam.conf"); + wxString newConf(GetConfigurationPath() + "/vbam.ini"); + if (wxFileExists(oldConf)) + { + wxRenameFile(oldConf, newConf, false); + } +#endif +// /END_MIGRATION cfg = new wxFileConfig(wxT("vbam"), wxEmptyString, vbamconf.GetFullPath(), wxEmptyString, wxCONFIG_USE_LOCAL_FILE); From 7373da1528070b74027119696fe8ddacc5d8aa0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Wed, 6 Mar 2019 22:43:32 -0300 Subject: [PATCH 02/42] Fix segmentation fault issue when using WX port command line on Linux and MacOS. --- src/wx/wxvbam.cpp | 3 ++- src/wx/wxvbam.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 3731f9c8..b28b5807 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -590,7 +590,8 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) } wxvbamApp::~wxvbamApp() { - free(home); + if (home != NULL) + free(home); } MainFrame::MainFrame() diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index fbefca0d..4ab2a013 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -142,7 +142,7 @@ protected: private: wxPathList config_path; - char* home; + char* home = NULL; }; DECLARE_APP(wxvbamApp); From 6a98f3c20008bf0d281fda85005f4e318a59e847 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Wed, 6 Mar 2019 18:49:31 -0800 Subject: [PATCH 03/42] define S_ISDIR for win32 #94 Followup on #383. Signed-off-by: Rafael Kitover --- src/common/ConfigManager.cpp | 7 +++++-- src/sdl/SDL.cpp | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/common/ConfigManager.cpp b/src/common/ConfigManager.cpp index b741338d..2ef6cc9a 100644 --- a/src/common/ConfigManager.cpp +++ b/src/common/ConfigManager.cpp @@ -40,7 +40,10 @@ extern "C" { #define snprintf sprintf #define stat _stat #define mkdir(X,Y) (_mkdir(X)) -#define S_ISDIR _S_IFDIR +// from: https://www.linuxquestions.org/questions/programming-9/porting-to-win32-429334/ +#ifndef S_ISDIR + #define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR) +#endif #endif // _WIN32 #ifndef __GNUC__ @@ -679,7 +682,7 @@ const char* FindConfigFile(const char *name) while (tok) { sprintf(path, "%s%c%s", tok, FILE_SEP, EXE_NAME); if (FileExists(path)) { - char path2[2048]; + static char path2[2048]; sprintf(path2, "%s%c%s", tok, FILE_SEP, name); if (FileExists(path2)) { return path2; diff --git a/src/sdl/SDL.cpp b/src/sdl/SDL.cpp index 8a2c6787..2ee65899 100644 --- a/src/sdl/SDL.cpp +++ b/src/sdl/SDL.cpp @@ -73,7 +73,10 @@ #define snprintf sprintf #define stat _stat #define mkdir(X,Y) (_mkdir(X)) -#define S_ISDIR _S_IFDIR +// from: https://www.linuxquestions.org/questions/programming-9/porting-to-win32-429334/ +#ifndef S_ISDIR + #define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR) +#endif #endif // _WIN32 #ifndef __GNUC__ From 530af1403027dde5b316689a5fb3d23de3b4a3f7 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Thu, 7 Mar 2019 07:13:07 -0800 Subject: [PATCH 04/42] rpi plugins fix + paths enhancements #94 Store the full relative path to found `.rpi` plugins, relative to the standard Plugins directory, as specified by wxWidgets. This fixes the problem of plugins being in a subdirectory while only the basename was stored, making the plugins unusable. This is done by using `wxFileName::GetFullPath()` instead of `wxFileName::GetFullName()` with a relative filename instance. Make a `GetPluginsDir()` method on the app class to simplify getting this directory, and for possible future overrides. Also make some minor, functionally equivalent changes to `get_config_path()` in `wxvbam.cpp`: - use the new `GetPluginsDir()` method for the plugins directory when building the config file search path - print the XdgConfigDir on all platforms, since the function works on all platforms - make a `add_nonstandard_path` macro which duplicates the `add_path` macro for wxWidgets standard paths but for any arbitrary string path - use `wxFileName` methods to make the XDG config directory path instead of string concatenation Signed-off-by: Rafael Kitover --- src/wx/guiinit.cpp | 6 +++--- src/wx/panel.cpp | 2 +- src/wx/wxvbam.cpp | 27 +++++++++++++++++++++------ src/wx/wxvbam.h | 1 + 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/wx/guiinit.cpp b/src/wx/guiinit.cpp index 87906f8a..e958385f 100644 --- a/src/wx/guiinit.cpp +++ b/src/wx/guiinit.cpp @@ -1775,8 +1775,8 @@ public: ch->Clear(); ch->Append(_("None")); plugins.clear(); - const wxString& plpath = wxStandardPaths::Get().GetPluginsDir(); - wxDir::GetAllFiles(plpath, &plugins, wxT("*.rpi")); + const wxString plpath = wxGetApp().GetPluginsDir(); + wxDir::GetAllFiles(plpath, &plugins, wxT("*.rpi"), wxDIR_FILES | wxDIR_DIRS); for (int i = 0; i < plugins.size(); i++) { wxDynamicLibrary dl(plugins[i], wxDL_VERBATIM | wxDL_NOW); @@ -1798,7 +1798,7 @@ public: s += wxT(": "); s += wxString(rpi->Name, wxConvUTF8, sizeof(rpi->Name)); fn.MakeRelativeTo(plpath); - plugins[i] = fn.GetFullName(); + plugins[i] = fn.GetFullPath(); ch->Append(s); if (plugins[i] == gopts.filter_plugin) diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index c9acce93..268037fd 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -1336,7 +1336,7 @@ DrawingPanelBase::DrawingPanelBase(int _width, int _height) break; wxFileName fpn(gopts.filter_plugin); - fpn.MakeAbsolute(wxStandardPaths::Get().GetPluginsDir()); + fpn.MakeAbsolute(wxGetApp().GetPluginsDir()); if (!filt_plugin.Load(fpn.GetFullPath(), wxDL_VERBATIM | wxDL_NOW)) break; diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index b28b5807..9d2deaf2 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -48,6 +48,14 @@ static void get_config_path(wxPathList& path, bool exists = true) if ((wxDirExists(s) && wxIsWritable(s)) || ((!exists || !wxDirExists(s)) && parent.IsDirWritable())) \ path.Add(s); \ } while (0) +#define add_nonstandard_path(p) \ + do { \ + const wxString& s = p; \ + wxFileName parent = wxFileName::DirName(s + wxT("//..")); \ + parent.MakeAbsolute(); \ + if ((wxDirExists(s) && wxIsWritable(s)) || ((!exists || !wxDirExists(s)) && parent.IsDirWritable())) \ + path.Add(s); \ + } while (0) static bool debug_dumped = false; @@ -58,10 +66,8 @@ static void get_config_path(wxPathList& path, bool exists = true) wxLogDebug(wxT("GetResourcesDir(): %s"), stdp.GetResourcesDir().mb_str()); wxLogDebug(wxT("GetDataDir(): %s"), stdp.GetDataDir().mb_str()); wxLogDebug(wxT("GetLocalDataDir(): %s"), stdp.GetLocalDataDir().mb_str()); - wxLogDebug(wxT("GetPluginsDir(): %s"), stdp.GetPluginsDir().mb_str()); -#if defined(__WXGTK__) + wxLogDebug(wxT("plugins_dir: %s"), wxGetApp().GetPluginsDir().mb_str()); wxLogDebug(wxT("XdgConfigDir: %s"), get_xdg_user_config_home() + current_app_name); -#endif debug_dumped = true; } @@ -74,12 +80,16 @@ static void get_config_path(wxPathList& path, bool exists = true) wxString new_config(get_xdg_user_config_home()); if (!wxDirExists(old_config) && wxIsWritable(new_config)) { - path.Add(new_config + current_app_name); + wxFileName new_path(new_config, wxEmptyString); + new_path.AppendDir(current_app_name); + new_path.MakeAbsolute(); + + add_nonstandard_path(new_path.GetFullPath()); } else { // config is in $HOME/.vbam/vbam.conf - path.Add(old_config); + add_nonstandard_path(old_config); } #endif @@ -90,7 +100,7 @@ static void get_config_path(wxPathList& path, bool exists = true) add_path(GetResourcesDir()); add_path(GetDataDir()); add_path(GetLocalDataDir()); - add_path(GetPluginsDir()); + add_nonstandard_path(wxGetApp().GetPluginsDir()); } static void tack_full_path(wxString& s, const wxString& app = wxEmptyString) @@ -103,6 +113,11 @@ static void tack_full_path(wxString& s, const wxString& app = wxEmptyString) s += wxT("\n\t") + full_config_path[i] + app; } +const wxString wxvbamApp::GetPluginsDir() +{ + return wxStandardPaths::Get().GetPluginsDir(); +} + wxString wxvbamApp::GetConfigurationPath() { #if defined(__WXMSW__) || defined(__APPLE__) diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 4ab2a013..7c92b918 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -87,6 +87,7 @@ public: virtual void OnInitCmdLine(wxCmdLineParser&); virtual bool OnCmdLineParsed(wxCmdLineParser&); wxString GetConfigurationPath(); + const wxString GetPluginsDir(); wxString GetAbsolutePath(wxString path); // name of a file to load at earliest opportunity wxString pending_load; From dbd1d8c1f815ce2ea98eea34d3b95e3277f966e3 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 8 Mar 2019 16:56:46 -0800 Subject: [PATCH 05/42] attempt to re-enable travis mingw slaves The mxe pkg server seems to be back online with some changes, and an invalid SSL certificate. Also thanks to @denisfa's work on 7373da15 we can re-enable the `--help` check on travis. Let's see if this works. Signed-off-by: Rafael Kitover --- .travis.yml | 60 ++++++++++++++++++++++++++--------------------------- installdeps | 15 ++++++++++++-- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/.travis.yml b/.travis.yml index a55a356f..7df77f27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,38 +15,38 @@ matrix: - cd build - cmake .. - make -j2 -# - ./visualboyadvance-m --help + - ./visualboyadvance-m --help + cache: + directories: + - "$HOME/.ccache" + - env: BUILD_ENV=mingw-w64 + language: cpp + os: linux + dist: trusty + before_script: + - ./installdeps MinGW-w64-x86_64 + script: + - mkdir build + - cd build + - /usr/lib/mxe/usr/bin/x86_64-w64-mingw32.static-cmake .. + - make -j2 + cache: + directories: + - "$HOME/.ccache" + - env: BUILD_ENV=mingw-w32 + language: cpp + os: linux + dist: trusty + before_script: + - ./installdeps MinGW-w64-i686 + script: + - mkdir build + - cd build + - /usr/lib/mxe/usr/bin/i686-w64-mingw32.static-cmake .. + - make -j2 cache: directories: - "$HOME/.ccache" -# - env: BUILD_ENV=mingw-w64 -# language: cpp -# os: linux -# dist: trusty -# before_script: -# - ./installdeps MinGW-w64-x86_64 -# script: -# - mkdir build -# - cd build -# - /usr/lib/mxe/usr/bin/x86_64-w64-mingw32.static-cmake .. -# - make -j2 -# cache: -# directories: -# - "$HOME/.ccache" -# - env: BUILD_ENV=mingw-w32 -# language: cpp -# os: linux -# dist: trusty -# before_script: -# - ./installdeps MinGW-w64-i686 -# script: -# - mkdir build -# - cd build -# - /usr/lib/mxe/usr/bin/i686-w64-mingw32.static-cmake .. -# - make -j2 -# cache: -# directories: -# - "$HOME/.ccache" - env: BUILD_ENV=libretro language: cpp os: linux @@ -70,7 +70,7 @@ matrix: - cd build - cmake .. - make -j2 -# - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help + - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help cache: directories: - "$HOME/.ccache" diff --git a/installdeps b/installdeps index 68ca78b5..7d659d40 100755 --- a/installdeps +++ b/installdeps @@ -302,12 +302,23 @@ debian_installdeps() { ;; esac - mxe_apt_sources='/etc/apt/sources.list.d/mxeapt.list' + debian_rel=stretch + + apt_ssl_exceptions=/etc/apt/apt.conf.d/80ssl-exceptions + + if ! grep -q 'pkg\.mxe\.cc' $apt_ssl_exceptions; then + sudo sh -c "cat >> $apt_ssl_exceptions" < $mxe_apt_sources" + echo "deb http://pkg.mxe.cc/repos/apt/dists $debian_rel main" | sudo -- sh -c "cat > $mxe_apt_sources" check sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB else error "$mxe_apt_sources exists but mxe packages are not found in apt, either delete it or fix it" From 8f0a578ade1538d8d3d9b95519ec767be7b27ba2 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 8 Mar 2019 17:13:48 -0800 Subject: [PATCH 06/42] travis update attempt 2 Use `xvfb` as per instructions at: https://docs.travis-ci.com/user/gui-and-headless-browsers/ to run the `--help` check on linux. Try https url for `pkg.mxe.cc`. Signed-off-by: Rafael Kitover --- .travis.yml | 5 ++++- installdeps | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7df77f27..635a8ad5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ --- sudo: required +services: + - xvfb + matrix: fast_finish: true include: @@ -15,7 +18,7 @@ matrix: - cd build - cmake .. - make -j2 - - ./visualboyadvance-m --help + - xvfb-run ./visualboyadvance-m --help cache: directories: - "$HOME/.ccache" diff --git a/installdeps b/installdeps index 7d659d40..f856d833 100755 --- a/installdeps +++ b/installdeps @@ -306,7 +306,7 @@ debian_installdeps() { apt_ssl_exceptions=/etc/apt/apt.conf.d/80ssl-exceptions - if ! grep -q 'pkg\.mxe\.cc' $apt_ssl_exceptions; then + if ! grep -q 'pkg\.mxe\.cc' $apt_ssl_exceptions 2>/dev/null; then sudo sh -c "cat >> $apt_ssl_exceptions" < $mxe_apt_sources" + echo "deb https://pkg.mxe.cc/repos/apt/dists $debian_rel main" | sudo -- sh -c "cat > $mxe_apt_sources" check sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB else error "$mxe_apt_sources exists but mxe packages are not found in apt, either delete it or fix it" From 7b3a3a0c4f88a65247386fc6c06738df30195781 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 8 Mar 2019 19:55:10 -0800 Subject: [PATCH 07/42] travis update attempt 3 Disable the `--help` test for now, for some reason the exit code is 255, something is still not quite working there. Update installdeps to force a partial upgrade from trusty to xenial on travis to get a newer version of libcurl-gnutls, which is necessary to use the mxe package server. Fix mxe package server repo url. Add `mirror.mxe.cc` to list of apt hostnames to ignore SSL errors for. Signed-off-by: Rafael Kitover --- .travis.yml | 4 ++-- installdeps | 34 +++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 635a8ad5..740e3073 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ matrix: - cd build - cmake .. - make -j2 - - xvfb-run ./visualboyadvance-m --help +# - xvfb-run ./visualboyadvance-m --help cache: directories: - "$HOME/.ccache" @@ -73,7 +73,7 @@ matrix: - cd build - cmake .. - make -j2 - - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help +# - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help cache: directories: - "$HOME/.ccache" diff --git a/installdeps b/installdeps index f856d833..36b0aae8 100755 --- a/installdeps +++ b/installdeps @@ -280,7 +280,7 @@ debian_installdeps() { installing if [ -z "$target" ]; then - sudo apt-get -qq update + sudo apt-get -qq -y update sfml_libs=$(apt-cache search libsfml | grep -E 'graphics|window|network' | sed 's/ - .*//') @@ -302,23 +302,43 @@ debian_installdeps() { ;; esac + # if on the travis ubuntu trusty, add xenial sources for newer gnutls + # otherwise the mxe pkg server does not work + if [ -n "$TRAVIS" ]; then + if grep -q trusty /etc/apt/sources.list 2>/dev/null; then + sudo sh -c "sed 's/trusty/xenial/g' /etc/apt/sources.list > /etc/apt/sources.list.d/xenial.list" + fi + fi + + sudo apt-get -qq -y update + + curl_gnutls_lib=$(apt-cache search libcurl | grep -E '^libcurl[0-9]+-gnutls - ' | sed 's/ - .*//' | sort | tail -1) + + sudo apt-get -qy install apt apt-transport-https ca-certificates $curl_gnutls_lib curl + + # this is necessary to upgrade libcurl from trusty to xenial on travis + sudo apt-get -qy -f install + debian_rel=stretch apt_ssl_exceptions=/etc/apt/apt.conf.d/80ssl-exceptions - if ! grep -q 'pkg\.mxe\.cc' $apt_ssl_exceptions 2>/dev/null; then + if ! grep -Eq '(pkg|mirror)\.mxe\.cc' $apt_ssl_exceptions 2>/dev/null; then sudo sh -c "cat >> $apt_ssl_exceptions" < $mxe_apt_sources" + echo "deb https://pkg.mxe.cc/repos/apt $debian_rel main" | sudo -- sh -c "cat > $mxe_apt_sources" check sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB else error "$mxe_apt_sources exists but mxe packages are not found in apt, either delete it or fix it" @@ -329,7 +349,7 @@ EOF for dep in gcc zlib ffmpeg gettext sdl2 sfml openal wxwidgets; do set -- "$@" "mxe-${target}-$dep" done - check sudo apt-get -qq update + check sudo apt-get -qq -y update # native wx-common needed for wxrc executable check sudo apt-get -qy install build-essential cmake ccache wx-common "$@" fi From 77bcbbf445c6edd78bac49a3d300ee15c4731e12 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 8 Mar 2019 20:03:17 -0800 Subject: [PATCH 08/42] travis update attempt 4 Pass --allow-unauthenticated to apt when installing mxe packages, perhaps the gpg key changed. Signed-off-by: Rafael Kitover --- installdeps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installdeps b/installdeps index 36b0aae8..c095aafa 100755 --- a/installdeps +++ b/installdeps @@ -351,7 +351,7 @@ EOF done check sudo apt-get -qq -y update # native wx-common needed for wxrc executable - check sudo apt-get -qy install build-essential cmake ccache wx-common "$@" + check sudo apt-get -qy --allow-unauthenticated install build-essential cmake ccache wx-common "$@" fi build_instructions From 36fbf71527fe5fab5725cea7003066de3f7d0439 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 8 Mar 2019 20:52:09 -0800 Subject: [PATCH 09/42] travis update attempt 5 `stretch` mxe binaries are failing due to missing libraries like `libssl.so.1.1`, try to use the `trusty` repo instead. Signed-off-by: Rafael Kitover --- installdeps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installdeps b/installdeps index c095aafa..d093ca7f 100755 --- a/installdeps +++ b/installdeps @@ -319,7 +319,7 @@ debian_installdeps() { # this is necessary to upgrade libcurl from trusty to xenial on travis sudo apt-get -qy -f install - debian_rel=stretch + debian_rel=trusty apt_ssl_exceptions=/etc/apt/apt.conf.d/80ssl-exceptions From 944c263e7f43f565c006b72d0ea96fae8136b59b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Mon, 11 Mar 2019 14:32:39 -0300 Subject: [PATCH 10/42] auto save/load geometry for wx GUI #94 * Add support to save/load geometry options for GUI window. * Refactor code to use wxWidgets functions to get window geometry. * Call update_opts() from ::OnSize and ::OnMove functions. --- src/common/ConfigManager.cpp | 26 ++++++++++++++++++-- src/common/ConfigManager.h | 2 ++ src/wx/opts.cpp | 9 +++++-- src/wx/wxvbam.cpp | 46 ++++++++++++++++++++++++++++++++++++ src/wx/wxvbam.h | 3 +++ 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/common/ConfigManager.cpp b/src/common/ConfigManager.cpp index 2ef6cc9a..f860fdf0 100644 --- a/src/common/ConfigManager.cpp +++ b/src/common/ConfigManager.cpp @@ -109,8 +109,10 @@ enum named_opts OPT_SYNCHRONIZE, OPT_THREAD_PRIORITY, OPT_VIDEO_OPTION, + OPT_WINDOW_HEIGHT, OPT_WINDOW_POSITION_X, OPT_WINDOW_POSITION_Y, + OPT_WINDOW_WIDTH, OPT_SPEEDUP_THROTTLE, OPT_SPEEDUP_FRAME_SKIP }; @@ -239,8 +241,10 @@ int useBiosFileGBC; int videoOption; int vsync; int wasPaused = 0; +uint32_t windowHeight; int windowPositionX; int windowPositionY; +uint32_t windowWidth; int winFlashSize; int winGbBorderOn; int winGbPrinterEnabled; @@ -394,8 +398,10 @@ struct option argOptions[] = { { "video-option", required_argument, 0, OPT_VIDEO_OPTION }, { "vsync", no_argument, &vsync, 1 }, { "win-gb-printer-enabled", no_argument, &winGbPrinterEnabled, 1 }, + { "window-height", required_argument, 0, OPT_WINDOW_HEIGHT }, { "window-position-x", required_argument, 0, OPT_WINDOW_POSITION_X }, { "window-position-y", required_argument, 0, OPT_WINDOW_POSITION_Y }, + { "window-width", required_argument, 0, OPT_WINDOW_WIDTH }, { NULL, no_argument, NULL, 0 } @@ -547,8 +553,10 @@ void LoadConfig() useBiosFileGBC = ReadPref("useBiosGBC", 0); videoOption = ReadPref("video", 2); // VIDEO_3X = 2 vsync = ReadPref("vsync", false); - windowPositionX = ReadPref("windowX", 0); - windowPositionY = ReadPref("windowY", 0); + windowHeight = ReadPref("windowHeight", 0); + windowPositionX = ReadPref("windowX", -1); + windowPositionY = ReadPref("windowY", -1); + windowWidth = ReadPref("windowWidth", 0); winFlashSize = ReadPref("flashSize", 0x10000); winGbBorderOn = ReadPref("borderOn", 0); winGbPrinterEnabled = ReadPref("gbPrinter", 0); @@ -1333,6 +1341,20 @@ int ReadOpts(int argc, char ** argv) } break; + case OPT_WINDOW_HEIGHT: + // --window-height + if (optarg) { + windowHeight = atoi(optarg); + } + break; + + case OPT_WINDOW_WIDTH: + // --window-width + if (optarg) { + windowWidth = atoi(optarg); + } + break; + case OPT_DOTCODE_FILE_NAME_LOAD: // --dotcode-file-name-load loadDotCodeFile = optarg; diff --git a/src/common/ConfigManager.h b/src/common/ConfigManager.h index 77ac8c7b..7983fe87 100644 --- a/src/common/ConfigManager.h +++ b/src/common/ConfigManager.h @@ -132,8 +132,10 @@ extern int useBiosFileGBC; extern int videoOption; extern int vsync; extern int wasPaused; +extern uint32_t windowHeight; extern int windowPositionX; extern int windowPositionY; +extern uint32_t windowWidth; extern int winFlashSize; extern int winGbBorderOn; extern int winGbPrinterEnabled; diff --git a/src/wx/opts.cpp b/src/wx/opts.cpp index 48c561d7..5ea9d72f 100644 --- a/src/wx/opts.cpp +++ b/src/wx/opts.cpp @@ -239,7 +239,6 @@ opt_desc opts[] = { INTOPT("preferences/fsFrequency", "", wxTRANSLATE("Fullscreen mode frequency (0 = any)"), fsFrequency, 0, 999), INTOPT("preferences/fsHeight", "", wxTRANSLATE("Fullscreen mode height (0 = desktop)"), fsHeight, 0, 99999), INTOPT("preferences/fsWidth", "", wxTRANSLATE("Fullscreen mode width (0 = desktop)"), fsWidth, 0, 99999), - INTOPT("preferences/fullScreen", "Fullscreen", wxTRANSLATE("Enter fullscreen mode at startup"), fullScreen, 0, 1), INTOPT("preferences/gbPaletteOption", "", wxTRANSLATE("The palette to use"), gbPaletteOption, 0, 2), INTOPT("preferences/gbPrinter", "Printer", wxTRANSLATE("Enable printer emulation"), winGbPrinterEnabled, 0, 1), INTOPT("preferences/gdbBreakOnLoad", "DebugGDBBreakOnLoad", wxTRANSLATE("Break into GDB after loading the game."), gdbBreakOnLoad, 0, 1), @@ -264,8 +263,14 @@ opt_desc opts[] = { INTOPT("preferences/useBiosGBC", "BootRomGBC", wxTRANSLATE("Use the specified BIOS file for GBC"), useBiosFileGBC, 0, 1), INTOPT("preferences/vsync", "VSync", wxTRANSLATE("Wait for vertical sync"), vsync, 0, 1), -/// Sound + /// Geometry + INTOPT("geometry/fullScreen", "Fullscreen", wxTRANSLATE("Enter fullscreen mode at startup"), fullScreen, 0, 1), + UINTOPT("geometry/windowHeight", "Height", wxTRANSLATE("Window height at startup"), windowHeight, 0, 99999), + UINTOPT("geometry/windowWidth", "Width", wxTRANSLATE("Window width at startup"), windowWidth, 0, 99999), + INTOPT("geometry/windowX", "X", wxTRANSLATE("Window axis X position at startup"), windowPositionX, -1, 99999), + INTOPT("geometry/windowY", "Y", wxTRANSLATE("Window axis Y position at startup"), windowPositionY, -1, 99999), + /// Sound ENUMOPT("Sound/AudioAPI", "", wxTRANSLATE("Sound API; if unsupported, default API will be used"), gopts.audio_api, wxTRANSLATE("sdl|openal|directsound|xaudio2|faudio")), STROPT("Sound/AudioDevice", "", wxTRANSLATE("Device ID of chosen audio device for chosen driver"), gopts.audio_dev), INTOPT("Sound/Buffers", "", wxTRANSLATE("Number of sound buffers"), gopts.audio_buffers, 2, 10), diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 9d2deaf2..a72d6590 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -398,6 +398,11 @@ bool wxvbamApp::OnInit() } // create the main window + int x = windowPositionX; + int y = windowPositionX; + int width = windowWidth; + int height = windowHeight; + int isFullscreen = fullScreen; frame = wxDynamicCast(xr->LoadFrame(NULL, wxT("MainFrame")), MainFrame); if (!frame) { @@ -409,6 +414,11 @@ bool wxvbamApp::OnInit() if (!frame->BindControls()) return false; + if (x >= 0 && y >= 0 && width > 0 && height > 0) + frame->SetSize(x, y, width, height); + + if (isFullscreen && wxGetApp().pending_load != wxEmptyString) + frame->ShowFullScreen(isFullscreen); frame->Show(true); return true; } @@ -633,6 +643,9 @@ EVT_ACTIVATE(MainFrame::OnActivate) // requires DragAcceptFiles(true); even then may not do anything EVT_DROP_FILES(MainFrame::OnDropFile) +// for window geometry +EVT_MOVE(MainFrame::OnMove) +EVT_SIZE(MainFrame::OnSize) // pause game if menu pops up // // This is a feature most people don't like, and it causes problems with @@ -688,6 +701,39 @@ void MainFrame::OnMenu(wxContextMenuEvent& event) } } +void MainFrame::OnMove(wxMoveEvent& event) +{ + wxRect pos = GetRect(); + int x = pos.GetX(), y = pos.GetY(); + if (x >= 0 && y >= 0 && !IsFullScreen()) + { + windowPositionX = x; + windowPositionY = y; + update_opts(); + } +} + +void MainFrame::OnSize(wxSizeEvent& event) +{ + wxFrame::OnSize(event); + wxRect pos = GetRect(); + int height = pos.GetHeight(), width = pos.GetWidth(); + int x = pos.GetX(), y = pos.GetY(); + bool isFullscreen = IsFullScreen(); + if (height > 0 && width > 0 && !isFullscreen) + { + windowHeight = height; + windowWidth = width; + } + if (x >= 0 && y >= 0 && !isFullscreen) + { + windowPositionX = x; + windowPositionY = y; + } + fullScreen = isFullscreen; + update_opts(); +} + wxString MainFrame::GetGamePath(wxString path) { wxString game_path = path; diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 7c92b918..9213410e 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -356,6 +356,9 @@ private: void OnDropFile(wxDropFilesEvent&); // pop up menu in fullscreen mode void OnMenu(wxContextMenuEvent&); + // window geometry + void OnMove(wxMoveEvent& event); + void OnSize(wxSizeEvent& event); // Load a named wxDialog from the XRC file wxDialog* LoadXRCDialog(const char* name); // Load a named wxDialog from the XRC file From 1ebb8efdb6ef9e524db6025b1c3851829c5ca36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Tue, 12 Mar 2019 14:37:16 -0300 Subject: [PATCH 11/42] Fix to set correctly position Y. --- src/wx/wxvbam.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index a72d6590..1abec074 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -399,7 +399,7 @@ bool wxvbamApp::OnInit() // create the main window int x = windowPositionX; - int y = windowPositionX; + int y = windowPositionY; int width = windowWidth; int height = windowHeight; int isFullscreen = fullScreen; From 513b0559cef5c9c7db5245b38d06d2db53accd35 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Tue, 12 Mar 2019 07:41:01 -0700 Subject: [PATCH 12/42] minor travis update for mingw jobs Use the right gpg key id for the mxe apt server and remove the `--allow-unauthenticated`. Signed-off-by: Rafael Kitover --- installdeps | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/installdeps b/installdeps index d093ca7f..6fa82e29 100755 --- a/installdeps +++ b/installdeps @@ -339,7 +339,7 @@ EOF if [ -z "$(apt-cache search '^mxe-source$')" ]; then if [ ! -f "$mxe_apt_sources" ]; then echo "deb https://pkg.mxe.cc/repos/apt $debian_rel main" | sudo -- sh -c "cat > $mxe_apt_sources" - check sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB + check sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C6BF758A33A3A276 else error "$mxe_apt_sources exists but mxe packages are not found in apt, either delete it or fix it" fi @@ -351,7 +351,7 @@ EOF done check sudo apt-get -qq -y update # native wx-common needed for wxrc executable - check sudo apt-get -qy --allow-unauthenticated install build-essential cmake ccache wx-common "$@" + check sudo apt-get -qy install build-essential cmake ccache wx-common "$@" fi build_instructions From 3fd444da91ecc51d38e3fd00b6e85fff158b6a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Thu, 14 Mar 2019 02:05:02 -0300 Subject: [PATCH 13/42] XDG related cleanups #94 * Add migration support for 'vbam.cfg' to 'vbam.ini' on MacOS and Windows. * Cleanup from XDG Base Dir code. * Set home to NULL after using free(). --- src/Util.cpp | 28 ++++++++++++---------------- src/Util.h | 6 ++++++ src/common/ConfigManager.cpp | 17 ++--------------- src/wx/wxvbam.cpp | 21 +++++++++++---------- 4 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/Util.cpp b/src/Util.cpp index 6daa7809..8366a1bb 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -66,62 +66,58 @@ bool FileExists(const char *filename) // Get user-specific config dir manually. // apple: ~/Library/Application Support/ -// windows: %APPDATA% -// unix: ${XDG_CONFIG_HOME:-~/.config} +// windows: %APPDATA%\ +// unix: ${XDG_CONFIG_HOME:-~/.config}/ std::string get_xdg_user_config_home() { std::string path; #ifdef __APPLE__ std::string home(getenv("HOME")); - path = home + "/Library/Application Support/"; + path = home + "/Library/Application Support"; #elif _WIN32 std::string app_data(getenv("LOCALAPPDATA")); - path = app_data + '\\'; + path = app_data; #else // Unix char *xdg_var = getenv("XDG_CONFIG_HOME"); if (!xdg_var || !*xdg_var) { std::string xdg_default(getenv("HOME")); - xdg_default += "/.config"; - path = xdg_default; + path = xdg_default + "/.config"; } else { path = xdg_var; } - path += '/'; #endif - return path; + return path + FILE_SEP; } // Get user-specific data dir manually. // apple: ~/Library/Application Support/ -// windows: %APPDATA% -// unix: ${XDG_DATA_HOME:-~/.local/share} +// windows: %APPDATA%\ +// unix: ${XDG_DATA_HOME:-~/.local/share}/ std::string get_xdg_user_data_home() { std::string path; #ifdef __APPLE__ std::string home(getenv("HOME")); - path = home + "/Library/Application Support/"; + path = home + "/Library/Application Support"; #elif _WIN32 std::string app_data(getenv("LOCALAPPDATA")); - path = app_data + '\\'; + path = app_data; #else // Unix char *xdg_var = getenv("XDG_DATA_HOME"); if (!xdg_var || !*xdg_var) { std::string xdg_default(getenv("HOME")); - xdg_default += "/.local/share"; - path = xdg_default; + path = xdg_default + "/.local/share"; } else { path = xdg_var; } - path += '/'; #endif - return path; + return path + FILE_SEP; } void utilReadScreenPixels(uint8_t *dest, int w, int h) diff --git a/src/Util.h b/src/Util.h index 69bcaab6..a37141c0 100644 --- a/src/Util.h +++ b/src/Util.h @@ -4,6 +4,12 @@ #include #include "System.h" +#ifdef _WIN32 +#define FILE_SEP '\\' +#else // MacOS, Unix +#define FILE_SEP '/' +#endif + enum IMAGE_TYPE { IMAGE_UNKNOWN = -1, IMAGE_GBA = 0, IMAGE_GB = 1 }; // save game diff --git a/src/common/ConfigManager.cpp b/src/common/ConfigManager.cpp index f860fdf0..2f2b756d 100644 --- a/src/common/ConfigManager.cpp +++ b/src/common/ConfigManager.cpp @@ -644,11 +644,9 @@ const char* FindConfigFile(const char *name) #ifdef _WIN32 #define PATH_SEP ";" -#define FILE_SEP '\\' #define EXE_NAME "vbam.exe" #else // ! _WIN32 #define PATH_SEP ":" -#define FILE_SEP '/' #define EXE_NAME "vbam" #endif // ! _WIN32 @@ -732,7 +730,7 @@ const char* FindConfigFile(const char *name) void LoadConfigFile() { struct stat s; - std::string homeDirTmp = get_xdg_user_config_home() + FILE_SEP + DOT_DIR; + std::string homeDirTmp = get_xdg_user_config_home() + DOT_DIR; homeDir = (char *)homeDirTmp.c_str(); if (stat(homeDir, &s) == -1 || !S_ISDIR(s.st_mode)) mkdir(homeDir, 0755); @@ -742,29 +740,18 @@ void LoadConfigFile() const char* configFile = FindConfigFile("vbam.ini"); OpenPreferences(configFile); } - - if (preferences == NULL) - { - const char* configFile = FindConfigFile("vbam.cfg"); - OpenPreferences(configFile); - } } void SaveConfigFile() { struct stat s; - std::string homeDirTmp = get_xdg_user_config_home() + FILE_SEP + DOT_DIR; + std::string homeDirTmp = get_xdg_user_config_home() + DOT_DIR; homeDir = (char *)homeDirTmp.c_str(); if (stat(homeDir, &s) == -1 || !S_ISDIR(s.st_mode)) mkdir(homeDir, 0755); const char* configFile = FindConfigFile("vbam.ini"); - if (configFile == NULL) - { - configFile = FindConfigFile("vbam.cfg"); - } - if (configFile != NULL) { FILE *f = fopen(configFile, "w"); diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 1abec074..540ec416 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -76,7 +76,7 @@ static void get_config_path(wxPathList& path, bool exists = true) #if defined(__WXGTK__) // XDG spec manual support // ${XDG_CONFIG_HOME:-$HOME/.config}/`appname` - wxString old_config = wxString(getenv("HOME")) + "/.vbam"; + wxString old_config = wxString(getenv("HOME")) + FILE_SEP + ".vbam"; wxString new_config(get_xdg_user_config_home()); if (!wxDirExists(old_config) && wxIsWritable(new_config)) { @@ -88,7 +88,7 @@ static void get_config_path(wxPathList& path, bool exists = true) } else { - // config is in $HOME/.vbam/vbam.conf + // config is in $HOME/.vbam/ add_nonstandard_path(old_config); } #endif @@ -120,11 +120,7 @@ const wxString wxvbamApp::GetPluginsDir() wxString wxvbamApp::GetConfigurationPath() { -#if defined(__WXMSW__) || defined(__APPLE__) wxString config("vbam.ini"); -#else - wxString config("vbam.conf"); -#endif // first check if config files exists in reverse order // (from system paths to more local paths.) if (data_path.empty()) { @@ -251,16 +247,18 @@ bool wxvbamApp::OnInit() wxString confname("vbam.ini"); wxFileName vbamconf(GetConfigurationPath(), confname); // /MIGRATION -// migrate from 'vbam.conf' to 'vbam.ini' to manage a single config +// migrate from 'vbam.{cfg,conf}' to 'vbam.ini' to manage a single config // file for all platforms. #if !defined(__WXMSW__) && !defined(__APPLE__) - wxString oldConf(GetConfigurationPath() + "/vbam.conf"); - wxString newConf(GetConfigurationPath() + "/vbam.ini"); + wxString oldConf(GetConfigurationPath() + FILE_SEP + "vbam.conf"); +#else + wxString oldConf(GetConfigurationPath() + FILE_SEP + "vbam.cfg"); +#endif + wxString newConf(GetConfigurationPath() + FILE_SEP + "vbam.ini"); if (wxFileExists(oldConf)) { wxRenameFile(oldConf, newConf, false); } -#endif // /END_MIGRATION cfg = new wxFileConfig(wxT("vbam"), wxEmptyString, vbamconf.GetFullPath(), @@ -616,7 +614,10 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) wxvbamApp::~wxvbamApp() { if (home != NULL) + { free(home); + home = NULL; + } } MainFrame::MainFrame() From a57e51f699117bd4d7e84362aa21a7935be57b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Thu, 14 Mar 2019 16:12:48 -0300 Subject: [PATCH 14/42] Return non-error code for given command line parameters. --- src/wx/wxvbam.cpp | 32 ++++++++++++++++++++++++++++---- src/wx/wxvbam.h | 3 +++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 540ec416..6a89c9a4 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -421,6 +421,26 @@ bool wxvbamApp::OnInit() return true; } +int wxvbamApp::OnRun() +{ + if (console_mode) + { + // we could check for our own error codes here... + return EXIT_SUCCESS; + } + else + { + return wxApp::OnRun(); + } +} + +bool wxvbamApp::OnCmdLineHelp(wxCmdLineParser& parser) +{ + wxApp::OnCmdLineHelp(parser); + console_mode = true; + return true; +} + void wxvbamApp::OnInitCmdLine(wxCmdLineParser& cl) { wxApp::OnInitCmdLine(cl); @@ -505,7 +525,8 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) s.mb_str()); tack_full_path(lm); wxLogMessage(lm); - return false; + console_mode = true; + return true; } if (cl.Found(wxT("print-cfg-path"))) { @@ -515,7 +536,8 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) wxString lm(_("Configuration is read from, in order:")); tack_full_path(lm); wxLogMessage(lm); - return false; + console_mode = true; + return true; } if (cl.Found(wxT("save-over"), &s)) { @@ -533,7 +555,8 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) tack_full_path(lm, oi); lm.append(_("\n\tbuilt-in")); wxLogMessage(lm); - return false; + console_mode = true; + return true; } if (cl.Found(wxT("f"))) { @@ -567,7 +590,8 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) for (int i = 0; i < ncmds; i++) wxPrintf(wxT("%s (%s)\n"), cmdtab[i].cmd, cmdtab[i].name); - return false; + console_mode = true; + return true; } #if !defined(NO_LINK) && !defined(__WXMSW__) diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 9213410e..37e28271 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -83,6 +83,8 @@ public: { } virtual bool OnInit(); + virtual int OnRun(); + virtual bool OnCmdLineHelp(wxCmdLineParser&); virtual bool UsingWayland() { return using_wayland; } virtual void OnInitCmdLine(wxCmdLineParser&); virtual bool OnCmdLineParsed(wxCmdLineParser&); @@ -140,6 +142,7 @@ public: protected: bool using_wayland; + bool console_mode = false; private: wxPathList config_path; From 6ca59412a83ac669465c803e4675f777312849f2 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 15 Mar 2019 04:44:45 -0700 Subject: [PATCH 15/42] travis: disable mxe pkg key The mxe package server key has been removed from the keyservers, allow apt-key to fail and add `--allow-unauthenticated` to the apt-get options. Signed-off-by: Rafael Kitover --- installdeps | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/installdeps b/installdeps index 6fa82e29..7ce1e9ad 100755 --- a/installdeps +++ b/installdeps @@ -339,7 +339,7 @@ EOF if [ -z "$(apt-cache search '^mxe-source$')" ]; then if [ ! -f "$mxe_apt_sources" ]; then echo "deb https://pkg.mxe.cc/repos/apt $debian_rel main" | sudo -- sh -c "cat > $mxe_apt_sources" - check sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C6BF758A33A3A276 + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C6BF758A33A3A276 || : else error "$mxe_apt_sources exists but mxe packages are not found in apt, either delete it or fix it" fi @@ -349,9 +349,9 @@ EOF for dep in gcc zlib ffmpeg gettext sdl2 sfml openal wxwidgets; do set -- "$@" "mxe-${target}-$dep" done - check sudo apt-get -qq -y update + check sudo apt-get --allow-unauthenticated -qq -y update # native wx-common needed for wxrc executable - check sudo apt-get -qy install build-essential cmake ccache wx-common "$@" + check sudo apt-get --allow-unauthenticated -qy install build-essential cmake ccache wx-common "$@" fi build_instructions From 101fac5910e5c7e37c1172ebac64fc9e76ca0e23 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 15 Mar 2019 19:26:16 -0700 Subject: [PATCH 16/42] travis: try re-enabling binary sanity check On the ubuntu and mac jobs, try re-enabling the `--help` check, it should now work thanks to @denisfa's work on a57e51f6. If this works we also want to use wine for the mingw jobs to do the same. Signed-off-by: Rafael Kitover --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 740e3073..635a8ad5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ matrix: - cd build - cmake .. - make -j2 -# - xvfb-run ./visualboyadvance-m --help + - xvfb-run ./visualboyadvance-m --help cache: directories: - "$HOME/.ccache" @@ -73,7 +73,7 @@ matrix: - cd build - cmake .. - make -j2 -# - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help + - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help cache: directories: - "$HOME/.ccache" From 2142a46dd51bce3993c3a5dcc0401f369e5e1621 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Sat, 16 Mar 2019 03:45:36 -0700 Subject: [PATCH 17/42] Revert "travis: try re-enabling binary check" This reverts commit 101fac5910e5c7e37c1172ebac64fc9e76ca0e23. Both ubuntu and mac jobs timeout when trying to call `--help`. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 635a8ad5..740e3073 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ matrix: - cd build - cmake .. - make -j2 - - xvfb-run ./visualboyadvance-m --help +# - xvfb-run ./visualboyadvance-m --help cache: directories: - "$HOME/.ccache" @@ -73,7 +73,7 @@ matrix: - cd build - cmake .. - make -j2 - - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help +# - ./visualboyadvance-m.app/Contents/MacOS/visualboyadvance-m --help cache: directories: - "$HOME/.ccache" From a1f0c34acec3e0483570b927ee921b5a37c8fc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Mon, 18 Mar 2019 05:08:53 -0300 Subject: [PATCH 18/42] XDG followup work #94 * Apply save order for save states and batteries. The order for save state/battery: 1. StateDir / BatteryDir; 2. The path of the current loaded game; 3. XDG Base Dir fallback. * Use XDG Base Dir fallback to save screenshots and recordings. * Apply search order for all dirs except recording (not implemented yet) of SDL port. The order for battery/save state/screenshot is: 1. StateDir/BatteryDir/ScreenshotDir; 2. The path of the current loaded game; 3. XDG Base Dir (or equivalent) fallback. * Refactor code. * Fix freeing and setting pointer to NULL of SDL port. --- src/sdl/SDL.cpp | 180 ++++++++++++++++++++++++++-------------------- src/wx/panel.cpp | 12 ++-- src/wx/wxvbam.cpp | 15 +++- src/wx/wxvbam.h | 2 + 4 files changed, 126 insertions(+), 83 deletions(-) diff --git a/src/sdl/SDL.cpp b/src/sdl/SDL.cpp index 2ee65899..9697ae44 100644 --- a/src/sdl/SDL.cpp +++ b/src/sdl/SDL.cpp @@ -64,14 +64,22 @@ #include "inputSDL.h" #include "text.h" +// from: https://stackoverflow.com/questions/7608714/why-is-my-pointer-not-null-after-free +#define freeSafe(ptr) free(ptr); ptr = NULL; + #ifndef _WIN32 #include #define GETCWD getcwd #else // _WIN32 #include +#include #define GETCWD _getcwd #define snprintf sprintf #define stat _stat +#define access _access +#ifndef W_OK + #define W_OK 2 +#endif #define mkdir(X,Y) (_mkdir(X)) // from: https://www.linuxquestions.org/questions/programming-9/porting-to-win32-429334/ #ifndef S_ISDIR @@ -208,7 +216,8 @@ int sdlMirroringEnable = 1; void systemConsoleMessage(const char*); char* home; -char homeDataDir[2048]; +char homeConfigDir[1024]; +char homeDataDir[1024]; char screenMessageBuffer[21]; uint32_t screenMessageTime = 0; @@ -253,7 +262,7 @@ void StartLirc(void) fprintf(stdout, "Success\n"); //read the config file char LIRCConfigLoc[2048]; - sprintf(LIRCConfigLoc, "%s/%s", homeDataDir, "lircrc"); + sprintf(LIRCConfigLoc, "%s%c%s", homeConfigDir, FILE_SEP, "lircrc"); fprintf(stdout, "LIRC Config file:"); if (lirc_readconfig(LIRCConfigLoc, &LIRCConfigInfo, NULL) == 0) { //check vbam dir for lircrc @@ -291,59 +300,47 @@ void StopLirc(void) bool sdlCheckDirectory(const char* dir) { - bool res = false; - - if (!dir || !dir[0]) { - return false; - } - struct stat buf; - int len = strlen(dir); + if (!dir || !dir[0]) + return false; - char* p = (char*)dir + len - 1; - - while (p != dir && (*p == '/' || *p == '\\')) { - *p = 0; - p--; + if (stat(dir, &buf) == 0) + { + if (!(buf.st_mode & S_IFDIR)) + { + fprintf(stderr, "Error: %s is not a directory\n", dir); + return false; + } + return true; } - - if (stat(dir, &buf) == 0) { - if (!(buf.st_mode & S_IFDIR)) { - fprintf(stderr, "Error: %s is not a directory\n", dir); - } - res = true; - } else { - fprintf(stderr, "Error: %s does not exist\n", dir); + else + { + fprintf(stderr, "Error: %s does not exist\n", dir); + return false; } - - return res; } char* sdlGetFilename(char* name) { - static char filebuffer[2048]; - - int len = strlen(name); - - char* p = name + len - 1; - - while (true) { - if (*p == '/' || *p == '\\') { - p++; - break; - } - len--; - p--; - if (len == 0) - break; - } - - if (len == 0) - strcpy(filebuffer, name); + char path[1024] = ""; // avoid warning about uninitialised value + char *filename = strrchr(name, FILE_SEP); + if (filename) + strncpy(path, filename + 1, strlen(filename)); else - strcpy(filebuffer, p); - return filebuffer; + sprintf(path, "%s", name); + return strdup(path); +} + +char* sdlGetFilePath(char* name) +{ + char path[1024] = ""; // avoid warning about uninitialised value + char *filename = strrchr(name, FILE_SEP); + if (filename) + strncpy(path, name, strlen(name) - strlen(filename)); + else + sprintf(path, "%c%c", '.', FILE_SEP); + return strdup(path); } FILE* sdlFindFile(const char* name) @@ -661,15 +658,18 @@ static int sdlCalculateShift(uint32_t mask) static char* sdlStateName(int num) { static char stateName[2048]; + char *gameDir = sdlGetFilePath(filename); + char *gameFile = sdlGetFilename(filename); if (saveDir) - sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), - num + 1); - else if (homeDir) - sprintf(stateName, "%s/%s%d.sgm", homeDataDir, sdlGetFilename(filename), num + 1); + sprintf(stateName, "%s%c%s%d.sgm", saveDir, FILE_SEP, gameFile, num + 1); + else if (access(gameDir, W_OK) == 0) + sprintf(stateName, "%s%c%s%d.sgm", gameDir, FILE_SEP, gameFile, num + 1); else - sprintf(stateName, "%s%d.sgm", filename, num + 1); + sprintf(stateName, "%s%c%s%d.sgm", homeDataDir, FILE_SEP, gameFile, num + 1); + freeSafe(gameDir); + freeSafe(gameFile); return stateName; } @@ -760,37 +760,46 @@ void sdlWriteBackupStateExchange(int from, int to, int backup) void sdlWriteBattery() { - char buffer[1048]; + char buffer[2048]; + char *gameDir = sdlGetFilePath(filename); + char *gameFile = sdlGetFilename(filename); if (batteryDir) - sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); - else if (homeDir) - sprintf(buffer, "%s/%s.sav", homeDataDir, sdlGetFilename(filename)); + sprintf(buffer, "%s%c%s.sav", batteryDir, FILE_SEP, gameFile); + else if (access(gameDir, W_OK) == 0) + sprintf(buffer, "%s%c%s.sav", gameDir, FILE_SEP, gameFile); else - sprintf(buffer, "%s.sav", filename); + sprintf(buffer, "%s%c%s.sav", homeDataDir, FILE_SEP, gameFile); - emulator.emuWriteBattery(buffer); + bool result = emulator.emuWriteBattery(buffer); - systemScreenMessage("Wrote battery"); + if (result) + systemMessage(0, "Wrote battery '%s'", buffer); + + freeSafe(gameFile); + freeSafe(gameDir); } void sdlReadBattery() { - char buffer[1048]; + char buffer[2048]; + char *gameDir = sdlGetFilePath(filename); + char *gameFile = sdlGetFilename(filename); if (batteryDir) - sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); - else if (homeDir) - sprintf(buffer, "%s/%s.sav", homeDataDir, sdlGetFilename(filename)); + sprintf(buffer, "%s%c%s.sav", batteryDir, FILE_SEP, gameFile); + else if (access(gameDir, W_OK) == 0) + sprintf(buffer, "%s%c%s.sav", gameDir, FILE_SEP, gameFile); else - sprintf(buffer, "%s.sav", filename); + sprintf(buffer, "%s%c%s.sav", homeDataDir, FILE_SEP, gameFile); - bool res = false; + bool result = emulator.emuReadBattery(buffer); - res = emulator.emuReadBattery(buffer); + if (result) + systemMessage(0, "Loaded battery '%s'", buffer); - if (res) - systemScreenMessage("Loaded battery"); + freeSafe(gameFile); + freeSafe(gameDir); } void sdlReadDesktopVideoMode() @@ -1644,6 +1653,14 @@ void handleRewinds() } } +void SetHomeConfigDir() +{ + sprintf(homeConfigDir, "%s%s", get_xdg_user_config_home().c_str(), DOT_DIR); + struct stat s; + if (stat(homeDataDir, &s) == -1 || !S_ISDIR(s.st_mode)) + mkdir(homeDataDir, 0755); +} + void SetHomeDataDir() { sprintf(homeDataDir, "%s%s", get_xdg_user_data_home().c_str(), DOT_DIR); @@ -1658,6 +1675,7 @@ int main(int argc, char** argv) home = argv[0]; SetHome(home); + SetHomeConfigDir(); SetHomeDataDir(); frameSkip = 2; @@ -2224,27 +2242,35 @@ void system10Frames(int rate) void systemScreenCapture(int a) { char buffer[2048]; + bool result = false; + char *gameDir = sdlGetFilePath(filename); + char *gameFile = sdlGetFilename(filename); if (captureFormat) { if (screenShotDir) - sprintf(buffer, "%s/%s%02d.bmp", screenShotDir, sdlGetFilename(filename), a); - else if (homeDir) - sprintf(buffer, "%s/%s%02d.bmp", homeDataDir, sdlGetFilename(filename), a); + sprintf(buffer, "%s%c%s%02d.bmp", screenShotDir, FILE_SEP, gameFile, a); + else if (access(gameDir, W_OK) == 0) + sprintf(buffer, "%s%c%s%02d.bmp", gameDir, FILE_SEP, gameFile, a); else - sprintf(buffer, "%s%02d.bmp", filename, a); + sprintf(buffer, "%s%c%s%02d.bmp", homeDataDir, FILE_SEP, gameFile, a); - emulator.emuWriteBMP(buffer); + result = emulator.emuWriteBMP(buffer); } else { if (screenShotDir) - sprintf(buffer, "%s/%s%02d.png", screenShotDir, sdlGetFilename(filename), a); - else if (homeDir) - sprintf(buffer, "%s/%s%02d.png", homeDataDir, sdlGetFilename(filename), a); + sprintf(buffer, "%s%c%s%02d.png", screenShotDir, FILE_SEP, gameFile, a); + else if (access(gameDir, W_OK) == 0) + sprintf(buffer, "%s%c%s%02d.png", gameDir, FILE_SEP, gameFile, a); else - sprintf(buffer, "%s%02d.png", filename, a); - emulator.emuWritePNG(buffer); + sprintf(buffer, "%s%c%s%02d.png", homeDataDir, FILE_SEP, gameFile, a); + + result = emulator.emuWritePNG(buffer); } - systemScreenMessage("Screen capture"); + if (result) + systemScreenMessage("Screen capture"); + + freeSafe(gameFile); + freeSafe(gameDir); } void systemSaveOldest() diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index 268037fd..edc35a0f 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -461,6 +461,10 @@ void GameArea::recompute_dirs() batdir = wxGetApp().GetAbsolutePath(gopts.battery_dir); } + if (!wxIsWritable(batdir)) { + batdir = wxGetApp().GetDataDir(); + } + statedir = gopts.state_dir; if (!statedir.size()) { @@ -469,11 +473,9 @@ void GameArea::recompute_dirs() statedir = wxGetApp().GetAbsolutePath(gopts.state_dir); } - if (!wxIsWritable(batdir)) - batdir = wxGetApp().GetConfigurationPath(); - - if (!wxIsWritable(statedir)) - statedir = wxGetApp().GetConfigurationPath(); + if (!wxIsWritable(statedir)) { + statedir = wxGetApp().GetDataDir(); + } } void GameArea::UnloadGame(bool destruct) diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 6a89c9a4..8e874011 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -636,6 +636,16 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl) return true; } +wxString wxvbamApp::GetConfigDir() +{ + return GetAbsolutePath(get_xdg_user_config_home() + DOT_DIR); +} + +wxString wxvbamApp::GetDataDir() +{ + return GetAbsolutePath(get_xdg_user_data_home() + DOT_DIR); +} + wxvbamApp::~wxvbamApp() { if (home != NULL) { @@ -774,7 +784,10 @@ wxString MainFrame::GetGamePath(wxString path) game_path = wxFileName::GetCwd(); if (!wxIsWritable(game_path)) - game_path = wxGetApp().GetConfigurationPath(); + { + game_path = wxGetApp().GetAbsolutePath(get_xdg_user_data_home() + DOT_DIR); + wxFileName::Mkdir(game_path, 0777, wxPATH_MKDIR_FULL); + } return game_path; } diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 37e28271..1222356a 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -88,6 +88,8 @@ public: virtual bool UsingWayland() { return using_wayland; } virtual void OnInitCmdLine(wxCmdLineParser&); virtual bool OnCmdLineParsed(wxCmdLineParser&); + virtual wxString GetConfigDir(); + virtual wxString GetDataDir(); wxString GetConfigurationPath(); const wxString GetPluginsDir(); wxString GetAbsolutePath(wxString path); From c714ff825a93cc1e5e76c6aaee76d0cb4f427601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ed=C3=AAnis=20Freindorfer=20Azevedo?= Date: Tue, 19 Mar 2019 00:38:42 -0300 Subject: [PATCH 19/42] fix problems of command line parameters * Fix return code for wrong command line parameters. * Update return code for incorrect command line option on WX port. --- src/wx/wxvbam.cpp | 13 ++++++++++++- src/wx/wxvbam.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 8e874011..850bf0f6 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -206,6 +206,9 @@ bool wxvbamApp::OnInit() if (!wxApp::OnInit()) return false; + if (console_mode) + return true; + // prepare for loading xrc files wxXmlResource* xr = wxXmlResource::Get(); // note: if linking statically, next 2 pull in lot of unused code @@ -426,7 +429,7 @@ int wxvbamApp::OnRun() if (console_mode) { // we could check for our own error codes here... - return EXIT_SUCCESS; + return console_status; } else { @@ -441,6 +444,14 @@ bool wxvbamApp::OnCmdLineHelp(wxCmdLineParser& parser) return true; } +bool wxvbamApp::OnCmdLineError(wxCmdLineParser& parser) +{ + wxApp::OnCmdLineError(parser); + console_mode = true; + console_status = 1; + return true; +} + void wxvbamApp::OnInitCmdLine(wxCmdLineParser& cl) { wxApp::OnInitCmdLine(cl); diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 1222356a..b4004f0c 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -85,6 +85,7 @@ public: virtual bool OnInit(); virtual int OnRun(); virtual bool OnCmdLineHelp(wxCmdLineParser&); + virtual bool OnCmdLineError(wxCmdLineParser&); virtual bool UsingWayland() { return using_wayland; } virtual void OnInitCmdLine(wxCmdLineParser&); virtual bool OnCmdLineParsed(wxCmdLineParser&); @@ -145,6 +146,7 @@ public: protected: bool using_wayland; bool console_mode = false; + int console_status = 0; private: wxPathList config_path; From 3da07f40833f0946cd2de77ebe4fb2e18fa208de Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Tue, 19 Mar 2019 18:41:25 -0700 Subject: [PATCH 20/42] detect llvm toolchain utilities #392 Use `clang -print-prog-path=` to find the locations of llvm toolchain utilities such as `llvm-ranlib` and set the appropriate cmake variables to the resultant paths. Signed-off-by: Rafael Kitover --- CMakeLists.txt | 6 +++++- cmake/LLVMToolchain.cmake | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 cmake/LLVMToolchain.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8073871a..cd4e26b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,7 +359,11 @@ endif() include(ProcessorCount) ProcessorCount(num_cpus) -# Compiler flags +# Compiler stuff + +if(CMAKE_C_COMPILER_ID STREQUAL Clang AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) + include(LLVMToolchain) +endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) set(LTO_FLAGS "") diff --git a/cmake/LLVMToolchain.cmake b/cmake/LLVMToolchain.cmake new file mode 100644 index 00000000..0953f968 --- /dev/null +++ b/cmake/LLVMToolchain.cmake @@ -0,0 +1,32 @@ +function(use_llvm_toolchain) + if(CMAKE_C_COMPILER_ID STREQUAL Clang) + set(compiler "${CMAKE_C_COMPILER}") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set(compiler "${CMAKE_CXX_COMPILER}") + else() + return() + endif() + + foreach(tool ar ranlib ld nm objdump as) + execute_process( + COMMAND "${compiler}" -print-prog-name=llvm-${tool} + OUTPUT_VARIABLE prog_path + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(prog_path MATCHES "^/") + if(tool STREQUAL ld) + set(tool linker) + elseif(tool STREQUAL as) + set(tool asm_compiler) + endif() + + string(TOUPPER ${tool} utool) + + set(CMAKE_${utool} "${prog_path}" PARENT_SCOPE) + set(CMAKE_${utool} "${prog_path}" CACHE FILEPATH "${tool}" FORCE) + endif() + endforeach() +endfunction() + +use_llvm_toolchain() From f1ecd7c3225aa583c54abcbd4bcc29f31a506a97 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Thu, 21 Mar 2019 16:01:46 -0700 Subject: [PATCH 21/42] auto deps for visual studio, take 1 Use vcpkg to build deps when Visual Studio on Windows is detected, this only happens on first build, but does take a while because things like wxWidgets need to be built. Building from the developer command line is also supported. I considered making a pre-built tarball available, but the resulting files are just too big for this to be practical. Make the necessary cmake code changes for this to work and to use the vcpkg packages, which work just like on linux or have other cmake glue code available. To do this, we make vcpkg a submodule, use git to checkout all submodules, then just build and use the `vcpkg.exe`. Then we set the CMAKE_TOOLCHAIN_FILE to the vcpkg toolchain and also include it directly, why this is necessary I don't know, without it it doesn't work in the IDE but does on the command line. All of this requires no vcpkg integration with either the user or the project. A user-wide `ENV{VCPKG_ROOT}` is also supported. Fix the dynamic arrays in the GBA core, MSVC follows the C++ standard on this and gcc does not. TODO: add the necessary gcc flags to make this an error in cmake. Use `wxArrayString` instead of `std::vector` in `src/wx/strutils.cpp` which is used in options parsing. This was necessary because of a bizarre linker error with wxWidgets when using Visual Studio: https://trac.wxwidgets.org/ticket/10884#comment:46 In `src/wx/panel.cpp` make sure the unimplemented D3D renderer code does not get compiled if it's actually `OFF`. Also fix the new spacer code for the drawing panel to not combine `wxEXPAND` with `wxALIGN_CENTER`, which is an error on wxWidgets 3.1.2, which is what vcpkg uses. The drawing panel seems to be automatically stretched to the max size automatically anyway. TODO: if all of this works, we'll need an Appveyor set up for visual studio. Signed-off-by: Rafael Kitover --- .gitignore | 2 + .gitmodules | 3 + CMakeLists.txt | 93 +++---- CMakeSettings.json | 53 ++++ README.md | 15 +- cmake/Architecture.cmake | 24 ++ cmake/Win32Deps.cmake | 62 +++++ src/gba/remote.cpp | 13 +- src/wx/CMakeLists.txt | 543 ++++++++++++++++++++++----------------- src/wx/panel.cpp | 4 +- src/wx/strutils.cpp | 24 +- src/wx/strutils.h | 8 +- vcpkg | 1 + 13 files changed, 525 insertions(+), 320 deletions(-) create mode 100644 CMakeSettings.json create mode 100644 cmake/Architecture.cmake create mode 100644 cmake/Win32Deps.cmake create mode 160000 vcpkg diff --git a/.gitignore b/.gitignore index 76c99d48..9c6e4e48 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,9 @@ src/wx/cmdtab.cpp src/wx/wxvbam.xrs build/* build32/* +vsbuild/* dependencies/* +vcpkg/* .vs/* *.o *.so diff --git a/.gitmodules b/.gitmodules index ff35d490..048fc2d6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "dependencies"] path = dependencies url = https://github.com/visualboyadvance-m/dependencies.git +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/Microsoft/vcpkg.git diff --git a/CMakeLists.txt b/CMakeLists.txt index cd4e26b8..5275d009 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,17 @@ +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) # link to full path of libs + cmake_policy(SET CMP0005 NEW) # escapes in add_definitions +endif() + +option(ENABLE_VCPKG "Use dependencies for Visual Studio from vcpkg" ON) + +set(NLS_DEFAULT ON) + +# get win32 deps before project declaration, because toolchain is set for vcpkg +set(VCPKG_DEPS zlib libpng SDL2 SFML gettext wxWidgets) + +include(${CMAKE_SOURCE_DIR}/cmake/Win32Deps.cmake) + project(VBA-M C CXX) cmake_minimum_required(VERSION 2.8.12) @@ -12,19 +26,13 @@ endif() set(ALL_TARGETS fex visualboyadvance-m vbamcore vbam) -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) # link to full path of libs - cmake_policy(SET CMP0005 NEW) # escapes in add_definitions -endif() - -set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) #Output all binaries at top level set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) option(ENABLE_SDL "Build the SDL port" OFF) option(ENABLE_WX "Build the wxWidgets port" ON) option(ENABLE_DEBUGGER "Enable the debugger" ON) -option(ENABLE_NLS "Enable translations" ON) option(ENABLE_ASAN "Enable -fsanitize=