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.
This commit is contained in:
Edênis Freindorfer Azevedo 2019-03-18 05:08:53 -03:00 committed by Rafael Kitover
parent 2142a46dd5
commit a1f0c34ace
4 changed files with 126 additions and 83 deletions

View File

@ -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 <unistd.h>
#define GETCWD getcwd
#else // _WIN32
#include <direct.h>
#include <io.h>
#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()

View File

@ -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)

View File

@ -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;
}

View File

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