Browse Source

updated to latest mobile-common (should fix love.touch index problems)

fysx 11 years ago
parent
commit
97d9154e48
40 changed files with 321 additions and 199 deletions
  1. 1 1
      jni/love/src/common/Data.h
  2. 10 10
      jni/love/src/common/EnumMap.h
  3. 21 22
      jni/love/src/common/StringMap.h
  4. 2 1
      jni/love/src/common/Variant.h
  5. 11 24
      jni/love/src/common/int.h
  6. 1 1
      jni/love/src/common/runtime.cpp
  7. 9 9
      jni/love/src/modules/event/sdl/Event.cpp
  8. 1 1
      jni/love/src/modules/event/sdl/Event.h
  9. 7 7
      jni/love/src/modules/graphics/opengl/ParticleSystem.cpp
  10. 1 1
      jni/love/src/modules/graphics/opengl/ParticleSystem.h
  11. 55 9
      jni/love/src/modules/graphics/opengl/Shader.cpp
  12. 37 18
      jni/love/src/modules/graphics/opengl/Shader.h
  13. 2 2
      jni/love/src/modules/graphics/opengl/SpriteBatch.cpp
  14. 3 0
      jni/love/src/modules/graphics/opengl/wrap_Mesh.cpp
  15. 33 0
      jni/love/src/modules/graphics/opengl/wrap_Shader.cpp
  16. 1 0
      jni/love/src/modules/graphics/opengl/wrap_Shader.h
  17. 1 1
      jni/love/src/modules/joystick/Joystick.cpp
  18. 1 3
      jni/love/src/modules/joystick/Joystick.h
  19. 2 3
      jni/love/src/modules/keyboard/sdl/Keyboard.cpp
  20. 2 0
      jni/love/src/modules/keyboard/sdl/Keyboard.h
  21. 2 2
      jni/love/src/modules/keyboard/wrap_Keyboard.cpp
  22. 6 1
      jni/love/src/modules/math/RandomGenerator.cpp
  23. 2 2
      jni/love/src/modules/mouse/sdl/Cursor.cpp
  24. 2 2
      jni/love/src/modules/mouse/sdl/Mouse.cpp
  25. 1 1
      jni/love/src/modules/mouse/wrap_Cursor.cpp
  26. 3 3
      jni/love/src/modules/mouse/wrap_Mouse.cpp
  27. 3 4
      jni/love/src/modules/physics/box2d/Physics.cpp
  28. 3 3
      jni/love/src/modules/system/wrap_System.cpp
  29. 8 2
      jni/love/src/modules/thread/Channel.h
  30. 8 5
      jni/love/src/modules/thread/LuaThread.h
  31. 2 2
      jni/love/src/modules/thread/Thread.h
  32. 2 1
      jni/love/src/modules/thread/sdl/Thread.h
  33. 6 0
      jni/love/src/modules/thread/sdl/threads.cpp
  34. 11 4
      jni/love/src/modules/thread/sdl/threads.h
  35. 1 1
      jni/love/src/modules/thread/threads.h
  36. 33 40
      jni/love/src/modules/touch/sdl/Touch.cpp
  37. 18 0
      jni/love/src/modules/touch/sdl/Touch.h
  38. 3 4
      jni/love/src/scripts/boot.lua
  39. 4 7
      jni/love/src/scripts/boot.lua.h
  40. 2 2
      jni/love/src/scripts/graphics.lua.h

+ 1 - 1
jni/love/src/common/Data.h

@@ -47,7 +47,7 @@ public:
 	 * Gets a pointer to the data. This pointer will obviously not
 	 * Gets a pointer to the data. This pointer will obviously not
 	 * be valid if the Data object is destroyed.
 	 * be valid if the Data object is destroyed.
 	 **/
 	 **/
