added Android project files
[rocksndiamonds.git] / src / tape.c
index 5e55cb0453fad9166df5de9c971aaba03950abfc..43c3c30699807efed1332e53488ab6adbf02ae5a 100644 (file)
 
 #define DEBUG_TAPE_WHEN_PLAYING                        FALSE
 
-/* tape button identifiers */
+// tape button identifiers
 #define TAPE_CTRL_ID_EJECT                     0
 #define TAPE_CTRL_ID_EXTRA                     1
 #define TAPE_CTRL_ID_STOP                      2
 #define TAPE_CTRL_ID_PAUSE                     3
 #define TAPE_CTRL_ID_RECORD                    4
 #define TAPE_CTRL_ID_PLAY                      5
+#define TAPE_CTRL_ID_INSERT_SOLUTION           6
+#define TAPE_CTRL_ID_PLAY_SOLUTION             7
 
-#define NUM_TAPE_BUTTONS                       6
+#define NUM_TAPE_BUTTONS                       8
 
-/* values for tape handling */
+// values for tape handling
 #define TAPE_PAUSE_SECONDS_BEFORE_DEATH                5
 
-/* forward declaration for internal use */
+// forward declaration for internal use
 static void HandleTapeButtons(struct GadgetInfo *);
-static void TapeStopWarpForward();
+static void TapeStopWarpForward(void);
+static float GetTapeLengthSecondsFloat(void);
 
 static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
 
 
-/* ========================================================================= */
-/* video tape definitions                                                    */
-/* ========================================================================= */
+// ============================================================================
+// video tape definitions
+// ============================================================================
 
 #define VIDEO_INFO_OFF                 (VIDEO_STATE_DATE_OFF   |       \
                                         VIDEO_STATE_TIME_OFF   |       \
@@ -95,9 +98,9 @@ static struct GadgetInfo *tape_gadget[NUM_TAPE_BUTTONS];
 #define NUM_TAPE_FUNCTION_STATES       2
 
 
-/* ========================================================================= */
-/* video display functions                                                   */
-/* ========================================================================= */
+// ============================================================================
+// video display functions
+// ============================================================================
 
 static void DrawVideoDisplay_Graphics(unsigned int state, unsigned int value)
 {
@@ -131,7 +134,7 @@ static void DrawVideoDisplay_Graphics(unsigned int state, unsigned int value)
       { -1,                                    NULL                    },
     },
     {
-      /* (no label for displaying optional frame) */
+      // (no label for displaying optional frame)
       { -1,                                    NULL                    },
       { -1,                                    NULL                    },
     },
@@ -157,11 +160,11 @@ static void DrawVideoDisplay_Graphics(unsigned int state, unsigned int value)
     },
   };
 
