changeset 1398:5842a06169ff GLES2-compatibility

Merged default into GLES2-compatibility
author Alex Szpakowski <slime73@gmail.com>
date Thu, 21 Mar 2013 17:23:45 -0300
parents 2619c2c02312 (current diff) 43f2b4936ca8 (diff)
children bd104779dd89
files src/modules/graphics/Image.h src/modules/graphics/opengl/Canvas.cpp src/modules/graphics/opengl/Canvas.h src/modules/graphics/opengl/Context.cpp src/modules/graphics/opengl/Context.h src/modules/graphics/opengl/Font.cpp src/modules/graphics/opengl/Font.h src/modules/graphics/opengl/Graphics.cpp src/modules/graphics/opengl/Graphics.h src/modules/graphics/opengl/Image.cpp src/modules/graphics/opengl/Image.h src/modules/graphics/opengl/Shader.cpp src/modules/graphics/opengl/Shader.h src/modules/graphics/opengl/wrap_Font.cpp src/modules/graphics/opengl/wrap_Graphics.cpp src/modules/graphics/opengl/wrap_Graphics.h src/modules/graphics/opengl/wrap_Image.cpp src/scripts/graphics.lua src/scripts/graphics.lua.h
diffstat 30 files changed, 1009 insertions(+), 766 deletions(-) [+]
line wrap: on
line diff
--- a/changes.txt	Sun Mar 17 18:00:24 2013 -0300
+++ b/changes.txt	Thu Mar 21 17:23:45 2013 -0300
@@ -21,14 +21,20 @@
   * Added SoundData:getDuration.
   * Added new Channels api for love.thread.
   * Added flags to setMode.
-  * Added support for resizable and borderless windows.
+  * Added support for resizable, borderless, and non-centered windows.
   * Added resize event.
   * Added love.math module.
   * Added a platform-independent (good) random implementation to love.math.
+  * Added love.math.triangulate.
   * Added blend mode "none".
   * Added SpriteBatch:isEmpty and SpriteBatch:isFull.
   * Added support for extern Images in Shaders when drawing graphics primitives.
   * Added love.timer.getAverageDelta.
+  * Added love.joystickaxis/ball/hat event callbacks.
+  * Added ParticleSystem:setQuads.
+  * Added love.graphics.getDimensions and Image/Canvas/ImageData:getDimensions.
+  * Added love.filesystem.append.
+  * Added love.filesystem.getSize.
   * OPTIONAL: Added support for GME.
 
   * Fixed crashes with font drawing on some ATI cards.
@@ -52,6 +58,8 @@
   * Fixed Shader:send with Images and Canvases failing sometimes.
   * Fixed love.graphics.getPointStyle.
   * Fixed line numbers in shader errors.
+  * Fixed line wrapping in love.graphics.printf.
+  * Fixed fused release mode in OS X.
 
   * Moved love's startup to modules/love.
 
@@ -76,6 +84,8 @@
   * Updated SpriteBatch code, now more performant when (un)binding.
   * Updated Image creation code to error when creation fails.
   * Updated Canvas code to support more systems.
+  * Updated love.timer.getFPS to be microsecond-accurate.
+  * Updated love.graphics.newScreenshot to create a fully opaque image by default.
 
 LOVE 0.8.0 [Rubber Piggy]
 -------------------------
--- a/platform/macosx/SDLMain.m	Sun Mar 17 18:00:24 2013 -0300
+++ b/platform/macosx/SDLMain.m	Thu Mar 21 17:23:45 2013 -0300
@@ -1,8 +1,8 @@
 /*   SDLMain.m - main entry point for our Cocoa-ized SDL app
-       Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
-       Non-NIB-Code & other changes: Max Horn <max@quendi.de>
+	   Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
+	   Non-NIB-Code & other changes: Max Horn <max@quendi.de>
 
-    Feel free to customize this file to suit your needs
+	Feel free to customize this file to suit your needs
 */
 
 //#import "SDL.h"
@@ -43,18 +43,18 @@
 
 static NSString *getApplicationName(void)
 {
-    NSDictionary *dict;
-    NSString *appName = 0;
+	NSDictionary *dict;
+	NSString *appName = 0;
 
-    /* Determine the application name */
-    dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
-    if (dict)
-        appName = [dict objectForKey: @"CFBundleName"];
-    
-    if (![appName length])
-        appName = [[NSProcessInfo processInfo] processName];
+	/* Determine the application name */
+	dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
+	if (dict)
+		appName = [dict objectForKey: @"CFBundleName"];
 
-    return appName;
+	if (![appName length])
+		appName = [[NSProcessInfo processInfo] processName];
+
+	return appName;
 }
 
 #if SDL_USE_NIB_FILE
@@ -71,10 +71,10 @@
 /* Invoked from the Quit menu item */
 - (void)terminate:(id)sender
 {
-    /* Post a SDL_QUIT event */
-    SDL_Event event;
-    event.type = SDL_QUIT;
-    SDL_PushEvent(&event);
+	/* Post a SDL_QUIT event */
+	SDL_Event event;
+	event.type = SDL_QUIT;
+	SDL_PushEvent(&event);
 }
 
 /* Hack to make Cocoa ignore keystrokes that aren't shortcuts, otherwise it beeps on every key press */