-	virtual void *getData() const = 0 ;
+	virtual void *getData() const = 0;
 
 
 	/**
 	/**
 	 * Gets the size of the Data in bytes.
 	 * Gets the size of the Data in bytes.

+ 10 - 10
jni/love/src/common/EnumMap.h

@@ -26,7 +26,7 @@
 namespace love
 namespace love
 {
 {
 
 
-template<typename T, typename U, unsigned PEAK>
+template<typename T, typename U, unsigned int PEAK>
 class EnumMap
 class EnumMap
 {
 {
 public:
 public:
@@ -37,14 +37,14 @@ public:
 		U u;
 		U u;
 	};
 	};
 
 
-	EnumMap(Entry *entries, unsigned size)
+	EnumMap(const Entry *entries, unsigned int size)
 	{
 	{
-		unsigned n = size/sizeof(Entry);
+		unsigned int n = size / sizeof(Entry);
 
 
-		for (unsigned i = 0; i<n; ++i)
+		for (unsigned int i = 0; i < n; ++i)
 		{
 		{
-			unsigned e_t = (unsigned)entries[i].t;
-			unsigned e_u = (unsigned)entries[i].u;
+			unsigned int e_t = (unsigned int) entries[i].t;
+			unsigned int e_u = (unsigned int) entries[i].u;
 
 
 			if (e_t < PEAK)
 			if (e_t < PEAK)
 			{
 			{
@@ -61,9 +61,9 @@ public:
 
 
 	bool find(T t, U &u)
 	bool find(T t, U &u)
 	{
 	{
-		if ((unsigned)t < PEAK && values_u[(unsigned)t].set)
+		if ((unsigned int) t < PEAK && values_u[(unsigned int) t].set)
 		{
 		{
-			u = (U)values_u[(unsigned)t].v;
+			u = (U) values_u[(unsigned int) t].v;
 			return true;
 			return true;
 		}
 		}
 
 
@@ -72,9 +72,9 @@ public:
 
 
 	bool find(U u, T &t)
 	bool find(U u, T &t)
 	{
 	{
-		if ((unsigned)u < PEAK && values_t[(unsigned)u].set)
+		if ((unsigned int) u < PEAK && values_t[(unsigned int) u].set)
 		{
 		{
-			t = (T)values_t[(unsigned)u].v;
+			t = (T) values_t[(unsigned int) u].v;
 			return true;
 			return true;
 		}
 		}
 
 

+ 21 - 22
jni/love/src/common/StringMap.h

@@ -26,7 +26,7 @@
 namespace love
 namespace love
 {
 {
 
 
-template<typename T, unsigned SIZE>
+template<typename T, unsigned int SIZE>
 class StringMap
 class StringMap
 {
 {
 public:
 public:
@@ -37,18 +37,16 @@ public:
 		T value;
 		T value;
 	};
 	};
 
 
-	StringMap(Entry *entries, unsigned num)
+	StringMap(const Entry *entries, unsigned int num)
 	{
 	{
 
 
-		for (unsigned i = 0; i < SIZE; ++i)
-			reverse[i] = 0;
+		for (unsigned int i = 0; i < SIZE; ++i)
+			reverse[i] = nullptr;
 
 
-		unsigned n = num/sizeof(Entry);
+		unsigned int n = num / sizeof(Entry);
 
 
-		for (unsigned i = 0; i < n; ++i)
-		{
+		for (unsigned int i = 0; i < n; ++i)
 			add(entries[i].key, entries[i].value);
 			add(entries[i].key, entries[i].value);
-		}
 	}
 	}
 
 
 	bool streq(const char *a, const char *b)
 	bool streq(const char *a, const char *b)
@@ -57,6 +55,7 @@ public:
 		{
 		{
 			if (*a != *b)
 			if (*a != *b)
 				return false;
 				return false;
+
 			++a;
 			++a;
 			++b;
 			++b;
 		}
 		}
@@ -66,11 +65,11 @@ public:
 
 
 	bool find(const char *key, T &t)
 	bool find(const char *key, T &t)
 	{
 	{
-		unsigned str_hash = djb2(key);
+		unsigned int str_hash = djb2(key);
 
 
-		for (unsigned i = 0; i < MAX; ++i)
+		for (unsigned int i = 0; i < MAX; ++i)
 		{
 		{
-			unsigned str_i = (str_hash + i) % MAX;
+			unsigned int str_i = (str_hash + i) % MAX;
 
 
 			if (!records[str_i].set)
 			if (!records[str_i].set)
 				return false;
 				return false;
@@ -85,14 +84,14 @@ public:
 		return false;
 		return false;
 	}
 	}
 
 
-	bool find(T key, const char  *&str)
+	bool find(T key, const char *&str)
 	{
 	{
-		unsigned index = (unsigned)key;
+		unsigned int index = (unsigned int) key;
 
 
 		if (index >= SIZE)
 		if (index >= SIZE)
 			return false;
 			return false;
 
 
-		if (reverse[index] != 0)
+		if (reverse[index] != nullptr)
 		{
 		{
 			str = reverse[index];
 			str = reverse[index];
 			return true;
 			return true;
@@ -105,12 +104,12 @@ public:
 
 
 	bool add(const char *key, T value)
 	bool add(const char *key, T value)
 	{
 	{
-		unsigned str_hash = djb2(key);
+		unsigned int str_hash = djb2(key);
 		bool inserted = false;
 		bool inserted = false;
 
 
-		for (unsigned i = 0; i < MAX; ++i)
+		for (unsigned int i = 0; i < MAX; ++i)
 		{
 		{
-			unsigned str_i = (str_hash + i) % MAX;
+			unsigned int str_i = (str_hash + i) % MAX;
 
 
 			if (!records[str_i].set)
 			if (!records[str_i].set)
 			{
 			{
@@ -122,11 +121,11 @@ public:
 			}
 			}
 		}
 		}
 
 
-		unsigned index = (unsigned)value;
+		unsigned int index = (unsigned int) value;
 
 
 		if (index >= SIZE)
 		if (index >= SIZE)
 		{
 		{
-			printf("\nConstant %s out of bounds with %i!\n", key, index);
+			printf("Constant %s out of bounds with %u!\n", key, index);
 			return false;
 			return false;
 		}
 		}
 
 
@@ -135,9 +134,9 @@ public:
 		return inserted;
 		return inserted;
 	}
 	}
 
 
-	unsigned djb2(const char *key)
+	unsigned int djb2(const char *key)
 	{
 	{
-		unsigned hash = 5381;
+		unsigned int hash = 5381;
 		int c;
 		int c;
 
 
 		while ((c = *key++))
 		while ((c = *key++))
@@ -156,7 +155,7 @@ private:
 		Record() : set(false) {}
 		Record() : set(false) {}
 	};
 	};
 
 
-	const static unsigned MAX = SIZE*2;
+	static const unsigned int MAX = SIZE * 2;
 
 
 	Record records[MAX];
 	Record records[MAX];
 	const char *reverse[SIZE];
 	const char *reverse[SIZE];

+ 2 - 1
jni/love/src/common/Variant.h

@@ -48,7 +48,6 @@ public:
 	static Variant *fromLua(lua_State *L, int n, bool allowTables = true);
 	static Variant *fromLua(lua_State *L, int n, bool allowTables = true);
 	void toLua(lua_State *L);
 	void toLua(lua_State *L);
 
 
-private:
 	enum Type
 	enum Type
 	{
 	{
 		UNKNOWN = 0,
 		UNKNOWN = 0,
@@ -74,6 +73,8 @@ private:
 		void *userdata;
 		void *userdata;
 		std::vector<std::pair<Variant*, Variant*> > *table;
 		std::vector<std::pair<Variant*, Variant*> > *table;
 	} data;
 	} data;
+
+private:
 	love::Type udatatype;
 	love::Type udatatype;
 	bits flags;
 	bits flags;
 
 

+ 11 - 24
jni/love/src/common/int.h

@@ -21,11 +21,10 @@
 #ifndef LOVE_INT_H
 #ifndef LOVE_INT_H
 #define LOVE_INT_H
 #define LOVE_INT_H
 
 
-#include "common/config.h"
-
-#ifndef LOVE_WINDOWS
+// C standard sized integer types.
+// This header was added to Visual studio in VS 2012, which is LOVE's current
+// minimum supported VS version (as of this comment's commit date.)
 #include <stdint.h>
 #include <stdint.h>
-#endif
 
 
 #define LOVE_INT8_MAX   0x7F
 #define LOVE_INT8_MAX   0x7F
 #define LOVE_UINT8_MAX  0xFF
 #define LOVE_UINT8_MAX  0xFF
@@ -39,26 +38,14 @@
 namespace love
 namespace love
 {
 {
 
 
-// Blame Microsoft
-#ifdef LOVE_WINDOWS
-	typedef __int8 int8;
-	typedef unsigned __int8 uint8;
-	typedef __int16 int16;
-	typedef unsigned __int16 uint16;
-	typedef __int32 int32;
-	typedef unsigned __int32 uint32;
-	typedef __int64 int64;
-	typedef unsigned __int64 uint64;
-#else // LOVE_WINDOWS
-	typedef int8_t int8;
-	typedef uint8_t uint8;
-	typedef int16_t int16;
-	typedef uint16_t uint16;
-	typedef int32_t int32;
-	typedef uint32_t uint32;
-	typedef int64_t int64;
-	typedef uint64_t uint64;
-#endif // LOVE_WINDOWS
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
 
 
 } // love
 } // love
 
 

+ 1 - 1
jni/love/src/common/runtime.cpp

@@ -538,7 +538,7 @@ int luax_insist(lua_State *L, int idx, const char *k)
 {
 {
 	// Convert to absolute index if necessary.
 	// Convert to absolute index if necessary.
 	if (idx < 0 && idx > LUA_REGISTRYINDEX)
 	if (idx < 0 && idx > LUA_REGISTRYINDEX)
-		idx = lua_gettop(L) + ++idx;
+		idx += lua_gettop(L) + 1;
 
 
 	lua_getfield(L, idx, k);
 	lua_getfield(L, idx, k);
 
 

+ 9 - 9
jni/love/src/modules/event/sdl/Event.cpp

@@ -24,6 +24,7 @@
 #include "mouse/Mouse.h"
 #include "mouse/Mouse.h"
 #include "joystick/JoystickModule.h"
 #include "joystick/JoystickModule.h"
 #include "joystick/sdl/Joystick.h"
 #include "joystick/sdl/Joystick.h"
+#include "touch/sdl/Touch.h"
 #include "graphics/Graphics.h"
 #include "graphics/Graphics.h"
 #include "window/Window.h"
 #include "window/Window.h"
 #include "common/Exception.h"
 #include "common/Exception.h"
@@ -123,6 +124,7 @@ Message *Event::convert(const SDL_Event &e) const
 	vargs.reserve(4);
 	vargs.reserve(4);
 
 
 	love::keyboard::Keyboard *kb = nullptr;
 	love::keyboard::Keyboard *kb = nullptr;
+	love::touch::sdl::Touch *touch = nullptr;
 
 
 	love::keyboard::Keyboard::Key key;
 	love::keyboard::Keyboard::Key key;
 	love::mouse::Mouse::Button button;
 	love::mouse::Mouse::Button button;
@@ -214,6 +216,11 @@ Message *Event::convert(const SDL_Event &e) const
 	case SDL_FINGERDOWN:
 	case SDL_FINGERDOWN:
 	case SDL_FINGERUP:
 	case SDL_FINGERUP:
 	case SDL_FINGERMOTION:
 	case SDL_FINGERMOTION:
+		// We need to update the love.touch.sdl internal state from here.
+		touch = (touch::sdl::Touch *) Module::getInstance("love.touch.sdl");
+		if (touch)
+			touch->onEvent(e.tfinger);
+
 		vargs.push_back(new Variant((double) e.tfinger.fingerId));
 		vargs.push_back(new Variant((double) e.tfinger.fingerId));
 		vargs.push_back(new Variant((double) e.tfinger.x));
 		vargs.push_back(new Variant((double) e.tfinger.x));
 		vargs.push_back(new Variant((double) e.tfinger.y));
 		vargs.push_back(new Variant((double) e.tfinger.y));
@@ -312,10 +319,7 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
 
 
 			vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
 			vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
 			vargs.push_back(new Variant((double)(e.jaxis.axis+1)));
 			vargs.push_back(new Variant((double)(e.jaxis.axis+1)));
-			float value = e.jaxis.value / 32768.0f;
-			if (fabsf(value) < 0.001f) value = 0.0f;
-			if (value < -0.99f) value = -1.0f;
-			if (value > 0.99f) value = 1.0f;
+			float value = joystick::Joystick::clampval(e.jaxis.value / 32768.0f);
 			vargs.push_back(new Variant((double) value));
 			vargs.push_back(new Variant((double) value));
 			msg = new Message("joystickaxis", vargs);
 			msg = new Message("joystickaxis", vargs);
 		}
 		}
@@ -364,12 +368,8 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
 				break;
 				break;
 
 
 			vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
 			vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
-
 			vargs.push_back(new Variant(txt, strlen(txt)));
 			vargs.push_back(new Variant(txt, strlen(txt)));
-			float value = e.jaxis.value / 32768.0f;
-			if (fabsf(value) < 0.001f) value = 0.0f;
-			if (value < -0.99f) value = -1.0f;
-			if (value > 0.99f) value = 1.0f;
+			float value = joystick::Joystick::clampval(e.caxis.value / 32768.0f);
 			vargs.push_back(new Variant((double) value));
 			vargs.push_back(new Variant((double) value));
 			msg = new Message("gamepadaxis", vargs);
 			msg = new Message("gamepadaxis", vargs);
 		}
 		}

+ 1 - 1
jni/love/src/modules/event/sdl/Event.h

@@ -80,7 +80,7 @@ private:
 	static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry buttonEntries[];
 	static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry buttonEntries[];
 	static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM> buttons;
 	static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM> buttons;
 
 
-}; // System
+}; // Event
 
 
 } // sdl
 } // sdl
 } // event
 } // event

+ 7 - 7
jni/love/src/modules/graphics/opengl/ParticleSystem.cpp

@@ -286,8 +286,8 @@ void ParticleSystem::initParticle(Particle *p, float t)
 	min = speedMin;
 	min = speedMin;
 	max = speedMax;
 	max = speedMax;
 	float speed = (float) rng.random(min, max);
 	float speed = (float) rng.random(min, max);
-	p->speed = love::Vector(cosf(p->direction), sinf(p->direction));
-	p->speed *= speed;
+	p->velocity = love::Vector(cosf(p->direction), sinf(p->direction));
+	p->velocity *= speed;
 
 
 	p->linearAcceleration.x = (float) rng.random(linearAccelerationMin.x, linearAccelerationMax.x);
 	p->linearAcceleration.x = (float) rng.random(linearAccelerationMin.x, linearAccelerationMax.x);
 	p->linearAcceleration.y = (float) rng.random(linearAccelerationMin.y, linearAccelerationMax.y);
 	p->linearAcceleration.y = (float) rng.random(linearAccelerationMin.y, linearAccelerationMax.y);
@@ -312,7 +312,7 @@ void ParticleSystem::initParticle(Particle *p, float t)
 
 
 	p->angle = p->rotation;
 	p->angle = p->rotation;
 	if (relativeRotation)
 	if (relativeRotation)
-		p->angle += atan2f(p->speed.y, p->speed.x);
+		p->angle += atan2f(p->velocity.y, p->velocity.x);
 
 
 	p->color = colors[0];
 	p->color = colors[0];
 }
 }
@@ -920,11 +920,11 @@ void ParticleSystem::update(float dt)
 			// Resize tangential.
 			// Resize tangential.
 			tangential *= p->tangentialAcceleration;
 			tangential *= p->tangentialAcceleration;
 
 
-			// Update position.
-			p->speed += (radial+tangential+p->linearAcceleration)*dt;
+			// Update velocity.
+			p->velocity += (radial + tangential + p->linearAcceleration) * dt;
 
 
 			// Modify position.
 			// Modify position.
-			ppos += p->speed * dt;
+			ppos += p->velocity * dt;
 
 
 			p->position[0] = ppos.getX();
 			p->position[0] = ppos.getX();
 			p->position[1] = ppos.getY();
 			p->position[1] = ppos.getY();
@@ -937,7 +937,7 @@ void ParticleSystem::update(float dt)
 			p->angle = p->rotation;
 			p->angle = p->rotation;
 
 
 			if (relativeRotation)
 			if (relativeRotation)
-				p->angle += atan2f(p->speed.y, p->speed.x);
+				p->angle += atan2f(p->velocity.y, p->velocity.x);
 
 
 			// Change size according to given intervals:
 			// Change size according to given intervals:
 			// i = 0       1       2      3          n-1
 			// i = 0       1       2      3          n-1

+ 1 - 1
jni/love/src/modules/graphics/opengl/ParticleSystem.h

@@ -517,7 +517,7 @@ protected:
 		// Particles gravitate towards this point.
 		// Particles gravitate towards this point.
 		love::Vector origin;
 		love::Vector origin;
 
 
-		love::Vector speed;
+		love::Vector velocity;
 		love::Vector linearAcceleration;
 		love::Vector linearAcceleration;
 		float radialAcceleration;
 		float radialAcceleration;
 		float tangentialAcceleration;
 		float tangentialAcceleration;

+ 55 - 9
jni/love/src/modules/graphics/opengl/Shader.cpp

@@ -193,8 +193,16 @@ void Shader::createProgram(const std::vector<GLuint> &shaderids)
 		if (!GLAD_ES_VERSION_2_0 && i <= int(OpenGL::ATTRIB_COLOR))
 		if (!GLAD_ES_VERSION_2_0 && i <= int(OpenGL::ATTRIB_COLOR))
 			continue;
 			continue;
 
 
+		OpenGL::VertexAttrib attrib = (OpenGL::VertexAttrib) i;
+
+		// FIXME: We skip this both because pseudo-instancing is temporarily
+		// disabled (see graphics.lua), and because binding a non-existant
+		// attribute name to a location causes a shader linker warning.
+		if (attrib == OpenGL::ATTRIB_PSEUDO_INSTANCE_ID)
+			continue;
+
 		const char *name = nullptr;
 		const char *name = nullptr;
-		if (attribNames.find((OpenGL::VertexAttrib) i, name))
+		if (attribNames.find(attrib, name))
 			glBindAttribLocation(program, i, (const GLchar *) name);
 			glBindAttribLocation(program, i, (const GLchar *) name);
 	}
 	}
 
 
@@ -254,7 +262,7 @@ void Shader::mapActiveUniforms()
 		}
 		}
 
 
 		// If this is a built-in (LOVE-created) uniform, store the location.
 		// If this is a built-in (LOVE-created) uniform, store the location.
-		BuiltinExtern builtin;
+		BuiltinUniform builtin;
 		if (builtinNames.find(u.name.c_str(), builtin))
 		if (builtinNames.find(u.name.c_str(), builtin))
 			builtinUniforms[int(builtin)] = u.location;
 			builtinUniforms[int(builtin)] = u.location;
 
 
@@ -685,19 +693,36 @@ int Shader::getTextureUnit(const std::string &name)
 	return texunit;
 	return texunit;
 }
 }
 
 
+Shader::UniformType Shader::getExternVariable(const std::string &name, int &components, int &count)
+{
+	auto it = uniforms.find(name);
+
+	if (it == uniforms.end())
+	{
+		components = 0;
+		count = 0;
+		return UNIFORM_UNKNOWN;
+	}
+
+	components = getUniformTypeSize(it->second.type);
+	count = (int) it->second.count;
+
+	return it->second.baseType;
+}
+
 bool Shader::hasVertexAttrib(OpenGL::VertexAttrib attrib) const
 bool Shader::hasVertexAttrib(OpenGL::VertexAttrib attrib) const
 {
 {
 	return vertexAttributes[int(attrib)] != -1;
 	return vertexAttributes[int(attrib)] != -1;
 }
 }
 
 
-bool Shader::hasBuiltinExtern(BuiltinExtern builtin) const
+bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const
 {
 {
 	return builtinUniforms[int(builtin)] != -1;
 	return builtinUniforms[int(builtin)] != -1;
 }
 }
 
 
-bool Shader::sendBuiltinFloat(BuiltinExtern builtin, int size, const GLfloat *vec, int count)
+bool Shader::sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *vec, int count)
 {
 {
-	if (!hasBuiltinExtern(builtin))
+	if (!hasBuiltinUniform(builtin))
 		return false;
 		return false;
 
 
 	GLint location = builtinUniforms[int(builtin)];
 	GLint location = builtinUniforms[int(builtin)];
@@ -725,9 +750,9 @@ bool Shader::sendBuiltinFloat(BuiltinExtern builtin, int size, const GLfloat *ve
 	return true;
 	return true;
 }
 }
 
 
-bool Shader::sendBuiltinMatrix(BuiltinExtern builtin, int size, const GLfloat *m, int count)
+bool Shader::sendBuiltinMatrix(BuiltinUniform builtin, int size, const GLfloat *m, int count)
 {
 {
-	if (!hasBuiltinExtern(builtin))
+	if (!hasBuiltinUniform(builtin))
 		return false;
 		return false;
 
 
 	GLint location = builtinUniforms[GLint(builtin)];
 	GLint location = builtinUniforms[GLint(builtin)];
@@ -818,6 +843,16 @@ bool Shader::isSupported()
 	return GLAD_ES_VERSION_2_0 || (GLAD_VERSION_2_0 && getGLSLVersion() >= "1.2");
 	return GLAD_ES_VERSION_2_0 || (GLAD_VERSION_2_0 && getGLSLVersion() >= "1.2");
 }
 }
 
 
+bool Shader::getConstant(const char *in, UniformType &out)
+{
+	return uniformTypes.find(in, out);
+}
+
+bool Shader::getConstant(UniformType in, const char *&out)
+{
+	return uniformTypes.find(in, out);
+}
+
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntries[] =
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntries[] =
 {
 {
 	{"vertex", Shader::TYPE_VERTEX},
 	{"vertex", Shader::TYPE_VERTEX},
@@ -826,6 +861,17 @@ StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntr
 
 
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM> Shader::typeNames(Shader::typeNameEntries, sizeof(Shader::typeNameEntries));
 StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM> Shader::typeNames(Shader::typeNameEntries, sizeof(Shader::typeNameEntries));
 
 
+StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM>::Entry Shader::uniformTypeEntries[] =
+{
+	{"float", Shader::UNIFORM_FLOAT},
+	{"int", Shader::UNIFORM_INT},
+	{"bool", Shader::UNIFORM_BOOL},
+	{"image", Shader::UNIFORM_SAMPLER},
+	{"unknown", Shader::UNIFORM_UNKNOWN},
+};
+
+StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM> Shader::uniformTypes(Shader::uniformTypeEntries, sizeof(Shader::uniformTypeEntries));
+
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry Shader::attribNameEntries[] =
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry Shader::attribNameEntries[] =
 {
 {
 	{"VertexPosition", OpenGL::ATTRIB_POS},
 	{"VertexPosition", OpenGL::ATTRIB_POS},
@@ -836,7 +882,7 @@ StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry Shader::attribNa
 
 
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries));
 StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries));
 
 
-StringMap<Shader::BuiltinExtern, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builtinNameEntries[] =
+StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builtinNameEntries[] =
 {
 {
 	{"TransformMatrix", Shader::BUILTIN_TRANSFORM_MATRIX},
 	{"TransformMatrix", Shader::BUILTIN_TRANSFORM_MATRIX},
 	{"ProjectionMatrix", Shader::BUILTIN_PROJECTION_MATRIX},
 	{"ProjectionMatrix", Shader::BUILTIN_PROJECTION_MATRIX},
@@ -845,7 +891,7 @@ StringMap<Shader::BuiltinExtern, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builti
 	{"love_ScreenSize", Shader::BUILTIN_SCREEN_SIZE},
 	{"love_ScreenSize", Shader::BUILTIN_SCREEN_SIZE},
 };
 };
 
 
-StringMap<Shader::BuiltinExtern, Shader::BUILTIN_MAX_ENUM> Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries));
+StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries));
 
 
 } // opengl
 } // opengl
 } // graphics
 } // graphics

+ 37 - 18
jni/love/src/modules/graphics/opengl/Shader.h

@@ -60,8 +60,8 @@ public:
 		TYPE_MAX_ENUM
 		TYPE_MAX_ENUM
 	};
 	};
 
 
-	// Built-in extern (uniform) variables.
-	enum BuiltinExtern
+	// Built-in uniform (extern) variables.
+	enum BuiltinUniform
 	{
 	{
 		BUILTIN_TRANSFORM_MATRIX = 0,
 		BUILTIN_TRANSFORM_MATRIX = 0,
 		BUILTIN_PROJECTION_MATRIX,
 		BUILTIN_PROJECTION_MATRIX,
@@ -71,6 +71,17 @@ public:
 		BUILTIN_MAX_ENUM
 		BUILTIN_MAX_ENUM
 	};
 	};
 
 
+	// Types of potential uniform (extern) variables used in love's shaders.
+	enum UniformType
+	{
+		UNIFORM_FLOAT,
+		UNIFORM_INT,
+		UNIFORM_BOOL,
+		UNIFORM_SAMPLER,
+		UNIFORM_UNKNOWN,
+		UNIFORM_MAX_ENUM
+	};
+
 	// Type for a list of shader source codes in the form of sources[shadertype] = code
 	// Type for a list of shader source codes in the form of sources[shadertype] = code
 	typedef std::map<ShaderType, std::string> ShaderSources;
 	typedef std::map<ShaderType, std::string> ShaderSources;
 
 
@@ -143,13 +154,26 @@ public:
 	 **/
 	 **/
 	void sendTexture(const std::string &name, Texture *texture);
 	void sendTexture(const std::string &name, Texture *texture);
 
 