-  for (k = 0; k < NUM_TAPE_FUNCTION_STATES; k++)       /* on or off states */
+  for (k = 0; k < NUM_TAPE_FUNCTION_STATES; k++)       // on or off states
   {
-    for (i = 0; i < NUM_TAPE_FUNCTIONS; i++)           /* record, play, ... */
+    for (i = 0; i < NUM_TAPE_FUNCTIONS; i++)           // record, play, ...
     {
-      for (j = 0; j < NUM_TAPE_FUNCTION_PARTS; j++)    /* label or symbol */
+      for (j = 0; j < NUM_TAPE_FUNCTION_PARTS; j++)    // label or symbol
       {
        int graphic = video_pos[i][j].graphic;
        struct XY *pos = video_pos[i][j].pos;
@@ -183,20 +186,20 @@ static void DrawVideoDisplay_Graphics(unsigned int state, unsigned int value)
          if (value == skip_value)
            continue;
 
-         if (k == 1)           /* on */
+         if (k == 1)           // on
          {
            gd_bitmap = gfx->bitmap;
            gd_x = gfx->src_x;
            gd_y = gfx->src_y;
          }
-         else                  /* off */
+         else                  // off
          {
            gd_bitmap = gfx_bg->bitmap;
            gd_x = gfx_bg->src_x + pos->x;
            gd_y = gfx_bg->src_y + pos->y;
          }
 
-         /* some tape graphics may be undefined -- only draw if defined */
+         // some tape graphics may be undefined -- only draw if defined
          if (gd_bitmap != NULL)
            BlitBitmap(gd_bitmap, drawto, gd_x, gd_y, gfx->width, gfx->height,
                       VX + pos->x, VY + pos->y);
@@ -346,17 +349,17 @@ void DrawVideoDisplay(unsigned int state, unsigned int value)
   DrawVideoDisplay_DateTime(state, value);
 }
 
-void DrawVideoDisplayLabel(unsigned int state)
+static void DrawVideoDisplayLabel(unsigned int state)
 {
   DrawVideoDisplay(state, VIDEO_DISPLAY_LABEL_ONLY);
 }
 
-void DrawVideoDisplaySymbol(unsigned int state)
+static void DrawVideoDisplaySymbol(unsigned int state)
 {
   DrawVideoDisplay(state, VIDEO_DISPLAY_SYMBOL_ONLY);
 }
 
-void DrawVideoDisplayCurrentState()
+static void DrawVideoDisplayCurrentState(void)
 {
   int state = 0;
 
@@ -395,15 +398,15 @@ void DrawVideoDisplayCurrentState()
   DrawVideoDisplaySymbol(state);
 }
 
-void DrawCompleteVideoDisplay()
+void DrawCompleteVideoDisplay(void)
 {
   struct GraphicInfo *g_tape = &graphic_info[IMG_BACKGROUND_TAPE];
 
-  /* draw tape background */
+  // draw tape background
   BlitBitmap(g_tape->bitmap, drawto, g_tape->src_x, g_tape->src_y,
             gfx.vxsize, gfx.vysize, gfx.vx, gfx.vy);
 
-  /* draw tape buttons (forced) */
+  // draw tape buttons (forced)
   RedrawOrRemapTapeButtons();
 
   DrawVideoDisplay(VIDEO_ALL_OFF, 0);
@@ -439,7 +442,7 @@ void DrawCompleteVideoDisplay()
             0, 0);
 }
 
-void TapeDeactivateDisplayOn()
+void TapeDeactivateDisplayOn(void)
 {
   SetDrawDeactivationMask(REDRAW_FIELD);
   audio.sound_deactivated = TRUE;
@@ -458,11 +461,11 @@ void TapeDeactivateDisplayOff(boolean redraw_display)
 }
 
 
-/* ========================================================================= */
-/* tape logging functions                                                    */
-/* ========================================================================= */
+// ============================================================================
+// tape logging functions
+// ============================================================================
 
-void PrintTapeReplayProgress(boolean replay_finished)
+static void PrintTapeReplayProgress(boolean replay_finished)
 {
   static unsigned int counter_last = -1;
   unsigned int counter = Counter();
@@ -484,11 +487,13 @@ void PrintTapeReplayProgress(boolean replay_finished)
   }
   else
   {
+    float tape_length_seconds = GetTapeLengthSecondsFloat();
+
     PrintNoLog("\r");
     Print("Level %03d [%02d:%02d]: (%02d:%02d.%03d / %.2f %%) - %s.\n",
          level_nr, tape.length_seconds / 60, tape.length_seconds % 60,
          counter_seconds / 60, counter_seconds % 60, counter % 1000,
-         (float)counter / tape.length_seconds / 10,
+         (float)counter / tape_length_seconds / 10,
          tape.auto_play_level_solved ? "solved" : "NOT SOLVED");
 
     counter_last = -1;
@@ -496,9 +501,9 @@ void PrintTapeReplayProgress(boolean replay_finished)
 }
 
 
-/* ========================================================================= */
-/* tape control functions                                                    */
-/* ========================================================================= */
+// ============================================================================
+// tape control functions
+// ============================================================================
 
 void TapeSetDateFromEpochSeconds(time_t epoch_seconds)
 {
@@ -507,12 +512,12 @@ void TapeSetDateFromEpochSeconds(time_t epoch_seconds)
   tape.date = 10000 * (lt->tm_year % 100) + 100 * lt->tm_mon + lt->tm_mday;
 }
 
-void TapeSetDateFromNow()
+void TapeSetDateFromNow(void)
 {
   TapeSetDateFromEpochSeconds(time(NULL));
 }
 
-void TapeErase()
+void TapeErase(void)
 {
   int i;
 
@@ -541,9 +546,11 @@ void TapeErase()
 
   tape.centered_player_nr_next = -1;
   tape.set_centered_player = FALSE;
+
+  tape.use_mouse = (level.game_engine_type == GAME_ENGINE_TYPE_MM);
 }
 
-static void TapeRewind()
+static void TapeRewind(void)
 {
   tape.counter = 0;
   tape.delay_played = 0;
@@ -589,25 +596,18 @@ void TapeStartRecording(int random_seed)
 
   SetDrawDeactivationMask(REDRAW_NONE);
   audio.sound_deactivated = FALSE;
+
+  // required here to update video display if tape door is closed
+  if (GetDoorState() & DOOR_CLOSE_2)
+    OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
 }
 
-static void TapeStartGameRecording()
+static void TapeStartGameRecording(void)
 {
-  TapeStartRecording(level.random_seed);
-
-#if defined(NETWORK_AVALIABLE)
-  if (options.network)
-  {
-    SendToServer_StartPlaying();
-
-    return;
-  }
-#endif
-
-  InitGame();
+  StartGameActions(network.enabled, TRUE, level.random_seed);
 }
 
-static void TapeAppendRecording()
+static void TapeAppendRecording(void)
 {
   if (!tape.playing || !tape.pausing)
     return;
@@ -635,11 +635,8 @@ static void TapeAppendRecording()
   UpdateAndDisplayGameControlValues();
 }
 
-void TapeHaltRecording()
+void TapeHaltRecording(void)
 {
-  if (!tape.recording)
-    return;
-
   tape.counter++;
 
   // initialize delay for next tape entry (to be able to continue recording)
@@ -651,9 +648,10 @@ void TapeHaltRecording()
   tape.length_seconds = GetTapeLengthSeconds();
 }
 
-void TapeStopRecording()
+void TapeStopRecording(void)
 {
-  TapeHaltRecording();
+  if (tape.recording)
+    TapeHaltRecording();
 
   tape.recording = FALSE;
   tape.pausing = FALSE;
@@ -662,34 +660,11 @@ void TapeStopRecording()
   MapTapeEjectButton();
 }
 
-void TapeRecordAction(byte action_raw[MAX_PLAYERS])
+boolean TapeAddAction(byte action[MAX_PLAYERS])
 {
-  byte action[MAX_PLAYERS];
   int i;
 
-  if (!tape.recording)         /* (record action even when tape is paused) */
-    return;
-
-  if (tape.counter >= MAX_TAPE_LEN - 1)
-  {
-    TapeStopRecording();
-    return;
-  }
-
-  for (i = 0; i < MAX_PLAYERS; i++)
-    action[i] = action_raw[i];
-
-  if (tape.set_centered_player)
-  {
-    for (i = 0; i < MAX_PLAYERS; i++)
-      if (tape.centered_player_nr_next == i ||
-         tape.centered_player_nr_next == -1)
-       action[i] |= KEY_SET_FOCUS;
-
-    tape.set_centered_player = FALSE;
-  }
-
-  if (tape.pos[tape.counter].delay > 0)                /* already stored action */
+  if (tape.pos[tape.counter].delay > 0)                // already stored action
   {
     boolean changed_events = FALSE;
 
@@ -699,6 +674,9 @@ void TapeRecordAction(byte action_raw[MAX_PLAYERS])
 
     if (changed_events || tape.pos[tape.counter].delay >= 255)
     {
+      if (tape.counter >= MAX_TAPE_LEN - 1)
+       return FALSE;
+
       tape.counter++;
       tape.pos[tape.counter].delay = 0;
     }
@@ -706,13 +684,40 @@ void TapeRecordAction(byte action_raw[MAX_PLAYERS])
       tape.pos[tape.counter].delay++;
   }
 
-  if (tape.pos[tape.counter].delay == 0)       /* store new action */
+  if (tape.pos[tape.counter].delay == 0)       // store new action
   {
     for (i = 0; i < MAX_PLAYERS; i++)
       tape.pos[tape.counter].action[i] = action[i];
 
     tape.pos[tape.counter].delay++;
   }
+
+  return TRUE;
+}
+
+void TapeRecordAction(byte action_raw[MAX_PLAYERS])
+{
+  byte action[MAX_PLAYERS];
+  int i;
+
+  if (!tape.recording)         // (record action even when tape is paused)
+    return;
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    action[i] = action_raw[i];
+
+  if (!tape.use_mouse && tape.set_centered_player)
+  {
+    for (i = 0; i < MAX_PLAYERS; i++)
+      if (tape.centered_player_nr_next == i ||
+         tape.centered_player_nr_next == -1)
+       action[i] |= KEY_SET_FOCUS;
+
+    tape.set_centered_player = FALSE;
+  }
+
+  if (!TapeAddAction(action))
+    TapeStopRecording();
 }
 
 void TapeTogglePause(boolean toggle_mode)
@@ -759,18 +764,21 @@ void TapeTogglePause(boolean toggle_mode)
     return;
   }
 