@@ -95,15 +95,15 @@
 /*CHANGED to Bundle's Resource Directory. */
 - (void) setupWorkingDirectory:(BOOL)shouldChdir
 {
-    if (shouldChdir)
-    {
-    	/*
-        char parentdir[PATH_MAX];
+	if (shouldChdir)
+	{
+		/*
+		char parentdir[PATH_MAX];
 		//CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
 		CFURLRef url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
 		CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
 		if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, PATH_MAX)) {
-	        assert ( chdir (parentdir) == 0 );   // chdir to the binary app's parent //
+			assert ( chdir (parentdir) == 0 );   // chdir to the binary app's parent //
 		}
 		CFRelease(url);
 		CFRelease(url2);
@@ -113,7 +113,7 @@
 		char path[PATH_MAX];
 		if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
 		{
-		    // error!
+			// error!
 		}
 		CFRelease(resourcesURL);
 		chdir(path);
@@ -126,133 +126,133 @@
 /* Fix menu to contain the real app name instead of "SDL App" */
 - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
 {
-    NSRange aRange;
-    NSEnumerator *enumerator;
-    NSMenuItem *menuItem;
+	NSRange aRange;
+	NSEnumerator *enumerator;
+	NSMenuItem *menuItem;
 
-    aRange = [[aMenu title] rangeOfString:@"SDL App"];
-    if (aRange.length != 0)
-        [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
+	aRange = [[aMenu title] rangeOfString:@"SDL App"];
+	if (aRange.length != 0)
+		[aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
 
-    enumerator = [[aMenu itemArray] objectEnumerator];
-    while ((menuItem = [enumerator nextObject]))
-    {
-        aRange = [[menuItem title] rangeOfString:@"SDL App"];
-        if (aRange.length != 0)
-            [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
-        if ([menuItem hasSubmenu])
-            [self fixMenu:[menuItem submenu] withAppName:appName];
-    }
-    [ aMenu sizeToFit ];
+	enumerator = [[aMenu itemArray] objectEnumerator];
+	while ((menuItem = [enumerator nextObject]))
+	{
+		aRange = [[menuItem title] rangeOfString:@"SDL App"];
+		if (aRange.length != 0)
+			[menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
+		if ([menuItem hasSubmenu])
+			[self fixMenu:[menuItem submenu] withAppName:appName];
+	}
+	[ aMenu sizeToFit ];
 }
 
 #else
 
 static void setApplicationMenu(void)
 {
-    /* warning: this code is very odd */
-    NSMenu *appleMenu;
-    NSMenuItem *menuItem;
-    NSString *title;
-    NSString *appName;
-    
-    appName = getApplicationName();
-    appleMenu = [[NSMenu alloc] initWithTitle:@""];
-    
-    /* Add menu items */
-    title = [@"About " stringByAppendingString:appName];
-    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+	/* warning: this code is very odd */
+	NSMenu *appleMenu;
+	NSMenuItem *menuItem;
+	NSString *title;
+	NSString *appName;
+
+	appName = getApplicationName();
+	appleMenu = [[NSMenu alloc] initWithTitle:@""];
 
-    [appleMenu addItem:[NSMenuItem separatorItem]];
+	/* Add menu items */
+	title = [@"About " stringByAppendingString:appName];
+	[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
 
-    title = [@"Hide " stringByAppendingString:appName];
-    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
+	[appleMenu addItem:[NSMenuItem separatorItem]];
+
+	title = [@"Hide " stringByAppendingString:appName];
+	[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
 
-    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
-    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
+	menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+	[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
 
-    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
+	[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
 
-    [appleMenu addItem:[NSMenuItem separatorItem]];
+	[appleMenu addItem:[NSMenuItem separatorItem]];
 
-    title = [@"Quit " stringByAppendingString:appName];
-    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+	title = [@"Quit " stringByAppendingString:appName];
+	[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+
 
-    
-    /* Put menu into the menubar */
-    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
-    [menuItem setSubmenu:appleMenu];
-    [[NSApp mainMenu] addItem:menuItem];
+	/* Put menu into the menubar */
+	menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
+	[menuItem setSubmenu:appleMenu];
+	[[NSApp mainMenu] addItem:menuItem];
 
-    /* Tell the application object that this is now the application menu */
-    [NSApp setAppleMenu:appleMenu];
+	/* Tell the application object that this is now the application menu */
+	[NSApp setAppleMenu:appleMenu];
 
-    /* Finally give up our references to the objects */
-    [appleMenu release];
-    [menuItem release];
+	/* Finally give up our references to the objects */
+	[appleMenu release];
+	[menuItem release];
 }
 
 /* Create a window menu */
 static void setupWindowMenu(void)
 {
-    NSMenu      *windowMenu;
-    NSMenuItem  *windowMenuItem;
-    NSMenuItem  *menuItem;
+	NSMenu      *windowMenu;
+	NSMenuItem  *windowMenuItem;
+	NSMenuItem  *menuItem;
+
+	windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+
+	/* "Minimize" item */
+	menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+	[windowMenu addItem:menuItem];
+	[menuItem release];
 
-    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
-    
-    /* "Minimize" item */
-    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
-    [windowMenu addItem:menuItem];
-    [menuItem release];
-    
-    /* Put menu into the menubar */
-    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
-    [windowMenuItem setSubmenu:windowMenu];
-    [[NSApp mainMenu] addItem:windowMenuItem];
-    
-    /* Tell the application object that this is now the window menu */
-    [NSApp setWindowsMenu:windowMenu];
+	/* Put menu into the menubar */
+	windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
+	[windowMenuItem setSubmenu:windowMenu];
+	[[NSApp mainMenu] addItem:windowMenuItem];
 
-    /* Finally give up our references to the objects */
-    [windowMenu release];
-    [windowMenuItem release];
+	/* Tell the application object that this is now the window menu */
+	[NSApp setWindowsMenu:windowMenu];
+
+	/* Finally give up our references to the objects */
+	[windowMenu release];
+	[windowMenuItem release];
 }
 
 /* Replacement for NSApplicationMain */
 static void CustomApplicationMain (int argc, char **argv)
 {
-    NSAutoreleasePool	*pool = [[NSAutoreleasePool alloc] init];
-    SDLMain				*sdlMain;
+	NSAutoreleasePool	*pool = [[NSAutoreleasePool alloc] init];
+	SDLMain				*sdlMain;
 
-    /* Ensure the application object is initialised */
-    [SDLApplication sharedApplication];
-    
+	/* Ensure the application object is initialised */
+	[SDLApplication sharedApplication];
+	
 #ifdef SDL_USE_CPS
-    {
-        CPSProcessSerNum PSN;
-        /* Tell the dock about us */
-        if (!CPSGetCurrentProcess(&PSN))
-            if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
-                if (!CPSSetFrontProcess(&PSN))
-                    [SDLApplication sharedApplication];
-    }
+	{
+		CPSProcessSerNum PSN;
+		/* Tell the dock about us */
+		if (!CPSGetCurrentProcess(&PSN))
+			if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
+				if (!CPSSetFrontProcess(&PSN))
+					[SDLApplication sharedApplication];
+	}
 #endif /* SDL_USE_CPS */
 
-    /* Set up the menubar */
-    [NSApp setMainMenu:[[[NSMenu alloc] init] autorelease]];
-    setApplicationMenu();
-    setupWindowMenu();
+	/* Set up the menubar */
+	[NSApp setMainMenu:[[[NSMenu alloc] init] autorelease]];
+	setApplicationMenu();
+	setupWindowMenu();
 
-    /* Create SDLMain and make it the app delegate */
-    sdlMain = [[SDLMain alloc] init];
-    [NSApp setDelegate:sdlMain];
-    
-    /* Start the main event loop */
-    [NSApp run];
-    
-    [sdlMain release];
-    [pool release];
+	/* Create SDLMain and make it the app delegate */
+	sdlMain = [[SDLMain alloc] init];
+	[NSApp setDelegate:sdlMain];
+
+	/* Start the main event loop */
+	[NSApp run];
+
+	[sdlMain release];
+	[pool release];
 }
 
 #endif
@@ -275,60 +275,60 @@
  */
 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
 {
-    const char *temparg;
-    size_t arglen;
-    char *arg;
-    char **newargv;
+	const char *temparg;
+	size_t arglen;
+	char *arg;
+	char **newargv;
 
-    if (!gFinderLaunch)  /* MacOS is passing command line args. */
-        return FALSE;
+	if (!gFinderLaunch)  /* MacOS is passing command line args. */
+		return FALSE;
 
-    if (gCalledAppMainline)  /* app has started, ignore this document. */
-        return FALSE;
+	if (gCalledAppMainline)  /* app has started, ignore this document. */
+		return FALSE;
 
-    temparg = [filename UTF8String];
-    arglen = SDL_strlen(temparg) + 1;
-    arg = (char *) SDL_malloc(arglen);
-    if (arg == NULL)
-        return FALSE;
+	temparg = [filename UTF8String];
+	arglen = SDL_strlen(temparg) + 1;
+	arg = (char *) SDL_malloc(arglen);
+	if (arg == NULL)
+		return FALSE;
 
-    newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
-    if (newargv == NULL)
-    {
-        SDL_free(arg);
-        return FALSE;
-    }
-    gArgv = newargv;
+	newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
+	if (newargv == NULL)
+	{
+		SDL_free(arg);
+		return FALSE;
+	}
+	gArgv = newargv;
 
-    SDL_strlcpy(arg, temparg, arglen);
-    gArgv[gArgc++] = arg;
-    gArgv[gArgc] = NULL;
-    return TRUE;
+	SDL_strlcpy(arg, temparg, arglen);
+	gArgv[gArgc++] = arg;
+	gArgv[gArgc] = NULL;
+	return TRUE;
 }
 
 
 /* Called when the internal event loop has just started running */
 - (void) applicationDidFinishLaunching: (NSNotification *) note
 {
-    int status;
+	int status;
 
-    /* Set the working directory to the .app's parent directory */
-    [self setupWorkingDirectory:gFinderLaunch];
+	/* Set the working directory to the .app's parent directory */
+	[self setupWorkingDirectory:gFinderLaunch];
 
 #if SDL_USE_NIB_FILE
-    /* Set the main menu to contain the real app name instead of "SDL App" */
-    [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
+	/* Set the main menu to contain the real app name instead of "SDL App" */
+	[self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
 #endif
-	
+
 	/* Set up the app to receive menu events via keyboard shortcut */
 	setenv("SDL_ENABLEAPPEVENTS", "1", 1);
 
-    /* Hand off to main application code */
-    gCalledAppMainline = TRUE;
-    status = SDL_main (gArgc, gArgv);
+	/* Hand off to main application code */
+	gCalledAppMainline = TRUE;
+	status = SDL_main (gArgc, gArgv);
 
-    /* We're done, thank you for playing */
-    exit(status);
+	/* We're done, thank you for playing */
+	exit(status);
 }
 @end
 
@@ -337,37 +337,37 @@
 
 - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
 {
-    unsigned int bufferSize;
-    unsigned int selfLen = [self length];
-    unsigned int aStringLen = [aString length];
-    unichar *buffer;
-    NSRange localRange;
-    NSString *result;
+	unsigned int bufferSize;
+	unsigned int selfLen = [self length];
+	unsigned int aStringLen = [aString length];
+	unichar *buffer;
+	NSRange localRange;
+	NSString *result;
+
+	bufferSize = selfLen + aStringLen - aRange.length;
+	buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
+
+	/* Get first part into buffer */
+	localRange.location = 0;
+	localRange.length = aRange.location;
+	[self getCharacters:buffer range:localRange];
 
-    bufferSize = selfLen + aStringLen - aRange.length;
-    buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
-    
-    /* Get first part into buffer */
-    localRange.location = 0;
-    localRange.length = aRange.location;
-    [self getCharacters:buffer range:localRange];
-    
-    /* Get middle part into buffer */
-    localRange.location = 0;
-    localRange.length = aStringLen;
-    [aString getCharacters:(buffer+aRange.location) range:localRange];
-     
-    /* Get last part into buffer */
-    localRange.location = aRange.location + aRange.length;
-    localRange.length = selfLen - localRange.location;
-    [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
-    
-    /* Build output string */
-    result = [NSString stringWithCharacters:buffer length:bufferSize];
-    
-    NSDeallocateMemoryPages(buffer, bufferSize);
-    
-    return result;
+	/* Get middle part into buffer */
+	localRange.location = 0;
+	localRange.length = aStringLen;
+	[aString getCharacters:(buffer+aRange.location) range:localRange];
+
+	/* Get last part into buffer */
+	localRange.location = aRange.location + aRange.length;
+	localRange.length = selfLen - localRange.location;
+	[self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
+
+	/* Build output string */
+	result = [NSString stringWithCharacters:buffer length:bufferSize];
+
+	NSDeallocateMemoryPages(buffer, bufferSize);
+
+	return result;
 }
 
 @end
@@ -382,56 +382,81 @@
 /* Main entry point to executable - should *not* be SDL_main! */
 int main (int argc, char **argv)
 {
-    /* Copy the arguments into a global variable */
-    /* This is passed if we are launched by double-clicking */
-    if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
-        gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
-        gArgv[0] = argv[0];
-        gArgv[1] = NULL;
-        gArgc = 1;
-        gFinderLaunch = YES;
-		
-		/* check to see if there are any .love files in Resources - props to stevejohnson/diordna */
-		NSArray *lovePaths = [[NSBundle mainBundle] pathsForResourcesOfType:@"love" inDirectory:nil];
-		if ([lovePaths count] > 0) { /* there are, load the first one we found and run it */
-			NSString *firstLovePath = [lovePaths objectAtIndex:0];
-			gCalledAppMainline = YES;
-			//NSLog(firstLovePath);
-			
-			const char *temparg;
-			size_t arglen;
-			char *arg;
-			char **newargv;
-			
-			temparg = [firstLovePath UTF8String];
-			arglen = SDL_strlen(temparg) + 1;
-			arg = (char *)SDL_malloc(arglen);
-			if (arg == NULL)
-				return FALSE;
-			newargv = (char **)realloc(gArgv, sizeof(char *) * (gArgc + 2));
-			if (newargv == NULL) {
-				SDL_free(arg);
-				return FALSE;
-			}
-			gArgv = newargv;
-			SDL_strlcpy(arg, temparg, arglen);
-			gArgv[gArgc++] = arg;
-			gArgv[gArgc] = NULL;
+	/* Copy the arguments into a global variable */
+	/* This is passed if we are launched by double-clicking */
+	if (argc >= 2 && strncmp (argv[1], "-psn", 4) == 0)
+	{
+		gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
+		gArgv[0] = argv[0];
+		gArgv[1] = NULL;
+		gArgc = 1;
+		gFinderLaunch = YES;
+	}
+	else
+	{
+		int i;
+		gArgc = argc;
+		gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
+		for (i = 0; i <= argc; i++)
+			gArgv[i] = argv[i];
+		gFinderLaunch = NO;
+	}
+
+	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+	/* check to see if there are any .love files in Resources - props to stevejohnson/diordna */
+	NSArray *lovePaths = [[NSBundle mainBundle] pathsForResourcesOfType:@"love" inDirectory:nil];
+
+	if ([lovePaths count] > 0) /* there are, load the first one we found and run it */
+	{
+		NSString *firstLovePath = [lovePaths objectAtIndex:0];
+		gCalledAppMainline = YES;
+
+		const char *temparg;
+		size_t arglen;
+		char *arg;
+		char **newargv;
+
+		temparg = [firstLovePath UTF8String];
+		arglen = SDL_strlen(temparg) + 1;
+
+		arg = (char *)SDL_malloc(arglen);
+		if (arg == NULL)
+			return FALSE;
+
+		const char *fusedstr = "--fused";
+		size_t fusedarglen = SDL_strlen(fusedstr) + 1;
+
+		char *fusedarg = (char *) SDL_malloc(fusedarglen);
+		if (fusedarg == NULL)
+		{
+			SDL_free(arg);
+			return FALSE;
 		}
-    } else {
-        int i;
-        gArgc = argc;
-        gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
-        for (i = 0; i <= argc; i++)
-            gArgv[i] = argv[i];
-        gFinderLaunch = NO;
-    }
+
+		newargv = (char **) realloc(gArgv, sizeof(char *) * (gArgc + 3));
+		if (newargv == NULL)
+		{
+			SDL_free(arg);
+			SDL_free(fusedarg);
+			return FALSE;
+		}
+
+		gArgv = newargv;
+		SDL_strlcpy(arg, temparg, arglen);
+		SDL_strlcpy(fusedarg, fusedstr, fusedarglen);
+		gArgv[gArgc++] = arg;
+		gArgv[gArgc++] = fusedarg; // run in pseudo-fused mode
+		gArgv[gArgc] = NULL;
+	}
+
+	[pool drain];
 
 #if SDL_USE_NIB_FILE
-    [SDLApplication poseAsClass:[NSApplication class]];
-    NSApplicationMain (argc, argv);
+	[SDLApplication poseAsClass:[NSApplication class]];
+	NSApplicationMain (argc, argv);
 #else
-    CustomApplicationMain (argc, argv);
+	CustomApplicationMain (argc, argv);
 #endif
-    return 0;
+	return 0;
 }
--- a/src/modules/filesystem/physfs/Filesystem.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/filesystem/physfs/Filesystem.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -174,12 +174,12 @@
 	return true;
 }
 
-File *Filesystem::newFile(const char *filename)
+File *Filesystem::newFile(const char *filename) const
 {
 	return new File(filename);
 }
 
-FileData *Filesystem::newFileData(void *data, unsigned int size, const char *filename)
+FileData *Filesystem::newFileData(void *data, unsigned int size, const char *filename) const
 {
 	FileData *fd = new FileData(size, std::string(filename));
 
@@ -189,7 +189,7 @@
 	return fd;
 }
 
-FileData *Filesystem::newFileData(const char *b64, const char *filename)
+FileData *Filesystem::newFileData(const char *b64, const char *filename) const
 {
 	int size = strlen(b64);
 	int outsize = 0;
@@ -270,21 +270,21 @@
 	return save_path_full.c_str();
 }
 
-bool Filesystem::exists(const char *file)
+bool Filesystem::exists(const char *file) const
 {
 	if (PHYSFS_exists(file))
 		return true;
 	return false;
 }
 
-bool Filesystem::isDirectory(const char *file)
+bool Filesystem::isDirectory(const char *file) const
 {
 	if (PHYSFS_isDirectory(file))
 		return true;
 	return false;
 }
 
-bool Filesystem::isFile(const char *file)
+bool Filesystem::isFile(const char *file) const
 {
 	return exists(file) && !isDirectory(file);
 }
@@ -309,118 +309,36 @@
 	return true;
 }
 
-int Filesystem::read(lua_State *L)
+Data *Filesystem::read(const char *filename, int64 size) const
 {
-	// The file to read from. The file must either be created
-	// on-the-fly, or passed as a parameter.
-	File *file;
-
-	if (lua_isstring(L, 1))
-	{
-		// Create the file.
-		file = newFile(lua_tostring(L, 1));
-	}
-	else
-		return luaL_error(L, "Expected filename.");
-
-	// Optionally, the caller can specify whether to read
-	// the whole file, or just a part of it.
-	int count = luaL_optint(L, 2, (lua_Integer)file->getSize()); // FIXME
+	File file(filename);
 
-	// Read the data.
-	Data *data = file->read(count);
-
-	// Error check.
-	if (data == 0)
-		return luaL_error(L, "File could not be read.");
+	file.open(File::READ);
 
-	// Close and delete the file, if we created it.
-	// (I.e. if the first parameter is a string).
-	if (lua_isstring(L, 1))
-		file->release();
-
-	// Push the string.
-	lua_pushlstring(L, (char *)data->getData(), data->getSize());
-
-	// Push the size.
-	lua_pushinteger(L, data->getSize());
-
-	// Lua has a copy now, so we can free it.
-	data->release();
-
-	return 2;
+	// close() is called in the File destructor.
+	return file.read(size);
 }
 
-int Filesystem::write(lua_State *L)
+void Filesystem::write(const char *filename, const void *data, int64 size) const
 {
-	// The file to write to. The file must either be created
-	// on-the-fly, or passed as a parameter.
-	File *file;
-
-	// We know for sure that we need a second parameter, so
-	// let's check that first.
-	if (lua_isnoneornil(L, 2))
-		return luaL_error(L, "Second argument needed.");
+	File file(filename);
 
-	if (lua_isstring(L, 1))
-	{
-		// Create the file.
-		file = newFile(lua_tostring(L, 1));
-	}
-	else
-		return luaL_error(L, "Expected filename.");
-
-	// Get the current mode of the file.
-	File::Mode mode = file->getMode();
-
-	if (mode == File::CLOSED)
-	{
-		// It should be possible to use append mode, but
-		// normal File::Mode::Write is the default.
-		int mode = luaL_optint(L, 4, File::WRITE);
-
-		// Open the file.
-		if (!file->open((File::Mode)mode))
-			return luaL_error(L, "Could not open file.");
-	}
+	file.open(File::WRITE);
 
-	size_t length = 0;
-	const char *input;
-	if (lua_isstring(L, 2))
-	{
-		input = lua_tolstring(L, 2, &length);
-	}
-	else if (luax_istype(L, 2, DATA_T))
-	{
-		love::Data *data = luax_totype<love::Data>(L, 2, "Data", DATA_T);
-		length = data->getSize();
-		input = (char *)data->getData();
-	}
-	else
-	{
-		return luaL_error(L, "Expected string or data for argument #2.");
-	}
+	// close() is called in the File destructor.
+	if (!file.write(data, size))
+		throw love::Exception("Data could not be written.");
+}
 
-	// Get how much we should write. Length of string default.
-	length = luaL_optint(L, 3, length);
-
-	// Write the data.
-	bool success = file->write(input, length);
+void Filesystem::append(const char *filename, const void *data, int64 size) const
+{
+	File file(filename);
 
-	// Close and delete the file, if we created
-	// it in this function.
-	if (lua_isstring(L, 1))
-	{
-		// Kill the file if "we" created it.
-		file->close();
-		file->release();
-	}
+	file.open(File::APPEND);
 
-	if (!success)
-		return luaL_error(L, "Data could not be written.");
-
-	lua_pushboolean(L, success);
-	return 1;
+	// close() is called in the File destructor.
+	if (!file.write(data, size))
+		throw love::Exception("Data could not be written.");
 }
 
 int Filesystem::enumerate(lua_State *L)
@@ -553,56 +471,21 @@
 	return 0;
 }
 
-int Filesystem::load(lua_State *L)
+int64 Filesystem::getLastModified(const char *filename) const
 {
-	// Need only one arg.
-	luax_assert_argc(L, 1, 1);
-
-	// Must be string.
-	if (!lua_isstring(L, -1))
-		return luaL_error(L, "The argument must be a string.");
-
-	std::string filename = lua_tostring(L, -1);
-
-	// The file must exist.
-	if (!exists(filename.c_str()))
-		return luaL_error(L, "File %s does not exist.", filename.c_str());
-
-	// Create the file.
-	File *file = newFile(filename.c_str());
+	PHYSFS_sint64 time = PHYSFS_getLastModTime(filename);
 
-	// Get the data from the file.
-	Data *data = file->read();
-
-	int status = luaL_loadbuffer(L, (const char *)data->getData(), data->getSize(), ("@" + filename).c_str());
-
-	data->release();
-	file->release();
+	if (time == -1)
+		throw love::Exception("Could not determine file modification date.");
 
-	// Load the chunk, but don't run it.
-	switch (status)
-	{
-	case LUA_ERRMEM:
-		return luaL_error(L, "Memory allocation error: %s\n", lua_tostring(L, -1));
-	case LUA_ERRSYNTAX:
-		return luaL_error(L, "Syntax error: %s\n", lua_tostring(L, -1));
-	default: // success
-		return 1;
-	}
+	return time;
 }
 
-int Filesystem::getLastModified(lua_State *L)
+int64 Filesystem::getSize(const char *filename) const
 {
-	const char *filename = luaL_checkstring(L, 1);
-	PHYSFS_sint64 time = PHYSFS_getLastModTime(filename);
-	if (time == -1)
-	{
-		lua_pushnil(L);
-		lua_pushstring(L, "Could not determine file modification date.");
-		return 2;
-	}
-	lua_pushnumber(L, static_cast<lua_Number>(time));
-	return 1;
+	File file(filename);
+	int64 size = file.getSize();
+	return size;
 }
 
 } // physfs
--- a/src/modules/filesystem/physfs/Filesystem.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/filesystem/physfs/Filesystem.h	Thu Mar 21 17:23:45 2013 -0300
@@ -147,7 +147,7 @@
 	/**
 	 * Creates a new file.
 	 **/
-	File *newFile(const char *filename);
+	File *newFile(const char *filename) const;
 
 	/**
 	 * Creates a new FileData object. Data will be copied.
@@ -155,13 +155,13 @@
 	 * @param size The size of the data.
 	 * @param filename The full filename used to file type identification.
 	 **/
-	FileData *newFileData(void *data, unsigned int size, const char *filename);
+	FileData *newFileData(void *data, unsigned int size, const char *filename) const;
 
 	/**
 	 * Creates a new FileData object from base64 data.
 	 * @param b64 The base64 data.
 	 **/
-	FileData *newFileData(const char *b64, const char *filename);
+	FileData *newFileData(const char *b64, const char *filename) const;
 
 	/**
 	 * Gets the current working directory.
@@ -190,20 +190,20 @@
 	 * or not.
 	 * @param file The filename to check.
 	 **/
-	bool exists(const char *file);
+	bool exists(const char *file) const;
 
 	/**
 	 * Checks if an existing file really is a directory.
 	 * @param file The filename to check.
 	 **/
-	bool isDirectory(const char *file);
+	bool isDirectory(const char *file) const;
 
 	/**
 	 * Checks if an existing file really is a file,
 	 * and not a directory.
 	 * @param file The filename to check.
 	 **/
-	bool isFile(const char *file);
+	bool isFile(const char *file) const;
 
 	/**
 	 * Creates a directory. Write dir must be set.
@@ -232,20 +232,27 @@
 	bool close(File *file);
 
 	/**
-	 * Reads count bytes from an open file.
-	 * The first parameter is either a File or
-	 * a string. An optional second parameter specified the
-	 * max number of bytes to read.
+	 * Reads data from a file.
+	 * @param filename The name of the file to read from.
+	 * @param size The size in bytes of the data to read.
 	 **/
-	int read(lua_State *L);
+	Data *read(const char *filename, int64 size = File::ALL) const;
 
 	/**
-	 * Write the bytes in data to the file. File
-	 * must be opened for write.
-	 * The first parameter is either a File or
-	 * a string.
+	 * Write data to a file.
+	 * @param filename The name of the file to write to.
+	 * @param data The data to write.
+	 * @param size The size in bytes of the data to write.
 	 **/
-	int write(lua_State *L);
+	void write(const char *filename, const void *data, int64 size) const;
+
+	/**
+	 * Append data to a file, creating it if it doesn't exist.
+	 * @param filename The name of the file to write to.
+	 * @param data The data to append.
+	 * @param size The size in bytes of the data to append.
+	 **/
+	void append(const char *filename, const void *data, int64 size) const;
 
 	/**
 	 * Check if end-of-file is reached.
@@ -272,14 +279,17 @@
 	int enumerate(lua_State *L);
 
 	/**
-	 * Loads a file without running it. The loaded
-	 * chunk is returned as a function.
-	 * @param filename The filename of the file to load.
-	 * @return A function.
+	 * Gets the last modification time of a file, in seconds
+	 * since the Unix epoch.
+	 * @param filename The name of the file.
 	 **/
-	int load(lua_State *L);
+	int64 getLastModified(const char *filename) const;
 
-	int getLastModified(lua_State *L);
+	/**
+	 * Gets the size of a file in bytes.
+	 * @param filename The name of the file.
+	 **/
+	int64 getSize(const char *filename) const;
 
 	/**
 	 * Text file line-reading iterator function used and
--- a/src/modules/filesystem/physfs/wrap_Filesystem.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/filesystem/physfs/wrap_Filesystem.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -199,26 +199,80 @@
 
 int w_read(lua_State *L)
 {
+	const char *filename = luaL_checkstring(L, 1);
+	int64 len = (int64) luaL_optinteger(L, 2, File::ALL);
+
+	Data *data = 0;
 	try
 	{
-		return instance->read(L);
+		data = instance->read(filename, len);
+	}
+	catch (love::Exception &e)
+	{
+		return luaL_error(L, "%s", e.what());
 	}
-	catch(Exception e)
+
+	if (data == 0)
+		return luaL_error(L, "File could not be read.");
+
+	// Push the string.
+	lua_pushlstring(L, (const char *) data->getData(), data->getSize());
+
+	// Push the size.
+	lua_pushinteger(L, data->getSize());
+
+	// Lua has a copy now, so we can free it.
+	data->release();
+
+	return 2;
+}
+
+static int w_write_or_append(lua_State *L, File::Mode mode)
+{
+	const char *filename = luaL_checkstring(L, 1);
+
+	const char *input = 0;
+	size_t len = 0;
+
+	if (luax_istype(L, 2, DATA_T))
 	{
-		return luaL_error(L, e.what());
+		love::Data *data = luax_totype<love::Data>(L, 2, "Data", DATA_T);
+		input = (const char *) data->getData();
+		len = data->getSize();
 	}
+	else if (lua_isstring(L, 2))
+		input = lua_tolstring(L, 2, &len);
+	else
+		return luaL_argerror(L, 2, "string or Data expected");
+
+	// Get how much we should write. Length of string default.
+	len = luaL_optinteger(L, 3, len);
+
+	try
+	{
+		if (mode == File::APPEND)
+			instance->append(filename, (const void *) input, len);
+		else
+			instance->write(filename, (const void *) input, len);
+	}
+	catch (love::Exception &e)
+	{
+		return luaL_error(L, "%s", e.what());
+	}
+
+	luax_pushboolean(L, true);
+
+	return 1;
 }
 
 int w_write(lua_State *L)
 {
-	try
-	{
-		return instance->write(L);
-	}
-	catch(Exception e)
-	{
-		return luaL_error(L, e.what());
-	}
+	return w_write_or_append(L, File::WRITE);
+}
+
+int w_append(lua_State *L)
+{
+	return w_write_or_append(L, File::APPEND);
 }
 
 int w_enumerate(lua_State *L)
@@ -253,19 +307,78 @@
 
 int w_load(lua_State *L)
 {
+	std::string filename = std::string(luaL_checkstring(L, 1));
+
+	Data *data = 0;
 	try
 	{
-		return instance->load(L);
+		data = instance->read(filename.c_str());
+	}
+	catch (love::Exception &e)
+	{
+		return luaL_error(L, "%s", e.what());
 	}
-	catch(love::Exception &e)
+
+	int status = luaL_loadbuffer(L, (const char *)data->getData(), data->getSize(), ("@" + filename).c_str());
+
+	data->release();
+
+	// Load the chunk, but don't run it.
+	switch (status)
 	{
-		return luaL_error(L, e.what());
+	case LUA_ERRMEM:
+		return luaL_error(L, "Memory allocation error: %s\n", lua_tostring(L, -1));
+	case LUA_ERRSYNTAX:
+		return luaL_error(L, "Syntax error: %s\n", lua_tostring(L, -1));
+	default: // success
+		return 1;
 	}
 }
 
 int w_getLastModified(lua_State *L)
 {
-	return instance->getLastModified(L);
+	const char *filename = luaL_checkstring(L, 1);
+
+	int64 time = 0;
+	try
+	{
+		time = instance->getLastModified(filename);
+	}
+	catch (love::Exception &e)
+	{
+		lua_pushnil(L);
+		lua_pushstring(L, e.what());
+		return 2;
+	}
+
+	lua_pushnumber(L, static_cast<lua_Number>(time));
+
+	return 1;
+}
+
+int w_getSize(lua_State *L)
+{
+	const char *filename = luaL_checkstring(L, 1);
+
+	int64 size = -1;
+	try
+	{
+		size = instance->getSize(filename);
+	}
+	catch (love::Exception &e)
+	{
+		return luaL_error(L, "%s", e.what());
+	}
+
+	// Error on failure or if size does not fit into a double precision floating-point number.
+	if (size == -1)
+		return luaL_error(L, "Could not determine file size.");
+	else if (size >= 0x20000000000000LL)
+		return luaL_error(L, "Size too large to fit into a Lua number!");
+
+
+	lua_pushnumber(L, (lua_Number) size);
+	return 1;
 }
 
 int loader(lua_State *L)
@@ -291,7 +404,7 @@
 		lua_pop(L, 1);
 		lua_pushstring(L, tmp.c_str());
 		// Ok, load it.
-		return instance->load(L);
+		return w_load(L);
 	}
 
 	tmp = filename;
@@ -312,7 +425,7 @@
 			lua_pop(L, 1);
 			lua_pushstring(L, tmp.c_str());
 			// Ok, load it.
-			return instance->load(L);
+			return w_load(L);
 		}
 	}
 
@@ -391,10 +504,12 @@
 	{ "remove",  w_remove },
 	{ "read",  w_read },
 	{ "write",  w_write },
+	{ "append", w_append },
 	{ "enumerate",  w_enumerate },
 	{ "lines",  w_lines },
 	{ "load",  w_load },
 	{ "getLastModified", w_getLastModified },
+	{ "getSize", w_getSize },
 	{ "newFileData", w_newFileData },
 	{ 0, 0 }
 };
--- a/src/modules/filesystem/physfs/wrap_Filesystem.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/filesystem/physfs/wrap_Filesystem.h	Thu Mar 21 17:23:45 2013 -0300
@@ -57,6 +57,7 @@
 int w_close(lua_State *L);
 int w_read(lua_State *L);
 int w_write(lua_State *L);
+int w_append(lua_State *L);
 int w_eof(lua_State *L);
 int w_tell(lua_State *L);
 int w_seek(lua_State *L);
@@ -64,6 +65,7 @@
 int w_lines(lua_State *L);
 int w_load(lua_State *L);
 int w_getLastModified(lua_State *L);
+int w_getSize(lua_State *L);
 int loader(lua_State *L);
 int extloader(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_filesystem(lua_State *L);
--- a/src/modules/graphics/Image.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/Image.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -31,6 +31,7 @@
 	: min(FILTER_LINEAR)
 	, mag(FILTER_LINEAR)
 	, mipmap(FILTER_NONE)
+	, anisotropy(1.0f)
 {
 }
 
--- a/src/modules/graphics/Image.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/Image.h	Thu Mar 21 17:23:45 2013 -0300
@@ -56,6 +56,7 @@
 		FilterMode min;
 		FilterMode mag;
 		FilterMode mipmap;
+		float anisotropy;
 	};
 
 	struct Wrap
@@ -78,7 +79,7 @@
 
 private:
 
-	// The default image filter
+	// The default texture filter.
 	static Filter defaultFilter;
 
 	static StringMap<FilterMode, FILTER_MAX_ENUM>::Entry filterModeEntries[];
--- a/src/modules/graphics/opengl/Canvas.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Canvas.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -19,8 +19,10 @@
  **/
 
 #include "Canvas.h"
+#include "Image.h"
 #include "Graphics.h"
 #include "common/Matrix.h"
+#include "common/config.h"
 
 #include <cstring> // For memcpy
 
--- a/src/modules/graphics/opengl/Context.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Context.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -56,6 +56,8 @@
 }
 
 Context::Context()
+	: shadersSupported(false)
+	, maxAnisotropy(1.0f)
 {
 	initExtensions();
 	initState();
@@ -282,6 +284,12 @@
 		glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &state.defaultFramebuffer);
 	else
 		state.defaultFramebuffer = 0;
+
+	// get the maximum anisotropic filtering value
+	if (GLEW_EXT_texture_filter_anisotropic)
+		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
+	else
+		maxAnisotropy = 1.0f;
 }
 
 void Context::setupRender()
@@ -670,7 +678,7 @@
 	glDeleteTextures(1, &texture);
 }
 
-void Context::setTextureFilter(const graphics::Image::Filter &f) const
+float Context::setTextureFilter(const graphics::Image::Filter &f) const
 {
 	GLint gmin, gmag;
 
@@ -708,6 +716,16 @@
 
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gmin);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gmag);
+
+	float anisotropy = 1.0f;
+
+	if (GLEW_EXT_texture_filter_anisotropic)
+	{
+		anisotropy = std::min(std::max(f.anisotropy, 1.0f), maxAnisotropy);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
+	}
+
+	return anisotropy;
 }
 
 graphics::Image::Filter Context::getTextureFilter() const
@@ -756,6 +774,9 @@
 		break;
 	}
 
+	if (GLEW_EXT_texture_filter_anisotropic)
+		glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &f.anisotropy);
+
 	return f;
 }
 
--- a/src/modules/graphics/opengl/Context.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Context.h	Thu Mar 21 17:23:45 2013 -0300
@@ -254,8 +254,9 @@
 
 	/**
 	 * Sets the image filter mode for the currently bound texture.
+	 * Returns the actual amount of anisotropic filtering set.
 	 */
-	void setTextureFilter(const graphics::Image::Filter &f) const;
+	float setTextureFilter(const graphics::Image::Filter &f) const;
 
 	/**
 	 * Gets the image filter mode for the currently bound texture.
@@ -327,6 +328,7 @@
 	} state;
 
 	bool shadersSupported;
+	float maxAnisotropy;
 
 	static bool extensionsInitialized;
 
--- a/src/modules/graphics/opengl/Font.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Font.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -539,8 +539,8 @@
 	for (it = textures.begin(); it != textures.end(); ++it)
 	{
 		ctx->bindTexture(*it);
-		ctx->setTextureFilter(f);
-	}	
+		filter.anisotropy = ctx->setTextureFilter(f);
+	}
 }
 
 const Image::Filter &Font::getFilter()
--- a/src/modules/graphics/opengl/Graphics.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Graphics.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -584,16 +584,28 @@
 	return BLEND_MAX_ENUM; // Should never be reached.
 }
 
-void Graphics::setDefaultImageFilter(const Image::Filter &f)
+void Graphics::setDefaultFilter(const Image::Filter &f)
 {
 	Image::setDefaultFilter(f);
 }
 
-const Image::Filter &Graphics::getDefaultImageFilter() const
+const Image::Filter &Graphics::getDefaultFilter() const
 {
 	return Image::getDefaultFilter();
 }
 
+void Graphics::setDefaultMipmapFilter(Image::FilterMode filter, float sharpness)
+{
+	Image::setDefaultMipmapFilter(filter);
+	Image::setDefaultMipmapSharpness(sharpness);
+}
+
+void Graphics::getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness) const
+{
+	*filter = Image::getDefaultMipmapFilter();
+	*sharpness = Image::getDefaultMipmapSharpness();
+}
+
 void Graphics::setLineWidth(float width)
 {
 	lineWidth = width;
@@ -668,7 +680,7 @@
 	}
 }
 
-void Graphics::printf(const char *str, float x, float y, float wrap, AlignMode align)
+void Graphics::printf(const char *str, float x, float y, float wrap, AlignMode align, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
 {
 	if (currentFont == 0)
 		return;
@@ -677,34 +689,55 @@
 	string text(str);
 	vector<string> lines_to_draw = currentFont->getWrap(text, wrap);
 
-	// now for the actual printing
-	vector<string>::const_iterator line_iter, line_end = lines_to_draw.end();
-	float letter_spacing = 0.0f;
-	for (line_iter = lines_to_draw.begin(); line_iter != line_end; ++line_iter)
+	Context *ctx = getContext();
+
+	ctx->modelViewStack.push(ctx->modelViewStack.top());
+	glPushMatrix();
+
+	static Matrix t;
+	t.setTransformation(ceil(x), ceil(y), angle, sx, sy, ox, oy, kx, ky);
+	ctx->modelViewStack.top() *= t;
+
+	x = y = 0.0f;
+
+	try
 	{
-		float width = static_cast<float>(currentFont->getWidth(*line_iter));
-		switch (align)
+		// now for the actual printing
+		vector<string>::const_iterator line_iter, line_end = lines_to_draw.end();
+		float letter_spacing = 0.0f;
+		for (line_iter = lines_to_draw.begin(); line_iter != line_end; ++line_iter)
 		{
-		case ALIGN_RIGHT:
-			currentFont->print(*line_iter, ceil(x + wrap - width), ceil(y));
-			break;
-		case ALIGN_CENTER:
-			currentFont->print(*line_iter, ceil(x + (wrap - width) / 2), ceil(y));
-			break;
-		case ALIGN_JUSTIFY:
-			if (line_iter->length() > 1 && (line_iter+1) != line_end)
-				letter_spacing = (wrap - width) / float(line_iter->length() - 1);
-			else
-				letter_spacing = 0.0f;
-			currentFont->print(*line_iter, ceil(x), ceil(y), letter_spacing);
-			break;
-		case ALIGN_LEFT:
-		default:
-			currentFont->print(*line_iter, ceil(x), ceil(y));
-			break;
+			float width = static_cast<float>(currentFont->getWidth(*line_iter));
+			switch (align)
+			{
+			case ALIGN_RIGHT:
+				currentFont->print(*line_iter, ceil(x + (wrap - width)), ceil(y), 0.0f);
+				break;
+			case ALIGN_CENTER:
+				currentFont->print(*line_iter, ceil(x + (wrap - width) / 2), ceil(y), 0.0f);
+				break;
+			case ALIGN_JUSTIFY:
+				if (line_iter->length() > 1 && (line_iter+1) != line_end)
+					letter_spacing = (wrap - width) / float(line_iter->length() - 1);
+				else
+					letter_spacing = 0.0f;
+				currentFont->print(*line_iter, ceil(x), ceil(y), letter_spacing);
+				break;
+			case ALIGN_LEFT:
+			default:
+				currentFont->print(*line_iter, ceil(x), ceil(y), 0.0f);
+				break;
+			}
+			y += currentFont->getHeight() * currentFont->getLineHeight();
 		}
-		y += currentFont->getHeight() * currentFont->getLineHeight();
 	}
+	catch (love::Exception &)
+	{
+		ctx->modelViewStack.pop();
+		throw;
+	}
+
+	ctx->modelViewStack.pop();
 }
 
 /**
--- a/src/modules/graphics/opengl/Graphics.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Graphics.h	Thu Mar 21 17:23:45 2013 -0300
@@ -310,19 +310,25 @@
 	void setBlendMode(BlendMode mode);
 
 	/**
-	 * Sets the current image filter.
-	 **/
-	void setDefaultImageFilter(const Image::Filter &f);
-
-	/**
 	 * Gets the current blend mode.
 	 **/
 	BlendMode getBlendMode() const;
 
 	/**
-	 * Gets the current image filter.
+	 * Sets the default filter for images, canvases, and fonts.
+	 **/
+	void setDefaultFilter(const Image::Filter &f);
+
+	/**
+	 * Gets the default filter for images, canvases, and fonts.
 	 **/
-	const Image::Filter &getDefaultImageFilter() const;
+	const Image::Filter &getDefaultFilter() const;
+
+	/**
+	 * Default Image mipmap filter mode and sharpness values.
+	 **/
+	void setDefaultMipmapFilter(Image::FilterMode filter, float sharpness);
+	void getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness) const;
 
 	/**
 	 * Sets the line width.
@@ -397,7 +403,7 @@
 	 * @param kx Shear along the x-axis.
 	 * @param ky Shear along the y-axis.
 	 **/
-	void print(const char *str, float x, float y , float angle, float sx, float sy, float ox, float oy, float kx, float ky);
+	void print(const char *str, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
 
 	/**
 	 * Draw formatted text on screen at the specified coordinates.
@@ -407,8 +413,15 @@
 	 * @param y The y-coordinate.
 	 * @param wrap The maximum width of the text area.
 	 * @param align Where to align the text.
+	 * @param angle The amount of rotation.
+	 * @param sx The scale factor along the x-axis. (1 = normal).
+	 * @param sy The scale factor along the y-axis. (1 = normal).
+	 * @param ox The origin offset along the x-axis.
+	 * @param oy The origin offset along the y-axis.
+	 * @param kx Shear along the x-axis.
+	 * @param ky Shear along the y-axis.
 	 **/
-	void printf(const char *str, float x, float y, float wrap, AlignMode align);
+	void printf(const char *str, float x, float y, float wrap, AlignMode align, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
 
 	/**
 	 * Draws a point at (x,y).
--- a/src/modules/graphics/opengl/Image.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Image.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -33,11 +33,16 @@
 namespace opengl
 {
 
+float Image::maxMipmapSharpness = 0.0f;
+
+Image::FilterMode Image::defaultMipmapFilter = Image::FILTER_NONE;
+float Image::defaultMipmapSharpness = 0.0f;
+
 Image::Image(love::image::ImageData *data)
 	: width((float)(data->getWidth()))
 	, height((float)(data->getHeight()))
 	, texture(0)
-	, mipmapSharpness(0.0f)
+	, mipmapSharpness(defaultMipmapSharpness)
 	, mipmapsCreated(false)
 {
 	data->retain();
@@ -69,6 +74,7 @@
 	vertices[3].t = 0;
 
 	filter = getDefaultFilter();
+	filter.mipmap = defaultMipmapFilter;
 }
 
 Image::~Image()
@@ -205,7 +211,7 @@
 	filter = f;
 
 	bind();
-	getContext()->setTextureFilter(f);
+	filter.anisotropy = getContext()->setTextureFilter(f);
 	checkMipmapsCreated();
 }
 
@@ -229,14 +235,16 @@
 
 void Image::setMipmapSharpness(float sharpness)
 {
-	if (!hasMipmapSharpnessSupport())
-		return;
+	if (hasMipmapSharpnessSupport())
+	{
+		// LOD bias has the range (-maxbias, maxbias)
+		mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f);
 
-	// LOD bias has the range (-maxbias, maxbias)
-	mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f);
-
-	bind();
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapSharpness); // negative bias is sharper
+		bind();
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapSharpness); // negative bias is sharper
+	}
+	else
+		mipmapSharpness = 0.0f;
 }
 
 float Image::getMipmapSharpness() const
@@ -264,7 +272,7 @@
 
 bool Image::loadVolatile()
 {
-	if (hasMipmapSharpnessSupport())
+	if (hasMipmapSharpnessSupport() && maxMipmapSharpness == 0.0f)
 		glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &maxMipmapSharpness);
 
 	if (hasNpot())
@@ -280,7 +288,7 @@
 	glGenTextures(1,(GLuint *)&texture);
 	ctx->bindTexture(texture);
 
-	ctx->setTextureFilter(filter);
+	filter.anisotropy = ctx->setTextureFilter(filter);
 	ctx->setTextureWrap(wrap);
 
 	float p2width = next_p2(width);
@@ -320,6 +328,7 @@
 
 	mipmapsCreated = false;
 	checkMipmapsCreated();
+
 	setMipmapSharpness(mipmapSharpness);
 
 	return true;
@@ -332,7 +341,7 @@
 	glGenTextures(1,(GLuint *)&texture);
 	ctx->bindTexture(texture);
 
-	ctx->setTextureFilter(filter);
+	filter.anisotropy = ctx->setTextureFilter(filter);
 	ctx->setTextureWrap(wrap);
 
 	while (glGetError() != GL_NO_ERROR); // clear errors
@@ -352,6 +361,7 @@
 
 	mipmapsCreated = false;
 	checkMipmapsCreated();
+
 	setMipmapSharpness(mipmapSharpness);
 
 	return true;
@@ -387,11 +397,36 @@
 	ctx->modelViewStack.pop();
 }
 
+void Image::setDefaultMipmapSharpness(float sharpness)
+{
+	defaultMipmapSharpness = sharpness;
+}
+
+float Image::getDefaultMipmapSharpness()
+{
+	return defaultMipmapSharpness;
+}
+
+void Image::setDefaultMipmapFilter(Image::FilterMode f)
+{
+	defaultMipmapFilter = f;
+}
+
+Image::FilterMode Image::getDefaultMipmapFilter()
+{
+	return defaultMipmapFilter;
+}
+
 bool Image::hasNpot()
 {
 	return GLEW_ES_VERSION_2_0 || GLEW_VERSION_2_0 || GLEW_ARB_texture_non_power_of_two;
 }
 
+bool Image::hasAnisotropicFilteringSupport()
+{
+	return GLEW_EXT_texture_filter_anisotropic;
+}
+
 bool Image::hasMipmapSupport()
 {
 	return GLEW_ES_VERSION_2_0 || GLEW_VERSION_1_4 || GLEW_SGIS_generate_mipmap;
--- a/src/modules/graphics/opengl/Image.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Image.h	Thu Mar 21 17:23:45 2013 -0300
@@ -105,7 +105,6 @@
 	const Image::Wrap &getWrap() const;
 
 	void setMipmapSharpness(float sharpness);
-
 	float getMipmapSharpness() const;
 
 	void bind() const;
@@ -117,7 +116,13 @@
 	bool loadVolatile();
 	void unloadVolatile();
 
+	static void setDefaultMipmapSharpness(float sharpness);
+	static float getDefaultMipmapSharpness();
+	static void setDefaultMipmapFilter(FilterMode f);
+	static FilterMode getDefaultMipmapFilter();
+
 	static bool hasNpot();
+	static bool hasAnisotropicFilteringSupport();
 	static bool hasMipmapSupport();
 	static bool hasMipmapSharpnessSupport();
 
@@ -145,9 +150,6 @@
 	// Mipmap texture LOD bias (sharpness) value.
 	float mipmapSharpness;
 
-	// Implementation-dependent min/max mipmap sharpness values.
-	float maxMipmapSharpness;
-
 	// True if mipmaps have been created for this Image.
 	bool mipmapsCreated;
 
@@ -162,6 +164,11 @@
 
 	void checkMipmapsCreated();
 
+	static float maxMipmapSharpness;
+
+	static FilterMode defaultMipmapFilter;
+	static float defaultMipmapSharpness;
+
 }; // Image
 
 } // opengl
--- a/src/modules/graphics/opengl/Shader.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Shader.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -84,7 +84,7 @@
 	vertexAttribNames[Context::ATTRIB_COLOR] = "VertexColor";
 	vertexAttribNames[Context::ATTRIB_TEXCOORD] = "VertexTexCoord";
 
-	// Make sure we have both vertex and fragment source codes
+	// Make sure we have both vertex and pixel source codes
 	checkCodeCompleteness();
 
 	// load shader source and create program object
@@ -113,13 +113,13 @@
 			throw love::Exception("Cannot create shader: no default vertex shader code!");
 	}
 
-	if (shaderSources.find(TYPE_FRAGMENT) == shaderSources.end())
+	if (shaderSources.find(TYPE_PIXEL) == shaderSources.end())
 	{
-		it = defaultSources.find(TYPE_FRAGMENT);
+		it = defaultSources.find(TYPE_PIXEL);
 		if (it != defaultSources.end())
-			shaderSources[TYPE_FRAGMENT] = it->second;
+			shaderSources[TYPE_PIXEL] = it->second;
 		else
-			throw love::Exception("Cannot create shader: no default fragment shader code!");
+			throw love::Exception("Cannot create shader: no default pixel shader code!");
 	}
 }
 
@@ -134,9 +134,9 @@
 		glshadertype = GL_VERTEX_SHADER;
 		shadertypename = "vertex";
 		break;
-	case TYPE_FRAGMENT:
+	case TYPE_PIXEL:
 		glshadertype = GL_FRAGMENT_SHADER;
-		shadertypename = "fragment";
+		shadertypename = "pixel";
 		break;
 	default:
 		throw love::Exception("Cannot create shader object: unknown shader type.");
@@ -497,10 +497,10 @@
 void Shader::setDefaultSources(const ShaderSources &sources)
 {
 	ShaderSources::const_iterator vertsource = sources.find(TYPE_VERTEX);
-	ShaderSources::const_iterator fragsource = sources.find(TYPE_FRAGMENT);
+	ShaderSources::const_iterator fragsource = sources.find(TYPE_PIXEL);
 
 	if (vertsource == sources.end() || fragsource == sources.end())
-		throw love::Exception("Default shader sources need both vertex and fragment code.");
+		throw love::Exception("Default shader sources need both vertex and pixel code.");
 
 	defaultSources = sources;
 }
--- a/src/modules/graphics/opengl/Shader.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/Shader.h	Thu Mar 21 17:23:45 2013 -0300
@@ -49,7 +49,7 @@
 	enum ShaderType
 	{
 		TYPE_VERTEX,
-		TYPE_FRAGMENT,
+		TYPE_PIXEL,
 		TYPE_MAX_ENUM
 	};
 
@@ -58,7 +58,7 @@
 
 	/**
 	 * Creates a new Shader using a list of source codes.
-	 * Sources must contain either vertex or fragment shader code, or both.
+	 * Sources must contain either vertex or pixel shader code, or both.
 	 **/
 	Shader(const ShaderSources &sources);
 
@@ -138,7 +138,7 @@
 
 	/**
 	 * Sets the source codes used in new Shaders that are missing vertex or
-	 * fragment sources.
+	 * pixel sources.
 	 **/
 	static void setDefaultSources(const ShaderSources &sources);
 
--- a/src/modules/graphics/opengl/wrap_Canvas.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/wrap_Canvas.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -99,6 +99,8 @@
 	if (!Image::getConstant(magstr, f.mag))
 		return luaL_error(L, "Invalid filter mode: %s", magstr);
 
+	f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
+
 	canvas->setFilter(f);
 
 	return 0;
@@ -117,8 +119,9 @@
 
 	lua_pushstring(L, minstr);
 	lua_pushstring(L, magstr);
+	lua_pushnumber(L, f.anisotropy);
 
-	return 2;
+	return 3;
 }
 
 int w_Canvas_setWrap(lua_State *L)
--- a/src/modules/graphics/opengl/wrap_Font.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/wrap_Font.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -103,6 +103,8 @@
 	if (!Image::getConstant(magstr, f.mag))
 		return luaL_error(L, "Invalid filter mode: %s", magstr);
 
+	f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
+
 	try
 	{
 		t->setFilter(f);
@@ -125,7 +127,8 @@
 	Image::getConstant(f.mag, magstr);
 	lua_pushstring(L, minstr);
 	lua_pushstring(L, magstr);
-	return 2;
+	lua_pushnumber(L, f.anisotropy);
+	return 3;
 }
 
 int w_Font_getAscent(lua_State *L)
--- a/src/modules/graphics/opengl/wrap_Graphics.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/wrap_Graphics.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -376,7 +376,7 @@
 	try
 	{
 		// Create the font.
-		font = instance->newFont(rasterizer, instance->getDefaultImageFilter());
+		font = instance->newFont(rasterizer, instance->getDefaultFilter());
 	}
 	catch (love::Exception &e)
 	{
@@ -441,7 +441,7 @@
 	}
 
 	if (!setFilter)
-		img_filter = instance->getDefaultImageFilter();
+		img_filter = instance->getDefaultFilter();
 
 	// Create the font.
 	Font *font = instance->newFont(rasterizer, img_filter);
@@ -528,40 +528,85 @@
 	if (!Shader::isSupported())
 		return luaL_error(L, "Sorry, your graphics card does not support shaders.");
 
+	// clamp stack to 2 elements
+	lua_settop(L, 2);
+
+	// read any filepath arguments
+	for (int i = 1; i <= 2; i++)
+	{
+		if (!lua_isstring(L, i))
+			continue;
+
+		// call love.filesystem.isFile(arg_i)
+		luax_getfunction(L, "filesystem", "isFile");
+		lua_pushvalue(L, i);
+		lua_call(L, 1, 1);
+
+		bool isFile = luax_toboolean(L, -1);
+		lua_pop(L, 1);
+
+		if (isFile)
+		{
+			luax_getfunction(L, "filesystem", "read");
+			lua_pushvalue(L, i);
+			lua_call(L, 1, 1);
+			lua_replace(L, i);
+		}
+	}
+
+	bool has_arg1 = lua_isstring(L, 1);
+	bool has_arg2 = lua_isstring(L, 2);
+
+	// require at least one string argument
+	if (!(has_arg1 || has_arg2))
+		luaL_checkstring(L, 1);
+
+	luax_getfunction(L, "graphics", "_shaderCodeToGLSL");
+
+	// push vertexcode and pixelcode strings to the top of the stack
+	lua_pushvalue(L, 1);
+	lua_pushvalue(L, 2);
+
+	// call effectCodeToGLSL, returned values will be at the top of the stack
+	if (lua_pcall(L, 2, 2, 0) != 0)
+		return luaL_error(L, "%s", lua_tostring(L, -1));
+
+	Shader::ShaderSources sources;
+
+	// vertex shader code
+	if (lua_isstring(L, -2))
+	{
+		std::string vertexcode(luaL_checkstring(L, -2));
+		sources[Shader::TYPE_VERTEX] = vertexcode;
+	}
+	else if (has_arg1 && has_arg2)
+		return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
+
+	// pixel shader code
+	if (lua_isstring(L, -1))
+	{
+		std::string pixelcode(luaL_checkstring(L, -1));
+		sources[Shader::TYPE_PIXEL] = pixelcode;
+	}
+	else if (has_arg1 && has_arg2)
+		return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
+
+	if (sources.empty())
+	{
+		// Original args had source code, but effectCodeToGLSL couldn't translate it
+		for (int i = 1; i <= 2; i++)
+		{
+			if (lua_isstring(L, i))
+				return luaL_argerror(L, i, "missing 'position' or 'effect' function?");
+		}
+	}
+
 	try
 	{
-		// clamp stack to 2 elements
-		lua_settop(L, 2);
-
-		luax_getfunction(L, "graphics", "_shaderCodeToGLSL");
-
-		// push code strings to the top of the stack so they become function arguments
-		lua_pushvalue(L, 1);
-		lua_pushvalue(L, 2);
-
-		// call shaderCodeToGLSL, returned values will be at the top of the stack
-		lua_pcall(L, 2, 2, 0);
-
-		Shader::ShaderSources sources;
-
-		// vertex shader code
-		if (lua_isstring(L, -2))
-		{
-			std::string vertcode(luaL_checkstring(L, -2));
-			sources[Shader::TYPE_VERTEX] = vertcode;
-		}
-
-		// fragment shader code
-		if (lua_isstring(L, -1))
-		{
-			std::string fragcode(luaL_checkstring(L, -1));
-			sources[Shader::TYPE_FRAGMENT] = fragcode;
-		}
-
 		Shader *shader = instance->newShader(sources);
 		luax_newtype(L, "Shader", GRAPHICS_SHADER_T, (void *)shader);
 	}
-	catch(const love::Exception &e)
+	catch (const love::Exception &e)
 	{
 		// memory is freed in Graphics::newShader
 		luax_getfunction(L, "graphics", "_transformGLSLErrorMessages");
@@ -697,28 +742,6 @@
 	return 0;
 }
 
-int w_setDefaultImageFilter(lua_State *L)
-{
-	Image::FilterMode min;
-	Image::FilterMode mag;
-
-	const char *minstr = luaL_checkstring(L, 1);
-	const char *magstr = luaL_optstring(L, 2, minstr);
-
-	if (!Image::getConstant(minstr, min))
-		return luaL_error(L, "Invalid filter mode: %s", minstr);
-	if (!Image::getConstant(magstr, mag))
-		return luaL_error(L, "Invalid filter mode: %s", magstr);
-
-	Image::Filter f;
-	f.min = min;
-	f.mag = mag;
-
-	instance->setDefaultImageFilter(f);
-
-	return 0;
-}
-
 int w_getBlendMode(lua_State *L)
 {
 	try
@@ -736,17 +759,78 @@
 	}
 }
 
-int w_getDefaultImageFilter(lua_State *L)
+int w_setDefaultFilter(lua_State *L)
 {
-	const Image::Filter &f = instance->getDefaultImageFilter();
+	Image::FilterMode min;
+	Image::FilterMode mag;
+
+	const char *minstr = luaL_checkstring(L, 1);
+	const char *magstr = luaL_optstring(L, 2, minstr);
+
+	if (!Image::getConstant(minstr, min))
+		return luaL_error(L, "Invalid filter mode: %s", minstr);
+	if (!Image::getConstant(magstr, mag))
+		return luaL_error(L, "Invalid filter mode: %s", magstr);
+
+	float anisotropy = (float) luaL_optnumber(L, 3, 1.0);
+
+	Image::Filter f;
+	f.min = min;
+	f.mag = mag;
+	f.anisotropy = anisotropy;
+
+	instance->setDefaultFilter(f);
+	
+	return 0;
+}
+
+int w_getDefaultFilter(lua_State *L)
+{
+	const Image::Filter &f = instance->getDefaultFilter();
 	const char *minstr;
 	const char *magstr;
 	if (!Image::getConstant(f.min, minstr))
-		return luaL_error(L, "Unknown filter mode for argument #1");
+		return luaL_error(L, "Unknown minification filter mode");
 	if (!Image::getConstant(f.mag, magstr))
-		return luaL_error(L, "Unknown filter mode for argument #2");
+		return luaL_error(L, "Unknown magnification filter mode");
 	lua_pushstring(L, minstr);
 	lua_pushstring(L, magstr);
+	lua_pushnumber(L, f.anisotropy);
+	return 3;
+}
+
+int w_setDefaultMipmapFilter(lua_State *L)
+{
+	Image::FilterMode filter = Image::FILTER_NONE;
+	if (!lua_isnoneornil(L, 1))
+	{
+		const char *str = luaL_checkstring(L, 1);
+		if (!Image::getConstant(str, filter))
+			return luaL_error(L, "Invalid filter mode: %s", str);
+	}
+
+	float sharpness = luaL_optnumber(L, 2, 0);
+
+	instance->setDefaultMipmapFilter(filter, sharpness);
+
+	return 0;
+}
+
+int w_getDefaultMipmapFilter(lua_State *L)
+{
+	Image::FilterMode filter;
+	float sharpness;
+
+	instance->getDefaultMipmapFilter(&filter, &sharpness);
+
+	const char *str;
+	if (Image::getConstant(filter, str))
+		lua_pushstring(L, str);
+	else
+		lua_pushnil(L);
+	
+	lua_pushnumber(L, sharpness);
+
 	return 2;
 }
 
@@ -951,11 +1035,11 @@
 
 	Shader *shader = luax_checkshader(L, 1);
 
-	// make sure the default shader will have both vertex and fragment source codes
+	// make sure the default shader will have both vertex and pixel source codes
 	const Shader::ShaderSources &sources = shader->getSources();
 	Shader::ShaderSources::const_iterator it;
-	if (sources.find(Shader::TYPE_VERTEX) == sources.end() || sources.find(Shader::TYPE_FRAGMENT) == sources.end())
-		return luaL_error(L, "Default shader must have both vertex and fragment source codes.");
+	if (sources.find(Shader::TYPE_VERTEX) == sources.end() || sources.find(Shader::TYPE_PIXEL) == sources.end())
+		return luaL_error(L, "Default shader must have both vertex and pixel source codes.");
 
 	Shader *prevdefault = Shader::defaultShader;
 
@@ -1009,11 +1093,11 @@
 		sources[Shader::TYPE_VERTEX] = vertcode;
 	}
 
-	// fragment shader code
+	// pixel shader code
 	if (lua_isstring(L, -1))
 	{
 		std::string fragcode(luaL_checkstring(L, -1));
-		sources[Shader::TYPE_FRAGMENT] = fragcode;
+		sources[Shader::TYPE_PIXEL] = fragcode;
 	}
 
 	try
@@ -1168,18 +1252,34 @@
 	float y = (float)luaL_checknumber(L, 3);
 	float wrap = (float)luaL_checknumber(L, 4);
 
+	float angle = 0.0f;
+	float sx = 1.0f, sy = 1.0f;
+	float ox = 0.0f, oy = 0.0f;
+	float kx = 0.0f, ky = 0.0f;
+
 	Graphics::AlignMode align = Graphics::ALIGN_LEFT;
 
 	if (lua_gettop(L) >= 5)
 	{
-		const char *str = luaL_checkstring(L, 5);
-		if (!Graphics::getConstant(str, align))
-			return luaL_error(L, "Incorrect alignment: %s", str);
+		if (!lua_isnil(L, 5))
+		{
+			const char *str = luaL_checkstring(L, 5);
+			if (!Graphics::getConstant(str, align))
+				return luaL_error(L, "Incorrect alignment: %s", str);
+		}
+
+		angle = (float) luaL_optnumber(L, 6, 0.0f);
+		sx = (float) luaL_optnumber(L, 7, 1.0f);
+		sy = (float) luaL_optnumber(L, 8, sx);
+		ox = (float) luaL_optnumber(L, 9, 0.0f);
+		oy = (float) luaL_optnumber(L, 10, 0.0f);
+		kx = (float) luaL_optnumber(L, 11, 0.0f);
+		ky = (float) luaL_optnumber(L, 12, 0.0f);
 	}
 
 	try
 	{
-		instance->printf(str, x, y, wrap, align);
+		instance->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky);
 	}
 	catch(love::Exception e)
 	{
@@ -1434,9 +1534,11 @@
 	{ "getFont", w_getFont },
 
 	{ "setBlendMode", w_setBlendMode },
-	{ "setDefaultImageFilter", w_setDefaultImageFilter },
 	{ "getBlendMode", w_getBlendMode },
-	{ "getDefaultImageFilter", w_getDefaultImageFilter },
+	{ "setDefaultFilter", w_setDefaultFilter },
+	{ "getDefaultFilter", w_getDefaultFilter },
+	{ "setDefaultMipmapFilter", w_setDefaultMipmapFilter },
+	{ "getDefaultMipmapFilter", w_getDefaultMipmapFilter },
 	{ "setLineWidth", w_setLineWidth },
 	{ "setLineStyle", w_setLineStyle },
 	{ "setLine", w_setLine },
--- a/src/modules/graphics/opengl/wrap_Graphics.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/wrap_Graphics.h	Thu Mar 21 17:23:45 2013 -0300
@@ -73,9 +73,11 @@
 int w_setFont(lua_State *L);
 int w_getFont(lua_State *L);
 int w_setBlendMode(lua_State *L);
-int w_setDefaultImageFilter(lua_State *L);
 int w_getBlendMode(lua_State *L);
-int w_getDefaultImageFilter(lua_State *L);
+int w_setDefaultFilter(lua_State *L);
+int w_getDefaultFilter(lua_State *L);
+int w_setDefaultMipmapFilter(lua_State *L);
+int w_getDefaultMipmapFilter(lua_State *L);
 int w_setLineWidth(lua_State *L);
 int w_setLineStyle(lua_State *L);
 int w_setLine(lua_State *L);
--- a/src/modules/graphics/opengl/wrap_Image.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/wrap_Image.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -68,6 +68,8 @@
 	if (!Image::getConstant(magstr, f.mag))
 		return luaL_error(L, "Invalid filter mode: %s", magstr);
 
+	f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
+
 	try
 	{
 		t->setFilter(f);
@@ -90,7 +92,8 @@
 	Image::getConstant(f.mag, magstr);
 	lua_pushstring(L, minstr);
 	lua_pushstring(L, magstr);
-	return 2;
+	lua_pushnumber(L, f.anisotropy);
+	return 3;
 }
 
 int w_Image_setMipmapFilter(lua_State *L)
@@ -116,21 +119,28 @@
 		return luaL_error(L, "%s", e.what());
 	}
 
