moved change of "grass" to "dirt" for pre-V5 EM levels to filter table
[rocksndiamonds.git] / src / game_em / reademc.c
index 11c32ac771624eda1cde793b55d2cee0930f079f..c1af429dfe7687e17182482908c40cb04e499381 100644 (file)
@@ -40,6 +40,9 @@
  * behaviour.
  */
 
+#define GET_BE16(x)            ((&x)[0] << 8 | (&x)[1])
+#define PUT_BE16(x, y)         {(&x)[0] = (y) >> 8; (&x)[1] = (y) & 0xff;}
+
 static const short map_emc[256] =
 {
   Xstone,              Xstone,         Xdiamond,       Xdiamond,
@@ -123,20 +126,6 @@ static const short map_emc[256] =
   Xblank,              Xblank,         Xalpha_copyr,   Xfake_acid_1
 };
 
-static int get_em_element(unsigned short em_element_raw, int file_version)
-{
-  int em_element = map_emc[em_element_raw];
-
-  if (file_version < FILE_VERSION_EM_V5)
-  {
-    /* versions below V5 had no grass, but only sand/dirt */
-    if (em_element == Xgrass)
-      em_element = Xdirt;
-  }
-
-  return em_element;
-}
-
 void convert_em_level(unsigned char *src, int file_version)
 {
   static int eater_offset[8] =
@@ -146,30 +135,15 @@ void convert_em_level(unsigned char *src, int file_version)
   };
   int i, x, y, temp;
 
-  lev.time_seconds = src[2110] << 8 | src[2111];
+  /* common to all emc caves */
+
+  lev.time_seconds = GET_BE16(src[2110]);
   if (lev.time_seconds > 9999)
     lev.time_seconds = 9999;
 
   lev.required_initial = src[2095];
 
-  for (i = 0; i < 2; i++)
-  {
-    temp = src[2096 + i * 2] << 8 | src[2097 + i * 2];
-    ply[i].x_initial = (temp & 63);
-    ply[i].y_initial = (temp >> 6 & 31);
-  }
-
-  temp = (src[2100] << 8 | src[2101]) * 28;
-  if (temp > 9999)
-    temp = 9999;
-  lev.amoeba_time = temp;
-
-  lev.android_move_time  = src[2164] << 8 | src[2165];
-  lev.android_clone_time = src[2166] << 8 | src[2167];
-
-  lev.ball_random       = src[2162] & 1 ? 1 : 0;
-  lev.ball_state_initial = src[2162] & 128 ? 1 : 0;
-  lev.ball_time                 = src[2160] << 8 | src[2161];
+  /* scores */
 
   lev.emerald_score    = src[2084];
   lev.diamond_score    = src[2085];
@@ -186,9 +160,22 @@ void convert_em_level(unsigned char *src, int file_version)
   lev.magnify_score    = src[2152];
   lev.slurp_score      = src[2153];
 
-  lev.lenses_time      = src[2154] << 8 | src[2155];
-  lev.magnify_time     = src[2156] << 8 | src[2157];
-  lev.wheel_time       = src[2104] << 8 | src[2105];
+  /* times */
+
+  lev.android_move_time  = GET_BE16(src[2164]);
+  lev.android_clone_time = GET_BE16(src[2166]);
+  lev.ball_time                 = GET_BE16(src[2160]);
+
+  lev.lenses_time      = GET_BE16(src[2154]);
+  lev.magnify_time     = GET_BE16(src[2156]);
+  lev.wheel_time       = GET_BE16(src[2104]);
+
+  temp = GET_BE16(src[2100]) * 28;
+  if (temp > 9999)
+    temp = 9999;
+  lev.amoeba_time = temp;
+
+  lev.wonderwall_time_initial = GET_BE16(src[2102]);
 
   lev.wind_cnt_initial = src[2149] & 15 ? lev.wind_time : 0;
   temp = src[2149];
@@ -196,15 +183,64 @@ void convert_em_level(unsigned char *src, int file_version)
                                temp & 1 ? 1 :
                                temp & 2 ? 2 :
                                temp & 4 ? 3 : 0);