-  if (setup.show_snapshot_buttons &&
-      game_status == GAME_MODE_PLAYING &&
-      CheckEngineSnapshotList())
+  if (game_status == GAME_MODE_PLAYING)
   {
-    if (tape.pausing)
-      MapUndoRedoButtons();
-    else if (!tape.single_step)
-      UnmapUndoRedoButtons();
+    if (setup.show_snapshot_buttons && CheckEngineSnapshotList())
+    {
+      if (tape.pausing)
+       MapUndoRedoButtons();
+      else if (!tape.single_step)
+       UnmapUndoRedoButtons();
+    }
+
+    ModifyPauseButtons();
   }
 }
 
-void TapeStartPlaying()
+void TapeStartPlaying(void)
 {
   if (TAPE_IS_EMPTY(tape))
     return;
@@ -793,14 +801,14 @@ void TapeStartPlaying()
   audio.sound_deactivated = FALSE;
 }
 
-static void TapeStartGamePlaying()
+static void TapeStartGamePlaying(void)
 {
   TapeStartPlaying();
 
   InitGame();
 }
 
-void TapeStopPlaying()
+void TapeStopPlaying(void)
 {
   tape.playing = FALSE;
   tape.pausing = FALSE;
@@ -812,7 +820,7 @@ void TapeStopPlaying()
   MapTapeEjectButton();
 }
 
