X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=2e58ad30240e469571637a99b075a5267d87dd4d;hb=949580a3bafe5c8abd1fac99202411b65900b883;hp=cd288bce594a83cd27d8570348372e2e914d1faf;hpb=0d3657c231b2a0a50582965140e42b85a4e02c7d;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index cd288bce..2e58ad30 100644 --- a/src/files.c +++ b/src/files.c @@ -236,6 +236,12 @@ static struct LevelFileConfigInfo chunk_config_INFO[] = &li.score[SC_TIME_BONUS], 1 }, + { + -1, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(9), + &li.auto_exit_sokoban, FALSE + }, + { -1, -1, -1, -1, @@ -1314,6 +1320,22 @@ filetype_id_list[] = /* level file functions */ /* ========================================================================= */ +static boolean check_special_flags(char *flag) +{ +#if 0 + printf("::: '%s', '%s', '%s'\n", + flag, + options.special_flags, + leveldir_current->special_flags); +#endif + + if (strEqual(options.special_flags, flag) || + strEqual(leveldir_current->special_flags, flag)) + return TRUE; + + return FALSE; +} + static struct DateInfo getCurrentDate() { time_t epoch_seconds = time(NULL); @@ -1324,6 +1346,8 @@ static struct DateInfo getCurrentDate() date.month = now->tm_mon + 1; date.day = now->tm_mday; + date.src = DATE_SRC_CLOCK; + return date; } @@ -1752,9 +1776,44 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info) static void ActivateLevelTemplate() { + int x, y; + /* Currently there is no special action needed to activate the template data, because 'element_info' property settings overwrite the original level data, while all other variables do not change. */ + + /* Exception: 'from_level_template' elements in the original level playfield + are overwritten with the corresponding elements at the same position in + playfield from the level template. */ + + for (x = 0; x < level.fieldx; x++) + for (y = 0; y < level.fieldy; y++) + if (level.field[x][y] == EL_FROM_LEVEL_TEMPLATE) + level.field[x][y] = level_template.field[x][y]; + + if (check_special_flags("load_xsb_to_ces")) + { + struct LevelInfo level_backup = level; + + /* overwrite all individual level settings from template level settings */ + level = level_template; + + /* restore playfield size */ + level.fieldx = level_backup.fieldx; + level.fieldy = level_backup.fieldy; + + /* restore playfield content */ + for (x = 0; x < level.fieldx; x++) + for (y = 0; y < level.fieldy; y++) + level.field[x][y] = level_backup.field[x][y]; + + /* restore name and author from individual level */ + strcpy(level.name, level_backup.name); + strcpy(level.author, level_backup.author); + + /* restore flag "use_custom_template" */ + level.use_custom_template = level_backup.use_custom_template; + } } static char *getLevelFilenameFromBasename(char *basename) @@ -1820,18 +1879,23 @@ static boolean checkForPackageFromBasename(char *basename) return (getFileTypeFromBasename(basename) != LEVEL_FILE_TYPE_UNKNOWN); } -static char *getSingleLevelBasename(int nr) +static char *getSingleLevelBasenameExt(int nr, char *extension) { static char basename[MAX_FILENAME_LEN]; if (nr < 0) - sprintf(basename, "template.%s", LEVELFILE_EXTENSION); + sprintf(basename, "template.%s", extension); else - sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION); + sprintf(basename, "%03d.%s", nr, extension); return basename; } +static char *getSingleLevelBasename(int nr) +{ + return getSingleLevelBasenameExt(nr, LEVELFILE_EXTENSION); +} + static char *getPackedLevelBasename(int type) { static char basename[MAX_FILENAME_LEN]; @@ -2163,6 +2227,8 @@ static int LoadLevel_DATE(FILE *file, int chunk_size, struct LevelInfo *level) level->creation_date.month = getFile8Bit(file); level->creation_date.day = getFile8Bit(file); + level->creation_date.src = DATE_SRC_LEVELFILE; + return chunk_size; } @@ -4212,29 +4278,12 @@ void CopyNativeLevel_RND_to_SP(struct LevelInfo *level) LevelInfoType *header = &level_sp->header; int i, x, y; - level_sp->width = level->fieldx; + level_sp->width = level->fieldx; level_sp->height = level->fieldy; for (x = 0; x < level->fieldx; x++) - { for (y = 0; y < level->fieldy; y++) - { - int element_old = level->field[x][y]; - int element_new; - - if (element_old >= EL_SP_START && - element_old <= EL_SP_END) - element_new = element_old - EL_SP_START; - else if (element_old == EL_EMPTY_SPACE) - element_new = 0x00; - else if (element_old == EL_INVISIBLE_WALL) - element_new = 0x28; - else - element_new = 0x20; /* map unknown elements to yellow "hardware" */ - - level_sp->playfield[x][y] = element_new; - } - } + level_sp->playfield[x][y] = map_element_RND_to_SP(level->field[x][y]); header->InitialGravity = (level->initial_player_gravity[0] ? 1 : 0); @@ -4244,7 +4293,67 @@ void CopyNativeLevel_RND_to_SP(struct LevelInfo *level) header->InfotronsNeeded = level->gems_needed; - /* !!! ADD SPECIAL PORT DATABASE STUFF !!! */ + header->SpecialPortCount = 0; + + for (x = 0; x < level->fieldx; x++) for (y = 0; y < level->fieldy; y++) + { + boolean gravity_port_found = FALSE; + boolean gravity_port_valid = FALSE; + int gravity_port_flag; + int gravity_port_base_element; + int element = level->field[x][y]; + + if (element >= EL_SP_GRAVITY_ON_PORT_RIGHT && + element <= EL_SP_GRAVITY_ON_PORT_UP) + { + gravity_port_found = TRUE; + gravity_port_valid = TRUE; + gravity_port_flag = 1; + gravity_port_base_element = EL_SP_GRAVITY_ON_PORT_RIGHT; + } + else if (element >= EL_SP_GRAVITY_OFF_PORT_RIGHT && + element <= EL_SP_GRAVITY_OFF_PORT_UP) + { + gravity_port_found = TRUE; + gravity_port_valid = TRUE; + gravity_port_flag = 0; + gravity_port_base_element = EL_SP_GRAVITY_OFF_PORT_RIGHT; + } + else if (element >= EL_SP_GRAVITY_PORT_RIGHT && + element <= EL_SP_GRAVITY_PORT_UP) + { + /* change R'n'D style gravity inverting special port to normal port + (there are no gravity inverting ports in native Supaplex engine) */ + + gravity_port_found = TRUE; + gravity_port_valid = FALSE; + gravity_port_base_element = EL_SP_GRAVITY_PORT_RIGHT; + } + + if (gravity_port_found) + { + if (gravity_port_valid && + header->SpecialPortCount < SP_MAX_SPECIAL_PORTS) + { + SpecialPortType *port = &header->SpecialPort[header->SpecialPortCount]; + + port->PortLocation = (y * level->fieldx + x) * 2; + port->Gravity = gravity_port_flag; + + element += EL_SP_GRAVITY_PORT_RIGHT - gravity_port_base_element; + + header->SpecialPortCount++; + } + else + { + /* change special gravity port to normal port */ + + element += EL_SP_PORT_RIGHT - gravity_port_base_element; + } + + level_sp->playfield[x][y] = element - EL_SP_START; + } + } } void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) @@ -4261,20 +4370,12 @@ void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) for (y = 0; y < level->fieldy; y++) { int element_old = level_sp->playfield[x][y]; - int element_new; + int element_new = getMappedElement(map_element_SP_to_RND(element_old)); - if (element_old <= 0x27) - element_new = getMappedElement(EL_SP_START + element_old); - else if (element_old == 0x28) - element_new = EL_INVISIBLE_WALL; - else - { + if (element_new == EL_UNKNOWN) Error(ERR_WARN, "invalid element %d at position %d, %d", element_old, x, y); - element_new = EL_UNKNOWN; - } - level->field[x][y] = element_new; } } @@ -4352,22 +4453,61 @@ void CopyNativeLevel_SP_to_RND(struct LevelInfo *level) level->yamyam_content[i].e[x][y] = EL_EMPTY; } +static void CopyNativeTape_RND_to_SP(struct LevelInfo *level) +{ + struct LevelInfo_SP *level_sp = level->native_sp_level; + struct DemoInfo_SP *demo = &level_sp->demo; + int i, j; + + /* always start with reliable default values */ + demo->is_available = FALSE; + demo->length = 0; + + if (TAPE_IS_EMPTY(tape)) + return; + + demo->level_nr = tape.level_nr; /* (currently not used) */ + + level_sp->header.DemoRandomSeed = tape.random_seed; + + demo->length = 0; + for (i = 0; i < tape.length; i++) + { + int demo_action = map_key_RND_to_SP(tape.pos[i].action[0]); + int demo_repeat = tape.pos[i].delay; + + for (j = 0; j < demo_repeat / 16; j++) + demo->data[demo->length++] = 0xf0 | demo_action; + + if (demo_repeat % 16) + demo->data[demo->length++] = ((demo_repeat % 16 - 1) << 4) | demo_action; + } + + demo->data[demo->length++] = 0xff; + + demo->is_available = TRUE; +} + static void setTapeInfoToDefaults(); static void CopyNativeTape_SP_to_RND(struct LevelInfo *level) { struct LevelInfo_SP *level_sp = level->native_sp_level; struct DemoInfo_SP *demo = &level_sp->demo; + char *filename = level->file_info.filename; int i; /* always start with reliable default values */ setTapeInfoToDefaults(); + if (!demo->is_available) + return; + tape.level_nr = demo->level_nr; /* (currently not used) */ tape.length = demo->length - 1; /* without "end of demo" byte */ tape.random_seed = level_sp->header.DemoRandomSeed; - // tape.date = + TapeSetDateFromEpochSeconds(getFileTimestampEpochSeconds(filename)); for (i = 0; i < demo->length - 1; i++) { @@ -6359,40 +6499,6 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level, /* functions for loading SB level */ /* ------------------------------------------------------------------------- */ -#if 1 - -static boolean check_special_flags(char *flag) -{ -#if 0 - printf("::: '%s', '%s', '%s'\n", - flag, - options.special_flags, - leveldir_current->special_flags); -#endif - - if (strEqual(options.special_flags, flag) || - strEqual(leveldir_current->special_flags, flag)) - return TRUE; - - return FALSE; -} - -#else - -#define SPECIAL_FLAG_LOAD_XSB_TO_CES (1 << 0) - -static unsigned long get_special_flags(char *flags_string) -{ - unsigned long flags_value = 0; - - if (strEqual(flags_string, "load_xsb_to_ces")) - flags_value = SPECIAL_FLAG_LOAD_XSB_TO_CES; - - return flags_value; -} - -#endif - int getMappedElement_SB(int element_ascii, boolean use_ces) { static struct @@ -6410,7 +6516,11 @@ int getMappedElement_SB(int element_ascii, boolean use_ces) { '.', EL_SOKOBAN_FIELD_EMPTY, EL_CUSTOM_5 }, /* goal square */ { '*', EL_SOKOBAN_FIELD_FULL, EL_CUSTOM_6 }, /* box on goal square */ { '+', EL_SOKOBAN_FIELD_PLAYER, EL_CUSTOM_7 }, /* player on goal square */ +#if 0 { '_', EL_INVISIBLE_STEELWALL, EL_CUSTOM_8 }, /* floor beyond border */ +#else + { '_', EL_INVISIBLE_STEELWALL, EL_FROM_LEVEL_TEMPLATE }, /* floor beyond border */ +#endif { 0, -1, -1 }, }; @@ -6438,11 +6548,7 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, boolean reading_playfield = FALSE; boolean got_valid_playfield_line = FALSE; boolean invalid_playfield_char = FALSE; -#if 1 boolean load_xsb_to_ces = check_special_flags("load_xsb_to_ces"); -#else - boolean load_xsb_to_ces = options.special_flags & SPECIAL_FLAG_LOAD_XSB_TO_CES; -#endif int file_level_nr = 0; int line_nr = 0; int x, y; @@ -6694,7 +6800,11 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, if (load_xsb_to_ces) { +#if 1 + /* !!! special global settings can now be set in level template !!! */ +#else level->initial_player_stepsize[0] = STEPSIZE_SLOW; +#endif /* fill smaller playfields with padding "beyond border wall" elements */ if (level->fieldx < SCR_FIELDX || @@ -6767,6 +6877,20 @@ void CopyNativeLevel_Native_to_RND(struct LevelInfo *level) CopyNativeLevel_SP_to_RND(level); } +void SaveNativeLevel(struct LevelInfo *level) +{ + if (level->game_engine_type == GAME_ENGINE_TYPE_SP) + { + char *basename = getSingleLevelBasenameExt(level->file_info.nr, "sp"); + char *filename = getLevelFilenameFromBasename(basename); + + CopyNativeLevel_RND_to_SP(level); + CopyNativeTape_RND_to_SP(level); + + SaveNativeLevel_SP(filename); + } +} + /* ------------------------------------------------------------------------- */ /* functions for loading generic level */ @@ -8854,8 +8978,16 @@ void SaveScore(int nr) #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_3 5 #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_4 6 #define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_ALL 7 +#define SETUP_TOKEN_SHORTCUT_TAPE_EJECT 8 +#define SETUP_TOKEN_SHORTCUT_TAPE_STOP 9 +#define SETUP_TOKEN_SHORTCUT_TAPE_PAUSE 10 +#define SETUP_TOKEN_SHORTCUT_TAPE_RECORD 11 +#define SETUP_TOKEN_SHORTCUT_TAPE_PLAY 12 +#define SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE 13 +#define SETUP_TOKEN_SHORTCUT_SOUND_LOOPS 14 +#define SETUP_TOKEN_SHORTCUT_SOUND_MUSIC 15 -#define NUM_SHORTCUT_SETUP_TOKENS 8 +#define NUM_SHORTCUT_SETUP_TOKENS 16 /* player setup */ #define SETUP_TOKEN_PLAYER_USE_JOYSTICK 0 @@ -9000,6 +9132,14 @@ static struct TokenInfo shortcut_setup_tokens[] = { TYPE_KEY_X11, &ssi.focus_player[2], "shortcut.focus_player_3" }, { TYPE_KEY_X11, &ssi.focus_player[3], "shortcut.focus_player_4" }, { TYPE_KEY_X11, &ssi.focus_player_all,"shortcut.focus_player_all" }, + { TYPE_KEY_X11, &ssi.tape_eject, "shortcut.tape_eject" }, + { TYPE_KEY_X11, &ssi.tape_stop, "shortcut.tape_stop" }, + { TYPE_KEY_X11, &ssi.tape_pause, "shortcut.tape_pause" }, + { TYPE_KEY_X11, &ssi.tape_record, "shortcut.tape_record" }, + { TYPE_KEY_X11, &ssi.tape_play, "shortcut.tape_play" }, + { TYPE_KEY_X11, &ssi.sound_simple, "shortcut.sound_simple" }, + { TYPE_KEY_X11, &ssi.sound_loops, "shortcut.sound_loops" }, + { TYPE_KEY_X11, &ssi.sound_music, "shortcut.sound_music" }, }; static struct TokenInfo player_setup_tokens[] = @@ -9116,6 +9256,16 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->shortcut.focus_player[3] = DEFAULT_KEY_FOCUS_PLAYER_4; si->shortcut.focus_player_all = DEFAULT_KEY_FOCUS_PLAYER_ALL; + si->shortcut.tape_eject = DEFAULT_KEY_TAPE_EJECT; + si->shortcut.tape_stop = DEFAULT_KEY_TAPE_STOP; + si->shortcut.tape_pause = DEFAULT_KEY_TAPE_PAUSE; + si->shortcut.tape_record = DEFAULT_KEY_TAPE_RECORD; + si->shortcut.tape_play = DEFAULT_KEY_TAPE_PLAY; + + si->shortcut.sound_simple = DEFAULT_KEY_SOUND_SIMPLE; + si->shortcut.sound_loops = DEFAULT_KEY_SOUND_LOOPS; + si->shortcut.sound_music = DEFAULT_KEY_SOUND_MUSIC; + for (i = 0; i < MAX_PLAYERS; i++) { si->input[i].use_joystick = FALSE;