Browse Source

Merge branch '12.0-development' into metal

Alex Szpakowski 3 years ago
parent
commit
3d8117ccbb
61 changed files with 2099 additions and 2923 deletions
  1. 18 25
      .github/workflows/main.yml
  2. 9 0
      changes.txt
  3. 8 4
      platform/xcode/liblove.xcodeproj/project.pbxproj
  4. 1 1
      platform/xcode/love.xcodeproj/project.pbxproj
  5. 5 5
      readme.md
  6. 154 55
      src/common/android.cpp
  7. 2 0
      src/common/android.h
  8. 5 1
      src/common/runtime.cpp
  9. 40 14
      src/libraries/enet/enet.cpp
  10. 136 49
      src/libraries/lodepng/lodepng.cpp
  11. 91 17
      src/libraries/lodepng/lodepng.h
  12. 1 1
      src/libraries/luasocket/libluasocket/ftp.lua.h
  13. 1 1
      src/libraries/luasocket/libluasocket/headers.lua.h
  14. 1 1
      src/libraries/luasocket/libluasocket/http.lua.h
  15. 1 1
      src/libraries/luasocket/libluasocket/ltn12.lua.h
  16. 1 1
      src/libraries/luasocket/libluasocket/mbox.lua.h
  17. 1 1
      src/libraries/luasocket/libluasocket/mime.lua.h
  18. 1 1
      src/libraries/luasocket/libluasocket/smtp.lua.h
  19. 1 1
      src/libraries/luasocket/libluasocket/socket.lua.h
  20. 1 1
      src/libraries/luasocket/libluasocket/tp.lua.h
  21. 1 1
      src/libraries/luasocket/libluasocket/url.lua.h
  22. 82 82
      src/libraries/noise1234/noise1234.cpp
  23. 12 16
      src/libraries/noise1234/noise1234.h
  24. 34 36
      src/libraries/noise1234/simplexnoise1234.cpp
  25. 4 9
      src/libraries/noise1234/simplexnoise1234.h
  26. 208 73
      src/libraries/stb/stb_image.h
  27. 16 8
      src/love.cpp
  28. 11 0
      src/modules/data/wrap_ByteData.cpp
  29. 12 1
      src/modules/data/wrap_DataView.cpp
  30. 1 1
      src/modules/event/wrap_Event.cpp
  31. 1 1
      src/modules/filesystem/Filesystem.cpp
  32. 7 5
      src/modules/filesystem/physfs/Filesystem.cpp
  33. 38 2
      src/modules/filesystem/wrap_Filesystem.cpp
  34. 24 5
      src/modules/graphics/Buffer.cpp
  35. 5 8
      src/modules/graphics/Font.cpp
  36. 3 2
      src/modules/graphics/Graphics.cpp
  37. 1 1
      src/modules/graphics/ParticleSystem.cpp
  38. 4 4
      src/modules/graphics/Shader.cpp
  39. 21 2
      src/modules/graphics/opengl/Shader.cpp
  40. 1 1
      src/modules/graphics/opengl/Shader.h
  41. 2 0
      src/modules/graphics/wrap_Buffer.cpp
  42. 1 1
      src/modules/graphics/wrap_Graphics.cpp
  43. 3 9
      src/modules/graphics/wrap_Shader.cpp
  44. 1 1
      src/modules/graphics/wrap_Video.cpp
  45. 27 4
      src/modules/joystick/sdl/Joystick.cpp
  46. 186 0
      src/modules/love/arg.lua
  47. 388 0
      src/modules/love/boot.lua
  48. 313 0
      src/modules/love/callbacks.lua
  49. 71 0
      src/modules/love/jitsetup.lua
  50. 96 9
      src/modules/love/love.cpp
  51. 3 0
      src/modules/love/love.h
  52. 8 8
      src/modules/math/MathModule.h
  53. 7 7
      src/modules/math/wrap_Math.cpp
  54. 4 4
      src/modules/math/wrap_Math.lua
  55. 2 1
      src/modules/physics/box2d/RevoluteJoint.cpp
  56. 2 2
      src/modules/physics/box2d/RevoluteJoint.h
  57. 2 2
      src/modules/physics/box2d/wrap_RevoluteJoint.cpp
  58. 18 5
      src/modules/video/theora/OggDemuxer.cpp
  59. 1 1
      src/modules/video/theora/OggDemuxer.h
  60. 0 814
      src/scripts/boot.lua
  61. 0 1617
      src/scripts/boot.lua.h

+ 18 - 25
.github/workflows/main.yml

@@ -9,37 +9,30 @@ jobs:
       run: sudo apt-get update
       run: sudo apt-get update
     - name: Install Dependencies
     - name: Install Dependencies
       run: |
       run: |
-        sudo apt-get install --assume-yes build-essential autotools-dev automake libtool pkg-config \
-                                          libfreetype6-dev libluajit-5.1-dev libsdl2-dev libopenal-dev \
-                                          libogg-dev libvorbis-dev libmodplug-dev libmpg123-dev libtheora-dev
-    - name: Checkout
+        sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \
+                                          libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \
+                                          libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \
+                                          libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \
+                                          libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \
+                                          libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \
+                                          libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev
+    - name: Checkout love-appimage-source
       uses: actions/checkout@v2
       uses: actions/checkout@v2
-    - name: Pre-Configure
-      run: $PWD/platform/unix/automagic
-    - name: Configure
-      run: mkdir build && cd build && ../configure
-    - name: Build
-      run: cd build && make -j2
-    - name: Prepare appimagetool
-      run: |
-        cd build &&
-        wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O appimagetool &&
-        chmod +x appimagetool &&
-        sudo apt install -y appstream
-    - name: Clone love-appimages
+      with:
+        repository: MikuAuahDark/love-appimage-source
+    - name: Checkout LÖVE
       uses: actions/checkout@v2
       uses: actions/checkout@v2
       with:
       with:
-        path: build/love-appimages
-        repository: pfirsich/love-appimages
+        path: love2d-${{ github.sha }}
     - name: Build AppImage
     - name: Build AppImage
-      run: |
-        cd build &&
-        python3 love-appimages/build.py .. AppDir --builddir build --appimage love.AppImage
+      run: make LOVE_BRANCH=${{ github.sha }}
+    - name: Print LuaJIT branch
+      run: git -C LuaJIT-v2.1 branch -v
     - name: Artifact
     - name: Artifact
-      uses: actions/upload-artifact@v2-preview
+      uses: actions/upload-artifact@v2
       with:
       with:
-        name: love.AppImage
-        path: build/love.AppImage
+        name: love-x86_64.AppImage
+        path: love-${{ github.sha }}.AppImage
   windows-os:
   windows-os:
     runs-on: windows-latest
     runs-on: windows-latest
     strategy:
     strategy:

+ 9 - 0
changes.txt

@@ -38,12 +38,14 @@ LOVE 11.4 [Mysterious Mysteries]
 
 
 Released: N/A
 Released: N/A
 
 
+* Added native arm64 support on macOS.
 * Added Body:getLocalPoints.
 * Added Body:getLocalPoints.
 * Added Font:getKerning.
 * Added Font:getKerning.
 * Added support for r16, rg16, and rgba16 pixel formats in Canvases.
 * Added support for r16, rg16, and rgba16 pixel formats in Canvases.
 * Added Shader:send(name, matrixlayout, data, ...) variant, whose argument order is more consistent than Shader:send(name, data, matrixlayout, ...).
 * Added Shader:send(name, matrixlayout, data, ...) variant, whose argument order is more consistent than Shader:send(name, data, matrixlayout, ...).
 
 
 * Changed love.timer.getTime to start at 0 when the module is first loaded.
 * Changed love.timer.getTime to start at 0 when the module is first loaded.
+* Changed certain out-of-Lua-memory situations to show a message box instead of instantly crashing.
 
 
 * Fixed build-time compatibility with Lua 5.4.
 * Fixed build-time compatibility with Lua 5.4.
 * Fixed code compatibility with math.mod and string.gfind when LuaJIT 2.1 is used.
 * Fixed code compatibility with math.mod and string.gfind when LuaJIT 2.1 is used.
@@ -54,21 +56,28 @@ Released: N/A
 * Fixed support for > 2GB dropped files on desktops.
 * Fixed support for > 2GB dropped files on desktops.
 * Fixed love.physics meter scale value persisting after love.event.quit("restart").
 * Fixed love.physics meter scale value persisting after love.event.quit("restart").
 * Fixed audio to resume properly after interruption on iOS.
 * Fixed audio to resume properly after interruption on iOS.
+* Fixed love.graphics.newVideo to error instead of crash when an invalid video file is given.
 * Fixed initial window creation to set the window's title during creation instead of after.
 * Fixed initial window creation to set the window's title during creation instead of after.
 * Fixed the window's screen position when exiting fullscreen via love.window.setFullscreen.
 * Fixed the window's screen position when exiting fullscreen via love.window.setFullscreen.
+* Fixed love.displayrotated being given a boolean instead of an enum string.
 * Fixed memory corruption and a crash when drawing smooth lines.
 * Fixed memory corruption and a crash when drawing smooth lines.
 * Fixed a crash in Canvas:newImageData when the pixel format's pixel byte size multiplied by its width isn't a multiple of 4.
 * Fixed a crash in Canvas:newImageData when the pixel format's pixel byte size multiplied by its width isn't a multiple of 4.
 * Fixed love.graphics.newVolumeImage when explicit mipmaps are provided.
 * Fixed love.graphics.newVolumeImage when explicit mipmaps are provided.
 * Fixed freezes and crashes in automatic batching when an AMD GPU is used.
 * Fixed freezes and crashes in automatic batching when an AMD GPU is used.
 * Fixed love.graphics.print and Image:replacePixels on more AMD/ATI GPUs.
 * Fixed love.graphics.print and Image:replacePixels on more AMD/ATI GPUs.
 * Fixed Font:setFallbacks to account for different DPI scales in each fallback font.
 * Fixed Font:setFallbacks to account for different DPI scales in each fallback font.
+* Fixed Font:getWrap to not remove trailing newlines.
 * Fixed Text:getWidth when the Text's string only contains spaces.
 * Fixed Text:getWidth when the Text's string only contains spaces.
 * Fixed a crash with some Intel graphics drivers on Linux.
 * Fixed a crash with some Intel graphics drivers on Linux.
 * Fixed a hang with some Intel graphics drivers on Windows, by preventing gamma correct rendering on affected systems.
 * Fixed a hang with some Intel graphics drivers on Windows, by preventing gamma correct rendering on affected systems.
 * Fixed a crash with some Intel graphics drivers on Windows when mipmapped Canvases are used.
 * Fixed a crash with some Intel graphics drivers on Windows when mipmapped Canvases are used.
 * Fixed texture memory reported by love.graphics.getStats when a volume or array Canvas is created.
 * Fixed texture memory reported by love.graphics.getStats when a volume or array Canvas is created.
+* Fixed DXT1 textures which use 1 bit alpha-cutout.
 * Fixed rare issues where textures were not sent to shaders correctly.
 * Fixed rare issues where textures were not sent to shaders correctly.
 * Fixed Shader:send(name, data, matrixlayout, ...).
 * Fixed Shader:send(name, data, matrixlayout, ...).
+* Fixed quad offsets in ParticleSystems when ParticleSystem:setOffset is not used.
+* Fixed rounded rectangles breaking if the rx or ry parameters are negative.
+* Fixed rounded rectangle automatic points calculation when rx or ry are more than half the rectangle's size.
 * Fixed source code compilation on Xcode 12+.
 * Fixed source code compilation on Xcode 12+.
 * Fixed source code compilation on Linux systems that don't provide posix_spawn APIs.
 * Fixed source code compilation on Linux systems that don't provide posix_spawn APIs.
 
 

+ 8 - 4
platform/xcode/liblove.xcodeproj/project.pbxproj

@@ -1357,7 +1357,6 @@
 		217DFBD41D9F6D490055D849 /* url.lua.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = url.lua.h; sourceTree = "<group>"; };
 		217DFBD41D9F6D490055D849 /* url.lua.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = url.lua.h; sourceTree = "<group>"; };
 		217DFBD51D9F6D490055D849 /* usocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = usocket.c; sourceTree = "<group>"; };
 		217DFBD51D9F6D490055D849 /* usocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = usocket.c; sourceTree = "<group>"; };
 		217DFBD61D9F6D490055D849 /* usocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usocket.h; sourceTree = "<group>"; };
 		217DFBD61D9F6D490055D849 /* usocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usocket.h; sourceTree = "<group>"; };
-		503971A86B7167A91B670FBA /* boot.lua.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = boot.lua.h; sourceTree = "<group>"; };
 		FA08F5AE16C7525600F007B5 /* liblove-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "liblove-macosx.plist"; path = "macosx/liblove-macosx.plist"; sourceTree = "<group>"; };
 		FA08F5AE16C7525600F007B5 /* liblove-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "liblove-macosx.plist"; path = "macosx/liblove-macosx.plist"; sourceTree = "<group>"; };
 		FA0A3A5D23366CE9001C269E /* floattypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = floattypes.h; sourceTree = "<group>"; };
 		FA0A3A5D23366CE9001C269E /* floattypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = floattypes.h; sourceTree = "<group>"; };
 		FA0A3A5E23366CE9001C269E /* floattypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floattypes.cpp; sourceTree = "<group>"; };
 		FA0A3A5E23366CE9001C269E /* floattypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floattypes.cpp; sourceTree = "<group>"; };
@@ -1810,6 +1809,8 @@
 		FA1E887D1DF363CD00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
 		FA1E887D1DF363CD00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
 		FA1E88811DF363DB00E808AA /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = "<group>"; };
 		FA1E88811DF363DB00E808AA /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = "<group>"; };
 		FA1E88821DF363DB00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
 		FA1E88821DF363DB00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
+		FA1E95B4271F932B0044CF08 /* arg.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = arg.lua; sourceTree = "<group>"; };
+		FA1E95B5271F932B0044CF08 /* callbacks.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = callbacks.lua; sourceTree = "<group>"; };
 		FA24348121D401CB00B8918A /* attribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attribute.h; sourceTree = "<group>"; };
 		FA24348121D401CB00B8918A /* attribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attribute.h; sourceTree = "<group>"; };
 		FA24348221D401CB00B8918A /* attribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = attribute.cpp; sourceTree = "<group>"; };
 		FA24348221D401CB00B8918A /* attribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = attribute.cpp; sourceTree = "<group>"; };
 		FA24348321D401CB00B8918A /* pch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pch.h; sourceTree = "<group>"; };
 		FA24348321D401CB00B8918A /* pch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pch.h; sourceTree = "<group>"; };
@@ -1882,6 +1883,7 @@
 		FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = "<group>"; };
 		FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = "<group>"; };
 		FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Texture.h; sourceTree = "<group>"; };
 		FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Texture.h; sourceTree = "<group>"; };
 		FA620A391AA305F6005DB4C2 /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = "<group>"; };
 		FA620A391AA305F6005DB4C2 /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = "<group>"; };
+		FA69B918273828DD00CDC2E7 /* jitsetup.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = jitsetup.lua; sourceTree = "<group>"; };
 		FA6A2B641F5F7B6B0074C308 /* wrap_Data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Data.h; sourceTree = "<group>"; };
 		FA6A2B641F5F7B6B0074C308 /* wrap_Data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Data.h; sourceTree = "<group>"; };
 		FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Data.cpp; sourceTree = "<group>"; };
 		FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Data.cpp; sourceTree = "<group>"; };
 		FA6A2B681F5F7F560074C308 /* DataView.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DataView.cpp; sourceTree = "<group>"; };
 		FA6A2B681F5F7F560074C308 /* DataView.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DataView.cpp; sourceTree = "<group>"; };
@@ -2262,8 +2264,6 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				FA577A8C16C71D3600860150 /* auto.lua */,
 				FA577A8C16C71D3600860150 /* auto.lua */,
-				FA577A8D16C71D3600860150 /* boot.lua */,
-				503971A86B7167A91B670FBA /* boot.lua.h */,
 				FA283EDC1B27CFAA00C70067 /* nogame.lua */,
 				FA283EDC1B27CFAA00C70067 /* nogame.lua */,
 				FA283EDD1B27CFAA00C70067 /* nogame.lua.h */,
 				FA283EDD1B27CFAA00C70067 /* nogame.lua.h */,
 			);
 			);
@@ -2965,6 +2965,10 @@
 		FA0B7BFD1A95902C000E1D17 /* love */ = {
 		FA0B7BFD1A95902C000E1D17 /* love */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				FA1E95B4271F932B0044CF08 /* arg.lua */,
+				FA577A8D16C71D3600860150 /* boot.lua */,
+				FA1E95B5271F932B0044CF08 /* callbacks.lua */,
+				FA69B918273828DD00CDC2E7 /* jitsetup.lua */,
 				FA0B7BFE1A95902C000E1D17 /* love.cpp */,
 				FA0B7BFE1A95902C000E1D17 /* love.cpp */,
 				FA0B7BFF1A95902C000E1D17 /* love.h */,
 				FA0B7BFF1A95902C000E1D17 /* love.h */,
 			);
 			);
@@ -4429,7 +4433,7 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			isa = PBXProject;
 			attributes = {
 			attributes = {
-				LastUpgradeCheck = 1250;
+				LastUpgradeCheck = 1310;
 				TargetAttributes = {
 				TargetAttributes = {
 					FA0B78DC1A958B90000E1D17 = {
 					FA0B78DC1A958B90000E1D17 = {
 						CreatedOnToolsVersion = 6.1.1;
 						CreatedOnToolsVersion = 6.1.1;

+ 1 - 1
platform/xcode/love.xcodeproj/project.pbxproj

@@ -324,7 +324,7 @@
 		29B97313FDCFA39411CA2CEA /* Project object */ = {
 		29B97313FDCFA39411CA2CEA /* Project object */ = {
 			isa = PBXProject;
 			isa = PBXProject;
 			attributes = {
 			attributes = {
-				LastUpgradeCheck = 1250;
+				LastUpgradeCheck = 1310;
 				TargetAttributes = {
 				TargetAttributes = {
 					FA0B7F051A95AAF3000E1D17 = {
 					FA0B7F051A95AAF3000E1D17 = {
 						CreatedOnToolsVersion = 6.1.1;
 						CreatedOnToolsVersion = 6.1.1;

+ 5 - 5
readme.md

@@ -12,7 +12,7 @@ If you need further help, feel free to ask on our [forums][forums], our [Discord
 Repository
 Repository
 ----------
 ----------
 
 
-We use the 'master' branch for patch development of the current major release, and therefore it should not be considered stable.
+We use the 'main' branch for patch development of the current major release, and therefore it should not be considered stable.
 There may also be a branch for the next major version in development, which is named after that version.
 There may also be a branch for the next major version in development, which is named after that version.
 
 
 We tag all our releases (since we started using mercurial and git), and have binary downloads available for them.
 We tag all our releases (since we started using mercurial and git), and have binary downloads available for them.
@@ -83,16 +83,16 @@ Dependencies
 - Vorbisfile
 - Vorbisfile
 - Theora
 - Theora
 
 
-[site]: http://love2d.org
-[wiki]: http://love2d.org/wiki
-[forums]: http://love2d.org/forums
+[site]: https://love2d.org
+[wiki]: https://love2d.org/wiki
+[forums]: https://love2d.org/forums
 [discord]: https://discord.gg/rhUets9
 [discord]: https://discord.gg/rhUets9
 [irc]: irc://irc.oftc.net/love
 [irc]: irc://irc.oftc.net/love
 [dependencies-macos]: https://github.com/slime73/love-apple-dependencies
 [dependencies-macos]: https://github.com/slime73/love-apple-dependencies
 [dependencies-ios]: https://github.com/love2d/love/releases
 [dependencies-ios]: https://github.com/love2d/love/releases
 [megasource]: https://github.com/love2d/megasource
 [megasource]: https://github.com/love2d/megasource
 [unstableppa]: https://launchpad.net/~bartbes/+archive/love-unstable
 [unstableppa]: https://launchpad.net/~bartbes/+archive/love-unstable
-[aur]: http://aur.archlinux.org/packages/love-git
+[aur]: https://aur.archlinux.org/packages/love-git
 [love-experiments]: https://github.com/slime73/love-experiments
 [love-experiments]: https://github.com/slime73/love-experiments
 [codestyle]: https://love2d.org/wiki/Code_Style
 [codestyle]: https://love2d.org/wiki/Code_Style
 [android-repository]: https://github.com/love2d/love-android
 [android-repository]: https://github.com/love2d/love-android

+ 154 - 55
src/common/android.cpp

@@ -333,24 +333,59 @@ void showRecordingPermissionMissingDialog()
 	env->DeleteLocalRef(activity);
 	env->DeleteLocalRef(activity);
 }
 }
 
 
+/* A container for AssetManager Java object */
+class AssetManagerObject
+{
+public:
+	AssetManagerObject()
+	{
+		JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
+		jobject am = getLocalAssetManager(env);
+
+		assetManager = env->NewGlobalRef(am);
+		env->DeleteLocalRef(am);
+	}
+
+	~AssetManagerObject()
+	{
+		JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
+		env->DeleteGlobalRef(assetManager);
+	}
+
+	static jobject getLocalAssetManager(JNIEnv *env) {
+		jobject self = (jobject) SDL_AndroidGetActivity();
+		jclass activity = env->GetObjectClass(self);
+		jmethodID method = env->GetMethodID(activity, "getAssets", "()Landroid/content/res/AssetManager;");
+		jobject am = env->CallObjectMethod(self, method);
+
+		env->DeleteLocalRef(self);
+		env->DeleteLocalRef(activity);
+		return am;
+	}
+
+	explicit operator jobject()
+	{
+		return assetManager;
+	};
+private:
+	jobject assetManager;
+};
+
 /*
 /*
  * Helper functions to aid new fusing method
  * Helper functions to aid new fusing method
  */
  */
+
+// This returns *global* reference, no need to free it.
+static jobject getJavaAssetManager()
+{
+	static AssetManagerObject assetManager;
+	return (jobject) assetManager;
+}
+
 static AAssetManager *getAssetManager()
 static AAssetManager *getAssetManager()
 {
 {
 	JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
 	JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
-	jobject self = (jobject) SDL_AndroidGetActivity();
-	jclass activity = env->GetObjectClass(self);
-	jmethodID method = env->GetMethodID(activity, "getAssetManager", "()Landroid/content/res/AssetManager;");
-
-	jobject assetManager = env->CallObjectMethod(self, method);
-	AAssetManager *assetManagerObject = AAssetManager_fromJava(env, assetManager);
-
-	env->DeleteLocalRef(assetManager);
-	env->DeleteLocalRef(activity);
-	env->DeleteLocalRef(self);
-
-	return assetManagerObject;
+	return AAssetManager_fromJava(env, (jobject) getJavaAssetManager());
 }
 }
 
 
 namespace aasset
 namespace aasset
@@ -368,35 +403,6 @@ struct AssetInfo
 
 
 static std::unordered_map<std::string, PHYSFS_FileType> fileTree;
 static std::unordered_map<std::string, PHYSFS_FileType> fileTree;
 
 
-// Workaround AAsset can't detect whetever something is a directory or doesn't exist
-static void buildFileLookup(
-	AAssetManager *assetManager,
-	std::unordered_map<std::string, PHYSFS_FileType> &out,
-	const std::string &path = ""
-)
-{
-	if (!path.empty())
-	{
-		AAsset *test = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_STREAMING);
-		if (test)
-		{
-			AAsset_close(test);
-			out[path] = PHYSFS_FILETYPE_REGULAR;
-			return;
-		}
-
-		out[path] = PHYSFS_FILETYPE_DIRECTORY;
-	}
-
-	AAssetDir *dir = AAssetManager_openDir(assetManager, path.c_str());
-	const char *file;
-
-	while ((file = AAssetDir_getNextFileName(dir)) != nullptr)
-		buildFileLookup(assetManager, out, file);
-
-	AAssetDir_close(dir);
-}
-
 PHYSFS_sint64 read(PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
 PHYSFS_sint64 read(PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
 {
 {
 	AAsset *asset = ((AssetInfo *) io->opaque)->asset;
 	AAsset *asset = ((AssetInfo *) io->opaque)->asset;
@@ -505,7 +511,31 @@ void *openArchive(PHYSFS_Io *io, const char *name, int forWrite, int *claimed)
 	AAssetManager *assetManager = getAssetManager();
 	AAssetManager *assetManager = getAssetManager();
 
 
 	if (io::fileTree.empty())
 	if (io::fileTree.empty())
-		io::buildFileLookup(assetManager, io::fileTree);
+	{
+		// AAssetDir_getNextFileName intentionally excludes directories, so
+		// we have to use JNI that calls AssetManager.list() recursively.
+		JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
+		jobject activity = (jobject) SDL_AndroidGetActivity();
+		jclass clazz = env->GetObjectClass(activity);
+
+		jmethodID method = env->GetMethodID(clazz, "buildFileTree", "()[Ljava/lang/String;");
+		jobjectArray list = (jobjectArray) env->CallObjectMethod(activity, method);
+
+		for (jsize i = 0; i < env->GetArrayLength(list); i++)
+		{
+			jstring jstr = (jstring) env->GetObjectArrayElement(list, i);
+			const char *str = env->GetStringUTFChars(jstr, nullptr);
+
+			io::fileTree[str + 1] = str[0] == 'd' ? PHYSFS_FILETYPE_DIRECTORY : PHYSFS_FILETYPE_REGULAR;
+
+			env->ReleaseStringUTFChars(jstr, str);
+			env->DeleteLocalRef(jstr);
+		}
+
+		env->DeleteLocalRef(list);
+		env->DeleteLocalRef(clazz);
+		env->DeleteLocalRef(activity);
+	}
 
 
 	return assetManager;
 	return assetManager;
 }
 }
@@ -518,33 +548,60 @@ PHYSFS_EnumerateCallbackResult enumerate(
 	void *callbackdata
 	void *callbackdata
 )
 )
 {
 {
+	using FileTreeIterator = std::unordered_map<std::string, PHYSFS_FileType>::iterator;
+	LOVE_UNUSED(opaque);
+
 	const char *path = dirname;
 	const char *path = dirname;
 	if (path == nullptr || (path[0] == '/' && path[1] == 0))
 	if (path == nullptr || (path[0] == '/' && path[1] == 0))
 		path = "";
 		path = "";
 
 
-	AAssetManager *assetManager = (AAssetManager *) opaque;
-	AAssetDir *dir = AAssetManager_openDir(assetManager, path);
-
-	if (dir == nullptr)
+	if (path[0] != 0)
 	{
 	{
-		PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
-		return PHYSFS_ENUM_ERROR;
+		FileTreeIterator result = io::fileTree.find(path);
+
+		if (result == io::fileTree.end() || result->second != PHYSFS_FILETYPE_DIRECTORY)
+		{
+			PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
+			return PHYSFS_ENUM_ERROR;
+		}
 	}
 	}
 
 
+	JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
+	jobject assetManager = getJavaAssetManager();
+	jclass clazz = env->GetObjectClass(assetManager);
+	jmethodID method = env->GetMethodID(clazz, "list", "(Ljava/lang/String;)[Ljava/lang/String;");
+
+	jstring jstringDir = env->NewStringUTF(path);
+	jobjectArray dir = (jobjectArray) env->CallObjectMethod(assetManager, method, jstringDir);
+
 	PHYSFS_EnumerateCallbackResult ret = PHYSFS_ENUM_OK;
 	PHYSFS_EnumerateCallbackResult ret = PHYSFS_ENUM_OK;
 
 
-	while (ret == PHYSFS_ENUM_OK)
+	if (env->ExceptionCheck())
+	{
+		// IOException occured
+		ret = PHYSFS_ENUM_ERROR;
+		env->ExceptionClear();
+	}
+	else
 	{
 	{
-		const char *name = AAssetDir_getNextFileName(dir);
+		jsize i = 0;
+		jsize len = env->GetArrayLength(dir);
+
+		while (ret == PHYSFS_ENUM_OK && i < len) {
+			jstring jstr = (jstring) env->GetObjectArrayElement(dir, i++);
+			const char *name = env->GetStringUTFChars(jstr, nullptr);
 
 
-		// No more files?
-		if (name == nullptr)
-			break;
+			ret = cb(callbackdata, origdir, name);
+
+			env->ReleaseStringUTFChars(jstr, name);
+			env->DeleteLocalRef(jstr);
+		}
 
 
-		ret = cb(callbackdata, origdir, name);
+		env->DeleteLocalRef(dir);
 	}
 	}
 
 
-	AAssetDir_close(dir);
+	env->DeleteLocalRef(jstringDir);
+	env->DeleteLocalRef(clazz);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -724,6 +781,48 @@ bool checkFusedGame(void **physfsIO_Out)
 	return false;
 	return false;
 }
 }
 
 
+const char *getCRequirePath()
+{
+	static bool initialized = false;
+	static const char *path = nullptr;
+
+	if (!initialized)
+	{
+		JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
+		jobject activity = (jobject) SDL_AndroidGetActivity();
+
+		jclass clazz(env->GetObjectClass(activity));
+		jmethodID method_id = env->GetMethodID(clazz, "getCRequirePath", "()Ljava/lang/String;");
+
+		path = "";
+		initialized = true;
+
+		if (method_id)
+		{
+			jstring cpath = (jstring) env->CallObjectMethod(activity, method_id);
+			const char *utf = env->GetStringUTFChars(cpath, nullptr);
+			if (utf)
+			{
+				path = SDL_strdup(utf);
+				env->ReleaseStringUTFChars(cpath, utf);
+			}
+
+			env->DeleteLocalRef(cpath);
+		}
+		else
+		{
+			// NoSuchMethodException is thrown in case methodID is null
+			env->ExceptionClear();
+			return "";
+		}
+
+		env->DeleteLocalRef(activity);
+		env->DeleteLocalRef(clazz);
+	}
+
+	return path;
+}
+
 } // android
 } // android
 } // love
 } // love
 
 

+ 2 - 0
src/common/android.h

@@ -101,6 +101,8 @@ void deinitializeVirtualArchive();
  */
  */
 bool checkFusedGame(void **physfsIO_Out);
 bool checkFusedGame(void **physfsIO_Out);
 
 
+const char *getCRequirePath();
+
 } // android
 } // android
 } // love
 } // love
 
 

+ 5 - 1
src/common/runtime.cpp

@@ -1156,7 +1156,9 @@ void luax_runwrapper(lua_State *L, const char *filedata, size_t datalen, const c
 	// functions struct pointer as arguments.
 	// functions struct pointer as arguments.
 	if (lua_istable(L, -1))
 	if (lua_istable(L, -1))
 	{
 	{
-		luaL_loadbuffer(L, filedata, datalen, filename);
+		std::string chunkname = std::string("=[love \"") + std::string(filename) + std::string("\"]");
+
+		luaL_loadbuffer(L, filedata, datalen, chunkname.c_str());
 		lua_pushvalue(L, -2);
 		lua_pushvalue(L, -2);
 		if (ffifuncs != nullptr)
 		if (ffifuncs != nullptr)
 			luax_pushpointerasstring(L, ffifuncs);
 			luax_pushpointerasstring(L, ffifuncs);
@@ -1179,8 +1181,10 @@ int luax_resume(lua_State *L, int nargs, int* nres)
 #if LUA_VERSION_NUM >= 504
 #if LUA_VERSION_NUM >= 504
 	return lua_resume(L, nullptr, nargs, nres);
 	return lua_resume(L, nullptr, nargs, nres);
 #elif LUA_VERSION_NUM >= 502
 #elif LUA_VERSION_NUM >= 502
+	LOVE_UNUSED(nres);
 	return lua_resume(L, nullptr, nargs);
 	return lua_resume(L, nullptr, nargs);
 #else
 #else
+	LOVE_UNUSED(nres);
 	return lua_resume(L, nargs);
 	return lua_resume(L, nargs);
 #endif
 #endif
 }
 }

+ 40 - 14
src/libraries/enet/enet.cpp

@@ -118,11 +118,30 @@ static size_t find_peer_index(lua_State *l, ENetHost *enet_host, ENetPeer *peer)
 #define ENET_ALIGNOF(x) alignof(x)
 #define ENET_ALIGNOF(x) alignof(x)
 #endif
 #endif
 
 
-// For use with the enet_peers registry.
-// Using the pointer directly via lightuserdata would be ideal, but LuaJIT
-// cannot use lightuserdata with more than 47 bits whereas some newer arm64
-// architectures allow pointers which use more than that.
-static lua_Number compute_peer_key(lua_State *L, ENetPeer *peer)
+static bool supports_full_lightuserdata(lua_State *L)
+{
+	static bool checked = false;
+	static bool supported = false;
+
+	if (!checked)
+	{
+		lua_pushcclosure(L, [](lua_State* L) -> int
+		{
+			// Try to push pointer with all bits set.
+			lua_pushlightuserdata(L, (void*)(~((size_t)0)));
+			return 1;
+		}, 0);
+
+		supported = lua_pcall(L, 0, 1, 0) == 0;
+		checked = true;
+
+		lua_pop(L, 1);
+	}
+
+	return supported;
+}
+
+static uintptr_t compute_peer_key(lua_State *L, ENetPeer *peer)
 {
 {
 	// ENet peers are be allocated on the heap in an array. Lua numbers
 	// ENet peers are be allocated on the heap in an array. Lua numbers
 	// (doubles) can store all possible integers up to 2^53. We can store
 	// (doubles) can store all possible integers up to 2^53. We can store
@@ -140,21 +159,28 @@ static lua_Number compute_peer_key(lua_State *L, ENetPeer *peer)
 
 
 	static const size_t shift = (size_t) log2((double) minalign);
 	static const size_t shift = (size_t) log2((double) minalign);
 
 
-	key >>= shift;
-
-	// Make sure our key isn't larger than 2^53.
-	if (key > 0x20000000000000ULL)
-		luaL_error(L, "Cannot push enet peer to Lua: pointer value %p is too large", peer);
+	return key >> shift;
+}
 
 
-	return (lua_Number) key;
+static void push_peer_key(lua_State *L, uintptr_t key)
+{
+	// If full 64-bit lightuserdata is supported, always use that. Otherwise,
+	// if the key is smaller than 2^53 (which is integer precision for double
+	// datatype), then push number. Otherwise, throw error.
+	if (supports_full_lightuserdata(L))
+		lua_pushlightuserdata(L, (void*) key);
+	else if (key > 0x20000000000000ULL) // 2^53
+		luaL_error(L, "Cannot push enet peer to Lua: pointer value %p is too large", key);
+	else
+		lua_pushnumber(L, (lua_Number) key);
 }
 }
 
 
 static void push_peer(lua_State *l, ENetPeer *peer) {
 static void push_peer(lua_State *l, ENetPeer *peer) {
-	lua_Number key = compute_peer_key(l, peer);
+	uintptr_t key = compute_peer_key(l, peer);
 
 
 	// try to find in peer table
 	// try to find in peer table
 	lua_getfield(l, LUA_REGISTRYINDEX, "enet_peers");
 	lua_getfield(l, LUA_REGISTRYINDEX, "enet_peers");
-	lua_pushnumber(l, key);
+	push_peer_key(l, key);
 	lua_gettable(l, -2);
 	lua_gettable(l, -2);
 
 
 	if (lua_isnil(l, -1)) {
 	if (lua_isnil(l, -1)) {
@@ -165,7 +191,7 @@ static void push_peer(lua_State *l, ENetPeer *peer) {
 		luaL_getmetatable(l, "enet_peer");
 		luaL_getmetatable(l, "enet_peer");
 		lua_setmetatable(l, -2);
 		lua_setmetatable(l, -2);
 
 
-		lua_pushnumber(l, key);
+		push_peer_key(l, key);
 		lua_pushvalue(l, -2);
 		lua_pushvalue(l, -2);
 
 
 		lua_settable(l, -4);
 		lua_settable(l, -4);

+ 136 - 49
src/libraries/lodepng/lodepng.cpp

@@ -1,7 +1,7 @@
 /*
 /*
-LodePNG version 20200306
+LodePNG version 20210627
 
 
-Copyright (c) 2005-2020 Lode Vandevenne
+Copyright (c) 2005-2021 Lode Vandevenne
 
 
 This software is provided 'as-is', without any express or implied
 This software is provided 'as-is', without any express or implied
 warranty. In no event will the authors be held liable for any damages
 warranty. In no event will the authors be held liable for any damages
@@ -44,7 +44,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
 #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
 #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
 #endif /*_MSC_VER */
 #endif /*_MSC_VER */
 
 
-const char* LODEPNG_VERSION_STRING = "20200306";
+const char* LODEPNG_VERSION_STRING = "20210627";
 
 
 /*
 /*
 This source file is built up in the following large parts. The code sections
 This source file is built up in the following large parts. The code sections
@@ -299,6 +299,7 @@ static void string_cleanup(char** out) {
   *out = NULL;
   *out = NULL;
 }
 }
 
 
+/*also appends null termination character*/
 static char* alloc_string_sized(const char* in, size_t insize) {
 static char* alloc_string_sized(const char* in, size_t insize) {
   char* out = (char*)lodepng_malloc(insize + 1);
   char* out = (char*)lodepng_malloc(insize + 1);
   if(out) {
   if(out) {
@@ -1260,7 +1261,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
 
 
 /*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/
 /*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/
 static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
 static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
-                                    unsigned btype) {
+                                    unsigned btype, size_t max_output_size) {
   unsigned error = 0;
   unsigned error = 0;
   HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
   HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
   HuffmanTree tree_d; /*the huffman tree for distance codes*/
   HuffmanTree tree_d; /*the huffman tree for distance codes*/
@@ -1341,6 +1342,9 @@ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
       /* TODO: revise error codes 10,11,50: the above comment is no longer valid */
       /* TODO: revise error codes 10,11,50: the above comment is no longer valid */
       ERROR_BREAK(51); /*error, bit pointer jumps past memory*/
       ERROR_BREAK(51); /*error, bit pointer jumps past memory*/
     }
     }
+    if(max_output_size && out->size > max_output_size) {
+      ERROR_BREAK(109); /*error, larger than max size*/
+    }
   }
   }
 
 
   HuffmanTree_cleanup(&tree_ll);
   HuffmanTree_cleanup(&tree_ll);
@@ -1398,9 +1402,9 @@ static unsigned lodepng_inflatev(ucvector* out,
 
 
     if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
     if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
     else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/
     else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/
-    else error = inflateHuffmanBlock(out, &reader, BTYPE); /*compression, BTYPE 01 or 10*/
-
-    if(error) return error;
+    else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/
+    if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109;
+    if(error) break;
   }
   }
 
 
   return error;
   return error;
@@ -1421,6 +1425,12 @@ static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize,
   if(settings->custom_inflate) {
   if(settings->custom_inflate) {
     unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings);
     unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings);
     out->allocsize = out->size;
     out->allocsize = out->size;
+    if(error) {
+      /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/
+      error = 110;
+      /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
+      if(settings->max_output_size && out->size > settings->max_output_size) error = 109;
+    }
     return error;
     return error;
   } else {
   } else {
     return lodepng_inflatev(out, in, insize, settings);
     return lodepng_inflatev(out, in, insize, settings);
@@ -2116,7 +2126,9 @@ static unsigned deflate(unsigned char** out, size_t* outsize,
                         const unsigned char* in, size_t insize,
                         const unsigned char* in, size_t insize,
                         const LodePNGCompressSettings* settings) {
                         const LodePNGCompressSettings* settings) {
   if(settings->custom_deflate) {
   if(settings->custom_deflate) {
-    return settings->custom_deflate(out, outsize, in, insize, settings);
+    unsigned error = settings->custom_deflate(out, outsize, in, insize, settings);
+    /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/
+    return error ? 111 : 0;
   } else {
   } else {
     return lodepng_deflate(out, outsize, in, insize, settings);
     return lodepng_deflate(out, outsize, in, insize, settings);
   }
   }
@@ -2213,10 +2225,16 @@ unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const uns
 /*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */
 /*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */
 static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
 static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
                                 const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
                                 const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
+  unsigned error;
   if(settings->custom_zlib) {
   if(settings->custom_zlib) {
-    return settings->custom_zlib(out, outsize, in, insize, settings);
+    error = settings->custom_zlib(out, outsize, in, insize, settings);
+    if(error) {
+      /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/
+      error = 110;
+      /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
+      if(settings->max_output_size && *outsize > settings->max_output_size) error = 109;
+    }
   } else {
   } else {
-    unsigned error;
     ucvector v = ucvector_init(*out, *outsize);
     ucvector v = ucvector_init(*out, *outsize);
     if(expected_size) {
     if(expected_size) {
       /*reserve the memory to avoid intermediate reallocations*/
       /*reserve the memory to avoid intermediate reallocations*/
@@ -2226,8 +2244,8 @@ static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t exp
     error = lodepng_zlib_decompressv(&v, in, insize, settings);
     error = lodepng_zlib_decompressv(&v, in, insize, settings);
     *out = v.data;
     *out = v.data;
     *outsize = v.size;
     *outsize = v.size;
-    return error;
   }
   }
+  return error;
 }
 }
 
 
 #endif /*LODEPNG_COMPILE_DECODER*/
 #endif /*LODEPNG_COMPILE_DECODER*/
@@ -2275,7 +2293,9 @@ unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsig
 static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
 static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
                               size_t insize, const LodePNGCompressSettings* settings) {
                               size_t insize, const LodePNGCompressSettings* settings) {
   if(settings->custom_zlib) {
   if(settings->custom_zlib) {
-    return settings->custom_zlib(out, outsize, in, insize, settings);
+    unsigned error = settings->custom_zlib(out, outsize, in, insize, settings);
+    /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/
+    return error ? 111 : 0;
   } else {
   } else {
     return lodepng_zlib_compress(out, outsize, in, insize, settings);
     return lodepng_zlib_compress(out, outsize, in, insize, settings);
   }
   }
@@ -2334,13 +2354,14 @@ const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT
 void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
 void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
   settings->ignore_adler32 = 0;
   settings->ignore_adler32 = 0;
   settings->ignore_nlen = 0;
   settings->ignore_nlen = 0;
+  settings->max_output_size = 0;
 
 
   settings->custom_zlib = 0;
   settings->custom_zlib = 0;
   settings->custom_inflate = 0;
   settings->custom_inflate = 0;
   settings->custom_context = 0;
   settings->custom_context = 0;
 }
 }
 
 
-const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0};
+const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0};
 
 
 #endif /*LODEPNG_COMPILE_DECODER*/
 #endif /*LODEPNG_COMPILE_DECODER*/
 
 
@@ -2872,8 +2893,8 @@ static void LodePNGText_cleanup(LodePNGInfo* info) {
 
 
 static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
 static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
   size_t i = 0;
   size_t i = 0;
-  dest->text_keys = 0;
-  dest->text_strings = 0;
+  dest->text_keys = NULL;
+  dest->text_strings = NULL;
   dest->text_num = 0;
   dest->text_num = 0;
   for(i = 0; i != source->text_num; ++i) {
   for(i = 0; i != source->text_num; ++i) {
     CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
     CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
@@ -2932,10 +2953,10 @@ static void LodePNGIText_cleanup(LodePNGInfo* info) {
 
 
 static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
 static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
   size_t i = 0;
   size_t i = 0;
-  dest->itext_keys = 0;
-  dest->itext_langtags = 0;
-  dest->itext_transkeys = 0;
-  dest->itext_strings = 0;
+  dest->itext_keys = NULL;
+  dest->itext_langtags = NULL;
+  dest->itext_transkeys = NULL;
+  dest->itext_strings = NULL;
   dest->itext_num = 0;
   dest->itext_num = 0;
   for(i = 0; i != source->itext_num; ++i) {
   for(i = 0; i != source->itext_num; ++i) {
     CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
     CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
@@ -4093,10 +4114,12 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
     case 0:
     case 0:
       for(i = 0; i != length; ++i) recon[i] = scanline[i];
       for(i = 0; i != length; ++i) recon[i] = scanline[i];
       break;
       break;
-    case 1:
+    case 1: {
+      size_t j = 0;
       for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
       for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
-      for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];
+      for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + recon[j];
       break;
       break;
+    }
     case 2:
     case 2:
       if(precon) {
       if(precon) {
         for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
         for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
@@ -4106,24 +4129,56 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
       break;
       break;
     case 3:
     case 3:
       if(precon) {
       if(precon) {
+        size_t j = 0;
         for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u);
         for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u);
-        for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1u);
+        /* Unroll independent paths of this predictor. A 6x and 8x version is also possible but that adds
+        too much code. Whether this speeds up anything depends on compiler and settings. */
+        if(bytewidth >= 4) {
+          for(; i + 3 < length; i += 4, j += 4) {
+            unsigned char s0 = scanline[i + 0], r0 = recon[j + 0], p0 = precon[i + 0];
+            unsigned char s1 = scanline[i + 1], r1 = recon[j + 1], p1 = precon[i + 1];
+            unsigned char s2 = scanline[i + 2], r2 = recon[j + 2], p2 = precon[i + 2];
+            unsigned char s3 = scanline[i + 3], r3 = recon[j + 3], p3 = precon[i + 3];
+            recon[i + 0] = s0 + ((r0 + p0) >> 1u);
+            recon[i + 1] = s1 + ((r1 + p1) >> 1u);
+            recon[i + 2] = s2 + ((r2 + p2) >> 1u);
+            recon[i + 3] = s3 + ((r3 + p3) >> 1u);
+          }
+        } else if(bytewidth >= 3) {
+          for(; i + 2 < length; i += 3, j += 3) {
+            unsigned char s0 = scanline[i + 0], r0 = recon[j + 0], p0 = precon[i + 0];
+            unsigned char s1 = scanline[i + 1], r1 = recon[j + 1], p1 = precon[i + 1];
+            unsigned char s2 = scanline[i + 2], r2 = recon[j + 2], p2 = precon[i + 2];
+            recon[i + 0] = s0 + ((r0 + p0) >> 1u);
+            recon[i + 1] = s1 + ((r1 + p1) >> 1u);
+            recon[i + 2] = s2 + ((r2 + p2) >> 1u);
+          }
+        } else if(bytewidth >= 2) {
+          for(; i + 1 < length; i += 2, j += 2) {
+            unsigned char s0 = scanline[i + 0], r0 = recon[j + 0], p0 = precon[i + 0];
+            unsigned char s1 = scanline[i + 1], r1 = recon[j + 1], p1 = precon[i + 1];
+            recon[i + 0] = s0 + ((r0 + p0) >> 1u);
+            recon[i + 1] = s1 + ((r1 + p1) >> 1u);
+          }
+        }
+        for(; i != length; ++i, ++j) recon[i] = scanline[i] + ((recon[j] + precon[i]) >> 1u);
       } else {
       } else {
+        size_t j = 0;
         for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
         for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
-        for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1u);
+        for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + (recon[j] >> 1u);
       }
       }
       break;
       break;
     case 4:
     case 4:
       if(precon) {
       if(precon) {
+        size_t j = 0;
         for(i = 0; i != bytewidth; ++i) {
         for(i = 0; i != bytewidth; ++i) {
           recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
           recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
         }
         }
 
 
-        /* Unroll independent paths of the paeth predictor. A 6x and 8x version would also be possible but that
-        adds too much code. Whether this actually speeds anything up at all depends on compiler and settings. */
+        /* Unroll independent paths of the paeth predictor. A 6x and 8x version is also possible but that
+        adds too much code. Whether this speeds up anything depends on compiler and settings. */
         if(bytewidth >= 4) {
         if(bytewidth >= 4) {
-          for(; i + 3 < length; i += 4) {
-            size_t j = i - bytewidth;
+          for(; i + 3 < length; i += 4, j += 4) {
             unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
             unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
             unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
             unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
             unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
             unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
@@ -4134,8 +4189,7 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
             recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
             recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
           }
           }
         } else if(bytewidth >= 3) {
         } else if(bytewidth >= 3) {
-          for(; i + 2 < length; i += 3) {
-            size_t j = i - bytewidth;
+          for(; i + 2 < length; i += 3, j += 3) {
             unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
             unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
             unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
             unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
             unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
             unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
@@ -4145,8 +4199,7 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
             recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
             recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
           }
           }
         } else if(bytewidth >= 2) {
         } else if(bytewidth >= 2) {
-          for(; i + 1 < length; i += 2) {
-            size_t j = i - bytewidth;
+          for(; i + 1 < length; i += 2, j += 2) {
             unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
             unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
             unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
             unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
             unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
             unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
@@ -4156,16 +4209,17 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
           }
           }
         }
         }
 
 
-        for(; i != length; ++i) {
-          recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
+        for(; i != length; ++i, ++j) {
+          recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[j]));
         }
         }
       } else {
       } else {
+        size_t j = 0;
         for(i = 0; i != bytewidth; ++i) {
         for(i = 0; i != bytewidth; ++i) {
           recon[i] = scanline[i];
           recon[i] = scanline[i];
         }
         }
-        for(i = bytewidth; i < length; ++i) {
+        for(i = bytewidth; i != length; ++i, ++j) {
           /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
           /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
-          recon[i] = (scanline[i] + recon[i - bytewidth]);
+          recon[i] = (scanline[i] + recon[j]);
         }
         }
       }
       }
       break;
       break;
@@ -4447,10 +4501,13 @@ static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, siz
 }
 }
 
 
 /*compressed text chunk (zTXt)*/
 /*compressed text chunk (zTXt)*/
-static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
+static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
                                const unsigned char* data, size_t chunkLength) {
                                const unsigned char* data, size_t chunkLength) {
   unsigned error = 0;
   unsigned error = 0;
 
 
+  /*copy the object to change parameters in it*/
+  LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
+
   unsigned length, string2_begin;
   unsigned length, string2_begin;
   char *key = 0;
   char *key = 0;
   unsigned char* str = 0;
   unsigned char* str = 0;
@@ -4473,12 +4530,14 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
     if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
     if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
 
 
     length = (unsigned)chunkLength - string2_begin;
     length = (unsigned)chunkLength - string2_begin;
+    zlibsettings.max_output_size = decoder->max_text_size;
     /*will fail if zlib error, e.g. if length is too small*/
     /*will fail if zlib error, e.g. if length is too small*/
     error = zlib_decompress(&str, &size, 0, &data[string2_begin],
     error = zlib_decompress(&str, &size, 0, &data[string2_begin],
-                            length, zlibsettings);
+                            length, &zlibsettings);
+    /*error: compressed text larger than  decoder->max_text_size*/
+    if(error && size > zlibsettings.max_output_size) error = 112;
     if(error) break;
     if(error) break;
     error = lodepng_add_text_sized(info, key, (char*)str, size);
     error = lodepng_add_text_sized(info, key, (char*)str, size);
-
     break;
     break;
   }
   }
 
 
@@ -4489,11 +4548,14 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
 }
 }
 
 
 /*international text chunk (iTXt)*/
 /*international text chunk (iTXt)*/
-static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
+static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
                                const unsigned char* data, size_t chunkLength) {
                                const unsigned char* data, size_t chunkLength) {
   unsigned error = 0;
   unsigned error = 0;
   unsigned i;
   unsigned i;
 
 
+  /*copy the object to change parameters in it*/
+  LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
+
   unsigned length, begin, compressed;
   unsigned length, begin, compressed;
   char *key = 0, *langtag = 0, *transkey = 0;
   char *key = 0, *langtag = 0, *transkey = 0;
 
 
@@ -4550,9 +4612,12 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
     if(compressed) {
     if(compressed) {
       unsigned char* str = 0;
       unsigned char* str = 0;
       size_t size = 0;
       size_t size = 0;
+      zlibsettings.max_output_size = decoder->max_text_size;
       /*will fail if zlib error, e.g. if length is too small*/
       /*will fail if zlib error, e.g. if length is too small*/
       error = zlib_decompress(&str, &size, 0, &data[begin],
       error = zlib_decompress(&str, &size, 0, &data[begin],
-                              length, zlibsettings);
+                              length, &zlibsettings);
+      /*error: compressed text larger than  decoder->max_text_size*/
+      if(error && size > zlibsettings.max_output_size) error = 112;
       if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size);
       if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size);
       lodepng_free(str);
       lodepng_free(str);
     } else {
     } else {
@@ -4628,11 +4693,13 @@ static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, siz
   return 0; /* OK */
   return 0; /* OK */
 }
 }
 
 
