void savegame::finish_save_game(const config_writer &out) { std::string name = gamestate_.classification().label; replace_space2underbar(name); std::string fname(get_saves_dir() + "/" + name); try { if(!out.good()) { throw game::save_game_failed(_("Could not write to file")); } config& summary = save_index::save_summary(gamestate_.classification().label); extract_summary_data_from_save(summary); const int mod_time = static_cast<int>(file_create_time(fname)); summary["mod_time"] = str_cast(mod_time); save_index::write_save_index(); } catch(io_exception& e) { throw game::save_game_failed(e.what()); } }
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); }