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] 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);