+ if (i != tape->length)
+ chunk_size = (tape->num_participating_players + 1) * i;
+
+ return chunk_size;
+}
+
+void LoadTape(int level_nr)
+{
+ char *filename = getTapeFilename(level_nr);
+ char cookie[MAX_LINE_LEN];
+ char chunk_name[CHUNK_ID_LEN + 1];
+ FILE *file;
+ int chunk_size;
+
+ /* always start with reliable default values */
+ setTapeInfoToDefaults();
+
+ if (!(file = fopen(filename, MODE_READ)))
+ return;
+
+ getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN);
+ if (strcmp(chunk_name, "RND1") == 0)
+ {
+ getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN); /* not used */
+
+ getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN);
+ if (strcmp(chunk_name, "TAPE") != 0)
+ {
+ Error(ERR_WARN, "unknown format of tape file '%s'", filename);
+ fclose(file);
+ return;
+ }
+ }
+ else /* check for pre-2.0 file format with cookie string */
+ {
+ strcpy(cookie, chunk_name);
+ fgets(&cookie[4], MAX_LINE_LEN - 4, file);
+ if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
+ cookie[strlen(cookie) - 1] = '\0';
+
+ if (!checkCookieString(cookie, TAPE_COOKIE_TMPL))
+ {
+ Error(ERR_WARN, "unknown format of tape file '%s'", filename);
+ fclose(file);
+ return;
+ }
+
+ if ((tape.file_version = getFileVersionFromCookieString(cookie)) == -1)
+ {
+ Error(ERR_WARN, "unsupported version of tape file '%s'", filename);
+ fclose(file);
+ return;
+ }
+ }
+
+ tape.game_version = tape.file_version;
+
+ if (tape.file_version < FILE_VERSION_1_2)
+ {
+ /* tape files from versions before 1.2.0 without chunk structure */
+ LoadTape_HEAD(file, TAPE_HEADER_SIZE, &tape);
+ LoadTape_BODY(file, 2 * tape.length, &tape);
+ }
+ else
+ {
+ static struct
+ {
+ char *name;
+ int size;
+ int (*loader)(FILE *, int, struct TapeInfo *);
+ }
+ chunk_info[] =
+ {
+ { "VERS", FILE_VERS_CHUNK_SIZE, LoadTape_VERS },
+ { "HEAD", TAPE_HEADER_SIZE, LoadTape_HEAD },
+ { "BODY", -1, LoadTape_BODY },
+ { NULL, 0, NULL }
+ };
+
+ while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_BIG_ENDIAN))
+ {
+ int i = 0;
+
+ while (chunk_info[i].name != NULL &&
+ strcmp(chunk_name, chunk_info[i].name) != 0)
+ i++;
+
+ if (chunk_info[i].name == NULL)
+ {
+ Error(ERR_WARN, "unknown chunk '%s' in tape file '%s'",
+ chunk_name, filename);
+ ReadUnusedBytesFromFile(file, chunk_size);
+ }
+ else if (chunk_info[i].size != -1 &&
+ chunk_info[i].size != chunk_size)
+ {
+ Error(ERR_WARN, "wrong size (%d) of chunk '%s' in tape file '%s'",
+ chunk_size, chunk_name, filename);
+ ReadUnusedBytesFromFile(file, chunk_size);
+ }
+ else
+ {
+ /* call function to load this tape chunk */
+ int chunk_size_expected =
+ (chunk_info[i].loader)(file, chunk_size, &tape);
+
+ /* the size of some chunks cannot be checked before reading other
+ chunks first (like "HEAD" and "BODY") that contain some header
+ information, so check them here */
+ if (chunk_size_expected != chunk_size)
+ {
+ Error(ERR_WARN, "wrong size (%d) of chunk '%s' in tape file '%s'",
+ chunk_size, chunk_name, filename);
+ }
+ }
+ }
+ }