-static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
+static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
                                const unsigned char* data, size_t chunkLength) {
                                const unsigned char* data, size_t chunkLength) {
   unsigned error = 0;
   unsigned error = 0;
   unsigned i;
   unsigned i;
   size_t size = 0;
   size_t size = 0;
+  /*copy the object to change parameters in it*/
+  LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
 
 
   unsigned length, string2_begin;
   unsigned length, string2_begin;
 
 
@@ -4655,9 +4722,12 @@ static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSetting
   if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
   if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
 
 
   length = (unsigned)chunkLength - string2_begin;
   length = (unsigned)chunkLength - string2_begin;
+  zlibsettings.max_output_size = decoder->max_icc_size;
   error = zlib_decompress(&info->iccp_profile, &size, 0,
   error = zlib_decompress(&info->iccp_profile, &size, 0,
                           &data[string2_begin],
                           &data[string2_begin],
-                          length, zlibsettings);
+                          length, &zlibsettings);
+  /*error: ICC profile larger than  decoder->max_icc_size*/
+  if(error && size > zlibsettings.max_output_size) error = 113;
   info->iccp_profile_size = size;
   info->iccp_profile_size = size;
   if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
   if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
   return error;
   return error;
@@ -4688,9 +4758,9 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
   } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
   } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
     error = readChunk_tEXt(&state->info_png, data, chunkLength);
     error = readChunk_tEXt(&state->info_png, data, chunkLength);
   } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
   } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
-    error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+    error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
   } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
   } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
-    error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+    error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
   } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
   } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
     error = readChunk_tIME(&state->info_png, data, chunkLength);
     error = readChunk_tIME(&state->info_png, data, chunkLength);
   } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
   } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
@@ -4702,7 +4772,7 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
   } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
   } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
     error = readChunk_sRGB(&state->info_png, data, chunkLength);
     error = readChunk_sRGB(&state->info_png, data, chunkLength);
   } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
   } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
-    error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+    error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
   } else {
   } else {
     /* unhandled chunk is ok (is not an error) */
     /* unhandled chunk is ok (is not an error) */
@@ -4820,13 +4890,13 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
     } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
     } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
       /*compressed text chunk (zTXt)*/
       /*compressed text chunk (zTXt)*/
       if(state->decoder.read_text_chunks) {
       if(state->decoder.read_text_chunks) {
-        state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+        state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
         if(state->error) break;
         if(state->error) break;
       }
       }
     } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
     } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
       /*international text chunk (iTXt)*/
       /*international text chunk (iTXt)*/
       if(state->decoder.read_text_chunks) {
       if(state->decoder.read_text_chunks) {
-        state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+        state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
         if(state->error) break;
         if(state->error) break;
       }
       }
     } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
     } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
@@ -4845,7 +4915,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
       state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
       state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
       if(state->error) break;
       if(state->error) break;
     } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
     } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
-      state->error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+      state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
       if(state->error) break;
       if(state->error) break;
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
     } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
     } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
@@ -4871,7 +4941,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
     if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
     if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
   }
   }
 
 
-  if(state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) {
+  if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) {
     state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */
     state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */
   }
   }
 
 
@@ -4955,6 +5025,11 @@ unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, co
   lodepng_state_init(&state);
   lodepng_state_init(&state);
   state.info_raw.colortype = colortype;
   state.info_raw.colortype = colortype;
   state.info_raw.bitdepth = bitdepth;
   state.info_raw.bitdepth = bitdepth;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+  /*disable reading things that this function doesn't output*/
+  state.decoder.read_text_chunks = 0;
+  state.decoder.remember_unknown_chunks = 0;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
   error = lodepng_decode(out, w, h, &state, in, insize);
   error = lodepng_decode(out, w, h, &state, in, insize);
   lodepng_state_cleanup(&state);
   lodepng_state_cleanup(&state);
   return error;
   return error;
@@ -4997,6 +5072,8 @@ void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) {
 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
   settings->read_text_chunks = 1;
   settings->read_text_chunks = 1;
   settings->remember_unknown_chunks = 0;
   settings->remember_unknown_chunks = 0;
+  settings->max_text_size = 16777216;
+  settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
   settings->ignore_crc = 0;
   settings->ignore_crc = 0;
   settings->ignore_critical = 0;
   settings->ignore_critical = 0;
@@ -6204,6 +6281,16 @@ const char* lodepng_error_text(unsigned code) {
     case 106: return "PNG file must have PLTE chunk if color type is palette";
     case 106: return "PNG file must have PLTE chunk if color type is palette";
     case 107: return "color convert from palette mode requested without setting the palette data in it";
     case 107: return "color convert from palette mode requested without setting the palette data in it";
     case 108: return "tried to add more than 256 values to a palette";
     case 108: return "tried to add more than 256 values to a palette";
+    /*this limit can be configured in LodePNGDecompressSettings*/
+    case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size";
+    case 110: return "custom zlib or inflate decompression failed";
+    case 111: return "custom zlib or deflate compression failed";
+    /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents
+    unreasonable memory consumption when decoding due to impossibly large text sizes.*/
+    case 112: return "compressed text unreasonably large";
+    /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents
+    unreasonable memory consumption when decoding due to impossibly large ICC profile*/
+    case 113: return "ICC profile unreasonably large";
   }
   }
   return "unknown error code";
   return "unknown error code";
 }
 }

+ 91 - 17
src/libraries/lodepng/lodepng.h

@@ -1,7 +1,7 @@
 /*
 /*
-LodePNG version 20200306
+LodePNG version 20210627
 
 
-Copyright (c) 2005-2020 Lode Vandevenne
+Copyright (c) 2005-2021 Lode Vandevenne
 
 
 This software is provided 'as-is', without any express or implied
 This software is provided 'as-is', without any express or implied
 warranty. In no event will the authors be held liable for any damages
 warranty. In no event will the authors be held liable for any damages
@@ -142,16 +142,24 @@ unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,
 /*
 /*
 Load PNG from disk, from file with given name.
 Load PNG from disk, from file with given name.
 Same as the other decode functions, but instead takes a filename as input.
 Same as the other decode functions, but instead takes a filename as input.
-*/
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and decode in-memory.*/
 unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
 unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
                              const char* filename,
                              const char* filename,
                              LodePNGColorType colortype, unsigned bitdepth);
                              LodePNGColorType colortype, unsigned bitdepth);
 
 
-/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/
+/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and decode in-memory.*/
 unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
 unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
                                const char* filename);
                                const char* filename);
 
 
-/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/
+/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and decode in-memory.*/
 unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
 unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
                                const char* filename);
                                const char* filename);
 #endif /*LODEPNG_COMPILE_DISK*/
 #endif /*LODEPNG_COMPILE_DISK*/
@@ -191,17 +199,26 @@ unsigned lodepng_encode24(unsigned char** out, size_t* outsize,
 /*
 /*
 Converts raw pixel data into a PNG file on disk.
 Converts raw pixel data into a PNG file on disk.
 Same as the other encode functions, but instead takes a filename as output.
 Same as the other encode functions, but instead takes a filename as output.
+
 NOTE: This overwrites existing files without warning!
 NOTE: This overwrites existing files without warning!
-*/
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and encode in-memory.*/
 unsigned lodepng_encode_file(const char* filename,
 unsigned lodepng_encode_file(const char* filename,
                              const unsigned char* image, unsigned w, unsigned h,
                              const unsigned char* image, unsigned w, unsigned h,
                              LodePNGColorType colortype, unsigned bitdepth);
                              LodePNGColorType colortype, unsigned bitdepth);
 
 
-/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/
+/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and encode in-memory.*/
 unsigned lodepng_encode32_file(const char* filename,
 unsigned lodepng_encode32_file(const char* filename,
                                const unsigned char* image, unsigned w, unsigned h);
                                const unsigned char* image, unsigned w, unsigned h);
 
 
-/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/
+/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and encode in-memory.*/
 unsigned lodepng_encode24_file(const char* filename,
 unsigned lodepng_encode24_file(const char* filename,
                                const unsigned char* image, unsigned w, unsigned h);
                                const unsigned char* image, unsigned w, unsigned h);
 #endif /*LODEPNG_COMPILE_DISK*/
 #endif /*LODEPNG_COMPILE_DISK*/
@@ -223,6 +240,9 @@ unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
 /*
 /*
 Converts PNG file from disk to raw pixel data in memory.
 Converts PNG file from disk to raw pixel data in memory.
 Same as the other decode functions, but instead takes a filename as input.
 Same as the other decode functions, but instead takes a filename as input.
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and decode in-memory.
 */
 */
 unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
 unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
                 const std::string& filename,
                 const std::string& filename,
@@ -243,7 +263,11 @@ unsigned encode(std::vector<unsigned char>& out,
 /*
 /*
 Converts 32-bit RGBA raw pixel data into a PNG file on disk.
 Converts 32-bit RGBA raw pixel data into a PNG file on disk.
 Same as the other encode functions, but instead takes a filename as output.
 Same as the other encode functions, but instead takes a filename as output.
+
 NOTE: This overwrites existing files without warning!
 NOTE: This overwrites existing files without warning!
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and decode in-memory.
 */
 */
 unsigned encode(const std::string& filename,
 unsigned encode(const std::string& filename,
                 const unsigned char* in, unsigned w, unsigned h,
                 const unsigned char* in, unsigned w, unsigned h,
@@ -270,12 +294,21 @@ struct LodePNGDecompressSettings {
   unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
   unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
   unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/
   unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/
 
 
-  /*use custom zlib decoder instead of built in one (default: null)*/
+  /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding,
+  return an error, output a data size > max_output_size and all the data up to that point. This is
+  not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is
+  ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones.
+  Set to 0 to impose no limit (the default).*/
+  size_t max_output_size;
+
+  /*use custom zlib decoder instead of built in one (default: null).
+  Should return 0 if success, any non-0 if error (numeric value not exposed).*/
   unsigned (*custom_zlib)(unsigned char**, size_t*,
   unsigned (*custom_zlib)(unsigned char**, size_t*,
                           const unsigned char*, size_t,
                           const unsigned char*, size_t,
                           const LodePNGDecompressSettings*);
                           const LodePNGDecompressSettings*);
   /*use custom deflate decoder instead of built in one (default: null)
   /*use custom deflate decoder instead of built in one (default: null)
-  if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate)*/
+  if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate).
+  Should return 0 if success, any non-0 if error (numeric value not exposed).*/
   unsigned (*custom_inflate)(unsigned char**, size_t*,
   unsigned (*custom_inflate)(unsigned char**, size_t*,
                              const unsigned char*, size_t,
                              const unsigned char*, size_t,
                              const LodePNGDecompressSettings*);
                              const LodePNGDecompressSettings*);
@@ -454,30 +487,36 @@ typedef struct LodePNGInfo {
   unsigned background_b;       /*blue component of suggested background color*/
   unsigned background_b;       /*blue component of suggested background color*/
 
 
   /*
   /*
-  non-international text chunks (tEXt and zTXt)
+  Non-international text chunks (tEXt and zTXt)
 
 
   The char** arrays each contain num strings. The actual messages are in
   The char** arrays each contain num strings. The actual messages are in
   text_strings, while text_keys are keywords that give a short description what
   text_strings, while text_keys are keywords that give a short description what
   the actual text represents, e.g. Title, Author, Description, or anything else.
   the actual text represents, e.g. Title, Author, Description, or anything else.
 
 
-  All the string fields below including keys, names and language tags are null terminated.
+  All the string fields below including strings, keys, names and language tags are null terminated.
   The PNG specification uses null characters for the keys, names and tags, and forbids null
   The PNG specification uses null characters for the keys, names and tags, and forbids null
   characters to appear in the main text which is why we can use null termination everywhere here.
   characters to appear in the main text which is why we can use null termination everywhere here.
 
 
-  A keyword is minimum 1 character and maximum 79 characters long. It's
-  discouraged to use a single line length longer than 79 characters for texts.
+  A keyword is minimum 1 character and maximum 79 characters long (plus the
+  additional null terminator). It's discouraged to use a single line length
+  longer than 79 characters for texts.
 
 
   Don't allocate these text buffers yourself. Use the init/cleanup functions
   Don't allocate these text buffers yourself. Use the init/cleanup functions
   correctly and use lodepng_add_text and lodepng_clear_text.
   correctly and use lodepng_add_text and lodepng_clear_text.
+
+  Standard text chunk keywords and strings are encoded using Latin-1.
   */
   */
   size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
   size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
   char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
   char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
   char** text_strings; /*the actual text*/
   char** text_strings; /*the actual text*/
 
 
   /*
   /*
-  international text chunks (iTXt)
+  International text chunks (iTXt)
   Similar to the non-international text chunks, but with additional strings
   Similar to the non-international text chunks, but with additional strings
-  "langtags" and "transkeys".
+  "langtags" and "transkeys", and the following text encodings are used:
+  keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8.
+  keys must be 1-79 characters (plus the additional null terminator), the other
+  strings are any length.
   */
   */
   size_t itext_num; /*the amount of international texts in this PNG*/
   size_t itext_num; /*the amount of international texts in this PNG*/
   char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
   char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
@@ -639,8 +678,19 @@ typedef struct LodePNGDecoderSettings {
 
 
 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
   unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
   unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
+
   /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
   /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
   unsigned remember_unknown_chunks;
   unsigned remember_unknown_chunks;
+
+  /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned,
+  unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size.
+  By default it is a value that prevents unreasonably large strings from hogging memory. */
+  size_t max_text_size;
+
+  /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to
+  0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any
+  legitimate profile could be to hog memory. */
+  size_t max_icc_size;
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
 } LodePNGDecoderSettings;
 } LodePNGDecoderSettings;
 
 
@@ -950,6 +1000,9 @@ out: output parameter, contains pointer to loaded buffer.
 outsize: output parameter, size of the allocated out buffer
 outsize: output parameter, size of the allocated out buffer
 filename: the path to the file to load
 filename: the path to the file to load
 return value: error code (0 means ok)
 return value: error code (0 means ok)
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and decode in-memory.
 */
 */
 unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
 unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
 
 
@@ -960,6 +1013,9 @@ buffer: the buffer to write
 buffersize: size of the buffer to write
 buffersize: size of the buffer to write
 filename: the path to the file to save to
 filename: the path to the file to save to
 return value: error code (0 means ok)
 return value: error code (0 means ok)
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and encode in-memory
 */
 */
 unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
 unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
 #endif /*LODEPNG_COMPILE_DISK*/
 #endif /*LODEPNG_COMPILE_DISK*/
@@ -1000,12 +1056,18 @@ unsigned encode(std::vector<unsigned char>& out,
 /*
 /*
 Load a file from disk into an std::vector.
 Load a file from disk into an std::vector.
 return value: error code (0 means ok)
 return value: error code (0 means ok)
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and decode in-memory
 */
 */
 unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
 unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
 
 
 /*
 /*
 Save the binary data in an std::vector to a file on disk. The file is overwritten
 Save the binary data in an std::vector to a file on disk. The file is overwritten
 without warning.
 without warning.
+
+NOTE: Wide-character filenames are not supported, you can use an external method
+to handle such files and encode in-memory
 */
 */
 unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
 unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
 #endif /* LODEPNG_COMPILE_DISK */
 #endif /* LODEPNG_COMPILE_DISK */
@@ -1505,6 +1567,11 @@ of the error in English as a string.
 
 
 Check the implementation of lodepng_error_text to see the meaning of each code.
 Check the implementation of lodepng_error_text to see the meaning of each code.
 
 
+It is not recommended to use the numerical values to programmatically make
+different decisions based on error types as the numbers are not guaranteed to
+stay backwards compatible. They are for human consumption only. Programmatically
+only 0 or non-0 matter.
+
 
 
 8. chunks and PNG editing
 8. chunks and PNG editing
 -------------------------
 -------------------------
@@ -1678,6 +1745,9 @@ try to fix it if the compiler is modern and standards compliant.
 This decoder example shows the most basic usage of LodePNG. More complex
 This decoder example shows the most basic usage of LodePNG. More complex
 examples can be found on the LodePNG website.
 examples can be found on the LodePNG website.
 
 
+NOTE: these examples do not support wide-character filenames, you can use an
+external method to handle such files and encode or decode in-memory
+
 10.1. decoder C++ example
 10.1. decoder C++ example
 -------------------------
 -------------------------
 
 
@@ -1775,6 +1845,10 @@ symbol.
 Not all changes are listed here, the commit history in github lists more:
 Not all changes are listed here, the commit history in github lists more:
 https://github.com/lvandeve/lodepng
 https://github.com/lvandeve/lodepng
 
 
+*) 27 jun 2021: added warnings that file reading/writing functions don't support
+   wide-character filenames (support for this is not planned, opening files is
+   not the core part of PNG decoding/decoding and is platform dependent).
+*) 17 okt 2020: prevent decoding too large text/icc chunks by default.
 *) 06 mar 2020: simplified some of the dynamic memory allocations.
 *) 06 mar 2020: simplified some of the dynamic memory allocations.
 *) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct
 *) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct
    overflow checks.
    overflow checks.
@@ -1941,5 +2015,5 @@ Domain: gmail dot com.
 Account: lode dot vandevenne.
 Account: lode dot vandevenne.
 
 
 
 
-Copyright (c) 2005-2020 Lode Vandevenne
+Copyright (c) 2005-2021 Lode Vandevenne
 */
 */

+ 1 - 1
src/libraries/luasocket/libluasocket/ftp.lua.h

