Browse Source

Backout changeset b3928e24add23da69dcd90c34985cd6a05454be0

Alex Szpakowski 11 years ago
parent
commit
5428a5d75f

+ 2 - 2
src/modules/graphics/opengl/Graphics.cpp

@@ -544,9 +544,9 @@ Canvas *Graphics::newCanvas(int width, int height, Texture::Format format, int f
 	return NULL; // never reached
 	return NULL; // never reached
 }
 }
 
 
-Shader *Graphics::newShader(const std::vector<std::string> &vertcode, const std::vector<std::string> &pixelcode)
+Shader *Graphics::newShader(const Shader::ShaderSources &sources)
 {
 {
-	return new Shader(vertcode, pixelcode);
+	return new Shader(sources);
 }
 }
 
 
 Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode)
 Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode)

+ 1 - 1
src/modules/graphics/opengl/Graphics.h

@@ -210,7 +210,7 @@ public:
 
 
 	Canvas *newCanvas(int width, int height, Texture::Format format = Texture::FORMAT_NORMAL, int fsaa = 0);
 	Canvas *newCanvas(int width, int height, Texture::Format format = Texture::FORMAT_NORMAL, int fsaa = 0);
 
 
-	Shader *newShader(const std::vector<std::string> &vertcode, const std::vector<std::string> &pixelcode);
+	Shader *newShader(const Shader::ShaderSources &sources);
 
 
 	Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
 	Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
 	Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
 	Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);

+ 12 - 27
src/modules/graphics/opengl/Shader.cpp

@@ -66,25 +66,21 @@ Shader *Shader::current = nullptr;
 GLint Shader::maxTexUnits = 0;
 GLint Shader::maxTexUnits = 0;
 std::vector<int> Shader::textureCounters;
 std::vector<int> Shader::textureCounters;
 
 
-Shader::Shader(const std::vector<std::string> &vertcode, const std::vector<std::string> &pixelcode)
-	: program(0)
+Shader::Shader(const ShaderSources &sources)
+	: shaderSources(sources)
+	, program(0)
 	, builtinUniforms()
 	, builtinUniforms()
 	, vertexAttributes()
 	, vertexAttributes()
 	, lastCanvas((Canvas *) -1)
 	, lastCanvas((Canvas *) -1)
 	, lastViewport()
 	, lastViewport()
 {
 {
-	if (vertcode.empty() && pixelcode.empty())
+	if (shaderSources.empty())
 		throw love::Exception("Cannot create shader: no source code!");
 		throw love::Exception("Cannot create shader: no source code!");
 
 
-	shaderSources[TYPE_VERTEX] = vertcode;
-	shaderSources[TYPE_PIXEL] = pixelcode;
-
 	if (maxTexUnits <= 0)
 	if (maxTexUnits <= 0)
 	{
 	{
 		GLint maxtexunits;
 		GLint maxtexunits;
 		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtexunits);
 		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtexunits);
-
-		// TU 0 is never used for stored Shader images.
 		maxTexUnits = std::max(maxtexunits - 1, 0);
 		maxTexUnits = std::max(maxtexunits - 1, 0);
 	}
 	}
 
 
@@ -110,7 +106,7 @@ Shader::~Shader()
 	unloadVolatile();
 	unloadVolatile();
 }
 }
 
 
