void parse_rank_tbl() { atexit(scoreing_close); char buf[MULTITEXT_LENGTH]; int rval, idx, persona; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "rank.tbl", rval)); return; } read_file_text("rank.tbl", CF_TYPE_TABLES); reset_parse(); // parse in all the rank names idx = 0; skip_to_string("[RANK NAMES]"); ignore_white_space(); while ( required_string_either("#End", "$Name:") ) { Assert ( idx < NUM_RANKS ); required_string("$Name:"); stuff_string( Ranks[idx].name, F_NAME, NAME_LENGTH ); required_string("$Points:"); stuff_int( &Ranks[idx].points ); required_string("$Bitmap:"); stuff_string( Ranks[idx].bitmap, F_NAME, MAX_FILENAME_LEN ); required_string("$Promotion Voice Base:"); stuff_string( Ranks[idx].promotion_voice_base, F_NAME, MAX_FILENAME_LEN ); while (check_for_string("$Promotion Text:")) { required_string("$Promotion Text:"); stuff_string(buf, F_MULTITEXT, sizeof(buf)); drop_white_space(buf); compact_multitext_string(buf); persona = -1; if (optional_string("+Persona:")) { stuff_int(&persona); if (persona < 0) { Warning(LOCATION, "Debriefing text for %s rank is assigned to an invalid persona: %i (must be 0 or greater).\n", Ranks[idx].name, persona); continue; } } Ranks[idx].promotion_text[persona] = vm_strdup(buf); } if (Ranks[idx].promotion_text.find(-1) == Ranks[idx].promotion_text.end()) { Warning(LOCATION, "%s rank is missing default debriefing text.\n", Ranks[idx].name); Ranks[idx].promotion_text[-1] = ""; } idx++; } required_string("#End"); // be sure that all rank points are in order #ifndef NDEBUG for ( idx = 0; idx < NUM_RANKS-1; idx++ ) { if ( Ranks[idx].points >= Ranks[idx+1].points ) Int3(); } #endif }
// initialization stuff for cutscenes void cutscene_init() { atexit(cutscene_close); char buf[MULTITEXT_LENGTH]; int rval; cutscene_info cutinfo; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "cutscenes.tbl", rval)); return; } read_file_text("cutscenes.tbl", CF_TYPE_TABLES); reset_parse(); // parse in all the cutscenes Cutscenes.clear(); skip_to_string("#Cutscenes"); ignore_white_space(); bool isFirstCutscene = true; while ( required_string_either("#End", "$Filename:") ) { required_string("$Filename:"); stuff_string( cutinfo.filename, F_PATHNAME, MAX_FILENAME_LEN ); required_string("$Name:"); stuff_string( cutinfo.name, F_NAME, NAME_LENGTH ); required_string("$Description:"); stuff_string(buf, F_MULTITEXT, sizeof(buf)); drop_white_space(buf); compact_multitext_string(buf); cutinfo.description = vm_strdup(buf); if (optional_string("$cd:")) stuff_int( &cutinfo.cd ); else cutinfo.cd = 0; cutinfo.viewable = false; if (isFirstCutscene) { isFirstCutscene = false; // The original code assumes the first movie is the intro, so always viewable cutinfo.viewable = true; } if (optional_string("$Always Viewable:")) { stuff_boolean(&cutinfo.viewable); } Cutscenes.push_back(cutinfo); } required_string("#End"); }
// initialization stuff for cutscenes void cutscene_init() { char buf[MULTITEXT_LENGTH]; int rval; if ((rval = setjmp(parse_abort)) != 0) { Error(LOCATION, "Error parsing 'rank.tbl'\r\nError code = %i.\r\n", rval); } // open localization lcl_ext_open(); read_file_text("cutscenes.tbl"); reset_parse(); // parse in all the rank names Num_cutscenes = 0; skip_to_string("#Cutscenes"); ignore_white_space(); while ( required_string_either("#End", "$Filename:") ) { Assert ( Num_cutscenes < MAX_CUTSCENES ); required_string("$Filename:"); stuff_string( Cutscenes[Num_cutscenes].filename, F_PATHNAME, NULL ); required_string("$Name:"); stuff_string( Cutscenes[Num_cutscenes].name, F_NAME, NULL ); required_string("$Description:"); stuff_string(buf, F_MULTITEXT, NULL); drop_white_space(buf); compact_multitext_string(buf); Cutscenes[Num_cutscenes].description = strdup(buf); required_string("$cd:"); stuff_int( &Cutscenes[Num_cutscenes].cd ); Num_cutscenes++; } required_string("#End"); Cutscenes_viewable = INTRO_CUTSCENE_FLAG; // close localization lcl_ext_close(); }
void credits_parse_table(const char* filename) { try { read_file_text(filename, CF_TYPE_TABLES); reset_parse(); // any metadata? if (optional_string("$Music:")) { stuff_string(Credits_music_name, F_NAME, NAME_LENGTH); } if (optional_string("$Number of Images:")) { int temp; stuff_int(&temp); if (temp > 0) Credits_num_images = temp; } if (optional_string("$Start Image Index:")) { stuff_int(&Credits_artwork_index); // bounds check if (Credits_artwork_index < 0) { Credits_artwork_index = 0; } else if (Credits_artwork_index >= Credits_num_images) { Credits_artwork_index = Credits_num_images - 1; } } if (optional_string("$Text scroll rate:")) { stuff_float(&Credits_scroll_rate); if (Credits_scroll_rate < 0.01f) Credits_scroll_rate = 0.01f; } if (optional_string("$Artworks display time:")) { stuff_float(&Credits_artwork_display_time); if (Credits_artwork_display_time < 0.01f) Credits_artwork_display_time = 0.01f; } if (optional_string("$Artworks fade time:")) { stuff_float(&Credits_artwork_fade_time); if (Credits_artwork_fade_time < 0.01f) Credits_artwork_fade_time = 0.01f; } if (optional_string("$SCP Credits position:")) { char mode[NAME_LENGTH]; stuff_string(mode, F_NAME, NAME_LENGTH); if (!stricmp(mode, "Start")) SCP_credits_position = START; else if (!stricmp(mode, "End")) SCP_credits_position = END; else Warning(LOCATION, "Unknown credits position mode \"%s\".", mode); } ignore_white_space(); SCP_string credits_text; SCP_string line; SCP_vector<int> charNum; SCP_vector<const char*> lines; int numLines = -1; bool first_run = true; while (!check_for_string_raw("#end")) { // Read in a line of text stuff_string_line(line); // This is a bit odd but it means if a total conversion uses different credits the // Volition credit won't happen // Also don't append the default credits anymore when there was already a parsed table if (first_run && !Credits_parsed && !line.compare(mod_check)) { credits_text.append(unmodified_credits); } first_run = false; if (line.empty()) { // If the line is empty then just append a newline, don't bother with splitting it first credits_text.append("\n"); } else { // split_str doesn't take care of this. charNum.clear(); // Split the string into multiple lines if it's too long numLines = split_str(line.c_str(), Credits_text_coords[gr_screen.res][2], charNum, lines, -1); // Make sure that we have valid data Assertion(lines.size() == (size_t)numLines, "split_str reported %d lines but vector contains " SIZE_T_ARG " entries!", numLines, lines.size()); Assertion(lines.size() <= charNum.size(), "Something has gone wrong while splitting strings. Got " SIZE_T_ARG " lines but only " SIZE_T_ARG " chacter lengths.", lines.size(), charNum.size()); // Now add all splitted lines to the credit text and append a newline to the end for (int i = 0; i < numLines; i++) { credits_text.append(SCP_string(lines[i], charNum[i])); credits_text.append("\n"); } } } Credit_text_parts.push_back(credits_text); Credits_parsed = true; } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what())); return; } }
/** * @brief Parses controlconfigdefault.tbl, and overrides the default control configuration for each valid entry in the .tbl */ void control_config_common_load_overrides() { LoadEnumsIntoMaps(); try { if (cf_exists_full("controlconfigdefaults.tbl", CF_TYPE_TABLES)) { read_file_text("controlconfigdefaults.tbl", CF_TYPE_TABLES); } else { read_file_text_from_default(defaults_get_file("controlconfigdefaults.tbl")); } reset_parse(); // start parsing // TODO: Split this out into more helps. Too many tabs! while(optional_string("#ControlConfigOverride")) { config_item *cfg_preset = new config_item[CCFG_MAX + 1]; std::copy(Control_config, Control_config + CCFG_MAX + 1, cfg_preset); Control_config_presets.push_back(cfg_preset); SCP_string preset_name; if (optional_string("$Name:")) { stuff_string_line(preset_name); } else { preset_name = "<unnamed preset>"; } Control_config_preset_names.push_back(preset_name); while (required_string_either("#End","$Bind Name:")) { const int iBufferLength = 64; char szTempBuffer[iBufferLength]; required_string("$Bind Name:"); stuff_string(szTempBuffer, F_NAME, iBufferLength); const size_t cCntrlAryLength = sizeof(Control_config) / sizeof(Control_config[0]); for (size_t i = 0; i < cCntrlAryLength; ++i) { config_item& r_ccConfig = cfg_preset[i]; if (!strcmp(szTempBuffer, r_ccConfig.text)) { /** * short key_default; * short joy_default; * char tab; * bool hasXSTR; * char type; */ int iTemp; if (optional_string("$Key Default:")) { if (optional_string("NONE")) { r_ccConfig.key_default = (short)-1; } else { stuff_string(szTempBuffer, F_NAME, iBufferLength); r_ccConfig.key_default = (short)mKeyNameToVal[szTempBuffer]; } } if (optional_string("$Joy Default:")) { stuff_int(&iTemp); r_ccConfig.joy_default = (short)iTemp; } if (optional_string("$Key Mod Shift:")) { stuff_int(&iTemp); r_ccConfig.key_default |= (iTemp == 1) ? KEY_SHIFTED : 0; } if (optional_string("$Key Mod Alt:")) { stuff_int(&iTemp); r_ccConfig.key_default |= (iTemp == 1) ? KEY_ALTED : 0; } if (optional_string("$Key Mod Ctrl:")) { stuff_int(&iTemp); r_ccConfig.key_default |= (iTemp == 1) ? KEY_CTRLED : 0; } if (optional_string("$Category:")) { stuff_string(szTempBuffer, F_NAME, iBufferLength); r_ccConfig.tab = (char)mCCTabNameToVal[szTempBuffer]; } if (optional_string("$Has XStr:")) { stuff_int(&iTemp); r_ccConfig.hasXSTR = (iTemp == 1); } if (optional_string("$Type:")) { stuff_string(szTempBuffer, F_NAME, iBufferLength); r_ccConfig.type = (char)mCCTypeNameToVal[szTempBuffer]; } if (optional_string("+Disable")) { r_ccConfig.disabled = true; } if (optional_string("$Disable:")) { stuff_boolean(&r_ccConfig.disabled); } // Nerf the buffer now. szTempBuffer[0] = '\0'; } else if ((i + 1) == cCntrlAryLength) { error_display(1, "Bind Name not found: %s\n", szTempBuffer); advance_to_eoln(NULL); ignore_white_space(); return; } } } required_string("#End"); } } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse 'controlconfigdefaults.tbl'! Error message = %s.\n", e.what())); return; } // Overwrite the control config with the first preset that was found if (!Control_config_presets.empty()) { std::copy(Control_config_presets[0], Control_config_presets[0] + CCFG_MAX + 1, Control_config); } }
// Unified function for loading strings.tbl and tstrings.tbl (and their modular versions). // The "external" parameter controls which format to load: true for tstrings.tbl, false for strings.tbl void parse_stringstbl_common(const char *filename, const bool external) { char chr, buf[4096]; char language_tag[512]; int z, index; char *p_offset = NULL; int offset_lo = 0, offset_hi = 0; read_file_text(filename, CF_TYPE_TABLES); reset_parse(); // move down to the proper section memset(language_tag, 0, sizeof(language_tag)); strcpy_s(language_tag, "#"); if (external && Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE){ strcat_s(language_tag, "default"); } else { strcat_s(language_tag, Lcl_languages[Lcl_current_lang].lang_name); } if ( skip_to_string(language_tag) != 1 ) { mprintf(("Current language not found in %s\n", filename)); return; } // parse all the strings in this section of the table while ( !check_for_string("#") ) { int num_offsets_on_this_line = 0; stuff_int(&index); if (external) { ignore_white_space(); get_string(buf, sizeof(buf)); drop_trailing_white_space(buf); } else { stuff_string(buf, F_RAW, sizeof(buf)); } if (external && (index < 0 || index >= LCL_MAX_STRINGS)) { error_display(0, "Invalid tstrings table index specified (%i). Please increment LCL_MAX_STRINGS in localize.cpp.", index); return; } else if (!external && (index < 0 || index >= XSTR_SIZE)) { Error(LOCATION, "Invalid strings table index specified (%i)", index); } if (!external) { size_t i = strlen(buf); while (i--) { if ( !isspace(buf[i]) ) break; } // trim unnecessary end of string // Assert(buf[i] == '"'); if (buf[i] != '"') { // probably an offset on this entry // drop down a null terminator (prolly unnecessary) buf[i+1] = 0; // back up over the potential offset while ( !is_white_space(buf[i]) ) i--; // now back up over intervening spaces while ( is_white_space(buf[i]) ) i--; num_offsets_on_this_line = 1; if (buf[i] != '"') { // could have a 2nd offset value (one for 640, one for 1024) // so back up again while ( !is_white_space(buf[i]) ) i--; // now back up over intervening spaces while ( is_white_space(buf[i]) ) i--; num_offsets_on_this_line = 2; } p_offset = &buf[i+1]; // get ptr to string section with offset in it if (buf[i] != '"') Error(LOCATION, "%s is corrupt", filename); // now its an error } buf[i] = 0; // copy string into buf z = 0; for (i = 1; buf[i]; i++) { chr = buf[i]; if (chr == '\\') { chr = buf[++i]; if (chr == 'n') chr = '\n'; else if (chr == 'r') chr = '\r'; } buf[z++] = chr; } // null terminator on buf buf[z] = 0; } // write into Xstr_table (for strings.tbl) or Lcl_ext_str (for tstrings.tbl) if (Parsing_modular_table) { if ( external && (Lcl_ext_str[index] != NULL) ) { vm_free((void *) Lcl_ext_str[index]); Lcl_ext_str[index] = NULL; } else if ( !external && (Xstr_table[index].str != NULL) ) { vm_free((void *) Xstr_table[index].str); Xstr_table[index].str = NULL; } } if (external && (Lcl_ext_str[index] != NULL)) { Warning(LOCATION, "Tstrings table index %d used more than once", index); } else if (!external && (Xstr_table[index].str != NULL)) { Warning(LOCATION, "Strings table index %d used more than once", index); } if (external) { Lcl_ext_str[index] = vm_strdup(buf); } else { Xstr_table[index].str = vm_strdup(buf); } // the rest of this loop applies only to strings.tbl, // so we can move on to the next line if we're reading from tstrings.tbl if (external) { continue; } // read offset information, assume 0 if nonexistant if (p_offset != NULL) { if (sscanf(p_offset, "%d%d", &offset_lo, &offset_hi) < num_offsets_on_this_line) { // whatever is in the file ain't a proper offset Error(LOCATION, "%s is corrupt", filename); } } Xstr_table[index].offset_x = offset_lo; if (num_offsets_on_this_line == 2) Xstr_table[index].offset_x_hi = offset_hi; else Xstr_table[index].offset_x_hi = offset_lo; // clear out our vars p_offset = NULL; offset_lo = 0; offset_hi = 0; } }