+	float sharpness = luaL_optnumber(L, 3, 0);
+
+	t->setMipmapSharpness(sharpness);
+
 	return 0;
 }
 
 int w_Image_getMipmapFilter(lua_State *L)
 {
 	Image *t = luax_checkimage(L, 1);
-	const Image::Filter f = t->getFilter();
+
+	const Image::Filter &f = t->getFilter();
 
 	const char *mipmapstr;
-	if (!Image::getConstant(f.mipmap, mipmapstr))
-		return 0; // only return a mipmap filter if mipmapping is enabled
+	if (Image::getConstant(f.mipmap, mipmapstr))
+		lua_pushstring(L, mipmapstr);
+	else
+		lua_pushnil(L); // only return a mipmap filter if mipmapping is enabled
 
-	lua_pushstring(L, mipmapstr);
+	lua_pushnumber(L, t->getMipmapSharpness());
 
-	return 1;
+	return 2;
 }
 
 int w_Image_setWrap(lua_State *L)
@@ -165,23 +175,6 @@
 	return 2;
 }
 
-int w_Image_setMipmapSharpness(lua_State *L)
-{
-	Image *i = luax_checkimage(L, 1);
-
-	float sharpness = (float) luaL_checknumber(L, 2);
-	i->setMipmapSharpness(sharpness);
-
-	return 0;
-}
-
-int w_Image_getMipmapSharpness(lua_State *L)
-{
-	Image *i = luax_checkimage(L, 1);
-	lua_pushnumber(L, i->getMipmapSharpness());
-	return 1;
-}
-
 static const luaL_Reg functions[] =
 {
 	{ "getWidth", w_Image_getWidth },
@@ -193,8 +186,6 @@
 	{ "getWrap", w_Image_getWrap },
 	{ "setMipmapFilter", w_Image_setMipmapFilter },
 	{ "getMipmapFilter", w_Image_getMipmapFilter },
-	{ "setMipmapSharpness", w_Image_setMipmapSharpness },
-	{ "getMipmapSharpness", w_Image_getMipmapSharpness },
 	{ 0, 0 }
 };
 
