/* functions for loading Supaplex level */
/* ------------------------------------------------------------------------- */
-void setTapeInfoToDefaults_SP()
+static void setTapeInfoToDefaults_SP(void)
{
native_sp_level.demo.is_available = FALSE;
native_sp_level.demo.length = 0;
}
-void setLevelInfoToDefaults_SP()
+void setLevelInfoToDefaults_SP(void)
{
LevelInfoType *header = &native_sp_level.header;
char *empty_title = "-------- EMPTY --------";
setTapeInfoToDefaults_SP();
}
-void copyInternalEngineVars_SP()
+void copyInternalEngineVars_SP(void)
{
- 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;
- for (i = 0; preceding_playfield_memory[i] != NULL; i++)
- preceding_buffer_size += 8; /* eight 16-bit integer values */
-
- /* needed for engine snapshots */
- game_sp.preceding_buffer_size = preceding_buffer_size;
-
LInfo = native_sp_level.header;
FieldWidth = native_sp_level.width;
FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1;
LevelMax = (FieldWidth * FieldHeight) - 1;
- /* (add one byte for the level number stored as first byte of demo data) */
- FileMax = FieldMax + native_sp_level.demo.length + 1;
+ /* initialize preceding playfield buffer */
+ for (i = -game_sp.preceding_buffer_size; i < 0; i++)
+ PlayField16[i] = 0;
-#if 0
- PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax);
- DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax);
- PlayField16 = REDIM_1D(sizeof(int), -preceding_buffer_size, FieldMax);
-#endif
+ /* initialize preceding playfield buffer */
+ for (i = -SP_MAX_PLAYFIELD_WIDTH; i < 0; i++)
+ PlayField8[i] = 0;
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')
if (hi_byte)
byte <<= 8;
- PlayField16[-preceding_buffer_size + count] |= byte;
+ PlayField16[-game_sp.preceding_buffer_size + count] |= byte;
if (hi_byte)
count++;
}
if (native_sp_level.demo.is_available)
- {
DemoAvailable = True;
-#if 0
- /* !!! NEVER USED !!! */
- PlayField8[FieldMax + 1] = native_sp_level.demo.level_nr;
-
- /* !!! NEVER USED !!! */
- for (i = 0; i < native_sp_level.demo.length; i++)
- PlayField8[FieldMax + 2 + i] = native_sp_level.demo.data[i];
-#endif
- }
-
-#if 0
- 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);
-#endif
-
GravityFlag = LInfo.InitialGravity;
FreezeZonks = LInfo.InitialFreezeZonks;
-#if 1
- /* this is set by main game tape code to native random generator directly */
-#else
- 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;
/* 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) */
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);
if (native_sp_level.demo.data[i] == 0xff) /* "end of demo" byte */
- {
- i++;
-
break;
- }
}
+ if (i >= SP_MAX_TAPE_LEN)
+ Error(ERR_WARN, "SP demo truncated: size exceeds maximum SP demo size %d",
+ SP_MAX_TAPE_LEN);
+
native_sp_level.demo.length = i;
native_sp_level.demo.is_available = (native_sp_level.demo.length > 0);
}
}
-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;
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;
}
}
/* 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);
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)
{
}
}
- fclose(file);
+ closeFile(file);
if (use_empty_level)
{
for (i = 0; i < native_sp_level.demo.length; i++)
putFile8Bit(file, native_sp_level.demo.data[i]);
+
+ putFile8Bit(file, 0xff); /* "end of demo" byte */
}
fclose(file);