+  /* global flags */
+
+  lev.ball_random       = src[2162] & 1   ? 1 : 0;
+  lev.ball_state_initial = src[2162] & 128 ? 1 : 0;
+
+  for (temp = 1; temp < 2047; temp++)
+  {
+    switch (src[temp])
+    {
+      case 36:                                 /* wonderwall */
+       lev.wonderwall_state_initial = 1;
+       lev.wonderwall_time_initial = 9999;
+       break;
+
+      case 40:                                 /* wheel */
+       lev.wheel_x_initial = temp & 63;
+       lev.wheel_y_initial = temp >> 6;
+       lev.wheel_cnt_initial = lev.wheel_time;
+       break;
+
+      case 163:                                        /* fake blank */
+       lev.lenses_cnt_initial = 9999;
+       break;
+
+      case 164:                                        /* fake grass */
+       lev.magnify_cnt_initial = 9999;
+       break;
+    }
+  }
+
+  /* android */
+
+  temp = GET_BE16(src[2168]);
+
+  lev.android_emerald  = (temp & 1)    != 0;
+  lev.android_diamond  = (temp & 2)    != 0;
+  lev.android_stone    = (temp & 4)    != 0;
+  lev.android_bomb     = (temp & 8)    != 0;
+  lev.android_nut      = (temp & 16)   != 0;
+  lev.android_tank     = (temp & 32)   != 0;
+  lev.android_eater    = (temp & 64)   != 0;
+  lev.android_bug      = (temp & 128)  != 0;
+  lev.android_alien    = (temp & 256)  != 0;
+  lev.android_spring   = (temp & 512)  != 0;
+  lev.android_balloon  = (temp & 1024) != 0;
+  lev.android_amoeba   = (temp & 2048) != 0;
+  lev.android_dynamite = (temp & 4096) != 0;
 
-  lev.wonderwall_time_initial = src[2102] << 8 | src[2103];
+  /* eaters */
 
   for (i = 0; i < 8; i++)
     for (x = 0; x < 9; x++)
-      lev.eater_array[i][x] =
-       get_em_element(src[eater_offset[i] + x], file_version);
+      lev.eater_array[i][x] = map_emc[src[eater_offset[i] + x]];
+
+  /* ball */
+
+  temp = map_emc[src[2159]];
 
-  temp = get_em_element(src[2159], file_version);
   for (y = 0; y < 8; y++)
   {
     if (src[2162] & 1)
@@ -225,47 +261,18 @@ void convert_em_level(unsigned char *src, int file_version)
     }
   }
 
-  temp = src[2168] << 8 | src[2169];
+  /* players */
 
-  lev.android_emerald  = (temp & 1)    != 0;
-  lev.android_diamond  = (temp & 2)    != 0;
-  lev.android_stone    = (temp & 4)    != 0;
-  lev.android_bomb     = (temp & 8)    != 0;
-  lev.android_nut      = (temp & 16)   != 0;
-  lev.android_tank     = (temp & 32)   != 0;
-  lev.android_eater    = (temp & 64)   != 0;
-  lev.android_bug      = (temp & 128)  != 0;
-  lev.android_alien    = (temp & 256)  != 0;
-  lev.android_spring   = (temp & 512)  != 0;
-  lev.android_balloon  = (temp & 1024) != 0;
-  lev.android_amoeba   = (temp & 2048) != 0;
-  lev.android_dynamite = (temp & 4096) != 0;
-
-  for (temp = 1; temp < 2047; temp++)
+  for (i = 0; i < 2; i++)
   {
-    switch (src[temp])
-    {
-      case 36:                                 /* wonderwall */
-       lev.wonderwall_state_initial = 1;
-       lev.wonderwall_time_initial = 9999;
-       break;
-
-      case 40:                                 /* wheel */
-       lev.wheel_x_initial = temp & 63;
-       lev.wheel_y_initial = temp >> 6;
-       lev.wheel_cnt_initial = lev.wheel_time;
-       break;
+    temp = GET_BE16(src[2096 + i * 2]);
 
-      case 163:                                        /* fake blank */
-       lev.lenses_cnt_initial = 9999;
-       break;
-
-      case 164:                                        /* fake grass */
-       lev.magnify_cnt_initial = 9999;
-       break;
-    }
+    ply[i].x_initial = (temp & 63);
+    ply[i].y_initial = (temp >> 6 & 31);
   }
 
+  /* cave */
+
   /* first fill the complete playfield with the default border element */
   for (y = 0; y < CAVE_HEIGHT; y++)
     for (x = 0; x < CAVE_WIDTH; x++)
@@ -275,8 +282,7 @@ void convert_em_level(unsigned char *src, int file_version)
   temp = 0;
   for (y = 0; y < lev.height; y++)
     for (x = 0; x < lev.width; x++)
-      native_em_level.cave[x][y] =
-       get_em_element(src[temp++], file_version);
+      native_em_level.cave[x][y] = map_emc[src[temp++]];
 
   /* at last, set the two players at their positions in the playfield */
   /* (native EM[C] levels always have exactly two players in a level) */