--- a/src/modules/graphics/opengl/wrap_Image.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/graphics/opengl/wrap_Image.h	Thu Mar 21 17:23:45 2013 -0300
@@ -42,8 +42,6 @@
 int w_Image_getMipmapFilter(lua_State *L);
 int w_Image_setWrap(lua_State *L);
 int w_Image_getWrap(lua_State *L);
-int w_Image_setMipmapSharpness(lua_State *L);
-int w_Image_getMipmapSharpness(lua_State *L);
 extern "C" int luaopen_image(lua_State *L);
 
 } // opengl
--- a/src/modules/image/ImageData.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/image/ImageData.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -168,7 +168,6 @@
 {
 	{"tga", ImageData::FORMAT_TGA},
 	{"bmp", ImageData::FORMAT_BMP},
-	{"gif", ImageData::FORMAT_GIF},
 	{"jpg", ImageData::FORMAT_JPG},
 	{"png", ImageData::FORMAT_PNG},
 };
--- a/src/modules/image/ImageData.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/image/ImageData.h	Thu Mar 21 17:23:45 2013 -0300
@@ -67,7 +67,6 @@
 	{
 		FORMAT_TGA = 1,
 		FORMAT_BMP,
-		FORMAT_GIF,
 		FORMAT_JPG,
 		FORMAT_PNG,
 		FORMAT_MAX_ENUM
--- a/src/modules/image/devil/ImageData.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/image/devil/ImageData.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -53,7 +53,15 @@
 ImageData::ImageData(filesystem::File *file)
 {
 	Data *data = file->read();
-	load(data);
+	try
+	{
+		load(data);
+	}
+	catch (love::Exception &)
+	{
+		data->release();
+		throw;
+	}
 	data->release();
 }
 
@@ -124,10 +132,10 @@
 
 		create(width, height, ilGetData());
 	}
