fixed saving game engine snapshots (save after game actions are finished)
[rocksndiamonds.git] / src / tools.c
index 30e9cd5660b5de185b254e3600845d92d49b29e3..e534cc29c3e79c465cd50d0ee79420ed0bd5bc17 100644 (file)
@@ -528,6 +528,22 @@ static void PrintFrameTimeDebugging()
 }
 #endif
 
+static int unifiedRedrawMask(int mask)
+{
+  if (mask & REDRAW_ALL)
+    return REDRAW_ALL;
+
+  if (mask & REDRAW_FIELD && mask & REDRAW_DOORS)
+    return REDRAW_ALL;
+
+  return mask;
+}
+
+static boolean equalRedrawMasks(int mask_1, int mask_2)
+{
+  return unifiedRedrawMask(mask_1) == unifiedRedrawMask(mask_2);
+}
+
 void BackToFront()
 {
   static int last_redraw_mask = REDRAW_NONE;
@@ -625,9 +641,10 @@ void BackToFront_WithFrameDelay(unsigned int frame_delay_value)
   SetVideoFrameDelay(frame_delay_value_old);
 }
 
+static int fade_type_skip = FADE_TYPE_NONE;
+
 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
 {
-  static int fade_type_skip = FADE_TYPE_NONE;
   void (*draw_border_function)(void) = NULL;
   int x, y, width, height;
   int fade_delay, post_delay;
@@ -719,7 +736,8 @@ static void SetScreenStates_BeforeFadingIn()
   global.anim_status = global.anim_status_next;
 
   // store backbuffer with all animations that will be started after fading in
-  PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
+  if (fade_type_skip != FADE_MODE_SKIP_FADE_IN)
+    PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
 
   // set screen mode for animations back to fading
   global.anim_status = GAME_MODE_PSEUDO_FADING;
@@ -731,10 +749,6 @@ static void SetScreenStates_AfterFadingIn()
   gfx.fade_border_source_status = global.border_status;
 
   global.anim_status = global.anim_status_next;
-
-  // force update of global animation status in case of rapid screen changes
-  redraw_mask = REDRAW_ALL;
-  BackToFront();
 }
 
 static void SetScreenStates_BeforeFadingOut()
@@ -746,7 +760,8 @@ static void SetScreenStates_BeforeFadingOut()
   global.anim_status = GAME_MODE_PSEUDO_FADING;
 
   // store backbuffer with all animations that will be stopped for fading out
-  PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
+  if (fade_type_skip != FADE_MODE_SKIP_FADE_OUT)
+    PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
 }
 
 static void SetScreenStates_AfterFadingOut()
@@ -773,10 +788,18 @@ void FadeIn(int fade_mask)
   FADE_SYSIZE = FULL_SYSIZE;
 
   SetScreenStates_AfterFadingIn();
+
+  // force update of global animation status in case of rapid screen changes
+  redraw_mask = REDRAW_ALL;
+  BackToFront();
 }
 
 void FadeOut(int fade_mask)
 {
+  // update screen if areas covered by "fade_mask" and "redraw_mask" differ
+  if (!equalRedrawMasks(fade_mask, redraw_mask))
+    BackToFront();
+
   SetScreenStates_BeforeFadingOut();
 
 #if 0
@@ -1196,52 +1219,64 @@ int getGraphicAnimationFrame(int graphic, int sync_frame)
                           sync_frame);
 }
 
-void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
-                             Bitmap **bitmap, int *x, int *y,
-                             boolean get_backside)
+void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
 {
   struct GraphicInfo *g = &graphic_info[graphic];
-  Bitmap *src_bitmap = g->bitmap;
-  int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
-  int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
   int tilesize_capped = MIN(MAX(1, tilesize), TILESIZE);
 
-  // if no in-game graphics defined, always use standard graphic size
-  if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
-    tilesize = TILESIZE;
-
   if (tilesize == gfx.standard_tile_size)
-    src_bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
+    *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
   else if (tilesize == game.tile_size)
-    src_bitmap = g->bitmaps[IMG_BITMAP_GAME];
+    *bitmap = g->bitmaps[IMG_BITMAP_GAME];
   else
-    src_bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
+    *bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
+}
+
+void getGraphicSourceXY(int graphic, int frame, int *x, int *y,
+                       boolean get_backside)
+{
+  struct GraphicInfo *g = &graphic_info[graphic];
+  int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
+  int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
 
   if (g->offset_y == 0)                /* frames are ordered horizontally */
   {
     int max_width = g->anim_frames_per_line * g->width;
     int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
 
-    src_x = pos % max_width;
-    src_y = src_y % g->height + pos / max_width * g->height;
+    *x = pos % max_width;
+    *y = src_y % g->height + pos / max_width * g->height;
   }
   else if (g->offset_x == 0)   /* frames are ordered vertically */
   {
     int max_height = g->anim_frames_per_line * g->height;
     int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
 
-    src_x = src_x % g->width + pos / max_height * g->width;
-    src_y = pos % max_height;
+    *x = src_x % g->width + pos / max_height * g->width;
+    *y = pos % max_height;
   }
   else                         /* frames are ordered diagonally */
   {
-    src_x = src_x + frame * g->offset_x;
-    src_y = src_y + frame * g->offset_y;
+    *x = src_x + frame * g->offset_x;
+    *y = src_y + frame * g->offset_y;
   }
+}
 
