diff options
Diffstat (limited to 'xbmc/games/addons/GameClientInGameSaves.cpp')
-rw-r--r-- | xbmc/games/addons/GameClientInGameSaves.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/xbmc/games/addons/GameClientInGameSaves.cpp b/xbmc/games/addons/GameClientInGameSaves.cpp new file mode 100644 index 0000000..802ebb7 --- /dev/null +++ b/xbmc/games/addons/GameClientInGameSaves.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2016-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GameClientInGameSaves.h" + +#include "GameClient.h" +#include "GameClientTranslator.h" +#include "ServiceBroker.h" +#include "filesystem/Directory.h" +#include "filesystem/File.h" +#include "games/GameServices.h" +#include "utils/URIUtils.h" +#include "utils/log.h" + +#include <assert.h> + +using namespace KODI; +using namespace GAME; + +#define INGAME_SAVES_DIRECTORY "InGameSaves" +#define INGAME_SAVES_EXTENSION_SAVE_RAM ".sav" +#define INGAME_SAVES_EXTENSION_RTC ".rtc" + +CGameClientInGameSaves::CGameClientInGameSaves(CGameClient* addon, + const AddonInstance_Game* dllStruct) + : m_gameClient(addon), m_dllStruct(dllStruct) +{ + assert(m_gameClient != nullptr); + assert(m_dllStruct != nullptr); +} + +void CGameClientInGameSaves::Load() +{ + Load(GAME_MEMORY_SAVE_RAM); + Load(GAME_MEMORY_RTC); +} + +void CGameClientInGameSaves::Save() +{ + Save(GAME_MEMORY_SAVE_RAM); + Save(GAME_MEMORY_RTC); +} + +std::string CGameClientInGameSaves::GetPath(GAME_MEMORY memoryType) +{ + const CGameServices& gameServices = CServiceBroker::GetGameServices(); + std::string path = + URIUtils::AddFileToFolder(gameServices.GetSavestatesFolder(), INGAME_SAVES_DIRECTORY); + if (!XFILE::CDirectory::Exists(path)) + XFILE::CDirectory::Create(path); + + // Append save game filename + std::string gamePath = URIUtils::GetFileName(m_gameClient->GetGamePath()); + path = URIUtils::AddFileToFolder(path, gamePath.empty() ? m_gameClient->ID() : gamePath); + + // Append file extension + switch (memoryType) + { + case GAME_MEMORY_SAVE_RAM: + return path + INGAME_SAVES_EXTENSION_SAVE_RAM; + case GAME_MEMORY_RTC: + return path + INGAME_SAVES_EXTENSION_RTC; + default: + break; + } + return std::string(); +} + +void CGameClientInGameSaves::Load(GAME_MEMORY memoryType) +{ + uint8_t* gameMemory = nullptr; + size_t size = 0; + + try + { + m_dllStruct->toAddon->GetMemory(m_dllStruct, memoryType, &gameMemory, &size); + } + catch (...) + { + CLog::Log(LOGERROR, "GAME: {}: Exception caught in GetMemory()", m_gameClient->ID()); + } + + const std::string path = GetPath(memoryType); + if (size > 0 && XFILE::CFile::Exists(path)) + { + XFILE::CFile file; + if (file.Open(path)) + { + ssize_t read = file.Read(gameMemory, size); + if (read == static_cast<ssize_t>(size)) + { + CLog::Log(LOGINFO, "GAME: In-game saves ({}) loaded from {}", + CGameClientTranslator::ToString(memoryType), path); + } + else + { + CLog::Log(LOGERROR, "GAME: Failed to read in-game saves ({}): {}/{} bytes read", + CGameClientTranslator::ToString(memoryType), read, size); + } + } + else + { + CLog::Log(LOGERROR, "GAME: Unable to open in-game saves ({}) from file {}", + CGameClientTranslator::ToString(memoryType), path); + } + } + else + { + CLog::Log(LOGDEBUG, "GAME: No in-game saves ({}) to load", + CGameClientTranslator::ToString(memoryType)); + } +} + +void CGameClientInGameSaves::Save(GAME_MEMORY memoryType) +{ + uint8_t* gameMemory = nullptr; + size_t size = 0; + + try + { + m_dllStruct->toAddon->GetMemory(m_dllStruct, memoryType, &gameMemory, &size); + } + catch (...) + { + CLog::Log(LOGERROR, "GAME: {}: Exception caught in GetMemory()", m_gameClient->ID()); + } + + if (size > 0) + { + const std::string path = GetPath(memoryType); + XFILE::CFile file; + if (file.OpenForWrite(path, true)) + { + ssize_t written = 0; + written = file.Write(gameMemory, size); + file.Close(); + if (written == static_cast<ssize_t>(size)) + { + CLog::Log(LOGINFO, "GAME: In-game saves ({}) written to {}", + CGameClientTranslator::ToString(memoryType), path); + } + else + { + CLog::Log(LOGERROR, "GAME: Failed to write in-game saves ({}): {}/{} bytes written", + CGameClientTranslator::ToString(memoryType), written, size); + } + } + else + { + CLog::Log(LOGERROR, "GAME: Unable to open in-game saves ({}) from file {}", + CGameClientTranslator::ToString(memoryType), path); + } + } + else + { + CLog::Log(LOGDEBUG, "GAME: No in-game saves ({}) to save", + CGameClientTranslator::ToString(memoryType)); + } +} |