-	catch(std::exception &)
+	catch(std::exception &e)
 	{
 		ilDeleteImages(1, &image);
-		throw;
+		throw love::Exception("%s", e.what());
 	}
 
 	ilDeleteImages(1, &image);
@@ -186,9 +194,6 @@
 		case ImageData::FORMAT_TGA:
 			ilFormat = IL_TGA;
 			break;
-		case ImageData::FORMAT_GIF:
-			ilFormat = IL_GIF;
-			break;
 		case ImageData::FORMAT_JPG:
 			ilFormat = IL_JPG;
 			break;
--- a/src/modules/math/MathModule.cpp	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/modules/math/MathModule.cpp	Thu Mar 21 17:23:45 2013 -0300
@@ -144,22 +144,30 @@
 	else if (polygon.size() == 3)
 		return vector<Triangle>(1, Triangle(polygon[0], polygon[1], polygon[2]));
 
-	vector<size_t> next_vertex(polygon.size()), prev_vertex(polygon.size());
-
-	// collect list of connections
+	// collect list of connections and record leftmost item to check if the polygon
+	// has the expected winding
+	vector<size_t> next_idx(polygon.size()), prev_idx(polygon.size());
+	size_t idx_lm = 0;
 	for (size_t i = 0; i < polygon.size(); ++i)
 	{
-		next_vertex[i] = i+1;
-		prev_vertex[i] = i-1;
+		const vertex &lm = polygon[idx_lm], &p = polygon[i];
+		if (p.x < lm.x || (p.x == lm.x && p.y < lm.y))
+			idx_lm = i;
+		next_idx[i] = i+1;
+		prev_idx[i] = i-1;
 	}
