major cleanup of preprocessor hell
[rocksndiamonds.git] / src / game_sp / file.c
index f7b833c10474fd26003d51b86b67c49a8599ff20..a38c80667cff3390b9426f37c07fd7d2771f9832 100644 (file)
@@ -60,66 +60,9 @@ void setLevelInfoToDefaults_SP()
 
 void copyInternalEngineVars_SP()
 {
-  char *preceding_playfield_memory[] =
-  {
-    "95 89 95 89 95 89 3b 8a  3b 8a 3b 8a 3b 8a 3b 8a",        // |......;.;.;.;.;.|
-    "3b 8a 3b 8a 3b 8a e8 8a  e8 8a e8 8a e8 8a e8 8a",        // |;.;.;.è.è.è.è.è.|
-    "e8 8a e8 8a e8 8a b1 8b  b1 8b b1 8b b1 8b b1 8b",        // |è.è.è.±.±.±.±.±.|
-    "b1 8b b1 8b b1 8b 85 8c  85 8c 85 8c 85 8c 85 8c",        // |±.±.±...........|
-    "85 8c 85 8c 85 8c 5b 8d  5b 8d 5b 8d 5b 8d 5b 8d",        // |......[.[.[.[.[.|
-    "5b 8d 5b 8d 5b 8d 06 8e  06 8e 06 8e 06 8e 06 8e",        // |[.[.[...........|
-    "06 8e 06 8e 06 8e ac 8e  ac 8e ac 8e ac 8e ac 8e",        // |......¬.¬.¬.¬.¬.|
-    "ac 8e ac 8e ac 8e 59 8f  59 8f 59 8f 59 8f 59 8f",        // |¬.¬.¬.Y.Y.Y.Y.Y.|
-    "59 8f 59 8f 59 8f 00 00  70 13 00 00 00 00 e8 17",        // |Y.Y.Y...p.....è.|
-    "00 00 00 00 00 00 69 38  00 00 00 00 00 00 00 00",        // |......i8........|
-    "00 00 00 00 00 00 00 00  d0 86 00 00 b2 34 00 00",        // |........Ð...²4..|
-    "00 00 00 00 00 00 8f 8b  1d 34 00 00 00 00 00 00",        // |.........4......|
-    "00 00 00 00 23 39 09 09  00 0c 00 08 00 58 00 00",        // |....#9.......X..|
-    "00 00 00 25 77 06 7f 00  00 00 01 00 00 00 00 00",        // |...%w...........|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 ec 06 26 05 00 00 00",        // |.........ì.&....|
-    "00 00 00 01 00 00 00 00  31 32 33 34 35 36 37 38",        // |........12345678|
-    "39 30 2d 00 08 00 51 57  45 52 54 59 55 49 4f 50",        // |90-...QWERTYUIOP|
-    "00 00 0a 00 41 53 44 46  47 48 4a 4b 4c 00 00 00",        // |....ASDFGHJKL...|
-    "00 00 5a 58 43 56 42 4e  4d 00 00 00 00 00 00 20",        // |..ZXCVBNM...... |
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 2e 00  1e 00 31 00 14 00 39 00",        // |..........1...9.|
-    "1f 00 14 00 18 00 ff ff  01 00 01 4c 45 56 45 4c",        // |......ÿÿ...LEVEL|
-    "53 2e 44 41 54 00 00 00  00 00 00 00 00 00 00 00",        // |S.DAT...........|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-    "00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00",        // |................|
-
-    NULL
-  };
-  int preceding_buffer_size = 0;
   int count;
   int i, x, y;
 
-#if 1
-  for (i = 0; preceding_playfield_memory[i] != NULL; i++)
-    preceding_buffer_size += 8;                /* eight 16-bit integer values */
-#endif
-
-  /* needed for engine snapshots */
-  game_sp.preceding_buffer_size = preceding_buffer_size;
-
   LInfo = native_sp_level.header;
 
   FieldWidth  = native_sp_level.width;
@@ -129,29 +72,18 @@ void copyInternalEngineVars_SP()
   FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1;
   LevelMax = (FieldWidth * FieldHeight) - 1;
 
-  FileMax = FieldMax + native_sp_level.demo.length;
-
-  PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax + 1 - 1);
-  DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
-#if 1
-  PlayField16 = REDIM_1D(sizeof(int), -preceding_buffer_size, FieldMax);
-#else
-  PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax);
-#endif
+  /* initialize preceding playfield buffer */
+  for (i = -game_sp.preceding_buffer_size; i < 0; i++)
+    PlayField16[i] = 0;
 
-#if 1
-
-#if 0
-  /* fill preceding playfield buffer zone with (indestructible) "hardware" */
-  for (i = -FieldWidth; i < 0; i++)
-    PlayField16[i] = 0x20;
-#endif
+  /* initialize preceding playfield buffer */
+  for (i = -SP_MAX_PLAYFIELD_WIDTH; i < 0; i++)
+    PlayField8[i] = 0;
 
