refactored loading of games on android

This commit is contained in:
fysx
2015-01-16 20:00:51 +01:00
parent fd9e9758a9
commit 54215b7ce4
3 changed files with 146 additions and 119 deletions
+100
View File
@@ -25,6 +25,11 @@
#include "SDL.h"
#include "jni.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
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<char*>(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
+13
View File
@@ -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
@@ -32,10 +32,6 @@
#include <string>
#ifdef LOVE_ANDROID
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#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<char*>(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) {