Browse Source

Implemented love.filesystem support for Android.

Martin Felis 10 years ago
parent
commit
19b7d1e115
1 changed files with 87 additions and 3 deletions
  1. 87 3
      src/modules/filesystem/physfs/Filesystem.cpp

+ 87 - 3
src/modules/filesystem/physfs/Filesystem.cpp

@@ -50,6 +50,13 @@
 #	include "common/iOS.h"
 #endif
 
+#include <string>
+
+#ifdef LOVE_ANDROID
+#include <SDL.h>
+#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;
 }