-GLuint Shader::compileCode(ShaderType type, const std::vector<std::string> &code)
+GLuint Shader::compileCode(ShaderType type, const std::string &code)
 {
 {
 	GLenum glshadertype;
 	GLenum glshadertype;
 	const char *typestr;
 	const char *typestr;
@@ -146,18 +142,9 @@ GLuint Shader::compileCode(ShaderType type, const std::vector<std::string> &code
 			throw love::Exception("Cannot create %s shader object.", typestr);
 			throw love::Exception("Cannot create %s shader object.", typestr);
 	}
 	}
 
 
-	std::vector<const GLchar *> codelist;
-	std::vector<GLint> lengthlist;
-
-	for (size_t i = 0; i < code.size(); i++)
-	{
-		codelist.push_back((const GLchar *) code[i].c_str());
-		lengthlist.push_back((GLint) code[i].length());
-	}
-
-	// The code parameter is a list of source code "files." We can hand them
-	// all to OpenGL at once using glShaderSource.
-	glShaderSource(shaderid, codelist.size(), &codelist[0], &lengthlist[0]);
+	const char *src = code.c_str();
+	size_t srclen = code.length();
+	glShaderSource(shaderid, 1, (const GLchar **)&src, (GLint *)&srclen);
 
 
 	glCompileShader(shaderid);
 	glCompileShader(shaderid);
 
 
@@ -289,12 +276,10 @@ bool Shader::loadVolatile()
 
 
 	std::vector<GLuint> shaderids;
 	std::vector<GLuint> shaderids;
 
 
-	for (int i = 0; i < (int) TYPE_MAX_ENUM; i++)
+	ShaderSources::const_iterator source;
+	for (source = shaderSources.begin(); source != shaderSources.end(); ++source)
 	{
 	{
-		if (shaderSources[i].empty())
-			continue;
-
-		GLuint shaderid = compileCode((ShaderType) i, shaderSources[i]);
+		GLuint shaderid = compileCode(source->first, source->second);
 		shaderids.push_back(shaderid);
 		shaderids.push_back(shaderid);
 	}
 	}
 
 
@@ -303,7 +288,7 @@ bool Shader::loadVolatile()
 
 
 	createProgram(shaderids);
 	createProgram(shaderids);
 
 
-	// Get all active uniform variables in this shader from OpenGL.
+	// Retreive all active uniform variables in this shader from OpenGL.
 	mapActiveUniforms();
 	mapActiveUniforms();
 
 
 	for (int i = 0; i < int(OpenGL::ATTRIB_MAX_ENUM); i++)
 	for (int i = 0; i < int(OpenGL::ATTRIB_MAX_ENUM); i++)

+ 8 - 6
src/modules/graphics/opengl/Shader.h

@@ -74,11 +74,14 @@ public:
 		UNIFORM_MAX_ENUM
 		UNIFORM_MAX_ENUM
 	};
 	};
 
 
+	// Type for a list of shader source codes in the form of sources[shadertype] = code
+	typedef std::map<ShaderType, std::string> ShaderSources;
+
 	/**
 	/**
 	 * Creates a new Shader using a list of source codes.
 	 * Creates a new Shader using a list of source codes.
-	 * The sources must contain either vertex or pixel shader code, or both.
+	 * Sources must contain either vertex or pixel shader code, or both.
 	 **/
 	 **/
-	Shader(const std::vector<std::string> &vertcode, const std::vector<std::string> &pixelcode);
+	Shader(const ShaderSources &sources);
 
 
 	virtual ~Shader();
 	virtual ~Shader();
 
 
@@ -193,7 +196,7 @@ private:
 	UniformType getUniformBaseType(GLenum type) const;
 	UniformType getUniformBaseType(GLenum type) const;
 	void checkSetUniformError(const Uniform &u, int size, int count, UniformType sendtype) const;
 	void checkSetUniformError(const Uniform &u, int size, int count, UniformType sendtype) const;
 
 
-	GLuint compileCode(ShaderType type, const std::vector<std::string> &code);
+	GLuint compileCode(ShaderType type, const std::string &code);
 	void createProgram(const std::vector<GLuint> &shaderids);
 	void createProgram(const std::vector<GLuint> &shaderids);
 
 
 	int getTextureUnit(const std::string &name);
 	int getTextureUnit(const std::string &name);
@@ -203,9 +206,8 @@ private:
 	// Get any warnings or errors generated only by the shader program object.
 	// Get any warnings or errors generated only by the shader program object.
 	std::string getProgramWarnings() const;
 	std::string getProgramWarnings() const;
 
 
-	// List of all shader code attached to this Shader. Each shader type has its
-	// own list, which represents separate "files".
-	std::vector<std::string> shaderSources[TYPE_MAX_ENUM];
+	// List of all shader code attached to this Shader
+	ShaderSources shaderSources;
 
 
 	// Shader compiler warning strings for individual shader stages.
 	// Shader compiler warning strings for individual shader stages.
 	std::map<ShaderType, std::string> shaderWarnings;
 	std::map<ShaderType, std::string> shaderWarnings;

