void pilotfile::plr_read_multiplayer() { // netgame options p->m_server_options.squad_set = cfread_ubyte(cfp); p->m_server_options.endgame_set = cfread_ubyte(cfp); p->m_server_options.flags = cfread_int(cfp); p->m_server_options.respawn = cfread_uint(cfp); p->m_server_options.max_observers = cfread_ubyte(cfp); p->m_server_options.skill_level = cfread_ubyte(cfp); p->m_server_options.voice_qos = cfread_ubyte(cfp); p->m_server_options.voice_token_wait = cfread_int(cfp); p->m_server_options.voice_record_time = cfread_int(cfp); p->m_server_options.mission_time_limit = (fix)cfread_int(cfp); p->m_server_options.kill_limit = cfread_int(cfp); // local options p->m_local_options.flags = cfread_int(cfp); p->m_local_options.obj_update_level = cfread_int(cfp); // netgame protocol Multi_options_g.protocol = cfread_int(cfp); if (Multi_options_g.protocol == NET_VMT) { Multi_options_g.protocol = NET_TCP; } Assert( (Multi_options_g.protocol == NET_IPX) || (Multi_options_g.protocol == NET_TCP) ); }
void pilotfile_convert::csg_import_techroom() { int idx, list_size = 0; bool visible; unsigned char in = 0; // intel entry count int intel_count = cfread_int(cfp); csg->ships_techroom.reserve( csg->ship_list.size() ); csg->weapons_techroom.reserve( csg->weapon_list.size() ); csg->intel_techroom.reserve( intel_count ); // ships list_size = (int)csg->ship_list.size(); for (idx = 0; idx < list_size; idx++) { in = cfread_ubyte(cfp); if (in > 1) { throw std::runtime_error("Data check failure (techroom-ship)!"); } visible = (in == 1) ? true : false; csg->ships_techroom.push_back( visible ); } // weapons list_size = (int)csg->weapon_list.size(); for (idx = 0; idx < list_size; idx++) { in = cfread_ubyte(cfp); if (in > 1) { throw std::runtime_error("Data check failure (techroom-weapon)!"); } visible = (in == 1) ? true : false; csg->weapons_techroom.push_back( visible ); } // intel list_size = intel_count; for (idx = 0; idx < list_size; idx++) { in = cfread_ubyte(cfp); if (in > 1) { throw std::runtime_error("Data check failure (techroom-intel)!"); } visible = (in == 1) ? true : false; csg->intel_techroom.push_back( visible ); } }
void pilotfile::csg_read_techroom() { int idx, list_size = 0; ubyte visible; if ( !m_have_info ) { throw "Techroom before Info!"; } // visible ships list_size = (int)ship_list.size(); for (idx = 0; idx < list_size; idx++) { visible = cfread_ubyte(cfp); if (visible) { if (ship_list[idx].index >= 0) { Ship_info[ship_list[idx].index].flags.set(Ship::Info_Flags::In_tech_database); } else { m_data_invalid = true; } } } // visible weapons list_size = (int)weapon_list.size(); for (idx = 0; idx < list_size; idx++) { visible = cfread_ubyte(cfp); if (visible) { if (weapon_list[idx].index >= 0) { Weapon_info[weapon_list[idx].index].wi_flags |= WIF_IN_TECH_DATABASE; } else { m_data_invalid = true; } } } // visible intel entries list_size = (int)intel_list.size(); for (idx = 0; idx < list_size; idx++) { visible = cfread_ubyte(cfp); if (visible) { if (intel_list[idx].index >= 0) { Intel_info[intel_list[idx].index].flags |= IIF_IN_TECH_DATABASE; } else { m_data_invalid = true; } } } // if anything we need/use was missing then it should be considered fatal if (m_data_invalid) { throw "Invalid data for CSG!"; } }
void pilotfile_convert::plr_import_controls() { int idx; config_item con; unsigned char num_controls = cfread_ubyte(cfp); if ( !num_controls ) { return; } // it may be less than 118, but it shouldn't be more than 118 if (num_controls > 118) { throw "Data check failure in controls!"; } plr->controls.reserve(num_controls); for (idx = 0; idx < num_controls; idx++) { con.key_id = cfread_short(cfp); if (con.key_id == 255) { con.key_id = -1; } con.joy_id = cfread_short(cfp); if (con.joy_id == 255) { con.joy_id = -1; } plr->controls.push_back( con ); } }
void pilotfile_convert::plr_import_hud() { int idx; conv_color c; plr->hud_show_flags = cfread_int(cfp); plr->hud_show_flags2 = cfread_int(cfp); plr->hud_popup_flags = cfread_int(cfp); plr->hud_popup_flags2 = cfread_int(cfp); plr->hud_num_lines = cfread_ubyte(cfp); plr->hud_rp_flags = cfread_int(cfp); plr->hud_rp_dist = cfread_int(cfp); for (idx = 0; idx < 39; idx++) { cfread(&c, sizeof(conv_color), 1, cfp); if ( (c.alphacolor != -1) || (c.is_alphacolor != 1) ) { throw "Data check failure in hud!"; } plr->hud_colors[idx][0] = c.red; plr->hud_colors[idx][1] = c.green; plr->hud_colors[idx][2] = c.blue; plr->hud_colors[idx][3] = c.alpha; } }
void pilotfile::plr_read_flags() { // tips? p->tips = (int)cfread_ubyte(cfp); // saved flags p->save_flags = cfread_int(cfp); // listing mode (single or campaign missions p->readyroom_listing_mode = cfread_int(cfp); // briefing auto-play p->auto_advance = cfread_int(cfp); // special rank setting (to avoid having to read all stats on verify) // will be the multi rank // if there's a valid CSG, this will be overwritten p->stats.rank = cfread_int(cfp); if (version > 0) { p->player_was_multi = cfread_int(cfp); } else { p->player_was_multi = 0; // Default to single player } // which language was this pilot created with if (version > 1) { cfread_string_len(p->language, sizeof(p->language), cfp); } else { // if we don't know, default to the current language setting lcl_get_language_name(p->language); } }
void pilotfile::plr_read_flags() { // tips? p->tips = (int)cfread_ubyte(cfp); // saved flags p->save_flags = cfread_int(cfp); // listing mode (single or campaign missions p->readyroom_listing_mode = cfread_int(cfp); // briefing auto-play p->auto_advance = cfread_int(cfp); // special rank setting (to avoid having to read all stats on verify) p->stats.rank = cfread_int(cfp); if (version > 0) { p->player_was_multi = cfread_int(cfp); } else { p->player_was_multi = 0; // Default to single player } }
void pilotfile_convert::plr_import_multiplayer() { plr->multi_squad_set = cfread_ubyte(cfp); plr->multi_endgame_set = cfread_ubyte(cfp); plr->multi_flags = cfread_int(cfp); plr->multi_respawn = cfread_uint(cfp); plr->multi_max_observers = cfread_ubyte(cfp); plr->multi_skill_level = cfread_ubyte(cfp); plr->multi_voice_qos = cfread_ubyte(cfp); plr->multi_voice_token_wait = cfread_int(cfp); plr->multi_voice_record_time = cfread_int(cfp); plr->multi_time_limit = cfread_int(cfp); plr->multi_kill_limit = cfread_int(cfp); plr->multi_local_flags = cfread_int(cfp); plr->multi_local_update_level = cfread_int(cfp); }
void pilotfile::plr_read_hud() { int idx; // flags HUD_config.show_flags = cfread_int(cfp); HUD_config.show_flags2 = cfread_int(cfp); HUD_config.popup_flags = cfread_int(cfp); HUD_config.popup_flags2 = cfread_int(cfp); // settings HUD_config.num_msg_window_lines = cfread_ubyte(cfp); HUD_config.rp_flags = cfread_int(cfp); HUD_config.rp_dist = cfread_int(cfp); // basic colors HUD_config.main_color = cfread_int(cfp); HUD_color_alpha = cfread_int(cfp); if (HUD_color_alpha < HUD_COLOR_ALPHA_USER_MIN) { HUD_color_alpha = HUD_COLOR_ALPHA_DEFAULT; } hud_config_set_color(HUD_config.main_color); // gauge-specific colors int num_gauges = cfread_int(cfp); for (idx = 0; idx < num_gauges; idx++) { ubyte red = cfread_ubyte(cfp); ubyte green = cfread_ubyte(cfp); ubyte blue = cfread_ubyte(cfp); ubyte alpha = cfread_ubyte(cfp); if (idx >= NUM_HUD_GAUGES) { continue; } HUD_config.clr[idx].red = red; HUD_config.clr[idx].green = green; HUD_config.clr[idx].blue = blue; HUD_config.clr[idx].alpha = alpha; } }
void pilotfile::csg_read_flags() { // tips? p->tips = (int)cfread_ubyte(cfp); // avoid having to read everything to get the rank if (csg_ver >= 5) { p->stats.rank = cfread_int(cfp); } }
// ----------------------------------------------------------------------------- // anim_read_header() // // Read the header of a .ani file. Below is the format of a .ani header // // #bytes | description // 2 | obsolete, kept for compatibility with old versions // 2 | version number // 2 | fps // 1 | transparent red value // 1 | transparent green value // 1 | transparent blue value // 2 | width // 2 | height // 2 | number of frames // 1 | packer code // 763 | palette // 2 | number of key frames // 2 | key frame number } repeats // 4 | key frame offset } repeats // 4 | compressed data length // void anim_read_header(anim *ptr, CFILE *fp) { ptr->width = cfread_short(fp); // If first 2 bytes are zero, this means we are using a new format, which includes // a version, and fps values. This is only done since a version number was not included // in the original header. // default Color_xparent.red = 0; Color_xparent.green = 255; Color_xparent.blue = 0; if ( ptr->width == 0 ) { ptr->version = cfread_short(fp); ptr->fps = cfread_short(fp); // version 2 added a custom transparency color if ( ptr->version >= 2 ) { cfread(&Color_xparent.red, 1, 1, fp); cfread(&Color_xparent.green, 1, 1, fp); cfread(&Color_xparent.blue, 1, 1, fp); } ptr->width = cfread_short(fp); } else { ptr->version = 0; ptr->fps = 30; } ptr->height = cfread_short(fp); #ifndef NDEBUG // get size of ani compared to power of 2 int r, floor_pow; r = ptr->height; floor_pow = 0; while(r >= 2) { r /= 2; floor_pow++; } int floor_size = (int) pow(2.0, floor_pow); int diff = ptr->height - floor_size; float waste = 100.0f * float((floor_size - diff))/(2.0f *(float)floor_size); if (diff != 0) { if (ptr->height > 16) { mprintf(("ANI %s with size %dx%d (%.1f%% wasted)\n", ptr->name, ptr->width, ptr->height, waste)); } } #endif ptr->total_frames = cfread_short(fp); ptr->packer_code = cfread_ubyte(fp); cfread(&ptr->palette, 256, 3, fp); ptr->num_keys = cfread_short(fp); // store xparent colors ptr->xparent_r = Color_xparent.red; ptr->xparent_g = Color_xparent.green; ptr->xparent_b = Color_xparent.blue; if(ptr->total_frames == ptr->num_keys){ ptr->flags |= ANF_ALL_KEYFRAMES; } }
void pilotfile::csg_read_info() { char t_string[NAME_LENGTH+1] = { '\0' }; index_list_t ilist; int idx, list_size = 0; ubyte allowed = 0; if ( !m_have_flags ) { throw "Info before Flags!"; } // // NOTE: lists may contain missing/invalid entries for current data // this is not necessarily fatal // // ship list (NOTE: may contain more than MAX_SHIP_CLASSES) list_size = cfread_int(cfp); for (idx = 0; idx < list_size; idx++) { cfread_string_len(t_string, NAME_LENGTH, cfp); ilist.name = t_string; ilist.index = ship_info_lookup(t_string); ship_list.push_back(ilist); } // weapon list (NOTE: may contain more than MAX_WEAPON_TYPES) list_size = cfread_int(cfp); for (idx = 0; idx < list_size; idx++) { cfread_string_len(t_string, NAME_LENGTH, cfp); ilist.name = t_string; ilist.index = weapon_info_lookup(t_string); weapon_list.push_back(ilist); } // intel list (NOTE: may contain more than MAX_INTEL_ENTRIES) list_size = cfread_int(cfp); for (idx = 0; idx < list_size; idx++) { cfread_string_len(t_string, NAME_LENGTH, cfp); ilist.name = t_string; ilist.index = intel_info_lookup(t_string); intel_list.push_back(ilist); } // medals list (NOTE: may contain more than Num_medals) list_size = cfread_int(cfp); for (idx = 0; idx < list_size; idx++) { cfread_string_len(t_string, NAME_LENGTH, cfp); ilist.name = t_string; ilist.index = medals_info_lookup(t_string); medals_list.push_back(ilist); } // last ship flown (index into ship_list) idx = cfread_int(cfp); // check the idx is within bounds Assertion ((idx < (int)ship_list.size()), "Campaign file contains an incorrect value for the last flown ship class. No data in ship_list for ship number %d.", idx); if (idx >= (int)ship_list.size()) idx = -1; else if (idx != -1) p->last_ship_flown_si_index = ship_list[idx].index; else p->last_ship_flown_si_index = -1; // progression state Campaign.prev_mission = cfread_int(cfp); Campaign.next_mission = cfread_int(cfp); // loop state Campaign.loop_reentry = cfread_int(cfp); Campaign.loop_enabled = cfread_int(cfp); // missions completed Campaign.num_missions_completed = cfread_int(cfp); // allowed ships list_size = (int)ship_list.size(); for (idx = 0; idx < list_size; idx++) { allowed = cfread_ubyte(cfp); if (allowed) { if (ship_list[idx].index >= 0) { Campaign.ships_allowed[ship_list[idx].index] = 1; } else { m_data_invalid = true; } } } // allowed weapons list_size = (int)weapon_list.size(); for (idx = 0; idx < list_size; idx++) { allowed = cfread_ubyte(cfp); if (allowed) { if (weapon_list[idx].index >= 0) { Campaign.weapons_allowed[weapon_list[idx].index] = 1; } else { m_data_invalid = true; } } } if (csg_ver >= 2) { // single/campaign squad name & image cfread_string_len(p->s_squad_name, NAME_LENGTH, cfp); cfread_string_len(p->s_squad_filename, MAX_FILENAME_LEN, cfp); } // if anything we need/use was missing then it should be considered fatal if (m_data_invalid) { throw "Invalid data for CSG!"; } }
void pilotfile_convert::csg_import(bool inferno) { Assert( cfp != NULL ); char name[35]; unsigned int csg_id = cfread_uint(cfp); if (csg_id != 0xbeefcafe) { throw std::runtime_error("Invalid file signature!"); } fver = cfread_uint(cfp); if (fver != 15) { throw std::runtime_error("Unsupported file version!"); } // campaign type (single/multi) csg->sig = cfread_int(cfp); // trash cfread_string_len(name, sizeof(name), cfp); csg->prev_mission = cfread_int(cfp); csg->next_mission = cfread_int(cfp); csg->loop_reentry = cfread_int(cfp); csg->loop_enabled = cfread_int(cfp); csg_import_ships_weapons(); csg_import_missions(inferno); csg->main_hall = cfread_ubyte(cfp); csg_import_red_alert(); csg_import_techroom(); csg_import_loadout(); csg_import_stats(); csg->cutscenes = cfread_int(cfp); // final data checks if ( csg->ship_list.size() != csg->ships_allowed.size() ) { throw std::runtime_error("Data check failure (ship size)!"); } else if ( csg->ship_list.size() != csg->ships_techroom.size() ) { throw std::runtime_error("Data check failure (ship size)!"); } else if ( csg->weapon_list.size() != csg->weapons_allowed.size() ) { throw std::runtime_error("Data check failure (weapon size)!"); } else if ( csg->weapon_list.size() != csg->weapons_techroom.size() ) { throw std::runtime_error("Data check failure (weapon size)!"); } else if ( csg->intel_list.size() != csg->intel_techroom.size() ) { throw std::runtime_error("Data check failure (intel size)!"); } // and... we're done! }
/* * get_csg_rank: this function is called from plr.cpp & is * tightly linked with pilotfile::verify() */ bool pilotfile::get_csg_rank(int *rank) { player t_csg; // set player ptr first thing p = &t_csg; // filename has already been set cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("CSG => Unable to open '%s'!\n", filename.c_str())); return false; } unsigned int csg_id = cfread_uint(cfp); if (csg_id != CSG_FILE_ID) { mprintf(("CSG => Invalid header id for '%s'!\n", filename.c_str())); csg_close(); return false; } // version, now used csg_ver = cfread_ubyte(cfp); mprintf(("CSG => Get Rank from '%s' with version %d...\n", filename.c_str(), (int)csg_ver)); // the point of all this: read in the CSG contents while ( !m_have_flags && !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); size_t offset_pos; // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("CSG => Parsing: Flags...\n")); m_have_flags = true; csg_read_flags(); break; default: break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("CSG => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("CSG => ERROR: %s\n", err)); csg_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("CSG => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, (int)offset_pos, CF_SEEK_CUR); } } // this is what we came for... *rank = p->stats.rank; mprintf(("CSG => Get Rank complete!\n")); // cleanup & return csg_close(); return true; }
bool pilotfile::load_savefile(const char *campaign) { char base[_MAX_FNAME] = { '\0' }; std::ostringstream buf; if (Game_mode & GM_MULTIPLAYER) { return false; } if ( (campaign == NULL) || !strlen(campaign) ) { return false; } // set player ptr first thing Assert( (Player_num >= 0) && (Player_num < MAX_PLAYERS) ); p = &Players[Player_num]; // build up filename for the savefile... _splitpath((char*)campaign, NULL, NULL, base, NULL); buf << p->callsign << "." << base << ".csg"; filename = buf.str().c_str(); // if campaign file doesn't exist, abort so we don't load irrelevant data buf.str(std::string()); buf << base << FS_CAMPAIGN_FILE_EXT; if ( !cf_exists_full((char*)buf.str().c_str(), CF_TYPE_MISSIONS) ) { mprintf(("CSG => Unable to find campaign file '%s'!\n", buf.str().c_str())); return false; } // we need to reset this early, in case open fails and we need to create m_data_invalid = false; // open it, hopefully... cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("CSG => Unable to open '%s' for reading!\n", filename.c_str())); return false; } unsigned int csg_id = cfread_uint(cfp); if (csg_id != CSG_FILE_ID) { mprintf(("CSG => Invalid header id for '%s'!\n", filename.c_str())); csg_close(); return false; } // version, now used csg_ver = cfread_ubyte(cfp); mprintf(("CSG => Loading '%s' with version %d...\n", filename.c_str(), (int)csg_ver)); csg_reset_data(); // the point of all this: read in the CSG contents while ( !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("CSG => Parsing: Flags...\n")); m_have_flags = true; csg_read_flags(); break; case Section::Info: mprintf(("CSG => Parsing: Info...\n")); m_have_info = true; csg_read_info(); break; case Section::Variables: mprintf(("CSG => Parsing: Variables...\n")); csg_read_variables(); break; case Section::HUD: mprintf(("CSG => Parsing: HUD...\n")); csg_read_hud(); break; case Section::RedAlert: mprintf(("CSG => Parsing: RedAlert...\n")); csg_read_redalert(); break; case Section::Scoring: mprintf(("CSG => Parsing: Scoring...\n")); csg_read_stats(); break; case Section::Loadout: mprintf(("CSG => Parsing: Loadout...\n")); csg_read_loadout(); break; case Section::Techroom: mprintf(("CSG => Parsing: Techroom...\n")); csg_read_techroom(); break; case Section::Missions: mprintf(("CSG => Parsing: Missions...\n")); csg_read_missions(); break; case Section::Settings: mprintf(("CSG => Parsing: Settings...\n")); csg_read_settings(); break; case Section::Controls: mprintf(("CSG => Parsing: Controls...\n")); csg_read_controls(); break; case Section::Cutscenes: mprintf(("CSG => Parsing: Cutscenes...\n")); csg_read_cutscenes(); break; case Section::LastMissions: mprintf(("CSG => Parsing: Last Missions...\n")); csg_read_lastmissions(); break; default: mprintf(("CSG => Skipping unknown section 0x%04x!\n", section_id)); break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("CSG => Warning: (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("CSG => ERROR: %s\n", err)); csg_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("CSG => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, (int)offset_pos, CF_SEEK_CUR); } } // if the campaign (for whatever reason) doesn't have a squad image, use the multi one if (p->s_squad_filename[0] == '\0') { strcpy_s(p->s_squad_filename, p->m_squad_filename); } player_set_squad_bitmap(p, p->s_squad_filename, false); mprintf(("CSG => Loading complete!\n")); // cleanup and return csg_close(); return true; }
std::uint8_t pilot::BinaryFileHandler::readUByte(const char*) { return cfread_ubyte(_cfp); }
bool pilotfile::load_player(const char *callsign, player *_p) { // if we're a standalone server in multiplayer, just fill in some bogus values // since we don't have a pilot file if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_STANDALONE_SERVER) ) { Player->insignia_texture = -1; strcpy_s(Player->callsign, NOX("Standalone")); strcpy_s(Player->short_callsign, NOX("Standalone")); return true; } // set player ptr first thing p = _p; if ( !p ) { Assert( (Player_num >= 0) && (Player_num < MAX_PLAYERS) ); p = &Players[Player_num]; } filename = callsign; filename += ".plr"; if ( filename.size() == 4 ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("PLR => Unable to open '%s' for reading!\n", filename.c_str())); return false; } unsigned int plr_id = cfread_uint(cfp); if (plr_id != PLR_FILE_ID) { mprintf(("PLR => Invalid header id for '%s'!\n", filename.c_str())); plr_close(); return false; } // version, should be able to just ignore it version = cfread_ubyte(cfp); mprintf(("PLR => Loading '%s' with version %d...\n", filename.c_str(), version)); plr_reset_data(); // the point of all this: read in the PLR contents while ( !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("PLR => Parsing: Flags...\n")); m_have_flags = true; plr_read_flags(); break; case Section::Info: mprintf(("PLR => Parsing: Info...\n")); m_have_info = true; plr_read_info(); break; case Section::Variables: mprintf(("PLR => Parsing: Variables...\n")); plr_read_variables(); break; case Section::HUD: mprintf(("PLR => Parsing: HUD...\n")); plr_read_hud(); break; case Section::Scoring: mprintf(("PLR => Parsing: Scoring...\n")); plr_read_stats(); break; case Section::ScoringMulti: mprintf(("PLR => Parsing: ScoringMulti...\n")); plr_read_stats_multi(); break; case Section::Multiplayer: mprintf(("PLR => Parsing: Multiplayer...\n")); plr_read_multiplayer(); break; case Section::Controls: mprintf(("PLR => Parsing: Controls...\n")); plr_read_controls(); break; case Section::Settings: mprintf(("PLR => Parsing: Settings...\n")); plr_read_settings(); break; default: mprintf(("PLR => Skipping unknown section 0x%04x!\n", section_id)); break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("PLR => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("PLR => ERROR: %s\n", err)); plr_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { cfseek(cfp, offset_pos, CF_SEEK_CUR); } } // restore the callsign into the Player structure strcpy_s(p->callsign, callsign); // restore the truncated callsign into Player structure pilot_set_short_callsign(p, SHORT_CALLSIGN_PIXEL_W); player_set_squad_bitmap(p, p->m_squad_filename, true); hud_squadmsg_save_keys(); // set last pilot os_config_write_string(NULL, "LastPlayer", (char*)callsign); mprintf(("PLR => Loading complete!\n")); // cleanup and return plr_close(); return true; }
bool pilotfile::verify(const char *fname, int *rank, char *valid_language) { player t_plr; // set player ptr first thing p = &t_plr; filename = fname; if ( filename.size() == 4 ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("PLR => Unable to open '%s'!\n", filename.c_str())); return false; } unsigned int plr_id = cfread_uint(cfp); if (plr_id != PLR_FILE_ID) { mprintf(("PLR => Invalid header id for '%s'!\n", filename.c_str())); plr_close(); return false; } // version, now used version = cfread_ubyte(cfp); mprintf(("PLR => Verifying '%s' with version %d...\n", filename.c_str(), (int)version)); // the point of all this: read in the PLR contents while ( !(m_have_flags && m_have_info) && !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("PLR => Parsing: Flags...\n")); m_have_flags = true; plr_read_flags(); break; // now reading the Info section to get the campaign // and be able to lookup the campaign rank case Section::Info: mprintf(("PLR => Parsing: Info...\n")); m_have_info = true; plr_read_info(); break; default: break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("PLR => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("PLR => ERROR: %s\n", err)); plr_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("PLR => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, offset_pos, CF_SEEK_CUR); } } if (valid_language) { strncpy(valid_language, p->language, sizeof(p->language)); } // need to cleanup early to ensure everything is OK for use in the CSG next // also means we can't use *p from now on, use t_plr instead for a few vars plr_close(); if (rank) { // maybe get the rank from the CSG if ( !(Game_mode & GM_MULTIPLAYER) ) { // build the csg filename // since filename/fname was validated above, perform less safety checks here filename = fname; filename = filename.replace(filename.find_last_of('.')+1,filename.npos, t_plr.current_campaign); filename.append(".csg"); if (!this->get_csg_rank(rank)) { // if we failed to get the csg rank, default to multi rank *rank = t_plr.stats.rank; } } else { // if the CSG isn't valid, or for multi, use this rank *rank = t_plr.stats.rank; } } mprintf(("PLR => Verifying complete!\n")); return true; }
void pilotfile_convert::plr_import() { char name[35]; int idx; unsigned int plr_id = cfread_uint(cfp); if (plr_id != 0x46505346) { throw "Invalid file signature!"; } fver = cfread_uint(cfp); if ( (fver != 142) && (fver != 242) ) { throw "Unsupported file version!"; } // multi flag plr->is_multi = (int)cfread_ubyte(cfp); // rank plr->rank = cfread_int(cfp); // mainhall, don't need it if (fver < 242) { cfread_ubyte(cfp); } plr->tips = cfread_int(cfp); if ( (plr->tips < 0) || (plr->tips > 1) ) { throw "Data check failure!"; } cfread_string_len(plr->image_filename, sizeof(plr->image_filename), cfp); cfread_string_len(plr->squad_name, sizeof(plr->squad_name), cfp); cfread_string_len(plr->squad_filename, sizeof(plr->squad_filename), cfp); cfread_string_len(plr->current_campaign, sizeof(plr->current_campaign), cfp); cfread_string_len(plr->last_ship_flown, sizeof(plr->last_ship_flown), cfp); // controls plr_import_controls(); // hud config plr_import_hud(); // cutscenes, don't need it if (fver < 242) { cfread_int(cfp); } // volume stuff plr->sound_volume = cfread_float(cfp); plr->music_volume = cfread_float(cfp); plr->voice_volume = cfread_float(cfp); // detail settings plr_import_detail(); // recent missions, don't need it int num_missions = cfread_int(cfp); for (idx = 0; idx < num_missions; idx++) { cfread_string_len(name, sizeof(name), cfp); } // stats, will skip if fver < 242 plr_import_stats(); plr->skill_level = cfread_int(cfp); if ( (plr->skill_level < 0) || (plr->skill_level > 4) ) { throw "Data check failure!"; } // extra joystick stuff for (idx = 0; idx < 5; idx++) { plr->joy_axis_map_to[idx] = cfread_int(cfp); plr->joy_invert_axis[idx] = cfread_int(cfp); } // flags plr->save_flags = cfread_int(cfp); // loadout, will skip if fver < 242 plr_import_loadout(); // multiplayer plr_import_multiplayer(); // two briefing related values plr->readyroom_listing_mode = cfread_int(cfp); Briefing_voice_enabled = cfread_int(cfp); plr->net_protocol = cfread_int(cfp); // protocol must be set to something if (plr->net_protocol == NET_NONE) { plr->net_protocol = NET_TCP; } else if ( (plr->net_protocol < 0) || (plr->net_protocol > NET_VMT) ) { throw "Data check failure!"; } // red alert status, will skip if fver < 242 (and should be empty if multi) plr_import_red_alert(); // briefing auto-advance plr->auto_advance = cfread_int(cfp); if ( (plr->auto_advance < 0) || (plr->auto_advance > 1) ) { throw "Data check failure!"; } // some input options plr->Use_mouse_to_fly = cfread_int(cfp); plr->Mouse_sensitivity = cfread_int(cfp); plr->Joy_sensitivity = cfread_int(cfp); plr->Dead_zone_size = cfread_int(cfp); // variables plr_import_variables(); // and... we're done! :) }
bool pilotfile::verify(const char *fname, int *rank) { player t_plr; // set player ptr first thing p = &t_plr; filename = fname; if ( filename.size() == 4 ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("PLR => Unable to open '%s'!\n", filename.c_str())); return false; } unsigned int plr_id = cfread_uint(cfp); if (plr_id != PLR_FILE_ID) { mprintf(("PLR => Invalid header id for '%s'!\n", filename.c_str())); plr_close(); return false; } // version, should be able to just ignore it ubyte plr_ver = cfread_ubyte(cfp); mprintf(("PLR => Verifying '%s' with version %d...\n", filename.c_str(), (int)plr_ver)); // the point of all this: read in the PLR contents while ( !m_have_flags && !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("PLR => Parsing: Flags...\n")); m_have_flags = true; plr_read_flags(); break; default: break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("PLR => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("PLR => ERROR: %s\n", err)); plr_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("PLR => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, offset_pos, CF_SEEK_CUR); } } if (rank) { *rank = p->stats.rank; } mprintf(("PLR => Verifying complete!\n")); // cleanup and return plr_close(); return true; }
void pilotfile_convert::csg_import_ships_weapons() { index_list_t ilist; char name[35]; int idx; int list_size = 0; int ship_count = cfread_int(cfp); int weap_count = cfread_int(cfp); for (idx = 0; idx < ship_count; idx++) { ubyte allowed = cfread_ubyte(cfp); csg->ships_allowed.push_back( (allowed != 0) ); cfread_string_len(name, sizeof(name), cfp); ilist.name = name; ilist.index = ship_info_lookup(name); if (ilist.index < 0) { std::ostringstream error_msg; error_msg << "Data mismatch (ship lookup: " << ilist.name << ")!"; throw std::runtime_error(error_msg.str().c_str()); } csg->ship_list.push_back( ilist ); } for (idx = 0; idx < weap_count; idx++) { ubyte allowed = cfread_ubyte(cfp); csg->weapons_allowed.push_back( allowed != 0 ); cfread_string_len(name, sizeof(name), cfp); ilist.name = name; ilist.index = weapon_info_lookup(name); if (ilist.index < 0) { std::ostringstream error_msg; error_msg << "Data mismatch (weapon lookup: " << ilist.name << ")!"; throw std::runtime_error(error_msg.str().c_str()); } csg->weapon_list.push_back( ilist ); } // get last ship flown index for (idx = 0; idx < ship_count; idx++) { if ( csg->ship_list[idx].name == plr->last_ship_flown ) { csg->last_ship_flown_index = idx; break; } } if (csg->last_ship_flown_index < 0) { std::ostringstream error_msg; error_msg << "Data mismatch (player ship: " << csg->last_ship_flown_index << ")!"; throw std::runtime_error(error_msg.str().c_str()); } // create list of medals (since it's missing from the old files) list_size = Num_medals; for (idx = 0; idx < list_size; idx++) { ilist.name = Medals[idx].name; ilist.index = idx; csg->medals_list.push_back( ilist ); } // stuff intel list as well (present but burried in old files) list_size = Intel_info_size; for (idx = 0; idx < list_size; idx++) { ilist.name = Intel_info[idx].name; ilist.index = idx; csg->intel_list.push_back( ilist ); } }