From 54215b7ce462e35f59e028961debec3e9cc33fa1 Mon Sep 17 00:00:00 2001 From: fysx Date: Fri, 16 Jan 2015 20:00:51 +0100 Subject: [PATCH] refactored loading of games on android --- jni/love/src/common/android.cpp | 100 ++++++++++++ jni/love/src/common/android.h | 13 ++ .../modules/filesystem/physfs/Filesystem.cpp | 152 ++++-------------- 3 files changed, 146 insertions(+), 119 deletions(-) diff --git a/jni/love/src/common/android.cpp b/jni/love/src/common/android.cpp index fd623e44..9e64df23 100644 --- a/jni/love/src/common/android.cpp +++ b/jni/love/src/common/android.cpp @@ -25,6 +25,11 @@ #include "SDL.h" #include "jni.h" +#include +#include +#include +#include + namespace love { namespace android @@ -102,6 +107,101 @@ void vibrate (double seconds) env->DeleteLocalRef (activity); } +/* + * Helper functions for the filesystem module + */ +void freeGameArchiveMemory (void *ptr) { + SDL_Log ("Freeing memory for in-memory LÖVE archive 0x%x", (int) ptr); + char *game_love_data = static_cast(ptr); + delete[] game_love_data; +} + +bool loadGameArchiveToMemory (const char* filename, char **ptr, size_t *size) { + SDL_Log ("Trying to mount %s", filename); + SDL_RWops *asset_game_file = SDL_RWFromFile(filename, "rb"); + if (!asset_game_file) { + SDL_Log ("Could not find %s", filename); + return false; + } + + Sint64 file_size = asset_game_file->size(asset_game_file); + + if (file_size <= 0) { + SDL_Log ("Could not load game from %s. File has invalid file size: %d.", filename, (int) file_size); + return false; + } + + (*ptr) = new char[file_size]; + SDL_Log ("Allocated memory for in-memory LÖVE archive at: 0x%x", (int) (*ptr)); + + if (!(*ptr)) { + SDL_Log ("Could not allocate memory for in-memory game archive"); + return false; + } + + size_t bytes_copied = asset_game_file->read(asset_game_file, (void*) (*ptr), sizeof(char), (size_t) file_size); + + if (bytes_copied != file_size) { + SDL_Log ("Only copied %d of %d bytes into in-memory game archive!", (unsigned int) bytes_copied, (unsigned int) file_size); + delete[] (*ptr); + return false; + } + + SDL_Log ("Copied %d of %d bytes into in-memory game archive", (unsigned int) bytes_copied, (unsigned int) file_size); + + *size = (size_t) file_size; + + return true; +} + +bool directoryExists(const char* path) { + SDL_Log ("Checking directory exists for %s", path); + struct stat s; + int err = stat(path, &s); + if (err == -1) { + if (errno == ENOENT) + return false; + else { + SDL_Log ("Error checking for directory %s errno = %d: %s", path, errno, strerror (errno)); + return false; + } + } else if(S_ISDIR(s.st_mode)) { + SDL_Log ("Directory %s exists!", path); + return true; + } + return false; +} + +bool mkdir (const char* path) { + int err = ::mkdir (path, 0770); + if (err == -1) { + SDL_Log ("Error: Could not create directory %s", path); + return false; + } + + return true; +} + +bool createStorageDirectories () { + std::string internal_storage_path = SDL_AndroidGetInternalStoragePath(); + + std::string save_directory = internal_storage_path + "/save"; + if (!directoryExists (save_directory.c_str())) { + if (!mkdir(save_directory.c_str())) + return false; + } + + std::string game_directory = internal_storage_path + "/game"; + if (!directoryExists (game_directory.c_str())) { + if (!mkdir(game_directory.c_str())) + return false; + } + + SDL_Log ("Creating storage directories successful!"); + + return true; +} + } // android } // love diff --git a/jni/love/src/common/android.h b/jni/love/src/common/android.h index 14fbf3bf..04060326 100644 --- a/jni/love/src/common/android.h +++ b/jni/love/src/common/android.h @@ -47,6 +47,19 @@ bool openURL (const std::string &url); void vibrate (double seconds); +/* + * Helper functions for the filesystem module + */ +void freeGameArchiveMemory (void *ptr); + +bool loadGameArchiveToMemory (const char* filename, char **ptr, size_t *size); + +bool directoryExists(const char* path); + +bool mkdir (const char* path); + +bool createStorageDirectories (); + } // android } // love diff --git a/jni/love/src/modules/filesystem/physfs/Filesystem.cpp b/jni/love/src/modules/filesystem/physfs/Filesystem.cpp index 8690ccee..13c1f66f 100644 --- a/jni/love/src/modules/filesystem/physfs/Filesystem.cpp +++ b/jni/love/src/modules/filesystem/physfs/Filesystem.cpp @@ -32,10 +32,6 @@ #include #ifdef LOVE_ANDROID -#include -#include -#include -#include #include "common/android.h" #endif @@ -60,113 +56,6 @@ namespace return input.substr(getDriveDelim(input)+1); } -#ifdef LOVE_ANDROID - void androidDeleteAssetGameMemory (void *ptr) { - SDL_Log ("freeing memory for in-memory game.love"); - char *game_love_data = static_cast(ptr); - delete[] game_love_data; - } - - bool androidMountGame (const char *filename) { - SDL_Log ("Trying to mount %s", filename); - SDL_RWops *asset_game_file = SDL_RWFromFile(filename, "rb"); - if (!asset_game_file) { - SDL_Log ("Could not find %s", filename); - return false; - } - - Sint64 file_size = asset_game_file->size(asset_game_file); - - if (file_size == 0) { - SDL_Log ("Could not find valid %s. File has zero size.", filename); - return false; - } - - char *game_love_data = new char[file_size]; - - if (!game_love_data) { - SDL_Log ("Could not allocate memory for in-memory game archive"); - return false; - } - - size_t bytes_copied = asset_game_file->read(asset_game_file, game_love_data, sizeof(char), (size_t) file_size); - - if (bytes_copied != file_size) { - SDL_Log ("Only copied %d of %d bytes into in-memory game archive!", bytes_copied, file_size); - delete[] game_love_data; - return false; - } - - SDL_Log ("Copied %d of %d bytes into in-memory game archive", bytes_copied, file_size); - - bool result = false; - if (PHYSFS_mountMemory (game_love_data, file_size, androidDeleteAssetGameMemory, "archive.zip", "/", 0)) { - result = true; - SDL_Log ("Mounting of in-memory game archive successful!"); - } else { - SDL_Log ("Mounting of in-memory game archive failed!"); - } - - return result; - } - - bool androidMountAssetGame () { - return androidMountGame ("game.love"); - } - - bool androidMountSelectedGame () { - return androidMountGame (love::android::getSelectedGameFile()); - } - - bool androidDirectoryExists(const char* path) { - SDL_Log ("Checking directory exists for %s", path); - struct stat s; - int err = stat(path, &s); - if (err == -1) { - if (errno == ENOENT) - return false; - else { - SDL_Log ("Error checking for directory %s errno = %d: %s", path, errno, strerror (errno)); - return false; - } - } else if(S_ISDIR(s.st_mode)) { - SDL_Log ("Directory %s exists!", path); - return true; - } - return false; - } - - bool androidMkdir (const char* path) { - int err = mkdir (path, 0770); - if (err == -1) { - SDL_Log ("Error: Could not create directory %s", path); - return false; - } - - return true; - } - - bool androidCreateStorageDirectories () { - std::string internal_storage_path = SDL_AndroidGetInternalStoragePath(); - - std::string save_directory = internal_storage_path + "/save"; - if (!androidDirectoryExists (save_directory.c_str())) { - if (!androidMkdir(save_directory.c_str())) - return false; - } - - std::string game_directory = internal_storage_path + "/game"; - if (!androidDirectoryExists (game_directory.c_str())) { - if (!androidMkdir(game_directory.c_str())) - return false; - } - - SDL_Log ("Creating storage directories successful!"); - - return true; - } -#endif - std::string normalize(const std::string &input) { std::stringstream out; @@ -268,14 +157,14 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath) save_path_full = std::string(SDL_AndroidGetInternalStoragePath()) + std::string("/save/") + save_identity; - if (androidDirectoryExists (save_path_full.c_str())) { + if (love::android::directoryExists (save_path_full.c_str())) { SDL_Log ("dir exists"); } else { SDL_Log ("does not exist"); } - if (!androidDirectoryExists (save_path_full.c_str())) { - if (!androidMkdir (save_path_full.c_str())) { + if (!love::android::directoryExists (save_path_full.c_str())) { + if (!love::android::mkdir (save_path_full.c_str())) { SDL_Log ("Error: Could not create save directory %s!", save_path_full.c_str()); } else { SDL_Log ("Save directory %s successfuly created!", save_path_full.c_str()); @@ -323,15 +212,40 @@ bool Filesystem::setSource(const char *source) std::string new_search_path = source; #ifdef LOVE_ANDROID - if (!androidCreateStorageDirectories ()) { + if (!love::android::createStorageDirectories ()) { SDL_Log ("Error creating storage directories!"); } - std::string game_path = std::string(love::android::getSelectedGameFile()); - if (game_path == "") - game_path = "/sdcard/lovegame/"; + 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 successful!"); + } else { + 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/"; + } - if (!androidMountSelectedGame() && !androidMountAssetGame()) { SDL_RWops *sdcard_main = SDL_RWFromFile(std::string(game_path + "main.lua").c_str(), "rb"); if (sdcard_main) {