@@ -309,6 +315,14 @@ void convert_em_level(unsigned char *src, int file_version)
  * wrong bug(24 instead of 20) and tank(12 instead of 8).
  */
 
+/* changes for game engine integration in Rocks'n'Diamonds:
+ *
+ * cave versions below V5 had no grass, but only sand/dirt
+ * - object code 130 (V6 grass) is changed to 189 (V6 dirt)
+ * - object codes are changed in both cave and eater arrays
+ * - only graphical change, as both objects behave the same
+ */
+
 static const unsigned char map_v6[256] =
 {
   /* filter for v6 */
@@ -373,7 +387,7 @@ static const unsigned char map_v4[256] =
   153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
   153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
 
-  128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
+  128,129,189,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
   144,145,146,147, 148,149,150,151, 152,68,154,155,  156,157,158,160,
   160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
   153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
@@ -388,7 +402,7 @@ static const unsigned char map_v4_eater[32] =
 {
   /* filter for v4 eater */
 
-  128,18,2,0,      4,8,16,20,       28,37,41,45,     130,129,131,132,
+  128,18,2,0,      4,8,16,20,       28,37,41,45,     189,129,131,132,
   133,134,135,136, 146,147,175,65,  66,64,2,18,      128,128,128,128
 };
 
@@ -624,32 +638,23 @@ int cleanup_em_level(unsigned char *src, int length, char *filename)
 
   /* player 1 pos */
   src[2096] &= 7;
-  src[src[2096] << 8 | src[2097]] = 128;
+  src[GET_BE16(src[2096])] = 128;
 
   /* player 2 pos */
   src[2098] &= 7;
-  src[src[2098] << 8 | src[2099]] = 128;
+  src[GET_BE16(src[2098])] = 128;
 
   /* amoeba speed */
-  if ((src[2100] << 8 | src[2101]) > 9999)
-  {
-    src[2100] = 39;
-    src[2101] = 15;
-  }
+  if (GET_BE16(src[2100]) > 9999)
+    PUT_BE16(src[2100], 9999);
 
   /* time wonderwall */
-  if ((src[2102] << 8 | src[2103]) > 9999)
-  {
-    src[2102] = 39;
-    src[2103] = 15;
-  }
+  if (GET_BE16(src[2102]) > 9999)
+    PUT_BE16(src[2102], 9999);
 
   /* time */
-  if ((src[2110] << 8 | src[2111]) > 9999)
-  {
-    src[2110] = 39;
-    src[2111] = 15;
-  }
+  if (GET_BE16(src[2110]) > 9999)
+    PUT_BE16(src[2110], 9999);
 
   /* wind direction */
   i = src[2149];
@@ -658,29 +663,20 @@ int cleanup_em_level(unsigned char *src, int length, char *filename)
   src[2149] = i;
 
   /* time lenses */
-  if ((src[2154] << 8 | src[2155]) > 9999)
-  {
-    src[2154] = 39;
-    src[2155] = 15;
-  }
+  if (GET_BE16(src[2154]) > 9999)
+    PUT_BE16(src[2154], 9999);
 
   /* time magnify */
-  if ((src[2156] << 8 | src[2157]) > 9999)
-  {
-    src[2156] = 39;
-    src[2157] = 15;
-  }
+  if (GET_BE16(src[2156]) > 9999)
+    PUT_BE16(src[2156], 9999);
 
   /* ball object */
   src[2158] = 0;
   src[2159] = map_v6[src[2159]];
 
   /* ball pause */
-  if ((src[2160] << 8 | src[2161]) > 9999)
-  {
-    src[2160] = 39;
-    src[2161] = 15;
-  }
+  if (GET_BE16(src[2160]) > 9999)
+    PUT_BE16(src[2160], 9999);
 
   /* ball data */
   src[2162] &= 129;
@@ -688,18 +684,12 @@ int cleanup_em_level(unsigned char *src, int length, char *filename)
     src[2163] = 0;
 
   /* android move pause */
-  if ((src[2164] << 8 | src[2165]) > 9999)
-  {
-    src[2164] = 39;
-    src[2165] = 15;
-  }
+  if (GET_BE16(src[2164]) > 9999)
+    PUT_BE16(src[2164], 9999);
 
   /* android clone pause */
-  if ((src[2166] << 8 | src[2167]) > 9999)
-  {
-    src[2166] = 39;
-    src[2167] = 15;
-  }
+  if (GET_BE16(src[2166]) > 9999)
+    PUT_BE16(src[2166], 9999);
 
   /* android data */
   src[2168] &= 31;