diff options
Diffstat (limited to 'src/core')
76 files changed, 1346 insertions, 291 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 299f1f261..3dd3310cb 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -18,10 +18,12 @@ set(SRCS file_sys/archive_backend.cpp file_sys/archive_extsavedata.cpp file_sys/archive_ncch.cpp + file_sys/archive_other_savedata.cpp file_sys/archive_romfs.cpp file_sys/archive_savedata.cpp file_sys/archive_sdmc.cpp file_sys/archive_sdmcwriteonly.cpp + file_sys/archive_source_sd_savedata.cpp file_sys/archive_systemsavedata.cpp file_sys/disk_archive.cpp file_sys/ivfc_archive.cpp @@ -103,8 +105,13 @@ set(SRCS hle/service/ldr_ro/ldr_ro.cpp hle/service/ldr_ro/memory_synchronizer.cpp hle/service/mic_u.cpp + hle/service/mvd/mvd.cpp + hle/service/mvd/mvd_std.cpp hle/service/ndm/ndm.cpp hle/service/ndm/ndm_u.cpp + hle/service/nfc/nfc.cpp + hle/service/nfc/nfc_m.cpp + hle/service/nfc/nfc_u.cpp hle/service/news/news.cpp hle/service/news/news_s.cpp hle/service/news/news_u.cpp @@ -119,6 +126,10 @@ set(SRCS hle/service/ptm/ptm_play.cpp hle/service/ptm/ptm_sysm.cpp hle/service/ptm/ptm_u.cpp + hle/service/qtm/qtm.cpp + hle/service/qtm/qtm_s.cpp + hle/service/qtm/qtm_sp.cpp + hle/service/qtm/qtm_u.cpp hle/service/service.cpp hle/service/soc_u.cpp hle/service/srv.cpp @@ -163,10 +174,12 @@ set(HEADERS file_sys/archive_backend.h file_sys/archive_extsavedata.h file_sys/archive_ncch.h + file_sys/archive_other_savedata.h file_sys/archive_romfs.h file_sys/archive_savedata.h file_sys/archive_sdmc.h file_sys/archive_sdmcwriteonly.h + file_sys/archive_source_sd_savedata.h file_sys/archive_systemsavedata.h file_sys/directory_backend.h file_sys/disk_archive.h @@ -252,8 +265,13 @@ set(HEADERS hle/service/ldr_ro/ldr_ro.h hle/service/ldr_ro/memory_synchronizer.h hle/service/mic_u.h + hle/service/mvd/mvd.h + hle/service/mvd/mvd_std.h hle/service/ndm/ndm.h hle/service/ndm/ndm_u.h + hle/service/nfc/nfc.h + hle/service/nfc/nfc_m.h + hle/service/nfc/nfc_u.h hle/service/news/news.h hle/service/news/news_s.h hle/service/news/news_u.h @@ -268,6 +286,10 @@ set(HEADERS hle/service/ptm/ptm_play.h hle/service/ptm/ptm_sysm.h hle/service/ptm/ptm_u.h + hle/service/qtm/qtm.h + hle/service/qtm/qtm_s.h + hle/service/qtm/qtm_sp.h + hle/service/qtm/qtm_u.h hle/service/service.h hle/service/soc_u.h hle/service/srv.h diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index e1c4931ec..5b172df4a 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -64,7 +64,7 @@ private: */ class ExtSaveDataArchive : public SaveDataArchive { public: - ExtSaveDataArchive(const std::string& mount_point) : SaveDataArchive(mount_point) {} + explicit ExtSaveDataArchive(const std::string& mount_point) : SaveDataArchive(mount_point) {} std::string GetName() const override { return "ExtSaveDataArchive: " + mount_point; diff --git a/src/core/file_sys/archive_ncch.h b/src/core/file_sys/archive_ncch.h index 66b8ce75d..753b91f96 100644 --- a/src/core/file_sys/archive_ncch.h +++ b/src/core/file_sys/archive_ncch.h @@ -17,7 +17,7 @@ namespace FileSys { /// File system interface to the NCCH archive class ArchiveFactory_NCCH final : public ArchiveFactory { public: - ArchiveFactory_NCCH(const std::string& mount_point); + explicit ArchiveFactory_NCCH(const std::string& mount_point); std::string GetName() const override { return "NCCH"; diff --git a/src/core/file_sys/archive_other_savedata.cpp b/src/core/file_sys/archive_other_savedata.cpp new file mode 100644 index 000000000..d3cf080da --- /dev/null +++ b/src/core/file_sys/archive_other_savedata.cpp @@ -0,0 +1,145 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <tuple> +#include "core/file_sys/archive_other_savedata.h" +#include "core/file_sys/errors.h" +#include "core/hle/kernel/process.h" +#include "core/hle/service/fs/archive.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +// TODO(wwylele): The storage info in exheader should be checked before accessing these archives + +using Service::FS::MediaType; + +namespace { + +template <typename T> +ResultVal<std::tuple<MediaType, u64>> ParsePath(const Path& path, T program_id_reader) { + if (path.GetType() != Binary) { + LOG_ERROR(Service_FS, "Wrong path type %d", static_cast<int>(path.GetType())); + return ERROR_INVALID_PATH; + } + + std::vector<u8> vec_data = path.AsBinary(); + + if (vec_data.size() != 12) { + LOG_ERROR(Service_FS, "Wrong path length %zu", vec_data.size()); + return ERROR_INVALID_PATH; + } + + const u32* data = reinterpret_cast<const u32*>(vec_data.data()); + auto media_type = static_cast<MediaType>(data[0]); + + if (media_type != MediaType::SDMC && media_type != MediaType::GameCard) { + LOG_ERROR(Service_FS, "Unsupported media type %u", static_cast<u32>(media_type)); + + // Note: this is strange, but the error code was verified with a real 3DS + return ERROR_UNSUPPORTED_OPEN_FLAGS; + } + + return MakeResult<std::tuple<MediaType, u64>>(media_type, program_id_reader(data)); +} + +ResultVal<std::tuple<MediaType, u64>> ParsePathPermitted(const Path& path) { + return ParsePath(path, + [](const u32* data) -> u64 { return (data[1] << 8) | 0x0004000000000000ULL; }); +} + +ResultVal<std::tuple<MediaType, u64>> ParsePathGeneral(const Path& path) { + return ParsePath( + path, [](const u32* data) -> u64 { return data[1] | (static_cast<u64>(data[2]) << 32); }); +} + +} // namespace + +ArchiveFactory_OtherSaveDataPermitted::ArchiveFactory_OtherSaveDataPermitted( + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata) + : sd_savedata_source(sd_savedata) {} + +ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataPermitted::Open( + const Path& path) { + MediaType media_type; + u64 program_id; + CASCADE_RESULT(std::tie(media_type, program_id), ParsePathPermitted(path)); + + if (media_type == MediaType::GameCard) { + LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); + return ERROR_GAMECARD_NOT_INSERTED; + } + + return sd_savedata_source->Open(program_id); +} + +ResultCode ArchiveFactory_OtherSaveDataPermitted::Format( + const Path& path, const FileSys::ArchiveFormatInfo& format_info) { + LOG_ERROR(Service_FS, "Attempted to format a OtherSaveDataPermitted archive."); + return ERROR_INVALID_PATH; +} + +ResultVal<ArchiveFormatInfo> ArchiveFactory_OtherSaveDataPermitted::GetFormatInfo( + const Path& path) const { + MediaType media_type; + u64 program_id; + CASCADE_RESULT(std::tie(media_type, program_id), ParsePathPermitted(path)); + + if (media_type == MediaType::GameCard) { + LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); + return ERROR_GAMECARD_NOT_INSERTED; + } + + return sd_savedata_source->GetFormatInfo(program_id); +} + +ArchiveFactory_OtherSaveDataGeneral::ArchiveFactory_OtherSaveDataGeneral( + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata) + : sd_savedata_source(sd_savedata) {} + +ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataGeneral::Open( + const Path& path) { + MediaType media_type; + u64 program_id; + CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path)); + + if (media_type == MediaType::GameCard) { + LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); + return ERROR_GAMECARD_NOT_INSERTED; + } + + return sd_savedata_source->Open(program_id); +} + +ResultCode ArchiveFactory_OtherSaveDataGeneral::Format( + const Path& path, const FileSys::ArchiveFormatInfo& format_info) { + MediaType media_type; + u64 program_id; + CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path)); + + if (media_type == MediaType::GameCard) { + LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); + return ERROR_GAMECARD_NOT_INSERTED; + } + + return sd_savedata_source->Format(program_id, format_info); +} + +ResultVal<ArchiveFormatInfo> ArchiveFactory_OtherSaveDataGeneral::GetFormatInfo( + const Path& path) const { + MediaType media_type; + u64 program_id; + CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path)); + + if (media_type == MediaType::GameCard) { + LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); + return ERROR_GAMECARD_NOT_INSERTED; + } + + return sd_savedata_source->GetFormatInfo(program_id); +} + +} // namespace FileSys diff --git a/src/core/file_sys/archive_other_savedata.h b/src/core/file_sys/archive_other_savedata.h new file mode 100644 index 000000000..d80725158 --- /dev/null +++ b/src/core/file_sys/archive_other_savedata.h @@ -0,0 +1,52 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/file_sys/archive_source_sd_savedata.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +/// File system interface to the OtherSaveDataPermitted archive +class ArchiveFactory_OtherSaveDataPermitted final : public ArchiveFactory { +public: + explicit ArchiveFactory_OtherSaveDataPermitted( + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source); + + std::string GetName() const override { + return "OtherSaveDataPermitted"; + } + + ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; + ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; + ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; + +private: + std::string mount_point; + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source; +}; + +/// File system interface to the OtherSaveDataGeneral archive +class ArchiveFactory_OtherSaveDataGeneral final : public ArchiveFactory { +public: + explicit ArchiveFactory_OtherSaveDataGeneral( + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source); + + std::string GetName() const override { + return "OtherSaveDataGeneral"; + } + + ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; + ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; + ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; + +private: + std::string mount_point; + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index 8a8082a05..1eaf99b54 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h @@ -20,7 +20,7 @@ namespace FileSys { /// File system interface to the RomFS archive class ArchiveFactory_RomFS final : public ArchiveFactory { public: - ArchiveFactory_RomFS(Loader::AppLoader& app_loader); + explicit ArchiveFactory_RomFS(Loader::AppLoader& app_loader); std::string GetName() const override { return "RomFS"; diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp index ecb44a215..61f7654f7 100644 --- a/src/core/file_sys/archive_savedata.cpp +++ b/src/core/file_sys/archive_savedata.cpp @@ -2,96 +2,29 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <algorithm> -#include <memory> -#include "common/common_types.h" -#include "common/file_util.h" -#include "common/logging/log.h" -#include "common/string_util.h" #include "core/file_sys/archive_savedata.h" -#include "core/file_sys/savedata_archive.h" #include "core/hle/kernel/process.h" -#include "core/hle/service/fs/archive.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // FileSys namespace namespace FileSys { -static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { - return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), - SYSTEM_ID.c_str(), SDCARD_ID.c_str()); -} - -static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { - u32 high = (u32)(program_id >> 32); - u32 low = (u32)(program_id & 0xFFFFFFFF); - return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, - low); -} - -static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { - u32 high = (u32)(program_id >> 32); - u32 low = (u32)(program_id & 0xFFFFFFFF); - return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), - high, low); -} - -ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) - : mount_point(GetSaveDataContainerPath(sdmc_directory)) { - LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); -} +ArchiveFactory_SaveData::ArchiveFactory_SaveData( + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata) + : sd_savedata_source(sd_savedata) {} ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { - std::string concrete_mount_point = - GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); - if (!FileUtil::Exists(concrete_mount_point)) { - // 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. - return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); - } - - auto archive = std::make_unique<SaveDataArchive>(std::move(concrete_mount_point)); - return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); + return sd_savedata_source->Open(Kernel::g_current_process->codeset->program_id); } ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { - std::string concrete_mount_point = - GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); - FileUtil::DeleteDirRecursively(concrete_mount_point); - FileUtil::CreateFullPath(concrete_mount_point); - - // Write the format metadata - std::string metadata_path = - GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); - FileUtil::IOFile file(metadata_path, "wb"); - - if (file.IsOpen()) { - file.WriteBytes(&format_info, sizeof(format_info)); - return RESULT_SUCCESS; - } - return RESULT_SUCCESS; + return sd_savedata_source->Format(Kernel::g_current_process->codeset->program_id, format_info); } ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { - std::string metadata_path = - GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); - FileUtil::IOFile file(metadata_path, "rb"); - - if (!file.IsOpen()) { - LOG_ERROR(Service_FS, "Could not open metadata information for archive"); - // TODO(Subv): Verify error code - return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); - } - - ArchiveFormatInfo info = {}; - file.ReadBytes(&info, sizeof(info)); - return MakeResult<ArchiveFormatInfo>(info); + return sd_savedata_source->GetFormatInfo(Kernel::g_current_process->codeset->program_id); } } // namespace FileSys diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h index 6a372865a..41aa6f189 100644 --- a/src/core/file_sys/archive_savedata.h +++ b/src/core/file_sys/archive_savedata.h @@ -4,10 +4,7 @@ #pragma once -#include <memory> -#include <string> -#include "core/file_sys/archive_backend.h" -#include "core/hle/result.h" +#include "core/file_sys/archive_source_sd_savedata.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // FileSys namespace @@ -17,7 +14,7 @@ namespace FileSys { /// File system interface to the SaveData archive class ArchiveFactory_SaveData final : public ArchiveFactory { public: - ArchiveFactory_SaveData(const std::string& mount_point); + explicit ArchiveFactory_SaveData(std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source); std::string GetName() const override { return "SaveData"; @@ -30,6 +27,7 @@ public: private: std::string mount_point; + std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source; }; } // namespace FileSys diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 9d99b110c..f6c70bfcc 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h @@ -17,7 +17,7 @@ namespace FileSys { /// Archive backend for SDMC archive class SDMCArchive : public ArchiveBackend { public: - SDMCArchive(const std::string& mount_point_) : mount_point(mount_point_) {} + explicit SDMCArchive(const std::string& mount_point_) : mount_point(mount_point_) {} std::string GetName() const override { return "SDMCArchive: " + mount_point; @@ -43,7 +43,7 @@ protected: /// File system interface to the SDMC archive class ArchiveFactory_SDMC final : public ArchiveFactory { public: - ArchiveFactory_SDMC(const std::string& mount_point); + explicit ArchiveFactory_SDMC(const std::string& mount_point); /** * Initialize the archive. diff --git a/src/core/file_sys/archive_sdmcwriteonly.h b/src/core/file_sys/archive_sdmcwriteonly.h index ed977485a..9cd38d96f 100644 --- a/src/core/file_sys/archive_sdmcwriteonly.h +++ b/src/core/file_sys/archive_sdmcwriteonly.h @@ -19,7 +19,7 @@ namespace FileSys { */ class SDMCWriteOnlyArchive : public SDMCArchive { public: - SDMCWriteOnlyArchive(const std::string& mount_point) : SDMCArchive(mount_point) {} + explicit SDMCWriteOnlyArchive(const std::string& mount_point) : SDMCArchive(mount_point) {} std::string GetName() const override { return "SDMCWriteOnlyArchive: " + mount_point; @@ -34,7 +34,7 @@ public: /// File system interface to the SDMC write-only archive class ArchiveFactory_SDMCWriteOnly final : public ArchiveFactory { public: - ArchiveFactory_SDMCWriteOnly(const std::string& mount_point); + explicit ArchiveFactory_SDMCWriteOnly(const std::string& mount_point); /** * Initialize the archive. diff --git a/src/core/file_sys/archive_source_sd_savedata.cpp b/src/core/file_sys/archive_source_sd_savedata.cpp new file mode 100644 index 000000000..2d8a950a3 --- /dev/null +++ b/src/core/file_sys/archive_source_sd_savedata.cpp @@ -0,0 +1,93 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/file_util.h" +#include "common/logging/log.h" +#include "common/string_util.h" +#include "core/file_sys/archive_source_sd_savedata.h" +#include "core/file_sys/savedata_archive.h" +#include "core/hle/service/fs/archive.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +namespace { + +std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { + return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), + SYSTEM_ID.c_str(), SDCARD_ID.c_str()); +} + +std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { + u32 high = static_cast<u32>(program_id >> 32); + u32 low = static_cast<u32>(program_id & 0xFFFFFFFF); + return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, + low); +} + +std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { + u32 high = static_cast<u32>(program_id >> 32); + u32 low = static_cast<u32>(program_id & 0xFFFFFFFF); + return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), + high, low); +} + +} // namespace + +ArchiveSource_SDSaveData::ArchiveSource_SDSaveData(const std::string& sdmc_directory) + : mount_point(GetSaveDataContainerPath(sdmc_directory)) { + LOG_INFO(Service_FS, "Directory %s set as SaveData.", mount_point.c_str()); +} + +ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveSource_SDSaveData::Open(u64 program_id) { + std::string concrete_mount_point = GetSaveDataPath(mount_point, program_id); + if (!FileUtil::Exists(concrete_mount_point)) { + // 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. + return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, + ErrorSummary::InvalidState, ErrorLevel::Status); + } + + auto archive = std::make_unique<SaveDataArchive>(std::move(concrete_mount_point)); + return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); +} + +ResultCode ArchiveSource_SDSaveData::Format(u64 program_id, + const FileSys::ArchiveFormatInfo& format_info) { + std::string concrete_mount_point = GetSaveDataPath(mount_point, program_id); + FileUtil::DeleteDirRecursively(concrete_mount_point); + FileUtil::CreateFullPath(concrete_mount_point); + + // Write the format metadata + std::string metadata_path = GetSaveDataMetadataPath(mount_point, program_id); + FileUtil::IOFile file(metadata_path, "wb"); + + if (file.IsOpen()) { + file.WriteBytes(&format_info, sizeof(format_info)); + return RESULT_SUCCESS; + } + return RESULT_SUCCESS; +} + +ResultVal<ArchiveFormatInfo> ArchiveSource_SDSaveData::GetFormatInfo(u64 program_id) const { + std::string metadata_path = GetSaveDataMetadataPath(mount_point, program_id); + FileUtil::IOFile file(metadata_path, "rb"); + + if (!file.IsOpen()) { + LOG_ERROR(Service_FS, "Could not open metadata information for archive"); + // TODO(Subv): Verify error code + return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, + ErrorSummary::InvalidState, ErrorLevel::Status); + } + + ArchiveFormatInfo info = {}; + file.ReadBytes(&info, sizeof(info)); + return MakeResult<ArchiveFormatInfo>(info); +} + +} // namespace FileSys diff --git a/src/core/file_sys/archive_source_sd_savedata.h b/src/core/file_sys/archive_source_sd_savedata.h new file mode 100644 index 000000000..b33126c31 --- /dev/null +++ b/src/core/file_sys/archive_source_sd_savedata.h @@ -0,0 +1,30 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include "core/file_sys/archive_backend.h" +#include "core/hle/result.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +/// A common source of SD save data archive +class ArchiveSource_SDSaveData { +public: + explicit ArchiveSource_SDSaveData(const std::string& mount_point); + + ResultVal<std::unique_ptr<ArchiveBackend>> Open(u64 program_id); + ResultCode Format(u64 program_id, const FileSys::ArchiveFormatInfo& format_info); + ResultVal<ArchiveFormatInfo> GetFormatInfo(u64 program_id) const; + +private: + std::string mount_point; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h index a24b89f2b..52eb6c630 100644 --- a/src/core/file_sys/archive_systemsavedata.h +++ b/src/core/file_sys/archive_systemsavedata.h @@ -18,7 +18,7 @@ namespace FileSys { /// File system interface to the SystemSaveData archive class ArchiveFactory_SystemSaveData final : public ArchiveFactory { public: - ArchiveFactory_SystemSaveData(const std::string& mount_point); + explicit ArchiveFactory_SystemSaveData(const std::string& mount_point); ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h index fd1b07df0..4d5f62b08 100644 --- a/src/core/file_sys/errors.h +++ b/src/core/file_sys/errors.h @@ -36,5 +36,8 @@ const ResultCode ERROR_ALREADY_EXISTS(ErrorDescription::FS_AlreadyExists, ErrorM ErrorSummary::NothingHappened, ErrorLevel::Status); const ResultCode ERROR_DIRECTORY_NOT_EMPTY(ErrorDescription::FS_DirectoryNotEmpty, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); +const ResultCode ERROR_GAMECARD_NOT_INSERTED(ErrorDescription::FS_GameCardNotInserted, + ErrorModule::FS, ErrorSummary::NotFound, + ErrorLevel::Status); } // namespace FileSys diff --git a/src/core/file_sys/path_parser.h b/src/core/file_sys/path_parser.h index 990802579..b9f52f65d 100644 --- a/src/core/file_sys/path_parser.h +++ b/src/core/file_sys/path_parser.h @@ -17,7 +17,7 @@ namespace FileSys { */ class PathParser { public: - PathParser(const Path& path); + explicit PathParser(const Path& path); /** * Checks if the Path is valid. diff --git a/src/core/file_sys/savedata_archive.h b/src/core/file_sys/savedata_archive.h index 2fb6c452a..176d35710 100644 --- a/src/core/file_sys/savedata_archive.h +++ b/src/core/file_sys/savedata_archive.h @@ -18,7 +18,7 @@ namespace FileSys { /// Archive backend for general save data archive type (SaveData and SystemSaveData) class SaveDataArchive : public ArchiveBackend { public: - SaveDataArchive(const std::string& mount_point_) : mount_point(mount_point_) {} + explicit SaveDataArchive(const std::string& mount_point_) : mount_point(mount_point_) {} std::string GetName() const override { return "SaveDataArchive: " + mount_point; diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp index 4311d9897..645b2d5fe 100644 --- a/src/core/hle/applets/applet.cpp +++ b/src/core/hle/applets/applet.cpp @@ -101,6 +101,10 @@ ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter) return result; } +bool Applet::IsRunning() const { + return is_running; +} + bool IsLibraryAppletRunning() { // Check the applets map for instances of any applet for (auto itr = applets.begin(); itr != applets.end(); ++itr) diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h index bfdcad126..ebeed9813 100644 --- a/src/core/hle/applets/applet.h +++ b/src/core/hle/applets/applet.h @@ -13,8 +13,7 @@ namespace Applets { class Applet { public: - virtual ~Applet() {} - Applet(Service::APT::AppletId id) : id(id) {} + virtual ~Applet() = default; /** * Creates an instance of the Applet subclass identified by the parameter. @@ -48,7 +47,7 @@ public: /** * Whether the applet is currently executing instead of the host application or not. */ - virtual bool IsRunning() const = 0; + bool IsRunning() const; /** * Handles an update tick for the Applet, lets it update the screen, send commands, etc. @@ -56,6 +55,8 @@ public: virtual void Update() = 0; protected: + explicit Applet(Service::APT::AppletId id) : id(id) {} + /** * Handles the Applet start event, triggered from the application. * @param parameter Parameter data to handle. @@ -65,6 +66,9 @@ protected: Service::APT::AppletId id; ///< Id of this Applet std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet + + /// Whether this applet is currently running instead of the host application or not. + bool is_running = false; }; /// Returns whether a library applet is currently running diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp index e1379ac4d..75d7fd9fc 100644 --- a/src/core/hle/applets/erreula.cpp +++ b/src/core/hle/applets/erreula.cpp @@ -47,7 +47,7 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param } ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { - started = true; + is_running = true; // TODO(Subv): Set the expected fields in the response buffer before resending it to the // application. @@ -62,7 +62,7 @@ ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parame message.sender_id = static_cast<u32>(id); Service::APT::SendParameter(message); - started = false; + is_running = false; return RESULT_SUCCESS; } diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h index a7ec7ec01..681bbea0c 100644 --- a/src/core/hle/applets/erreula.h +++ b/src/core/hle/applets/erreula.h @@ -17,18 +17,12 @@ public: ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; void Update() override; - bool IsRunning() const override { - return started; - } +private: /// This SharedMemory will be created when we receive the LibAppJustStarted message. /// It holds the framebuffer info retrieved by the application with /// GSPGPU::ImportDisplayCaptureInfo Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; - -private: - /// Whether this applet is currently running instead of the host application or not. - bool started = false; }; } // namespace Applets diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index 3455b9201..07c7f5b99 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp @@ -55,7 +55,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p } ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { - started = true; + is_running = true; // TODO(Subv): Set the expected fields in the response buffer before resending it to the // application. @@ -78,7 +78,7 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa message.sender_id = static_cast<u32>(id); Service::APT::SendParameter(message); - started = false; + is_running = false; return RESULT_SUCCESS; } diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index e3ab9f0cd..ec00e29d2 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h @@ -65,23 +65,18 @@ ASSERT_REG_POSITION(unk_6C, 0x6C); class MiiSelector final : public Applet { public: - MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) {} + MiiSelector(Service::APT::AppletId id) : Applet(id) {} ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; void Update() override; - bool IsRunning() const override { - return started; - } +private: /// This SharedMemory will be created when we receive the LibAppJustStarted message. /// It holds the framebuffer info retrieved by the application with /// GSPGPU::ImportDisplayCaptureInfo Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; - /// Whether this applet is currently running instead of the host application or not. - bool started; - MiiConfig config; }; } diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 1e21337f5..edd30d7ef 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp @@ -70,7 +70,7 @@ ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter cons DrawScreenKeyboard(); - started = true; + is_running = true; return RESULT_SUCCESS; } @@ -113,7 +113,7 @@ void SoftwareKeyboard::Finalize() { message.sender_id = static_cast<u32>(id); Service::APT::SendParameter(message); - started = false; + is_running = false; } } } // namespace diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h index ea0b1fba9..cc92a8f19 100644 --- a/src/core/hle/applets/swkbd.h +++ b/src/core/hle/applets/swkbd.h @@ -52,14 +52,11 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config class SoftwareKeyboard final : public Applet { public: - SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) {} + SoftwareKeyboard(Service::APT::AppletId id) : Applet(id) {} ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; void Update() override; - bool IsRunning() const override { - return started; - } /** * Draws a keyboard to the current bottom screen framebuffer. @@ -72,6 +69,7 @@ public: */ void Finalize(); +private: /// This SharedMemory will be created when we receive the LibAppJustStarted message. /// It holds the framebuffer info retrieved by the application with /// GSPGPU::ImportDisplayCaptureInfo @@ -82,9 +80,6 @@ public: /// Configuration of this instance of the SoftwareKeyboard, as received from the application SoftwareKeyboardConfig config; - - /// Whether this applet is currently running instead of the host application or not. - bool started; }; } } // namespace diff --git a/src/core/hle/result.h b/src/core/hle/result.h index f7356f9d8..8d29117a8 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -22,6 +22,7 @@ enum class ErrorDescription : u32 { FS_ArchiveNotMounted = 101, FS_FileNotFound = 112, FS_PathNotFound = 113, + FS_GameCardNotInserted = 141, FS_NotFound = 120, FS_FileAlreadyExists = 180, FS_DirectoryAlreadyExists = 185, diff --git a/src/core/hle/service/act_a.cpp b/src/core/hle/service/act_a.cpp index 3a775fa90..35ba71f79 100644 --- a/src/core/hle/service/act_a.cpp +++ b/src/core/hle/service/act_a.cpp @@ -10,6 +10,13 @@ namespace ACT_A { const Interface::FunctionInfo FunctionTable[] = { + // act:u shared commands + {0x00010084, nullptr, "Initialize"}, + {0x00020040, nullptr, "GetErrorCode"}, + {0x000600C2, nullptr, "GetAccountDataBlock"}, + {0x000B0042, nullptr, "AcquireEulaList"}, + {0x000D0040, nullptr, "GenerateUuid"}, + // act:a {0x041300C2, nullptr, "UpdateMiiImage"}, {0x041B0142, nullptr, "AgreeEula"}, {0x04210042, nullptr, "UploadMii"}, diff --git a/src/core/hle/service/act_u.cpp b/src/core/hle/service/act_u.cpp index 05de4d002..1b871d441 100644 --- a/src/core/hle/service/act_u.cpp +++ b/src/core/hle/service/act_u.cpp @@ -10,10 +10,13 @@ namespace ACT_U { const Interface::FunctionInfo FunctionTable[] = { + // clang-format off {0x00010084, nullptr, "Initialize"}, {0x00020040, nullptr, "GetErrorCode"}, {0x000600C2, nullptr, "GetAccountDataBlock"}, + {0x000B0042, nullptr, "AcquireEulaList"}, {0x000D0040, nullptr, "GenerateUuid"}, + // clang-format on }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index f7a990d69..d344a622f 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -20,7 +20,7 @@ static std::array<u32, 3> am_titles_list_count = {0, 0, 0}; static u32 am_ticket_count = 0; static u32 am_ticket_list_count = 0; -void GetTitleCount(Service::Interface* self) { +void GetNumPrograms(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 media_type = cmd_buff[1] & 0xFF; @@ -81,7 +81,7 @@ void DeleteContents(Service::Interface* self) { media_type, title_id, am_content_count[media_type], content_ids_pointer); } -void GetTitleList(Service::Interface* self) { +void GetProgramList(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 media_type = cmd_buff[2] & 0xFF; @@ -97,7 +97,7 @@ void GetTitleList(Service::Interface* self) { media_type, am_titles_list_count[media_type], title_ids_output_pointer); } -void GetTitleInfo(Service::Interface* self) { +void GetProgramInfos(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 media_type = cmd_buff[1] & 0xFF; @@ -113,7 +113,7 @@ void GetTitleInfo(Service::Interface* self) { } void GetDataTitleInfos(Service::Interface* self) { - GetTitleInfo(self); + GetProgramInfos(self); LOG_WARNING(Service_AM, "(STUBBED) called"); } @@ -151,7 +151,7 @@ void DeleteTicket(Service::Interface* self) { LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id); } -void GetTicketCount(Service::Interface* self) { +void GetNumTickets(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 5676cdd5f..9bc2ca305 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -11,7 +11,7 @@ class Interface; namespace AM { /** - * AM::GetTitleCount service function + * AM::GetNumPrograms service function * Gets the number of installed titles in the requested media type * Inputs: * 0 : Command header (0x00010040) @@ -20,7 +20,7 @@ namespace AM { * 1 : Result, 0 on success, otherwise error code * 2 : The number of titles in the requested media type */ -void GetTitleCount(Service::Interface* self); +void GetNumPrograms(Service::Interface* self); /** * AM::FindContentInfos service function @@ -62,7 +62,7 @@ void ListContentInfos(Service::Interface* self); void DeleteContents(Service::Interface* self); /** - * AM::GetTitleList service function + * AM::GetProgramList service function * Loads information about the desired number of titles from the desired media type into an array * Inputs: * 1 : Title count @@ -72,10 +72,10 @@ void DeleteContents(Service::Interface* self); * 1 : Result, 0 on success, otherwise error code * 2 : The number of titles loaded from the requested media type */ -void GetTitleList(Service::Interface* self); +void GetProgramList(Service::Interface* self); /** - * AM::GetTitleInfo service function + * AM::GetProgramInfos service function * Inputs: * 1 : u8 Mediatype * 2 : Total titles @@ -84,11 +84,11 @@ void GetTitleList(Service::Interface* self); * Outputs: * 1 : Result, 0 on success, otherwise error code */ -void GetTitleInfo(Service::Interface* self); +void GetProgramInfos(Service::Interface* self); /** * AM::GetDataTitleInfos service function - * Wrapper for AM::GetTitleInfo + * Wrapper for AM::GetProgramInfos * Inputs: * 1 : u8 Mediatype * 2 : Total titles @@ -135,12 +135,12 @@ void GetNumContentInfos(Service::Interface* self); void DeleteTicket(Service::Interface* self); /** - * AM::GetTicketCount service function + * AM::GetNumTickets service function * Outputs: * 1 : Result, 0 on success, otherwise error code - * 2 : Total titles + * 2 : Number of tickets */ -void GetTicketCount(Service::Interface* self); +void GetNumTickets(Service::Interface* self); /** * AM::GetTicketList service function diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp index bfc1ca6bd..218375c8f 100644 --- a/src/core/hle/service/am/am_app.cpp +++ b/src/core/hle/service/am/am_app.cpp @@ -14,9 +14,14 @@ const Interface::FunctionInfo FunctionTable[] = { {0x10030142, ListContentInfos, "ListContentInfos"}, {0x10040102, DeleteContents, "DeleteContents"}, {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, + {0x10060080, nullptr, "GetNumDataTitleTickets"}, {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, + {0x100801C2, nullptr, "GetItemRights"}, {0x100900C0, nullptr, "IsDataTitleInUse"}, {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, + {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, + {0x100C0142, nullptr, "ListExistingContentInfos"}, + {0x100D0084, nullptr, "GetPatchTitleInfos"}, }; AM_APP_Interface::AM_APP_Interface() { diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp index 3a597a34c..f3cd1d23f 100644 --- a/src/core/hle/service/am/am_net.cpp +++ b/src/core/hle/service/am/am_net.cpp @@ -9,61 +9,116 @@ namespace Service { namespace AM { const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetTitleCount, "GetTitleCount"}, - {0x00020082, GetTitleList, "GetTitleList"}, - {0x00030084, GetTitleInfo, "GetTitleInfo"}, - {0x000400C0, nullptr, "DeleteApplicationTitle"}, - {0x000500C0, nullptr, "GetTitleProductCode"}, - {0x000600C0, nullptr, "GetTitleExtDataId"}, + {0x00010040, GetNumPrograms, "GetNumPrograms"}, + {0x00020082, GetProgramList, "GetProgramList"}, + {0x00030084, GetProgramInfos, "GetProgramInfos"}, + {0x000400C0, nullptr, "DeleteUserProgram"}, + {0x000500C0, nullptr, "GetProductCode"}, + {0x000600C0, nullptr, "GetStorageId"}, {0x00070080, DeleteTicket, "DeleteTicket"}, - {0x00080000, GetTicketCount, "GetTicketCount"}, + {0x00080000, GetNumTickets, "GetNumTickets"}, {0x00090082, GetTicketList, "GetTicketList"}, {0x000A0000, nullptr, "GetDeviceID"}, - {0x000D0084, nullptr, "GetPendingTitleInfo"}, - {0x000E00C0, nullptr, "DeletePendingTitle"}, - {0x00140040, nullptr, "FinalizePendingTitles"}, - {0x00150040, nullptr, "DeleteAllPendingTitles"}, + {0x000B0040, nullptr, "GetNumImportTitleContexts"}, + {0x000C0082, nullptr, "GetImportTitleContextList"}, + {0x000D0084, nullptr, "GetImportTitleContexts"}, + {0x000E00C0, nullptr, "DeleteImportTitleContext"}, + {0x000F00C0, nullptr, "GetNumImportContentContexts"}, + {0x00100102, nullptr, "GetImportContentContextList"}, + {0x00110104, nullptr, "GetImportContentContexts"}, + {0x00120102, nullptr, "DeleteImportContentContexts"}, + {0x00130040, nullptr, "NeedsCleanup"}, + {0x00140040, nullptr, "DoCleanup"}, + {0x00150040, nullptr, "DeleteAllImportContexts"}, + {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, + {0x00170044, nullptr, "ImportTwlBackupLegacy"}, {0x00180080, nullptr, "InitializeTitleDatabase"}, - {0x00190040, nullptr, "ReloadDBS"}, - {0x001A00C0, nullptr, "GetDSiWareExportSize"}, - {0x001B0144, nullptr, "ExportDSiWare"}, - {0x001C0084, nullptr, "ImportDSiWare"}, - {0x00230080, nullptr, "TitleIDListGetTotal2"}, - {0x002400C2, nullptr, "GetTitleIDList2"}, - {0x04010080, nullptr, "InstallFIRM"}, - {0x04020040, nullptr, "StartInstallCIADB0"}, - {0x04030000, nullptr, "StartInstallCIADB1"}, - {0x04040002, nullptr, "AbortCIAInstall"}, - {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, - {0x04060002, nullptr, "CloseCIA"}, - {0x040700C2, nullptr, "FinalizeTitlesInstall"}, - {0x04080042, nullptr, "GetCiaFileInfo"}, - {0x040E00C2, nullptr, "InstallTitlesFinish"}, - {0x040F0000, nullptr, "InstallNATIVEFIRM"}, - {0x041000C0, nullptr, "DeleteTitle"}, - {0x04120000, nullptr, "Initialize"}, - {0x041700C0, nullptr, "MigrateAGBtoSAV"}, - {0x08010000, nullptr, "OpenTicket"}, - {0x08020002, nullptr, "TicketAbortInstall"}, - {0x08030002, nullptr, "TicketFinalizeInstall"}, - {0x08040100, nullptr, "InstallTitleBegin"}, - {0x08050000, nullptr, "InstallTitleAbort"}, - {0x080600C0, nullptr, "InstallTitleResume"}, - {0x08070000, nullptr, "InstallTitleAbortTMD"}, - {0x08080000, nullptr, "InstallTitleFinish"}, - {0x080A0000, nullptr, "OpenTMD"}, - {0x080B0002, nullptr, "TMDAbortInstall"}, - {0x080C0042, nullptr, "TMDFinalizeInstall"}, - {0x080E0040, nullptr, "OpenContentCreate"}, - {0x080F0002, nullptr, "ContentAbortInstall"}, - {0x08100040, nullptr, "OpenContentResume"}, - {0x08120002, nullptr, "ContentFinalizeInstall"}, - {0x08130000, nullptr, "GetTotalContents"}, - {0x08140042, nullptr, "GetContentIndexes"}, - {0x08150044, nullptr, "GetContentsInfo"}, - {0x08180042, nullptr, "GetCTCert"}, - {0x08190108, nullptr, "SetCertificates"}, - {0x081B00C2, nullptr, "InstallTitlesFinish"}, + {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, + {0x001A00C0, nullptr, "CalcTwlBackupSize"}, + {0x001B0144, nullptr, "ExportTwlBackup"}, + {0x001C0084, nullptr, "ImportTwlBackup"}, + {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, + {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, + {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, + {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, + {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, + {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, + {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, + {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, + {0x002500C0, nullptr, "CheckContentRights"}, + {0x00260044, nullptr, "GetTicketLimitInfos"}, + {0x00270044, nullptr, "GetDemoLaunchInfos"}, + {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, + {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, + {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, + {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, + {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, + {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, + {0x04010080, nullptr, "UpdateFirmwareTo"}, + {0x04020040, nullptr, "BeginImportProgram"}, + {0x04030000, nullptr, "BeginImportProgramTemporarily"}, + {0x04040002, nullptr, "CancelImportProgram"}, + {0x04050002, nullptr, "EndImportProgram"}, + {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, + {0x040700C2, nullptr, "CommitImportPrograms"}, + {0x04080042, nullptr, "GetProgramInfoFromCia"}, + {0x04090004, nullptr, "GetSystemMenuDataFromCia"}, + {0x040A0002, nullptr, "GetDependencyListFromCia"}, + {0x040B0002, nullptr, "GetTransferSizeFromCia"}, + {0x040C0002, nullptr, "GetCoreVersionFromCia"}, + {0x040D0042, nullptr, "GetRequiredSizeFromCia"}, + {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, + {0x040F0000, nullptr, "UpdateFirmwareAuto"}, + {0x041000C0, nullptr, "DeleteProgram"}, + {0x04110044, nullptr, "GetTwlProgramListForReboot"}, + {0x04120000, nullptr, "GetSystemUpdaterMutex"}, + {0x04130002, nullptr, "GetMetaSizeFromCia"}, + {0x04140044, nullptr, "GetMetaDataFromCia"}, + {0x04150080, nullptr, "CheckDemoLaunchRights"}, + {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, + {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, + {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, + {0x04190000, nullptr, "BeginImportSystemProgram"}, + {0x08010000, nullptr, "BeginImportTicket"}, + {0x08020002, nullptr, "CancelImportTicket"}, + {0x08030002, nullptr, "EndImportTicket"}, + {0x08040100, nullptr, "BeginImportTitle"}, + {0x08050000, nullptr, "StopImportTitle"}, + {0x080600C0, nullptr, "ResumeImportTitle"}, + {0x08070000, nullptr, "CancelImportTitle"}, + {0x08080000, nullptr, "EndImportTitle"}, + {0x080900C2, nullptr, "CommitImportTitles"}, + {0x080A0000, nullptr, "BeginImportTmd"}, + {0x080B0002, nullptr, "CancelImportTmd"}, + {0x080C0042, nullptr, "EndImportTmd"}, + {0x080D0042, nullptr, "CreateImportContentContexts"}, + {0x080E0040, nullptr, "BeginImportContent"}, + {0x080F0002, nullptr, "StopImportContent"}, + {0x08100040, nullptr, "ResumeImportContent"}, + {0x08110002, nullptr, "CancelImportContent"}, + {0x08120002, nullptr, "EndImportContent"}, + {0x08130000, nullptr, "GetNumCurrentImportContentContexts"}, + {0x08140042, nullptr, "GetCurrentImportContentContextList"}, + {0x08150044, nullptr, "GetCurrentImportContentContexts"}, + {0x08160146, nullptr, "Sign"}, + {0x08170146, nullptr, "Verify"}, + {0x08180042, nullptr, "GetDeviceCert"}, + {0x08190108, nullptr, "ImportCertificates"}, + {0x081A0042, nullptr, "ImportCertificate"}, + {0x081B00C2, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"}, + {0x081C0100, nullptr, "DeleteTicketId"}, + {0x081D0080, nullptr, "GetNumTicketIds"}, + {0x081E0102, nullptr, "GetTicketIdList"}, + {0x081F0080, nullptr, "GetNumTicketsOfProgram"}, + {0x08200102, nullptr, "ListTicketInfos"}, + {0x08210142, nullptr, "GetRightsOnlyTicketData"}, + {0x08220000, nullptr, "GetNumCurrentContentInfos"}, + {0x08230044, nullptr, "FindCurrentContentInfos"}, + {0x08240082, nullptr, "ListCurrentContentInfos"}, + {0x08250102, nullptr, "CalculateContextRequiredSize"}, + {0x08260042, nullptr, "UpdateImportContentContexts"}, + {0x08270000, nullptr, "DeleteAllDemoLaunchInfos"}, + {0x082800C0, nullptr, "BeginImportTitleForOverWrite"}, }; AM_NET_Interface::AM_NET_Interface() { diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp index a2268303c..949b3591d 100644 --- a/src/core/hle/service/am/am_sys.cpp +++ b/src/core/hle/service/am/am_sys.cpp @@ -9,27 +9,64 @@ namespace Service { namespace AM { const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetTitleCount, "GetTitleCount"}, - {0x00020082, GetTitleList, "GetTitleList"}, - {0x00030084, GetTitleInfo, "GetTitleInfo"}, - {0x000400C0, nullptr, "DeleteApplicationTitle"}, - {0x000500C0, nullptr, "GetTitleProductCode"}, - {0x000600C0, nullptr, "GetTitleExtDataId"}, + {0x00010040, GetNumPrograms, "GetNumPrograms"}, + {0x00020082, GetProgramList, "GetProgramList"}, + {0x00030084, GetProgramInfos, "GetProgramInfos"}, + {0x000400C0, nullptr, "DeleteUserProgram"}, + {0x000500C0, nullptr, "GetProductCode"}, + {0x000600C0, nullptr, "GetStorageId"}, {0x00070080, DeleteTicket, "DeleteTicket"}, - {0x00080000, GetTicketCount, "GetTicketCount"}, + {0x00080000, GetNumTickets, "GetNumTickets"}, {0x00090082, GetTicketList, "GetTicketList"}, {0x000A0000, nullptr, "GetDeviceID"}, - {0x000D0084, nullptr, "GetPendingTitleInfo"}, - {0x000E00C0, nullptr, "DeletePendingTitle"}, - {0x00140040, nullptr, "FinalizePendingTitles"}, - {0x00150040, nullptr, "DeleteAllPendingTitles"}, + {0x000B0040, nullptr, "GetNumImportTitleContexts"}, + {0x000C0082, nullptr, "GetImportTitleContextList"}, + {0x000D0084, nullptr, "GetImportTitleContexts"}, + {0x000E00C0, nullptr, "DeleteImportTitleContext"}, + {0x000F00C0, nullptr, "GetNumImportContentContexts"}, + {0x00100102, nullptr, "GetImportContentContextList"}, + {0x00110104, nullptr, "GetImportContentContexts"}, + {0x00120102, nullptr, "DeleteImportContentContexts"}, + {0x00130040, nullptr, "NeedsCleanup"}, + {0x00140040, nullptr, "DoCleanup"}, + {0x00150040, nullptr, "DeleteAllImportContexts"}, + {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, + {0x00170044, nullptr, "ImportTwlBackupLegacy"}, {0x00180080, nullptr, "InitializeTitleDatabase"}, - {0x00190040, nullptr, "ReloadDBS"}, - {0x001A00C0, nullptr, "GetDSiWareExportSize"}, - {0x001B0144, nullptr, "ExportDSiWare"}, - {0x001C0084, nullptr, "ImportDSiWare"}, - {0x00230080, nullptr, "GetPendingTitleCount"}, - {0x002400C2, nullptr, "GetPendingTitleList"}, + {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, + {0x001A00C0, nullptr, "CalcTwlBackupSize"}, + {0x001B0144, nullptr, "ExportTwlBackup"}, + {0x001C0084, nullptr, "ImportTwlBackup"}, + {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, + {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, + {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, + {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, + {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, + {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, + {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, + {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, + {0x002500C0, nullptr, "CheckContentRights"}, + {0x00260044, nullptr, "GetTicketLimitInfos"}, + {0x00270044, nullptr, "GetDemoLaunchInfos"}, + {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, + {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, + {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, + {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, + {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, + {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, + {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, + {0x10020104, FindContentInfos, "FindContentInfos"}, + {0x10030142, ListContentInfos, "ListContentInfos"}, + {0x10040102, DeleteContents, "DeleteContents"}, + {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, + {0x10060080, nullptr, "GetNumDataTitleTickets"}, + {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, + {0x100801C2, nullptr, "GetItemRights"}, + {0x100900C0, nullptr, "IsDataTitleInUse"}, + {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, + {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, + {0x100C0142, nullptr, "ListExistingContentInfos"}, + {0x100D0084, nullptr, "GetPatchTitleInfos"}, }; AM_SYS_Interface::AM_SYS_Interface() { diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp index 151b5e42b..354d51610 100644 --- a/src/core/hle/service/am/am_u.cpp +++ b/src/core/hle/service/am/am_u.cpp @@ -9,40 +9,76 @@ namespace Service { namespace AM { const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetTitleCount, "GetTitleCount"}, - {0x00020082, GetTitleList, "GetTitleList"}, - {0x00030084, GetTitleInfo, "GetTitleInfo"}, - {0x000400C0, nullptr, "DeleteApplicationTitle"}, - {0x000500C0, nullptr, "GetTitleProductCode"}, - {0x000600C0, nullptr, "GetTitleExtDataId"}, + {0x00010040, GetNumPrograms, "GetNumPrograms"}, + {0x00020082, GetProgramList, "GetProgramList"}, + {0x00030084, GetProgramInfos, "GetProgramInfos"}, + {0x000400C0, nullptr, "DeleteUserProgram"}, + {0x000500C0, nullptr, "GetProductCode"}, + {0x000600C0, nullptr, "GetStorageId"}, {0x00070080, DeleteTicket, "DeleteTicket"}, - {0x00080000, GetTicketCount, "GetTicketCount"}, + {0x00080000, GetNumTickets, "GetNumTickets"}, {0x00090082, GetTicketList, "GetTicketList"}, {0x000A0000, nullptr, "GetDeviceID"}, - {0x000D0084, nullptr, "GetPendingTitleInfo"}, - {0x000E00C0, nullptr, "DeletePendingTitle"}, - {0x00140040, nullptr, "FinalizePendingTitles"}, - {0x00150040, nullptr, "DeleteAllPendingTitles"}, + {0x000B0040, nullptr, "GetNumImportTitleContexts"}, + {0x000C0082, nullptr, "GetImportTitleContextList"}, + {0x000D0084, nullptr, "GetImportTitleContexts"}, + {0x000E00C0, nullptr, "DeleteImportTitleContext"}, + {0x000F00C0, nullptr, "GetNumImportContentContexts"}, + {0x00100102, nullptr, "GetImportContentContextList"}, + {0x00110104, nullptr, "GetImportContentContexts"}, + {0x00120102, nullptr, "DeleteImportContentContexts"}, + {0x00130040, nullptr, "NeedsCleanup"}, + {0x00140040, nullptr, "DoCleanup"}, + {0x00150040, nullptr, "DeleteAllImportContexts"}, + {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, + {0x00170044, nullptr, "ImportTwlBackupLegacy"}, {0x00180080, nullptr, "InitializeTitleDatabase"}, - {0x00190040, nullptr, "ReloadDBS"}, - {0x001A00C0, nullptr, "GetDSiWareExportSize"}, - {0x001B0144, nullptr, "ExportDSiWare"}, - {0x001C0084, nullptr, "ImportDSiWare"}, - {0x00230080, nullptr, "TitleIDListGetTotal2"}, - {0x002400C2, nullptr, "GetTitleIDList2"}, - {0x04010080, nullptr, "InstallFIRM"}, - {0x04020040, nullptr, "StartInstallCIADB0"}, - {0x04030000, nullptr, "StartInstallCIADB1"}, - {0x04040002, nullptr, "AbortCIAInstall"}, - {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, - {0x04060002, nullptr, "CloseCIA"}, - {0x040700C2, nullptr, "FinalizeTitlesInstall"}, - {0x04080042, nullptr, "GetCiaFileInfo"}, - {0x040E00C2, nullptr, "InstallTitlesFinish"}, - {0x040F0000, nullptr, "InstallNATIVEFIRM"}, - {0x041000C0, nullptr, "DeleteTitle"}, - {0x04120000, nullptr, "Initialize"}, - {0x041700C0, nullptr, "MigrateAGBtoSAV"}, + {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, + {0x001A00C0, nullptr, "CalcTwlBackupSize"}, + {0x001B0144, nullptr, "ExportTwlBackup"}, + {0x001C0084, nullptr, "ImportTwlBackup"}, + {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, + {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, + {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, + {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, + {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, + {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, + {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, + {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, + {0x002500C0, nullptr, "CheckContentRights"}, + {0x00260044, nullptr, "GetTicketLimitInfos"}, + {0x00270044, nullptr, "GetDemoLaunchInfos"}, + {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, + {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, + {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, + {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, + {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, + {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, + {0x04010080, nullptr, "UpdateFirmwareTo"}, + {0x04020040, nullptr, "BeginImportProgram"}, + {0x04030000, nullptr, "BeginImportProgramTemporarily"}, + {0x04040002, nullptr, "CancelImportProgram"}, + {0x04050002, nullptr, "EndImportProgram"}, + {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, + {0x040700C2, nullptr, "CommitImportPrograms"}, + {0x04080042, nullptr, "GetProgramInfoFromCia"}, + {0x04090004, nullptr, "GetSystemMenuDataFromCia"}, + {0x040A0002, nullptr, "GetDependencyListFromCia"}, + {0x040B0002, nullptr, "GetTransferSizeFromCia"}, + {0x040C0002, nullptr, "GetCoreVersionFromCia"}, + {0x040D0042, nullptr, "GetRequiredSizeFromCia"}, + {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, + {0x040F0000, nullptr, "UpdateFirmwareAuto"}, + {0x041000C0, nullptr, "DeleteProgram"}, + {0x04110044, nullptr, "GetTwlProgramListForReboot"}, + {0x04120000, nullptr, "GetSystemUpdaterMutex"}, + {0x04130002, nullptr, "GetMetaSizeFromCia"}, + {0x04140044, nullptr, "GetMetaDataFromCia"}, + {0x04150080, nullptr, "CheckDemoLaunchRights"}, + {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, + {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, + {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, + {0x04190000, nullptr, "BeginImportSystemProgram"}, }; AM_U_Interface::AM_U_Interface() { diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index a7a0c8a41..6e35e1d29 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -9,34 +9,97 @@ namespace Service { namespace APT { const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetLockHandle, "GetLockHandle?"}, - {0x00020080, Initialize, "Initialize?"}, - {0x00030040, Enable, "Enable?"}, - {0x00040040, nullptr, "Finalize?"}, + {0x00010040, GetLockHandle, "GetLockHandle"}, + {0x00020080, Initialize, "Initialize"}, + {0x00030040, Enable, "Enable"}, + {0x00040040, nullptr, "Finalize"}, {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, {0x00060040, GetAppletInfo, "GetAppletInfo"}, + {0x00070000, nullptr, "GetLastSignaledAppletId"}, + {0x00080000, nullptr, "CountRegisteredApplet"}, {0x00090040, IsRegistered, "IsRegistered"}, + {0x000A0040, nullptr, "GetAttribute"}, {0x000B0040, InquireNotification, "InquireNotification"}, {0x000C0104, SendParameter, "SendParameter"}, {0x000D0080, ReceiveParameter, "ReceiveParameter"}, {0x000E0080, GlanceParameter, "GlanceParameter"}, {0x000F0100, CancelParameter, "CancelParameter"}, + {0x001000C2, nullptr, "DebugFunc"}, + {0x001100C0, nullptr, "MapProgramIdForDebug"}, + {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, + {0x00130000, nullptr, "GetPreparationState"}, + {0x00140040, nullptr, "SetPreparationState"}, {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, + {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, + {0x00190040, nullptr, "PrepareToStartSystemApplet"}, + {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, + {0x001B00C4, nullptr, "StartApplication"}, + {0x001C0000, nullptr, "WakeupApplication"}, + {0x001D0000, nullptr, "CancelApplication"}, {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, + {0x001F0084, nullptr, "StartSystemApplet"}, + {0x00200044, nullptr, "StartNewestHomeMenu"}, + {0x00210000, nullptr, "OrderToCloseApplication"}, + {0x00220040, nullptr, "PrepareToCloseApplication"}, + {0x00230040, nullptr, "PrepareToJumpToApplication"}, + {0x00240044, nullptr, "JumpToApplication"}, + {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, + {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, + {0x00270044, nullptr, "CloseApplication"}, + {0x00280044, nullptr, "CloseLibraryApplet"}, + {0x00290044, nullptr, "CloseSystemApplet"}, + {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, + {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, + {0x002C0044, nullptr, "JumpToHomeMenu"}, + {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, + {0x002E0044, nullptr, "LeaveHomeMenu"}, + {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, + {0x00300044, nullptr, "LeaveResidentApplet"}, + {0x00310100, nullptr, "PrepareToDoApplicationJump"}, + {0x00320084, nullptr, "DoApplicationJump"}, + {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, + {0x00340084, nullptr, "SendDeliverArg"}, + {0x00350080, nullptr, "ReceiveDeliverArg"}, + {0x00360040, nullptr, "LoadSysMenuArg"}, + {0x00370042, nullptr, "StoreSysMenuArg"}, + {0x00380040, nullptr, "PreloadResidentApplet"}, + {0x00390040, nullptr, "PrepareToStartResidentApplet"}, + {0x003A0044, nullptr, "StartResidentApplet"}, {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"}, + {0x003C0042, nullptr, "SendDspSleep"}, + {0x003D0042, nullptr, "SendDspWakeUp"}, {0x003E0080, nullptr, "ReplySleepQuery"}, - {0x00430040, NotifyToWait, "NotifyToWait?"}, - {0x00440000, GetSharedFont, "GetSharedFont?"}, - {0x004B00C2, AppletUtility, "AppletUtility?"}, + {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, + {0x00400042, nullptr, "SendCaptureBufferInfo"}, + {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, + {0x00420080, nullptr, "SleepSystem"}, + {0x00430040, NotifyToWait, "NotifyToWait"}, + {0x00440000, GetSharedFont, "GetSharedFont"}, + {0x00450040, nullptr, "GetWirelessRebootInfo"}, + {0x00460104, nullptr, "Wrap"}, + {0x00470104, nullptr, "Unwrap"}, + {0x00480100, nullptr, "GetProgramInfo"}, + {0x00490180, nullptr, "Reboot"}, + {0x004A0040, nullptr, "GetCaptureInfo"}, + {0x004B00C2, AppletUtility, "AppletUtility"}, + {0x004C0000, nullptr, "SetFatalErrDispMode"}, + {0x004D0080, nullptr, "GetAppletProgramInfo"}, + {0x004E0000, nullptr, "HardwareResetAsync"}, {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, {0x00510080, GetStartupArgument, "GetStartupArgument"}, + {0x00520104, nullptr, "Wrap1"}, + {0x00530104, nullptr, "Unwrap1"}, {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, + {0x00570044, nullptr, "WakeupApplication2"}, + {0x00580002, nullptr, "GetProgramID"}, {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, {0x01020000, CheckNew3DS, "CheckNew3DS"}, + {0x01040000, nullptr, "IsStandardMemoryLayout"}, + {0x01050100, nullptr, "IsTitleAllowed"}, }; APT_A_Interface::APT_A_Interface() { diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index c4556a5de..84019e6e5 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -94,9 +94,12 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00530104, nullptr, "Unwrap1"}, {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, + {0x00570044, nullptr, "WakeupApplication2"}, {0x00580002, nullptr, "GetProgramID"}, {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, {0x01020000, CheckNew3DS, "CheckNew3DS"}, + {0x01040000, nullptr, "IsStandardMemoryLayout"}, + {0x01050100, nullptr, "IsTitleAllowed"}, }; APT_S_Interface::APT_S_Interface() { diff --git a/src/core/hle/service/boss/boss_p.cpp b/src/core/hle/service/boss/boss_p.cpp index dfee8d055..ee941e228 100644 --- a/src/core/hle/service/boss/boss_p.cpp +++ b/src/core/hle/service/boss/boss_p.cpp @@ -2,16 +2,81 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/hle/service/boss/boss.h" #include "core/hle/service/boss/boss_p.h" namespace Service { namespace BOSS { -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; +const Interface::FunctionInfo FunctionTable[] = { + // boss:u shared commands + {0x00010082, InitializeSession, "InitializeSession"}, + {0x00020100, RegisterStorage, "RegisterStorage"}, + {0x00030000, UnregisterStorage, "UnregisterStorage"}, + {0x00040000, GetStorageInfo, "GetStorageInfo"}, + {0x00050042, RegisterPrivateRootCa, "RegisterPrivateRootCa"}, + {0x00060084, RegisterPrivateClientCert, "RegisterPrivateClientCert"}, + {0x00070000, GetNewArrivalFlag, "GetNewArrivalFlag"}, + {0x00080002, RegisterNewArrivalEvent, "RegisterNewArrivalEvent"}, + {0x00090040, SetOptoutFlag, "SetOptoutFlag"}, + {0x000A0000, GetOptoutFlag, "GetOptoutFlag"}, + {0x000B00C2, RegisterTask, "RegisterTask"}, + {0x000C0082, UnregisterTask, "UnregisterTask"}, + {0x000D0082, ReconfigureTask, "ReconfigureTask"}, + {0x000E0000, GetTaskIdList, "GetTaskIdList"}, + {0x000F0042, GetStepIdList, "GetStepIdList"}, + {0x00100102, GetNsDataIdList, "GetNsDataIdList"}, + {0x00110102, GetOwnNsDataIdList, "GetOwnNsDataIdList"}, + {0x00120102, GetNewDataNsDataIdList, "GetNewDataNsDataIdList"}, + {0x00130102, GetOwnNewDataNsDataIdList, "GetOwnNewDataNsDataIdList"}, + {0x00140082, SendProperty, "SendProperty"}, + {0x00150042, SendPropertyHandle, "SendPropertyHandle"}, + {0x00160082, ReceiveProperty, "ReceiveProperty"}, + {0x00170082, UpdateTaskInterval, "UpdateTaskInterval"}, + {0x00180082, UpdateTaskCount, "UpdateTaskCount"}, + {0x00190042, GetTaskInterval, "GetTaskInterval"}, + {0x001A0042, GetTaskCount, "GetTaskCount"}, + {0x001B0042, GetTaskServiceStatus, "GetTaskServiceStatus"}, + {0x001C0042, StartTask, "StartTask"}, + {0x001D0042, StartTaskImmediate, "StartTaskImmediate"}, + {0x001E0042, CancelTask, "CancelTask"}, + {0x001F0000, GetTaskFinishHandle, "GetTaskFinishHandle"}, + {0x00200082, GetTaskState, "GetTaskState"}, + {0x00210042, GetTaskResult, "GetTaskResult"}, + {0x00220042, GetTaskCommErrorCode, "GetTaskCommErrorCode"}, + {0x002300C2, GetTaskStatus, "GetTaskStatus"}, + {0x00240082, GetTaskError, "GetTaskError"}, + {0x00250082, GetTaskInfo, "GetTaskInfo"}, + {0x00260040, DeleteNsData, "DeleteNsData"}, + {0x002700C2, GetNsDataHeaderInfo, "GetNsDataHeaderInfo"}, + {0x00280102, ReadNsData, "ReadNsData"}, + {0x00290080, SetNsDataAdditionalInfo, "SetNsDataAdditionalInfo"}, + {0x002A0040, GetNsDataAdditionalInfo, "GetNsDataAdditionalInfo"}, + {0x002B0080, SetNsDataNewFlag, "SetNsDataNewFlag"}, + {0x002C0040, GetNsDataNewFlag, "GetNsDataNewFlag"}, + {0x002D0040, GetNsDataLastUpdate, "GetNsDataLastUpdate"}, + {0x002E0040, GetErrorCode, "GetErrorCode"}, + {0x002F0140, RegisterStorageEntry, "RegisterStorageEntry"}, + {0x00300000, GetStorageEntryInfo, "GetStorageEntryInfo"}, + {0x00310100, SetStorageOption, "SetStorageOption"}, + {0x00320000, GetStorageOption, "GetStorageOption"}, + {0x00330042, StartBgImmediate, "StartBgImmediate"}, + {0x00340042, GetTaskActivePriority, "GetTaskActivePriority"}, + {0x003500C2, RegisterImmediateTask, "RegisterImmediateTask"}, + {0x00360084, SetTaskQuery, "SetTaskQuery"}, + {0x00370084, GetTaskQuery, "GetTaskQuery"}, + // boss:p + {0x04040080, nullptr, "GetAppNewFlag"}, + {0x04130082, nullptr, "SendPropertyPrivileged"}, + {0x041500C0, nullptr, "DeleteNsDataPrivileged"}, + {0x04160142, nullptr, "GetNsDataHeaderInfoPrivileged"}, + {0x04170182, nullptr, "ReadNsDataPrivileged"}, + {0x041A0100, nullptr, "SetNsDataNewFlagPrivileged"}, + {0x041B00C0, nullptr, "GetNsDataNewFlagPrivileged"}, +}; BOSS_P_Interface::BOSS_P_Interface() { - // Register(FunctionTable); + Register(FunctionTable); } } // namespace BOSS diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp index 4b747de7b..7d98ba6e9 100644 --- a/src/core/hle/service/cecd/cecd_u.cpp +++ b/src/core/hle/service/cecd/cecd_u.cpp @@ -9,10 +9,22 @@ namespace Service { namespace CECD { static const Interface::FunctionInfo FunctionTable[] = { + {0x000100C2, nullptr, "OpenRawFile"}, + {0x00020042, nullptr, "ReadRawFile"}, + {0x00030104, nullptr, "ReadMessage"}, + {0x00040106, nullptr, "ReadMessageWithHMAC"}, + {0x00050042, nullptr, "WriteRawFile"}, + {0x00060104, nullptr, "WriteMessage"}, + {0x00070106, nullptr, "WriteMessageWithHMAC"}, + {0x00080102, nullptr, "Delete"}, + {0x000A00C4, nullptr, "GetSystemInfo"}, + {0x000B0040, nullptr, "RunCommand"}, + {0x000C0040, nullptr, "RunCommandAlt"}, {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"}, {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, - {0x00120104, nullptr, "ReadSavedData"}, + {0x00110104, nullptr, "OpenAndWrite"}, + {0x00120104, nullptr, "OpenAndRead"}, }; CECD_U_Interface::CECD_U_Interface() { diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp index 2ff52c8b8..46312da4b 100644 --- a/src/core/hle/service/cfg/cfg_i.cpp +++ b/src/core/hle/service/cfg/cfg_i.cpp @@ -20,6 +20,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00080080, nullptr, "GoThroughTable"}, {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, + {0x000B0000, nullptr, "IsFangateSupported"}, // cfg:i {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp index eed26dec7..564a9bb08 100644 --- a/src/core/hle/service/cfg/cfg_s.cpp +++ b/src/core/hle/service/cfg/cfg_s.cpp @@ -20,6 +20,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00080080, nullptr, "GoThroughTable"}, {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, + {0x000B0000, nullptr, "IsFangateSupported"}, // cfg:s {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp index f28217134..4c82846c0 100644 --- a/src/core/hle/service/cfg/cfg_u.cpp +++ b/src/core/hle/service/cfg/cfg_u.cpp @@ -20,6 +20,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00080080, nullptr, "GoThroughTable"}, {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, + {0x000B0000, nullptr, "IsFangateSupported"}, }; CFG_U_Interface::CFG_U_Interface() { diff --git a/src/core/hle/service/dlp/dlp_srvr.cpp b/src/core/hle/service/dlp/dlp_srvr.cpp index 49d5b8d1c..25c07f401 100644 --- a/src/core/hle/service/dlp/dlp_srvr.cpp +++ b/src/core/hle/service/dlp/dlp_srvr.cpp @@ -22,7 +22,14 @@ static void unk_0x000E0040(Interface* self) { const Interface::FunctionInfo FunctionTable[] = { {0x00010183, nullptr, "Initialize"}, {0x00020000, nullptr, "Finalize"}, + {0x00030000, nullptr, "GetServerState"}, + {0x00050080, nullptr, "StartAccepting"}, + {0x00070000, nullptr, "StartDistribution"}, {0x000800C0, nullptr, "SendWirelessRebootPassphrase"}, + {0x00090040, nullptr, "AcceptClient"}, + {0x000B0042, nullptr, "GetConnectingClients"}, + {0x000C0040, nullptr, "GetClientInfo"}, + {0x000D0040, nullptr, "GetClientState"}, {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, }; diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 4c29784e8..bef75f5df 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -16,6 +16,7 @@ #include "core/file_sys/archive_backend.h" #include "core/file_sys/archive_extsavedata.h" #include "core/file_sys/archive_ncch.h" +#include "core/file_sys/archive_other_savedata.h" #include "core/file_sys/archive_savedata.h" #include "core/file_sys/archive_sdmc.h" #include "core/file_sys/archive_sdmcwriteonly.h" @@ -535,8 +536,17 @@ void RegisterArchiveTypes() { sdmc_directory.c_str()); // Create the SaveData archive - auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); + auto sd_savedata_source = std::make_shared<FileSys::ArchiveSource_SDSaveData>(sdmc_directory); + auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sd_savedata_source); RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); + auto other_savedata_permitted_factory = + std::make_unique<FileSys::ArchiveFactory_OtherSaveDataPermitted>(sd_savedata_source); + RegisterArchiveType(std::move(other_savedata_permitted_factory), + ArchiveIdCode::OtherSaveDataPermitted); + auto other_savedata_general_factory = + std::make_unique<FileSys::ArchiveFactory_OtherSaveDataGeneral>(sd_savedata_source); + RegisterArchiveType(std::move(other_savedata_general_factory), + ArchiveIdCode::OtherSaveDataGeneral); auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 21ed9717b..87089bd92 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -34,10 +34,12 @@ enum class ArchiveIdCode : u32 { SDMC = 0x00000009, SDMCWriteOnly = 0x0000000A, NCCH = 0x2345678A, + OtherSaveDataGeneral = 0x567890B2, + OtherSaveDataPermitted = 0x567890B4, }; /// Media types for the archives -enum class MediaType : u32 { NAND = 0, SDMC = 1 }; +enum class MediaType : u32 { NAND = 0, SDMC = 1, GameCard = 2 }; typedef u64 ArchiveHandle; diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 9ec17b395..d6ab5b065 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -1003,6 +1003,8 @@ const Interface::FunctionInfo FunctionTable[] = { {0x08680000, nullptr, "GetMediaType"}, {0x08690000, nullptr, "GetNandEraseCount"}, {0x086A0082, nullptr, "ReadNandReport"}, + {0x087A0180, nullptr, "AddSeed"}, + {0x088600C0, nullptr, "CheckUpdatedDat"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp index b916dd759..3fdf5cca4 100644 --- a/src/core/hle/service/gsp_lcd.cpp +++ b/src/core/hle/service/gsp_lcd.cpp @@ -11,11 +11,15 @@ namespace GSP_LCD { const Interface::FunctionInfo FunctionTable[] = { // clang-format off + {0x000A0080, nullptr, "SetBrightnessRaw"}, + {0x000B0080, nullptr, "SetBrightness"}, {0x000F0000, nullptr, "PowerOnAllBacklights"}, {0x00100000, nullptr, "PowerOffAllBacklights"}, {0x00110040, nullptr, "PowerOnBacklight"}, {0x00120040, nullptr, "PowerOffBacklight"}, {0x00130040, nullptr, "SetLedForceOff"}, + {0x00140000, nullptr, "GetVendor"}, + {0x00150040, nullptr, "GetBrightness"}, // clang-format on }; diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 3cf62a4b8..65c7babe5 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -55,6 +55,10 @@ const Interface::FunctionInfo FunctionTable[] = { {0x002E0040, nullptr, "DestroyRootCertChain"}, {0x002F0082, nullptr, "RootCertChainAddCert"}, {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, + {0x00310080, nullptr, "RootCertChainRemoveCert"}, + {0x00320084, nullptr, "OpenClientCertContext"}, + {0x00330040, nullptr, "OpenDefaultClientCertContext"}, + {0x00340040, nullptr, "CloseClientCertContext"}, {0x00350186, nullptr, "SetDefaultProxy"}, {0x00360000, nullptr, "ClearDNSCache"}, {0x00370080, nullptr, "SetKeepAlive"}, diff --git a/src/core/hle/service/mvd/mvd.cpp b/src/core/hle/service/mvd/mvd.cpp new file mode 100644 index 000000000..9416fe5d6 --- /dev/null +++ b/src/core/hle/service/mvd/mvd.cpp @@ -0,0 +1,17 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/mvd/mvd.h" +#include "core/hle/service/mvd/mvd_std.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace MVD { + +void Init() { + AddService(new MVD_STD()); +} + +} // namespace MVD +} // namespace Service diff --git a/src/core/hle/service/mvd/mvd.h b/src/core/hle/service/mvd/mvd.h new file mode 100644 index 000000000..7b212e839 --- /dev/null +++ b/src/core/hle/service/mvd/mvd.h @@ -0,0 +1,14 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Service { +namespace MVD { + +/// Initializes all MVD services. +void Init(); + +} // namespace MVD +} // namespace Service diff --git a/src/core/hle/service/mvd/mvd_std.cpp b/src/core/hle/service/mvd/mvd_std.cpp new file mode 100644 index 000000000..fd7ca87d3 --- /dev/null +++ b/src/core/hle/service/mvd/mvd_std.cpp @@ -0,0 +1,32 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/mvd/mvd_std.h" + +namespace Service { +namespace MVD { + +const Interface::FunctionInfo FunctionTable[] = { + // clang-format off + {0x00010082, nullptr, "Initialize"}, + {0x00020000, nullptr, "Shutdown"}, + {0x00030300, nullptr, "CalculateWorkBufSize"}, + {0x000400C0, nullptr, "CalculateImageSize"}, + {0x00080142, nullptr, "ProcessNALUnit"}, + {0x00090042, nullptr, "ControlFrameRendering"}, + {0x000A0000, nullptr, "GetStatus"}, + {0x000B0000, nullptr, "GetStatusOther"}, + {0x001D0042, nullptr, "GetConfig"}, + {0x001E0044, nullptr, "SetConfig"}, + {0x001F0902, nullptr, "SetOutputBuffer"}, + {0x00210100, nullptr, "OverrideOutputBuffers"} + // clang-format on +}; + +MVD_STD::MVD_STD() { + Register(FunctionTable); +} + +} // namespace MVD +} // namespace Service diff --git a/src/core/hle/service/mvd/mvd_std.h b/src/core/hle/service/mvd/mvd_std.h new file mode 100644 index 000000000..7db9e2e50 --- /dev/null +++ b/src/core/hle/service/mvd/mvd_std.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace MVD { + +class MVD_STD final : public Interface { +public: + MVD_STD(); + + std::string GetPortName() const override { + return "mvd:std"; + } +}; + +} // namespace MVD +} // namespace Service diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp new file mode 100644 index 000000000..d9738c6a1 --- /dev/null +++ b/src/core/hle/service/nfc/nfc.cpp @@ -0,0 +1,18 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/nfc/nfc.h" +#include "core/hle/service/nfc/nfc_m.h" +#include "core/hle/service/nfc/nfc_u.h" + +namespace Service { +namespace NFC { + +void Init() { + AddService(new NFC_M()); + AddService(new NFC_U()); +} + +} // namespace NFC +} // namespace Service diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h new file mode 100644 index 000000000..cd65a5fdc --- /dev/null +++ b/src/core/hle/service/nfc/nfc.h @@ -0,0 +1,14 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Service { +namespace NFC { + +/// Initialize all NFC services. +void Init(); + +} // namespace NFC +} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_m.cpp b/src/core/hle/service/nfc/nfc_m.cpp new file mode 100644 index 000000000..717335c11 --- /dev/null +++ b/src/core/hle/service/nfc/nfc_m.cpp @@ -0,0 +1,44 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/nfc/nfc_m.h" + +namespace Service { +namespace NFC { + +const Interface::FunctionInfo FunctionTable[] = { + // clang-format off + // nfc:u shared commands + {0x00010040, nullptr, "Initialize"}, + {0x00020040, nullptr, "Shutdown"}, + {0x00030000, nullptr, "StartCommunication"}, + {0x00040000, nullptr, "StopCommunication"}, + {0x00050040, nullptr, "StartTagScanning"}, + {0x00060000, nullptr, "StopTagScanning"}, + {0x00070000, nullptr, "LoadAmiiboData"}, + {0x00080000, nullptr, "ResetTagScanState"}, + {0x00090002, nullptr, "UpdateStoredAmiiboData"}, + {0x000D0000, nullptr, "GetTagState"}, + {0x000F0000, nullptr, "CommunicationGetStatus"}, + {0x00100000, nullptr, "GetTagInfo2"}, + {0x00110000, nullptr, "GetTagInfo"}, + {0x00120000, nullptr, "CommunicationGetResult"}, + {0x00130040, nullptr, "OpenAppData"}, + {0x00140384, nullptr, "InitializeWriteAppData"}, + {0x00150040, nullptr, "ReadAppData"}, + {0x00160242, nullptr, "WriteAppData"}, + {0x00170000, nullptr, "GetAmiiboSettings"}, + {0x00180000, nullptr, "GetAmiiboConfig"}, + {0x00190000, nullptr, "GetAppDataInitStruct"}, + // nfc:m + {0x04040A40, nullptr, "SetAmiiboSettings"} + // clang-format on +}; + +NFC_M::NFC_M() { + Register(FunctionTable); +} + +} // namespace NFC +} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_m.h b/src/core/hle/service/nfc/nfc_m.h new file mode 100644 index 000000000..fae75535b --- /dev/null +++ b/src/core/hle/service/nfc/nfc_m.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace NFC { + +class NFC_M final : public Interface { +public: + NFC_M(); + + std::string GetPortName() const override { + return "nfc:m"; + } +}; + +} // namespace NFC +} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_u.cpp b/src/core/hle/service/nfc/nfc_u.cpp new file mode 100644 index 000000000..deffb0b4f --- /dev/null +++ b/src/core/hle/service/nfc/nfc_u.cpp @@ -0,0 +1,41 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/nfc/nfc_u.h" + +namespace Service { +namespace NFC { + +const Interface::FunctionInfo FunctionTable[] = { + // clang-format off + {0x00010040, nullptr, "Initialize"}, + {0x00020040, nullptr, "Shutdown"}, + {0x00030000, nullptr, "StartCommunication"}, + {0x00040000, nullptr, "StopCommunication"}, + {0x00050040, nullptr, "StartTagScanning"}, + {0x00060000, nullptr, "StopTagScanning"}, + {0x00070000, nullptr, "LoadAmiiboData"}, + {0x00080000, nullptr, "ResetTagScanState"}, + {0x00090002, nullptr, "UpdateStoredAmiiboData"}, + {0x000D0000, nullptr, "GetTagState"}, + {0x000F0000, nullptr, "CommunicationGetStatus"}, + {0x00100000, nullptr, "GetTagInfo2"}, + {0x00110000, nullptr, "GetTagInfo"}, + {0x00120000, nullptr, "CommunicationGetResult"}, + {0x00130040, nullptr, "OpenAppData"}, + {0x00140384, nullptr, "InitializeWriteAppData"}, + {0x00150040, nullptr, "ReadAppData"}, + {0x00160242, nullptr, "WriteAppData"}, + {0x00170000, nullptr, "GetAmiiboSettings"}, + {0x00180000, nullptr, "GetAmiiboConfig"}, + {0x00190000, nullptr, "GetAppDataInitStruct"}, + // clang-format on +}; + +NFC_U::NFC_U() { + Register(FunctionTable); +} + +} // namespace NFC +} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_u.h b/src/core/hle/service/nfc/nfc_u.h new file mode 100644 index 000000000..eb7507314 --- /dev/null +++ b/src/core/hle/service/nfc/nfc_u.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace NFC { + +class NFC_U final : public Interface { +public: + NFC_U(); + + std::string GetPortName() const override { + return "nfc:u"; + } +}; + +} // namespace NFC +} // namespace Service diff --git a/src/core/hle/service/nim/nim_s.cpp b/src/core/hle/service/nim/nim_s.cpp index e2ba693c9..28b87e6f7 100644 --- a/src/core/hle/service/nim/nim_s.cpp +++ b/src/core/hle/service/nim/nim_s.cpp @@ -10,6 +10,7 @@ namespace NIM { const Interface::FunctionInfo FunctionTable[] = { {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"}, {0x0016020A, nullptr, "ListTitles"}, + {0x00290000, nullptr, "AccountCheckBalanceSOAP"}, {0x002D0042, nullptr, "DownloadTickets"}, {0x00420240, nullptr, "StartDownload"}, }; diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp index 7e07d02e8..7664bad60 100644 --- a/src/core/hle/service/nim/nim_u.cpp +++ b/src/core/hle/service/nim/nim_u.cpp @@ -15,6 +15,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00050000, nullptr, "CheckForSysUpdateEvent"}, {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"}, {0x000A0000, nullptr, "GetState"}, + {0x000B0000, nullptr, "GetSystemTitleHash"}, }; NIM_U_Interface::NIM_U_Interface() { diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp index 80081aae2..8a2b00614 100644 --- a/src/core/hle/service/nwm_uds.cpp +++ b/src/core/hle/service/nwm_uds.cpp @@ -90,7 +90,7 @@ static void RecvBeaconBroadcastData(Service::Interface* self) { * 2 : Value 0 * 3 : Output handle */ -static void Initialize(Service::Interface* self) { +static void InitializeWithVersion(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 unk1 = cmd_buff[1]; u32 unk2 = cmd_buff[12]; @@ -120,24 +120,26 @@ static void Initialize(Service::Interface* self) { const Interface::FunctionInfo FunctionTable[] = { {0x00020000, nullptr, "Scrap"}, {0x00030000, Shutdown, "Shutdown"}, - {0x00040402, nullptr, "CreateNetwork"}, + {0x00040402, nullptr, "CreateNetwork (deprecated)"}, {0x00050040, nullptr, "EjectClient"}, {0x00060000, nullptr, "EjectSpectator"}, {0x00070080, nullptr, "UpdateNetworkAttribute"}, {0x00080000, nullptr, "DestroyNetwork"}, + {0x00090442, nullptr, "ConnectNetwork (deprecated)"}, {0x000A0000, nullptr, "DisconnectNetwork"}, {0x000B0000, nullptr, "GetConnectionStatus"}, {0x000D0040, nullptr, "GetNodeInformation"}, + {0x000E0006, nullptr, "DecryptBeaconData (deprecated)"}, {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"}, - {0x00100042, nullptr, "SetBeaconAdditionalData"}, + {0x00100042, nullptr, "SetApplicationData"}, {0x00110040, nullptr, "GetApplicationData"}, {0x00120100, nullptr, "Bind"}, {0x00130040, nullptr, "Unbind"}, - {0x001400C0, nullptr, "RecvBroadcastDataFrame"}, + {0x001400C0, nullptr, "PullPacket"}, {0x00150080, nullptr, "SetMaxSendDelay"}, {0x00170182, nullptr, "SendTo"}, {0x001A0000, nullptr, "GetChannel"}, - {0x001B0302, Initialize, "Initialize"}, + {0x001B0302, InitializeWithVersion, "InitializeWithVersion"}, {0x001D0044, nullptr, "BeginHostingNetwork"}, {0x001E0084, nullptr, "ConnectToNetwork"}, {0x001F0006, nullptr, "DecryptBeaconData"}, diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp index 7d91694f6..194d7c40d 100644 --- a/src/core/hle/service/pm_app.cpp +++ b/src/core/hle/service/pm_app.cpp @@ -10,18 +10,21 @@ namespace PM_APP { const Interface::FunctionInfo FunctionTable[] = { + // clang-format off {0x00010140, nullptr, "LaunchTitle"}, - {0x00020082, nullptr, "LaunchFIRMSetParams"}, - {0x00030080, nullptr, "TerminateProcesse"}, - {0x00040100, nullptr, "TerminateProcessTID"}, - {0x000500C0, nullptr, "TerminateProcessTID_unknown"}, + {0x00020082, nullptr, "LaunchFIRM"}, + {0x00030080, nullptr, "TerminateApplication"}, + {0x00040100, nullptr, "TerminateTitle"}, + {0x000500C0, nullptr, "TerminateProcess"}, + {0x00060082, nullptr, "PrepareForReboot"}, {0x00070042, nullptr, "GetFIRMLaunchParams"}, {0x00080100, nullptr, "GetTitleExheaderFlags"}, {0x00090042, nullptr, "SetFIRMLaunchParams"}, - {0x000A0140, nullptr, "SetResourceLimit"}, - {0x000B0140, nullptr, "GetResourceLimitMax"}, + {0x000A0140, nullptr, "SetAppResourceLimit"}, + {0x000B0140, nullptr, "GetAppResourceLimit"}, {0x000C0080, nullptr, "UnregisterProcess"}, {0x000D0240, nullptr, "LaunchTitleUpdate"}, + // clang-format on }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index cc859c14c..6a9f1d24d 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -81,7 +81,7 @@ void GetTotalStepCount(Service::Interface* self) { LOG_WARNING(Service_PTM, "(STUBBED) called"); } -void IsLegacyPowerOff(Service::Interface* self) { +void GetSoftwareClosedFlag(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index 6e163a6f9..a1a628012 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h @@ -82,12 +82,13 @@ void GetBatteryChargeState(Interface* self); void GetTotalStepCount(Interface* self); /** - * PTM::IsLegacyPowerOff service function + * PTM::GetSoftwareClosedFlag service function * Outputs: * 1: Result code, 0 on success, otherwise error code - * 2: Whether the system is going through a power off + * 2: Whether or not the "software closed" dialog was requested by the last FIRM + * and should be displayed. */ -void IsLegacyPowerOff(Interface* self); +void GetSoftwareClosedFlag(Interface* self); /** * PTM::CheckNew3DS service function diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp index 693158dbf..82e118e2b 100644 --- a/src/core/hle/service/ptm/ptm_sysm.cpp +++ b/src/core/hle/service/ptm/ptm_sysm.cpp @@ -33,8 +33,8 @@ const Interface::FunctionInfo FunctionTable[] = { {0x080C0080, nullptr, "SetUserTime"}, {0x080D0000, nullptr, "InvalidateSystemTime"}, {0x080E0140, nullptr, "NotifyPlayEvent"}, - {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, - {0x08100000, nullptr, "ClearLegacyPowerOff"}, + {0x080F0000, GetSoftwareClosedFlag, "GetSoftwareClosedFlag"}, + {0x08100000, nullptr, "ClearSoftwareClosedFlag"}, {0x08110000, GetShellState, "GetShellState"}, {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, {0x08130000, nullptr, "FormatSavedata"}, diff --git a/src/core/hle/service/qtm/qtm.cpp b/src/core/hle/service/qtm/qtm.cpp new file mode 100644 index 000000000..f11542263 --- /dev/null +++ b/src/core/hle/service/qtm/qtm.cpp @@ -0,0 +1,21 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/qtm/qtm.h" +#include "core/hle/service/qtm/qtm_s.h" +#include "core/hle/service/qtm/qtm_sp.h" +#include "core/hle/service/qtm/qtm_u.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace QTM { + +void Init() { + AddService(new QTM_S()); + AddService(new QTM_SP()); + AddService(new QTM_U()); +} + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/qtm/qtm.h b/src/core/hle/service/qtm/qtm.h new file mode 100644 index 000000000..33b774c79 --- /dev/null +++ b/src/core/hle/service/qtm/qtm.h @@ -0,0 +1,14 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Service { +namespace QTM { + +/// Initializes all QTM services. +void Init(); + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_s.cpp b/src/core/hle/service/qtm/qtm_s.cpp new file mode 100644 index 000000000..ad7df24a0 --- /dev/null +++ b/src/core/hle/service/qtm/qtm_s.cpp @@ -0,0 +1,23 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/qtm/qtm_s.h" + +namespace Service { +namespace QTM { + +const Interface::FunctionInfo FunctionTable[] = { + // clang-format off + // qtm common commands + {0x00010080, nullptr, "GetHeadtrackingInfoRaw"}, + {0x00020080, nullptr, "GetHeadtrackingInfo"}, + // clang-format on +}; + +QTM_S::QTM_S() { + Register(FunctionTable); +} + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_s.h b/src/core/hle/service/qtm/qtm_s.h new file mode 100644 index 000000000..e66138ed0 --- /dev/null +++ b/src/core/hle/service/qtm/qtm_s.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace QTM { + +class QTM_S final : public Interface { +public: + QTM_S(); + + std::string GetPortName() const override { + return "qtm:s"; + } +}; + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_sp.cpp b/src/core/hle/service/qtm/qtm_sp.cpp new file mode 100644 index 000000000..6e0695d34 --- /dev/null +++ b/src/core/hle/service/qtm/qtm_sp.cpp @@ -0,0 +1,23 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/qtm/qtm_sp.h" + +namespace Service { +namespace QTM { + +const Interface::FunctionInfo FunctionTable[] = { + // clang-format off + // qtm common commands + {0x00010080, nullptr, "GetHeadtrackingInfoRaw"}, + {0x00020080, nullptr, "GetHeadtrackingInfo"}, + // clang-format on +}; + +QTM_SP::QTM_SP() { + Register(FunctionTable); +} + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_sp.h b/src/core/hle/service/qtm/qtm_sp.h new file mode 100644 index 000000000..0ae0618fc --- /dev/null +++ b/src/core/hle/service/qtm/qtm_sp.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace QTM { + +class QTM_SP final : public Interface { +public: + QTM_SP(); + + std::string GetPortName() const override { + return "qtm:sp"; + } +}; + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_u.cpp b/src/core/hle/service/qtm/qtm_u.cpp new file mode 100644 index 000000000..a0f808432 --- /dev/null +++ b/src/core/hle/service/qtm/qtm_u.cpp @@ -0,0 +1,23 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/qtm/qtm_u.h" + +namespace Service { +namespace QTM { + +const Interface::FunctionInfo FunctionTable[] = { + // clang-format off + // qtm common commands + {0x00010080, nullptr, "GetHeadtrackingInfoRaw"}, + {0x00020080, nullptr, "GetHeadtrackingInfo"}, + // clang-format on +}; + +QTM_U::QTM_U() { + Register(FunctionTable); +} + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_u.h b/src/core/hle/service/qtm/qtm_u.h new file mode 100644 index 000000000..1ed4c0adc --- /dev/null +++ b/src/core/hle/service/qtm/qtm_u.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace QTM { + +class QTM_U final : public Interface { +public: + QTM_U(); + + std::string GetPortName() const override { + return "qtm:u"; + } +}; + +} // namespace QTM +} // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ca7eeac8a..407ca4139 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -26,13 +26,16 @@ #include "core/hle/service/ir/ir.h" #include "core/hle/service/ldr_ro/ldr_ro.h" #include "core/hle/service/mic_u.h" +#include "core/hle/service/mvd/mvd.h" #include "core/hle/service/ndm/ndm.h" #include "core/hle/service/news/news.h" +#include "core/hle/service/nfc/nfc.h" #include "core/hle/service/nim/nim.h" #include "core/hle/service/ns_s.h" #include "core/hle/service/nwm_uds.h" #include "core/hle/service/pm_app.h" #include "core/hle/service/ptm/ptm.h" +#include "core/hle/service/qtm/qtm.h" #include "core/hle/service/service.h" #include "core/hle/service/soc_u.h" #include "core/hle/service/srv.h" @@ -109,21 +112,24 @@ void Init() { AddNamedPort(new SRV::Interface); AddNamedPort(new ERR_F::Interface); - Service::FS::ArchiveInit(); - Service::AM::Init(); - Service::APT::Init(); - Service::BOSS::Init(); - Service::CAM::Init(); - Service::CECD::Init(); - Service::CFG::Init(); - Service::DLP::Init(); - Service::FRD::Init(); - Service::HID::Init(); - Service::IR::Init(); - Service::NEWS::Init(); - Service::NDM::Init(); - Service::NIM::Init(); - Service::PTM::Init(); + FS::ArchiveInit(); + AM::Init(); + APT::Init(); + BOSS::Init(); + CAM::Init(); + CECD::Init(); + CFG::Init(); + DLP::Init(); + FRD::Init(); + HID::Init(); + IR::Init(); + MVD::Init(); + NDM::Init(); + NEWS::Init(); + NFC::Init(); + NIM::Init(); + PTM::Init(); + QTM::Init(); AddService(new AC_U::Interface); AddService(new ACT_A::Interface); @@ -148,21 +154,21 @@ void Init() { /// Shutdown ServiceManager void Shutdown() { - Service::PTM::Shutdown(); - Service::NDM::Shutdown(); - Service::NIM::Shutdown(); - Service::NEWS::Shutdown(); - Service::IR::Shutdown(); - Service::HID::Shutdown(); - Service::FRD::Shutdown(); - Service::DLP::Shutdown(); - Service::CFG::Shutdown(); - Service::CECD::Shutdown(); - Service::CAM::Shutdown(); - Service::BOSS::Shutdown(); - Service::APT::Shutdown(); - Service::AM::Shutdown(); - Service::FS::ArchiveShutdown(); + PTM::Shutdown(); + NIM::Shutdown(); + NEWS::Shutdown(); + NDM::Shutdown(); + IR::Shutdown(); + HID::Shutdown(); + FRD::Shutdown(); + DLP::Shutdown(); + CFG::Shutdown(); + CECD::Shutdown(); + CAM::Shutdown(); + BOSS::Shutdown(); + APT::Shutdown(); + AM::Shutdown(); + FS::ArchiveShutdown(); g_srv_services.clear(); g_kernel_named_ports.clear(); diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp index abab1d271..6d36e5a24 100644 --- a/src/core/hle/service/ssl_c.cpp +++ b/src/core/hle/service/ssl_c.cpp @@ -66,6 +66,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00050082, nullptr, "AddTrustedRootCA"}, {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, {0x00070080, nullptr, "RootCertChainRemoveCert"}, + {0x000D0084, nullptr, "OpenClientCertContext"}, {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, {0x000F0040, nullptr, "CloseClientCertContext"}, {0x00110042, GenerateRandomData, "GenerateRandomData"}, @@ -73,10 +74,12 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00130040, nullptr, "StartConnection"}, {0x00140040, nullptr, "StartConnectionGetOut"}, {0x00150082, nullptr, "Read"}, + {0x00160082, nullptr, "ReadPeek"}, {0x00170082, nullptr, "Write"}, {0x00180080, nullptr, "ContextSetRootCertChain"}, {0x00190080, nullptr, "ContextSetClientCert"}, {0x001B0080, nullptr, "ContextClearOpt"}, + {0x001C00C4, nullptr, "ContextGetProtocolCipher"}, {0x001E0040, nullptr, "DestroyContext"}, {0x001F0082, nullptr, "ContextInitSharedmem"}, }; diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 7cb03ba8e..1503b45da 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -8,7 +8,10 @@ #include "common/color.h" #include "common/common_types.h" #include "common/logging/log.h" +#include "common/math_util.h" #include "common/microprofile.h" +#include "common/thread.h" +#include "common/timer.h" #include "common/vector_math.h" #include "core/core_timing.h" #include "core/hle/service/gsp_gpu.h" @@ -35,6 +38,14 @@ const u64 frame_ticks = 268123480ull / 60; static int vblank_event; /// Total number of frames drawn static u64 frame_count; +/// Start clock for frame limiter +static u32 time_point; +/// Total delay caused by slow frames +static float time_delay; +constexpr float FIXED_FRAME_TIME = 1000.0f / 60; +// Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher +// values increases time needed to limit frame rate after spikes +constexpr float MAX_LAG_TIME = 18; template <typename T> inline void Read(T& var, const u32 raw_addr) { @@ -512,6 +523,21 @@ template void Write<u32>(u32 addr, const u32 data); template void Write<u16>(u32 addr, const u16 data); template void Write<u8>(u32 addr, const u8 data); +static void FrameLimiter() { + time_delay += FIXED_FRAME_TIME; + time_delay = MathUtil::Clamp(time_delay, -MAX_LAG_TIME, MAX_LAG_TIME); + s32 desired_time = static_cast<s32>(time_delay); + s32 elapsed_time = static_cast<s32>(Common::Timer::GetTimeMs() - time_point); + + if (elapsed_time < desired_time) { + Common::SleepCurrentThread(desired_time - elapsed_time); + } + + u32 frame_time = Common::Timer::GetTimeMs() - time_point; + + time_delay -= frame_time; +} + /// Update hardware static void VBlankCallback(u64 userdata, int cycles_late) { frame_count++; @@ -528,6 +554,12 @@ static void VBlankCallback(u64 userdata, int cycles_late) { // Check for user input updates Service::HID::Update(); + if (!Settings::values.use_vsync && Settings::values.toggle_framelimit) { + FrameLimiter(); + } + + time_point = Common::Timer::GetTimeMs(); + // Reschedule recurrent event CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event); } @@ -563,6 +595,7 @@ void Init() { framebuffer_sub.active_fb = 0; frame_count = 0; + time_point = Common::Timer::GetTimeMs(); vblank_event = CoreTiming::RegisterEvent("GPU::VBlankCallback", VBlankCallback); CoreTiming::ScheduleEvent(frame_ticks, vblank_event); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 05f41f798..626e06cd9 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -21,6 +21,7 @@ void Apply() { VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; VideoCore::g_shader_jit_enabled = values.use_shader_jit; VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; + VideoCore::g_toggle_framelimit_enabled = values.toggle_framelimit; if (VideoCore::g_emu_window) { auto layout = VideoCore::g_emu_window->GetFramebufferLayout(); diff --git a/src/core/settings.h b/src/core/settings.h index 7470fdbeb..db4c8fada 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -90,6 +90,7 @@ struct Values { bool use_shader_jit; bool use_scaled_resolution; bool use_vsync; + bool toggle_framelimit; LayoutOption layout_option; bool swap_screen; |