bool hero_map::map_to_file_fp(posix_file_t fp) { uint32_t idx, bytertd, *u32ptr; uint8_t* data = NULL; bool fok = false; uint8_t prefix[HEROS_FILE_PREFIX_BYTES]; if (map_vsize_ == 0) { goto exit; } data = (uint8_t*)malloc(map_vsize_ * HEROS_BYTES_PER_HERO); if (!data) { goto exit; } for (idx = 0; idx < map_vsize_; idx ++) { map_[idx]->write(data + idx * HEROS_BYTES_PER_HERO); } memset(&prefix, 0, sizeof(prefix)); u32ptr = (uint32_t*)prefix; // 第四个字节是作为版本号,当前版本V.0 *u32ptr = mmioFOURCC('H', 'E', 'R', '0'); posix_fwrite(fp, prefix, HEROS_FILE_PREFIX_BYTES, bytertd); posix_fwrite(fp, data, map_vsize_ * HEROS_BYTES_PER_HERO, bytertd); fok = true; exit: if (data) { free(data); } return fok; }
// config就三个成员变量, values, children, orderer_children. orderer_child_ren可由children推出 // config被组织成一个树状结构 void wml_config_to_file(const std::string &fname, config &cfg, uint32_t nfiles, uint32_t sum_size, uint32_t modified) { posix_file_t fp = INVALID_FILE; uint32_t max_str_len, bytertd, u32n; std::vector<std::string> tdomain; posix_print("<xwml.cpp>::wml_config_to_file------fname: %s\n", fname.c_str()); posix_fopen(fname.c_str(), GENERIC_WRITE, CREATE_ALWAYS, fp); if (fp == INVALID_FILE) { posix_print("------<xwml.cpp>::wml_config_to_file, cannot create %s for wrtie\n", fname.c_str()); goto exit; } // max_str_len = posix_max(WMLBIN_MARK_CONFIG_LEN, WMLBIN_MARK_VALUE_LEN); posix_fseek(fp, 16 + sizeof(max_str_len) + sizeof(u32n), 0); // write [textdomain] BOOST_FOREACH (const config &d, cfg.child_range("textdomain")) { if (std::find(tdomain.begin(), tdomain.end(), d.get("name")->str()) != tdomain.end()) { continue; } tdomain.push_back(d.get("name")->str()); u32n = tdomain.back().size(); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_fwrite(fp, tdomain.back().c_str(), u32n, bytertd); } wml_config_to_fp(fp, cfg, &max_str_len, tdomain, 0); // update max_str_len/textdomain_count posix_fseek(fp, 0, 0); // 0--15 u32n = mmioFOURCC('X', 'W', 'M', 'L'); posix_fwrite(fp, &u32n, 4, bytertd); posix_fwrite(fp, &nfiles, 4, bytertd); posix_fwrite(fp, &sum_size, 4, bytertd); posix_fwrite(fp, &modified, 4, bytertd); // 16--19(max_str_len) posix_fwrite(fp, &max_str_len, sizeof(max_str_len), bytertd); // 20--23(textdomain_count) u32n = tdomain.size(); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_print("------<xwml.cpp>::wml_config_to_file, return\n"); exit: if (fp != INVALID_FILE) { posix_fclose(fp); } return; }
/* return value: false: 1)cannot open file that fname specified */ bool hero_map::map_to_file(const std::string& fname) { uint32_t idx, bytertd, *u32ptr; posix_file_t fp = INVALID_FILE; uint8_t* data = NULL; bool fok = false; uint8_t prefix[HEROS_FILE_PREFIX_BYTES]; if (map_vsize_ == 0) { goto exit; } data = (uint8_t*)malloc(map_vsize_ * HEROS_BYTES_PER_HERO); if (!data) { goto exit; } for (idx = 0; idx < map_vsize_; idx ++) { map_[idx]->write(data + idx * HEROS_BYTES_PER_HERO); } posix_fopen(fname.c_str(), GENERIC_WRITE, CREATE_ALWAYS, fp); if (fp == INVALID_FILE) { goto exit; } memset(&prefix, 0, sizeof(prefix)); u32ptr = (uint32_t*)prefix; // 第四个字节是作为版本号,当前版本V.0 *u32ptr = mmioFOURCC('H', 'E', 'R', '0'); posix_fwrite(fp, prefix, HEROS_FILE_PREFIX_BYTES, bytertd); posix_fwrite(fp, data, map_vsize_ * HEROS_BYTES_PER_HERO, bytertd); fok = true; exit: if (fp != INVALID_FILE) { posix_fclose(fp); } if (data) { free(data); } return fok; }
void string_to_file(std::string str, char* fname) { posix_file_t fp; uint32_t bytertd; posix_fopen(fname, GENERIC_WRITE, CREATE_ALWAYS, fp); if (fp == INVALID_FILE) { posix_print_mb("string_to_file, cann't create file %s for write", fname); return; } posix_fwrite(fp, str.c_str(), str.length(), bytertd); posix_fclose(fp); return; }
void wml_building_rules_to_file(const std::string& fname, terrain_builder::building_rule* rules, uint32_t rules_size, uint32_t nfiles, uint32_t sum_size, uint32_t modified) { posix_file_t fp = INVALID_FILE; uint32_t max_str_len, bytertd, u32n, idx, size, size1; posix_print("<xwml.cpp>::wml_building_rules_to_file------fname: %s, will save %u rules\n", fname.c_str(), rules_size); posix_fopen(fname.c_str(), GENERIC_WRITE, CREATE_ALWAYS, fp); if (fp == INVALID_FILE) { posix_print("------<xwml.cpp>::wml_building_rules_to_file, cannot create %s for wrtie\n", fname.c_str()); return; } // max str len max_str_len = 63; // 0--15 u32n = mmioFOURCC('X', 'W', 'M', 'L'); posix_fwrite(fp, &u32n, 4, bytertd); posix_fwrite(fp, &nfiles, 4, bytertd); posix_fwrite(fp, &sum_size, 4, bytertd); posix_fwrite(fp, &modified, 4, bytertd); posix_fseek(fp, 16 + sizeof(max_str_len), 0); // rules size posix_fwrite(fp, &rules_size, sizeof(rules_size), bytertd); uint32_t rule_index = 0; for (rule_index = 0; rule_index < rules_size; rule_index ++) { // // typedef std::multiset<building_rule> building_ruleset; // // building_rule const terrain_builder::building_rule& rule = rules[rule_index]; // *int precedence posix_fwrite(fp, &rule.precedence, sizeof(int), bytertd); // *map_location location_constraints; posix_fwrite(fp, &rule.location_constraints.x, sizeof(int), bytertd); posix_fwrite(fp, &rule.location_constraints.y, sizeof(int), bytertd); // *int probability posix_fwrite(fp, &rule.probability, sizeof(int), bytertd); // size of constraints size = rule.constraints.size(); posix_fwrite(fp, &size, sizeof(uint32_t), bytertd); // constraint_set constraints for (terrain_builder::constraint_set::const_iterator constraint = rule.constraints.begin(); constraint != rule.constraints.end(); ++constraint) { // typedef std::vector<terrain_constraint> constraint_set; posix_fwrite(fp, &constraint->loc.x, sizeof(int), bytertd); posix_fwrite(fp, &constraint->loc.y, sizeof(int), bytertd); // // terrain_constraint // // t_translation::t_match terrain_types_match; const t_translation::t_match& match = constraint->terrain_types_match; // struct t_match{ // ...... // t_list terrain; // t_list mask; // t_list masked_terrain; // bool has_wildcard; // bool is_empty; // }; // typedef std::vector<t_terrain> t_list; // terrain, mask和masked_terrain肯定一样长度, 为节省空间,只写一个长度值 size = match.terrain.size(); posix_fwrite(fp, &size, sizeof(size), bytertd); t_list_to_fp(fp, match.terrain, idx, size, bytertd); t_list_to_fp(fp, match.mask, idx, size, bytertd); t_list_to_fp(fp, match.masked_terrain, idx, size, bytertd); u32n = match.has_wildcard? 1: 0; posix_fwrite(fp, &u32n, sizeof(int), bytertd); u32n = match.is_empty? 1: 0; posix_fwrite(fp, &u32n, sizeof(int), bytertd); // std::vector<std::string> set_flag; vstr_to_fp(fp, constraint->set_flag, idx, size, u32n, bytertd, max_str_len); // std::vector<std::string> no_flag; vstr_to_fp(fp, constraint->no_flag, idx, size, u32n, bytertd, max_str_len); // std::vector<std::string> has_flag; vstr_to_fp(fp, constraint->has_flag, idx, size, u32n, bytertd, max_str_len); // (typedef std::vector<rule_image> rule_imagelist) rule_imagelist images size = constraint->images.size(); posix_fwrite(fp, &size, sizeof(size), bytertd); for (idx = 0; idx < size; idx ++) { const struct terrain_builder::rule_image& ri = constraint->images[idx]; // rule_image // struct rule_image { // ...... // int layer; // int basex, basey; // bool global_image; // int center_x, center_y; // rule_image_variantlist variants; // } posix_fwrite(fp, &ri.layer, sizeof(int), bytertd); posix_fwrite(fp, &ri.basex, sizeof(int), bytertd); posix_fwrite(fp, &ri.basey, sizeof(int), bytertd); u32n = ri.global_image? 1: 0; posix_fwrite(fp, &u32n, sizeof(int), bytertd); posix_fwrite(fp, &ri.center_x, sizeof(int), bytertd); posix_fwrite(fp, &ri.center_y, sizeof(int), bytertd); // (std::vector<rule_image_variant>) variants size1 = ri.variants.size(); posix_fwrite(fp, &size1, sizeof(size), bytertd); for (std::vector<terrain_builder::rule_image_variant>::const_iterator imgitor = ri.variants.begin(); imgitor != ri.variants.end(); ++imgitor) { // value: rule_image_variant // struct rule_image_variant { // ...... // std::string image_string; // std::string variations; // std::string tod; // animated<image::locator> image; // bool random_start; // } u32n = imgitor->image_string.size(); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_fwrite(fp, imgitor->image_string.c_str(), u32n, bytertd); max_str_len = posix_max(max_str_len, u32n); u32n = imgitor->variations.size(); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_fwrite(fp, imgitor->variations.c_str(), u32n, bytertd); max_str_len = posix_max(max_str_len, u32n); u32n = imgitor->random_start? 1: 0; posix_fwrite(fp, &u32n, sizeof(int), bytertd); // // 到此为止,只有rule_image_variant中的image没有生成 // image涉及到两个类class animated和class locator,类中有数据private成员数据,很难直接赋值 // 考虑到from时也会调用构造函数以构造类,这里就填上构造函数需的参数就行了。 // 如何由构造函数生成animated和locator参考:bool terrain_builder::start_animation(building_rule &rule) // // class animated // int starting_frame_time_; // bool does_not_change_; // bool started_; // bool need_first_update_; // int start_tick_; // bool cycles_; // double acceleration_; // int last_update_tick_; // int current_frame_key_; // +std::vector<frame> frames_; // int duration_; // int start_time_; // +T value_; // +class locator // static int last_index_; // int index_; // value val_; // struct value { // ...... // type type_; // std::string filename_; // map_location loc_; // std::string modifications_; // int center_x_; // int center_y_; // } } } } } // 更新最大的存储区大小 posix_fseek(fp, 16, 0); posix_fwrite(fp, &max_str_len, sizeof(max_str_len), bytertd); posix_fclose(fp); posix_print("------<xwml.cpp>::wml_building_rules_to_file, return\n"); return; }
// @deep: 嵌套深度, 顶层: 0 void wml_config_to_fp(posix_file_t fp, const config &cfg, uint32_t *max_str_len, std::vector<std::string> &td, uint16_t deep) { uint32_t u32n, bytertd; int first; // config::child_list::const_iterator ichildlist; // string_map::const_iterator istrmap; // recursively resolve children BOOST_FOREACH (const config::any_child &value, cfg.all_children_range()) { // save {[cfg]}{len}{name} posix_fwrite(fp, WMLBIN_MARK_CONFIG, WMLBIN_MARK_CONFIG_LEN, bytertd); u32n = posix_mku32(value.key.size(), deep); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_fwrite(fp, value.key.c_str(), posix_lo16(u32n), bytertd); *max_str_len = posix_max(*max_str_len, value.key.size()); // save {[val]}{len}{name0}{len}{val0}{len}{name1}{len}{val1}{...} // string_map &values = value.cfg.gvalues(); // for (istrmap = values.begin(); istrmap != values.end(); istrmap ++) { first = 1; BOOST_FOREACH (const config::attribute &istrmap, value.cfg.attribute_range()) { if (first) { posix_fwrite(fp, WMLBIN_MARK_VALUE, WMLBIN_MARK_VALUE_LEN, bytertd); first = 0; } u32n = istrmap.first.size(); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_fwrite(fp, istrmap.first.c_str(), u32n, bytertd); *max_str_len = posix_max(*max_str_len, u32n); if (istrmap.second.t_str().translatable()) { // parse translatable string std::vector<t_string_base::trans_str> trans = istrmap.second.t_str().valuex(); for (std::vector<t_string_base::trans_str>::const_iterator ti = trans.begin(); ti != trans.end(); ti ++) { if (ti == trans.begin()) { if (ti->td.empty()) { u32n = posix_mku32(0, posix_mku16(0, trans.size())); } else { u32n = posix_mku32(0, posix_mku16(tstring_textdomain_idx(ti->td.c_str(), td), trans.size())); } } else { if (ti->td.empty()) { u32n = posix_mku32(0, 0); } else { u32n = posix_mku32(0, posix_mku16(tstring_textdomain_idx(ti->td.c_str(), td), 0)); } } // flag posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); // length of value u32n = ti->str.size(); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_fwrite(fp, ti->str.c_str(), u32n, bytertd); } } else { // flag u32n = 0; posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); // length of value u32n = istrmap.second.str().size(); posix_fwrite(fp, &u32n, sizeof(u32n), bytertd); posix_fwrite(fp, istrmap.second.str().c_str(), u32n, bytertd); } *max_str_len = posix_max(*max_str_len, u32n); } wml_config_to_fp(fp, value.cfg, max_str_len, td, deep + 1); } return; }
void savegame::write_game_to_disk(const std::string& filename) { filename_ = filename; filename_ += ".sav"; std::stringstream ss; { config_writer out(ss, false); write_game(out); } // start scenario data(write it to stream only first, others write stream to file direct) if (!gamestate_.start_scenario_ss.str().length()) { ::write(gamestate_.start_scenario_ss, gamestate_.starting_pos); } if (!gamestate_.start_hero_data_) { gamestate_.start_hero_data_ = (uint8_t*)malloc(heros_start_.file_size()); heros_start_.map_to_mem(gamestate_.start_hero_data_); } config cfg_summary; std::stringstream summary_ss; extract_summary_data_from_save(cfg_summary); ::write(summary_ss, cfg_summary); // if enable compress, ss.str() is compressed format data. posix_file_t fp; uint32_t summary_size, scenario_size, side_size, start_scenario_size, start_hero_size, replay_size, hero_size, member_data_size, bytertd; int size; // replace_space2underbar(filename_); std::string fullfilename = get_saves_dir() + "/" + filename_; #ifdef _WIN32 // utf8 ---> utf16 int wlen = MultiByteToWideChar(CP_UTF8, 0, fullfilename.c_str(), -1, NULL, 0); WCHAR *wc = new WCHAR[wlen]; MultiByteToWideChar(CP_UTF8, 0, fullfilename.c_str(), -1, wc, wlen); fp = CreateFileW(wc, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); // posix_fopen(wc, GENERIC_WRITE, CREATE_ALWAYS, fp); delete [] wc; #else posix_fopen(fullfilename.c_str(), GENERIC_WRITE, CREATE_ALWAYS, fp); #endif if (fp == INVALID_FILE) { throw game::save_game_failed(_("Could not write to file")); } // length of summary data summary_size = summary_ss.str().length(); // length of scenario data scenario_size = ss.str().length(); // length of side data side_size = ((unit_segment2*)game_config::savegame_cache)->size_; // length of start scenario data start_scenario_size = gamestate_.start_scenario_ss.str().length(); // length of start hero data start_hero_size = heros_start_.file_size(); // length of replay data if (gamestate_.replay_data.pool_pos_vsize()) { replay_size = 16 + gamestate_.replay_data.pool_data_gzip_size() + gamestate_.replay_data.pool_pos_vsize() * sizeof(unsigned int); } else { replay_size = 0; } // length of runtime hero data hero_size = heros_.file_size(); // length of runtime-member data member_data_size = runtime_groups::size(); // [write] length of summary data posix_fwrite(fp, &summary_size, sizeof(summary_size), bytertd); // [write] length of scenario data posix_fwrite(fp, &scenario_size, sizeof(scenario_size), bytertd); // [write] length of side data posix_fwrite(fp, &side_size, sizeof(side_size), bytertd); // [write] length of start scenario data posix_fwrite(fp, &start_scenario_size, sizeof(start_scenario_size), bytertd); // [write] length of start hero data posix_fwrite(fp, &start_hero_size, sizeof(start_hero_size), bytertd); // [write] length of replay data posix_fwrite(fp, &replay_size, sizeof(replay_size), bytertd); // [write] length of runtime hero data posix_fwrite(fp, &hero_size, sizeof(hero_size), bytertd); // [write] length of member data posix_fwrite(fp, &member_data_size, sizeof(member_data_size), bytertd); // summary data posix_fwrite(fp, summary_ss.str().c_str(), summary_ss.str().length(), bytertd); // scenario data posix_fwrite(fp, ss.str().c_str(), ss.str().length(), bytertd); // side data if (side_size) { posix_fwrite(fp, game_config::savegame_cache, side_size, bytertd); } // start scenario data posix_fwrite(fp, gamestate_.start_scenario_ss.str().c_str(), gamestate_.start_scenario_ss.str().length(), bytertd); // start hero data posix_fwrite(fp, gamestate_.start_hero_data_, start_hero_size, bytertd); // replay data if (replay_size) { size = gamestate_.replay_data.pool_data_size(); posix_fwrite(fp, &size, sizeof(size), bytertd); size = gamestate_.replay_data.pool_data_gzip_size(); posix_fwrite(fp, &size, sizeof(size), bytertd); size = gamestate_.replay_data.pool_pos_size(); posix_fwrite(fp, &size, sizeof(size), bytertd); size = gamestate_.replay_data.pool_pos_vsize(); posix_fwrite(fp, &size, sizeof(size), bytertd); // pool data posix_fwrite(fp, gamestate_.replay_data.pool_data(), gamestate_.replay_data.pool_data_gzip_size(), bytertd); // pool pos posix_fwrite(fp, gamestate_.replay_data.pool_pos(), gamestate_.replay_data.pool_pos_vsize() * sizeof(unsigned int), bytertd); } // hero data heros_.map_to_file_fp(fp); // member data runtime_groups::to_fp(fp); posix_fclose(fp); }