From 19b7d1e1153e81194cf8dc5c4805f3a9200c4245 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Thu, 13 Aug 2015 19:42:31 -0300 Subject: [PATCH] Implemented love.filesystem support for Android. --- src/modules/filesystem/physfs/Filesystem.cpp | 90 +++++++++++++++++++- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/src/modules/filesystem/physfs/Filesystem.cpp b/src/modules/filesystem/physfs/Filesystem.cpp index 5dbd63e24..d922ca640 100644 --- a/src/modules/filesystem/physfs/Filesystem.cpp +++ b/src/modules/filesystem/physfs/Filesystem.cpp @@ -50,6 +50,13 @@ # include "common/iOS.h" #endif +#include + +#ifdef LOVE_ANDROID +#include +#include "common/android.h" +#endif + namespace { size_t getDriveDelim(const std::string &input) @@ -85,6 +92,7 @@ namespace return out.str(); } + } namespace love @@ -160,7 +168,21 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath) else save_path_full += save_path_relative; - save_path_full = normalize(save_path_full); + save_path_full = normalize(save_path_full); + +#ifdef LOVE_ANDROID + if (save_identity == "") + save_identity = "unnamed"; + + std::string internal_storage_path = SDL_AndroidGetInternalStoragePath(); + std::string save_directory = internal_storage_path + "/save"; + + save_path_full = std::string(SDL_AndroidGetInternalStoragePath()) + std::string("/save/") + save_identity; + + if (!love::android::directoryExists(save_path_full.c_str()) && + !love::android::mkdir(save_path_full.c_str())) + SDL_Log("Error: Could not create save directory %s!", save_path_full.c_str()); +#endif // We now have something like: // save_identity: game @@ -198,12 +220,74 @@ bool Filesystem::setSource(const char *source) if (!game_source.empty()) return false; + std::string new_search_path = source; + +#ifdef LOVE_ANDROID + if (!love::android::createStorageDirectories ()) + SDL_Log("Error creating storage directories!"); + + char* game_archive_ptr = NULL; + size_t game_archive_size = 0; + bool archive_loaded = false; + + // try to load the game that was sent to LÖVE via a Intent + archive_loaded = love::android::loadGameArchiveToMemory(love::android::getSelectedGameFile(), &game_archive_ptr, &game_archive_size); + + if (!archive_loaded) + { + // try to load the game in the assets/ folder + archive_loaded = love::android::loadGameArchiveToMemory("game.love", &game_archive_ptr, &game_archive_size); + } + + if (archive_loaded) + { + if (!PHYSFS_mountMemory(game_archive_ptr, game_archive_size, love::android::freeGameArchiveMemory, "archive.zip", "/", 0)) + { + SDL_Log("Mounting of in-memory game archive failed!"); + love::android::freeGameArchiveMemory(game_archive_ptr); + return false; + } + } + else + { + // try to load the game in the directory that was sent to LÖVE via an + // Intent ... + std::string game_path = std::string(love::android::getSelectedGameFile()); + + if (game_path == "") + { + // ... or fall back to the game at /sdcard/lovegame + game_path = "/sdcard/lovegame/"; + } + + SDL_RWops *sdcard_main = SDL_RWFromFile(std::string(game_path + "main.lua").c_str(), "rb"); + + if (sdcard_main) + { + new_search_path = game_path; + sdcard_main->close(sdcard_main); + + if (!PHYSFS_mount(new_search_path.c_str(), nullptr, 1)) + { + SDL_Log("mounting of %s failed", new_search_path.c_str()); + return false; + } + } + else + { + // Neither assets/game.love or /sdcard/lovegame was mounted + // sucessfully, therefore simply fail. + return false; + } + } +#else // Add the directory. - if (!PHYSFS_mount(source, nullptr, 1)) + if (!PHYSFS_mount(new_search_path.c_str(), nullptr, 1)) return false; +#endif // Save the game source. - game_source = std::string(source); + game_source = new_search_path; return true; }