-	next_vertex[next_vertex.size()-1] = 0;
-	prev_vertex[0] = prev_vertex.size()-1;
+	next_idx[next_idx.size()-1] = 0;
+	prev_idx[0] = prev_idx.size()-1;
+
+	// check if the polygon has the expected winding and reverse polygon if needed
+	if (!is_oriented_ccw(polygon[prev_idx[idx_lm]], polygon[idx_lm], polygon[next_idx[idx_lm]]))
+		next_idx.swap(prev_idx);
 
 	// collect list of concave polygons
 	list<const vertex *> concave_vertices;
 	for (size_t i = 0; i < polygon.size(); ++i)
 	{
-		if (!is_oriented_ccw(polygon[prev_vertex[i]], polygon[i], polygon[next_vertex[i]]))
+		if (!is_oriented_ccw(polygon[prev_idx[i]], polygon[i], polygon[next_idx[i]]))
 			concave_vertices.push_back(&polygon[i]);
 	}
 
@@ -169,14 +177,14 @@
 	size_t current = 1, skipped = 0, next, prev;
 	while (n_vertices > 3)
 	{
-		next = next_vertex[current];
-		prev = prev_vertex[current];
+		next = next_idx[current];
+		prev = prev_idx[current];
 		const vertex &a = polygon[prev], &b = polygon[current], &c = polygon[next];
 		if (is_ear(a,b,c, concave_vertices))
 		{
 			triangles.push_back(Triangle(a,b,c));
-			next_vertex[prev] = next;
-			prev_vertex[next] = prev;
+			next_idx[prev] = next;
+			prev_idx[next] = prev;
 			concave_vertices.remove(&b);
 			--n_vertices;
 			skipped = 0;
@@ -187,8 +195,8 @@
 		}
 		current = next;
 	}
