diff options
Diffstat (limited to 'src/core/hle/service/acc/acc.cpp')
-rw-r--r-- | src/core/hle/service/acc/acc.cpp | 76 |
1 files changed, 57 insertions, 19 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index e61748ca3..c6437a671 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -2,9 +2,13 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> #include <array> +#include "common/common_paths.h" #include "common/common_types.h" +#include "common/file_util.h" #include "common/logging/log.h" +#include "common/string_util.h" #include "common/swap.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" @@ -16,6 +20,7 @@ #include "core/hle/service/acc/profile_manager.h" namespace Service::Account { + // TODO: RE this structure struct UserData { INSERT_PADDING_WORDS(1); @@ -27,6 +32,29 @@ struct UserData { }; static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size"); +// Smallest JPEG https://github.com/mathiasbynens/small/blob/master/jpeg.jpg +// used as a backup should the one on disk not exist +constexpr u32 backup_jpeg_size = 107; +constexpr std::array<u8, backup_jpeg_size> backup_jpeg{{ + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, + 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05, + 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, + 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, + 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, + 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, + 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9, +}}; + +static std::string GetImagePath(UUID uuid) { + return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + + "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; +} + +static constexpr u32 SanitizeJPEGSize(std::size_t size) { + constexpr std::size_t max_jpeg_image_size = 0x20000; + return static_cast<u32>(std::min(size, max_jpeg_image_size)); +} + class IProfile final : public ServiceFramework<IProfile> { public: explicit IProfile(UUID user_id, ProfileManager& profile_manager) @@ -73,32 +101,42 @@ private: } void LoadImage(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); - // smallest jpeg https://github.com/mathiasbynens/small/blob/master/jpeg.jpg - // TODO(mailwl): load actual profile image from disk, width 256px, max size 0x20000 - constexpr u32 jpeg_size = 107; - static constexpr std::array<u8, jpeg_size> jpeg{ - 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x08, 0x06, 0x06, 0x05, 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, - 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, - 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, - 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x11, 0x00, - 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, - 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9, - }; - ctx.WriteBuffer(jpeg); + LOG_DEBUG(Service_ACC, "called"); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(jpeg_size); + + const FileUtil::IOFile image(GetImagePath(user_id), "rb"); + if (!image.IsOpen()) { + LOG_WARNING(Service_ACC, + "Failed to load user provided image! Falling back to built-in backup..."); + ctx.WriteBuffer(backup_jpeg); + rb.Push<u32>(backup_jpeg_size); + return; + } + + const u32 size = SanitizeJPEGSize(image.GetSize()); + std::vector<u8> buffer(size); + image.ReadBytes(buffer.data(), buffer.size()); + + ctx.WriteBuffer(buffer.data(), buffer.size()); + rb.Push<u32>(size); } void GetImageSize(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); - constexpr u32 jpeg_size = 107; + LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(jpeg_size); + + const FileUtil::IOFile image(GetImagePath(user_id), "rb"); + + if (!image.IsOpen()) { + LOG_WARNING(Service_ACC, + "Failed to load user provided image! Falling back to built-in backup..."); + rb.Push<u32>(backup_jpeg_size); + } else { + rb.Push<u32>(SanitizeJPEGSize(image.GetSize())); + } } const ProfileManager& profile_manager; |