-#if 1
   count = 0;
-  for (i = 0; preceding_playfield_memory[i] != NULL; i++)
+  for (i = 0; game_sp.preceding_buffer[i] != NULL; i++)
   {
-    char *s = preceding_playfield_memory[i];
+    char *s = game_sp.preceding_buffer[i];
     boolean hi_byte = FALSE;   /* little endian data => start with low byte */
 
     while (s[0] != '\0' && s[1] != '\0')
@@ -163,7 +95,7 @@ void copyInternalEngineVars_SP()
       if (hi_byte)
        byte <<= 8;
 
-      PlayField16[-preceding_buffer_size + count] |= byte;
+      PlayField16[-game_sp.preceding_buffer_size + count] |= byte;
 
       if (hi_byte)
        count++;
@@ -176,7 +108,6 @@ void copyInternalEngineVars_SP()
        s++;
     }
   }
-#endif
 
   count = 0;
   for (y = 0; y < native_sp_level.height; y++)
@@ -194,83 +125,18 @@ void copyInternalEngineVars_SP()
     PlayField8[i] = 0;
   }
 
-#if 0
-  {
-    static int x = 0;
-
-    if (x == 1)
-    {
-      printf("++++++++");
-      printf("----------\n");
-      for (i = 0; i < preceding_buffer_size + FieldMax; i++)
-      {
-       int x = PlayField16[-preceding_buffer_size + i];
-
-       printf("%c%c", x & 0xff, x >> 8);
-      }
-      printf("----------\n");
-      exit(0);
-    }
-
-    x++;
-  }
-#endif
-
-#else
-
-  for (i = 0; y = 0; y < native_sp_level.height; y++)
-  {
-    for (x = 0; x < native_sp_level.width; x++)
-    {
-      PlayField8[i] = native_sp_level.playfield[x][y];
-
-      PlayField16[i] = PlayField8[i];
-      DisPlayField[i] = PlayField8[i];
-      PlayField8[i] = 0;
-
-      i++;
-    }
-  }
-
-#endif
-
   if (native_sp_level.demo.is_available)
-  {
     DemoAvailable = True;
 
-    PlayField8[FieldMax + 1] = native_sp_level.demo.level_nr;
-
-    for (i = 0; i < native_sp_level.demo.length; i++)
-      PlayField8[FieldMax + i + 2] = native_sp_level.demo.data[i];
-  }
-
-  AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 * FieldWidth);
-  AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 * FieldWidth);
-  TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
-
-  DemoPointer = FieldMax + 1;
-  DemoOffset = DemoPointer;
-  DemoKeyRepeatCounter = 0;
-
   GravityFlag = LInfo.InitialGravity;
   FreezeZonks = LInfo.InitialFreezeZonks;
 
-#if 1
-  /* this is set by main game tape code to native random generator directly */
-#else
-
-#if 1
-  printf("::: file.c: copyInternalEngineVars_SP(): RandomSeed = LInfo.DemoRandomSeed\n");
-#endif
-
-  RandomSeed = LInfo.DemoRandomSeed;
-
-#endif
-
   LevelLoaded = True;
+
+  /* random seed set by main game tape code to native random generator seed */
 }
 