-	next = next_vertex[current];
-	prev = prev_vertex[current];
+	next = next_idx[current];
+	prev = prev_idx[current];
 	triangles.push_back(Triangle(polygon[prev], polygon[current], polygon[next]));
 
 	return triangles;
--- a/src/scripts/graphics.lua	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/scripts/graphics.lua	Thu Mar 21 17:23:45 2013 -0300
@@ -1333,21 +1333,21 @@
 varying lowp vec4 VaryingColor;
 varying mediump vec2 VaryingTexCoord;]]
 
-local GLSLES_PRECISION_FRAG = [[
+local GLSLES_PRECISION_PIXEL = [[
 #ifdef GL_FRAGMENT_PRECISION_HIGH
 precision highp float;
 #else
 precision mediump float;
 #endif]]
 
-	local GLSL_MAIN_VERT = [[
+	local GLSL_MAIN_VERTEX = [[
 void main() {
 	VaryingColor = VertexColor;
 	VaryingTexCoord = VertexTexCoord.st;
 	gl_Position = position(ModelViewProjectionMatrix, VertexPosition);
 }]]
 
-	local GLSLES_MAIN_VERT = [[
+	local GLSLES_MAIN_VERTEX = [[
 void main() {
 	VaryingColor = VertexColor;
 	VaryingTexCoord = VertexTexCoord.st;
@@ -1355,7 +1355,7 @@
 	gl_Position = position(ModelViewProjectionMatrix, VertexPosition);
 }]]
 
-	local GLSL_MAIN_FRAG = [[
+	local GLSL_MAIN_PIXEL = [[
 void main() {
 	// fix crashing issue in OSX when _tex0_ is unused within effect()
 	float dummy = texture2D(_tex0_, vec2(.5)).r;
@@ -1375,12 +1375,12 @@
 		return code
 	end
 
-	local function createVertCode(vertcode)
+	local function createVertexCode(vertexcode)
 		local gles = love.graphics.getRenderer() == "opengl es"
 		if not gles then
-			vertcode = stripPrecisionQualifiers(vertcode)
+			vertexcode = stripPrecisionQualifiers(vertexcode)
 		end
-		local vertcodes = {
+		local vertexcodes = {
 			gles and GLSLES_VERSION or GLSL_VERSION,
 			"#define VERTEX",
 			GLSL_SYNTAX,
@@ -1388,61 +1388,61 @@
 			gles and GLSLES_VARYINGS or GLSL_VARYINGS,
 			gles and GLSLES_UNIFORMS or GLSL_UNIFORMS,
 			"#line 0",
-			vertcode,
-			gles and GLSLES_MAIN_VERT or GLSL_MAIN_VERT,
+			vertexcode,
+			gles and GLSLES_MAIN_VERTEX or GLSL_MAIN_VERTEX,
 		}
-		return table_concat(vertcodes, "\n")
+		return table_concat(vertexcodes, "\n")
 	end
 
-	local function createFragCode(fragcode)
+	local function createPixelCode(pixelcode)
 		local gles = love.graphics.getRenderer() == "opengl es"
 		if not gles then
-			fragcode = stripPrecisionQualifiers(fragcode)
+			pixelcode = stripPrecisionQualifiers(pixelcode)
 		end
-		local fragcodes = {
+		local pixelcodes = {
 			gles and GLSLES_VERSION or GLSL_VERSION,
 			"#define PIXEL",
-			gles and GLSLES_PRECISION_FRAG or "",
+			gles and GLSLES_PRECISION_PIXEL or "",
 			GLSL_SYNTAX,
 			gles and GLSLES_VARYINGS or GLSL_VARYINGS,
 			gles and GLSLES_UNIFORMS or GLSL_UNIFORMS,
 			"#line 0",
-			fragcode,
-			GLSL_MAIN_FRAG,
+			pixelcode,
+			GLSL_MAIN_PIXEL,
 		}
-		return table_concat(fragcodes, "\n")
+		return table_concat(pixelcodes, "\n")
 	end
 
-	function love.graphics._shaderCodeToGLSL(vertcode, fragcode)
-		if vertcode then
-			local s = vertcode:gsub("\r\n\t", " ")
-			s = s:gsub("%w+(%s+)%(", "")
+	function love.graphics._shaderCodeToGLSL(vertexcode, pixelcode)
+		if vertexcode then
+			local s = vertexcode:gsub("\r\n\t", " ")
+			s = s:gsub("(%w+)(%s+)%(", "%1(")
 			if s:match("vec4%s*effect%(") then
-				fragcode = vertcode -- first argument contains frag shader code
+				pixelcode = vertexcode -- first argument contains pixel shader code
 			end
 			if not s:match("vec4%s*position%(") then
-				vertcode = nil -- first argument doesn't contain vert shader code
+				vertexcode = nil -- first argument doesn't contain vertex shader code
 			end
 		end
-		if fragcode then
-			local s = fragcode:gsub("\r\n\t", " ")
-			s = s:gsub("%w+(%s+)%(", "")
+		if pixelcode then
+			local s = pixelcode:gsub("\r\n\t", " ")
+			s = s:gsub("(%w+)(%s+)%(", "%1(")
 			if s:match("vec4%s*position%(") then
-				vertcode = fragcode -- second argument contains vert shader code
+				vertexcode = pixelcode -- second argument contains vertex shader code
 			end
 			if not s:match("vec4%s*effect%(") then
-				fragcode = nil -- second argument doesn't contain frag shader code
+				pixelcode = nil -- second argument doesn't contain pixel shader code
 			end
 		end
 
-		if vertcode then
-			vertcode = createVertCode(vertcode)
+		if vertexcode then
+			vertexcode = createVertexCode(vertexcode)
 		end
-		if fragcode then
-			fragcode = createFragCode(fragcode)
+		if pixelcode then
+			pixelcode = createPixelCode(pixelcode)
 		end
 
-		return vertcode, fragcode
+		return vertexcode, pixelcode
 	end
 
 	function love.graphics._transformGLSLErrorMessages(message)
@@ -1516,43 +1516,33 @@
 	end
 
 	local newShader = love.graphics.newShader
-	function love.graphics.newShader(vertcode, fragcode)
-		love.graphics.newShader = function(vertcode, fragcode)
-			if love.filesystem then
-				if vertcode and love.filesystem.exists(vertcode) then
-					vertcode = love.filesystem.read(vertcode)
-				end
-				if fragcode and love.filesystem.exists(fragcode) then
-					fragcode = love.filesystem.read(fragcode)
-				end
-			end
-			return newShader(vertcode, fragcode)
-		end
+	function love.graphics.newShader(vertexcode, pixelcode)
+		love.graphics.newShader = newShader
 
-		local shader = love.graphics.newShader(vertcode, fragcode)
+		local shader = newShader(vertexcode, pixelcode)
 		local meta = getmetatable(shader)
 		meta.send = shader_dispatch_send
 		meta.sendBoolean = meta.sendFloat
 		return shader
 	end
 
-	local defaultvert = [[
+	local defaultvertex = [[
 vec4 position(mat4 mvp_matrix, vec4 vertex)
 {
 	return mvp_matrix * vertex;
 }]]
-	local defaultfrag = [[
+	local defaultpixel = [[
 vec4 effect(vec4 vcolor, Image texture, vec2 texcoord, vec2 pixcoord)
 {
 	return vcolor * Texel(texture, texcoord);
 }]]
 
-	love.graphics.setDefaultShaderSources(defaultvert, defaultfrag)
+	love.graphics.setDefaultShaderSources(defaultvertex, defaultpixel)
 
 	local defaultshader
 	local function makeDefaultShader()
 		if not defaultshader and love.graphics.isSupported("shader") and love.graphics.getRenderer() == "opengl es" then
-			defaultshader = love.graphics.newShader(defaultvert, defaultfrag)
+			defaultshader = love.graphics.newShader(defaultvertex, defaultpixel)
 		end
 		return defaultshader
 	end
--- a/src/scripts/graphics.lua.h	Sun Mar 17 18:00:24 2013 -0300
+++ b/src/scripts/graphics.lua.h	Thu Mar 21 17:23:45 2013 -0300
@@ -6345,7 +6345,7 @@
 	0x63, 0x32, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 
 	0x3b, 0x5d, 0x5d, 0x0a,
 	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x43, 0x49, 
-	0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x47, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
+	0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
 	0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x47, 0x4d, 0x45, 0x4e, 0x54, 
 	0x5f, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x49, 0x47, 0x48, 0x0a,
 	0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 
@@ -6355,7 +6355,7 @@
 	0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a,
 	0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x5d, 0x5d, 0x0a,
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x56, 
-	0x45, 0x52, 0x54, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
+	0x45, 0x52, 0x54, 0x45, 0x58, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
 	0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a,
 	0x09, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x56, 0x65, 
 	0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a,
@@ -6368,7 +6368,7 @@
 	0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0a,
 	0x7d, 0x5d, 0x5d, 0x0a,
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 
-	0x5f, 0x56, 0x45, 0x52, 0x54, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
+	0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
 	0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a,
 	0x09, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x56, 0x65, 
 	0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a,
@@ -6382,8 +6382,8 @@
 	0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x2c, 0x20, 0x56, 0x65, 0x72, 
 	0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0a,
 	0x7d, 0x5d, 0x5d, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 
-	0x52, 0x41, 0x47, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x50, 
+	0x49, 0x58, 0x45, 0x4c, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
 	0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a,
 	0x09, 0x2f, 0x2f, 0x20, 0x66, 0x69, 0x78, 0x20, 0x63, 0x72, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69, 
 	0x73, 0x73, 0x75, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x4f, 0x53, 0x58, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x5f, 
@@ -6418,19 +6418,19 @@
 	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	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, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 
-	0x6f, 0x64, 0x65, 0x29, 0x0a,
+	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,
 	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 
 	0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6e, 0x64, 
 	0x65, 0x72, 0x65, 0x72, 0x28, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6f, 0x70, 0x65, 0x6e, 0x67, 0x6c, 0x20, 
 	0x65, 0x73, 0x22, 0x0a,
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 
-	0x70, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 
-	0x72, 0x73, 0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
+	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 
+	0x72, 0x69, 0x70, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 
+	0x69, 0x65, 0x72, 0x73, 0x28, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 
-	0x3d, 0x20, 0x7b, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 
+	0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
 	0x09, 0x09, 0x09, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 
 	0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x20, 0x6f, 0x72, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 
 	0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x2c, 0x0a,
@@ -6447,37 +6447,37 @@
 	0x5f, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x20, 0x6f, 0x72, 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, 0x30, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 
-	0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x20, 0x6f, 0x72, 0x20, 0x47, 0x4c, 0x53, 0x4c, 
-	0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x2c, 0x0a,
+	0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x20, 0x6f, 0x72, 0x20, 0x47, 0x4c, 
+	0x53, 0x4c, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x2c, 0x0a,
 	0x09, 0x09, 0x7d, 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, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 
-	0x22, 0x29, 0x0a,
+	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, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72, 
-	0x65, 0x61, 0x74, 0x65, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x66, 0x72, 0x61, 0x67, 0x63, 
-	0x6f, 0x64, 0x65, 0x29, 0x0a,
+	0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x70, 0x69, 0x78, 0x65, 
+	0x6c, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
 	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 
 	0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6e, 0x64, 
 	0x65, 0x72, 0x65, 0x72, 0x28, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6f, 0x70, 0x65, 0x6e, 0x67, 0x6c, 0x20, 
 	0x65, 0x73, 0x22, 0x0a,
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 
-	0x70, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 
-	0x72, 0x73, 0x28, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
+	0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 
+	0x69, 0x70, 0x50, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 
+	0x65, 0x72, 0x73, 0x28, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 
-	0x3d, 0x20, 0x7b, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x73, 
+	0x20, 0x3d, 0x20, 0x7b, 0x0a,
 	0x09, 0x09, 0x09, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 
 	0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x20, 0x6f, 0x72, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 
 	0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x22, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x22, 
 	0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 
-	0x5f, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x47, 0x20, 0x6f, 0x72, 
-	0x20, 0x22, 0x22, 0x2c, 0x0a,
+	0x5f, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x20, 0x6f, 
+	0x72, 0x20, 0x22, 0x22, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x67, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 
 	0x5f, 0x56, 0x41, 0x52, 0x59, 0x49, 0x4e, 0x47, 0x53, 0x20, 0x6f, 0x72, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 
@@ -6486,75 +6486,82 @@
 	0x5f, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x20, 0x6f, 0x72, 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, 0x30, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x47, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x0a,
+	0x09, 0x09, 0x09, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x50, 0x49, 0x58, 0x45, 0x4c, 
+	0x2c, 0x0a,
 	0x09, 0x09, 0x7d, 0x0a,
 	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 
-	0x63, 0x61, 0x74, 0x28, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 
-	0x22, 0x29, 0x0a,
+	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, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
 	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x54, 
-	0x6f, 0x47, 0x4c, 0x53, 0x4c, 0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x66, 0x72, 
-	0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x72, 0x74, 0x63, 
-	0x6f, 0x64, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x72, 0x5c, 0x6e, 0x5c, 0x74, 0x22, 0x2c, 
-	0x20, 0x22, 0x20, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x25, 0x77, 0x2b, 
-	0x28, 0x25, 0x73, 0x2b, 0x29, 0x25, 0x28, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x29, 0x0a,
+	0x6f, 0x47, 0x4c, 0x53, 0x4c, 0x28, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 
+	0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
+	0x09, 0x09, 0x69, 0x66, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 
+	0x65, 0x6e, 0x0a,
+	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 
+	0x78, 0x63, 0x6f, 0x64, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x72, 0x5c, 0x6e, 0x5c, 0x74, 
+	0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0x0a,
+	0x09, 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x28, 0x25, 0x77, 
+	0x2b, 0x29, 0x28, 0x25, 0x73, 0x2b, 0x29, 0x25, 0x28, 0x22, 0x2c, 0x20, 0x22, 0x25, 0x31, 0x28, 0x22, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x73, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 0x76, 0x65, 0x63, 
 	0x34, 0x25, 0x73, 0x2a, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x25, 0x28, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 
 	0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x72, 
-	0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x2d, 0x2d, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x61, 0x72, 0x67, 
-	0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x66, 0x72, 0x61, 
-	0x67, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a,
+	0x09, 0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x76, 0x65, 
+	0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x2d, 0x2d, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 
+	0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 
+	0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a,
 	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 
 	0x22, 0x76, 0x65, 0x63, 0x34, 0x25, 0x73, 0x2a, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x25, 0x28, 
 	0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 
-	0x20, 0x2d, 0x2d, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 
-	0x20, 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x76, 
-	0x65, 0x72, 0x74, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a,
+	0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x6e, 
+	0x69, 0x6c, 0x20, 0x2d, 0x2d, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 
+	0x6e, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 
+	0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 
+	0x65, 0x0a,
 	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 
-	0x6f, 0x64, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x72, 0x5c, 0x6e, 0x5c, 0x74, 0x22, 0x2c, 
-	0x20, 0x22, 0x20, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x25, 0x77, 0x2b, 
-	0x28, 0x25, 0x73, 0x2b, 0x29, 0x25, 0x28, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x29, 0x0a,
+	0x09, 0x09, 0x69, 0x66, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 
+	0x6e, 0x0a,
+	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 
+	0x63, 0x6f, 0x64, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x72, 0x5c, 0x6e, 0x5c, 0x74, 0x22, 
+	0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0x0a,
+	0x09, 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x28, 0x25, 0x77, 
+	0x2b, 0x29, 0x28, 0x25, 0x73, 0x2b, 0x29, 0x25, 0x28, 0x22, 0x2c, 0x20, 0x22, 0x25, 0x31, 0x28, 0x22, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x73, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 0x76, 0x65, 0x63, 
 	0x34, 0x25, 0x73, 0x2a, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x25, 0x28, 0x22, 0x29, 0x20, 0x74, 
 	0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x72, 0x61, 
-	0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x61, 0x72, 
-	0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x76, 0x65, 
-	0x72, 0x74, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a,
+	0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x70, 
+	0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 
+	0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 
+	0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 
+	0x65, 0x0a,
 	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 
 	0x22, 0x76, 0x65, 0x63, 0x34, 0x25, 0x73, 0x2a, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x25, 0x28, 0x22, 0x29, 
 	0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 
-	0x20, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 
-	0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 
-	0x66, 0x72, 0x61, 0x67, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a,
+	0x09, 0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x6e, 0x69, 
+	0x6c, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 
+	0x6e, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 
+	0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a,
 	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x72, 0x65, 0x61, 
-	0x74, 0x65, 0x56, 0x65, 0x72, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 
-	0x65, 0x29, 0x0a,
+	0x09, 0x09, 0x69, 0x66, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 
+	0x65, 0x6e, 0x0a,
+	0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x63, 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,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x72, 0x65, 0x61, 
-	0x74, 0x65, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 
-	0x65, 0x29, 0x0a,
+	0x09, 0x09, 0x69, 0x66, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 
+	0x6e, 0x0a,
+	0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x72, 0x65, 
+	0x61, 0x74, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x70, 0x69, 0x78, 0x65, 0x6c, 
+	0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 
-	0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x0a,
+	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 
+	0x65, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
 	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x47, 0x4c, 
@@ -6726,38 +6733,14 @@
 	0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x0a,
 	0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
 	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x28, 0x76, 0x65, 
-	0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 
-	0x77, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 
-	0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 
+	0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 
 	0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 
-	0x74, 0x65, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 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, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x72, 0x65, 0x61, 0x64, 
-	0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 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, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x72, 0x65, 0x61, 0x64, 
-	0x28, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x65, 0x77, 0x53, 0x68, 0x61, 0x64, 0x65, 
-	0x72, 0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 
-	0x64, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x53, 0x68, 
-	0x61, 0x64, 0x65, 0x72, 0x28, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x61, 
-	0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 
+	0x77, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x53, 0x68, 0x61, 0x64, 0x65, 
+	0x72, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6e, 
+	0x65, 0x77, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x28, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 
+	0x65, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a,
 	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 
 	0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x29, 0x0a,
 	0x09, 0x09, 0x6d, 0x65, 0x74, 0x61, 0x2e, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x73, 0x68, 0x61, 0x64, 
@@ -6767,7 +6750,7 @@
 	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x76, 0x65, 0x72, 0x74, 
-	0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
+	0x65, 0x78, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
 	0x76, 0x65, 0x63, 0x34, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6d, 0x61, 0x74, 0x34, 
 	0x20, 0x6d, 0x76, 0x70, 0x5f, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 
 	0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x29, 0x0a,
@@ -6775,8 +6758,8 @@
 	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x76, 0x70, 0x5f, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 
 	0x20, 0x2a, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x3b, 0x0a,
 	0x7d, 0x5d, 0x5d, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x66, 0x72, 0x61, 0x67, 
-	0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x70, 0x69, 0x78, 0x65, 
+	0x6c, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
 	0x76, 0x65, 0x63, 0x34, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x28, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 
 	0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 
 	0x72, 0x65, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 
@@ -6788,8 +6771,8 @@
 	0x7d, 0x5d, 0x5d, 0x0a,
 	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 
 	0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x53, 0x6f, 0x75, 0x72, 0x63, 
-	0x65, 0x73, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x76, 0x65, 0x72, 0x74, 0x2c, 0x20, 0x64, 0x65, 
-	0x66, 0x61, 0x75, 0x6c, 0x74, 0x66, 0x72, 0x61, 0x67, 0x29, 0x0a,
+	0x65, 0x73, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x2c, 0x20, 
+	0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x29, 0x0a,
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x68, 0x61, 0x64, 
 	0x65, 0x72, 0x0a,
 	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 
@@ -6804,7 +6787,7 @@
 	0x09, 0x09, 0x09, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x3d, 
 	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 
 	0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x76, 0x65, 0x72, 0x74, 
-	0x2c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x66, 0x72, 0x61, 0x67, 0x29, 0x0a,
+	0x65, 0x78, 0x2c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x29, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x68, 
 	0x61, 0x64, 0x65, 0x72, 0x0a,