+	/**
+	 * Gets the type, number of components, and number of array elements of
+	 * an active 'extern' (uniform) variable in the shader. If a uniform
+	 * variable with the specified name doesn't exist, returns UNIFORM_UNKNOWN
+	 * and sets the 'components' and 'count' values to 0.
+	 *
+	 * @param name The name of the uniform variable in the source code.
+	 * @param[out] components Number of components of the variable (2 for vec2.)
+	 * @param[out] count Number of array elements, if the variable is an array.
+	 * @return The base type of the uniform variable.
+	 **/
+	UniformType getExternVariable(const std::string &name, int &components, int &count);
+
 	/**
 	/**
 	 * Internal use only.
 	 * Internal use only.
 	 **/
 	 **/
 	bool hasVertexAttrib(OpenGL::VertexAttrib attrib) const;
 	bool hasVertexAttrib(OpenGL::VertexAttrib attrib) const;
-	bool hasBuiltinExtern(BuiltinExtern builtin) const;
-	bool sendBuiltinMatrix(BuiltinExtern builtin, int size, const GLfloat *m, int count);
-	bool sendBuiltinFloat(BuiltinExtern builtin, int size, const GLfloat *m, int count);
+	bool hasBuiltinUniform(BuiltinUniform builtin) const;
+	bool sendBuiltinMatrix(BuiltinUniform builtin, int size, const GLfloat *m, int count);
+	bool sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *m, int count);
 	void checkSetScreenParams();
 	void checkSetScreenParams();
 
 
 	const std::map<std::string, Object *> &getBoundRetainables() const;
 	const std::map<std::string, Object *> &getBoundRetainables() const;
