From 45242b805b1e7534a4a43ea5db68886a73b7af9e Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sun, 12 Jan 2014 17:41:04 +0100 Subject: [PATCH] removed debug code --- jni/love/src/love.cpp.orig | 258 ++++++ .../modules/filesystem/physfs/Filesystem.cpp | 2 - .../filesystem/physfs/Filesystem.cpp.orig | 781 ++++++++++++++++++ jni/love/src/modules/window/sdl/Window.cpp | 1 - .../src/modules/window/sdl/Window.cpp.orig | 622 ++++++++++++++ jni/love/src/scripts/boot.lua | 15 +- jni/love/src/scripts/boot.lua.h | 26 - 7 files changed, 1662 insertions(+), 43 deletions(-) create mode 100644 jni/love/src/love.cpp.orig create mode 100644 jni/love/src/modules/filesystem/physfs/Filesystem.cpp.orig create mode 100644 jni/love/src/modules/window/sdl/Window.cpp.orig diff --git a/jni/love/src/love.cpp.orig b/jni/love/src/love.cpp.orig new file mode 100644 index 00000000..27c03a73 --- /dev/null +++ b/jni/love/src/love.cpp.orig @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#include "modules/love/love.h" +#include + +#ifdef LOVE_BUILD_EXE + +// Lua +extern "C" { + #include + #include + #include +} + +#ifdef LOVE_WINDOWS +#include +#endif // LOVE_WINDOWS + +#ifdef LOVE_MACOSX +#include "OSX.h" +#endif // LOVE_MACOSX + +#ifdef LOVE_LEGENDARY_UTF8_ARGV_HACK + +void get_utf8_arguments(int &argc, char **&argv) +{ + LPWSTR cmd = GetCommandLineW(); + + if (!cmd) + return; + + LPWSTR *argv_w = CommandLineToArgvW(cmd, &argc); + + argv = new char *[argc]; + + for (int i = 0; i < argc; ++i) + { + // Size of wide char buffer (plus one for trailing '\0'). + size_t wide_len = wcslen(argv_w[i]) + 1; + + // Get size in UTF-8. + int utf8_size = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], wide_len, argv[i], 0, 0, 0); + + argv[i] = new char[utf8_size]; + + // Convert to UTF-8. + int ok = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], wide_len, argv[i], utf8_size, 0, 0); + + int len = strlen(argv[i]); + + if (!ok) + printf("Warning: could not convert to UTF8.\n"); + } + + LocalFree(argv_w); +} + +#endif // LOVE_LEGENDARY_UTF8_ARGV_HACK + +#ifdef LOVE_LEGENDARY_APP_ARGV_HACK + +#include + +static void get_app_arguments(int argc, char **argv, int &new_argc, char **&new_argv) +{ + std::vector temp_argv; + for (int i = 0; i < argc; i++) + { + // Don't copy -psn_xxx argument from argv. + if (i == 0 || strncmp(argv[i], "-psn_", 5) != 0) + temp_argv.push_back(std::string(argv[i])); + } + + // Check for a drop file string. + std::string dropfilestr = love::osx::checkDropEvents(); + if (!dropfilestr.empty()) + { + temp_argv.insert(temp_argv.begin() + 1, dropfilestr); + } + else + { + // If it exists, add the love file in love.app/Contents/Resources/ to argv. + std::string loveResourcesPath = love::osx::getLoveInResources(); + if (!loveResourcesPath.empty()) + { + // Run in pseudo-fused mode. + std::vector::iterator it = temp_argv.begin(); + it = temp_argv.insert(it + 1, loveResourcesPath); + temp_argv.insert(it + 1, std::string("--fused")); + } + } + + // Copy temp argv vector to new argv array. + new_argc = (int) temp_argv.size(); + new_argv = new char *[new_argc+1]; + + for (int i = 0; i < new_argc; i++) + { + new_argv[i] = new char[temp_argv[i].length() + 1]; + strcpy(new_argv[i], temp_argv[i].c_str()); + } + + new_argv[new_argc] = NULL; +} + +#endif // LOVE_LEGENDARY_APP_ARGV_HACK + +static int love_preload(lua_State *L, lua_CFunction f, const char *name) +{ + lua_getglobal(L, "package"); + lua_getfield(L, -1, "preload"); + lua_pushcfunction(L, f); + lua_setfield(L, -2, name); + lua_pop(L, 2); + return 0; +} + +static int l_sdl_log(lua_State *L) { + if ((lua_gettop(L) != 1) || !lua_isstring(L, -1)) { + SDL_Log ("[LöveSDL] invalid error message: expected string"); + return 0; + } + + SDL_Log ("[LöveSDL] %s", lua_tostring(L, -1)); + + return 0; +} + +static const struct luaL_Reg sdl_lib[] = { + {"log", l_sdl_log}, + {NULL, NULL} +}; + +int main(int argc, char **argv) +{ + SDL_SetHint("LOVE_GRAPHICS_USE_OPENGLES", "1"); + + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); + +#ifdef LOVE_LEGENDARY_UTF8_ARGV_HACK + int hack_argc = 0; char **hack_argv = 0; + get_utf8_arguments(hack_argc, hack_argv); + argc = hack_argc; + argv = hack_argv; +#endif // LOVE_LEGENDARY_UTF8_ARGV_HACK + +#ifdef LOVE_LEGENDARY_APP_ARGV_HACK + int hack_argc = 0; + char **hack_argv = 0; + get_app_arguments(argc, argv, hack_argc, hack_argv); + argc = hack_argc; + argv = hack_argv; +#endif // LOVE_LEGENDARY_APP_ARGV_HACK + + // Oh, you just want the version? Okay! + if (argc > 1 && strcmp(argv[1], "--version") == 0) + { + printf("LOVE %s (%s)\n", love_version(), love_codename()); + return 0; + } + + // Create the virtual machine. + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + + luaL_register (L, "SDL", sdl_lib); + + // Add love to package.preload for easy requiring. + love_preload(L, luaopen_love, "love"); + + // Add command line arguments to global arg (like stand-alone Lua). + { + lua_newtable(L); + + if (argc > 0) + { + lua_pushstring(L, argv[0]); + lua_rawseti(L, -2, -2); + } + + lua_pushstring(L, "embedded boot.lua"); + lua_rawseti(L, -2, -1); + + for (int i = 1; i < argc; i++) + { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i); + } + + lua_setglobal(L, "arg"); + } + + // require "love" + lua_getglobal(L, "require"); + lua_pushstring(L, "love"); + lua_call(L, 1, 1); // leave the returned table on the stack. + + // Add love.__exe = true. + // This indicates that we're running the standalone version of love, and not + // the library version. + { + lua_pushboolean(L, 1); + lua_setfield(L, -2, "_exe"); + } + + // Pop the love table returned by require "love". + lua_pop(L, 1); + + // require "love.boot" (preloaded when love was required.) + lua_getglobal(L, "require"); + lua_pushstring(L, "love.boot"); + lua_call(L, 1, 1); + + // Call the returned boot function. + lua_call(L, 0, 1); + + int retval = 0; + if (lua_isnumber(L, -1)) + retval = (int) lua_tonumber(L, -1); + + lua_close(L); + +#if defined(LOVE_LEGENDARY_UTF8_ARGV_HACK) || defined(LOVE_LEGENDARY_APP_ARGV_HACK) + if (hack_argv) + { + for (int i = 0; i + +#include "common/utf8.h" +#include "common/b64.h" + +#include "Filesystem.h" + +#include "SDL.h" +#include + +#ifdef __ANDROID__ +#include +#include +#include +#include +#endif + +namespace +{ + size_t getDriveDelim(const std::string &input) + { + for (size_t i = 0; i < input.size(); ++i) + if (input[i] == '/' || input[i] == '\\') + return i; + // Something's horribly wrong + return 0; + } + + std::string getDriveRoot(const std::string &input) + { + return input.substr(0, getDriveDelim(input)+1); + } + + std::string skipDriveRoot(const std::string &input) + { + return input.substr(getDriveDelim(input)+1); + } + +#ifdef __ANDROID__ + 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; + } + + bool androidCopyGameFromAssets () { + SDL_RWops *asset_game_file = SDL_RWFromFile("game.love", "rb"); + + if (!asset_game_file) { + SDL_Log ("Could not find game.love in assets."); + return false; + } + Sint64 file_size = asset_game_file->size(asset_game_file); + + if (file_size == 0) { + SDL_Log ("Could not find valid game.love in assets. File has zero size.", (int) file_size); + return false; + } + + SDL_Log ("Found game.love in assets. Size: %d", (int) file_size); + + std::string internal_storage_path = SDL_AndroidGetInternalStoragePath(); + std::string internal_game_file = internal_storage_path + "/game/game.love"; + SDL_RWops *storage_game_file = SDL_RWFromFile (internal_game_file.c_str(), "wb"); + + if (!storage_game_file) { + SDL_Log ("Error creating internal storage game file: %s", SDL_GetError()); + asset_game_file->close(asset_game_file); + return false; + } + + size_t buff_size = 128 * 1024; + char *data_buffer = new char[buff_size]; + + if (!data_buffer) { + SDL_Log ("Error allocating memory for file copy buffer!"); + asset_game_file->close(asset_game_file); + storage_game_file->close(storage_game_file); + return false; + } + + size_t bytes_copied = 0; + while (bytes_copied != (size_t) file_size) { + size_t bytes_read = asset_game_file->read(asset_game_file, data_buffer, sizeof(char), (size_t) buff_size); + size_t bytes_written = storage_game_file->write(storage_game_file, data_buffer, sizeof(char), bytes_read); + + bytes_copied += bytes_written; + SDL_Log ("Copied %d of %d bytes", bytes_copied, file_size); + + if (bytes_written != bytes_read) { + SDL_Log ("Error copying asset game to internal storage: %s", SDL_GetError()); + asset_game_file->close(asset_game_file); + storage_game_file->close(storage_game_file); + return false; + } + } + + delete[] data_buffer; + data_buffer = NULL; + + asset_game_file->close(asset_game_file); + storage_game_file->close(storage_game_file); + + SDL_Log ("Copying of asset game to internal storage %s successful!", internal_game_file.c_str()); + + return true; + } +#endif +} + +namespace love +{ +namespace filesystem +{ +namespace physfs +{ + +Filesystem::Filesystem() + : initialized(false) + , fused(false) + , fusedSet(false) +{ +} + +Filesystem::~Filesystem() +{ + if (initialized) + PHYSFS_deinit(); +} + +const char *Filesystem::getName() const +{ + return "love.filesystem.physfs"; +} + +void Filesystem::init(const char *arg0) +{ + if (!PHYSFS_init(arg0)) + throw Exception(PHYSFS_getLastError()); + initialized = true; +} + +void Filesystem::setFused(bool fused) +{ + if (fusedSet) + return; + this->fused = fused; + fusedSet = true; +} + +bool Filesystem::isFused() const +{ + if (!fusedSet) + return false; + return fused; +} + +bool Filesystem::setIdentity(const char *ident, bool appendToPath) +{ + SDL_Log ("identity = %s", ident); + + if (!initialized) + return false; + + std::string old_save_path = save_path_full; + + // Store the save directory. + save_identity = std::string(ident); + + // Generate the relative path to the game save folder. + save_path_relative = std::string(LOVE_APPDATA_PREFIX LOVE_APPDATA_FOLDER LOVE_PATH_SEPARATOR) + save_identity; + + // Generate the full path to the game save folder. + save_path_full = std::string(getAppdataDirectory()) + std::string(LOVE_PATH_SEPARATOR); + if (fused) + save_path_full += std::string(LOVE_APPDATA_PREFIX) + save_identity; + else + save_path_full += save_path_relative; + +#ifdef __ANDROID__ + 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 (androidDirectoryExists (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())) { + 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()); + } + } else { + SDL_Log ("Save directory %s exists!", save_path_full.c_str()); + } +#endif + // We now have something like: + // save_identity: game + // save_path_relative: ./LOVE/game + // save_path_full: C:\Documents and Settings\user\Application Data/LOVE/game + + // We don't want old read-only save paths to accumulate when we set a new + // identity. + if (!old_save_path.empty()) + PHYSFS_removeFromSearchPath(old_save_path.c_str()); + + // Try to add the save directory to the search path. + // (No error on fail, it means that the path doesn't exist). + PHYSFS_addToSearchPath(save_path_full.c_str(), appendToPath); + + return true; +} + +const char *Filesystem::getIdentity() const +{ + return save_identity.c_str(); +} + +bool Filesystem::setSource(const char *source) +{ + if (!initialized) + return false; + + // Check whether directory is already set. + if (!game_source.empty()) + return false; + + std::string new_search_path = source; + +#ifdef __ANDROID__ + if (!androidCreateStorageDirectories ()) { + SDL_Log ("Error creating storage directories!"); + } + + if (androidCopyGameFromAssets()) + new_search_path = std::string(SDL_AndroidGetInternalStoragePath()) + std::string("/game/game.love"); + else { + SDL_RWops *sdcard_main = SDL_RWFromFile("/sdcard/lovegame/main.lua", "rb"); + + if (sdcard_main) { + SDL_Log ("using game from /sdcard/lovegame"); + new_search_path = "/sdcard/lovegame"; + sdcard_main->close(sdcard_main); + } + } +#endif + + // Add the directory. + if (!PHYSFS_addToSearchPath(new_search_path.c_str(), 1)) { + SDL_Log ("mounting of %s failed", new_search_path.c_str()); + return false; + } + + // Save the game source. + game_source = new_search_path; + + return true; +} + +const char *Filesystem::getSource() const +{ + return game_source.c_str(); +} + +bool Filesystem::setupWriteDirectory() +{ + if (!initialized) + return false; + + // These must all be set. + if (save_identity.empty() || save_path_full.empty() || save_path_relative.empty()) + return false; + + // Set the appdata folder as writable directory. + // (We must create the save folder before mounting it). + if (!PHYSFS_setWriteDir(getDriveRoot(save_path_full).c_str())) + return false; + + // Create the save folder. (We're now "at" %APPDATA%). + if (!createDirectory(skipDriveRoot(save_path_full).c_str())) + { + // Clear the write directory in case of error. + PHYSFS_setWriteDir(0); + return false; + } + + // Set the final write directory. + if (!PHYSFS_setWriteDir(save_path_full.c_str())) + return false; + + // Add the directory. (Will not be readded if already present). + if (!PHYSFS_addToSearchPath(save_path_full.c_str(), 0)) + { + PHYSFS_setWriteDir(0); // Clear the write directory in case of error. + return false; + } + + return true; +} + +bool Filesystem::mount(const char *archive, const char *mountpoint, bool appendToPath) +{ + if (!initialized || !archive) + return false; + + std::string realPath; + std::string sourceBase = getSourceBaseDirectory(); + + if (isFused() && sourceBase.compare(archive) == 0) + { + // Special case: if the game is fused and the archive is the source's + // base directory, mount it even though it's outside of the save dir. + realPath = sourceBase; + } + else + { + // Not allowed for safety reasons. + if (strlen(archive) == 0 || strstr(archive, "..") || strcmp(archive, "/") == 0) + return false; + + const char *realDir = PHYSFS_getRealDir(archive); + if (!realDir) + return false; + + realPath = realDir; + + // Always disallow mounting of files inside the game source, since it + // won't work anyway if the game source is a zipped .love file. + if (realPath.find(game_source) == 0) + return false; + + realPath += LOVE_PATH_SEPARATOR; + realPath += archive; + } + + if (realPath.length() == 0) + return false; + + return PHYSFS_mount(realPath.c_str(), mountpoint, appendToPath); +} + +bool Filesystem::unmount(const char *archive) +{ + if (!initialized || !archive) + return false; + + std::string realPath; + std::string sourceBase = getSourceBaseDirectory(); + + if (isFused() && sourceBase.compare(archive) == 0) + { + // Special case: if the game is fused and the archive is the source's + // base directory, unmount it even though it's outside of the save dir. + realPath = sourceBase; + } + else + { + // Not allowed for safety reasons. + if (strlen(archive) == 0 || strstr(archive, "..") || strcmp(archive, "/") == 0) + return false; + + const char *realDir = PHYSFS_getRealDir(archive); + if (!realDir) + return false; + + realPath = realDir; + realPath += LOVE_PATH_SEPARATOR; + realPath += archive; + } + + const char *mountPoint = PHYSFS_getMountPoint(realPath.c_str()); + if (!mountPoint) + return false; + + return PHYSFS_removeFromSearchPath(realPath.c_str()); +} + +File *Filesystem::newFile(const char *filename) const +{ + return new File(filename); +} + +FileData *Filesystem::newFileData(void *data, unsigned int size, const char *filename) const +{ + FileData *fd = new FileData(size, std::string(filename)); + + // Copy the data into FileData. + memcpy(fd->getData(), data, size); + + return fd; +} + +FileData *Filesystem::newFileData(const char *b64, const char *filename) const +{ + int size = strlen(b64); + int outsize = 0; + char *dst = b64_decode(b64, size, outsize); + FileData *fd = new FileData(outsize, std::string(filename)); + + // Copy the data into FileData. + memcpy(fd->getData(), dst, outsize); + delete [] dst; + + return fd; +} + +const char *Filesystem::getWorkingDirectory() +{ + if (cwd.empty()) + { +#ifdef LOVE_WINDOWS + + WCHAR w_cwd[LOVE_MAX_PATH]; + _wgetcwd(w_cwd, LOVE_MAX_PATH); + cwd = to_utf8(w_cwd); + replace_char(cwd, '\\', '/'); +#else + char *cwd_char = new char[LOVE_MAX_PATH]; + + if (getcwd(cwd_char, LOVE_MAX_PATH)) + cwd = cwd_char; // if getcwd fails, cwd_char (and thus cwd) will still be empty + + delete [] cwd_char; +#endif + } + + return cwd.c_str(); +} + +const char *Filesystem::getUserDirectory() +{ + return PHYSFS_getUserDir(); +} + +const char *Filesystem::getAppdataDirectory() +{ +#ifdef LOVE_WINDOWS + if (appdata.empty()) + { + wchar_t *w_appdata = _wgetenv(L"APPDATA"); + appdata = to_utf8(w_appdata); + replace_char(appdata, '\\', '/'); + } + return appdata.c_str(); +#elif defined(LOVE_MACOSX) + if (appdata.empty()) + { + std::string udir = getUserDirectory(); + udir.append("/Library/Application Support"); + appdata = udir; + } + return appdata.c_str(); +#elif defined(LOVE_LINUX) + if (appdata.empty()) + { + char *xdgdatahome = getenv("XDG_DATA_HOME"); + if (!xdgdatahome) + appdata = std::string(getUserDirectory()) + "/.local/share/"; + else + appdata = xdgdatahome; + } + return appdata.c_str(); +#else + return getUserDirectory(); +#endif +} + + +const char *Filesystem::getSaveDirectory() +{ + return save_path_full.c_str(); +} + +std::string Filesystem::getSourceBaseDirectory() const +{ + size_t source_len = game_source.length(); + + if (source_len == 0) + return ""; + + // FIXME: This doesn't take into account parent and current directory + // symbols (i.e. '..' and '.') +#ifdef LOVE_WINDOWS + // In windows, delimiters can be either '/' or '\'. + size_t base_end_pos = game_source.find_last_of("/\\", source_len - 2); +#else + size_t base_end_pos = game_source.find_last_of('/', source_len - 2); +#endif + + if (base_end_pos == std::string::npos) + return ""; + + // If the source is in the unix root (aka '/'), we want to keep the '/'. + if (base_end_pos == 0) + base_end_pos = 1; + + return game_source.substr(0, base_end_pos); +} + +bool Filesystem::exists(const char *file) const +{ + return PHYSFS_exists(file); +} + +bool Filesystem::isDirectory(const char *file) const +{ + return PHYSFS_isDirectory(file); +} + +bool Filesystem::isFile(const char *file) const +{ + return exists(file) && !isDirectory(file); +} + +bool Filesystem::createDirectory(const char *dir) +{ + if (PHYSFS_getWriteDir() == 0 && !setupWriteDirectory()) + return false; + + if (!PHYSFS_mkdir(dir)) + return false; + return true; +} + +bool Filesystem::remove(const char *file) +{ + if (PHYSFS_getWriteDir() == 0 && !setupWriteDirectory()) + return false; + + if (!PHYSFS_delete(file)) + return false; + return true; +} + +Data *Filesystem::read(const char *filename, int64 size) const +{ + File file(filename); + + file.open(File::READ); + + // close() is called in the File destructor. + return file.read(size); +} + +void Filesystem::write(const char *filename, const void *data, int64 size) const +{ + File file(filename); + + file.open(File::WRITE); + + // close() is called in the File destructor. + if (!file.write(data, size)) + throw love::Exception("Data could not be written."); +} + +void Filesystem::append(const char *filename, const void *data, int64 size) const +{ + File file(filename); + + file.open(File::APPEND); + + // close() is called in the File destructor. + if (!file.write(data, size)) + throw love::Exception("Data could not be written."); +} + +int Filesystem::getDirectoryItems(lua_State *L) +{ + const char *dir = luaL_checkstring(L, 1); + + char **rc = PHYSFS_enumerateFiles(dir); + int index = 1; + + lua_newtable(L); + + for (char **i = rc; *i != 0; i++) + { + lua_pushstring(L, *i); + lua_rawseti(L, -2, index); + index++; + } + + PHYSFS_freeList(rc); + + return 1; +} + +int Filesystem::lines_i(lua_State *L) +{ + const int bufsize = 1024; + char buf[bufsize]; + int linesize = 0; + bool newline = false; + + File *file = luax_checktype(L, lua_upvalueindex(1), "File", FILESYSTEM_FILE_T); + + // Only accept read mode at this point. + if (file->getMode() != File::READ) + return luaL_error(L, "File needs to stay in read mode."); + + int64 pos = file->tell(); + int64 userpos = -1; + + if (lua_isnoneornil(L, lua_upvalueindex(2)) == 0) + { + // User may have changed the file position. + userpos = pos; + pos = (int64) lua_tonumber(L, lua_upvalueindex(2)); + if (userpos != pos) + file->seek(pos); + } + + while (!newline && !file->eof()) + { + // This 64-bit to 32-bit integer cast should be safe as it never exceeds bufsize. + int read = (int) file->read(buf, bufsize); + if (read < 0) + return luaL_error(L, "Could not read from file."); + + linesize += read; + + for (int i = 0; i < read; i++) + { + if (buf[i] == '\n') + { + linesize -= read - i; + newline = true; + break; + } + } + } + + if (newline || (file->eof() && linesize > 0)) + { + if (linesize < bufsize) + { + // We have the line in the buffer on the stack. No 'new' and 'read' needed. + lua_pushlstring(L, buf, linesize > 0 && buf[linesize - 1] == '\r' ? linesize - 1 : linesize); + if (userpos < 0) + file->seek(pos + linesize + 1); + } + else + { + char *str = 0; + try + { + str = new char[linesize + 1]; + } + catch(std::bad_alloc &) + { + // Can't lua_error (longjmp) in exception handlers. + } + + if (!str) + return luaL_error(L, "Out of memory."); + + file->seek(pos); + + // Read the \n anyway and save us a call to seek. + if (file->read(str, linesize + 1) == -1) + { + delete [] str; + return luaL_error(L, "Could not read from file."); + } + + lua_pushlstring(L, str, str[linesize - 1] == '\r' ? linesize - 1 : linesize); + delete [] str; + } + + if (userpos >= 0) + { + // Save new position in upvalue. + lua_pushnumber(L, (lua_Number)(pos + linesize + 1)); + lua_replace(L, lua_upvalueindex(2)); + file->seek(userpos); + } + + return 1; + } + + // EOF reached. + if (userpos >= 0 && luax_toboolean(L, lua_upvalueindex(3))) + file->seek(userpos); + else + file->close(); + + return 0; +} + +int64 Filesystem::getLastModified(const char *filename) const +{ + PHYSFS_sint64 time = PHYSFS_getLastModTime(filename); + + if (time == -1) + throw love::Exception("Could not determine file modification date."); + + return time; +} + +int64 Filesystem::getSize(const char *filename) const +{ + File file(filename); + int64 size = file.getSize(); + return size; +} + +} // physfs +} // filesystem +} // love diff --git a/jni/love/src/modules/window/sdl/Window.cpp b/jni/love/src/modules/window/sdl/Window.cpp index 5d2ee663..49af2244 100644 --- a/jni/love/src/modules/window/sdl/Window.cpp +++ b/jni/love/src/modules/window/sdl/Window.cpp @@ -95,7 +95,6 @@ bool Window::setWindow(int width, int height, WindowAttributes *attribs) Uint32 sdlflags = SDL_WINDOW_OPENGL; - if (f.fullscreen) { if (f.fstype == FULLSCREEN_TYPE_DESKTOP) diff --git a/jni/love/src/modules/window/sdl/Window.cpp.orig b/jni/love/src/modules/window/sdl/Window.cpp.orig new file mode 100644 index 00000000..5d2ee663 --- /dev/null +++ b/jni/love/src/modules/window/sdl/Window.cpp.orig @@ -0,0 +1,622 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +// LOVE +#include "common/config.h" +#include "graphics/Graphics.h" +#include "Window.h" + +// C++ +#include +#include +#include + +namespace love +{ +namespace window +{ +namespace sdl +{ + +Window::Window() + : windowTitle("") + , created(false) + , mouseGrabbed(false) + , window(0) + , context(0) +{ + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) + throw love::Exception("%s", SDL_GetError()); +} + +Window::~Window() +{ + if (curMode.icon) + curMode.icon->release(); + + if (window) + SDL_DestroyWindow(window); + + if (context) + SDL_GL_DeleteContext(context); + + SDL_QuitSubSystem(SDL_INIT_VIDEO); +} + +Window::_currentMode::_currentMode() + : width(800) + , height(600) + , attribs() + , icon(0) +{ +} + +bool Window::setWindow(int width, int height, WindowAttributes *attribs) +{ + graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics."); + if (gfx) + gfx->unSetMode(); + + WindowAttributes f; + + if (attribs) + f = *attribs; + + f.minwidth = std::max(f.minwidth, 1); + f.minheight = std::max(f.minheight, 1); + + f.display = std::min(std::max(f.display, 0), getDisplayCount()); + + // Use the desktop resolution if a width or height of 0 is specified. + if (width == 0 || height == 0) + { + SDL_DisplayMode mode = {}; + SDL_GetDesktopDisplayMode(f.display, &mode); + width = mode.w; + height = mode.h; + } + + Uint32 sdlflags = SDL_WINDOW_OPENGL; + + + if (f.fullscreen) + { + if (f.fstype == FULLSCREEN_TYPE_DESKTOP) + sdlflags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + else + { + sdlflags |= SDL_WINDOW_FULLSCREEN; + + // Fullscreen window creation will bug out if no mode can be used. + SDL_DisplayMode mode = {0, width, height, 0, 0}; + if (SDL_GetClosestDisplayMode(f.display, &mode, &mode) == 0) + return false; + } + } + + if (f.resizable) + sdlflags |= SDL_WINDOW_RESIZABLE; + + if (f.borderless) + sdlflags |= SDL_WINDOW_BORDERLESS; + + // Destroy and recreate the window if the dimensions or flags have changed. + if (window) + { + int curdisplay = SDL_GetWindowDisplayIndex(window); + Uint32 wflags = SDL_GetWindowFlags(window); + wflags &= (SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS); + + if (sdlflags != wflags || width != curMode.width || height != curMode.height + || f.display != curdisplay || f.fsaa != curMode.attribs.fsaa) + { + SDL_DestroyWindow(window); + window = 0; + + // The old window may have generated pending events which are no + // longer relevant. Destroy them all! + SDL_FlushEvent(SDL_WINDOWEVENT); + } + } + + int centeredpos = SDL_WINDOWPOS_CENTERED_DISPLAY(f.display); + int uncenteredpos = SDL_WINDOWPOS_UNDEFINED_DISPLAY(f.display); + + if (!window) + { + // In Windows and Linux, some GL attributes are set on window creation. + setWindowGLAttributes(f.fsaa); + + const char *title = windowTitle.c_str(); + int pos = f.centered ? centeredpos : uncenteredpos; + + window = SDL_CreateWindow(title, pos, pos, width, height, sdlflags); + + if (!window && f.fsaa > 0) + { + // FSAA might have caused the failure, disable it and try again. + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + + window = SDL_CreateWindow(title, pos, pos, width, height, sdlflags); + f.fsaa = 0; + } + + // Make sure the window keeps any previously set icon. + if (window && curMode.icon) + setIcon(curMode.icon); + } + + if (!window) + { + displayError("Could not create window", SDL_GetError()); + return false; + } + + // Enforce minimum window dimensions. + SDL_SetWindowMinimumSize(window, f.minwidth, f.minheight); + + if (f.centered && !f.fullscreen) + SDL_SetWindowPosition(window, centeredpos, centeredpos); + + SDL_RaiseWindow(window); + + if (!setContext(f.fsaa, f.vsync)) + { + created = false; + return false; + } + + created = true; + + updateAttributes(f); + + if (gfx) + { + if (!gfx->setMode(curMode.width, curMode.height)) + displayError("Could not set graphics mode", "Unsupported OpenGL version?"); + } + + // Make sure the mouse keeps its previous grab setting. + setMouseGrab(mouseGrabbed); + + return true; +} + +bool Window::onWindowResize(int width, int height) +{ + if (!window) + return false; + + curMode.width = width; + curMode.height = height; + + return true; +} + +bool Window::setContext(int fsaa, bool vsync) +{ + // We would normally only need to recreate the context if FSAA changes or + // SDL_GL_MakeCurrent is unsuccessful, but in Windows MakeCurrent can + // sometimes claim success but the context will actually be trashed. + if (context) + { + SDL_GL_DeleteContext(context); + context = 0; + } + + // Make sure the proper attributes are set. + setWindowGLAttributes(fsaa); + + context = SDL_GL_CreateContext(window); + + if (!context && fsaa > 0) + { + // FSAA might have caused the failure, disable it and try again. + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + context = SDL_GL_CreateContext(window); + } + + if (!context) + { + displayError("Could not create OpenGL context", SDL_GetError()); + return false; + } + + // Set vertical synchronization. + SDL_GL_SetSwapInterval(vsync ? 1 : 0); + + // Verify FSAA setting. + int buffers; + int samples; + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers); + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples); + + // Don't fail because of this, but issue a warning. + if ((!buffers && fsaa) || (samples != fsaa)) + { + std::cerr << "Warning, FSAA setting failed! (Result: buffers: " << buffers << ", samples: " << samples << ")" << std::endl; + fsaa = (buffers > 0) ? samples : 0; + } + + curMode.attribs.fsaa = fsaa; + curMode.attribs.vsync = SDL_GL_GetSwapInterval() != 0; + + return true; +} + +void Window::setWindowGLAttributes(int fsaa) const +{ + // Set GL window attributes. + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); + + // FSAA. + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0); + + const char *glesHint = SDL_GetHint("LOVE_GRAPHICS_USE_OPENGLES"); + if (glesHint && *glesHint == '1') + { + // Use OpenGL ES 2+. + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } + else + { + // Use desktop OpenGL. + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); // default + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + } +} + +void Window::updateAttributes(const WindowAttributes &newattribs) +{ + Uint32 wflags = SDL_GetWindowFlags(window); + + // Set the new display mode as the current display mode. + SDL_GetWindowSize(window, &curMode.width, &curMode.height); + + if ((wflags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) + { + curMode.attribs.fullscreen = true; + curMode.attribs.fstype = FULLSCREEN_TYPE_DESKTOP; + } + else if ((wflags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN) + { + curMode.attribs.fullscreen = true; + curMode.attribs.fstype = FULLSCREEN_TYPE_NORMAL; + } + else + { + curMode.attribs.fullscreen = false; + curMode.attribs.fstype = newattribs.fstype; + } + + // The min width/height is set to 0 internally in SDL when in fullscreen. + if (curMode.attribs.fullscreen) + { + curMode.attribs.minwidth = newattribs.minwidth; + curMode.attribs.minheight = newattribs.minheight; + } + else + SDL_GetWindowMinimumSize(window, &curMode.attribs.minwidth, &curMode.attribs.minheight); + + curMode.attribs.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0; + curMode.attribs.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0; + curMode.attribs.centered = newattribs.centered; + curMode.attribs.display = std::max(SDL_GetWindowDisplayIndex(window), 0); + + // Only minimize on focus loss if the window is in exclusive-fullscreen + // mode (mimics behaviour of SDL 2.0.2+). + // In OS X we always disable this to prevent dock minimization weirdness. +#ifndef LOVE_MACOSX + if (curMode.attribs.fullscreen && curMode.attribs.fstype == FULLSCREEN_TYPE_NORMAL) + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1"); + else +#endif + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); +} + +void Window::displayError(const std::string &title, const std::string &text) const +{ + std::cerr << title << ": " << text << std::endl; + + if (!window) + return; + + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title.c_str(), text.c_str(), window); +} + +void Window::getWindow(int &width, int &height, WindowAttributes &attribs) +{ + // Window position may be different from creation - update display index. + if (window) + curMode.attribs.display = std::max(SDL_GetWindowDisplayIndex(window), 0); + + width = curMode.width; + height = curMode.height; + attribs = curMode.attribs; +} + +bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype) +{ + if (!window) + return false; + + WindowAttributes newattribs = curMode.attribs; + newattribs.fullscreen = fullscreen; + newattribs.fstype = fstype; + + Uint32 sdlflags = 0; + + if (fullscreen) + { + if (fstype == FULLSCREEN_TYPE_DESKTOP) + sdlflags = SDL_WINDOW_FULLSCREEN_DESKTOP; + else + { + sdlflags = SDL_WINDOW_FULLSCREEN; + + SDL_DisplayMode mode = {}; + mode.w = curMode.width; + mode.h = curMode.height; + + SDL_GetClosestDisplayMode(SDL_GetWindowDisplayIndex(window), &mode, &mode); + SDL_SetWindowDisplayMode(window, &mode); + } + } + + if (SDL_SetWindowFullscreen(window, sdlflags) == 0) + { + SDL_GL_MakeCurrent(window, context); + updateAttributes(newattribs); + + // Update the viewport size now instead of waiting for event polling. + graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics."); + if (gfx) + gfx->setViewportSize(curMode.width, curMode.height); + + return true; + } + + return false; +} + +bool Window::setFullscreen(bool fullscreen) +{ + return setFullscreen(fullscreen, curMode.attribs.fstype); +} + +int Window::getDisplayCount() const +{ + return SDL_GetNumVideoDisplays(); +} + +typedef Window::WindowSize WindowSize; + +std::vector Window::getFullscreenSizes(int displayindex) const +{ + std::vector sizes; + + SDL_DisplayMode mode = {}; + std::vector::const_iterator it; + for (int i = 0; i < SDL_GetNumDisplayModes(displayindex); i++) + { + SDL_GetDisplayMode(displayindex, i, &mode); + + // SDL2's display mode list has multiple entries for modes of the same + // size with different bits per pixel, so we need to filter those out. + bool alreadyhassize = false; + for (it = sizes.begin(); it != sizes.end(); ++it) + { + if (it->width == mode.w && it->height == mode.h) + { + alreadyhassize = true; + break; + } + } + + if (!alreadyhassize) + { + WindowSize w = {mode.w, mode.h}; + sizes.push_back(w); + } + } + + return sizes; +} + +int Window::getWidth() const +{ + return curMode.width; +} + +int Window::getHeight() const +{ + return curMode.height; +} + +void Window::getDesktopDimensions(int displayindex, int &width, int &height) const +{ + if (displayindex >= 0 && displayindex < getDisplayCount()) + { + SDL_DisplayMode mode = {}; + SDL_GetDesktopDisplayMode(displayindex, &mode); + width = mode.w; + height = mode.h; + } + else + { + width = 0; + height = 0; + } +} + +bool Window::isCreated() const +{ + return created; +} + +void Window::setWindowTitle(const std::string &title) +{ + windowTitle = title; + + if (window) + SDL_SetWindowTitle(window, title.c_str()); +} + +const std::string &Window::getWindowTitle() const +{ + return windowTitle; +} + +bool Window::setIcon(love::image::ImageData *imgd) +{ + if (!imgd) + return false; + + imgd->retain(); + if (curMode.icon) + curMode.icon->release(); + curMode.icon = imgd; + + if (!window) + return false; + + Uint32 rmask, gmask, bmask, amask; +#ifdef LOVE_BIG_ENDIAN + rmask = 0xFF000000; + gmask = 0x00FF0000; + bmask = 0x0000FF00; + amask = 0x000000FF; +#else + rmask = 0x000000FF; + gmask = 0x0000FF00; + bmask = 0x00FF0000; + amask = 0xFF000000; +#endif + + int w = imgd->getWidth(); + int h = imgd->getHeight(); + int pitch = imgd->getWidth() * 4; + + SDL_Surface *sdlicon = 0; + + { + // We don't want another thread modifying the ImageData mid-copy. + love::thread::Lock lock(imgd->getMutex()); + sdlicon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask); + } + + if (!sdlicon) + return false; + + SDL_SetWindowIcon(window, sdlicon); + SDL_FreeSurface(sdlicon); + + return true; +} + +love::image::ImageData *Window::getIcon() +{ + return curMode.icon; +} + +void Window::swapBuffers() +{ + SDL_GL_SwapWindow(window); +} + +bool Window::hasFocus() const +{ + return (window && SDL_GetKeyboardFocus() == window); +} + +bool Window::hasMouseFocus() const +{ + return (window && SDL_GetMouseFocus() == window); +} + +bool Window::isVisible() const +{ + return window && (SDL_GetWindowFlags(window) & SDL_WINDOW_SHOWN) != 0; +} + +void Window::setMouseVisible(bool visible) +{ + SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE); +} + +bool Window::getMouseVisible() const +{ + return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE); +} + +void Window::setMouseGrab(bool grab) +{ + mouseGrabbed = grab; + if (window) + SDL_SetWindowGrab(window, (SDL_bool) grab); +} + +bool Window::isMouseGrabbed() const +{ + if (window) + return (bool) SDL_GetWindowGrab(window); + else + return mouseGrabbed; +} + +const void *Window::getHandle() const +{ + return window; +} + +love::window::Window *Window::createSingleton() +{ + if (!singleton) + singleton = new Window(); + else + singleton->retain(); + + return singleton; +} + +love::window::Window *Window::getSingleton() +{ + return singleton; +} + +const char *Window::getName() const +{ + return "love.window.sdl"; +} + +} // sdl +} // window +} // love diff --git a/jni/love/src/scripts/boot.lua b/jni/love/src/scripts/boot.lua index ac39cb3c..aac6e071 100644 --- a/jni/love/src/scripts/boot.lua +++ b/jni/love/src/scripts/boot.lua @@ -243,11 +243,6 @@ end -- This can't be overriden. function love.boot() - if type(jit) == 'table' then - SDL.log ("Lua Version = " .. jit.version) - else - SDL.log ("Lua Version = Stock Lua") - end -- This is absolutely needed. require("love") @@ -258,14 +253,8 @@ function love.boot() local o = love.arg.options local arg0 = love.arg.getLow(arg) - SDL.log("trying to load lovegame") --- arg0 = "/sdcard/lovegame/" love.filesystem.init(arg0) - for i,a in ipairs (o.game.arg) do - SDL.log("arg " .. tostring(i) .. " = " .. tostring(a)) - end - -- Is this one of those fancy "fused" games? local can_has_game = pcall(love.filesystem.setSource, arg0) is_fused_game = can_has_game @@ -290,9 +279,7 @@ function love.boot() if can_has_game and not (love.filesystem.exists("main.lua") or love.filesystem.exists("conf.lua")) then no_game_code = true end - - SDL.log("loaded game") - + if not can_has_game then love.nogame() end diff --git a/jni/love/src/scripts/boot.lua.h b/jni/love/src/scripts/boot.lua.h index 3e755cc2..93e248de 100644 --- a/jni/love/src/scripts/boot.lua.h +++ b/jni/love/src/scripts/boot.lua.h @@ -443,16 +443,6 @@ const unsigned char boot_lua[] = 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x6e, 0x2e, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x28, 0x29, 0x0a, - 0x09, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x6a, 0x69, 0x74, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x27, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x27, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, - 0x09, 0x09, 0x53, 0x44, 0x4c, 0x2e, 0x6c, 0x6f, 0x67, 0x20, 0x28, 0x22, 0x4c, 0x75, 0x61, 0x20, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6a, 0x69, 0x74, 0x2e, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a, - 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a, - 0x09, 0x09, 0x53, 0x44, 0x4c, 0x2e, 0x6c, 0x6f, 0x67, 0x20, 0x28, 0x22, 0x4c, 0x75, 0x61, 0x20, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x20, 0x4c, 0x75, 0x61, 0x22, - 0x29, 0x20, 0x20, 0x20, 0x0a, - 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x6c, 0x79, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6c, 0x6f, 0x76, 0x65, 0x22, 0x29, 0x0a, @@ -464,20 +454,8 @@ const unsigned char boot_lua[] = 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x67, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x77, 0x28, 0x61, 0x72, 0x67, 0x29, 0x0a, - 0x09, 0x53, 0x44, 0x4c, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x22, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, - 0x6f, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x67, 0x61, 0x6d, 0x65, 0x22, 0x29, 0x0a, - 0x2d, 0x2d, 0x09, 0x61, 0x72, 0x67, 0x30, 0x20, 0x3d, 0x20, 0x22, 0x2f, 0x73, 0x64, 0x63, 0x61, 0x72, 0x64, - 0x2f, 0x6c, 0x6f, 0x76, 0x65, 0x67, 0x61, 0x6d, 0x65, 0x2f, 0x22, 0x0a, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x28, 0x61, 0x72, 0x67, 0x30, 0x29, 0x0a, - 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x2c, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, - 0x20, 0x28, 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x29, 0x20, 0x64, 0x6f, 0x0a, - 0x09, 0x09, 0x53, 0x44, 0x4c, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x22, 0x61, 0x72, 0x67, 0x20, 0x22, 0x20, 0x2e, - 0x2e, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x69, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, - 0x20, 0x3d, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x61, - 0x29, 0x29, 0x0a, - 0x09, 0x65, 0x6e, 0x64, 0x0a, - 0x09, 0x0a, 0x09, 0x2d, 0x2d, 0x20, 0x49, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x20, 0x22, 0x66, 0x75, 0x73, 0x65, 0x64, 0x22, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x3f, 0x0a, @@ -538,10 +516,6 @@ const unsigned char boot_lua[] = 0x09, 0x09, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, - 0x09, 0x0a, - 0x09, 0x53, 0x44, 0x4c, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x22, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, 0x67, - 0x61, 0x6d, 0x65, 0x22, 0x29, 0x0a, - 0x09, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6e, 0x6f, 0x67, 0x61, 0x6d, 0x65, 0x28, 0x29, 0x0a,