mirror of https://github.com/mgba-emu/mgba.git
Core: Handle relative paths for saves, screenshots, etc consistently (fixes #2826)
This commit is contained in:
parent
cd0b5193cb
commit
fc35395ab8
1
CHANGES
1
CHANGES
|
@ -28,6 +28,7 @@ Other fixes:
|
||||||
- Scripting: Fix receiving packets for client sockets
|
- Scripting: Fix receiving packets for client sockets
|
||||||
- Scripting: Fix empty receive calls returning unknown error on Windows
|
- Scripting: Fix empty receive calls returning unknown error on Windows
|
||||||
Misc:
|
Misc:
|
||||||
|
- Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826)
|
||||||
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
|
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
|
||||||
- GBA: Improve detection of valid ELF ROMs
|
- GBA: Improve detection of valid ELF ROMs
|
||||||
- Qt: Include wayland QPA in AppImage (fixes mgba.io/i/2796)
|
- Qt: Include wayland QPA in AppImage (fixes mgba.io/i/2796)
|
||||||
|
|
|
@ -338,6 +338,8 @@ find_function(popcount32)
|
||||||
find_function(futimens)
|
find_function(futimens)
|
||||||
find_function(futimes)
|
find_function(futimes)
|
||||||
|
|
||||||
|
find_function(realpath)
|
||||||
|
|
||||||
if(ANDROID AND ANDROID_NDK_MAJOR GREATER 13)
|
if(ANDROID AND ANDROID_NDK_MAJOR GREATER 13)
|
||||||
find_function(localtime_r)
|
find_function(localtime_r)
|
||||||
set(HAVE_STRTOF_L ON)
|
set(HAVE_STRTOF_L ON)
|
||||||
|
|
|
@ -100,6 +100,9 @@ struct VFile* VFileFromFILE(FILE* file);
|
||||||
|
|
||||||
void separatePath(const char* path, char* dirname, char* basename, char* extension);
|
void separatePath(const char* path, char* dirname, char* basename, char* extension);
|
||||||
|
|
||||||
|
bool isAbsolute(const char* path);
|
||||||
|
void makeAbsolute(const char* path, const char* base, char* out);
|
||||||
|
|
||||||
struct VFile* VDirFindFirst(struct VDir* dir, bool (*filter)(struct VFile*));
|
struct VFile* VDirFindFirst(struct VDir* dir, bool (*filter)(struct VFile*));
|
||||||
struct VFile* VDirFindNextAvailable(struct VDir*, const char* basename, const char* infix, const char* suffix, int mode);
|
struct VFile* VDirFindNextAvailable(struct VDir*, const char* basename, const char* infix, const char* suffix, int mode);
|
||||||
|
|
||||||
|
|
|
@ -116,10 +116,15 @@ struct VFile* mDirectorySetOpenSuffix(struct mDirectorySet* dirs, struct VDir* d
|
||||||
}
|
}
|
||||||
|
|
||||||
void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptions* opts) {
|
void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptions* opts) {
|
||||||
|
char abspath[PATH_MAX + 1];
|
||||||
|
char configDir[PATH_MAX + 1];
|
||||||
|
mCoreConfigDirectory(configDir, sizeof(configDir));
|
||||||
|
|
||||||
if (opts->savegamePath) {
|
if (opts->savegamePath) {
|
||||||
struct VDir* dir = VDirOpen(opts->savegamePath);
|
makeAbsolute(opts->savegamePath, configDir, abspath);
|
||||||
if (!dir && VDirCreate(opts->savegamePath)) {
|
struct VDir* dir = VDirOpen(abspath);
|
||||||
dir = VDirOpen(opts->savegamePath);
|
if (!dir && VDirCreate(abspath)) {
|
||||||
|
dir = VDirOpen(abspath);
|
||||||
}
|
}
|
||||||
if (dir) {
|
if (dir) {
|
||||||
if (dirs->save && dirs->save != dirs->base) {
|
if (dirs->save && dirs->save != dirs->base) {
|
||||||
|
@ -130,9 +135,10 @@ void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptio
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->savestatePath) {
|
if (opts->savestatePath) {
|
||||||
struct VDir* dir = VDirOpen(opts->savestatePath);
|
makeAbsolute(opts->savestatePath, configDir, abspath);
|
||||||
if (!dir && VDirCreate(opts->savestatePath)) {
|
struct VDir* dir = VDirOpen(abspath);
|
||||||
dir = VDirOpen(opts->savestatePath);
|
if (!dir && VDirCreate(abspath)) {
|
||||||
|
dir = VDirOpen(abspath);
|
||||||
}
|
}
|
||||||
if (dir) {
|
if (dir) {
|
||||||
if (dirs->state && dirs->state != dirs->base) {
|
if (dirs->state && dirs->state != dirs->base) {
|
||||||
|
@ -143,9 +149,10 @@ void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptio
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->screenshotPath) {
|
if (opts->screenshotPath) {
|
||||||
struct VDir* dir = VDirOpen(opts->screenshotPath);
|
makeAbsolute(opts->screenshotPath, configDir, abspath);
|
||||||
if (!dir && VDirCreate(opts->screenshotPath)) {
|
struct VDir* dir = VDirOpen(abspath);
|
||||||
dir = VDirOpen(opts->screenshotPath);
|
if (!dir && VDirCreate(abspath)) {
|
||||||
|
dir = VDirOpen(abspath);
|
||||||
}
|
}
|
||||||
if (dir) {
|
if (dir) {
|
||||||
if (dirs->screenshot && dirs->screenshot != dirs->base) {
|
if (dirs->screenshot && dirs->screenshot != dirs->base) {
|
||||||
|
@ -156,9 +163,10 @@ void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptio
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->patchPath) {
|
if (opts->patchPath) {
|
||||||
struct VDir* dir = VDirOpen(opts->patchPath);
|
makeAbsolute(opts->patchPath, configDir, abspath);
|
||||||
if (!dir && VDirCreate(opts->patchPath)) {
|
struct VDir* dir = VDirOpen(abspath);
|
||||||
dir = VDirOpen(opts->patchPath);
|
if (!dir && VDirCreate(abspath)) {
|
||||||
|
dir = VDirOpen(abspath);
|
||||||
}
|
}
|
||||||
if (dir) {
|
if (dir) {
|
||||||
if (dirs->patch && dirs->patch != dirs->base) {
|
if (dirs->patch && dirs->patch != dirs->base) {
|
||||||
|
@ -169,9 +177,10 @@ void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptio
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->cheatsPath) {
|
if (opts->cheatsPath) {
|
||||||
struct VDir* dir = VDirOpen(opts->cheatsPath);
|
makeAbsolute(opts->cheatsPath, configDir, abspath);
|
||||||
if (!dir && VDirCreate(opts->cheatsPath)) {
|
struct VDir* dir = VDirOpen(abspath);
|
||||||
dir = VDirOpen(opts->cheatsPath);
|
if (!dir && VDirCreate(abspath)) {
|
||||||
|
dir = VDirOpen(abspath);
|
||||||
}
|
}
|
||||||
if (dir) {
|
if (dir) {
|
||||||
if (dirs->cheats && dirs->cheats != dirs->base) {
|
if (dirs->cheats && dirs->cheats != dirs->base) {
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
#ifdef __3DS__
|
#ifdef __3DS__
|
||||||
#include <mgba-util/platform/3ds/3ds-vfs.h>
|
#include <mgba-util/platform/3ds/3ds-vfs.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct VFile* VFileOpen(const char* path, int flags) {
|
struct VFile* VFileOpen(const char* path, int flags) {
|
||||||
#ifdef USE_VFS_FILE
|
#ifdef USE_VFS_FILE
|
||||||
|
@ -207,6 +211,41 @@ void separatePath(const char* path, char* dirname, char* basename, char* extensi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isAbsolute(const char* path) {
|
||||||
|
// XXX: Is this robust?
|
||||||
|
#ifdef _WIN32
|
||||||
|
WCHAR wpath[PATH_MAX];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX);
|
||||||
|
return !PathIsRelativeW(wpath);
|
||||||
|
#else
|
||||||
|
return path[0] == '/';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeAbsolute(const char* path, const char* base, char* out) {
|
||||||
|
if (isAbsolute(path)) {
|
||||||
|
strncpy(out, path, PATH_MAX);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
snprintf(buf, sizeof(buf), "%s" PATH_SEP "%s", base, path);
|
||||||
|
#ifdef _WIN32
|
||||||
|
WCHAR wbuf[PATH_MAX];
|
||||||
|
WCHAR wout[PATH_MAX];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, PATH_MAX);
|
||||||
|
if (GetFullPathNameW(wbuf, PATH_MAX, wout, NULL)) {
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wout, -1, out, PATH_MAX, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_REALPATH)
|
||||||
|
if (realpath(buf, out)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
strncpy(out, buf, PATH_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
struct VFile* VDirFindFirst(struct VDir* dir, bool (*filter)(struct VFile*)) {
|
struct VFile* VDirFindFirst(struct VDir* dir, bool (*filter)(struct VFile*)) {
|
||||||
dir->rewind(dir);
|
dir->rewind(dir);
|
||||||
struct VDirEntry* dirent = dir->listNext(dir);
|
struct VDirEntry* dirent = dir->listNext(dir);
|
||||||
|
|
Loading…
Reference in New Issue