예제 #1
0
fs::path GetPath(PathType path_type) {
    switch (path_type) {
    case PATH_BINARY:
        return GetBinDir();
    case PATH_RESOURCE:
        return GetResourceDir();
    case PATH_DATA_ROOT:
        return GetRootDataDir();
    case PATH_DATA_USER:
        return GetUserDataDir();
    case PATH_CONFIG:
        return GetUserConfigDir();
    case PATH_SAVE:
        return GetSaveDir();
    case PATH_TEMP:
        return fs::temp_directory_path();
    case PATH_PYTHON:
#if defined(FREEORION_MACOSX) || defined(FREEORION_WIN32)
        return GetPythonHome();
#endif
    case PATH_INVALID:
    default:
        ErrorLogger() << "Invalid path type " << path_type;
        return fs::temp_directory_path();
    }
}
예제 #2
0
bool HiScoreDb::Load(std::string filename)
{
  // Load local hi score table
  m_hsVec.clear();
  filename = GetSaveDir() + filename;
  File f(false, File::STD);
  if (!f.OpenRead(filename, false, false))
  {
    f.ReportError("Failed to load hi scores!");
    return false;
  }
  int n = 0;
  if (!f.GetInteger(&n))
  {
    f.ReportError("Expected number of hi scores");
    return false;
  }
  for (int i = 0; i < n; i++)
  {
    Hi hi;
    if (!hi.Load(&f))
    {
      f.ReportError("Failed to load hi score line");
      return false;
    }
    int hash = MakeHash(hi);
    hi.m_hash = hash;
    m_hsVec.push_back(hi);
  }
  return true;
}
예제 #3
0
bool SingleHiScoreTable::Save()
{
  int check = 0;
  File f;
  std::string root = File::GetRoot();
  File::SetRoot(GetSaveDir(APPLICATION_NAME), "/");
  if (!f.OpenWrite("hiscores.cfg"))
  {
    File::SetRoot(root, "/");
    return false;
  }

  for (HiScores::iterator it = m_hiScores.begin(); it != m_hiScores.end(); ++it)
  {
    check ^= it->first;
    f.WriteInteger(it->first);
    f.Write(it->second);
  }
  f.WriteInteger(check);

  File::SetRoot(root, "/");
  
  // Send hi scores to web site. 
  SendToUrl("www.amju.com/cgi-bin/hiscores1.pl");
  return true;
}
예제 #4
0
bool SavedataParam::IsSaveEncrypted(SceUtilitySavedataParam* param, const std::string &saveDirName)
{
	bool isCrypted = false;

	ParamSFOData sfoFile;
	std::string dirPath = GetSaveFilePath(param, GetSaveDir(param, saveDirName));
	std::string sfopath = dirPath + "/" + SFO_FILENAME;
	PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
	if(sfoInfo.exists) // Read sfo
	{
		u8 *sfoData = new u8[(size_t)sfoInfo.size];
		size_t sfoSize = (size_t)sfoInfo.size;
		if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL))
		{
			sfoFile.ReadSFO(sfoData,sfoSize);

			// save created in PPSSPP and not encrypted has '0' in SAVEDATA_PARAMS
			u32 tmpDataSize = 0;
			u8* tmpDataOrig = sfoFile.GetValueData("SAVEDATA_PARAMS", &tmpDataSize);
			for(u32 i = 0; i < tmpDataSize; i++)
			{
				if(tmpDataOrig[i] != 0)
				{
					isCrypted = true;
					break;
				}
			}
		}
		delete[] sfoData;
	}
	return isCrypted;
}
예제 #5
0
void LoadSaveGamePreviews(const fs::path& orig_path, const std::string& extension, std::vector<FullPreview>& previews) {
    FullPreview data;
    fs::directory_iterator end_it;

    fs::path path = orig_path;
    // Relative path relative to the save directory
    if (path.is_relative()) {
        path = GetSaveDir() / path;
    }

    if (!fs::exists(path)) {
        ErrorLogger() << "SaveFileListBox::LoadSaveGamePreviews: Save Game directory \"" << path << "\" not found";
        return;
    }
    if (!fs::is_directory(path)) {
        ErrorLogger() << "SaveFileListBox::LoadSaveGamePreviews: Save Game directory \"" << path << "\" was not a directory";
        return;
    }

    for (fs::directory_iterator it(path); it != end_it; ++it) {
        try {
            std::string filename = PathString(it->path().filename());
            if (it->path().filename().extension() == extension & !fs::is_directory(it->path())) {
                if (LoadSaveGamePreviewData(*it, data)) {
                    // Add preview entry to list
                    previews.push_back(data);
                }
            }
        } catch (const std::exception& e) {
            ErrorLogger() << "SaveFileListBox::LoadSaveGamePreviews: Failed loading preview from " << it->path() << " because: " << e.what();
        }
    }
}
예제 #6
0
std::string SavedataParam::GetSaveFilePath(SceUtilitySavedataParam* param, int saveId)
{
	if (!param) {
		return "";
	}

	return savePath + GetSaveDir(param,saveId);
}
예제 #7
0
/**
**  Save a game to file.
**
**  @param filename  File name to be stored.
**
**  @note  Later we want to store in a more compact binary format.
*/
void SaveGame(const std::string &filename)
{
	time_t now;
	CFile file;
	char *s;
	char *s1;
	std::string fullpath;

	fullpath = GetSaveDir() + filename;
	if (file.open(fullpath.c_str(), CL_WRITE_GZ | CL_OPEN_WRITE) == -1) {
		fprintf(stderr, "Can't save to `%s'\n", filename.c_str());
		return;
	}

	time(&now);
	s = ctime(&now);
	if ((s1 = strchr(s, '\n'))) {
		*s1 = '\0';
	}

	// Parseable header
	file.printf("SavedGameInfo({\n");
	file.printf("---  generator = \"Generated by Bos Wars Version " VERSION "\",\n");
	file.printf("---  comment = \"Visit http://www.boswars.org for more informations\",\n");
	file.printf("---  type = \"%s\",\n", "single-player");
	file.printf("---  date = \"%s\",\n", s);
	file.printf("---  map = \"%s\",\n", Map.Info.Description.c_str());
	file.printf("---  media-version = \"%s\",\n", "Undefined");
	file.printf("---  engine = {%d, %d, %d},\n",
		StratagusMajorVersion, StratagusMinorVersion, StratagusPatchLevel);
	file.printf("  SyncHash = %d, \n", SyncHash);
	file.printf("  SyncRandSeed = %d, \n", SyncRandSeed);
	file.printf("  SaveFile = \"%s\"\n", CurrentMapPath);
	file.printf("} )\n\n");

	// FIXME: probably not the right place for this
	file.printf("GameCycle = %lu\n", GameCycle);

	SaveCcl(&file);
	Map.Save(&file);
	SavePlayers(&file);
	SaveUpgrades(&file);
	SaveUnits(&file);
	SaveUserInterface(&file);
	SaveAi(&file);
	SaveSelections(&file);
	SaveGroups(&file);
	SaveMissiles(&file);
	SaveTriggers(&file);
	SaveReplayList(&file);
	// FIXME: find all state information which must be saved.
	s = SaveGlobal(Lua, true);
	if (s != NULL) {
		file.printf("-- Lua state\n\n%s\n", s);
		delete[] s;
	}
	file.close();
}
예제 #8
0
/**
**  Delete save game
**
**  @param filename  Name of file to delete
*/
void DeleteSaveGame(const std::string &filename)
{
	// Security check
	if (filename.find_first_of("/\\") != std::string::npos) {
		return;
	}

	std::string fullpath = GetSaveDir() + "/" + filename;
	if (unlink(fullpath.c_str()) == -1) {
		fprintf(stderr, "delete failed for %s", fullpath.c_str());
	}
}
예제 #9
0
bool HiScoreDb::Save(std::string filename)
{
  filename = GetSaveDir() + filename;
  File f(false, File::STD);
  if (!f.OpenWrite(filename, 0, false, false, true))
  {
    f.ReportError("Failed to save hi scores!");
    return false;
  }
  f.WriteInteger(static_cast<int>(m_hsVec.size()));
  for (const auto& hi : m_hsVec)
  {
    hi.Save(&f);
  }
  return true;
}
예제 #10
0
void InitDirs(const std::string& argv0) {
    if (g_initialized)
        return;

    fs::path local_dir = GetUserDir();
    if (!exists(local_dir))
        fs::create_directories(local_dir);

    fs::path p(GetSaveDir());
    if (!exists(p))
        fs::create_directories(p);

    InitBinDir(argv0);

    g_initialized = true;
}
예제 #11
0
bool SingleHiScoreTable::Load()
{
  File f(true, File::STD); // yes has version info, no to glue file.

  std::string root = File::GetRoot();
  File::SetRoot(GetSaveDir(APPLICATION_NAME), "/");
  if (!f.OpenRead("hiscores.cfg"))
  {
    // Make default hi score table and return.
    MakeDefault();   
    File::SetRoot(root, "/");
    return true;
  } 
  File::SetRoot(root, "/");

  int c = 0; 
  for (int i = 0; i < TABLE_SIZE; i++)
  {
    int score = 0;
    std::string name;
    if (!f.GetInteger(&score))
    {
      MakeDefault();   
      return true;
    }
    if (!f.GetDataLine(&name))
    {
      MakeDefault();   
      return true;
    }
    c ^= score;
    m_hiScores.insert(std::make_pair(score, name));
  }
  int check = 0;
  if (!f.GetInteger(&check))
  {
    MakeDefault();   
    return true;
  }
  if (check != c)
  {
    MakeDefault();   
    return true;
  }

  return true;
}
예제 #12
0
void InitDirs(const std::string& argv0) {
    if (g_initialized)
        return;

    fs::path local_dir = GetUserConfigDir();
    if (!exists(local_dir))
        fs::create_directories(local_dir);

    fs::path p(GetSaveDir());
    if (!exists(p))
        fs::create_directories(p);

    // Intentionally do not create the server save dir.
    // The server save dir is publically accessible and should not be
    // automatically created for the user.

    InitBinDir(argv0);

    g_initialized = true;
}
예제 #13
0
void InGameMenu::Save() {
    Logger().debugStream() << "InGameMenu::Save";

    HumanClientApp* app = HumanClientApp::GetApp();
    if (!app)
        return;
    if (!app->CanSaveNow()) {
        Logger().errorStream() << "InGameMenu::Save aborting; Client app can't save now";
        return;
    }

    const std::string SAVE_GAME_EXTENSION =
        HumanClientApp::GetApp()->SinglePlayerGame() ?
        SP_SAVE_FILE_EXTENSION : MP_SAVE_FILE_EXTENSION;

    std::vector<std::pair<std::string, std::string> > save_file_types;
    save_file_types.push_back(std::make_pair(UserString("GAME_MENU_SAVE_FILES"), "*" + SAVE_GAME_EXTENSION));

    try {
        Logger().debugStream() << "... getting save path string";
        std::string path_string = PathString(GetSaveDir());
        Logger().debugStream() << "... got save path string: " << path_string;

        Logger().debugStream() << "... running file dialog";
        FileDlg dlg(path_string, "", true, false, save_file_types);
        dlg.Run();
        if (!dlg.Result().empty()) {
            if (!app->CanSaveNow()) {
                Logger().errorStream() << "InGameMenu::Save aborting; Client app can't save now";
                throw std::runtime_error(UserString("UNABLE_TO_SAVE_NOW_TRY_AGAIN"));
            }
            Logger().debugStream() << "... initiating save";
            app->SaveGame(*dlg.Result().begin());
            CloseClicked();
            Logger().debugStream() << "... save done";
        }
    } catch (const std::exception& e) {
        Logger().errorStream() << "Exception thrown attempting save: " << e.what();
        ClientUI::MessageBox(e.what(), true);
    }
}
예제 #14
0
파일: Pi.cpp 프로젝트: lwho/pioneer
void Pi::HandleEvents()
{
	PROFILE_SCOPED()
	SDL_Event event;

	// XXX for most keypresses SDL will generate KEYUP/KEYDOWN and TEXTINPUT
	// events. keybindings run off KEYUP/KEYDOWN. the console is opened/closed
	// via keybinding. the console TextInput widget uses TEXTINPUT events. thus
	// after switching the console, the stray TEXTINPUT event causes the
	// console key (backtick) to appear in the text entry field. we hack around
	// this by setting this flag if the console was switched. if its set, we
	// swallow the TEXTINPUT event this hack must remain until we have a
	// unified input system
	bool skipTextInput = false;

	Pi::mouseMotion[0] = Pi::mouseMotion[1] = 0;
	while (SDL_PollEvent(&event)) {
		if (event.type == SDL_QUIT) {
			if (Pi::game)
				Pi::EndGame();
			Pi::Quit();
		}

		if (skipTextInput && event.type == SDL_TEXTINPUT) {
			skipTextInput = false;
			continue;
		}
		if (ui->DispatchSDLEvent(event))
			continue;

		bool consoleActive = Pi::IsConsoleActive();
		if (!consoleActive)
			KeyBindings::DispatchSDLEvent(&event);
		else
			KeyBindings::toggleLuaConsole.CheckSDLEventAndDispatch(&event);
		if (consoleActive != Pi::IsConsoleActive()) {
			skipTextInput = true;
			continue;
		}

		if (Pi::IsConsoleActive())
			continue;

		Gui::HandleSDLEvent(&event);

		switch (event.type) {
			case SDL_KEYDOWN:
				if (event.key.keysym.sym == SDLK_ESCAPE) {
					if (Pi::game) {
						// only accessible once game started
						if (currentView != 0) {
							if (currentView != Pi::game->GetSettingsView()) {
								Pi::game->SetTimeAccel(Game::TIMEACCEL_PAUSED);
								SetView(Pi::game->GetSettingsView());
							}
							else {
								Pi::game->RequestTimeAccel(Game::TIMEACCEL_1X);
								SetView(Pi::player->IsDead()
										? static_cast<View*>(Pi::game->GetDeathView())
										: static_cast<View*>(Pi::game->GetWorldView()));
							}
						}
					}
					break;
				}
				// special keys. LCTRL+turd
				if ((KeyState(SDLK_LCTRL) || (KeyState(SDLK_RCTRL)))) {
					switch (event.key.keysym.sym) {
						case SDLK_q: // Quit
							if (Pi::game)
								Pi::EndGame();
							Pi::Quit();
							break;
						case SDLK_PRINTSCREEN: // print
						case SDLK_KP_MULTIPLY: // screen
						{
							char buf[256];
							const time_t t = time(0);
							struct tm *_tm = localtime(&t);
							strftime(buf, sizeof(buf), "screenshot-%Y%m%d-%H%M%S.png", _tm);
							Graphics::ScreendumpState sd;
							Pi::renderer->Screendump(sd);
							write_screenshot(sd, buf);
							break;
						}
#if WITH_DEVKEYS
						case SDLK_i: // Toggle Debug info
							Pi::showDebugInfo = !Pi::showDebugInfo;
							break;

#ifdef PIONEER_PROFILER
						case SDLK_p: // alert it that we want to profile
							if (KeyState(SDLK_LSHIFT) || KeyState(SDLK_RSHIFT))
								Pi::doProfileOne = true;
							else {
								Pi::doProfileSlow = !Pi::doProfileSlow;
								Output("slow frame profiling %s\n", Pi::doProfileSlow ? "enabled" : "disabled");
							}
							break;
#endif

						case SDLK_F12:
						{
							if(Pi::game) {
								vector3d dir = -Pi::player->GetOrient().VectorZ();
								/* add test object */
								if (KeyState(SDLK_RSHIFT)) {
									Missile *missile =
										new Missile(ShipType::MISSILE_GUIDED, Pi::player);
									missile->SetOrient(Pi::player->GetOrient());
									missile->SetFrame(Pi::player->GetFrame());
									missile->SetPosition(Pi::player->GetPosition()+50.0*dir);
									missile->SetVelocity(Pi::player->GetVelocity());
									game->GetSpace()->AddBody(missile);
									missile->AIKamikaze(Pi::player->GetCombatTarget());
								} else if (KeyState(SDLK_LSHIFT)) {
									SpaceStation *s = static_cast<SpaceStation*>(Pi::player->GetNavTarget());
									if (s) {
										Ship *ship = new Ship(ShipType::POLICE);
										int port = s->GetFreeDockingPort(ship);
										if (port != -1) {
											Output("Putting ship into station\n");
											// Make police ship intent on killing the player
											ship->AIKill(Pi::player);
											ship->SetFrame(Pi::player->GetFrame());
											ship->SetDockedWith(s, port);
											game->GetSpace()->AddBody(ship);
										} else {
											delete ship;
											Output("No docking ports free dude\n");
										}
									} else {
											Output("Select a space station...\n");
									}
								} else {
									Ship *ship = new Ship(ShipType::POLICE);
									if( KeyState(SDLK_LCTRL) )
										ship->AIFlyTo(Pi::player);	// a less lethal option
									else
										ship->AIKill(Pi::player);	// a really lethal option!
									lua_State *l = Lua::manager->GetLuaState();
									pi_lua_import(l, "Equipment");
									LuaTable equip(l, -1);
									LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("laser").Sub("pulsecannon_dual_1mw"));
									LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("misc").Sub("laser_cooling_booster"));
									LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("misc").Sub("atmospheric_shielding"));
									lua_pop(l, 5);
									ship->SetFrame(Pi::player->GetFrame());
									ship->SetPosition(Pi::player->GetPosition()+100.0*dir);
									ship->SetVelocity(Pi::player->GetVelocity());
									ship->UpdateEquipStats();
									game->GetSpace()->AddBody(ship);
								}
							}
							break;
						}
#endif /* DEVKEYS */
#if WITH_OBJECTVIEWER
						case SDLK_F10:
							Pi::SetView(Pi::game->GetObjectViewerView());
							break;
#endif
						case SDLK_F11:
							// XXX only works on X11
							//SDL_WM_ToggleFullScreen(Pi::scrSurface);
#if WITH_DEVKEYS
							renderer->ReloadShaders();
#endif
							break;
						case SDLK_F9: // Quicksave
						{
							if(Pi::game) {
								if (Pi::game->IsHyperspace())
									Pi::game->log->Add(Lang::CANT_SAVE_IN_HYPERSPACE);

								else {
									const std::string name = "_quicksave";
									const std::string path = FileSystem::JoinPath(GetSaveDir(), name);
									try {
										Game::SaveGame(name, Pi::game);
										Pi::game->log->Add(Lang::GAME_SAVED_TO + path);
									} catch (CouldNotOpenFileException) {
										Pi::game->log->Add(stringf(Lang::COULD_NOT_OPEN_FILENAME, formatarg("path", path)));
									}
									catch (CouldNotWriteToFileException) {
										Pi::game->log->Add(Lang::GAME_SAVE_CANNOT_WRITE);
									}
								}
							}
							break;
						}
						default:
							break; // This does nothing but it stops the compiler warnings
					}
				}
				Pi::keyState[event.key.keysym.sym] = true;
				Pi::keyModState = event.key.keysym.mod;
				Pi::onKeyPress.emit(&event.key.keysym);
				break;
			case SDL_KEYUP:
				Pi::keyState[event.key.keysym.sym] = false;
				Pi::keyModState = event.key.keysym.mod;
				Pi::onKeyRelease.emit(&event.key.keysym);
				break;
			case SDL_MOUSEBUTTONDOWN:
				if (event.button.button < COUNTOF(Pi::mouseButton)) {
					Pi::mouseButton[event.button.button] = 1;
					Pi::onMouseButtonDown.emit(event.button.button,
							event.button.x, event.button.y);
				}
				break;
			case SDL_MOUSEBUTTONUP:
				if (event.button.button < COUNTOF(Pi::mouseButton)) {
					Pi::mouseButton[event.button.button] = 0;
					Pi::onMouseButtonUp.emit(event.button.button,
							event.button.x, event.button.y);
				}
				break;
			case SDL_MOUSEWHEEL:
				Pi::onMouseWheel.emit(event.wheel.y > 0); // true = up
				break;
			case SDL_MOUSEMOTION:
				Pi::mouseMotion[0] += event.motion.xrel;
				Pi::mouseMotion[1] += event.motion.yrel;
		//		SDL_GetRelativeMouseState(&Pi::mouseMotion[0], &Pi::mouseMotion[1]);
				break;
			case SDL_JOYAXISMOTION:
				if (!joysticks[event.jaxis.which].joystick)
					break;
				if (event.jaxis.value == -32768)
					joysticks[event.jaxis.which].axes[event.jaxis.axis] = 1.f;
				else
					joysticks[event.jaxis.which].axes[event.jaxis.axis] = -event.jaxis.value / 32767.f;
				break;
			case SDL_JOYBUTTONUP:
			case SDL_JOYBUTTONDOWN:
				if (!joysticks[event.jaxis.which].joystick)
					break;
				joysticks[event.jbutton.which].buttons[event.jbutton.button] = event.jbutton.state != 0;
				break;
			case SDL_JOYHATMOTION:
				if (!joysticks[event.jaxis.which].joystick)
					break;
				joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value;
				break;
		}
	}
}
예제 #15
0
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data,
              const std::vector<PlayerSaveGameData>& player_save_game_data,
              const Universe& universe, const EmpireManager& empire_manager,
              const SpeciesManager& species_manager, const CombatLogManager& combat_log_manager,
              const GalaxySetupData& galaxy_setup_data, bool multiplayer)
{
    DebugLogger() << "SaveGame:: filename: " << filename;
    GetUniverse().EncodingEmpire() = ALL_EMPIRES;

    std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager);
    SaveGamePreviewData save_preview_data;
    CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data);

    try {
        fs::path path = FilenameToPath(filename);
        // A relative path should be relative to the save directory.
        if (path.is_relative()) {
            path = GetSaveDir()/path;
            DebugLogger() << "Made save path relative to save dir. Is now: " << path;
        }

        if (multiplayer) {
            // Make sure the path points into our save directory
            if (!IsInside(path, GetSaveDir())){
                path = GetSaveDir() / path.filename();
            }
        }

        fs::ofstream ofs(path, std::ios_base::binary);

        if (!ofs)
            throw std::runtime_error(UNABLE_TO_OPEN_FILE);

        if (GetOptionsDB().Get<bool>("binary-serialization")) {
            freeorion_bin_oarchive oa(ofs);
            oa << BOOST_SERIALIZATION_NVP(save_preview_data);
            oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            oa << BOOST_SERIALIZATION_NVP(server_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_manager);
            oa << BOOST_SERIALIZATION_NVP(species_manager);
            oa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(oa, universe);
        } else {
            freeorion_xml_oarchive oa(ofs);
            oa << BOOST_SERIALIZATION_NVP(save_preview_data);
            oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            oa << BOOST_SERIALIZATION_NVP(server_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_manager);
            oa << BOOST_SERIALIZATION_NVP(species_manager);
            oa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(oa, universe);
        }
    } catch (const std::exception& e) {
        ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what();
        throw e;
    }
}
예제 #16
0
void HumanClientApp::Autosave() {
    // autosave only on appropriate turn numbers, and when enabled for current
    // game type (single vs. multiplayer)
    int autosave_turns = GetOptionsDB().Get<int>("autosave.turns");
    if (autosave_turns < 1)
        return;     // avoid divide by zero
    if (CurrentTurn() % autosave_turns != 0 && CurrentTurn() != 1)
        return;     // turns divisible by autosave_turns, and first turn, have autosaves done
    if (m_single_player_game && !GetOptionsDB().Get<bool>("autosave.single-player"))
        return;
    if (!m_single_player_game && !GetOptionsDB().Get<bool>("autosave.multiplayer"))
        return;

    const char* legal_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-";

    // get empire name, filtered for filename acceptability
    int client_empire_id = EmpireID();
    const Empire* empire = GetEmpire(client_empire_id);
    std::string empire_name;
    if (empire)
        empire_name = empire->Name();
    else
        empire_name = UserString("OBSERVER");
    std::string::size_type first_good_empire_char = empire_name.find_first_of(legal_chars);
    if (first_good_empire_char == std::string::npos) {
        empire_name.clear();
    } else {
        std::string::size_type first_bad_empire_char = empire_name.find_first_not_of(legal_chars, first_good_empire_char);
        empire_name = empire_name.substr(first_good_empire_char, first_bad_empire_char - first_good_empire_char);
    }

    // get player name, also filtered
    std::string player_name;
    if (empire)
        player_name = empire->PlayerName();
    std::string::size_type first_good_player_char = player_name.find_first_of(legal_chars);
    if (first_good_player_char == std::string::npos) {
        player_name.clear();
    } else {
        std::string::size_type first_bad_player_char = player_name.find_first_not_of(legal_chars, first_good_player_char);
        player_name = player_name.substr(first_good_player_char, first_bad_player_char - first_good_player_char);
    }

    // select filename extension
    std::string extension;
    if (m_single_player_game)
        extension = SP_SAVE_FILE_EXTENSION;
    else
        extension = MP_SAVE_FILE_EXTENSION;

    // Add timestamp to autosave generated files
    std::string datetime_str = FilenameTimestamp();

    boost::filesystem::path autosave_dir_path(GetSaveDir() / "auto");

    std::string save_filename = boost::io::str(boost::format("FreeOrion_%s_%s_%04d_%s%s") % player_name % empire_name % CurrentTurn() % datetime_str % extension);
    boost::filesystem::path save_path(autosave_dir_path / save_filename);
    std::string path_string = PathString(save_path);

    try {
        // ensure autosave directory exists
        if (!exists(autosave_dir_path))
            boost::filesystem::create_directories(autosave_dir_path);
    } catch (const std::exception& e) {
        ErrorLogger() << "Autosave unable to check / create autosave directory: " << e.what();
        std::cerr << "Autosave unable to check / create autosave directory: " << e.what() << std::endl;
    }

    // check for and remove excess oldest autosaves
    int max_autosaves = GetOptionsDB().Get<int>("autosave.limit");
    RemoveOldestFiles(max_autosaves, autosave_dir_path);

    // create new save
    DebugLogger() << "Autosaving to: " << path_string;
    try {
        SaveGame(path_string);
    } catch (const std::exception& e) {
        ErrorLogger() << "Autosave failed: " << e.what();
        std::cerr << "Autosave failed: " << e.what() << std::endl;
    }
}
예제 #17
0
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data,
              const std::vector<PlayerSaveGameData>& player_save_game_data, const Universe& universe,
              const EmpireManager& empire_manager, const SpeciesManager& species_manager,
              const CombatLogManager& combat_log_manager, const GalaxySetupData& galaxy_setup_data,
              bool multiplayer)
{
    ScopedTimer timer("SaveGame: " + filename, true);

    bool use_binary = GetOptionsDB().Get<bool>("binary-serialization");
    DebugLogger() << "SaveGame(" << (use_binary ? "binary" : "zlib-xml") << ") filename: " << filename;
    GetUniverse().EncodingEmpire() = ALL_EMPIRES;

    DebugLogger() << "Compiling save empire and preview data";
    std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager);
    SaveGamePreviewData save_preview_data;
    CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data);


    // reinterpret save game data as header data for uncompressed header
    std::vector<PlayerSaveHeaderData> player_save_header_data;
    for (std::vector<PlayerSaveGameData>::const_iterator it = player_save_game_data.begin();
            it != player_save_game_data.end(); ++it)
    {
        player_save_header_data.push_back(*it);
    }


    try {
        fs::path path = FilenameToPath(filename);
        // A relative path should be relative to the save directory.
        if (path.is_relative()) {
            path = GetSaveDir()/path;
            DebugLogger() << "Made save path relative to save dir. Is now: " << path;
        }

        if (multiplayer) {
            // Make sure the path points into our save directory
            if (!IsInside(path, GetSaveDir())) {
                path = GetSaveDir() / path.filename();
            }
        }

        // set up output archive / stream for saving
        fs::ofstream ofs(path, std::ios_base::binary);
        if (!ofs)
            throw std::runtime_error(UNABLE_TO_OPEN_FILE);

        if (use_binary) {
            DebugLogger() << "Creating binary oarchive";
            freeorion_bin_oarchive boa(ofs);
            boa << BOOST_SERIALIZATION_NVP(save_preview_data);
            boa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            boa << BOOST_SERIALIZATION_NVP(server_save_game_data);
            boa << BOOST_SERIALIZATION_NVP(player_save_header_data);
            boa << BOOST_SERIALIZATION_NVP(empire_save_game_data);

            boa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            boa << BOOST_SERIALIZATION_NVP(empire_manager);
            boa << BOOST_SERIALIZATION_NVP(species_manager);
            boa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(boa, universe);
            DebugLogger() << "Done serializing";

        } else {
            // Two-tier serialization:
            // main archive is uncompressed serialized header data first
            // then contains a string for compressed second archive
            // that contains the main gamestate info


            // allocate buffers for serialized gamestate
            DebugLogger() << "Allocating buffers for XML serialization...";
            std::string serial_str, compressed_str;
            try {
                serial_str.reserve(    std::pow(2.0, 29.0));
                compressed_str.reserve(std::pow(2.0, 26.0));
            } catch (...) {
                DebugLogger() << "Unable to preallocate full serialization buffers. Attempting serialization with dynamic buffer allocation.";
            }

            // wrap buffer string in iostream::stream to receive serialized data
            typedef boost::iostreams::back_insert_device<std::string> InsertDevice;
            InsertDevice serial_inserter(serial_str);
            boost::iostreams::stream<InsertDevice> s_sink(serial_inserter);

            // create archive with (preallocated) buffer...
            freeorion_xml_oarchive xoa(s_sink);
            // serialize main gamestate info
            xoa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            xoa << BOOST_SERIALIZATION_NVP(empire_manager);
            xoa << BOOST_SERIALIZATION_NVP(species_manager);
            xoa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(xoa, universe);
            s_sink.flush();

            // wrap gamestate string in iostream::stream to extract serialized data
            typedef boost::iostreams::basic_array_source<char> SourceDevice;
            SourceDevice source(serial_str.data(), serial_str.size());
            boost::iostreams::stream<SourceDevice> s_source(source);

            // wrap compresed buffer string in iostream::streams to receive compressed string
            InsertDevice compressed_inserter(compressed_str);
            boost::iostreams::stream<InsertDevice> c_sink(compressed_inserter);

            // compression-filter gamestate into compressed string
            boost::iostreams::filtering_ostreambuf o;
            o.push(boost::iostreams::zlib_compressor());
            o.push(c_sink);
            boost::iostreams::copy(s_source, o);
            c_sink.flush();

            // write to save file: uncompressed header serialized data, with compressed main archive string at end...
            freeorion_xml_oarchive xoa2(ofs);
            // serialize uncompressed save header info
            xoa2 << BOOST_SERIALIZATION_NVP(save_preview_data);
            xoa2 << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            xoa2 << BOOST_SERIALIZATION_NVP(server_save_game_data);
            xoa2 << BOOST_SERIALIZATION_NVP(player_save_header_data);
            xoa2 << BOOST_SERIALIZATION_NVP(empire_save_game_data);
            // append compressed gamestate info
            xoa2 << BOOST_SERIALIZATION_NVP(compressed_str);
        }

    } catch (const std::exception& e) {
        ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what();
        throw e;
    }
    DebugLogger() << "SaveGame : Successfully wrote save file";
}
예제 #18
0
bool SavedataParam::Load(SceUtilitySavedataParam *param, const std::string &saveDirName, int saveId, bool secureMode)
{
	if (!param) {
		return false;
	}

	u8 *data_ = param->dataBuf;

	std::string dirPath = GetSaveFilePath(param, GetSaveDir(param, saveDirName));
	if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it
	{
		if (saveDataList[saveId].size == 0) // don't read no existing file
		{
			return false;
		}
	}

	std::string filePath = dirPath+"/"+GetFileName(param);
	s64 readSize;
	INFO_LOG(HLE,"Loading file with size %u in %s",param->dataBufSize,filePath.c_str());
	u8* saveData = 0;
	int saveSize = -1;
	if (!ReadPSPFile(filePath, &saveData, saveSize, &readSize))
	{
		ERROR_LOG(HLE,"Error reading file %s",filePath.c_str());
		return false;
	}
	saveSize = (int)readSize;

	// copy back save name in request
	strncpy(param->saveName, saveDirName.c_str(), 20);

	ParamSFOData sfoFile;
	std::string sfopath = dirPath+"/" + SFO_FILENAME;
	PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
	if(sfoInfo.exists) // Read sfo
	{
		u8 *sfoData = new u8[(size_t)sfoInfo.size];
		size_t sfoSize = (size_t)sfoInfo.size;
		if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL))
		{
			sfoFile.ReadSFO(sfoData,sfoSize);

			// copy back info in request
			strncpy(param->sfoParam.title,sfoFile.GetValueString("TITLE").c_str(),128);
			strncpy(param->sfoParam.savedataTitle,sfoFile.GetValueString("SAVEDATA_TITLE").c_str(),128);
			strncpy(param->sfoParam.detail,sfoFile.GetValueString("SAVEDATA_DETAIL").c_str(),1024);
			param->sfoParam.parentalLevel = sfoFile.GetValueInt("PARENTAL_LEVEL");
		}
		delete[] sfoData;
	}
	// Don't know what it is, but PSP always respond this and this unlock some game
	param->bind = 1021;

	bool isCrypted = IsSaveEncrypted(param, saveDirName) && secureMode;
	bool saveDone = false;
	if(isCrypted)// Try to decrypt
	{
		int align_len = align16(saveSize);
		u8* data_base = new u8[align_len];
		u8* cryptKey = new u8[0x10];
		memset(cryptKey,0,0x10);

		if(param->key[0] != 0)
		{
			memcpy(cryptKey, param->key, 0x10);
		}
		memset(data_base + saveSize, 0, align_len - saveSize);
		memcpy(data_base, saveData, saveSize);

		int decryptMode = 1;
		if(param->key[0] != 0)
		{
			decryptMode = (GetSDKMainVersion(sceKernelGetCompiledSdkVersion()) >= 4 ? 5 : 3);
		}

		if(DecryptSave(decryptMode, data_base, &saveSize, &align_len, ((param->key[0] != 0)?cryptKey:0)) == 0)
		{
			memcpy(data_, data_base, saveSize);
			saveDone = true;
		}
		delete[] data_base;
		delete[] cryptKey;
	}
	if(!saveDone) // not crypted or decrypt fail
	{
		memcpy(data_, saveData, saveSize);
	}
	param->dataSize = (SceSize)saveSize;
	delete[] saveData;

	return true;
}
예제 #19
0
std::string SavedataParam::GetSaveFilePath(SceUtilitySavedataParam* param, int saveId)
{
	return GetSaveFilePath(param, GetSaveDir(param, saveId));
}
예제 #20
0
SaveFileDialog::SaveFileDialog (const std::string& extension, bool load ) :
CUIWnd ( UserString ( "GAME_MENU_SAVE_FILES" ),
         ( GG::GUI::GetGUI()->AppWidth() - SAVE_FILE_DIALOG_WIDTH ) / 2,
         ( GG::GUI::GetGUI()->AppHeight() - SAVE_FILE_DIALOG_HEIGHT ) / 2,
         SAVE_FILE_DIALOG_WIDTH,
         SAVE_FILE_DIALOG_HEIGHT,
         GG::INTERACTIVE | GG::DRAGABLE | GG::MODAL | GG::RESIZABLE ) {
    m_extension = extension;
    m_load_only = load;
    boost::shared_ptr<GG::Font> font = ClientUI::GetFont();
    SetMinSize ( GG::Pt ( 2*SAVE_FILE_DIALOG_MIN_WIDTH, 2*SAVE_FILE_DIALOG_MIN_HEIGHT ) );

    m_layout = new GG::Layout ( GG::X0, GG::Y0,
                                SAVE_FILE_DIALOG_WIDTH - LeftBorder() - RightBorder(),
                                SAVE_FILE_DIALOG_HEIGHT - TopBorder() - BottomBorder(), 3, 4 );
    m_layout->SetCellMargin ( SAVE_FILE_CELL_MARGIN );
    m_layout->SetBorderMargin ( SAVE_FILE_CELL_MARGIN*2 );

    m_file_list = new SaveFileListBox();
    m_file_list->SetStyle ( GG::LIST_SINGLESEL | GG::LIST_SORTDESCENDING );
    m_file_list->SetColHeaders ( new SaveFileRow() );


    m_confirm_btn = new CUIButton ( UserString ( "OK" ) );
    CUIButton* cancel_btn = new CUIButton ( UserString ( "CANCEL" ) );

    m_name_edit = new CUIEdit ( GG::X0, GG::Y0, GG::X1, "", font );
    GG::TextControl* filename_label = new GG::TextControl ( GG::X0, GG::Y0, UserString ( "SAVE_FILENAME" ), font, ClientUI::TextColor() );
    GG::TextControl* directory_label = new GG::TextControl ( GG::X0, GG::Y0, UserString ( "SAVE_DIRECTORY" ), font, ClientUI::TextColor() );
    m_current_dir_edit = new CUIEdit ( GG::X0, GG::Y0, GG::X1, PathString ( GetSaveDir() ), font );
    m_browse_dir_btn = new CUIButton ( "..." );

    m_layout->Add ( m_file_list,    0, 0, 1, 4 );
    m_layout->Add ( filename_label, 1, 0, 1, 1 );
    m_layout->Add ( m_name_edit,    1, 1, 1, 2 );
    m_layout->Add ( m_confirm_btn,    1, 3 );
    m_layout->Add ( directory_label,2, 0 );
    m_layout->Add ( m_current_dir_edit,  2, 1 );
    m_layout->Add ( m_browse_dir_btn,    2, 2 );
    m_layout->Add ( cancel_btn,          2, 3 );


    m_layout->SetRowStretch ( 0, 1.0 );
    m_layout->SetMinimumRowHeight ( 1, font->TextExtent ( m_confirm_btn->Text() ).y );
    m_layout->SetMinimumRowHeight ( 2, font->TextExtent ( cancel_btn->Text() ).y );

    m_layout->SetMinimumColumnWidth ( 0, std::max ( font->TextExtent ( filename_label->Text() ).x,
                                      font->TextExtent ( directory_label->Text() ).x ) );
    m_layout->SetColumnStretch ( 1, 1.0 );
    m_layout->SetMinimumColumnWidth ( 2, m_browse_dir_btn->MinUsableSize().x +
                                      SAVE_FILE_BUTTON_MARGIN*2 );
    m_layout->SetMinimumColumnWidth ( 3, std::max ( m_confirm_btn->MinUsableSize().x,
                                      cancel_btn->MinUsableSize().x ) +
                                      SAVE_FILE_BUTTON_MARGIN );

    SetLayout ( m_layout );

    GG::Connect ( m_confirm_btn->LeftClickedSignal,      &SaveFileDialog::Confirm,           this );
    GG::Connect ( cancel_btn->LeftClickedSignal,         &SaveFileDialog::Cancel,            this );
    GG::Connect ( m_file_list->SelChangedSignal,         &SaveFileDialog::SelectionChanged,  this );
    GG::Connect ( m_file_list->DoubleClickedSignal,      &SaveFileDialog::DoubleClickRow,    this );
    GG::Connect ( m_browse_dir_btn->LeftClickedSignal,   &SaveFileDialog::BrowseDirectories, this );
    GG::Connect ( m_name_edit->EditedSignal,             &SaveFileDialog::FileNameEdited,    this );

    UpdatePreviewList();
    
    if(!m_load_only){
        m_name_edit->SetText(std::string("save-") + FilenameTimestamp());
        m_name_edit->SelectAll();
    }
}
예제 #21
0
bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId)
{
	if (!param) {
		return false;
	}

	std::string dirPath = GetSaveFilePath(param, saveId);

	if (!pspFileSystem.GetFileInfo(dirPath).exists)
		pspFileSystem.MkDir(dirPath);

	if(param->dataBuf != 0)	// Can launch save without save data in mode 13
	{
		std::string filePath = dirPath+"/"+GetFileName(param);
		SceSize saveSize = param->dataSize;
		if(saveSize == 0 || saveSize > param->dataBufSize)
			saveSize = param->dataBufSize; // fallback, should never use this
		INFO_LOG(HLE,"Saving file with size %u in %s",saveSize,filePath.c_str());
		u8 *data_ = (u8*)Memory::GetPointer(param->dataBuf);

		// copy back save name in request
		strncpy(param->saveName,GetSaveDirName(param, saveId).c_str(),20);

		if (!WritePSPFile(filePath, data_, saveSize))
		{
			ERROR_LOG(HLE,"Error writing file %s",filePath.c_str());
			return false;
		}
	}

	// SAVE PARAM.SFO
	ParamSFOData sfoFile;
	std::string sfopath = dirPath+"/"+sfoName;
	PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
	if(sfoInfo.exists) // Read old sfo if exist
	{
		u8 *sfoData = new u8[(size_t)sfoInfo.size];
		size_t sfoSize = (size_t)sfoInfo.size;
		if(ReadPSPFile(sfopath,sfoData,sfoSize, NULL))
		{
			sfoFile.ReadSFO(sfoData,sfoSize);
			delete[] sfoData;
		}
	}

	// Update values
	sfoFile.SetValue("TITLE",param->sfoParam.title,128);
	sfoFile.SetValue("SAVEDATA_TITLE",param->sfoParam.savedataTitle,128);
	sfoFile.SetValue("SAVEDATA_DETAIL",param->sfoParam.detail,1024);
	sfoFile.SetValue("PARENTAL_LEVEL",param->sfoParam.parentalLevel,4);
	sfoFile.SetValue("CATEGORY","MS",4);
	sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64);

	// For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding
	const int FILE_LIST_ITEM_SIZE = 13 + 16 + 3;
	const int FILE_LIST_COUNT_MAX = 99;
	const int FILE_LIST_TOTAL_SIZE = FILE_LIST_ITEM_SIZE * FILE_LIST_COUNT_MAX;
	u32 tmpDataSize = 0;
	u8* tmpDataOrig = sfoFile.GetValueData("SAVEDATA_FILE_LIST", &tmpDataSize);
	u8* tmpData = new u8[FILE_LIST_TOTAL_SIZE];

	if (tmpDataOrig != NULL)
		memcpy(tmpData, tmpDataOrig, tmpDataSize > FILE_LIST_TOTAL_SIZE ? FILE_LIST_TOTAL_SIZE : tmpDataSize);
	else
		memset(tmpData, 0, FILE_LIST_TOTAL_SIZE);

	if (param->dataBuf != 0)
	{
		char *fName = (char*)tmpData;
		for(int i = 0; i < FILE_LIST_COUNT_MAX; i++)
		{
			if(fName[0] == 0)
				break; // End of list
			if(strncmp(fName,GetFileName(param).c_str(),20) == 0)
				break; // File already in SFO

			fName += FILE_LIST_ITEM_SIZE;
		}

		if (fName + 20 <= (char*)tmpData + FILE_LIST_TOTAL_SIZE)
			snprintf(fName, 20, "%s",GetFileName(param).c_str());
	}
	sfoFile.SetValue("SAVEDATA_FILE_LIST", tmpData, FILE_LIST_TOTAL_SIZE, FILE_LIST_TOTAL_SIZE);
	delete[] tmpData;

	// No crypted save, so fill with 0
	tmpData = new u8[128];
	memset(tmpData, 0, 128);
	sfoFile.SetValue("SAVEDATA_PARAMS", tmpData, 128, 128);
	delete[] tmpData;

	u8 *sfoData;
	size_t sfoSize;
	sfoFile.WriteSFO(&sfoData,&sfoSize);
	WritePSPFile(sfopath, sfoData, (SceSize)sfoSize);
	delete[] sfoData;

	// SAVE ICON0
	if (param->icon0FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->icon0FileData.buf);
		std::string icon0path = dirPath+"/"+icon0Name;
		WritePSPFile(icon0path, data_, param->icon0FileData.bufSize);
	}
	// SAVE ICON1
	if (param->icon1FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->icon1FileData.buf);
		std::string icon1path = dirPath+"/"+icon1Name;
		WritePSPFile(icon1path, data_, param->icon1FileData.bufSize);
	}
	// SAVE PIC1
	if (param->pic1FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->pic1FileData.buf);
		std::string pic1path = dirPath+"/"+pic1Name;
		WritePSPFile(pic1path, data_, param->pic1FileData.bufSize);
	}

	// Save SND
	if (param->snd0FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->snd0FileData.buf);
		std::string snd0path = dirPath+"/"+snd0Name;
		WritePSPFile(snd0path, data_, param->snd0FileData.bufSize);
	}

	// Save Encryption Data
	{
		EncryptFileInfo encryptInfo;
		SceSize dataSize = sizeof(encryptInfo); // version + key + sdkVersion
		memset(&encryptInfo,0,dataSize);

		encryptInfo.fileVersion = 1;
		encryptInfo.sdkVersion = sceKernelGetCompiledSdkVersion();
		if(param->size > 1500)
			memcpy(encryptInfo.key,param->key,16);

		std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN";
		WritePSPFile(encryptInfoPath, (u8*)&encryptInfo, dataSize);
	}
	return true;
}
예제 #22
0
파일: Pi.cpp 프로젝트: robothauler/pioneer
void Pi::HandleKeyDown(SDL_Keysym *key)
{
	if (key->sym == SDLK_ESCAPE) {
		if (Pi::game) {
			// only accessible once game started
			HandleEscKey();
		}
		return;
	}
	const bool CTRL = input.KeyState(SDLK_LCTRL) || input.KeyState(SDLK_RCTRL);

	// special keys.
	if (CTRL) {
		switch (key->sym) {
		case SDLK_q: // Quit
			Pi::RequestQuit();
			break;
		case SDLK_PRINTSCREEN: // print
		case SDLK_KP_MULTIPLY: // screen
		{
			char buf[256];
			const time_t t = time(0);
			struct tm *_tm = localtime(&t);
			strftime(buf, sizeof(buf), "screenshot-%Y%m%d-%H%M%S.png", _tm);
			Graphics::ScreendumpState sd;
			Pi::renderer->Screendump(sd);
			write_screenshot(sd, buf);
			break;
		}

		case SDLK_SCROLLLOCK: // toggle video recording
			Pi::isRecordingVideo = !Pi::isRecordingVideo;
			if (Pi::isRecordingVideo) {
				char videoName[256];
				const time_t t = time(0);
				struct tm *_tm = localtime(&t);
				strftime(videoName, sizeof(videoName), "pioneer-%Y%m%d-%H%M%S", _tm);
				const std::string dir = "videos";
				FileSystem::userFiles.MakeDirectory(dir);
				const std::string fname = FileSystem::JoinPathBelow(FileSystem::userFiles.GetRoot() + "/" + dir, videoName);
				Output("Video Recording started to %s.\n", fname.c_str());
				// start ffmpeg telling it to expect raw rgba 720p-60hz frames
				// -i - tells it to read frames from stdin
				// if given no frame rate (-r 60), it will just use vfr
				char cmd[256] = { 0 };
				snprintf(cmd, sizeof(cmd), "ffmpeg -f rawvideo -pix_fmt rgba -s %dx%d -i - -threads 0 -preset fast -y -pix_fmt yuv420p -crf 21 -vf vflip %s.mp4", config->Int("ScrWidth"), config->Int("ScrHeight"), fname.c_str());

				// open pipe to ffmpeg's stdin in binary write mode
#if defined(_MSC_VER) || defined(__MINGW32__)
				Pi::ffmpegFile = _popen(cmd, "wb");
#else
				Pi::ffmpegFile = _popen(cmd, "w");
#endif
			} else {
				Output("Video Recording ended.\n");
				if (Pi::ffmpegFile != nullptr) {
					_pclose(Pi::ffmpegFile);
					Pi::ffmpegFile = nullptr;
				}
			}
			break;
#if WITH_DEVKEYS
		case SDLK_i: // Toggle Debug info
			Pi::showDebugInfo = !Pi::showDebugInfo;
			break;

#ifdef PIONEER_PROFILER
		case SDLK_p: // alert it that we want to profile
			if (input.KeyState(SDLK_LSHIFT) || input.KeyState(SDLK_RSHIFT))
				Pi::doProfileOne = true;
			else {
				Pi::doProfileSlow = !Pi::doProfileSlow;
				Output("slow frame profiling %s\n", Pi::doProfileSlow ? "enabled" : "disabled");
			}
			break;
#endif

		case SDLK_F12: {
			if (Pi::game) {
				vector3d dir = -Pi::player->GetOrient().VectorZ();
				/* add test object */
				if (input.KeyState(SDLK_RSHIFT)) {
					Missile *missile =
						new Missile(ShipType::MISSILE_GUIDED, Pi::player);
					missile->SetOrient(Pi::player->GetOrient());
					missile->SetFrame(Pi::player->GetFrame());
					missile->SetPosition(Pi::player->GetPosition() + 50.0 * dir);
					missile->SetVelocity(Pi::player->GetVelocity());
					game->GetSpace()->AddBody(missile);
					missile->AIKamikaze(Pi::player->GetCombatTarget());
				} else if (input.KeyState(SDLK_LSHIFT)) {
					SpaceStation *s = static_cast<SpaceStation *>(Pi::player->GetNavTarget());
					if (s) {
						Ship *ship = new Ship(ShipType::POLICE);
						int port = s->GetFreeDockingPort(ship);
						if (port != -1) {
							Output("Putting ship into station\n");
							// Make police ship intent on killing the player
							ship->AIKill(Pi::player);
							ship->SetFrame(Pi::player->GetFrame());
							ship->SetDockedWith(s, port);
							game->GetSpace()->AddBody(ship);
						} else {
							delete ship;
							Output("No docking ports free dude\n");
						}
					} else {
						Output("Select a space station...\n");
					}
				} else {
					Ship *ship = new Ship(ShipType::POLICE);
					if (!input.KeyState(SDLK_LALT)) { //Left ALT = no AI
						if (!input.KeyState(SDLK_LCTRL))
							ship->AIFlyTo(Pi::player); // a less lethal option
						else
							ship->AIKill(Pi::player); // a really lethal option!
					}
					lua_State *l = Lua::manager->GetLuaState();
					pi_lua_import(l, "Equipment");
					LuaTable equip(l, -1);
					LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("laser").Sub("pulsecannon_dual_1mw"));
					LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("misc").Sub("laser_cooling_booster"));
					LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("misc").Sub("atmospheric_shielding"));
					lua_pop(l, 5);
					ship->SetFrame(Pi::player->GetFrame());
					ship->SetPosition(Pi::player->GetPosition() + 100.0 * dir);
					ship->SetVelocity(Pi::player->GetVelocity());
					ship->UpdateEquipStats();
					game->GetSpace()->AddBody(ship);
				}
			}
			break;
		}
