Merge branch 'main' into 12.0-development

This commit is contained in:
Alex Szpakowski
2021-12-24 11:35:35 -04:00
37 changed files with 488 additions and 159 deletions
+19 -26
View File
@@ -9,37 +9,30 @@ jobs:
run: sudo apt-get update
- name: Install Dependencies
run: |
sudo apt-get install --assume-yes build-essential autotools-dev automake libtool pkg-config \
libfreetype6-dev libluajit-5.1-dev libsdl2-dev libopenal-dev \
libogg-dev libvorbis-dev libmodplug-dev libmpg123-dev libtheora-dev
- name: Checkout
uses: actions/checkout@v2
- name: Pre-Configure
run: $PWD/platform/unix/automagic
- name: Configure
run: mkdir build && cd build && ../configure
- name: Build
run: cd build && make -j2
- name: Prepare appimagetool
run: |
cd build &&
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O appimagetool &&
chmod +x appimagetool &&
sudo apt install -y appstream
- name: Clone love-appimages
sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \
libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \
libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \
libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \
libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \
libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \
libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev
- name: Checkout love-appimage-source
uses: actions/checkout@v2
with:
path: build/love-appimages
repository: pfirsich/love-appimages
repository: MikuAuahDark/love-appimage-source
- name: Checkout LÖVE
uses: actions/checkout@v2
with:
path: love2d-${{ github.sha }}
- name: Build AppImage
run: |
cd build &&
python3 love-appimages/build.py .. AppDir --builddir build --appimage love.AppImage
run: make LOVE_BRANCH=${{ github.sha }}
- name: Print LuaJIT branch
run: git -C LuaJIT-v2.1 branch -v
- name: Artifact
uses: actions/upload-artifact@v2-preview
uses: actions/upload-artifact@v2
with:
name: love.AppImage
path: build/love.AppImage
name: love-x86_64.AppImage
path: love-${{ github.sha }}.AppImage
windows-os:
runs-on: windows-latest
strategy:
+9
View File
@@ -38,12 +38,14 @@ LOVE 11.4 [Mysterious Mysteries]
Released: N/A
* Added native arm64 support on macOS.
* Added Body:getLocalPoints.
* Added Font:getKerning.
* Added support for r16, rg16, and rgba16 pixel formats in Canvases.
* Added Shader:send(name, matrixlayout, data, ...) variant, whose argument order is more consistent than Shader:send(name, data, matrixlayout, ...).
* Changed love.timer.getTime to start at 0 when the module is first loaded.
* Changed certain out-of-Lua-memory situations to show a message box instead of instantly crashing.
* Fixed build-time compatibility with Lua 5.4.
* Fixed code compatibility with math.mod and string.gfind when LuaJIT 2.1 is used.
@@ -54,21 +56,28 @@ Released: N/A
* Fixed support for > 2GB dropped files on desktops.
* Fixed love.physics meter scale value persisting after love.event.quit("restart").
* Fixed audio to resume properly after interruption on iOS.
* Fixed love.graphics.newVideo to error instead of crash when an invalid video file is given.
* Fixed initial window creation to set the window's title during creation instead of after.
* Fixed the window's screen position when exiting fullscreen via love.window.setFullscreen.
* Fixed love.displayrotated being given a boolean instead of an enum string.
* Fixed memory corruption and a crash when drawing smooth lines.
* Fixed a crash in Canvas:newImageData when the pixel format's pixel byte size multiplied by its width isn't a multiple of 4.
* Fixed love.graphics.newVolumeImage when explicit mipmaps are provided.
* Fixed freezes and crashes in automatic batching when an AMD GPU is used.
* Fixed love.graphics.print and Image:replacePixels on more AMD/ATI GPUs.
* Fixed Font:setFallbacks to account for different DPI scales in each fallback font.
* Fixed Font:getWrap to not remove trailing newlines.
* Fixed Text:getWidth when the Text's string only contains spaces.
* Fixed a crash with some Intel graphics drivers on Linux.
* Fixed a hang with some Intel graphics drivers on Windows, by preventing gamma correct rendering on affected systems.
* Fixed a crash with some Intel graphics drivers on Windows when mipmapped Canvases are used.
* Fixed texture memory reported by love.graphics.getStats when a volume or array Canvas is created.
* Fixed DXT1 textures which use 1 bit alpha-cutout.
* Fixed rare issues where textures were not sent to shaders correctly.
* Fixed Shader:send(name, data, matrixlayout, ...).
* Fixed quad offsets in ParticleSystems when ParticleSystem:setOffset is not used.
* Fixed rounded rectangles breaking if the rx or ry parameters are negative.
* Fixed rounded rectangle automatic points calculation when rx or ry are more than half the rectangle's size.
* Fixed source code compilation on Xcode 12+.
* Fixed source code compilation on Linux systems that don't provide posix_spawn APIs.
@@ -1769,6 +1769,7 @@
FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = "<group>"; };
FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Texture.h; sourceTree = "<group>"; };
FA620A391AA305F6005DB4C2 /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = "<group>"; };
FA69B918273828DD00CDC2E7 /* jitsetup.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = jitsetup.lua; sourceTree = "<group>"; };
FA6A2B641F5F7B6B0074C308 /* wrap_Data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Data.h; sourceTree = "<group>"; };
FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Data.cpp; sourceTree = "<group>"; };
FA6A2B681F5F7F560074C308 /* DataView.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DataView.cpp; sourceTree = "<group>"; };
@@ -2850,6 +2851,7 @@
FA1E95B4271F932B0044CF08 /* arg.lua */,
FA577A8D16C71D3600860150 /* boot.lua */,
FA1E95B5271F932B0044CF08 /* callbacks.lua */,
FA69B918273828DD00CDC2E7 /* jitsetup.lua */,
FA0B7BFE1A95902C000E1D17 /* love.cpp */,
FA0B7BFF1A95902C000E1D17 /* love.h */,
);
@@ -4208,7 +4210,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1250;
LastUpgradeCheck = 1310;
TargetAttributes = {
FA0B78DC1A958B90000E1D17 = {
CreatedOnToolsVersion = 6.1.1;
@@ -324,7 +324,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1250;
LastUpgradeCheck = 1310;
TargetAttributes = {
FA0B7F051A95AAF3000E1D17 = {
CreatedOnToolsVersion = 6.1.1;
+4 -4
View File
@@ -83,16 +83,16 @@ Dependencies
- Vorbisfile
- Theora
[site]: http://love2d.org
[wiki]: http://love2d.org/wiki
[forums]: http://love2d.org/forums
[site]: https://love2d.org
[wiki]: https://love2d.org/wiki
[forums]: https://love2d.org/forums
[discord]: https://discord.gg/rhUets9
[irc]: irc://irc.oftc.net/love
[dependencies-macos]: https://github.com/slime73/love-apple-dependencies
[dependencies-ios]: https://github.com/love2d/love/releases
[megasource]: https://github.com/love2d/megasource
[unstableppa]: https://launchpad.net/~bartbes/+archive/love-unstable
[aur]: http://aur.archlinux.org/packages/love-git
[aur]: https://aur.archlinux.org/packages/love-git
[love-experiments]: https://github.com/slime73/love-experiments
[codestyle]: https://love2d.org/wiki/Code_Style
[android-repository]: https://github.com/love2d/love-android
+154 -55
View File
@@ -333,24 +333,59 @@ void showRecordingPermissionMissingDialog()
env->DeleteLocalRef(activity);
}
/* A container for AssetManager Java object */
class AssetManagerObject
{
public:
AssetManagerObject()
{
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jobject am = getLocalAssetManager(env);
assetManager = env->NewGlobalRef(am);
env->DeleteLocalRef(am);
}
~AssetManagerObject()
{
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
env->DeleteGlobalRef(assetManager);
}
static jobject getLocalAssetManager(JNIEnv *env) {
jobject self = (jobject) SDL_AndroidGetActivity();
jclass activity = env->GetObjectClass(self);
jmethodID method = env->GetMethodID(activity, "getAssets", "()Landroid/content/res/AssetManager;");
jobject am = env->CallObjectMethod(self, method);
env->DeleteLocalRef(self);
env->DeleteLocalRef(activity);
return am;
}
explicit operator jobject()
{
return assetManager;
};
private:
jobject assetManager;
};
/*
* Helper functions to aid new fusing method
*/
// This returns *global* reference, no need to free it.
static jobject getJavaAssetManager()
{
static AssetManagerObject assetManager;
return (jobject) assetManager;
}
static AAssetManager *getAssetManager()
{
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jobject self = (jobject) SDL_AndroidGetActivity();
jclass activity = env->GetObjectClass(self);
jmethodID method = env->GetMethodID(activity, "getAssetManager", "()Landroid/content/res/AssetManager;");
jobject assetManager = env->CallObjectMethod(self, method);
AAssetManager *assetManagerObject = AAssetManager_fromJava(env, assetManager);
env->DeleteLocalRef(assetManager);
env->DeleteLocalRef(activity);
env->DeleteLocalRef(self);
return assetManagerObject;
return AAssetManager_fromJava(env, (jobject) getJavaAssetManager());
}
namespace aasset
@@ -368,35 +403,6 @@ struct AssetInfo
static std::unordered_map<std::string, PHYSFS_FileType> fileTree;
// Workaround AAsset can't detect whetever something is a directory or doesn't exist
static void buildFileLookup(
AAssetManager *assetManager,
std::unordered_map<std::string, PHYSFS_FileType> &out,
const std::string &path = ""
)
{
if (!path.empty())
{
AAsset *test = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_STREAMING);
if (test)
{
AAsset_close(test);
out[path] = PHYSFS_FILETYPE_REGULAR;
return;
}
out[path] = PHYSFS_FILETYPE_DIRECTORY;
}
AAssetDir *dir = AAssetManager_openDir(assetManager, path.c_str());
const char *file;
while ((file = AAssetDir_getNextFileName(dir)) != nullptr)
buildFileLookup(assetManager, out, file);
AAssetDir_close(dir);
}
PHYSFS_sint64 read(PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
{
AAsset *asset = ((AssetInfo *) io->opaque)->asset;
@@ -505,7 +511,31 @@ void *openArchive(PHYSFS_Io *io, const char *name, int forWrite, int *claimed)
AAssetManager *assetManager = getAssetManager();
if (io::fileTree.empty())
io::buildFileLookup(assetManager, io::fileTree);
{
// AAssetDir_getNextFileName intentionally excludes directories, so
// we have to use JNI that calls AssetManager.list() recursively.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jobject activity = (jobject) SDL_AndroidGetActivity();
jclass clazz = env->GetObjectClass(activity);
jmethodID method = env->GetMethodID(clazz, "buildFileTree", "()[Ljava/lang/String;");
jobjectArray list = (jobjectArray) env->CallObjectMethod(activity, method);
for (jsize i = 0; i < env->GetArrayLength(list); i++)
{
jstring jstr = (jstring) env->GetObjectArrayElement(list, i);
const char *str = env->GetStringUTFChars(jstr, nullptr);
io::fileTree[str + 1] = str[0] == 'd' ? PHYSFS_FILETYPE_DIRECTORY : PHYSFS_FILETYPE_REGULAR;
env->ReleaseStringUTFChars(jstr, str);
env->DeleteLocalRef(jstr);
}
env->DeleteLocalRef(list);
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(activity);
}
return assetManager;
}
@@ -518,33 +548,60 @@ PHYSFS_EnumerateCallbackResult enumerate(
void *callbackdata
)
{
using FileTreeIterator = std::unordered_map<std::string, PHYSFS_FileType>::iterator;
LOVE_UNUSED(opaque);
const char *path = dirname;
if (path == nullptr || (path[0] == '/' && path[1] == 0))
path = "";
AAssetManager *assetManager = (AAssetManager *) opaque;
AAssetDir *dir = AAssetManager_openDir(assetManager, path);
if (dir == nullptr)
if (path[0] != 0)
{
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
return PHYSFS_ENUM_ERROR;
FileTreeIterator result = io::fileTree.find(path);
if (result == io::fileTree.end() || result->second != PHYSFS_FILETYPE_DIRECTORY)
{
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
return PHYSFS_ENUM_ERROR;
}
}
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jobject assetManager = getJavaAssetManager();
jclass clazz = env->GetObjectClass(assetManager);
jmethodID method = env->GetMethodID(clazz, "list", "(Ljava/lang/String;)[Ljava/lang/String;");
jstring jstringDir = env->NewStringUTF(path);
jobjectArray dir = (jobjectArray) env->CallObjectMethod(assetManager, method, jstringDir);
PHYSFS_EnumerateCallbackResult ret = PHYSFS_ENUM_OK;
while (ret == PHYSFS_ENUM_OK)
if (env->ExceptionCheck())
{
const char *name = AAssetDir_getNextFileName(dir);
// IOException occured
ret = PHYSFS_ENUM_ERROR;
env->ExceptionClear();
}
else
{
jsize i = 0;
jsize len = env->GetArrayLength(dir);
// No more files?
if (name == nullptr)
break;
while (ret == PHYSFS_ENUM_OK && i < len) {
jstring jstr = (jstring) env->GetObjectArrayElement(dir, i++);
const char *name = env->GetStringUTFChars(jstr, nullptr);
ret = cb(callbackdata, origdir, name);
ret = cb(callbackdata, origdir, name);
env->ReleaseStringUTFChars(jstr, name);
env->DeleteLocalRef(jstr);
}
env->DeleteLocalRef(dir);
}
AAssetDir_close(dir);
env->DeleteLocalRef(jstringDir);
env->DeleteLocalRef(clazz);
return ret;
}
@@ -724,6 +781,48 @@ bool checkFusedGame(void **physfsIO_Out)
return false;
}
const char *getCRequirePath()
{
static bool initialized = false;
static const char *path = nullptr;
if (!initialized)
{
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jobject activity = (jobject) SDL_AndroidGetActivity();
jclass clazz(env->GetObjectClass(activity));
jmethodID method_id = env->GetMethodID(clazz, "getCRequirePath", "()Ljava/lang/String;");
path = "";
initialized = true;
if (method_id)
{
jstring cpath = (jstring) env->CallObjectMethod(activity, method_id);
const char *utf = env->GetStringUTFChars(cpath, nullptr);
if (utf)
{
path = SDL_strdup(utf);
env->ReleaseStringUTFChars(cpath, utf);
}
env->DeleteLocalRef(cpath);
}
else
{
// NoSuchMethodException is thrown in case methodID is null
env->ExceptionClear();
return "";
}
env->DeleteLocalRef(activity);
env->DeleteLocalRef(clazz);
}
return path;
}
} // android
} // love
+2
View File
@@ -101,6 +101,8 @@ void deinitializeVirtualArchive();
*/
bool checkFusedGame(void **physfsIO_Out);
const char *getCRequirePath();
} // android
} // love
+5 -1
View File
@@ -1156,7 +1156,9 @@ void luax_runwrapper(lua_State *L, const char *filedata, size_t datalen, const c
// functions struct pointer as arguments.
if (lua_istable(L, -1))
{
luaL_loadbuffer(L, filedata, datalen, filename);
std::string chunkname = std::string("=[love \"") + std::string(filename) + std::string("\"]");
luaL_loadbuffer(L, filedata, datalen, chunkname.c_str());
lua_pushvalue(L, -2);
if (ffifuncs != nullptr)
luax_pushpointerasstring(L, ffifuncs);
@@ -1179,8 +1181,10 @@ int luax_resume(lua_State *L, int nargs, int* nres)
#if LUA_VERSION_NUM >= 504
return lua_resume(L, nullptr, nargs, nres);
#elif LUA_VERSION_NUM >= 502
LOVE_UNUSED(nres);
return lua_resume(L, nullptr, nargs);
#else
LOVE_UNUSED(nres);
return lua_resume(L, nargs);
#endif
}
+40 -14
View File
@@ -118,11 +118,30 @@ static size_t find_peer_index(lua_State *l, ENetHost *enet_host, ENetPeer *peer)
#define ENET_ALIGNOF(x) alignof(x)
#endif
// For use with the enet_peers registry.
// Using the pointer directly via lightuserdata would be ideal, but LuaJIT
// cannot use lightuserdata with more than 47 bits whereas some newer arm64
// architectures allow pointers which use more than that.
static lua_Number compute_peer_key(lua_State *L, ENetPeer *peer)
static bool supports_full_lightuserdata(lua_State *L)
{
static bool checked = false;
static bool supported = false;
if (!checked)
{
lua_pushcclosure(L, [](lua_State* L) -> int
{
// Try to push pointer with all bits set.
lua_pushlightuserdata(L, (void*)(~((size_t)0)));
return 1;
}, 0);
supported = lua_pcall(L, 0, 1, 0) == 0;
checked = true;
lua_pop(L, 1);
}
return supported;
}
static uintptr_t compute_peer_key(lua_State *L, ENetPeer *peer)
{
// ENet peers are be allocated on the heap in an array. Lua numbers
// (doubles) can store all possible integers up to 2^53. We can store
@@ -140,21 +159,28 @@ static lua_Number compute_peer_key(lua_State *L, ENetPeer *peer)
static const size_t shift = (size_t) log2((double) minalign);
key >>= shift;
return key >> shift;
}
// Make sure our key isn't larger than 2^53.
if (key > 0x20000000000000ULL)
luaL_error(L, "Cannot push enet peer to Lua: pointer value %p is too large", peer);
return (lua_Number) key;
static void push_peer_key(lua_State *L, uintptr_t key)
{
// If full 64-bit lightuserdata is supported, always use that. Otherwise,
// if the key is smaller than 2^53 (which is integer precision for double
// datatype), then push number. Otherwise, throw error.
if (supports_full_lightuserdata(L))
lua_pushlightuserdata(L, (void*) key);
else if (key > 0x20000000000000ULL) // 2^53
luaL_error(L, "Cannot push enet peer to Lua: pointer value %p is too large", key);
else
lua_pushnumber(L, (lua_Number) key);
}
static void push_peer(lua_State *l, ENetPeer *peer) {
lua_Number key = compute_peer_key(l, peer);
uintptr_t key = compute_peer_key(l, peer);
// try to find in peer table
lua_getfield(l, LUA_REGISTRYINDEX, "enet_peers");
lua_pushnumber(l, key);
push_peer_key(l, key);
lua_gettable(l, -2);
if (lua_isnil(l, -1)) {
@@ -165,7 +191,7 @@ static void push_peer(lua_State *l, ENetPeer *peer) {
luaL_getmetatable(l, "enet_peer");
lua_setmetatable(l, -2);
lua_pushnumber(l, key);
push_peer_key(l, key);
lua_pushvalue(l, -2);
lua_settable(l, -4);
@@ -540,5 +540,5 @@ static const unsigned char B1[]={
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"ftp.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"ftp.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -192,5 +192,5 @@ static const unsigned char B1[]={
108,101,114, 34, 44, 10,125, 10, 10,114,101,116,117,114,110, 32, 95, 77,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"headers.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"headers.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -668,5 +668,5 @@ static const unsigned char B1[]={
101,110,100, 41, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"http.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"http.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -442,5 +442,5 @@ static const unsigned char B1[]={
110,100, 10,101,110,100, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"ltn12.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"ltn12.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -140,5 +140,5 @@ static const unsigned char B1[]={
110,100, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"mbox.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"mbox.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -132,5 +132,5 @@ static const unsigned char B1[]={
116,117,114,110, 32, 95, 77,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"mime.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"mime.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -411,5 +411,5 @@ static const unsigned char B1[]={
110,100, 41, 10, 10,114,101,116,117,114,110, 32, 95, 77,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"smtp.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"smtp.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -230,5 +230,5 @@ static const unsigned char B1[]={
116,117,114,110, 32, 95, 77, 10,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"socket.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"socket.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -196,5 +196,5 @@ static const unsigned char B1[]={
114,110, 32, 95, 77, 10,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"tp.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"tp.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
@@ -563,5 +563,5 @@ static const unsigned char B1[]={
110, 32, 95, 77, 10,
};
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"url.lua")==0) lua_call(L, 0, LUA_MULTRET);
if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"url.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
}
+16 -8
View File
@@ -143,14 +143,6 @@ enum DoneAction
static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &restartvalue)
{
#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)
{
@@ -167,6 +159,22 @@ static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &res
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// LuaJIT-specific setup needs to be done as early as possible - before
// get_app_arguments because that loads external library code. This is also
// loaded inside require("love"). Note that it doesn't use the love table.
love_preload(L, luaopen_love_jitsetup, "love.jitsetup");
lua_getglobal(L, "require");
lua_pushstring(L, "love.jitsetup");
lua_call(L, 1, 0);
#ifdef LOVE_LEGENDARY_APP_ARGV_HACK
int hack_argc = 0;
char **hack_argv = nullptr;
get_app_arguments(argc, argv, hack_argc, hack_argv);
argc = hack_argc;
argv = hack_argv;
#endif // LOVE_LEGENDARY_APP_ARGV_HACK
// Add love to package.preload for easy requiring.
love_preload(L, luaopen_love, "love");
+11
View File
@@ -31,8 +31,19 @@ ByteData *luax_checkbytedata(lua_State *L, int idx)
return luax_checktype<ByteData>(L, idx);
}
int w_ByteData_clone(lua_State *L)
{
ByteData *t = luax_checkbytedata(L, 1);
ByteData *c = nullptr;
luax_catchexcept(L, [&](){ c = t->clone(); });
luax_pushtype(L, c);
c->release();
return 1;
}
static const luaL_Reg w_ByteData_functions[] =
{
{ "clone", w_ByteData_clone },
{ 0, 0 }
};
+12 -1
View File
@@ -26,13 +26,24 @@ namespace love
namespace data
{
DataView *luax_checkdataView(lua_State *L, int idx)
DataView *luax_checkdataview(lua_State *L, int idx)
{
return luax_checktype<DataView>(L, idx);
}
int w_DataView_clone(lua_State *L)
{
DataView *t = luax_checkdataview(L, 1);
DataView *c = nullptr;
luax_catchexcept(L, [&](){ c = t->clone(); });
luax_pushtype(L, c);
c->release();
return 1;
}
static const luaL_Reg w_DataView_functions[] =
{
{ "clone", w_DataView_clone },
{ 0, 0 }
};
+1 -1
View File
@@ -180,7 +180,7 @@ extern "C" int luaopen_love_event(lua_State *L)
int ret = luax_register_module(L, w);
if (luaL_loadbuffer(L, (const char *)event_lua, sizeof(event_lua), "wrap_Event.lua") == 0)
if (luaL_loadbuffer(L, (const char *)event_lua, sizeof(event_lua), "=[love \"wrap_Event.lua\"]") == 0)
lua_call(L, 0, 0);
else
lua_error(L);
+7 -5
View File
@@ -240,15 +240,13 @@ bool Filesystem::setSource(const char *source)
PHYSFS_Io *gameLoveIO;
bool hasFusedGame = love::android::checkFusedGame((void **) &gameLoveIO);
bool isAAssetMounted = false;
if (hasFusedGame)
{
if (gameLoveIO)
{
// Actually we should just be able to mount gameLoveIO, but that's experimental.
gameLoveIO->destroy(gameLoveIO);
goto oldschool;
}
else
{
if (!love::android::initializeVirtualArchive())
@@ -256,11 +254,15 @@ bool Filesystem::setSource(const char *source)
SDL_Log("Unable to mount AAsset: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
return false;
}
// See love::android::initializeVirtualArchive()
new_search_path = "ASET.AASSET";
isAAssetMounted = true;
}
}
else
if (!isAAssetMounted)
{
oldschool:
new_search_path = love::android::getSelectedGameFile();
// try mounting first, if that fails, load to memory and mount
+38 -2
View File
@@ -29,6 +29,10 @@
#include "physfs/Filesystem.h"
#ifdef LOVE_ANDROID
#include "common/android.h"
#endif
// SDL
#include <SDL_loadso.h>
@@ -380,11 +384,22 @@ int w_newFileData(lua_State *L)
}
size_t length = 0;
const char *str = luaL_checklstring(L, 1, &length);
const void *ptr = nullptr;
if (luax_istype(L, 1, Data::type))
{
Data *data = data::luax_checkdata(L, 1);
ptr = data->getData();
length = data->getSize();
}
else if (lua_isstring(L, 1))
ptr = luaL_checklstring(L, 1, &length);
else
return luaL_argerror(L, 1, "string or Data expected");
const char *filename = luaL_checkstring(L, 2);
FileData *t = nullptr;
luax_catchexcept(L, [&](){ t = instance()->newFileData(str, length, filename); });
luax_catchexcept(L, [&](){ t = instance()->newFileData(ptr, length, filename); });
luax_pushtype(L, t);
t->release();
@@ -849,6 +864,23 @@ int extloader(lua_State *L)
void *handle = nullptr;
auto *inst = instance();
#ifdef LOVE_ANDROID
// Specifically Android, look the library path based on getCRequirePath first
std::string androidPath(love::android::getCRequirePath());
if (!androidPath.empty())
{
// Replace ? with just the dotted filename (not tokenized_name)
replaceAll(androidPath, "?", filename);
// Load directly, don't check for existence.
handle = SDL_LoadObject(androidPath.c_str());
}
if (!handle)
{
#endif // LOVE_ANDROID
for (const std::string &el : inst->getCRequirePath())
{
for (const char *ext : library_extensions)
@@ -878,6 +910,10 @@ int extloader(lua_State *L)
break;
}
#ifdef LOVE_ANDROID
} // if (!handle)
#endif
if (!handle)
{
lua_pushfstring(L, "\n\tno file '%s' in LOVE paths.", tokenized_name.c_str());
+4 -7
View File
@@ -901,14 +901,11 @@ void Font::getWrap(const ColoredCodepoints &codepoints, float wraplimit, std::ve
}
// Push the last line.
if (!wline.cps.empty())
{
lines.push_back(wline);
lines.push_back(wline);
// Ignore the width of any trailing spaces, for individual lines.
if (linewidths)
linewidths->push_back(width - widthoftrailingspace);
}
// Ignore the width of any trailing spaces, for individual lines.
if (linewidths)
linewidths->push_back(width - widthoftrailingspace);
}
void Font::getWrap(const std::vector<ColoredString> &text, float wraplimit, std::vector<std::string> &lines, std::vector<int> *linewidths)
+1 -1
View File
@@ -177,7 +177,7 @@ void ParticleSystem::resetOffset()
else
{
Quad::Viewport v = quads[0]->getViewport();
offset = love::Vector2(v.x*0.5f, v.y*0.5f);
offset = love::Vector2(v.w*0.5f, v.h*0.5f);
}
}
+1 -1
View File
@@ -3648,7 +3648,7 @@ extern "C" int luaopen_love_graphics(lua_State *L)
int n = luax_register_module(L, w);
if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "wrap_Graphics.lua") == 0)
if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "=[love \"wrap_Graphics.lua\"]") == 0)
lua_call(L, 0, 0);
else
lua_error(L);
+1 -1
View File
@@ -168,7 +168,7 @@ int luaopen_video(lua_State *L)
{
int ret = luax_register_type(L, &Video::type, functions, nullptr);
luaL_loadbuffer(L, video_lua, sizeof(video_lua), "Video.lua");
luaL_loadbuffer(L, video_lua, sizeof(video_lua), "=[love \"Video.lua\"]");
luax_gettypemetatable(L, Video::type);
lua_call(L, 1, 0);
+27 -4
View File
@@ -440,6 +440,11 @@ bool Joystick::checkCreateHaptic()
bool Joystick::isVibrationSupported()
{
#if SDL_VERSION_ATLEAST(2, 0, 18)
if (isConnected() && SDL_JoystickHasRumble(joyhandle) == SDL_TRUE)
return true;
#endif
if (!checkCreateHaptic())
return false;
@@ -490,8 +495,12 @@ bool Joystick::setVibration(float left, float right, float duration)
if (left == 0.0f && right == 0.0f)
return setVibration();
if (!checkCreateHaptic())
if (!isConnected())
{
vibration.left = vibration.right = 0.0f;
vibration.endtime = SDL_HAPTIC_INFINITY;
return false;
}
Uint32 length = SDL_HAPTIC_INFINITY;
if (duration >= 0.0f)
@@ -501,10 +510,19 @@ bool Joystick::setVibration(float left, float right, float duration)
}
bool success = false;
#if SDL_VERSION_ATLEAST(2, 0, 9)
if (SDL_JoystickRumble(joyhandle, (Uint16)(left * LOVE_UINT16_MAX), (Uint16)(right * LOVE_UINT16_MAX), length) == 0)
success = true;
#endif
if (!success && !checkCreateHaptic())
return false;
unsigned int features = SDL_HapticQuery(haptic);
int axes = SDL_HapticNumAxes(haptic);
if ((features & SDL_HAPTIC_LEFTRIGHT) != 0)
if (!success && (features & SDL_HAPTIC_LEFTRIGHT) != 0)
{
memset(&vibration.effect, 0, sizeof(SDL_HapticEffect));
vibration.effect.type = SDL_HAPTIC_LEFTRIGHT;
@@ -576,9 +594,14 @@ bool Joystick::setVibration(float left, float right, float duration)
bool Joystick::setVibration()
{
bool success = true;
bool success = false;
if (SDL_WasInit(SDL_INIT_HAPTIC) && haptic && SDL_HapticIndex(haptic) != -1)
#if SDL_VERSION_ATLEAST(2, 0, 9)
if (!success)
success = isConnected() && SDL_JoystickRumble(joyhandle, 0, 0, 0) == 0;
#endif
if (!success && SDL_WasInit(SDL_INIT_HAPTIC) && haptic && SDL_HapticIndex(haptic) != -1)
success = (SDL_HapticStopEffect(haptic, vibration.id) == 0);
if (success)
+1 -1
View File
@@ -256,6 +256,7 @@ function love.errhand(msg)
p = p:gsub("%[string \"(.-)\"%]", "%1")
local function draw()
if not love.graphics.isActive() then return end
local pos = 70
love.graphics.clear(89/255, 157/255, 220/255)
love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
@@ -267,7 +268,6 @@ function love.errhand(msg)
if not love.system then return end
love.system.setClipboardText(fullErrorText)
p = p .. "\nCopied to clipboard!"
draw()
end
if love.system then
+71
View File
@@ -0,0 +1,71 @@
R"luastring"--(
-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
-- There is a matching delimiter at the bottom of the file.
--[[
Copyright (c) 2006-2021 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.
--]]
if type(jit) ~= "table" or not jit.status() then
return
end
-- Double the defaults.
jit.opt.start("maxtrace=2000", "maxrecord=8000")
-- Somewhat arbitrary value. Needs to be higher than the combined sizes below,
-- and higher than the default (512) because that's already too low.
jit.opt.start("maxmcode=16384")
if jit.arch == "arm64" then
-- https://github.com/LuaJIT/LuaJIT/issues/285
-- LuaJIT 2.1 on arm64 currently (as of commit b4b2dce) can only use memory
-- for JIT compilation within a certain short range. Other libraries such as
-- SDL can take all the usable space in that range and cause attempts at JIT
-- compilation to both fail and take a long time.
-- This is a very hacky attempt at a workaround. LuaJIT allocates executable
-- code in pools. We'll try "reserving" pools before any external code is
-- executed, by causing JIT compilation via a small loop. We can't easily
-- tell if JIT compilation succeeded, so we do several successively smaller
-- pool allocations in case previous ones fail.
-- This is a really hacky hack and by no means foolproof - there are a lot of
-- potential situations (especially when threads are used) where previously
-- executed external code will still take up space that LuaJIT needed for itself.
jit.opt.start("sizemcode=2048")
for i=1, 100 do end
jit.opt.start("sizemcode=1024")
for i=1, 100 do end
jit.opt.start("sizemcode=512")
for i=1, 100 do end
jit.opt.start("sizemcode=256")
for i=1, 100 do end
jit.opt.start("sizemcode=128")
for i=1, 100 do end
else
-- Somewhat arbitrary value (>= the default).
jit.opt.start("sizemcode=128")
end
-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
--)luastring"--"
+27 -8
View File
@@ -102,6 +102,10 @@ static const char boot_lua[] =
#include "boot.lua"
;
static const char jit_setup_lua[] =
#include "jitsetup.lua"
;
// All modules define a c-accessible luaopen
// so let's make use of those, instead
// of addressing implementations directly.
@@ -165,6 +169,7 @@ extern "C"
extern int luaopen_love_window(lua_State*);
#endif
extern int luaopen_love_nogame(lua_State*);
extern int luaopen_love_jitsetup(lua_State*);
extern int luaopen_love_arg(lua_State*);
extern int luaopen_love_callbacks(lua_State*);
extern int luaopen_love_boot(lua_State*);
@@ -229,6 +234,7 @@ static const luaL_Reg modules[] = {
{ "love.window", luaopen_love_window },
#endif
{ "love.nogame", luaopen_love_nogame },
{ "love.jitsetup", luaopen_love_jitsetup },
{ "love.arg", luaopen_love_arg },
{ "love.callbacks", luaopen_love_callbacks },
{ "love.boot", luaopen_love_boot },
@@ -440,6 +446,15 @@ static void luax_addcompatibilityalias(lua_State *L, const char *module, const c
int luaopen_love(lua_State *L)
{
// Preload module loaders.
for (int i = 0; modules[i].name != nullptr; i++)
love::luax_preload(L, modules[i].func, modules[i].name);
// jitsetup is also loaded in the love executable runlove function. It's
// needed here too for threads. Note that it doesn't use the love table.
love::luax_require(L, "love.jitsetup");
lua_pop(L, 1);
love::luax_insistpinnedthread(L);
love::luax_insistglobal(L, "love");
@@ -543,10 +558,6 @@ int luaopen_love(lua_State *L)
lua_setfield(L, -2, "hasDeprecationOutput");
}
// Preload module loaders.
for (int i = 0; modules[i].name != nullptr; i++)
love::luax_preload(L, modules[i].func, modules[i].name);
// Necessary for Data-creating methods to work properly in Data subclasses.
love::luax_require(L, "love.data");
lua_pop(L, 1);
@@ -693,7 +704,15 @@ int w__setAccelerometerAsJoystick(lua_State *L)
int luaopen_love_nogame(lua_State *L)
{
if (luaL_loadbuffer(L, (const char *)love::nogame_lua, sizeof(love::nogame_lua), "nogame.lua") == 0)
if (luaL_loadbuffer(L, (const char *)love::nogame_lua, sizeof(love::nogame_lua), "=[love \"nogame.lua\"]") == 0)
lua_call(L, 0, 1);
return 1;
}
int luaopen_love_jitsetup(lua_State *L)
{
if (luaL_loadbuffer(L, jit_setup_lua, sizeof(jit_setup_lua), "=[love \"jitsetup.lua\"]") == 0)
lua_call(L, 0, 1);
return 1;
@@ -701,7 +720,7 @@ int luaopen_love_nogame(lua_State *L)
int luaopen_love_arg(lua_State *L)
{
if (luaL_loadbuffer(L, arg_lua, sizeof(arg_lua), "arg.lua") == 0)
if (luaL_loadbuffer(L, arg_lua, sizeof(arg_lua), "=[love \"arg.lua\"]") == 0)
lua_call(L, 0, 1);
return 1;
@@ -709,7 +728,7 @@ int luaopen_love_arg(lua_State *L)
int luaopen_love_callbacks(lua_State *L)
{
if (luaL_loadbuffer(L, callbacks_lua, sizeof(callbacks_lua), "callbacks.lua") == 0)
if (luaL_loadbuffer(L, callbacks_lua, sizeof(callbacks_lua), "=[love \"callbacks.lua\"]") == 0)
lua_call(L, 0, 1);
return 1;
@@ -717,7 +736,7 @@ int luaopen_love_callbacks(lua_State *L)
int luaopen_love_boot(lua_State *L)
{
if (luaL_loadbuffer(L, boot_lua, sizeof(boot_lua), "boot.lua") == 0)
if (luaL_loadbuffer(L, boot_lua, sizeof(boot_lua), "=[love \"boot.lua\"]") == 0)
lua_call(L, 0, 1);
return 1;
+3
View File
@@ -36,6 +36,9 @@ LOVE_EXPORT const char *love_version();
LOVE_EXPORT const char *love_codename();
LOVE_EXPORT int luaopen_love(lua_State *L);
LOVE_EXPORT int luaopen_love_nogame(lua_State *L);
LOVE_EXPORT int luaopen_love_jitsetup(lua_State *L);
LOVE_EXPORT int luaopen_love_arg(lua_State *L);
LOVE_EXPORT int luaopen_love_callbacks(lua_State *L);
LOVE_EXPORT int luaopen_love_boot(lua_State *L);
#ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
+1 -1
View File
@@ -415,7 +415,7 @@ extern "C" int luaopen_love_math(lua_State *L)
int n = luax_register_module(L, w);
// Execute wrap_Math.lua, sending the math table and ffifuncs pointer as args.
luaL_loadbuffer(L, math_lua, sizeof(math_lua), "wrap_Math.lua");
luaL_loadbuffer(L, math_lua, sizeof(math_lua), "=[love \"wrap_Math.lua\"]");
lua_pushvalue(L, -2);
luax_pushpointerasstring(L, &ffifuncs);
lua_call(L, 2, 0);
+18 -5
View File
@@ -43,7 +43,7 @@ OggDemuxer::~OggDemuxer()
ogg_sync_clear(&sync);
}
void OggDemuxer::readPage()
bool OggDemuxer::readPage(bool erroreof)
{
char *syncBuffer = nullptr;
while (ogg_sync_pageout(&sync, &page) != 1)
@@ -53,8 +53,13 @@ void OggDemuxer::readPage()
syncBuffer = ogg_sync_buffer(&sync, 8192);
size_t read = file->read(syncBuffer, 8192);
if (read == 0 && erroreof)
return false;
ogg_sync_wrote(&sync, read);
}
return true;
}
bool OggDemuxer::readPacket(ogg_packet &packet, bool mustSucceed)
@@ -118,22 +123,25 @@ OggDemuxer::StreamType OggDemuxer::findStream()
if (streamInited)
{
eos = false;
streamInited = false;
file->seek(0);
ogg_stream_clear(&stream);
ogg_sync_reset(&sync);
}
streamInited = true;
while (true)
{
if (!readPage(true))
return TYPE_UNKNOWN;
// If this page isn't at the start of a stream, we've seen all streams
readPage();
if (!ogg_page_bos(&page))
break;
videoSerial = ogg_page_serialno(&page);
ogg_stream_init(&stream, videoSerial);
ogg_stream_pagein(&stream, &page);
streamInited = true;
StreamType type = determineType();
switch(type)
@@ -145,10 +153,15 @@ OggDemuxer::StreamType OggDemuxer::findStream()
}
ogg_stream_clear(&stream);
streamInited = false;
}
if (streamInited)
{
streamInited = false;
ogg_stream_clear(&stream);
}
streamInited = false;
ogg_stream_clear(&stream);
ogg_sync_reset(&sync);
return TYPE_UNKNOWN;
+1 -1
View File
@@ -67,7 +67,7 @@ private:
int videoSerial;
bool eos;
void readPage();
bool readPage(bool erroreof = false);
StreamType determineType();
}; // OggDemuxer