+ 18 - 51
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -353,16 +353,16 @@ int w_newShader(lua_State *L)
 	if (!Shader::isSupported())
 	if (!Shader::isSupported())
 		return luaL_error(L, "Sorry, your graphics card does not support shaders.");
 		return luaL_error(L, "Sorry, your graphics card does not support shaders.");
 
 
-	// Clamp stack to 2 elements.
+	// clamp stack to 2 elements
 	lua_settop(L, 2);
 	lua_settop(L, 2);
 
 
-	// Read any filepath arguments.
+	// read any filepath arguments
 	for (int i = 1; i <= 2; i++)
 	for (int i = 1; i <= 2; i++)
 	{
 	{
 		if (!lua_isstring(L, i))
 		if (!lua_isstring(L, i))
 			continue;
 			continue;
 
 
-		// Call love.filesystem.isFile(arg_i)
+		// call love.filesystem.isFile(arg_i)
 		luax_getfunction(L, "filesystem", "isFile");
 		luax_getfunction(L, "filesystem", "isFile");
 		lua_pushvalue(L, i);
 		lua_pushvalue(L, i);
 		lua_call(L, 1, 1);
 		lua_call(L, 1, 1);
@@ -382,76 +382,43 @@ int w_newShader(lua_State *L)
 	bool has_arg1 = lua_isstring(L, 1);
 	bool has_arg1 = lua_isstring(L, 1);
 	bool has_arg2 = lua_isstring(L, 2);
 	bool has_arg2 = lua_isstring(L, 2);
 
 
-	// Require at least one string argument.
+	// require at least one string argument
 	if (!(has_arg1 || has_arg2))
 	if (!(has_arg1 || has_arg2))
 		luaL_checkstring(L, 1);
 		luaL_checkstring(L, 1);
 
 
 	luax_getfunction(L, "graphics", "_shaderCodeToGLSL");
 	luax_getfunction(L, "graphics", "_shaderCodeToGLSL");
 
 
-	// Push vertexcode and pixelcode strings to the top of the stack.
+	// push vertexcode and pixelcode strings to the top of the stack
 	lua_pushvalue(L, 1);
 	lua_pushvalue(L, 1);
 	lua_pushvalue(L, 2);
 	lua_pushvalue(L, 2);
 
 
-	// Call shaderCodeToGLSL, returned values will be at the top of the stack.
+	// call effectCodeToGLSL, returned values will be at the top of the stack
 	if (lua_pcall(L, 2, 2, 0) != 0)
 	if (lua_pcall(L, 2, 2, 0) != 0)
 		return luaL_error(L, "%s", lua_tostring(L, -1));
 		return luaL_error(L, "%s", lua_tostring(L, -1));
 
 
-	// Each shader type might contain several source code strings.
-	std::vector<std::string> sources[Shader::TYPE_MAX_ENUM];
+	Shader::ShaderSources sources;
 
 
-	// Vertex shader code.
-	if (!lua_isnoneornil(L, -2))
+	// vertex shader code
+	if (lua_isstring(L, -2))
 	{
 	{
-		std::vector<std::string> &source = sources[Shader::TYPE_VERTEX];
-
-		// The argument might be a Lua array containing strings for the code.
-		if (lua_istable(L, -2))
-		{
-			// Convert table index to absolute.
-			int idx = lua_gettop(L) + 1 - 2;
-
-			// Get all the shader code strings from the Lua array.
-			for (size_t i = 1; i <= lua_objlen(L, idx); i++)
-			{
-				lua_rawgeti(L, idx, i);
-				source.push_back(luax_checkstring(L, -1));
-				lua_pop(L, 1);
-			}
-		}
-		else
-			source.push_back(luax_checkstring(L, -2));
+		std::string vertexcode(luaL_checkstring(L, -2));
+		sources[Shader::TYPE_VERTEX] = vertexcode;
 	}
 	}
 	else if (has_arg1 && has_arg2)
 	else if (has_arg1 && has_arg2)
 		return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
 		return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
 
 
-	// Pixel shader code.
-	if (!lua_isnoneornil(L, -1))
+	// pixel shader code
+	if (lua_isstring(L, -1))
 	{
 	{
-		std::vector<std::string> &source = sources[Shader::TYPE_PIXEL];
-
-		// The argument might be a Lua array containing strings for the code.
-		if (lua_istable(L, -1))
-		{
-			// Convert table index to absolute.
-			int idx = lua_gettop(L) + 1 - 1;
-
-			// Get all the shader code strings from the Lua array.
-			for (size_t i = 1; i <= lua_objlen(L, idx); i++)
-			{
-				lua_rawgeti(L, idx, i);
-				source.push_back(luax_checkstring(L, -1));
-				lua_pop(L, 1);
-			}
-		}
-		else
-			source.push_back(luax_checkstring(L, -1));
+		std::string pixelcode(luaL_checkstring(L, -1));
+		sources[Shader::TYPE_PIXEL] = pixelcode;
 	}
 	}
 	else if (has_arg1 && has_arg2)
 	else if (has_arg1 && has_arg2)
 		return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
 		return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
 
 
-	if (sources[Shader::TYPE_VERTEX].empty() && sources[Shader::TYPE_PIXEL].empty())
+	if (sources.empty())
 	{
 	{
-		// Original args had source code, but shaderCodeToGLSL couldn't translate it
+		// Original args had source code, but effectCodeToGLSL couldn't translate it
 		for (int i = 1; i <= 2; i++)
 		for (int i = 1; i <= 2; i++)
 		{
 		{
 			if (lua_isstring(L, i))
 			if (lua_isstring(L, i))
@@ -462,7 +429,7 @@ int w_newShader(lua_State *L)
 	bool should_error = false;
 	bool should_error = false;
 	try
 	try
 	{
 	{
-		Shader *shader = instance->newShader(sources[Shader::TYPE_VERTEX], sources[Shader::TYPE_PIXEL]);
+		Shader *shader = instance->newShader(sources);
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 	}
 	}
 	catch (love::Exception &e)
 	catch (love::Exception &e)

+ 12 - 22
src/scripts/graphics.lua

@@ -1365,35 +1365,25 @@ void main() {
 	}
 	}
 
 
 	local function createVertexCode(vertexcode)
 	local function createVertexCode(vertexcode)
-		-- If we return an array, each string in the array is considered separate to GLSL,
-		-- and the line numbers in GLSL errors/warnings maintain this.
 		local vertexcodes = {
 		local vertexcodes = {
-			table_concat({
-				GLSL_VERSION,
-				GLSL_SYNTAX, GLSL_VERTEX.HEADER, GLSL_UNIFORMS,
-			}, "\n") .. "\n",
-			table_concat({
-				vertexcode,
-				GLSL_VERTEX.FOOTER
-			}, "\n"),
+			GLSL_VERSION,
+			GLSL_SYNTAX, GLSL_VERTEX.HEADER, GLSL_UNIFORMS,
+			"#line 1",
+			vertexcode,
+			GLSL_VERTEX.FOOTER,
 		}
 		}
-		return vertexcodes
+		return table_concat(vertexcodes, "\n")
 	end
 	end
 
 
 	local function createPixelCode(pixelcode, is_multicanvas)
 	local function createPixelCode(pixelcode, is_multicanvas)
-		-- If we return an array, each string in the array is considered separate to GLSL,
-		-- and the line numbers in GLSL errors/warnings maintain this.
 		local pixelcodes = {
 		local pixelcodes = {
-			table_concat({
-				GLSL_VERSION,
-				GLSL_SYNTAX, GLSL_PIXEL.HEADER, GLSL_UNIFORMS,
-			}, "\n") .. "\n",
-			table_concat({
-				pixelcode,
-				is_multicanvas and GLSL_PIXEL.FOOTER_MULTI_CANVAS or GLSL_PIXEL.FOOTER,
-			}, "\n"),
+			GLSL_VERSION,
+			GLSL_SYNTAX, GLSL_PIXEL.HEADER, GLSL_UNIFORMS,
+			"#line 1",
+			pixelcode,
+			is_multicanvas and GLSL_PIXEL.FOOTER_MULTI_CANVAS or GLSL_PIXEL.FOOTER,
 		}
 		}
-		return pixelcodes
+		return table_concat(pixelcodes, "\n")
 	end
 	end
 
 
 	local function isVertexCode(code)
 	local function isVertexCode(code)

+ 25 - 49
src/scripts/graphics.lua.h

@@ -6404,66 +6404,42 @@ const unsigned char graphics_lua[] =
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72, 
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72, 
 	0x65, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x76, 0x65, 0x72, 
 	0x65, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x76, 0x65, 0x72, 
 	0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
 	0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x77, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 
-	0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x74, 0x72, 
-	0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, 
-	0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 
-	0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x2c, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 
-	0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x20, 0x65, 0x72, 
-	0x72, 0x6f, 0x72, 0x73, 0x2f, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6d, 0x61, 0x69, 0x6e, 
-	0x74, 0x61, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x0a,
 	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 
 	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 
 	0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
 	0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x47, 
-	0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 
-	0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x7d, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5c, 0x6e, 
-	0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x46, 0x4f, 
-	0x4f, 0x54, 0x45, 0x52, 0x0a,
-	0x09, 0x09, 0x09, 0x7d, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x47, 0x4c, 
+	0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 
+	0x47, 0x4c, 0x53, 0x4c, 0x5f, 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, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2e, 0x46, 0x4f, 0x4f, 
+	0x54, 0x45, 0x52, 0x2c, 0x0a,
 	0x09, 0x09, 0x7d, 0x0a,
 	0x09, 0x09, 0x7d, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 
-	0x65, 0x73, 0x0a,
+	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 
+	0x63, 0x61, 0x74, 0x28, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x22, 
+	0x5c, 0x6e, 0x22, 0x29, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72, 
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72, 
 	0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x70, 0x69, 0x78, 0x65, 
 	0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x70, 0x69, 0x78, 0x65, 
 	0x6c, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x73, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x6e, 
 	0x6c, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x73, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x6e, 
 	0x76, 0x61, 0x73, 0x29, 0x0a,
 	0x76, 0x61, 0x73, 0x29, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x77, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 
-	0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x74, 0x72, 
-	0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, 
-	0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 
-	0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x2c, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 
-	0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x20, 0x65, 0x72, 
-	0x72, 0x6f, 0x72, 0x73, 0x2f, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6d, 0x61, 0x69, 0x6e, 
-	0x74, 0x61, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x0a,
 	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x73, 
 	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x73, 
 	0x20, 0x3d, 0x20, 0x7b, 0x0a,
 	0x20, 0x3d, 0x20, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x47, 
-	0x4c, 0x53, 0x4c, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 
-	0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x7d, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5c, 0x6e, 
-	0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x69, 0x73, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 
-	0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x46, 0x4f, 
-	0x4f, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x43, 0x41, 0x4e, 0x56, 0x41, 0x53, 0x20, 
-	0x6f, 0x72, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x46, 0x4f, 0x4f, 0x54, 
-	0x45, 0x52, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x7d, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x20, 0x47, 0x4c, 
+	0x53, 0x4c, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2c, 0x20, 0x47, 
+	0x4c, 0x53, 0x4c, 0x5f, 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, 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, 
+	0x61, 0x6e, 0x64, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x46, 0x4f, 0x4f, 
+	0x54, 0x45, 0x52, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x43, 0x41, 0x4e, 0x56, 0x41, 0x53, 0x20, 0x6f, 
+	0x72, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x2e, 0x46, 0x4f, 0x4f, 0x54, 0x45, 
+	0x52, 0x2c, 0x0a,
 	0x09, 0x09, 0x7d, 0x0a,
 	0x09, 0x09, 0x7d, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 
-	0x73, 0x0a,
+	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 
+	0x63, 0x61, 0x74, 0x28, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x5c, 
+	0x6e, 0x22, 0x29, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 
 	0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
 	0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,