-byte *TapePlayAction()
+byte *TapePlayAction(void)
 {
   int update_delay = FRAMES_PER_SECOND / 2;
   boolean update_video_display = (FrameCounter % update_delay == 0);
@@ -834,7 +842,7 @@ byte *TapePlayAction()
     }
   }
 
-  if (tape.counter >= tape.length)     /* end of tape reached */
+  if (tape.counter >= tape.length)     // end of tape reached
   {
     if (tape.warp_forward && !tape.auto_play)
     {
@@ -879,16 +887,19 @@ byte *TapePlayAction()
   tape.set_centered_player = FALSE;
   tape.centered_player_nr_next = -999;
 
-  for (i = 0; i < MAX_PLAYERS; i++)
+  if (!tape.use_mouse)
   {
-    if (action[i] & KEY_SET_FOCUS)
+    for (i = 0; i < MAX_PLAYERS; i++)
     {
-      tape.set_centered_player = TRUE;
-      tape.centered_player_nr_next =
-       (tape.centered_player_nr_next == -999 ? i : -1);
-    }
+      if (action[i] & KEY_SET_FOCUS)
+      {
+       tape.set_centered_player = TRUE;
+       tape.centered_player_nr_next =
+         (tape.centered_player_nr_next == -999 ? i : -1);
+      }
 
-    action[i] &= ~KEY_SET_FOCUS;
+      action[i] &= ~KEY_SET_FOCUS;
+    }
   }
 
   tape.delay_played++;
@@ -904,8 +915,11 @@ byte *TapePlayAction()
   return action;
 }
 