@@ -540,5 +540,5 @@ static const unsigned char B1[]={
 
 
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"ftp.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"ftp.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/headers.lua.h

@@ -192,5 +192,5 @@ static const unsigned char B1[]={
 108,101,114, 34, 44, 10,125, 10, 10,114,101,116,117,114,110, 32, 95, 77,
 108,101,114, 34, 44, 10,125, 10, 10,114,101,116,117,114,110, 32, 95, 77,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"headers.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"headers.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/http.lua.h

@@ -668,5 +668,5 @@ static const unsigned char B1[]={
 101,110,100, 41, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
 101,110,100, 41, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"http.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"http.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/ltn12.lua.h

@@ -442,5 +442,5 @@ static const unsigned char B1[]={
 110,100, 10,101,110,100, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
 110,100, 10,101,110,100, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"ltn12.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"ltn12.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/mbox.lua.h

@@ -140,5 +140,5 @@ static const unsigned char B1[]={
 110,100, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
 110,100, 10, 10,114,101,116,117,114,110, 32, 95, 77, 10,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"mbox.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"mbox.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/mime.lua.h

@@ -132,5 +132,5 @@ static const unsigned char B1[]={
 116,117,114,110, 32, 95, 77,
 116,117,114,110, 32, 95, 77,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"mime.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"mime.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/smtp.lua.h

@@ -411,5 +411,5 @@ static const unsigned char B1[]={
 110,100, 41, 10, 10,114,101,116,117,114,110, 32, 95, 77,
 110,100, 41, 10, 10,114,101,116,117,114,110, 32, 95, 77,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"smtp.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"smtp.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/socket.lua.h

@@ -230,5 +230,5 @@ static const unsigned char B1[]={
 116,117,114,110, 32, 95, 77, 10,
 116,117,114,110, 32, 95, 77, 10,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"socket.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"socket.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/tp.lua.h

@@ -196,5 +196,5 @@ static const unsigned char B1[]={
 114,110, 32, 95, 77, 10,
 114,110, 32, 95, 77, 10,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"tp.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"tp.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 1 - 1
src/libraries/luasocket/libluasocket/url.lua.h

@@ -563,5 +563,5 @@ static const unsigned char B1[]={
 110, 32, 95, 77, 10,
 110, 32, 95, 77, 10,
 };
 };
 
 
- if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"url.lua")==0) lua_call(L, 0, LUA_MULTRET);
+ if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"=[socket \"url.lua\"]")==0) lua_call(L, 0, LUA_MULTRET);
 }
 }

+ 82 - 82
src/libraries/noise1234/noise1234.cpp

@@ -106,47 +106,47 @@ unsigned char Noise1234::perm[] = {151,160,137,91,90,15,
  * float SLnoise = (Noise1234::noise(x,y,z) + 1.0) * 0.5;
  * float SLnoise = (Noise1234::noise(x,y,z) + 1.0) * 0.5;
  */
  */
 
 
-float  Noise1234::grad( int hash, float x ) {
+double  Noise1234::grad( int hash, double x ) {
     int h = hash & 15;
     int h = hash & 15;
-    float grad = 1.0 + (h & 7);  // Gradient value 1.0, 2.0, ..., 8.0
+    double grad = 1.0 + (h & 7);   // Gradient value 1.0, 2.0, ..., 8.0
     if (h&8) grad = -grad;         // and a random sign for the gradient
     if (h&8) grad = -grad;         // and a random sign for the gradient
     return ( grad * x );           // Multiply the gradient with the distance
     return ( grad * x );           // Multiply the gradient with the distance
 }
 }
 
 
-float  Noise1234::grad( int hash, float x, float y ) {
-    int h = hash & 7;      // Convert low 3 bits of hash code
-    float u = h<4 ? x : y;  // into 8 simple gradient directions,
-    float v = h<4 ? y : x;  // and compute the dot product with (x,y).
+double  Noise1234::grad( int hash, double x, double y ) {
+    int h = hash & 7;        // Convert low 3 bits of hash code
+    double u = h<4 ? x : y;  // into 8 simple gradient directions,
+    double v = h<4 ? y : x;  // and compute the dot product with (x,y).
     return ((h&1)? -u : u) + ((h&2)? -2.0*v : 2.0*v);
     return ((h&1)? -u : u) + ((h&2)? -2.0*v : 2.0*v);
 }
 }
 
 
-float  Noise1234::grad( int hash, float x, float y , float z ) {
-    int h = hash & 15;     // Convert low 4 bits of hash code into 12 simple
-    float u = h<8 ? x : y; // gradient directions, and compute dot product.
-    float v = h<4 ? y : h==12||h==14 ? x : z; // Fix repeats at h = 12 to 15
+double  Noise1234::grad( int hash, double x, double y , double z ) {
+    int h = hash & 15;      // Convert low 4 bits of hash code into 12 simple
+    double u = h<8 ? x : y; // gradient directions, and compute dot product.
+    double v = h<4 ? y : h==12||h==14 ? x : z; // Fix repeats at h = 12 to 15
     return ((h&1)? -u : u) + ((h&2)? -v : v);
     return ((h&1)? -u : u) + ((h&2)? -v : v);
 }
 }
 
 
-float  Noise1234::grad( int hash, float x, float y, float z, float t ) {
-    int h = hash & 31;      // Convert low 5 bits of hash code into 32 simple
-    float u = h<24 ? x : y; // gradient directions, and compute dot product.
-    float v = h<16 ? y : z;
-    float w = h<8 ? z : t;
+double  Noise1234::grad( int hash, double x, double y, double z, double t ) {
+    int h = hash & 31;       // Convert low 5 bits of hash code into 32 simple
+    double u = h<24 ? x : y; // gradient directions, and compute dot product.
+    double v = h<16 ? y : z;
+    double w = h<8 ? z : t;
     return ((h&1)? -u : u) + ((h&2)? -v : v) + ((h&4)? -w : w);
     return ((h&1)? -u : u) + ((h&2)? -v : v) + ((h&4)? -w : w);
 }
 }
 
 
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 /** 1D float Perlin noise, SL "noise()"
 /** 1D float Perlin noise, SL "noise()"
  */
  */
-float Noise1234::noise( float x )
+float Noise1234::noise( double x )
 {
 {
     int ix0, ix1;
     int ix0, ix1;
-    float fx0, fx1;
-    float s, n0, n1;
+    double fx0, fx1;
+    double s, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
-    fx0 = x - ix0;       // Fractional part of x
-    fx1 = fx0 - 1.0f;
+    fx0 = x - ix0;        // Fractional part of x
+    fx1 = fx0 - 1.0;
     ix1 = ( ix0+1 ) & 0xff;
     ix1 = ( ix0+1 ) & 0xff;
     ix0 = ix0 & 0xff;    // Wrap to 0..255
     ix0 = ix0 & 0xff;    // Wrap to 0..255
 
 
@@ -160,17 +160,17 @@ float Noise1234::noise( float x )
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 /** 1D float Perlin periodic noise, SL "pnoise()"
 /** 1D float Perlin periodic noise, SL "pnoise()"
  */
  */
-float Noise1234::pnoise( float x, int px )
+float Noise1234::pnoise( double x, int px )
 {
 {
     int ix0, ix1;
     int ix0, ix1;
-    float fx0, fx1;
-    float s, n0, n1;
+    double fx0, fx1;
+    double s, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
-    fx0 = x - ix0;       // Fractional part of x
-    fx1 = fx0 - 1.0f;
+    fx0 = x - ix0;        // Fractional part of x
+    fx1 = fx0 - 1.0;
     ix1 = (( ix0 + 1 ) % px) & 0xff; // Wrap to 0..px-1 *and* wrap to 0..255
     ix1 = (( ix0 + 1 ) % px) & 0xff; // Wrap to 0..px-1 *and* wrap to 0..255
-    ix0 = ( ix0 % px ) & 0xff;      // (because px might be greater than 256)
+    ix0 = ( ix0 % px ) & 0xff;       // (because px might be greater than 256)
 
 
     s = FADE( fx0 );
     s = FADE( fx0 );
 
 
@@ -183,23 +183,23 @@ float Noise1234::pnoise( float x, int px )
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 /** 2D float Perlin noise.
 /** 2D float Perlin noise.
  */
  */
-float Noise1234::noise( float x, float y )
+float Noise1234::noise( double x, double y )
 {
 {
     int ix0, iy0, ix1, iy1;
     int ix0, iy0, ix1, iy1;
-    float fx0, fy0, fx1, fy1;
-    float s, t, nx0, nx1, n0, n1;
+    double fx0, fy0, fx1, fy1;
+    double s, t, nx0, nx1, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
     iy0 = FASTFLOOR( y ); // Integer part of y
     iy0 = FASTFLOOR( y ); // Integer part of y
     fx0 = x - ix0;        // Fractional part of x
     fx0 = x - ix0;        // Fractional part of x
     fy0 = y - iy0;        // Fractional part of y
     fy0 = y - iy0;        // Fractional part of y
-    fx1 = fx0 - 1.0f;
-    fy1 = fy0 - 1.0f;
+    fx1 = fx0 - 1.0;
+    fy1 = fy0 - 1.0;
     ix1 = (ix0 + 1) & 0xff;  // Wrap to 0..255
     ix1 = (ix0 + 1) & 0xff;  // Wrap to 0..255
     iy1 = (iy0 + 1) & 0xff;
     iy1 = (iy0 + 1) & 0xff;
     ix0 = ix0 & 0xff;
     ix0 = ix0 & 0xff;
     iy0 = iy0 & 0xff;
     iy0 = iy0 & 0xff;
-    
+
     t = FADE( fy0 );
     t = FADE( fy0 );
     s = FADE( fx0 );
     s = FADE( fx0 );
 
 
@@ -217,23 +217,23 @@ float Noise1234::noise( float x, float y )
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 /** 2D float Perlin periodic noise.
 /** 2D float Perlin periodic noise.
  */
  */
-float Noise1234::pnoise( float x, float y, int px, int py )
+float Noise1234::pnoise( double x, double y, int px, int py )
 {
 {
     int ix0, iy0, ix1, iy1;
     int ix0, iy0, ix1, iy1;
-    float fx0, fy0, fx1, fy1;
-    float s, t, nx0, nx1, n0, n1;
+    double fx0, fy0, fx1, fy1;
+    double s, t, nx0, nx1, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
     iy0 = FASTFLOOR( y ); // Integer part of y
     iy0 = FASTFLOOR( y ); // Integer part of y
     fx0 = x - ix0;        // Fractional part of x
     fx0 = x - ix0;        // Fractional part of x
     fy0 = y - iy0;        // Fractional part of y
     fy0 = y - iy0;        // Fractional part of y
-    fx1 = fx0 - 1.0f;
-    fy1 = fy0 - 1.0f;
+    fx1 = fx0 - 1.0;
+    fy1 = fy0 - 1.0;
     ix1 = (( ix0 + 1 ) % px) & 0xff;  // Wrap to 0..px-1 and wrap to 0..255
     ix1 = (( ix0 + 1 ) % px) & 0xff;  // Wrap to 0..px-1 and wrap to 0..255
     iy1 = (( iy0 + 1 ) % py) & 0xff;  // Wrap to 0..py-1 and wrap to 0..255
     iy1 = (( iy0 + 1 ) % py) & 0xff;  // Wrap to 0..py-1 and wrap to 0..255
     ix0 = ( ix0 % px ) & 0xff;
     ix0 = ( ix0 % px ) & 0xff;
     iy0 = ( iy0 % py ) & 0xff;
     iy0 = ( iy0 % py ) & 0xff;
-    
+
     t = FADE( fy0 );
     t = FADE( fy0 );
     s = FADE( fx0 );
     s = FADE( fx0 );
 
 
@@ -252,12 +252,12 @@ float Noise1234::pnoise( float x, float y, int px, int py )
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 /** 3D float Perlin noise.
 /** 3D float Perlin noise.
  */
  */
-float Noise1234::noise( float x, float y, float z )
+float Noise1234::noise( double x, double y, double z )
 {
 {
     int ix0, iy0, ix1, iy1, iz0, iz1;
     int ix0, iy0, ix1, iy1, iz0, iz1;
-    float fx0, fy0, fz0, fx1, fy1, fz1;
-    float s, t, r;
-    float nxy0, nxy1, nx0, nx1, n0, n1;
+    double fx0, fy0, fz0, fx1, fy1, fz1;
+    double s, t, r;
+    double nxy0, nxy1, nx0, nx1, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
     iy0 = FASTFLOOR( y ); // Integer part of y
     iy0 = FASTFLOOR( y ); // Integer part of y
@@ -265,16 +265,16 @@ float Noise1234::noise( float x, float y, float z )
     fx0 = x - ix0;        // Fractional part of x
     fx0 = x - ix0;        // Fractional part of x
     fy0 = y - iy0;        // Fractional part of y
     fy0 = y - iy0;        // Fractional part of y
     fz0 = z - iz0;        // Fractional part of z
     fz0 = z - iz0;        // Fractional part of z
-    fx1 = fx0 - 1.0f;
-    fy1 = fy0 - 1.0f;
-    fz1 = fz0 - 1.0f;
+    fx1 = fx0 - 1.0;
+    fy1 = fy0 - 1.0;
+    fz1 = fz0 - 1.0;
     ix1 = ( ix0 + 1 ) & 0xff; // Wrap to 0..255
     ix1 = ( ix0 + 1 ) & 0xff; // Wrap to 0..255
     iy1 = ( iy0 + 1 ) & 0xff;
     iy1 = ( iy0 + 1 ) & 0xff;
     iz1 = ( iz0 + 1 ) & 0xff;
     iz1 = ( iz0 + 1 ) & 0xff;
     ix0 = ix0 & 0xff;
     ix0 = ix0 & 0xff;
     iy0 = iy0 & 0xff;
     iy0 = iy0 & 0xff;
     iz0 = iz0 & 0xff;
     iz0 = iz0 & 0xff;
-    
+
     r = FADE( fz0 );
     r = FADE( fz0 );
     t = FADE( fy0 );
     t = FADE( fy0 );
     s = FADE( fx0 );
     s = FADE( fx0 );
@@ -298,19 +298,19 @@ float Noise1234::noise( float x, float y, float z )
     nx1 = LERP( r, nxy0, nxy1 );
     nx1 = LERP( r, nxy0, nxy1 );
 
 
     n1 = LERP( t, nx0, nx1 );
     n1 = LERP( t, nx0, nx1 );
-    
+
     return 0.936f * ( LERP( s, n0, n1 ) );
     return 0.936f * ( LERP( s, n0, n1 ) );
 }
 }
 
 
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 /** 3D float Perlin periodic noise.
 /** 3D float Perlin periodic noise.
  */
  */
-float Noise1234::pnoise( float x, float y, float z, int px, int py, int pz )
+float Noise1234::pnoise( double x, double y, double z, int px, int py, int pz )
 {
 {
     int ix0, iy0, ix1, iy1, iz0, iz1;
     int ix0, iy0, ix1, iy1, iz0, iz1;
-    float fx0, fy0, fz0, fx1, fy1, fz1;
-    float s, t, r;
-    float nxy0, nxy1, nx0, nx1, n0, n1;
+    double fx0, fy0, fz0, fx1, fy1, fz1;
+    double s, t, r;
+    double nxy0, nxy1, nx0, nx1, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
     iy0 = FASTFLOOR( y ); // Integer part of y
     iy0 = FASTFLOOR( y ); // Integer part of y
@@ -318,16 +318,16 @@ float Noise1234::pnoise( float x, float y, float z, int px, int py, int pz )
     fx0 = x - ix0;        // Fractional part of x
     fx0 = x - ix0;        // Fractional part of x
     fy0 = y - iy0;        // Fractional part of y
     fy0 = y - iy0;        // Fractional part of y
     fz0 = z - iz0;        // Fractional part of z
     fz0 = z - iz0;        // Fractional part of z
-    fx1 = fx0 - 1.0f;
-    fy1 = fy0 - 1.0f;
-    fz1 = fz0 - 1.0f;
+    fx1 = fx0 - 1.0;
+    fy1 = fy0 - 1.0;
+    fz1 = fz0 - 1.0;
     ix1 = (( ix0 + 1 ) % px ) & 0xff; // Wrap to 0..px-1 and wrap to 0..255
     ix1 = (( ix0 + 1 ) % px ) & 0xff; // Wrap to 0..px-1 and wrap to 0..255
     iy1 = (( iy0 + 1 ) % py ) & 0xff; // Wrap to 0..py-1 and wrap to 0..255
     iy1 = (( iy0 + 1 ) % py ) & 0xff; // Wrap to 0..py-1 and wrap to 0..255
     iz1 = (( iz0 + 1 ) % pz ) & 0xff; // Wrap to 0..pz-1 and wrap to 0..255
     iz1 = (( iz0 + 1 ) % pz ) & 0xff; // Wrap to 0..pz-1 and wrap to 0..255
     ix0 = ( ix0 % px ) & 0xff;
     ix0 = ( ix0 % px ) & 0xff;
     iy0 = ( iy0 % py ) & 0xff;
     iy0 = ( iy0 % py ) & 0xff;
     iz0 = ( iz0 % pz ) & 0xff;
     iz0 = ( iz0 % pz ) & 0xff;
-    
+
     r = FADE( fz0 );
     r = FADE( fz0 );
     t = FADE( fy0 );
     t = FADE( fy0 );
     s = FADE( fx0 );
     s = FADE( fx0 );
@@ -351,7 +351,7 @@ float Noise1234::pnoise( float x, float y, float z, int px, int py, int pz )
     nx1 = LERP( r, nxy0, nxy1 );
     nx1 = LERP( r, nxy0, nxy1 );
 
 
     n1 = LERP( t, nx0, nx1 );
     n1 = LERP( t, nx0, nx1 );
-    
+
     return 0.936f * ( LERP( s, n0, n1 ) );
     return 0.936f * ( LERP( s, n0, n1 ) );
 }
 }
 
 
@@ -360,12 +360,12 @@ float Noise1234::pnoise( float x, float y, float z, int px, int py, int pz )
 /** 4D float Perlin noise.
 /** 4D float Perlin noise.
  */
  */
 
 
-float Noise1234::noise( float x, float y, float z, float w )
+float Noise1234::noise( double x, double y, double z, double w )
 {
 {
     int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1;
     int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1;
-    float fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1;
-    float s, t, r, q;
-    float nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1;
+    double fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1;
+    double s, t, r, q;
+    double nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
     iy0 = FASTFLOOR( y ); // Integer part of y
     iy0 = FASTFLOOR( y ); // Integer part of y
@@ -375,10 +375,10 @@ float Noise1234::noise( float x, float y, float z, float w )
     fy0 = y - iy0;        // Fractional part of y
     fy0 = y - iy0;        // Fractional part of y
     fz0 = z - iz0;        // Fractional part of z
     fz0 = z - iz0;        // Fractional part of z
     fw0 = w - iw0;        // Fractional part of w
     fw0 = w - iw0;        // Fractional part of w
-    fx1 = fx0 - 1.0f;
-    fy1 = fy0 - 1.0f;
-    fz1 = fz0 - 1.0f;
-    fw1 = fw0 - 1.0f;
+    fx1 = fx0 - 1.0;
+    fy1 = fy0 - 1.0;
+    fz1 = fz0 - 1.0;
+    fw1 = fw0 - 1.0;
     ix1 = ( ix0 + 1 ) & 0xff;  // Wrap to 0..255
     ix1 = ( ix0 + 1 ) & 0xff;  // Wrap to 0..255
     iy1 = ( iy0 + 1 ) & 0xff;
     iy1 = ( iy0 + 1 ) & 0xff;
     iz1 = ( iz0 + 1 ) & 0xff;
     iz1 = ( iz0 + 1 ) & 0xff;
@@ -396,17 +396,17 @@ float Noise1234::noise( float x, float y, float z, float w )
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );
-        
+
     nx0 = LERP ( r, nxy0, nxy1 );
     nx0 = LERP ( r, nxy0, nxy1 );
 
 
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );
@@ -418,7 +418,7 @@ float Noise1234::noise( float x, float y, float z, float w )
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );
@@ -428,7 +428,7 @@ float Noise1234::noise( float x, float y, float z, float w )
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );
@@ -444,13 +444,13 @@ float Noise1234::noise( float x, float y, float z, float w )
 /** 4D float Perlin periodic noise.
 /** 4D float Perlin periodic noise.
  */
  */
 
 
-float Noise1234::pnoise( float x, float y, float z, float w,
+float Noise1234::pnoise( double x, double y, double z, double w,
                             int px, int py, int pz, int pw )
                             int px, int py, int pz, int pw )
 {
 {
     int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1;
     int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1;
-    float fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1;
-    float s, t, r, q;
-    float nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1;
+    double fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1;
+    double s, t, r, q;
+    double nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1;
 
 
     ix0 = FASTFLOOR( x ); // Integer part of x
     ix0 = FASTFLOOR( x ); // Integer part of x
     iy0 = FASTFLOOR( y ); // Integer part of y
     iy0 = FASTFLOOR( y ); // Integer part of y
@@ -460,10 +460,10 @@ float Noise1234::pnoise( float x, float y, float z, float w,
     fy0 = y - iy0;        // Fractional part of y
     fy0 = y - iy0;        // Fractional part of y
     fz0 = z - iz0;        // Fractional part of z
     fz0 = z - iz0;        // Fractional part of z
     fw0 = w - iw0;        // Fractional part of w
     fw0 = w - iw0;        // Fractional part of w
-    fx1 = fx0 - 1.0f;
-    fy1 = fy0 - 1.0f;
-    fz1 = fz0 - 1.0f;
-    fw1 = fw0 - 1.0f;
+    fx1 = fx0 - 1.0;
+    fy1 = fy0 - 1.0;
+    fz1 = fz0 - 1.0;
+    fw1 = fw0 - 1.0;
     ix1 = (( ix0 + 1 ) % px ) & 0xff;  // Wrap to 0..px-1 and wrap to 0..255
     ix1 = (( ix0 + 1 ) % px ) & 0xff;  // Wrap to 0..px-1 and wrap to 0..255
     iy1 = (( iy0 + 1 ) % py ) & 0xff;  // Wrap to 0..py-1 and wrap to 0..255
     iy1 = (( iy0 + 1 ) % py ) & 0xff;  // Wrap to 0..py-1 and wrap to 0..255
     iz1 = (( iz0 + 1 ) % pz ) & 0xff;  // Wrap to 0..pz-1 and wrap to 0..255
     iz1 = (( iz0 + 1 ) % pz ) & 0xff;  // Wrap to 0..pz-1 and wrap to 0..255
@@ -481,17 +481,17 @@ float Noise1234::pnoise( float x, float y, float z, float w,
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );
-        
+
     nx0 = LERP ( r, nxy0, nxy1 );
     nx0 = LERP ( r, nxy0, nxy1 );
 
 
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0);
     nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1);
     nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );
@@ -503,7 +503,7 @@ float Noise1234::pnoise( float x, float y, float z, float w,
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );
@@ -513,7 +513,7 @@ float Noise1234::pnoise( float x, float y, float z, float w,
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1);
     nxy0 = LERP( q, nxyz0, nxyz1 );
     nxy0 = LERP( q, nxyz0, nxyz1 );
-        
+
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0);
     nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1);
     nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1);
     nxy1 = LERP( q, nxyz0, nxyz1 );
     nxy1 = LERP( q, nxyz0, nxyz1 );

+ 12 - 16
src/libraries/noise1234/noise1234.h

@@ -20,10 +20,6 @@
  * This is a clean, fast, modern and free Perlin noise class in C++.
  * This is a clean, fast, modern and free Perlin noise class in C++.
  * Being a stand-alone class with no external dependencies, it is
  * Being a stand-alone class with no external dependencies, it is
  * highly reusable without source code modifications.
  * highly reusable without source code modifications.
- *
- * Note:
- * Replacing the "float" type with "double" can actually make this run faster
- * on some platforms. A templatized version of Noise1234 could be useful.
  */
  */
 
 
 class Noise1234 {
 class Noise1234 {
@@ -34,24 +30,24 @@ class Noise1234 {
 
 
 /** 1D, 2D, 3D and 4D float Perlin noise, SL "noise()"
 /** 1D, 2D, 3D and 4D float Perlin noise, SL "noise()"
  */
  */
-    static float noise( float x );
-    static float noise( float x, float y );
-    static float noise( float x, float y, float z );
-    static float noise( float x, float y, float z, float w );
+    static float noise( double x );
+    static float noise( double x, double y );
+    static float noise( double x, double y, double z );
+    static float noise( double x, double y, double z, double w );
 
 
 /** 1D, 2D, 3D and 4D float Perlin periodic noise, SL "pnoise()"
 /** 1D, 2D, 3D and 4D float Perlin periodic noise, SL "pnoise()"
  */
  */
-    static float pnoise( float x, int px );
-    static float pnoise( float x, float y, int px, int py );
-    static float pnoise( float x, float y, float z, int px, int py, int pz );
-    static float pnoise( float x, float y, float z, float w,
+    static float pnoise( double x, int px );
+    static float pnoise( double x, double y, int px, int py );
+    static float pnoise( double x, double y, double z, int px, int py, int pz );
+    static float pnoise( double x, double y, double z, double w,
                               int px, int py, int pz, int pw );
                               int px, int py, int pz, int pw );
 
 
   private:
   private:
     static unsigned char perm[];
     static unsigned char perm[];
-    static float  grad( int hash, float x );
-    static float  grad( int hash, float x, float y );
-    static float  grad( int hash, float x, float y , float z );
-    static float  grad( int hash, float x, float y, float z, float t );
+    static double  grad( int hash, double x );
+    static double  grad( int hash, double x, double y );
+    static double  grad( int hash, double x, double y , double z );
+    static double  grad( int hash, double x, double y, double z, double t );
 
 
 };
 };

+ 34 - 36
src/libraries/noise1234/simplexnoise1234.cpp

@@ -85,7 +85,7 @@ unsigned char SimplexNoise1234::perm[512] = {151,160,137,91,90,15,
   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
-  138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 
+  138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
 };
 };
 
 
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
@@ -103,37 +103,35 @@ unsigned char SimplexNoise1234::perm[512] = {151,160,137,91,90,15,
  * float SLnoise = (SimplexNoise1234::noise(x,y,z) + 1.0) * 0.5;
  * float SLnoise = (SimplexNoise1234::noise(x,y,z) + 1.0) * 0.5;
  */
  */
 
 
-float  SimplexNoise1234::grad( int hash, float x ) {
+double  SimplexNoise1234::grad( int hash, double x ) {
     int h = hash & 15;
     int h = hash & 15;
-    float grad = 1.0f + (h & 7);   // Gradient value 1.0, 2.0, ..., 8.0
+    double grad = 1.0 + (h & 7);   // Gradient value 1.0, 2.0, ..., 8.0
     if (h&8) grad = -grad;         // Set a random sign for the gradient
     if (h&8) grad = -grad;         // Set a random sign for the gradient
     return ( grad * x );           // Multiply the gradient with the distance
     return ( grad * x );           // Multiply the gradient with the distance
 }
 }
 
 
-float  SimplexNoise1234::grad( int hash, float x, float y ) {
+double  SimplexNoise1234::grad( int hash, double x, double y ) {
     int h = hash & 7;      // Convert low 3 bits of hash code
     int h = hash & 7;      // Convert low 3 bits of hash code
-    float u = h<4 ? x : y;  // into 8 simple gradient directions,
-    float v = h<4 ? y : x;  // and compute the dot product with (x,y).
-    return ((h&1)? -u : u) + ((h&2)? -2.0f*v : 2.0f*v);
+    double u = h<4 ? x : y;  // into 8 simple gradient directions,
+    double v = h<4 ? y : x;  // and compute the dot product with (x,y).
+    return ((h&1)? -u : u) + ((h&2)? -2.0*v : 2.0*v);
 }
 }
 
 
 // 1D simplex noise
 // 1D simplex noise
-float SimplexNoise1234::noise(float x) {
+float SimplexNoise1234::noise(double x) {
 
 
   int i0 = FASTFLOOR(x);
   int i0 = FASTFLOOR(x);
   int i1 = i0 + 1;
   int i1 = i0 + 1;
-  float x0 = x - i0;
-  float x1 = x0 - 1.0f;
+  double x0 = x - i0;
+  double x1 = x0 - 1.0;
 
 
-  float n0, n1;
+  double n0, n1;
 
 
-  float t0 = 1.0f - x0*x0;
-//  if(t0 < 0.0f) t0 = 0.0f;
+  double t0 = 1.0 - x0*x0;
   t0 *= t0;
   t0 *= t0;
   n0 = t0 * t0 * grad(perm[i0 & 0xff], x0);
   n0 = t0 * t0 * grad(perm[i0 & 0xff], x0);
 
 
-  float t1 = 1.0f - x1*x1;
-//  if(t1 < 0.0f) t1 = 0.0f;
+  double t1 = 1.0 - x1*x1;
   t1 *= t1;
   t1 *= t1;
   n1 = t1 * t1 * grad(perm[i1 & 0xff], x1);
   n1 = t1 * t1 * grad(perm[i1 & 0xff], x1);
   // The maximum value of this noise is 8*(3/4)^4 = 2.53125
   // The maximum value of this noise is 8*(3/4)^4 = 2.53125
@@ -143,25 +141,25 @@ float SimplexNoise1234::noise(float x) {
 }
 }
 
 
 // 2D simplex noise
 // 2D simplex noise
-float SimplexNoise1234::noise(float x, float y) {
+float SimplexNoise1234::noise(double x, double y) {
 
 
 #define F2 0.366025403 // F2 = 0.5*(sqrt(3.0)-1.0)
 #define F2 0.366025403 // F2 = 0.5*(sqrt(3.0)-1.0)
 #define G2 0.211324865 // G2 = (3.0-Math.sqrt(3.0))/6.0
 #define G2 0.211324865 // G2 = (3.0-Math.sqrt(3.0))/6.0
 
 
-    float n0, n1, n2; // Noise contributions from the three corners
+    double n0, n1, n2; // Noise contributions from the three corners
 
 
     // Skew the input space to determine which simplex cell we're in
     // Skew the input space to determine which simplex cell we're in
-    float s = (x+y)*F2; // Hairy factor for 2D
-    float xs = x + s;
-    float ys = y + s;
+    double s = (x+y)*F2; // Hairy factor for 2D
+    double xs = x + s;
+    double ys = y + s;
     int i = FASTFLOOR(xs);
     int i = FASTFLOOR(xs);
     int j = FASTFLOOR(ys);
     int j = FASTFLOOR(ys);
 
 
-    float t = (float)(i+j)*G2;
-    float X0 = i-t; // Unskew the cell origin back to (x,y) space
-    float Y0 = j-t;
-    float x0 = x-X0; // The x,y distances from the cell origin
-    float y0 = y-Y0;
+    double t = (i+j)*G2;
+    double X0 = i-t; // Unskew the cell origin back to (x,y) space
+    double Y0 = j-t;
+    double x0 = x-X0; // The x,y distances from the cell origin
+    double y0 = y-Y0;
 
 
     // For the 2D case, the simplex shape is an equilateral triangle.
     // For the 2D case, the simplex shape is an equilateral triangle.
     // Determine which simplex we are in.
     // Determine which simplex we are in.
@@ -173,32 +171,32 @@ float SimplexNoise1234::noise(float x, float y) {
     // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
     // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
     // c = (3-sqrt(3))/6
     // c = (3-sqrt(3))/6
 
 
-    float x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
-    float y1 = y0 - j1 + G2;
-    float x2 = x0 - 1.0f + 2.0f * G2; // Offsets for last corner in (x,y) unskewed coords
-    float y2 = y0 - 1.0f + 2.0f * G2;
+    double x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
+    double y1 = y0 - j1 + G2;
+    double x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
+    double y2 = y0 - 1.0 + 2.0 * G2;
 
 
     // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds
     // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds
     int ii = i & 0xff;
     int ii = i & 0xff;
     int jj = j & 0xff;
     int jj = j & 0xff;
 
 
     // Calculate the contribution from the three corners
     // Calculate the contribution from the three corners
-    float t0 = 0.5f - x0*x0-y0*y0;
-    if(t0 < 0.0f) n0 = 0.0f;
+    double t0 = 0.5 - x0*x0-y0*y0;
+    if(t0 < 0.0) n0 = 0.0;
     else {
     else {
       t0 *= t0;
       t0 *= t0;
-      n0 = t0 * t0 * grad(perm[ii+perm[jj]], x0, y0); 
+      n0 = t0 * t0 * grad(perm[ii+perm[jj]], x0, y0);
     }
     }
 
 
-    float t1 = 0.5f - x1*x1-y1*y1;
-    if(t1 < 0.0f) n1 = 0.0f;
+    double t1 = 0.5 - x1*x1-y1*y1;
+    if(t1 < 0.0) n1 = 0.0;
     else {
     else {
       t1 *= t1;
       t1 *= t1;
       n1 = t1 * t1 * grad(perm[ii+i1+perm[jj+j1]], x1, y1);
       n1 = t1 * t1 * grad(perm[ii+i1+perm[jj+j1]], x1, y1);
     }
     }
 
 
-    float t2 = 0.5f - x2*x2-y2*y2;
-    if(t2 < 0.0f) n2 = 0.0f;
+    double t2 = 0.5 - x2*x2-y2*y2;
+    if(t2 < 0.0) n2 = 0.0;
     else {
     else {
       t2 *= t2;
       t2 *= t2;
       n2 = t2 * t2 * grad(perm[ii+1+perm[jj+1]], x2, y2);
       n2 = t2 * t2 * grad(perm[ii+1+perm[jj+1]], x2, y2);

+ 4 - 9
src/libraries/noise1234/simplexnoise1234.h

@@ -25,11 +25,6 @@
  * This is a clean, fast, modern and free Perlin Simplex noise class in C++.
  * This is a clean, fast, modern and free Perlin Simplex noise class in C++.
  * Being a stand-alone class with no external dependencies, it is
  * Being a stand-alone class with no external dependencies, it is
  * highly reusable without source code modifications.
  * highly reusable without source code modifications.
- *
- *
- * Note:
- * Replacing the "float" type with "double" can actually make this run faster
- * on some platforms. A templatized version of SimplexNoise1234 could be useful.
  */
  */
 
 
 class SimplexNoise1234 {
 class SimplexNoise1234 {
@@ -40,12 +35,12 @@ class SimplexNoise1234 {
 
 
 /** 1D and 2D float Perlin noise
 /** 1D and 2D float Perlin noise
  */
  */
-    static float noise( float x );
-    static float noise( float x, float y );
+    static float noise( double x );
+    static float noise( double x, double y );
 
 
   private:
   private:
     static unsigned char perm[];
     static unsigned char perm[];
-    static float  grad( int hash, float x );
-    static float  grad( int hash, float x, float y );
+    static double  grad( int hash, double x );
+    static double  grad( int hash, double x, double y );
 
 
 };
 };

+ 208 - 73
src/libraries/stb/stb_image.h

@@ -1,4 +1,4 @@
-/* stb_image - v2.26 - public domain image loader - http://nothings.org/stb
+/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb
                                   no warranty implied; use at your own risk
                                   no warranty implied; use at your own risk
 
 
    Do this:
    Do this:
@@ -48,6 +48,7 @@ LICENSE
 
 
 RECENT REVISION HISTORY:
 RECENT REVISION HISTORY:
 
 
+      2.27  (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
       2.26  (2020-07-13) many minor fixes
       2.26  (2020-07-13) many minor fixes
       2.25  (2020-02-02) fix warnings
       2.25  (2020-02-02) fix warnings
       2.24  (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
       2.24  (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
@@ -89,7 +90,7 @@ RECENT REVISION HISTORY:
                                            Jeremy Sawicki (handle all ImageNet JPGs)
                                            Jeremy Sawicki (handle all ImageNet JPGs)
  Optimizations & bugfixes                  Mikhail Morozov (1-bit BMP)
  Optimizations & bugfixes                  Mikhail Morozov (1-bit BMP)
     Fabian "ryg" Giesen                    Anael Seghezzi (is-16-bit query)
     Fabian "ryg" Giesen                    Anael Seghezzi (is-16-bit query)
-    Arseny Kapoulkine
+    Arseny Kapoulkine                      Simon Breuss (16-bit PNM)
     John-Mark Allen
     John-Mark Allen
     Carmelo J Fdez-Aguera
     Carmelo J Fdez-Aguera
 
 
@@ -102,7 +103,7 @@ RECENT REVISION HISTORY:
     Thomas Ruf              Ronny Chevalier                         github:rlyeh
     Thomas Ruf              Ronny Chevalier                         github:rlyeh
     Janez Zemva             John Bartholomew   Michal Cichon        github:romigrou
     Janez Zemva             John Bartholomew   Michal Cichon        github:romigrou
     Jonathan Blow           Ken Hamada         Tero Hanninen        github:svdijk
     Jonathan Blow           Ken Hamada         Tero Hanninen        github:svdijk
-                            Laurent Gomila     Cort Stratton        github:snagar
+    Eugene Golushkov        Laurent Gomila     Cort Stratton        github:snagar
     Aruelien Pocheville     Sergio Gonzalez    Thibault Reuille     github:Zelex
     Aruelien Pocheville     Sergio Gonzalez    Thibault Reuille     github:Zelex
     Cass Everitt            Ryamond Barbiero                        github:grim210
     Cass Everitt            Ryamond Barbiero                        github:grim210
     Paul Du Bois            Engin Manap        Aldo Culquicondor    github:sammyhw
     Paul Du Bois            Engin Manap        Aldo Culquicondor    github:sammyhw
@@ -110,11 +111,13 @@ RECENT REVISION HISTORY:
     Josh Tobin                                 Matthew Gregan       github:poppolopoppo
     Josh Tobin                                 Matthew Gregan       github:poppolopoppo
     Julian Raschke          Gregory Mullen     Christian Floisand   github:darealshinji
     Julian Raschke          Gregory Mullen     Christian Floisand   github:darealshinji
     Baldur Karlsson         Kevin Schmidt      JR Smith             github:Michaelangel007
     Baldur Karlsson         Kevin Schmidt      JR Smith             github:Michaelangel007
-                            Brad Weinberger    Matvey Cherevko      [reserved]
+                            Brad Weinberger    Matvey Cherevko      github:mosra
     Luca Sas                Alexander Veselov  Zack Middleton       [reserved]
     Luca Sas                Alexander Veselov  Zack Middleton       [reserved]
     Ryan C. Gordon          [reserved]                              [reserved]
     Ryan C. Gordon          [reserved]                              [reserved]
                      DO NOT ADD YOUR NAME HERE
                      DO NOT ADD YOUR NAME HERE
 
 
+                     Jacko Dirks
+
   To add your name to the credits, pick a random blank space in the middle and fill it.
   To add your name to the credits, pick a random blank space in the middle and fill it.
   80% of merge conflicts on stb PRs are due to people adding their name at the end
   80% of merge conflicts on stb PRs are due to people adding their name at the end
   of the credits.
   of the credits.
@@ -176,6 +179,32 @@ RECENT REVISION HISTORY:
 //
 //
 // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
 // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
 //
 //
+// To query the width, height and component count of an image without having to
+// decode the full file, you can use the stbi_info family of functions:
+//
+//   int x,y,n,ok;
+//   ok = stbi_info(filename, &x, &y, &n);
+//   // returns ok=1 and sets x, y, n if image is a supported format,
+//   // 0 otherwise.
+//
+// Note that stb_image pervasively uses ints in its public API for sizes,
+// including sizes of memory buffers. This is now part of the API and thus
+// hard to change without causing breakage. As a result, the various image
+// loaders all have certain limits on image size; these differ somewhat
+// by format but generally boil down to either just under 2GB or just under
+// 1GB. When the decoded image would be larger than this, stb_image decoding
+// will fail.
+//
+// Additionally, stb_image will reject image files that have any of their
+// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS,
+// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit,
+// the only way to have an image with such dimensions load correctly
+// is for it to have a rather extreme aspect ratio. Either way, the
+// assumption here is that such larger images are likely to be malformed
+// or malicious. If you do need to load an image with individual dimensions
+// larger than that, and it still fits in the overall size limit, you can
+// #define STBI_MAX_DIMENSIONS on your own to be something larger.
+//
 // ===========================================================================
 // ===========================================================================
 //
 //
 // UNICODE:
 // UNICODE:
@@ -281,11 +310,10 @@ RECENT REVISION HISTORY:
 //
 //
 // iPhone PNG support:
 // iPhone PNG support:
 //
 //
-// By default we convert iphone-formatted PNGs back to RGB, even though
-// they are internally encoded differently. You can disable this conversion
-// by calling stbi_convert_iphone_png_to_rgb(0), in which case
-// you will always just get the native iphone "format" through (which
-// is BGR stored in RGB).
+// We optionally support converting iPhone-formatted PNGs (which store
+// premultiplied BGRA) back to RGB, even though they're internally encoded
+// differently. To enable this conversion, call
+// stbi_convert_iphone_png_to_rgb(1).
 //
 //
 // Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
 // Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
 // pixel to remove any premultiplied alpha *only* if the image file explicitly
 // pixel to remove any premultiplied alpha *only* if the image file explicitly
@@ -489,6 +517,8 @@ STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
 // as above, but only applies to images loaded on the thread that calls the function
 // as above, but only applies to images loaded on the thread that calls the function
 // this function is only available if your compiler supports thread-local variables;
 // this function is only available if your compiler supports thread-local variables;
 // calling it will fail to link if your compiler doesn't
 // calling it will fail to link if your compiler doesn't
+STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply);
+STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert);
 STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
 STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
 
 
 // ZLIB client - used by PNG, available for other purposes
 // ZLIB client - used by PNG, available for other purposes
@@ -634,7 +664,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
 #ifdef STBI_HAS_LROTL
 #ifdef STBI_HAS_LROTL
    #define stbi_lrot(x,y)  _lrotl(x,y)
    #define stbi_lrot(x,y)  _lrotl(x,y)
 #else
 #else
-   #define stbi_lrot(x,y)  (((x) << (y)) | ((x) >> (32 - (y))))
+   #define stbi_lrot(x,y)  (((x) << (y)) | ((x) >> (-(y) & 31)))
 #endif
 #endif
 
 
 #if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
 #if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
@@ -748,9 +778,12 @@ static int stbi__sse2_available(void)
 
 
 #ifdef STBI_NEON
 #ifdef STBI_NEON
 #include <arm_neon.h>
 #include <arm_neon.h>
-// assume GCC or Clang on ARM targets
+#ifdef _MSC_VER
+#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
+#else
 #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
 #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
 #endif
 #endif
+#endif
 
 
 #ifndef STBI_SIMD_ALIGN
 #ifndef STBI_SIMD_ALIGN
 #define STBI_SIMD_ALIGN(type, name) type name
 #define STBI_SIMD_ALIGN(type, name) type name
@@ -924,6 +957,7 @@ static int      stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
 static int      stbi__pnm_test(stbi__context *s);
 static int      stbi__pnm_test(stbi__context *s);
 static void    *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
 static void    *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
 static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
 static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
+static int      stbi__pnm_is16(stbi__context *s);
 #endif
 #endif
 
 
 static
 static
@@ -998,7 +1032,7 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add)
 }
 }
 
 
 // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
 // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
-#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM)
 static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
 static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
 {
 {
    return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
    return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
@@ -1021,7 +1055,7 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add)
    return stbi__malloc(a*b*c + add);
    return stbi__malloc(a*b*c + add);
 }
 }
 
 
-#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM)
 static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
 static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
 {
 {
    if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
    if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
@@ -1087,9 +1121,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
    ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
    ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
    ri->num_channels = 0;
    ri->num_channels = 0;
 
 
-   #ifndef STBI_NO_JPEG
-   if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
-   #endif
+   // test the formats with a very explicit header first (at least a FOURCC
+   // or distinctive magic number first)
    #ifndef STBI_NO_PNG
    #ifndef STBI_NO_PNG
    if (stbi__png_test(s))  return stbi__png_load(s,x,y,comp,req_comp, ri);
    if (stbi__png_test(s))  return stbi__png_load(s,x,y,comp,req_comp, ri);
    #endif
    #endif
@@ -1107,6 +1140,13 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
    #ifndef STBI_NO_PIC
    #ifndef STBI_NO_PIC
    if (stbi__pic_test(s))  return stbi__pic_load(s,x,y,comp,req_comp, ri);
    if (stbi__pic_test(s))  return stbi__pic_load(s,x,y,comp,req_comp, ri);
    #endif
    #endif
+
+   // then the formats that can end up attempting to load with just 1 or 2
+   // bytes matching expectations; these are prone to false positives, so
+   // try them later
+   #ifndef STBI_NO_JPEG
+   if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
+   #endif
    #ifndef STBI_NO_PNM
    #ifndef STBI_NO_PNM
    if (stbi__pnm_test(s))  return stbi__pnm_load(s,x,y,comp,req_comp, ri);
    if (stbi__pnm_test(s))  return stbi__pnm_load(s,x,y,comp,req_comp, ri);
    #endif
    #endif
@@ -1262,12 +1302,12 @@ static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, in
 
 
 #ifndef STBI_NO_STDIO
 #ifndef STBI_NO_STDIO
 
 
-#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
+#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
 STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
 STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
 STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
 STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
 #endif
 #endif
 
 
-#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
+#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
 STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
 STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
 {
 {
 	return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
 	return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
@@ -1277,16 +1317,16 @@ STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wch
 static FILE *stbi__fopen(char const *filename, char const *mode)
 static FILE *stbi__fopen(char const *filename, char const *mode)
 {
 {
    FILE *f;
    FILE *f;
-#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
+#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
    wchar_t wMode[64];
    wchar_t wMode[64];
    wchar_t wFilename[1024];
    wchar_t wFilename[1024];
-	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
+	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
       return 0;
       return 0;
 
 
-	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
+	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
       return 0;
       return 0;
 
 
-#if _MSC_VER >= 1400
+#if defined(_MSC_VER) && _MSC_VER >= 1400
 	if (0 != _wfopen_s(&f, wFilename, wMode))
 	if (0 != _wfopen_s(&f, wFilename, wMode))
 		f = 0;
 		f = 0;
 #else
 #else
@@ -1662,7 +1702,8 @@ static int stbi__get16le(stbi__context *s)
 static stbi__uint32 stbi__get32le(stbi__context *s)
 static stbi__uint32 stbi__get32le(stbi__context *s)
 {
 {
    stbi__uint32 z = stbi__get16le(s);
    stbi__uint32 z = stbi__get16le(s);
-   return z + (stbi__get16le(s) << 16);
+   z += (stbi__uint32)stbi__get16le(s) << 16;
+   return z;
 }
 }
 #endif
 #endif
 
 
@@ -2090,13 +2131,12 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
    int sgn;
    int sgn;
    if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
    if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
 
 
-   sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
+   sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
    k = stbi_lrot(j->code_buffer, n);
    k = stbi_lrot(j->code_buffer, n);
-   if (n < 0 || n >= (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))) return 0;
    j->code_buffer = k & ~stbi__bmask[n];
    j->code_buffer = k & ~stbi__bmask[n];
    k &= stbi__bmask[n];
    k &= stbi__bmask[n];
    j->code_bits -= n;
    j->code_bits -= n;
-   return k + (stbi__jbias[n] & ~sgn);
+   return k + (stbi__jbias[n] & (sgn - 1));
 }
 }
 
 
 // get some unsigned bits
 // get some unsigned bits
@@ -2146,7 +2186,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
 
 
    if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
    if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
    t = stbi__jpeg_huff_decode(j, hdc);
    t = stbi__jpeg_huff_decode(j, hdc);
-   if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG");
+   if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG");
 
 
    // 0 all the ac values now so we can do it 32-bits at a time
    // 0 all the ac values now so we can do it 32-bits at a time
    memset(data,0,64*sizeof(data[0]));
    memset(data,0,64*sizeof(data[0]));
@@ -2203,12 +2243,12 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
       // first scan for DC coefficient, must be first
       // first scan for DC coefficient, must be first
       memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
       memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
       t = stbi__jpeg_huff_decode(j, hdc);
       t = stbi__jpeg_huff_decode(j, hdc);
-      if (t == -1) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
+      if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
       diff = t ? stbi__extend_receive(j, t) : 0;
       diff = t ? stbi__extend_receive(j, t) : 0;
 
 
       dc = j->img_comp[b].dc_pred + diff;
       dc = j->img_comp[b].dc_pred + diff;
       j->img_comp[b].dc_pred = dc;
       j->img_comp[b].dc_pred = dc;
-      data[0] = (short) (dc << j->succ_low);
+      data[0] = (short) (dc * (1 << j->succ_low));
    } else {
    } else {
       // refinement scan for DC coefficient
       // refinement scan for DC coefficient
       if (stbi__jpeg_get_bit(j))
       if (stbi__jpeg_get_bit(j))
@@ -2245,7 +2285,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
             j->code_buffer <<= s;
             j->code_buffer <<= s;
             j->code_bits -= s;
             j->code_bits -= s;
             zig = stbi__jpeg_dezigzag[k++];
             zig = stbi__jpeg_dezigzag[k++];
-            data[zig] = (short) ((r >> 8) << shift);
+            data[zig] = (short) ((r >> 8) * (1 << shift));
          } else {
          } else {
             int rs = stbi__jpeg_huff_decode(j, hac);
             int rs = stbi__jpeg_huff_decode(j, hac);
             if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
             if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
@@ -2263,7 +2303,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
             } else {
             } else {
                k += r;
                k += r;
                zig = stbi__jpeg_dezigzag[k++];
                zig = stbi__jpeg_dezigzag[k++];
-               data[zig] = (short) (stbi__extend_receive(j,s) << shift);
+               data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift));
             }
             }
          }
          }
       } while (k <= j->spec_end);
       } while (k <= j->spec_end);
@@ -3227,6 +3267,13 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
       if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
       if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
    }
    }
 
 
+   // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios
+   // and I've never seen a non-corrupted JPEG file actually use them
+   for (i=0; i < s->img_n; ++i) {
+      if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG");
+      if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG");
+   }
+
    // compute interleaved mcu info
    // compute interleaved mcu info
    z->img_h_max = h_max;
    z->img_h_max = h_max;
    z->img_v_max = v_max;
    z->img_v_max = v_max;
@@ -3782,6 +3829,10 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
    else
    else
       decode_n = z->s->img_n;
       decode_n = z->s->img_n;
 
 
+   // nothing to do if no components requested; check this now to avoid
+   // accessing uninitialized coutput[0] later
+   if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; }
+
    // resample and color-convert
    // resample and color-convert
    {
    {
       int k;
       int k;
@@ -3924,6 +3975,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re
 {
 {
    unsigned char* result;
    unsigned char* result;
    stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
    stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
+   if (!j) return stbi__errpuc("outofmem", "Out of memory");
    STBI_NOTUSED(ri);
    STBI_NOTUSED(ri);
    j->s = s;
    j->s = s;
    stbi__setup_jpeg(j);
    stbi__setup_jpeg(j);
@@ -3936,6 +3988,7 @@ static int stbi__jpeg_test(stbi__context *s)
 {
 {
    int r;
    int r;
    stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
    stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
+   if (!j) return stbi__err("outofmem", "Out of memory");
    j->s = s;
    j->s = s;
    stbi__setup_jpeg(j);
    stbi__setup_jpeg(j);
    r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
    r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
@@ -3960,6 +4013,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
 {
 {
    int result;
    int result;
    stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
    stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
+   if (!j) return stbi__err("outofmem", "Out of memory");
    j->s = s;
    j->s = s;
    result = stbi__jpeg_info_raw(j, x, y, comp);
    result = stbi__jpeg_info_raw(j, x, y, comp);
    STBI_FREE(j);
    STBI_FREE(j);
@@ -3979,6 +4033,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
 // fast-way is faster to check than jpeg huffman, but slow way is slower
 // fast-way is faster to check than jpeg huffman, but slow way is slower
 #define STBI__ZFAST_BITS  9 // accelerate all cases in default tables
 #define STBI__ZFAST_BITS  9 // accelerate all cases in default tables
 #define STBI__ZFAST_MASK  ((1 << STBI__ZFAST_BITS) - 1)
 #define STBI__ZFAST_MASK  ((1 << STBI__ZFAST_BITS) - 1)
+#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet
 
 
 // zlib-style huffman encoding
 // zlib-style huffman encoding
 // (jpegs packs from left, zlib from right, so can't share code)
 // (jpegs packs from left, zlib from right, so can't share code)
@@ -3988,8 +4043,8 @@ typedef struct
    stbi__uint16 firstcode[16];
    stbi__uint16 firstcode[16];
    int maxcode[17];
    int maxcode[17];
    stbi__uint16 firstsymbol[16];
    stbi__uint16 firstsymbol[16];
-   stbi_uc  size[288];
-   stbi__uint16 value[288];
+   stbi_uc  size[STBI__ZNSYMS];
+   stbi__uint16 value[STBI__ZNSYMS];
 } stbi__zhuffman;
 } stbi__zhuffman;
 
 
 stbi_inline static int stbi__bitreverse16(int n)
 stbi_inline static int stbi__bitreverse16(int n)
@@ -4120,7 +4175,7 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
    if (s >= 16) return -1; // invalid code!
    if (s >= 16) return -1; // invalid code!
    // code size is s, so:
    // code size is s, so:
    b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
    b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
-   if (b >= sizeof (z->size)) return -1; // some data was corrupt somewhere!
+   if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere!
    if (z->size[b] != s) return -1;  // was originally an assert, but report failure instead.
    if (z->size[b] != s) return -1;  // was originally an assert, but report failure instead.
    a->code_buffer >>= s;
    a->code_buffer >>= s;
    a->num_bits -= s;
    a->num_bits -= s;
@@ -4317,7 +4372,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a)
    return 1;
    return 1;
 }
 }
 
 
-static const stbi_uc stbi__zdefault_length[288] =
+static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] =
 {
 {
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
@@ -4363,7 +4418,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
       } else {
       } else {
          if (type == 1) {
          if (type == 1) {
             // use fixed code lengths
             // use fixed code lengths
-            if (!stbi__zbuild_huffman(&a->z_length  , stbi__zdefault_length  , 288)) return 0;
+            if (!stbi__zbuild_huffman(&a->z_length  , stbi__zdefault_length  , STBI__ZNSYMS)) return 0;
             if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance,  32)) return 0;
             if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance,  32)) return 0;
          } else {
          } else {
             if (!stbi__compute_huffman_codes(a)) return 0;
             if (!stbi__compute_huffman_codes(a)) return 0;
@@ -4759,6 +4814,7 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3
 
 
    // de-interlacing
    // de-interlacing
    final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
    final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
+   if (!final) return stbi__err("outofmem", "Out of memory");
    for (p=0; p < 7; ++p) {
    for (p=0; p < 7; ++p) {
       int xorig[] = { 0,4,0,2,0,1,0 };
       int xorig[] = { 0,4,0,2,0,1,0 };
       int yorig[] = { 0,0,4,0,2,0,1 };
       int yorig[] = { 0,0,4,0,2,0,1 };
@@ -4879,19 +4935,46 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
    return 1;
    return 1;
 }
 }
 
 
-static int stbi__unpremultiply_on_load = 0;
-static int stbi__de_iphone_flag = 0;
+static int stbi__unpremultiply_on_load_global = 0;
+static int stbi__de_iphone_flag_global = 0;
 
 
 STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
 STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
 {
 {
-   stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply;
+   stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply;
 }
 }
 
 
 STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
 STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
 {
 {
-   stbi__de_iphone_flag = flag_true_if_should_convert;
+   stbi__de_iphone_flag_global = flag_true_if_should_convert;
+}
+
+#ifndef STBI_THREAD_LOCAL
+#define stbi__unpremultiply_on_load  stbi__unpremultiply_on_load_global
+#define stbi__de_iphone_flag  stbi__de_iphone_flag_global
+#else
+static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;
+static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;
+
+STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
+{
+   stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
+   stbi__unpremultiply_on_load_set = 1;
+}
+
+STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert)
+{
+   stbi__de_iphone_flag_local = flag_true_if_should_convert;
+   stbi__de_iphone_flag_set = 1;
 }
 }
 
 
+#define stbi__unpremultiply_on_load  (stbi__unpremultiply_on_load_set           \
+                                       ? stbi__unpremultiply_on_load_local      \
+                                       : stbi__unpremultiply_on_load_global)
+#define stbi__de_iphone_flag  (stbi__de_iphone_flag_set                         \
+                                ? stbi__de_iphone_flag_local                    \
+                                : stbi__de_iphone_flag_global)
+#endif // STBI_THREAD_LOCAL
+
 static void stbi__de_iphone(stbi__png *z)
 static void stbi__de_iphone(stbi__png *z)
 {
 {
    stbi__context *s = z->s;
    stbi__context *s = z->s;
@@ -5272,6 +5355,32 @@ typedef struct
    int extra_read;
    int extra_read;
 } stbi__bmp_data;
 } stbi__bmp_data;
 
 
+static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress)
+{
+   // BI_BITFIELDS specifies masks explicitly, don't override
+   if (compress == 3)
+      return 1;
+
+   if (compress == 0) {
+      if (info->bpp == 16) {
+         info->mr = 31u << 10;
+         info->mg = 31u <<  5;
+         info->mb = 31u <<  0;
+      } else if (info->bpp == 32) {
+         info->mr = 0xffu << 16;
+         info->mg = 0xffu <<  8;
+         info->mb = 0xffu <<  0;
+         info->ma = 0xffu << 24;
+         info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
+      } else {
+         // otherwise, use defaults, which is all-0
+         info->mr = info->mg = info->mb = info->ma = 0;
+      }
+      return 1;
+   }
+   return 0; // error
+}
+
 static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
 static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
 {
 {
    int hsz;
    int hsz;
@@ -5299,6 +5408,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
    if (hsz != 12) {
    if (hsz != 12) {
       int compress = stbi__get32le(s);
       int compress = stbi__get32le(s);
       if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
       if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
+      if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes
+      if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel
       stbi__get32le(s); // discard sizeof
       stbi__get32le(s); // discard sizeof
       stbi__get32le(s); // discard hres
       stbi__get32le(s); // discard hres
       stbi__get32le(s); // discard vres
       stbi__get32le(s); // discard vres
@@ -5313,17 +5424,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
          }
          }
          if (info->bpp == 16 || info->bpp == 32) {
          if (info->bpp == 16 || info->bpp == 32) {
             if (compress == 0) {
             if (compress == 0) {
-               if (info->bpp == 32) {
-                  info->mr = 0xffu << 16;
-                  info->mg = 0xffu <<  8;
-                  info->mb = 0xffu <<  0;
-                  info->ma = 0xffu << 24;
-                  info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
-               } else {
-                  info->mr = 31u << 10;
-                  info->mg = 31u <<  5;
-                  info->mb = 31u <<  0;
-               }
+               stbi__bmp_set_mask_defaults(info, compress);
             } else if (compress == 3) {
             } else if (compress == 3) {
                info->mr = stbi__get32le(s);
                info->mr = stbi__get32le(s);
                info->mg = stbi__get32le(s);
                info->mg = stbi__get32le(s);
@@ -5338,6 +5439,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
                return stbi__errpuc("bad BMP", "bad BMP");
                return stbi__errpuc("bad BMP", "bad BMP");
          }
          }
       } else {
       } else {
+         // V4/V5 header
          int i;
          int i;
          if (hsz != 108 && hsz != 124)
          if (hsz != 108 && hsz != 124)
             return stbi__errpuc("bad BMP", "bad BMP");
             return stbi__errpuc("bad BMP", "bad BMP");
@@ -5345,6 +5447,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
          info->mg = stbi__get32le(s);
          info->mg = stbi__get32le(s);
          info->mb = stbi__get32le(s);
          info->mb = stbi__get32le(s);
          info->ma = stbi__get32le(s);
          info->ma = stbi__get32le(s);
+         if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs
+            stbi__bmp_set_mask_defaults(info, compress);
          stbi__get32le(s); // discard color space
          stbi__get32le(s); // discard color space
          for (i=0; i < 12; ++i)
          for (i=0; i < 12; ++i)
             stbi__get32le(s); // discard color space parameters
             stbi__get32le(s); // discard color space parameters
@@ -5394,8 +5498,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
          psize = (info.offset - info.extra_read - info.hsz) >> 2;
          psize = (info.offset - info.extra_read - info.hsz) >> 2;
    }
    }
    if (psize == 0) {
    if (psize == 0) {
-      STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original));
-      if (info.offset != s->callback_already_read + (s->img_buffer - s->buffer_start)) {
+      if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) {
         return stbi__errpuc("bad offset", "Corrupt BMP");
         return stbi__errpuc("bad offset", "Corrupt BMP");
       }
       }
    }
    }
@@ -6342,6 +6445,7 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c
 
 
    // intermediate buffer is RGBA
    // intermediate buffer is RGBA
    result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
    result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
+   if (!result) return stbi__errpuc("outofmem", "Out of memory");
    memset(result, 0xff, x*y*4);
    memset(result, 0xff, x*y*4);
 
 
    if (!stbi__pic_load_core(s,x,y,comp, result)) {
    if (!stbi__pic_load_core(s,x,y,comp, result)) {
@@ -6457,6 +6561,7 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
 static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
 static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
 {
 {
    stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
    stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
+   if (!g) return stbi__err("outofmem", "Out of memory");
    if (!stbi__gif_header(s, g, comp, 1)) {
    if (!stbi__gif_header(s, g, comp, 1)) {
       STBI_FREE(g);
       STBI_FREE(g);
       stbi__rewind( s );
       stbi__rewind( s );
@@ -6766,6 +6871,17 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
    }
    }
 }
 }
 
 
+static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays)
+{
+   STBI_FREE(g->out);
+   STBI_FREE(g->history);
+   STBI_FREE(g->background);
+
+   if (out) STBI_FREE(out);
+   if (delays && *delays) STBI_FREE(*delays);
+   return stbi__errpuc("outofmem", "Out of memory");
+}
+
 static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
 static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
 {
 {
    if (stbi__gif_test(s)) {
    if (stbi__gif_test(s)) {
@@ -6777,6 +6893,10 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
       int stride;
       int stride;
       int out_size = 0;
       int out_size = 0;
       int delays_size = 0;
       int delays_size = 0;
+
+      STBI_NOTUSED(out_size);
+      STBI_NOTUSED(delays_size);
+
       memset(&g, 0, sizeof(g));
       memset(&g, 0, sizeof(g));
       if (delays) {
       if (delays) {
          *delays = 0;
          *delays = 0;
@@ -6794,26 +6914,29 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
 
 
             if (out) {
             if (out) {
                void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
                void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
-               if (NULL == tmp) {
-                  STBI_FREE(g.out);
-                  STBI_FREE(g.history);
-                  STBI_FREE(g.background);
-                  return stbi__errpuc("outofmem", "Out of memory");
-               }
+               if (!tmp)
+                  return stbi__load_gif_main_outofmem(&g, out, delays);
                else {
                else {
                    out = (stbi_uc*) tmp;
                    out = (stbi_uc*) tmp;
                    out_size = layers * stride;
                    out_size = layers * stride;
                }
                }
 
 
                if (delays) {
                if (delays) {
-                  *delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
+                  int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
+                  if (!new_delays)
+                     return stbi__load_gif_main_outofmem(&g, out, delays);
+                  *delays = new_delays;
                   delays_size = layers * sizeof(int);
                   delays_size = layers * sizeof(int);
                }
                }
             } else {
             } else {
                out = (stbi_uc*)stbi__malloc( layers * stride );
                out = (stbi_uc*)stbi__malloc( layers * stride );
+               if (!out)
+                  return stbi__load_gif_main_outofmem(&g, out, delays);
                out_size = layers * stride;
                out_size = layers * stride;
                if (delays) {
                if (delays) {
                   *delays = (int*) stbi__malloc( layers * sizeof(int) );
                   *delays = (int*) stbi__malloc( layers * sizeof(int) );
+                  if (!*delays)
+                     return stbi__load_gif_main_outofmem(&g, out, delays);
                   delays_size = layers * sizeof(int);
                   delays_size = layers * sizeof(int);
                }
                }
             }
             }
@@ -7138,9 +7261,10 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
 
 
    info.all_a = 255;
    info.all_a = 255;
    p = stbi__bmp_parse_header(s, &info);
    p = stbi__bmp_parse_header(s, &info);
-   stbi__rewind( s );
-   if (p == NULL)
+   if (p == NULL) {
+      stbi__rewind( s );
       return 0;
       return 0;
+   }
    if (x) *x = s->img_x;
    if (x) *x = s->img_x;
    if (y) *y = s->img_y;
    if (y) *y = s->img_y;
    if (comp) {
    if (comp) {
@@ -7206,8 +7330,8 @@ static int stbi__psd_is16(stbi__context *s)
        stbi__rewind( s );
        stbi__rewind( s );
        return 0;
        return 0;
    }
    }
-   (void) stbi__get32be(s);
-   (void) stbi__get32be(s);
+   STBI_NOTUSED(stbi__get32be(s));
+   STBI_NOTUSED(stbi__get32be(s));
    depth = stbi__get16be(s);
    depth = stbi__get16be(s);
    if (depth != 16) {
    if (depth != 16) {
        stbi__rewind( s );
        stbi__rewind( s );
@@ -7286,7 +7410,6 @@ static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)
 // Known limitations:
 // Known limitations:
 //    Does not support comments in the header section
 //    Does not support comments in the header section
 //    Does not support ASCII image data (formats P2 and P3)
 //    Does not support ASCII image data (formats P2 and P3)
-//    Does not support 16-bit-per-channel
 
 
 #ifndef STBI_NO_PNM
 #ifndef STBI_NO_PNM
 
 
@@ -7307,7 +7430,8 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
    stbi_uc *out;
    stbi_uc *out;
    STBI_NOTUSED(ri);
    STBI_NOTUSED(ri);
 
 
-   if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
+   ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n);
+   if (ri->bits_per_channel == 0)
       return 0;
       return 0;
 
 
    if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
    if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
@@ -7317,12 +7441,12 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
    *y = s->img_y;
    *y = s->img_y;
    if (comp) *comp = s->img_n;
    if (comp) *comp = s->img_n;
 
 
-   if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
+   if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0))
       return stbi__errpuc("too large", "PNM too large");
       return stbi__errpuc("too large", "PNM too large");
 
 
-   out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
+   out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
    if (!out) return stbi__errpuc("outofmem", "Out of memory");
    if (!out) return stbi__errpuc("outofmem", "Out of memory");
-   stbi__getn(s, out, s->img_n * s->img_x * s->img_y);
+   stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8));
 
 
    if (req_comp && req_comp != s->img_n) {
    if (req_comp && req_comp != s->img_n) {
       out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
       out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
@@ -7398,11 +7522,19 @@ static int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
    stbi__pnm_skip_whitespace(s, &c);
    stbi__pnm_skip_whitespace(s, &c);
 
 
    maxv = stbi__pnm_getinteger(s, &c);  // read max value
    maxv = stbi__pnm_getinteger(s, &c);  // read max value
-
-   if (maxv > 255)
-      return stbi__err("max value > 255", "PPM image not 8-bit");
+   if (maxv > 65535)
+      return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images");
+   else if (maxv > 255)
+      return 16;
    else
    else
-      return 1;
+      return 8;
+}
+
+static int stbi__pnm_is16(stbi__context *s)
+{
+   if (stbi__pnm_info(s, NULL, NULL, NULL) == 16)
+	   return 1;
+   return 0;
 }
 }
 #endif
 #endif
 
 
@@ -7458,6 +7590,9 @@ static int stbi__is_16_main(stbi__context *s)
    if (stbi__psd_is16(s))  return 1;
    if (stbi__psd_is16(s))  return 1;
    #endif
    #endif
 
 
+   #ifndef STBI_NO_PNM
+   if (stbi__pnm_is16(s))  return 1;
+   #endif
    return 0;
    return 0;
 }
 }
 
 

+ 16 - 8
src/love.cpp

@@ -143,14 +143,6 @@ enum DoneAction
 
 
 static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &restartvalue)
 static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &restartvalue)
 {
 {
-#ifdef LOVE_LEGENDARY_APP_ARGV_HACK
-	int hack_argc = 0;
-	char **hack_argv = 0;
-	get_app_arguments(argc, argv, hack_argc, hack_argv);
-	argc = hack_argc;
-	argv = hack_argv;
-#endif // LOVE_LEGENDARY_APP_ARGV_HACK
-
 	// Oh, you just want the version? Okay!
 	// Oh, you just want the version? Okay!
 	if (argc > 1 && strcmp(argv[1], "--version") == 0)
 	if (argc > 1 && strcmp(argv[1], "--version") == 0)
 	{
 	{
@@ -167,6 +159,22 @@ static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &res
 	lua_State *L = luaL_newstate();
 	lua_State *L = luaL_newstate();
 	luaL_openlibs(L);
 	luaL_openlibs(L);
 
 
+	// LuaJIT-specific setup needs to be done as early as possible - before
+	// get_app_arguments because that loads external library code. This is also
+	// loaded inside require("love"). Note that it doesn't use the love table.
+	love_preload(L, luaopen_love_jitsetup, "love.jitsetup");
+	lua_getglobal(L, "require");
+	lua_pushstring(L, "love.jitsetup");
+	lua_call(L, 1, 0);
+
+#ifdef LOVE_LEGENDARY_APP_ARGV_HACK
+	int hack_argc = 0;
+	char **hack_argv = nullptr;
+	get_app_arguments(argc, argv, hack_argc, hack_argv);
+	argc = hack_argc;
+	argv = hack_argv;
+#endif // LOVE_LEGENDARY_APP_ARGV_HACK
+
 	// Add love to package.preload for easy requiring.
 	// Add love to package.preload for easy requiring.
 	love_preload(L, luaopen_love, "love");
 	love_preload(L, luaopen_love, "love");
 
 

+ 11 - 0
src/modules/data/wrap_ByteData.cpp

@@ -31,8 +31,19 @@ ByteData *luax_checkbytedata(lua_State *L, int idx)
 	return luax_checktype<ByteData>(L, idx);
 	return luax_checktype<ByteData>(L, idx);
 }
 }
 
 
+int w_ByteData_clone(lua_State *L)
+{
+	ByteData *t = luax_checkbytedata(L, 1);
+	ByteData *c = nullptr;
+	luax_catchexcept(L, [&](){ c = t->clone(); });
+	luax_pushtype(L, c);
+	c->release();
+	return 1;
+}
+
 static const luaL_Reg w_ByteData_functions[] =
 static const luaL_Reg w_ByteData_functions[] =
 {
 {
+	{ "clone", w_ByteData_clone },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
 
 

+ 12 - 1
src/modules/data/wrap_DataView.cpp

@@ -26,13 +26,24 @@ namespace love
 namespace data
 namespace data
 {
 {
 
 
-DataView *luax_checkdataView(lua_State *L, int idx)
+DataView *luax_checkdataview(lua_State *L, int idx)
 {
 {
 	return luax_checktype<DataView>(L, idx);
 	return luax_checktype<DataView>(L, idx);
 }
 }
 
 
+int w_DataView_clone(lua_State *L)
+{
+	DataView *t = luax_checkdataview(L, 1);
+	DataView *c = nullptr;
+	luax_catchexcept(L, [&](){ c = t->clone(); });
+	luax_pushtype(L, c);
+	c->release();
+	return 1;
+}
+
 static const luaL_Reg w_DataView_functions[] =
 static const luaL_Reg w_DataView_functions[] =
 {
 {
+	{ "clone", w_DataView_clone },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
 
 

+ 1 - 1
src/modules/event/wrap_Event.cpp

@@ -180,7 +180,7 @@ extern "C" int luaopen_love_event(lua_State *L)
 
 
 	int ret = luax_register_module(L, w);
 	int ret = luax_register_module(L, w);
 
 
-	if (luaL_loadbuffer(L, (const char *)event_lua, sizeof(event_lua), "wrap_Event.lua") == 0)
+	if (luaL_loadbuffer(L, (const char *)event_lua, sizeof(event_lua), "=[love \"wrap_Event.lua\"]") == 0)
 		lua_call(L, 0, 0);
 		lua_call(L, 0, 0);
 	else
 	else
 		lua_error(L);
 		lua_error(L);

+ 1 - 1
src/modules/filesystem/Filesystem.cpp

@@ -122,7 +122,7 @@ static bool getContainingDirectory(const std::string &path, std::string &newpath
 	newpath = path.substr(0, index);
 	newpath = path.substr(0, index);
 
 
 	// Bail if the root has been stripped out.
 	// Bail if the root has been stripped out.
-	return newpath.find("/\\") != std::string::npos;
+	return newpath.find_first_of("/\\") != std::string::npos;
 }
 }
 
 
 static bool createDirectoryRaw(const std::string &path)
 static bool createDirectoryRaw(const std::string &path)

+ 7 - 5
src/modules/filesystem/physfs/Filesystem.cpp

@@ -240,15 +240,13 @@ bool Filesystem::setSource(const char *source)
 
 
 	PHYSFS_Io *gameLoveIO;
 	PHYSFS_Io *gameLoveIO;
 	bool hasFusedGame = love::android::checkFusedGame((void **) &gameLoveIO);
 	bool hasFusedGame = love::android::checkFusedGame((void **) &gameLoveIO);
+	bool isAAssetMounted = false;
 
 
 	if (hasFusedGame)
 	if (hasFusedGame)
 	{
 	{
 		if (gameLoveIO)
 		if (gameLoveIO)
-		{
 			// Actually we should just be able to mount gameLoveIO, but that's experimental.
 			// Actually we should just be able to mount gameLoveIO, but that's experimental.
 			gameLoveIO->destroy(gameLoveIO);
 			gameLoveIO->destroy(gameLoveIO);
-			goto oldschool;
-		}
 		else
 		else
 		{
 		{
 			if (!love::android::initializeVirtualArchive())
 			if (!love::android::initializeVirtualArchive())
@@ -256,11 +254,15 @@ bool Filesystem::setSource(const char *source)
 				SDL_Log("Unable to mount AAsset: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
 				SDL_Log("Unable to mount AAsset: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
 				return false;
 				return false;
 			}
 			}
+
+			// See love::android::initializeVirtualArchive()
+			new_search_path = "ASET.AASSET";
+			isAAssetMounted = true;
 		}
 		}
 	}
 	}
-	else
+
+	if (!isAAssetMounted)
 	{
 	{
-	oldschool:
 		new_search_path = love::android::getSelectedGameFile();
 		new_search_path = love::android::getSelectedGameFile();
 
 
 		// try mounting first, if that fails, load to memory and mount
 		// try mounting first, if that fails, load to memory and mount

+ 38 - 2
src/modules/filesystem/wrap_Filesystem.cpp

@@ -29,6 +29,10 @@
 
 
 #include "physfs/Filesystem.h"
 #include "physfs/Filesystem.h"
 
 
+#ifdef LOVE_ANDROID
+#include "common/android.h"
+#endif
+
 // SDL
 // SDL
 #include <SDL_loadso.h>
 #include <SDL_loadso.h>
 
 
@@ -380,11 +384,22 @@ int w_newFileData(lua_State *L)
 	}
 	}
 
 
 	size_t length = 0;
 	size_t length = 0;
-	const char *str = luaL_checklstring(L, 1, &length);
+	const void *ptr = nullptr;
+	if (luax_istype(L, 1, Data::type))
+	{
+		Data *data = data::luax_checkdata(L, 1);
+		ptr = data->getData();
+		length = data->getSize();
+	}
+	else if (lua_isstring(L, 1))
+		ptr = luaL_checklstring(L, 1, &length);
+	else
+		return luaL_argerror(L, 1, "string or Data expected");
+
 	const char *filename = luaL_checkstring(L, 2);
 	const char *filename = luaL_checkstring(L, 2);
 
 
 	FileData *t = nullptr;
 	FileData *t = nullptr;
-	luax_catchexcept(L, [&](){ t = instance()->newFileData(str, length, filename); });
+	luax_catchexcept(L, [&](){ t = instance()->newFileData(ptr, length, filename); });
 
 
 	luax_pushtype(L, t);
 	luax_pushtype(L, t);
 	t->release();
 	t->release();
@@ -849,6 +864,23 @@ int extloader(lua_State *L)
 	void *handle = nullptr;
 	void *handle = nullptr;
 	auto *inst = instance();
 	auto *inst = instance();
 
 
+#ifdef LOVE_ANDROID
+	// Specifically Android, look the library path based on getCRequirePath first
+	std::string androidPath(love::android::getCRequirePath());
+
+	if (!androidPath.empty())
+	{
+		// Replace ? with just the dotted filename (not tokenized_name)
+		replaceAll(androidPath, "?", filename);
+
+		// Load directly, don't check for existence.
+		handle = SDL_LoadObject(androidPath.c_str());
+	}
+
+	if (!handle)
+	{
+#endif // LOVE_ANDROID
+
 	for (const std::string &el : inst->getCRequirePath())
 	for (const std::string &el : inst->getCRequirePath())
 	{
 	{
 		for (const char *ext : library_extensions)
 		for (const char *ext : library_extensions)
@@ -878,6 +910,10 @@ int extloader(lua_State *L)
 			break;
 			break;
 	}
 	}
 
 
+#ifdef LOVE_ANDROID
+	} // if (!handle)
+#endif
+
 	if (!handle)
 	if (!handle)
 	{
 	{
 		lua_pushfstring(L, "\n\tno file '%s' in LOVE paths.", tokenized_name.c_str());
 		lua_pushfstring(L, "\n\tno file '%s' in LOVE paths.", tokenized_name.c_str());

+ 24 - 5
src/modules/graphics/Buffer.cpp

@@ -147,11 +147,30 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataDe
 
 
 			// GLSL's std430 packing rules. We also assume all matrices are
 			// GLSL's std430 packing rules. We also assume all matrices are
 			// column-major.
 			// column-major.
-			if (info.isMatrix)
-				alignment = info.matrixRows * info.componentSize;
-			else
-				alignment = info.components * info.componentSize;
-
+			// https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf
+
+			// "If the member is a column-major matrix with C columns and R rows,
+			// the matrix is stored identically to an array of C column vectors
+			// with R components each".
+			// "If the member is a three-component vector with components
+			// consuming N basic machine units, the base alignment is 4N."
+			int c = info.isMatrix ? info.matrixRows : info.components;
+			alignment = c == 3 ? 4 * info.componentSize : c * info.componentSize;
+
+			// std430 will effectively turn a floatmat3x3 into a floatmat4x3
+			// because of its vec3 padding rules. For now we'd rather not
+			// support those formats at all, because it's not easy for users to
+			// deal with.
+			if (alignment != c * info.componentSize && (decl.arrayLength > 0 || info.isMatrix))
+			{
+				const char *fstr = "unknown";
+				getConstant(decl.format, fstr);
+				throw love::Exception("Data format %s%s is not currently supported in shader storage buffers.", fstr, decl.arrayLength > 0 ? " array" : "");
+			}
+
+			// "If the member is a structure, the base alignment of the structure
+			// is N, where N is the largest base alignment value of any of its
+			// members"
 			structurealignment = std::max(structurealignment, alignment);
 			structurealignment = std::max(structurealignment, alignment);
 
 
 			memberoffset = alignUp(memberoffset, alignment);
 			memberoffset = alignUp(memberoffset, alignment);

+ 5 - 8
src/modules/graphics/Font.cpp

@@ -338,7 +338,7 @@ float Font::getKerning(uint32 leftglyph, uint32 rightglyph)
 	if (it != kerning.end())
 	if (it != kerning.end())
 		return it->second;
 		return it->second;
 
 
-	float k = rasterizers[0]->getKerning(leftglyph, rightglyph) / dpiScale + 0.5f;
+	float k = floorf(rasterizers[0]->getKerning(leftglyph, rightglyph) / dpiScale + 0.5f);
 
 
 	for (const auto &r : rasterizers)
 	for (const auto &r : rasterizers)
 	{
 	{
@@ -901,14 +901,11 @@ void Font::getWrap(const ColoredCodepoints &codepoints, float wraplimit, std::ve
 	}
 	}
 
 
 	// Push the last line.
 	// Push the last line.
-	if (!wline.cps.empty())
-	{
-		lines.push_back(wline);
+	lines.push_back(wline);
 
 
-		// Ignore the width of any trailing spaces, for individual lines.
-		if (linewidths)
-			linewidths->push_back(width - widthoftrailingspace);
-	}
+	// Ignore the width of any trailing spaces, for individual lines.
+	if (linewidths)
+		linewidths->push_back(width - widthoftrailingspace);
 }
 }
 
 
 void Font::getWrap(const std::vector<ColoredString> &text, float wraplimit, std::vector<std::string> &lines, std::vector<int> *linewidths)
 void Font::getWrap(const std::vector<ColoredString> &text, float wraplimit, std::vector<std::string> &lines, std::vector<int> *linewidths)

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

@@ -1526,7 +1526,7 @@ void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h)
 
 
 void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry, int points)
 void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry, int points)
 {
 {
-	if (rx == 0 || ry == 0)
+	if (rx <= 0 || ry <= 0)
 	{
 	{
 		rectangle(mode, x, y, w, h);
 		rectangle(mode, x, y, w, h);
 		return;
 		return;
@@ -1585,7 +1585,8 @@ void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, floa
 
 
 void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry)
 void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry)
 {
 {
-	rectangle(mode, x, y, w, h, rx, ry, calculateEllipsePoints(rx, ry));
+	int points = calculateEllipsePoints(std::min(rx, std::abs(w/2)), std::min(ry, std::abs(h/2)));
+	rectangle(mode, x, y, w, h, rx, ry, points);
 }
 }
 
 
 void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)
 void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)

+ 1 - 1
src/modules/graphics/ParticleSystem.cpp

@@ -177,7 +177,7 @@ void ParticleSystem::resetOffset()
 	else
 	else
 	{
 	{
 		Quad::Viewport v = quads[0]->getViewport();
 		Quad::Viewport v = quads[0]->getViewport();
-		offset = love::Vector2(v.x*0.5f, v.y*0.5f);
+		offset = love::Vector2(v.w*0.5f, v.h*0.5f);
 	}
 	}
 }
 }
 
 

+ 4 - 4
src/modules/graphics/Shader.cpp

@@ -896,14 +896,14 @@ bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err,
 			const glslang::TTypeList *structure = type->getStruct();
 			const glslang::TTypeList *structure = type->getStruct();
 			if (structure == nullptr || structure->size() != 1)
 			if (structure == nullptr || structure->size() != 1)
 			{
 			{
-				err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of structs.";
+				err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of base types or structs.";
 				return false;
 				return false;
 			}
 			}
 
 
-			const glslang::TType* structtype = (*structure)[0].type;
-			if (structtype == nullptr || structtype->getBasicType() != glslang::EbtStruct || !structtype->isUnsizedArray())
+			const glslang::TType* elementtype = (*structure)[0].type;
+			if (elementtype == nullptr || !elementtype->isUnsizedArray())
 			{
 			{
-				err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of structs.";
+				err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of base types or structs.";
 				return false;
 				return false;
 			}
 			}
 
 

+ 21 - 2
src/modules/graphics/opengl/Shader.cpp

@@ -166,6 +166,12 @@ void Shader::mapActiveUniforms()
 				u.storageTextureFormat = reflectionit->second.format;
 				u.storageTextureFormat = reflectionit->second.format;
 				u.access = reflectionit->second.access;
 				u.access = reflectionit->second.access;
 			}
 			}
+			else
+			{
+				// No reflection info - maybe glslang was better at detecting
+				// dead code than the driver's compiler?
+				continue;
+			}
 
 
 			StorageTextureBinding binding = {};
 			StorageTextureBinding binding = {};
 			binding.gltexture = gl.getDefaultTexture(u.textureType, u.dataBaseType);
 			binding.gltexture = gl.getDefaultTexture(u.textureType, u.dataBaseType);
@@ -352,6 +358,7 @@ void Shader::mapActiveUniforms()
 		glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numstoragebuffers);
 		glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numstoragebuffers);
 
 
 		char namebuffer[2048] = { '\0' };
 		char namebuffer[2048] = { '\0' };
+		int nextstoragebufferbinding = 0;
 
 
 		for (int sindex = 0; sindex < numstoragebuffers; sindex++)
 		for (int sindex = 0; sindex < numstoragebuffers; sindex++)
 		{
 		{
@@ -372,6 +379,12 @@ void Shader::mapActiveUniforms()
 				u.bufferMemberCount = reflectionit->second.memberCount;
 				u.bufferMemberCount = reflectionit->second.memberCount;
 				u.access = reflectionit->second.access;
 				u.access = reflectionit->second.access;
 			}
 			}
+			else
+			{
+				// No reflection info - maybe glslang was better at detecting
+				// dead code than the driver's compiler?
+				continue;
+			}
 
 
 			// Make sure previously set uniform data is preserved, and shader-
 			// Make sure previously set uniform data is preserved, and shader-
 			// initialized values are retrieved.
 			// initialized values are retrieved.
@@ -393,8 +406,11 @@ void Shader::mapActiveUniforms()
 				memset(u.buffers, 0, sizeof(Buffer*)* u.count);
 				memset(u.buffers, 0, sizeof(Buffer*)* u.count);
 			}
 			}
 
 
-			GLenum props[] = { GL_BUFFER_BINDING };
-			glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, sindex, 1, props, 1, nullptr, u.ints);
+			// Unlike local uniforms and attributes, OpenGL doesn't auto-assign storage
+			// block bindings if they're unspecified in the shader. So we overwrite them
+			// regardless, here.
+			u.ints[0] = nextstoragebufferbinding++;
+			glShaderStorageBlockBinding(program, sindex, u.ints[0]);
 
 
 			BufferBinding binding;
 			BufferBinding binding;
 			binding.bindingindex = u.ints[0];
 			binding.bindingindex = u.ints[0];
@@ -1074,6 +1090,9 @@ Shader::MatrixSize Shader::getMatrixSize(GLenum type) const
 		m.columns = 4;
 		m.columns = 4;
 		m.rows = 3;
 		m.rows = 3;
 		break;
 		break;
+	default:
+		m.columns = m.rows = 0;
+		break;
 	}
 	}
 
 
 	return m;
 	return m;

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

@@ -45,7 +45,7 @@ public:
 
 
 	struct StorageTextureBinding
 	struct StorageTextureBinding
 	{
 	{
-		Texture *texture = nullptr;
+		love::graphics::Texture *texture = nullptr;
 		GLuint gltexture = 0;
 		GLuint gltexture = 0;
 		TextureType type = TEXTURE_2D;
 		TextureType type = TEXTURE_2D;
 		GLenum access = GL_READ_ONLY;
 		GLenum access = GL_READ_ONLY;

+ 2 - 0
src/modules/graphics/wrap_Buffer.cpp

@@ -22,6 +22,8 @@
 #include "Buffer.h"
 #include "Buffer.h"
 #include "common/Data.h"
 #include "common/Data.h"
 
 
+#include <limits>
+
 namespace love
 namespace love
 {
 {
 namespace graphics
 namespace graphics

+ 1 - 1
src/modules/graphics/wrap_Graphics.cpp

@@ -3657,7 +3657,7 @@ extern "C" int luaopen_love_graphics(lua_State *L)
 
 
 	int n = luax_register_module(L, w);
 	int n = luax_register_module(L, w);
 
 
-	if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "wrap_Graphics.lua") == 0)
+	if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "=[love \"wrap_Graphics.lua\"]") == 0)
 		lua_call(L, 0, 0);
 		lua_call(L, 0, 0);
 	else
 	else
 		lua_error(L);
 		lua_error(L);

+ 3 - 9
src/modules/graphics/wrap_Shader.cpp

@@ -447,18 +447,12 @@ int w_Shader_send(lua_State *L)
 
 
 	const Shader::UniformInfo *info = shader->getUniformInfo(name);
 	const Shader::UniformInfo *info = shader->getUniformInfo(name);
 	if (info == nullptr)
 	if (info == nullptr)
-	{
-		luax_pushboolean(L, false);
-		return 1;
-	}
+		return luaL_error(L, "Shader uniform '%s' does not exist.\nA common error is to define but not use the variable.", name);
 
 
 	if (luax_istype(L, 3, Data::type) || (info->baseType == Shader::UNIFORM_MATRIX && luax_istype(L, 4, Data::type)))
 	if (luax_istype(L, 3, Data::type) || (info->baseType == Shader::UNIFORM_MATRIX && luax_istype(L, 4, Data::type)))
-		w_Shader_sendData(L, 3, shader, info, false);
+		return w_Shader_sendData(L, 3, shader, info, false);
 	else
 	else
-		w_Shader_sendLuaValues(L, 3, shader, info, name);
-
-	luax_pushboolean(L, true);
-	return 1;
+		return w_Shader_sendLuaValues(L, 3, shader, info, name);
 }
 }
 
 
 int w_Shader_sendColors(lua_State *L)
 int w_Shader_sendColors(lua_State *L)

+ 1 - 1
src/modules/graphics/wrap_Video.cpp

@@ -168,7 +168,7 @@ int luaopen_video(lua_State *L)
 {
 {
 	int ret = luax_register_type(L, &Video::type, functions, nullptr);
 	int ret = luax_register_type(L, &Video::type, functions, nullptr);
 
 
-	luaL_loadbuffer(L, video_lua, sizeof(video_lua), "Video.lua");
+	luaL_loadbuffer(L, video_lua, sizeof(video_lua), "=[love \"Video.lua\"]");
 	luax_gettypemetatable(L, Video::type);
 	luax_gettypemetatable(L, Video::type);
 	lua_call(L, 1, 0);
 	lua_call(L, 1, 0);
 
 

+ 27 - 4
src/modules/joystick/sdl/Joystick.cpp

@@ -440,6 +440,11 @@ bool Joystick::checkCreateHaptic()
 
 
 bool Joystick::isVibrationSupported()
 bool Joystick::isVibrationSupported()
 {
 {
+#if SDL_VERSION_ATLEAST(2, 0, 18)
+	if (isConnected() && SDL_JoystickHasRumble(joyhandle) == SDL_TRUE)
+		return true;
+#endif
+
 	if (!checkCreateHaptic())
 	if (!checkCreateHaptic())
 		return false;
 		return false;
 
 
@@ -490,8 +495,12 @@ bool Joystick::setVibration(float left, float right, float duration)
 	if (left == 0.0f && right == 0.0f)
 	if (left == 0.0f && right == 0.0f)
 		return setVibration();
 		return setVibration();
 
 
-	if (!checkCreateHaptic())
+	if (!isConnected())
+	{
+		vibration.left = vibration.right = 0.0f;
+		vibration.endtime = SDL_HAPTIC_INFINITY;
 		return false;
 		return false;
+	}
 
 
 	Uint32 length = SDL_HAPTIC_INFINITY;
 	Uint32 length = SDL_HAPTIC_INFINITY;
 	if (duration >= 0.0f)
 	if (duration >= 0.0f)
@@ -501,10 +510,19 @@ bool Joystick::setVibration(float left, float right, float duration)
 	}
 	}
 
 
 	bool success = false;
 	bool success = false;
+
+#if SDL_VERSION_ATLEAST(2, 0, 9)
+	if (SDL_JoystickRumble(joyhandle, (Uint16)(left * LOVE_UINT16_MAX), (Uint16)(right * LOVE_UINT16_MAX), length) == 0)
+		success = true;
+#endif
+
+	if (!success && !checkCreateHaptic())
+		return false;
+
 	unsigned int features = SDL_HapticQuery(haptic);
 	unsigned int features = SDL_HapticQuery(haptic);
 	int axes = SDL_HapticNumAxes(haptic);
 	int axes = SDL_HapticNumAxes(haptic);
 
 
-	if ((features & SDL_HAPTIC_LEFTRIGHT) != 0)
+	if (!success && (features & SDL_HAPTIC_LEFTRIGHT) != 0)
 	{
 	{
 		memset(&vibration.effect, 0, sizeof(SDL_HapticEffect));
 		memset(&vibration.effect, 0, sizeof(SDL_HapticEffect));
 		vibration.effect.type = SDL_HAPTIC_LEFTRIGHT;
 		vibration.effect.type = SDL_HAPTIC_LEFTRIGHT;
@@ -576,9 +594,14 @@ bool Joystick::setVibration(float left, float right, float duration)
 
 
 bool Joystick::setVibration()
 bool Joystick::setVibration()
 {
 {
-	bool success = true;
+	bool success = false;
+
+#if SDL_VERSION_ATLEAST(2, 0, 9)
+	if (!success)
+		success = isConnected() && SDL_JoystickRumble(joyhandle, 0, 0, 0) == 0;
+#endif
 
 
-	if (SDL_WasInit(SDL_INIT_HAPTIC) && haptic && SDL_HapticIndex(haptic) != -1)
+	if (!success && SDL_WasInit(SDL_INIT_HAPTIC) && haptic && SDL_HapticIndex(haptic) != -1)
 		success = (SDL_HapticStopEffect(haptic, vibration.id) == 0);
 		success = (SDL_HapticStopEffect(haptic, vibration.id) == 0);
 
 
 	if (success)
 	if (success)

+ 186 - 0
src/modules/love/arg.lua

@@ -0,0 +1,186 @@
+R"luastring"--(
+-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
+-- There is a matching delimiter at the bottom of the file.
+
+--[[
+Copyright (c) 2006-2021 LOVE Development Team
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+--]]
+
+local love = require("love")
+
+-- Used for setup:
+love.path = {}
+love.arg = {}
+
+-- Replace any \ with /.
+function love.path.normalslashes(p)
+	return p:gsub("\\", "/")
+end
+
+-- Makes sure there is a slash at the end
+-- of a path.
+function love.path.endslash(p)
+	if p:sub(-1) ~= "/" then
+		return p .. "/"
+	else
+		return p
+	end
+end
+
+-- Checks whether a path is absolute or not.
+function love.path.abs(p)
+
+	local tmp = love.path.normalslashes(p)
+
+	-- Path is absolute if it starts with a "/".
+	if tmp:find("/") == 1 then
+		return true
+	end
+
+	-- Path is absolute if it starts with a
+	-- letter followed by a colon.
+	if tmp:find("%a:") == 1 then
+		return true
+	end
+
+	-- Relative.
+	return false
+
+end
+
+-- Converts any path into a full path.
+function love.path.getFull(p)
+
+	if love.path.abs(p) then
+		return love.path.normalslashes(p)
+	end
+
+	local cwd = love.filesystem.getWorkingDirectory()
+	cwd = love.path.normalslashes(cwd)
+	cwd = love.path.endslash(cwd)
+
+	-- Construct a full path.
+	local full = cwd .. love.path.normalslashes(p)
+
+	-- Remove trailing /., if applicable
+	return full:match("(.-)/%.$") or full
+end
+
+-- Returns the leaf of a full path.
+function love.path.leaf(p)
+	p = love.path.normalslashes(p)
+
+	local a = 1
+	local last = p
+
+	while a do
+		a = p:find("/", a+1)
+
+		if a then
+			last = p:sub(a+1)
+		end
+	end
+
+	return last
+end
+
+-- Finds the key in the table with the lowest integral index. The lowest
+-- will typically the executable, for instance "lua5.1.exe".
+function love.arg.getLow(a)
+	local m = math.huge
+	for k,v in pairs(a) do
+		if k < m then
+			m = k
+		end
+	end
+	return a[m], m
+end
+
+love.arg.options = {
+	console = { a = 0 },
+	fused = {a = 0 },
+	game = { a = 1 }
+}
+
+love.arg.optionIndices = {}
+
+function love.arg.parseOption(m, i)
+	m.set = true
+
+	if m.a > 0 then
+		m.arg = {}
+		for j=i,i+m.a-1 do
+			love.arg.optionIndices[j] = true
+			table.insert(m.arg, arg[j])
+		end
+	end
+
+	return m.a
+end
+
+function love.arg.parseOptions(arg)
+
+	local game
+	local argc = #arg
+
+	local i = 1
+	while i <= argc do
+		-- Look for options.
+		local m = arg[i]:match("^%-%-(.*)")
+
+		if m and m ~= "" and love.arg.options[m] and not love.arg.options[m].set then
+			love.arg.optionIndices[i] = true
+			i = i + love.arg.parseOption(love.arg.options[m], i+1)
+		elseif m == "" then -- handle '--' as an option
+			love.arg.optionIndices[i] = true
+			if not game then -- handle '--' followed by game name
+				game = i + 1
+			end
+			break
+		elseif not game then
+			game = i
+		end
+		i = i + 1
+	end
+
+	if not love.arg.options.game.set then
+		love.arg.parseOption(love.arg.options.game, game or 0)
+	end
+end
+
+-- Returns the arguments that are passed to your game via love.load()
+-- arguments that were parsed as options are skipped.
+function love.arg.parseGameArguments(a)
+	local out = {}
+
+	local _, lowindex = love.arg.getLow(a)
+
+	local o = lowindex
+	for i=lowindex, #a do
+		if not love.arg.optionIndices[i] then
+			out[o] = a[i]
+			o = o + 1
+		end
+	end
+
+	return out
+end
+
+-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
+--)luastring"--"

+ 388 - 0
src/modules/love/boot.lua

@@ -0,0 +1,388 @@
+R"luastring"--(
+-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
+-- There is a matching delimiter at the bottom of the file.
+
+--[[
+Copyright (c) 2006-2021 LOVE Development Team
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+--]]
+
+-- Make sure love exists.
+local love = require("love")
+
+-- Essential code boot/init.
+require("love.arg")
+require("love.callbacks")
+
+local function uridecode(s)
+	return s:gsub("%%%x%x", function(str)
+		return string.char(tonumber(str:sub(2), 16))
+	end)
+end
+
+local no_game_code = false
+local invalid_game_path = nil
+
+-- This can't be overridden.
+function love.boot()
+
+	-- This is absolutely needed.
+	require("love.filesystem")
+
+	love.rawGameArguments = arg
+
+	local arg0 = love.arg.getLow(love.rawGameArguments)
+	love.filesystem.init(arg0)
+
+	local exepath = love.filesystem.getExecutablePath()
+	if #exepath == 0 then
+		-- This shouldn't happen, but just in case we'll fall back to arg0.
+		exepath = arg0
+	end
+
+	no_game_code = false
+	invalid_game_path = nil
+
+	-- Is this one of those fancy "fused" games?
+	local can_has_game = pcall(love.filesystem.setSource, exepath)
+
+	-- It's a fused game, don't parse --game argument
+	if can_has_game then
+		love.arg.options.game.set = true
+	end
+
+	-- Parse options now that we know which options we're looking for.
+	love.arg.parseOptions(love.rawGameArguments)
+
+	-- parseGameArguments can only be called after parseOptions.
+	love.parsedGameArguments = love.arg.parseGameArguments(love.rawGameArguments)
+
+	local o = love.arg.options
+
+	local is_fused_game = can_has_game or love.arg.options.fused.set
+
+	love.filesystem.setFused(is_fused_game)
+
+	love.setDeprecationOutput(not love.filesystem.isFused())
+
+	local identity = ""
+	if not can_has_game and o.game.set and o.game.arg[1] then
+		local nouri = o.game.arg[1]
+
+		if nouri:sub(1, 7) == "file://" then
+			nouri = uridecode(nouri:sub(8))
+		end
+
+		local full_source = love.path.getFull(nouri)
+		can_has_game = pcall(love.filesystem.setSource, full_source)
+
+		if not can_has_game then
+			invalid_game_path = full_source
+		end
+
+		-- Use the name of the source .love as the identity for now.
+		identity = love.path.leaf(full_source)
+	else
+		-- Use the name of the exe as the identity for now.
+		identity = love.path.leaf(exepath)
+	end
+
+	-- Try to use the archive containing main.lua as the identity name. It
+	-- might not be available, in which case the fallbacks above are used.
+	local realdir = love.filesystem.getRealDirectory("main.lua")
+	if realdir then
+		identity = love.path.leaf(realdir)
+	end
+
+	identity = identity:gsub("^([%.]+)", "") -- strip leading "."'s
+	identity = identity:gsub("%.([^%.]+)$", "") -- strip extension
+	identity = identity:gsub("%.", "_") -- replace remaining "."'s with "_"
+	identity = #identity > 0 and identity or "lovegame"
+
+	-- When conf.lua is initially loaded, the main source should be checked
+	-- before the save directory (the identity should be appended.)
+	pcall(love.filesystem.setIdentity, identity, true)
+
+	if can_has_game and not (love.filesystem.getInfo("main.lua") or love.filesystem.getInfo("conf.lua")) then
+		no_game_code = true
+	end
+
+	if not can_has_game then
+		local nogame = require("love.nogame")
+		nogame()
+	end
+end
+
+function love.init()
+
+	-- Create default configuration settings.
+	-- NOTE: Adding a new module to the modules list
+	-- will NOT make it load, see below.
+	local c = {
+		title = "Untitled",
+		version = love._version,
+		window = {
+			width = 800,
+			height = 600,
+			x = nil,
+			y = nil,
+			minwidth = 1,
+			minheight = 1,
+			fullscreen = false,
+			fullscreentype = "desktop",
+			display = 1,
+			vsync = 1,
+			msaa = 0,
+			borderless = false,
+			resizable = false,
+			centered = true,
+			usedpiscale = true,
+		},
+		modules = {
+			data = true,
+			event = true,
+			keyboard = true,
+			mouse = true,
+			timer = true,
+			joystick = true,
+			touch = true,
+			image = true,
+			graphics = true,
+			audio = true,
+			math = true,
+			physics = true,
+			sound = true,
+			system = true,
+			font = true,
+			thread = true,
+			window = true,
+			video = true,
+		},
+		audio = {
+			mixwithsystem = true, -- Only relevant for Android / iOS.
+			mic = false, -- Only relevant for Android.
+		},
+		console = false, -- Only relevant for windows.
+		identity = false,
+		appendidentity = false,
+		externalstorage = false, -- Only relevant for Android.
+		accelerometerjoystick = true, -- Only relevant for Android / iOS.
+		gammacorrect = false,
+		highdpi = false,
+	}
+
+	-- Console hack, part 1.
+	local openedconsole = false
+	if love.arg.options.console.set and love._openConsole then
+		love._openConsole()
+		openedconsole = true
+	end
+
+	-- If config file exists, load it and allow it to update config table.
+	local confok, conferr
+	if (not love.conf) and love.filesystem and love.filesystem.getInfo("conf.lua") then
+		confok, conferr = pcall(require, "conf")
+	end
+
+	-- Yes, conf.lua might not exist, but there are other ways of making
+	-- love.conf appear, so we should check for it anyway.
+	if love.conf then
+		confok, conferr = pcall(love.conf, c)
+		-- If love.conf errors, we'll trigger the error after loading modules so
+		-- the error message can be displayed in the window.
+	end
+
+	-- Console hack, part 2.
+	if c.console and love._openConsole and not openedconsole then
+		love._openConsole()
+	end
+
+	-- Hack for disabling accelerometer-as-joystick on Android / iOS.
+	if love._setAccelerometerAsJoystick then
+		love._setAccelerometerAsJoystick(c.accelerometerjoystick)
+	end
+
+	if love._setGammaCorrect then
+		love._setGammaCorrect(c.gammacorrect)
+	end
+
+	if love._setHighDPIAllowed then
+		love._setHighDPIAllowed(c.highdpi)
+	end
+
+	if love._setAudioMixWithSystem then
+		if c.audio and c.audio.mixwithsystem ~= nil then
+			love._setAudioMixWithSystem(c.audio.mixwithsystem)
+		end
+	end
+
+	if love._requestRecordingPermission then
+		love._requestRecordingPermission(c.audio and c.audio.mic)
+	end
+
+	-- Gets desired modules.
+	for k,v in ipairs{
+		"data",
+		"thread",
+		"timer",
+		"event",
+		"keyboard",
+		"joystick",
+		"mouse",
+		"touch",
+		"sound",
+		"system",
+		"audio",
+		"image",
+		"video",
+		"font",
+		"window",
+		"graphics",
+		"math",
+		"physics",
+	} do
+		if c.modules[v] then
+			require("love." .. v)
+		end
+	end
+
+	if love.event then
+		love.createhandlers()
+	end
+
+	-- Check the version
+	c.version = tostring(c.version)
+	if not love.isVersionCompatible(c.version) then
+		local major, minor, revision = c.version:match("^(%d+)%.(%d+)%.(%d+)$")
+		if (not major or not minor or not revision) or (major ~= love._version_major and minor ~= love._version_minor) then
+			local msg = ("This game indicates it was made for version '%s' of LOVE.\n"..
+				"It may not be compatible with the running version (%s)."):format(c.version, love._version)
+
+			print(msg)
+
+			if love.window then
+				love.window.showMessageBox("Compatibility Warning", msg, "warning")
+			end
+		end
+	end
+
+	if not confok and conferr then
+		error(conferr)
+	end
+
+	-- Setup window here.
+	if c.window and c.modules.window then
+		love.window.setTitle(c.window.title or c.title)
+		assert(love.window.setMode(c.window.width, c.window.height,
+		{
+			fullscreen = c.window.fullscreen,
+			fullscreentype = c.window.fullscreentype,
+			vsync = c.window.vsync,
+			msaa = c.window.msaa,
+			stencil = c.window.stencil,
+			depth = c.window.depth,
+			resizable = c.window.resizable,
+			minwidth = c.window.minwidth,
+			minheight = c.window.minheight,
+			borderless = c.window.borderless,
+			centered = c.window.centered,
+			display = c.window.display,
+			highdpi = c.window.highdpi, -- deprecated
+			usedpiscale = c.window.usedpiscale,
+			x = c.window.x,
+			y = c.window.y,
+		}), "Could not set window mode")
+		if c.window.icon then
+			assert(love.image, "If an icon is set in love.conf, love.image must be loaded!")
+			love.window.setIcon(love.image.newImageData(c.window.icon))
+		end
+	end
+
+	-- Our first timestep, because window creation can take some time
+	if love.timer then
+		love.timer.step()
+	end
+
+	if love.filesystem then
+		love.filesystem._setAndroidSaveExternal(c.externalstorage)
+		love.filesystem.setIdentity(c.identity or love.filesystem.getIdentity(), c.appendidentity)
+		if love.filesystem.getInfo("main.lua") then
+			require("main")
+		end
+	end
+
+	if no_game_code then
+		error("No code to run\nYour game might be packaged incorrectly.\nMake sure main.lua is at the top level of the zip.")
+	elseif invalid_game_path then
+		error("Cannot load game at path '" .. invalid_game_path .. "'.\nMake sure a folder exists at the specified path.")
+	end
+end
+
+local print, debug, tostring = print, debug, tostring
+
+local function error_printer(msg, layer)
+	print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
+end
+
+-----------------------------------------------------------
+-- The root of all calls.
+-----------------------------------------------------------
+
+return function()
+	local func
+	local inerror = false
+
+	local function deferErrhand(...)
+		local errhand = love.errorhandler or love.errhand
+		local handler = (not inerror and errhand) or error_printer
+		inerror = true
+		func = handler(...)
+	end
+
+	local function earlyinit()
+		-- If love.boot fails, return 1 and finish immediately
+		local result = xpcall(love.boot, error_printer)
+		if not result then return 1 end
+
+		-- If love.init or love.run fails, don't return a value,
+		-- as we want the error handler to take over
+		result = xpcall(love.init, deferErrhand)
+		if not result then return end
+
+		-- NOTE: We can't assign to func directly, as we'd
+		-- overwrite the result of deferErrhand with nil on error
+		local main
+		result, main = xpcall(love.run, deferErrhand)
+		if result then
+			func = main
+		end
+	end
+
+	func = earlyinit
+
+	while func do
+		local _, retval, restartvalue = xpcall(func, deferErrhand)
+		if retval then return retval, restartvalue end
+		coroutine.yield()
+	end
+
+	return 1
+end
+
+-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
+--)luastring"--"

+ 313 - 0
src/modules/love/callbacks.lua

@@ -0,0 +1,313 @@
+R"luastring"--(
+-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
+-- There is a matching delimiter at the bottom of the file.
+
+--[[
+Copyright (c) 2006-2021 LOVE Development Team
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+--]]
+
+local love = require("love")
+
+function love.createhandlers()
+
+	-- Standard callback handlers.
+	love.handlers = setmetatable({
+		keypressed = function (b,s,r)
+			if love.keypressed then return love.keypressed(b,s,r) end
+		end,
+		keyreleased = function (b,s)
+			if love.keyreleased then return love.keyreleased(b,s) end
+		end,
+		textinput = function (t)
+			if love.textinput then return love.textinput(t) end
+		end,
+		textedited = function (t,s,l)
+			if love.textedited then return love.textedited(t,s,l) end
+		end,
+		mousemoved = function (x,y,dx,dy,t)
+			if love.mousemoved then return love.mousemoved(x,y,dx,dy,t) end
+		end,
+		mousepressed = function (x,y,b,t,c)
+			if love.mousepressed then return love.mousepressed(x,y,b,t,c) end
+		end,
+		mousereleased = function (x,y,b,t,c)
+			if love.mousereleased then return love.mousereleased(x,y,b,t,c) end
+		end,
+		wheelmoved = function (x,y)
+			if love.wheelmoved then return love.wheelmoved(x,y) end
+		end,
+		touchpressed = function (id,x,y,dx,dy,p)
+			if love.touchpressed then return love.touchpressed(id,x,y,dx,dy,p) end
+		end,
+		touchreleased = function (id,x,y,dx,dy,p)
+			if love.touchreleased then return love.touchreleased(id,x,y,dx,dy,p) end
+		end,
+		touchmoved = function (id,x,y,dx,dy,p)
+			if love.touchmoved then return love.touchmoved(id,x,y,dx,dy,p) end
+		end,
+		joystickpressed = function (j,b)
+			if love.joystickpressed then return love.joystickpressed(j,b) end
+		end,
+		joystickreleased = function (j,b)
+			if love.joystickreleased then return love.joystickreleased(j,b) end
+		end,
+		joystickaxis = function (j,a,v)
+			if love.joystickaxis then return love.joystickaxis(j,a,v) end
+		end,
+		joystickhat = function (j,h,v)
+			if love.joystickhat then return love.joystickhat(j,h,v) end
+		end,
+		gamepadpressed = function (j,b)
+			if love.gamepadpressed then return love.gamepadpressed(j,b) end
+		end,
+		gamepadreleased = function (j,b)
+			if love.gamepadreleased then return love.gamepadreleased(j,b) end
+		end,
+		gamepadaxis = function (j,a,v)
+			if love.gamepadaxis then return love.gamepadaxis(j,a,v) end
+		end,
+		joystickadded = function (j)
+			if love.joystickadded then return love.joystickadded(j) end
+		end,
+		joystickremoved = function (j)
+			if love.joystickremoved then return love.joystickremoved(j) end
+		end,
+		focus = function (f)
+			if love.focus then return love.focus(f) end
+		end,
+		mousefocus = function (f)
+			if love.mousefocus then return love.mousefocus(f) end
+		end,
+		visible = function (v)
+			if love.visible then return love.visible(v) end
+		end,
+		quit = function ()
+			return
+		end,
+		threaderror = function (t, err)
+			if love.threaderror then return love.threaderror(t, err) end
+		end,
+		resize = function (w, h)
+			if love.resize then return love.resize(w, h) end
+		end,
+		filedropped = function (f)
+			if love.filedropped then return love.filedropped(f) end
+		end,
+		directorydropped = function (dir)
+			if love.directorydropped then return love.directorydropped(dir) end
+		end,
+		lowmemory = function ()
+			if love.lowmemory then love.lowmemory() end
+			collectgarbage()
+			collectgarbage()
+		end,
+		displayrotated = function (display, orient)
+			if love.displayrotated then return love.displayrotated(display, orient) end
+		end,
+	}, {
+		__index = function(self, name)
+			error("Unknown event: " .. name)
+		end,
+	})
+
+end
+
+-----------------------------------------------------------
+-- Default callbacks.
+-----------------------------------------------------------
+
+function love.run()
+	if love.load then love.load(love.parsedGameArguments, love.rawGameArguments) end
+
+	-- We don't want the first frame's dt to include time taken by love.load.
+	if love.timer then love.timer.step() end
+
+	-- Main loop time.
+	return function()
+		-- Process events.
+		if love.event then
+			love.event.pump()
+			for name, a,b,c,d,e,f in love.event.poll() do
+				if name == "quit" then
+					if not love.quit or not love.quit() then
+						return a or 0, b
+					end
+				end
+				love.handlers[name](a,b,c,d,e,f)
+			end
+		end
+
+		-- Update dt, as we'll be passing it to update
+		local dt = love.timer and love.timer.step() or 0
+
+		-- Call update and draw
+		if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
+
+		if love.graphics and love.graphics.isActive() then
+			love.graphics.origin()
+			love.graphics.clear(love.graphics.getBackgroundColor())
+
+			if love.draw then love.draw() end
+
+			love.graphics.present()
+		end
+
+		if love.timer then love.timer.sleep(0.001) end
+	end
+end
+
+local debug, print, tostring, error = debug, print, tostring, error
+
+function love.threaderror(t, err)
+	error("Thread error ("..tostring(t)..")\n\n"..err, 0)
+end
+
+local utf8 = require("utf8")
+
+local function error_printer(msg, layer)
+	print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
+end
+
+function love.errhand(msg)
+	msg = tostring(msg)
+
+	error_printer(msg, 2)
+
+	if not love.window or not love.graphics or not love.event then
+		return
+	end
+
+	if not love.graphics.isCreated() or not love.window.isOpen() then
+		local success, status = pcall(love.window.setMode, 800, 600)
+		if not success or not status then
+			return
+		end
+	end
+
+	-- Reset state.
+	if love.mouse then
+		love.mouse.setVisible(true)
+		love.mouse.setGrabbed(false)
+		love.mouse.setRelativeMode(false)
+		if love.mouse.isCursorSupported() then
+			love.mouse.setCursor()
+		end
+	end
+	if love.joystick then
+		-- Stop all joystick vibrations.
+		for i,v in ipairs(love.joystick.getJoysticks()) do
+			v:setVibration()
+		end
+	end
+	if love.audio then love.audio.stop() end
+
+	love.graphics.reset()
+	local font = love.graphics.setNewFont(14)
+
+	love.graphics.setColor(1, 1, 1)
+
+	local trace = debug.traceback()
+
+	love.graphics.origin()
+
+	local sanitizedmsg = {}
+	for char in msg:gmatch(utf8.charpattern) do
+		table.insert(sanitizedmsg, char)
+	end
+	sanitizedmsg = table.concat(sanitizedmsg)
+
+	local err = {}
+
+	table.insert(err, "Error\n")
+	table.insert(err, sanitizedmsg)
+
+	if #sanitizedmsg ~= #msg then
+		table.insert(err, "Invalid UTF-8 string in error message.")
+	end
+
+	table.insert(err, "\n")
+
+	for l in trace:gmatch("(.-)\n") do
+		if not l:match("boot.lua") then
+			l = l:gsub("stack traceback:", "Traceback\n")
+			table.insert(err, l)
+		end
+	end
+
+	local p = table.concat(err, "\n")
+
+	p = p:gsub("\t", "")
+	p = p:gsub("%[string \"(.-)\"%]", "%1")
+
+	local function draw()
+		if not love.graphics.isActive() then return end
+		local pos = 70
+		love.graphics.clear(89/255, 157/255, 220/255)
+		love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
+		love.graphics.present()
+	end
+
+	local fullErrorText = p
+	local function copyToClipboard()
+		if not love.system then return end
+		love.system.setClipboardText(fullErrorText)
+		p = p .. "\nCopied to clipboard!"
+	end
+
+	if love.system then
+		p = p .. "\n\nPress Ctrl+C or tap to copy this error"
+	end
+
+	return function()
+		love.event.pump()
+
+		for e, a, b, c in love.event.poll() do
+			if e == "quit" then
+				return 1
+			elseif e == "keypressed" and a == "escape" then
+				return 1
+			elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
+				copyToClipboard()
+			elseif e == "touchpressed" then
+				local name = love.window.getTitle()
+				if #name == 0 or name == "Untitled" then name = "Game" end
+				local buttons = {"OK", "Cancel"}
+				if love.system then
+					buttons[3] = "Copy to clipboard"
+				end
+				local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
+				if pressed == 1 then
+					return 1
+				elseif pressed == 3 then
+					copyToClipboard()
+				end
+			end
+		end
+
+		draw()
+
+		if love.timer then
+			love.timer.sleep(0.1)
+		end
+	end
+
+end
+
+-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
+--)luastring"--"

+ 71 - 0
src/modules/love/jitsetup.lua

@@ -0,0 +1,71 @@
+R"luastring"--(
+-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
+-- There is a matching delimiter at the bottom of the file.
+
+--[[
+Copyright (c) 2006-2021 LOVE Development Team
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+--]]
+
+if type(jit) ~= "table" or not jit.status() then
+	return
+end
+
+-- Double the defaults.
+jit.opt.start("maxtrace=2000", "maxrecord=8000")
+
+-- Somewhat arbitrary value. Needs to be higher than the combined sizes below,
+-- and higher than the default (512) because that's already too low.
+jit.opt.start("maxmcode=16384")
+
+if jit.arch == "arm64" then
+	-- https://github.com/LuaJIT/LuaJIT/issues/285
+	-- LuaJIT 2.1 on arm64 currently (as of commit b4b2dce) can only use memory
+	-- for JIT compilation within a certain short range. Other libraries such as
+	-- SDL can take all the usable space in that range and cause attempts at JIT
+	-- compilation to both fail and take a long time.
+	-- This is a very hacky attempt at a workaround. LuaJIT allocates executable
+	-- code in pools. We'll try "reserving" pools before any external code is
+	-- executed, by causing JIT compilation via a small loop. We can't easily
+	-- tell if JIT compilation succeeded, so we do several successively smaller
+	-- pool allocations in case previous ones fail.
+	-- This is a really hacky hack and by no means foolproof - there are a lot of
+	-- potential situations (especially when threads are used) where previously
+	-- executed external code will still take up space that LuaJIT needed for itself.
+
+	jit.opt.start("sizemcode=2048")
+	for i=1, 100 do end
+	
+	jit.opt.start("sizemcode=1024")
+	for i=1, 100 do end
+	
+	jit.opt.start("sizemcode=512")
+	for i=1, 100 do end
+	
+	jit.opt.start("sizemcode=256")
+	for i=1, 100 do end
+	
+	jit.opt.start("sizemcode=128")
+	for i=1, 100 do end
+else
+	-- Somewhat arbitrary value (>= the default).
+	jit.opt.start("sizemcode=128")
+end
+
+-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
+--)luastring"--"

+ 96 - 9
src/modules/love/love.cpp

@@ -23,6 +23,7 @@
 #include "common/version.h"
 #include "common/version.h"
 #include "common/deprecation.h"
 #include "common/deprecation.h"
 #include "common/runtime.h"
 #include "common/runtime.h"
+#include "modules/window/Window.h"
 
 
 #include "love.h"
 #include "love.h"
 
 
@@ -32,10 +33,20 @@
 
 
 #ifdef LOVE_WINDOWS
 #ifdef LOVE_WINDOWS
 #include <windows.h>
 #include <windows.h>
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+// VS 2013 and earlier doesn't have snprintf
+#define snprintf sprintf_s
+#endif // defined(_MSC_VER) && (_MSC_VER < 1900)
+
 #endif // LOVE_WINDOWS
 #endif // LOVE_WINDOWS
 
 
 #ifdef LOVE_ANDROID
 #ifdef LOVE_ANDROID
 #include <SDL.h>
 #include <SDL.h>
+extern "C"
+{
+#include "luajit.h"
+}
 #endif // LOVE_ANDROID
 #endif // LOVE_ANDROID
 
 
 #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
 #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
@@ -75,9 +86,25 @@
 #	include "audio/Audio.h"
 #	include "audio/Audio.h"
 #endif
 #endif
 
 
-// Scripts
+// Scripts.
 #include "scripts/nogame.lua.h"
 #include "scripts/nogame.lua.h"
-#include "scripts/boot.lua.h"
+
+// Put the Lua code directly into a raw string literal.
+static const char arg_lua[] =
+#include "arg.lua"
+;
+
+static const char callbacks_lua[] =
+#include "callbacks.lua"
+;
+
+static const char boot_lua[] =
+#include "boot.lua"
+;
+
+static const char jit_setup_lua[] =
+#include "jitsetup.lua"
+;
 
 
 // All modules define a c-accessible luaopen
 // All modules define a c-accessible luaopen
 // so let's make use of those, instead
 // so let's make use of those, instead
@@ -142,6 +169,9 @@ extern "C"
 	extern int luaopen_love_window(lua_State*);
 	extern int luaopen_love_window(lua_State*);
 #endif
 #endif
 	extern int luaopen_love_nogame(lua_State*);
 	extern int luaopen_love_nogame(lua_State*);
+	extern int luaopen_love_jitsetup(lua_State*);
+	extern int luaopen_love_arg(lua_State*);
+	extern int luaopen_love_callbacks(lua_State*);
 	extern int luaopen_love_boot(lua_State*);
 	extern int luaopen_love_boot(lua_State*);
 }
 }
 
 
@@ -204,6 +234,9 @@ static const luaL_Reg modules[] = {
 	{ "love.window", luaopen_love_window },
 	{ "love.window", luaopen_love_window },
 #endif
 #endif
 	{ "love.nogame", luaopen_love_nogame },
 	{ "love.nogame", luaopen_love_nogame },
+	{ "love.jitsetup", luaopen_love_jitsetup },
+	{ "love.arg", luaopen_love_arg },
+	{ "love.callbacks", luaopen_love_callbacks },
 	{ "love.boot", luaopen_love_boot },
 	{ "love.boot", luaopen_love_boot },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
@@ -413,6 +446,15 @@ static void luax_addcompatibilityalias(lua_State *L, const char *module, const c
 
 
 int luaopen_love(lua_State *L)
 int luaopen_love(lua_State *L)
 {
 {
+	// Preload module loaders.
+	for (int i = 0; modules[i].name != nullptr; i++)
+		love::luax_preload(L, modules[i].func, modules[i].name);
+
+	// jitsetup is also loaded in the love executable runlove function. It's
+	// needed here too for threads. Note that it doesn't use the love table.
+	love::luax_require(L, "love.jitsetup");
+	lua_pop(L, 1);
+
 	love::luax_insistpinnedthread(L);
 	love::luax_insistpinnedthread(L);
 
 
 	love::luax_insistglobal(L, "love");
 	love::luax_insistglobal(L, "love");
@@ -432,6 +474,7 @@ int luaopen_love(lua_State *L)
 	lua_setfield(L, -2, "_version_codename");
 	lua_setfield(L, -2, "_version_codename");
 
 
 #ifdef LOVE_ANDROID
 #ifdef LOVE_ANDROID
+	luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF);
 	lua_register(L, "print", w_print_sdl_log);
 	lua_register(L, "print", w_print_sdl_log);
 #endif
 #endif
 
 
@@ -515,10 +558,6 @@ int luaopen_love(lua_State *L)
 		lua_setfield(L, -2, "hasDeprecationOutput");
 		lua_setfield(L, -2, "hasDeprecationOutput");
 	}
 	}
 
 
-	// Preload module loaders.
-	for (int i = 0; modules[i].name != nullptr; i++)
-		love::luax_preload(L, modules[i].func, modules[i].name);
-
 	// Necessary for Data-creating methods to work properly in Data subclasses.
 	// Necessary for Data-creating methods to work properly in Data subclasses.
 	love::luax_require(L, "love.data");
 	love::luax_require(L, "love.data");
 	lua_pop(L, 1);
 	lua_pop(L, 1);
@@ -540,6 +579,33 @@ int luaopen_love(lua_State *L)
 	love::luax_preload(L, luaopen_luautf8, "utf8");
 	love::luax_preload(L, luaopen_luautf8, "utf8");
 #endif
 #endif
 
 
+#ifdef LOVE_ENABLE_WINDOW
+	// In some environments, LuaJIT is limited to 2GB and LuaJIT sometimes panic when it
+	// reaches OOM and closes the whole program, leaving the user confused about what's
+	// going on.
+	// We can't recover the state at this point, but it's better to inform user that
+	// something very bad happening instead of silently exiting.
+	// Note that this is not foolproof. In some cases, the whole process crashes by
+	// uncaught exception that LuaJIT throws or simply exit as if calling
+	// love.event.quit("not enough memory")
+	lua_atpanic(L, [](lua_State *L)
+	{
+		using namespace love;
+		using namespace love::window;
+
+		char message[128];
+		Window* windowModule = Module::getInstance<Window>(Module::M_WINDOW);
+
+		snprintf(message, sizeof(message), "PANIC: unprotected error in call to Lua API (%s)", lua_tostring(L, -1));
+
+		if (windowModule)
+			windowModule->showMessageBox("Lua Fatal Error", message, Window::MESSAGEBOX_ERROR, windowModule->isOpen());
+
+		fprintf(stderr, "%s\n", message);
+		return 0;
+	});
+#endif
+
 	return 1;
 	return 1;
 }
 }
 
 
@@ -638,19 +704,40 @@ int w__setAccelerometerAsJoystick(lua_State *L)
 
 
 int luaopen_love_nogame(lua_State *L)
 int luaopen_love_nogame(lua_State *L)
 {
 {
-	if (luaL_loadbuffer(L, (const char *)love::nogame_lua, sizeof(love::nogame_lua), "nogame.lua") == 0)
+	if (luaL_loadbuffer(L, (const char *)love::nogame_lua, sizeof(love::nogame_lua), "=[love \"nogame.lua\"]") == 0)
 		lua_call(L, 0, 1);
 		lua_call(L, 0, 1);
 
 
 	return 1;
 	return 1;
 }
 }
 
 
-int luaopen_love_boot(lua_State *L)
+int luaopen_love_jitsetup(lua_State *L)
+{
+	if (luaL_loadbuffer(L, jit_setup_lua, sizeof(jit_setup_lua), "=[love \"jitsetup.lua\"]") == 0)
+		lua_call(L, 0, 1);
+
+	return 1;
+}
+
+int luaopen_love_arg(lua_State *L)
 {
 {
-	if (luaL_loadbuffer(L, (const char *)love::boot_lua, sizeof(love::boot_lua), "boot.lua") == 0)
+	if (luaL_loadbuffer(L, arg_lua, sizeof(arg_lua), "=[love \"arg.lua\"]") == 0)
 		lua_call(L, 0, 1);
 		lua_call(L, 0, 1);
 
 
 	return 1;
 	return 1;
 }
 }
 
 
+int luaopen_love_callbacks(lua_State *L)
+{
+	if (luaL_loadbuffer(L, callbacks_lua, sizeof(callbacks_lua), "=[love \"callbacks.lua\"]") == 0)
+		lua_call(L, 0, 1);
 
 
+	return 1;
+}
 
 
+int luaopen_love_boot(lua_State *L)
+{
+	if (luaL_loadbuffer(L, boot_lua, sizeof(boot_lua), "=[love \"boot.lua\"]") == 0)
+		lua_call(L, 0, 1);
+
+	return 1;
+}

+ 3 - 0
src/modules/love/love.h

@@ -36,6 +36,9 @@ LOVE_EXPORT const char *love_version();
 LOVE_EXPORT const char *love_codename();
 LOVE_EXPORT const char *love_codename();
 LOVE_EXPORT int luaopen_love(lua_State *L);
 LOVE_EXPORT int luaopen_love(lua_State *L);
 LOVE_EXPORT int luaopen_love_nogame(lua_State *L);
 LOVE_EXPORT int luaopen_love_nogame(lua_State *L);
+LOVE_EXPORT int luaopen_love_jitsetup(lua_State *L);
+LOVE_EXPORT int luaopen_love_arg(lua_State *L);
+LOVE_EXPORT int luaopen_love_callbacks(lua_State *L);
 LOVE_EXPORT int luaopen_love_boot(lua_State *L);
 LOVE_EXPORT int luaopen_love_boot(lua_State *L);
 
 
 #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
 #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK

+ 8 - 8
src/modules/math/MathModule.h

@@ -83,10 +83,10 @@ float linearToGamma(float c);
  *
  *
  * @return Noise value in the range of [0, 1].
  * @return Noise value in the range of [0, 1].
  **/
  **/
-static float noise1(float x);
-static float noise2(float x, float y);
-static float noise3(float x, float y, float z);
-static float noise4(float x, float y, float z, float w);
+static float noise1(double x);
+static float noise2(double x, double y);
+static float noise3(double x, double y, double z);
+static float noise4(double x, double y, double z, double w);
 
 
 
 
 class Math : public Module
 class Math : public Module
@@ -132,12 +132,12 @@ private:
 }; // Math
 }; // Math
 
 
 
 
-static inline float noise1(float x)
+static inline float noise1(double x)
 {
 {
 	return SimplexNoise1234::noise(x) * 0.5f + 0.5f;
 	return SimplexNoise1234::noise(x) * 0.5f + 0.5f;
 }
 }
 
 
-static inline float noise2(float x, float y)
+static inline float noise2(double x, double y)
 {
 {
 	return SimplexNoise1234::noise(x, y) * 0.5f + 0.5f;
 	return SimplexNoise1234::noise(x, y) * 0.5f + 0.5f;
 }
 }
@@ -145,12 +145,12 @@ static inline float noise2(float x, float y)
 // Perlin noise is used instead of Simplex noise in the 3D and 4D cases to avoid
 // Perlin noise is used instead of Simplex noise in the 3D and 4D cases to avoid
 // patent issues.
 // patent issues.
 
 
-static inline float noise3(float x, float y, float z)
+static inline float noise3(double x, double y, double z)
 {
 {
 	return Noise1234::noise(x, y, z) * 0.5f + 0.5f;
 	return Noise1234::noise(x, y, z) * 0.5f + 0.5f;
 }
 }
 
 
-static inline float noise4(float x, float y, float z, float w)
+static inline float noise4(double x, double y, double z, double w)
 {
 {
 	return Noise1234::noise(x, y, z, w) * 0.5f + 0.5f;
 	return Noise1234::noise(x, y, z, w) * 0.5f + 0.5f;
 }
 }

+ 7 - 7
src/modules/math/wrap_Math.cpp

@@ -319,10 +319,10 @@ int w_linearToGamma(lua_State *L)
 int w_noise(lua_State *L)
 int w_noise(lua_State *L)
 {
 {
 	int nargs = std::min(std::max(lua_gettop(L), 1), 4);
 	int nargs = std::min(std::max(lua_gettop(L), 1), 4);
-	float args[4];
+	double args[4];
 
 
 	for (int i = 0; i < nargs; i++)
 	for (int i = 0; i < nargs; i++)
-		args[i] = (float) luaL_checknumber(L, i + 1);
+		args[i] = luaL_checknumber(L, i + 1);
 
 
 	float val = 0.0f;
 	float val = 0.0f;
 
 
@@ -349,10 +349,10 @@ int w_noise(lua_State *L)
 // C functions in a struct, necessary for the FFI versions of math functions.
 // C functions in a struct, necessary for the FFI versions of math functions.
 struct FFI_Math
 struct FFI_Math
 {
 {
-	float (*noise1)(float x);
-	float (*noise2)(float x, float y);
-	float (*noise3)(float x, float y, float z);
-	float (*noise4)(float x, float y, float z, float w);
+	float (*noise1)(double x);
+	float (*noise2)(double x, double y);
+	float (*noise3)(double x, double y, double z);
+	float (*noise4)(double x, double y, double z, double w);
 
 
 	float (*gammaToLinear)(float c);
 	float (*gammaToLinear)(float c);
 	float (*linearToGamma)(float c);
 	float (*linearToGamma)(float c);
@@ -415,7 +415,7 @@ extern "C" int luaopen_love_math(lua_State *L)
 	int n = luax_register_module(L, w);
 	int n = luax_register_module(L, w);
 
 
 	// Execute wrap_Math.lua, sending the math table and ffifuncs pointer as args.
 	// Execute wrap_Math.lua, sending the math table and ffifuncs pointer as args.
-	luaL_loadbuffer(L, math_lua, sizeof(math_lua), "wrap_Math.lua");
+	luaL_loadbuffer(L, math_lua, sizeof(math_lua), "=[love \"wrap_Math.lua\"]");
 	lua_pushvalue(L, -2);
 	lua_pushvalue(L, -2);
 	luax_pushpointerasstring(L, &ffifuncs);
 	luax_pushpointerasstring(L, &ffifuncs);
 	lua_call(L, 2, 0);
 	lua_call(L, 2, 0);

+ 4 - 4
src/modules/math/wrap_Math.lua

@@ -93,10 +93,10 @@ if not status then return end
 pcall(ffi.cdef, [[
 pcall(ffi.cdef, [[
 typedef struct FFI_Math
 typedef struct FFI_Math
 {
 {
-	float (*noise1)(float x);
-	float (*noise2)(float x, float y);
-	float (*noise3)(float x, float y, float z);
-	float (*noise4)(float x, float y, float z, float w);
+	float (*noise1)(double x);
+	float (*noise2)(double x, double y);
+	float (*noise3)(double x, double y, double z);
+	float (*noise4)(double x, double y, double z, double w);
 
 
 	float (*gammaToLinear)(float c);
 	float (*gammaToLinear)(float c);
 	float (*linearToGamma)(float c);
 	float (*linearToGamma)(float c);

+ 2 - 1
src/modules/physics/box2d/RevoluteJoint.cpp

@@ -101,8 +101,9 @@ float RevoluteJoint::getMotorSpeed() const
 	return joint->GetMotorSpeed();
 	return joint->GetMotorSpeed();
 }
 }
 
 
-float RevoluteJoint::getMotorTorque(float inv_dt) const
+float RevoluteJoint::getMotorTorque(float dt) const
 {
 {
+	float inv_dt = 1.0f / dt;
 	return Physics::scaleUp(Physics::scaleUp(joint->GetMotorTorque(inv_dt)));
 	return Physics::scaleUp(Physics::scaleUp(joint->GetMotorTorque(inv_dt)));
 }
 }
 
 

+ 2 - 2
src/modules/physics/box2d/RevoluteJoint.h

@@ -87,9 +87,9 @@ public:
 
 
 	/**
 	/**
 	 * Get the current motor torque, usually in N-m.
 	 * Get the current motor torque, usually in N-m.
-	 * @param inv_dt The inverse timestep.
+	 * @param dt The timestep.
 	 **/
 	 **/
-	float getMotorTorque(float inv_dt) const;
+	float getMotorTorque(float dt) const;
 
 
 	/**
 	/**
 	 * Get the maximum motor torque, usually in N-m.
 	 * Get the maximum motor torque, usually in N-m.

+ 2 - 2
src/modules/physics/box2d/wrap_RevoluteJoint.cpp

@@ -91,8 +91,8 @@ int w_RevoluteJoint_getMotorSpeed(lua_State *L)
 int w_RevoluteJoint_getMotorTorque(lua_State *L)
 int w_RevoluteJoint_getMotorTorque(lua_State *L)
 {
 {
 	RevoluteJoint *t = luax_checkrevolutejoint(L, 1);
 	RevoluteJoint *t = luax_checkrevolutejoint(L, 1);
-	float inv_dt = (float)luaL_checknumber(L, 2);
-	lua_pushnumber(L, t->getMotorTorque(inv_dt));
+	float dt = (float)luaL_checknumber(L, 2);
+	lua_pushnumber(L, t->getMotorTorque(dt));
 	return 1;
 	return 1;
 }
 }
 
 

+ 18 - 5
src/modules/video/theora/OggDemuxer.cpp

@@ -43,7 +43,7 @@ OggDemuxer::~OggDemuxer()
 	ogg_sync_clear(&sync);
 	ogg_sync_clear(&sync);
 }
 }
 
 
-void OggDemuxer::readPage()
+bool OggDemuxer::readPage(bool erroreof)
 {
 {
 	char *syncBuffer = nullptr;
 	char *syncBuffer = nullptr;
 	while (ogg_sync_pageout(&sync, &page) != 1)
 	while (ogg_sync_pageout(&sync, &page) != 1)
@@ -53,8 +53,13 @@ void OggDemuxer::readPage()
 
 
 		syncBuffer = ogg_sync_buffer(&sync, 8192);
 		syncBuffer = ogg_sync_buffer(&sync, 8192);
 		size_t read = file->read(syncBuffer, 8192);
 		size_t read = file->read(syncBuffer, 8192);
+		if (read == 0 && erroreof)
+			return false;
+
 		ogg_sync_wrote(&sync, read);
 		ogg_sync_wrote(&sync, read);
 	}
 	}
+
+	return true;
 }
 }
 
 
 bool OggDemuxer::readPacket(ogg_packet &packet, bool mustSucceed)
 bool OggDemuxer::readPacket(ogg_packet &packet, bool mustSucceed)
@@ -118,22 +123,25 @@ OggDemuxer::StreamType OggDemuxer::findStream()
 	if (streamInited)
 	if (streamInited)
 	{
 	{
 		eos = false;
 		eos = false;
+		streamInited = false;
 		file->seek(0);
 		file->seek(0);
 		ogg_stream_clear(&stream);
 		ogg_stream_clear(&stream);
 		ogg_sync_reset(&sync);
 		ogg_sync_reset(&sync);
 	}
 	}
 
 
-	streamInited = true;
 	while (true)
 	while (true)
 	{
 	{
+		if (!readPage(true))
+			return TYPE_UNKNOWN;
+
 		// If this page isn't at the start of a stream, we've seen all streams
 		// If this page isn't at the start of a stream, we've seen all streams
-		readPage();
 		if (!ogg_page_bos(&page))
 		if (!ogg_page_bos(&page))
 			break;
 			break;
 
 
 		videoSerial = ogg_page_serialno(&page);
 		videoSerial = ogg_page_serialno(&page);
 		ogg_stream_init(&stream, videoSerial);
 		ogg_stream_init(&stream, videoSerial);
 		ogg_stream_pagein(&stream, &page);
 		ogg_stream_pagein(&stream, &page);
+		streamInited = true;
 
 
 		StreamType type = determineType();
 		StreamType type = determineType();
 		switch(type)
 		switch(type)
@@ -145,10 +153,15 @@ OggDemuxer::StreamType OggDemuxer::findStream()
 		}
 		}
 
 
 		ogg_stream_clear(&stream);
 		ogg_stream_clear(&stream);
+		streamInited = false;
+	}
+
+	if (streamInited)
+	{
+		streamInited = false;
+		ogg_stream_clear(&stream);
 	}
 	}
 
 
-	streamInited = false;
-	ogg_stream_clear(&stream);
 	ogg_sync_reset(&sync);
 	ogg_sync_reset(&sync);
 
 
 	return TYPE_UNKNOWN;
 	return TYPE_UNKNOWN;

+ 1 - 1
src/modules/video/theora/OggDemuxer.h

@@ -67,7 +67,7 @@ private:
 	int videoSerial;
 	int videoSerial;
 	bool eos;
 	bool eos;
 
 
-	void readPage();
+	bool readPage(bool erroreof = false);
 	StreamType determineType();
 	StreamType determineType();
 }; // OggDemuxer
 }; // OggDemuxer
 
 

+ 0 - 814
src/scripts/boot.lua

@@ -1,814 +0,0 @@
---[[
-Copyright (c) 2006-2021 LOVE Development Team
-
-This software is provided 'as-is', without any express or implied
-warranty.  In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-   claim that you wrote the original software. If you use this software
-   in a product, an acknowledgment in the product documentation would be
-   appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-   misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
---]]
-
--- Make sure love exists.
-local love = require("love")
-
--- Used for setup:
-love.path = {}
-love.arg = {}
-
--- Replace any \ with /.
-function love.path.normalslashes(p)
-	return p:gsub("\\", "/")
-end
-
--- Makes sure there is a slash at the end
--- of a path.
-function love.path.endslash(p)
-	if p:sub(-1) ~= "/" then
-		return p .. "/"
-	else
-		return p
-	end
-end
-
--- Checks whether a path is absolute or not.
-function love.path.abs(p)
-
-	local tmp = love.path.normalslashes(p)
-
-	-- Path is absolute if it starts with a "/".
-	if tmp:find("/") == 1 then
-		return true
-	end
-
-	-- Path is absolute if it starts with a
-	-- letter followed by a colon.
-	if tmp:find("%a:") == 1 then
-		return true
-	end
-
-	-- Relative.
-	return false
-
-end
-
--- Converts any path into a full path.
-function love.path.getFull(p)
-
-	if love.path.abs(p) then
-		return love.path.normalslashes(p)
-	end
-
-	local cwd = love.filesystem.getWorkingDirectory()
-	cwd = love.path.normalslashes(cwd)
-	cwd = love.path.endslash(cwd)
-
-	-- Construct a full path.
-	local full = cwd .. love.path.normalslashes(p)
-
-	-- Remove trailing /., if applicable
-	return full:match("(.-)/%.$") or full
-end
-
--- Returns the leaf of a full path.
-function love.path.leaf(p)
-	p = love.path.normalslashes(p)
-
-	local a = 1
-	local last = p
-
-	while a do
-		a = p:find("/", a+1)
-
-		if a then
-			last = p:sub(a+1)
-		end
-	end
-
-	return last
-end
-
--- Finds the key in the table with the lowest integral index. The lowest
--- will typically the executable, for instance "lua5.1.exe".
-function love.arg.getLow(a)
-	local m = math.huge
-	for k,v in pairs(a) do
-		if k < m then
-			m = k
-		end
-	end
-	return a[m], m
-end
-
-love.arg.options = {
-	console = { a = 0 },
-	fused = {a = 0 },
-	game = { a = 1 }
-}
-
-love.arg.optionIndices = {}
-
-function love.arg.parseOption(m, i)
-	m.set = true
-
-	if m.a > 0 then
-		m.arg = {}
-		for j=i,i+m.a-1 do
-			love.arg.optionIndices[j] = true
-			table.insert(m.arg, arg[j])
-		end
-	end
-
-	return m.a
-end
-
-function love.arg.parseOptions(arg)
-
-	local game
-	local argc = #arg
-
-	local i = 1
-	while i <= argc do
-		-- Look for options.
-		local m = arg[i]:match("^%-%-(.*)")
-
-		if m and m ~= "" and love.arg.options[m] and not love.arg.options[m].set then
-			love.arg.optionIndices[i] = true
-			i = i + love.arg.parseOption(love.arg.options[m], i+1)
-		elseif m == "" then -- handle '--' as an option
-			love.arg.optionIndices[i] = true
-			if not game then -- handle '--' followed by game name
-				game = i + 1
-			end
-			break
-		elseif not game then
-			game = i
-		end
-		i = i + 1
-	end
-
-	if not love.arg.options.game.set then
-		love.arg.parseOption(love.arg.options.game, game or 0)
-	end
-end
-
--- Returns the arguments that are passed to your game via love.load()
--- arguments that were parsed as options are skipped.
-function love.arg.parseGameArguments(a)
-	local out = {}
-
-	local _, lowindex = love.arg.getLow(a)
-
-	local o = lowindex
-	for i=lowindex, #a do
-		if not love.arg.optionIndices[i] then
-			out[o] = a[i]
-			o = o + 1
-		end
-	end
-
-	return out
-end
-
-function love.createhandlers()
-
-	-- Standard callback handlers.
-	love.handlers = setmetatable({
-		keypressed = function (b,s,r)
-			if love.keypressed then return love.keypressed(b,s,r) end
-		end,
-		keyreleased = function (b,s)
-			if love.keyreleased then return love.keyreleased(b,s) end
-		end,
-		textinput = function (t)
-			if love.textinput then return love.textinput(t) end
-		end,
-		textedited = function (t,s,l)
-			if love.textedited then return love.textedited(t,s,l) end
-		end,
-		mousemoved = function (x,y,dx,dy,t)
-			if love.mousemoved then return love.mousemoved(x,y,dx,dy,t) end
-		end,
-		mousepressed = function (x,y,b,t,c)
-			if love.mousepressed then return love.mousepressed(x,y,b,t,c) end
-		end,
-		mousereleased = function (x,y,b,t,c)
-			if love.mousereleased then return love.mousereleased(x,y,b,t,c) end
-		end,
-		wheelmoved = function (x,y)
-			if love.wheelmoved then return love.wheelmoved(x,y) end
-		end,
-		touchpressed = function (id,x,y,dx,dy,p)
-			if love.touchpressed then return love.touchpressed(id,x,y,dx,dy,p) end
-		end,
-		touchreleased = function (id,x,y,dx,dy,p)
-			if love.touchreleased then return love.touchreleased(id,x,y,dx,dy,p) end
-		end,
-		touchmoved = function (id,x,y,dx,dy,p)
-			if love.touchmoved then return love.touchmoved(id,x,y,dx,dy,p) end
-		end,
-		joystickpressed = function (j,b)
-			if love.joystickpressed then return love.joystickpressed(j,b) end
-		end,
-		joystickreleased = function (j,b)
-			if love.joystickreleased then return love.joystickreleased(j,b) end
-		end,
-		joystickaxis = function (j,a,v)
-			if love.joystickaxis then return love.joystickaxis(j,a,v) end
-		end,
-		joystickhat = function (j,h,v)
-			if love.joystickhat then return love.joystickhat(j,h,v) end
-		end,
-		gamepadpressed = function (j,b)
-			if love.gamepadpressed then return love.gamepadpressed(j,b) end
-		end,
-		gamepadreleased = function (j,b)
-			if love.gamepadreleased then return love.gamepadreleased(j,b) end
-		end,
-		gamepadaxis = function (j,a,v)
-			if love.gamepadaxis then return love.gamepadaxis(j,a,v) end
-		end,
-		joystickadded = function (j)
-			if love.joystickadded then return love.joystickadded(j) end
-		end,
-		joystickremoved = function (j)
-			if love.joystickremoved then return love.joystickremoved(j) end
-		end,
-		focus = function (f)
-			if love.focus then return love.focus(f) end
-		end,
-		mousefocus = function (f)
-			if love.mousefocus then return love.mousefocus(f) end
-		end,
-		visible = function (v)
-			if love.visible then return love.visible(v) end
-		end,
-		quit = function ()
-			return
-		end,
-		threaderror = function (t, err)
-			if love.threaderror then return love.threaderror(t, err) end
-		end,
-		resize = function (w, h)
-			if love.resize then return love.resize(w, h) end
-		end,
-		filedropped = function (f)
-			if love.filedropped then return love.filedropped(f) end
-		end,
-		directorydropped = function (dir)
-			if love.directorydropped then return love.directorydropped(dir) end
-		end,
-		lowmemory = function ()
-			if love.lowmemory then love.lowmemory() end
-			collectgarbage()
-			collectgarbage()
-		end,
-		displayrotated = function (display, orient)
-			if love.displayrotated then return love.displayrotated(display, orient) end
-		end,
-	}, {
-		__index = function(self, name)
-			error("Unknown event: " .. name)
-		end,
-	})
-
-end
-
-local function uridecode(s)
-	return s:gsub("%%%x%x", function(str)
-		return string.char(tonumber(str:sub(2), 16))
-	end)
-end
-
-local no_game_code = false
-local invalid_game_path = nil
-
--- This can't be overridden.
-function love.boot()
-
-	-- This is absolutely needed.
-	require("love.filesystem")
-
-	love.rawGameArguments = arg
-
-	local arg0 = love.arg.getLow(love.rawGameArguments)
-	love.filesystem.init(arg0)
-
-	local exepath = love.filesystem.getExecutablePath()
-	if #exepath == 0 then
-		-- This shouldn't happen, but just in case we'll fall back to arg0.
-		exepath = arg0
-	end
-
-	no_game_code = false
-	invalid_game_path = nil
-
-	-- Is this one of those fancy "fused" games?
-	local can_has_game = pcall(love.filesystem.setSource, exepath)
-
-	-- It's a fused game, don't parse --game argument
-	if can_has_game then
-		love.arg.options.game.set = true
-	end
-
-	-- Parse options now that we know which options we're looking for.
-	love.arg.parseOptions(love.rawGameArguments)
-
-	-- parseGameArguments can only be called after parseOptions.
-	love.parsedGameArguments = love.arg.parseGameArguments(love.rawGameArguments)
-
-	local o = love.arg.options
-
-	local is_fused_game = can_has_game or love.arg.options.fused.set
-
-	love.filesystem.setFused(is_fused_game)
-
-	love.setDeprecationOutput(not love.filesystem.isFused())
-
-	local identity = ""
-	if not can_has_game and o.game.set and o.game.arg[1] then
-		local nouri = o.game.arg[1]
-
-		if nouri:sub(1, 7) == "file://" then
-			nouri = uridecode(nouri:sub(8))
-		end
-
-		local full_source = love.path.getFull(nouri)
-		can_has_game = pcall(love.filesystem.setSource, full_source)
-
-		if not can_has_game then
-			invalid_game_path = full_source
-		end
-
-		-- Use the name of the source .love as the identity for now.
-		identity = love.path.leaf(full_source)
-	else
-		-- Use the name of the exe as the identity for now.
-		identity = love.path.leaf(exepath)
-	end
-
-	-- Try to use the archive containing main.lua as the identity name. It
-	-- might not be available, in which case the fallbacks above are used.
-	local realdir = love.filesystem.getRealDirectory("main.lua")
-	if realdir then
-		identity = love.path.leaf(realdir)
-	end
-
-	identity = identity:gsub("^([%.]+)", "") -- strip leading "."'s
-	identity = identity:gsub("%.([^%.]+)$", "") -- strip extension
-	identity = identity:gsub("%.", "_") -- replace remaining "."'s with "_"
-	identity = #identity > 0 and identity or "lovegame"
-
-	-- When conf.lua is initially loaded, the main source should be checked
-	-- before the save directory (the identity should be appended.)
-	pcall(love.filesystem.setIdentity, identity, true)
-
-	if can_has_game and not (love.filesystem.getInfo("main.lua") or love.filesystem.getInfo("conf.lua")) then
-		no_game_code = true
-	end
-
-	if not can_has_game then
-		local nogame = require("love.nogame")
-		nogame()
-	end
-end
-
-function love.init()
-
-	-- Create default configuration settings.
-	-- NOTE: Adding a new module to the modules list
-	-- will NOT make it load, see below.
-	local c = {
-		title = "Untitled",
-		version = love._version,
-		window = {
-			width = 800,
-			height = 600,
-			x = nil,
-			y = nil,
-			minwidth = 1,
-			minheight = 1,
-			fullscreen = false,
-			fullscreentype = "desktop",
-			display = 1,
-			vsync = 1,
-			msaa = 0,
-			borderless = false,
-			resizable = false,
-			centered = true,
-			usedpiscale = true,
-		},
-		modules = {
-			data = true,
-			event = true,
-			keyboard = true,
-			mouse = true,
-			timer = true,
-			joystick = true,
-			touch = true,
-			image = true,
-			graphics = true,
-			audio = true,
-			math = true,
-			physics = true,
-			sound = true,
-			system = true,
-			font = true,
-			thread = true,
-			window = true,
-			video = true,
-		},
-		audio = {
-			mixwithsystem = true, -- Only relevant for Android / iOS.
-			mic = false, -- Only relevant for Android.
-		},
-		console = false, -- Only relevant for windows.
-		identity = false,
-		appendidentity = false,
-		externalstorage = false, -- Only relevant for Android.
-		accelerometerjoystick = true, -- Only relevant for Android / iOS.
-		gammacorrect = false,
-		highdpi = false,
-	}
-
-	-- Console hack, part 1.
-	local openedconsole = false
-	if love.arg.options.console.set and love._openConsole then
-		love._openConsole()
-		openedconsole = true
-	end
-
-	-- If config file exists, load it and allow it to update config table.
-	local confok, conferr
-	if (not love.conf) and love.filesystem and love.filesystem.getInfo("conf.lua") then
-		confok, conferr = pcall(require, "conf")
-	end
-
-	-- Yes, conf.lua might not exist, but there are other ways of making
-	-- love.conf appear, so we should check for it anyway.
-	if love.conf then
-		confok, conferr = pcall(love.conf, c)
-		-- If love.conf errors, we'll trigger the error after loading modules so
-		-- the error message can be displayed in the window.
-	end
-
-	-- Console hack, part 2.
-	if c.console and love._openConsole and not openedconsole then
-		love._openConsole()
-	end
-
-	-- Hack for disabling accelerometer-as-joystick on Android / iOS.
-	if love._setAccelerometerAsJoystick then
-		love._setAccelerometerAsJoystick(c.accelerometerjoystick)
-	end
-
-	if love._setGammaCorrect then
-		love._setGammaCorrect(c.gammacorrect)
-	end
-
-	if love._setHighDPIAllowed then
-		love._setHighDPIAllowed(c.highdpi)
-	end
-
-	if love._setAudioMixWithSystem then
-		if c.audio and c.audio.mixwithsystem ~= nil then
-			love._setAudioMixWithSystem(c.audio.mixwithsystem)
-		end
-	end
-
-	if love._requestRecordingPermission then
-		love._requestRecordingPermission(c.audio and c.audio.mic)
-	end
-
-	-- Gets desired modules.
-	for k,v in ipairs{
-		"data",
-		"thread",
-		"timer",
-		"event",
-		"keyboard",
-		"joystick",
-		"mouse",
-		"touch",
-		"sound",
-		"system",
-		"audio",
-		"image",
-		"video",
-		"font",
-		"window",
-		"graphics",
-		"math",
-		"physics",
-	} do
-		if c.modules[v] then
-			require("love." .. v)
-		end
-	end
-
-	if love.event then
-		love.createhandlers()
-	end
-
-	-- Check the version
-	c.version = tostring(c.version)
-	if not love.isVersionCompatible(c.version) then
-		local major, minor, revision = c.version:match("^(%d+)%.(%d+)%.(%d+)$")
-		if (not major or not minor or not revision) or (major ~= love._version_major and minor ~= love._version_minor) then
-			local msg = ("This game indicates it was made for version '%s' of LOVE.\n"..
-				"It may not be compatible with the running version (%s)."):format(c.version, love._version)
-
-			print(msg)
-
-			if love.window then
-				love.window.showMessageBox("Compatibility Warning", msg, "warning")
-			end
-		end
-	end
-
-	if not confok and conferr then
-		error(conferr)
-	end
-
-	-- Setup window here.
-	if c.window and c.modules.window then
-		love.window.setTitle(c.window.title or c.title)
-		assert(love.window.setMode(c.window.width, c.window.height,
-		{
-			fullscreen = c.window.fullscreen,
-			fullscreentype = c.window.fullscreentype,
-			vsync = c.window.vsync,
-			msaa = c.window.msaa,
-			stencil = c.window.stencil,
-			depth = c.window.depth,
-			resizable = c.window.resizable,
-			minwidth = c.window.minwidth,
-			minheight = c.window.minheight,
-			borderless = c.window.borderless,
-			centered = c.window.centered,
-			display = c.window.display,
-			highdpi = c.window.highdpi, -- deprecated
-			usedpiscale = c.window.usedpiscale,
-			x = c.window.x,
-			y = c.window.y,
-		}), "Could not set window mode")
-		if c.window.icon then
-			assert(love.image, "If an icon is set in love.conf, love.image must be loaded!")
-			love.window.setIcon(love.image.newImageData(c.window.icon))
-		end
-	end
-
-	-- Our first timestep, because window creation can take some time
-	if love.timer then
-		love.timer.step()
-	end
-
-	if love.filesystem then
-		love.filesystem._setAndroidSaveExternal(c.externalstorage)
-		love.filesystem.setIdentity(c.identity or love.filesystem.getIdentity(), c.appendidentity)
-		if love.filesystem.getInfo("main.lua") then
-			require("main")
-		end
-	end
-
-	if no_game_code then
-		error("No code to run\nYour game might be packaged incorrectly.\nMake sure main.lua is at the top level of the zip.")
-	elseif invalid_game_path then
-		error("Cannot load game at path '" .. invalid_game_path .. "'.\nMake sure a folder exists at the specified path.")
-	end
-end
-
------------------------------------------------------------
--- Default callbacks.
------------------------------------------------------------
-
-function love.run()
-	if love.load then love.load(love.parsedGameArguments, love.rawGameArguments) end
-
-	-- We don't want the first frame's dt to include time taken by love.load.
-	if love.timer then love.timer.step() end
-
-	-- Main loop time.
-	return function()
-		-- Process events.
-		if love.event then
-			love.event.pump()
-			for name, a,b,c,d,e,f in love.event.poll() do
-				if name == "quit" then
-					if not love.quit or not love.quit() then
-						return a or 0, b
-					end
-				end
-				love.handlers[name](a,b,c,d,e,f)
-			end
-		end
-
-		-- Update dt, as we'll be passing it to update
-		local dt = love.timer and love.timer.step() or 0
-
-		-- Call update and draw
-		if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
-
-		if love.graphics and love.graphics.isActive() then
-			love.graphics.origin()
-			love.graphics.clear(love.graphics.getBackgroundColor())
-
-			if love.draw then love.draw() end
-
-			love.graphics.present()
-		end
-
-		if love.timer then love.timer.sleep(0.001) end
-	end
-end
-
-local debug, print, error = debug, print, error
-
-function love.threaderror(t, err)
-	error("Thread error ("..tostring(t)..")\n\n"..err, 0)
-end
-
-local utf8 = require("utf8")
-
-local function error_printer(msg, layer)
-	print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
-end
-
-function love.errhand(msg)
-	msg = tostring(msg)
-
-	error_printer(msg, 2)
-
-	if not love.window or not love.graphics or not love.event then
-		return
-	end
-
-	if not love.graphics.isCreated() or not love.window.isOpen() then
-		local success, status = pcall(love.window.setMode, 800, 600)
-		if not success or not status then
-			return
-		end
-	end
-
-	-- Reset state.
-	if love.mouse then
-		love.mouse.setVisible(true)
-		love.mouse.setGrabbed(false)
-		love.mouse.setRelativeMode(false)
-		if love.mouse.isCursorSupported() then
-			love.mouse.setCursor()
-		end
-	end
-	if love.joystick then
-		-- Stop all joystick vibrations.
-		for i,v in ipairs(love.joystick.getJoysticks()) do
-			v:setVibration()
-		end
-	end
-	if love.audio then love.audio.stop() end
-
-	love.graphics.reset()
-	local font = love.graphics.setNewFont(14)
-
-	love.graphics.setColor(1, 1, 1)
-
-	local trace = debug.traceback()
-
-	love.graphics.origin()
-
-	local sanitizedmsg = {}
-	for char in msg:gmatch(utf8.charpattern) do
-		table.insert(sanitizedmsg, char)
-	end
-	sanitizedmsg = table.concat(sanitizedmsg)
-
-	local err = {}
-
-	table.insert(err, "Error\n")
-	table.insert(err, sanitizedmsg)
-
-	if #sanitizedmsg ~= #msg then
-		table.insert(err, "Invalid UTF-8 string in error message.")
-	end
-
-	table.insert(err, "\n")
-
-	for l in trace:gmatch("(.-)\n") do
-		if not l:match("boot.lua") then
-			l = l:gsub("stack traceback:", "Traceback\n")
-			table.insert(err, l)
-		end
-	end
-
-	local p = table.concat(err, "\n")
-
-	p = p:gsub("\t", "")
-	p = p:gsub("%[string \"(.-)\"%]", "%1")
-
-	local function draw()
-		local pos = 70
-		love.graphics.clear(89/255, 157/255, 220/255)
-		love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
-		love.graphics.present()
-	end
-
-	local fullErrorText = p
-	local function copyToClipboard()
-		if not love.system then return end
-		love.system.setClipboardText(fullErrorText)
-		p = p .. "\nCopied to clipboard!"
-		draw()
-	end
-
-	if love.system then
-		p = p .. "\n\nPress Ctrl+C or tap to copy this error"
-	end
-
-	return function()
-		love.event.pump()
-
-		for e, a, b, c in love.event.poll() do
-			if e == "quit" then
-				return 1
-			elseif e == "keypressed" and a == "escape" then
-				return 1
-			elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
-				copyToClipboard()
-			elseif e == "touchpressed" then
-				local name = love.window.getTitle()
-				if #name == 0 or name == "Untitled" then name = "Game" end
-				local buttons = {"OK", "Cancel"}
-				if love.system then
-					buttons[3] = "Copy to clipboard"
-				end
-				local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
-				if pressed == 1 then
-					return 1
-				elseif pressed == 3 then
-					copyToClipboard()
-				end
-			end
-		end
-
-		draw()
-
-		if love.timer then
-			love.timer.sleep(0.1)
-		end
-	end
-
-end
-
------------------------------------------------------------
--- The root of all calls.
------------------------------------------------------------
-
-return function()
-	local func
-	local inerror = false
-
-	local function deferErrhand(...)
-		local errhand = love.errorhandler or love.errhand
-		local handler = (not inerror and errhand) or error_printer
-		inerror = true
-		func = handler(...)
-	end
-
-	local function earlyinit()
-		-- If love.boot fails, return 1 and finish immediately
-		local result = xpcall(love.boot, error_printer)
-		if not result then return 1 end
-
-		-- If love.init or love.run fails, don't return a value,
-		-- as we want the error handler to take over
-		result = xpcall(love.init, deferErrhand)
-		if not result then return end
-
-		-- NOTE: We can't assign to func directly, as we'd
-		-- overwrite the result of deferErrhand with nil on error
-		local main
-		result, main = xpcall(love.run, deferErrhand)
-		if result then
-			func = main
-		end
-	end
-
-	func = earlyinit
-
-	while func do
-		local _, retval, restartvalue = xpcall(func, deferErrhand)
-		if retval then return retval, restartvalue end
-		coroutine.yield()
-	end
-
-	return 1
-end

+ 0 - 1617
src/scripts/boot.lua.h

@@ -1,1617 +0,0 @@
-/**
- * Copyright (c) 2006-2021 LOVE Development Team
- * 
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- * 
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- * 
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
-
-namespace love
-{
-
-// [boot.lua]
-const unsigned char boot_lua[] = 
-{
-
-	0x2d, 0x2d, 0x5b, 0x5b, 0x0a,
-	0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 
-	0x2d, 0x32, 0x30, 0x32, 0x31, 0x20, 0x4c, 0x4f, 0x56, 0x45, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 
-	0x6d, 0x65, 0x6e, 0x74, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x0a,
-	0x0a,
-	0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 
-	0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x27, 0x61, 0x73, 0x2d, 0x69, 0x73, 0x27, 0x2c, 0x20, 0x77, 
-	0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 
-	0x20, 0x6f, 0x72, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x0a,
-	0x77, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2e, 0x20, 0x20, 0x49, 0x6e, 0x20, 0x6e, 0x6f, 0x20, 0x65, 
-	0x76, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, 
-	0x6f, 0x72, 0x73, 0x20, 0x62, 0x65, 0x20, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 
-	0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x0a,
-	0x61, 0x72, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 
-	0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 
-	0x65, 0x2e, 0x0a,
-	0x0a,
-	0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x67, 0x72, 0x61, 0x6e, 
-	0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, 
-	0x73, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x66, 
-	0x6f, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x2c, 0x0a,
-	0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69, 
-	0x61, 0x6c, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 
-	0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 
-	0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, 0x74, 0x0a,
-	0x66, 0x72, 0x65, 0x65, 0x6c, 0x79, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 
-	0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x73, 
-	0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x0a,
-	0x0a,
-	0x31, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 
-	0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 
-	0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x69, 0x73, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 
-	0x74, 0x65, 0x64, 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x0a,
-	0x20, 0x20, 0x20, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 
-	0x77, 0x72, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 
-	0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 
-	0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0a,
-	0x20, 0x20, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2c, 0x20, 0x61, 
-	0x6e, 0x20, 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 
-	0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x20, 0x64, 0x6f, 0x63, 0x75, 
-	0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x0a,
-	0x20, 0x20, 0x20, 0x61, 0x70, 0x70, 0x72, 0x65, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x75, 0x74, 
-	0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x2e, 0x0a,
-	0x32, 0x2e, 0x20, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x70, 
-	0x6c, 0x61, 0x69, 0x6e, 0x6c, 0x79, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x73, 
-	0x75, 0x63, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 
-	0x62, 0x65, 0x0a,
-	0x20, 0x20, 0x20, 0x6d, 0x69, 0x73, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 
-	0x61, 0x73, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 
-	0x6e, 0x61, 0x6c, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x0a,
-	0x33, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x79, 
-	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x6f, 0x72, 
-	0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x79, 0x20, 
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 
-	0x6e, 0x2e, 0x0a,
-	0x2d, 0x2d, 0x5d, 0x5d, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x4d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20, 
-	0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x2e, 0x0a,
-	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 
-	0x72, 0x65, 0x28, 0x22, 0x6c, 0x6f, 0x76, 0x65, 0x22, 0x29, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x74, 0x75, 0x70, 0x3a, 0x0a,
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x5c, 0x20, 0x77, 
-	0x69, 0x74, 0x68, 0x20, 0x2f, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 
-	0x2e, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x28, 0x70, 0x29, 0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x5c, 
-	0x22, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x29, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x4d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 
-	0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 
-	0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x2d, 0x2d, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 
-	0x2e, 0x65, 0x6e, 0x64, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x28, 0x70, 0x29, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x70, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x2d, 0x31, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22, 
-	0x2f, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2f, 0x22, 0x0a,
-	0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 
-	0x61, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 
-	0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 
-	0x2e, 0x61, 0x62, 0x73, 0x28, 0x70, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x6d, 0x70, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x70, 0x61, 0x74, 0x68, 0x2e, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 
-	0x28, 0x70, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 
-	0x74, 0x65, 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x77, 0x69, 
-	0x74, 0x68, 0x20, 0x61, 0x20, 0x22, 0x2f, 0x22, 0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x74, 0x6d, 0x70, 0x3a, 0x66, 0x69, 0x6e, 0x64, 0x28, 0x22, 0x2f, 0x22, 0x29, 0x20, 
-	0x3d, 0x3d, 0x20, 0x31, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 
-	0x74, 0x65, 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x77, 0x69, 
-	0x74, 0x68, 0x20, 0x61, 0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 
-	0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6e, 0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x74, 0x6d, 0x70, 0x3a, 0x66, 0x69, 0x6e, 0x64, 0x28, 0x22, 0x25, 0x61, 0x3a, 0x22, 
-	0x29, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2e, 0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
-	0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x61, 
-	0x74, 0x68, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x70, 0x61, 0x74, 
-	0x68, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 
-	0x2e, 0x67, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x28, 0x70, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x61, 0x62, 0x73, 0x28, 
-	0x70, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 
-	0x2e, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x28, 0x70, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x77, 0x64, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 
-	0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x28, 0x29, 0x0a,
-	0x09, 0x63, 0x77, 0x64, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x6e, 
-	0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x28, 0x63, 0x77, 0x64, 0x29, 0x0a,
-	0x09, 0x63, 0x77, 0x64, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x65, 
-	0x6e, 0x64, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x28, 0x63, 0x77, 0x64, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x61, 0x20, 0x66, 0x75, 
-	0x6c, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x3d, 0x20, 0x63, 0x77, 0x64, 0x20, 
-	0x2e, 0x2e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 
-	0x6c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x28, 0x70, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 
-	0x67, 0x20, 0x2f, 0x2e, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 
-	0x65, 0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 
-	0x28, 0x22, 0x28, 0x2e, 0x2d, 0x29, 0x2f, 0x25, 0x2e, 0x24, 0x22, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x75, 
-	0x6c, 0x6c, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, 
-	0x66, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 
-	0x2e, 0x6c, 0x65, 0x61, 0x66, 0x28, 0x70, 0x29, 0x0a,
-	0x09, 0x70, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x6e, 0x6f, 0x72, 
-	0x6d, 0x61, 0x6c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x28, 0x70, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x31, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x70, 0x0a,
-	0x0a,
-	0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x61, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x61, 0x20, 0x3d, 0x20, 0x70, 0x3a, 0x66, 0x69, 0x6e, 0x64, 0x28, 0x22, 0x2f, 0x22, 0x2c, 0x20, 
-	0x61, 0x2b, 0x31, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x61, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x70, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x61, 0x2b, 
-	0x31, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x46, 0x69, 0x6e, 0x64, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 
-	0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 
-	0x68, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x6c, 
-	0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x73, 0x74, 0x0a,
-	0x2d, 0x2d, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x79, 0x70, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x20, 
-	0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x66, 0x6f, 
-	0x72, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x22, 0x6c, 0x75, 0x61, 0x35, 0x2e, 0x31, 
-	0x2e, 0x65, 0x78, 0x65, 0x22, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 
-	0x67, 0x65, 0x74, 0x4c, 0x6f, 0x77, 0x28, 0x61, 0x29, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x68, 0x75, 
-	0x67, 0x65, 0x0a,
-	0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 
-	0x61, 0x29, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6b, 0x20, 0x3c, 0x20, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x20, 0x3d, 0x20, 0x6b, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x5b, 0x6d, 0x5d, 0x2c, 0x20, 0x6d, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 
-	0x20, 0x7b, 0x0a,
-	0x09, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x30, 
-	0x20, 0x7d, 0x2c, 0x0a,
-	0x09, 0x66, 0x75, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x7b, 0x61, 0x20, 0x3d, 0x20, 0x30, 0x20, 0x7d, 0x2c, 0x0a,
-	0x09, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x31, 0x20, 0x7d, 0x0a,
-	0x7d, 0x0a,
-	0x0a,
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x64, 
-	0x69, 0x63, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
-	0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 
-	0x70, 0x61, 0x72, 0x73, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6d, 0x2c, 0x20, 0x69, 0x29, 0x0a,
-	0x09, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6d, 0x2e, 0x61, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6d, 0x2e, 0x61, 0x72, 0x67, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
-	0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x6a, 0x3d, 0x69, 0x2c, 0x69, 0x2b, 0x6d, 0x2e, 0x61, 0x2d, 0x31, 0x20, 
-	0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 
-	0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x6a, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6d, 0x2e, 
-	0x61, 0x72, 0x67, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x5b, 0x6a, 0x5d, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x2e, 0x61, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 
-	0x70, 0x61, 0x72, 0x73, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x28, 0x61, 0x72, 0x67, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x67, 0x63, 0x20, 0x3d, 0x20, 0x23, 0x61, 0x72, 0x67, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x31, 0x0a,
-	0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x69, 0x20, 0x3c, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x63, 0x20, 0x64, 
-	0x6f, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x4c, 0x6f, 0x6f, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x70, 0x74, 0x69, 
-	0x6f, 0x6e, 0x73, 0x2e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x5b, 0x69, 0x5d, 
-	0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 0x5e, 0x25, 0x2d, 0x25, 0x2d, 0x28, 0x2e, 0x2a, 0x29, 0x22, 
-	0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x20, 0x7e, 0x3d, 0x20, 0x22, 0x22, 
-	0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 
-	0x6f, 0x6e, 0x73, 0x5b, 0x6d, 0x5d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 
-	0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5b, 0x6d, 0x5d, 0x2e, 0x73, 
-	0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 
-	0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x20, 0x3d, 0x20, 0x69, 0x20, 0x2b, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 
-	0x67, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x65, 
-	0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5b, 0x6d, 0x5d, 0x2c, 0x20, 0x69, 
-	0x2b, 0x31, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x6d, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x22, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x27, 0x2d, 0x2d, 0x27, 
-	0x20, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 
-	0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 
-	0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x27, 0x2d, 0x2d, 0x27, 0x20, 0x66, 
-	0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x6e, 0x61, 
-	0x6d, 0x65, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x69, 0x20, 0x2b, 0x20, 0x31, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x0a,
-	0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x69, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x69, 0x20, 0x3d, 0x20, 0x69, 0x20, 0x2b, 0x20, 0x31, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 
-	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4f, 0x70, 
-	0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 
-	0x6f, 0x6e, 0x73, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x72, 0x20, 
-	0x30, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x67, 
-	0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x61, 
-	0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 
-	0x76, 0x69, 0x61, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x29, 0x0a,
-	0x2d, 0x2d, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 
-	0x77, 0x65, 0x72, 0x65, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x70, 0x74, 
-	0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 
-	0x70, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 
-	0x28, 0x61, 0x29, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x2c, 0x20, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x64, 0x65, 0x78, 
-	0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x77, 
-	0x28, 0x61, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x64, 0x65, 
-	0x78, 0x0a,
-	0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x3d, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x23, 
-	0x61, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 
-	0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6f, 0x75, 0x74, 0x5b, 0x6f, 0x5d, 0x20, 0x3d, 0x20, 0x61, 0x5b, 0x69, 0x5d, 0x0a,
-	0x09, 0x09, 0x09, 0x6f, 0x20, 0x3d, 0x20, 0x6f, 0x20, 0x2b, 0x20, 0x31, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x72, 0x65, 0x61, 
-	0x74, 0x65, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x28, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 
-	0x61, 0x63, 0x6b, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x73, 
-	0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x7b, 0x0a,
-	0x09, 0x09, 0x6b, 0x65, 0x79, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x62, 0x2c, 0x73, 0x2c, 0x72, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x70, 0x72, 0x65, 0x73, 
-	0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x28, 0x62, 0x2c, 0x73, 0x2c, 
-	0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6b, 0x65, 0x79, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 
-	0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x62, 0x2c, 0x73, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x72, 0x65, 0x6c, 0x65, 
-	0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x28, 0x62, 0x2c, 
-	0x73, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x74, 0x65, 0x78, 0x74, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 
-	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x74, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x69, 0x6e, 0x70, 
-	0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 
-	0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x28, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x74, 0x2c, 0x73, 0x2c, 0x6c, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69, 
-	0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64, 0x28, 0x74, 0x2c, 0x73, 0x2c, 
-	0x6c, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x64, 0x78, 0x2c, 0x64, 0x79, 0x2c, 0x74, 
-	0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 
-	0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x78, 0x2c, 0x79, 0x2c, 
-	0x64, 0x78, 0x2c, 0x64, 0x79, 0x2c, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 
-	0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x62, 0x2c, 0x74, 0x2c, 0x63, 
-	0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 
-	0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x28, 
-	0x78, 0x2c, 0x79, 0x2c, 0x62, 0x2c, 0x74, 0x2c, 0x63, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x62, 0x2c, 0x74, 0x2c, 
-	0x63, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x65, 
-	0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 
-	0x64, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x62, 0x2c, 0x74, 0x2c, 0x63, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x6d, 0x6f, 
-	0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x78, 0x2c, 0x79, 0x29, 
-	0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 
-	0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x69, 0x64, 0x2c, 0x78, 0x2c, 0x79, 0x2c, 0x64, 0x78, 
-	0x2c, 0x64, 0x79, 0x2c, 0x70, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x70, 0x72, 
-	0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x28, 
-	0x69, 0x64, 0x2c, 0x78, 0x2c, 0x79, 0x2c, 0x64, 0x78, 0x2c, 0x64, 0x79, 0x2c, 0x70, 0x29, 0x20, 0x65, 0x6e, 
-	0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x69, 0x64, 0x2c, 0x78, 0x2c, 0x79, 0x2c, 0x64, 
-	0x78, 0x2c, 0x64, 0x79, 0x2c, 0x70, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x72, 0x65, 
-	0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 
-	0x64, 0x28, 0x69, 0x64, 0x2c, 0x78, 0x2c, 0x79, 0x2c, 0x64, 0x78, 0x2c, 0x64, 0x79, 0x2c, 0x70, 0x29, 0x20, 
-	0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x69, 0x64, 0x2c, 0x78, 0x2c, 0x79, 0x2c, 0x64, 0x78, 0x2c, 0x64, 
-	0x79, 0x2c, 0x70, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x6d, 0x6f, 
-	0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x69, 0x64, 0x2c, 0x78, 
-	0x2c, 0x79, 0x2c, 0x64, 0x78, 0x2c, 0x64, 0x79, 0x2c, 0x70, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 
-	0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 
-	0x6b, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 
-	0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x70, 0x72, 
-	0x65, 0x73, 0x73, 0x65, 0x64, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 
-	0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 
-	0x6b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 
-	0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x72, 
-	0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x61, 0x78, 0x69, 0x73, 0x20, 0x3d, 0x20, 0x66, 
-	0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x61, 0x2c, 0x76, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 
-	0x6b, 0x61, 0x78, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x61, 0x78, 0x69, 0x73, 0x28, 
-	0x6a, 0x2c, 0x61, 0x2c, 0x76, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x68, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 
-	0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x68, 0x2c, 0x76, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 
-	0x6b, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x68, 0x61, 0x74, 0x28, 0x6a, 0x2c, 
-	0x68, 0x2c, 0x76, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 
-	0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 
-	0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 
-	0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x70, 0x72, 0x65, 0x73, 
-	0x73, 0x65, 0x64, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 
-	0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 
-	0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 
-	0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x72, 0x65, 0x6c, 
-	0x65, 0x61, 0x73, 0x65, 0x64, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x61, 0x78, 0x69, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 
-	0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x61, 0x2c, 0x76, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 
-	0x61, 0x78, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x61, 0x78, 0x69, 0x73, 0x28, 0x6a, 0x2c, 
-	0x61, 0x2c, 0x76, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x3d, 0x20, 
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 
-	0x6b, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x61, 0x64, 0x64, 0x65, 
-	0x64, 0x28, 0x6a, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 
-	0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 
-	0x6b, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 
-	0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x72, 0x65, 
-	0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x6a, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 
-	0x20, 0x28, 0x66, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x6f, 
-	0x63, 0x75, 0x73, 0x28, 0x66, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x66, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x66, 0x6f, 
-	0x63, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
-	0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x28, 0x66, 0x29, 0x20, 0x65, 
-	0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 
-	0x6f, 0x6e, 0x20, 0x28, 0x76, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 
-	0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x28, 0x76, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x71, 0x75, 0x69, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 
-	0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x66, 0x75, 
-	0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x74, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 
-	0x72, 0x72, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x74, 0x2c, 
-	0x20, 0x65, 0x72, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 
-	0x6e, 0x20, 0x28, 0x77, 0x2c, 0x20, 0x68, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 
-	0x65, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x77, 0x2c, 0x20, 0x68, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 
-	0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x66, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x64, 0x72, 0x6f, 
-	0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x28, 0x66, 0x29, 
-	0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 
-	0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x64, 0x69, 0x72, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 
-	0x72, 0x79, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 
-	0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 
-	0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x28, 0x64, 0x69, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x77, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 
-	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6c, 0x6f, 0x77, 0x6d, 0x65, 0x6d, 0x6f, 
-	0x72, 0x79, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6c, 0x6f, 0x77, 0x6d, 0x65, 
-	0x6d, 0x6f, 0x72, 0x79, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x28, 
-	0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x28, 
-	0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x3d, 
-	0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 
-	0x2c, 0x20, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 
-	0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 
-	0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x72, 0x6f, 0x74, 0x61, 
-	0x74, 0x65, 0x64, 0x28, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x2c, 0x20, 0x6f, 0x72, 0x69, 0x65, 0x6e, 
-	0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x7d, 0x2c, 0x20, 0x7b, 0x0a,
-	0x09, 0x09, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 
-	0x6f, 0x6e, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 
-	0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
-	0x09, 0x7d, 0x29, 0x0a,
-	0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x72, 0x69, 
-	0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x28, 0x73, 0x29, 0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x25, 0x25, 
-	0x25, 0x78, 0x25, 0x78, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x74, 
-	0x72, 0x29, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x68, 
-	0x61, 0x72, 0x28, 0x74, 0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, 0x73, 0x74, 0x72, 0x3a, 0x73, 0x75, 
-	0x62, 0x28, 0x32, 0x29, 0x2c, 0x20, 0x31, 0x36, 0x29, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x29, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 
-	0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
-	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x67, 0x61, 0x6d, 0x65, 
-	0x5f, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6f, 
-	0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x2e, 0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 
-	0x28, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 
-	0x74, 0x65, 0x6c, 0x79, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2e, 0x0a,
-	0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 
-	0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x61, 0x77, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 
-	0x65, 0x6e, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x67, 0x30, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 
-	0x2e, 0x61, 0x72, 0x67, 0x2e, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x77, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 
-	0x61, 0x77, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 
-	0x6e, 0x69, 0x74, 0x28, 0x61, 0x72, 0x67, 0x30, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 
-	0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x28, 0x29, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x23, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 
-	0x74, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6a, 0x75, 0x73, 0x74, 
-	0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x77, 0x65, 0x27, 0x6c, 0x6c, 0x20, 0x66, 0x61, 0x6c, 
-	0x6c, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x30, 0x2e, 0x0a,
-	0x09, 0x09, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x30, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 
-	0x6c, 0x73, 0x65, 0x0a,
-	0x09, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 
-	0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x49, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 
-	0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x20, 0x22, 0x66, 0x75, 0x73, 0x65, 
-	0x64, 0x22, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x3f, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 
-	0x65, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 
-	0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2c, 
-	0x20, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x49, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, 0x73, 0x65, 0x64, 0x20, 0x67, 
-	0x61, 0x6d, 0x65, 0x2c, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x20, 0x2d, 
-	0x2d, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 
-	0x2e, 0x67, 0x61, 0x6d, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x50, 0x61, 0x72, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 
-	0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x77, 
-	0x68, 0x69, 0x63, 0x68, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x65, 0x27, 0x72, 0x65, 
-	0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4f, 0x70, 0x74, 
-	0x69, 0x6f, 0x6e, 0x73, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x61, 0x77, 0x47, 0x61, 0x6d, 0x65, 0x41, 
-	0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 
-	0x65, 0x6e, 0x74, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x63, 
-	0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4f, 
-	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x64, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 
-	0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 
-	0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 
-	0x73, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x61, 0x77, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 
-	0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 
-	0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x67, 0x61, 
-	0x6d, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 
-	0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 
-	0x73, 0x2e, 0x66, 0x75, 0x73, 0x65, 0x64, 0x2e, 0x73, 0x65, 0x74, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x73, 
-	0x65, 0x74, 0x46, 0x75, 0x73, 0x65, 0x64, 0x28, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x67, 
-	0x61, 0x6d, 0x65, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 
-	0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x75, 0x73, 0x65, 0x64, 
-	0x28, 0x29, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 
-	0x22, 0x22, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 
-	0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x20, 
-	0x61, 0x6e, 0x64, 0x20, 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x5b, 0x31, 0x5d, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x6f, 0x75, 0x72, 0x69, 0x20, 0x3d, 0x20, 0x6f, 0x2e, 
-	0x67, 0x61, 0x6d, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x5b, 0x31, 0x5d, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x75, 0x72, 0x69, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x31, 0x2c, 0x20, 
-	0x37, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2f, 0x22, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6e, 0x6f, 0x75, 0x72, 0x69, 0x20, 0x3d, 0x20, 0x75, 0x72, 0x69, 0x64, 0x65, 0x63, 0x6f, 
-	0x64, 0x65, 0x28, 0x6e, 0x6f, 0x75, 0x72, 0x69, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x38, 0x29, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 
-	0x65, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x67, 0x65, 0x74, 0x46, 
-	0x75, 0x6c, 0x6c, 0x28, 0x6e, 0x6f, 0x75, 0x72, 0x69, 0x29, 0x0a,
-	0x09, 0x09, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x70, 
-	0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 
-	0x65, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2c, 0x20, 0x66, 0x75, 0x6c, 0x6c, 
-	0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 
-	0x61, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 
-	0x74, 0x68, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x55, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 
-	0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x2e, 0x6c, 0x6f, 0x76, 
-	0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 
-	0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x2e, 0x0a,
-	0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x70, 0x61, 0x74, 0x68, 0x2e, 0x6c, 0x65, 0x61, 0x66, 0x28, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 
-	0x72, 0x63, 0x65, 0x29, 0x0a,
-	0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x55, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 
-	0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 
-	0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x2e, 0x0a,
-	0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x70, 0x61, 0x74, 0x68, 0x2e, 0x6c, 0x65, 0x61, 0x66, 0x28, 0x65, 0x78, 0x65, 0x70, 0x61, 0x74, 0x68, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x54, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 
-	0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 
-	0x67, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 
-	0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x20, 0x49, 0x74, 0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 
-	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 
-	0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 
-	0x73, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x64, 0x69, 0x72, 0x20, 0x3d, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 
-	0x52, 0x65, 0x61, 0x6c, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x28, 0x22, 0x6d, 0x61, 0x69, 
-	0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x64, 0x69, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x70, 0x61, 0x74, 0x68, 0x2e, 0x6c, 0x65, 0x61, 0x66, 0x28, 0x72, 0x65, 0x61, 0x6c, 0x64, 0x69, 0x72, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 
-	0x74, 0x79, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5e, 0x28, 0x5b, 0x25, 0x2e, 0x5d, 0x2b, 0x29, 0x22, 
-	0x2c, 0x20, 0x22, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x70, 0x20, 0x6c, 0x65, 0x61, 
-	0x64, 0x69, 0x6e, 0x67, 0x20, 0x22, 0x2e, 0x22, 0x27, 0x73, 0x0a,
-	0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 
-	0x74, 0x79, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x25, 0x2e, 0x28, 0x5b, 0x5e, 0x25, 0x2e, 0x5d, 0x2b, 
-	0x29, 0x24, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x70, 0x20, 
-	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x0a,
-	0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 
-	0x74, 0x79, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x25, 0x2e, 0x22, 0x2c, 0x20, 0x22, 0x5f, 0x22, 0x29, 
-	0x20, 0x2d, 0x2d, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 
-	0x69, 0x6e, 0x67, 0x20, 0x22, 0x2e, 0x22, 0x27, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x22, 0x5f, 0x22, 0x0a,
-	0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x23, 0x69, 0x64, 0x65, 0x6e, 0x74, 
-	0x69, 0x74, 0x79, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 
-	0x74, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x22, 0x6c, 0x6f, 0x76, 0x65, 0x67, 0x61, 0x6d, 0x65, 0x22, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x20, 
-	0x69, 0x73, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x65, 
-	0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 
-	0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x76, 
-	0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x69, 
-	0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 
-	0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x2e, 0x29, 0x0a,
-	0x09, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 
-	0x73, 0x74, 0x65, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2c, 0x20, 
-	0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x61, 
-	0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 
-	0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x22, 0x6d, 0x61, 0x69, 
-	0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 
-	0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x22, 
-	0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x74, 
-	0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61, 
-	0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x6f, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x72, 
-	0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6e, 0x6f, 0x67, 0x61, 0x6d, 
-	0x65, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x6e, 0x6f, 0x67, 0x61, 0x6d, 0x65, 0x28, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x69, 0x6e, 0x69, 0x74, 
-	0x28, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 
-	0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x74, 
-	0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x4e, 0x4f, 0x54, 0x45, 0x3a, 0x20, 0x41, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 
-	0x20, 0x6e, 0x65, 0x77, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 
-	0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 
-	0x69, 0x74, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 
-	0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
-	0x09, 0x09, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x55, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 
-	0x64, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x0a,
-	0x09, 0x09, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x38, 0x30, 0x30, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x36, 0x30, 0x30, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x78, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x79, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x61, 
-	0x6c, 0x73, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x20, 
-	0x3d, 0x20, 0x22, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x73, 0x61, 0x61, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x61, 
-	0x6c, 0x73, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 
-	0x73, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 
-	0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x75, 0x73, 0x65, 0x64, 0x70, 0x69, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x74, 
-	0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x7d, 0x2c, 0x0a,
-	0x09, 0x09, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 
-	0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 
-	0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 
-	0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x7d, 0x2c, 0x0a,
-	0x09, 0x09, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x69, 0x78, 0x77, 0x69, 0x74, 0x68, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x3d, 
-	0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x6c, 
-	0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 
-	0x2f, 0x20, 0x69, 0x4f, 0x53, 0x2e, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x69, 0x63, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x20, 0x2d, 0x2d, 
-	0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 
-	0x20, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x0a,
-	0x09, 0x09, 0x7d, 0x2c, 0x0a,
-	0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 
-	0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 
-	0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x0a,
-	0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 
-	0x2c, 0x0a,
-	0x09, 0x09, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 
-	0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 
-	0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 
-	0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 
-	0x64, 0x2e, 0x0a,
-	0x09, 0x09, 0x61, 0x63, 0x63, 0x65, 0x6c, 0x65, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x6a, 0x6f, 0x79, 
-	0x73, 0x74, 0x69, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 
-	0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 
-	0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x2f, 0x20, 0x69, 0x4f, 0x53, 0x2e, 0x0a,
-	0x09, 0x09, 0x67, 0x61, 0x6d, 0x6d, 0x61, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x66, 
-	0x61, 0x6c, 0x73, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x0a,
-	0x09, 0x7d, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x63, 0x6b, 0x2c, 0x20, 
-	0x70, 0x61, 0x72, 0x74, 0x20, 0x31, 0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 
-	0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 
-	0x6e, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 
-	0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 
-	0x65, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x3d, 0x20, 
-	0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 
-	0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x2c, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x69, 0x74, 0x20, 0x61, 
-	0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x70, 0x64, 
-	0x61, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 
-	0x66, 0x65, 0x72, 0x72, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 
-	0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 
-	0x74, 0x65, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 
-	0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x22, 0x63, 0x6f, 0x6e, 
-	0x66, 0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x20, 
-	0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x22, 
-	0x63, 0x6f, 0x6e, 0x66, 0x22, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x59, 0x65, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x20, 
-	0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x2c, 0x20, 0x62, 
-	0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 
-	0x20, 0x77, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x61, 0x70, 0x70, 0x65, 
-	0x61, 0x72, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x77, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63, 
-	0x68, 0x65, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x77, 0x61, 0x79, 
-	0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x20, 
-	0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2c, 
-	0x20, 0x63, 0x29, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 
-	0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x77, 0x65, 0x27, 0x6c, 0x6c, 0x20, 0x74, 0x72, 0x69, 0x67, 
-	0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x61, 0x66, 0x74, 0x65, 
-	0x72, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 
-	0x73, 0x6f, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x73, 
-	0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 
-	0x79, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x63, 0x6b, 0x2c, 0x20, 
-	0x70, 0x61, 0x72, 0x74, 0x20, 0x32, 0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 
-	0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x73, 
-	0x6f, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 
-	0x65, 0x28, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x48, 0x61, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 
-	0x6c, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x63, 0x63, 0x65, 0x6c, 0x65, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 
-	0x2d, 0x61, 0x73, 0x2d, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x20, 0x6f, 0x6e, 0x20, 0x41, 0x6e, 
-	0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x2f, 0x20, 0x69, 0x4f, 0x53, 0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x6c, 
-	0x65, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x41, 0x73, 0x4a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 
-	0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x6c, 0x65, 0x72, 
-	0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x41, 0x73, 0x4a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x28, 0x63, 
-	0x2e, 0x61, 0x63, 0x63, 0x65, 0x6c, 0x65, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x6a, 0x6f, 0x79, 0x73, 
-	0x74, 0x69, 0x63, 0x6b, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x47, 0x61, 0x6d, 0x6d, 0x61, 
-	0x43, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x47, 0x61, 0x6d, 0x6d, 0x61, 0x43, 0x6f, 
-	0x72, 0x72, 0x65, 0x63, 0x74, 0x28, 0x63, 0x2e, 0x67, 0x61, 0x6d, 0x6d, 0x61, 0x63, 0x6f, 0x72, 0x72, 0x65, 
-	0x63, 0x74, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x48, 0x69, 0x67, 0x68, 0x44, 
-	0x50, 0x49, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x48, 0x69, 0x67, 0x68, 0x44, 0x50, 0x49, 
-	0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x28, 0x63, 0x2e, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x6f, 
-	0x4d, 0x69, 0x78, 0x57, 0x69, 0x74, 0x68, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 
-	0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x6d, 0x69, 0x78, 0x77, 0x69, 0x74, 0x68, 0x73, 0x79, 0x73, 0x74, 
-	0x65, 0x6d, 0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x4d, 
-	0x69, 0x78, 0x57, 0x69, 0x74, 0x68, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x28, 0x63, 0x2e, 0x61, 0x75, 0x64, 
-	0x69, 0x6f, 0x2e, 0x6d, 0x69, 0x78, 0x77, 0x69, 0x74, 0x68, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 
-	0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 
-	0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x63, 
-	0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x28, 0x63, 
-	0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 
-	0x2e, 0x6d, 0x69, 0x63, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x47, 0x65, 0x74, 0x73, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x20, 0x6d, 
-	0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x0a,
-	0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 
-	0x7b, 0x0a,
-	0x09, 0x09, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x66, 0x6f, 0x6e, 0x74, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x6d, 0x61, 0x74, 0x68, 0x22, 0x2c, 0x0a,
-	0x09, 0x09, 0x22, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x73, 0x22, 0x2c, 0x0a,
-	0x09, 0x7d, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x5b, 0x76, 0x5d, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x22, 
-	0x20, 0x2e, 0x2e, 0x20, 0x76, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 
-	0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x68, 0x61, 0x6e, 0x64, 0x6c, 
-	0x65, 0x72, 0x73, 0x28, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 
-	0x69, 0x6f, 0x6e, 0x0a,
-	0x09, 0x63, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 
-	0x69, 0x6e, 0x67, 0x28, 0x63, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x69, 0x73, 0x56, 0x65, 0x72, 
-	0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x28, 0x63, 0x2e, 0x76, 
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x2c, 0x20, 0x6d, 0x69, 0x6e, 
-	0x6f, 0x72, 0x2c, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x76, 
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 0x5e, 0x28, 0x25, 0x64, 
-	0x2b, 0x29, 0x25, 0x2e, 0x28, 0x25, 0x64, 0x2b, 0x29, 0x25, 0x2e, 0x28, 0x25, 0x64, 0x2b, 0x29, 0x24, 0x22, 
-	0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x6f, 0x72, 
-	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 
-	0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x28, 0x6d, 0x61, 0x6a, 0x6f, 
-	0x72, 0x20, 0x7e, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 
-	0x5f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x20, 0x7e, 
-	0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 
-	0x6e, 0x6f, 0x72, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x20, 0x28, 0x22, 0x54, 
-	0x68, 0x69, 0x73, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 
-	0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x76, 
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x27, 0x25, 0x73, 0x27, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x4f, 0x56, 
-	0x45, 0x2e, 0x5c, 0x6e, 0x22, 0x2e, 0x2e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x22, 0x49, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 
-	0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 
-	0x68, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 
-	0x20, 0x28, 0x25, 0x73, 0x29, 0x2e, 0x22, 0x29, 0x3a, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x63, 0x2e, 
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x76, 0x65, 0x72, 
-	0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x68, 
-	0x6f, 0x77, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6f, 0x78, 0x28, 0x22, 0x43, 0x6f, 0x6d, 0x70, 
-	0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 
-	0x2c, 0x20, 0x6d, 0x73, 0x67, 0x2c, 0x20, 0x22, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x20, 0x61, 0x6e, 0x64, 
-	0x20, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x53, 0x65, 0x74, 0x75, 0x70, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x68, 
-	0x65, 0x72, 0x65, 0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 
-	0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 0x54, 
-	0x69, 0x74, 0x6c, 0x65, 0x28, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x74, 0x69, 0x74, 0x6c, 
-	0x65, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x2e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 
-	0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 
-	0x77, 0x2e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 
-	0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x0a,
-	0x09, 0x09, 0x7b, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x63, 0x2e, 
-	0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x20, 
-	0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 
-	0x65, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 
-	0x77, 0x2e, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x73, 0x61, 0x61, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 
-	0x2e, 0x6d, 0x73, 0x61, 0x61, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 
-	0x64, 0x6f, 0x77, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x64, 0x65, 0x70, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 
-	0x77, 0x2e, 0x64, 0x65, 0x70, 0x74, 0x68, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 
-	0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 
-	0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6d, 0x69, 0x6e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 
-	0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6d, 0x69, 0x6e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x63, 0x2e, 
-	0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 
-	0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 
-	0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 
-	0x64, 0x6f, 0x77, 0x2e, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x2c, 0x20, 0x2d, 0x2d, 0x20, 0x64, 0x65, 
-	0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x75, 0x73, 0x65, 0x64, 0x70, 0x69, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x63, 
-	0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x75, 0x73, 0x65, 0x64, 0x70, 0x69, 0x73, 0x63, 0x61, 0x6c, 
-	0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x78, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x78, 0x2c, 0x0a,
-	0x09, 0x09, 0x09, 0x79, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x79, 0x2c, 0x0a,
-	0x09, 0x09, 0x7d, 0x29, 0x2c, 0x20, 0x22, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 
-	0x65, 0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x69, 0x63, 0x6f, 0x6e, 
-	0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x69, 0x6d, 0x61, 
-	0x67, 0x65, 0x2c, 0x20, 0x22, 0x49, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x69, 0x73, 
-	0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2c, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 
-	0x65, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x21, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 
-	0x49, 0x63, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2e, 0x6e, 0x65, 
-	0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x28, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 
-	0x77, 0x2e, 0x69, 0x63, 0x6f, 0x6e, 0x29, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x4f, 0x75, 0x72, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, 
-	0x73, 0x74, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 
-	0x6f, 0x77, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x61, 
-	0x6b, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 
-	0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 
-	0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	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, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 
-	0x5f, 0x73, 0x65, 0x74, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x61, 0x76, 0x65, 0x45, 0x78, 0x74, 
-	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x28, 0x63, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x74, 
-	0x6f, 0x72, 0x61, 0x67, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 
-	0x73, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x28, 0x63, 0x2e, 0x69, 0x64, 0x65, 0x6e, 
-	0x74, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 
-	0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x28, 
-	0x29, 0x2c, 0x20, 0x63, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 
-	0x79, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 
-	0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 
-	0x75, 0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 
-	0x6f, 0x20, 0x72, 0x75, 0x6e, 0x5c, 0x6e, 0x59, 0x6f, 0x75, 0x72, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x6d, 
-	0x69, 0x67, 0x68, 0x74, 0x20, 0x62, 0x65, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x64, 0x20, 0x69, 
-	0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x2e, 0x5c, 0x6e, 0x4d, 0x61, 0x6b, 0x65, 0x20, 
-	0x73, 0x75, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x20, 0x69, 0x73, 0x20, 0x61, 
-	0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x6f, 0x66, 
-	0x20, 0x74, 0x68, 0x65, 0x20, 0x7a, 0x69, 0x70, 0x2e, 0x22, 0x29, 0x0a,
-	0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x67, 0x61, 
-	0x6d, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 
-	0x61, 0x64, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x74, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x27, 0x22, 
-	0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x70, 
-	0x61, 0x74, 0x68, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x27, 0x2e, 0x5c, 0x6e, 0x4d, 0x61, 0x6b, 0x65, 0x20, 0x73, 
-	0x75, 0x72, 0x65, 0x20, 0x61, 0x20, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 
-	0x73, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 
-	0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x22, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a,
-	0x2d, 0x2d, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 
-	0x6b, 0x73, 0x2e, 0x0a,
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a,
-	0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x75, 0x6e, 0x28, 
-	0x29, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x61, 
-	0x72, 0x73, 0x65, 0x64, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x61, 0x77, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 
-	0x65, 0x6e, 0x74, 0x73, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x57, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 
-	0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x27, 0x73, 0x20, 
-	0x64, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 
-	0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x62, 0x79, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6c, 0x6f, 0x61, 
-	0x64, 0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 
-	0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 
-	0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x4d, 0x61, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x74, 0x69, 0x6d, 0x65, 
-	0x2e, 0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 
-	0x73, 0x2e, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 
-	0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x2c, 0x62, 0x2c, 0x63, 
-	0x2c, 0x64, 0x2c, 0x65, 0x2c, 0x66, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 
-	0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x71, 0x75, 
-	0x69, 0x74, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71, 
-	0x75, 0x69, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71, 0x75, 
-	0x69, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x6f, 0x72, 0x20, 
-	0x30, 0x2c, 0x20, 0x62, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 
-	0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x28, 0x61, 0x2c, 0x62, 0x2c, 0x63, 0x2c, 0x64, 0x2c, 0x65, 0x2c, 0x66, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x64, 0x74, 0x2c, 0x20, 0x61, 0x73, 
-	0x20, 0x77, 0x65, 0x27, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x70, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 
-	0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 
-	0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 
-	0x65, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x43, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x61, 
-	0x6e, 0x64, 0x20, 0x64, 0x72, 0x61, 0x77, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 
-	0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x64, 0x74, 
-	0x29, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x2d, 0x2d, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70, 0x61, 0x73, 0x73, 
-	0x20, 0x30, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x69, 
-	0x73, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 
-	0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 
-	0x2e, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 
-	0x72, 0x69, 0x67, 0x69, 0x6e, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x63, 
-	0x6c, 0x65, 0x61, 0x72, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 
-	0x2e, 0x67, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 
-	0x72, 0x28, 0x29, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 
-	0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x6c, 0x65, 0x65, 
-	0x70, 0x28, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2c, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 
-	0x2c, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2c, 0x20, 0x70, 
-	0x72, 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a,
-	0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x68, 0x72, 0x65, 
-	0x61, 0x64, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x74, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x29, 0x0a,
-	0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 
-	0x6f, 0x72, 0x20, 0x28, 0x22, 0x2e, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x74, 0x29, 
-	0x2e, 0x2e, 0x22, 0x29, 0x5c, 0x6e, 0x5c, 0x6e, 0x22, 0x2e, 0x2e, 0x65, 0x72, 0x72, 0x2c, 0x20, 0x30, 0x29, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x75, 0x74, 0x66, 0x38, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 
-	0x72, 0x65, 0x28, 0x22, 0x75, 0x74, 0x66, 0x38, 0x22, 0x29, 0x0a,
-	0x0a,
-	0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x72, 0x72, 
-	0x6f, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x28, 0x6d, 0x73, 0x67, 0x2c, 0x20, 0x6c, 0x61, 
-	0x79, 0x65, 0x72, 0x29, 0x0a,
-	0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x28, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2e, 0x74, 0x72, 0x61, 0x63, 
-	0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x22, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20, 0x22, 0x20, 0x2e, 0x2e, 
-	0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x2c, 0x20, 0x31, 0x2b, 
-	0x28, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x20, 0x6f, 0x72, 0x20, 0x31, 0x29, 0x29, 0x3a, 0x67, 0x73, 0x75, 0x62, 
-	0x28, 0x22, 0x5c, 0x6e, 0x5b, 0x5e, 0x5c, 0x6e, 0x5d, 0x2b, 0x24, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x29, 0x29, 
-	0x29, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x68, 
-	0x61, 0x6e, 0x64, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x0a,
-	0x09, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6d, 0x73, 
-	0x67, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x28, 0x6d, 0x73, 0x67, 
-	0x2c, 0x20, 0x32, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 
-	0x77, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 
-	0x68, 0x69, 0x63, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 
-	0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 
-	0x69, 0x63, 0x73, 0x2e, 0x69, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x28, 0x29, 0x20, 0x6f, 0x72, 
-	0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x69, 
-	0x73, 0x4f, 0x70, 0x65, 0x6e, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x73, 
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 
-	0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x38, 
-	0x30, 0x30, 0x2c, 0x20, 0x36, 0x30, 0x30, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x6f, 
-	0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x73, 0x65, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 
-	0x6e, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x56, 0x69, 
-	0x73, 0x69, 0x62, 0x6c, 0x65, 0x28, 0x74, 0x72, 0x75, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x47, 0x72, 
-	0x61, 0x62, 0x62, 0x65, 0x64, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x65, 
-	0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x69, 0x73, 
-	0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x28, 0x29, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x43, 
-	0x75, 0x72, 0x73, 0x6f, 0x72, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x53, 0x74, 0x6f, 0x70, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6a, 0x6f, 0x79, 0x73, 
-	0x74, 0x69, 0x63, 0x6b, 0x20, 0x76, 0x69, 0x62, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a,
-	0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 
-	0x73, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x2e, 0x67, 0x65, 
-	0x74, 0x4a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x73, 0x28, 0x29, 0x29, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x09, 0x76, 0x3a, 0x73, 0x65, 0x74, 0x56, 0x69, 0x62, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 
-	0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x74, 0x68, 0x65, 
-	0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x74, 0x6f, 0x70, 0x28, 
-	0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x72, 0x65, 0x73, 
-	0x65, 0x74, 0x28, 0x29, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 
-	0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x46, 0x6f, 
-	0x6e, 0x74, 0x28, 0x31, 0x34, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 
-	0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x62, 
-	0x75, 0x67, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 
-	0x67, 0x69, 0x6e, 0x28, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x6d, 0x73, 
-	0x67, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
-	0x09, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x73, 0x67, 0x3a, 0x67, 
-	0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x75, 0x74, 0x66, 0x38, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x70, 0x61, 0x74, 
-	0x74, 0x65, 0x72, 0x6e, 0x29, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x73, 0x61, 0x6e, 
-	0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x6d, 0x73, 0x67, 0x2c, 0x20, 0x63, 0x68, 0x61, 0x72, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x73, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x20, 0x74, 0x61, 
-	0x62, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x73, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 
-	0x65, 0x64, 0x6d, 0x73, 0x67, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
-	0x0a,
-	0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x65, 0x72, 0x72, 0x2c, 
-	0x20, 0x22, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x5c, 0x6e, 0x22, 0x29, 0x0a,
-	0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x65, 0x72, 0x72, 0x2c, 
-	0x20, 0x73, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x6d, 0x73, 0x67, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x23, 0x73, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x6d, 0x73, 0x67, 0x20, 
-	0x7e, 0x3d, 0x20, 0x23, 0x6d, 0x73, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x65, 0x72, 0x72, 
-	0x2c, 0x20, 0x22, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x20, 0x73, 
-	0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x73, 
-	0x73, 0x61, 0x67, 0x65, 0x2e, 0x22, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x65, 0x72, 0x72, 0x2c, 
-	0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x3a, 0x67, 0x6d, 
-	0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 0x28, 0x2e, 0x2d, 0x29, 0x5c, 0x6e, 0x22, 0x29, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 
-	0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x20, 0x3d, 0x20, 0x6c, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x73, 0x74, 0x61, 
-	0x63, 0x6b, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x22, 0x2c, 0x20, 0x22, 0x54, 
-	0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x5c, 0x6e, 0x22, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x65, 0x72, 
-	0x72, 0x2c, 0x20, 0x6c, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x20, 0x3d, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x63, 
-	0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x65, 0x72, 0x72, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x70, 0x20, 0x3d, 0x20, 0x70, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x74, 0x22, 0x2c, 0x20, 
-	0x22, 0x22, 0x29, 0x0a,
-	0x09, 0x70, 0x20, 0x3d, 0x20, 0x70, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x25, 0x5b, 0x73, 0x74, 0x72, 
-	0x69, 0x6e, 0x67, 0x20, 0x5c, 0x22, 0x28, 0x2e, 0x2d, 0x29, 0x5c, 0x22, 0x25, 0x5d, 0x22, 0x2c, 0x20, 0x22, 
-	0x25, 0x31, 0x22, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x72, 
-	0x61, 0x77, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x6f, 0x73, 0x20, 0x3d, 0x20, 0x37, 0x30, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c, 
-	0x65, 0x61, 0x72, 0x28, 0x38, 0x39, 0x2f, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x31, 0x35, 0x37, 0x2f, 0x32, 0x35, 
-	0x35, 0x2c, 0x20, 0x32, 0x32, 0x30, 0x2f, 0x32, 0x35, 0x35, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 
-	0x69, 0x6e, 0x74, 0x66, 0x28, 0x70, 0x2c, 0x20, 0x70, 0x6f, 0x73, 0x2c, 0x20, 0x70, 0x6f, 0x73, 0x2c, 0x20, 
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x67, 0x65, 0x74, 0x57, 
-	0x69, 0x64, 0x74, 0x68, 0x28, 0x29, 0x20, 0x2d, 0x20, 0x70, 0x6f, 0x73, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 
-	0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x65, 
-	0x78, 0x74, 0x20, 0x3d, 0x20, 0x70, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 
-	0x70, 0x79, 0x54, 0x6f, 0x43, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x73, 0x79, 0x73, 0x74, 
-	0x65, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x43, 
-	0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x54, 0x65, 0x78, 0x74, 0x28, 0x66, 0x75, 0x6c, 0x6c, 0x45, 
-	0x72, 0x72, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x29, 0x0a,
-	0x09, 0x09, 0x70, 0x20, 0x3d, 0x20, 0x70, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5c, 0x6e, 0x43, 0x6f, 0x70, 0x69, 
-	0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x21, 0x22, 0x0a,
-	0x09, 0x09, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x70, 0x20, 0x3d, 0x20, 0x70, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x5c, 0x6e, 0x5c, 0x6e, 0x50, 0x72, 
-	0x65, 0x73, 0x73, 0x20, 0x43, 0x74, 0x72, 0x6c, 0x2b, 0x43, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x61, 0x70, 0x20, 
-	0x74, 0x6f, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 
-	0x22, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28, 
-	0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x20, 0x69, 
-	0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 
-	0x29, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x71, 0x75, 0x69, 0x74, 0x22, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6b, 0x65, 
-	0x79, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x3d, 0x3d, 
-	0x20, 0x22, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6b, 0x65, 
-	0x79, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x3d, 0x3d, 
-	0x20, 0x22, 0x63, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x62, 
-	0x6f, 0x61, 0x72, 0x64, 0x2e, 0x69, 0x73, 0x44, 0x6f, 0x77, 0x6e, 0x28, 0x22, 0x6c, 0x63, 0x74, 0x72, 0x6c, 
-	0x22, 0x2c, 0x20, 0x22, 0x72, 0x63, 0x74, 0x72, 0x6c, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x70, 0x79, 0x54, 0x6f, 0x43, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 
-	0x64, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x74, 0x6f, 
-	0x75, 0x63, 0x68, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x6c, 
-	0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x67, 0x65, 0x74, 0x54, 0x69, 0x74, 0x6c, 
-	0x65, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x23, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 
-	0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x55, 0x6e, 0x74, 0x69, 0x74, 0x6c, 
-	0x65, 0x64, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x47, 
-	0x61, 0x6d, 0x65, 0x22, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x20, 
-	0x3d, 0x20, 0x7b, 0x22, 0x4f, 0x4b, 0x22, 0x2c, 0x20, 0x22, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x22, 0x7d, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 
-	0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x3d, 0x20, 
-	0x22, 0x43, 0x6f, 0x70, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 
-	0x22, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 
-	0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x68, 0x6f, 0x77, 
-	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6f, 0x78, 0x28, 0x22, 0x51, 0x75, 0x69, 0x74, 0x20, 0x22, 
-	0x2e, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x2e, 0x22, 0x3f, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x2c, 0x20, 0x62, 
-	0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x3d, 0x20, 
-	0x31, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 
-	0x20, 0x3d, 0x3d, 0x20, 0x33, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x70, 0x79, 0x54, 0x6f, 0x43, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 
-	0x72, 0x64, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x6c, 0x65, 0x65, 
-	0x70, 0x28, 0x30, 0x2e, 0x31, 0x29, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a,
-	0x2d, 0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 
-	0x20, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x2e, 0x0a,
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
-	0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a,
-	0x0a,
-	0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x66, 
-	0x61, 0x6c, 0x73, 0x65, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x65, 
-	0x66, 0x65, 0x72, 0x45, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x3d, 0x20, 
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x20, 
-	0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x20, 0x3d, 0x20, 
-	0x28, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 
-	0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x70, 
-	0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x0a,
-	0x09, 0x09, 0x69, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x28, 0x2e, 
-	0x2e, 0x2e, 0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x61, 
-	0x72, 0x6c, 0x79, 0x69, 0x6e, 0x69, 0x74, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x20, 
-	0x66, 0x61, 0x69, 0x6c, 0x73, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x20, 0x61, 0x6e, 
-	0x64, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 
-	0x6c, 0x79, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x78, 
-	0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x2c, 0x20, 0x65, 
-	0x72, 0x72, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x20, 
-	0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x75, 0x6e, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x73, 0x2c, 
-	0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x76, 0x61, 
-	0x6c, 0x75, 0x65, 0x2c, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x68, 
-	0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x20, 0x74, 0x6f, 
-	0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x78, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 
-	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x2c, 0x20, 0x64, 0x65, 0x66, 0x65, 0x72, 0x45, 0x72, 
-	0x72, 0x68, 0x61, 0x6e, 0x64, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x4e, 0x4f, 0x54, 0x45, 0x3a, 0x20, 0x57, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x27, 
-	0x74, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x64, 
-	0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x27, 0x64, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 
-	0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x65, 0x66, 0x65, 0x72, 0x45, 0x72, 
-	0x72, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x6f, 0x6e, 0x20, 
-	0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x0a,
-	0x09, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2c, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x3d, 0x20, 0x78, 
-	0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x75, 0x6e, 0x2c, 0x20, 0x64, 0x65, 
-	0x66, 0x65, 0x72, 0x45, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x0a,
-	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x69, 0x74, 0x0a,
-	0x0a,
-	0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x64, 0x6f, 0x0a,
-	0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x2c, 
-	0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x78, 0x70, 
-	0x63, 0x61, 0x6c, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2c, 0x20, 0x64, 0x65, 0x66, 0x65, 0x72, 0x45, 0x72, 
-	0x72, 0x68, 0x61, 0x6e, 0x64, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 
-	0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x74, 
-	0x61, 0x72, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x09, 0x63, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x2e, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x28, 
-	0x29, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x0a,
-	0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a,
-	0x65, 0x6e, 0x64, 0x0a,
-}; // [boot.lua]
-} // love