diff options
| -rw-r--r-- | CMakeLists.txt | 9 | ||||
| -rw-r--r-- | src/citra_qt/main.cpp | 2 | ||||
| -rw-r--r-- | src/common/scm_rev.cpp.in | 2 | ||||
| -rw-r--r-- | src/common/scm_rev.h | 1 | ||||
| -rw-r--r-- | src/core/core.h | 9 | ||||
| -rw-r--r-- | src/core/file_sys/archive_sdmc.cpp | 41 | ||||
| -rw-r--r-- | src/core/file_sys/savedata_archive.cpp | 41 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/dlp/dlp_clnt.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/service/dlp/dlp_fkcl.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/service/dlp/dlp_srvr.cpp | 9 | ||||
| -rw-r--r-- | src/core/loader/loader.h | 9 | ||||
| -rw-r--r-- | src/core/loader/ncch.cpp | 20 | ||||
| -rw-r--r-- | src/core/loader/ncch.h | 14 | ||||
| -rw-r--r-- | src/core/telemetry_session.cpp | 17 | 
15 files changed, 191 insertions, 26 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 79d8046d9..ddba04ef9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,11 +295,18 @@ function(create_directory_groups)      endforeach()  endfunction() -# generate git revision information +# Gets a UTC timstamp and sets the provided variable to it +function(get_timestamp _var) +    string(TIMESTAMP timestamp UTC) +    set(${_var} "${timestamp}" PARENT_SCOPE) +endfunction() + +# generate git/build information  include(GetGitRevisionDescription)  get_git_head_revision(GIT_REF_SPEC GIT_REV)  git_describe(GIT_DESC --always --long --dirty)  git_branch_name(GIT_BRANCH) +get_timestamp(BUILD_DATE)  enable_testing()  add_subdirectory(externals) diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 02bfdca3d..c1ae0ccc8 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -311,7 +311,7 @@ bool GMainWindow::LoadROM(const QString& filename) {      if (!gladLoadGL()) {          QMessageBox::critical(this, tr("Error while initializing OpenGL 3.3 Core!"), -                              tr("Your GPU may not support OpenGL 3.3, or you do not" +                              tr("Your GPU may not support OpenGL 3.3, or you do not "                                   "have the latest graphics driver."));          return false;      } diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index 0080db5d5..4083095d5 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in @@ -8,6 +8,7 @@  #define GIT_BRANCH   "@GIT_BRANCH@"  #define GIT_DESC     "@GIT_DESC@"  #define BUILD_NAME   "@REPO_NAME@" +#define BUILD_DATE   "@BUILD_DATE@"  namespace Common { @@ -15,6 +16,7 @@ const char g_scm_rev[]      = GIT_REV;  const char g_scm_branch[]   = GIT_BRANCH;  const char g_scm_desc[]     = GIT_DESC;  const char g_build_name[]   = BUILD_NAME; +const char g_build_date[]   = BUILD_DATE;  } // namespace diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h index e22389803..18aaa1735 100644 --- a/src/common/scm_rev.h +++ b/src/common/scm_rev.h @@ -10,5 +10,6 @@ extern const char g_scm_rev[];  extern const char g_scm_branch[];  extern const char g_scm_desc[];  extern const char g_build_name[]; +extern const char g_build_date[];  } // namespace diff --git a/src/core/core.h b/src/core/core.h index 4e3b6b409..9805cc694 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -7,6 +7,7 @@  #include <memory>  #include <string>  #include "common/common_types.h" +#include "core/loader/loader.h"  #include "core/memory.h"  #include "core/perf_stats.h"  #include "core/telemetry_session.h" @@ -14,10 +15,6 @@  class EmuWindow;  class ARM_Interface; -namespace Loader { -class AppLoader; -} -  namespace Core {  class System { @@ -119,6 +116,10 @@ public:          return status_details;      } +    Loader::AppLoader& GetAppLoader() const { +        return *app_loader; +    } +  private:      /**       * Initialize the emulated system. diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 679909d06..fe3dce5d4 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp @@ -121,7 +121,25 @@ ResultCode SDMCArchive::DeleteFile(const Path& path) const {  }  ResultCode SDMCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { -    if (FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString())) { +    const PathParser path_parser_src(src_path); + +    // TODO: Verify these return codes with HW +    if (!path_parser_src.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid src path %s", src_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const PathParser path_parser_dest(dest_path); + +    if (!path_parser_dest.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid dest path %s", dest_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const auto src_path_full = path_parser_src.BuildHostPath(mount_point); +    const auto dest_path_full = path_parser_dest.BuildHostPath(mount_point); + +    if (FileUtil::Rename(src_path_full, dest_path_full)) {          return RESULT_SUCCESS;      } @@ -260,8 +278,27 @@ ResultCode SDMCArchive::CreateDirectory(const Path& path) const {  }  ResultCode SDMCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { -    if (FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString())) +    const PathParser path_parser_src(src_path); + +    // TODO: Verify these return codes with HW +    if (!path_parser_src.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid src path %s", src_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const PathParser path_parser_dest(dest_path); + +    if (!path_parser_dest.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid dest path %s", dest_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const auto src_path_full = path_parser_src.BuildHostPath(mount_point); +    const auto dest_path_full = path_parser_dest.BuildHostPath(mount_point); + +    if (FileUtil::Rename(src_path_full, dest_path_full)) {          return RESULT_SUCCESS; +    }      // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't      // exist or similar. Verify. diff --git a/src/core/file_sys/savedata_archive.cpp b/src/core/file_sys/savedata_archive.cpp index f540c4a93..f8f811ba0 100644 --- a/src/core/file_sys/savedata_archive.cpp +++ b/src/core/file_sys/savedata_archive.cpp @@ -106,7 +106,25 @@ ResultCode SaveDataArchive::DeleteFile(const Path& path) const {  }  ResultCode SaveDataArchive::RenameFile(const Path& src_path, const Path& dest_path) const { -    if (FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString())) { +    const PathParser path_parser_src(src_path); + +    // TODO: Verify these return codes with HW +    if (!path_parser_src.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid src path %s", src_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const PathParser path_parser_dest(dest_path); + +    if (!path_parser_dest.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid dest path %s", dest_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const auto src_path_full = path_parser_src.BuildHostPath(mount_point); +    const auto dest_path_full = path_parser_dest.BuildHostPath(mount_point); + +    if (FileUtil::Rename(src_path_full, dest_path_full)) {          return RESULT_SUCCESS;      } @@ -247,8 +265,27 @@ ResultCode SaveDataArchive::CreateDirectory(const Path& path) const {  }  ResultCode SaveDataArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { -    if (FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString())) +    const PathParser path_parser_src(src_path); + +    // TODO: Verify these return codes with HW +    if (!path_parser_src.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid src path %s", src_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const PathParser path_parser_dest(dest_path); + +    if (!path_parser_dest.IsValid()) { +        LOG_ERROR(Service_FS, "Invalid dest path %s", dest_path.DebugStr().c_str()); +        return ERROR_INVALID_PATH; +    } + +    const auto src_path_full = path_parser_src.BuildHostPath(mount_point); +    const auto dest_path_full = path_parser_dest.BuildHostPath(mount_point); + +    if (FileUtil::Rename(src_path_full, dest_path_full)) {          return RESULT_SUCCESS; +    }      // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't      // exist or similar. Verify. diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 4e6b7b6f5..0109fa2b2 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -75,6 +75,10 @@ void Initialize(Service::Interface* self) {  void GetSharedFont(Service::Interface* self) {      IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x44, 0, 0); // 0x00440000      IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); + +    // Log in telemetry if the game uses the shared font +    Core::Telemetry().AddField(Telemetry::FieldType::Session, "RequiresSharedFont", true); +      if (!shared_font_loaded) {          LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds");          rb.Push<u32>(-1); // TODO: Find the right error code diff --git a/src/core/hle/service/dlp/dlp_clnt.cpp b/src/core/hle/service/dlp/dlp_clnt.cpp index 56f934b3f..6f2bf2061 100644 --- a/src/core/hle/service/dlp/dlp_clnt.cpp +++ b/src/core/hle/service/dlp/dlp_clnt.cpp @@ -8,7 +8,26 @@ namespace Service {  namespace DLP {  const Interface::FunctionInfo FunctionTable[] = { -    {0x000100C3, nullptr, "Initialize"}, {0x00110000, nullptr, "GetWirelessRebootPassphrase"}, +    {0x000100C3, nullptr, "Initialize"}, +    {0x00020000, nullptr, "Finalize"}, +    {0x00030000, nullptr, "GetEventDesc"}, +    {0x00040000, nullptr, "GetChannel"}, +    {0x00050180, nullptr, "StartScan"}, +    {0x00060000, nullptr, "StopScan"}, +    {0x00070080, nullptr, "GetServerInfo"}, +    {0x00080100, nullptr, "GetTitleInfo"}, +    {0x00090040, nullptr, "GetTitleInfoInOrder"}, +    {0x000A0080, nullptr, "DeleteScanInfo"}, +    {0x000B0100, nullptr, "PrepareForSystemDownload"}, +    {0x000C0000, nullptr, "StartSystemDownload"}, +    {0x000D0100, nullptr, "StartTitleDownload"}, +    {0x000E0000, nullptr, "GetMyStatus"}, +    {0x000F0040, nullptr, "GetConnectingNodes"}, +    {0x00100040, nullptr, "GetNodeInfo"}, +    {0x00110000, nullptr, "GetWirelessRebootPassphrase"}, +    {0x00120000, nullptr, "StopSession"}, +    {0x00130100, nullptr, "GetCupVersion"}, +    {0x00140100, nullptr, "GetDupAvailability"},  };  DLP_CLNT_Interface::DLP_CLNT_Interface() { diff --git a/src/core/hle/service/dlp/dlp_fkcl.cpp b/src/core/hle/service/dlp/dlp_fkcl.cpp index 29b9d52e0..fe6be7d32 100644 --- a/src/core/hle/service/dlp/dlp_fkcl.cpp +++ b/src/core/hle/service/dlp/dlp_fkcl.cpp @@ -8,7 +8,23 @@ namespace Service {  namespace DLP {  const Interface::FunctionInfo FunctionTable[] = { -    {0x00010083, nullptr, "Initialize"}, {0x000F0000, nullptr, "GetWirelessRebootPassphrase"}, +    {0x00010083, nullptr, "Initialize"}, +    {0x00020000, nullptr, "Finalize"}, +    {0x00030000, nullptr, "GetEventDesc"}, +    {0x00040000, nullptr, "GetChannels"}, +    {0x00050180, nullptr, "StartScan"}, +    {0x00060000, nullptr, "StopScan"}, +    {0x00070080, nullptr, "GetServerInfo"}, +    {0x00080100, nullptr, "GetTitleInfo"}, +    {0x00090040, nullptr, "GetTitleInfoInOrder"}, +    {0x000A0080, nullptr, "DeleteScanInfo"}, +    {0x000B0100, nullptr, "StartFakeSession"}, +    {0x000C0000, nullptr, "GetMyStatus"}, +    {0x000D0040, nullptr, "GetConnectingNodes"}, +    {0x000E0040, nullptr, "GetNodeInfo"}, +    {0x000F0000, nullptr, "GetWirelessRebootPassphrase"}, +    {0x00100000, nullptr, "StopSession"}, +    {0x00110203, nullptr, "Initialize2"},  };  DLP_FKCL_Interface::DLP_FKCL_Interface() { diff --git a/src/core/hle/service/dlp/dlp_srvr.cpp b/src/core/hle/service/dlp/dlp_srvr.cpp index 32cfa2c44..1bcea43d3 100644 --- a/src/core/hle/service/dlp/dlp_srvr.cpp +++ b/src/core/hle/service/dlp/dlp_srvr.cpp @@ -11,7 +11,7 @@  namespace Service {  namespace DLP { -static void unk_0x000E0040(Interface* self) { +static void IsChild(Interface* self) {      u32* cmd_buff = Kernel::GetCommandBuffer();      cmd_buff[1] = RESULT_SUCCESS.raw; @@ -24,14 +24,19 @@ const Interface::FunctionInfo FunctionTable[] = {      {0x00010183, nullptr, "Initialize"},      {0x00020000, nullptr, "Finalize"},      {0x00030000, nullptr, "GetServerState"}, +    {0x00040000, nullptr, "GetEventDescription"},      {0x00050080, nullptr, "StartAccepting"}, +    {0x00060000, nullptr, "EndAccepting"},      {0x00070000, nullptr, "StartDistribution"},      {0x000800C0, nullptr, "SendWirelessRebootPassphrase"},      {0x00090040, nullptr, "AcceptClient"}, +    {0x000A0040, nullptr, "DisconnectClient"},      {0x000B0042, nullptr, "GetConnectingClients"},      {0x000C0040, nullptr, "GetClientInfo"},      {0x000D0040, nullptr, "GetClientState"}, -    {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, +    {0x000E0040, IsChild, "IsChild"}, +    {0x000F0303, nullptr, "InitializeWithName"}, +    {0x00100000, nullptr, "GetDupNoticeNeed"},  };  DLP_SRVR_Interface::DLP_SRVR_Interface() { diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 48bbf687d..e731888a2 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -166,6 +166,15 @@ public:          return ResultStatus::ErrorNotImplemented;      } +    /** +     * Get the title of the application +     * @param title Reference to store the application title into +     * @return ResultStatus result of function +     */ +    virtual ResultStatus ReadTitle(std::string& title) { +        return ResultStatus::ErrorNotImplemented; +    } +  protected:      FileUtil::IOFile file;      bool is_loaded = false; diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index fc4d14a59..c007069a9 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -4,7 +4,9 @@  #include <algorithm>  #include <cinttypes> +#include <codecvt>  #include <cstring> +#include <locale>  #include <memory>  #include "common/logging/log.h"  #include "common/string_util.h" @@ -420,4 +422,22 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_      return ResultStatus::ErrorNotUsed;  } +ResultStatus AppLoader_NCCH::ReadTitle(std::string& title) { +    std::vector<u8> data; +    Loader::SMDH smdh; +    ReadIcon(data); + +    if (!Loader::IsValidSMDH(data)) { +        return ResultStatus::ErrorInvalidFormat; +    } + +    memcpy(&smdh, data.data(), sizeof(Loader::SMDH)); + +    const auto& short_title = smdh.GetShortTitle(SMDH::TitleLanguage::English); +    auto title_end = std::find(short_title.begin(), short_title.end(), u'\0'); +    title = Common::UTF16ToUTF8(std::u16string{short_title.begin(), title_end}); + +    return ResultStatus::Success; +} +  } // namespace Loader diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 0ebd47fd5..e40cef764 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -191,23 +191,13 @@ public:      ResultStatus ReadLogo(std::vector<u8>& buffer) override; -    /** -     * Get the program id of the application -     * @param out_program_id Reference to store program id into -     * @return ResultStatus result of function -     */      ResultStatus ReadProgramId(u64& out_program_id) override; -    /** -     * Get the RomFS of the application -     * @param romfs_file Reference to buffer to store data -     * @param offset     Offset in the file to the RomFS -     * @param size       Size of the RomFS in bytes -     * @return ResultStatus result of function -     */      ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,                             u64& size) override; +    ResultStatus ReadTitle(std::string& title) override; +  private:      /**       * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.) diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 841d6cfa1..94483f385 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -7,6 +7,7 @@  #include "common/assert.h"  #include "common/scm_rev.h"  #include "common/x64/cpu_detect.h" +#include "core/core.h"  #include "core/settings.h"  #include "core/telemetry_session.h" @@ -39,12 +40,19 @@ TelemetrySession::TelemetrySession() {                              std::chrono::system_clock::now().time_since_epoch())                              .count()};      AddField(Telemetry::FieldType::Session, "Init_Time", init_time); +    std::string program_name; +    const Loader::ResultStatus res{System::GetInstance().GetAppLoader().ReadTitle(program_name)}; +    if (res == Loader::ResultStatus::Success) { +        AddField(Telemetry::FieldType::Session, "ProgramName", program_name); +    }      // Log application information      const bool is_git_dirty{std::strstr(Common::g_scm_desc, "dirty") != nullptr};      AddField(Telemetry::FieldType::App, "Git_IsDirty", is_git_dirty);      AddField(Telemetry::FieldType::App, "Git_Branch", Common::g_scm_branch);      AddField(Telemetry::FieldType::App, "Git_Revision", Common::g_scm_rev); +    AddField(Telemetry::FieldType::App, "BuildDate", Common::g_build_date); +    AddField(Telemetry::FieldType::App, "BuildName", Common::g_build_name);      // Log user system information      AddField(Telemetry::FieldType::UserSystem, "CPU_Model", Common::GetCPUCaps().cpu_string); @@ -68,6 +76,15 @@ TelemetrySession::TelemetrySession() {               Common::GetCPUCaps().sse4_1);      AddField(Telemetry::FieldType::UserSystem, "CPU_Extension_x64_SSE42",               Common::GetCPUCaps().sse4_2); +#ifdef __APPLE__ +    AddField(Telemetry::FieldType::UserSystem, "OsPlatform", "Apple"); +#elif defined(_WIN32) +    AddField(Telemetry::FieldType::UserSystem, "OsPlatform", "Windows"); +#elif defined(__linux__) || defined(linux) || defined(__linux) +    AddField(Telemetry::FieldType::UserSystem, "OsPlatform", "Linux"); +#else +    AddField(Telemetry::FieldType::UserSystem, "OsPlatform", "Unknown"); +#endif      // Log user configuration information      AddField(Telemetry::FieldType::UserConfig, "Audio_EnableAudioStretching",  | 