@@ -160,17 +184,10 @@ public:
 	// Default code used when renderers require code for a shader stage.
 	// Default code used when renderers require code for a shader stage.
 	static ShaderSources defaultCode[Graphics::RENDERER_MAX_ENUM];
 	static ShaderSources defaultCode[Graphics::RENDERER_MAX_ENUM];
 
 
-private:
+	static bool getConstant(const char *in, UniformType &out);
+	static bool getConstant(UniformType in, const char *&out);
 
 
-	// Types of potential uniform variables used in love's shaders.
-	enum UniformType
-	{
-		UNIFORM_FLOAT,
-		UNIFORM_INT,
-		UNIFORM_BOOL,
-		UNIFORM_SAMPLER,
-		UNIFORM_UNKNOWN
-	};
+private:
 
 
 	// Represents a single uniform/extern shader variable.
 	// Represents a single uniform/extern shader variable.
 	struct Uniform
 	struct Uniform
@@ -241,13 +258,15 @@ private:
 	static StringMap<ShaderType, TYPE_MAX_ENUM>::Entry typeNameEntries[];
 	static StringMap<ShaderType, TYPE_MAX_ENUM>::Entry typeNameEntries[];
 	static StringMap<ShaderType, TYPE_MAX_ENUM> typeNames;
 	static StringMap<ShaderType, TYPE_MAX_ENUM> typeNames;
 
 
+	static StringMap<UniformType, UNIFORM_MAX_ENUM>::Entry uniformTypeEntries[];
+	static StringMap<UniformType, UNIFORM_MAX_ENUM> uniformTypes;
+
 	// Names for the generic vertex attributes used by love.
 	// Names for the generic vertex attributes used by love.
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry attribNameEntries[];
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM>::Entry attribNameEntries[];
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> attribNames;
 	static StringMap<OpenGL::VertexAttrib, OpenGL::ATTRIB_MAX_ENUM> attribNames;
 
 
