SDL: Added SDL_SCALEMODE_PIXELART

From 3e9e22f17dcc234cf77e73af47982905bd9b6912 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 12 Mar 2025 08:45:25 -0700
Subject: [PATCH] Added SDL_SCALEMODE_PIXELART

This is based on the algorithm presented by t3ssel8r:
https://www.youtube.com/watch?v=d6tp43wZqps
---
 include/SDL3/SDL_surface.h                    |    5 +-
 src/render/SDL_render.c                       |   10 +-
 src/render/direct3d/SDL_render_d3d.c          |    1 +
 .../direct3d11/D3D11_PixelShader_Advanced.h   | 2021 +++++-----
 .../direct3d11/D3D11_PixelShader_Colors.h     |  438 +-
 .../direct3d11/D3D11_PixelShader_Common.hlsli |   23 +-
 .../direct3d11/D3D11_PixelShader_Textures.h   |  510 +--
 src/render/direct3d11/D3D11_VertexShader.h    |  484 +--
 src/render/direct3d11/SDL_render_d3d11.c      |   23 +-
 .../direct3d12/D3D12_PixelShader_Advanced.h   | 2456 ++++++------
 .../direct3d12/D3D12_PixelShader_Colors.h     |  671 ++--
 .../direct3d12/D3D12_PixelShader_Common.hlsli |   23 +-
 .../direct3d12/D3D12_PixelShader_Textures.h   |  809 ++--
 .../direct3d12/D3D12_RootSig_Advanced.h       |    6 +-
 src/render/direct3d12/D3D12_RootSig_Color.h   |    6 +-
 src/render/direct3d12/D3D12_RootSig_Texture.h |    6 +-
 .../direct3d12/D3D12_Shader_Common.hlsli      |    6 +-
 .../direct3d12/D3D12_VertexShader_Advanced.h  |  786 ++--
 .../direct3d12/D3D12_VertexShader_Color.h     |  754 ++--
 .../direct3d12/D3D12_VertexShader_Texture.h   |  770 ++--
 src/render/direct3d12/SDL_render_d3d12.c      |   25 +-
 src/render/gpu/SDL_render_gpu.c               |   55 +-
 src/render/gpu/SDL_shaders_gpu.c              |   14 +
 src/render/gpu/SDL_shaders_gpu.h              |    2 +
 src/render/gpu/shaders/dxil.h                 |    8 +-
 src/render/gpu/shaders/msl.h                  |    8 +-
 src/render/gpu/shaders/spir-v.h               |    8 +-
 .../gpu/shaders/texture_pixelart.frag.hlsli   |   33 +
 .../shaders/texture_rgb_pixelart.frag.dxil.h  |  401 ++
 .../shaders/texture_rgb_pixelart.frag.hlsl    |    8 +
 .../shaders/texture_rgb_pixelart.frag.msl.h   |   87 +
 .../shaders/texture_rgb_pixelart.frag.spv.h   |  148 +
 .../shaders/texture_rgba_pixelart.frag.dxil.h |  402 ++
 .../shaders/texture_rgba_pixelart.frag.hlsl   |    8 +
 .../shaders/texture_rgba_pixelart.frag.msl.h  |   86 +
 .../shaders/texture_rgba_pixelart.frag.spv.h  |  141 +
 src/render/metal/SDL_render_metal.m           |   22 +-
 src/render/metal/SDL_shaders_metal.metal      |   33 +-
 src/render/metal/SDL_shaders_metal_ios.h      | 3012 +++++++-------
 .../metal/SDL_shaders_metal_iphonesimulator.h | 3400 ++++++++--------
 src/render/metal/SDL_shaders_metal_macos.h    | 2779 ++++++-------
 src/render/metal/SDL_shaders_metal_tvos.h     | 3012 +++++++-------
 .../metal/SDL_shaders_metal_tvsimulator.h     | 3506 +++++++++--------
 src/render/opengl/SDL_render_gl.c             |   28 +-
 src/render/opengl/SDL_shaders_gl.c            |   90 +-
 src/render/opengl/SDL_shaders_gl.h            |    2 +
 src/render/opengles2/SDL_render_gles2.c       |  108 +-
 src/render/opengles2/SDL_shaders_gles2.c      |  318 +-
 src/render/opengles2/SDL_shaders_gles2.h      |    4 +
 src/render/ps2/SDL_render_ps2.c               |    1 +
 src/render/psp/SDL_render_psp.c               |    1 +
 src/render/software/SDL_render_sw.c           |    2 +-
 src/render/vitagxm/SDL_render_vita_gxm.c      |    1 +
 src/render/vulkan/SDL_render_vulkan.c         |   20 +-
 .../vulkan/VULKAN_PixelShader_Advanced.h      |  558 +--
 src/render/vulkan/VULKAN_PixelShader_Colors.h |   66 +-
 .../vulkan/VULKAN_PixelShader_Common.hlsli    |   22 +-
 .../vulkan/VULKAN_PixelShader_Textures.h      |   84 +-
 src/render/vulkan/VULKAN_VertexShader.h       |   14 +-
 src/video/SDL_stretch.c                       |   14 +-
 src/video/SDL_surface.c                       |   15 +-
 test/testautomation_surface.c                 |    6 +-
 test/testscale.c                              |    1 +
 63 files changed, 15602 insertions(+), 12759 deletions(-)
 create mode 100644 src/render/gpu/shaders/texture_pixelart.frag.hlsli
 create mode 100644 src/render/gpu/shaders/texture_rgb_pixelart.frag.dxil.h
 create mode 100644 src/render/gpu/shaders/texture_rgb_pixelart.frag.hlsl
 create mode 100644 src/render/gpu/shaders/texture_rgb_pixelart.frag.msl.h
 create mode 100644 src/render/gpu/shaders/texture_rgb_pixelart.frag.spv.h
 create mode 100644 src/render/gpu/shaders/texture_rgba_pixelart.frag.dxil.h
 create mode 100644 src/render/gpu/shaders/texture_rgba_pixelart.frag.hlsl
 create mode 100644 src/render/gpu/shaders/texture_rgba_pixelart.frag.msl.h
 create mode 100644 src/render/gpu/shaders/texture_rgba_pixelart.frag.spv.h

diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h
index 7bff7cfb287e4..7cd9d2b122760 100644
--- a/include/SDL3/SDL_surface.h
+++ b/include/SDL3/SDL_surface.h
@@ -83,8 +83,9 @@ typedef Uint32 SDL_SurfaceFlags;
 typedef enum SDL_ScaleMode
 {
     SDL_SCALEMODE_INVALID = -1,
-    SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */
-    SDL_SCALEMODE_LINEAR   /**< linear filtering */
+    SDL_SCALEMODE_NEAREST,  /**< nearest pixel sampling */
+    SDL_SCALEMODE_LINEAR,   /**< linear filtering */
+    SDL_SCALEMODE_PIXELART  /**< nearest pixel sampling with improved scaling for pixel art */
 } SDL_ScaleMode;
 
 /**
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index dbca32ce43875..a03796a4e6ff8 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -1964,8 +1964,12 @@ bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
 {
     CHECK_TEXTURE_MAGIC(texture, false);
 
-    if (scaleMode != SDL_SCALEMODE_NEAREST &&
-        scaleMode != SDL_SCALEMODE_LINEAR) {
+    switch (scaleMode) {
+    case SDL_SCALEMODE_NEAREST:
+    case SDL_SCALEMODE_LINEAR:
+    case SDL_SCALEMODE_PIXELART:
+        break;
+    default:
         return SDL_InvalidParamError("scaleMode");
     }
 
@@ -5707,7 +5711,7 @@ static bool CreateDebugTextAtlas(SDL_Renderer *renderer)
     // Convert temp surface into texture
     SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, atlas);
     if (texture) {
-        SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
+        SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_PIXELART);
         renderer->debug_char_texture_atlas = texture;
     }
     SDL_DestroySurface(atlas);
diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c
index f70b56170bae8..fa1b1b7bf6684 100644
--- a/src/render/direct3d/SDL_render_d3d.c
+++ b/src/render/direct3d/SDL_render_d3d.c
@@ -921,6 +921,7 @@ static void UpdateTextureScaleMode(D3D_RenderData *data, SDL_ScaleMode scaleMode
 {
     if (scaleMode != data->scaleMode[index]) {
         switch (scaleMode) {
+        case SDL_SCALEMODE_PIXELART:
         case SDL_SCALEMODE_NEAREST:
             IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_POINT);
             IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
diff --git a/src/render/direct3d11/D3D11_PixelShader_Advanced.h b/src/render/direct3d11/D3D11_PixelShader_Advanced.h
index a1297c981cffa..59c90ae6e5032 100644
--- a/src/render/direct3d11/D3D11_PixelShader_Advanced.h
+++ b/src/render/direct3d11/D3D11_PixelShader_Advanced.h
@@ -3,7 +3,7 @@
 // Generated by Microsoft (R) HLSL Shader Compiler 10.1
 //
 //
-// Buffer Definitions: 
+// Buffer Definitions:
 //
 // cbuffer Constants
 // {
@@ -12,14 +12,15 @@
 //   float texture_type;                // Offset:    4 Size:     4
 //   float input_type;                  // Offset:    8 Size:     4
 //   float color_scale;                 // Offset:   12 Size:     4
-//   float tonemap_method;              // Offset:   16 Size:     4
-//   float tonemap_factor1;             // Offset:   20 Size:     4
-//   float tonemap_factor2;             // Offset:   24 Size:     4
-//   float sdr_white_point;             // Offset:   28 Size:     4
-//   float4 Yoffset;                    // Offset:   32 Size:    16
-//   float4 Rcoeff;                     // Offset:   48 Size:    16
-//   float4 Gcoeff;                     // Offset:   64 Size:    16
-//   float4 Bcoeff;                     // Offset:   80 Size:    16
+//   float4 texel_size;                 // Offset:   16 Size:    16
+//   float tonemap_method;              // Offset:   32 Size:     4
+//   float tonemap_factor1;             // Offset:   36 Size:     4
+//   float tonemap_factor2;             // Offset:   40 Size:     4
+//   float sdr_white_point;             // Offset:   44 Size:     4
+//   float4 Yoffset;                    // Offset:   48 Size:    16
+//   float4 Rcoeff;                     // Offset:   64 Size:    16
+//   float4 Gcoeff;                     // Offset:   80 Size:    16
+//   float4 Bcoeff;                     // Offset:   96 Size:    16
 //
 // }
 //
@@ -28,11 +29,11 @@
 //
 // Name                                 Type  Format         Dim      HLSL Bind  Count
 // ------------------------------ ---------- ------- ----------- -------------- ------
-// sampler0                          sampler      NA          NA             s0      1 
-// texture0                          texture  float4          2d             t0      1 
-// texture1                          texture  float4          2d             t1      1 
-// texture2                          texture  float4          2d             t2      1 
-// Constants                         cbuffer      NA          NA            cb0      1 
+// sampler0                          sampler      NA          NA             s0      1
+// texture0                          texture  float4          2d             t0      1
+// texture1                          texture  float4          2d             t1      1
+// texture2                          texture  float4          2d             t2      1
+// Constants                         cbuffer      NA          NA            cb0      1
 //
 //
 //
@@ -40,8 +41,8 @@
 //
 // Name                 Index   Mask Register SysValue  Format   Used
 // -------------------- ----- ------ -------- -------- ------- ------
-// SV_POSITION              0   xyzw        0      POS   float       
-// TEXCOORD                 0   xy          1     NONE   float   xy  
+// SV_POSITION              0   xyzw        0      POS   float
+// TEXCOORD                 0   xy          1     NONE   float   xy
 // COLOR                    0   xyzw        2     NONE   float   xyzw
 //
 //
@@ -53,7 +54,7 @@
 //
 ps_5_0
 dcl_globalFlags refactoringAllowed
-dcl_constantbuffer CB0[6], immediateIndexed
+dcl_constantbuffer CB0[7], immediateIndexed
 dcl_sampler s0, mode_default
 dcl_resource_texture2d (float,float,float,float) t0
 dcl_resource_texture2d (float,float,float,float) t1
@@ -65,46 +66,71 @@ dcl_temps 7
 eq r0.xyzw, cb0[0].yzzz, l(0.000000, 3.000000, 2.000000, 1.000000)
 if_nz r0.x
   mov r1.xyzw, l(1.000000,1.000000,1.000000,1.000000)
-else 
+else
   eq r0.x, cb0[0].y, l(1.000000)
   if_nz r0.x
     sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v1.xyxx, t0.xyzw, s0
-  else 
+  else
     eq r0.x, cb0[0].y, l(2.000000)
     if_nz r0.x
-      sample_indexable(texture2d)(float,float,float,float) r2.x, v1.xyxx, t0.xyzw, s0
-      sample_indexable(texture2d)(float,float,float,float) r2.yz, v1.xyxx, t1.zxyw, s0
-      add r2.xyz, r2.xyzx, cb0[2].xyzx
-      dp3 r1.x, r2.xyzx, cb0[3].xyzx
-      dp3 r1.y, r2.xyzx, cb0[4].xyzx
-      dp3 r1.z, r2.xyzx, cb0[5].xyzx
-    else 
+      deriv_rtx_coarse r2.xy, v1.xyxx
+      deriv_rty_coarse r2.zw, v1.xxxy
+      add r3.xy, |r2.zwzz|, |r2.xyxx|
+      mul r3.xy, r3.xyxx, cb0[1].zwzz
+      max r3.xy, r3.xyxx, l(0.000010, 0.000010, 0.000000, 0.000000)
+      min r3.xy, r3.xyxx, l(1.000000, 1.000000, 0.000000, 0.000000)
+      mul r3.zw, r3.xxxy, l(0.000000, 0.000000, 0.500000, 0.500000)
+      mad r3.zw, v1.xxxy, cb0[1].zzzw, -r3.zzzw
+      add r3.xy, -r3.xyxx, l(1.000000, 1.000000, 0.000000, 0.000000)
+      frc r4.xy, r3.zwzz
+      add r4.zw, -r3.xxxy, l(0.000000, 0.000000, 1.000000, 1.000000)
+      add r3.xy, -r3.xyxx, r4.xyxx
+      div r4.xy, l(1.000000, 1.000000, 1.000000, 1.000000), r4.zwzz
+      mul_sat r3.xy, r3.xyxx, r4.xyxx
+      mad r4.xy, r3.xyxx, l(-2.000000, -2.000000, 0.000000, 0.000000), l(3.000000, 3.000000, 0.000000, 0.000000)
+      mul r3.xy, r3.xyxx, r3.xyxx
+      round_ni r3.zw, r3.zzzw
+      mad r3.xy, r4.xyxx, r3.xyxx, r3.zwzz
+      add r3.xy, r3.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000)
+      mul r3.xy, r3.xyxx, cb0[1].xyxx
+      sample_d_indexable(texture2d)(float,float,float,float) r1.xyzw, r3.xyxx, t0.xyzw, s0, r2.xyxx, r2.zwzz
+    else
       eq r0.x, cb0[0].y, l(3.000000)
       if_nz r0.x
         sample_indexable(texture2d)(float,float,float,float) r2.x, v1.xyxx, t0.xyzw, s0
-        sample_indexable(texture2d)(float,float,float,float) r2.yz, v1.xyxx, t1.zyxw, s0
-        add r2.xyz, r2.xyzx, cb0[2].xyzx
-        dp3 r1.x, r2.xyzx, cb0[3].xyzx
-        dp3 r1.y, r2.xyzx, cb0[4].xyzx
-        dp3 r1.z, r2.xyzx, cb0[5].xyzx
-      else 
+        sample_indexable(texture2d)(float,float,float,float) r2.yz, v1.xyxx, t1.zxyw, s0
+        add r2.xyz, r2.xyzx, cb0[3].xyzx
+        dp3 r1.x, r2.xyzx, cb0[4].xyzx
+        dp3 r1.y, r2.xyzx, cb0[5].xyzx
+        dp3 r1.z, r2.xyzx, cb0[6].xyzx
+      else
         eq r0.x, cb0[0].y, l(4.000000)
         if_nz r0.x
           sample_indexable(texture2d)(float,float,float,float) r2.x, v1.xyxx, t0.xyzw, s0
-          sample_indexable(texture2d)(float,float,float,float) r2.y, v1.xyxx, t1.yxzw, s0
-          sample_indexable(texture2d)(float,float,float,float) r2.z, v1.xyxx, t2.yzxw, s0
-          add r2.xyz, r2.xyzx, cb0[2].xyzx
-          dp3 r1.x, r2.xyzx, cb0[3].xyzx
-          dp3 r1.y, r2.xyzx, cb0[4].xyzx
-          dp3 r1.z, r2.xyzx, cb0[5].xyzx
-        else 
-          mov r1.xyz, l(1.000000,0,0,0)
-        endif 
-      endif 
-    endif 
-    mov r1.w, l(1.000000)
-  endif 
-endif 
+          sample_indexable(texture2d)(float,float,float,float) r2.yz, v1.xyxx, t1.zyxw, s0
+          add r2.xyz, r2.xyzx, cb0[3].xyzx
+          dp3 r1.x, r2.xyzx, cb0[4].xyzx
+          dp3 r1.y, r2.xyzx, cb0[5].xyzx
+          dp3 r1.z, r2.xyzx, cb0[6].xyzx
+        else
+          eq r0.x, cb0[0].y, l(5.000000)
+          if_nz r0.x
+            sample_indexable(texture2d)(float,float,float,float) r2.x, v1.xyxx, t0.xyzw, s0
+            sample_indexable(texture2d)(float,float,float,float) r2.y, v1.xyxx, t1.yxzw, s0
+            sample_indexable(texture2d)(float,float,float,float) r2.z, v1.xyxx, t2.yzxw, s0
+            add r2.xyz, r2.xyzx, cb0[3].xyzx
+            dp3 r1.x, r2.xyzx, cb0[4].xyzx
+            dp3 r1.y, r2.xyzx, cb0[5].xyzx
+            dp3 r1.z, r2.xyzx, cb0[6].xyzx
+          else
+            mov r1.xyz, l(1.000000,0,0,0)
+          endif
+        endif
+      endif
+      mov r1.w, l(1.000000)
+    endif
+  endif
+endif
 log r2.xyz, |r1.xyzx|
 mul r2.xyz, r2.xyzx, l(0.012683, 0.012683, 0.012683, 0.000000)
 exp r2.xyz, r2.xyzx
@@ -116,11 +142,11 @@ log r2.xyz, |r2.xyzx|
 mul r2.xyz, r2.xyzx, l(6.277395, 6.277395, 6.277395, 0.000000)
 exp r2.xyz, r2.xyzx
 mul r2.xyz, r2.xyzx, l(10000.000000, 10000.000000, 10000.000000, 0.000000)
-div r2.xyz, r2.xyzx, cb0[1].wwww
+div r2.xyz, r2.xyzx, cb0[2].wwww
 movc r2.xyz, r0.yyyy, r2.xyzx, r1.xyzx
-ne r0.x, cb0[1].x, l(0.000000)
-mul r3.xyz, r2.xyzx, cb0[1].yyyy
-eq r4.xy, cb0[1].xxxx, l(1.000000, 2.000000, 0.000000, 0.000000)
+ne r0.x, cb0[2].x, l(0.000000)
+mul r3.xyz, r2.xyzx, cb0[2].yyyy
+eq r4.xy, cb0[2].xxxx, l(1.000000, 2.000000, 0.000000, 0.000000)
 dp3 r5.x, l(0.627404, 0.329283, 0.043313, 0.000000), r2.xyzx
 dp3 r5.y, l(0.069097, 0.919541, 0.011362, 0.000000), r2.xyzx
 dp3 r5.z, l(0.016391, 0.088013, 0.895595, 0.000000), r2.xyzx
@@ -128,7 +154,7 @@ movc r5.xyz, r0.zzzz, r5.xyzx, r2.xyzx
 max r2.w, r5.z, r5.y
 max r2.w, r2.w, r5.x
 lt r3.w, l(0.000000), r2.w
-mad r4.zw, cb0[1].yyyz, r2.wwww, l(0.000000, 0.000000, 1.000000, 1.000000)
+mad r4.zw, cb0[2].yyyz, r2.wwww, l(0.000000, 0.000000, 1.000000, 1.000000)
 div r2.w, r4.z, r4.w
 mul r6.xyz, r2.wwww, r5.xyzx
 movc r5.xyz, r3.wwww, r6.xyzx, r5.xyzx
@@ -150,9 +176,9 @@ if_nz r0.w
     mul r5.xyz, r5.xyzx, l(2.400000, 2.400000, 2.400000, 0.000000)
     exp r5.xyz, r5.xyzx
     movc r2.xyz, r3.xyzx, r4.xyzx, r5.xyzx
-  endif 
+  endif
   mul r1.xyz, r2.xyzx, cb0[0].wwww
-else 
+else
   if_nz r0.z
     mul r1.xyz, r2.xyzx, cb0[0].wwww
     ne r0.x, l(0.000000, 0.000000, 0.000000, 0.000000), cb0[0].x
@@ -164,8 +190,8 @@ else
       exp r4.xyz, r4.xyzx
       mad r4.xyz, r4.xyzx, l(1.055000, 1.055000, 1.055000, 0.000000), l(-0.055000, -0.055000, -0.055000, 0.000000)
       movc_sat r1.xyz, r0.xzwx, r3.xyzx, r4.xyzx
-    endif 
-  else 
+    endif
+  else
     if_nz r0.y
       dp3 r0.x, l(1.660496, -0.587656, -0.072840, 0.000000), r2.xyzx
       dp3 r0.y, l(-0.124547, 1.132895, -0.008348, 0.000000), r2.xyzx
@@ -180,881 +206,1024 @@ else
         exp r4.xyz, r4.xyzx
         mad r4.xyz, r4.xyzx, l(1.055000, 1.055000, 1.055000, 0.000000), l(-0.055000, -0.055000, -0.055000, 0.000000)
         movc_sat r1.xyz, r0.xyzx, r3.xyzx, r4.xyzx
-      endif 
-    else 
+      endif
+    else
       mul r1.xyz, r2.xyzx, cb0[0].wwww
-    endif 
-  endif 
-endif 
+    endif
+  endif
+endif
 mul o0.xyzw, r1.xyzw, v2.xyzw
-ret 
-// Approximately 126 instruction slots used
+ret
+// Approximately 151 instruction slots used
 #endif
 
 const BYTE g_main[] =
 {
-     68,  88,  66,  67, 154, 200, 
-     28,  25,  30, 140,   0, 183, 
-    251,  32,   6, 185, 210,  29, 
-    251, 110,   1,   0,   0,   0, 
-     64,  20,   0,   0,   5,   0, 
-      0,   0,  52,   0,   0,   0, 
-     80,   4,   0,   0, 196,   4, 
-      0,   0, 248,   4,   0,   0, 
-    164,  19,   0,   0,  82,  68, 
-     69,  70,  20,   4,   0,   0, 
-      1,   0,   0,   0,  12,   1, 
-      0,   0,   5,   0,   0,   0, 
-     60,   0,   0,   0,   0,   5, 
-    255, 255,   0,   1,   0,   0, 
-    233,   3,   0,   0,  82,  68, 
-     49,  49,  60,   0,   0,   0, 
-     24,   0,   0,   0,  32,   0, 
-      0,   0,  40,   0,   0,   0, 
-     36,   0,   0,   0,  12,   0, 
-      0,   0,   0,   0,   0,   0, 
-    220,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   1,   0, 
-      0,   0, 229,   0,   0,   0, 
-      2,   0,   0,   0,   5,   0, 
-      0,   0,   4,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-     13,   0,   0,   0, 238,   0, 
-      0,   0,   2,   0,   0,   0, 
-      5,   0,   0,   0,   4,   0, 
-      0,   0, 255, 255, 255, 255, 
-      1,   0,   0,   0,   1,   0, 
-      0,   0,  13,   0,   0,   0, 
-    247,   0,   0,   0,   2,   0, 
-      0,   0,   5,   0,   0,   0, 
-      4,   0,   0,   0, 255, 255, 
-    255, 255,   2,   0,   0,   0, 
-      1,   0,   0,   0,  13,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-      1,   0,   0,   0, 115,  97, 
-    109, 112, 108, 101, 114,  48, 
-      0, 116, 101, 120, 116, 117, 
-    114, 101,  48,   0, 116, 101, 
-    120, 116, 117, 114, 101,  49, 
-      0, 116, 101, 120, 116, 117, 
-    114, 101,  50,   0,  67, 111, 
-    110, 115, 116,  97, 110, 116, 
-    115,   0, 171, 171,   0,   1, 
-      0,   0,  12,   0,   0,   0, 
-     36,   1,   0,   0,  96,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   4,   3, 
-      0,   0,   0,   0,   0,   0, 
-      4,   0,   0,   0,   2,   0, 
-      0,   0,  24,   3,   0,   0, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0,  60,   3,   0,   0, 
-      4,   0,   0,   0,   4,   0, 
-      0,   0,   2,   0,   0,   0, 
-     24,   3,   0,   0,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-     73,   3,   0,   0,   8,   0, 
-      0,   0,   4,   0,   0,   0, 
-      2,   0,   0,   0,  24,   3, 
-      0,   0,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0,  84,   3, 
-      0,   0,  12,   0,   0,   0, 
-      4,   0,   0,   0,   2,   0, 
-      0,   0,  24,   3,   0,   0, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0,  96,   3,   0,   0, 
-     16,   0,   0,   0,   4,   0, 
-      0,   0,   2,   0,   0,   0, 
-     24,   3,   0,   0,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-    111,   3,   0,   0,  20,   0, 
-      0,   0,   4,   0,   0,   0, 
-      2,   0,   0,   0,  24,   3, 
-      0,   0,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0, 127,   3, 
-      0,   0,  24,   0,   0,   0, 
-      4,   0,   0,   0,   2,   0, 
-      0,   0,  24,   3,   0,   0, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0, 143,   3,   0,   0, 
-     28,   0,   0,   0,   4,   0, 
-      0,   0,   2,   0,   0,   0, 
-     24,   3,   0,   0,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-    159,   3,   0,   0,  32,   0, 
-      0,   0,  16,   0,   0,   0, 
-      2,   0,   0,   0, 176,   3, 
-      0,   0,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0, 212,   3, 
-      0,   0,  48,   0,   0,   0, 
-     16,   0,   0,   0,   2,   0, 
-      0,   0, 176,   3,   0,   0, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0, 219,   3,   0,   0, 
-     64,   0,   0,   0,  16,   0, 
-      0,   0,   2,   0,   0,   0, 
-    176,   3,   0,   0,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0, 255, 255, 
-    255, 255,   0,   0,   0,   0, 
-    226,   3,   0,   0,  80,   0, 
-      0,   0,  16,   0,   0,   0, 
-      2,   0,   0,   0, 176,   3, 
-      0,   0,   0,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0, 115,  99, 
-     82,  71,  66,  95, 111, 117, 
-    116, 112, 117, 116,   0, 102, 
-    108, 111,  97, 116,   0, 171, 
-      0,   0,   3,   0,   1,   0, 
-      1,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,  17,   3,   0,   0, 
-    116, 101, 120, 116, 117, 114, 
-    101,  95, 116, 121, 112, 101, 
-      0, 105, 110, 112, 117, 116, 
-     95, 116, 121, 112, 101,   0, 
-     99, 111, 108, 111, 114,  95, 
-    115,  99,  97, 108, 101,   0, 
-    116, 111, 110, 101, 109,  97, 
-    112,  95, 109, 101, 116, 104, 
-    111, 100,   0, 116, 111, 110, 
-    101, 109,  97, 112,  95, 102, 
-     97,  99, 116, 111, 114,  49, 
-      0, 116, 111, 110, 101, 109, 
-     97, 112,  95, 102,  97,  99, 
-    116, 111, 114,  50,   0, 115, 
-    100, 114,  95, 119, 104, 105, 
-    116, 101,  95, 112, 111, 105, 
-    110, 116,   0,  89, 111, 102, 
-    102, 115, 101, 116,   0, 102, 
-    108, 111,  97, 116,  52,   0, 
-    171, 171,   1,   0,   3,   0, 
-      1,   0,   4,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0, 167,   3, 
-      0,   0,  82,  99, 111, 101, 
-    102, 102,   0,  71,  99, 111, 
-    101, 102, 102,   0,  66,  99, 
-    111, 101, 102, 102,   0,  77, 
-    105,  99, 114, 111, 115, 111, 
-    102, 116,  32,  40,  82,  41, 
-     32,  72,  76,  83,  76,  32, 
-     83, 104,  97, 100, 101, 114, 
-     32,  67, 111, 109, 112, 105, 
-    108, 101, 114,  32,  49,  48, 
-     46,  49,   0, 171, 171, 171, 
-     73,  83,  71,  78, 108,   0, 
-      0,   0,   3,   0,   0,   0, 
-      8,   0,   0,   0,  80,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-     15,   0,   0,   0,  92,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   1,   0,   0,   0, 
-      3,   3,   0,   0, 101,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   2,   0,   0,   0, 
-     15,  15,   0,   0,  83,  86, 
-     95,  80,  79,  83,  73,  84, 
-     73,  79,  78,   0,  84,  69, 
-     88,  67,  79,  79,  82,  68, 
-      0,  67,  79,  76,  79,  82, 
-      0, 171,  79,  83,  71,  78, 
-     44,   0,   0,   0,   1,   0, 
-      0,   0,   8,   0,   0,   0, 
-     32,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,   0,   0, 
-      0,   0,  15,   0,   0,   0, 
-     83,  86,  95,  84,  65,  82, 
-     71,  69,  84,   0, 171, 171, 
-     83,  72,  69,  88, 164,  14, 
-      0,   0,  80,   0,   0,   0, 
-    169,   3,   0,   0, 106,   8, 
-      0,   1,  89,   0,   0,   4, 
-     70, 142,  32,   0,   0,   0, 
-      0,   0,   6,   0,   0,   0, 
-     90,   0,   0,   3,   0,  96, 
-     16,   0,   0,   0,   0,   0, 
-     88,  24,   0,   4,   0, 112, 
-     16,   0,   0,   0,   0,   0, 
-     85,  85,   0,   0,  88,  24, 
-      0,   4,   0, 112,  16,   0, 
-      1,   0,   0,   0,  85,  85, 
-      0,   0,  88,  24,   0,   4, 
-      0, 112,  16,   0,   2,   0, 
-      0,   0,  85,  85,   0,   0, 
-     98,  16,   0,   3,  50,  16, 
-     16,   0,   1,   0,   0,   0, 
-     98,  16,   0,   3, 242,  16, 
-     16,   0,   2,   0,   0,   0, 
-    101,   0,   0,   3, 242,  32, 
-     16,   0,   0,   0,   0,   0, 
-    104,   0,   0,   2,   7,   0, 
-      0,   0,  24,   0,   0,  11, 
-    242,   0,  16,   0,   0,   0, 
-      0,   0, 150, 138,  32,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   2,  64,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     64,  64,   0,   0,   0,  64, 
-      0,   0, 128,  63,  31,   0, 
-      4,   3,  10,   0,  16,   0, 
-      0,   0,   0,   0,  54,   0, 
-      0,   8, 242,   0,  16,   0, 
-      1,   0,   0,   0,   2,  64, 
-      0,   0,   0,   0, 128,  63, 
-      0,   0, 128,  63,   0,   0, 
-    128,  63,   0,   0, 128,  63, 
-     18,   0,   0,   1,  24,   0, 
-      0,   8,  18,   0,  16,   0, 
-      0,   0,   0,   0,  26, 128, 
-     32,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   1,  64, 
-      0,   0,   0,   0, 128,  63, 
-     31,   0,   4,   3,  10,   0, 
-     16,   0,   0,   0,   0,   0, 
-     69,   0,   0, 139, 194,   0, 
-      0, 128,  67,  85,  21,   0, 
-    242,   0,  16,   0,   1,   0, 
-      0,   0,  70,  16,  16,   0, 
-      1,   0,   0,   0,  70, 126, 
-     16,   0,   0,   0,   0,   0, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,  18,   0,   0,   1, 
-     24,   0,   0,   8,  18,   0, 
-     16,   0,   0,   0,   0,   0, 
-     26, 128,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,  64,   0,   0,   0,   0, 
-      0,  64,  31,   0,   4,   3, 
-     10,   0,  16,   0,   0,   0, 
-      0,   0,  69,   0,   0, 139, 
-    194,   0,   0, 128,  67,  85, 
-     21,   0,  18,   0,  16,   0, 
-      2,   0,   0,   0,  70,  16, 
-     16,   0,   1,   0,   0,   0, 
-     70, 126,  16,   0,   0,   0, 
-      0,   0,   0,  96,  16,   0, 
-      0,   0,   0,   0,  69,   0, 
-      0, 139, 194,   0,   0, 128, 
-     67,  85,  21,   0,  98,   0, 
-     16,   0,   2,   0,   0,   0, 
-     70,  16,  16,   0,   1,   0, 
-      0,   0,  38, 125,  16,   0, 
-      1,   0,   0,   0,   0,  96, 
-     16,   0,   0,   0,   0,   0, 
-      0,   0,   0,   8, 114,   0, 
-     16,   0,   2,   0,   0,   0, 
-     70,   2,  16,   0,   2,   0, 
-      0,   0,  70, 130,  32,   0, 
-      0,   0,   0,   0,   2,   0, 
-      0,   0,  16,   0,   0,   8, 
-     18,   0,  16,   0,   1,   0, 
-      0,   0,  70,   2,  16,   0, 
-      2,   0,   0,   0,  70, 130, 
-     32,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,  16,   0, 
-      0,   8,  34,   0,  16,   0, 
-      1,   0,   0,   0,  70,   2, 
-     16,   0,   2,   0,   0,   0, 
-     70, 130,  32,   0,   0,   0, 
-      0,   0,   4,   0,   0,   0, 
-     16,   0,   0,   8,  66,   0, 
-     16,   0,   1,   0,   0,   0, 
-     70,   2,  16,   0,   2,   0, 
-      0,   0,  70, 130,  32,   0, 
-      0,   0,   0,   0,   5,   0, 
-      0,   0,  18,   0,   0,   1, 
-     24,   0,   0,   8,  18,   0, 
-     16,   0,   0,   0,   0,   0, 
-     26, 128,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,  64,   0,   0,   0,   0, 
-     64,  64,  31,   0,   4,   3, 
-     10,   0,  16,   0,   0,   0, 
-      0,   0,  69,   0,   0, 139, 
-    194,   0,   0, 128,  67,  85, 
-     21,   0,  18,   0,  16,   0, 
-      2,   0,   0,   0,  70,  16, 
-     16,   0,   1,   0,   0,   0, 
-     70, 126,  16,   0,   0,   0, 
-      0,   0,   0,  96,  16,   0, 
-      0,   0,   0,   0,  69,   0, 
-      0, 139, 194,   0,   0, 128, 
-     67,  85,  21,   0,  98,   0, 
-     16,   0,   2,   0,   0,   0, 
-     70,  16,  16,   0,   1,   0, 
-      0,   0, 102, 124,  16,   0, 
-      1,   0,   0,   0,   0,  96, 
-     16,   0,   0,   0,   0,   0, 
-      0,   0,   0,   8, 114,   0, 
-     16,   0,   2,   0,   0,   0, 
-     70,   2,  16,   0,   2,   0, 
-      0,   0,  70, 130,  32,   0, 
-      0,   0,   0,   0,   2,   0, 
-      0,   0,  16,   0,   0,   8, 
-     18,   0,  16,   0,   1,   0, 
-      0,   0,  70,   2,  16,   0, 
-      2,   0,   0,   0,  70, 130, 
-     32,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,  16,   0, 
-      0,   8,  34,   0,  16,   0, 
-      1,   0,   0,   0,  70,   2, 
-     16,   0,   2,   0,   0,   0, 
-     70, 130,  32,   0,   0,   0, 
-      0,   0,   4,   0,   0,   0, 
-     16,   0,   0,   8,  66,   0, 
-     16,   0,   1,   0,   0,   0, 
-     70,   2,  16,   0,   2,   0, 
-      0,   0,  70, 130,  32,   0, 
-      0,   0,   0,   0,   5,   0, 
-      0,   0,  18,   0,   0,   1, 
-     24,   0,   0,   8,  18,   0, 
-     16,   0,   0,   0,   0,   0, 
-     26, 128,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,  64,   0,   0,   0,   0, 
-    128,  64,  31,   0,   4,   3, 
-     10,   0,  16,   0,   0,   0, 
-      0,   0,  69,   0,   0, 139, 
-    194,   0,   0, 128,  67,  85, 
-     21,   0,  18,   0,  16,   0, 
-      2,   0,   0,   0,  70,  16, 
-     16,   0,   1,   0,   0,   0, 
-     70, 126,  16,   0,   0,   0, 
-      0,   0,   0,  96,  16,   0, 
-      0,   0,   0,   0,  69,   0, 
-      0, 139, 194,   0,   0, 128, 
-     67,  85,  21,   0,  34,   0, 
-     16,   0,   2,   0,   0,   0, 
-     70,  16,  16,   0,   1,   0, 
-      0,   0,  22, 126,  16,   0, 
-      1,   0,   0,   0,   0,  96, 
-     16,   0,   0,   0,   0,   0, 
-     69,   0,   0, 139, 194,   0, 
-      0, 128,  67,  85,  21,   0, 
-     66,   0,  16,   0,   2,   0, 
-      0,   0,  70,  16,  16,   0, 
-      1,   0,   0,   0, 150, 124, 
-     16,   0,   2,   0,   0,   0, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,   0,   0,   0,   8, 
-    114,   0,  16,   0,   2,   0, 
-      0,   0,  70,   2,  16,   0, 
-      2,   0,   0,   0,  70, 130, 
-     32,   0,   0,   0,   0,   0, 
-      2,   0,   0,   0,  16,   0, 
-      0,   8,  18,   0,  16,   0, 
-      1,   0,   0,   0,  70,   2, 
-     16,   0,   2,   0,   0,   0, 
-     70, 130,  32,   0,   0,   0, 
-      0,   0,   3,   0, 

(Patch may be truncated, please check the link at the top of this post.)