rnd-20060824-1-src
[rocksndiamonds.git] / src / game.c
index fea0d6ce8e1588f28bfc94634545cf5e5a180c74..489c476b30e431b297f420e71a904557873a4662 100644 (file)
@@ -12412,6 +12412,233 @@ void RequestQuitGame(boolean ask_if_really_quit)
 }
 
 
+/* ------------------------------------------------------------------------- */
+/* game engine snapshot handling                                             */
+/* ------------------------------------------------------------------------- */
+
+#define ARGS_ADDRESS_AND_SIZEOF(x)             (&(x)), (sizeof(x))
+
+struct EngineSnapshotInfo
+{
+  int collect_score[NUM_CUSTOM_ELEMENTS];
+  int belt_graphic[4 * NUM_BELT_PARTS];
+  int belt_anim_mode[4 * NUM_BELT_PARTS];
+};
+
+struct EngineSnapshotNodeInfo
+{
+  void *buffer_orig;
+  void *buffer_copy;
+  int size;
+};
+
+static struct EngineSnapshotInfo engine_snapshot_rnd;
+static ListNode *engine_snapshot_list = NULL;
+static char *snapshot_level_identifier = NULL;
+static int snapshot_level_nr = -1;
+
+void FreeEngineSnapshot()
+{
+  while (engine_snapshot_list != NULL)
+    deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key,
+                      checked_free);
+
+  setString(&snapshot_level_identifier, NULL);
+  snapshot_level_nr = -1;
+}
+
+static void SaveEngineSnapshotValues_RND()
+{
+  static int belt_base_active_element[4] =
+  {
+    EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_4_LEFT_ACTIVE
+  };
+  int i, j;
+
+  for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+    engine_snapshot_rnd.collect_score[i] = element_info[i].collect_score;
+
+  for (i = 0; i < 4; i++)
+  {
+    for (j = 0; j < NUM_BELT_PARTS; j++)
+    {
+      int element = belt_base_active_element[i] + j;
+      int graphic = el2img(element);
+      int anim_mode = graphic_info[graphic].anim_mode;
+
+      engine_snapshot_rnd.belt_graphic[i * 4 + j] = graphic;
+      engine_snapshot_rnd.belt_anim_mode[i * 4 + j] = anim_mode;
+    }
+  }
+}
+
+static void LoadEngineSnapshotValues_RND()
+{
+  int i, j;
+
+  for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+    element_info[i].collect_score = engine_snapshot_rnd.collect_score[i];
+
+  for (i = 0; i < 4; i++)
+  {
+    for (j = 0; j < NUM_BELT_PARTS; j++)
+    {
+      int graphic = engine_snapshot_rnd.belt_graphic[i * 4 + j];
+      int anim_mode = engine_snapshot_rnd.belt_anim_mode[i * 4 + j];
+
+      graphic_info[graphic].anim_mode = anim_mode;
+    }
+  }
+}
+
+static void SaveEngineSnapshotBuffer(void *buffer, int size)
+{
+  struct EngineSnapshotNodeInfo *bi =
+    checked_calloc(sizeof(struct EngineSnapshotNodeInfo));
+
+  bi->buffer_orig = buffer;
+  bi->buffer_copy = checked_malloc(size);
+  bi->size = size;
+
+  memcpy(bi->buffer_copy, buffer, size);
+
+  addNodeToList(&engine_snapshot_list, NULL, bi);
+}
+
+void SaveEngineSnapshot()
+{
+  FreeEngineSnapshot();                /* free previous snapshot, if needed */
+
+  /* copy some special values to a structure better suited for the snapshot */
+
+  SaveEngineSnapshotValues_RND();
+  SaveEngineSnapshotValues_EM();
+
+  /* save values stored in special snapshot structure */
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em));
+
+  /* save further RND engine values */
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(stored_player));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(game));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(tape));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZX));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZY));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitX));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitY));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FrameCounter));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeFrames));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimePlayed));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeLeft));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TapeTime));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovDir));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovPos));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenGfxPos));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Feld));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovPos));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDir));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDelay));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeDelay));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangePage));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CustomValue));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store2));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(StorePlayer));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Back));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaNr));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustMoving));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustFalling));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CheckCollision));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Stop));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Pushed));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeCount));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeEvent));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodePhase));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeDelay));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeField));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RunnerVisit));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(PlayerVisit));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxFrame));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxRandom));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxElement));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxAction));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxDir));
+
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_x));
+  SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_y));
+
+  /* save level identification information */
+
+  setString(&snapshot_level_identifier, leveldir_current->identifier);
+  snapshot_level_nr = level_nr;
+
+#if 0
+  ListNode *node = engine_snapshot_list;
+  int num_bytes = 0;
+
+  while (node != NULL)
+  {
+    num_bytes += ((struct EngineSnapshotNodeInfo *)node->content)->size;
+
+    node = node->next;
+  }
+
+  printf("::: size of engine snapshot: %d bytes\n", num_bytes);
+#endif
+}
+
+static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi)
+{
+  memcpy(bi->buffer_orig, bi->buffer_copy, bi->size);
+}
+
+void LoadEngineSnapshot()
+{
+  ListNode *node = engine_snapshot_list;
+
+  if (engine_snapshot_list == NULL)
+    return;
+
+  while (node != NULL)
+  {
+    LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content);
+
+    node = node->next;
+  }
+
+  /* restore special values from snapshot structure */
+
+  LoadEngineSnapshotValues_RND();
+  LoadEngineSnapshotValues_EM();
+}
+
+boolean CheckEngineSnapshot()
+{
+  return (strEqual(snapshot_level_identifier, leveldir_current->identifier) &&
+         snapshot_level_nr == level_nr);
+}
+
+
 /* ---------- new game button stuff ---------------------------------------- */
 
 /* graphic position values for game buttons */