diff options
| author | bunnei <bunneidev@gmail.com> | 2014-12-29 23:00:54 -0500 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2014-12-29 23:00:54 -0500 | 
| commit | 66f70143c3ac4c4733ae3779b2d0e27e4dec1a68 (patch) | |
| tree | 34b388e1f581edf4d1260e1aa4b61403635e7ffb /src/core/hle | |
| parent | 3d14eb285382740b144e5b047cb2ad072f6129ea (diff) | |
| parent | 545ded954d5276729a5c1a49457439a6b0e93ade (diff) | |
Merge pull request #364 from Subv/master
Archives: Implemented ExtSaveData and SharedExtSaveData
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/apt_a.cpp | 29 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 59 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/service/ptm_u.cpp | 47 | 
5 files changed, 102 insertions, 53 deletions
| diff --git a/src/core/hle/service/apt_a.cpp b/src/core/hle/service/apt_a.cpp index dcf5ec4fe..4b0f761d9 100644 --- a/src/core/hle/service/apt_a.cpp +++ b/src/core/hle/service/apt_a.cpp @@ -6,22 +6,31 @@  #include "core/hle/hle.h"  #include "core/hle/service/apt_a.h" +namespace APT_U { +    extern void Initialize(Service::Interface* self); +    extern void GetLockHandle(Service::Interface* self); +    extern void ReceiveParameter(Service::Interface* self); +    extern void GlanceParameter(Service::Interface* self); +} +  ////////////////////////////////////////////////////////////////////////////////////////////////////  // Namespace APT_A  namespace APT_A {  const Interface::FunctionInfo FunctionTable[] = { -    {0x00010040, nullptr,               "GetLockHandle?"}, -    {0x00020080, nullptr,               "Initialize?"}, -    {0x00030040, nullptr,               "Enable?"}, -    {0x00040040, nullptr,               "Finalize?"}, -    {0x00050040, nullptr,               "GetAppletManInfo?"}, -    {0x00060040, nullptr,               "GetAppletInfo?"}, -    {0x003B0040, nullptr,               "CancelLibraryApplet?"}, -    {0x00430040, nullptr,               "NotifyToWait?"}, -    {0x004B00C2, nullptr,               "AppletUtility?"}, -    {0x00550040, nullptr,               "WriteInputToNsState?"}, +    {0x00010040, APT_U::GetLockHandle,      "GetLockHandle?"}, +    {0x00020080, APT_U::Initialize,         "Initialize?"}, +    {0x00030040, nullptr,                   "Enable?"}, +    {0x00040040, nullptr,                   "Finalize?"}, +    {0x00050040, nullptr,                   "GetAppletManInfo?"}, +    {0x00060040, nullptr,                   "GetAppletInfo?"}, +    {0x003B0040, nullptr,                   "CancelLibraryApplet?"}, +    {0x00430040, nullptr,                   "NotifyToWait?"}, +    {0x004B00C2, nullptr,                   "AppletUtility?"}, +    {0x00550040, nullptr,                   "WriteInputToNsState?"}, +    {0x000D0080, APT_U::ReceiveParameter,   "ReceiveParameter" }, +    {0x000E0080, APT_U::GlanceParameter,    "GlanceParameter" },  };  //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 487bf3aa7..f19ca3a9f 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -11,6 +11,7 @@  #include "common/math_util.h"  #include "core/file_sys/archive_savedata.h" +#include "core/file_sys/archive_extsavedata.h"  #include "core/file_sys/archive_backend.h"  #include "core/file_sys/archive_sdmc.h"  #include "core/file_sys/directory_backend.h" @@ -224,25 +225,20 @@ static Archive* GetArchive(ArchiveHandle handle) {      return (itr == handle_map.end()) ? nullptr : itr->second;  } -ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code) { +ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) {      LOG_TRACE(Service_FS, "Opening archive with id code 0x%08X", id_code);      auto itr = id_code_map.find(id_code);      if (itr == id_code_map.end()) { -        if (id_code == ArchiveIdCode::SaveData) { -            // When a SaveData archive is created for the first time, it is not yet formatted -            // and the save file/directory structure expected by the game has not yet been initialized.  -            // Returning the NotFormatted error code will signal the game to provision the SaveData archive  -            // with the files and folders that it expects.  -            // The FormatSaveData service call will create the SaveData archive when it is called. -            return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, -                              ErrorSummary::InvalidState, ErrorLevel::Status); -        }          // TODO: Verify error against hardware          return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,                            ErrorSummary::NotFound, ErrorLevel::Permanent);      } +    ResultCode res = itr->second->backend->Open(archive_path); +    if (!res.IsSuccess()) +        return res; +      // This should never even happen in the first place with 64-bit handles,       while (handle_map.count(next_handle) != 0) {          ++next_handle; @@ -395,25 +391,14 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F  }  ResultCode FormatSaveData() { -    // TODO(Subv): Actually wipe the savedata folder after creating or opening it -      // Do not create the archive again if it already exists -    if (id_code_map.find(ArchiveIdCode::SaveData) != id_code_map.end()) -        return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the correct error code - -    // Create the SaveData archive -    std::string savedata_directory = FileUtil::GetUserPath(D_SAVEDATA_IDX); -    auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(savedata_directory, -        Kernel::g_program_id); - -    if (savedata_archive->Initialize()) { -        CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); -        return RESULT_SUCCESS; -    } else { -        LOG_ERROR(Service_FS, "Can't instantiate SaveData archive with path %s", -            savedata_archive->GetMountPoint().c_str()); -        return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the proper error code +    auto archive_itr = id_code_map.find(ArchiveIdCode::SaveData); +    if (archive_itr == id_code_map.end()) { +        return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error      } + +    // Use an empty path, we do not use it when formatting the savedata +    return archive_itr->second->backend->Format(FileSys::Path());  }  /// Initialize archives @@ -430,6 +415,26 @@ void ArchiveInit() {          CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC);      else          LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); +     +    // Create the SaveData archive +    std::string savedata_directory = FileUtil::GetUserPath(D_SAVEDATA_IDX); +    auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(savedata_directory); +    CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); + +    std::string extsavedata_directory = FileUtil::GetUserPath(D_EXTSAVEDATA); +    auto extsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(extsavedata_directory); +    if (extsavedata_archive->Initialize()) +        CreateArchive(std::move(extsavedata_archive), ArchiveIdCode::ExtSaveData); +    else +        LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_directory.c_str()); + +    std::string sharedextsavedata_directory = FileUtil::GetUserPath(D_EXTSAVEDATA); +    auto sharedextsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(sharedextsavedata_directory); +    if (sharedextsavedata_archive->Initialize()) +        CreateArchive(std::move(sharedextsavedata_archive), ArchiveIdCode::SharedExtSaveData); +    else +        LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",  +                  sharedextsavedata_directory.c_str());  }  /// Shutdown archives diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index b39bc41b6..c23b8cc46 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -29,9 +29,10 @@ typedef u64 ArchiveHandle;  /**   * Opens an archive   * @param id_code IdCode of the archive to open + * @param archive_path Path to the archive, used with Binary paths   * @return Handle to the opened archive   */ -ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code); +ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path);  /**   * Closes an archive diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index b1a465274..7eb32146d 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -107,14 +107,7 @@ static void OpenFileDirectly(Service::Interface* self) {      LOG_DEBUG(Service_FS, "archive_path=%s file_path=%s, mode=%u attributes=%d",                archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); -    if (archive_path.GetType() != FileSys::Empty) { -        LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported"); -        cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; -        cmd_buff[3] = 0; -        return; -    } - -    ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id); +    ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);      if (archive_handle.Failed()) {          LOG_ERROR(Service_FS, "failed to get a handle for archive");          cmd_buff[1] = archive_handle.Code().raw; @@ -376,13 +369,7 @@ static void OpenArchive(Service::Interface* self) {      LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str()); -    if (archive_path.GetType() != FileSys::Empty) { -        LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported"); -        cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; -        return; -    } - -    ResultVal<ArchiveHandle> handle = OpenArchive(archive_id); +    ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path);      cmd_buff[1] = handle.Code().raw;      if (handle.Succeeded()) {          cmd_buff[2] = *handle & 0xFFFFFFFF; diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index d1498f05c..9cc700c46 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp @@ -3,6 +3,8 @@  // Refer to the license.txt file included.  #include "common/log.h" +#include "common/make_unique.h" +#include "core/file_sys/archive_extsavedata.h"  #include "core/hle/hle.h"  #include "core/hle/service/ptm_u.h" @@ -11,6 +13,24 @@  namespace PTM_U { +/**  + * Represents the gamecoin file structure in the SharedExtData archive + * More information in 3dbrew (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) + */ +struct GameCoin { +    u32 magic; ///< Magic number: 0x4F00 +    u16 total_coins; ///< Total Play Coins  +    u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. +    u32 step_count; ///< Total step count at the time a new Play Coin was obtained.  +    u32 last_step_count; ///< Step count for the day the last Play Coin was obtained +    u16 year; +    u8 month; +    u8 day; +}; +static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; +static std::unique_ptr<FileSys::Archive_ExtSaveData> ptm_shared_extsavedata; +static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; +  /// Charge levels used by PTM functions  enum class ChargeLevels : u32 {      CriticalBattery    = 1, @@ -120,6 +140,33 @@ const Interface::FunctionInfo FunctionTable[] = {  Interface::Interface() {      Register(FunctionTable, ARRAY_SIZE(FunctionTable)); +    // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file +    // TODO(Subv): In the future we should use the FS service to query this archive +    std::string extsavedata_directory = FileUtil::GetUserPath(D_EXTSAVEDATA); +    ptm_shared_extsavedata = Common::make_unique<FileSys::Archive_ExtSaveData>(extsavedata_directory); +    if (!ptm_shared_extsavedata->Initialize()) { +        LOG_CRITICAL(Service_PTM, "Could not initialize ExtSaveData archive for the PTM:U service"); +        return; +    } +    FileSys::Path archive_path(ptm_shared_extdata_id); +    ResultCode result = ptm_shared_extsavedata->Open(archive_path); +    // If the archive didn't exist, create the files inside +    if (result.description == ErrorDescription::FS_NotFormatted) { +        // Format the archive to clear the directories +        ptm_shared_extsavedata->Format(archive_path); +        // Open it again to get a valid archive now that the folder exists +        ptm_shared_extsavedata->Open(archive_path); +        FileSys::Path gamecoin_path("gamecoin.dat"); +        FileSys::Mode open_mode = {}; +        open_mode.write_flag = 1; +        open_mode.create_flag = 1; +        // Open the file and write the default gamecoin information +        auto gamecoin = ptm_shared_extsavedata->OpenFile(gamecoin_path, open_mode); +        if (gamecoin != nullptr) { +            gamecoin->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); +            gamecoin->Close(); +        } +    }  }  } // namespace | 