-void TapeStop()
+void TapeStop(void)
 {
+  if (tape.pausing)
+    TapeTogglePause(TAPE_TOGGLE_MANUAL);
+
   TapeStopRecording();
   TapeStopPlaying();
 
@@ -919,7 +933,7 @@ void TapeStop()
   }
 }
 
-unsigned int GetTapeLengthFrames()
+unsigned int GetTapeLengthFrames(void)
 {
   unsigned int tape_length_frames = 0;
   int i;
@@ -933,11 +947,16 @@ unsigned int GetTapeLengthFrames()
   return tape_length_frames;
 }
 
-unsigned int GetTapeLengthSeconds()
+unsigned int GetTapeLengthSeconds(void)
 {
   return (GetTapeLengthFrames() * GAME_FRAME_DELAY / 1000);
 }
 
+static float GetTapeLengthSecondsFloat(void)
+{
+  return ((float)GetTapeLengthFrames() * GAME_FRAME_DELAY / 1000);
+}
+
 static void TapeStartWarpForward(int mode)
 {
   tape.fast_forward = (mode & AUTOPLAY_FFWD);
@@ -952,7 +971,7 @@ static void TapeStartWarpForward(int mode)
   DrawVideoDisplayCurrentState();
 }
 
-static void TapeStopWarpForward()
+static void TapeStopWarpForward(void)
 {
   tape.fast_forward = FALSE;
   tape.warp_forward = FALSE;
@@ -965,9 +984,9 @@ static void TapeStopWarpForward()
   DrawVideoDisplayCurrentState();
 }
 
-static void TapeSingleStep()
+static void TapeSingleStep(void)
 {
-  if (options.network)
+  if (network.enabled)
     return;
 
   if (!tape.pausing)
@@ -978,7 +997,7 @@ static void TapeSingleStep()
   DrawVideoDisplay(VIDEO_STATE_1STEP(tape.single_step), 0);
 }
 
