SDL: Fixed blitting bitmaps with a non-zero x offset (6d2d2)

From 6d2d2839542cc7c0828e90827330f4b5211fd33d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 6 Nov 2025 22:13:22 -0800
Subject: [PATCH] Fixed blitting bitmaps with a non-zero x offset

Also added basic testautomation coverage of bitmap blits

Fixes https://github.com/libsdl-org/sdl2-compat/issues/546

(cherry picked from commit a2ed1a41970c9db0bb477f6614a340df649e3626)
---
 src/video/SDL_blit.c          |  21 +++-
 src/video/SDL_blit.h          |   1 +
 src/video/SDL_blit_0.c        | 218 +++++++++++++++++++++++++++++-----
 test/testautomation_surface.c |  90 +++++++++++++-
 4 files changed, 290 insertions(+), 40 deletions(-)

diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c
index 860a2a9bc2e7d..ea7e070074af8 100644
--- a/src/video/SDL_blit.c
+++ b/src/video/SDL_blit.c
@@ -64,17 +64,26 @@ static bool SDLCALL SDL_SoftBlit(SDL_Surface *src, const SDL_Rect *srcrect,
         SDL_BlitInfo *info = &src->map.info;
 
         // Set up the blit information
-        info->src = (Uint8 *)src->pixels +
-                    (Uint16)srcrect->y * src->pitch +
-                    (Uint16)srcrect->x * info->src_fmt->bytes_per_pixel;
+        if (info->src_fmt->bits_per_pixel >= 8) {
+            info->src = (Uint8 *)src->pixels +
+                        srcrect->y * src->pitch +
+                        srcrect->x * info->src_fmt->bytes_per_pixel;
+        } else {
+            info->src = (Uint8 *)src->pixels +
+                        srcrect->y * src->pitch +
+                        (srcrect->x * info->src_fmt->bits_per_pixel) / 8;
+            info->leading_skip =
+                        ((srcrect->x * info->src_fmt->bits_per_pixel) % 8) /
+                        info->src_fmt->bits_per_pixel;
+        }
         info->src_w = srcrect->w;
         info->src_h = srcrect->h;
         info->src_pitch = src->pitch;
         info->src_skip =
             info->src_pitch - info->src_w * info->src_fmt->bytes_per_pixel;
-        info->dst =
-            (Uint8 *)dst->pixels + (Uint16)dstrect->y * dst->pitch +
-            (Uint16)dstrect->x * info->dst_fmt->bytes_per_pixel;
+        info->dst = (Uint8 *)dst->pixels +
+                    dstrect->y * dst->pitch +
+                    dstrect->x * info->dst_fmt->bytes_per_pixel;
         info->dst_w = dstrect->w;
         info->dst_h = dstrect->h;
         info->dst_pitch = dst->pitch;
diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h
index 714feebe0aaeb..c6e13a836d808 100644
--- a/src/video/SDL_blit.h
+++ b/src/video/SDL_blit.h
@@ -60,6 +60,7 @@ typedef struct
     int src_w, src_h;
     int src_pitch;
     int src_skip;
+    int leading_skip;
     SDL_Surface *dst_surface;
     Uint8 *dst;
     int dst_w, dst_h;
diff --git a/src/video/SDL_blit_0.c b/src/video/SDL_blit_0.c
index 0d05bddfb1a32..dcc5a71165dbc 100644
--- a/src/video/SDL_blit_0.c
+++ b/src/video/SDL_blit_0.c
@@ -45,6 +45,8 @@ SDL_FORCE_INLINE void BlitBto1(SDL_BlitInfo *info, const Uint32 srcbpp)
     dstskip = info->dst_skip;
     map = info->table;
 
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -56,7 +58,13 @@ SDL_FORCE_INLINE void BlitBto1(SDL_BlitInfo *info, const Uint32 srcbpp)
         if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte >>= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -73,7 +81,13 @@ SDL_FORCE_INLINE void BlitBto1(SDL_BlitInfo *info, const Uint32 srcbpp)
         } else {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte <<= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -92,7 +106,13 @@ SDL_FORCE_INLINE void BlitBto1(SDL_BlitInfo *info, const Uint32 srcbpp)
         if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte >>= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -109,7 +129,13 @@ SDL_FORCE_INLINE void BlitBto1(SDL_BlitInfo *info, const Uint32 srcbpp)
         } else {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte <<= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -147,6 +173,8 @@ SDL_FORCE_INLINE void BlitBto2(SDL_BlitInfo *info, const Uint32 srcbpp)
     dstskip = info->dst_skip / 2;
     map = (Uint16 *)info->table;
 
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -157,7 +185,13 @@ SDL_FORCE_INLINE void BlitBto2(SDL_BlitInfo *info, const Uint32 srcbpp)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -174,7 +208,13 @@ SDL_FORCE_INLINE void BlitBto2(SDL_BlitInfo *info, const Uint32 srcbpp)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -210,6 +250,8 @@ SDL_FORCE_INLINE void BlitBto3(SDL_BlitInfo *info, const Uint32 srcbpp)
     dstskip = info->dst_skip;
     map = info->table;
 
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -220,7 +262,13 @@ SDL_FORCE_INLINE void BlitBto3(SDL_BlitInfo *info, const Uint32 srcbpp)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -240,7 +288,13 @@ SDL_FORCE_INLINE void BlitBto3(SDL_BlitInfo *info, const Uint32 srcbpp)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -280,6 +334,8 @@ SDL_FORCE_INLINE void BlitBto4(SDL_BlitInfo *info, const Uint32 srcbpp)
     dstskip = info->dst_skip / 4;
     map = (Uint32 *)info->table;
 
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -290,7 +346,13 @@ SDL_FORCE_INLINE void BlitBto4(SDL_BlitInfo *info, const Uint32 srcbpp)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -307,7 +369,13 @@ SDL_FORCE_INLINE void BlitBto4(SDL_BlitInfo *info, const Uint32 srcbpp)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -339,7 +407,8 @@ SDL_FORCE_INLINE void BlitBto1Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     Uint8 *palmap = info->table;
     int c;
 
-    // Set up some basic variables
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -351,7 +420,13 @@ SDL_FORCE_INLINE void BlitBto1Key(SDL_BlitInfo *info, const Uint32 srcbpp)
         if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte >>= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -368,7 +443,13 @@ SDL_FORCE_INLINE void BlitBto1Key(SDL_BlitInfo *info, const Uint32 srcbpp)
         } else {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte <<= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -387,7 +468,13 @@ SDL_FORCE_INLINE void BlitBto1Key(SDL_BlitInfo *info, const Uint32 srcbpp)
         if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte >>= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -404,7 +491,13 @@ SDL_FORCE_INLINE void BlitBto1Key(SDL_BlitInfo *info, const Uint32 srcbpp)
         } else {
             while (height--) {
                 Uint8 byte = 0, bit;
-                for (c = 0; c < width; ++c) {
+                for (c = 0; c < info->leading_skip; ++c) {
+                    if (!(c & align)) {
+                        byte = *src++;
+                    }
+                    byte <<= srcbpp;
+                }
+                for (; c < width; ++c) {
                     if (!(c & align)) {
                         byte = *src++;
                     }
@@ -437,7 +530,8 @@ SDL_FORCE_INLINE void BlitBto2Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     Uint8 *palmap = info->table;
     int c;
 
-    // Set up some basic variables
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -449,7 +543,13 @@ SDL_FORCE_INLINE void BlitBto2Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -466,7 +566,13 @@ SDL_FORCE_INLINE void BlitBto2Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -498,7 +604,8 @@ SDL_FORCE_INLINE void BlitBto3Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     Uint8 *palmap = info->table;
     int c;
 
-    // Set up some basic variables
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -509,7 +616,13 @@ SDL_FORCE_INLINE void BlitBto3Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -526,7 +639,13 @@ SDL_FORCE_INLINE void BlitBto3Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -558,7 +677,8 @@ SDL_FORCE_INLINE void BlitBto4Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     Uint8 *palmap = info->table;
     int c;
 
-    // Set up some basic variables
+    width += info->leading_skip;
+
     if (srcbpp == 4)
         srcskip += width - (width + 1) / 2;
     else if (srcbpp == 2)
@@ -570,7 +690,13 @@ SDL_FORCE_INLINE void BlitBto4Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -587,7 +713,13 @@ SDL_FORCE_INLINE void BlitBto4Key(SDL_BlitInfo *info, const Uint32 srcbpp)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -622,7 +754,8 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info)
     unsigned dR, dG, dB, dA;
     const unsigned A = info->a;
 
-    // Set up some basic variables
+    width += info->leading_skip;
+
     srcbpp = srcfmt->bytes_per_pixel;
     dstbpp = dstfmt->bytes_per_pixel;
     if (srcbpp == 4)
@@ -637,7 +770,13 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -659,7 +798,13 @@ static void BlitBtoNAlpha(SDL_BlitInfo *info)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -700,7 +845,8 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
     const unsigned A = info->a;
     Uint32 ckey = info->colorkey;
 
-    // Set up some basic variables
+    width += info->leading_skip;
+
     srcbpp = srcfmt->bytes_per_pixel;
     dstbpp = dstfmt->bytes_per_pixel;
     if (srcbpp == 4)
@@ -715,7 +861,13 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
     if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte >>= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
@@ -737,7 +889,13 @@ static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
     } else {
         while (height--) {
             Uint8 byte = 0, bit;
-            for (c = 0; c < width; ++c) {
+            for (c = 0; c < info->leading_skip; ++c) {
+                if (!(c & align)) {
+                    byte = *src++;
+                }
+                byte <<= srcbpp;
+            }
+            for (; c < width; ++c) {
                 if (!(c & align)) {
                     byte = *src++;
                 }
diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c
index 2a52fbb4bf5e2..1f660df33551d 100644
--- a/test/testautomation_surface.c
+++ b/test/testautomation_surface.c
@@ -959,6 +959,83 @@ static int SDLCALL surface_testBlitBlendMul(void *arg)
     return TEST_COMPLETED;
 }
 
+/**
+ * Tests blitting bitmaps
+ */
+static int SDLCALL surface_testBlitBitmap(void *arg)
+{
+    const SDL_PixelFormat formats[] = {
+        SDL_PIXELFORMAT_INDEX1LSB,
+        SDL_PIXELFORMAT_INDEX1MSB,
+        SDL_PIXELFORMAT_INDEX2LSB,
+        SDL_PIXELFORMAT_INDEX2MSB,
+        SDL_PIXELFORMAT_INDEX4LSB,
+        SDL_PIXELFORMAT_INDEX4MSB
+    };
+    Uint8 pixel;
+    int i, j;
+    bool result;
+    SDL_Surface *dst = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888);
+    SDL_Color colors[] = {
+        { 0x00, 0x00, 0x00, 0xFF },
+        { 0xFF, 0xFF, 0xFF, 0xFF }
+    };
+    SDL_Palette *palette;
+    Uint32 value, expected = 0xFFFFFFFF;
+
+    palette = SDL_CreatePalette(SDL_arraysize(colors));
+    SDLTest_AssertCheck(palette != NULL, "SDL_CreatePalette() != NULL, result = %p", palette);
+
+    result = SDL_SetPaletteColors(palette, colors, 0, SDL_arraysize(colors));
+    SDLTest_AssertCheck(result, "SDL_SetPaletteColors, result = %s", result ? "true" : "false");
+
+    for (i = 0; i < SDL_arraysize(formats); ++i) {
+        SDL_PixelFormat format = formats[i];
+        int bpp = SDL_BITSPERPIXEL(format);
+        int width = (8 / bpp);
+
+        if (SDL_PIXELORDER(format) == SDL_BITMAPORDER_1234) {
+            switch (bpp) {
+            case 1:
+                pixel = 0x80;
+                break;
+            case 2:
+                pixel = 0x40;
+                break;
+            case 4:
+                pixel = 0x10;
+                break;
+            default:
+                SDL_assert(!"Unexpected bpp");
+                break;
+            }
+        } else {
+            pixel = 0x01;
+        }
+        for (j = 0; j < width; ++j) {
+            SDL_Rect rect = { j, 0, 1, 1 };
+            SDL_Surface *src = SDL_CreateSurfaceFrom(width, 1, format, &pixel, 1);
+            SDL_SetSurfacePalette(src, palette);
+            *(Uint32 *)dst->pixels = 0;
+            result = SDL_BlitSurface(src, &rect, dst, NULL);
+            SDLTest_AssertCheck(result, "SDL_BlitSurface(%s pixel %d), result = %s", SDL_GetPixelFormatName(format), j, result ? "true" : "false");
+            value = *(Uint32 *)dst->pixels;
+            SDLTest_AssertCheck(value == expected, "Expected value == 0x%" SDL_PRIx32 ", actually = 0x%" SDL_PRIx32, expected, value);
+            SDL_DestroySurface(src);
+
+            if (SDL_PIXELORDER(format) == SDL_BITMAPORDER_1234) {
+                pixel >>= bpp;
+            } else {
+                pixel <<= bpp;
+            }
+        }
+    }
+    SDL_DestroyPalette(palette);
+    SDL_DestroySurface(dst);
+
+    return TEST_COMPLETED;
+}
+
 /**
  * Tests blitting invalid surfaces.
  */
@@ -974,14 +1051,14 @@ static int SDLCALL surface_testBlitInvalid(void *arg)
     SDLTest_AssertCheck(invalid->pixels == NULL, "Check surface pixels are NULL");
 
     result = SDL_BlitSurface(invalid, NULL, valid, NULL);
-    SDLTest_AssertCheck(result == true, "SDL_BlitSurface(invalid, NULL, valid, NULL), result = %s\n", result ? "true" : "false");
+    SDLTest_AssertCheck(result == true, "SDL_BlitSurface(invalid, NULL, valid, NULL), result = %s", result ? "true" : "false");
     result = SDL_BlitSurface(valid, NULL, invalid, NULL);
-    SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, NULL, invalid, NULL), result = %s\n", result ? "true" : "false");
+    SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, NULL, invalid, NULL), result = %s", result ? "true" : "false");
 
     result = SDL_BlitSurfaceScaled(invalid, NULL, valid, NULL, SDL_SCALEMODE_NEAREST);
-    SDLTest_AssertCheck(result == false, "SDL_BlitSurfaceScaled(invalid, NULL, valid, NULL, SDL_SCALEMODE_NEAREST), result = %s\n", result ? "true" : "false");
+    SDLTest_AssertCheck(result == false, "SDL_BlitSurfaceScaled(invalid, NULL, valid, NULL, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
     result = SDL_BlitSurfaceScaled(valid, NULL, invalid, NULL, SDL_SCALEMODE_NEAREST);
-    SDLTest_AssertCheck(result == false, "SDL_BlitSurfaceScaled(valid, NULL, invalid, NULL, SDL_SCALEMODE_NEAREST), result = %s\n", result ? "true" : "false");
+    SDLTest_AssertCheck(result == false, "SDL_BlitSurfaceScaled(valid, NULL, invalid, NULL, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
 
     SDL_DestroySurface(valid);
     SDL_DestroySurface(invalid);
@@ -1699,6 +1776,10 @@ static const SDLTest_TestCaseReference surfaceTestBlitBlendMul = {
     surface_testBlitBlendMul, "surface_testBlitBlendMul", "Tests blitting routines with mul blending mode.", TEST_ENABLED
 };
 
+static const SDLTest_TestCaseReference surfaceTestBlitBitmap = {
+    surface_testBlitBitmap, "surface_testBlitBitmap", "Tests blitting routines with bitmap surfaces.", TEST_ENABLED
+};
+
 static const SDLTest_TestCaseReference surfaceTestBlitInvalid = {
     surface_testBlitInvalid, "surface_testBlitInvalid", "Tests blitting routines with invalid surfaces.", TEST_ENABLED
 };
@@ -1755,6 +1836,7 @@ static const SDLTest_TestCaseReference *surfaceTests[] = {
     &surfaceTestBlitBlendAddPremultiplied,
     &surfaceTestBlitBlendMod,
     &surfaceTestBlitBlendMul,
+    &surfaceTestBlitBitmap,
     &surfaceTestBlitInvalid,
     &surfaceTestBlitsWithBadCoordinates,
     &surfaceTestOverflow,