#endif /* DEVKEYS */
#if WITH_OBJECTVIEWER
		case SDLK_F10:
			Pi::SetView(Pi::game->GetObjectViewerView());
			break;
#endif
		case SDLK_F11:
			// XXX only works on X11
			//SDL_WM_ToggleFullScreen(Pi::scrSurface);
#if WITH_DEVKEYS
			renderer->ReloadShaders();
#endif
			break;
		case SDLK_F9: // Quicksave
		{
			if (Pi::game) {
				if (Pi::game->IsHyperspace())
					Pi::game->log->Add(Lang::CANT_SAVE_IN_HYPERSPACE);

				else {
					const std::string name = "_quicksave";
					const std::string path = FileSystem::JoinPath(GetSaveDir(), name);
					try {
						Game::SaveGame(name, Pi::game);
						Pi::game->log->Add(Lang::GAME_SAVED_TO + path);
					} catch (CouldNotOpenFileException) {
						Pi::game->log->Add(stringf(Lang::COULD_NOT_OPEN_FILENAME, formatarg("path", path)));
					} catch (CouldNotWriteToFileException) {
						Pi::game->log->Add(Lang::GAME_SAVE_CANNOT_WRITE);
					}
				}
			}
			break;
		}
		default:
			break; // This does nothing but it stops the compiler warnings
		}
	}
}
예제 #23
0
void render_window()
{
    game_config = GetGameConfig();
    game_levels = GetGameLevels();
    game_levels_count = GetGameLevelsCount();

    arguments = GetArguments();
    user_set = GetUserSettings();
    int start_level = get_start_level();

    save_dir_full = GetSaveDir();
    cache_dir_full = GetCacheDir();
    can_cache = (save_dir_full && cache_dir_full);

//------------------------------------------------------------------------------
    ApplyArguments();

    const SDL_VideoInfo *video_info = SDL_GetVideoInfo();
    if (user_set->geom_x > 0 && user_set->geom_y > 0)
    {
        disp_x = user_set->geom_x;
        disp_y = user_set->geom_y;
    }
    else
    {
        disp_x = video_info->current_w;
        disp_y = video_info->current_h;
    }

    int probe_bpp = (user_set->bpp == 0 ? video_info->vfmt->BitsPerPixel : user_set->bpp);
    disp_bpp = (probe_bpp == 32 ? probe_bpp : 16);

    bool rot = TransformGeom();

//------------------------------------------------------------------------------
#define BTN_SPACE_KOEF 4.5
    int btn_side = disp_y / 7;
    int btn_space = btn_side / BTN_SPACE_KOEF;
    int btns_padded_width = btn_side * 4 + btn_space * 5;
    if (btns_padded_width > disp_x)
    {
        //btn_side = ( wnd_w - 5 * ( btn_side / BTN_SPACE_KOEF ) ) / 4
        btn_side = (int)(disp_x / (4 + 5 / BTN_SPACE_KOEF));
        btn_space = btn_side / BTN_SPACE_KOEF;
    }
    int btns_width = btn_side * 4 + btn_space * 3;
    int font_height = btn_side / 3;
    int font_padding = font_height / 2;

//-- font and labels -----------------------------------------------------------
    TTF_Font *font = TTF_OpenFont(DEFAULT_FONT_FILE, font_height);
    if (!font)
    {
        log_error("Can't load font '%s'. Exiting.", DEFAULT_FONT_FILE);
        return;
    }

    SDL_Surface *levelTextSurface = NULL;
    SDL_Rect levelTextLocation;
    levelTextLocation.y = font_padding;

    SDL_Color fontColor = {0};
#ifndef RGBSWAP
    fontColor.r = 231;
    fontColor.g = 190;
    fontColor.b = 114;
#else
    //--enable-rgb-swap
    fontColor.r = 114;
    fontColor.g = 190;
    fontColor.b = 231;
#endif

    /* Window initialization */
    ingame = true;
    Uint32 sdl_flags = SDL_SWSURFACE;
    if (user_set->fullscreen_mode != FULLSCREEN_NONE)
        sdl_flags |= SDL_FULLSCREEN;
    SDL_Surface *disp = SDL_SetVideoMode(disp_x, disp_y, disp_bpp, sdl_flags);
    if (disp == NULL)
    {
        log_error("Can't set video mode %dx%dx%dbpp. Exiting.", disp_x, disp_y, disp_bpp);
        return;
    }
    screen = disp;
    SDL_Surface *gui_surface = disp;
    SDL_WM_SetCaption("Mokomaze", "Mokomaze");

    /* Draw loading screen */
    SDL_Color whiteColor = {0};
    whiteColor.r = whiteColor.g = whiteColor.b = 255;
    SDL_Surface *titleSurface = TTF_RenderText_Blended(font, "Loading...", whiteColor);
    SDL_Rect title_rect;
    title_rect.x = (disp_x - titleSurface->w) / 2;
    title_rect.y = (disp_y - titleSurface->h) / 2;
    title_rect.w = titleSurface->w;
    title_rect.h = titleSurface->h;
    SDL_BlitSurface(titleSurface, NULL, screen, &title_rect);
    SDL_UpdateRect(screen, title_rect.x, title_rect.y, title_rect.w, title_rect.h);
    SDL_FreeSurface(titleSurface);

//-- load pictures -------------------------------------------------------------
    SDL_Surface *back_pic     = LoadSvg(MDIR "prev-main.svg", btn_side, btn_side, false, false);
    SDL_Surface *forward_pic  = LoadSvg(MDIR "next-main.svg", btn_side, btn_side, false, false);
    SDL_Surface *settings_pic = LoadSvg(MDIR "settings-main.svg", btn_side, btn_side, false, false);
    SDL_Surface *exit_pic     = LoadSvg(MDIR "close-main.svg", btn_side, btn_side, false, false);

    SDL_Surface *back_i_pic    = LoadSvg(MDIR "prev-grey.svg", btn_side, btn_side, false, false);
    SDL_Surface *forward_i_pic = LoadSvg(MDIR "next-grey.svg", btn_side, btn_side, false, false);

    SDL_Surface *back_p_pic    = LoadSvg(MDIR "prev-light.svg", btn_side, btn_side, false, false);
    SDL_Surface *forward_p_pic = LoadSvg(MDIR "next-light.svg", btn_side, btn_side, false, false);

    int tmpx = (rot ? game_config.wnd_h : game_config.wnd_w);
    int tmpy = (rot ? game_config.wnd_w : game_config.wnd_h);
    desk_pic = LoadSvg(MDIR "desk.svg", tmpx, tmpy, rot, true);
    wall_pic = LoadSvg(MDIR "wall.svg", tmpx, tmpy, rot, true);
    int hole_d = game_config.hole_r * 2;
    fin_pic = LoadSvg(MDIR "openmoko.svg", hole_d, hole_d, rot, false);

    if (LoadImgErrors > 0)
    {
        log_error("Some images were not loaded. Exiting.");
        return;
    }

//-- positions of buttons ------------------------------------------------------
    SDL_Rect gui_rect_1, gui_rect_2, gui_rect_3, gui_rect_4;
    gui_rect_1.y = gui_rect_2.y = gui_rect_3.y = gui_rect_4.y = levelTextLocation.y + font_height + font_padding;
    gui_rect_1.x = (disp_x - btns_width) / 2;
    gui_rect_2.x = gui_rect_1.x + btn_side + btn_space;
    gui_rect_3.x = gui_rect_2.x + btn_side + btn_space;
    gui_rect_4.x = gui_rect_3.x + btn_side + btn_space;
//-- for click detection -------------------------------------------------------
    Box gui_box_1, gui_box_2, gui_box_3, gui_box_4;
    gui_box_1.x1 = gui_rect_1.x;
    gui_box_1.y1 = gui_rect_1.y;
    gui_box_1.x2 = gui_rect_1.x + btn_side;
    gui_box_1.y2 = gui_rect_1.y + btn_side;
    gui_box_2.x1 = gui_rect_2.x;
    gui_box_2.y1 = gui_rect_2.y;
    gui_box_2.x2 = gui_rect_2.x + btn_side;
    gui_box_2.y2 = gui_rect_2.y + btn_side;
    gui_box_3.x1 = gui_rect_3.x;
    gui_box_3.y1 = gui_rect_3.y;
    gui_box_3.x2 = gui_rect_3.x + btn_side;
    gui_box_3.y2 = gui_rect_3.y + btn_side;
    gui_box_4.x1 = gui_rect_4.x;
    gui_box_4.y1 = gui_rect_4.y;
    gui_box_4.x2 = gui_rect_4.x + btn_side;
    gui_box_4.y2 = gui_rect_4.y + btn_side;

    //create surface for rendering the level
    render_pic = CreateSurface(SDL_SWSURFACE, game_config.wnd_w, game_config.wnd_h, disp);

    if (user_set->scrolling)
        screen = CreateSurface(SDL_SWSURFACE, game_config.wnd_w, game_config.wnd_h, disp);

    if (user_set->fullscreen_mode != FULLSCREEN_NONE)
        SDL_ShowCursor(!ingame);

    desk_rect.x = 0;
    desk_rect.y = 0;
    desk_rect.w = game_config.wnd_w;
    desk_rect.h = game_config.wnd_h;

    SDL_Rect ball_rect;

    int disp_scroll_border = min(disp_x, disp_y) * 0.27;
    SDL_Rect screen_rect;
    screen_rect.x = 0;
    screen_rect.y = 0;
    screen_rect.w = disp_x;
    screen_rect.h = disp_y;
    SDL_Rect disp_rect;
    disp_rect = screen_rect;

    SDL_Color ballColor = {0};
    ballColor.r = 255;
    ballColor.g = 127;
    ballColor.b = 0;

    User user_set_new = *user_set;
    bool video_set_modified = false;

    /* Settings window initialization */
    settings_init(disp, font_height, user_set, &user_set_new);

    /* Render initialization */
    InitRender();

    /* Input system initialization */
    input_get_dummy(&input);
    SetInput();

    /* Vibro system initialization */
    vibro_get_dummy(&vibro);
    SetVibro();

    /* MazeCore initialization */
    maze_init();
    maze_set_config(game_config);
    maze_set_vibro_callback(BumpVibrate);
    maze_set_levels_data(game_levels, game_levels_count);

    cur_level = start_level;
    RenderLevel();
    RedrawDesk();
    maze_set_level(cur_level);
    ResetPrevPos();

    SDL_Event event;
    bool done = false;
    bool redraw_all = true;
    bool ingame_changed = false;
    int prev_ticks = SDL_GetTicks();
    Point mouse = {0};

//== Game Loop =================================================================
    while (!done)
    {
        bool wasclick = false;
        bool show_settings = false;
        while (SDL_PollEvent(&event))
        {
            bool btndown = false;
            bool btnesc = false;
            if (event.type == SDL_QUIT)
            {
                done = true;
            }
            else if (event.type == SDL_ACTIVEEVENT)
            {
                int g = event.active.gain;
                int s = event.active.state;
                if (ingame && !g && ((s & SDL_APPINPUTFOCUS) || (s & SDL_APPACTIVE)))
                {
                    btndown = true;
                }
            }
            else if (event.type == SDL_MOUSEMOTION)
            {
                mouse.x = event.motion.x;
                mouse.y = event.motion.y;
            }
            else if (event.type == SDL_MOUSEBUTTONUP)
            {
                StopFastChange();
            }
            else if (event.type == SDL_MOUSEBUTTONDOWN)
            {
                btndown = true;
            }
            else if (event.type == SDL_KEYDOWN)
            {
                switch(event.key.keysym.sym)
                {
                case SDLK_q:
                case SDLK_ESCAPE:
                    btnesc = true;
                case SDLK_SPACE:
                case SDLK_p:
                case SDLK_PAUSE:
                    btndown = true;
                    break;
                default:
                    break;
                }
            }
            else if (event.type == SDL_KEYUP)
            {
                switch(event.key.keysym.sym)
                {
                case SDLK_q:
                case SDLK_ESCAPE:
                    if( !wasclick || ingame || show_settings )
                        StopFastChange();
                    else
                        done = true;
                    break;
                case SDLK_SPACE:
                case SDLK_p:
                case SDLK_PAUSE:
                    StopFastChange();
                    break;
                default:
                    break;
                }
            }

            if (btndown)
            {
                if (!ingame)
                {
                    if (inbox(mouse.x, mouse.y, gui_box_1) && !btnesc)
                    {
                        if (cur_level > 0)
                        {
                            SDL_BlitSurface(back_p_pic, NULL, gui_surface, &gui_rect_1);
                            SDL_UpdateRect(gui_surface, gui_rect_1.x, gui_rect_1.y, gui_rect_1.w, gui_rect_1.h);

                            ChangeLevel(cur_level-1, &redraw_all, &wasclick);

                            fastchange_step = -10;
                            StopFastChange();
                            fastchange_timer = SDL_AddTimer(FASTCHANGE_INTERVAL, fastchange_callback, NULL);
                        }
                        continue;
                    }
                    else if (inbox(mouse.x, mouse.y, gui_box_2) && !btnesc)
                    {
                        if (cur_level < game_levels_count - 1)
                        {
                            SDL_BlitSurface(forward_p_pic, NULL, gui_surface, &gui_rect_2);
                            SDL_UpdateRect(gui_surface, gui_rect_2.x, gui_rect_2.y, gui_rect_2.w, gui_rect_2.h);

                            ChangeLevel(cur_level+1, &redraw_all, &wasclick);

                            fastchange_step = +10;
                            StopFastChange();
                            fastchange_timer = SDL_AddTimer(FASTCHANGE_INTERVAL, fastchange_callback, NULL);
                        }
                        continue;
                    }
                    else if (inbox(mouse.x, mouse.y, gui_box_3) && !btnesc)
                    {
                        show_settings = true;
                        RedrawDesk();
                        redraw_all = true;
                        wasclick = true;
                        continue;
                    }
                    else if (inbox(mouse.x, mouse.y, gui_box_4) || btnesc)
                    {
                        done = true;
                        continue;
                    }
                }
                ingame_changed = true;
            } //if (btndown)
        }

        if (ingame_changed)
        {
            ingame = !ingame;
            if (!ingame)
            {
                wasclick = true;
            }
            else
            {
                RedrawDesk();
                redraw_all = true;
            }

            if (user_set->fullscreen_mode == FULLSCREEN_INGAME)
                SDL_WM_ToggleFullScreen(disp);
            if (user_set->fullscreen_mode != FULLSCREEN_NONE)
                SDL_ShowCursor(!ingame);

            prev_ticks = SDL_GetTicks();
            ingame_changed = false;
        }

        if ((!ingame) && (!wasclick) && (must_fastchange))
        {
            int new_cur_level = cur_level + fastchange_dostep;
            clamp_max(new_cur_level, game_levels_count - 1);
            clamp_min(new_cur_level, 0);

            if (new_cur_level != cur_level)
            {
                if (fastchange_dostep < 0)
                {
                    SDL_BlitSurface(back_p_pic, NULL, gui_surface, &gui_rect_1);
                    SDL_UpdateRect(gui_surface, gui_rect_1.x, gui_rect_1.y, gui_rect_1.w, gui_rect_1.h);
                }
                else
                {
                    SDL_BlitSurface(forward_p_pic, NULL, gui_surface, &gui_rect_2);
                    SDL_UpdateRect(gui_surface, gui_rect_2.x, gui_rect_2.y, gui_rect_2.w, gui_rect_2.h);
                }

                ChangeLevel(new_cur_level, &redraw_all, &wasclick);
            }
            must_fastchange = false;
        }

        if (!ingame && !wasclick)
        {
            SDL_Delay(user_set->frame_delay);
            continue;
        }

//-- physics step --------------------------------------------------------------
        int ticks = SDL_GetTicks();
        int delta_ticks = ticks - prev_ticks;
        prev_ticks = ticks;
        clamp_min(delta_ticks, 1);
        clamp_max(delta_ticks, 1000 / 15);

        float acx = 0, acy = 0;
        input.read(&acx, &acy, NULL);
        if (input_cal_cycle)
            input_cal_cycle = (input_calibration_sample(&user_set->input_calibration_data, &acx, &acy, NULL) < MAX_CALIBRATION_SAMPLES);
        input_calibration_adjust(&user_set->input_calibration_data, &acx, &acy, NULL);
        maze_set_speed(user_set->ball_speed);
        maze_set_tilt(acx, acy, 0);
        GameState game_state = maze_step(delta_ticks);

        const dReal *R;
        int tk_px, tk_py, tk_pz;
        maze_get_ball(&tk_px, &tk_py, &tk_pz, &R);
        maze_get_animations(&keys_anim, &final_anim);
//------------------------------------------------------------------------------

        //restore the background
        ball_rect.w = game_config.ball_r * 2;
        ball_rect.h = game_config.ball_r * 2; //
        ball_rect.x = prev_px - game_config.ball_r;
        ball_rect.y = prev_py - game_config.ball_r;
        SDL_BlitSurface(render_pic, &ball_rect, screen, &ball_rect);

        UpdateBufAnimation();
        DrawBall(tk_px, tk_py, tk_pz, R, ballColor);

        //update the screen
        if (!redraw_all && !user_set->scrolling)
        {
            int min_px, max_px;
            int min_py, max_py;
            if (prev_px <= tk_px)
            {
                min_px = prev_px;
                max_px = tk_px;
            }
            else
            {
                min_px = tk_px;
                max_px = prev_px;
            }

            if (prev_py <= tk_py)
            {
                min_py = prev_py;
                max_py = tk_py;
            }
            else
            {
                min_py = tk_py;
                max_py = prev_py;
            }
            min_px -= game_config.ball_r;
            max_px += game_config.ball_r;
            min_py -= game_config.ball_r;
            max_py += game_config.ball_r;
            clamp_min(min_px, 0);
            clamp_max(max_px, game_config.wnd_w - 1);
            clamp_min(min_py, 0);
            clamp_max(max_py, game_config.wnd_h - 1);
            SDL_UpdateRect(screen, min_px, min_py, max_px - min_px, max_py - min_py);
            UpdateScreenAnimation();
        }

        if (user_set->scrolling)
        {
            clamp_min(screen_rect.x, tk_px - disp_x + disp_scroll_border);
            clamp_max(screen_rect.x, tk_px - disp_scroll_border);
            clamp_min(screen_rect.y, tk_py - disp_y + disp_scroll_border);
            clamp_max(screen_rect.y, tk_py - disp_scroll_border);
            clamp(screen_rect.x, 0, game_config.wnd_w - disp_x);
            clamp(screen_rect.y, 0, game_config.wnd_h - disp_y);
            SDL_BlitSurface(screen, &screen_rect, disp, &disp_rect);
        }

        prev_px = tk_px;
        prev_py = tk_py;

//-- GUI -----------------------------------------------------------------------
        if (wasclick && !ingame && !show_settings)
        {
            char txt[32];
            sprintf(txt, "Level %d/%d", cur_level + 1, game_levels_count);
            SDL_FreeSurface(levelTextSurface);
            levelTextSurface = TTF_RenderText_Blended(font, txt, fontColor);
            levelTextLocation.x = (disp_x - levelTextSurface->w) / 2;
            SDL_BlitSurface(levelTextSurface, NULL, gui_surface, &levelTextLocation);

            if (cur_level > 0)
                SDL_BlitSurface(back_pic, NULL, gui_surface, &gui_rect_1);
            else
                SDL_BlitSurface(back_i_pic, NULL, gui_surface, &gui_rect_1);

            if (cur_level < game_levels_count - 1)
                SDL_BlitSurface(forward_pic, NULL, gui_surface, &gui_rect_2);
            else
                SDL_BlitSurface(forward_i_pic, NULL, gui_surface, &gui_rect_2);

            SDL_BlitSurface(settings_pic, NULL, gui_surface, &gui_rect_3);
            SDL_BlitSurface(exit_pic, NULL, gui_surface, &gui_rect_4);
            redraw_all = true;
        }
//------------------------------------------------------------------------------

        //update the whole screen if needed
        if (user_set->scrolling)
        {
            SDL_Flip(disp);
        }
        else if (redraw_all)
        {
            SDL_Flip(screen);
        }
        redraw_all = false;

        if (show_settings)
        {
            bool _video_set_modified = false;
            bool _input_set_modified = false;
            bool _vibro_set_modified = false;
            settings_show(&input_cal_cycle, &_video_set_modified, &_input_set_modified, &_vibro_set_modified);
            if (input_cal_cycle)
                input_calibration_reset();
            if (_video_set_modified)
                video_set_modified = true;
            if (_input_set_modified)
                SetInput();
            if (_vibro_set_modified)
                SetVibro();
            SDL_GetMouseState(&mouse.x, &mouse.y);
            ingame_changed = true;
        }

        switch (game_state)
        {
        case GAME_STATE_FAILED:
            RedrawDesk();
            maze_restart_level();
            ResetPrevPos();
            redraw_all = true;
            break;
        case GAME_STATE_SAVED:
            RedrawDesk();
            maze_reload_level();
            ResetPrevPos();
            redraw_all = true;
            break;
        case GAME_STATE_WIN:
            if (++cur_level >= game_levels_count) cur_level=0;
            RenderLevel();
            RedrawDesk();
            maze_set_level(cur_level);
            ResetPrevPos();
            redraw_all = true;
            break;
        default:
            break;
        }

        SDL_Delay(user_set->frame_delay);
    }
//==============================================================================

    if (video_set_modified)
    {
        user_set->scrolling = user_set_new.scrolling;
        user_set->geom_x = user_set_new.geom_x;
        user_set->geom_y = user_set_new.geom_y;
        user_set->bpp = user_set_new.bpp;
        user_set->fullscreen_mode = user_set_new.fullscreen_mode;
        user_set->frame_delay = user_set_new.frame_delay;
    }

    user_set->level = cur_level + 1;
    SaveUserSettings();

    settings_shutdown();

    SDL_FreeSurface(levelTextSurface);
    TTF_CloseFont(font);
    vibro.shutdown();
    input.shutdown();
}
예제 #24
0
bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId)
{
	if (!param) {
		return false;
	}

	std::string dirPath = GetSaveFilePath(param, saveId);

	if (!pspFileSystem.GetFileInfo(dirPath).exists)
		pspFileSystem.MkDir(dirPath);

	u8* cryptedData = 0;
	int cryptedSize = 0;
	u8 cryptedHash[0x10];
	memset(cryptedHash,0,0x10);
	// Encrypt save.
	if(param->dataBuf != 0 && g_Config.bEncryptSave)
	{
		cryptedSize = param->dataSize;
		if(cryptedSize == 0 || (SceSize)cryptedSize > param->dataBufSize)
			cryptedSize = param->dataBufSize; // fallback, should never use this
		u8* data_ = (u8*)Memory::GetPointer(param->dataBuf);

		int aligned_len = align16(cryptedSize);
		cryptedData = new u8[aligned_len + 0x10];
		memcpy(cryptedData, data_, cryptedSize);

		int decryptMode = 1;
		if(param->key[0] != 0)
		{
			decryptMode = (GetSDKMainVersion(sceKernelGetCompiledSdkVersion()) >= 4 ? 5 : 3);
		}

		if(EncryptData(decryptMode, cryptedData, &cryptedSize, &aligned_len, cryptedHash, ((param->key[0] != 0)?param->key:0)) == 0)
		{
		}
		else
		{
			ERROR_LOG(HLE,"Save encryption failed. This save won't work on real PSP");
			delete[] cryptedData;
			cryptedData = 0;
		}
	}

	// SAVE PARAM.SFO
	ParamSFOData sfoFile;
	std::string sfopath = dirPath+"/"+sfoName;
	PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
	if(sfoInfo.exists) // Read old sfo if exist
	{
		u8 *sfoData = new u8[(size_t)sfoInfo.size];
		size_t sfoSize = (size_t)sfoInfo.size;
		if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL))
		{
			sfoFile.ReadSFO(sfoData,sfoSize);
			delete[] sfoData;
		}
	}

	// Update values
	sfoFile.SetValue("TITLE",param->sfoParam.title,128);
	sfoFile.SetValue("SAVEDATA_TITLE",param->sfoParam.savedataTitle,128);
	sfoFile.SetValue("SAVEDATA_DETAIL",param->sfoParam.detail,1024);
	sfoFile.SetValue("PARENTAL_LEVEL",param->sfoParam.parentalLevel,4);
	sfoFile.SetValue("CATEGORY","MS",4);
	sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64);

	// For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding
	const int FILE_LIST_ITEM_SIZE = 13 + 16 + 3;
	const int FILE_LIST_COUNT_MAX = 99;
	const int FILE_LIST_TOTAL_SIZE = FILE_LIST_ITEM_SIZE * FILE_LIST_COUNT_MAX;
	u32 tmpDataSize = 0;
	u8* tmpDataOrig = sfoFile.GetValueData("SAVEDATA_FILE_LIST", &tmpDataSize);
	u8* tmpData = new u8[FILE_LIST_TOTAL_SIZE];

	if (tmpDataOrig != NULL)
		memcpy(tmpData, tmpDataOrig, tmpDataSize > FILE_LIST_TOTAL_SIZE ? FILE_LIST_TOTAL_SIZE : tmpDataSize);
	else
		memset(tmpData, 0, FILE_LIST_TOTAL_SIZE);

	if (param->dataBuf != 0)
	{
		char *fName = (char*)tmpData;
		for(int i = 0; i < FILE_LIST_COUNT_MAX; i++)
		{
			if(fName[0] == 0)
				break; // End of list
			if(strncmp(fName,GetFileName(param).c_str(),20) == 0)
				break;
			fName += FILE_LIST_ITEM_SIZE;
		}

		if (fName + 13 <= (char*)tmpData + FILE_LIST_TOTAL_SIZE)
			snprintf(fName, 13, "%s",GetFileName(param).c_str());
		if (fName + 13 + 16 <= (char*)tmpData + FILE_LIST_TOTAL_SIZE)
			memcpy(fName+13, cryptedHash, 16);
	}
	sfoFile.SetValue("SAVEDATA_FILE_LIST", tmpData, FILE_LIST_TOTAL_SIZE, FILE_LIST_TOTAL_SIZE);
	delete[] tmpData;

	// Init param with 0. This will be used to detect crypted save or not on loading
	tmpData = new u8[128];
	memset(tmpData, 0, 128);
	sfoFile.SetValue("SAVEDATA_PARAMS", tmpData, 128, 128);
	delete[] tmpData;

	u8 *sfoData;
	size_t sfoSize;
	sfoFile.WriteSFO(&sfoData,&sfoSize);

	// Calc SFO hash for PSP.
	if(cryptedData != 0)
	{
		int offset = sfoFile.GetDataOffset(sfoData,"SAVEDATA_PARAMS");
		if(offset >= 0)
			UpdateHash(sfoData, sfoSize, offset, (param->key[0]?3:1));
	}
	WritePSPFile(sfopath, sfoData, (SceSize)sfoSize);
	delete[] sfoData;

	if(param->dataBuf != 0)	// Can launch save without save data in mode 13
	{
		std::string filePath = dirPath+"/"+GetFileName(param);
		u8* data_ = 0;
		SceSize saveSize = 0;
		if(cryptedData == 0) // Save decrypted data
		{
			saveSize = param->dataSize;
			if(saveSize == 0 || saveSize > param->dataBufSize)
				saveSize = param->dataBufSize; // fallback, should never use this

			data_ = (u8*)Memory::GetPointer(param->dataBuf);
		}
		else
		{
			data_ = cryptedData;
			saveSize = cryptedSize;
		}

		INFO_LOG(HLE,"Saving file with size %u in %s",saveSize,filePath.c_str());

		// copy back save name in request
		strncpy(param->saveName,GetSaveDirName(param, saveId).c_str(),20);

		if (!WritePSPFile(filePath, data_, saveSize))
		{
			ERROR_LOG(HLE,"Error writing file %s",filePath.c_str());
			if(cryptedData != 0)
			{
				delete[] cryptedData;
			}
			return false;
		}
		delete[] cryptedData;
	}


	// SAVE ICON0
	if (param->icon0FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->icon0FileData.buf);
		std::string icon0path = dirPath+"/"+icon0Name;
		WritePSPFile(icon0path, data_, param->icon0FileData.bufSize);
	}
	// SAVE ICON1
	if (param->icon1FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->icon1FileData.buf);
		std::string icon1path = dirPath+"/"+icon1Name;
		WritePSPFile(icon1path, data_, param->icon1FileData.bufSize);
	}
	// SAVE PIC1
	if (param->pic1FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->pic1FileData.buf);
		std::string pic1path = dirPath+"/"+pic1Name;
		WritePSPFile(pic1path, data_, param->pic1FileData.bufSize);
	}

	// Save SND
	if (param->snd0FileData.buf)
	{
		u8* data_ = (u8*)Memory::GetPointer(param->snd0FileData.buf);
		std::string snd0path = dirPath+"/"+snd0Name;
		WritePSPFile(snd0path, data_, param->snd0FileData.bufSize);
	}

	// Save Encryption Data
	{
		EncryptFileInfo encryptInfo;
		SceSize dataSize = sizeof(encryptInfo); // version + key + sdkVersion
		memset(&encryptInfo,0,dataSize);

		encryptInfo.fileVersion = 1;
		encryptInfo.sdkVersion = sceKernelGetCompiledSdkVersion();
		if(param->size > 1500)
			memcpy(encryptInfo.key,param->key,16);

		std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN";
		WritePSPFile(encryptInfoPath, (u8*)&encryptInfo, dataSize);
	}
	return true;
}
예제 #25
0
파일: Pi.cpp 프로젝트: bitplane/pioneer
void Pi::HandleEvents()
{
	SDL_Event event;

	Pi::mouseMotion[0] = Pi::mouseMotion[1] = 0;
	while (SDL_PollEvent(&event)) {
		if (event.type == SDL_QUIT) {
			if (Pi::game)
				Pi::EndGame();
			Pi::Quit();
		}
		else if (ui->DispatchSDLEvent(event))
			continue;

		Gui::HandleSDLEvent(&event);
		if (!Pi::IsConsoleActive())
			KeyBindings::DispatchSDLEvent(&event);
		else
			KeyBindings::toggleLuaConsole.CheckSDLEventAndDispatch(&event);

		switch (event.type) {
			case SDL_KEYDOWN:
				if (event.key.keysym.sym == SDLK_ESCAPE) {
					if (Pi::game) {
						// only accessible once game started
						if (currentView != 0) {
							if (currentView != gameMenuView) {
								Pi::game->SetTimeAccel(Game::TIMEACCEL_PAUSED);
								SetView(gameMenuView);
							}
							else {
								Pi::game->RequestTimeAccel(Game::TIMEACCEL_1X);
								SetView(Pi::player->IsDead()
										? static_cast<View*>(deathView)
										: static_cast<View*>(worldView));
							}
						}
					}
					break;
				}
				// special keys. LCTRL+turd
				if ((KeyState(SDLK_LCTRL) || (KeyState(SDLK_RCTRL)))) {
					switch (event.key.keysym.sym) {
						case SDLK_q: // Quit
							if (Pi::game)
								Pi::EndGame();
							Pi::Quit();
							break;
						case SDLK_PRINT:	   // print
						case SDLK_KP_MULTIPLY: // screen
						{
							char buf[256];
							const time_t t = time(0);
							struct tm *_tm = localtime(&t);
							strftime(buf, sizeof(buf), "screenshot-%Y%m%d-%H%M%S.png", _tm);
							Screendump(buf, Graphics::GetScreenWidth(), Graphics::GetScreenHeight());
							break;
						}
#if WITH_DEVKEYS
						case SDLK_i: // Toggle Debug info
							Pi::showDebugInfo = !Pi::showDebugInfo;
							break;
						case SDLK_m:  // Gimme money!
							if(Pi::game) {
								Pi::player->SetMoney(Pi::player->GetMoney() + 10000000);
							}
							break;
						case SDLK_F12:
						{
							if(Pi::game) {
								vector3d dir = -Pi::player->GetOrient().VectorZ();
								/* add test object */
								if (KeyState(SDLK_RSHIFT)) {
									Missile *missile =
										new Missile(ShipType::MISSILE_GUIDED, Pi::player, Pi::player->GetCombatTarget());
									missile->SetOrient(Pi::player->GetOrient());
									missile->SetFrame(Pi::player->GetFrame());
									missile->SetPosition(Pi::player->GetPosition()+50.0*dir);
									missile->SetVelocity(Pi::player->GetVelocity());
									game->GetSpace()->AddBody(missile);
								} else if (KeyState(SDLK_LSHIFT)) {
									SpaceStation *s = static_cast<SpaceStation*>(Pi::player->GetNavTarget());
									if (s) {
										int port = s->GetFreeDockingPort();
										if (port != -1) {
											printf("Putting ship into station\n");
											// Make police ship intent on killing the player
											Ship *ship = new Ship(ShipType::LADYBIRD);
											ship->AIKill(Pi::player);
											ship->SetFrame(Pi::player->GetFrame());
											ship->SetDockedWith(s, port);
											game->GetSpace()->AddBody(ship);
										} else {
											printf("No docking ports free dude\n");
										}
									} else {
											printf("Select a space station...\n");
									}
								} else {
									Ship *ship = new Ship(ShipType::LADYBIRD);
									ship->m_equipment.Set(Equip::SLOT_LASER, 0, Equip::PULSECANNON_1MW);
									ship->AIKill(Pi::player);
									ship->SetFrame(Pi::player->GetFrame());
									ship->SetPosition(Pi::player->GetPosition()+100.0*dir);
									ship->SetVelocity(Pi::player->GetVelocity());
									ship->m_equipment.Add(Equip::DRIVE_CLASS2);
									ship->m_equipment.Add(Equip::RADAR_MAPPER);
									ship->m_equipment.Add(Equip::SCANNER);
									ship->m_equipment.Add(Equip::SHIELD_GENERATOR);
									ship->m_equipment.Add(Equip::HYDROGEN, 10);
									ship->UpdateStats();
									game->GetSpace()->AddBody(ship);
								}
							}
							break;
						}
#endif /* DEVKEYS */
#if WITH_OBJECTVIEWER
						case SDLK_F10:
							Pi::SetView(Pi::objectViewerView);
							break;
#endif
						case SDLK_F11:
							// XXX only works on X11
							//SDL_WM_ToggleFullScreen(Pi::scrSurface);
#if WITH_DEVKEYS
							renderer->ReloadShaders();
#endif
							break;
						case SDLK_F9: // Quicksave
						{
							if(Pi::game) {
								if (Pi::game->IsHyperspace())
									Pi::cpan->MsgLog()->Message("", Lang::CANT_SAVE_IN_HYPERSPACE);

								else {
									const std::string name = "_quicksave";
									const std::string path = FileSystem::JoinPath(GetSaveDir(), name);
									try {
										Game::SaveGame(name, Pi::game);
										Pi::cpan->MsgLog()->Message("", Lang::GAME_SAVED_TO + path);
									} catch (CouldNotOpenFileException) {
										Pi::cpan->MsgLog()->Message("", stringf(Lang::COULD_NOT_OPEN_FILENAME, formatarg("path", path)));
									}
									catch (CouldNotWriteToFileException) {
										Pi::cpan->MsgLog()->Message("", Lang::GAME_SAVE_CANNOT_WRITE);
									}
								}
							}
							break;
						}
						default:
							break; // This does nothing but it stops the compiler warnings
					}
				}
				Pi::keyState[event.key.keysym.sym] = 1;
				Pi::keyModState = event.key.keysym.mod;
				Pi::onKeyPress.emit(&event.key.keysym);
				break;
			case SDL_KEYUP:
				Pi::keyState[event.key.keysym.sym] = 0;
				Pi::keyModState = event.key.keysym.mod;
				Pi::onKeyRelease.emit(&event.key.keysym);
				break;
			case SDL_MOUSEBUTTONDOWN:
				if (event.button.button < COUNTOF(Pi::mouseButton)) {
					Pi::mouseButton[event.button.button] = 1;
					Pi::onMouseButtonDown.emit(event.button.button,
							event.button.x, event.button.y);
				}
				break;
			case SDL_MOUSEBUTTONUP:
				if (event.button.button < COUNTOF(Pi::mouseButton)) {
					Pi::mouseButton[event.button.button] = 0;
					Pi::onMouseButtonUp.emit(event.button.button,
							event.button.x, event.button.y);
				}
				break;
			case SDL_MOUSEMOTION:
				Pi::mouseMotion[0] += event.motion.xrel;
				Pi::mouseMotion[1] += event.motion.yrel;
		//		SDL_GetRelativeMouseState(&Pi::mouseMotion[0], &Pi::mouseMotion[1]);
				break;
			case SDL_JOYAXISMOTION:
				if (joysticks[event.jaxis.which].joystick == NULL)
					break;
				if (event.jaxis.value == -32768)
					joysticks[event.jaxis.which].axes[event.jaxis.axis] = 1.f;
				else
					joysticks[event.jaxis.which].axes[event.jaxis.axis] = -event.jaxis.value / 32767.f;
				break;
			case SDL_JOYBUTTONUP:
			case SDL_JOYBUTTONDOWN:
				if (joysticks[event.jaxis.which].joystick == NULL)
					break;
				joysticks[event.jbutton.which].buttons[event.jbutton.button] = event.jbutton.state != 0;
				break;
			case SDL_JOYHATMOTION:
				if (joysticks[event.jaxis.which].joystick == NULL)
					break;
				joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value;
				break;
		}
	}
}
예제 #26
0
/**
**  Save a game to file.
**
**  @param filename  File name to be stored.
**  @return  -1 if saving failed, 0 if all OK
**
**  @note  Later we want to store in a more compact binary format.
*/
int SaveGame(const std::string &filename)
{
	CFile file;
	std::string fullpath(GetSaveDir());

	fullpath += "/";
	fullpath += filename;
	if (file.open(fullpath.c_str(), CL_WRITE_GZ | CL_OPEN_WRITE) == -1) {
		fprintf(stderr, "Can't save to `%s'\n", filename.c_str());
		return -1;
	}

	time_t now;
	char dateStr[64];

	time(&now);
	const struct tm *timeinfo = localtime(&now);
	strftime(dateStr, sizeof(dateStr), "%c", timeinfo);

	// Load initial level // Without units
	file.printf("local oldCreateUnit = CreateUnit\n");
	file.printf("local oldSetResourcesHeld = SetResourcesHeld\n");
	file.printf("local oldSetTile = SetTile\n");
	file.printf("function CreateUnit() end\n");
	file.printf("function SetResourcesHeld() end\n");
	file.printf("function SetTile() end\n");
	file.printf("Load(\"%s\")\n", Map.Info.Filename.c_str());
	file.printf("CreateUnit = oldCreateUnit\n");
	file.printf("SetResourcesHeld = oldSetResourcesHeld\n");
	file.printf("SetTile = oldSetTile\n");
	//
	// Parseable header
	//
	file.printf("SavedGameInfo({\n");
	file.printf("---  \"comment\", \"Generated by Stratagus Version " VERSION "\",\n");
	file.printf("---  \"comment\", \"Visit https://launchpad.net/stratagus for more informations\",\n");
	file.printf("---  \"type\",    \"%s\",\n", "single-player");
	file.printf("---  \"date\",    \"%s\",\n", dateStr);
	file.printf("---  \"map\",     \"%s\",\n", Map.Info.Description.c_str());
	file.printf("---  \"media-version\", \"%s\"", "Undefined");
	file.printf("---  \"engine\",  {%d, %d, %d},\n",
				StratagusMajorVersion, StratagusMinorVersion, StratagusPatchLevel);
	file.printf("  SyncHash = %d, \n", SyncHash);
	file.printf("  SyncRandSeed = %d, \n", SyncRandSeed);
	file.printf("  SaveFile = \"%s\"\n", CurrentMapPath);
	file.printf("\n---  \"preview\", \"%s.pam\",\n", filename.c_str());
	file.printf("} )\n\n");

	// FIXME: probably not the right place for this
	file.printf("GameCycle = %lu\n", GameCycle);

	file.printf("SetGodMode(%s)\n", GodMode ? "true" : "false");

	SaveUnitTypes(file);
	SaveUpgrades(file);
	SavePlayers(file);
	Map.Save(file);
	UnitManager.Save(file);
	SaveUserInterface(file);
	SaveAi(file);
	SaveSelections(file);
	SaveGroups(file);
	SaveMissiles(file);
	SaveReplayList(file);
	// FIXME: find all state information which must be saved.
	const std::string s = SaveGlobal(Lua);
	if (!s.empty()) {
		file.printf("-- Lua state\n\n %s\n", s.c_str());
	}
	SaveTriggers(file); //Triggers are saved in SaveGlobal, so load it after Global
	file.close();
	return 0;
}