fixed several bugs with shared playfield bitmap in MM game engine
authorHolger Schemel <info@artsoft.org>
Thu, 30 Mar 2023 19:36:06 +0000 (21:36 +0200)
committerHolger Schemel <info@artsoft.org>
Thu, 30 Mar 2023 19:36:06 +0000 (21:36 +0200)
This fixes several bugs that resulted from using the normal background
bitmap for the Mirror Magic game engine (which was possible because
this game engine does not support scrolling levels and therefore only
uses the visible playfield viewport).

The main bugs fixed by this change are preventing MM engine levels
that are larger than the visible playfield area drawing over the
border area, and some problems with envelope style requests (like
restoring an outdated copy of the backbuffer after an envelope
request was answered after a game was lost).

While fixing these visible bugs, this change also brings a cleanup of
the MM engine code, which used three different bitmap pointers before
(that all pointed to the same backbuffer bitmap).

src/engines.h
src/game_mm/mm_game.c
src/game_mm/mm_init.c
src/game_mm/mm_main.h
src/game_mm/mm_tools.c
src/game_mm/mm_tools.h
src/init.c
src/tools.c

index 142c064f7040b42e17ceee386eb9c28d72176375..f2f9fe2f76cc5ce7f05322f978a2401d14739084 100644 (file)
@@ -59,12 +59,13 @@ boolean isNextAnimationFrame_SP(int, int);
 // ============================================================================
 
 void SetDrawtoField(int);
+void BackToFront(void);
 
 int el2img_mm(int);
 int el_act2img_mm(int, int);
 
 void CheckSingleStepMode_MM(boolean, boolean);
-void ShowEnvelope_MM(int);
+void ShowEnvelope(int);
 
 int getGraphicAnimationFrame(int, int);
 int getGraphicAnimationFrameXY(int, int, int);
index 5cdc8ed3114712b6e97fd8f11d1ce9c22a8f8b21..c5cfa1d562c738c32adbd5c5d6ec84cdc8d8c61b 100644 (file)
@@ -364,7 +364,7 @@ static void DrawLaserLines(struct XY *points, int num_points, int mode)
   Pixel pixel_drawto = (mode == DL_LASER_ENABLED ? pen_ray     : pen_bg);
   Pixel pixel_buffer = (mode == DL_LASER_ENABLED ? WHITE_PIXEL : BLACK_PIXEL);
 
-  DrawLines(drawto, points, num_points, pixel_drawto);
+  DrawLines(drawto_mm, points, num_points, pixel_drawto);
 
   BEGIN_NO_HEADLESS
   {
@@ -644,8 +644,8 @@ void InitGameEngine_MM(void)
   BEGIN_NO_HEADLESS
   {
     // initialize laser bitmap to current playfield (screen) size
-    ReCreateBitmap(&laser_bitmap, drawto->width, drawto->height);
-    ClearRectangle(laser_bitmap, 0, 0, drawto->width, drawto->height);
+    ReCreateBitmap(&laser_bitmap, drawto_mm->width, drawto_mm->height);
+    ClearRectangle(laser_bitmap, 0, 0, drawto_mm->width, drawto_mm->height);
   }
   END_NO_HEADLESS
 
@@ -762,7 +762,7 @@ void InitGameActions_MM(void)
 
     DrawLevel_MM();
 
-    BackToFront();
+    BackToFront_MM();
 
 #ifdef DEBUG
     if (setup.quick_doors)
@@ -795,7 +795,7 @@ static void FadeOutLaser(void)
 
     DrawLaser(0, DL_LASER_ENABLED);
 
-    BackToFront();
+    BackToFront_MM();
     Delay_WithScreenUpdates(50);
   }
 
@@ -2567,7 +2567,7 @@ static void OpenGrayBall(int x, int y)
       DrawWalls_MM(x, y, Store[x][y]);
 
       // copy wall tile to spare bitmap for "melting" animation
-      BlitBitmap(drawto, bitmap_db_field, cSX + x * TILEX, cSY + y * TILEY,
+      BlitBitmap(drawto_mm, bitmap_db_field, cSX + x * TILEX, cSY + y * TILEY,
                 TILEX, TILEY, x * TILEX, y * TILEY);
 
       DrawElement_MM(x, y, EL_GRAY_BALL);
@@ -2600,7 +2600,7 @@ static void OpenGrayBall(int x, int y)
        getGraphicSource(graphic, 0, &bitmap, &gx, &gy);
       }
 