-	// Names for the built-in uniform variables.
-	static StringMap<BuiltinExtern, BUILTIN_MAX_ENUM>::Entry builtinNameEntries[];
-	static StringMap<BuiltinExtern, BUILTIN_MAX_ENUM> builtinNames;
+	static StringMap<BuiltinUniform, BUILTIN_MAX_ENUM>::Entry builtinNameEntries[];
+	static StringMap<BuiltinUniform, BUILTIN_MAX_ENUM> builtinNames;
 
 
 }; // Shader
 }; // Shader
 
 

+ 2 - 2
jni/love/src/modules/graphics/opengl/SpriteBatch.cpp

@@ -111,7 +111,7 @@ int SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, fl
 	memcpy(sprite, texture->getVertices(), sizeof(Vertex) * 4);
 	memcpy(sprite, texture->getVertices(), sizeof(Vertex) * 4);
 
 
 	// Transform.
 	// Transform.
-	static Matrix t;
+	Matrix t;
 	t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 	t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 	t.transform(sprite, sprite, 4);
 	t.transform(sprite, sprite, 4);
 
 
@@ -138,7 +138,7 @@ int SpriteBatch::addq(Quad *quad, float x, float y, float a, float sx, float sy,
 	// Needed for colors.
 	// Needed for colors.
 	memcpy(sprite, quad->getVertices(), sizeof(Vertex) * 4);
 	memcpy(sprite, quad->getVertices(), sizeof(Vertex) * 4);
 
 
-	static Matrix t;
+	Matrix t;
 	t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 	t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 	t.transform(sprite, sprite, 4);
 	t.transform(sprite, sprite, 4);
 
 

+ 3 - 0
jni/love/src/modules/graphics/opengl/wrap_Mesh.cpp

@@ -147,6 +147,9 @@ int w_Mesh_getVertices(lua_State *L)
 	size_t count = t->getVertexCount();
 	size_t count = t->getVertexCount();
 	lua_createtable(L, count, 0);
 	lua_createtable(L, count, 0);
 
 
+	if (count == 0 || vertices == nullptr)
+		return 1;
+
 	for (size_t i = 0; i < count; i++)
 	for (size_t i = 0; i < count; i++)
 	{
 	{
 		// Create vertex table.
 		// Create vertex table.

+ 33 - 0
jni/love/src/modules/graphics/opengl/wrap_Shader.cpp

@@ -346,6 +346,38 @@ int w_Shader_send(lua_State *L)
 	return luaL_argerror(L, 3, "number, boolean, table, image, or canvas expected");
 	return luaL_argerror(L, 3, "number, boolean, table, image, or canvas expected");
 }
 }
 
 
+int w_Shader_getExternVariable(lua_State *L)
+{
+	Shader *shader = luax_checkshader(L, 1);
+	const char *name = luaL_checkstring(L, 2);
+
+	int components = 0;
+	int arrayelements = 0;
+	Shader::UniformType type = Shader::UNIFORM_UNKNOWN;
+
+	type = shader->getExternVariable(name, components, arrayelements);
+
+	// Check if the variable exists (function will set components to 0 if not.)
+	if (components > 0)
+	{
+		const char *tname = nullptr;
+		if (!Shader::getConstant(type, tname))
+			return luaL_error(L, "Unknown extern variable type name.");
+
+		lua_pushstring(L, tname);
+		lua_pushinteger(L, components);
+		lua_pushinteger(L, arrayelements);
+	}
+	else
+	{
+		lua_pushnil(L);
+		lua_pushnil(L);
+		lua_pushnil(L);
+	}
+
+	return 3;
+}
+
 static const luaL_Reg functions[] =
 static const luaL_Reg functions[] =
 {
 {
 	{ "getWarnings", w_Shader_getWarnings },
 	{ "getWarnings", w_Shader_getWarnings },
@@ -355,6 +387,7 @@ static const luaL_Reg functions[] =
 	{ "sendMatrix",  w_Shader_sendMatrix },
 	{ "sendMatrix",  w_Shader_sendMatrix },
 	{ "sendTexture", w_Shader_sendTexture },
 	{ "sendTexture", w_Shader_sendTexture },
 	{ "send",        w_Shader_send },
 	{ "send",        w_Shader_send },
+	{ "getExternVariable", w_Shader_getExternVariable },
 
 
 	// Deprecated since 0.9.1.
 	// Deprecated since 0.9.1.
 	{ "sendImage",   w_Shader_sendTexture },
 	{ "sendImage",   w_Shader_sendTexture },

+ 1 - 0
jni/love/src/modules/graphics/opengl/wrap_Shader.h

@@ -38,6 +38,7 @@ int w_Shader_sendFloat(lua_State *L);
 int w_Shader_sendMatrix(lua_State *L);
 int w_Shader_sendMatrix(lua_State *L);
 int w_Shader_sendTexture(lua_State *L);
 int w_Shader_sendTexture(lua_State *L);
 int w_Shader_send(lua_State *L);
 int w_Shader_send(lua_State *L);
+int w_Shader_getExternVariable(lua_State *L);
 extern "C" int luaopen_shader(lua_State *L);
 extern "C" int luaopen_shader(lua_State *L);
 
 
 } // opengl
 } // opengl

+ 1 - 1
jni/love/src/modules/joystick/Joystick.cpp

@@ -29,7 +29,7 @@ namespace love
 namespace joystick
 namespace joystick
 {
 {
 
 
-float Joystick::clampval(float x) const
+float Joystick::clampval(float x)
 {
 {
 	if (fabsf(x) < 0.01)
 	if (fabsf(x) < 0.01)
 		return 0.0f;
 		return 0.0f;

+ 1 - 3
jni/love/src/modules/joystick/Joystick.h

@@ -173,9 +173,7 @@ public:
 	static bool getConstant(const char *in, InputType &out);
 	static bool getConstant(const char *in, InputType &out);
 	static bool getConstant(InputType in, const char *&out);
 	static bool getConstant(InputType in, const char *&out);
 
 
-protected:
-
-	float clampval(float x) const;
+	static float clampval(float x);
 
 
 private:
 private:
 
 

+ 2 - 3
jni/love/src/modules/keyboard/sdl/Keyboard.cpp

@@ -51,12 +51,11 @@ bool Keyboard::hasKeyRepeat() const
 
 
 bool Keyboard::isDown(Key *keylist) const
 bool Keyboard::isDown(Key *keylist) const
 {
 {
-	const Uint8 *keystate = SDL_GetKeyboardState(0);
-	std::map<Key, SDL_Keycode>::const_iterator it;
+	const Uint8 *keystate = SDL_GetKeyboardState(nullptr);
 
 
 	for (Key key = *keylist; key != KEY_MAX_ENUM; key = *(++keylist))
 	for (Key key = *keylist; key != KEY_MAX_ENUM; key = *(++keylist))
 	{
 	{
-		it = keys.find(key);
+		auto it = keys.find(key);
 		if (it != keys.end() && keystate[SDL_GetScancodeFromKey(it->second)])
 		if (it != keys.end() && keystate[SDL_GetScancodeFromKey(it->second)])
 			return true;
 			return true;
 	}
 	}

+ 2 - 0
jni/love/src/modules/keyboard/sdl/Keyboard.h

@@ -56,6 +56,8 @@ public:
 
 
 private:
 private:
 
 
+	// Whether holding down a key triggers repeated key press events.
+	// The real implementation is in love::event::sdl::Event::Convert.
 	bool key_repeat;
 	bool key_repeat;
 
 
 	static std::map<Key, SDL_Keycode> createKeyMap();
 	static std::map<Key, SDL_Keycode> createKeyMap();

+ 2 - 2
jni/love/src/modules/keyboard/wrap_Keyboard.cpp

@@ -29,7 +29,7 @@ namespace love
 namespace keyboard
 namespace keyboard
 {
 {
 
 
-static Keyboard *instance = 0;
+static Keyboard *instance = nullptr;
 
 
 int w_setKeyRepeat(lua_State *L)
 int w_setKeyRepeat(lua_State *L)
 {
 {
@@ -87,7 +87,7 @@ static const luaL_Reg functions[] =
 
 
 extern "C" int luaopen_love_keyboard(lua_State *L)
 extern "C" int luaopen_love_keyboard(lua_State *L)
 {
 {
-	if (instance == 0)
+	if (instance == nullptr)
 	{
 	{
 		EXCEPT_GUARD(instance = new love::keyboard::sdl::Keyboard();)
 		EXCEPT_GUARD(instance = new love::keyboard::sdl::Keyboard();)
 	}
 	}

+ 6 - 1
jni/love/src/modules/math/RandomGenerator.cpp

@@ -77,10 +77,15 @@ void RandomGenerator::setSeed(RandomGenerator::Seed newseed)
 {
 {
 	// 0 xor 0 is still 0, so Xorshift can't generate new numbers.
 	// 0 xor 0 is still 0, so Xorshift can't generate new numbers.
 	if (newseed.b64 == 0)
 	if (newseed.b64 == 0)
-		throw love::Exception("Invalid random seed.");
+		throw love::Exception("Random seed cannot be 0.");
 
 
 	seed = newseed;
 	seed = newseed;
 	rng_state = seed;
 	rng_state = seed;
+
+	// Xorshift's first couple results after seeding will be similar to results
+	// from very similar seeds, so we immediately discard them here.
+	for (int i = 0; i < 2; i++)
+		rand();
 }
 }
 
 
 RandomGenerator::Seed RandomGenerator::getSeed() const
 RandomGenerator::Seed RandomGenerator::getSeed() const

+ 2 - 2
jni/love/src/modules/mouse/sdl/Cursor.cpp

@@ -30,7 +30,7 @@ namespace sdl
 {
 {
 
 
 Cursor::Cursor(image::ImageData *data, int hotx, int hoty)
 Cursor::Cursor(image::ImageData *data, int hotx, int hoty)
-	: cursor(0)
+	: cursor(nullptr)
 	, type(CURSORTYPE_IMAGE)
 	, type(CURSORTYPE_IMAGE)
 	, systemType(CURSOR_MAX_ENUM)
 	, systemType(CURSOR_MAX_ENUM)
 {
 {
@@ -63,7 +63,7 @@ Cursor::Cursor(image::ImageData *data, int hotx, int hoty)
 }
 }
 
 
 Cursor::Cursor(mouse::Cursor::SystemCursor cursortype)
 Cursor::Cursor(mouse::Cursor::SystemCursor cursortype)
-	: cursor(0)
+	: cursor(nullptr)
 	, type(CURSORTYPE_SYSTEM)
 	, type(CURSORTYPE_SYSTEM)
 	, systemType(cursortype)
 	, systemType(cursortype)
 {
 {

+ 2 - 2
jni/love/src/modules/mouse/sdl/Mouse.cpp

@@ -75,7 +75,7 @@ const char *Mouse::getName() const
 }
 }
 
 
 Mouse::Mouse()
 Mouse::Mouse()
-	: curCursor(0)
+	: curCursor(nullptr)
 {
 {
 }
 }
 
 
@@ -191,7 +191,7 @@ void Mouse::setVisible(bool visible)
 
 
 bool Mouse::isDown(Button *buttonlist) const
 bool Mouse::isDown(Button *buttonlist) const
 {
 {
-	Uint32 buttonstate = SDL_GetMouseState(0, 0);
+	Uint32 buttonstate = SDL_GetMouseState(nullptr, nullptr);
 
 
 	for (Button button = *buttonlist; button != BUTTON_MAX_ENUM; button = *(++buttonlist))
 	for (Button button = *buttonlist; button != BUTTON_MAX_ENUM; button = *(++buttonlist))
 	{
 	{

+ 1 - 1
jni/love/src/modules/mouse/wrap_Cursor.cpp

@@ -36,7 +36,7 @@ int w_Cursor_getType(lua_State *L)
 	Cursor *cursor = luax_checkcursor(L, 1);
 	Cursor *cursor = luax_checkcursor(L, 1);
 
 
 	Cursor::CursorType ctype = cursor->getType();
 	Cursor::CursorType ctype = cursor->getType();
-	const char *typestr = 0;
+	const char *typestr = nullptr;
 
 
 	if (ctype == Cursor::CURSORTYPE_IMAGE)
 	if (ctype == Cursor::CURSORTYPE_IMAGE)
 		mouse::Cursor::getConstant(ctype, typestr);
 		mouse::Cursor::getConstant(ctype, typestr);

+ 3 - 3
jni/love/src/modules/mouse/wrap_Mouse.cpp

@@ -30,11 +30,11 @@ namespace love
 namespace mouse
 namespace mouse
 {
 {
 
 
-static Mouse *instance = 0;
+static Mouse *instance = nullptr;
 
 
 int w_newCursor(lua_State *L)
 int w_newCursor(lua_State *L)
 {
 {
-	Cursor *cursor = 0;
+	Cursor *cursor = nullptr;
 
 
 	if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
 	if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
 		luax_convobj(L, 1, "image", "newImageData");
 		luax_convobj(L, 1, "image", "newImageData");
@@ -212,7 +212,7 @@ static const lua_CFunction types[] =
 
 
 extern "C" int luaopen_love_mouse(lua_State *L)
 extern "C" int luaopen_love_mouse(lua_State *L)
 {
 {
-	if (instance == 0)
+	if (instance == nullptr)
 	{
 	{
 		EXCEPT_GUARD(instance = new love::mouse::sdl::Mouse();)
 		EXCEPT_GUARD(instance = new love::mouse::sdl::Mouse();)
 	}
 	}

+ 3 - 4
jni/love/src/modules/physics/box2d/Physics.cpp

@@ -133,12 +133,12 @@ int Physics::newPolygonShape(lua_State *L)
 int Physics::newChainShape(lua_State *L)
 int Physics::newChainShape(lua_State *L)
 {
 {
 	int argc = lua_gettop(L)-1; // first argument is looping
 	int argc = lua_gettop(L)-1; // first argument is looping
-	int vcount = (int)argc/2;
+	if (argc % 2 != 0)
+		return luaL_error(L, "Number of vertex components must be a multiple of two.");
 
 
+	int vcount = (int)argc/2;
 	b2ChainShape *s = new b2ChainShape();
 	b2ChainShape *s = new b2ChainShape();
-
 	bool loop = luax_toboolean(L, 1);
 	bool loop = luax_toboolean(L, 1);
-
 	b2Vec2 *vecs = new b2Vec2[vcount];
 	b2Vec2 *vecs = new b2Vec2[vcount];
 
 
 	for (int i = 0; i<vcount; i++)
 	for (int i = 0; i<vcount; i++)
@@ -166,7 +166,6 @@ int Physics::newChainShape(lua_State *L)
 	delete[] vecs;
 	delete[] vecs;
 
 
 	ChainShape *c = new ChainShape(s);
 	ChainShape *c = new ChainShape(s);
-
 	luax_pushtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, c);
 	luax_pushtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, c);
 	return 1;
 	return 1;
 }
 }

+ 3 - 3
jni/love/src/modules/system/wrap_System.cpp

@@ -27,7 +27,7 @@ namespace love
 namespace system
 namespace system
 {
 {
 
 
-static System *instance = 0;
+static System *instance = nullptr;
 
 
 int w_getOS(lua_State *L)
 int w_getOS(lua_State *L)
 {
 {
@@ -99,7 +99,7 @@ static const luaL_Reg functions[] =
 
 
 extern "C" int luaopen_love_system(lua_State *L)
 extern "C" int luaopen_love_system(lua_State *L)
 {
 {
-	if (instance == 0)
+	if (instance == nullptr)
 	{
 	{
 		instance = new love::system::sdl::System();
 		instance = new love::system::sdl::System();
 	}
 	}
@@ -111,7 +111,7 @@ extern "C" int luaopen_love_system(lua_State *L)
 	w.name = "system";
 	w.name = "system";
 	w.flags = MODULE_T;
 	w.flags = MODULE_T;
 	w.functions = functions;
 	w.functions = functions;
-	w.types = 0;
+	w.types = nullptr;
 
 
 	return luax_register_module(L, w);
 	return luax_register_module(L, w);
 }
 }

+ 8 - 2
jni/love/src/modules/thread/Channel.h

@@ -26,13 +26,14 @@
 #include <string>
 #include <string>
 
 
 // LOVE
 // LOVE
-#include <common/Variant.h>
-#include <thread/threads.h>
+#include "common/Variant.h"
+#include "threads.h"
 
 
 namespace love
 namespace love
 {
 {
 namespace thread
 namespace thread
 {
 {
+
 class Channel : public love::Object
 class Channel : public love::Object
 {
 {
 // FOR WRAPPER USE ONLY
 // FOR WRAPPER USE ONLY
@@ -40,8 +41,10 @@ friend void retainVariant(Channel *, Variant *);
 friend void releaseVariant(Channel *, Variant *);
 friend void releaseVariant(Channel *, Variant *);
 
 
 public:
 public:
+
 	Channel();
 	Channel();
 	~Channel();
 	~Channel();
+
 	static Channel *getChannel(const std::string &name);
 	static Channel *getChannel(const std::string &name);
 
 
 	unsigned long push(Variant *var);
 	unsigned long push(Variant *var);
@@ -56,6 +59,7 @@ public:
 	void release();
 	void release();
 
 
 private:
 private:
+
 	Channel(const std::string &name);
 	Channel(const std::string &name);
 	void lockMutex();
 	void lockMutex();
 	void unlockMutex();
 	void unlockMutex();
@@ -68,7 +72,9 @@ private:
 
 
 	unsigned long sent;
 	unsigned long sent;
 	unsigned long received;
 	unsigned long received;
+
 }; // Channel
 }; // Channel
+
 } // thread
 } // thread
 } // love
 } // love
 
 

+ 8 - 5
jni/love/src/modules/thread/LuaThread.h

@@ -25,15 +25,16 @@
 #include <string>
 #include <string>
 
 
 // LOVE
 // LOVE
-#include <common/Data.h>
-#include <common/Object.h>
-#include <common/Variant.h>
-#include <thread/threads.h>
+#include "common/Data.h"
+#include "common/Object.h"
+#include "common/Variant.h"
+#include "threads.h"
 
 
 namespace love
 namespace love
 {
 {
 namespace thread
 namespace thread
 {
 {
+
 class LuaThread : public love::Object, public Threadable
 class LuaThread : public love::Object, public Threadable
 {
 {
 public:
 public:
@@ -55,7 +56,9 @@ private:
 
 
 	Variant **args;
 	Variant **args;
 	int nargs;
 	int nargs;
-};
+
+}; // LuaThread
+
 } // thread
 } // thread
 } // love
 } // love
 
 

+ 2 - 2
jni/love/src/modules/thread/Thread.h

@@ -22,8 +22,8 @@
 #define LOVE_THREAD_THREAD_H
 #define LOVE_THREAD_THREAD_H
 
 
 // LOVE
 // LOVE
-#include <common/runtime.h>
-#include <common/Object.h>
+#include "common/runtime.h"
+#include "common/Object.h"
 
 
 namespace love
 namespace love
 {
 {

+ 2 - 1
jni/love/src/modules/thread/sdl/Thread.h

@@ -22,7 +22,7 @@
 #define LOVE_THREAD_SDL_THREAD_H
 #define LOVE_THREAD_SDL_THREAD_H
 
 
 // LOVE
 // LOVE
-#include <thread/Thread.h>
+#include "thread/Thread.h"
 #include "threads.h"
 #include "threads.h"
 
 
 // SDL
 // SDL
@@ -34,6 +34,7 @@ namespace thread
 {
 {
 namespace sdl
 namespace sdl
 {
 {
+
 class Thread : public thread::Thread
 class Thread : public thread::Thread
 {
 {
 public:
 public:

+ 6 - 0
jni/love/src/modules/thread/sdl/threads.cpp

@@ -27,6 +27,7 @@ namespace thread
 {
 {
 namespace sdl
 namespace sdl
 {
 {
+
 Mutex::Mutex()
 Mutex::Mutex()
 {
 {
 	mutex = SDL_CreateMutex();
 	mutex = SDL_CreateMutex();
@@ -81,6 +82,11 @@ bool Conditional::wait(thread::Mutex *_mutex, int timeout)
 
 
 } // sdl
 } // sdl
 
 
+
+/**
+ * Implementations of the functions declared in src/modules/threads.h.
+ **/
+
 thread::Mutex *newMutex()
 thread::Mutex *newMutex()
 {
 {
 	return new sdl::Mutex();
 	return new sdl::Mutex();

+ 11 - 4
jni/love/src/modules/thread/sdl/threads.h

@@ -21,8 +21,8 @@
 #ifndef LOVE_THREAD_SDL_THREADS_H
 #ifndef LOVE_THREAD_SDL_THREADS_H
 #define LOVE_THREAD_SDL_THREADS_H
 #define LOVE_THREAD_SDL_THREADS_H
 
 
-#include <common/config.h>
-#include <thread/threads.h>
+#include "common/config.h"
+#include "thread/threads.h"
 
 
 #include <SDL_thread.h>
 #include <SDL_thread.h>
 
 
@@ -32,11 +32,13 @@ namespace thread
 {
 {
 namespace sdl
 namespace sdl
 {
 {
+
 class Conditional;
 class Conditional;
 
 
 class Mutex : public thread::Mutex
 class Mutex : public thread::Mutex
 {
 {
 public:
 public:
+
 	Mutex();
 	Mutex();
 	~Mutex();
 	~Mutex();
 
 
@@ -44,15 +46,18 @@ public:
 	void unlock();
 	void unlock();
 
 
 private:
 private:
+
 	SDL_mutex *mutex;
 	SDL_mutex *mutex;
 	Mutex(const Mutex&/* mutex*/) {}
 	Mutex(const Mutex&/* mutex*/) {}
 
 
 	friend class Conditional;
 	friend class Conditional;
-};
+
+}; // Mutex
 
 
 class Conditional : public thread::Conditional
 class Conditional : public thread::Conditional
 {
 {
 public:
 public:
+
 	Conditional();
 	Conditional();
 	~Conditional();
 	~Conditional();
 
 
@@ -61,8 +66,10 @@ public:
 	bool wait(thread::Mutex *mutex, int timeout=-1);
 	bool wait(thread::Mutex *mutex, int timeout=-1);
 
 
 private:
 private:
+
 	SDL_cond *cond;
 	SDL_cond *cond;
-};
+
+}; // Conditional
 
 
 } // sdl
 } // sdl
 } // thread
 } // thread

+ 1 - 1
jni/love/src/modules/thread/threads.h

@@ -21,7 +21,7 @@
 #ifndef LOVE_THREAD_THREADS_H
 #ifndef LOVE_THREAD_THREADS_H
 #define LOVE_THREAD_THREADS_H
 #define LOVE_THREAD_THREADS_H
 
 
-#include <common/config.h>
+#include "common/config.h"
 #include "Thread.h"
 #include "Thread.h"
 
 
 namespace love
 namespace love

+ 33 - 40
jni/love/src/modules/touch/sdl/Touch.cpp

@@ -23,9 +23,6 @@
 #include "common/Exception.h"
 #include "common/Exception.h"
 #include "Touch.h"
 #include "Touch.h"
 
 
-// SDL
-#include <SDL_touch.h>
-
 namespace love
 namespace love
 {
 {
 namespace touch
 namespace touch
@@ -35,52 +32,25 @@ namespace sdl
 
 
 int Touch::getTouchCount() const
 int Touch::getTouchCount() const
 {
 {
-	int count = 0;
-
-	for (int i = 0; i < SDL_GetNumTouchDevices(); i++)
-		count += SDL_GetNumTouchFingers(SDL_GetTouchDevice(i));
-
-	return count;
+	return (int) touches.size();
 }
 }
 
 
 Touch::TouchInfo Touch::getTouch(int index) const
 Touch::TouchInfo Touch::getTouch(int index) const
 {
 {
-	SDL_TouchID deviceID = 0;
+	if (index < 0)
+		throw love::Exception("Invalid touch index: %d", index);
 
 
-	int touchcount = 0;
-	int fingerindex = -1;
+	std::map<int64, TouchInfo>::const_iterator it = touches.begin();
 
 
-	// Find the device and finger index from the given external index.
-	for (int i = 0; i < SDL_GetNumTouchDevices(); i++)
+	// We can't do something like "touches.begin() + index", so we get the
+	// value at the index by iterating from the beginning of the map.
+	for (int i = 0; i < index; i++)
 	{
 	{
-		deviceID = SDL_GetTouchDevice(i);
-		int fingercount = SDL_GetNumTouchFingers(deviceID);
-
-		if (index < touchcount + fingercount)
-		{
-			fingerindex = index - touchcount;
-			break;
-		}
-
-		touchcount += fingercount;
+		if (++it == touches.end())
+			throw love::Exception("Invalid touch index: %d", index);
 	}
 	}
 
 
-	if (fingerindex < 0)
-		throw love::Exception("Invalid touch index.");
-
-	SDL_Finger *finger = SDL_GetTouchFinger(deviceID, fingerindex);
-
-	if (finger == nullptr)
-		throw love::Exception("Cannot get touch info.");
-
-	TouchInfo info = {};
-
-	info.id = (int64) finger->id;
-	info.x = finger->x;
-	info.y = finger->y;
-	info.pressure = finger->pressure;
-
-	return info;
+	return it->second;
 }
 }
 
 
 const char *Touch::getName() const
 const char *Touch::getName() const
@@ -88,6 +58,29 @@ const char *Touch::getName() const
 	return "love.touch.sdl";
 	return "love.touch.sdl";
 }
 }
 
 
+void Touch::onEvent(const SDL_TouchFingerEvent &event)
+{
+	TouchInfo info = {
+		(int64) event.fingerId,
+		event.x,
+		event.y,
+		event.pressure
+	};
+
+	switch (event.type)
+	{
+	case SDL_FINGERDOWN:
+	case SDL_FINGERMOTION:
+		touches[info.id] = info;
+		break;
+	case SDL_FINGERUP:
+		touches.erase(info.id);
+		break;
+	default:
+		break;
+	}
+}
+
 } // sdl
 } // sdl
 } // touch
 } // touch
 } // love
 } // love

+ 18 - 0
jni/love/src/modules/touch/sdl/Touch.h

@@ -24,6 +24,12 @@
 // LOVE
 // LOVE
 #include "touch/Touch.h"
 #include "touch/Touch.h"
 
 
+// C++
+#include <map>
+
+// SDL
+#include <SDL_events.h>
+
 namespace love
 namespace love
 {
 {
 namespace touch
 namespace touch
@@ -43,6 +49,18 @@ public:
 	// Implements Module.
 	// Implements Module.
 	virtual const char *getName() const;
 	virtual const char *getName() const;
 
 
+	// SDL has functions to query the state of touch presses, but unfortunately
+	// they are updated on a different thread in some backends, which causes
+	// issues especially if the user is iterating through the current touches
+	// when they're updated. So we only update our touch press state in
+	// love::event::sdl::Event::convert.
+	void onEvent(const SDL_TouchFingerEvent &event);
+
+private:
+
+	// All current touches, indexed by their IDs.
+	std::map<int64, TouchInfo> touches;
+
 }; // Touch
 }; // Touch
 
 
 } // sdl
 } // sdl

+ 3 - 4
jni/love/src/scripts/boot.lua

@@ -295,7 +295,7 @@ function love.boot()
 	-- before the save directory (the identity should be appended.)
 	-- before the save directory (the identity should be appended.)
 	pcall(love.filesystem.setIdentity, identity, true)
 	pcall(love.filesystem.setIdentity, identity, true)
 
 
-	if can_has_game and not (love.filesystem.exists("main.lua") or love.filesystem.exists("conf.lua")) then
+	if can_has_game and not (love.filesystem.isFile("main.lua") or love.filesystem.isFile("conf.lua")) then
 		no_game_code = true
 		no_game_code = true
 	end
 	end
 
 
@@ -352,7 +352,7 @@ function love.init()
 	}
 	}
 
 
 	-- If config file exists, load it and allow it to update config table.
 	-- If config file exists, load it and allow it to update config table.
-	if not love.conf and love.filesystem and love.filesystem.exists("conf.lua") then
+	if not love.conf and love.filesystem and love.filesystem.isFile("conf.lua") then
 		require("conf")
 		require("conf")
 	end
 	end
 
 
@@ -434,7 +434,7 @@ function love.init()
 
 
 	if love.filesystem then
 	if love.filesystem then
 		love.filesystem.setIdentity(c.identity or love.filesystem.getIdentity(), c.appendidentity)
 		love.filesystem.setIdentity(c.identity or love.filesystem.getIdentity(), c.appendidentity)
-		if love.filesystem.exists("main.lua") then
+		if love.filesystem.isFile("main.lua") then
 			require("main")
 			require("main")
 		end
 		end
 	end
 	end
@@ -486,7 +486,6 @@ function love.run()
 
 
 	if love.math then
 	if love.math then
 		love.math.setRandomSeed(os.time())
 		love.math.setRandomSeed(os.time())
-		for i=1,3 do love.math.random() end
 	end
 	end
 
 
 	if love.event then
 	if love.event then

+ 4 - 7
jni/love/src/scripts/boot.lua.h

@@ -553,9 +553,9 @@ const unsigned char boot_lua[] =
 	0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x0a,
 	0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x0a,
 	0x09, 0x69, 0x66, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x61, 
 	0x09, 0x69, 0x66, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x61, 
 	0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 
 	0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 
-	0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 
+	0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 
 	0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 
 	0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 
-	0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x28, 0x22, 0x63, 0x6f, 
+	0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x22, 0x63, 0x6f, 
 	0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x74, 
 	0x09, 0x09, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x74, 
 	0x72, 0x75, 0x65, 0x0a,
 	0x72, 0x75, 0x65, 0x0a,
@@ -639,7 +639,7 @@ const unsigned char boot_lua[] =
 	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 
 	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 
 	0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 
 	0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 
 	0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 
 	0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 
-	0x74, 0x65, 0x6d, 0x2e, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 
+	0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 
 	0x75, 0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x75, 0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x22, 0x29, 0x0a,
 	0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x22, 0x29, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
@@ -775,7 +775,7 @@ const unsigned char boot_lua[] =
 	0x29, 0x2c, 0x20, 0x63, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 
 	0x29, 0x2c, 0x20, 0x63, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 
 	0x79, 0x29, 0x0a,
 	0x79, 0x29, 0x0a,
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 
-	0x65, 0x6d, 0x2e, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 
+	0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 
 	0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x29, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
@@ -877,9 +877,6 @@ const unsigned char boot_lua[] =
 	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x61, 0x6e, 
 	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x61, 0x6e, 
 	0x64, 0x6f, 0x6d, 0x53, 0x65, 0x65, 0x64, 0x28, 0x6f, 0x73, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x28, 0x29, 0x29, 0x0a,
 	0x64, 0x6f, 0x6d, 0x53, 0x65, 0x65, 0x64, 0x28, 0x6f, 0x73, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x28, 0x29, 0x29, 0x0a,
-	0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x3d, 0x31, 0x2c, 0x33, 0x20, 0x64, 0x6f, 0x20, 0x6c, 0x6f, 0x76, 
-	0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x29, 0x20, 0x65, 0x6e, 
-	0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 
 	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 
 	0x6e, 0x0a,
 	0x6e, 0x0a,

+ 2 - 2
jni/love/src/scripts/graphics.lua.h

@@ -6490,7 +6490,7 @@ const unsigned char graphics_lua[] =
 	0x09, 0x09, 0x09, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x6c, 0x61, 
 	0x09, 0x09, 0x09, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x6c, 0x61, 
 	0x6e, 0x67, 0x2e, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 
 	0x6e, 0x67, 0x2e, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 
 	0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x2c, 0x0a,
 	0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x22, 0x23, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x22, 0x23, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x30, 0x22, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x46, 0x4f, 0x4f, 
 	0x09, 0x09, 0x09, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x46, 0x4f, 0x4f, 
 	0x54, 0x45, 0x52, 0x2c, 0x0a,
 	0x54, 0x45, 0x52, 0x2c, 0x0a,
@@ -6509,7 +6509,7 @@ const unsigned char graphics_lua[] =
 	0x09, 0x09, 0x09, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x6c, 0x61, 
 	0x09, 0x09, 0x09, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x6c, 0x61, 
 	0x6e, 0x67, 0x2e, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 0x6c, 
 	0x6e, 0x67, 0x2e, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 0x6c, 
 	0x61, 0x6e, 0x67, 0x2e, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x2c, 0x0a,
 	0x61, 0x6e, 0x67, 0x2e, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x22, 0x23, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x22, 0x23, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x30, 0x22, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x73, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x20, 
 	0x09, 0x09, 0x09, 0x69, 0x73, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x20, 
 	0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x46, 0x4f, 0x4f, 
 	0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x46, 0x4f, 0x4f,