-  *bitmap = src_bitmap;
-  *x = src_x * tilesize / g->tile_size;
-  *y = src_y * tilesize / g->tile_size;
+void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
+                             Bitmap **bitmap, int *x, int *y,
+                             boolean get_backside)
+{
+  struct GraphicInfo *g = &graphic_info[graphic];
+
+  // if no in-game graphics defined, always use standard graphic size
+  if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
+    tilesize = TILESIZE;
+
+  getGraphicSourceBitmap(graphic, tilesize, bitmap);
+  getGraphicSourceXY(graphic, frame, x, y, get_backside);
+
+  *x = *x * tilesize / g->tile_size;
+  *y = *y * tilesize / g->tile_size;
 }
 
 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
@@ -1271,40 +1306,8 @@ void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
 inline static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
                                       int *x, int *y, boolean get_backside)
 {
-  struct GraphicInfo *g = &graphic_info[graphic];
-  int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
-  int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
-
-  if (TILESIZE_VAR != TILESIZE)
-    return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
-                                   get_backside);
-
-  *bitmap = g->bitmap;
-
-  if (g->offset_y == 0)                /* frames are ordered horizontally */
-  {
-    int max_width = g->anim_frames_per_line * g->width;
-    int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
-
-    *x = pos % max_width;
-    *y = src_y % g->height + pos / max_width * g->height;
-  }
-  else if (g->offset_x == 0)   /* frames are ordered vertically */
-  {
-    int max_height = g->anim_frames_per_line * g->height;
-    int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
-
-    *x = src_x % g->width + pos / max_height * g->width;
-    *y = pos % max_height;
-  }
-  else                         /* frames are ordered diagonally */
-  {
-    *x = src_x + frame * g->offset_x;
-    *y = src_y + frame * g->offset_y;
-  }
-
-  *x = *x * TILESIZE_VAR / g->tile_size;
-  *y = *y * TILESIZE_VAR / g->tile_size;
+  getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
+                          get_backside);
 }
 
 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
@@ -3662,7 +3665,10 @@ static int RequestHandleEvents(unsigned int req_state)
          }
 
          case EVENT_KEYPRESS:
-           switch (GetEventKey((KeyEvent *)&event, TRUE))
+         {
+           Key key = GetEventKey((KeyEvent *)&event, TRUE);
+
+           switch (key)
            {
              case KSYM_space:
                if (req_state & REQ_CONFIRM)
@@ -3684,12 +3690,15 @@ static int RequestHandleEvents(unsigned int req_state)
                break;
 
              default:
+               HandleKeysDebug(key);
                break;
            }
 
            if (req_state & REQ_PLAYER)
              result = 0;
+
            break;
+         }
 
          case EVENT_KEYRELEASE:
            ClearPlayerAction();
@@ -4451,7 +4460,8 @@ unsigned int MoveDoor(unsigned int door_state)
          int sync_frame = kk_door * door_delay_value;
          int frame = getGraphicAnimationFrame(dpc->graphic, sync_frame);
 
-         getGraphicSource(dpc->graphic, frame, &bitmap, &g_src_x, &g_src_y);
+         getFixedGraphicSource(dpc->graphic, frame, &bitmap,
+                               &g_src_x, &g_src_y);
        }
 
        // draw door panel
@@ -8023,42 +8033,38 @@ void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
                                boolean any_player_snapping,
                                boolean any_player_dropping)
 {
-  static boolean player_was_waiting = TRUE;
-
   if (frame == 0 && !any_player_dropping)
   {
-    if (!player_was_waiting)
+    if (!local_player->was_waiting)
     {
-      if (!SaveEngineSnapshotToList())
+      if (!CheckSaveEngineSnapshotToList())
        return;
 
-      player_was_waiting = TRUE;
+      local_player->was_waiting = TRUE;
     }
   }
   else if (any_player_moving || any_player_snapping || any_player_dropping)
   {
-    player_was_waiting = FALSE;
+    local_player->was_waiting = FALSE;
   }
 }
 
 void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting,
                                boolean murphy_is_dropping)
 {
-  static boolean player_was_waiting = TRUE;
-
   if (murphy_is_waiting)
   {
-    if (!player_was_waiting)
+    if (!local_player->was_waiting)
     {
-      if (!SaveEngineSnapshotToList())
+      if (!CheckSaveEngineSnapshotToList())
        return;
 
-      player_was_waiting = TRUE;
+      local_player->was_waiting = TRUE;
     }
   }
   else
   {
-    player_was_waiting = FALSE;
+    local_player->was_waiting = FALSE;
   }
 }