-      BlitBitmap(bitmap, drawto, gx + dx, gy + dy, 6, 6,
+      BlitBitmap(bitmap, drawto_mm, gx + dx, gy + dy, 6, 6,
                 cSX + x * TILEX + dx, cSY + y * TILEY + dy);
 
       laser.redraw = TRUE;
@@ -2653,7 +2653,7 @@ static void OpenEnvelope(int x, int y)
 
       ScanLaser();
 
-      ShowEnvelope_MM(nr);
+      ShowEnvelope(nr);
     }
   }
 }
@@ -3750,7 +3750,7 @@ static void GameActions_MM_Ext(void)
 
       UpdateAndDisplayGameControlValues();
 
-      BackToFront();
+      BackToFront_MM();
     }
 
     Tile[ELX][ELY] = laser.dest_element = EL_FUEL_EMPTY;
@@ -3849,7 +3849,7 @@ static void MovePacMen(void)
     }
 
     DrawField_MM(nx, ny);
-    BackToFront();
+    BackToFront_MM();
 
     if (!laser.fuse_off)
     {
index a82b61df28d21917bb3a6258b2bda0e7e62c1f5d..d982d190dcbb0cffda52ef888e7d5f74d3346cb9 100644 (file)
 #include "mm_main.h"
 
 
+Bitmap *drawto_mm;
+
 struct EngineSnapshotInfo_MM engine_snapshot_mm;
 
 
+void InitGfxBuffers_MM(void)
+{
+  ReCreateBitmap(&drawto_mm, video.width, video.height);
+}
+
 unsigned int InitEngineRandom_MM(int seed)
 {
   return InitEngineRandom(seed);
index 1404fb03401b6ee1411ae48903655c0dc566b06e..16246b2b7cd8cd42d369f18770a4d96597dd91e6 100644 (file)
 #define LEVEL_SCORE_ELEMENTS   16      // level elements with score
 
 
-extern DrawBuffer      *drawto_field;
+extern DrawBuffer      *drawto_mm;
 extern DrawBuffer      *bitmap_db_field;
 
 extern int             game_status;
index dd7edbdf16660f5115b6e2200a20e52692053080..39bb24671273009ff21270cc47acb651e879e626 100644 (file)
@@ -41,9 +41,16 @@ void SetDrawtoField_MM(int mode)
   SetTileCursorSXSY(cSX, cSY);
 }
 
+void BackToFront_MM(void)
+{
+  BlitScreenToBitmap_MM(backbuffer);
+
+  BackToFront();
+}
+
 void ClearWindow(void)
 {
-  ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+  ClearRectangle(drawto_mm, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
 
   SetDrawtoField(DRAW_TO_BACKBUFFER);
   SetDrawtoField_MM(DRAW_TO_BACKBUFFER);
@@ -58,7 +65,7 @@ void DrawGraphicAnimation_MM(int x, int y, int graphic, int frame)
 
   getGraphicSource(graphic, frame, &bitmap, &src_x, &src_y);
 
-  BlitBitmap(bitmap, drawto_field, src_x, src_y, TILEX, TILEY,
+  BlitBitmap(bitmap, drawto_mm, src_x, src_y, TILEX, TILEY,
             cFX + x * TILEX, cFY + y * TILEY);
 }
 
@@ -105,7 +112,7 @@ void DrawGraphicThruMask_MM(int x, int y, int graphic, int frame)
   }
 #endif
 
-  DrawGraphicThruMaskExt_MM(drawto_field, cFX + x * TILEX, cFY + y * TILEY,
+  DrawGraphicThruMaskExt_MM(drawto_mm, cFX + x * TILEX, cFY + y * TILEY,
                            graphic, frame);
 
   MarkTileDirty(x,y);
@@ -127,7 +134,7 @@ void DrawGraphicThruMaskExt_MM(DrawBuffer *d, int dest_x, int dest_y,
 
 void DrawMiniGraphic_MM(int x, int y, int graphic)
 {
-  DrawMiniGraphicExt_MM(drawto, cSX + x * MINI_TILEX, cSY + y * MINI_TILEY,
+  DrawMiniGraphicExt_MM(drawto_mm, cSX + x * MINI_TILEX, cSY + y * MINI_TILEY,
                        graphic);
 
   MarkTileDirty(x / 2, y / 2);
@@ -246,10 +253,10 @@ void DrawGraphicShifted_MM(int x,int y, int dx,int dy, int graphic,
 #endif
 
   if (mask_mode == USE_MASKING)
-    BlitBitmapMasked(src_bitmap, drawto_field,
+    BlitBitmapMasked(src_bitmap, drawto_mm,
                     src_x, src_y, TILEX, TILEY, dest_x, dest_y);
   else
-    BlitBitmap(src_bitmap, drawto_field,
+    BlitBitmap(src_bitmap, drawto_mm,
               src_x, src_y, width, height, dest_x, dest_y);
 
   MarkTileDirty(x,y);
@@ -434,10 +441,10 @@ void DrawWallsExt_MM(int x, int y, int element, int draw_mask)
       continue;
 
     if (element & (1 << i))
-      BlitBitmap(bitmap, drawto, gx, gy, MINI_TILEX, MINI_TILEY,
+      BlitBitmap(bitmap, drawto_mm, gx, gy, MINI_TILEX, MINI_TILEY,
                 dest_x, dest_y);
     else
-      ClearRectangle(drawto, dest_x, dest_y, MINI_TILEX, MINI_TILEY);
+      ClearRectangle(drawto_mm, dest_x, dest_y, MINI_TILEX, MINI_TILEY);
   }
 
   MarkTileDirty(x, y);
@@ -488,7 +495,7 @@ void DrawWallsAnimation_MM(int x, int y, int element, int phase, int bit_mask)
       getSizedGraphicSource(graphic, frame, MINI_TILESIZE, &bitmap,
                            &src_x, &src_y);
 
-      BlitBitmap(bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY,
+      BlitBitmap(bitmap, drawto_mm, src_x, src_y, MINI_TILEX, MINI_TILEY,
                 dst_x, dst_y);
     }
   }
@@ -1243,6 +1250,6 @@ void RedrawPlayfield_MM(void)
 
 void BlitScreenToBitmap_MM(Bitmap *target_bitmap)
 {
-  BlitBitmap(drawto_field, target_bitmap,
+  BlitBitmap(drawto_mm, target_bitmap,
             REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
 }
index f226f420ed88656e4a54695af543d2338f0d6f13..5f116c900ed4f86a90cfa841413393d4c31526d7 100644 (file)
@@ -50,7 +50,8 @@
 
 
 void SetDrawtoField_MM(int);
-void BackToFront(void);
+void BackToFront_MM(void);
+
 void FadeToFront(void);
 void ClearWindow(void);
 
index aae262f58332f4479498f562389b9ec9f6a7b9e4..718e1ca2c0d37c2d7643f199d4bce3511ac608fa 100644 (file)
@@ -5713,6 +5713,7 @@ void InitGfxBuffers(void)
 
   InitGfxBuffers_EM();
   InitGfxBuffers_SP();
+  InitGfxBuffers_MM();
 }
 
 static void InitGfx(void)
index 124cab52fd644914325f55ea753b1535a8dfab15..45447912c488dfba517c9b5718fc342d2567fe97 100644 (file)
@@ -3008,19 +3008,6 @@ void ShowEnvelope(int envelope_nr)
   BackToFront();
 }
 
-void ShowEnvelope_MM(int envelope_nr)
-{
-  BlitBitmap(backbuffer, bitmap_db_field, REAL_SX, REAL_SY,
-            FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
-
-  ShowEnvelope(envelope_nr);
-
-  SetDrawtoField(DRAW_TO_BACKBUFFER);
-
-  BlitBitmap(bitmap_db_field, backbuffer, REAL_SX, REAL_SY,
-            FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
-}
-
 static void PrepareEnvelopeRequestToScreen(Bitmap *bitmap, int sx, int sy,
                                           int xsize, int ysize)
 {