-static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
+static void LoadNativeLevelFromFileStream_SP(File *file, int width, int height,
                                             boolean demo_available)
 {
   LevelInfoType *header = &native_sp_level.header;
@@ -279,13 +145,22 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
   /* for details of the Supaplex level format, see Herman Perk's Supaplex
      documentation file "SPFIX63.DOC" from his Supaplex "SpeedFix" package */
 
-  native_sp_level.width  = width;
-  native_sp_level.height = height;
+  native_sp_level.width  = MIN(width,  SP_MAX_PLAYFIELD_WIDTH);
+  native_sp_level.height = MIN(height, SP_MAX_PLAYFIELD_HEIGHT);
 
   /* read level playfield (width * height == 60 * 24 tiles == 1440 bytes) */
-  for (y = 0; y < native_sp_level.height; y++)
-    for (x = 0; x < native_sp_level.width; x++)
-      native_sp_level.playfield[x][y] = getFile8Bit(file);
+  /* (MPX levels may have non-standard playfield size -- check max. size) */
+  for (y = 0; y < height; y++)
+  {
+    for (x = 0; x < width; x++)
+    {
+      byte element = getFile8Bit(file);
+
+      if (x < SP_MAX_PLAYFIELD_WIDTH &&
+         y < SP_MAX_PLAYFIELD_HEIGHT)
+       native_sp_level.playfield[x][y] = element;
+    }
+  }
 
   /* read level header (96 bytes) */
 
@@ -312,10 +187,6 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
   /* number of special ("gravity") port entries below (maximum 10 allowed) */
   header->SpecialPortCount = getFile8Bit(file);
 
-#if 0
-  printf("::: num_special_ports == %d\n", header->SpecialPortCount);
-#endif
-
   /* database of properties of up to 10 special ports (6 bytes per port) */
   for (i = 0; i < SP_MAX_SPECIAL_PORTS; i++)
   {
@@ -328,16 +199,6 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
        which is 2 bytes per tile) */
     port->PortLocation = getFile16BitBE(file);         /* yes, big endian */
 
-#if 0
-    {
-      int port_x = (port->PortLocation / 2) % SP_PLAYFIELD_WIDTH;
-      int port_y = (port->PortLocation / 2) / SP_PLAYFIELD_WIDTH;
-
-      printf("::: %d: port_location == %d => (%d, %d)\n",
-            i, port->PortLocation, port_x, port_y);
-    }
-#endif
-
     /* change gravity: 1 == "turn on", anything else (0) == "turn off" */
     port->Gravity = getFile8Bit(file);
 
@@ -358,11 +219,6 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
 
   /* random seed used for recorded demos */
   header->DemoRandomSeed = getFile16BitLE(file);       /* yes, little endian */
-  // header->DemoRandomSeed = getFile16BitBE(file);    /* !!! TEST ONLY !!! */
-
-#if 0
-  printf("::: file.c: DemoRandomSeed == %d\n", header->DemoRandomSeed);
-#endif
 
   /* auto-determine number of infotrons if it was stored as "0" -- see above */
   if (header->InfotronsNeeded == 0)
@@ -377,9 +233,9 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
 
   /* read raw level header bytes (96 bytes) */
 
-  fseek(file, -(SP_HEADER_SIZE), SEEK_CUR);    /* rewind file */
+  seekFile(file, -(SP_HEADER_SIZE), SEEK_CUR); /* rewind file */
   for (i = 0; i < SP_HEADER_SIZE; i++)
-    native_sp_level.header_raw_bytes[i] = fgetc(file);
+    native_sp_level.header_raw_bytes[i] = getByteFromFile(file);
 
   /* also load demo tape, if available (only in single level files) */
 
@@ -393,7 +249,7 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
 
     native_sp_level.demo.level_nr = level_nr;
 
-    for (i = 0; i < SP_MAX_TAPE_LEN && !feof(file); i++)
+    for (i = 0; i < SP_MAX_TAPE_LEN && !checkEndOfFile(file); i++)
     {
       native_sp_level.demo.data[i] = getFile8Bit(file);
 
@@ -410,9 +266,10 @@ static void LoadNativeLevelFromFileStream_SP(FILE *file, int width, int height,
   }
 }
 
-boolean LoadNativeLevel_SP(char *filename, int level_pos)
+boolean LoadNativeLevel_SP(char *filename, int level_pos,
+                          boolean level_info_only)
 {
-  FILE *file;
+  File *file;
   int i, l, x, y;
   char name_first, name_last;
   struct LevelInfo_SP multipart_level;
@@ -434,9 +291,10 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
   setLevelInfoToDefaults_SP();
   copyInternalEngineVars_SP();
 
-  if (!(file = fopen(filename, MODE_READ)))
+  if (!(file = openFile(filename, MODE_READ)))
   {
-    Error(ERR_WARN, "cannot open file '%s' -- using empty level", filename);
+    if (!level_info_only)
+      Error(ERR_WARN, "cannot open file '%s' -- using empty level", filename);
 
     return FALSE;
   }
@@ -505,7 +363,7 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
   }
 
   /* position file stream to the requested level (in case of level package) */
-  if (fseek(file, file_seek_pos, SEEK_SET) != 0)
+  if (seekFile(file, file_seek_pos, SEEK_SET) != 0)
   {
     Error(ERR_WARN, "cannot fseek in file '%s' -- using empty level", filename);
 
@@ -616,11 +474,6 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
     multipart_xpos = (int)(name_first - '0');
     multipart_ypos = (int)(name_last  - '0');
 
-#if 0
-    printf("----------> part (%d/%d) of multi-part level '%s'\n",
-          multipart_xpos, multipart_ypos, multipart_level.header.LevelTitle);
-#endif
-
     if (multipart_xpos * SP_STD_PLAYFIELD_WIDTH  > SP_MAX_PLAYFIELD_WIDTH ||
        multipart_ypos * SP_STD_PLAYFIELD_HEIGHT > SP_MAX_PLAYFIELD_HEIGHT)
     {
@@ -648,7 +501,7 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos)
     }
   }
 
-  fclose(file);
+  closeFile(file);
 
   if (use_empty_level)
   {