diff --git a/src/filesystem/filesystem.c b/src/filesystem/filesystem.c index cd523b81..ecfe8e5b 100644 --- a/src/filesystem/filesystem.c +++ b/src/filesystem/filesystem.c @@ -1,14 +1,20 @@ #include "filesystem.h" #include "../util.h" #include +#include #ifdef __APPLE__ #include #endif +static FilesystemState state; + void lovrFilesystemInit(const char* arg0) { if (!PHYSFS_init(arg0)) { error("Could not initialize filesystem: %s", PHYSFS_getLastError()); } + + state.gameSource = NULL; + state.identity = NULL; } void lovrFilesystemDestroy() { @@ -19,16 +25,38 @@ int lovrFilesystemExists(const char* path) { return PHYSFS_exists(path); } -const char* lovrFilesystemGetExecutablePath() { +int lovrFilesystemGetExecutablePath(char* dest, unsigned int size) { #ifdef __APPLE__ - char* path = malloc(1024); - uint32_t size = sizeof(path); - if (_NSGetExecutablePath(path, &size) == 0) { - return path; + if (_NSGetExecutablePath(dest, &size) == 0) { + return 0; } #endif - return NULL; + return 1; +} + +const char* lovrFilesystemGetIdentity() { + return state.identity; +} + +const char* lovrFilesystemGetRealDirectory(const char* path) { + if (!PHYSFS_isInit()) { + return NULL; + } + + return PHYSFS_getRealDir(path); +} + +const char* lovrFilesystemGetSource() { + return state.gameSource; +} + +const char* lovrFilesystemGetUserDirectory() { + if (!PHYSFS_isInit()) { + return NULL; + } + + return PHYSFS_getUserDir(); } int lovrFilesystemIsDirectory(const char* path) { @@ -40,6 +68,9 @@ int lovrFilesystemIsFile(const char* path) { } void* lovrFilesystemRead(const char* path, int* bytesRead) { + if (!PHYSFS_isInit()) { + return NULL; + } // Open file PHYSFS_file* handle = PHYSFS_openRead(path); @@ -72,6 +103,44 @@ void* lovrFilesystemRead(const char* path, int* bytesRead) { return data; } -int lovrFilesystemSetSource(const char* source) { - return PHYSFS_mount(source, NULL, 0); +int lovrFilesystemSetIdentity(const char* identity) { + state.identity = identity; + + // Unmount old write directory + if (state.savePathFull && state.savePathRelative) { + PHYSFS_removeFromSearchPath(state.savePathRelative); + } else { + state.savePathRelative = malloc(LOVR_PATH_MAX); + state.savePathFull = malloc(LOVR_PATH_MAX); + } + + // Set new write directory +#ifdef __APPLE__ + const char* userDir = PHYSFS_getUserDir(); + PHYSFS_setWriteDir(userDir); + + snprintf(state.savePathRelative, LOVR_PATH_MAX, "Library/Application Support/LOVR/%s", identity); + PHYSFS_mkdir(state.savePathRelative); + + snprintf(state.savePathFull, LOVR_PATH_MAX, "%s%s", userDir, state.savePathRelative); + if (PHYSFS_setWriteDir(state.savePathFull)) { + PHYSFS_mount(state.savePathFull, NULL, 0); + return 0; + } +#endif + + return 1; +} + +int lovrFilesystemSetSource(const char* source) { + if (state.gameSource) { + return 1; + } + + if (PHYSFS_mount(source, NULL, 0)) { + state.gameSource = source; + return 0; + } + + return 1; } diff --git a/src/filesystem/filesystem.h b/src/filesystem/filesystem.h index ef9c494d..69071d65 100644 --- a/src/filesystem/filesystem.h +++ b/src/filesystem/filesystem.h @@ -1,8 +1,27 @@ +#ifndef LOVR_FILESYSTEM_TYPES +#define LOVR_FILESYSTEM_TYPES + +#define LOVR_PATH_MAX 1024 + +typedef struct { + const char* gameSource; + const char* identity; + char* savePathRelative; + char* savePathFull; +} FilesystemState; + +#endif + void lovrFilesystemInit(const char* arg0); void lovrFilesystemDestroy(); int lovrFilesystemExists(const char* path); -const char* lovrFilesystemGetExecutablePath(); +int lovrFilesystemGetExecutablePath(char* dest, unsigned int size); +const char* lovrFilesystemGetIdentity(); +const char* lovrFilesystemGetRealDirectory(const char* path); +const char* lovrFilesystemGetSource(); +const char* lovrFilesystemGetUserDirectory(); int lovrFilesystemIsDirectory(const char* path); int lovrFilesystemIsFile(const char* path); void* lovrFilesystemRead(const char* path, int* bytesRead); +int lovrFilesystemSetIdentity(const char* identity); int lovrFilesystemSetSource(const char* source); diff --git a/src/lovr.c b/src/lovr.c index e5e94f4e..4d19306e 100644 --- a/src/lovr.c +++ b/src/lovr.c @@ -67,6 +67,8 @@ void lovrInit(lua_State* L, int argc, char** argv) { " end " "end " + "lovr.filesystem.setIdentity(conf.identity or 'default') " + "function lovr.run() " " if lovr.load then lovr.load() end " " while true do " diff --git a/src/lovr/filesystem.c b/src/lovr/filesystem.c index 8b26eb2c..7c5b3089 100644 --- a/src/lovr/filesystem.c +++ b/src/lovr/filesystem.c @@ -51,9 +51,14 @@ const luaL_Reg lovrFilesystem[] = { { "init", l_lovrFilesystemInitialize }, { "exists", l_lovrFilesystemExists }, { "getExecutablePath", l_lovrFilesystemGetExecutablePath }, + { "getIdentity", l_lovrFilesystemGetIdentity }, + { "getRealDirectory", l_lovrFilesystemGetRealDirectory }, + { "getSource", l_lovrFilesystemGetSource }, + { "getUserDirectory", l_lovrFilesystemGetUserDirectory }, { "isDirectory", l_lovrFilesystemIsDirectory }, { "isFile", l_lovrFilesystemIsFile }, { "read", l_lovrFilesystemRead }, + { "setIdentity", l_lovrFilesystemSetIdentity }, { "setSource", l_lovrFilesystemSetSource }, { NULL, NULL } }; @@ -88,10 +93,22 @@ int l_lovrFilesystemExists(lua_State* L) { } int l_lovrFilesystemGetExecutablePath(lua_State* L) { - const char* exePath = lovrFilesystemGetExecutablePath(); + char buffer[1024]; - if (exePath) { - lua_pushstring(L, exePath); + if (lovrFilesystemGetExecutablePath(buffer, sizeof(buffer))) { + lua_pushnil(L); + } else { + lua_pushstring(L, buffer); + } + + return 1; +} + +int l_lovrFilesystemGetIdentity(lua_State* L) { + const char* identity = lovrFilesystemGetIdentity(); + + if (identity) { + lua_pushstring(L, identity); } else { lua_pushnil(L); } @@ -99,6 +116,36 @@ int l_lovrFilesystemGetExecutablePath(lua_State* L) { return 1; } +int l_lovrFilesystemGetRealDirectory(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + const char* realDirectory = lovrFilesystemGetRealDirectory(path); + + if (realDirectory) { + lua_pushstring(L, realDirectory); + } else { + lua_pushnil(L); + } + + return 1; +} + +int l_lovrFilesystemGetSource(lua_State* L) { + const char* source = lovrFilesystemGetSource(); + + if (source) { + lua_pushstring(L, source); + } else { + lua_pushnil(L); + } + + return 1; +} + +int l_lovrFilesystemGetUserDirectory(lua_State* L) { + lua_pushstring(L, lovrFilesystemGetUserDirectory()); + return 1; +} + int l_lovrFilesystemIsDirectory(lua_State* L) { const char* path = luaL_checkstring(L, 1); lua_pushboolean(L, lovrFilesystemIsDirectory(path)); @@ -114,23 +161,27 @@ int l_lovrFilesystemIsFile(lua_State* L) { int l_lovrFilesystemRead(lua_State* L) { const char* path = luaL_checkstring(L, 1); int size; - char* contents = lovrFilesystemRead(path, &size); - if (!contents) { + char* content = lovrFilesystemRead(path, &size); + if (!content) { return luaL_error(L, "Could not read file '%s'", path); } - lua_pushlstring(L, contents, size); + lua_pushlstring(L, content, size); return 1; } +int l_lovrFilesystemSetIdentity(lua_State* L) { + const char* identity = luaL_checkstring(L, 1); + + if (lovrFilesystemSetIdentity(identity)) { + return luaL_error(L, "Could not set the filesystem identity"); + } + + return 0; +} + int l_lovrFilesystemSetSource(lua_State* L) { - const char* source = lua_tostring(L, 1); - - if (source) { - lua_pushboolean(L, lovrFilesystemSetSource(source)); - } else { - lua_pushboolean(L, 0); - } - + const char* source = luaL_checkstring(L, 1); + lua_pushboolean(L, !lovrFilesystemSetSource(source)); return 1; } diff --git a/src/lovr/filesystem.h b/src/lovr/filesystem.h index a9a565cd..e8ae0843 100644 --- a/src/lovr/filesystem.h +++ b/src/lovr/filesystem.h @@ -7,7 +7,12 @@ int l_lovrFilesystemInit(lua_State* L); int l_lovrFilesystemInitialize(lua_State* L); int l_lovrFilesystemExists(lua_State* L); int l_lovrFilesystemGetExecutablePath(lua_State* L); +int l_lovrFilesystemGetIdentity(lua_State* L); +int l_lovrFilesystemGetRealDirectory(lua_State* L); +int l_lovrFilesystemGetSource(lua_State* L); +int l_lovrFilesystemGetUserDirectory(lua_State* L); int l_lovrFilesystemIsDirectory(lua_State* L); int l_lovrFilesystemIsFile(lua_State* L); int l_lovrFilesystemRead(lua_State* L); +int l_lovrFilesystemSetIdentity(lua_State* L); int l_lovrFilesystemSetSource(lua_State* L);