-void TapeQuickSave()
+void TapeQuickSave(void)
 {
   if (game_status == GAME_MODE_MAIN)
   {
@@ -991,7 +1010,7 @@ void TapeQuickSave()
     return;
 
   if (tape.recording)
-    TapeHaltRecording();       /* prepare tape for saving on-the-fly */
+    TapeHaltRecording();       // prepare tape for saving on-the-fly
 
   if (TAPE_IS_EMPTY(tape))
   {
@@ -1004,7 +1023,7 @@ void TapeQuickSave()
     SaveEngineSnapshotSingle();
 }
 
-void TapeQuickLoad()
+void TapeQuickLoad(void)
 {
   char *filename = getTapeFilename(level_nr);
 
@@ -1059,7 +1078,7 @@ void TapeQuickLoad()
 
     tape.quick_resume = TRUE;
   }
-  else /* this should not happen (basically checked above) */
+  else // this should not happen (basically checked above)
   {
     int reopen_door = (game_status == GAME_MODE_PLAYING ? REQ_REOPEN : 0);
 
@@ -1067,35 +1086,60 @@ void TapeQuickLoad()
   }
 }
 
-void InsertSolutionTape()
+boolean hasSolutionTape(void)
 {
+  boolean tape_file_exists = fileExists(getSolutionTapeFilename(level_nr));
   boolean level_has_tape = (level.game_engine_type == GAME_ENGINE_TYPE_SP &&
                            level.native_sp_level->demo.is_available);
 
-  if (!fileExists(getSolutionTapeFilename(level_nr)) && !level_has_tape)
+  return (tape_file_exists || level_has_tape);
+}
+
+boolean InsertSolutionTape(void)
+{
+  if (!hasSolutionTape())
   {
     Request("No solution tape for this level!", REQ_CONFIRM);
 
-    return;
+    return FALSE;
   }
 
+  if (!TAPE_IS_STOPPED(tape))
+    TapeStop();
+
   // if tape recorder already contains a tape, remove it without asking
   TapeErase();
 
   LoadSolutionTape(level_nr);
 
+  DrawCompleteVideoDisplay();
+
   if (TAPE_IS_EMPTY(tape))
+  {
     Request("Loading solution tape for this level failed!", REQ_CONFIRM);
 
-  DrawCompleteVideoDisplay();
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+boolean PlaySolutionTape(void)
+{
+  if (!InsertSolutionTape())
+    return FALSE;
+
+  TapeStartGamePlaying();
+
+  return TRUE;
 }
 
 
-/* ------------------------------------------------------------------------- *
- * tape autoplay functions
- * ------------------------------------------------------------------------- */
+// ----------------------------------------------------------------------------
+// tape autoplay functions
+// ----------------------------------------------------------------------------
 
-void AutoPlayTape()
+void AutoPlayTape(void)
 {
   static LevelDirTree *autoplay_leveldir = NULL;
   static boolean autoplay_initialized = FALSE;
@@ -1108,7 +1152,7 @@ void AutoPlayTape()
 
   if (autoplay_initialized)
   {
-    /* just finished auto-playing tape */
+    // just finished auto-playing tape
     PrintTapeReplayProgress(TRUE);
 
     num_levels_played++;
@@ -1176,7 +1220,7 @@ void AutoPlayTape()
     }
 
 #if 0
-    /* ACTIVATE THIS FOR LOADING/TESTING OF LEVELS ONLY */
+    // ACTIVATE THIS FOR LOADING/TESTING OF LEVELS ONLY
     Print("Level %03d: (only testing level)\n", level_nr);
     continue;
 #endif
@@ -1229,7 +1273,7 @@ void AutoPlayTape()
 }
 
 
-/* ---------- new tape button stuff ---------------------------------------- */
+// ---------- new tape button stuff -------------------------------------------
 
 static struct
 {
@@ -1244,7 +1288,7 @@ static struct
     TAPE_CTRL_ID_EJECT,                        "eject tape"
   },
   {
-    /* (same position as "eject" button) */
+    // (same position as "eject" button)
     IMG_GFX_TAPE_BUTTON_EXTRA,         &tape.button.eject,
     TAPE_CTRL_ID_EXTRA,                        "extra functions"
   },
@@ -1263,16 +1307,25 @@ static struct
   {
     IMG_GFX_TAPE_BUTTON_PLAY,          &tape.button.play,
     TAPE_CTRL_ID_PLAY,                 "play tape"
+  },
+  {
+    IMG_GFX_TAPE_BUTTON_INSERT_SOLUTION,&tape.button.insert_solution,
+    TAPE_CTRL_ID_INSERT_SOLUTION,      "insert solution tape"
+  },
+  {
+    IMG_GFX_TAPE_BUTTON_PLAY_SOLUTION, &tape.button.play_solution,
+    TAPE_CTRL_ID_PLAY_SOLUTION,                "play solution tape"
   }
 };
 
-void CreateTapeButtons()
+void CreateTapeButtons(void)
 {
   int i;
 
   for (i = 0; i < NUM_TAPE_BUTTONS; i++)
   {
-    struct GraphicInfo *gfx = &graphic_info[tapebutton_info[i].graphic];
+    int graphic = tapebutton_info[i].graphic;
+    struct GraphicInfo *gfx = &graphic_info[graphic];
     struct XY *pos = tapebutton_info[i].pos;
     struct GadgetInfo *gi;
     int gd_x = gfx->src_x;
@@ -1282,6 +1335,7 @@ void CreateTapeButtons()
     int id = i;
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
+                     GDI_IMAGE_ID, graphic,
                      GDI_INFO_TEXT, tapebutton_info[i].infotext,
                      GDI_X, VX + pos->x,
                      GDI_Y, VY + pos->y,
@@ -1303,7 +1357,7 @@ void CreateTapeButtons()
   }
 }
 
-void FreeTapeButtons()
+void FreeTapeButtons(void)
 {
   int i;
 
@@ -1311,19 +1365,19 @@ void FreeTapeButtons()
     FreeGadget(tape_gadget[i]);
 }
 
-void MapTapeEjectButton()
+void MapTapeEjectButton(void)
 {
   UnmapGadget(tape_gadget[TAPE_CTRL_ID_EXTRA]);
   MapGadget(tape_gadget[TAPE_CTRL_ID_EJECT]);
 }
 
-void MapTapeWarpButton()
+void MapTapeWarpButton(void)
 {
   UnmapGadget(tape_gadget[TAPE_CTRL_ID_EJECT]);
   MapGadget(tape_gadget[TAPE_CTRL_ID_EXTRA]);
 }
 
-void MapTapeButtons()
+void MapTapeButtons(void)
 {
   int i;
 
@@ -1335,10 +1389,10 @@ void MapTapeButtons()
     MapTapeWarpButton();
 
   if (tape.show_game_buttons)
-    MapGameButtons();
+    MapGameButtonsOnTape();
 }
 
-void UnmapTapeButtons()
+void UnmapTapeButtons(void)
 {
   int i;
 
@@ -1346,10 +1400,10 @@ void UnmapTapeButtons()
     UnmapGadget(tape_gadget[i]);
 
   if (tape.show_game_buttons)
-    UnmapGameButtons();
+    UnmapGameButtonsOnTape();
 }
 
-void RedrawTapeButtons()
+void RedrawTapeButtons(void)
 {
   int i;
 
@@ -1357,13 +1411,10 @@ void RedrawTapeButtons()
     RedrawGadget(tape_gadget[i]);
 
   if (tape.show_game_buttons)
-    RedrawGameButtons();
-
-  // RedrawGadget() may have set REDRAW_ALL if buttons are defined off-area
-  redraw_mask &= ~REDRAW_ALL;
+    RedrawGameButtonsOnTape();
 }
 
-void RedrawOrRemapTapeButtons()
+void RedrawOrRemapTapeButtons(void)
 {
   if (tape_gadget[TAPE_CTRL_ID_PLAY]->mapped)
   {
@@ -1436,7 +1487,7 @@ static void HandleTapeButtonsExt(int id)
       }
       else if (tape.pausing)
       {
-       if (tape.playing)                       /* PLAY -> PAUSE -> RECORD */
+       if (tape.playing)                       // PLAY -> PAUSE -> RECORD
          TapeAppendRecording();
        else
          TapeTogglePause(TAPE_TOGGLE_MANUAL);
@@ -1445,7 +1496,7 @@ static void HandleTapeButtonsExt(int id)
       break;
 
     case TAPE_CTRL_ID_PLAY:
-      if (tape.recording && tape.pausing)      /* PAUSE -> RECORD */
+      if (tape.recording && tape.pausing)      // PAUSE -> RECORD
       {
        // ("TAPE_IS_EMPTY(tape)" is TRUE here -- probably fix this)
 
@@ -1461,25 +1512,25 @@ static void HandleTapeButtonsExt(int id)
       }
       else if (tape.playing)
       {
-       if (tape.pausing)                       /* PAUSE -> PLAY */
+       if (tape.pausing)                       // PAUSE -> PLAY
        {
          TapeTogglePause(TAPE_TOGGLE_MANUAL | TAPE_TOGGLE_PLAY_PAUSE);
        }
-       else if (!tape.fast_forward)            /* PLAY -> FFWD */
+       else if (!tape.fast_forward)            // PLAY -> FFWD
        {
          tape.fast_forward = TRUE;
        }
-       else if (!tape.warp_forward)            /* FFWD -> WARP */
+       else if (!tape.warp_forward)            // FFWD -> WARP
        {
          tape.warp_forward = TRUE;
        }
-       else if (!tape.deactivate_display)      /* WARP -> WARP BLIND */
+       else if (!tape.deactivate_display)      // WARP -> WARP BLIND
        {
          tape.deactivate_display = TRUE;
 
          TapeDeactivateDisplayOn();
        }
-       else                                    /* WARP BLIND -> PLAY */
+       else                                    // WARP BLIND -> PLAY
        {
          tape.fast_forward = FALSE;
          tape.warp_forward = FALSE;
@@ -1493,6 +1544,16 @@ static void HandleTapeButtonsExt(int id)
 
       break;
 
+    case TAPE_CTRL_ID_INSERT_SOLUTION:
+      InsertSolutionTape();
+
+      break;
+
+    case TAPE_CTRL_ID_PLAY_SOLUTION:
+      PlaySolutionTape();
+
+      break;
+
     default:
       break;
   }